diff --git a/.gitignore b/.gitignore index 53bde4d..29ca847 100644 --- a/.gitignore +++ b/.gitignore
@@ -223,6 +223,7 @@ /net/net_unittests_run.xml /net/Release /net/testserver.log +/net/third_party/quiche /out*/ /ppapi/native_client/nacl_irt.xml /ppapi/native_client/ppapi_lib.xml
diff --git a/BUILD.gn b/BUILD.gn index a22dc57..3bc64860 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -979,7 +979,7 @@ ":layout_test_data_mojo_bindings", ":layout_test_data_mojo_bindings_lite", "//content/shell:content_shell", - "//content/test:mojo_layouttest_bindings_js_data_deps", + "//content/test:mojo_web_test_bindings_js_data_deps", "//device/bluetooth/public/mojom:fake_bluetooth_interfaces_js_data_deps", "//device/usb/public/mojom:mojom_js_data_deps", "//device/vr/public/mojom:mojom_js_data_deps", @@ -1029,7 +1029,6 @@ } data = [ - "$root_build_dir/resources/inspector/", "//testing/scripts/common.py", "//testing/scripts/run_isolated_script_test.py", "//testing/xvfb.py",
diff --git a/DEPS b/DEPS index 123a0a7..da79a4e 100644 --- a/DEPS +++ b/DEPS
@@ -82,9 +82,8 @@ # By default do not check out the Oculus SDK. Only available for Googlers. 'checkout_oculus_sdk' : 'checkout_src_internal and checkout_win', - # TODO(dpranke): change to != "small" once != is supported. - 'checkout_traffic_annotation_tools': 'checkout_configuration == "default"', - 'checkout_instrumented_libraries': 'checkout_linux and checkout_configuration == "default"', + 'checkout_traffic_annotation_tools': 'checkout_configuration != "small"', + 'checkout_instrumented_libraries': 'checkout_linux and checkout_configuration != "small"', # Default to the empty board. Desktop Chrome OS builds don't need cros SDK # dependencies. Other Chrome OS builds should always define this explicitly. @@ -96,12 +95,16 @@ # ANGLE's deps are relative to the angle_root variable. 'angle_root': 'src/third_party/angle', + # luci-go CIPD package version. + 'luci_go': 'git_revision:fdf05508e8a66c773a41521e0243c9d11b9a2a1c', + 'android_git': 'https://android.googlesource.com', 'aomedia_git': 'https://aomedia.googlesource.com', 'boringssl_git': 'https://boringssl.googlesource.com', 'chromium_git': 'https://chromium.googlesource.com', 'dawn_git': 'https://dawn.googlesource.com', 'pdfium_git': 'https://pdfium.googlesource.com', + 'quiche_git': 'https://quiche.googlesource.com', 'skia_git': 'https://skia.googlesource.com', 'swiftshader_git': 'https://swiftshader.googlesource.com', 'webrtc_git': 'https://webrtc.googlesource.com', @@ -112,11 +115,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '6d59568196c0e923674905eb2c8d874586e5ae34', + 'skia_revision': 'e1c2354d08ba5f761bcf22d5036488e038f72d99', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'f5137533bdfac762e980b17eb7b4a2433dd07d1d', + 'v8_revision': '4bb7e4faf54548a6b8f9057dcab1f732797aec19', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -124,11 +127,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '8f1b7a66a5e3182e44635f18c5740b77fa7c057f', + 'angle_revision': '19f2f9eb2503b5c500a349752f16f3b0bd2f274d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. - 'buildtools_revision': '04161ec8d7c781e4498c699254c69ba0dd959fde', + 'buildtools_revision': '7d88270de197ebe8b439ab5eb57a4a2a0bb810e0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -136,7 +139,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '3d29bcfeed81dbc8b3a63a5e81cca619bc11abb5', + 'pdfium_revision': '841c145e2eb1b44fbaf6a0266181e14b75036266', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -160,19 +163,19 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling NaCl # and whatever else without interference from each other. - 'nacl_revision': '17af1e818981ebf2c492a678d4d31c9e1ee37fc7', + 'nacl_revision': '14b228f23bb875bd4a25d3e88bd5f15d1bc8c87a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': '3dd4e76b19f3cd4f706c3455d6ae01765d07eee5', + 'freetype_revision': 'd01e28f41f8810c8ea422b854f8722659589fa99', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling HarfBuzz # and whatever else without interference from each other. - 'harfbuzz_revision': '79e7e3445efef2dc57f8a10c7e355e802af08868', + 'harfbuzz_revision': '59345cdef38cf1f514a6a0eb6e8852350acb6166', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'c7cc237f9582380fbffb14049f1031237f368127', + 'catapult_revision': 'e09a3df387b3ffd12e1ef8e9ad529b8e4577c118', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -188,7 +191,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'feed_revision': '5eaab0ec4f162c4f8d7901e14333127b16bcb7ac', + 'feed_revision': '8f0baf678cd55565412717d583f036a9b529bfdc', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_build-tools_version # and whatever else without interference from each other. @@ -220,7 +223,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'spv_tools_revision': '03afee3b90817ae6d23c9d4872f747c3fe3587b4', + 'spv_tools_revision': 'aab6f4073f7e77794dc40749ccf0c493b883df5e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -236,7 +239,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'e2f948469c66a28ff4090dba313e473288fa3de4', + 'dawn_revision': 'c3ecb5a77c063f898644fb2fbe51ccf071b827e6', + # Three lines of non-changing comments so that + # the commit queue can handle CLs rolling feed + # and whatever else without interference from each other. + 'quiche_revision': '99ab07063ac358016b637d7f6521a6dd37263f90', } # Only these hosts are allowed for dependencies in this DEPS file. @@ -250,6 +257,7 @@ 'chromium.googlesource.com', 'dawn.googlesource.com', 'pdfium.googlesource.com', + 'quiche.googlesource.com', 'skia.googlesource.com', 'swiftshader.googlesource.com', 'webrtc.googlesource.com', @@ -373,7 +381,7 @@ }, 'src/ios/third_party/motion_interchange_objc/src': { - 'url': Var('chromium_git') + '/external/github.com/material-motion/motion-interchange-objc.git' + '@' + '9be1e8572f8debb8dd9033ce9bd6ae56dc7ae1ab', + 'url': Var('chromium_git') + '/external/github.com/material-motion/motion-interchange-objc.git' + '@' + '6c385396ae7d3ee6752c3d625e322138eb8e25fc', 'condition': 'checkout_ios', }, @@ -400,19 +408,22 @@ 'condition': 'checkout_nacl', }, + 'src/net/third_party/quiche/src': + Var('quiche_git') + '/quiche.git' + '@' + Var('quiche_revision'), + 'src/tools/luci-go': { 'packages': [ { 'package': 'infra/tools/luci/isolate/${{platform}}', - 'version': 'git_revision:fdf05508e8a66c773a41521e0243c9d11b9a2a1c', + 'version': Var('luci_go'), }, { 'package': 'infra/tools/luci/isolated/${{platform}}', - 'version': 'git_revision:fdf05508e8a66c773a41521e0243c9d11b9a2a1c', + 'version': Var('luci_go'), }, { 'package': 'infra/tools/luci/swarming/${{platform}}', - 'version': 'git_revision:fdf05508e8a66c773a41521e0243c9d11b9a2a1c', + 'version': Var('luci_go'), }, ], 'dep_type': 'cipd', @@ -651,7 +662,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd138913917ce0c16c2932a3e02711477b123627c', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'c054e0f9d1d4c14c2aae10ea2f327376bb153f32', 'condition': 'checkout_linux', }, @@ -666,7 +677,7 @@ # For Linux and Chromium OS. 'src/third_party/cros_system_api': { - 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '93d4079d4050509c24798de6d9965d5b27e9d5ae', + 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '5b955bc9a56817c072582c41f9af5dab518bca7b', 'condition': 'checkout_linux', }, @@ -676,7 +687,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '2e00228777c06d325418473f8dee87a6272a5822', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '03ee2d619043c4bacf6b17c4d5cfb3cd607026be', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -902,7 +913,7 @@ }, 'src/third_party/libvpx/source/libvpx': - Var('chromium_git') + '/webm/libvpx.git' + '@' + '932f8fa04dc15f4adf16df37402556e8c4dc72e7', + Var('chromium_git') + '/webm/libvpx.git' + '@' + '418acaa0bd06e0666d5a55743e3a85b83c759619', 'src/third_party/libwebm/source': Var('chromium_git') + '/webm/libwebm.git' + '@' + 'e4931ebc0a816458c18a6734e91a4d1b5acd5c56', @@ -1008,7 +1019,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'c30ed73dd52ad9aa63b079e1fa41abd88468a034', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '2efdf1d56ab23366f091b4d93d814981b2a4df79', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1081,7 +1092,7 @@ 'packages': [ { 'package': 'chromium/third_party/r8', - 'version': 'gMAAlElX8RMw__5KOpk-Ckdx3XDyEXspJVslmnblsrgC', + 'version': 'D9fqCyfGhC3zMZFOE-4gzA0yox519Qd-DRgqnkqJuqgC', }, ], 'condition': 'checkout_android', @@ -1171,7 +1182,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '5b6cbd789b9b91b4e46dde883c9f2ecb31eddade', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'c60a77731d68c8648135372dbe54c92dfba731bd', + Var('webrtc_git') + '/src.git' + '@' + 'b47ccc38e771ecb37002c82e6b4d4129603ca3be', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1202,7 +1213,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@3dc3d8f696a7502baa0bb6ff9ffc8e07bb24ab98', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@3831c191677407b835025e24c1b7c681bfcc64cf', 'condition': 'checkout_src_internal', }, @@ -2259,44 +2270,6 @@ '-d', 'src/chrome/build', ], }, - # Pull luci-go binaries (isolate, swarming) using checked-in hashes. - # TODO(maruel): Remove, https://crbug.com/851596 - { - 'name': 'luci-go_win', - 'pattern': '.', - 'condition': 'host_os == "win"', - 'action': [ 'python', - 'src/third_party/depot_tools/download_from_google_storage.py', - '--no_resume', - '--no_auth', - '--bucket', 'chromium-luci', - '-d', 'src/tools/luci-go/win64', - ], - }, - { - 'name': 'luci-go_mac', - 'pattern': '.', - 'condition': 'host_os == "mac"', - 'action': [ 'python', - 'src/third_party/depot_tools/download_from_google_storage.py', - '--no_resume', - '--no_auth', - '--bucket', 'chromium-luci', - '-d', 'src/tools/luci-go/mac64', - ], - }, - { - 'name': 'luci-go_linux', - 'pattern': '.', - 'condition': 'host_os == "linux"', - 'action': [ 'python', - 'src/third_party/depot_tools/download_from_google_storage.py', - '--no_resume', - '--no_auth', - '--bucket', 'chromium-luci', - '-d', 'src/tools/luci-go/linux64', - ], - }, { 'name': 'apache_win32', 'pattern': '\\.sha1',
diff --git a/WATCHLISTS b/WATCHLISTS index f93d878..03f0ac9 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -61,9 +61,6 @@ 'android_lint': { 'filepath': 'build/android/lint/' }, - 'android_loading': { - 'filepath': 'tools/android/loading/' - }, 'android_media': { 'filepath': 'content/browser/media/android' \ '|content/renderer/media/android' \ @@ -1573,9 +1570,9 @@ }, 'test_runner': { 'filepath': 'components/test_runner/' \ - '|content/shell/(common|browser|renderer)/layout_test/' \ - '|content/test/layouttest_support.cc' \ - '|content/public/test/layouttest_support.h' \ + '|content/shell/(common|browser|renderer)/web_test/' \ + '|content/test/web_test_support.cc' \ + '|content/public/test/web_test_support.h' \ }, 'tests': { 'filepath': 'apitest|unittest|browsertest|uitest|chrome/test/', @@ -1686,6 +1683,7 @@ # Includes VR, AR, and XR. 'filepath': '/vr/'\ '|/xr'\ + '|isolated_xr_device'\ '|third_party/arcore'\ '|third_party/gvr'\ '|third_party/libovr'\ @@ -1786,8 +1784,6 @@ 'android_item_chooser_dialogs': ['juncai+watch@chromium.org', 'ortuno+watch@chromium.org'], 'android_lint': ['wnwen+watch@chromium.org'], - 'android_loading': ['gabadie+watch@chromium.org', - 'lizeb+watch-android-loading@chromium.org'], 'android_media': ['mlamouri+watch-media@chromium.org'], 'android_search_widget': ['tedchoc+watch@chromium.org', 'yusufo+watch@chromium.org'], @@ -2137,7 +2133,8 @@ 'cywang@chromium.org', 'vovoy@chromium.org'], 'crostini': ['crostini-ui@chromium.org'], - 'custom_tabs': ['lizeb+watch-custom-tabs@chromium.org', + 'custom_tabs': ['amalova+watch@chromium.org', + 'lizeb+watch-custom-tabs@chromium.org', 'peconn@chromium.org', 'peter@chromium.org', 'pshmakov@chromium.org'],
diff --git a/android_webview/browser/aw_autofill_client.cc b/android_webview/browser/aw_autofill_client.cc index 6ac1646..448262e 100644 --- a/android_webview/browser/aw_autofill_client.cc +++ b/android_webview/browser/aw_autofill_client.cc
@@ -150,7 +150,7 @@ void AwAutofillClient::ConfirmSaveCreditCardLocally( const autofill::CreditCard& card, bool show_prompt, - base::OnceClosure callback) { + LocalSaveCardPromptCallback callback) { NOTIMPLEMENTED(); } @@ -165,7 +165,7 @@ bool should_request_name_from_user, bool should_request_expiration_date_from_user, bool show_prompt, - UserAcceptedUploadCallback callback) { + UploadSaveCardPromptCallback callback) { NOTIMPLEMENTED(); }
diff --git a/android_webview/browser/aw_autofill_client.h b/android_webview/browser/aw_autofill_client.h index 7d498776..468382a 100644 --- a/android_webview/browser/aw_autofill_client.h +++ b/android_webview/browser/aw_autofill_client.h
@@ -91,9 +91,10 @@ MigrationDeleteCardCallback delete_local_card_callback) override; void ConfirmSaveAutofillProfile(const autofill::AutofillProfile& profile, base::OnceClosure callback) override; - void ConfirmSaveCreditCardLocally(const autofill::CreditCard& card, - bool show_prompt, - base::OnceClosure callback) override; + void ConfirmSaveCreditCardLocally( + const autofill::CreditCard& card, + bool show_prompt, + LocalSaveCardPromptCallback callback) override; void ConfirmAccountNameFixFlow( base::OnceCallback<void(const base::string16&)> callback) override; void ConfirmSaveCreditCardToCloud( @@ -102,7 +103,7 @@ bool should_request_name_from_user, bool should_request_expiration_date_from_user, bool show_prompt, - UserAcceptedUploadCallback callback) override; + UploadSaveCardPromptCallback callback) override; void ConfirmCreditCardFillAssist(const autofill::CreditCard& card, base::OnceClosure callback) override; bool HasCreditCardScanFeature() override;
diff --git a/android_webview/browser/state_serializer_unittest.cc b/android_webview/browser/state_serializer_unittest.cc index 8348785..5cdf3b6 100644 --- a/android_webview/browser/state_serializer_unittest.cc +++ b/android_webview/browser/state_serializer_unittest.cc
@@ -62,9 +62,28 @@ return entry; } +class AndroidWebViewStateSerializerTest : public testing::Test { + public: + AndroidWebViewStateSerializerTest() { + content::SetContentClient(&content_client_); + content::SetBrowserClientForTesting(&browser_client_); + } + + ~AndroidWebViewStateSerializerTest() override { + content::SetBrowserClientForTesting(nullptr); + content::SetContentClient(nullptr); + } + + private: + content::ContentClient content_client_; + content::ContentBrowserClient browser_client_; + + DISALLOW_COPY_AND_ASSIGN(AndroidWebViewStateSerializerTest); +}; + } // namespace -TEST(AndroidWebViewStateSerializerTest, TestHeaderSerialization) { +TEST_F(AndroidWebViewStateSerializerTest, TestHeaderSerialization) { base::Pickle pickle; internal::WriteHeaderToPickle(&pickle); @@ -73,7 +92,8 @@ EXPECT_GT(version, 0U); } -TEST(AndroidWebViewStateSerializerTest, TestLegacyVersionHeaderSerialization) { +TEST_F(AndroidWebViewStateSerializerTest, + TestLegacyVersionHeaderSerialization) { base::Pickle pickle; internal::WriteHeaderToPickle(internal::AW_STATE_VERSION_INITIAL, &pickle); @@ -82,8 +102,8 @@ EXPECT_EQ(version, internal::AW_STATE_VERSION_INITIAL); } -TEST(AndroidWebViewStateSerializerTest, - TestUnsupportedVersionHeaderSerialization) { +TEST_F(AndroidWebViewStateSerializerTest, + TestUnsupportedVersionHeaderSerialization) { base::Pickle pickle; internal::WriteHeaderToPickle(20000101, &pickle); @@ -92,13 +112,7 @@ EXPECT_EQ(version, 0U); } -TEST(AndroidWebViewStateSerializerTest, TestNavigationEntrySerialization) { - // This is required for NavigationEntry::Create. - content::ContentClient content_client; - content::SetContentClient(&content_client); - content::ContentBrowserClient browser_client; - content::SetBrowserClientForTesting(&browser_client); - +TEST_F(AndroidWebViewStateSerializerTest, TestNavigationEntrySerialization) { std::unique_ptr<content::NavigationEntry> entry(CreateNavigationEntry()); base::Pickle pickle; @@ -128,14 +142,8 @@ EXPECT_EQ(entry->GetHttpStatusCode(), copy->GetHttpStatusCode()); } -TEST(AndroidWebViewStateSerializerTest, - TestLegacyNavigationEntrySerialization) { - // This is required for NavigationEntry::Create. - content::ContentClient content_client; - content::SetContentClient(&content_client); - content::ContentBrowserClient browser_client; - content::SetBrowserClientForTesting(&browser_client); - +TEST_F(AndroidWebViewStateSerializerTest, + TestLegacyNavigationEntrySerialization) { std::unique_ptr<content::NavigationEntry> entry(CreateNavigationEntry()); base::Pickle pickle; @@ -166,13 +174,7 @@ EXPECT_EQ(entry->GetHttpStatusCode(), copy->GetHttpStatusCode()); } -TEST(AndroidWebViewStateSerializerTest, TestEmptyDataURLSerialization) { - // This is required for NavigationEntry::Create. - content::ContentClient content_client; - content::SetContentClient(&content_client); - content::ContentBrowserClient browser_client; - content::SetBrowserClientForTesting(&browser_client); - +TEST_F(AndroidWebViewStateSerializerTest, TestEmptyDataURLSerialization) { std::unique_ptr<content::NavigationEntry> entry( content::NavigationEntry::Create()); EXPECT_FALSE(entry->GetDataURLAsString()); @@ -189,13 +191,7 @@ EXPECT_FALSE(entry->GetDataURLAsString()); } -TEST(AndroidWebViewStateSerializerTest, TestHugeDataURLSerialization) { - // This is required for NavigationEntry::Create. - content::ContentClient content_client; - content::SetContentClient(&content_client); - content::ContentBrowserClient browser_client; - content::SetBrowserClientForTesting(&browser_client); - +TEST_F(AndroidWebViewStateSerializerTest, TestHugeDataURLSerialization) { std::unique_ptr<content::NavigationEntry> entry( content::NavigationEntry::Create()); string huge_data_url(1024 * 1024 * 20 - 1, 'd');
diff --git a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java index ddf7b3ff..abb8ac1 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java +++ b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
@@ -133,21 +133,6 @@ throw new RuntimeException("Cannot initialize WebView", e); } }); - - // Only run cleanup task on N+ since on earlier versions there are no extra pak files. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - // Cleanup task to remove unnecessary extra pak files (crbug.com/752510). - // TODO(zpeng): Remove cleanup code after at least M64 (crbug.com/756580). - AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { - File extraPaksDir = new File(PathUtils.getDataDirectory(), "paks"); - if (extraPaksDir.exists()) { - for (File pakFile : extraPaksDir.listFiles()) { - pakFile.delete(); - } - extraPaksDir.delete(); - } - }); - } } }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 889e364..03ed223 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -46,7 +46,6 @@ "frame/header_view.h", "frame/non_client_frame_view_ash.h", "frame/wide_frame_view.h", - "login/ui/lock_window.h", "magnifier/magnification_controller.h", # TODO: move MultiUserWindowManager (and delegate) to sources: @@ -355,6 +354,8 @@ "events/select_to_speak_event_handler.h", "events/spoken_feedback_event_rewriter.cc", "events/spoken_feedback_event_rewriter.h", + "events/switch_access_event_handler.cc", + "events/switch_access_event_handler.h", "first_run/desktop_cleaner.cc", "first_run/desktop_cleaner.h", "first_run/first_run_helper.cc", @@ -445,7 +446,6 @@ "login/ui/lock_debug_view.h", "login/ui/lock_screen.cc", "login/ui/lock_screen.h", - "login/ui/lock_window.cc", "login/ui/login_auth_user_view.cc", "login/ui/login_auth_user_view.h", "login/ui/login_base_bubble_view.cc", @@ -1334,6 +1334,7 @@ "//chromeos:power_manager_proto", "//chromeos/assistant:buildflags", "//chromeos/components/proximity_auth/logging", + "//chromeos/services/assistant/public:feature_flags", "//chromeos/services/assistant/public/mojom", "//chromeos/services/multidevice_setup/public/mojom", "//chromeos/strings", @@ -1674,6 +1675,7 @@ "events/keyboard_driven_event_rewriter_unittest.cc", "events/select_to_speak_event_handler_unittest.cc", "events/spoken_feedback_event_rewriter_unittest.cc", + "events/switch_access_event_handler_unittest.cc", "extended_desktop_unittest.cc", "first_run/first_run_helper_unittest.cc", "focus_cycler_unittest.cc",
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc index bcc1316..7656adf 100644 --- a/ash/accelerators/accelerator_controller.cc +++ b/ash/accelerators/accelerator_controller.cc
@@ -325,7 +325,7 @@ return !keyboard::KeyboardController::Get()->IsKeyboardVisible(); } -void HandleNextIme() { +void HandleSwitchToNextIme() { base::RecordAction(UserMetricsAction("Accel_Next_Ime")); RecordImeSwitchByAccelerator(); Shell::Get()->ime_controller()->SwitchToNextIme(); @@ -336,11 +336,11 @@ Shell::Get()->new_window_controller()->OpenFeedbackPage(); } -void HandlePreviousIme(const ui::Accelerator& accelerator) { +void HandleSwitchToLastUsedIme(const ui::Accelerator& accelerator) { base::RecordAction(UserMetricsAction("Accel_Previous_Ime")); if (accelerator.key_state() == ui::Accelerator::KeyState::PRESSED) { RecordImeSwitchByAccelerator(); - Shell::Get()->ime_controller()->SwitchToPreviousIme(); + Shell::Get()->ime_controller()->SwitchToLastUsedIme(); } // Else: consume the Ctrl+Space ET_KEY_RELEASED event but do not do anything. } @@ -1298,10 +1298,6 @@ CanHandleMoveActiveWindowBetweenDisplays(); case NEW_INCOGNITO_WINDOW: return CanHandleNewIncognitoWindow(); - case NEXT_IME: - return CanCycleInputMethod(); - case PREVIOUS_IME: - return CanCycleInputMethod(); case ROTATE_SCREEN: return true; case SCALE_UI_DOWN: @@ -1316,6 +1312,10 @@ return display::Screen::GetScreen()->GetNumDisplays() > 1; case SWITCH_IME: return CanHandleSwitchIme(accelerator); + case SWITCH_TO_NEXT_IME: + return CanCycleInputMethod(); + case SWITCH_TO_LAST_USED_IME: + return CanCycleInputMethod(); case SWITCH_TO_PREVIOUS_USER: case SWITCH_TO_NEXT_USER: return CanHandleCycleUser(); @@ -1561,9 +1561,6 @@ case NEW_WINDOW: HandleNewWindow(); break; - case NEXT_IME: - HandleNextIme(); - break; case OPEN_CROSH: HandleCrosh(); break; @@ -1589,9 +1586,6 @@ // D-BUS), but we consume them to prevent them from getting // passed to apps -- see http://crbug.com/146609. break; - case PREVIOUS_IME: - HandlePreviousIme(accelerator); - break; case PRINT_UI_HIERARCHIES: debug::PrintUIHierarchies(); break; @@ -1637,6 +1631,12 @@ case SWITCH_IME: HandleSwitchIme(accelerator); break; + case SWITCH_TO_LAST_USED_IME: + HandleSwitchToLastUsedIme(accelerator); + break; + case SWITCH_TO_NEXT_IME: + HandleSwitchToNextIme(); + break; case SWITCH_TO_NEXT_USER: HandleCycleUser(CycleUserDirection::NEXT); break;
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc index 115932ca..c56e29f8 100644 --- a/ash/accelerators/accelerator_controller_unittest.cc +++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -1364,7 +1364,8 @@ // Add below the new accelerators that replaced the deprecated ones (if any). const AcceleratorData kNewAccelerators[] = { {true, ui::VKEY_L, ui::EF_COMMAND_DOWN, LOCK_SCREEN}, - {true, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN, NEXT_IME}, + {true, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN, + SWITCH_TO_NEXT_IME}, {true, ui::VKEY_ESCAPE, ui::EF_COMMAND_DOWN, SHOW_TASK_MANAGER}, {true, ui::VKEY_K, ui::EF_SHIFT_DOWN | ui::EF_COMMAND_DOWN, SHOW_IME_MENU_BUBBLE}, @@ -1372,7 +1373,7 @@ TOGGLE_HIGH_CONTRAST}, }; - // The NEXT_IME accelerator requires multiple IMEs to be available. + // The SWITCH_TO_NEXT_IME accelerator requires multiple IMEs to be available. AddTestImes(); EXPECT_TRUE(IsMessageCenterEmpty());
diff --git a/ash/accelerators/accelerator_table.cc b/ash/accelerators/accelerator_table.cc index 8449a0e..3bd0f13 100644 --- a/ash/accelerators/accelerator_table.cc +++ b/ash/accelerators/accelerator_table.cc
@@ -153,14 +153,14 @@ KEYBOARD_BRIGHTNESS_UP, MAGNIFIER_ZOOM_IN, // Control+F7 MAGNIFIER_ZOOM_OUT, // Control+F6 - NEXT_IME, - PREVIOUS_IME, PRINT_UI_HIERARCHIES, ROTATE_SCREEN, SCALE_UI_DOWN, SCALE_UI_RESET, SCALE_UI_UP, SHOW_IME_MENU_BUBBLE, + SWITCH_TO_LAST_USED_IME, + SWITCH_TO_NEXT_IME, TAKE_PARTIAL_SCREENSHOT, TAKE_SCREENSHOT, TAKE_WINDOW_SCREENSHOT, @@ -216,11 +216,9 @@ MEDIA_NEXT_TRACK, MEDIA_PLAY_PAUSE, MEDIA_PREV_TRACK, - NEXT_IME, OPEN_FEEDBACK_PAGE, POWER_PRESSED, POWER_RELEASED, - PREVIOUS_IME, PRINT_UI_HIERARCHIES, ROTATE_SCREEN, SCALE_UI_DOWN, @@ -230,6 +228,8 @@ SHOW_SHORTCUT_VIEWER, SUSPEND, SWAP_PRIMARY_DISPLAY, + SWITCH_TO_LAST_USED_IME, + SWITCH_TO_NEXT_IME, TAKE_PARTIAL_SCREENSHOT, TAKE_SCREENSHOT, TAKE_WINDOW_SCREENSHOT, @@ -284,16 +284,16 @@ MEDIA_NEXT_TRACK, MEDIA_PLAY_PAUSE, MEDIA_PREV_TRACK, - NEXT_IME, POWER_PRESSED, POWER_RELEASED, - PREVIOUS_IME, PRINT_UI_HIERARCHIES, ROTATE_SCREEN, SCALE_UI_DOWN, SCALE_UI_RESET, SCALE_UI_UP, SWAP_PRIMARY_DISPLAY, + SWITCH_TO_LAST_USED_IME, + SWITCH_TO_NEXT_IME, TOGGLE_CAPS_LOCK, TOGGLE_DICTATION, TOGGLE_DOCKED_MAGNIFIER, @@ -349,9 +349,9 @@ MEDIA_NEXT_TRACK, MEDIA_PLAY_PAUSE, MEDIA_PREV_TRACK, - NEXT_IME, - PREVIOUS_IME, PRINT_UI_HIERARCHIES, + SWITCH_TO_LAST_USED_IME, + SWITCH_TO_NEXT_IME, TAKE_PARTIAL_SCREENSHOT, TAKE_SCREENSHOT, TAKE_WINDOW_SCREENSHOT,
diff --git a/ash/accelerators/accelerator_table_unittest.cc b/ash/accelerators/accelerator_table_unittest.cc index 2c80fb20..f8f13fd3 100644 --- a/ash/accelerators/accelerator_table_unittest.cc +++ b/ash/accelerators/accelerator_table_unittest.cc
@@ -20,7 +20,7 @@ constexpr int kNonSearchAcceleratorsNum = 89; // The hash of non-Search-based accelerators. See HashAcceleratorData(). constexpr char kNonSearchAcceleratorsHash[] = - "569da153a9c19edb92a8b30896bf0ff3"; + "bb35892635c794d78a20ff5f8a051aab"; struct Cmp { bool operator()(const AcceleratorData& lhs,
diff --git a/ash/accessibility/accessibility_controller.cc b/ash/accessibility/accessibility_controller.cc index 28e3579c..ddd0dd4 100644 --- a/ash/accessibility/accessibility_controller.cc +++ b/ash/accessibility/accessibility_controller.cc
@@ -13,6 +13,7 @@ #include "ash/accessibility/accessibility_panel_layout_manager.h" #include "ash/autoclick/autoclick_controller.h" #include "ash/events/select_to_speak_event_handler.h" +#include "ash/events/switch_access_event_handler.h" #include "ash/high_contrast/high_contrast_controller.h" #include "ash/policy/policy_recommendation_restorer.h" #include "ash/public/cpp/ash_pref_names.h" @@ -290,6 +291,8 @@ false); registry->RegisterBooleanPref(prefs::kAccessibilityStickyKeysEnabled, false); + registry->RegisterBooleanPref(prefs::kAccessibilitySwitchAccessEnabled, + false); registry->RegisterBooleanPref(prefs::kAccessibilityVirtualKeyboardEnabled, false); registry->RegisterBooleanPref( @@ -327,6 +330,7 @@ registry->RegisterForeignPref(prefs::kAccessibilitySpokenFeedbackEnabled); registry->RegisterForeignPref(prefs::kAccessibilitySelectToSpeakEnabled); registry->RegisterForeignPref(prefs::kAccessibilityStickyKeysEnabled); + registry->RegisterForeignPref(prefs::kAccessibilitySwitchAccessEnabled); registry->RegisterForeignPref(prefs::kAccessibilityVirtualKeyboardEnabled); registry->RegisterForeignPref( prefs::kHighContrastAcceleratorDialogHasBeenAccepted); @@ -570,6 +574,33 @@ return select_to_speak_state_; } +void AccessibilityController::SetSwitchAccessEnabled(bool enabled) { + if (!active_user_prefs_) + return; + active_user_prefs_->SetBoolean(prefs::kAccessibilitySwitchAccessEnabled, + enabled); + active_user_prefs_->CommitPendingWrite(); +} + +void AccessibilityController::SetSwitchAccessKeysToCapture( + const std::vector<int>& keys_to_capture) { + // Forward the keys to capture to switch_access_event_handler_. + if (switch_access_event_handler_) + switch_access_event_handler_->set_keys_to_capture(keys_to_capture); + NotifyAccessibilityStatusChanged(); +} + +void AccessibilityController::SetSwitchAccessIgnoreVirtualKeyEvent( + bool should_ignore) { + switch_access_event_handler_->set_ignore_virtual_key_events(should_ignore); +} + +void AccessibilityController::SetSwitchAccessEventHandlerDelegate( + mojom::SwitchAccessEventHandlerDelegatePtr delegate) { + switch_access_event_handler_delegate_ptr_ = std::move(delegate); + MaybeCreateSwitchAccessEventHandler(); +} + void AccessibilityController::SetStickyKeysEnabled(bool enabled) { if (!active_user_prefs_) return; @@ -751,6 +782,8 @@ client_.FlushForTesting(); if (select_to_speak_event_handler_) select_to_speak_event_handler_->FlushMojoForTest(); + if (switch_access_event_handler_) + switch_access_event_handler_->FlushMojoForTest(); } void AccessibilityController::OnTabletModeStarted() { @@ -844,6 +877,10 @@ base::BindRepeating(&AccessibilityController::UpdateStickyKeysFromPref, base::Unretained(this))); pref_change_registrar_->Add( + prefs::kAccessibilitySwitchAccessEnabled, + base::BindRepeating(&AccessibilityController::UpdateSwitchAccessFromPref, + base::Unretained(this))); + pref_change_registrar_->Add( prefs::kAccessibilityVirtualKeyboardEnabled, base::BindRepeating( &AccessibilityController::UpdateVirtualKeyboardFromPref, @@ -865,6 +902,7 @@ UpdateSpokenFeedbackFromPref(); UpdateSelectToSpeakFromPref(); UpdateStickyKeysFromPref(); + UpdateSwitchAccessFromPref(); UpdateVirtualKeyboardFromPref(); } @@ -1131,6 +1169,37 @@ Shell::Get()->sticky_keys_controller()->Enable(enabled); } +void AccessibilityController::UpdateSwitchAccessFromPref() { + DCHECK(active_user_prefs_); + const bool enabled = + active_user_prefs_->GetBoolean(prefs::kAccessibilitySwitchAccessEnabled); + if (switch_access_enabled_ == enabled) + return; + + switch_access_enabled_ = enabled; + + if (enabled) + MaybeCreateSwitchAccessEventHandler(); + else + switch_access_event_handler_.reset(); + + NotifyAccessibilityStatusChanged(); +} + +void AccessibilityController::MaybeCreateSwitchAccessEventHandler() { + // Sometimes the handler is not yet created if the prefs change has taken + // longer to propogate than setting the delegate from Chrome. + // Create the handler here; we only set the delegate when Switch Access has + // been enabled. + if (!switch_access_enabled_ || switch_access_event_handler_ || + !switch_access_event_handler_delegate_ptr_) { + return; + } + + switch_access_event_handler_ = std::make_unique<SwitchAccessEventHandler>( + std::move(switch_access_event_handler_delegate_ptr_)); +} + void AccessibilityController::UpdateVirtualKeyboardFromPref() { DCHECK(active_user_prefs_); const bool enabled = active_user_prefs_->GetBoolean(
diff --git a/ash/accessibility/accessibility_controller.h b/ash/accessibility/accessibility_controller.h index a66d082..37d01415 100644 --- a/ash/accessibility/accessibility_controller.h +++ b/ash/accessibility/accessibility_controller.h
@@ -28,6 +28,7 @@ class AccessibilityObserver; class ScopedBacklightsForcedOff; class SelectToSpeakEventHandler; +class SwitchAccessEventHandler; enum AccessibilityNotificationVisibility { A11Y_NOTIFICATION_NONE, @@ -108,6 +109,11 @@ void SetStickyKeysEnabled(bool enabled); bool sticky_keys_enabled() const { return sticky_keys_enabled_; } + void SetSwitchAccessEnabled(bool enabled); + bool switch_access_enabled() const { return switch_access_enabled_; } + + void SetSwitchAccessIgnoreVirtualKeyEvent(bool should_ignore); + void SetVirtualKeyboardEnabled(bool enabled); bool virtual_keyboard_enabled() const { return virtual_keyboard_enabled_; } @@ -170,6 +176,10 @@ void SetSelectToSpeakState(mojom::SelectToSpeakState state) override; void SetSelectToSpeakEventHandlerDelegate( mojom::SelectToSpeakEventHandlerDelegatePtr delegate) override; + void SetSwitchAccessKeysToCapture( + const std::vector<int>& keys_to_capture) override; + void SetSwitchAccessEventHandlerDelegate( + mojom::SwitchAccessEventHandlerDelegatePtr delegate) override; void ToggleDictationFromSource(mojom::DictationToggleSource source) override; // SessionObserver: @@ -203,10 +213,12 @@ void UpdateSpokenFeedbackFromPref(); void UpdateSelectToSpeakFromPref(); void UpdateStickyKeysFromPref(); + void UpdateSwitchAccessFromPref(); void UpdateVirtualKeyboardFromPref(); void UpdateAccessibilityHighlightingFromPrefs(); void MaybeCreateSelectToSpeakEventHandler(); + void MaybeCreateSwitchAccessEventHandler(); // The pref service of the currently active user or the signin profile before // user logs in. Can be null in ash_unittests. @@ -233,6 +245,7 @@ bool spoken_feedback_enabled_ = false; bool select_to_speak_enabled_ = false; bool sticky_keys_enabled_ = false; + bool switch_access_enabled_ = false; bool virtual_keyboard_enabled_ = false; bool dictation_active_ = false; @@ -242,6 +255,12 @@ mojom::SelectToSpeakEventHandlerDelegatePtr select_to_speak_event_handler_delegate_ptr_; + // List of key codes that Switch Access should capture. + std::vector<int> switch_access_keys_to_capture_; + std::unique_ptr<SwitchAccessEventHandler> switch_access_event_handler_; + mojom::SwitchAccessEventHandlerDelegatePtr + switch_access_event_handler_delegate_ptr_; + // Used to control the highlights of caret, cursor and focus. std::unique_ptr<AccessibilityHighlightController> accessibility_highlight_controller_;
diff --git a/ash/app_list/home_launcher_gesture_handler.cc b/ash/app_list/home_launcher_gesture_handler.cc index 8724b66..2d2615f0 100644 --- a/ash/app_list/home_launcher_gesture_handler.cc +++ b/ash/app_list/home_launcher_gesture_handler.cc
@@ -24,6 +24,7 @@ #include "base/metrics/user_metrics.h" #include "base/numerics/ranges.h" #include "ui/aura/client/window_types.h" +#include "ui/aura/null_window_targeter.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/animation/tween.h" #include "ui/gfx/geometry/rect_f.h" @@ -164,6 +165,103 @@ } // namespace +// Class which allows us to make modifications to a window, and removes those +// modifications on destruction. +// TODO(sammiequon): Move to separate file and add test for +// ComputeWindowValues. +class HomeLauncherGestureHandler::ScopedWindowModifier + : public aura::WindowObserver { + public: + explicit ScopedWindowModifier(aura::Window* window) : window_(window) { + DCHECK(window_); + original_targeter_ = + window_->SetEventTargeter(std::make_unique<aura::NullWindowTargeter>()); + } + ~ScopedWindowModifier() override { + for (const auto& descendant : transient_descendants_values_) + descendant.first->RemoveObserver(this); + + ResetOpacityAndTransform(); + window_->SetEventTargeter(std::move(original_targeter_)); + } + + bool IsAnimating() const { + if (window_->layer()->GetAnimator()->is_animating()) + return true; + + for (const auto& descendant : transient_descendants_values_) { + if (descendant.first->layer()->GetAnimator()->is_animating()) + return true; + } + + return false; + } + + void StopAnimating() { + window_->layer()->GetAnimator()->StopAnimating(); + for (const auto& descendant : transient_descendants_values_) { + descendant.first->layer()->GetAnimator()->StopAnimating(); + } + } + + void ResetOpacityAndTransform() { + window_->SetTransform(window_values_.initial_transform); + window_->layer()->SetOpacity(window_values_.initial_opacity); + } + + // Calculates the values for |window_| and its transient descendants. + void ComputeWindowValues(const gfx::RectF& work_area, + const gfx::RectF& target_work_area) { + transient_descendants_values_.clear(); + for (auto* window : wm::GetTransientTreeIterator(window_)) { + WindowValues values; + values.initial_opacity = window->layer()->opacity(); + values.initial_transform = window->transform(); + values.target_opacity = 0.f; + values.target_transform = CalculateTransform( + gfx::RectF(window->GetTargetBounds()), + GetOffscreenWindowBounds(window, work_area, target_work_area)); + if (window == window_) { + window_values_ = values; + continue; + } + + window->AddObserver(this); + transient_descendants_values_[window] = values; + } + } + + // aura::WindowObserver: + void OnWindowDestroying(aura::Window* window) override { + auto it = transient_descendants_values_.find(window); + DCHECK(it != transient_descendants_values_.end()); + + window->RemoveObserver(this); + transient_descendants_values_.erase(it); + } + + aura::Window* window() { return window_; } + WindowValues window_values() const { return window_values_; } + const std::map<aura::Window*, WindowValues>& transient_descendants_values() + const { + return transient_descendants_values_; + } + + private: + aura::Window* window_; + + // Original and target transform and opacity of |window_|. + WindowValues window_values_; + + // Tracks the transient descendants of |window_| and their initial and + // target opacities and transforms. + std::map<aura::Window*, WindowValues> transient_descendants_values_; + + std::unique_ptr<aura::WindowTargeter> original_targeter_; + + DISALLOW_COPY_AND_ASSIGN(ScopedWindowModifier); +}; + HomeLauncherGestureHandler::HomeLauncherGestureHandler( AppListControllerImpl* app_list_controller) : app_list_controller_(app_list_controller) { @@ -216,10 +314,10 @@ return false; if (!IsDragInProgress()) { - if (window_) { - // |window_| may not be nullptr when this release event is triggered by - // opening |window_| with modal dialog in OnPressEvent(). In that case, - // just leave the |window_| in show state and stop tracking. + if (GetWindow1()) { + // |window1_| may not be nullptr when this release event is triggered + // by opening |window1_| with modal dialog in OnPressEvent(). In that + // case, just leave the |window1_| in show state and stop tracking. AnimateToFinalState(); RemoveObserversAndStopTracking(); return true; @@ -279,8 +377,20 @@ return true; } +aura::Window* HomeLauncherGestureHandler::GetWindow1() { + if (!window1_) + return nullptr; + return window1_->window(); +} + +aura::Window* HomeLauncherGestureHandler::GetWindow2() { + if (!window2_) + return nullptr; + return window2_->window(); +} + void HomeLauncherGestureHandler::OnWindowDestroying(aura::Window* window) { - if (window == window_) { + if (window1_ && window == GetWindow1()) { for (auto* hidden_window : hidden_windows_) hidden_window->Show(); @@ -288,24 +398,10 @@ return; } - if (window == window2_) { - DCHECK(window_); + if (window2_ && window == GetWindow2()) { + DCHECK(window1_); window->RemoveObserver(this); - window2_ = nullptr; - return; - } - - if (transient_descendants_values_.find(window) != - transient_descendants_values_.end()) { - window->RemoveObserver(this); - transient_descendants_values_.erase(window); - return; - } - - if (transient_descendants_values2_.find(window) != - transient_descendants_values2_.end()) { - window->RemoveObserver(this); - transient_descendants_values2_.erase(window); + window2_.reset(); return; } @@ -322,16 +418,11 @@ // When leaving tablet mode advance to the end of the in progress scroll // session or animation. StopObservingImplicitAnimations(); - if (window_) - window_->layer()->GetAnimator()->StopAnimating(); + if (window1_) + window1_->StopAnimating(); if (window2_) - window2_->layer()->GetAnimator()->StopAnimating(); - for (const auto& descendant : transient_descendants_values_) - descendant.first->layer()->GetAnimator()->StopAnimating(); - for (const auto& descendant : transient_descendants_values2_) - descendant.first->layer()->GetAnimator()->StopAnimating(); - UpdateWindows(IsFinalStateShow() ? 1.0 : 0.0, - /*animate=*/false); + window2_->StopAnimating(); + UpdateWindows(IsFinalStateShow() ? 1.0 : 0.0, /*animate=*/false); OnImplicitAnimationsCompleted(); } @@ -340,9 +431,9 @@ const bool is_final_state_show = IsFinalStateShow(); if (Shell::Get()->window_selector_controller()->IsSelecting()) { if (is_final_state_show) { - // Exit overview if event is released on the top half. This will also end - // splitview if it is active as SplitViewController observes overview mode - // ends. + // Exit overview if event is released on the top half. This will also + // end splitview if it is active as SplitViewController observes + // overview mode ends. Shell::Get()->window_selector_controller()->ToggleOverview( WindowSelector::EnterExitOverviewType::kSwipeFromShelf); } else { @@ -356,7 +447,7 @@ app_list_controller_->presenter()->UpdateYPositionAndOpacityForHomeLauncher( display_.work_area().y(), app_list_opacity, base::NullCallback()); - if (!window_) { + if (!window1_) { RemoveObserversAndStopTracking(); return; } @@ -367,22 +458,19 @@ Shell::Get()->split_view_controller()->EndSplitView(); } - window_->SetTransform(window_values_.initial_transform); - window_->layer()->SetOpacity(window_values_.initial_opacity); - if (window2_) { - window2_->SetTransform(window_values2_.initial_transform); - window2_->layer()->SetOpacity(window_values2_.initial_opacity); - } + window1_->ResetOpacityAndTransform(); + if (window2_) + window2_->ResetOpacityAndTransform(); if (is_final_state_show) { - ScopedAnimationDisabler disable(window_); - window_->Hide(); - wm::GetWindowState(window_)->Minimize(); + ScopedAnimationDisabler disable(GetWindow1()); + GetWindow1()->Hide(); + wm::GetWindowState(GetWindow1())->Minimize(); if (window2_) { - ScopedAnimationDisabler disable(window2_); - window2_->Hide(); - wm::GetWindowState(window2_)->Minimize(); + ScopedAnimationDisabler disable(GetWindow2()); + GetWindow2()->Hide(); + wm::GetWindowState(GetWindow2())->Minimize(); } // Minimize the hidden windows so they can be used normally with alt+tab @@ -401,9 +489,9 @@ } } - // Update the backdrop last as the backdrop controller listens for some state - // changes like minimizing above which may also alter the backdrop. - aura::Window* backdrop_window = GetBackdropWindow(window_); + // Update the backdrop last as the backdrop controller listens for some + // state changes like minimizing above which may also alter the backdrop. + aura::Window* backdrop_window = GetBackdropWindow(GetWindow1()); if (backdrop_window) { backdrop_window->SetTransform(gfx::Transform()); backdrop_window->layer()->SetOpacity(1.f); @@ -467,7 +555,7 @@ : base::NullCallback()); } - if (!window_) + if (!window1_) return; // Helper to update a single windows opacity and transform based on by @@ -485,19 +573,20 @@ settings = std::make_unique<ui::ScopedLayerAnimationSettings>( window->layer()->GetAnimator()); // There are multiple animations run on a release event (app list, - // overview and the stored windows). We only want to act on one animation - // end, so only observe one of the animations. If overview is active, - // observe the shield widget of the grid, else observe |window_|. + // overview and the stored windows). We only want to act on one + // animation end, so only observe one of the animations. If overview + // is active, observe the shield widget of the grid, else observe + // |window1_|. UpdateSettings( settings.get(), - this->window_ == window && + this->GetWindow1() == window && !Shell::Get()->window_selector_controller()->IsSelecting()); } window->layer()->SetOpacity(opacity); window->SetTransform(transform); }; - aura::Window* backdrop_window = GetBackdropWindow(window_); + aura::Window* backdrop_window = GetBackdropWindow(GetWindow1()); if (backdrop_window && backdrop_values_) { update_windows_helper(progress, animate, backdrop_window, *backdrop_values_); @@ -508,19 +597,21 @@ update_windows_helper(progress, animate, divider_window, *divider_values_); } - for (const auto& descendant : transient_descendants_values_) { + if (window2_) { + for (const auto& descendant : window2_->transient_descendants_values()) { + update_windows_helper(progress, animate, descendant.first, + descendant.second); + } + update_windows_helper(progress, animate, GetWindow2(), + window2_->window_values()); + } + + for (const auto& descendant : window1_->transient_descendants_values()) { update_windows_helper(progress, animate, descendant.first, descendant.second); } - - for (const auto& descendant : transient_descendants_values2_) { - update_windows_helper(progress, animate, descendant.first, - descendant.second); - } - - if (window2_) - update_windows_helper(progress, animate, window2_, window_values2_); - update_windows_helper(progress, animate, window_, window_values_); + update_windows_helper(progress, animate, GetWindow1(), + window1_->window_values()); } void HomeLauncherGestureHandler::RemoveObserversAndStopTracking() { @@ -535,21 +626,13 @@ window->RemoveObserver(this); hidden_windows_.clear(); - for (const auto& descendant : transient_descendants_values_) - descendant.first->RemoveObserver(this); - transient_descendants_values_.clear(); - - if (window_) - window_->RemoveObserver(this); - window_ = nullptr; - - for (const auto& descendant : transient_descendants_values2_) - descendant.first->RemoveObserver(this); - transient_descendants_values2_.clear(); + if (window1_) + GetWindow1()->RemoveObserver(this); + window1_.reset(); if (window2_) - window2_->RemoveObserver(this); - window2_ = nullptr; + GetWindow2()->RemoveObserver(this); + window2_.reset(); } bool HomeLauncherGestureHandler::IsIdle() { @@ -557,22 +640,12 @@ } bool HomeLauncherGestureHandler::IsAnimating() { - if (window_ && window_->layer()->GetAnimator()->is_animating()) + if (window1_ && window1_->IsAnimating()) return true; - if (window2_ && window2_->layer()->GetAnimator()->is_animating()) + if (window2_ && window2_->IsAnimating()) return true; - for (const auto& descendant : transient_descendants_values_) { - if (descendant.first->layer()->GetAnimator()->is_animating()) - return true; - } - - for (const auto& descendant : transient_descendants_values2_) { - if (descendant.first->layer()->GetAnimator()->is_animating()) - return true; - } - if (Shell::Get()->window_selector_controller()->IsSelecting() && Shell::Get() ->window_selector_controller() @@ -615,119 +688,98 @@ auto windows = Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(); if (window && (mode != Mode::kSlideDownToHide || overview_active || split_view_active)) { - window_ = nullptr; + window1_.reset(); return false; } if (window && !windows.empty() && windows[0] != window && windows[0]->IsVisible()) { - // Do not run slide down animation for the |window| if another active window - // in mru list exists. - window_ = nullptr; + // Do not run slide down animation for the |window| if another active + // window in mru list exists. + window1_.reset(); return false; } if (IsTabletMode() && overview_active && !split_view_active) { DCHECK_EQ(Mode::kSlideUpToShow, mode); - window_ = nullptr; + window1_.reset(); return true; } - // Always hide split view windows if they exist. Otherwise, hide the specified - // window if it is not null. If non of above is true, we want the first window - // in the mru list, if it exists and is usable. - window_ = split_view_active - ? split_view_controller->GetDefaultSnappedWindow() - : (window ? window : (windows.empty() ? nullptr : windows[0])); - if (!CanProcessWindow(window_, mode)) { - window_ = nullptr; + // Always hide split view windows if they exist. Otherwise, hide the + // specified window if it is not null. If none of above is true, we want + // the first window in the mru list, if it exists and is usable. + aura::Window* first_window = + split_view_active + ? split_view_controller->GetDefaultSnappedWindow() + : (window ? window : (windows.empty() ? nullptr : windows[0])); + if (!CanProcessWindow(first_window, mode)) { + window1_.reset(); return false; } - DCHECK(base::ContainsValue(windows, window_)); + DCHECK(base::ContainsValue(windows, first_window)); DCHECK_NE(Mode::kNone, mode); base::RecordAction(base::UserMetricsAction( mode == Mode::kSlideDownToHide ? "AppList_HomeLauncherToMRUWindowAttempt" : "AppList_CurrentWindowToHomeLauncherAttempt")); - window_->AddObserver(this); - base::EraseIf(windows, - [this](aura::Window* elem) { return elem == this->window_; }); + window1_ = std::make_unique<ScopedWindowModifier>(first_window); + GetWindow1()->AddObserver(this); + base::EraseIf(windows, [this](aura::Window* elem) { + return elem == this->GetWindow1(); + }); // Alter a second window if we are in split view mode with two windows // snapped. if (mode == Mode::kSlideUpToShow && split_view_controller->state() == SplitViewController::BOTH_SNAPPED) { DCHECK_GT(windows.size(), 0u); - window2_ = split_view_controller->default_snap_position() == - SplitViewController::LEFT - ? split_view_controller->right_window() - : split_view_controller->left_window(); - DCHECK(base::ContainsValue(windows, window2_)); - window2_->AddObserver(this); - base::EraseIf( - windows, [this](aura::Window* elem) { return elem == this->window2_; }); + aura::Window* second_window = + split_view_controller->default_snap_position() == + SplitViewController::LEFT + ? split_view_controller->right_window() + : split_view_controller->left_window(); + DCHECK(base::ContainsValue(windows, second_window)); + window2_ = std::make_unique<ScopedWindowModifier>(second_window); + GetWindow2()->AddObserver(this); + base::EraseIf(windows, [this](aura::Window* elem) { + return elem == this->GetWindow2(); + }); } - // Show |window_| if we are swiping down to hide. + // Show |window1_| if we are swiping down to hide. if (mode == Mode::kSlideDownToHide) { - ScopedAnimationDisabler disable(window_); - window_->Show(); + ScopedAnimationDisabler disable(GetWindow1()); + GetWindow1()->Show(); - // When |window_| has a modal dialog child, window_->Show() above would + // When |window1_| has a modal dialog child, window1_->Show() above would // cancel the current gesture and trigger OnReleaseEvent() to reset - // |window_|. - if (!window_) + // |window1_|. + if (!window1_ || !GetWindow1()) return false; - wm::ActivateWindow(window_); - window_->layer()->SetOpacity(1.f); + wm::ActivateWindow(GetWindow1()); + GetWindow1()->layer()->SetOpacity(1.f); } const gfx::RectF work_area = - gfx::RectF(screen_util::GetDisplayWorkAreaBoundsInParent(window_)); + gfx::RectF(screen_util::GetDisplayWorkAreaBoundsInParent(GetWindow1())); const gfx::RectF target_work_area = GetOffscreenWorkspaceBounds(work_area); - // Helper function that calculates the values for |window| and its transient - // descendants. - auto compute_window_values = - [this, &work_area, &target_work_area]( - aura::Window* window, WindowValues* out_window_values, - std::map<aura::Window*, WindowValues>* out_transient_values) { - out_transient_values->clear(); - for (auto* it : wm::GetTransientTreeIterator(window)) { - WindowValues values; - values.initial_opacity = it->layer()->opacity(); - values.initial_transform = it->transform(); - values.target_opacity = 0.f; - values.target_transform = CalculateTransform( - gfx::RectF(it->GetTargetBounds()), - GetOffscreenWindowBounds(it, work_area, target_work_area)); - if (it == window) { - *out_window_values = values; - continue; - } + window1_->ComputeWindowValues(work_area, target_work_area); + if (window2_) + window2_->ComputeWindowValues(work_area, target_work_area); - it->AddObserver(this); - (*out_transient_values)[it] = values; - } - }; - - compute_window_values(window_, &window_values_, - &transient_descendants_values_); - if (window2_) { - compute_window_values(window2_, &window_values2_, - &transient_descendants_values2_); - } - - aura::Window* backdrop_window = GetBackdropWindow(window_); + aura::Window* backdrop_window = GetBackdropWindow(GetWindow1()); if (backdrop_window) { - // Store the values needed to transform the backdrop. The backdrop actually - // covers the area behind the shelf as well, so initially transform it to be - // sized to the work area. Without the transform tweak, there is an extra - // shelf sized black area under |window_|. Go to 0.01 opacity instead of 0 - // opacity otherwise animation end code will attempt to update the backdrop - // which will try to show a 0 opacity window which causes a crash. + // Store the values needed to transform the backdrop. The backdrop + // actually covers the area behind the shelf as well, so initially + // transform it to be sized to the work area. Without the transform + // tweak, there is an extra shelf sized black area under |window1_|. Go + // to 0.01 opacity instead of 0 opacity otherwise animation end code + // will attempt to update the backdrop which will try to show a 0 + // opacity window which causes a crash. backdrop_values_ = base::make_optional(WindowValues()); backdrop_values_->initial_opacity = 1.f; backdrop_values_->initial_transform = gfx::Transform( @@ -753,8 +805,8 @@ } // Hide all visible windows which are behind our window so that when we - // scroll, the home launcher will be visible. This is only needed when swiping - // up, and not when overview mode is active. + // scroll, the home launcher will be visible. This is only needed when + // swiping up, and not when overview mode is active. hidden_windows_.clear(); if (mode == Mode::kSlideUpToShow && !overview_active) { for (auto* window : windows) {
diff --git a/ash/app_list/home_launcher_gesture_handler.h b/ash/app_list/home_launcher_gesture_handler.h index f0ec8472..cacd6d6d 100644 --- a/ash/app_list/home_launcher_gesture_handler.h +++ b/ash/app_list/home_launcher_gesture_handler.h
@@ -29,9 +29,10 @@ // Additionally hides windows which may block the home launcher. All // modifications are either transitioned to their final state, or back to their // initial state on release event. -class ASH_EXPORT HomeLauncherGestureHandler : aura::WindowObserver, - TabletModeObserver, - ui::ImplicitAnimationObserver { +class ASH_EXPORT HomeLauncherGestureHandler + : public aura::WindowObserver, + public TabletModeObserver, + public ui::ImplicitAnimationObserver { public: // Enum which tracks which mode the current scroll process is in. enum class Mode { @@ -66,6 +67,10 @@ bool HideHomeLauncherForWindow(const display::Display& display, aura::Window* window); + // Returns the windows being tracked. May be null. + aura::Window* GetWindow1(); + aura::Window* GetWindow2(); + bool IsDragInProgress() const { return last_event_location_.has_value(); } // TODO(sammiequon): Investigate if it is needed to observe potential window @@ -80,14 +85,13 @@ void OnImplicitAnimationsCompleted() override; Mode mode() const { return mode_; } - aura::Window* window() { return window_; } - aura::Window* window2() { return window2_; } private: + class ScopedWindowModifier; FRIEND_TEST_ALL_PREFIXES(HomeLauncherModeGestureHandlerTest, AnimatingToEndResetsState); - // Stores the initial and target opacities and transforms of a window. + // Stores the initial and target opacities and transforms of window. struct WindowValues { float initial_opacity; float target_opacity; @@ -133,18 +137,8 @@ // The windows we are tracking. They are null if a drag is not underway, or if // overview without splitview is active. |window2_| is the secondary window // for splitview and is always null if |window1_| is null. - aura::Window* window_ = nullptr; - aura::Window* window2_ = nullptr; - - // Original and target transform and opacity of |window_| and |window2_|. - WindowValues window_values_; - WindowValues window_values2_; - - // Tracks the transient descendants of |window_| and their initial and target - // opacities and transforms. - std::map<aura::Window*, WindowValues> transient_descendants_values_; - // Transient descendants of |window2_|. - std::map<aura::Window*, WindowValues> transient_descendants_values2_; + std::unique_ptr<ScopedWindowModifier> window1_; + std::unique_ptr<ScopedWindowModifier> window2_; // Original and target transform and opacity of the backdrop window. Empty if // there is no backdrop on mouse pressed.
diff --git a/ash/app_list/home_launcher_gesture_handler_unittest.cc b/ash/app_list/home_launcher_gesture_handler_unittest.cc index 6c5e3b0..4617821 100644 --- a/ash/app_list/home_launcher_gesture_handler_unittest.cc +++ b/ash/app_list/home_launcher_gesture_handler_unittest.cc
@@ -68,26 +68,26 @@ // none in the mru list. TEST_F(HomeLauncherGestureHandlerTest, NeedsOneWindowToShow) { DoPress(Mode::kSlideUpToShow); - EXPECT_FALSE(GetGestureHandler()->window()); + EXPECT_FALSE(GetGestureHandler()->GetWindow1()); auto window = CreateWindowForTesting(); DoPress(Mode::kSlideUpToShow); - EXPECT_TRUE(GetGestureHandler()->window()); + EXPECT_TRUE(GetGestureHandler()->GetWindow1()); } // Tests that the gesture handler will not have a window to act on if there are // none in the mru list, or if they are not minimized. TEST_F(HomeLauncherGestureHandlerTest, NeedsOneMinimizedWindowToHide) { DoPress(Mode::kSlideDownToHide); - EXPECT_FALSE(GetGestureHandler()->window()); + EXPECT_FALSE(GetGestureHandler()->GetWindow1()); auto window = CreateWindowForTesting(); DoPress(Mode::kSlideDownToHide); - EXPECT_FALSE(GetGestureHandler()->window()); + EXPECT_FALSE(GetGestureHandler()->GetWindow1()); wm::GetWindowState(window.get())->Minimize(); DoPress(Mode::kSlideDownToHide); - EXPECT_TRUE(GetGestureHandler()->window()); + EXPECT_TRUE(GetGestureHandler()->GetWindow1()); } // Tests that if there are other visible windows behind the most recent one, @@ -204,7 +204,7 @@ const int window2_initial_translation = window2->transform().To2dTranslation().y(); DoPress(Mode::kSlideUpToShow); - EXPECT_FALSE(GetGestureHandler()->window()); + EXPECT_FALSE(GetGestureHandler()->GetWindow1()); // Tests that while scrolling the window transform changes. GetGestureHandler()->OnScrollEvent(gfx::Point(0, 300), 1.f); @@ -252,7 +252,7 @@ const int window2_initial_translation = window2->transform().To2dTranslation().y(); DoPress(Mode::kSlideUpToShow); - EXPECT_EQ(window1.get(), GetGestureHandler()->window()); + EXPECT_EQ(window1.get(), GetGestureHandler()->GetWindow1()); // Tests that while scrolling the window transforms change. GetGestureHandler()->OnScrollEvent(gfx::Point(0, 300), 1.f); @@ -298,8 +298,8 @@ // HomeLauncherGestureHandler. ::wm::ActivateWindow(window1.get()); DoPress(Mode::kSlideUpToShow); - EXPECT_EQ(window1.get(), GetGestureHandler()->window()); - EXPECT_EQ(window2.get(), GetGestureHandler()->window2()); + EXPECT_EQ(window1.get(), GetGestureHandler()->GetWindow1()); + EXPECT_EQ(window2.get(), GetGestureHandler()->GetWindow2()); // Tests that while scrolling the window transforms change. GetGestureHandler()->OnScrollEvent(gfx::Point(0, 300), 1.f); @@ -355,7 +355,7 @@ auto window = CreateWindowForTesting(); DoPress(mode_); - ASSERT_TRUE(GetGestureHandler()->window()); + ASSERT_TRUE(GetGestureHandler()->GetWindow1()); // Test that on scrolling to a point on the top half of the work area, the // window's opacity is between 0 and 0.5 and its transform has changed. @@ -383,7 +383,7 @@ auto window1 = CreateWindowForTesting(); DoPress(mode_); - ASSERT_TRUE(GetGestureHandler()->window()); + ASSERT_TRUE(GetGestureHandler()->GetWindow1()); ASSERT_FALSE(window2->IsVisible()); ASSERT_FALSE(window3->IsVisible()); @@ -415,7 +415,7 @@ auto window1 = CreateWindowForTesting(); DoPress(mode_); - ASSERT_TRUE(GetGestureHandler()->window()); + ASSERT_TRUE(GetGestureHandler()->GetWindow1()); ASSERT_FALSE(window2->IsVisible()); ASSERT_FALSE(window3->IsVisible()); @@ -443,7 +443,7 @@ // |parent| should be the window that is getting hidden. DoPress(mode_); - ASSERT_EQ(parent.get(), GetGestureHandler()->window()); + ASSERT_EQ(parent.get(), GetGestureHandler()->GetWindow1()); // Tests that after scrolling to the halfway point, the transient child's // opacity and transform are halfway to their final values. @@ -465,17 +465,17 @@ auto window = CreateWindowForTesting(); DoPress(mode_); - ASSERT_TRUE(GetGestureHandler()->window()); + ASSERT_TRUE(GetGestureHandler()->GetWindow1()); // Scroll to a point above the halfway mark of the work area. GetGestureHandler()->OnScrollEvent(gfx::Point(0, 50), 1.f); - EXPECT_TRUE(GetGestureHandler()->window()); + EXPECT_TRUE(GetGestureHandler()->GetWindow1()); EXPECT_FALSE(wm::GetWindowState(window.get())->IsMinimized()); // Tests that on exiting tablet mode, |window| gets minimized and is no longer // tracked by the gesture handler. Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(false); - EXPECT_FALSE(GetGestureHandler()->window()); + EXPECT_FALSE(GetGestureHandler()->GetWindow1()); EXPECT_TRUE(wm::GetWindowState(window.get())->IsMinimized()); } @@ -498,22 +498,20 @@ // Tests that the variables which change when dragging are as expected. DoPress(mode_); - EXPECT_EQ(window1.get(), GetGestureHandler()->window()); + EXPECT_EQ(window1.get(), GetGestureHandler()->GetWindow1()); EXPECT_TRUE(GetGestureHandler()->last_event_location_); EXPECT_EQ(mode_, GetGestureHandler()->mode_); // We only need to hide windows when swiping up, so this will only be non // empty in that case. if (mode_ == Mode::kSlideUpToShow) EXPECT_FALSE(GetGestureHandler()->hidden_windows_.empty()); - EXPECT_FALSE(GetGestureHandler()->transient_descendants_values_.empty()); // Tests that after a drag, the variables are either null or empty. GetGestureHandler()->OnReleaseEvent(gfx::Point(10, 10)); - EXPECT_FALSE(GetGestureHandler()->window()); + EXPECT_FALSE(GetGestureHandler()->GetWindow1()); EXPECT_FALSE(GetGestureHandler()->last_event_location_); EXPECT_EQ(Mode::kNone, GetGestureHandler()->mode_); EXPECT_TRUE(GetGestureHandler()->hidden_windows_.empty()); - EXPECT_TRUE(GetGestureHandler()->transient_descendants_values_.empty()); } } // namespace ash
diff --git a/ash/app_list/views/apps_grid_view.cc b/ash/app_list/views/apps_grid_view.cc index 20fe92b..95aade0 100644 --- a/ash/app_list/views/apps_grid_view.cc +++ b/ash/app_list/views/apps_grid_view.cc
@@ -2194,15 +2194,21 @@ display::Screen::GetScreen()->GetDisplayNearestView( GetWidget()->GetNativeView()); - const int kBottomDragBufferMin = - GetBoundsInScreen().bottom() - - (AppListConfig::instance().page_flip_zone_size()); const int kBottomDragBufferMax = display.bounds().bottom() - (contents_view_->app_list_view()->is_side_shelf() ? 0 : (display.bounds().bottom() - display.work_area().bottom())); + // The minimum y position is the bottom of this view, which is sometimes + // transformed for display zoom. + gfx::RectF transformed_bounds_in_screen = gfx::RectF(GetBoundsInScreen()); + GetTransform().TransformRect(&transformed_bounds_in_screen); + const int kBottomDragBufferMin = transformed_bounds_in_screen.bottom(); + + DCHECK_GE(kBottomDragBufferMax - kBottomDragBufferMin, + AppListConfig::instance().page_flip_zone_size()); + return point_in_screen.y() > kBottomDragBufferMin && point_in_screen.y() < kBottomDragBufferMax; }
diff --git a/ash/app_list/views/apps_grid_view_unittest.cc b/ash/app_list/views/apps_grid_view_unittest.cc index bb884e25..428cb04 100644 --- a/ash/app_list/views/apps_grid_view_unittest.cc +++ b/ash/app_list/views/apps_grid_view_unittest.cc
@@ -1016,7 +1016,7 @@ gfx::Point from = GetItemRectOnCurrentPageAt(0, 0).CenterPoint(); gfx::Point to; const gfx::Rect apps_grid_bounds = apps_grid_view_->GetLocalBounds(); - to = gfx::Point(apps_grid_bounds.width() / 2, apps_grid_bounds.bottom()); + to = gfx::Point(apps_grid_bounds.width() / 2, apps_grid_bounds.bottom() + 1); // For fullscreen/bubble launcher, drag to the bottom/right of bounds. page_flip_waiter.Reset(); @@ -1113,7 +1113,7 @@ const gfx::Rect apps_grid_bounds = apps_grid_view_->GetLocalBounds(); gfx::Point point_in_page_flip_buffer = gfx::Point(apps_grid_bounds.width() / 2, - next_page ? apps_grid_bounds.bottom() : 0); + next_page ? apps_grid_bounds.bottom() + 1 : 0); // Build the drag event which will be triggered after page flip. gfx::Point root_to(to);
diff --git a/ash/app_list/views/folder_header_view.cc b/ash/app_list/views/folder_header_view.cc index 488b390..22eccc2 100644 --- a/ash/app_list/views/folder_header_view.cc +++ b/ash/app_list/views/folder_header_view.cc
@@ -44,6 +44,7 @@ void OnFocus() override { SetText(base::UTF8ToUTF16(folder_header_view_->folder_item_->name())); + folder_header_view_->previous_folder_name_ = text(); SelectAll(false); Textfield::OnFocus(); } @@ -221,10 +222,15 @@ folder_item_->RemoveObserver(this); // Enforce the maximum folder name length in UI. - std::string name = base::UTF16ToUTF8( - folder_name_view_->text().substr(0, kMaxFolderNameChars)); - if (name != folder_item_->name()) - delegate_->SetItemName(folder_item_, name); + if (new_contents.length() > kMaxFolderNameChars) { + folder_name_view_->SetText(previous_folder_name_.value()); + sender->SelectRange(gfx::Range(previous_cursor_position_.value(), + previous_cursor_position_.value())); + } else { + previous_folder_name_ = new_contents; + delegate_->SetItemName(folder_item_, base::UTF16ToUTF8(new_contents)); + } + folder_item_->AddObserver(this); UpdateFolderNameAccessibleName(); @@ -245,8 +251,22 @@ return ProcessLeftRightKeyTraversalForTextfield(folder_name_view_, key_event); } +void FolderHeaderView::OnBeforeUserAction(views::Textfield* sender) { + previous_cursor_position_ = sender->GetCursorPosition(); +} + void FolderHeaderView::ItemNameChanged() { Update(); } +void FolderHeaderView::SetPreviousCursorPositionForTest( + const size_t cursor_position) { + previous_cursor_position_ = cursor_position; +} + +void FolderHeaderView::SetPreviousFolderNameForTest( + const base::string16& previous_name) { + previous_folder_name_ = previous_name; +} + } // namespace app_list
diff --git a/ash/app_list/views/folder_header_view.h b/ash/app_list/views/folder_header_view.h index 082726e..46fa07a 100644 --- a/ash/app_list/views/folder_header_view.h +++ b/ash/app_list/views/folder_header_view.h
@@ -72,10 +72,25 @@ const base::string16& new_contents) override; bool HandleKeyEvent(views::Textfield* sender, const ui::KeyEvent& key_event) override; + void OnBeforeUserAction(views::Textfield* sender) override; // AppListItemObserver overrides: void ItemNameChanged() override; + // Sets the |previous_cursor_position_|, only for testing use + void SetPreviousCursorPositionForTest(const size_t cursor_position); + + // Sets the |previous_folder_name_|, only for testing use + void SetPreviousFolderNameForTest(const base::string16& previous_name); + + // Used to restore the folder name if the new folder name is longer than the + // max chars folder length allowed + base::Optional<base::string16> previous_folder_name_; + + // Used to restore the cursor position to its last known location when + // resetting the folder name in textfield + base::Optional<size_t> previous_cursor_position_; + AppListFolderItem* folder_item_; // Not owned. FolderNameView* folder_name_view_; // Owned by views hierarchy.
diff --git a/ash/app_list/views/folder_header_view_unittest.cc b/ash/app_list/views/folder_header_view_unittest.cc index d37b3fc..41d16327 100644 --- a/ash/app_list/views/folder_header_view_unittest.cc +++ b/ash/app_list/views/folder_header_view_unittest.cc
@@ -20,6 +20,7 @@ #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/views/controls/textfield/textfield.h" #include "ui/views/test/views_test_base.h" namespace app_list { @@ -73,11 +74,13 @@ widget_->Show(); folder_header_view_ = std::make_unique<FolderHeaderView>(delegate_.get()); + textfield_ = std::make_unique<views::Textfield>(); widget_->SetContentsView(folder_header_view_.get()); } void TearDown() override { widget_->Close(); + textfield_.reset(); folder_header_view_.reset(); // Release apps grid view before models. delegate_.reset(); views::ViewsTestBase::TearDown(); @@ -87,7 +90,7 @@ void UpdateFolderName(const std::string& name) { base::string16 folder_name = base::UTF8ToUTF16(name); folder_header_view_->SetFolderNameForTest(folder_name); - folder_header_view_->ContentsChanged(NULL, folder_name); + folder_header_view_->ContentsChanged(textfield_.get(), folder_name); } const std::string GetFolderNameFromUI() { @@ -98,9 +101,19 @@ return folder_header_view_->IsFolderNameEnabledForTest(); } + void UpdatePreviousCursorPosition(const size_t previous_cursor_position) { + folder_header_view_->SetPreviousCursorPositionForTest( + previous_cursor_position); + } + + void UpdatePreviousFolderName(const base::string16& previous_name) { + folder_header_view_->SetPreviousFolderNameForTest(previous_name); + } + std::unique_ptr<AppListTestModel> model_; std::unique_ptr<FolderHeaderView> folder_header_view_; std::unique_ptr<TestFolderHeaderViewDelegate> delegate_; + std::unique_ptr<views::Textfield> textfield_; std::unique_ptr<views::Widget> widget_; private: @@ -140,14 +153,27 @@ EXPECT_EQ("", GetFolderNameFromUI()); EXPECT_TRUE(CanEditFolderName()); - // Update UI to set folder name to really long one beyond its maxium limit, - // The folder name should be trucated to the maximum length. + // Update UI to set folder name to really long one beyond its maximum limit + // If folder name is set beyond the maximum char limit, it should revert to + // the previous valid folder name. std::string max_len_name; for (size_t i = 0; i < kMaxFolderNameChars; ++i) max_len_name += "a"; + std::string too_long_name = max_len_name + "a"; + UpdatePreviousCursorPosition(0); + UpdatePreviousFolderName(base::string16()); + + // Expect that the folder name does not change, and does not truncate + UpdateFolderName(too_long_name); + EXPECT_EQ(std::string(), delegate_->folder_name()); + + // Expect the folder does change to the new valid name given UpdateFolderName(max_len_name); EXPECT_EQ(max_len_name, delegate_->folder_name()); - std::string too_long_name = max_len_name + "a"; + + // Expect that the name is reverted to the previous valid name and is not + // truncated + too_long_name.insert(5, "testing"); UpdateFolderName(too_long_name); EXPECT_EQ(max_len_name, delegate_->folder_name()); }
diff --git a/ash/assistant/assistant_controller.cc b/ash/assistant/assistant_controller.cc index 6c72e5c9..db4f0bd0 100644 --- a/ash/assistant/assistant_controller.cc +++ b/ash/assistant/assistant_controller.cc
@@ -17,12 +17,14 @@ #include "ash/assistant/assistant_ui_controller.h" #include "ash/assistant/util/deep_link_util.h" #include "ash/new_window_controller.h" +#include "ash/public/cpp/ash_pref_names.h" #include "ash/session/session_controller.h" #include "ash/shell.h" #include "ash/utility/screenshot_controller.h" #include "ash/voice_interaction/voice_interaction_controller.h" #include "base/bind.h" #include "base/memory/scoped_refptr.h" +#include "components/prefs/pref_registry_simple.h" #include "services/content/public/mojom/constants.mojom.h" #include "services/service_manager/public/cpp/connector.h" @@ -58,6 +60,11 @@ RemoveObserver(this); } +// static +void AssistantController::RegisterProfilePrefs(PrefRegistrySimple* registry) { + registry->RegisterIntegerPref(prefs::kAssistantNumWarmerWelcomeTriggered, 0); +} + void AssistantController::BindRequest( mojom::AssistantControllerRequest request) { assistant_controller_bindings_.AddBinding(this, std::move(request));
diff --git a/ash/assistant/assistant_controller.h b/ash/assistant/assistant_controller.h index 852234a..97b29db 100644 --- a/ash/assistant/assistant_controller.h +++ b/ash/assistant/assistant_controller.h
@@ -28,6 +28,8 @@ #include "mojo/public/cpp/bindings/interface_ptr_set.h" #include "services/content/public/mojom/navigable_contents_factory.mojom.h" +class PrefRegistrySimple; + namespace ash { class AssistantCacheController; @@ -48,6 +50,8 @@ AssistantController(); ~AssistantController() override; + static void RegisterProfilePrefs(PrefRegistrySimple* registry); + void BindRequest(mojom::AssistantControllerRequest request); void BindRequest(mojom::AssistantVolumeControlRequest request);
diff --git a/ash/assistant/assistant_interaction_controller.cc b/ash/assistant/assistant_interaction_controller.cc index a0085f9..2c38147 100644 --- a/ash/assistant/assistant_interaction_controller.cc +++ b/ash/assistant/assistant_interaction_controller.cc
@@ -17,19 +17,25 @@ #include "ash/assistant/ui/assistant_ui_constants.h" #include "ash/assistant/util/deep_link_util.h" #include "ash/assistant/util/histogram_util.h" +#include "ash/public/cpp/ash_pref_names.h" #include "ash/public/interfaces/voice_interaction_controller.mojom.h" +#include "ash/session/session_controller.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/voice_interaction/voice_interaction_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/optional.h" #include "base/strings/utf_string_conversions.h" +#include "chromeos/services/assistant/public/features.h" +#include "components/prefs/pref_service.h" #include "ui/base/l10n/l10n_util.h" namespace ash { namespace { +constexpr int kWarmerWelcomesMaxTimesTriggered = 3; + // Helpers --------------------------------------------------------------------- // Returns true if device is in tablet mode, false otherwise. @@ -598,20 +604,50 @@ // Assistant UI will immediately start a voice interaction. const bool launch_with_mic_open = Shell::Get()->voice_interaction_controller()->launch_with_mic_open(); - if (launch_with_mic_open || IsTabletMode()) + if (launch_with_mic_open || IsTabletMode()) { StartVoiceInteraction(); + // TODO(yileili): Currently WW is only allowed when user logins and the + // entrypoint does not automatically start a user interaction, e.g. + // stylus or hotword, to avoid WW interrupts the user interaction. + // Need further UX design if to attempt WW after the first interaction. + should_attempt_warmer_welcome_ = false; + } break; } case AssistantEntryPoint::kStylus: model_.SetInputModality(InputModality::kStylus); - break; - case AssistantEntryPoint::kUnspecified: + FALLTHROUGH; case AssistantEntryPoint::kDeepLink: case AssistantEntryPoint::kHotword: + should_attempt_warmer_welcome_ = false; + break; + case AssistantEntryPoint::kUnspecified: case AssistantEntryPoint::kSetup: // No action necessary. break; } + + if (should_attempt_warmer_welcome_) { + if (chromeos::assistant::features::IsWarmerWelcomeEnabled()) { + auto* pref_service = + Shell::Get()->session_controller()->GetLastActiveUserPrefService(); + + DCHECK(pref_service); + + auto num_warmer_welcome_triggered = + pref_service->GetInteger(prefs::kAssistantNumWarmerWelcomeTriggered); + if (num_warmer_welcome_triggered < kWarmerWelcomesMaxTimesTriggered) { + // TODO(b/120242181): If allow_tts is true, Assistant response updates + // mic and starts a new voice interaction automatically. A void voice + // input could return a communication error or empty response. + assistant_->StartWarmerWelcomeInteraction(num_warmer_welcome_triggered, + /*allow_tts=*/false); + pref_service->SetInteger(prefs::kAssistantNumWarmerWelcomeTriggered, + ++num_warmer_welcome_triggered); + } + } + should_attempt_warmer_welcome_ = false; + } } void AssistantInteractionController::StartMetalayerInteraction(
diff --git a/ash/assistant/assistant_interaction_controller.h b/ash/assistant/assistant_interaction_controller.h index b2db253..076c5c4 100644 --- a/ash/assistant/assistant_interaction_controller.h +++ b/ash/assistant/assistant_interaction_controller.h
@@ -135,6 +135,8 @@ AssistantInteractionModel model_; + bool should_attempt_warmer_welcome_ = true; + base::WeakPtrFactory<AssistantInteractionController> weak_factory_; DISALLOW_COPY_AND_ASSIGN(AssistantInteractionController);
diff --git a/ash/assistant/ui/assistant_ui_constants.h b/ash/assistant/ui/assistant_ui_constants.h index dd7807a..eb74d035f 100644 --- a/ash/assistant/ui/assistant_ui_constants.h +++ b/ash/assistant/ui/assistant_ui_constants.h
@@ -25,9 +25,8 @@ constexpr int kUiElementHorizontalMarginDip = 32; // Typography. -constexpr SkColor kTextColorHint = gfx::kGoogleGrey500; +constexpr SkColor kTextColorHint = gfx::kGoogleGrey700; constexpr SkColor kTextColorPrimary = gfx::kGoogleGrey900; -constexpr SkColor kTextColorSecondary = gfx::kGoogleGrey700; // TODO(dmblack): Move the other constants into ash::assistant::ui. namespace assistant {
diff --git a/ash/assistant/util/views_util.h b/ash/assistant/util/views_util.h index b394dda..558a2b3 100644 --- a/ash/assistant/util/views_util.h +++ b/ash/assistant/util/views_util.h
@@ -32,7 +32,7 @@ int icon_size_in_dip, int accessible_name_id, AssistantButtonId button_id, - SkColor icon_color = gfx::kGoogleGrey600); + SkColor icon_color = gfx::kGoogleGrey700); } // namespace util } // namespace assistant
diff --git a/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc b/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc index 0a67ac7..99b81cd 100644 --- a/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc +++ b/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
@@ -548,7 +548,7 @@ {// |categories| {ShortcutCategory::kSystemAndDisplay, ShortcutCategory::kTextEditing}, - IDS_KSV_DESCRIPTION_NEXT_IME, + IDS_KSV_DESCRIPTION_SWITCH_TO_NEXT_IME, IDS_KSV_SHORTCUT_TWO_MODIFIERS_ONE_KEY, // |accelerator_ids| {{ui::VKEY_SPACE, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN}}}, @@ -562,7 +562,7 @@ {// |categories| {ShortcutCategory::kSystemAndDisplay, ShortcutCategory::kTextEditing}, - IDS_KSV_DESCRIPTION_PREVIOUS_IME, + IDS_KSV_DESCRIPTION_SWITCH_TO_LAST_USED_IME, IDS_KSV_SHORTCUT_ONE_MODIFIER_ONE_KEY, // |accelerator_ids| {{ui::VKEY_SPACE, ui::EF_CONTROL_DOWN}}},
diff --git a/ash/components/shortcut_viewer_strings.grdp b/ash/components/shortcut_viewer_strings.grdp index 9e0a5e9..d6451143 100644 --- a/ash/components/shortcut_viewer_strings.grdp +++ b/ash/components/shortcut_viewer_strings.grdp
@@ -123,8 +123,8 @@ <message name="IDS_KSV_SHORTCUT_HIGHLIGHT_NEXT_ITEM_ON_SHELF" desc="Human readable version of the keyboard shortcut."> <ph name="shift">$1<ex>Shift</ex></ph><ph name="separator1">$2<ex>+</ex></ph><ph name="alt">$3<ex>Alt</ex></ph><ph name="separator2">$4<ex>+</ex></ph><ph name="l">$5<ex>v</ex></ph>, then <ph name="tab">$6<ex>v</ex></ph> or <ph name="right">$7<ex>v</ex></ph> </message> - <message name="IDS_KSV_DESCRIPTION_PREVIOUS_IME" desc="Description of the command in keyboard shortcut viewer."> - Switch to the input method of the previous language + <message name="IDS_KSV_DESCRIPTION_SWITCH_TO_LAST_USED_IME" desc="Description of the command in keyboard shortcut viewer."> + Switch to the last used input method </message> <message name="IDS_KSV_DESCRIPTION_CYCLE_FORWARD_MRU" desc="Description of the command in keyboard shortcut viewer."> Switch quickly between windows @@ -171,8 +171,8 @@ <message name="IDS_KSV_DESCRIPTION_TOGGLE_CAPS_LOCK" desc="Description of the command in keyboard shortcut viewer."> Turn Caps Lock on and off </message> - <message name="IDS_KSV_DESCRIPTION_NEXT_IME" desc="Description of the command in keyboard shortcut viewer."> - Switch to the input method of the next language + <message name="IDS_KSV_DESCRIPTION_SWITCH_TO_NEXT_IME" desc="Description of the command in keyboard shortcut viewer."> + Switch to the next available input method </message> <message name="IDS_KSV_DESCRIPTION_NEW_WINDOW" desc="Description of the command in keyboard shortcut viewer."> Open new window
diff --git a/ash/display/extended_mouse_warp_controller.cc b/ash/display/extended_mouse_warp_controller.cc index 8ac159a..a164076d 100644 --- a/ash/display/extended_mouse_warp_controller.cc +++ b/ash/display/extended_mouse_warp_controller.cc
@@ -89,10 +89,19 @@ int64_t id) const { if (a_display_id_ == id) return a_indicator_bounds_; - CHECK_EQ(b_display_id_, id); + DCHECK_EQ(b_display_id_, id); return b_indicator_bounds_; } +const gfx::Rect& +ExtendedMouseWarpController::WarpRegion::GetIndicatorNativeBoundsForTest( + int64_t id) const { + if (a_display_id_ == id) + return a_edge_bounds_in_native_; + DCHECK_EQ(b_display_id_, id); + return b_edge_bounds_in_native_; +} + ExtendedMouseWarpController::ExtendedMouseWarpController( aura::Window* drag_source) : drag_source_root_(drag_source), allow_non_native_event_(false) {
diff --git a/ash/display/extended_mouse_warp_controller.h b/ash/display/extended_mouse_warp_controller.h index fa65c0e..6500936 100644 --- a/ash/display/extended_mouse_warp_controller.h +++ b/ash/display/extended_mouse_warp_controller.h
@@ -63,6 +63,7 @@ const gfx::Rect& b_indicator_bounds() { return b_indicator_bounds_; } const gfx::Rect& GetIndicatorBoundsForTest(int64_t id) const; + const gfx::Rect& GetIndicatorNativeBoundsForTest(int64_t id) const; private: friend class ExtendedMouseWarpController;
diff --git a/ash/display/extended_mouse_warp_controller_unittest.cc b/ash/display/extended_mouse_warp_controller_unittest.cc index 26b3bad..f52376586 100644 --- a/ash/display/extended_mouse_warp_controller_unittest.cc +++ b/ash/display/extended_mouse_warp_controller_unittest.cc
@@ -5,15 +5,23 @@ #include "ash/display/extended_mouse_warp_controller.h" #include "ash/display/mouse_cursor_event_filter.h" +#include "ash/display/screen_position_controller.h" +#include "ash/host/ash_window_tree_host_platform.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" +#include "ui/aura/env.h" +#include "ui/aura/test/test_windows.h" +#include "ui/aura/window_tree_host.h" +#include "ui/base/hit_test.h" #include "ui/display/display.h" #include "ui/display/display_layout.h" #include "ui/display/display_layout_builder.h" #include "ui/display/manager/display_manager.h" #include "ui/display/screen.h" #include "ui/display/test/display_manager_test_api.h" +#include "ui/events/base_event_utils.h" #include "ui/events/test/event_generator.h" +#include "ui/wm/core/coordinate_conversion.h" namespace ash { @@ -44,6 +52,28 @@ return GetWarpRegion(0)->GetIndicatorBoundsForTest(id); } + const gfx::Rect& GetIndicatorNativeBounds(int64_t id) { + return GetWarpRegion(0)->GetIndicatorNativeBoundsForTest(id); + } + + // Send mouse event with native event through AshWindowTreeHostPlatform. + void DispatchMouseEventWithNative(AshWindowTreeHostPlatform* host, + const gfx::Point& location_in_host_native, + ui::EventType event_type, + int event_flag1, + int event_flag2) { + ui::MouseEvent native_event(event_type, location_in_host_native, + location_in_host_native, ui::EventTimeForNow(), + event_flag1, event_flag2); + ui::MouseEvent mouseev(&native_event); + host->DispatchEventFromQueue(&mouseev); + + // The test relies on the last_mouse_location, which will be updated by + // a synthesized event posted asynchronusly. Wait until the synthesized + // event is handled and last mouse location is updated. + base::RunLoop().RunUntilIdle(); + } + private: DISALLOW_COPY_AND_ASSIGN(ExtendedMouseWarpControllerTest); }; @@ -356,4 +386,107 @@ event_filter()->HideSharedEdgeIndicator(); } +// Check that the point in the rotated secondary display's warp region is +// converted correctly from native host coordinates to screen DIP coordinates. +// (see https://crbug.com/905035) +TEST_F(ExtendedMouseWarpControllerTest, + CheckHostPointToScreenInMouseWarpRegion) { + // Zoom factor is needed to trigger rounding error which occured in previous + // code. + UpdateDisplay("50+50-200x200@0.8,50+300-300x100/r"); + + aura::Window::Windows root_windows = Shell::Get()->GetAllRootWindows(); + + // Check the primary display's size and scale. + display::Display primary_display = + display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[0]); + ASSERT_EQ("250x250", primary_display.size().ToString()); + ASSERT_EQ(0.8f, primary_display.device_scale_factor()); + + // Create a window to be dragged in primary display. + std::unique_ptr<aura::test::TestWindowDelegate> test_window_delegate = + std::make_unique<aura::test::TestWindowDelegate>(); + test_window_delegate->set_window_component(HTCAPTION); + const gfx::Size initial_window_size(100, 100); + std::unique_ptr<aura::Window> test_window( + CreateTestWindowInShellWithDelegateAndType( + test_window_delegate.get(), aura::client::WINDOW_TYPE_NORMAL, 0, + gfx::Rect(initial_window_size))); + ASSERT_EQ(root_windows[0], test_window->GetRootWindow()); + ASSERT_FALSE(test_window->HasCapture()); + + AshWindowTreeHostPlatform* window_host = + static_cast<AshWindowTreeHostPlatform*>(root_windows[0]->GetHost()); + + // Move mouse cursor and capture the window. + gfx::Point location_in_host_native(0, 0); + DispatchMouseEventWithNative(window_host, location_in_host_native, + ui::ET_MOUSE_MOVED, ui::EF_NONE, ui::EF_NONE); + DispatchMouseEventWithNative(window_host, location_in_host_native, + ui::ET_MOUSE_PRESSED, ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_LEFT_MOUSE_BUTTON); + + // Window should be captured. + ASSERT_TRUE(test_window->HasCapture()); + + int64_t display_0_id = primary_display.id(); + const gfx::Rect indicator_in_primary_display = + GetIndicatorNativeBounds(display_0_id); + int64_t display_1_id = display::Screen::GetScreen() + ->GetDisplayNearestWindow(root_windows[1]) + .id(); + const gfx::Rect indicator_in_secondary_display = + GetIndicatorNativeBounds(display_1_id); + + gfx::Point location_in_screen_native, location_in_screen_dip; + + // Move mouse cursor to the warp region of first display. + location_in_screen_native = indicator_in_primary_display.CenterPoint(); + location_in_host_native = + location_in_screen_native - + root_windows[0]->GetHost()->GetBoundsInPixels().OffsetFromOrigin(); + DispatchMouseEventWithNative(window_host, location_in_host_native, + ui::ET_MOUSE_DRAGGED, ui::EF_LEFT_MOUSE_BUTTON, + 0); + + // Mouse cursor should be warped into secondary display. + location_in_screen_dip = Shell::Get()->aura_env()->last_mouse_location(); + EXPECT_TRUE( + root_windows[1]->GetBoundsInScreen().Contains(location_in_screen_dip)); + + // Move mouse cursor to the warp region of secondary display. + location_in_screen_native = indicator_in_secondary_display.CenterPoint(); + location_in_host_native = + location_in_screen_native - + root_windows[0]->GetHost()->GetBoundsInPixels().OffsetFromOrigin(); + DispatchMouseEventWithNative(window_host, location_in_host_native, + ui::ET_MOUSE_DRAGGED, ui::EF_LEFT_MOUSE_BUTTON, + 0); + + // Mouse cursor should be warped into first display. + location_in_screen_dip = Shell::Get()->aura_env()->last_mouse_location(); + EXPECT_TRUE( + root_windows[0]->GetBoundsInScreen().Contains(location_in_screen_dip)); + + // After mouse warping, x-coordinate of mouse location in native coordinates + // should be 2 px away from end. Primary display has zoom factor of 0.8. So + // the offset in screen coordinates should be 2/0.8, which is 2.5. The end of + // primary display in screen coordinates is 250. So x-coordinate of mouse + // cursor in screen coordinates should be 247. + EXPECT_EQ(247, Shell::Get()->aura_env()->last_mouse_location().x()); + + // Get cursor's location in host native coordinates. + gfx::Point location_in_host_dip; + location_in_screen_dip = Shell::Get()->aura_env()->last_mouse_location(); + location_in_host_dip = location_in_screen_dip; + ::wm::ConvertPointFromScreen(root_windows[0], &location_in_host_dip); + location_in_host_native = location_in_host_dip; + root_windows[0]->GetHost()->ConvertDIPToPixels(&location_in_host_native); + + // Release mouse button. + DispatchMouseEventWithNative(window_host, location_in_host_native, + ui::ET_MOUSE_RELEASED, ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_LEFT_MOUSE_BUTTON); +} + } // namespace ash
diff --git a/ash/display/screen_position_controller.cc b/ash/display/screen_position_controller.cc index d24513f..a0490c5 100644 --- a/ash/display/screen_position_controller.cc +++ b/ash/display/screen_position_controller.cc
@@ -51,9 +51,13 @@ // display's coordinate system to anothers may cause events in the // primary's coordinate system which fall in the extended display. - gfx::Point location_in_native(point_in_root); + gfx::Point location_in_native(*point); - root_window->GetHost()->ConvertDIPToScreenInPixels(&location_in_native); + // |point| is in the native host window coordinate. Convert it to the native + // screen coordinate. + const gfx::Point host_origin = + root_window->GetHost()->GetBoundsInPixels().origin(); + location_in_native.Offset(host_origin.x(), host_origin.y()); for (size_t i = 0; i < root_windows.size(); ++i) { aura::WindowTreeHost* host = root_windows[i]->GetHost();
diff --git a/ash/display/screen_position_controller_unittest.cc b/ash/display/screen_position_controller_unittest.cc index a2737c98..844a169 100644 --- a/ash/display/screen_position_controller_unittest.cc +++ b/ash/display/screen_position_controller_unittest.cc
@@ -247,7 +247,7 @@ EXPECT_EQ("37,187", ConvertHostPointToScreen(60, 300)); // The point is on the 2nd host. Point on 2nd host (60,150) - // - screen [+(150,0)] - EXPECT_EQ("184,49", ConvertHostPointToScreen(60, 450)); + EXPECT_EQ("185,50", ConvertHostPointToScreen(60, 450)); // Move |window_| to the 2nd. window_->SetBoundsInScreen(gfx::Rect(300, 20, 50, 50),
diff --git a/ash/events/OWNERS b/ash/events/OWNERS index 07edfb5..fd423df3 100644 --- a/ash/events/OWNERS +++ b/ash/events/OWNERS
@@ -1,2 +1,3 @@ per-file spoken_feedback_event_rewriter*=file://ui/accessibility/OWNERS per-file select_to_speak_event_handler*=file://ui/accessibility/OWNERS +per-file switch_access_event_handler*=file://ui/accessibility/OWNERS
diff --git a/ash/events/switch_access_event_handler.cc b/ash/events/switch_access_event_handler.cc new file mode 100644 index 0000000..2102618 --- /dev/null +++ b/ash/events/switch_access_event_handler.cc
@@ -0,0 +1,59 @@ +// 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 "ash/events/switch_access_event_handler.h" + +#include "ash/accessibility/accessibility_controller.h" +#include "ash/shell.h" + +namespace ash { + +namespace { + +bool IsSwitchAccessEnabled() { + return Shell::Get()->accessibility_controller()->switch_access_enabled(); +} + +void CancelEvent(ui::Event* event) { + DCHECK(event); + if (event->cancelable()) { + event->SetHandled(); + event->StopPropagation(); + } +} + +} // namespace + +SwitchAccessEventHandler::SwitchAccessEventHandler( + mojom::SwitchAccessEventHandlerDelegatePtr delegate_ptr) + : delegate_ptr_(std::move(delegate_ptr)), ignore_virtual_key_events_(true) { + DCHECK(delegate_ptr_.is_bound()); + Shell::Get()->AddPreTargetHandler(this, + ui::EventTarget::Priority::kAccessibility); +} + +SwitchAccessEventHandler::~SwitchAccessEventHandler() { + Shell::Get()->RemovePreTargetHandler(this); +} + +void SwitchAccessEventHandler::FlushMojoForTest() { + delegate_ptr_.FlushForTesting(); +} + +void SwitchAccessEventHandler::OnKeyEvent(ui::KeyEvent* event) { + DCHECK(IsSwitchAccessEnabled()); + DCHECK(event); + + // Ignore virtual key events so users can type with the onscreen keyboard. + if (ignore_virtual_key_events_ && !event->HasNativeEvent()) + return; + + ui::KeyboardCode key_code = event->key_code(); + if (keys_to_capture_.find(key_code) != keys_to_capture_.end()) { + CancelEvent(event); + delegate_ptr_->DispatchKeyEvent(ui::Event::Clone(*event)); + } +} + +} // namespace ash
diff --git a/ash/events/switch_access_event_handler.h b/ash/events/switch_access_event_handler.h new file mode 100644 index 0000000..bed2b40 --- /dev/null +++ b/ash/events/switch_access_event_handler.h
@@ -0,0 +1,51 @@ +// 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 ASH_EVENTS_SWITCH_ACCESS_EVENT_HANDLER_H_ +#define ASH_EVENTS_SWITCH_ACCESS_EVENT_HANDLER_H_ + +#include "ash/ash_export.h" +#include "ash/public/interfaces/accessibility_controller.mojom.h" +#include "base/macros.h" +#include "ui/events/event_handler.h" + +namespace ash { + +// SwitchAccessEventHandler sends events to the Switch Access extension +// (via the delegate) when it is enabled. +class ASH_EXPORT SwitchAccessEventHandler : public ui::EventHandler { + public: + explicit SwitchAccessEventHandler( + mojom::SwitchAccessEventHandlerDelegatePtr delegate_ptr); + ~SwitchAccessEventHandler() override; + + // Sets the keys that are captured by Switch Access. + void set_keys_to_capture(std::vector<int> keys) { + keys_to_capture_ = std::set<int>(keys.begin(), keys.end()); + } + + // Sets whether virtual key events should be ignored. + void set_ignore_virtual_key_events(bool should_ignore) { + ignore_virtual_key_events_ = should_ignore; + } + + // For testing usage only. + void FlushMojoForTest(); + + private: + // ui::EventHandler: + void OnKeyEvent(ui::KeyEvent* event) override; + + // The delegate used to send key events to the Switch Access extension. + mojom::SwitchAccessEventHandlerDelegatePtr delegate_ptr_; + + std::set<int> keys_to_capture_; + bool ignore_virtual_key_events_; + + DISALLOW_COPY_AND_ASSIGN(SwitchAccessEventHandler); +}; + +} // namespace ash + +#endif // ASH_EVENTS_SWITCH_ACCESS_EVENT_HANDLER_H_
diff --git a/ash/events/switch_access_event_handler_unittest.cc b/ash/events/switch_access_event_handler_unittest.cc new file mode 100644 index 0000000..2d48bfb6 --- /dev/null +++ b/ash/events/switch_access_event_handler_unittest.cc
@@ -0,0 +1,209 @@ +// 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 "ash/events/switch_access_event_handler.h" + +#include "ash/accessibility/accessibility_controller.h" +#include "ash/public/interfaces/accessibility_controller.mojom.h" +#include "ash/shell.h" +#include "ash/test/ash_test_base.h" +#include "base/command_line.h" +#include "base/macros.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "ui/accessibility/accessibility_switches.h" +#include "ui/aura/env.h" +#include "ui/events/event.h" +#include "ui/events/event_handler.h" +#include "ui/events/test/event_generator.h" + +namespace ash { + +namespace { + +// Records all key events for testing. +class EventCapturer : public ui::EventHandler { + public: + EventCapturer() = default; + ~EventCapturer() override = default; + + void Reset() { last_key_event_.reset(); } + + ui::KeyEvent* last_key_event() { return last_key_event_.get(); } + + private: + void OnKeyEvent(ui::KeyEvent* event) override { + last_key_event_.reset(new ui::KeyEvent(*event)); + } + + std::unique_ptr<ui::KeyEvent> last_key_event_; + + DISALLOW_COPY_AND_ASSIGN(EventCapturer); +}; + +class TestDelegate : public mojom::SwitchAccessEventHandlerDelegate { + public: + TestDelegate() : binding_(this) {} + ~TestDelegate() override = default; + + mojom::SwitchAccessEventHandlerDelegatePtr BindInterface() { + mojom::SwitchAccessEventHandlerDelegatePtr ptr; + binding_.Bind(MakeRequest(&ptr)); + return ptr; + } + + ui::KeyEvent* last_key_event() { return key_events_.back().get(); } + + private: + // SwitchAccessEventHandlerDelegate: + void DispatchKeyEvent(std::unique_ptr<ui::Event> event) override { + DCHECK(event->IsKeyEvent()); + key_events_.push_back(std::make_unique<ui::KeyEvent>(event->AsKeyEvent())); + } + + mojo::Binding<mojom::SwitchAccessEventHandlerDelegate> binding_; + std::vector<std::unique_ptr<ui::KeyEvent>> key_events_; + + DISALLOW_COPY_AND_ASSIGN(TestDelegate); +}; + +class SwitchAccessEventHandlerTest : public AshTestBase { + public: + SwitchAccessEventHandlerTest() = default; + ~SwitchAccessEventHandlerTest() override = default; + + void SetUp() override { + AshTestBase::SetUp(); + + // This test triggers a resize of WindowTreeHost, which will end up + // throttling events. set_throttle_input_on_resize_for_testing() disables + // this. + Shell::Get()->aura_env()->set_throttle_input_on_resize_for_testing(false); + delegate_ = std::make_unique<TestDelegate>(); + + generator_ = AshTestBase::GetEventGenerator(); + CurrentContext()->AddPreTargetHandler(&event_capturer_); + + controller_ = Shell::Get()->accessibility_controller(); + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableExperimentalAccessibilitySwitchAccess); + controller_->SetSwitchAccessEnabled(true); + controller_->SetSwitchAccessEventHandlerDelegate( + delegate_->BindInterface()); + controller_->SetSwitchAccessIgnoreVirtualKeyEvent(false); + } + + void TearDown() override { + CurrentContext()->RemovePreTargetHandler(&event_capturer_); + generator_ = nullptr; + controller_ = nullptr; + AshTestBase::TearDown(); + } + + // Flush messages to the delegate before callers check its state. + TestDelegate* GetDelegate() { + controller_->FlushMojoForTest(); + return delegate_.get(); + } + + protected: + ui::test::EventGenerator* generator_ = nullptr; + EventCapturer event_capturer_; + AccessibilityController* controller_ = nullptr; + + private: + std::unique_ptr<TestDelegate> delegate_; + + DISALLOW_COPY_AND_ASSIGN(SwitchAccessEventHandlerTest); +}; + +TEST_F(SwitchAccessEventHandlerTest, CaptureSpecifiedKeys) { + Shell::Get()->accessibility_controller()->SetSwitchAccessKeysToCapture( + {ui::VKEY_1, ui::VKEY_2, ui::VKEY_3}); + + EXPECT_FALSE(event_capturer_.last_key_event()); + + // Press the "1" key. + generator_->PressKey(ui::VKEY_1, ui::EF_NONE); + generator_->ReleaseKey(ui::VKEY_1, ui::EF_NONE); + + // The event was handled by SwitchAccessEventHandler. + EXPECT_FALSE(event_capturer_.last_key_event()); + ui::KeyEvent* key_event_1 = GetDelegate()->last_key_event(); + EXPECT_TRUE(key_event_1); + + // Press the "2" key. + generator_->PressKey(ui::VKEY_2, ui::EF_NONE); + generator_->ReleaseKey(ui::VKEY_2, ui::EF_NONE); + + // We received a new event. + EXPECT_NE(GetDelegate()->last_key_event(), key_event_1); + + // The event was handled by SwitchAccessEventHandler. + EXPECT_FALSE(event_capturer_.last_key_event()); + ui::KeyEvent* key_event_2 = GetDelegate()->last_key_event(); + EXPECT_TRUE(key_event_2); + + // Press the "3" key. + generator_->PressKey(ui::VKEY_3, ui::EF_NONE); + generator_->ReleaseKey(ui::VKEY_3, ui::EF_NONE); + + // We received a new event. + EXPECT_NE(GetDelegate()->last_key_event(), key_event_2); + + // The event was handled by SwitchAccessEventHandler. + EXPECT_FALSE(event_capturer_.last_key_event()); + ui::KeyEvent* key_event_3 = GetDelegate()->last_key_event(); + EXPECT_TRUE(key_event_3); +} + +TEST_F(SwitchAccessEventHandlerTest, IgnoreKeysNotSpecifiedForCapture) { + // Switch Access only captures select keys. Ignore all others. + Shell::Get()->accessibility_controller()->SetSwitchAccessKeysToCapture( + {ui::VKEY_1, ui::VKEY_2, ui::VKEY_3}); + + EXPECT_FALSE(event_capturer_.last_key_event()); + + // Press the "X" key. + generator_->PressKey(ui::VKEY_X, ui::EF_NONE); + generator_->ReleaseKey(ui::VKEY_X, ui::EF_NONE); + + // We received an event, but did not handle it. + EXPECT_TRUE(event_capturer_.last_key_event()); + EXPECT_FALSE(event_capturer_.last_key_event()->handled()); +} + +TEST_F(SwitchAccessEventHandlerTest, KeysNoLongerCaptureAfterUpdate) { + // Set Switch Access to capture the keys {1, 2, 3}. + Shell::Get()->accessibility_controller()->SetSwitchAccessKeysToCapture( + {ui::VKEY_1, ui::VKEY_2, ui::VKEY_3}); + + EXPECT_FALSE(event_capturer_.last_key_event()); + + // Press the "1" key. + generator_->PressKey(ui::VKEY_1, ui::EF_NONE); + generator_->ReleaseKey(ui::VKEY_1, ui::EF_NONE); + + // The event was handled by SwitchAccessEventHandler. + EXPECT_FALSE(event_capturer_.last_key_event()); + ui::KeyEvent* key_event_1 = GetDelegate()->last_key_event(); + EXPECT_TRUE(key_event_1); + + // Update the Switch Access keys to capture {2, 3, 4}. + Shell::Get()->accessibility_controller()->SetSwitchAccessKeysToCapture( + {ui::VKEY_2, ui::VKEY_3, ui::VKEY_4}); + + // Press the "1" key. + generator_->PressKey(ui::VKEY_1, ui::EF_NONE); + generator_->ReleaseKey(ui::VKEY_1, ui::EF_NONE); + + // We received a new event. + EXPECT_NE(event_capturer_.last_key_event(), key_event_1); + + // The event was NOT handled by SwitchAccessEventHandler. + EXPECT_TRUE(event_capturer_.last_key_event()); + EXPECT_FALSE(event_capturer_.last_key_event()->handled()); +} + +} // namespace +} // namespace ash
diff --git a/ash/host/ash_window_tree_host_platform.h b/ash/host/ash_window_tree_host_platform.h index 243ff476..b65f23d6 100644 --- a/ash/host/ash_window_tree_host_platform.h +++ b/ash/host/ash_window_tree_host_platform.h
@@ -27,6 +27,7 @@ } namespace ash { +class ExtendedMouseWarpControllerTest; class ASH_EXPORT AshWindowTreeHostPlatform : public AshWindowTreeHost, @@ -40,6 +41,10 @@ ~AshWindowTreeHostPlatform() override; protected: + friend ExtendedMouseWarpControllerTest; + FRIEND_TEST_ALL_PREFIXES(ExtendedMouseWarpControllerTest, + CheckHostPointToScreenInMouseWarpRegion); + AshWindowTreeHostPlatform(); // AshWindowTreeHost:
diff --git a/ash/ime/ime_controller.cc b/ash/ime/ime_controller.cc index e52ab9b..92388fd 100644 --- a/ash/ime/ime_controller.cc +++ b/ash/ime/ime_controller.cc
@@ -10,13 +10,18 @@ #include "ash/system/tray/system_tray_notifier.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/ime/chromeos/extension_ime_util.h" +#include "ui/display/manager/display_manager.h" namespace ash { ImeController::ImeController() : mode_indicator_observer_(std::make_unique<ModeIndicatorObserver>()) {} -ImeController::~ImeController() = default; +ImeController::~ImeController() { + Shell* shell = Shell::Get(); + shell->cast_config()->RemoveObserver(this); + shell->display_manager()->RemoveObserver(this); +} void ImeController::AddObserver(Observer* observer) { observers_.AddObserver(observer); @@ -32,6 +37,11 @@ void ImeController::SetClient(mojom::ImeControllerClientPtr client) { client_ = std::move(client); + + // Initializes some observers for client. + Shell* shell = Shell::Get(); + shell->cast_config()->AddObserver(this); + shell->display_manager()->AddObserver(this); } bool ImeController::CanSwitchIme() const { @@ -49,9 +59,9 @@ client_->SwitchToNextIme(); } -void ImeController::SwitchToPreviousIme() { +void ImeController::SwitchToLastUsedIme() { if (client_) - client_->SwitchToPreviousIme(); + client_->SwitchToLastUsedIme(); } void ImeController::SwitchImeById(const std::string& ime_id, @@ -168,6 +178,27 @@ mi_view->ShowAndFadeOut(); } +void ImeController::OnDisplayMetricsChanged(const display::Display& display, + uint32_t changed_metrics) { + bool is_mirroring = + (changed_metrics & display::DisplayObserver::DISPLAY_METRIC_MIRROR_STATE); + client_->UpdateMirroringState(is_mirroring); +} + +void ImeController::OnDevicesUpdated( + std::vector<mojom::SinkAndRoutePtr> devices) { + DCHECK(client_); + + bool casting_desktop = false; + for (auto& receiver : devices) { + if (receiver->route->content_source == mojom::ContentSource::DESKTOP) { + casting_desktop = true; + break; + } + } + client_->UpdateCastingState(casting_desktop); +} + void ImeController::SetCapsLockEnabled(bool caps_enabled) { is_caps_lock_enabled_ = caps_enabled;
diff --git a/ash/ime/ime_controller.h b/ash/ime/ime_controller.h index e71b660..678a5a4 100644 --- a/ash/ime/ime_controller.h +++ b/ash/ime/ime_controller.h
@@ -9,11 +9,13 @@ #include <vector> #include "ash/ash_export.h" +#include "ash/cast_config_controller.h" #include "ash/public/interfaces/ime_controller.mojom.h" #include "ash/public/interfaces/ime_info.mojom.h" #include "base/macros.h" #include "base/observer_list.h" #include "mojo/public/cpp/bindings/binding_set.h" +#include "ui/display/display_observer.h" namespace ui { class Accelerator; @@ -25,7 +27,9 @@ // Connects ash IME users (e.g. the system tray) to the IME implementation, // which might live in Chrome browser or in a separate mojo service. -class ASH_EXPORT ImeController : public mojom::ImeController { +class ASH_EXPORT ImeController : public mojom::ImeController, + public display::DisplayObserver, + public CastConfigControllerObserver { public: class Observer { public: @@ -71,7 +75,7 @@ // Wrappers for mojom::ImeControllerClient methods. void SwitchToNextIme(); - void SwitchToPreviousIme(); + void SwitchToLastUsedIme(); void SwitchImeById(const std::string& ime_id, bool show_message); void ActivateImeMenuItem(const std::string& key); void SetCapsLockEnabled(bool caps_enabled); @@ -105,6 +109,13 @@ void ShowModeIndicator(const gfx::Rect& anchor_bounds, const base::string16& ime_short_name) override; + // display::DisplayObserver: + void OnDisplayMetricsChanged(const display::Display& display, + uint32_t changed_metrics) override; + + // CastConfigControllerObserver: + void OnDevicesUpdated(std::vector<mojom::SinkAndRoutePtr> devices) override; + // Synchronously returns the cached caps lock state. bool IsCapsLockEnabled() const;
diff --git a/ash/ime/ime_controller_unittest.cc b/ash/ime/ime_controller_unittest.cc index 8e0e4968..d0c91325 100644 --- a/ash/ime/ime_controller_unittest.cc +++ b/ash/ime/ime_controller_unittest.cc
@@ -171,8 +171,8 @@ controller->SwitchToNextIme(); EXPECT_EQ(0, client.next_ime_count_); - controller->SwitchToPreviousIme(); - EXPECT_EQ(0, client.previous_ime_count_); + controller->SwitchToLastUsedIme(); + EXPECT_EQ(0, client.last_used_ime_count_); controller->SwitchImeById("ime1", true /* show_message */); EXPECT_EQ(0, client.switch_ime_count_); @@ -183,9 +183,9 @@ controller->FlushMojoForTesting(); EXPECT_EQ(1, client.next_ime_count_); - controller->SwitchToPreviousIme(); + controller->SwitchToLastUsedIme(); controller->FlushMojoForTesting(); - EXPECT_EQ(1, client.previous_ime_count_); + EXPECT_EQ(1, client.last_used_ime_count_); controller->SwitchImeById("ime1", true /* show_message */); controller->FlushMojoForTesting();
diff --git a/ash/ime/test_ime_controller_client.cc b/ash/ime/test_ime_controller_client.cc index 5852fbc9..5d495f2 100644 --- a/ash/ime/test_ime_controller_client.cc +++ b/ash/ime/test_ime_controller_client.cc
@@ -26,8 +26,8 @@ ++next_ime_count_; } -void TestImeControllerClient::SwitchToPreviousIme() { - ++previous_ime_count_; +void TestImeControllerClient::SwitchToLastUsedIme() { + ++last_used_ime_count_; } void TestImeControllerClient::SwitchImeById(const std::string& id, @@ -50,4 +50,12 @@ std::move(callback).Run(); } +void TestImeControllerClient::UpdateMirroringState(bool enabled) { + is_mirroring_ = enabled; +} + +void TestImeControllerClient::UpdateCastingState(bool enabled) { + is_casting_ = enabled; +} + } // namespace ash
diff --git a/ash/ime/test_ime_controller_client.h b/ash/ime/test_ime_controller_client.h index fc621b45..a2b122ac 100644 --- a/ash/ime/test_ime_controller_client.h +++ b/ash/ime/test_ime_controller_client.h
@@ -20,21 +20,25 @@ // mojom::ImeControllerClient: void SwitchToNextIme() override; - void SwitchToPreviousIme() override; + void SwitchToLastUsedIme() override; void SwitchImeById(const std::string& id, bool show_message) override; void ActivateImeMenuItem(const std::string& key) override; void SetCapsLockEnabled(bool enabled) override; void OverrideKeyboardKeyset(chromeos::input_method::mojom::ImeKeyset keyset, OverrideKeyboardKeysetCallback callback) override; + void UpdateMirroringState(bool enabled) override; + void UpdateCastingState(bool enabled) override; int next_ime_count_ = 0; - int previous_ime_count_ = 0; + int last_used_ime_count_ = 0; int switch_ime_count_ = 0; int set_caps_lock_count_ = 0; std::string last_switch_ime_id_; bool last_show_message_ = false; chromeos::input_method::mojom::ImeKeyset last_keyset_ = chromeos::input_method::mojom::ImeKeyset::kNone; + bool is_mirroring_ = false; + bool is_casting_ = false; private: mojo::Binding<mojom::ImeControllerClient> binding_;
diff --git a/ash/login/login_screen_controller.cc b/ash/login/login_screen_controller.cc index c250fed..0d64986 100644 --- a/ash/login/login_screen_controller.cc +++ b/ash/login/login_screen_controller.cc
@@ -8,7 +8,6 @@ #include "ash/focus_cycler.h" #include "ash/login/ui/lock_screen.h" -#include "ash/login/ui/lock_window.h" #include "ash/login/ui/login_data_dispatcher.h" #include "ash/public/cpp/ash_pref_names.h" #include "ash/root_window_controller.h"
diff --git a/ash/login/login_screen_test_api.cc b/ash/login/login_screen_test_api.cc index 5f120ce8..0bad2a1 100644 --- a/ash/login/login_screen_test_api.cc +++ b/ash/login/login_screen_test_api.cc
@@ -9,7 +9,6 @@ #include "ash/login/ui/lock_contents_view.h" #include "ash/login/ui/lock_screen.h" -#include "ash/login/ui/lock_window.h" #include "ash/login/ui/login_auth_user_view.h" #include "ash/login/ui/login_big_user_view.h" #include "ash/login/ui/login_password_view.h"
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc index 25237bd..573159f 100644 --- a/ash/login/ui/lock_contents_view.cc +++ b/ash/login/ui/lock_contents_view.cc
@@ -733,9 +733,11 @@ DCHECK(enabled || auth_reenabled_time); state->disable_auth = !enabled; - // TODO(crbug.com/845287): Reenable lock screen note when auth is reenabled. - if (state->disable_auth) - DisableLockScreenNote(); + disable_lock_screen_note_ = state->disable_auth; + OnLockScreenNoteStateChanged( + disable_lock_screen_note_ + ? mojom::TrayActionState::kNotAvailable + : Shell::Get()->tray_action()->GetLockScreenNoteState()); LoginBigUserView* big_user = TryToFindBigUser(user, true /*require_auth_active*/); @@ -1759,11 +1761,6 @@ Layout(); } -void LockContentsView::DisableLockScreenNote() { - disable_lock_screen_note_ = true; - OnLockScreenNoteStateChanged(mojom::TrayActionState::kNotAvailable); -} - void LockContentsView::RegisterAccelerators() { // Accelerators that apply on login and lock: accel_map_[ui::Accelerator(ui::VKEY_RIGHT, 0)] =
diff --git a/ash/login/ui/lock_contents_view.h b/ash/login/ui/lock_contents_view.h index 7b19c8a..0dd8651 100644 --- a/ash/login/ui/lock_contents_view.h +++ b/ash/login/ui/lock_contents_view.h
@@ -332,10 +332,6 @@ // Change the visibility of child views based on the |style|. void SetDisplayStyle(DisplayStyle style); - // Set the lock screen note state to |mojom::TrayActionState::kNotAvailable|. - // All the subsequent calls of |OnLockScreenNoteStateChanged| will be ignored. - void DisableLockScreenNote(); - // Register accelerators used in login screen. void RegisterAccelerators();
diff --git a/ash/login/ui/lock_contents_view_unittest.cc b/ash/login/ui/lock_contents_view_unittest.cc index 045f61c2..2ab36d8 100644 --- a/ash/login/ui/lock_contents_view_unittest.cc +++ b/ash/login/ui/lock_contents_view_unittest.cc
@@ -32,6 +32,8 @@ #include "ash/system/power/backlights_forced_off_setter.h" #include "ash/system/power/power_button_controller.h" #include "ash/system/status_area_widget.h" +#include "ash/tray_action/test_tray_action_client.h" +#include "ash/tray_action/tray_action.h" #include "base/strings/utf_string_conversions.h" #include "base/test/simple_test_tick_clock.h" #include "chromeos/dbus/dbus_thread_manager.h" @@ -1695,7 +1697,7 @@ base::RunLoop().RunUntilIdle(); } -TEST_F(LockContentsViewUnitTest, OnUnlockAllowedForUserChanged) { +TEST_F(LockContentsViewUnitTest, OnAuthEnabledForUserChanged) { auto* contents = new LockContentsView( mojom::TrayActionState::kAvailable, LockScreen::ScreenType::kLock, DataDispatcher(), @@ -1708,30 +1710,24 @@ LockContentsView::TestApi contents_test_api(contents); LoginAuthUserView::TestApi auth_test_api( contents_test_api.primary_big_view()->auth_user()); - views::View* note_action_button = contents_test_api.note_action(); LoginPasswordView* password_view = auth_test_api.password_view(); LoginPinView* pin_view = auth_test_api.pin_view(); views::View* disabled_auth_message = auth_test_api.disabled_auth_message(); - // The password field is shown by default, and the note action button is - // shown because the lock screen note state is |kAvailable|. - EXPECT_TRUE(note_action_button->visible()); + // The password field is shown by default. EXPECT_TRUE(password_view->visible()); EXPECT_FALSE(pin_view->visible()); EXPECT_FALSE(disabled_auth_message->visible()); - // Setting auth disabled will hide the password field and the note action - // button, and show the message. + // Setting auth disabled will hide the password field and show the message. DataDispatcher()->SetAuthEnabledForUser( kFirstUserAccountId, false, base::Time::Now() + base::TimeDelta::FromHours(8)); - EXPECT_FALSE(note_action_button->visible()); EXPECT_FALSE(password_view->visible()); EXPECT_FALSE(pin_view->visible()); EXPECT_TRUE(disabled_auth_message->visible()); // Setting auth enabled will hide the message and show the password field. DataDispatcher()->SetAuthEnabledForUser(kFirstUserAccountId, true, base::nullopt); - EXPECT_FALSE(note_action_button->visible()); EXPECT_TRUE(password_view->visible()); EXPECT_FALSE(pin_view->visible()); EXPECT_FALSE(disabled_auth_message->visible()); @@ -1740,25 +1736,65 @@ DataDispatcher()->SetAuthEnabledForUser( kFirstUserAccountId, false, base::Time::Now() + base::TimeDelta::FromHours(8)); - EXPECT_FALSE(note_action_button->visible()); EXPECT_FALSE(password_view->visible()); EXPECT_FALSE(pin_view->visible()); EXPECT_TRUE(disabled_auth_message->visible()); // Enable PIN. There's no UI change because auth is currently disabled. DataDispatcher()->SetPinEnabledForUser(kFirstUserAccountId, true); - EXPECT_FALSE(note_action_button->visible()); EXPECT_FALSE(password_view->visible()); EXPECT_FALSE(pin_view->visible()); EXPECT_TRUE(disabled_auth_message->visible()); // Set auth enabled again. Both password field and PIN keyboard are shown. DataDispatcher()->SetAuthEnabledForUser(kFirstUserAccountId, true, base::nullopt); - EXPECT_FALSE(note_action_button->visible()); EXPECT_TRUE(password_view->visible()); EXPECT_TRUE(pin_view->visible()); EXPECT_FALSE(disabled_auth_message->visible()); } +TEST_F(LockContentsViewUnitTest, + ToggleNoteActionVisibilityOnAuthEnabledChanged) { + auto* tray_action = Shell::Get()->tray_action(); + TestTrayActionClient action_client; + tray_action->SetClient(action_client.CreateInterfacePtrAndBind(), + mojom::TrayActionState::kAvailable); + auto* contents = new LockContentsView( + Shell::Get()->tray_action()->GetLockScreenNoteState(), + LockScreen::ScreenType::kLock, DataDispatcher(), + std::make_unique<FakeLoginDetachableBaseModel>(DataDispatcher())); + SetUserCount(1); + SetWidget(CreateWidgetWithContent(contents)); + + const AccountId& kFirstUserAccountId = + users()[0]->basic_user_info->account_id; + LockContentsView::TestApi contents_test_api(contents); + views::View* note_action_button = contents_test_api.note_action(); + + EXPECT_TRUE(note_action_button->visible()); + // Setting auth disabled hides the note action button. + DataDispatcher()->SetAuthEnabledForUser( + kFirstUserAccountId, false, + base::Time::Now() + base::TimeDelta::FromHours(8)); + EXPECT_FALSE(note_action_button->visible()); + // Setting auth enabled shows the note action button. + DataDispatcher()->SetAuthEnabledForUser(kFirstUserAccountId, true, + base::nullopt); + EXPECT_TRUE(note_action_button->visible()); + + // Set auth disabled again. + DataDispatcher()->SetAuthEnabledForUser( + kFirstUserAccountId, false, + base::Time::Now() + base::TimeDelta::FromHours(8)); + EXPECT_FALSE(note_action_button->visible()); + // Set the lock screen note state to |kNotAvailable| while the note action + // button is hidden. + tray_action->UpdateLockScreenNoteState(mojom::TrayActionState::kNotAvailable); + DataDispatcher()->SetAuthEnabledForUser(kFirstUserAccountId, true, + base::nullopt); + // The note action button remains hidden after setting auth enabled. + EXPECT_FALSE(note_action_button->visible()); +} + TEST_F(LockContentsViewUnitTest, DisabledAuthMessageFocusBehavior) { auto* contents = new LockContentsView( mojom::TrayActionState::kAvailable, LockScreen::ScreenType::kLock,
diff --git a/ash/login/ui/lock_screen.cc b/ash/login/ui/lock_screen.cc index e2ca657..bd22b09 100644 --- a/ash/login/ui/lock_screen.cc +++ b/ash/login/ui/lock_screen.cc
@@ -9,9 +9,10 @@ #include "ash/login/ui/lock_contents_view.h" #include "ash/login/ui/lock_debug_view.h" -#include "ash/login/ui/lock_window.h" #include "ash/login/ui/login_data_dispatcher.h" #include "ash/login/ui/login_detachable_base_model.h" +#include "ash/public/cpp/lock_screen_widget_factory.h" +#include "ash/public/cpp/shell_window_ids.h" #include "ash/shelf/login_shelf_view.h" #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_widget.h" @@ -22,6 +23,7 @@ #include "chromeos/chromeos_switches.h" #include "ui/display/display.h" #include "ui/display/screen.h" +#include "ui/views/widget/widget.h" #include "ui/wm/core/capture_controller.h" namespace ash { @@ -44,9 +46,18 @@ LockScreen::LockScreen(ScreenType type) : type_(type) { tray_action_observer_.Add(ash::Shell::Get()->tray_action()); + saved_clipboard_ = ui::Clipboard::TakeForCurrentThread(); } -LockScreen::~LockScreen() = default; +LockScreen::~LockScreen() { + // Must happen before data_dispatcher_.reset(). + widget_.reset(); + data_dispatcher_.reset(); + + ui::Clipboard::DestroyClipboardForCurrentThread(); + if (saved_clipboard_) + ui::Clipboard::SetClipboardForCurrentThread(std::move(saved_clipboard_)); +} // static LockScreen* LockScreen::Get() { @@ -62,8 +73,13 @@ instance_ = new LockScreen(type); - instance_->window_ = new LockWindow(); - instance_->window_->SetBounds( + aura::Window* parent = nullptr; + if (Shell::HasInstance()) { + parent = Shell::GetContainer(Shell::GetPrimaryRootWindow(), + kShellWindowId_LockScreenContainer); + } + instance_->widget_ = CreateLockScreenWidget(parent); + instance_->widget_->SetBounds( display::Screen::GetScreen()->GetPrimaryDisplay().bounds()); auto data_dispatcher = std::make_unique<LoginDataDispatcher>(); @@ -74,21 +90,22 @@ auto* debug_view = new LockDebugView(initial_note_action_state, type, data_dispatcher.get()); instance_->contents_view_ = debug_view->lock(); - instance_->window_->SetContentsView(debug_view); + instance_->widget_->SetContentsView(debug_view); } else { auto detachable_base_model = LoginDetachableBaseModel::Create( Shell::Get()->detachable_base_handler(), data_dispatcher.get()); instance_->contents_view_ = new LockContentsView( initial_note_action_state, type, data_dispatcher.get(), std::move(detachable_base_model)); - instance_->window_->SetContentsView(instance_->contents_view_); + instance_->widget_->SetContentsView(instance_->contents_view_); } data_dispatcher->AddObserver(Shelf::ForWindow(Shell::GetPrimaryRootWindow()) ->shelf_widget() ->login_shelf_view()); - instance_->window_->set_data_dispatcher(std::move(data_dispatcher)); + instance_->data_dispatcher_ = std::move(data_dispatcher); + // Postpone showing the screen after the animation of the first wallpaper // completes, to make the transition smooth. The callback will be dispatched // immediately if the animation is already complete (e.g. kLock). @@ -98,9 +115,9 @@ if (!instance_ || instance_->is_shown_) return; instance_->is_shown_ = true; - instance_->window_->Show(); + instance_->widget_->Show(); }), - instance_->window_->GetNativeView()); + instance_->widget_->GetNativeView()); } // static @@ -119,20 +136,15 @@ } CHECK_EQ(instance_, this); - data_dispatcher()->RemoveObserver( + data_dispatcher_->RemoveObserver( Shelf::ForWindow(Shell::GetPrimaryRootWindow()) ->shelf_widget() ->login_shelf_view()); - window_->Close(); delete instance_; instance_ = nullptr; } -LoginDataDispatcher* LockScreen::data_dispatcher() { - return window_->data_dispatcher(); -} - void LockScreen::FocusNextUser() { contents_view_->FocusNextUser(); }
diff --git a/ash/login/ui/lock_screen.h b/ash/login/ui/lock_screen.h index 3377acb..54936d1c5 100644 --- a/ash/login/ui/lock_screen.h +++ b/ash/login/ui/lock_screen.h
@@ -10,11 +10,15 @@ #include "ash/tray_action/tray_action_observer.h" #include "base/macros.h" #include "base/scoped_observer.h" +#include "ui/base/clipboard/clipboard.h" + +namespace views { +class Widget; +} namespace ash { class LockContentsView; -class LockWindow; class LoginDataDispatcher; class TrayAction; @@ -47,7 +51,7 @@ // Returns true if the instance has been instantiated. static bool HasInstance(); - LockWindow* window() { return window_; } + views::Widget* widget() { return widget_.get(); } // Destroys an existing lock screen instance. void Destroy(); @@ -55,7 +59,7 @@ ScreenType screen_type() const { return type_; } // Returns the active data dispatcher. - LoginDataDispatcher* data_dispatcher(); + LoginDataDispatcher* data_dispatcher() { return data_dispatcher_.get(); } // Returns if the screen has been shown (i.e. |LockWindow::Show| was called). bool is_shown() const { return is_shown_; } @@ -77,14 +81,18 @@ // The type of screen shown. Controls how the screen is dismissed. const ScreenType type_; - // Unowned pointer to the window which hosts the lock screen. - LockWindow* window_ = nullptr; + // The lock screen widget. + std::unique_ptr<views::Widget> widget_; + + std::unique_ptr<LoginDataDispatcher> data_dispatcher_; // Unowned pointer to the LockContentsView hosted in lock window. LockContentsView* contents_view_ = nullptr; bool is_shown_ = false; + std::unique_ptr<ui::Clipboard> saved_clipboard_; + ScopedObserver<TrayAction, TrayActionObserver> tray_action_observer_{this}; ScopedSessionObserver session_observer_{this};
diff --git a/ash/login/ui/lock_screen_sanity_unittest.cc b/ash/login/ui/lock_screen_sanity_unittest.cc index be51e0f5..ae36a44 100644 --- a/ash/login/ui/lock_screen_sanity_unittest.cc +++ b/ash/login/ui/lock_screen_sanity_unittest.cc
@@ -20,6 +20,9 @@ #include "ash/shell.h" #include "ash/system/status_area_widget.h" #include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "ui/base/clipboard/scoped_clipboard_writer.h" +#include "ui/events/event_constants.h" #include "ui/events/test/event_generator.h" #include "ui/views/controls/textfield/textfield.h" #include "ui/views/focus/focus_manager.h" @@ -417,4 +420,28 @@ users()[1]->basic_user_info->account_id); } +TEST_F(LockScreenSanityTest, LockScreenKillsPreventsClipboardPaste) { + { + ui::ScopedClipboardWriter writer(ui::CLIPBOARD_TYPE_COPY_PASTE); + writer.WriteText(base::UTF8ToUTF16("password")); + } + + ShowLockScreen(); + + auto* text_input = new views::Textfield; + std::unique_ptr<views::Widget> widget = CreateWidgetWithContent(text_input); + + text_input->RequestFocus(); + ui::test::EventGenerator* generator = GetEventGenerator(); + generator->PressKey(ui::KeyboardCode::VKEY_V, ui::EF_CONTROL_DOWN); + + EXPECT_TRUE(text_input->text().empty()); + + LockScreen::Get()->Destroy(); + text_input->RequestFocus(); + generator->PressKey(ui::KeyboardCode::VKEY_V, ui::EF_CONTROL_DOWN); + + EXPECT_EQ(base::UTF8ToUTF16("password"), text_input->text()); +} + } // namespace ash
diff --git a/ash/login/ui/lock_window.cc b/ash/login/ui/lock_window.cc deleted file mode 100644 index 84e3a73..0000000 --- a/ash/login/ui/lock_window.cc +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright 2014 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 "ash/login/ui/lock_window.h" - -#include "ash/public/cpp/shell_window_ids.h" -#include "ash/shell.h" -#include "ui/events/gestures/gesture_recognizer.h" -#include "ui/keyboard/keyboard_controller.h" - -namespace ash { - -LockWindow::LockWindow() { - views::Widget::InitParams params( - views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); - params.delegate = this; - params.show_state = ui::SHOW_STATE_FULLSCREEN; - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - // Shell may be null in tests. - if (Shell::HasInstance()) { - params.parent = Shell::GetContainer(Shell::GetPrimaryRootWindow(), - kShellWindowId_LockScreenContainer); - } - Init(params); - GetGestureRecognizer()->CancelActiveTouchesExcept(nullptr); - SetVisibilityAnimationTransition(views::Widget::ANIMATE_NONE); - - // Disable virtual keyboard overscroll because it interferes with scrolling - // login/lock content. See crbug.com/363635. - keyboard::mojom::KeyboardConfig config = - keyboard::KeyboardController::Get()->keyboard_config(); - config.overscroll_behavior = - keyboard::mojom::KeyboardOverscrollBehavior::kDisabled; - keyboard::KeyboardController::Get()->UpdateKeyboardConfig(config); -} - -LockWindow::~LockWindow() { - keyboard::mojom::KeyboardConfig config = - keyboard::KeyboardController::Get()->keyboard_config(); - config.overscroll_behavior = - keyboard::mojom::KeyboardOverscrollBehavior::kDefault; - keyboard::KeyboardController::Get()->UpdateKeyboardConfig(config); - - // We need to destroy the root view before destroying |data_dispatcher_| - // because lock screen destruction assumes it is alive. We could hand out - // base::WeakPtr<LoginDataDispatcher> instances if needed instead. - delete views::Widget::GetContentsView(); -} - -views::Widget* LockWindow::GetWidget() { - return this; -} - -const views::Widget* LockWindow::GetWidget() const { - return this; -} - -views::View* LockWindow::GetInitiallyFocusedView() { - // There are multiple GetContentsView definitions; use the views::Widget one. - return views::Widget::GetContentsView(); -} - -} // namespace ash
diff --git a/ash/login/ui/lock_window.h b/ash/login/ui/lock_window.h deleted file mode 100644 index 7852c36..0000000 --- a/ash/login/ui/lock_window.h +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2014 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 ASH_LOGIN_UI_LOCK_WINDOW_H_ -#define ASH_LOGIN_UI_LOCK_WINDOW_H_ - -#include "ash/ash_export.h" -#include "ash/login/ui/login_data_dispatcher.h" -#include "base/macros.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace views { -class View; -class Widget; -} // namespace views - -namespace ash { - -// Shows the widget for the lock screen. -class ASH_EXPORT LockWindow : public views::Widget, - public views::WidgetDelegate { - public: - LockWindow(); - ~LockWindow() override; - - LoginDataDispatcher* data_dispatcher() const { - return data_dispatcher_.get(); - } - - // TODO(jdufault): After webui login is removed move |data_dispatcher| to a - // constructor parameter and assert it is non-null. - void set_data_dispatcher( - std::unique_ptr<LoginDataDispatcher> data_dispatcher) { - data_dispatcher_ = std::move(data_dispatcher); - } - - private: - // views::WidgetDelegate: - views::View* GetInitiallyFocusedView() override; - views::Widget* GetWidget() override; - const views::Widget* GetWidget() const override; - - // |data_dispatcher_| is owned by LockWindow because it needs to live longer - // than the attached view hierarchy. - std::unique_ptr<LoginDataDispatcher> data_dispatcher_; - - DISALLOW_COPY_AND_ASSIGN(LockWindow); -}; - -} // namespace ash - -#endif // ASH_LOGIN_UI_LOCK_WINDOW_H_
diff --git a/ash/login/ui/lock_window_unittest.cc b/ash/login/ui/lock_window_unittest.cc index 667d4e8..bfb1d0a 100644 --- a/ash/login/ui/lock_window_unittest.cc +++ b/ash/login/ui/lock_window_unittest.cc
@@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/login/ui/lock_window.h" - #include "ash/login/ui/lock_contents_view.h" #include "ash/login/ui/lock_screen.h" #include "ash/login/ui/login_big_user_view.h"
diff --git a/ash/login/ui/login_bubble.cc b/ash/login/ui/login_bubble.cc index cef31889..9c45d6b 100644 --- a/ash/login/ui/login_bubble.cc +++ b/ash/login/ui/login_bubble.cc
@@ -9,7 +9,6 @@ #include "ash/focus_cycler.h" #include "ash/login/ui/lock_screen.h" -#include "ash/login/ui/lock_window.h" #include "ash/login/ui/login_button.h" #include "ash/login/ui/login_menu_view.h" #include "ash/login/ui/non_accessible_view.h"
diff --git a/ash/media/OWNERS b/ash/media/OWNERS new file mode 100644 index 0000000..98a39ee --- /dev/null +++ b/ash/media/OWNERS
@@ -0,0 +1 @@ +beccahughes@chromium.org
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn index 1829733..d0f837f 100644 --- a/ash/public/cpp/BUILD.gn +++ b/ash/public/cpp/BUILD.gn
@@ -74,6 +74,8 @@ "immersive/immersive_fullscreen_controller_delegate.h", "immersive/immersive_revealed_lock.cc", "immersive/immersive_revealed_lock.h", + "lock_screen_widget_factory.cc", + "lock_screen_widget_factory.h", "login_constants.h", "menu_utils.cc", "menu_utils.h", @@ -126,7 +128,9 @@ "//ash/public/cpp/vector_icons", "//chromeos:power_manager_proto", "//components/prefs", + "//mojo/public/cpp/bindings", "//services/service_manager/public/cpp", + "//services/ws/public/cpp", "//services/ws/public/mojom", "//skia/public/interfaces", "//ui/aura",
diff --git a/ash/public/cpp/accelerators.cc b/ash/public/cpp/accelerators.cc index 689b091..3b82a84 100644 --- a/ash/public/cpp/accelerators.cc +++ b/ash/public/cpp/accelerators.cc
@@ -9,8 +9,8 @@ namespace ash { const AcceleratorData kAcceleratorData[] = { - {true, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN, PREVIOUS_IME}, - {false, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN, PREVIOUS_IME}, + {true, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN, SWITCH_TO_LAST_USED_IME}, + {false, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN, SWITCH_TO_LAST_USED_IME}, {true, ui::VKEY_TAB, ui::EF_ALT_DOWN, CYCLE_FORWARD_MRU}, {true, ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, CYCLE_BACKWARD_MRU}, @@ -82,7 +82,8 @@ {true, ui::VKEY_VOLUME_DOWN, ui::EF_NONE, VOLUME_DOWN}, {true, ui::VKEY_VOLUME_UP, ui::EF_NONE, VOLUME_UP}, {true, ui::VKEY_ESCAPE, ui::EF_COMMAND_DOWN, SHOW_TASK_MANAGER}, - {true, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN, NEXT_IME}, + {true, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN, + SWITCH_TO_NEXT_IME}, {true, ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, OPEN_FEEDBACK_PAGE}, {true, ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, EXIT}, {true, ui::VKEY_N, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
diff --git a/ash/public/cpp/accelerators.h b/ash/public/cpp/accelerators.h index e521854..29f6796 100644 --- a/ash/public/cpp/accelerators.h +++ b/ash/public/cpp/accelerators.h
@@ -65,14 +65,12 @@ NEW_INCOGNITO_WINDOW, NEW_TAB, NEW_WINDOW, - NEXT_IME, OPEN_CROSH, OPEN_FEEDBACK_PAGE, OPEN_FILE_MANAGER, OPEN_GET_HELP, POWER_PRESSED, POWER_RELEASED, - PREVIOUS_IME, PRINT_UI_HIERARCHIES, RESTORE_TAB, ROTATE_SCREEN, @@ -88,6 +86,8 @@ SUSPEND, SWAP_PRIMARY_DISPLAY, SWITCH_IME, // Switch to another IME depending on the accelerator. + SWITCH_TO_LAST_USED_IME, + SWITCH_TO_NEXT_IME, SWITCH_TO_NEXT_USER, SWITCH_TO_PREVIOUS_USER, TAKE_PARTIAL_SCREENSHOT,
diff --git a/ash/public/cpp/ash_pref_names.cc b/ash/public/cpp/ash_pref_names.cc index dc0ffbd..1e46c3b 100644 --- a/ash/public/cpp/ash_pref_names.cc +++ b/ash/public/cpp/ash_pref_names.cc
@@ -330,6 +330,10 @@ // bases - for exmaple the last used base per user. const char kDetachableBaseDevices[] = "ash.detachable_base.devices"; +// Integer pref storing the number of Assistant warmer welcome triggered times. +const char kAssistantNumWarmerWelcomeTriggered[] = + "ash.assistant.num_warmer_welcome_triggered"; + // NOTE: New prefs should start with the "ash." prefix. Existing prefs moved // into this file should not be renamed, since they may be synced.
diff --git a/ash/public/cpp/ash_pref_names.h b/ash/public/cpp/ash_pref_names.h index 3eda609..143550e 100644 --- a/ash/public/cpp/ash_pref_names.h +++ b/ash/public/cpp/ash_pref_names.h
@@ -128,6 +128,8 @@ ASH_PUBLIC_EXPORT extern const char kCursorMotionBlurEnabled[]; +ASH_PUBLIC_EXPORT extern const char kAssistantNumWarmerWelcomeTriggered[]; + } // namespace prefs } // namespace ash
diff --git a/ash/public/cpp/lock_screen_widget_factory.cc b/ash/public/cpp/lock_screen_widget_factory.cc new file mode 100644 index 0000000..b8276c9e --- /dev/null +++ b/ash/public/cpp/lock_screen_widget_factory.cc
@@ -0,0 +1,62 @@ +// 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 "ash/public/cpp/lock_screen_widget_factory.h" + +#include "ash/public/cpp/shell_window_ids.h" +#include "mojo/public/cpp/bindings/type_converter.h" +#include "services/ws/public/cpp/property_type_converters.h" +#include "services/ws/public/mojom/window_manager.mojom.h" +#include "ui/aura/mus/property_converter.h" +#include "ui/aura/window.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_delegate.h" + +namespace ash { +namespace { + +class LockScreenWidgetDelegate : public views::WidgetDelegate { + public: + explicit LockScreenWidgetDelegate(views::Widget* widget) : widget_(widget) { + DCHECK(widget_); + } + ~LockScreenWidgetDelegate() override = default; + + // views::WidgetDelegate: + views::View* GetInitiallyFocusedView() override { + return widget_->GetContentsView(); + } + views::Widget* GetWidget() override { return widget_; } + const views::Widget* GetWidget() const override { return widget_; } + void DeleteDelegate() override { delete this; } + + private: + views::Widget* widget_; + + DISALLOW_COPY_AND_ASSIGN(LockScreenWidgetDelegate); +}; + +} // namespace + +std::unique_ptr<views::Widget> CreateLockScreenWidget(aura::Window* parent) { + std::unique_ptr<views::Widget> widget = std::make_unique<views::Widget>(); + views::Widget::InitParams params( + views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + // Owned by Widget. + params.delegate = new LockScreenWidgetDelegate(widget.get()); + params.show_state = ui::SHOW_STATE_FULLSCREEN; + params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; + params.parent = parent; + if (!parent) { + params.mus_properties[ws::mojom::WindowManager::kContainerId_InitProperty] = + mojo::ConvertTo<std::vector<uint8_t>>( + static_cast<int32_t>(ash::kShellWindowId_OverlayContainer)); + } + widget->Init(params); + widget->SetVisibilityAnimationTransition(views::Widget::ANIMATE_NONE); + return widget; +} + +} // namespace ash
diff --git a/ash/public/cpp/lock_screen_widget_factory.h b/ash/public/cpp/lock_screen_widget_factory.h new file mode 100644 index 0000000..57a3848 --- /dev/null +++ b/ash/public/cpp/lock_screen_widget_factory.h
@@ -0,0 +1,31 @@ +// 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 ASH_PUBLIC_CPP_LOCK_SCREEN_WIDGET_FACTORY_H_ +#define ASH_PUBLIC_CPP_LOCK_SCREEN_WIDGET_FACTORY_H_ + +#include <memory> + +#include "ash/public/cpp/ash_public_export.h" + +namespace aura { +class Window; +} + +namespace views { +class Widget; +} + +namespace ash { + +// Creates a widget shown on the lock-screen. The widget is configured such +// that the caller owns it (InitParams::WIDGET_OWNS_NATIVE_WIDGET). |parent| +// should only be supplied if called from ash, otherwise use null to get the +// right container. +ASH_PUBLIC_EXPORT std::unique_ptr<views::Widget> CreateLockScreenWidget( + aura::Window* parent = nullptr); + +} // namespace ash + +#endif // ASH_PUBLIC_CPP_LOCK_SCREEN_WIDGET_FACTORY_H_
diff --git a/ash/public/interfaces/accessibility_controller.mojom b/ash/public/interfaces/accessibility_controller.mojom index f95fca1b..d330d57 100644 --- a/ash/public/interfaces/accessibility_controller.mojom +++ b/ash/public/interfaces/accessibility_controller.mojom
@@ -112,6 +112,13 @@ DispatchMouseEvent(ui.mojom.Event event); }; +// Allows a client to implement Switch Access. +interface SwitchAccessEventHandlerDelegate { + // Sends a KeyEvent to the Switch Access extension in Chrome. The event + // is cast to a key event with a type CHECK. + DispatchKeyEvent(ui.mojom.Event event); +}; + // Interface for ash client (e.g. Chrome) to control and query accessibility // features. interface AccessibilityController { @@ -151,6 +158,13 @@ SetSelectToSpeakEventHandlerDelegate( SelectToSpeakEventHandlerDelegate delegate); + // Sets the key codes that Switch Access should capture. + SetSwitchAccessKeysToCapture(array<int32> keys_to_capture); + + // Set the delegate used by the Switch Access event handler. + SetSwitchAccessEventHandlerDelegate( + SwitchAccessEventHandlerDelegate delegate); + // Starts or stops dictation. Records metrics for toggling via SwitchAccess. ToggleDictationFromSource(DictationToggleSource source); };
diff --git a/ash/public/interfaces/ime_controller.mojom b/ash/public/interfaces/ime_controller.mojom index 0adbc0e..6bbcbcc 100644 --- a/ash/public/interfaces/ime_controller.mojom +++ b/ash/public/interfaces/ime_controller.mojom
@@ -62,9 +62,9 @@ // is installed. SwitchToNextIme(); - // Switches to the previous input method. Does nothing if only one input + // Switches to the last used input method. Does nothing if only one input // method is installed. - SwitchToPreviousIme(); + SwitchToLastUsedIme(); // Switches to an input method by |id|. Does nothing if the input method is // not installed. The ID is usually the output of a call like @@ -86,6 +86,14 @@ // caps lock. SetCapsLockEnabled(bool enabled); + // Notifies the mirroring state change to the client where IME lives (e.g. + // Chrome), so that the IME can behave according to the state. + UpdateMirroringState(bool enabled); + + // Notifies the casting state change to the client where IME lives (e.g. + // Chrome), so that the IME can behave according to the state. + UpdateCastingState(bool enabled); + // Overrides the keyboard keyset (emoji, handwriting or voice). If keyset is // 'kNone', we switch to the default keyset. Because this is asynchronous, // any code that needs the keyset to be updated first must use the callback.
diff --git a/ash/shelf/login_shelf_view.cc b/ash/shelf/login_shelf_view.cc index d793634..b5e85711 100644 --- a/ash/shelf/login_shelf_view.cc +++ b/ash/shelf/login_shelf_view.cc
@@ -12,7 +12,6 @@ #include "ash/lock_screen_action/lock_screen_action_background_state.h" #include "ash/login/login_screen_controller.h" #include "ash/login/ui/lock_screen.h" -#include "ash/login/ui/lock_window.h" #include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/login_constants.h" #include "ash/public/interfaces/kiosk_app_info.mojom.h" @@ -56,6 +55,7 @@ #include "ui/views/controls/menu/menu_types.h" #include "ui/views/focus/focus_search.h" #include "ui/views/layout/box_layout.h" +#include "ui/views/widget/widget.h" using session_manager::SessionState; @@ -438,7 +438,7 @@ void LoginShelfView::GetAccessibleNodeData(ui::AXNodeData* node_data) { if (LockScreen::HasInstance()) { int previous_id = views::AXAuraObjCache::GetInstance()->GetID( - static_cast<views::Widget*>(LockScreen::Get()->window())); + LockScreen::Get()->widget()); node_data->AddIntAttribute(ax::mojom::IntAttribute::kPreviousFocusId, previous_id); }
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc index 8616142..6fde77b 100644 --- a/ash/shelf/shelf_layout_manager.cc +++ b/ash/shelf/shelf_layout_manager.cc
@@ -450,8 +450,75 @@ return false; } -//////////////////////////////////////////////////////////////////////////////// -// ShelfLayoutManager, wm::WmSnapToPixelLayoutManager implementation: +ShelfBackgroundType ShelfLayoutManager::GetShelfBackgroundType() const { + if (state_.pre_lock_screen_animation_active) + return SHELF_BACKGROUND_DEFAULT; + + // Handle all other non active screen states, including OOBE and pre-login. + if (state_.session_state == session_manager::SessionState::OOBE) + return SHELF_BACKGROUND_OOBE; + if (state_.session_state != session_manager::SessionState::ACTIVE) { + if (Shell::Get()->wallpaper_controller()->HasShownAnyWallpaper() && + !Shell::Get()->wallpaper_controller()->IsWallpaperBlurred()) { + return SHELF_BACKGROUND_LOGIN_NONBLURRED_WALLPAPER; + } + return SHELF_BACKGROUND_LOGIN; + } + + // If the app list is active and the home launcher is not shown, hide the + // shelf background to prevent overlap. + if (is_app_list_visible_ && !IsHomeLauncherEnabledInTabletMode()) + return SHELF_BACKGROUND_APP_LIST; + + if (state_.visibility_state != SHELF_AUTO_HIDE && + state_.window_state == wm::WORKSPACE_WINDOW_STATE_MAXIMIZED) { + return SHELF_BACKGROUND_MAXIMIZED; + } + + if (gesture_drag_status_ == GESTURE_DRAG_IN_PROGRESS || + window_overlaps_shelf_ || state_.visibility_state == SHELF_AUTO_HIDE) { + return SHELF_BACKGROUND_OVERLAP; + } + + if (Shell::Get()->window_selector_controller() && + Shell::Get()->window_selector_controller()->IsSelecting()) { + return SHELF_BACKGROUND_OVERLAP; + } + + // If split view mode is active, make the shelf fully opapue. + if (Shell::Get()->IsSplitViewModeActive()) + return SHELF_BACKGROUND_SPLIT_VIEW; + + return SHELF_BACKGROUND_DEFAULT; +} + +void ShelfLayoutManager::SetAccessibilityPanelHeight(int height) { + accessibility_panel_height_ = height; + LayoutShelf(); +} + +void ShelfLayoutManager::SetDockedMagnifierHeight(int height) { + docked_magnifier_height_ = height; + LayoutShelf(); +} + +void ShelfLayoutManager::MaybeUpdateShelfBackground(AnimationChangeType type) { + const ShelfBackgroundType new_background_type(GetShelfBackgroundType()); + + if (new_background_type == shelf_background_type_) + return; + + shelf_background_type_ = new_background_type; + for (auto& observer : observers_) + observer.OnBackgroundUpdated(shelf_background_type_, type); +} + +bool ShelfLayoutManager::ShouldBlurShelfBackground() { + return IsBackgroundBlurEnabled() && + (shelf_background_type_ == SHELF_BACKGROUND_DEFAULT || + shelf_background_type_ == SHELF_BACKGROUND_OVERLAP) && + state_.session_state == session_manager::SessionState::ACTIVE; +} void ShelfLayoutManager::OnWindowResized() { LayoutShelf(); @@ -538,67 +605,65 @@ } } -ShelfBackgroundType ShelfLayoutManager::GetShelfBackgroundType() const { - if (state_.pre_lock_screen_animation_active) - return SHELF_BACKGROUND_DEFAULT; - - // Handle all other non active screen states, including OOBE and pre-login. - if (state_.session_state == session_manager::SessionState::OOBE) - return SHELF_BACKGROUND_OOBE; - if (state_.session_state != session_manager::SessionState::ACTIVE) { - if (Shell::Get()->wallpaper_controller()->HasShownAnyWallpaper() && - !Shell::Get()->wallpaper_controller()->IsWallpaperBlurred()) { - return SHELF_BACKGROUND_LOGIN_NONBLURRED_WALLPAPER; - } - return SHELF_BACKGROUND_LOGIN; +void ShelfLayoutManager::OnLockStateEvent(LockStateObserver::EventType event) { + if (event == EVENT_LOCK_ANIMATION_STARTED) { + // Enter the screen locked state and update the visibility to avoid an odd + // animation when transitioning the orientation from L/R to bottom. + state_.pre_lock_screen_animation_active = true; + UpdateShelfVisibilityAfterLoginUIChange(); + } else { + state_.pre_lock_screen_animation_active = false; } - - // If the app list is active and the home launcher is not shown, hide the - // shelf background to prevent overlap. - if (is_app_list_visible_ && !IsHomeLauncherEnabledInTabletMode()) - return SHELF_BACKGROUND_APP_LIST; - - if (state_.visibility_state != SHELF_AUTO_HIDE && - state_.window_state == wm::WORKSPACE_WINDOW_STATE_MAXIMIZED) { - return SHELF_BACKGROUND_MAXIMIZED; - } - - if (gesture_drag_status_ == GESTURE_DRAG_IN_PROGRESS || - window_overlaps_shelf_ || state_.visibility_state == SHELF_AUTO_HIDE) { - return SHELF_BACKGROUND_OVERLAP; - } - - if (Shell::Get()->window_selector_controller() && - Shell::Get()->window_selector_controller()->IsSelecting()) { - return SHELF_BACKGROUND_OVERLAP; - } - - // If split view mode is active, make the shelf fully opapue. - if (Shell::Get()->IsSplitViewModeActive()) - return SHELF_BACKGROUND_SPLIT_VIEW; - - return SHELF_BACKGROUND_DEFAULT; + MaybeUpdateShelfBackground(AnimationChangeType::ANIMATE); } -void ShelfLayoutManager::SetAccessibilityPanelHeight(int height) { - accessibility_panel_height_ = height; - LayoutShelf(); -} - -void ShelfLayoutManager::SetDockedMagnifierHeight(int height) { - docked_magnifier_height_ = height; - LayoutShelf(); -} - -void ShelfLayoutManager::MaybeUpdateShelfBackground(AnimationChangeType type) { - const ShelfBackgroundType new_background_type(GetShelfBackgroundType()); - - if (new_background_type == shelf_background_type_) +void ShelfLayoutManager::OnSessionStateChanged( + session_manager::SessionState state) { + // Check transition changes to/from the add user to session and change the + // shelf alignment accordingly + const bool was_adding_user = state_.IsAddingSecondaryUser(); + const bool was_locked = state_.IsScreenLocked(); + state_.session_state = state; + MaybeUpdateShelfBackground(AnimationChangeType::ANIMATE); + if (was_adding_user != state_.IsAddingSecondaryUser()) { + UpdateShelfVisibilityAfterLoginUIChange(); return; + } - shelf_background_type_ = new_background_type; - for (auto& observer : observers_) - observer.OnBackgroundUpdated(shelf_background_type_, type); + // Force the shelf to layout for alignment (bottom if locked, restore the + // previous alignment otherwise). + if (was_locked != state_.IsScreenLocked()) + UpdateShelfVisibilityAfterLoginUIChange(); + + TargetBounds target_bounds; + CalculateTargetBounds(state_, &target_bounds); + UpdateBoundsAndOpacity(target_bounds, true /* animate */, nullptr); + UpdateVisibilityState(); +} + +void ShelfLayoutManager::OnLoginStatusChanged(LoginStatus loing_status) { + UpdateVisibilityState(); +} + +void ShelfLayoutManager::OnWallpaperBlurChanged() { + MaybeUpdateShelfBackground(AnimationChangeType::ANIMATE); +} + +void ShelfLayoutManager::OnFirstWallpaperShown() { + MaybeUpdateShelfBackground(AnimationChangeType::ANIMATE); +} + +void ShelfLayoutManager::OnDisplayMetricsChanged( + const display::Display& display, + uint32_t changed_metrics) { + // Update |user_work_area_bounds_| for the new display arrangement. + TargetBounds target_bounds; + CalculateTargetBounds(state_, &target_bounds); +} + +void ShelfLayoutManager::OnLocaleChanged() { + // Layout update is needed when language changes between LTR and RTL. + LayoutShelfAndUpdateBounds(); } //////////////////////////////////////////////////////////////////////////////// @@ -1106,54 +1171,6 @@ return 0; } -void ShelfLayoutManager::OnLockStateEvent(LockStateObserver::EventType event) { - if (event == EVENT_LOCK_ANIMATION_STARTED) { - // Enter the screen locked state and update the visibility to avoid an odd - // animation when transitioning the orientation from L/R to bottom. - state_.pre_lock_screen_animation_active = true; - UpdateShelfVisibilityAfterLoginUIChange(); - } else { - state_.pre_lock_screen_animation_active = false; - } - MaybeUpdateShelfBackground(AnimationChangeType::ANIMATE); -} - -void ShelfLayoutManager::OnSessionStateChanged( - session_manager::SessionState state) { - // Check transition changes to/from the add user to session and change the - // shelf alignment accordingly - const bool was_adding_user = state_.IsAddingSecondaryUser(); - const bool was_locked = state_.IsScreenLocked(); - state_.session_state = state; - MaybeUpdateShelfBackground(AnimationChangeType::ANIMATE); - if (was_adding_user != state_.IsAddingSecondaryUser()) { - UpdateShelfVisibilityAfterLoginUIChange(); - return; - } - - // Force the shelf to layout for alignment (bottom if locked, restore the - // previous alignment otherwise). - if (was_locked != state_.IsScreenLocked()) - UpdateShelfVisibilityAfterLoginUIChange(); - - TargetBounds target_bounds; - CalculateTargetBounds(state_, &target_bounds); - UpdateBoundsAndOpacity(target_bounds, true /* animate */, nullptr); - UpdateVisibilityState(); -} - -void ShelfLayoutManager::OnWallpaperBlurChanged() { - MaybeUpdateShelfBackground(AnimationChangeType::ANIMATE); -} - -void ShelfLayoutManager::OnFirstWallpaperShown() { - MaybeUpdateShelfBackground(AnimationChangeType::ANIMATE); -} - -void ShelfLayoutManager::OnLoginStatusChanged(LoginStatus loing_status) { - UpdateVisibilityState(); -} - void ShelfLayoutManager::UpdateShelfVisibilityAfterLoginUIChange() { UpdateVisibilityState(); LayoutShelf(); @@ -1186,16 +1203,6 @@ active_window->autohide_shelf_when_maximized_or_fullscreen(); } -bool ShelfLayoutManager::ShouldBlurShelfBackground() { - return IsBackgroundBlurEnabled() && - (shelf_background_type_ == SHELF_BACKGROUND_DEFAULT || - shelf_background_type_ == SHELF_BACKGROUND_OVERLAP) && - state_.session_state == session_manager::SessionState::ACTIVE; -} - -//////////////////////////////////////////////////////////////////////////////// -// ShelfLayoutManager, Gesture functions: - bool ShelfLayoutManager::ShouldHomeGestureHandleEvent(float scroll_y) const { HomeLauncherGestureHandler* home_launcher_handler = Shell::Get()->app_list_controller()->home_launcher_gesture_handler(); @@ -1490,14 +1497,6 @@ return false; } -void ShelfLayoutManager::OnDisplayMetricsChanged( - const display::Display& display, - uint32_t changed_metrics) { - // Update |user_work_area_bounds_| for the new display arrangement. - TargetBounds target_bounds; - CalculateTargetBounds(state_, &target_bounds); -} - void ShelfLayoutManager::UpdateWorkspaceMask( wm::WorkspaceWindowState window_state) { // Disable the mask on NonLockScreenContainer if maximized/fullscreen window @@ -1520,9 +1519,4 @@ } } -void ShelfLayoutManager::OnLocaleChanged() { - // Layout update is needed when language changes between LTR and RTL. - LayoutShelfAndUpdateBounds(); -} - } // namespace ash
diff --git a/ash/shelf/shelf_layout_manager.h b/ash/shelf/shelf_layout_manager.h index 416aedb5..a31e7b7 100644 --- a/ash/shelf/shelf_layout_manager.h +++ b/ash/shelf/shelf_layout_manager.h
@@ -75,8 +75,6 @@ ShelfLayoutManager(ShelfWidget* shelf_widget, Shelf* shelf); ~ShelfLayoutManager() override; - bool updating_bounds() const { return updating_bounds_; } - // Clears internal data for shutdown process. void PrepareForShutdown(); // Returns whether the shelf and its contents (shelf, status) are visible @@ -89,12 +87,6 @@ // Returns the preferred size of the shelf for the target visibility state. gfx::Size GetPreferredSize(); - // Returns the bounds within the root window not occupied by the shelf nor the - // virtual keyboard. - const gfx::Rect& user_work_area_bounds() const { - return user_work_area_bounds_; - } - // Stops any animations and sets the bounds of the shelf and status widgets. void LayoutShelfAndUpdateBounds(); @@ -120,21 +112,9 @@ void ProcessGestureEventOfAutoHideShelf(ui::GestureEvent* event, aura::Window* target); - ShelfVisibilityState visibility_state() const { - return state_.visibility_state; - } - ShelfAutoHideState auto_hide_state() const { return state_.auto_hide_state; } - - int accessibility_panel_height() const { return accessibility_panel_height_; } - - int docked_magnifier_height() const { return docked_magnifier_height_; } - - ShelfWidget* shelf_widget() { return shelf_widget_; } - // Sets whether any windows overlap the shelf. If a window overlaps the shelf // the shelf renders slightly differently. void SetWindowOverlapsShelf(bool value); - bool window_overlaps_shelf() const { return window_overlaps_shelf_; } void AddObserver(ShelfLayoutManagerObserver* observer); void RemoveObserver(ShelfLayoutManagerObserver* observer); @@ -149,20 +129,32 @@ // it's only allowed in tablet mode, not in laptop mode. bool IsDraggingWindowFromTopOrCaptionArea() const; - // Returns whether background blur is enabled. - bool IsBackgroundBlurEnabled() { return is_background_blur_enabled_; } + // Returns how the shelf background should be painted. + ShelfBackgroundType GetShelfBackgroundType() const; + + // Set the height of the accessibility panel, which takes away space from the + // available work area from the top of the screen. Used by ChromeVox. + void SetAccessibilityPanelHeight(int height); + + // Set the height of the Docked Magnifier viewport at the top of the screen, + // which will reduce the available screen work area similarly to the ChromeVox + // panel height. The Docked Magnifier appears above the ChromeVox panel. + void SetDockedMagnifierHeight(int height); + + // Updates the background of the shelf if it has changed. + void MaybeUpdateShelfBackground(AnimationChangeType change_type); // Returns whether the shelf should show a blurred background. This may // return false even if background blur is enabled depending on the session // state. bool ShouldBlurShelfBackground(); - // Overridden from wm::WmSnapToPixelLayoutManager: + // wm::WmSnapToPixelLayoutManager: void OnWindowResized() override; void SetChildBounds(aura::Window* child, const gfx::Rect& requested_bounds) override; - // Overridden from ShellObserver: + // ShellObserver: void OnShelfAutoHideBehaviorChanged(aura::Window* root_window) override; void OnPinnedStateChanged(aura::Window* pinned_window) override; void OnAppListVisibilityChanged(bool shown, @@ -172,24 +164,24 @@ void OnSplitViewModeStarted() override; void OnSplitViewModeEnded() override; - // Overridden from wm::ActivationChangeObserver: + // wm::ActivationChangeObserver: void OnWindowActivated(ActivationReason reason, aura::Window* gained_active, aura::Window* lost_active) override; - // Overridden from keyboard::KeyboardControllerObserver: + // keyboard::KeyboardControllerObserver: void OnKeyboardAppearanceChanged( const keyboard::KeyboardStateDescriptor& state) override; void OnKeyboardVisibilityStateChanged(bool is_visible) override; - // Overridden from LockStateObserver: + // LockStateObserver: void OnLockStateEvent(LockStateObserver::EventType event) override; - // Overridden from SessionObserver: + // SessionObserver: void OnSessionStateChanged(session_manager::SessionState state) override; void OnLoginStatusChanged(LoginStatus loing_status) override; - // Overridden from WallpaperControllerObserver: + // WallpaperControllerObserver: void OnWallpaperBlurChanged() override; void OnFirstWallpaperShown() override; @@ -197,6 +189,28 @@ void OnDisplayMetricsChanged(const display::Display& display, uint32_t changed_metrics) override; + // LocaleChangeObserver: + void OnLocaleChanged() override; + + // Returns the bounds within the root window not occupied by the shelf nor the + // virtual keyboard. + const gfx::Rect& user_work_area_bounds() const { + return user_work_area_bounds_; + } + + ShelfVisibilityState visibility_state() const { + return state_.visibility_state; + } + bool updating_bounds() const { return updating_bounds_; } + ShelfAutoHideState auto_hide_state() const { return state_.auto_hide_state; } + int accessibility_panel_height() const { return accessibility_panel_height_; } + int docked_magnifier_height() const { return docked_magnifier_height_; } + ShelfWidget* shelf_widget() { return shelf_widget_; } + bool window_overlaps_shelf() const { return window_overlaps_shelf_; } + + // Returns whether background blur is enabled. + bool IsBackgroundBlurEnabled() { return is_background_blur_enabled_; } + // TODO(harrym|oshima): These templates will be moved to a new Shelf class. // A helper function for choosing values specific to a shelf alignment. template <typename T> @@ -219,24 +233,6 @@ return shelf_->IsHorizontalAlignment() ? horizontal : vertical; } - // Returns how the shelf background should be painted. - ShelfBackgroundType GetShelfBackgroundType() const; - - // Set the height of the accessibility panel, which takes away space from the - // available work area from the top of the screen. Used by ChromeVox. - void SetAccessibilityPanelHeight(int height); - - // Set the height of the Docked Magnifier viewport at the top of the screen, - // which will reduce the available screen work area similarly to the ChromeVox - // panel height. The Docked Magnifier appears above the ChromeVox panel. - void SetDockedMagnifierHeight(int height); - - // Updates the background of the shelf if it has changed. - void MaybeUpdateShelfBackground(AnimationChangeType change_type); - - // LocaleChangeObserver: - void OnLocaleChanged() override; - private: class UpdateShelfObserver; friend class PanelLayoutManagerTest;
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc index 2f2ea86..ff77302 100644 --- a/ash/shelf/shelf_layout_manager_unittest.cc +++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -2392,37 +2392,37 @@ HomeLauncherGestureHandler* gesture_handler = Shell::Get()->app_list_controller()->home_launcher_gesture_handler(); ASSERT_TRUE(gesture_handler); - ASSERT_FALSE(gesture_handler->window()); + ASSERT_FALSE(gesture_handler->GetWindow1()); // Tests that after scrolling up on the shelf, the home launcher gesture // handler will be acting on |window|. manager->ProcessGestureEvent( create_scroll_event(ui::ET_GESTURE_SCROLL_BEGIN, -1.f)); - EXPECT_EQ(window.get(), gesture_handler->window()); + EXPECT_EQ(window.get(), gesture_handler->GetWindow1()); // Tests that since the initial scroll event was scrolled up, the home // launcher gesture handler will continue to act on |window| regardless of // direction of scroll updates. manager->ProcessGestureEvent( create_scroll_event(ui::ET_GESTURE_SCROLL_UPDATE, -1.f)); - EXPECT_EQ(window.get(), gesture_handler->window()); + EXPECT_EQ(window.get(), gesture_handler->GetWindow1()); manager->ProcessGestureEvent( create_scroll_event(ui::ET_GESTURE_SCROLL_UPDATE, 1.f)); - EXPECT_EQ(window.get(), gesture_handler->window()); + EXPECT_EQ(window.get(), gesture_handler->GetWindow1()); // End the scroll. manager->ProcessGestureEvent( create_scroll_event(ui::ET_GESTURE_SCROLL_END, 1.f)); - ASSERT_FALSE(gesture_handler->window()); + ASSERT_FALSE(gesture_handler->GetWindow1()); // Tests that if the initial scroll event is directed downwards, the home // launcher gesture handler will not act on |window|. manager->ProcessGestureEvent( create_scroll_event(ui::ET_GESTURE_SCROLL_BEGIN, 1.f)); - EXPECT_FALSE(gesture_handler->window()); + EXPECT_FALSE(gesture_handler->GetWindow1()); manager->ProcessGestureEvent( create_scroll_event(ui::ET_GESTURE_SCROLL_UPDATE, -1.f)); - EXPECT_FALSE(gesture_handler->window()); + EXPECT_FALSE(gesture_handler->GetWindow1()); } // Tests that tap outside of the AUTO_HIDE_SHOWN shelf should hide it.
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc index 99bbe3f..551cdd4 100644 --- a/ash/shelf/shelf_widget.cc +++ b/ash/shelf/shelf_widget.cc
@@ -220,9 +220,8 @@ return; } - if (!opaque_background_.visible()) { + if (!opaque_background_.visible()) opaque_background_.SetVisible(true); - } // Show rounded corners except in maximized and split modes. if (background_type == SHELF_BACKGROUND_MAXIMIZED ||
diff --git a/ash/shell.cc b/ash/shell.cc index eacdff0..9c2a4e2 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -241,6 +241,7 @@ // Registers prefs whose default values are same in user and signin prefs. void RegisterProfilePrefs(PrefRegistrySimple* registry, bool for_test) { AccessibilityController::RegisterProfilePrefs(registry, for_test); + AssistantController::RegisterProfilePrefs(registry); BluetoothPowerController::RegisterProfilePrefs(registry); DockedMagnifierController::RegisterProfilePrefs(registry, for_test); LoginScreenController::RegisterProfilePrefs(registry, for_test); @@ -870,6 +871,7 @@ accessibility_delegate_.reset(); accessibility_focus_ring_controller_.reset(); policy_recommendation_restorer_.reset(); + ime_controller_.reset(); // Balances the Install() in Initialize(). views::FocusManagerFactory::Install(nullptr);
diff --git a/ash/system/message_center/ash_message_center_lock_screen_controller.cc b/ash/system/message_center/ash_message_center_lock_screen_controller.cc index 9f83341..02fcf07 100644 --- a/ash/system/message_center/ash_message_center_lock_screen_controller.cc +++ b/ash/system/message_center/ash_message_center_lock_screen_controller.cc
@@ -5,7 +5,6 @@ #include "ash/system/message_center/ash_message_center_lock_screen_controller.h" #include "ash/login/ui/lock_screen.h" -#include "ash/login/ui/lock_window.h" #include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/ash_pref_names.h" #include "ash/session/session_controller.h" @@ -19,6 +18,7 @@ #include "base/strings/utf_string_conversions.h" #include "components/prefs/pref_service.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/views/widget/widget.h" namespace ash { @@ -92,9 +92,9 @@ DCHECK(locked_); DCHECK(LockScreen::Get()); - DCHECK(LockScreen::Get()->window()); + DCHECK(LockScreen::Get()->widget()); auto* unified_system_tray = - Shelf::ForWindow(LockScreen::Get()->window()->GetNativeWindow()) + Shelf::ForWindow(LockScreen::Get()->widget()->GetNativeWindow()) ->GetStatusAreaWidget() ->unified_system_tray(); if (unified_system_tray) {
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc index 0180cc08..fc7ee01 100644 --- a/ash/system/tray/tray_background_view.cc +++ b/ash/system/tray/tray_background_view.cc
@@ -9,7 +9,6 @@ #include "ash/focus_cycler.h" #include "ash/login/ui/lock_screen.h" -#include "ash/login/ui/lock_window.h" #include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/shelf/shelf_constants.h" @@ -303,7 +302,7 @@ if (LockScreen::HasInstance()) { int next_id = views::AXAuraObjCache::GetInstance()->GetID( - static_cast<views::Widget*>(LockScreen::Get()->window())); + LockScreen::Get()->widget()); node_data->AddIntAttribute(ax::mojom::IntAttribute::kNextFocusId, next_id); }
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc index 79c77290..611d5a5bb 100644 --- a/ash/wallpaper/wallpaper_controller_unittest.cc +++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -29,6 +29,7 @@ #include "base/task/post_task.h" #include "base/task/task_scheduler/task_scheduler.h" #include "base/test/bind_test_util.h" +#include "base/time/time_override.h" #include "chromeos/chromeos_switches.h" #include "components/prefs/testing_pref_service.h" #include "mojo/public/cpp/bindings/associated_binding.h" @@ -206,6 +207,7 @@ // See content::RunAllTasksUntilIdle(). void RunAllTasksUntilIdle() { + LOG(ERROR) << "RunAllTasksUntilIdle - before"; while (true) { TaskObserver task_observer; base::MessageLoopCurrent::Get()->AddTaskObserver(&task_observer); @@ -218,6 +220,7 @@ if (!task_observer.processed()) break; } + LOG(ERROR) << "RunAllTasksUntilIdle - after"; } // A test implementation of the WallpaperObserver mojo interface. @@ -2334,9 +2337,26 @@ base::BindLambdaForTesting( [&is_second_callback_run]() { is_second_callback_run = true; }), test_window.get()); + { + // The animation is quite short (0.01 seconds) which is problematic in + // debug builds if RunAllTasksUntilIdle is a bit slow to execute. That leads + // to test flakes. We work around that by temporarily freezing time, which + // prevents the animation from unexpectedly completing too soon. + // Ideally this test should use MockTime instead, which will become easier + // after https://crrev.com/c/1352260 lands. + base::subtle::ScopedTimeClockOverrides time_override( + nullptr, + []() { + static base::TimeTicks time_ticks = + base::subtle::TimeTicksNowIgnoringOverride(); + return time_ticks; + }, + nullptr); + + RunAllTasksUntilIdle(); + } // Neither callback is run because the animation of the first wallpaper // hasn't finished yet. - RunAllTasksUntilIdle(); EXPECT_FALSE(is_first_callback_run); EXPECT_FALSE(is_second_callback_run);
diff --git a/ash/wm/lock_layout_manager.cc b/ash/wm/lock_layout_manager.cc index 52ed90b..919385b 100644 --- a/ash/wm/lock_layout_manager.cc +++ b/ash/wm/lock_layout_manager.cc
@@ -9,7 +9,9 @@ #include "ash/wm/lock_window_state.h" #include "ash/wm/window_state.h" #include "ash/wm/wm_event.h" +#include "ui/aura/env.h" #include "ui/events/event.h" +#include "ui/events/gestures/gesture_recognizer.h" #include "ui/keyboard/keyboard_controller.h" namespace ash { @@ -49,13 +51,30 @@ wm::WindowState* window_state = LockWindowState::SetLockWindowState(child); wm::WMEvent event(wm::WM_EVENT_ADDED_TO_WORKSPACE); window_state->OnWMEvent(&event); + + Shell::Get()->aura_env()->gesture_recognizer()->CancelActiveTouchesExcept( + nullptr); + + // Disable virtual keyboard overscroll because it interferes with scrolling + // login/lock content. See crbug.com/363635. + keyboard::mojom::KeyboardConfig config = + keyboard::KeyboardController::Get()->keyboard_config(); + config.overscroll_behavior = + keyboard::mojom::KeyboardOverscrollBehavior::kDisabled; + keyboard::KeyboardController::Get()->UpdateKeyboardConfig(config); } void LockLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { child->RemoveObserver(this); } -void LockLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {} +void LockLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) { + keyboard::mojom::KeyboardConfig config = + keyboard::KeyboardController::Get()->keyboard_config(); + config.overscroll_behavior = + keyboard::mojom::KeyboardOverscrollBehavior::kDefault; + keyboard::KeyboardController::Get()->UpdateKeyboardConfig(config); +} void LockLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, bool visible) {}
diff --git a/ash/wm/splitview/split_view_drag_indicators.cc b/ash/wm/splitview/split_view_drag_indicators.cc index d893db42..22b7ba0b 100644 --- a/ash/wm/splitview/split_view_drag_indicators.cc +++ b/ash/wm/splitview/split_view_drag_indicators.cc
@@ -6,6 +6,7 @@ #include "ash/public/cpp/shell_window_ids.h" #include "ash/screen_util.h" +#include "ash/shelf/shelf.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/wm/overview/rounded_rect_view.h" @@ -100,6 +101,17 @@ return transform; } +// Returns the work area bounds that has no overlap with shelf. +gfx::Rect GetWorkAreaBoundsNoOverlapWithShelf(aura::Window* root_window) { + aura::Window* window = + root_window->GetChildById(kShellWindowId_OverlayContainer); + gfx::Rect bounds = screen_util::GetDisplayWorkAreaBoundsInParent(window); + ::wm::ConvertRectToScreen(root_window, &bounds); + + bounds.Subtract(Shelf::ForWindow(root_window)->GetIdealBounds()); + return bounds; +} + } // namespace // static @@ -339,9 +351,9 @@ display_width - highlight_width - kHighlightScreenEdgePaddingDp, kHighlightScreenEdgePaddingDp); - const gfx::Point hightlight_padding_point(kHighlightScreenEdgePaddingDp, - kHighlightScreenEdgePaddingDp); - gfx::Rect left_highlight_bounds(hightlight_padding_point, highlight_size); + const gfx::Point highlight_padding_point(kHighlightScreenEdgePaddingDp, + kHighlightScreenEdgePaddingDp); + gfx::Rect left_highlight_bounds(highlight_padding_point, highlight_size); gfx::Rect right_highlight_bounds(right_bottom_origin, highlight_size); if (!landscape) { left_highlight_bounds.Transpose(); @@ -356,10 +368,15 @@ GetWidget()->GetNativeWindow(), preview_left ? SplitViewController::LEFT : SplitViewController::RIGHT); - gfx::Rect work_area_bounds = Shell::Get() - ->split_view_controller() - ->GetDisplayWorkAreaBoundsInScreen( - GetWidget()->GetNativeWindow()); + + aura::Window* root_window = + GetWidget()->GetNativeWindow()->GetRootWindow(); + // Preview area should have no overlap with the shelf. + preview_area_bounds.Subtract( + Shelf::ForWindow(root_window)->GetIdealBounds()); + + const gfx::Rect work_area_bounds = + GetWorkAreaBoundsNoOverlapWithShelf(root_window); preview_area_bounds.set_y(preview_area_bounds.y() - work_area_bounds.y()); preview_area_bounds.Inset(kHighlightScreenEdgePaddingDp, kHighlightScreenEdgePaddingDp); @@ -379,7 +396,7 @@ left_highlight_bounds = preview_area_bounds; right_highlight_bounds = other_bounds; } else { - other_bounds.set_origin(hightlight_padding_point); + other_bounds.set_origin(highlight_padding_point); left_highlight_bounds = other_bounds; right_highlight_bounds = preview_area_bounds; } @@ -404,8 +421,8 @@ highlight_size.height() / 2 - size.height() / 2, size.width(), size.height()); gfx::Rect right_rotated_bounds = left_rotated_bounds; - left_rotated_bounds.Offset(hightlight_padding_point.x(), - hightlight_padding_point.y()); + left_rotated_bounds.Offset(highlight_padding_point.x(), + highlight_padding_point.y()); if (!landscape) { right_bottom_origin.SetPoint(right_bottom_origin.y(), right_bottom_origin.x()); @@ -483,10 +500,7 @@ Shell::GetContainer(root_window, kShellWindowId_OverlayContainer)); widget_->SetContentsView(indicators_view_); } - gfx::Rect bounds = screen_util::GetDisplayWorkAreaBoundsInParent( - root_window->GetChildById(kShellWindowId_OverlayContainer)); - ::wm::ConvertRectToScreen(root_window, &bounds); - widget_->SetBounds(bounds); + widget_->SetBounds(GetWorkAreaBoundsNoOverlapWithShelf(root_window)); current_indicator_state_ = indicator_state; indicators_view_->OnIndicatorTypeChanged(current_indicator_state_); @@ -494,10 +508,7 @@ void SplitViewDragIndicators::OnDisplayBoundsChanged() { aura::Window* root_window = widget_->GetNativeView()->GetRootWindow(); - gfx::Rect bounds = screen_util::GetDisplayWorkAreaBoundsInParent( - root_window->GetChildById(kShellWindowId_OverlayContainer)); - ::wm::ConvertRectToScreen(root_window, &bounds); - widget_->SetBounds(bounds); + widget_->SetBounds(GetWorkAreaBoundsNoOverlapWithShelf(root_window)); } bool SplitViewDragIndicators::GetIndicatorTypeVisibilityForTesting(
diff --git a/ash/wm/splitview/split_view_drag_indicators.h b/ash/wm/splitview/split_view_drag_indicators.h index f99b881..5d2e151 100644 --- a/ash/wm/splitview/split_view_drag_indicators.h +++ b/ash/wm/splitview/split_view_drag_indicators.h
@@ -81,9 +81,6 @@ // root window than |widget_|, |widget_| will reparent. void SetIndicatorState(IndicatorState indicator_state, const gfx::Point& event_location); - IndicatorState current_indicator_state() const { - return current_indicator_state_; - } // Called by owner of this class when display bounds changes are observed, so // that this class can relayout accordingly. @@ -91,6 +88,10 @@ bool GetIndicatorTypeVisibilityForTesting(IndicatorType type) const; + IndicatorState current_indicator_state() const { + return current_indicator_state_; + } + private: FRIEND_TEST_ALL_PREFIXES(SplitViewWindowSelectorTest, SplitViewDragIndicatorsWidgetReparenting);
diff --git a/base/BUILD.gn b/base/BUILD.gn index e83847b6..2cb3483 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -938,6 +938,8 @@ "trace_event/memory_usage_estimator.h", "trace_event/process_memory_dump.cc", "trace_event/process_memory_dump.h", + "trace_event/trace_arguments.cc", + "trace_event/trace_arguments.h", "trace_event/trace_buffer.cc", "trace_event/trace_buffer.h", "trace_event/trace_category.h", @@ -2530,6 +2532,7 @@ "trace_event/memory_infra_background_whitelist_unittest.cc", "trace_event/memory_usage_estimator_unittest.cc", "trace_event/process_memory_dump_unittest.cc", + "trace_event/trace_arguments_unittest.cc", "trace_event/trace_category_unittest.cc", "trace_event/trace_config_unittest.cc", "trace_event/trace_event_filter_test_utils.cc", @@ -2811,15 +2814,11 @@ if (enable_nocompile_tests) { nocompile_test("base_nocompile_tests") { sources = [ - "bind_unittest.nc", "callback_list_unittest.nc", "callback_unittest.nc", - "containers/span_unittest.nc", "memory/ref_counted_unittest.nc", "memory/weak_ptr_unittest.nc", "metrics/field_trial_params_unittest.nc", - "metrics/histogram_unittest.nc", - "observer_list_unittest.nc", "optional_unittest.nc", "strings/string16_unittest.nc", "task/task_traits_extension_unittest.nc", @@ -2895,7 +2894,7 @@ java_library("jni_java") { supports_android = true java_files = [ - "android/java/src/org/chromium/base/annotations/JniStaticNatives.java", + "android/java/src/org/chromium/base/annotations/NativeMethods.java", "android/java/src/org/chromium/base/JniStaticTestMocker.java", ] } @@ -2992,6 +2991,7 @@ "android/java/src/org/chromium/base/metrics/RecordUserAction.java", "android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java", "android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java", + "android/java/src/org/chromium/base/process_launcher/BindService.java", "android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java", "android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java", "android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java", @@ -3074,6 +3074,7 @@ testonly = true deps = [ ":base_java", + ":jni_java", "//testing/android/reporter:reporter_java", "//third_party/android_deps:android_support_annotations_java", "//third_party/android_deps:android_support_compat_java", @@ -3125,6 +3126,7 @@ "test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferences.java", "test/android/javatests/src/org/chromium/base/test/util/InstrumentationUtils.java", "test/android/javatests/src/org/chromium/base/test/util/IntegrationTest.java", + "test/android/javatests/src/org/chromium/base/test/util/JniMocker.java", "test/android/javatests/src/org/chromium/base/test/util/Manual.java", "test/android/javatests/src/org/chromium/base/test/util/Matchers.java", "test/android/javatests/src/org/chromium/base/test/util/MetricsUtils.java", @@ -3178,6 +3180,7 @@ junit_binary("base_junit_tests") { java_files = [ + "android/junit/src/org/chromium/base/AnimationFrameTimeHistogramTest.java", "android/junit/src/org/chromium/base/ApplicationStatusTest.java", "android/junit/src/org/chromium/base/DiscardableReferencePoolTest.java", "android/junit/src/org/chromium/base/LogTest.java", @@ -3205,6 +3208,7 @@ ":base_java_process_launcher_test_support", ":base_java_test_support", ":base_junit_test_support", + ":jni_java", "//third_party/hamcrest:hamcrest_java", ] }
diff --git a/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java b/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java index 7e884ea..1228c52 100644 --- a/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java +++ b/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java
@@ -11,7 +11,7 @@ import android.animation.TimeAnimator.TimeListener; import android.util.Log; -import org.chromium.base.annotations.JniStaticNatives; +import org.chromium.base.annotations.NativeMethods; /** * Record Android animation frame rate and save it to UMA histogram. This is mainly for monitoring @@ -143,7 +143,7 @@ } } - @JniStaticNatives + @NativeMethods interface Natives { void saveHistogram(String histogramName, long[] frameTimesMs, int count); }
diff --git a/base/android/java/src/org/chromium/base/JniStaticTestMocker.java b/base/android/java/src/org/chromium/base/JniStaticTestMocker.java index b73be10..d317737 100644 --- a/base/android/java/src/org/chromium/base/JniStaticTestMocker.java +++ b/base/android/java/src/org/chromium/base/JniStaticTestMocker.java
@@ -7,7 +7,7 @@ /** * Implemented by the TEST_HOOKS field in JNI wrapper classes that are generated * by the JNI annotation processor. Used in tests for setting the mock - * implementation of a {@link org.chromium.base.annotations.JniStaticNatives} interface. - * @param <T> The interface annotated with {@link org.chromium.base.annotations.JniStaticNatives} + * implementation of a {@link org.chromium.base.annotations.NativeMethods} interface. + * @param <T> The interface annotated with {@link org.chromium.base.annotations.NativeMethods} */ public interface JniStaticTestMocker<T> { void setInstanceForTesting(T instance); }
diff --git a/base/android/java/src/org/chromium/base/annotations/JCaller.java b/base/android/java/src/org/chromium/base/annotations/JCaller.java index f9c54cd..4a8e31e 100644 --- a/base/android/java/src/org/chromium/base/annotations/JCaller.java +++ b/base/android/java/src/org/chromium/base/annotations/JCaller.java
@@ -23,7 +23,7 @@ * * static native void nativeFoo(@JCaller A a, long nativeCppClass); * - * @JniStaticNatives + * @NativeMethods * interface Natives { * void foo(@JCaller A a, long nativeCppClass); * }
diff --git a/base/android/java/src/org/chromium/base/annotations/JniStaticNatives.java b/base/android/java/src/org/chromium/base/annotations/JniStaticNatives.java deleted file mode 100644 index b387854d..0000000 --- a/base/android/java/src/org/chromium/base/annotations/JniStaticNatives.java +++ /dev/null
@@ -1,13 +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. -package org.chromium.base.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.SOURCE) -public @interface JniStaticNatives {}
diff --git a/base/android/java/src/org/chromium/base/annotations/NativeMethods.java b/base/android/java/src/org/chromium/base/annotations/NativeMethods.java new file mode 100644 index 0000000..4c98ad2 --- /dev/null +++ b/base/android/java/src/org/chromium/base/annotations/NativeMethods.java
@@ -0,0 +1,13 @@ +// 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. +package org.chromium.base.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.SOURCE) +public @interface NativeMethods {}
diff --git a/base/android/java/src/org/chromium/base/compat/ApiHelperForO.java b/base/android/java/src/org/chromium/base/compat/ApiHelperForO.java index 52ac0555..c704827 100644 --- a/base/android/java/src/org/chromium/base/compat/ApiHelperForO.java +++ b/base/android/java/src/org/chromium/base/compat/ApiHelperForO.java
@@ -9,6 +9,7 @@ import android.content.res.Configuration; import android.os.Build; import android.view.Display; +import android.view.View; import org.chromium.base.annotations.DoNotInline; @@ -36,4 +37,9 @@ public static boolean isInstantApp(PackageManager packageManager) { return packageManager.isInstantApp(); } + + /** See {@link View#setDefaultFocusHighlightEnabled(boolean) }. */ + public static void setDefaultFocusHighlightEnabled(View view, boolean enabled) { + view.setDefaultFocusHighlightEnabled(enabled); + } }
diff --git a/base/android/java/src/org/chromium/base/process_launcher/BindService.java b/base/android/java/src/org/chromium/base/process_launcher/BindService.java new file mode 100644 index 0000000..bde1f2f --- /dev/null +++ b/base/android/java/src/org/chromium/base/process_launcher/BindService.java
@@ -0,0 +1,64 @@ +// 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. + +package org.chromium.base.process_launcher; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.ContextWrapper; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Build; +import android.os.Handler; +import android.os.Process; +import android.os.UserHandle; + +import java.lang.reflect.Method; + +/** + * Class of static helper methods to call Context.bindService variants. + */ +final class BindService { + private static Method sBindServiceAsUserMethod; + + // Note that handler is not guaranteed to be used, and client still need to correctly handle + // callbacks on the UI thread. + static boolean doBindService(Context context, Intent intent, ServiceConnection connection, + int flags, Handler handler) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + return bindServiceByCall(context, intent, connection, flags); + } + + try { + return bindServiceByReflection(context, intent, connection, flags, handler); + } catch (ReflectiveOperationException e) { + return bindServiceByCall(context, intent, connection, flags); + } + } + + private static boolean bindServiceByCall( + Context context, Intent intent, ServiceConnection connection, int flags) { + return context.bindService(intent, connection, flags); + } + + @TargetApi(Build.VERSION_CODES.N) + private static boolean bindServiceByReflection(Context context, Intent intent, + ServiceConnection connection, int flags, Handler handler) + throws ReflectiveOperationException { + if (sBindServiceAsUserMethod == null) { + sBindServiceAsUserMethod = + Context.class.getDeclaredMethod("bindServiceAsUser", Intent.class, + ServiceConnection.class, int.class, Handler.class, UserHandle.class); + } + // No need for null checks or worry about infinite looping here. Otherwise a regular calls + // into the ContextWrapper would lead to problems as well. + while (context instanceof ContextWrapper) { + context = ((ContextWrapper) context).getBaseContext(); + } + return (Boolean) sBindServiceAsUserMethod.invoke( + context, intent, connection, flags, handler, Process.myUserHandle()); + } + + private BindService() {} +}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java index 0d9709b..eef08c4 100644 --- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java +++ b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java
@@ -103,14 +103,16 @@ private final Context mContext; private final Intent mBindIntent; private final int mBindFlags; + private final Handler mHandler; private final ChildServiceConnectionDelegate mDelegate; private boolean mBound; private ChildServiceConnectionImpl(Context context, Intent bindIntent, int bindFlags, - ChildServiceConnectionDelegate delegate) { + Handler handler, ChildServiceConnectionDelegate delegate) { mContext = context; mBindIntent = bindIntent; mBindFlags = bindFlags; + mHandler = handler; mDelegate = delegate; } @@ -119,7 +121,8 @@ if (!mBound) { try { TraceEvent.begin("ChildProcessConnection.ChildServiceConnectionImpl.bind"); - mBound = mContext.bindService(mBindIntent, this, mBindFlags); + mBound = BindService.doBindService( + mContext, mBindIntent, this, mBindFlags, mHandler); } finally { TraceEvent.end("ChildProcessConnection.ChildServiceConnectionImpl.bind"); } @@ -281,30 +284,31 @@ @Override public ChildServiceConnection createConnection( Intent bindIntent, int bindFlags, ChildServiceConnectionDelegate delegate) { - return new ChildServiceConnectionImpl(context, bindIntent, bindFlags, delegate); + return new ChildServiceConnectionImpl( + context, bindIntent, bindFlags, mLauncherHandler, delegate); } }; } + // Methods on the delegate are can be called on launcher thread or UI thread, so need to + // handle both cases. See BindService for details. ChildServiceConnectionDelegate delegate = new ChildServiceConnectionDelegate() { @Override public void onServiceConnected(final IBinder service) { - mLauncherHandler.post(new Runnable() { - @Override - public void run() { - onServiceConnectedOnLauncherThread(service); - } - }); + if (mLauncherHandler.getLooper() == Looper.myLooper()) { + onServiceConnectedOnLauncherThread(service); + return; + } + mLauncherHandler.post(() -> onServiceConnectedOnLauncherThread(service)); } @Override public void onServiceDisconnected() { - mLauncherHandler.post(new Runnable() { - @Override - public void run() { - onServiceDisconnectedOnLauncherThread(); - } - }); + if (mLauncherHandler.getLooper() == Looper.myLooper()) { + onServiceDisconnectedOnLauncherThread(); + return; + } + mLauncherHandler.post(() -> onServiceDisconnectedOnLauncherThread()); } };
diff --git a/base/android/jni_generator/README.md b/base/android/jni_generator/README.md index f1d7b72..3593172 100644 --- a/base/android/jni_generator/README.md +++ b/base/android/jni_generator/README.md
@@ -69,11 +69,11 @@ bindings will automatically generate the appropriate cast and call into C++ code (JNI itself is only C). -**Method 2 - Using an interface annotated with @JniStaticNatives** +**Method 2 - Using an interface annotated with @NativeMethods** - Only works for static methods. - Supports mocking in tests. -- Inner-interfaces annotated with `@JniStaticNatives` defines the native +- Inner-interfaces annotated with `@NativeMethods` defines the native interface. - A companion JNI class is generated which implements this interface with the proper bindings to forward calls to C++ functions (that you must write). @@ -94,7 +94,7 @@ 1. Enable the JNI processor by adding `annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]` to the Java target. -2. Create an inner-interface annotated with `@JniStaticNatives` that contains +2. Create an inner-interface annotated with `@NativeMethods` that contains the declaration of the corresponding static methods you wish to have implemented. 3. Call native functions using `${OriginalClassName}Jni.get().${method}` e.g. @@ -125,7 +125,7 @@ // Using AJni.get() everywhere has no overhead when running in release with R8. } - @JniStaticNatives + @NativeMethods interface Natives { void foo(); double bar(int a, int b); @@ -133,7 +133,7 @@ } ``` -- If a class contains an interface annotated with `@JniStaticNatives`, the JNI +- If a class contains an interface annotated with `@NativeMethods`, the JNI annotation processor generates a class named `${OriginalClassName}Jni` which has a function `get()` which returns an implementation of the annotated interface (and will call the corresponding static method as if it
diff --git a/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForAnnotationProcessor.java b/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForAnnotationProcessor.java index a6af020..b9e6cd6 100644 --- a/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForAnnotationProcessor.java +++ b/base/android/jni_generator/java/src/org/chromium/example/jni_generator/SampleForAnnotationProcessor.java
@@ -4,7 +4,7 @@ package org.chromium.example.jni_generator; -import org.chromium.base.annotations.JniStaticNatives; +import org.chromium.base.annotations.NativeMethods; /** * Sample class that uses the JNI annotation processor for static methods. @@ -22,7 +22,7 @@ * with the name SampleForAnnotationProcessorJni which will implement * Natives. */ - @JniStaticNatives + @NativeMethods interface Natives { void foo(); SampleForAnnotationProcessor bar(SampleForAnnotationProcessor sample);
diff --git a/base/android/jni_generator/java/src/org/chromium/jni_generator/JniProcessor.java b/base/android/jni_generator/java/src/org/chromium/jni_generator/JniProcessor.java index 587746e..01ce5b9 100644 --- a/base/android/jni_generator/java/src/org/chromium/jni_generator/JniProcessor.java +++ b/base/android/jni_generator/java/src/org/chromium/jni_generator/JniProcessor.java
@@ -21,7 +21,7 @@ import com.squareup.javapoet.TypeSpec; import org.chromium.base.JniStaticTestMocker; -import org.chromium.base.annotations.JniStaticNatives; +import org.chromium.base.annotations.NativeMethods; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -49,17 +49,17 @@ /** * Annotation processor that finds inner interfaces annotated with - * {@link JniStaticNatives} and generates a class with native bindings + * {@link NativeMethods} and generates a class with native bindings * (GEN_JNI) and a class specific wrapper class with name (classnameJni) * * NativeClass - refers to the class that contains all native declarations. * NativeWrapperClass - refers to the class that is generated for each class - * containing an interface annotated with JniStaticNatives. + * containing an interface annotated with NativeMethods. * */ @AutoService(Processor.class) public class JniProcessor extends AbstractProcessor { - private static final Class<JniStaticNatives> JNI_STATIC_NATIVES_CLASS = JniStaticNatives.class; + private static final Class<NativeMethods> JNI_STATIC_NATIVES_CLASS = NativeMethods.class; private static final String NATIVE_WRAPPER_CLASS_POSTFIX = "Jni"; @@ -164,11 +164,11 @@ List<JavaFile> writeQueue = Lists.newArrayList(); for (Element e : roundEnvironment.getElementsAnnotatedWith(JNI_STATIC_NATIVES_CLASS)) { - // @JniStaticNatives can only annotate types so this is safe. + // @NativeMethods can only annotate types so this is safe. TypeElement type = (TypeElement) e; if (!e.getKind().isInterface()) { - printError("@JniStaticNatives must annotate an interface", e); + printError("@NativeMethods must annotate an interface", e); } // Interface must be nested within a class. @@ -208,7 +208,7 @@ // Queue this file for writing. // Can't write right now because the wrapper class depends on NativeClass - // to be written and we can't write NativeClass until all @JniStaticNatives + // to be written and we can't write NativeClass until all @NativeMethods // interfaces are processed because each will add new native methods. JavaFile file = JavaFile.builder(packageName, nativeWrapperClassSpec).build(); writeQueue.add(file); @@ -274,8 +274,8 @@ /** * Creates method specs for the native methods of NativeClass given - * the method declarations from a {@link JniStaticNatives} annotated interface - * @param interfaceMethods method declarations from a {@link JniStaticNatives} annotated + * the method declarations from a {@link NativeMethods} annotated interface + * @param interfaceMethods method declarations from a {@link NativeMethods} annotated * interface * @param outerType ClassName of class that contains the annotated interface * @return map from old method name to new native method specification @@ -318,11 +318,11 @@ void printError(String s, Element e) { processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, - String.format("Error processing @JniStaticNatives interface: %s", s), e); + String.format("Error processing @NativeMethods interface: %s", s), e); } /** - * Creates a class spec for an implementation of an {@link JniStaticNatives} annotated interface + * Creates a class spec for an implementation of an {@link NativeMethods} annotated interface * that will wrap calls to the NativesClass which contains the actual native method * declarations. * @@ -336,7 +336,7 @@ * * @param name name of the wrapper class. * @param isPublic if true, a public modifier will be added to this native wrapper. - * @param nativeInterface the {@link JniStaticNatives} annotated type that this native wrapper + * @param nativeInterface the {@link NativeMethods} annotated type that this native wrapper * will implement. * @param methodMap a map from the old method name to the new method spec in NativeClass. * */ @@ -355,7 +355,7 @@ // Start by adding all the native method wrappers. for (Element enclosed : nativeInterface.getEnclosedElements()) { if (enclosed.getKind() != ElementKind.METHOD) { - printError("Cannot have a non-method in a @JniStaticNatives annotated interface", + printError("Cannot have a non-method in a @NativeMethods annotated interface", enclosed); } @@ -452,7 +452,7 @@ /** * Creates a wrapper method that overrides interfaceMethod and calls staticNativeMethod. - * @param interfaceMethod method that will be overridden in a {@link JniStaticNatives} annotated + * @param interfaceMethod method that will be overridden in a {@link NativeMethods} annotated * interface. * @param staticNativeMethod method that will be called in NativeClass. */
diff --git a/base/android/jni_generator/jni_generator.py b/base/android/jni_generator/jni_generator.py index f8a5e2e5..d9c0254 100755 --- a/base/android/jni_generator/jni_generator.py +++ b/base/android/jni_generator/jni_generator.py
@@ -57,7 +57,7 @@ flags=re.DOTALL) _NATIVE_PROXY_EXTRACTION_REGEX = re.compile( - r'@JniStaticNatives\s*interface\s*' + r'@NativeMethods\s*(public|private)*\s*interface\s*' r'(?P<interface_name>\w*)\s*(?P<interface_body>{(\s*.*)+?\s*})') # Use 100 columns rather than 80 because it makes many lines more readable. @@ -837,7 +837,7 @@ return jni_from_javap -# 'Proxy' native methods are declared in an @JniStaticNatives interface without +# 'Proxy' native methods are declared in an @NativeMethods interface without # a native qualifier and indicate that the JNI annotation processor should # generate code to link between the equivalent native method as if it were # declared statically.
diff --git a/base/android/jni_generator/jni_generator_tests.py b/base/android/jni_generator/jni_generator_tests.py index b50bc0e5..bc99a7a 100755 --- a/base/android/jni_generator/jni_generator_tests.py +++ b/base/android/jni_generator/jni_generator_tests.py
@@ -1244,7 +1244,7 @@ class Foo { - @JniStaticNatives + @NativeMethods interface Natives { void foo(); String bar(String s, int y, char x, short z); @@ -1267,7 +1267,7 @@ def testEscapingProxyNatives(self): test_data = """ class SampleProxyJni { - @JniStaticNatives + @NativeMethods interface Natives { void foo_bar(); void foo__bar(); @@ -1306,7 +1306,7 @@ test_data = """ @MainDex class Foo() { - @JniStaticNatives + @NativeMethods interface Natives { void thisismaindex(); } @@ -1318,7 +1318,7 @@ non_main_dex_test_data = """ class Bar() { - @JniStaticNatives + @NativeMethods interface Natives { void foo(); void bar(); @@ -1382,7 +1382,7 @@ test_data = """ class SampleProxyJni { private void do_not_match(); - @JniStaticNatives + @NativeMethods interface Natives { void foo(); int bar(int x, int y); @@ -1396,7 +1396,7 @@ bad_spaced_test_data = """ class SampleProxyJni{ - @JniStaticNatives interface + @NativeMethods interface Natives
diff --git a/base/android/junit/src/org/chromium/base/AnimationFrameTimeHistogramTest.java b/base/android/junit/src/org/chromium/base/AnimationFrameTimeHistogramTest.java new file mode 100644 index 0000000..4e62f79 --- /dev/null +++ b/base/android/junit/src/org/chromium/base/AnimationFrameTimeHistogramTest.java
@@ -0,0 +1,51 @@ +// 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. + +package org.chromium.base; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.annotation.Config; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.JniMocker; + +/** + * Tests for {@link AnimationFrameTimeHistogram} + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class AnimationFrameTimeHistogramTest { + @Rule + public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Rule + public JniMocker mocker = new JniMocker(); + + @Mock + AnimationFrameTimeHistogram.Natives mNativeMock; + + @Before + public void setUp() { + mocker.mock(AnimationFrameTimeHistogramJni.TEST_HOOKS, mNativeMock); + } + + @Test + public void testNatives() { + AnimationFrameTimeHistogram hist = new AnimationFrameTimeHistogram("histName"); + hist.startRecording(); + hist.endRecording(); + verify(mNativeMock).saveHistogram(eq("histName"), any(long[].class), anyInt()); + } +}
diff --git a/base/bind_unittest.nc b/base/bind_unittest.nc deleted file mode 100644 index d549d2e..0000000 --- a/base/bind_unittest.nc +++ /dev/null
@@ -1,322 +0,0 @@ -// Copyright (c) 2011 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. - -// This is a "No Compile Test" suite. -// http://dev.chromium.org/developers/testing/no-compile-tests - -#include <utility> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/test/bind_test_util.h" - -namespace base { - -// Do not put everything inside an anonymous namespace. If you do, many of the -// helper function declarations will generate unused definition warnings. - -static const int kParentValue = 1; -static const int kChildValue = 2; - -class NoRef { - public: - void VoidMethod0() {} - void VoidConstMethod0() const {} - int IntMethod0() { return 1; } -}; - -class HasRef : public NoRef, public base::RefCounted<HasRef> { -}; - -class Parent { - public: - void AddRef() const {} - void Release() const {} - virtual void VirtualSet() { value = kParentValue; } - void NonVirtualSet() { value = kParentValue; } - int value; -}; - -class Child : public Parent { - public: - virtual void VirtualSet() { value = kChildValue; } - void NonVirtualSet() { value = kChildValue; } -}; - -class NoRefParent { - public: - virtual void VirtualSet() { value = kParentValue; } - void NonVirtualSet() { value = kParentValue; } - int value; -}; - -class NoRefChild : public NoRefParent { - virtual void VirtualSet() { value = kChildValue; } - void NonVirtualSet() { value = kChildValue; } -}; - -template <typename T> -T PolymorphicIdentity(T t) { - return t; -} - -int UnwrapParentRef(Parent& p) { - return p.value; -} - -template <typename T> -void VoidPolymorphic1(T t) { -} - -void TakesMoveOnly(std::unique_ptr<int>) { -} - -struct NonEmptyFunctor { - int x; - void operator()() const {} -}; - -// TODO(hans): Remove .* and update the static_assert expectations once we roll -// past Clang r313315. https://crbug.com/765692. - -#if defined(NCTEST_METHOD_ON_CONST_OBJECT) // [r"fatal error: static_assert failed .*\"Bound argument \|i\| of type \|Arg\| cannot be forwarded as \|Unwrapped\| to the bound functor, which declares it as \|Param\|\.\""] - -// Method bound to const-object. -// -// Only const methods should be allowed to work with const objects. -void WontCompile() { - HasRef has_ref; - const HasRef* const_has_ref_ptr_ = &has_ref; - Callback<void()> method_to_const_cb = - Bind(&HasRef::VoidMethod0, const_has_ref_ptr_); - method_to_const_cb.Run(); -} - -#elif defined(NCTEST_METHOD_BIND_NEEDS_REFCOUNTED_OBJECT) // [r"fatal error: static_assert failed \"Receivers may not be raw pointers\."] - - -// Method bound to non-refcounted object. -// -// We require refcounts unless you have Unretained(). -void WontCompile() { - NoRef no_ref; - Callback<void()> no_ref_cb = - Bind(&NoRef::VoidMethod0, &no_ref); - no_ref_cb.Run(); -} - -#elif defined(NCTEST_CONST_METHOD_NEEDS_REFCOUNTED_OBJECT) // [r"fatal error: static_assert failed \"Receivers may not be raw pointers\."] - -// Const Method bound to non-refcounted object. -// -// We require refcounts unless you have Unretained(). -void WontCompile() { - NoRef no_ref; - Callback<void()> no_ref_const_cb = - Bind(&NoRef::VoidConstMethod0, &no_ref); - no_ref_const_cb.Run(); -} - -#elif defined(NCTEST_CONST_POINTER) // [r"fatal error: static_assert failed .*\"Bound argument \|i\| of type \|Arg\| cannot be forwarded as \|Unwrapped\| to the bound functor, which declares it as \|Param\|\.\""] - -// Const argument used with non-const pointer parameter of same type. -// -// This is just a const-correctness check. -void WontCompile() { - const NoRef* const_no_ref_ptr; - Callback<NoRef*()> pointer_same_cb = - Bind(&PolymorphicIdentity<NoRef*>, const_no_ref_ptr); - pointer_same_cb.Run(); -} - -#elif defined(NCTEST_CONST_POINTER_SUBTYPE) // [r"fatal error: static_assert failed .*\"Bound argument \|i\| of type \|Arg\| cannot be forwarded as \|Unwrapped\| to the bound functor, which declares it as \|Param\|\.\""] - -// Const argument used with non-const pointer parameter of super type. -// -// This is just a const-correctness check. -void WontCompile() { - const NoRefChild* const_child_ptr; - Callback<NoRefParent*()> pointer_super_cb = - Bind(&PolymorphicIdentity<NoRefParent*>, const_child_ptr); - pointer_super_cb.Run(); -} - -#elif defined(DISABLED_NCTEST_DISALLOW_NON_CONST_REF_PARAM) // [r"fatal error: no member named 'AddRef' in 'base::NoRef'"] -// TODO(dcheng): I think there's a type safety promotion issue here where we can -// pass a const ref to a non const-ref function, or vice versa accidentally. Or -// we make a copy accidentally. Check. - -// Functions with reference parameters, unsupported. -// -// First, non-const reference parameters are disallowed by the Google -// style guide. Second, since we are doing argument forwarding it becomes -// very tricky to avoid copies, maintain const correctness, and not -// accidentally have the function be modifying a temporary, or a copy. -void WontCompile() { - Parent p; - Callback<int(Parent&)> ref_arg_cb = Bind(&UnwrapParentRef); - ref_arg_cb.Run(p); -} - -#elif defined(NCTEST_DISALLOW_BIND_TO_NON_CONST_REF_PARAM) // [r"fatal error: static_assert failed .*\"Bound argument \|i\| of type \|Arg\| cannot be forwarded as \|Unwrapped\| to the bound functor, which declares it as \|Param\|\.\""] - -// Binding functions with reference parameters, unsupported. -// -// See comment in NCTEST_DISALLOW_NON_CONST_REF_PARAM -void WontCompile() { - Parent p; - Callback<int()> ref_cb = Bind(&UnwrapParentRef, p); - ref_cb.Run(); -} - -#elif defined(NCTEST_NO_IMPLICIT_ARRAY_PTR_CONVERSION) // [r"fatal error: static_assert failed .*\"First bound argument to a method cannot be an array\.\""] - -// A method should not be bindable with an array of objects. -// -// This is likely not wanted behavior. We specifically check for it though -// because it is possible, depending on how you implement prebinding, to -// implicitly convert an array type to a pointer type. -void WontCompile() { - HasRef p[10]; - Callback<void()> method_bound_to_array_cb = - Bind(&HasRef::VoidMethod0, p); - method_bound_to_array_cb.Run(); -} - -#elif defined(NCTEST_NO_RVALUE_RAW_PTR_FOR_REFCOUNTED_TYPES) // [r"fatal error: static_assert failed .*\"A parameter is a refcounted type and needs scoped_refptr\.\""] - -// Refcounted types should not be bound as a raw pointer. -void WontCompile() { - HasRef for_raw_ptr; - int a; - Callback<void()> ref_count_as_raw_ptr_a = - Bind(&VoidPolymorphic1<int*>, &a); - Callback<void()> ref_count_as_raw_ptr = - Bind(&VoidPolymorphic1<HasRef*>, &for_raw_ptr); -} - -#elif defined(NCTEST_NO_LVALUE_RAW_PTR_FOR_REFCOUNTED_TYPES) // [r"fatal error: static_assert failed .*\"A parameter is a refcounted type and needs scoped_refptr\.\""] - -// Refcounted types should not be bound as a raw pointer. -void WontCompile() { - HasRef* for_raw_ptr = nullptr; - Callback<void()> ref_count_as_raw_ptr = - Bind(&VoidPolymorphic1<HasRef*>, for_raw_ptr); -} - -#elif defined(NCTEST_NO_RVALUE_CONST_RAW_PTR_FOR_REFCOUNTED_TYPES) // [r"fatal error: static_assert failed .*\"A parameter is a refcounted type and needs scoped_refptr\.\""] - -// Refcounted types should not be bound as a raw pointer. -void WontCompile() { - const HasRef for_raw_ptr; - Callback<void()> ref_count_as_raw_ptr = - Bind(&VoidPolymorphic1<const HasRef*>, &for_raw_ptr); -} - -#elif defined(NCTEST_NO_LVALUE_CONST_RAW_PTR_FOR_REFCOUNTED_TYPES) // [r"fatal error: static_assert failed .*\"A parameter is a refcounted type and needs scoped_refptr\.\""] - -// Refcounted types should not be bound as a raw pointer. -void WontCompile() { - const HasRef* for_raw_ptr = nullptr; - Callback<void()> ref_count_as_raw_ptr = - Bind(&VoidPolymorphic1<const HasRef*>, for_raw_ptr); -} - -#elif defined(NCTEST_WEAKPTR_BIND_MUST_RETURN_VOID) // [r"fatal error: static_assert failed .*\"weak_ptrs can only bind to methods without return values\""] - -// WeakPtrs cannot be bound to methods with return types. -void WontCompile() { - NoRef no_ref; - WeakPtrFactory<NoRef> weak_factory(&no_ref); - Callback<int()> weak_ptr_with_non_void_return_type = - Bind(&NoRef::IntMethod0, weak_factory.GetWeakPtr()); - weak_ptr_with_non_void_return_type.Run(); -} - -#elif defined(NCTEST_DISALLOW_ASSIGN_DIFFERENT_TYPES) // [r"fatal error: no viable conversion from 'Callback<MakeUnboundRunType<void \(\*\)\(int\)>>' to 'Callback<void \(\)>'"] - -// Bind result cannot be assigned to Callbacks with a mismatching type. -void WontCompile() { - Closure callback_mismatches_bind_type = Bind(&VoidPolymorphic1<int>); -} - -#elif defined(NCTEST_DISALLOW_CAPTURING_LAMBDA) // [r"fatal error: implicit instantiation of undefined template 'base::internal::FunctorTraits<\(lambda at (\.\./)+base/bind_unittest.nc:[0-9]+:[0-9]+\), void>'"] - -void WontCompile() { - int i = 0, j = 0; - Bind([i,&j]() {j = i;}); -} - -#elif defined(NCTEST_DISALLOW_ONCECALLBACK_RUN_ON_LVALUE) // [r"static_assert failed .*\"OnceCallback::Run\(\) may only be invoked on a non-const rvalue, i\.e\. std::move\(callback\)\.Run\(\)\.\""] - -void WontCompile() { - OnceClosure cb = Bind([] {}); - cb.Run(); -} - -#elif defined(NCTEST_DISALLOW_ONCECALLBACK_RUN_ON_CONST_LVALUE) // [r"static_assert failed .*\"OnceCallback::Run\(\) may only be invoked on a non-const rvalue, i\.e\. std::move\(callback\)\.Run\(\)\.\""] - -void WontCompile() { - const OnceClosure cb = Bind([] {}); - cb.Run(); -} - -#elif defined(NCTEST_DISALLOW_ONCECALLBACK_RUN_ON_CONST_RVALUE) // [r"static_assert failed .*\"OnceCallback::Run\(\) may only be invoked on a non-const rvalue, i\.e\. std::move\(callback\)\.Run\(\)\.\""] - -void WontCompile() { - const OnceClosure cb = Bind([] {}); - std::move(cb).Run(); -} - -#elif defined(NCTEST_DISALLOW_BIND_ONCECALLBACK) // [r"fatal error: static_assert failed .*\"BindRepeating cannot bind OnceCallback. Use BindOnce with std::move\(\)\.\""] - -void WontCompile() { - Bind(BindOnce([](int) {}), 42); -} - -#elif defined(NCTEST_DISALLOW_BINDONCE_LVALUE_ONCECALLBACK) // [r"fatal error: static_assert failed .*\"BindOnce requires non-const rvalue for OnceCallback binding\."] -void WontCompile() { - auto cb = BindOnce([](int) {}); - BindOnce(cb, 42); -} - -#elif defined(NCTEST_DISALLOW_BINDONCE_RVALUE_CONST_ONCECALLBACK) // [r"fatal error: static_assert failed .*\"BindOnce requires non-const rvalue for OnceCallback binding\."] - -void WontCompile() { - const auto cb = BindOnce([](int) {}); - BindOnce(std::move(cb), 42); -} - -#elif defined(NCTEST_BINDONCE_MOVEONLY_TYPE_BY_VALUE) // [r"fatal error: static_assert failed .*\"Bound argument \|i\| is move-only but will be bound by copy\. Ensure \|Arg\| is mutable and bound using std::move\(\)\.\""] - -void WontCompile() { - std::unique_ptr<int> x; - BindOnce(&TakesMoveOnly, x); -} - -#elif defined(NCTEST_BIND_MOVEONLY_TYPE_BY_VALUE) // [r"Bound argument \|i\| is move-only but will be forwarded by copy\. Ensure \|Arg\| is bound using base::Passed\(\), not std::move\(\)."] - -void WontCompile() { - std::unique_ptr<int> x; - Bind(&TakesMoveOnly, x); -} - -#elif defined(NCTEST_BIND_MOVEONLY_TYPE_WITH_STDMOVE) // [r"Bound argument \|i\| is move-only but will be forwarded by copy\. Ensure \|Arg\| is bound using base::Passed\(\), not std::move\(\)."] - -void WontCompile() { - std::unique_ptr<int> x; - Bind(&TakesMoveOnly, std::move(x)); -} - -#elif defined(NCTEST_BIND_NON_EMPTY_FUNCTOR) // [r"fatal error: implicit instantiation of undefined template 'base::internal::FunctorTraits<base::NonEmptyFunctor, void>'"] - -void WontCompile() { - Bind(NonEmptyFunctor()); -} - -#endif - -} // namespace base
diff --git a/base/containers/checked_iterators.h b/base/containers/checked_iterators.h index ba1158c..275a693 100644 --- a/base/containers/checked_iterators.h +++ b/base/containers/checked_iterators.h
@@ -42,20 +42,17 @@ const CheckedRandomAccessIterator& other) = default; bool operator==(const CheckedRandomAccessIterator& other) const { - CHECK_EQ(start_, other.start_); - CHECK_EQ(end_, other.end_); + CheckComparable(other); return current_ == other.current_; } bool operator!=(const CheckedRandomAccessIterator& other) const { - CHECK_EQ(start_, other.start_); - CHECK_EQ(end_, other.end_); + CheckComparable(other); return current_ != other.current_; } bool operator<(const CheckedRandomAccessIterator& other) const { - CHECK_EQ(start_, other.start_); - CHECK_EQ(end_, other.end_); + CheckComparable(other); return current_ < other.current_; } @@ -133,6 +130,11 @@ } private: + void CheckComparable(const CheckedRandomAccessIterator& other) const { + CHECK_EQ(start_, other.start_); + CHECK_EQ(end_, other.end_); + } + const T* start_ = nullptr; T* current_ = nullptr; const T* end_ = nullptr; @@ -174,20 +176,17 @@ CheckedRandomAccessConstIterator& other) = default; bool operator==(const CheckedRandomAccessConstIterator& other) const { - CHECK_EQ(start_, other.start_); - CHECK_EQ(end_, other.end_); + CheckComparable(other); return current_ == other.current_; } bool operator!=(const CheckedRandomAccessConstIterator& other) const { - CHECK_EQ(start_, other.start_); - CHECK_EQ(end_, other.end_); + CheckComparable(other); return current_ != other.current_; } bool operator<(const CheckedRandomAccessConstIterator& other) const { - CHECK_EQ(start_, other.start_); - CHECK_EQ(end_, other.end_); + CheckComparable(other); return current_ < other.current_; } @@ -266,6 +265,11 @@ } private: + void CheckComparable(const CheckedRandomAccessConstIterator& other) const { + CHECK_EQ(start_, other.start_); + CHECK_EQ(end_, other.end_); + } + const T* start_ = nullptr; const T* current_ = nullptr; const T* end_ = nullptr;
diff --git a/base/containers/span_unittest.nc b/base/containers/span_unittest.nc deleted file mode 100644 index f78685a..0000000 --- a/base/containers/span_unittest.nc +++ /dev/null
@@ -1,183 +0,0 @@ -// Copyright 2017 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. - -// This is a "No Compile Test" suite. -// http://dev.chromium.org/developers/testing/no-compile-tests - -#include "base/containers/span.h" - -#include <array> -#include <set> -#include <vector> - -namespace base { - -class Base { -}; - -class Derived : Base { -}; - -#if defined(NCTEST_DEFAULT_SPAN_WITH_NON_ZERO_STATIC_EXTENT_DISALLOWED) // [r"fatal error: static_assert failed \"Invalid Extent\""] - -// A default constructed span must have an extent of 0 or dynamic_extent. -void WontCompile() { - span<int, 1> span; -} - -#elif defined(NCTEST_SPAN_FROM_ARRAY_WITH_NON_MATCHING_STATIC_EXTENT_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<int, 1>'"] - -// A span with static extent constructed from an array must match the size of -// the array. -void WontCompile() { - int array[] = {1, 2, 3}; - span<int, 1> span(array); -} - -#elif defined(NCTEST_SPAN_FROM_STD_ARRAY_WITH_NON_MATCHING_STATIC_EXTENT_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<int, 2>'"] - -// A span with static extent constructed from std::array must match the size of -// the array. -void WontCompile() { - std::array<int, 3> array = {1, 2, 3}; - span<int, 2> span(array); -} - -#elif defined(NCTEST_SPAN_FROM_CONST_STD_ARRAY_WITH_NON_MATCHING_STATIC_EXTENT_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<const int, 2>'"] - -// A span with static extent constructed from std::array must match the size of -// the array. -void WontCompile() { - const std::array<int, 3> array = {1, 2, 3}; - span<const int, 2> span(array); -} - -#elif defined(NCTEST_SPAN_FROM_OTHER_SPAN_WITH_MISMATCHING_EXTENT_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<int, 4>'"] - -// A span with static extent constructed from another span must match the -// extent. -void WontCompile() { - std::array<int, 3> array = {1, 2, 3}; - span<int, 3> span3(array); - span<int, 4> span4(span3); -} - -#elif defined(NCTEST_DYNAMIC_SPAN_TO_STATIC_SPAN_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<int, 3>'"] - -// Converting a dynamic span to a static span should not be allowed. -void WontCompile() { - span<int> dynamic_span; - span<int, 3> static_span(dynamic_span); -} - -#elif defined(NCTEST_DERIVED_TO_BASE_CONVERSION_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<base::Base \*>'"] - -// Internally, this is represented as a pointer to pointers to Derived. An -// implicit conversion to a pointer to pointers to Base must not be allowed. -// If it were allowed, then something like this would be possible. -// Cat** cats = GetCats(); -// Animals** animals = cats; -// animals[0] = new Dog(); // Uhoh! -void WontCompile() { - span<Derived*> derived_span; - span<Base*> base_span(derived_span); -} - -#elif defined(NCTEST_PTR_TO_CONSTPTR_CONVERSION_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<const int \*>'"] - -// Similarly, converting a span<int*> to span<const int*> requires internally -// converting T** to const T**. This is also disallowed, as it would allow code -// to violate the contract of const. -void WontCompile() { - span<int*> non_const_span; - span<const int*> const_span(non_const_span); -} - -#elif defined(NCTEST_CONST_CONTAINER_TO_MUTABLE_CONVERSION_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<int>'"] - -// A const container should not be convertible to a mutable span. -void WontCompile() { - const std::vector<int> v = {1, 2, 3}; - span<int> span(v); -} - -#elif defined(NCTEST_IMPLICIT_CONVERSION_FROM_DYNAMIC_CONST_CONTAINER_TO_STATIC_SPAN_DISALLOWED) // [r"fatal error: no viable conversion from 'const std::vector<int>' to 'span<const int, 3>'"] - -// A dynamic const container should not be implicitly convertible to a static span. -void WontCompile() { - const std::vector<int> v = {1, 2, 3}; - span<const int, 3> span = v; -} - -#elif defined(NCTEST_IMPLICIT_CONVERSION_FROM_DYNAMIC_MUTABLE_CONTAINER_TO_STATIC_SPAN_DISALLOWED) // [r"fatal error: no viable conversion from 'std::vector<int>' to 'span<int, 3>'"] - -// A dynamic mutable container should not be implicitly convertible to a static span. -void WontCompile() { - std::vector<int> v = {1, 2, 3}; - span<int, 3> span = v; -} - -#elif defined(NCTEST_STD_SET_CONVERSION_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<int>'"] - -// A std::set() should not satisfy the requirements for conversion to a span. -void WontCompile() { - std::set<int> set; - span<int> span(set); -} - -#elif defined(NCTEST_STATIC_FRONT_WITH_EXCEEDING_COUNT_DISALLOWED) // [r"fatal error: static_assert failed \"Count must not exceed Extent\""] - -// Static first called on a span with static extent must not exceed the size. -void WontCompile() { - std::array<int, 3> array = {1, 2, 3}; - span<int, 3> span(array); - auto first = span.first<4>(); -} - -#elif defined(NCTEST_STATIC_LAST_WITH_EXCEEDING_COUNT_DISALLOWED) // [r"fatal error: static_assert failed \"Count must not exceed Extent\""] - -// Static last called on a span with static extent must not exceed the size. -void WontCompile() { - std::array<int, 3> array = {1, 2, 3}; - span<int, 3> span(array); - auto last = span.last<4>(); -} - -#elif defined(NCTEST_STATIC_SUBSPAN_WITH_EXCEEDING_OFFSET_DISALLOWED) // [r"fatal error: static_assert failed \"Offset must not exceed Extent\""] - -// Static subspan called on a span with static extent must not exceed the size. -void WontCompile() { - std::array<int, 3> array = {1, 2, 3}; - span<int, 3> span(array); - auto subspan = span.subspan<4>(); -} - -#elif defined(NCTEST_STATIC_SUBSPAN_WITH_EXCEEDING_COUNT_DISALLOWED) // [r"fatal error: static_assert failed \"Count must not exceed Extent - Offset\""] - -// Static subspan called on a span with static extent must not exceed the size. -void WontCompile() { - std::array<int, 3> array = {1, 2, 3}; - span<int, 3> span(array); - auto subspan = span.subspan<0, 4>(); -} - -#elif defined(NCTEST_AS_WRITABLE_BYTES_WITH_CONST_CONTAINER_DISALLOWED) // [r"fatal error: no matching function for call to 'as_writable_bytes'"] - -// as_writable_bytes should not be possible for a const container. -void WontCompile() { - const std::vector<int> v = {1, 2, 3}; - span<uint8_t> bytes = as_writable_bytes(make_span(v)); -} - -#elif defined(NCTEST_MAKE_SPAN_FROM_SET_CONVERSION_DISALLOWED) // [r"fatal error: no matching function for call to 'make_span'"] - -// A std::set() should not satisfy the requirements for conversion to a span. -void WontCompile() { - std::set<int> set; - auto span = make_span(set); -} - -#endif - -} // namespace base
diff --git a/base/i18n/break_iterator_unittest.cc b/base/i18n/break_iterator_unittest.cc index ed5de44..6e8632e 100644 --- a/base/i18n/break_iterator_unittest.cc +++ b/base/i18n/break_iterator_unittest.cc
@@ -448,8 +448,8 @@ }; std::vector<string16> characters; string16 text; - for (size_t i = 0; i < arraysize(kCharacters); ++i) { - characters.push_back(WideToUTF16(kCharacters[i])); + for (auto*& i : kCharacters) { + characters.push_back(WideToUTF16(i)); text.append(characters.back()); } BreakIterator iter(text, BreakIterator::BREAK_CHARACTER);
diff --git a/base/i18n/build_utf8_validator_tables.cc b/base/i18n/build_utf8_validator_tables.cc index b349c5f..ab897d4 100644 --- a/base/i18n/build_utf8_validator_tables.cc +++ b/base/i18n/build_utf8_validator_tables.cc
@@ -263,9 +263,9 @@ // algorithm is working. Use the command-line option // --vmodule=build_utf8_validator_tables=1 to see this output. void LogStringSets(const PairVector& pairs) { - for (auto pair_it = pairs.begin(); pair_it != pairs.end(); ++pair_it) { + for (const auto& pair_it : pairs) { std::string set_as_string; - for (auto set_it = pair_it->set.begin(); set_it != pair_it->set.end(); + for (auto set_it = pair_it.set.begin(); set_it != pair_it.set.end(); ++set_it) { set_as_string += base::StringPrintf("[\\x%02x-\\x%02x]", static_cast<int>(set_it->from()), @@ -373,13 +373,13 @@ std::vector<uint8_t> shifts; uint8_t pos = 0; - for (auto state_it = states.begin(); state_it != states.end(); ++state_it) { + for (const auto& state_it : states) { // We want to set |shift| to the (0-based) index of the least-significant // set bit in any of the ranges for this state, since this tells us how many // bits we can discard and still determine what range a byte lies in. Sadly // it appears that ffs() is not portable, so we do it clumsily. uint8_t shift = 7; - for (auto range_it = state_it->begin(); range_it != state_it->end(); + for (auto range_it = state_it.begin(); range_it != state_it.end(); ++range_it) { while (shift > 0 && range_it->from % (1 << shift) != 0) { --shift;
diff --git a/base/i18n/file_util_icu_unittest.cc b/base/i18n/file_util_icu_unittest.cc index 062d29b..f2ec0b0 100644 --- a/base/i18n/file_util_icu_unittest.cc +++ b/base/i18n/file_util_icu_unittest.cc
@@ -38,10 +38,10 @@ }; TEST_F(FileUtilICUTest, ReplaceIllegalCharactersInPathLinuxTest) { - for (size_t i = 0; i < arraysize(kLinuxIllegalCharacterCases); ++i) { - std::string bad_name(kLinuxIllegalCharacterCases[i].bad_name); + for (auto i : kLinuxIllegalCharacterCases) { + std::string bad_name(i.bad_name); ReplaceIllegalCharactersInPath(&bad_name, '-'); - EXPECT_EQ(kLinuxIllegalCharacterCases[i].good_name, bad_name); + EXPECT_EQ(i.good_name, bad_name); } } @@ -85,15 +85,15 @@ #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_POSIX) TEST_F(FileUtilICUTest, ReplaceIllegalCharactersInPathTest) { - for (size_t i = 0; i < arraysize(kIllegalCharacterCases); ++i) { + for (auto i : kIllegalCharacterCases) { #if defined(OS_WIN) - std::wstring bad_name(kIllegalCharacterCases[i].bad_name); + std::wstring bad_name(i.bad_name); ReplaceIllegalCharactersInPath(&bad_name, '-'); - EXPECT_EQ(kIllegalCharacterCases[i].good_name, bad_name); + EXPECT_EQ(i.good_name, bad_name); #else - std::string bad_name(WideToUTF8(kIllegalCharacterCases[i].bad_name)); + std::string bad_name(WideToUTF8(i.bad_name)); ReplaceIllegalCharactersInPath(&bad_name, '-'); - EXPECT_EQ(WideToUTF8(kIllegalCharacterCases[i].good_name), bad_name); + EXPECT_EQ(WideToUTF8(i.good_name), bad_name); #endif } }
diff --git a/base/i18n/number_formatting_unittest.cc b/base/i18n/number_formatting_unittest.cc index d2eb5687..11fdecc 100644 --- a/base/i18n/number_formatting_unittest.cc +++ b/base/i18n/number_formatting_unittest.cc
@@ -36,15 +36,13 @@ test::ScopedRestoreICUDefaultLocale restore_locale; - for (size_t i = 0; i < arraysize(cases); ++i) { + for (const auto& i : cases) { i18n::SetICUDefaultLocale("en"); testing::ResetFormatters(); - EXPECT_EQ(cases[i].expected_english, - UTF16ToUTF8(FormatNumber(cases[i].number))); + EXPECT_EQ(i.expected_english, UTF16ToUTF8(FormatNumber(i.number))); i18n::SetICUDefaultLocale("de"); testing::ResetFormatters(); - EXPECT_EQ(cases[i].expected_german, - UTF16ToUTF8(FormatNumber(cases[i].number))); + EXPECT_EQ(i.expected_german, UTF16ToUTF8(FormatNumber(i.number))); } } @@ -82,15 +80,15 @@ }; test::ScopedRestoreICUDefaultLocale restore_locale; - for (size_t i = 0; i < arraysize(cases); ++i) { + for (const auto& i : cases) { i18n::SetICUDefaultLocale("en"); testing::ResetFormatters(); - EXPECT_EQ(cases[i].expected_english, - UTF16ToUTF8(FormatDouble(cases[i].number, cases[i].frac_digits))); + EXPECT_EQ(i.expected_english, + UTF16ToUTF8(FormatDouble(i.number, i.frac_digits))); i18n::SetICUDefaultLocale("de"); testing::ResetFormatters(); - EXPECT_EQ(cases[i].expected_german, - UTF16ToUTF8(FormatDouble(cases[i].number, cases[i].frac_digits))); + EXPECT_EQ(i.expected_german, + UTF16ToUTF8(FormatDouble(i.number, i.frac_digits))); } } @@ -119,22 +117,17 @@ }; test::ScopedRestoreICUDefaultLocale restore_locale; - for (size_t i = 0; i < arraysize(cases); ++i) { + for (const auto& i : cases) { i18n::SetICUDefaultLocale("en"); - EXPECT_EQ(ASCIIToUTF16(cases[i].expected_english), - FormatPercent(cases[i].number)); + EXPECT_EQ(ASCIIToUTF16(i.expected_english), FormatPercent(i.number)); i18n::SetICUDefaultLocale("de"); - EXPECT_EQ(UTF8ToUTF16(cases[i].expected_german), - FormatPercent(cases[i].number)); + EXPECT_EQ(UTF8ToUTF16(i.expected_german), FormatPercent(i.number)); i18n::SetICUDefaultLocale("fa"); - EXPECT_EQ(UTF8ToUTF16(cases[i].expected_persian), - FormatPercent(cases[i].number)); + EXPECT_EQ(UTF8ToUTF16(i.expected_persian), FormatPercent(i.number)); i18n::SetICUDefaultLocale("ar"); - EXPECT_EQ(UTF8ToUTF16(cases[i].expected_arabic), - FormatPercent(cases[i].number)); + EXPECT_EQ(UTF8ToUTF16(i.expected_arabic), FormatPercent(i.number)); i18n::SetICUDefaultLocale("ar-EG"); - EXPECT_EQ(UTF8ToUTF16(cases[i].expected_arabic_egypt), - FormatPercent(cases[i].number)); + EXPECT_EQ(UTF8ToUTF16(i.expected_arabic_egypt), FormatPercent(i.number)); } }
diff --git a/base/i18n/rtl_unittest.cc b/base/i18n/rtl_unittest.cc index fbdd1a10..84426b59 100644 --- a/base/i18n/rtl_unittest.cc +++ b/base/i18n/rtl_unittest.cc
@@ -91,9 +91,9 @@ LEFT_TO_RIGHT }, }; - for (size_t i = 0; i < arraysize(cases); ++i) - EXPECT_EQ(cases[i].direction, - GetFirstStrongCharacterDirection(WideToUTF16(cases[i].text))); + for (auto& i : cases) + EXPECT_EQ(i.direction, + GetFirstStrongCharacterDirection(WideToUTF16(i.text))); } @@ -153,9 +153,9 @@ LEFT_TO_RIGHT }, }; - for (size_t i = 0; i < arraysize(cases); ++i) - EXPECT_EQ(cases[i].direction, - GetLastStrongCharacterDirection(WideToUTF16(cases[i].text))); + for (auto& i : cases) + EXPECT_EQ(i.direction, + GetLastStrongCharacterDirection(WideToUTF16(i.text))); } TEST_F(RTLTest, GetStringDirection) { @@ -231,9 +231,8 @@ LEFT_TO_RIGHT }, }; - for (size_t i = 0; i < arraysize(cases); ++i) - EXPECT_EQ(cases[i].direction, - GetStringDirection(WideToUTF16(cases[i].text))); + for (auto& i : cases) + EXPECT_EQ(i.direction, GetStringDirection(WideToUTF16(i.text))); } TEST_F(RTLTest, WrapPathWithLTRFormatting) { @@ -266,18 +265,17 @@ L"" }; - for (size_t i = 0; i < arraysize(cases); ++i) { + for (auto*& i : cases) { FilePath path; #if defined(OS_WIN) - std::wstring win_path(cases[i]); + std::wstring win_path(i); std::replace(win_path.begin(), win_path.end(), '/', '\\'); path = FilePath(win_path); std::wstring wrapped_expected = std::wstring(L"\x202a") + win_path + L"\x202c"; #else - path = FilePath(base::SysWideToNativeMB(cases[i])); - std::wstring wrapped_expected = - std::wstring(L"\x202a") + cases[i] + L"\x202c"; + path = FilePath(base::SysWideToNativeMB(i)); + std::wstring wrapped_expected = std::wstring(L"\x202a") + i + L"\x202c"; #endif string16 localized_file_path_string; WrapPathWithLTRFormatting(path, &localized_file_path_string); @@ -311,8 +309,8 @@ WrapStringWithRTLFormatting(&empty); EXPECT_TRUE(empty.empty()); - for (size_t i = 0; i < arraysize(cases); ++i) { - string16 input = WideToUTF16(cases[i]); + for (auto*& i : cases) { + string16 input = WideToUTF16(i); string16 ltr_wrap = input; WrapStringWithLTRFormatting(<r_wrap); EXPECT_EQ(ltr_wrap[0], kLeftToRightEmbeddingMark); @@ -352,11 +350,11 @@ for (size_t i = 0; i < 2; ++i) { // Toggle the application default text direction (to try each direction). SetRTLForTesting(!IsRTL()); - for (size_t i = 0; i < arraysize(cases); ++i) { - string16 input = WideToUTF16(cases[i].path); + for (auto& i : cases) { + string16 input = WideToUTF16(i.path); string16 output = GetDisplayStringInLTRDirectionality(input); // Test the expected wrapping behavior for the current UI directionality. - if (IsRTL() ? cases[i].wrap_rtl : cases[i].wrap_ltr) + if (IsRTL() ? i.wrap_rtl : i.wrap_ltr) EXPECT_NE(output, input); else EXPECT_EQ(output, input); @@ -440,8 +438,8 @@ // Toggle the application default text direction (to try each direction). SetRTLForTesting(!IsRTL()); - for (size_t i = 0; i < arraysize(cases); ++i) { - string16 test_case = WideToUTF16(cases[i]); + for (auto*& i : cases) { + string16 test_case = WideToUTF16(i); string16 adjusted_string = test_case; if (!AdjustStringForLocaleDirection(&adjusted_string)) @@ -490,9 +488,9 @@ for (size_t i = 0; i < 2; ++i) { // Toggle the application default text direction (to try each direction). SetRTLForTesting(!IsRTL()); - for (size_t i = 0; i < arraysize(cases); ++i) { - string16 unsanitized_text = WideToUTF16(cases[i].unformated_text); - string16 sanitized_text = WideToUTF16(cases[i].formatted_text); + for (auto& i : cases) { + string16 unsanitized_text = WideToUTF16(i.unformated_text); + string16 sanitized_text = WideToUTF16(i.formatted_text); EnsureTerminatedDirectionalFormatting(&unsanitized_text); EXPECT_EQ(sanitized_text, unsanitized_text); } @@ -523,16 +521,15 @@ }; - for (size_t i = 0; i < arraysize(cases); ++i) { + for (auto& i : cases) { // On Windows for an LTR locale, no changes to the string are made. string16 prefix, suffix = WideToUTF16(L""); #if !defined(OS_WIN) prefix = WideToUTF16(L"\x200e\x202b"); suffix = WideToUTF16(L"\x202c\x200e"); #endif // !OS_WIN - string16 unsanitized_text = WideToUTF16(cases[i].unformatted_text); - string16 sanitized_text = - prefix + WideToUTF16(cases[i].formatted_text) + suffix; + string16 unsanitized_text = WideToUTF16(i.unformatted_text); + string16 sanitized_text = prefix + WideToUTF16(i.formatted_text) + suffix; SanitizeUserSuppliedString(&unsanitized_text); EXPECT_EQ(sanitized_text, unsanitized_text); }
diff --git a/base/i18n/streaming_utf8_validator_perftest.cc b/base/i18n/streaming_utf8_validator_perftest.cc index ad328f8..b2e2a007 100644 --- a/base/i18n/streaming_utf8_validator_perftest.cc +++ b/base/i18n/streaming_utf8_validator_perftest.cc
@@ -51,8 +51,8 @@ // the results will not be meaningful with sequences containing // top-bit-set bytes. bool IsString7Bit(const std::string& s) { - for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) { - if (*it & 0x80) + for (auto it : s) { + if (it & 0x80) return false; } return true; @@ -154,8 +154,7 @@ base::Callback<std::string(size_t length)> construct_test_string, const TestFunctionDescription* test_functions, size_t test_count) { - for (size_t i = 0; i < arraysize(kTestLengths); ++i) { - const size_t length = kTestLengths[i]; + for (auto length : kTestLengths) { const std::string test_string = construct_test_string.Run(length); const int real_length = static_cast<int>(test_string.length()); const int times = (1 << 24) / real_length;
diff --git a/base/i18n/streaming_utf8_validator_unittest.cc b/base/i18n/streaming_utf8_validator_unittest.cc index d1b18a3..8193a026 100644 --- a/base/i18n/streaming_utf8_validator_unittest.cc +++ b/base/i18n/streaming_utf8_validator_unittest.cc
@@ -253,10 +253,8 @@ StreamingUtf8Validator validator; base::StringPiece sequence = *it; StreamingUtf8Validator::State state = VALID_ENDPOINT; - for (base::StringPiece::const_iterator cit = sequence.begin(); - cit != sequence.end(); - ++cit) { - state = validator.AddBytes(&*cit, 1); + for (const auto& cit : sequence) { + state = validator.AddBytes(&cit, 1); } EXPECT_EQ(expected, state) << "Failed for \"" << sequence << "\""; }
diff --git a/base/memory/scoped_refptr.h b/base/memory/scoped_refptr.h index 7d9bf72..23dec28 100644 --- a/base/memory/scoped_refptr.h +++ b/base/memory/scoped_refptr.h
@@ -24,6 +24,7 @@ class RefCounted; template <class, typename> class RefCountedThreadSafe; +class SequencedTaskRunner; template <typename T> scoped_refptr<T> AdoptRef(T* t); @@ -257,6 +258,11 @@ private: template <typename U> friend scoped_refptr<U> base::AdoptRef(U*); + friend class ::base::SequencedTaskRunner; + + // Returns the owned pointer (if any), releasing ownership to the caller. The + // caller is responsible for managing the lifetime of the reference. + T* release(); scoped_refptr(T* p, base::subtle::AdoptRefTag) : ptr_(p) {} @@ -272,6 +278,13 @@ static void Release(T* ptr); }; +template <typename T> +T* scoped_refptr<T>::release() { + T* ptr = ptr_; + ptr_ = nullptr; + return ptr; +} + // static template <typename T> void scoped_refptr<T>::AddRef(T* ptr) {
diff --git a/base/message_loop/message_loop_task_runner_unittest.cc b/base/message_loop/message_loop_task_runner_unittest.cc index 77d85f4..b490208 100644 --- a/base/message_loop/message_loop_task_runner_unittest.cc +++ b/base/message_loop/message_loop_task_runner_unittest.cc
@@ -273,6 +273,8 @@ Quit(); } + void AddRef() {} + void Quit() const { loop_.task_runner()->PostTask( FROM_HERE, RunLoop::QuitCurrentWhenIdleClosureDeprecated()); @@ -330,7 +332,7 @@ }; TEST_F(MessageLoopTaskRunnerThreadingTest, Release) { - EXPECT_TRUE(io_thread_->task_runner()->ReleaseSoon(FROM_HERE, this)); + io_thread_->task_runner()->ReleaseSoon(FROM_HERE, base::WrapRefCounted(this)); RunLoop().Run(); }
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc index a3be731..c766cc2f 100644 --- a/base/message_loop/message_loop_unittest.cc +++ b/base/message_loop/message_loop_unittest.cc
@@ -1522,6 +1522,48 @@ run_loop.Run(); } +TEST_P(MessageLoopTypedTest, IsIdleForTesting) { + auto loop = CreateMessageLoop(); + EXPECT_TRUE(loop->IsIdleForTesting()); + loop->task_runner()->PostTask(FROM_HERE, BindOnce([]() {})); + loop->task_runner()->PostDelayedTask(FROM_HERE, BindOnce([]() {}), + TimeDelta::FromMilliseconds(10)); + EXPECT_FALSE(loop->IsIdleForTesting()); + RunLoop().RunUntilIdle(); + EXPECT_TRUE(loop->IsIdleForTesting()); + + PlatformThread::Sleep(TimeDelta::FromMilliseconds(20)); + EXPECT_TRUE(loop->IsIdleForTesting()); +} + +TEST_P(MessageLoopTypedTest, IsIdleForTestingNonNestableTask) { + auto loop = CreateMessageLoop(); + RunLoop run_loop; + EXPECT_TRUE(loop->IsIdleForTesting()); + bool nested_task_run = false; + loop->task_runner()->PostTask( + FROM_HERE, BindLambdaForTesting([&]() { + RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed); + + loop->task_runner()->PostNonNestableTask( + FROM_HERE, BindLambdaForTesting([&]() { nested_task_run = true; })); + + loop->task_runner()->PostTask(FROM_HERE, BindLambdaForTesting([&]() { + EXPECT_FALSE(nested_task_run); + EXPECT_TRUE(loop->IsIdleForTesting()); + })); + + nested_run_loop.RunUntilIdle(); + EXPECT_FALSE(nested_task_run); + EXPECT_FALSE(loop->IsIdleForTesting()); + })); + + run_loop.RunUntilIdle(); + + EXPECT_TRUE(nested_task_run); + EXPECT_TRUE(loop->IsIdleForTesting()); +} + INSTANTIATE_TEST_CASE_P( , MessageLoopTypedTest,
diff --git a/base/message_loop/message_pump_mac.h b/base/message_loop/message_pump_mac.h index fa88c3a..f1194b82 100644 --- a/base/message_loop/message_pump_mac.h +++ b/base/message_loop/message_pump_mac.h
@@ -38,6 +38,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/message_loop/timer_slack.h" +#include "base/optional.h" #include "build/build_config.h" #if defined(__OBJC__) @@ -124,6 +125,10 @@ // Get the current mode mask from |enabled_modes_|. int GetModeMask() const; + // Controls whether the timer invalidation performance optimization is + // allowed. + void SetTimerInvalidationAllowed(bool allowed); + private: class ScopedModeEnabler; @@ -145,6 +150,10 @@ // from CFRunLoop.c. static void ChromeCFRunLoopTimerSetValid(CFRunLoopTimerRef timer, bool valid); + // Controls the validity of the delayed work timer. Does nothing if timer + // invalidation is disallowed. + void SetDelayedWorkTimerValid(bool valid); + // Timer callback scheduled by ScheduleDelayedWork. This does not do any // work, but it signals work_source_ so that delayed work can be performed // within the appropriate priority constraints. @@ -250,6 +259,14 @@ bool delegateless_work_; bool delegateless_idle_work_; + // Whether or not timer invalidation can be used in order to reduce the number + // of reschedulings. + bool allow_timer_invalidation_; + + // If changing timer validitity was attempted while it was disallowed, this + // value tracks the desired state of the timer. + Optional<bool> pending_timer_validity_; + DISALLOW_COPY_AND_ASSIGN(MessagePumpCFRunLoopBase); };
diff --git a/base/message_loop/message_pump_mac.mm b/base/message_loop/message_pump_mac.mm index fb25201..19df09f 100644 --- a/base/message_loop/message_pump_mac.mm +++ b/base/message_loop/message_pump_mac.mm
@@ -208,7 +208,7 @@ // // Please see the comment in RunDelayedWorkTimer() for more info on the whys // of invalidation. - ChromeCFRunLoopTimerSetValid(delayed_work_timer_, true); + SetDelayedWorkTimerValid(true); CFRunLoopTimerSetNextFireDate(delayed_work_timer_, delayed_work_fire_time_); if (timer_slack_ == TIMER_SLACK_MAXIMUM) { @@ -231,7 +231,8 @@ run_nesting_level_(0), deepest_nesting_level_(0), delegateless_work_(false), - delegateless_idle_work_(false) { + delegateless_idle_work_(false), + allow_timer_invalidation_(true) { run_loop_ = CFRunLoopGetCurrent(); CFRetain(run_loop_); @@ -383,6 +384,24 @@ #endif // !defined(OS_IOS) } +void MessagePumpCFRunLoopBase::SetDelayedWorkTimerValid(bool valid) { + if (allow_timer_invalidation_) { + ChromeCFRunLoopTimerSetValid(delayed_work_timer_, valid); + } else { + pending_timer_validity_ = valid; + } +} + +void MessagePumpCFRunLoopBase::SetTimerInvalidationAllowed(bool allowed) { + if (!allowed) + ChromeCFRunLoopTimerSetValid(delayed_work_timer_, true); + allow_timer_invalidation_ = allowed; + if (allowed && pending_timer_validity_.has_value()) { + SetDelayedWorkTimerValid(*pending_timer_validity_); + pending_timer_validity_ = nullopt; + } +} + // Called from the run loop. // static void MessagePumpCFRunLoopBase::RunDelayedWorkTimer(CFRunLoopTimerRef timer, @@ -415,7 +434,7 @@ // // ScheduleDelayedWork() flips the valid bit back just before setting the // timer's new firing time. - ChromeCFRunLoopTimerSetValid(self->delayed_work_timer_, false); + self->SetDelayedWorkTimerValid(false); // CFRunLoopTimers fire outside of the priority scheme for CFRunLoopSources. // In order to establish the proper priority in which work and delayed work @@ -765,13 +784,17 @@ DCHECK_EQ(kNSApplicationModalSafeModeMask, g_app_pump->GetModeMask()); // Pumping events in private runloop modes is known to interact badly with // app modal windows like NSAlert. - if (![NSApp modalWindow]) - g_app_pump->SetModeMask(kAllModesMask); + if ([NSApp modalWindow]) + return; + g_app_pump->SetModeMask(kAllModesMask); + // Disable timer invalidation to avoid hangs. See crbug.com/912273. + g_app_pump->SetTimerInvalidationAllowed(false); } ScopedPumpMessagesInPrivateModes::~ScopedPumpMessagesInPrivateModes() { DCHECK(g_app_pump); g_app_pump->SetModeMask(kNSApplicationModalSafeModeMask); + g_app_pump->SetTimerInvalidationAllowed(true); } int ScopedPumpMessagesInPrivateModes::GetModeMaskForTest() {
diff --git a/base/message_loop/message_pump_mac_unittest.mm b/base/message_loop/message_pump_mac_unittest.mm index 6b63aa1..d317f02 100644 --- a/base/message_loop/message_pump_mac_unittest.mm +++ b/base/message_loop/message_pump_mac_unittest.mm
@@ -207,6 +207,77 @@ EXPECT_EQ(NSAlertFirstButtonReturn, result); } +// This is a regression test for a scenario where the invalidation of the +// delayed work timer (using non-public APIs) causes a nested native run loop to +// hang. The exact root cause of the hang is unknown since it involves the +// closed-source Core Foundation runtime, but the steps needed to trigger it +// are: +// +// 1. Post a delayed task that will run some time after step #4. +// 2. Allow Chrome tasks to run in nested run loops (with +// ScopedNestableTaskAllower). +// 3. Allow running Chrome tasks during private run loop modes (with +// ScopedPumpMessagesInPrivateModes). +// 4. Open a pop-up menu via [NSMenu popupContextMenu]. This will start a +// private native run loop to process menu interaction. +// 5. In a posted task, close the menu with [NSMenu cancelTracking]. +// +// At this point the menu closes visually but the nested run loop (flakily) +// hangs forever in a live-lock, i.e., Chrome tasks keep executing but the +// NSMenu call in #4 never returns. +// +// The workaround is to avoid timer invalidation during nested native run loops. +// +// DANGER: As the pop-up menu captures keyboard input, the bug will make the +// machine's keyboard inoperable during the live-lock. Use a TTY-based remote +// terminal such as SSH (as opposed to Chromoting) to investigate the issue. +// +TEST(MessagePumpMacTest, DontInvalidateTimerInNativeRunLoop) { + MessageLoopForUI message_loop; + NSWindow* window = + [[[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100) + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:NO] autorelease]; + NSMenu* menu = [[NSMenu alloc] initWithTitle:@"Test menu"]; + [menu insertItemWithTitle:@"Dummy item" + action:@selector(dummy) + keyEquivalent:@"a" + atIndex:0]; + NSEvent* event = [NSEvent otherEventWithType:NSApplicationDefined + location:NSZeroPoint + modifierFlags:0 + timestamp:0 + windowNumber:0 + context:nil + subtype:0 + data1:0 + data2:0]; + + // Post a task to open the menu. This needs to be a separate task so that + // nested task execution can be allowed. + ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce( + [](NSWindow* window, NSMenu* menu, NSEvent* event) { + MessageLoopCurrent::ScopedNestableTaskAllower allow; + ScopedPumpMessagesInPrivateModes pump_private; + // When the bug triggers, this call never returns. + [NSMenu popUpContextMenu:menu + withEvent:event + forView:[window contentView]]; + }, + window, menu, event)); + + // Post another task to close the menu. The 100ms delay was determined + // experimentally on a 2013 Mac Pro. + ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce([](NSMenu* menu) { [menu cancelTracking]; }, menu), + base::TimeDelta::FromMilliseconds(100)); + + EXPECT_NO_FATAL_FAILURE(RunLoop().RunUntilIdle()); +} + } // namespace base @implementation TestModalAlertCloser
diff --git a/base/metrics/histogram_unittest.nc b/base/metrics/histogram_unittest.nc deleted file mode 100644 index c9c2657..0000000 --- a/base/metrics/histogram_unittest.nc +++ /dev/null
@@ -1,90 +0,0 @@ -// Copyright 2016 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. - -// This is a "No Compile Test" suite. -// http://dev.chromium.org/developers/testing/no-compile-tests - -#include "base/metrics/histogram_functions.h" -#include "base/metrics/histogram_macros.h" - -namespace base { - -#if defined(NCTEST_DIFFERENT_ENUM) // [r"\|sample\| and \|boundary\| shouldn't be of different enums"] - -void WontCompile() { - enum TypeA { A }; - enum TypeB { B }; - UMA_HISTOGRAM_ENUMERATION("", A, B); -} - -#elif defined(NCTEST_DIFFERENT_ENUM_CLASS) // [r"\|sample\| and \|boundary\| shouldn't be of different enums"] - -void WontCompile() { - enum class TypeA { A }; - enum class TypeB { B }; - UMA_HISTOGRAM_ENUMERATION("", TypeA::A, TypeB::B); -} - -#elif defined(NCTEST_DIFFERENT_ENUM_MIXED) // [r"\|sample\| and \|boundary\| shouldn't be of different enums"] - -void WontCompile() { - enum class TypeA { A }; - enum TypeB { B }; - UMA_HISTOGRAM_ENUMERATION("", TypeA::A, B); -} - -#elif defined(NCTEST_NEGATIVE_ENUM_MAX) // [r'static_assert failed "\|boundary\| is out of range of HistogramBase::Sample"'] - -void WontCompile() { - // Buckets for enumeration start from 0, so a boundary < 0 is illegal. - enum class TypeA { A = -1 }; - UMA_HISTOGRAM_ENUMERATION("", TypeA::A, TypeA::A); -} - -#elif defined(NCTEST_ENUM_MAX_OUT_OF_RANGE) // [r'static_assert failed "\|boundary\| is out of range of HistogramBase::Sample"'] - -void WontCompile() { - // HistogramBase::Sample is an int and can't hold larger values. - enum class TypeA : uint32_t { A = 0xffffffff }; - UMA_HISTOGRAM_ENUMERATION("", TypeA::A, TypeA::A); -} - -#elif defined(NCTEST_SAMPLE_NOT_ENUM) // [r'static_assert failed "Unexpected: \|boundary\| is enum, but \|sample\| is not."'] - -void WontCompile() { - enum TypeA { A }; - UMA_HISTOGRAM_ENUMERATION("", 0, TypeA::A); -} - -#elif defined(NCTEST_FUNCTION_INT) // [r"Non enum passed to UmaHistogramEnumeration"] - -void WontCompile() { - UmaHistogramEnumeration("", 1, 2); -} - -#elif defined(NCTEST_FUNCTION_DIFFERENT_ENUM) // [r"no matching function for call to 'UmaHistogramEnumeration'"] - -void WontCompile() { - enum TypeA { A }; - enum TypeB { B }; - UmaHistogramEnumeration("", A, B); -} - -#elif defined(NCTEST_FUNCTION_FIRST_NOT_ENUM) // [r"no matching function for call to 'UmaHistogramEnumeration'"] - -void WontCompile() { - enum TypeB { B }; - UmaHistogramEnumeration("", 1, B); -} - -#elif defined(NCTEST_FUNCTION_SECOND_NOT_ENUM) // [r"no matching function for call to 'UmaHistogramEnumeration'"] - -void WontCompile() { - enum TypeA { A }; - UmaHistogramEnumeration("", A, 2); -} - -#endif - -} // namespace base
diff --git a/base/observer_list_unittest.nc b/base/observer_list_unittest.nc deleted file mode 100644 index 3643cd0..0000000 --- a/base/observer_list_unittest.nc +++ /dev/null
@@ -1,38 +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. - -// This is a "No Compile Test" suite. -// http://dev.chromium.org/developers/testing/no-compile-tests - -#include <type_traits> - -#include "base/observer_list.h" - -namespace base { - -#if defined(NCTEST_CHECKED_OBSERVER_USING_UNCHECKED_LIST) // [r"fatal error: static_assert failed due to requirement '!std::is_base_of<CheckedObserver, Observer>::value' \"CheckedObserver classes must not use ObserverList<T>::Unchecked.\""] - -void WontCompile() { - struct Observer : public CheckedObserver { - void OnObserve() {} - }; - ObserverList<Observer>::Unchecked list; - for (auto& observer: list) - observer.OnObserve(); -} - -#elif defined(NCTEST_UNCHECKED_OBSERVER_USING_CHECKED_LIST) // [r"fatal error: static_assert failed due to requirement 'std::is_base_of<CheckedObserver, UncheckedObserver>::value' \"Observers should inherit from base::CheckedObserver. Use ObserverList<T>::Unchecked to observe with raw pointers.\""] - -void WontCompile() { - struct UncheckedObserver { - void OnObserve() {} - }; - ObserverList<UncheckedObserver> list; - for (auto& observer: list) - observer.OnObserve(); -} - -#endif - -} // namespace base
diff --git a/base/sequenced_task_runner.h b/base/sequenced_task_runner.h index 526912f..f03c63e0 100644 --- a/base/sequenced_task_runner.h +++ b/base/sequenced_task_runner.h
@@ -131,42 +131,25 @@ return DeleteSoon(from_here, object.release()); } - // Submits a non-nestable task to release the given object. Returns - // true if the object may be released at some point in the future, - // and false if the object definitely will not be released. + // Submits a non-nestable task to release the given object. // - // If the object was originally held by a scoped_refptr, please use the - // scoped_refptr variant of this function, as it does important housekeeping - // to ensure safe disposal of your object. + // ReleaseSoon makes sure that the object it the scoped_refptr points to gets + // properly released on the correct thread. + // We apply ReleaseSoon to the rvalue as the side-effects can be unclear to + // the caller if an lvalue is used. That being so, the scoped_refptr should + // always be std::move'd. // Example use: // // scoped_refptr<T> foo_scoped_refptr; // ... // task_runner->ReleaseSoon(std::move(foo_scoped_refptr)); template <class T> - bool ReleaseSoon(const Location& from_here, const T* object) { - return DeleteOrReleaseSoonInternal(from_here, &ReleaseHelper<T>::DoRelease, - object); - } - - // The scoped_refptr version of ReleaseSoon makes sure that the object it - // points to gets properly released on the correct thread. - // By calling AddRef on the scoped_refptr, we make sure that when it goes out - // of scope, it does not incorrectly release the object. If it were to do that - // it would be on the incorrect thread. - // We apply ReleaseSoon to the rvalue as the side-effects can be unclear to - // the caller if an lvalue is used. That being so, the scoped_refptr should - // always be std::move'd. - template <class T> - bool ReleaseSoon(const Location& from_here, scoped_refptr<T>&& object) { + void ReleaseSoon(const Location& from_here, scoped_refptr<T>&& object) { if (!object) - return true; + return; - object->AddRef(); - T* raw_ptr = object.get(); - object = nullptr; - return DeleteOrReleaseSoonInternal(from_here, &ReleaseHelper<T>::DoRelease, - raw_ptr); + DeleteOrReleaseSoonInternal(from_here, &ReleaseHelper<T>::DoRelease, + object.release()); } protected:
diff --git a/base/strings/utf_string_conversions.cc b/base/strings/utf_string_conversions.cc index 89acc38..cadb963 100644 --- a/base/strings/utf_string_conversions.cc +++ b/base/strings/utf_string_conversions.cc
@@ -4,8 +4,11 @@ #include "base/strings/utf_string_conversions.h" +#include <limits.h> #include <stdint.h> +#include <type_traits> + #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversion_utils.h" @@ -59,22 +62,28 @@ // Function overloads that write code_point to the output string. Output string // has to have enough space for the codepoint. -void UnicodeAppendUnsafe(char* out, int32_t* size, uint32_t code_point) { +// Convenience typedef that checks whether the passed in type is integral (i.e. +// bool, char, int or their extended versions) and is of the correct size. +template <typename Char, size_t N> +using EnableIfBitsAre = std::enable_if_t<std::is_integral<Char>::value && + CHAR_BIT * sizeof(Char) == N, + bool>; + +template <typename Char, EnableIfBitsAre<Char, 8> = true> +void UnicodeAppendUnsafe(Char* out, int32_t* size, uint32_t code_point) { CBU8_APPEND_UNSAFE(out, *size, code_point); } -void UnicodeAppendUnsafe(char16* out, int32_t* size, uint32_t code_point) { +template <typename Char, EnableIfBitsAre<Char, 16> = true> +void UnicodeAppendUnsafe(Char* out, int32_t* size, uint32_t code_point) { CBU16_APPEND_UNSAFE(out, *size, code_point); } -#if defined(WCHAR_T_IS_UTF32) - -void UnicodeAppendUnsafe(wchar_t* out, int32_t* size, uint32_t code_point) { +template <typename Char, EnableIfBitsAre<Char, 32> = true> +void UnicodeAppendUnsafe(Char* out, int32_t* size, uint32_t code_point) { out[(*size)++] = code_point; } -#endif // defined(WCHAR_T_IS_UTF32) - // DoUTFConversion ------------------------------------------------------------ // Main driver of UTFConversion specialized for different Src encodings. // dest has to have enough room for the converted text. @@ -232,21 +241,21 @@ // When wide == UTF-16 the conversions are a NOP. bool WideToUTF16(const wchar_t* src, size_t src_len, string16* output) { - output->assign(src, src_len); + output->assign(src, src + src_len); return true; } string16 WideToUTF16(WStringPiece wide) { - return wide.as_string(); + return string16(wide.begin(), wide.end()); } bool UTF16ToWide(const char16* src, size_t src_len, std::wstring* output) { - output->assign(src, src_len); + output->assign(src, src + src_len); return true; } std::wstring UTF16ToWide(StringPiece16 utf16) { - return utf16.as_string(); + return std::wstring(utf16.begin(), utf16.end()); } #elif defined(WCHAR_T_IS_UTF32) @@ -297,11 +306,12 @@ // Easy case since we can use the "utf" versions we already wrote above. bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output) { - return UTF16ToUTF8(src, src_len, output); + return UTF16ToUTF8(reinterpret_cast<const char16*>(src), src_len, output); } std::string WideToUTF8(WStringPiece wide) { - return UTF16ToUTF8(wide); + return UTF16ToUTF8( + StringPiece16(reinterpret_cast<const char16*>(wide.data()), wide.size())); } #elif defined(WCHAR_T_IS_UTF32)
diff --git a/base/task/sequence_manager/sequence_manager.h b/base/task/sequence_manager/sequence_manager.h index fa8861a0..066dd37f 100644 --- a/base/task/sequence_manager/sequence_manager.h +++ b/base/task/sequence_manager/sequence_manager.h
@@ -13,6 +13,7 @@ #include "base/single_thread_task_runner.h" #include "base/task/sequence_manager/task_queue_impl.h" #include "base/task/sequence_manager/task_time_observer.h" +#include "base/time/default_tick_clock.h" namespace base { namespace sequence_manager { @@ -66,6 +67,7 @@ MessageLoop::Type message_loop_type = MessageLoop::Type::TYPE_DEFAULT; bool randomised_sampling_enabled = false; + const TickClock* clock = DefaultTickClock::GetInstance(); DISALLOW_COPY_AND_ASSIGN(Settings); }; @@ -172,9 +174,12 @@ virtual scoped_refptr<TaskQueue> CreateTaskQueue( const TaskQueue::Spec& spec) = 0; - // Returns true iff this SequenceManager has no immediate work to do - // (tasks with unexpired delay are fine, tasks with zero delay and - // expired delay are not). + // Returns true iff this SequenceManager has no immediate work to do. I.e. + // there are no pending non-delayed tasks or delayed tasks that are due to + // run. This method ignores any pending delayed tasks that might have become + // eligible to run since the last task was executed. This is important because + // if it did tests would become flaky depending on the exact timing of this + // call. virtual bool IsIdleForTesting() = 0; // The total number of posted tasks that haven't executed yet.
diff --git a/base/task/sequence_manager/sequence_manager_impl.cc b/base/task/sequence_manager/sequence_manager_impl.cc index ec4dc16..3c528995 100644 --- a/base/task/sequence_manager/sequence_manager_impl.cc +++ b/base/task/sequence_manager/sequence_manager_impl.cc
@@ -56,8 +56,8 @@ std::unique_ptr<SequenceManager> CreateUnboundSequenceManager( MessageLoopBase* message_loop_base, SequenceManager::Settings settings) { - return internal::SequenceManagerImpl::CreateUnbound( - message_loop_base, DefaultTickClock::GetInstance(), std::move(settings)); + return internal::SequenceManagerImpl::CreateUnbound(message_loop_base, + std::move(settings)); } namespace internal { @@ -180,7 +180,7 @@ SequenceManager::Settings settings) { std::unique_ptr<SequenceManagerImpl> manager = CreateUnbound(MessageLoopCurrent::Get()->ToMessageLoopBaseDeprecated(), - DefaultTickClock::GetInstance(), std::move(settings)); + std::move(settings)); manager->BindToCurrentThread(); manager->CompleteInitializationOnBoundThread(); return manager; @@ -189,19 +189,17 @@ // static std::unique_ptr<SequenceManagerImpl> SequenceManagerImpl::CreateUnbound( MessageLoopBase* message_loop_base, - const TickClock* clock, SequenceManager::Settings settings) { return WrapUnique(new SequenceManagerImpl( - ThreadControllerImpl::Create(message_loop_base, clock), + ThreadControllerImpl::Create(message_loop_base, settings.clock), std::move(settings))); } // static std::unique_ptr<SequenceManagerImpl> SequenceManagerImpl::CreateUnboundWithPump( - SequenceManager::Settings settings, - const TickClock* clock) { + SequenceManager::Settings settings) { return WrapUnique(new SequenceManagerImpl( - ThreadControllerWithMessagePumpImpl::CreateUnbound(clock), + ThreadControllerWithMessagePumpImpl::CreateUnbound(settings.clock), std::move(settings))); } @@ -904,8 +902,11 @@ #endif bool SequenceManagerImpl::IsIdleForTesting() { - LazyNow lazy_now(controller_->GetClock()); - return DelayTillNextTask(&lazy_now) != TimeDelta(); + // We don't use DelayTillNextTask here because the MessageLoop version which + // we're emulating does not take Now() into account. If it did tests would + // become flaky wrt delayed tasks that are just about to run. + ReloadEmptyWorkQueues(); + return main_thread_only().selector.AllEnabledWorkQueuesAreEmpty(); } size_t SequenceManagerImpl::GetPendingTaskCountForTesting() const {
diff --git a/base/task/sequence_manager/sequence_manager_impl.h b/base/task/sequence_manager/sequence_manager_impl.h index ec322f4..25a8ebd1 100644 --- a/base/task/sequence_manager/sequence_manager_impl.h +++ b/base/task/sequence_manager/sequence_manager_impl.h
@@ -99,12 +99,10 @@ // This function should be called only once per MessageLoop. static std::unique_ptr<SequenceManagerImpl> CreateUnbound( MessageLoopBase* message_loop_base, - const TickClock* clock = DefaultTickClock::GetInstance(), SequenceManager::Settings settings = Settings()); static std::unique_ptr<SequenceManagerImpl> CreateUnboundWithPump( - SequenceManager::Settings settings, - const TickClock* clock = DefaultTickClock::GetInstance()); + SequenceManager::Settings settings); // SequenceManager implementation: void BindToCurrentThread() override;
diff --git a/base/task/sequence_manager/time_domain_unittest.cc b/base/task/sequence_manager/time_domain_unittest.cc index 34a67115..3e9dae1 100644 --- a/base/task/sequence_manager/time_domain_unittest.cc +++ b/base/task/sequence_manager/time_domain_unittest.cc
@@ -390,7 +390,7 @@ constexpr auto kDelay = TimeDelta::FromMilliseconds(20); SimpleTestTickClock clock; auto sequence_manager = internal::SequenceManagerImpl::CreateUnboundWithPump( - SequenceManager::Settings{.message_loop_type = kType}, &clock); + SequenceManager::Settings{.message_loop_type = kType, .clock = &clock}); sequence_manager->BindToMessagePump( MessageLoop::CreateMessagePumpForType(kType)); auto high_prio_queue =
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/JniMocker.java b/base/test/android/javatests/src/org/chromium/base/test/util/JniMocker.java new file mode 100644 index 0000000..f995309 --- /dev/null +++ b/base/test/android/javatests/src/org/chromium/base/test/util/JniMocker.java
@@ -0,0 +1,45 @@ +// 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. + +package org.chromium.base.test.util; + +import org.junit.rules.ExternalResource; + +import org.chromium.base.JniStaticTestMocker; +import org.chromium.base.annotations.NativeMethods; + +import java.util.ArrayList; + +/** + * A test rule to set up and tear down native implementation mocks. + */ +public class JniMocker extends ExternalResource { + private final ArrayList<JniStaticTestMocker> mHooks = new ArrayList<>(); + + /** + * Sets the native implementation of the class using a JniStaticTestMocker + * + * All TEST_HOOKS set with this function will have their test instance + * set to null after each test is run. + * + * @param T Interface type that implements {@link NativeMethods} + * @param hook Instance of the corresponding JniStaticTestMocker in the + * wrapper class generated by the JNI annotation processor + * @param testInst Mock instance of type T which will be set as the + * native implementation to be used in tests. + */ + public <T> void mock(JniStaticTestMocker<T> hook, T testInst) { + hook.setInstanceForTesting(testInst); + mHooks.add(hook); + } + + @Override + @SuppressWarnings("unchecked") + protected void after() { + for (JniStaticTestMocker hook : mHooks) { + hook.setInstanceForTesting(null); + } + mHooks.clear(); + } +}
diff --git a/base/test/scoped_task_environment.cc b/base/test/scoped_task_environment.cc index 7bd746a..b3c81c7 100644 --- a/base/test/scoped_task_environment.cc +++ b/base/test/scoped_task_environment.cc
@@ -20,6 +20,8 @@ #include "base/threading/thread_local.h" #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" +#include "base/time/tick_clock.h" #include "base/time/time.h" #if defined(OS_POSIX) || defined(OS_FUCHSIA) @@ -50,6 +52,23 @@ return nullptr; } +class TickClockBasedClock : public Clock { + public: + explicit TickClockBasedClock(const TickClock* tick_clock) + : tick_clock_(*tick_clock), + start_ticks_(tick_clock_.NowTicks()), + start_time_(Time::UnixEpoch()) {} + + Time Now() const override { + return start_time_ + (tick_clock_.NowTicks() - start_ticks_); + } + + private: + const TickClock& tick_clock_; + const TimeTicks start_ticks_; + const Time start_time_; +}; + } // namespace class ScopedTaskEnvironment::TestTaskTracker @@ -117,6 +136,10 @@ internal::ScopedSetSequenceLocalStorageMapForCurrentThread>( slsm_for_mock_time_.get()) : nullptr), + mock_clock_(mock_time_task_runner_ + ? std::make_unique<TickClockBasedClock>( + mock_time_task_runner_->GetMockTickClock()) + : nullptr), #if defined(OS_POSIX) || defined(OS_FUCHSIA) file_descriptor_watcher_(main_thread_type == MainThreadType::IO ? std::make_unique<FileDescriptorWatcher>( @@ -310,7 +333,7 @@ mock_time_task_runner_->FastForwardUntilNoTasksRemain(); } -const TickClock* ScopedTaskEnvironment::GetMockTickClock() { +const TickClock* ScopedTaskEnvironment::GetMockTickClock() const { DCHECK(mock_time_task_runner_); return mock_time_task_runner_->GetMockTickClock(); } @@ -325,6 +348,11 @@ return mock_time_task_runner_->NowTicks(); } +const Clock* ScopedTaskEnvironment::GetMockClock() const { + DCHECK(mock_clock_); + return mock_clock_.get(); +} + size_t ScopedTaskEnvironment::GetPendingMainThreadTaskCount() const { DCHECK(mock_time_task_runner_); return mock_time_task_runner_->GetPendingTaskCount();
diff --git a/base/test/scoped_task_environment.h b/base/test/scoped_task_environment.h index 77ec1bc..fe77549 100644 --- a/base/test/scoped_task_environment.h +++ b/base/test/scoped_task_environment.h
@@ -9,6 +9,7 @@ #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" #include "base/task/lazy_task_runner.h" +#include "base/time/time.h" #include "build/build_config.h" namespace base { @@ -18,6 +19,7 @@ class SequenceLocalStorageMap; } // namespace internal +class Clock; class FileDescriptorWatcher; class MessageLoop; class TaskScheduler; @@ -136,11 +138,19 @@ // Short for FastForwardBy(TimeDelta::Max()). void FastForwardUntilNoTasksRemain(); - // Only valid for instances with a MOCK_TIME MainThreadType. Returns a + // Only valid for instances with a MOCK_TIME MainThreadType. Returns a // TickClock whose time is updated by FastForward(By|UntilNoTasksRemain). - const TickClock* GetMockTickClock(); + const TickClock* GetMockTickClock() const; std::unique_ptr<TickClock> DeprecatedGetMockTickClock(); + // Only valid for instances with a MOCK_TIME MainThreadType. Returns a + // Clock whose time is updated by FastForward(By|UntilNoTasksRemain). The + // initial value is implementation defined and should be queried by tests that + // depend on it. + // TickClock should be used instead of Clock to measure elapsed time in a + // process. See time.h. + const Clock* GetMockClock() const; + // Only valid for instances with a MOCK_TIME MainThreadType. // Returns the current virtual tick time (initially starting at 0). base::TimeTicks NowTicks() const; @@ -174,6 +184,9 @@ internal::ScopedSetSequenceLocalStorageMapForCurrentThread> slsm_registration_for_mock_time_; + // Only set for instances with a MOCK_TIME MainThreadType. + const std::unique_ptr<Clock> mock_clock_; + #if defined(OS_POSIX) || defined(OS_FUCHSIA) // Enables the FileDescriptorWatcher API iff running a MainThreadType::IO. const std::unique_ptr<FileDescriptorWatcher> file_descriptor_watcher_;
diff --git a/base/test/scoped_task_environment_unittest.cc b/base/test/scoped_task_environment_unittest.cc index 56361df..2e89ade 100644 --- a/base/test/scoped_task_environment_unittest.cc +++ b/base/test/scoped_task_environment_unittest.cc
@@ -18,6 +18,8 @@ #include "base/threading/platform_thread.h" #include "base/threading/sequence_local_storage_slot.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" +#include "base/time/default_clock.h" #include "base/time/tick_clock.h" #include "base/win/com_init_util.h" #include "build/build_config.h" @@ -307,6 +309,18 @@ EXPECT_EQ(kLongTaskDelay * 2, tick_clock->NowTicks() - tick_clock_ref); } +TEST_F(ScopedTaskEnvironmentTest, FastForwardAdvanceMockClock) { + constexpr base::TimeDelta kDelay = TimeDelta::FromSeconds(42); + ScopedTaskEnvironment scoped_task_environment( + ScopedTaskEnvironment::MainThreadType::MOCK_TIME); + + const Clock* clock = scoped_task_environment.GetMockClock(); + const Time start_time = clock->Now(); + scoped_task_environment.FastForwardBy(kDelay); + + EXPECT_EQ(start_time + kDelay, clock->Now()); +} + #if defined(OS_WIN) // Regression test to ensure that ScopedTaskEnvironment enables the MTA in the // thread pool (so that the test environment matches that of the browser process
diff --git a/base/test/thread_test_helper.cc b/base/test/thread_test_helper.cc index f3ca7807..03d6b2d6 100644 --- a/base/test/thread_test_helper.cc +++ b/base/test/thread_test_helper.cc
@@ -24,7 +24,7 @@ FROM_HERE, base::BindOnce(&ThreadTestHelper::RunOnSequence, this))) { return false; } - base::ThreadRestrictions::ScopedAllowWait allow_wait; + base::ScopedAllowBaseSyncPrimitivesForTesting allow_wait; done_event_.Wait(); return test_result_; }
diff --git a/base/threading/simple_thread.cc b/base/threading/simple_thread.cc index 4b260627..670897d 100644 --- a/base/threading/simple_thread.cc +++ b/base/threading/simple_thread.cc
@@ -29,7 +29,7 @@ void SimpleThread::Start() { StartAsync(); - ThreadRestrictions::ScopedAllowWait allow_wait; + ScopedAllowBaseSyncPrimitives allow_wait; event_.Wait(); // Wait for the thread to complete initialization. } @@ -62,7 +62,6 @@ } bool SimpleThread::HasBeenStarted() { - ThreadRestrictions::ScopedAllowWait allow_wait; return event_.IsSignaled(); }
diff --git a/base/threading/thread.cc b/base/threading/thread.cc index 86062857..799da896 100644 --- a/base/threading/thread.cc +++ b/base/threading/thread.cc
@@ -143,7 +143,7 @@ DCHECK(owning_sequence_checker_.CalledOnValidSequence()); if (!message_loop_) return false; - base::ThreadRestrictions::ScopedAllowWait allow_wait; + base::ScopedAllowBaseSyncPrimitivesForTesting allow_wait; start_event_.Wait(); return true; } @@ -220,7 +220,7 @@ PlatformThreadId Thread::GetThreadId() const { // If the thread is created but not started yet, wait for |id_| being ready. - base::ThreadRestrictions::ScopedAllowWait allow_wait; + base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait; id_event_.Wait(); return id_; }
diff --git a/base/time/time_win_unittest.cc b/base/time/time_win_unittest.cc index 4d71254..84374566 100644 --- a/base/time/time_win_unittest.cc +++ b/base/time/time_win_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include <windows.h> + #include <mmsystem.h> #include <process.h> #include <stdint.h> @@ -35,9 +36,7 @@ ticker_ = -5; } - static void UninstallTicker() { - SetMockTickFunction(old_tick_function_); - } + static void UninstallTicker() { SetMockTickFunction(old_tick_function_); } private: static volatile LONG ticker_; @@ -101,9 +100,8 @@ for (int index = 0; index < kThreads; index++) { void* argument = reinterpret_cast<void*>(kChecks); unsigned thread_id; - threads[index] = reinterpret_cast<HANDLE>( - _beginthreadex(NULL, 0, RolloverTestThreadMain, argument, 0, - &thread_id)); + threads[index] = reinterpret_cast<HANDLE>(_beginthreadex( + NULL, 0, RolloverTestThreadMain, argument, 0, &thread_id)); EXPECT_NE((HANDLE)NULL, threads[index]); } @@ -162,8 +160,7 @@ EXPECT_GT(static_cast<int>(caps.wPeriodMax), 1); EXPECT_GE(static_cast<int>(caps.wPeriodMin), 1); EXPECT_GT(static_cast<int>(caps.wPeriodMax), 1); - printf("timeGetTime range is %d to %dms\n", caps.wPeriodMin, - caps.wPeriodMax); + printf("timeGetTime range is %d to %dms\n", caps.wPeriodMin, caps.wPeriodMax); } TEST(TimeTicks, QueryPerformanceFrequency) { @@ -174,7 +171,7 @@ EXPECT_EQ(TRUE, rv); EXPECT_GT(frequency.QuadPart, 1000000); // Expect at least 1MHz printf("QueryPerformanceFrequency is %5.2fMHz\n", - frequency.QuadPart / 1000000.0); + frequency.QuadPart / 1000000.0); } TEST(TimeTicks, TimerPerformance) { @@ -185,7 +182,7 @@ typedef TimeTicks (*TestFunc)(); struct TestCase { TestFunc func; - const char *description; + const char* description; }; // Cheating a bit here: assumes sizeof(TimeTicks) == sizeof(Time) // in order to create a single test case list. @@ -212,8 +209,8 @@ // The reason to remove the check is because the tests run on many // buildbots, some of which are VMs. These machines can run horribly // slow, and there is really no value for checking against a max timer. - //const int kMaxTime = 35; // Maximum acceptible milliseconds for test. - //EXPECT_LT((stop - start).InMilliseconds(), kMaxTime); + // const int kMaxTime = 35; // Maximum acceptible milliseconds for test. + // EXPECT_LT((stop - start).InMilliseconds(), kMaxTime); printf("%s: %1.2fus per call\n", test_case.description, (stop - start).InMillisecondsF() * 1000 / kLoops); } @@ -283,7 +280,7 @@ for (int64_t ticks : test_cases) { const double expected_microseconds_since_origin = (static_cast<double>(ticks) * Time::kMicrosecondsPerSecond) / - ticks_per_second; + ticks_per_second; const TimeTicks converted_value = TimeTicks::FromQPCValue(ticks); const double converted_microseconds_since_origin = static_cast<double>((converted_value - TimeTicks()).InMicroseconds());
diff --git a/base/trace_event/blame_context.cc b/base/trace_event/blame_context.cc index 0ed9aa7..b46412c 100644 --- a/base/trace_event/blame_context.cc +++ b/base/trace_event/blame_context.cc
@@ -33,9 +33,9 @@ BlameContext::~BlameContext() { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(WasInitialized()); - TRACE_EVENT_API_ADD_TRACE_EVENT( - TRACE_EVENT_PHASE_DELETE_OBJECT, category_group_enabled_, type_, scope_, - id_, 0, nullptr, nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID); + TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_DELETE_OBJECT, + category_group_enabled_, type_, scope_, id_, + nullptr, TRACE_EVENT_FLAG_HAS_ID); trace_event::TraceLog::GetInstance()->RemoveAsyncEnabledStateObserver(this); } @@ -43,7 +43,6 @@ DCHECK(WasInitialized()); TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_ENTER_CONTEXT, category_group_enabled_, name_, scope_, id_, - 0 /* num_args */, nullptr, nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID); } @@ -51,7 +50,6 @@ DCHECK(WasInitialized()); TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_LEAVE_CONTEXT, category_group_enabled_, name_, scope_, id_, - 0 /* num_args */, nullptr, nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID); } @@ -63,15 +61,10 @@ std::unique_ptr<trace_event::TracedValue> snapshot( new trace_event::TracedValue); AsValueInto(snapshot.get()); - static const char* const kArgName = "snapshot"; - const int kNumArgs = 1; - unsigned char arg_types[1] = {TRACE_VALUE_TYPE_CONVERTABLE}; - std::unique_ptr<trace_event::ConvertableToTraceFormat> arg_values[1] = { - std::move(snapshot)}; + TraceArguments args("snapshot", std::move(snapshot)); TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, category_group_enabled_, type_, scope_, id_, - kNumArgs, &kArgName, arg_types, nullptr, - arg_values, TRACE_EVENT_FLAG_HAS_ID); + &args, TRACE_EVENT_FLAG_HAS_ID); } void BlameContext::OnTraceLogEnabled() { @@ -95,9 +88,9 @@ DCHECK(thread_checker_.CalledOnValidThread()); category_group_enabled_ = TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_); - TRACE_EVENT_API_ADD_TRACE_EVENT( - TRACE_EVENT_PHASE_CREATE_OBJECT, category_group_enabled_, type_, scope_, - id_, 0, nullptr, nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID); + TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_CREATE_OBJECT, + category_group_enabled_, type_, scope_, id_, + nullptr, TRACE_EVENT_FLAG_HAS_ID); trace_event::TraceLog::GetInstance()->AddAsyncEnabledStateObserver( weak_factory_.GetWeakPtr()); TakeSnapshot();
diff --git a/base/trace_event/event_name_filter_unittest.cc b/base/trace_event/event_name_filter_unittest.cc index e1d6f51d..d0b32d11 100644 --- a/base/trace_event/event_name_filter_unittest.cc +++ b/base/trace_event/event_name_filter_unittest.cc
@@ -13,8 +13,8 @@ const TraceEvent& MakeTraceEvent(const char* name) { static TraceEvent event; - event.Reset(0, TimeTicks(), ThreadTicks(), 'b', nullptr, name, "", 0, 0, 0, - nullptr, nullptr, nullptr, nullptr, 0); + event.Reset(0, TimeTicks(), ThreadTicks(), 'b', nullptr, name, "", 0, 0, + nullptr, 0); return event; }
diff --git a/base/trace_event/process_memory_dump.cc b/base/trace_event/process_memory_dump.cc index 8f851f4..5a049cc 100644 --- a/base/trace_event/process_memory_dump.cc +++ b/base/trace_event/process_memory_dump.cc
@@ -13,6 +13,7 @@ #include "base/process/process_metrics.h" #include "base/strings/stringprintf.h" #include "base/trace_event/memory_infra_background_whitelist.h" +#include "base/trace_event/trace_event_impl.h" #include "base/trace_event/traced_value.h" #include "base/unguessable_token.h" #include "build/build_config.h"
diff --git a/base/trace_event/trace_arguments.cc b/base/trace_event/trace_arguments.cc new file mode 100644 index 0000000..002720f --- /dev/null +++ b/base/trace_event/trace_arguments.cc
@@ -0,0 +1,270 @@ +// 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 "base/trace_event/trace_arguments.h" + +#include <inttypes.h> +#include <stddef.h> +#include <string.h> + +#include <stdio.h> + +#include "base/json/string_escape.h" +#include "base/logging.h" +#include "base/stl_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" + +namespace base { +namespace trace_event { + +namespace { + +size_t GetAllocLength(const char* str) { + return str ? strlen(str) + 1 : 0; +} + +// Copies |*member| into |*buffer|, sets |*member| to point to this new +// location, and then advances |*buffer| by the amount written. +void CopyTraceEventParameter(char** buffer, + const char** member, + const char* end) { + if (*member) { + size_t written = strlcpy(*buffer, *member, end - *buffer) + 1; + DCHECK_LE(static_cast<int>(written), end - *buffer); + *member = *buffer; + *buffer += written; + } +} + +// Append |val| as a JSON output value to |*out|. +void AppendDoubleAsJSON(double val, std::string* out) { + // FIXME: base/json/json_writer.cc is using the same code, + // should be made into a common method. + std::string real; + if (std::isfinite(val)) { + real = NumberToString(val); + // Ensure that the number has a .0 if there's no decimal or 'e'. This + // makes sure that when we read the JSON back, it's interpreted as a + // real rather than an int. + if (real.find('.') == std::string::npos && + real.find('e') == std::string::npos && + real.find('E') == std::string::npos) { + real.append(".0"); + } + // The JSON spec requires that non-integer values in the range (-1,1) + // have a zero before the decimal point - ".52" is not valid, "0.52" is. + if (real[0] == '.') { + real.insert(0, "0"); + } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') { + // "-.1" bad "-0.1" good + real.insert(1, "0"); + } + } else if (std::isnan(val)) { + // The JSON spec doesn't allow NaN and Infinity (since these are + // objects in EcmaScript). Use strings instead. + real = "\"NaN\""; + } else if (val < 0) { + real = "\"-Infinity\""; + } else { + real = "\"Infinity\""; + } + StringAppendF(out, "%s", real.c_str()); +} + +const char* TypeToString(char arg_type) { + switch (arg_type) { + case TRACE_VALUE_TYPE_INT: + return "int"; + case TRACE_VALUE_TYPE_UINT: + return "uint"; + case TRACE_VALUE_TYPE_DOUBLE: + return "double"; + case TRACE_VALUE_TYPE_BOOL: + return "bool"; + case TRACE_VALUE_TYPE_POINTER: + return "pointer"; + case TRACE_VALUE_TYPE_STRING: + return "string"; + case TRACE_VALUE_TYPE_COPY_STRING: + return "copy_string"; + case TRACE_VALUE_TYPE_CONVERTABLE: + return "convertable"; + default: + NOTREACHED(); + return "UNKNOWN_TYPE"; + } +} + +void AppendValueDebugString(const TraceArguments& args, + size_t idx, + std::string* out) { + *out += (args.names()[idx] ? args.names()[idx] : "NULL_NAME"); + *out += "="; + *out += TypeToString(args.types()[idx]); + *out += "("; + args.values()[idx].AppendAsJSON(args.types()[idx], out); + *out += ")"; +} + +} // namespace + +void StringStorage::Reset(size_t alloc_size) { + if (!alloc_size) { + if (data_) + ::free(data_); + data_ = nullptr; + } else if (!data_ || alloc_size != data_->size) { + data_ = static_cast<Data*>(::realloc(data_, sizeof(size_t) + alloc_size)); + data_->size = alloc_size; + } +} + +bool StringStorage::Contains(const TraceArguments& args) const { + for (size_t n = 0; n < args.size(); ++n) { + if (args.types()[n] == TRACE_VALUE_TYPE_COPY_STRING && + !Contains(args.values()[n].as_string)) { + return false; + } + } + return true; +} + +static_assert( + std::is_pod<TraceValue>::value, + "TraceValue must be plain-old-data type for performance reasons!"); + +void TraceValue::AppendAsJSON(unsigned char type, std::string* out) const { + switch (type) { + case TRACE_VALUE_TYPE_BOOL: + *out += this->as_bool ? "true" : "false"; + break; + case TRACE_VALUE_TYPE_UINT: + StringAppendF(out, "%" PRIu64, static_cast<uint64_t>(this->as_uint)); + break; + case TRACE_VALUE_TYPE_INT: + StringAppendF(out, "%" PRId64, static_cast<int64_t>(this->as_int)); + break; + case TRACE_VALUE_TYPE_DOUBLE: + AppendDoubleAsJSON(this->as_double, out); + break; + case TRACE_VALUE_TYPE_POINTER: + // JSON only supports double and int numbers. + // So as not to lose bits from a 64-bit pointer, output as a hex string. + StringAppendF( + out, "\"0x%" PRIx64 "\"", + static_cast<uint64_t>(reinterpret_cast<uintptr_t>(this->as_pointer))); + break; + case TRACE_VALUE_TYPE_STRING: + case TRACE_VALUE_TYPE_COPY_STRING: + EscapeJSONString(this->as_string ? this->as_string : "NULL", true, out); + break; + case TRACE_VALUE_TYPE_CONVERTABLE: + this->as_convertable->AppendAsTraceFormat(out); + break; + default: + NOTREACHED() << "Don't know how to print this value"; + break; + } +} + +TraceArguments& TraceArguments::operator=(TraceArguments&& other) noexcept { + if (this != &other) { + this->~TraceArguments(); + new (this) TraceArguments(std::move(other)); + } + return *this; +} + +TraceArguments::TraceArguments(int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values) { + if (num_args > static_cast<int>(kMaxSize)) + num_args = static_cast<int>(kMaxSize); + + size_ = static_cast<unsigned char>(num_args); + for (size_t n = 0; n < size_; ++n) { + types_[n] = arg_types[n]; + names_[n] = arg_names[n]; + values_[n].as_uint = arg_values[n]; + } +} + +void TraceArguments::Reset() { + for (size_t n = 0; n < size_; ++n) { + if (types_[n] == TRACE_VALUE_TYPE_CONVERTABLE) + delete values_[n].as_convertable; + } + size_ = 0; +} + +void TraceArguments::CopyStringsTo(StringStorage* storage, + bool copy_all_strings, + const char** extra_string1, + const char** extra_string2) { + // First, compute total allocation size. + size_t alloc_size = 0; + + if (copy_all_strings) { + alloc_size += + GetAllocLength(*extra_string1) + GetAllocLength(*extra_string2); + for (size_t n = 0; n < size_; ++n) + alloc_size += GetAllocLength(names_[n]); + } + for (size_t n = 0; n < size_; ++n) { + if (copy_all_strings && types_[n] == TRACE_VALUE_TYPE_STRING) + types_[n] = TRACE_VALUE_TYPE_COPY_STRING; + if (types_[n] == TRACE_VALUE_TYPE_COPY_STRING) + alloc_size += GetAllocLength(values_[n].as_string); + } + + if (alloc_size) { + storage->Reset(alloc_size); + char* ptr = storage->data(); + const char* end = ptr + alloc_size; + if (copy_all_strings) { + CopyTraceEventParameter(&ptr, extra_string1, end); + CopyTraceEventParameter(&ptr, extra_string2, end); + for (size_t n = 0; n < size_; ++n) + CopyTraceEventParameter(&ptr, &names_[n], end); + } + for (size_t n = 0; n < size_; ++n) { + if (types_[n] == TRACE_VALUE_TYPE_COPY_STRING) + CopyTraceEventParameter(&ptr, &values_[n].as_string, end); + } +#if DCHECK_IS_ON() + DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end; + if (copy_all_strings) { + if (extra_string1 && *extra_string1) + DCHECK(storage->Contains(*extra_string1)); + if (extra_string2 && *extra_string2) + DCHECK(storage->Contains(*extra_string2)); + for (size_t n = 0; n < size_; ++n) + DCHECK(storage->Contains(names_[n])); + } + for (size_t n = 0; n < size_; ++n) { + if (types_[n] == TRACE_VALUE_TYPE_COPY_STRING) + DCHECK(storage->Contains(values_[n].as_string)); + } +#endif // DCHECK_IS_ON() + } else { + storage->Reset(); + } +} + +void TraceArguments::AppendDebugString(std::string* out) { + *out += "TraceArguments("; + for (size_t n = 0; n < size_; ++n) { + if (n > 0) + *out += ", "; + AppendValueDebugString(*this, n, out); + } + *out += ")"; +} + +} // namespace trace_event +} // namespace base
diff --git a/base/trace_event/trace_arguments.h b/base/trace_event/trace_arguments.h new file mode 100644 index 0000000..8e4df11f --- /dev/null +++ b/base/trace_event/trace_arguments.h
@@ -0,0 +1,670 @@ +// 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 BASE_TRACE_EVENT_TRACE_ARGUMENTS_H_ +#define BASE_TRACE_EVENT_TRACE_ARGUMENTS_H_ + +#include <stdlib.h> + +#include <algorithm> +#include <memory> +#include <string> + +#include "base/base_export.h" +#include "base/macros.h" +#include "base/trace_event/common/trace_event_common.h" + +// Trace macro can have one or two optional arguments, each one of them +// identified by a name (a C string literal) and a value, which can be an +// integer, enum, floating point, boolean, string pointer or reference, or +// std::unique_ptr<ConvertableToTraceFormat> compatible values. Additionally, +// custom data types need to be supported, like time values or WTF::CString. +// +// TraceArguments is a helper class used to store 0 to 2 named arguments +// corresponding to an individual trace macro call. As efficiently as possible, +// and with the minimal amount of generated machine code (since this affects +// any TRACE macro call). Each argument has: +// +// - A name (C string literal, e.g "dumps") +// - An 8-bit type value, corresponding to the TRACE_VALUE_TYPE_XXX macros. +// - A value, stored in a TraceValue union +// +// IMPORTANT: For a TRACE_VALUE_TYPE_CONVERTABLE types, the TraceArguments +// instance owns the pointed ConvertableToTraceFormat object, i.e. it will +// delete it automatically on destruction. +// +// TraceArguments instances should be built using one of specialized +// constructors declared below. One cannot modify an instance once it has +// been built, except for move operations, Reset() and destruction. Examples: +// +// TraceArguments args; // No arguments. +// // args.size() == 0 +// +// TraceArguments("foo", 100); +// // args.size() == 1 +// // args.types()[0] == TRACE_VALUE_TYPE_INT +// // args.names()[0] == "foo" +// // args.values()[0].as_int == 100 +// +// TraceArguments("bar", 1ULL); +// // args.size() == 1 +// // args.types()[0] == TRACE_VALUE_TYPE_UINT +// // args.names()[0] == "bar" +// // args.values()[0].as_uint == 100 +// +// TraceArguments("foo", "Hello", "bar", "World"); +// // args.size() == 2 +// // args.types()[0] == TRACE_VALUE_TYPE_STRING +// // args.types()[1] == TRACE_VALUE_TYPE_STRING +// // args.names()[0] == "foo" +// // args.names()[1] == "bar" +// // args.values()[0].as_string == "Hello" +// // args.values()[1].as_string == "World" +// +// std::string some_string = ...; +// TraceArguments("str1", some_string); +// // args.size() == 1 +// // args.types()[0] == TRACE_VALUE_TYPE_COPY_STRING +// // args.names()[0] == "str1" +// // args.values()[0].as_string == some_string.c_str() +// +// Note that TRACE_VALUE_TYPE_COPY_STRING corresponds to string pointers +// that point to temporary values that may disappear soon. The +// TraceArguments::CopyStringTo() method can be used to copy their content +// into a StringStorage memory block, and update the |as_string| value pointers +// to it to avoid keeping any dangling pointers. This is used by TraceEvent +// to keep copies of such strings in the log after their initialization values +// have disappeared. +// +// The TraceStringWithCopy helper class can be used to initialize a value +// from a regular string pointer with TRACE_VALUE_TYPE_COPY_STRING too, as in: +// +// const char str[] = "...."; +// TraceArguments("foo", str, "bar", TraceStringWithCopy(str)); +// // args.size() == 2 +// // args.types()[0] == TRACE_VALUE_TYPE_STRING +// // args.types()[1] == TRACE_VALUE_TYPE_COPY_STRING +// // args.names()[0] == "foo" +// // args.names()[1] == "bar" +// // args.values()[0].as_string == str +// // args.values()[1].as_string == str +// +// StringStorage storage; +// args.CopyStringTo(&storage, false, nullptr, nullptr); +// // args.size() == 2 +// // args.types()[0] == TRACE_VALUE_TYPE_STRING +// // args.types()[1] == TRACE_VALUE_TYPE_COPY_STRING +// // args.names()[0] == "foo" +// // args.names()[1] == "bar" +// // args.values()[0].as_string == str +// // args.values()[1].as_string == Address inside |storage|. +// +// Initialization from a std::unique_ptr<ConvertableToTraceFormat> +// is supported but will move ownership of the pointer objects to the +// TraceArguments instance: +// +// class MyConvertableType : +// public base::trace_event::AsConvertableToTraceFormat { +// ... +// }; +// +// { +// TraceArguments args("foo" , std::make_unique<MyConvertableType>(...)); +// // args.size() == 1 +// // args.values()[0].as_convertable == address of MyConvertable object. +// } // Calls |args| destructor, which will delete the object too. +// +// Finally, it is possible to support initialization from custom values by +// specializing the TraceValue::Helper<> template struct as described below. +// +// This is how values of custom types like WTF::CString can be passed directly +// to trace macros. + +namespace base { + +class Time; +class TimeTicks; +class ThreadTicks; + +namespace trace_event { + +class TraceEventMemoryOverhead; + +// For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided +// class must implement this interface. Note that unlike other values, +// these objects will be owned by the TraceArguments instance that points +// to them. +class BASE_EXPORT ConvertableToTraceFormat { + public: + ConvertableToTraceFormat() = default; + virtual ~ConvertableToTraceFormat() = default; + + // Append the class info to the provided |out| string. The appended + // data must be a valid JSON object. Strings must be properly quoted, and + // escaped. There is no processing applied to the content after it is + // appended. + virtual void AppendAsTraceFormat(std::string* out) const = 0; + + // Append the class info directly into the Perfetto-defined proto + // format; this is attempted first and if this returns true, + // AppendAsTraceFormat is not called. The ProtoAppender interface + // acts as a bridge to avoid proto/Perfetto dependencies in base. + class BASE_EXPORT ProtoAppender { + public: + virtual ~ProtoAppender() = default; + + virtual void AddBuffer(uint8_t* begin, uint8_t* end) = 0; + // Copy all of the previous buffers registered with AddBuffer + // into the proto, with the given |field_id|. + virtual size_t Finalize(uint32_t field_id) = 0; + }; + virtual bool AppendToProto(ProtoAppender* appender); + + virtual void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead); + + std::string ToString() const { + std::string result; + AppendAsTraceFormat(&result); + return result; + } + + private: + DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormat); +}; + +const int kTraceMaxNumArgs = 2; + +// A union used to hold the values of individual trace arguments. +// +// This is a POD union for performance reason. Initialization from an +// explicit C++ trace argument should be performed with the Init() +// templated method described below. +// +// Initialization from custom types is possible by implementing a custom +// TraceValue::Helper<> instantiation as described below. +// +// IMPORTANT: Pointer storage inside a TraceUnion follows specific rules: +// +// - |as_pointer| is for raw pointers that should be treated as a simple +// address and will never be dereferenced. Associated with the +// TRACE_VALUE_TYPE_POINTER type. +// +// - |as_string| is for C-string pointers, associated with both +// TRACE_VALUE_TYPE_STRING and TRACE_VALUE_TYPE_COPY_STRING. The former +// indicates that the string pointer is persistent (e.g. a C string +// literal), while the second indicates that the pointer belongs to a +// temporary variable that may disappear soon. The TraceArguments class +// provides a CopyStringTo() method to copy these strings into a +// StringStorage instance, which is useful if the instance needs to +// survive longer than the temporaries. +// +// - |as_convertable| is equivalent to +// std::unique_ptr<ConvertableToTraceFormat>, except that it is a pointer +// to keep this union POD and avoid un-necessary declarations and potential +// code generation. This means that its ownership is passed to the +// TraceValue instance when Init(std::unique_ptr<ConvertableToTraceFormat>) +// is called, and that it will be deleted by the containing TraceArguments +// destructor, or Reset() method. +// +union BASE_EXPORT TraceValue { + bool as_bool; + unsigned long long as_uint; + long long as_int; + double as_double; + const void* as_pointer; + const char* as_string; + ConvertableToTraceFormat* as_convertable; + + // There is no constructor to keep this structure POD intentionally. + // This avoids un-needed initialization when only 0 or 1 arguments are + // used to construct a TraceArguments instance. Use Init() instead to + // perform explicit initialization from a given C++ value. + + // Initialize TraceValue instance from a C++ trace value. + // This relies on the proper specialization of TraceValue::Helper<> + // described below. Usage is simply: + // + // TraceValue v; + // v.Init(<value>); + // + // NOTE: For ConvertableToTraceFormat values, see the note above and + // the one for TraceValue::Helper for CONVERTABLE_TYPE below. + template <typename T> + void Init(T&& value) { + using ValueType = typename InnerType<T>::type; + Helper<ValueType>::SetValue(this, std::forward<T>(value)); + } + + // Static method to create a new TraceValue instance from a given + // initialization value. Note that this deduces the TRACE_VALUE_TYPE_XXX + // type but doesn't return it, use ForType<T>::value for this. + // + // Usage example: + // auto v = TraceValue::Make(100); + // auto v2 = TraceValue::Make("Some text string"); + // + // IMPORTANT: Experience shows that the compiler generates worse code when + // using this method rather than calling Init() directly on an existing + // TraceValue union :-( + // + template <typename T> + static TraceValue Make(T&& value) { + TraceValue ret; + ret.Init(std::forward<T>(value)); + return ret; + } + + // Output current value as a JSON string. |type| must be a valid + // TRACE_VALUE_TYPE_XXX value. + void AppendAsJSON(unsigned char type, std::string* out) const; + + private: + // InnerType<T>::type removes reference, cv-qualifications and decays + // function and arrays into pointers. Only used internally. + template <typename T> + struct InnerType { + using type = typename std::remove_cv<typename std::remove_reference< + typename std::decay<T>::type>::type>::type; + }; + + public: + // TraceValue::Helper is used to provide information about initialization + // value types and an initialization function. It is a struct that should + // provide the following for supported initialization value types: + // + // - kType: is a static TRACE_VALUE_TYPE_XXX constant. + // + // - SetValue(TraceValue*, T): is a static inline method that sets + // TraceValue value from a given T value. Second parameter type + // can also be const T& or T&& to restrict uses. + // + // IMPORTANT: The type T must be InnerType<Q>, where Q is the real C++ + // argument type. I.e. you should not have to deal with reference types + // in your specialization. + // + // Specializations are defined for integers, enums, floating point, pointers, + // constant C string literals and pointers, std::string, time values below. + // + // Specializations for custom types are possible provided that there exists + // a corresponding Helper specialization, for example: + // + // template <> + // struct base::trace_event::TraceValue::Helper<Foo> { + // static constexpr unsigned char kTypes = TRACE_VALUE_TYPE_COPY_STRING; + // static inline void SetValue(TraceValue* v, const Foo& value) { + // v->as_string = value.c_str(); + // } + // }; + // + // Will allow code like: + // + // Foo foo = ...; + // auto v = TraceValue::Make(foo); + // + // Or even: + // Foo foo = ...; + // TraceArguments args("foo_arg1", foo); + // + template <typename T, class = void> + struct Helper {}; + + // TraceValue::TypeFor<T>::value returns the TRACE_VALUE_TYPE_XXX + // corresponding to initialization values of type T. + template <typename T> + struct TypeFor { + using ValueType = typename InnerType<T>::type; + static const unsigned char value = Helper<ValueType>::kType; + }; + + // TraceValue::TypeCheck<T>::value is only defined iff T can be used to + // initialize a TraceValue instance. This is useful to restrict template + // instantiation to only the appropriate type (see TraceArguments + // constructors below). + template <typename T, + class = decltype(TraceValue::Helper< + typename TraceValue::InnerType<T>::type>::kType)> + struct TypeCheck { + static const bool value = true; + }; +}; + +// TraceValue::Helper for integers and enums. +template <typename T> +struct TraceValue::Helper< + T, + typename std::enable_if<std::is_integral<T>::value || + std::is_enum<T>::value>::type> { + static constexpr unsigned char kType = + std::is_signed<T>::value ? TRACE_VALUE_TYPE_INT : TRACE_VALUE_TYPE_UINT; + static inline void SetValue(TraceValue* v, T value) { + v->as_uint = static_cast<unsigned long long>(value); + } +}; + +// TraceValue::Helper for floating-point types +template <typename T> +struct TraceValue:: + Helper<T, typename std::enable_if<std::is_floating_point<T>::value>::type> { + static constexpr unsigned char kType = TRACE_VALUE_TYPE_DOUBLE; + static inline void SetValue(TraceValue* v, T value) { v->as_double = value; } +}; + +// TraceValue::Helper for bool. +template <> +struct TraceValue::Helper<bool> { + static constexpr unsigned char kType = TRACE_VALUE_TYPE_BOOL; + static inline void SetValue(TraceValue* v, bool value) { v->as_bool = value; } +}; + +// TraceValue::Helper for generic pointer types. +template <typename T> +struct TraceValue::Helper<T*> { + static constexpr unsigned char kType = TRACE_VALUE_TYPE_POINTER; + static inline void SetValue(TraceValue* v, + const typename std::decay<T>::type* value) { + v->as_pointer = value; + } +}; + +// TraceValue::Helper for raw persistent C strings. +template <> +struct TraceValue::Helper<const char*> { + static constexpr unsigned char kType = TRACE_VALUE_TYPE_STRING; + static inline void SetValue(TraceValue* v, const char* value) { + v->as_string = value; + } +}; + +// TraceValue::Helper for std::string values. +template <> +struct TraceValue::Helper<std::string> { + static constexpr unsigned char kType = TRACE_VALUE_TYPE_COPY_STRING; + static inline void SetValue(TraceValue* v, const std::string& value) { + v->as_string = value.c_str(); + } +}; + +// Special case for scoped pointers to convertables to trace format. +// |CONVERTABLE_TYPE| must be a type whose pointers can be converted to a +// ConvertableToTraceFormat* pointer as well (e.g. a derived class). +// IMPORTANT: This takes an std::unique_ptr<CONVERTABLE_TYPE> value, and takes +// ownership of the pointed object! +template <typename CONVERTABLE_TYPE> +struct TraceValue::Helper<std::unique_ptr<CONVERTABLE_TYPE>, + typename std::enable_if<std::is_convertible< + CONVERTABLE_TYPE*, + ConvertableToTraceFormat*>::value>::type> { + static constexpr unsigned char kType = TRACE_VALUE_TYPE_CONVERTABLE; + static inline void SetValue(TraceValue* v, + std::unique_ptr<CONVERTABLE_TYPE> value) { + v->as_convertable = value.release(); + } +}; + +// Specialization for time-based values like base::Time, which provide a +// a ToInternalValue() method. +template <typename T> +struct TraceValue::Helper< + T, + typename std::enable_if<std::is_same<T, base::Time>::value || + std::is_same<T, base::TimeTicks>::value || + std::is_same<T, base::ThreadTicks>::value>::type> { + static constexpr unsigned char kType = TRACE_VALUE_TYPE_INT; + static inline void SetValue(TraceValue* v, const T& value) { + v->as_int = value.ToInternalValue(); + } +}; + +// Simple container for const char* that should be copied instead of retained. +// The goal is to indicate that the C string is copyable, unlike the default +// Init(const char*) implementation. Usage is: +// +// const char* str = ...; +// v.Init(TraceStringWithCopy(str)); +// +// Which will mark the string as TRACE_VALUE_TYPE_COPY_STRING, instead of +// TRACE_VALUE_TYPE_STRING. +// +class TraceStringWithCopy { + public: + explicit TraceStringWithCopy(const char* str) : str_(str) {} + const char* str() const { return str_; } + + private: + const char* str_; +}; + +template <> +struct TraceValue::Helper<TraceStringWithCopy> { + static constexpr unsigned char kType = TRACE_VALUE_TYPE_COPY_STRING; + static inline void SetValue(TraceValue* v, const TraceStringWithCopy& value) { + v->as_string = value.str(); + } +}; + +class TraceArguments; + +// A small class used to store a copy of all strings from a given +// TraceArguments instance (see below). When empty, this should only +// take the size of a pointer. Otherwise, this will point to a heap +// allocated block containing a size_t value followed by all characters +// in the storage area. For most cases, this is more efficient +// than using a std::unique_ptr<std::string> or an std::vector<char>. +class BASE_EXPORT StringStorage { + public: + constexpr StringStorage() = default; + + explicit StringStorage(size_t alloc_size) { Reset(alloc_size); } + + ~StringStorage() { + if (data_) + ::free(data_); + } + + StringStorage(StringStorage&& other) : data_(other.data_) { + other.data_ = nullptr; + } + + StringStorage& operator=(StringStorage&& other) { + if (this != &other) { + if (data_) + ::free(data_); + data_ = other.data_; + other.data_ = nullptr; + } + return *this; + } + + // Reset storage area to new allocation size. Existing content might not + // be preserved. If |alloc_size| is 0, this will free the storage area + // as well. + void Reset(size_t alloc_size = 0); + + // Accessors. + constexpr size_t size() const { return data_ ? data_->size : 0u; } + constexpr const char* data() const { return data_ ? data_->chars : nullptr; } + constexpr char* data() { return data_ ? data_->chars : nullptr; } + + constexpr const char* begin() const { return data(); } + constexpr const char* end() const { return data() + size(); } + inline char* begin() { return data(); } + inline char* end() { return data() + size(); } + + // True iff storage is empty. + constexpr bool empty() const { return size() == 0; } + + // Returns true if |ptr| is inside the storage area, false otherwise. + // Used during unit-testing. + constexpr bool Contains(const void* ptr) const { + const char* char_ptr = static_cast<const char*>(ptr); + return (char_ptr >= begin() && char_ptr < end()); + } + + // Returns true if all string pointers in |args| are contained in this + // storage area. + bool Contains(const TraceArguments& args) const; + + // Return an estimate of the memory overhead of this instance. This doesn't + // count the size of |data_| itself. + constexpr size_t EstimateTraceMemoryOverhead() const { + return data_ ? sizeof(size_t) + data_->size : 0u; + } + + private: + // Heap allocated data block (variable size), made of: + // + // - size: a size_t field, giving the size of the following |chars| array. + // - chars: an array of |size| characters, holding all zero-terminated + // strings referenced from a TraceArguments instance. + struct Data { + size_t size = 0; + char chars[1]; // really |size| character items in storage. + }; + + // This is an owning pointer. Normally, using a std::unique_ptr<> would be + // enough, but the compiler will then complaing about inlined constructors + // and destructors being too complex (!), resulting in larger code for no + // good reason. + Data* data_ = nullptr; +}; + +// TraceArguments models an array of kMaxSize trace-related items, +// each one of them having: +// - a name, which is a constant char array literal. +// - a type, as described by TRACE_VALUE_TYPE_XXX macros. +// - a value, stored in a TraceValue union. +// +// IMPORTANT: For TRACE_VALUE_TYPE_CONVERTABLE, the value holds an owning +// pointer to an AsConvertableToTraceFormat instance, which will +// be destroyed with the array (or moved out of it when passed +// to a TraceEvent instance). +// +// For TRACE_VALUE_TYPE_COPY_STRING, the value holds a const char* pointer +// whose content will be copied when creating a TraceEvent instance. +// +// IMPORTANT: Most constructors and the destructor are all inlined +// intentionally, in order to let the compiler remove un-necessary operations +// and reduce machine code. +// +class BASE_EXPORT TraceArguments { + public: + // Maximum number of arguments held by this structure. + static constexpr size_t kMaxSize = 2; + + // Default constructor, no arguments. + TraceArguments() : size_(0) {} + + // Constructor for a single argument. + template <typename T, class = decltype(TraceValue::TypeCheck<T>::value)> + TraceArguments(const char* arg1_name, T&& arg1_value) : size_(1) { + types_[0] = TraceValue::TypeFor<T>::value; + names_[0] = arg1_name; + values_[0].Init(std::forward<T>(arg1_value)); + } + + // Constructor for two arguments. + template <typename T1, + typename T2, + class = decltype(TraceValue::TypeCheck<T1>::value && + TraceValue::TypeCheck<T2>::value)> + TraceArguments(const char* arg1_name, + T1&& arg1_value, + const char* arg2_name, + T2&& arg2_value) + : size_(2) { + types_[0] = TraceValue::TypeFor<T1>::value; + types_[1] = TraceValue::TypeFor<T2>::value; + names_[0] = arg1_name; + names_[1] = arg2_name; + values_[0].Init(std::forward<T1>(arg1_value)); + values_[1].Init(std::forward<T2>(arg2_value)); + } + + // Constructor used to convert a legacy set of arguments when there + // are no convertable values at all. + TraceArguments(int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values); + + // Constructor used to convert legacy set of arguments, where the + // convertable values are also provided by an array of CONVERTABLE_TYPE. + template <typename CONVERTABLE_TYPE> + TraceArguments(int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + CONVERTABLE_TYPE* arg_convertables) { + static int max_args = static_cast<int>(kMaxSize); + if (num_args > max_args) + num_args = max_args; + size_ = static_cast<unsigned char>(num_args); + for (size_t n = 0; n < size_; ++n) { + types_[n] = arg_types[n]; + names_[n] = arg_names[n]; + if (arg_types[n] == TRACE_VALUE_TYPE_CONVERTABLE) { + values_[n].Init( + std::forward<CONVERTABLE_TYPE>(std::move(arg_convertables[n]))); + } else { + values_[n].as_uint = arg_values[n]; + } + } + } + + // Destructor. NOTE: Intentionally inlined (see note above). + ~TraceArguments() { + for (size_t n = 0; n < size_; ++n) { + if (types_[n] == TRACE_VALUE_TYPE_CONVERTABLE) + delete values_[n].as_convertable; + } + } + + // Disallow copy operations. + TraceArguments(const TraceArguments&) = delete; + TraceArguments& operator=(const TraceArguments&) = delete; + + // Allow move operations. + TraceArguments(TraceArguments&& other) noexcept { + ::memcpy(this, &other, sizeof(*this)); + // All owning pointers were copied to |this|. Setting |other.size_| will + // mask the pointer values still in |other|. + other.size_ = 0; + } + + TraceArguments& operator=(TraceArguments&&) noexcept; + + // Accessors + size_t size() const { return size_; } + const unsigned char* types() const { return types_; } + const char* const* names() const { return names_; } + const TraceValue* values() const { return values_; } + + // Reset to empty arguments list. + void Reset(); + + // Use |storage| to copy all copyable strings. + // If |copy_all_strings| is false, then only the TRACE_VALUE_TYPE_COPY_STRING + // values will be copied into storage. If it is true, then argument names are + // also copied to storage, as well as the strings pointed to by + // |*extra_string1| and |*extra_string2|. + // NOTE: If there are no strings to copy, |*storage| is left untouched. + void CopyStringsTo(StringStorage* storage, + bool copy_all_strings, + const char** extra_string1, + const char** extra_string2); + + // Append debug string representation to |*out|. + void AppendDebugString(std::string* out); + + private: + unsigned char size_; + unsigned char types_[kMaxSize]; + const char* names_[kMaxSize]; + TraceValue values_[kMaxSize]; +}; + +} // namespace trace_event +} // namespace base + +#endif // BASE_TRACE_EVENT_TRACE_ARGUMENTS_H_
diff --git a/base/trace_event/trace_arguments_unittest.cc b/base/trace_event/trace_arguments_unittest.cc new file mode 100644 index 0000000..a550cd6 --- /dev/null +++ b/base/trace_event/trace_arguments_unittest.cc
@@ -0,0 +1,472 @@ +// 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 "base/trace_event/trace_arguments.h" + +#include <gtest/gtest.h> +#include <string> + +namespace base { +namespace trace_event { + +namespace { + +// Simple convertable that holds a string to append to the trace, +// and can also write to a boolean flag on destruction. +class MyConvertable : public ConvertableToTraceFormat { + public: + MyConvertable(const char* text, bool* destroy_flag = nullptr) + : text_(text), destroy_flag_(destroy_flag) {} + ~MyConvertable() override { + if (destroy_flag_) + *destroy_flag_ = true; + } + void AppendAsTraceFormat(std::string* out) const override { *out += text_; } + const char* text() const { return text_; } + + private: + const char* text_; + bool* destroy_flag_; +}; + +} // namespace + +TEST(TraceArguments, StringStorageDefaultConstruction) { + StringStorage storage; + EXPECT_TRUE(storage.empty()); + EXPECT_FALSE(storage.data()); + EXPECT_EQ(0U, storage.size()); +} + +TEST(TraceArguments, StringStorageConstructionWithSize) { + const size_t kSize = 128; + StringStorage storage(kSize); + EXPECT_FALSE(storage.empty()); + EXPECT_TRUE(storage.data()); + EXPECT_EQ(kSize, storage.size()); + EXPECT_EQ(storage.data(), storage.begin()); + EXPECT_EQ(storage.data() + kSize, storage.end()); +} + +TEST(TraceArguments, StringStorageReset) { + StringStorage storage(128); + EXPECT_FALSE(storage.empty()); + + storage.Reset(); + EXPECT_TRUE(storage.empty()); + EXPECT_FALSE(storage.data()); + EXPECT_EQ(0u, storage.size()); +} + +TEST(TraceArguments, StringStorageResetWithSize) { + StringStorage storage; + EXPECT_TRUE(storage.empty()); + + const size_t kSize = 128; + storage.Reset(kSize); + EXPECT_FALSE(storage.empty()); + EXPECT_TRUE(storage.data()); + EXPECT_EQ(kSize, storage.size()); + EXPECT_EQ(storage.data(), storage.begin()); + EXPECT_EQ(storage.data() + kSize, storage.end()); +} + +TEST(TraceArguments, StringStorageEstimateTraceMemoryOverhead) { + StringStorage storage; + EXPECT_EQ(0u, storage.EstimateTraceMemoryOverhead()); + + const size_t kSize = 128; + storage.Reset(kSize); + EXPECT_EQ(sizeof(size_t) + kSize, storage.EstimateTraceMemoryOverhead()); +} + +static void CheckJSONFor(TraceValue v, char type, const char* expected) { + std::string out; + v.AppendAsJSON(type, &out); + EXPECT_STREQ(expected, out.c_str()); +} + +TEST(TraceArguments, TraceValueAppendAsJSON) { + TraceValue v; + + v.Init(-1024); + CheckJSONFor(v, TRACE_VALUE_TYPE_INT, "-1024"); + v.Init(1024ULL); + CheckJSONFor(v, TRACE_VALUE_TYPE_UINT, "1024"); + v.Init(3.1415926535); + CheckJSONFor(v, TRACE_VALUE_TYPE_DOUBLE, "3.1415926535"); + v.Init(true); + CheckJSONFor(v, TRACE_VALUE_TYPE_BOOL, "true"); + v.Init(false); + CheckJSONFor(v, TRACE_VALUE_TYPE_BOOL, "false"); + v.Init("Some \"nice\" String"); + CheckJSONFor(v, TRACE_VALUE_TYPE_STRING, "\"Some \\\"nice\\\" String\""); + CheckJSONFor(v, TRACE_VALUE_TYPE_COPY_STRING, "\"Some \\\"nice\\\" String\""); +} + +TEST(TraceArguments, DefaultConstruction) { + TraceArguments args; + EXPECT_EQ(0U, args.size()); +} + +TEST(TraceArguments, ConstructorSingleInteger) { + TraceArguments args("foo_int", int(10)); + EXPECT_EQ(1U, args.size()); + EXPECT_EQ(TRACE_VALUE_TYPE_INT, args.types()[0]); + EXPECT_STREQ("foo_int", args.names()[0]); + EXPECT_EQ(10, args.values()[0].as_int); +} + +TEST(TraceArguments, ConstructorSingleFloat) { + TraceArguments args("foo_pi", float(3.1415)); + double expected = float(3.1415); + EXPECT_EQ(1U, args.size()); + EXPECT_EQ(TRACE_VALUE_TYPE_DOUBLE, args.types()[0]); + EXPECT_STREQ("foo_pi", args.names()[0]); + EXPECT_EQ(expected, args.values()[0].as_double); +} + +TEST(TraceArguments, ConstructorSingleNoCopyString) { + const char kText[] = "Persistent string"; + TraceArguments args("foo_cstring", kText); + EXPECT_EQ(1U, args.size()); + EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args.types()[0]); + EXPECT_STREQ("foo_cstring", args.names()[0]); + EXPECT_EQ(kText, args.values()[0].as_string); +} + +TEST(TraceArguments, ConstructorSingleStdString) { + std::string text = "Non-persistent string"; + TraceArguments args("foo_stdstring", text); + EXPECT_EQ(1U, args.size()); + EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]); + EXPECT_STREQ("foo_stdstring", args.names()[0]); + EXPECT_EQ(text.c_str(), args.values()[0].as_string); +} + +TEST(TraceArguments, ConstructorSingleTraceStringWithCopy) { + const char kText[] = "Persistent string #2"; + TraceArguments args("foo_tracestring", TraceStringWithCopy(kText)); + EXPECT_EQ(1U, args.size()); + EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]); + EXPECT_STREQ("foo_tracestring", args.names()[0]); + EXPECT_EQ(kText, args.values()[0].as_string); +} + +TEST(TraceArguments, ConstructorSinglePointer) { + bool destroy_flag = false; + { + // Simple class that can set a boolean flag on destruction. + class Foo { + public: + Foo(bool* destroy_flag) : destroy_flag_(destroy_flag) {} + ~Foo() { + if (destroy_flag_) + *destroy_flag_ = true; + } + + private: + bool* destroy_flag_; + }; + auto foo = std::make_unique<Foo>(&destroy_flag); + EXPECT_FALSE(destroy_flag); + // This test also verifies that the object is not destroyed by the + // TraceArguments destructor. This should only be possible for + // TRACE_VALUE_TYPE_CONVERTABLE instances. + { + TraceArguments args("foo_pointer", foo.get()); + EXPECT_EQ(1U, args.size()); + EXPECT_EQ(TRACE_VALUE_TYPE_POINTER, args.types()[0]); + EXPECT_STREQ("foo_pointer", args.names()[0]); + EXPECT_EQ(foo.get(), args.values()[0].as_pointer); + EXPECT_FALSE(destroy_flag); + } // Calls TraceArguments destructor. + EXPECT_FALSE(destroy_flag); + } // Calls Foo destructor. + EXPECT_TRUE(destroy_flag); +} + +TEST(TraceArguments, ConstructorSingleConvertable) { + bool destroy_flag = false; + const char kText[] = "Text for MyConvertable instance"; + MyConvertable* ptr = new MyConvertable(kText, &destroy_flag); + + // This test also verifies that the MyConvertable instance is properly + // destroyed when the TraceArguments destructor is called. + EXPECT_FALSE(destroy_flag); + { + TraceArguments args("foo_convertable", std::unique_ptr<MyConvertable>(ptr)); + EXPECT_EQ(1U, args.size()); + EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args.types()[0]); + EXPECT_STREQ("foo_convertable", args.names()[0]); + EXPECT_EQ(ptr, args.values()[0].as_convertable); + EXPECT_FALSE(destroy_flag); + } // Calls TraceArguments destructor. + EXPECT_TRUE(destroy_flag); +} + +TEST(TraceArguments, ConstructorWithTwoArguments) { + const char kText1[] = "First argument"; + const char kText2[] = "Second argument"; + bool destroy_flag = false; + + { + MyConvertable* ptr = new MyConvertable(kText2, &destroy_flag); + TraceArguments args1("foo_arg1_cstring", kText1, "foo_arg2_convertable", + std::unique_ptr<MyConvertable>(ptr)); + EXPECT_EQ(2U, args1.size()); + EXPECT_STREQ("foo_arg1_cstring", args1.names()[0]); + EXPECT_STREQ("foo_arg2_convertable", args1.names()[1]); + EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args1.types()[0]); + EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args1.types()[1]); + EXPECT_EQ(kText1, args1.values()[0].as_string); + EXPECT_EQ(ptr, args1.values()[1].as_convertable); + EXPECT_FALSE(destroy_flag); + } // calls |args1| destructor. Should delete |ptr|. + EXPECT_TRUE(destroy_flag); +} + +TEST(TraceArguments, ConstructorLegacyNoConvertables) { + const char* const kNames[3] = {"legacy_arg1", "legacy_arg2", "legacy_arg3"}; + const unsigned char kTypes[3] = { + TRACE_VALUE_TYPE_INT, + TRACE_VALUE_TYPE_STRING, + TRACE_VALUE_TYPE_POINTER, + }; + static const char kText[] = "Some text"; + const unsigned long long kValues[3] = { + 1000042ULL, + reinterpret_cast<unsigned long long>(kText), + reinterpret_cast<unsigned long long>(kText + 2), + }; + TraceArguments args(3, kNames, kTypes, kValues); + // Check that only the first kMaxSize arguments are taken! + EXPECT_EQ(2U, args.size()); + EXPECT_STREQ(kNames[0], args.names()[0]); + EXPECT_STREQ(kNames[1], args.names()[1]); + EXPECT_EQ(TRACE_VALUE_TYPE_INT, args.types()[0]); + EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args.types()[1]); + EXPECT_EQ(kValues[0], args.values()[0].as_uint); + EXPECT_EQ(kText, args.values()[1].as_string); +}; + +TEST(TraceArguments, ConstructorLegacyWithConvertables) { + const char* const kNames[3] = {"legacy_arg1", "legacy_arg2", "legacy_arg3"}; + const unsigned char kTypes[3] = { + TRACE_VALUE_TYPE_CONVERTABLE, + TRACE_VALUE_TYPE_CONVERTABLE, + TRACE_VALUE_TYPE_CONVERTABLE, + }; + std::unique_ptr<MyConvertable> convertables[3] = { + std::make_unique<MyConvertable>("First one"), + std::make_unique<MyConvertable>("Second one"), + std::make_unique<MyConvertable>("Third one"), + }; + TraceArguments args(3, kNames, kTypes, nullptr, convertables); + // Check that only the first kMaxSize arguments are taken! + EXPECT_EQ(2U, args.size()); + EXPECT_STREQ(kNames[0], args.names()[0]); + EXPECT_STREQ(kNames[1], args.names()[1]); + EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args.types()[0]); + EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args.types()[1]); + // Check that only the first two items were moved to |args|. + EXPECT_FALSE(convertables[0].get()); + EXPECT_FALSE(convertables[1].get()); + EXPECT_TRUE(convertables[2].get()); +} + +TEST(TraceArguments, MoveConstruction) { + const char kText1[] = "First argument"; + const char kText2[] = "Second argument"; + bool destroy_flag = false; + + { + MyConvertable* ptr = new MyConvertable(kText2, &destroy_flag); + TraceArguments args1("foo_arg1_cstring", kText1, "foo_arg2_convertable", + std::unique_ptr<MyConvertable>(ptr)); + EXPECT_EQ(2U, args1.size()); + EXPECT_STREQ("foo_arg1_cstring", args1.names()[0]); + EXPECT_STREQ("foo_arg2_convertable", args1.names()[1]); + EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args1.types()[0]); + EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args1.types()[1]); + EXPECT_EQ(kText1, args1.values()[0].as_string); + EXPECT_EQ(ptr, args1.values()[1].as_convertable); + + { + TraceArguments args2(std::move(args1)); + EXPECT_FALSE(destroy_flag); + + // |args1| is now empty. + EXPECT_EQ(0U, args1.size()); + + // Check that everything was transferred to |args2|. + EXPECT_EQ(2U, args2.size()); + EXPECT_STREQ("foo_arg1_cstring", args2.names()[0]); + EXPECT_STREQ("foo_arg2_convertable", args2.names()[1]); + EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args2.types()[0]); + EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args2.types()[1]); + EXPECT_EQ(kText1, args2.values()[0].as_string); + EXPECT_EQ(ptr, args2.values()[1].as_convertable); + } // Calls |args2| destructor. Should delete |ptr|. + EXPECT_TRUE(destroy_flag); + destroy_flag = false; + } // Calls |args1| destructor. Should not delete |ptr|. + EXPECT_FALSE(destroy_flag); +} + +TEST(TraceArguments, MoveAssignment) { + const char kText1[] = "First argument"; + const char kText2[] = "Second argument"; + bool destroy_flag = false; + + { + MyConvertable* ptr = new MyConvertable(kText2, &destroy_flag); + TraceArguments args1("foo_arg1_cstring", kText1, "foo_arg2_convertable", + std::unique_ptr<MyConvertable>(ptr)); + EXPECT_EQ(2U, args1.size()); + EXPECT_STREQ("foo_arg1_cstring", args1.names()[0]); + EXPECT_STREQ("foo_arg2_convertable", args1.names()[1]); + EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args1.types()[0]); + EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args1.types()[1]); + EXPECT_EQ(kText1, args1.values()[0].as_string); + EXPECT_EQ(ptr, args1.values()[1].as_convertable); + + { + TraceArguments args2; + + args2 = std::move(args1); + EXPECT_FALSE(destroy_flag); + + // |args1| is now empty. + EXPECT_EQ(0U, args1.size()); + + // Check that everything was transferred to |args2|. + EXPECT_EQ(2U, args2.size()); + EXPECT_STREQ("foo_arg1_cstring", args2.names()[0]); + EXPECT_STREQ("foo_arg2_convertable", args2.names()[1]); + EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args2.types()[0]); + EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args2.types()[1]); + EXPECT_EQ(kText1, args2.values()[0].as_string); + EXPECT_EQ(ptr, args2.values()[1].as_convertable); + } // Calls |args2| destructor. Should delete |ptr|. + EXPECT_TRUE(destroy_flag); + destroy_flag = false; + } // Calls |args1| destructor. Should not delete |ptr|. + EXPECT_FALSE(destroy_flag); +} + +TEST(TraceArguments, Reset) { + bool destroy_flag = false; + { + TraceArguments args( + "foo_arg1", "Hello", "foo_arg2", + std::make_unique<MyConvertable>("World", &destroy_flag)); + + EXPECT_EQ(2U, args.size()); + EXPECT_FALSE(destroy_flag); + args.Reset(); + EXPECT_EQ(0U, args.size()); + EXPECT_TRUE(destroy_flag); + destroy_flag = false; + } // Calls |args| destructor. Should not delete twice. + EXPECT_FALSE(destroy_flag); +} + +TEST(TraceArguments, CopyStringsTo_NoStrings) { + StringStorage storage; + + TraceArguments args("arg1", 10, "arg2", 42); + args.CopyStringsTo(&storage, false, nullptr, nullptr); + EXPECT_TRUE(storage.empty()); + EXPECT_EQ(0U, storage.size()); +} + +TEST(TraceArguments, CopyStringsTo_OnlyArgs) { + StringStorage storage; + + TraceArguments args("arg1", TraceStringWithCopy("Hello"), "arg2", + TraceStringWithCopy("World")); + + const char kExtra1[] = "extra1"; + const char kExtra2[] = "extra2"; + const char* extra1 = kExtra1; + const char* extra2 = kExtra2; + + // Types should be copyable strings. + EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]); + EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[1]); + + args.CopyStringsTo(&storage, false, &extra1, &extra2); + + // Storage should be allocated. + EXPECT_TRUE(storage.data()); + EXPECT_NE(0U, storage.size()); + + // Types should not be changed. + EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]); + EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[1]); + + // names should not be copied. + EXPECT_FALSE(storage.Contains(args.names()[0])); + EXPECT_FALSE(storage.Contains(args.names()[1])); + EXPECT_STREQ("arg1", args.names()[0]); + EXPECT_STREQ("arg2", args.names()[1]); + + // strings should be copied. + EXPECT_TRUE(storage.Contains(args.values()[0].as_string)); + EXPECT_TRUE(storage.Contains(args.values()[1].as_string)); + EXPECT_STREQ("Hello", args.values()[0].as_string); + EXPECT_STREQ("World", args.values()[1].as_string); + + // |extra1| and |extra2| should not be copied. + EXPECT_EQ(kExtra1, extra1); + EXPECT_EQ(kExtra2, extra2); +} + +TEST(TraceArguments, CopyStringsTo_Everything) { + StringStorage storage; + + TraceArguments args("arg1", "Hello", "arg2", "World"); + const char kExtra1[] = "extra1"; + const char kExtra2[] = "extra2"; + const char* extra1 = kExtra1; + const char* extra2 = kExtra2; + + // Types should be normal strings. + EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args.types()[0]); + EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args.types()[1]); + + args.CopyStringsTo(&storage, true, &extra1, &extra2); + + // Storage should be allocated. + EXPECT_TRUE(storage.data()); + EXPECT_NE(0U, storage.size()); + + // Types should be changed to copyable strings. + EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]); + EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[1]); + + // names should be copied. + EXPECT_TRUE(storage.Contains(args.names()[0])); + EXPECT_TRUE(storage.Contains(args.names()[1])); + EXPECT_STREQ("arg1", args.names()[0]); + EXPECT_STREQ("arg2", args.names()[1]); + + // strings should be copied. + EXPECT_TRUE(storage.Contains(args.values()[0].as_string)); + EXPECT_TRUE(storage.Contains(args.values()[1].as_string)); + EXPECT_STREQ("Hello", args.values()[0].as_string); + EXPECT_STREQ("World", args.values()[1].as_string); + + // |extra1| and |extra2| should be copied. + EXPECT_NE(kExtra1, extra1); + EXPECT_NE(kExtra2, extra2); + EXPECT_TRUE(storage.Contains(extra1)); + EXPECT_TRUE(storage.Contains(extra2)); + EXPECT_STREQ(kExtra1, extra1); + EXPECT_STREQ(kExtra2, extra2); +} + +} // namespace trace_event +} // namespace base
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h index 9bac0061..53d8ca2 100644 --- a/base/trace_event/trace_event.h +++ b/base/trace_event/trace_event.h
@@ -22,6 +22,7 @@ #include "base/trace_event/builtin_categories.h" #include "base/trace_event/common/trace_event_common.h" #include "base/trace_event/heap_profiler.h" +#include "base/trace_event/trace_arguments.h" #include "base/trace_event/trace_category.h" #include "base/trace_event/trace_event_system_stats_monitor.h" #include "base/trace_event/trace_log.h" @@ -29,8 +30,7 @@ // By default, const char* argument values are assumed to have long-lived scope // and will not be copied. Use this macro to force a const char* to be copied. -#define TRACE_STR_COPY(str) \ - trace_event_internal::TraceStringWithCopy(str) +#define TRACE_STR_COPY(str) ::base::trace_event::TraceStringWithCopy(str) // DEPRECATED: do not use: Consider using the TRACE_ID_LOCAL macro instead. By // default, uint64_t ID argument values are not mangled with the Process ID in @@ -659,108 +659,6 @@ unsigned int id_flags_ = TRACE_EVENT_FLAG_HAS_ID; }; -// Simple union to store various types as unsigned long long. -union TraceValueUnion { - bool as_bool; - unsigned long long as_uint; - long long as_int; - double as_double; - const void* as_pointer; - const char* as_string; -}; - -// Simple container for const char* that should be copied instead of retained. -class TraceStringWithCopy { - public: - explicit TraceStringWithCopy(const char* str) : str_(str) {} - const char* str() const { return str_; } - private: - const char* str_; -}; - -// Define SetTraceValue for each allowed type. It stores the type and -// value in the return arguments. This allows this API to avoid declaring any -// structures so that it is portable to third_party libraries. -#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \ - arg_expression, \ - union_member, \ - value_type_id) \ - static inline void SetTraceValue( \ - actual_type arg, \ - unsigned char* type, \ - unsigned long long* value) { \ - TraceValueUnion type_value; \ - type_value.union_member = arg_expression; \ - *type = value_type_id; \ - *value = type_value.as_uint; \ - } -// Simpler form for int types that can be safely casted. -#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \ - value_type_id) \ - static inline void SetTraceValue( \ - actual_type arg, \ - unsigned char* type, \ - unsigned long long* value) { \ - *type = value_type_id; \ - *value = static_cast<unsigned long long>(arg); \ - } - -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long, TRACE_VALUE_TYPE_UINT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long, TRACE_VALUE_TYPE_INT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT) -INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT) -INTERNAL_DECLARE_SET_TRACE_VALUE(bool, arg, as_bool, TRACE_VALUE_TYPE_BOOL) -INTERNAL_DECLARE_SET_TRACE_VALUE(double, arg, as_double, - TRACE_VALUE_TYPE_DOUBLE) -INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, arg, as_pointer, - TRACE_VALUE_TYPE_POINTER) -INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, arg, as_string, - TRACE_VALUE_TYPE_STRING) -INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, arg.str(), - as_string, TRACE_VALUE_TYPE_COPY_STRING) - -#undef INTERNAL_DECLARE_SET_TRACE_VALUE -#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT - -// std::string version of SetTraceValue so that trace arguments can be strings. -static inline void SetTraceValue(const std::string& arg, - unsigned char* type, - unsigned long long* value) { - TraceValueUnion type_value; - type_value.as_string = arg.c_str(); - *type = TRACE_VALUE_TYPE_COPY_STRING; - *value = type_value.as_uint; -} - -// base::Time, base::TimeTicks, etc. versions of SetTraceValue to make it easier -// to trace these types. -static inline void SetTraceValue(const base::Time arg, - unsigned char* type, - unsigned long long* value) { - *type = TRACE_VALUE_TYPE_INT; - *value = arg.ToInternalValue(); -} - -static inline void SetTraceValue(const base::TimeTicks arg, - unsigned char* type, - unsigned long long* value) { - *type = TRACE_VALUE_TYPE_INT; - *value = arg.ToInternalValue(); -} - -static inline void SetTraceValue(const base::ThreadTicks arg, - unsigned char* type, - unsigned long long* value) { - *type = TRACE_VALUE_TYPE_INT; - *value = arg.ToInternalValue(); -} - // These functions all internally call // base::trace_event::TraceLog::GetInstance() then call the method with the same // name on it. This is used to reduce the generated machine code at each @@ -772,6 +670,81 @@ const char* name, const char* scope, unsigned long long id, + base::trace_event::TraceArguments* args, + unsigned int flags); + +base::trace_event::TraceEventHandle BASE_EXPORT +AddTraceEventWithBindId(char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + unsigned long long bind_id, + base::trace_event::TraceArguments* args, + unsigned int flags); + +base::trace_event::TraceEventHandle BASE_EXPORT +AddTraceEventWithProcessId(char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + int process_id, + base::trace_event::TraceArguments* args, + unsigned int flags); + +base::trace_event::TraceEventHandle BASE_EXPORT +AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + int thread_id, + const base::TimeTicks& timestamp, + base::trace_event::TraceArguments* args, + unsigned int flags); + +base::trace_event::TraceEventHandle BASE_EXPORT +AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + unsigned long long bind_id, + int thread_id, + const base::TimeTicks& timestamp, + base::trace_event::TraceArguments* args, + unsigned int flags); + +void BASE_EXPORT AddMetadataEvent(const unsigned char* category_group_enabled, + const char* name, + base::trace_event::TraceArguments* args, + unsigned int flags); + +int BASE_EXPORT GetNumTracesRecorded(); + +void BASE_EXPORT +UpdateTraceEventDuration(const unsigned char* category_group_enabled, + const char* name, + base::trace_event::TraceEventHandle handle); + +void BASE_EXPORT +UpdateTraceEventDurationExplicit(const unsigned char* category_group_enabled, + const char* name, + base::trace_event::TraceEventHandle handle, + const base::TimeTicks& now, + const base::ThreadTicks& thread_now); + +// TODO(898794): Remove these functions once all callers have been updated +// to use base::trace_event::Arguments instead. +base::trace_event::TraceEventHandle BASE_EXPORT +AddTraceEvent(char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, int num_args, const char* const* arg_names, const unsigned char* arg_types, @@ -856,27 +829,13 @@ convertable_values, unsigned int flags); -int BASE_EXPORT GetNumTracesRecorded(); - -void BASE_EXPORT -UpdateTraceEventDuration(const unsigned char* category_group_enabled, - const char* name, - base::trace_event::TraceEventHandle handle); - -void BASE_EXPORT -UpdateTraceEventDurationExplicit(const unsigned char* category_group_enabled, - const char* name, - base::trace_event::TraceEventHandle handle, - const base::TimeTicks& now, - const base::ThreadTicks& thread_now); - // These AddTraceEvent and AddTraceEventWithThreadIdAndTimestamp template // functions are defined here instead of in the macro, because the arg_values // could be temporary objects, such as std::string. In order to store // pointers to the internal c_str and pass through to the tracing API, // the arg_values must live throughout these procedures. -template <class ARG1_CONVERTABLE_TYPE> +template <class ARG1_TYPE> static inline base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( char phase, @@ -889,18 +848,15 @@ unsigned int flags, unsigned long long bind_id, const char* arg1_name, - std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val) { - const int num_args = 1; - unsigned char arg_types[1] = { TRACE_VALUE_TYPE_CONVERTABLE }; - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> - convertable_values[1] = {std::move(arg1_val)}; + ARG1_TYPE&& arg1_val) { + base::trace_event::TraceArguments args(arg1_name, + std::forward<ARG1_TYPE>(arg1_val)); return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, num_args, &arg1_name, arg_types, NULL, convertable_values, - flags); + timestamp, &args, flags); } -template <class ARG1_TYPE, class ARG2_CONVERTABLE_TYPE> +template <class ARG1_TYPE, class ARG2_TYPE> static inline base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( char phase, @@ -913,82 +869,15 @@ unsigned int flags, unsigned long long bind_id, const char* arg1_name, - const ARG1_TYPE& arg1_val, + ARG1_TYPE&& arg1_val, const char* arg2_name, - std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) { - const int num_args = 2; - const char* arg_names[2] = { arg1_name, arg2_name }; - - unsigned char arg_types[2]; - unsigned long long arg_values[2]; - SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); - arg_types[1] = TRACE_VALUE_TYPE_CONVERTABLE; - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> - convertable_values[2] = {nullptr, std::move(arg2_val)}; + ARG2_TYPE&& arg2_val) { + base::trace_event::TraceArguments args( + arg1_name, std::forward<ARG1_TYPE>(arg1_val), arg2_name, + std::forward<ARG2_TYPE>(arg2_val)); return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, num_args, arg_names, arg_types, arg_values, convertable_values, - flags); -} - -template <class ARG1_CONVERTABLE_TYPE, class ARG2_TYPE> -static inline base::trace_event::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val, - const char* arg2_name, - const ARG2_TYPE& arg2_val) { - const int num_args = 2; - const char* arg_names[2] = { arg1_name, arg2_name }; - - unsigned char arg_types[2]; - unsigned long long arg_values[2]; - arg_types[0] = TRACE_VALUE_TYPE_CONVERTABLE; - arg_values[0] = 0; - SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]); - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> - convertable_values[2] = {std::move(arg1_val), nullptr}; - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, num_args, arg_names, arg_types, arg_values, convertable_values, - flags); -} - -template <class ARG1_CONVERTABLE_TYPE, class ARG2_CONVERTABLE_TYPE> -static inline base::trace_event::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val, - const char* arg2_name, - std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) { - const int num_args = 2; - const char* arg_names[2] = { arg1_name, arg2_name }; - unsigned char arg_types[2] = - { TRACE_VALUE_TYPE_CONVERTABLE, TRACE_VALUE_TYPE_CONVERTABLE }; - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> - convertable_values[2] = {std::move(arg1_val), std::move(arg2_val)}; - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, num_args, arg_names, arg_types, NULL, convertable_values, - flags); + timestamp, &args, flags); } static inline base::trace_event::TraceEventHandle @@ -1004,7 +893,7 @@ unsigned long long bind_id) { return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, kZeroNumArgs, NULL, NULL, NULL, NULL, flags); + timestamp, nullptr, flags); } static inline base::trace_event::TraceEventHandle AddTraceEvent( @@ -1022,30 +911,7 @@ bind_id); } -template<class ARG1_TYPE> -static inline base::trace_event::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - const ARG1_TYPE& arg1_val) { - const int num_args = 1; - unsigned char arg_types[1]; - unsigned long long arg_values[1]; - SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, num_args, &arg1_name, arg_types, arg_values, NULL, flags); -} - -template<class ARG1_TYPE> +template <class ARG1_TYPE> static inline base::trace_event::TraceEventHandle AddTraceEvent( char phase, const unsigned char* category_group_enabled, @@ -1055,15 +921,15 @@ unsigned int flags, unsigned long long bind_id, const char* arg1_name, - const ARG1_TYPE& arg1_val) { + ARG1_TYPE&& arg1_val) { int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); base::TimeTicks now = TRACE_TIME_TICKS_NOW(); return AddTraceEventWithThreadIdAndTimestamp( phase, category_group_enabled, name, scope, id, thread_id, now, flags, - bind_id, arg1_name, arg1_val); + bind_id, arg1_name, std::forward<ARG1_TYPE>(arg1_val)); } -template <class ARG1_CONVERTABLE_TYPE> +template <class ARG1_TYPE, class ARG2_TYPE> static inline base::trace_event::TraceEventHandle AddTraceEvent( char phase, const unsigned char* category_group_enabled, @@ -1073,153 +939,26 @@ unsigned int flags, unsigned long long bind_id, const char* arg1_name, - std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val) { - int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - base::TimeTicks now = TRACE_TIME_TICKS_NOW(); - return AddTraceEventWithThreadIdAndTimestamp( - phase, category_group_enabled, name, scope, id, thread_id, now, flags, - bind_id, arg1_name, std::move(arg1_val)); -} - -template<class ARG1_TYPE, class ARG2_TYPE> -static inline base::trace_event::TraceEventHandle -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - const ARG1_TYPE& arg1_val, + ARG1_TYPE&& arg1_val, const char* arg2_name, - const ARG2_TYPE& arg2_val) { - const int num_args = 2; - const char* arg_names[2] = { arg1_name, arg2_name }; - unsigned char arg_types[2]; - unsigned long long arg_values[2]; - SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); - SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]); - return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( - phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, num_args, arg_names, arg_types, arg_values, NULL, flags); -} - -template <class ARG1_CONVERTABLE_TYPE, class ARG2_TYPE> -static inline base::trace_event::TraceEventHandle AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val, - const char* arg2_name, - const ARG2_TYPE& arg2_val) { + ARG2_TYPE&& arg2_val) { int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); base::TimeTicks now = TRACE_TIME_TICKS_NOW(); return AddTraceEventWithThreadIdAndTimestamp( phase, category_group_enabled, name, scope, id, thread_id, now, flags, - bind_id, arg1_name, std::move(arg1_val), arg2_name, arg2_val); -} - -template <class ARG1_TYPE, class ARG2_CONVERTABLE_TYPE> -static inline base::trace_event::TraceEventHandle AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - const ARG1_TYPE& arg1_val, - const char* arg2_name, - std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) { - int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - base::TimeTicks now = TRACE_TIME_TICKS_NOW(); - return AddTraceEventWithThreadIdAndTimestamp( - phase, category_group_enabled, name, scope, id, thread_id, now, flags, - bind_id, arg1_name, arg1_val, arg2_name, std::move(arg2_val)); -} - -template <class ARG1_CONVERTABLE_TYPE, class ARG2_CONVERTABLE_TYPE> -static inline base::trace_event::TraceEventHandle AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val, - const char* arg2_name, - std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) { - int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - base::TimeTicks now = TRACE_TIME_TICKS_NOW(); - return AddTraceEventWithThreadIdAndTimestamp( - phase, category_group_enabled, name, scope, id, thread_id, now, flags, - bind_id, arg1_name, std::move(arg1_val), arg2_name, std::move(arg2_val)); -} - -template<class ARG1_TYPE, class ARG2_TYPE> -static inline base::trace_event::TraceEventHandle AddTraceEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned int flags, - unsigned long long bind_id, - const char* arg1_name, - const ARG1_TYPE& arg1_val, - const char* arg2_name, - const ARG2_TYPE& arg2_val) { - int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); - base::TimeTicks now = TRACE_TIME_TICKS_NOW(); - return AddTraceEventWithThreadIdAndTimestamp( - phase, category_group_enabled, name, scope, id, thread_id, now, flags, - bind_id, arg1_name, arg1_val, arg2_name, arg2_val); -} - -template <class ARG1_CONVERTABLE_TYPE> -static inline void AddMetadataEvent( - const unsigned char* category_group_enabled, - const char* event_name, - const char* arg_name, - std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg_value) { - const char* arg_names[1] = {arg_name}; - unsigned char arg_types[1] = {TRACE_VALUE_TYPE_CONVERTABLE}; - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> - convertable_values[1] = {std::move(arg_value)}; - trace_event_internal::AddMetadataEvent(category_group_enabled, event_name, - 1, // num_args - arg_names, arg_types, - nullptr, // arg_values - convertable_values, - TRACE_EVENT_FLAG_NONE); + bind_id, arg1_name, std::forward<ARG1_TYPE>(arg1_val), arg2_name, + std::forward<ARG2_TYPE>(arg2_val)); } template <class ARG1_TYPE> static void AddMetadataEvent(const unsigned char* category_group_enabled, const char* event_name, const char* arg_name, - const ARG1_TYPE& arg_val) { - const int num_args = 1; - const char* arg_names[1] = {arg_name}; - unsigned char arg_types[1]; - unsigned long long arg_values[1]; - SetTraceValue(arg_val, &arg_types[0], &arg_values[0]); - - trace_event_internal::AddMetadataEvent( - category_group_enabled, event_name, num_args, arg_names, arg_types, - arg_values, nullptr, TRACE_EVENT_FLAG_NONE); + ARG1_TYPE&& arg_val) { + base::trace_event::TraceArguments args(arg_name, + std::forward<ARG1_TYPE>(arg_val)); + trace_event_internal::AddMetadataEvent(category_group_enabled, event_name, + &args, TRACE_EVENT_FLAG_NONE); } // Used by TRACE_EVENTx macros. Do not use directly.
diff --git a/base/trace_event/trace_event_android.cc b/base/trace_event/trace_event_android.cc index 30d9c74..a1e51e8 100644 --- a/base/trace_event/trace_event_android.cc +++ b/base/trace_event/trace_event_android.cc
@@ -39,32 +39,25 @@ } } -void WriteEvent( - char phase, - const char* category_group, - const char* name, - unsigned long long id, - const char** arg_names, - const unsigned char* arg_types, - const TraceEvent::TraceValue* arg_values, - const std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags) { +void WriteEvent(char phase, + const char* category_group, + const char* name, + unsigned long long id, + const TraceArguments& args, + unsigned int flags) { std::string out = StringPrintf("%c|%d|%s", phase, getpid(), name); if (flags & TRACE_EVENT_FLAG_HAS_ID) StringAppendF(&out, "-%" PRIx64, static_cast<uint64_t>(id)); out += '|'; - for (int i = 0; i < kTraceMaxNumArgs && arg_names[i]; - ++i) { + const char* const* arg_names = args.names(); + for (size_t i = 0; i < args.size() && arg_names[i]; ++i) { if (i) out += ';'; out += arg_names[i]; out += '='; std::string::size_type value_start = out.length(); - if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) - convertable_values[i]->AppendAsTraceFormat(&out); - else - TraceEvent::AppendValueAsJSON(arg_types[i], arg_values[i], &out); + args.values()[i].AppendAsJSON(args.types()[i], &out); // Remove the quotes which may confuse the atrace script. ReplaceSubstringsAfterOffset(&out, value_start, "\\\"", "'"); @@ -147,43 +140,35 @@ switch (phase_) { case TRACE_EVENT_PHASE_BEGIN: - WriteEvent('B', category_group, name_, id_, - arg_names_, arg_types_, arg_values_, convertable_values_, - flags_); + WriteEvent('B', category_group, name_, id_, args_, flags_); break; case TRACE_EVENT_PHASE_COMPLETE: - WriteEvent(duration_.ToInternalValue() == -1 ? 'B' : 'E', - category_group, name_, id_, - arg_names_, arg_types_, arg_values_, convertable_values_, - flags_); + WriteEvent(duration_.ToInternalValue() == -1 ? 'B' : 'E', category_group, + name_, id_, args_, flags_); break; case TRACE_EVENT_PHASE_END: // Though a single 'E' is enough, here append pid, name and // category_group etc. So that unpaired events can be found easily. - WriteEvent('E', category_group, name_, id_, - arg_names_, arg_types_, arg_values_, convertable_values_, - flags_); + WriteEvent('E', category_group, name_, id_, args_, flags_); break; case TRACE_EVENT_PHASE_INSTANT: // Simulate an instance event with a pair of begin/end events. - WriteEvent('B', category_group, name_, id_, - arg_names_, arg_types_, arg_values_, convertable_values_, - flags_); + WriteEvent('B', category_group, name_, id_, args_, flags_); WriteToATrace(g_atrace_fd, "E", 1); break; case TRACE_EVENT_PHASE_COUNTER: - for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { - DCHECK(arg_types_[i] == TRACE_VALUE_TYPE_INT); - std::string out = base::StringPrintf( - "C|%d|%s-%s", getpid(), name_, arg_names_[i]); + for (size_t i = 0; i < arg_size() && arg_name(i); ++i) { + DCHECK(arg_type(i) == TRACE_VALUE_TYPE_INT); + std::string out = + base::StringPrintf("C|%d|%s-%s", getpid(), name_, arg_name(i)); if (flags_ & TRACE_EVENT_FLAG_HAS_ID) StringAppendF(&out, "-%" PRIx64, static_cast<uint64_t>(id_)); - StringAppendF(&out, "|%d|%s", - static_cast<int>(arg_values_[i].as_int), category_group); + StringAppendF(&out, "|%d|%s", static_cast<int>(arg_value(i).as_int), + category_group); WriteToATrace(g_atrace_fd, out.c_str(), out.size()); } break;
diff --git a/base/trace_event/trace_event_etw_export_win.cc b/base/trace_event/trace_event_etw_export_win.cc index 89059da3..e2c4f80d 100644 --- a/base/trace_event/trace_event_etw_export_win.cc +++ b/base/trace_event/trace_event_etw_export_win.cc
@@ -168,16 +168,11 @@ } // static -void TraceEventETWExport::AddEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - const std::unique_ptr<ConvertableToTraceFormat>* convertable_values) { +void TraceEventETWExport::AddEvent(char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + const TraceArguments* args) { // We bail early in case exporting is disabled or no consumer is listening. auto* instance = GetInstance(); if (!instance || !instance->etw_export_enabled_ || !EventEnabledChromeEvent()) @@ -255,26 +250,22 @@ } std::string arg_values_string[3]; - for (int i = 0; i < num_args; i++) { - if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) { + size_t num_args = args ? args->size() : 0; + for (size_t i = 0; i < num_args; i++) { + if (args->types()[i] == TRACE_VALUE_TYPE_CONVERTABLE) { // Temporarily do nothing here. This function consumes 1/3 to 1/2 of // *total* process CPU time when ETW tracing, and many of the strings // created exceed WPA's 4094 byte limit and are shown as: // "Unable to parse data". See crbug.com/488257 - // convertable_values[i]->AppendAsTraceFormat(arg_values_string + i); } else { - TraceEvent::TraceValue trace_event; - trace_event.as_uint = arg_values[i]; - TraceEvent::AppendValueAsJSON(arg_types[i], trace_event, - arg_values_string + i); + args->values()[i].AppendAsJSON(args->types()[i], arg_values_string + i); } } EventWriteChromeEvent( - name, phase_string, num_args > 0 ? arg_names[0] : "", - arg_values_string[0].c_str(), num_args > 1 ? arg_names[1] : "", - arg_values_string[1].c_str(), num_args > 2 ? arg_names[2] : "", - arg_values_string[2].c_str()); + name, phase_string, num_args > 0 ? args->names()[0] : "", + arg_values_string[0].c_str(), num_args > 1 ? args->names()[1] : "", + arg_values_string[1].c_str(), "", ""); } // static
diff --git a/base/trace_event/trace_event_etw_export_win.h b/base/trace_event/trace_event_etw_export_win.h index 345e87b..ac19553 100644 --- a/base/trace_event/trace_event_etw_export_win.h +++ b/base/trace_event/trace_event_etw_export_win.h
@@ -47,16 +47,11 @@ // Exports an event to ETW. This is mainly used in // TraceLog::AddTraceEventWithThreadIdAndTimestamp to export internal events. - static void AddEvent( - char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - const std::unique_ptr<ConvertableToTraceFormat>* convertable_values); + static void AddEvent(char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + const TraceArguments* args); // Exports an ETW event that marks the end of a complete event. static void AddCompleteEndEvent(const char* name);
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc index 66b69c3d..ee3e21d 100644 --- a/base/trace_event/trace_event_impl.cc +++ b/base/trace_event/trace_event_impl.cc
@@ -22,25 +22,6 @@ namespace base { namespace trace_event { -namespace { - -size_t GetAllocLength(const char* str) { return str ? strlen(str) + 1 : 0; } - -// Copies |*member| into |*buffer|, sets |*member| to point to this new -// location, and then advances |*buffer| by the amount written. -void CopyTraceEventParameter(char** buffer, - const char** member, - const char* end) { - if (*member) { - size_t written = strlcpy(*buffer, *member, end - *buffer) + 1; - DCHECK_LE(static_cast<int>(written), end - *buffer); - *member = *buffer; - *buffer += written; - } -} - -} // namespace - bool ConvertableToTraceFormat::AppendToProto(ProtoAppender* appender) { return false; } @@ -49,48 +30,19 @@ static_assert(trace_event_internal::kGlobalScope == nullptr, "Invalid TraceEvent::scope default initializer value"); -TraceEvent::TraceEvent() { - for (int i = 0; i < kTraceMaxNumArgs; ++i) { - arg_values_[i].as_uint = 0u; - arg_names_[i] = nullptr; - arg_types_[i] = TRACE_VALUE_TYPE_UINT; - } -} +TraceEvent::TraceEvent() = default; -TraceEvent::~TraceEvent() = default; - -TraceEvent::TraceEvent(TraceEvent&& other) noexcept = default; - -#if !defined(__clang__) -// Clang will crash at runtime when trying to compile the line below -// with coverage instrumentation enabled (https://crbug.com/908937) -TraceEvent& TraceEvent::operator=(TraceEvent&& other) noexcept = default; -#else // defined(__clang__) -TraceEvent& TraceEvent::operator=(TraceEvent&& other) noexcept { - if (this != &other) { - this->~TraceEvent(); - new (this) TraceEvent(std::move(other)); - } - return *this; -} -#endif // defined(__clang__) - -TraceEvent::TraceEvent( - int thread_id, - TimeTicks timestamp, - ThreadTicks thread_timestamp, - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned long long bind_id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags) +TraceEvent::TraceEvent(int thread_id, + TimeTicks timestamp, + ThreadTicks thread_timestamp, + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + unsigned long long bind_id, + TraceArguments* args, + unsigned int flags) : timestamp_(timestamp), thread_timestamp_(thread_timestamp), scope_(scope), @@ -101,121 +53,33 @@ flags_(flags), bind_id_(bind_id), phase_(phase) { - InitArgs(num_args, arg_names, arg_types, arg_values, convertable_values, - flags); + InitArgs(args); } -void TraceEvent::InitArgs( - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags) { - // Clamp num_args since it may have been set by a third_party library. - num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args; - int i = 0; - for (; i < num_args; ++i) { - arg_names_[i] = arg_names[i]; - arg_types_[i] = arg_types[i]; +TraceEvent::~TraceEvent() = default; - if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) { - convertable_values_[i] = std::move(convertable_values[i]); - } else { - arg_values_[i].as_uint = arg_values[i]; - convertable_values_[i].reset(); - } - } - for (; i < kTraceMaxNumArgs; ++i) { - arg_names_[i] = nullptr; - arg_values_[i].as_uint = 0u; - convertable_values_[i].reset(); - arg_types_[i] = TRACE_VALUE_TYPE_UINT; - } - - bool copy = !!(flags & TRACE_EVENT_FLAG_COPY); - size_t alloc_size = 0; - if (copy) { - alloc_size += GetAllocLength(name_) + GetAllocLength(scope_); - for (i = 0; i < num_args; ++i) { - alloc_size += GetAllocLength(arg_names_[i]); - if (arg_types_[i] == TRACE_VALUE_TYPE_STRING) - arg_types_[i] = TRACE_VALUE_TYPE_COPY_STRING; - } - } - - bool arg_is_copy[kTraceMaxNumArgs]; - for (i = 0; i < num_args; ++i) { - // No copying of convertable types, we retain ownership. - if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) - continue; - - // We only take a copy of arg_vals if they are of type COPY_STRING. - arg_is_copy[i] = (arg_types_[i] == TRACE_VALUE_TYPE_COPY_STRING); - if (arg_is_copy[i]) - alloc_size += GetAllocLength(arg_values_[i].as_string); - } - - if (alloc_size) { - parameter_copy_storage_.reset(new std::string); - parameter_copy_storage_->resize(alloc_size); - char* ptr = base::data(*parameter_copy_storage_); - const char* end = ptr + alloc_size; - if (copy) { - CopyTraceEventParameter(&ptr, &name_, end); - CopyTraceEventParameter(&ptr, &scope_, end); - for (i = 0; i < num_args; ++i) { - CopyTraceEventParameter(&ptr, &arg_names_[i], end); - } - } - for (i = 0; i < num_args; ++i) { - if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) - continue; - if (arg_is_copy[i]) - CopyTraceEventParameter(&ptr, &arg_values_[i].as_string, end); - } - DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end; - } -} +TraceEvent::TraceEvent(TraceEvent&& other) noexcept = default; +TraceEvent& TraceEvent::operator=(TraceEvent&& other) noexcept = default; void TraceEvent::Reset() { // Only reset fields that won't be initialized in Reset(int, ...), or that may // hold references to other objects. duration_ = TimeDelta::FromInternalValue(-1); - - // The following pointers might point into parameter_copy_storage_ so - // must be reset to nullptr first. - for (int i = 0; i < kTraceMaxNumArgs; ++i) { - arg_names_[i] = nullptr; - arg_values_[i].as_uint = 0u; - arg_types_[i] = TRACE_VALUE_TYPE_UINT; - } - scope_ = nullptr; - name_ = nullptr; - - // It is now safe to reset the storage area. - parameter_copy_storage_.reset(); - - for (int i = 0; i < kTraceMaxNumArgs; ++i) - convertable_values_[i].reset(); + args_.Reset(); + parameter_copy_storage_.Reset(); } -void TraceEvent::Reset( - int thread_id, - TimeTicks timestamp, - ThreadTicks thread_timestamp, - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned long long bind_id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags) { +void TraceEvent::Reset(int thread_id, + TimeTicks timestamp, + ThreadTicks thread_timestamp, + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + unsigned long long bind_id, + TraceArguments* args, + unsigned int flags) { Reset(); timestamp_ = timestamp; thread_timestamp_ = thread_timestamp; @@ -228,8 +92,14 @@ bind_id_ = bind_id; phase_ = phase; - InitArgs(num_args, arg_names, arg_types, arg_values, convertable_values, - flags); + InitArgs(args); +} + +void TraceEvent::InitArgs(TraceArguments* args) { + if (args) + args_ = std::move(*args); + args_.CopyStringsTo(¶meter_copy_storage_, + !!(flags_ & TRACE_EVENT_FLAG_COPY), &name_, &scope_); } void TraceEvent::UpdateDuration(const TimeTicks& now, @@ -245,80 +115,12 @@ void TraceEvent::EstimateTraceMemoryOverhead( TraceEventMemoryOverhead* overhead) { - overhead->Add(TraceEventMemoryOverhead::kTraceEvent, sizeof(*this)); + overhead->Add(TraceEventMemoryOverhead::kTraceEvent, + parameter_copy_storage_.EstimateTraceMemoryOverhead()); - if (parameter_copy_storage_) - overhead->AddString(*parameter_copy_storage_); - - for (size_t i = 0; i < kTraceMaxNumArgs; ++i) { - if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) - convertable_values_[i]->EstimateTraceMemoryOverhead(overhead); - } -} - -// static -void TraceEvent::AppendValueAsJSON(unsigned char type, - TraceEvent::TraceValue value, - std::string* out) { - switch (type) { - case TRACE_VALUE_TYPE_BOOL: - *out += value.as_bool ? "true" : "false"; - break; - case TRACE_VALUE_TYPE_UINT: - StringAppendF(out, "%" PRIu64, static_cast<uint64_t>(value.as_uint)); - break; - case TRACE_VALUE_TYPE_INT: - StringAppendF(out, "%" PRId64, static_cast<int64_t>(value.as_int)); - break; - case TRACE_VALUE_TYPE_DOUBLE: { - // FIXME: base/json/json_writer.cc is using the same code, - // should be made into a common method. - std::string real; - double val = value.as_double; - if (std::isfinite(val)) { - real = NumberToString(val); - // Ensure that the number has a .0 if there's no decimal or 'e'. This - // makes sure that when we read the JSON back, it's interpreted as a - // real rather than an int. - if (real.find('.') == std::string::npos && - real.find('e') == std::string::npos && - real.find('E') == std::string::npos) { - real.append(".0"); - } - // The JSON spec requires that non-integer values in the range (-1,1) - // have a zero before the decimal point - ".52" is not valid, "0.52" is. - if (real[0] == '.') { - real.insert(0, "0"); - } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') { - // "-.1" bad "-0.1" good - real.insert(1, "0"); - } - } else if (std::isnan(val)){ - // The JSON spec doesn't allow NaN and Infinity (since these are - // objects in EcmaScript). Use strings instead. - real = "\"NaN\""; - } else if (val < 0) { - real = "\"-Infinity\""; - } else { - real = "\"Infinity\""; - } - StringAppendF(out, "%s", real.c_str()); - break; - } - case TRACE_VALUE_TYPE_POINTER: - // JSON only supports double and int numbers. - // So as not to lose bits from a 64-bit pointer, output as a hex string. - StringAppendF( - out, "\"0x%" PRIx64 "\"", - static_cast<uint64_t>(reinterpret_cast<uintptr_t>(value.as_pointer))); - break; - case TRACE_VALUE_TYPE_STRING: - case TRACE_VALUE_TYPE_COPY_STRING: - EscapeJSONString(value.as_string ? value.as_string : "NULL", true, out); - break; - default: - NOTREACHED() << "Don't know how to print this value"; - break; + for (size_t i = 0; i < arg_size(); ++i) { + if (arg_type(i) == TRACE_VALUE_TYPE_CONVERTABLE) + arg_value(i).as_convertable->EstimateTraceMemoryOverhead(overhead); } } @@ -353,7 +155,7 @@ // approach ArgumentNameFilterPredicate argument_name_filter_predicate; bool strip_args = - arg_names_[0] && !argument_filter_predicate.is_null() && + arg_size() > 0 && arg_name(0) && !argument_filter_predicate.is_null() && !argument_filter_predicate.Run(category_group_name, name_, &argument_name_filter_predicate); @@ -362,19 +164,16 @@ } else { *out += "{"; - for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { + for (size_t i = 0; i < arg_size() && arg_name(i); ++i) { if (i > 0) *out += ","; *out += "\""; - *out += arg_names_[i]; + *out += arg_name(i); *out += "\":"; if (argument_name_filter_predicate.is_null() || - argument_name_filter_predicate.Run(arg_names_[i])) { - if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) - convertable_values_[i]->AppendAsTraceFormat(out); - else - AppendValueAsJSON(arg_types_[i], arg_values_[i], out); + argument_name_filter_predicate.Run(arg_name(i))) { + arg_value(i).AppendAsJSON(arg_type(i), out); } else { *out += "\"__stripped__\""; } @@ -475,19 +274,14 @@ *out << name_ << "["; *out << TraceLog::GetCategoryGroupName(category_group_enabled_); *out << "]"; - if (arg_names_[0]) { + if (arg_size() > 0 && arg_name(0)) { *out << ", {"; - for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { + for (size_t i = 0; i < arg_size() && arg_name(i); ++i) { if (i > 0) *out << ", "; - *out << arg_names_[i] << ":"; + *out << arg_name(i) << ":"; std::string value_as_text; - - if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) - convertable_values_[i]->AppendAsTraceFormat(&value_as_text); - else - AppendValueAsJSON(arg_types_[i], arg_values_[i], &value_as_text); - + arg_value(i).AppendAsJSON(arg_type(i), &value_as_text); *out << value_as_text; } *out << "}";
diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h index f984091..afb7379 100644 --- a/base/trace_event/trace_event_impl.h +++ b/base/trace_event/trace_event_impl.h
@@ -24,6 +24,7 @@ #include "base/synchronization/lock.h" #include "base/threading/thread_local.h" #include "base/trace_event/common/trace_event_common.h" +#include "base/trace_event/trace_arguments.h" #include "base/trace_event/trace_event_memory_overhead.h" #include "build/build_config.h" @@ -37,48 +38,6 @@ ArgumentNameFilterPredicate*)> ArgumentFilterPredicate; -// For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided -// class must implement this interface. -class BASE_EXPORT ConvertableToTraceFormat { - public: - ConvertableToTraceFormat() = default; - virtual ~ConvertableToTraceFormat() = default; - - // Append the class info to the provided |out| string. The appended - // data must be a valid JSON object. Strings must be properly quoted, and - // escaped. There is no processing applied to the content after it is - // appended. - virtual void AppendAsTraceFormat(std::string* out) const = 0; - - // Append the class info directly into the Perfetto-defined proto - // format; this is attempted first and if this returns true, - // AppendAsTraceFormat is not called. The ProtoAppender interface - // acts as a bridge to avoid proto/Perfetto dependencies in base. - class BASE_EXPORT ProtoAppender { - public: - virtual ~ProtoAppender() = default; - - virtual void AddBuffer(uint8_t* begin, uint8_t* end) = 0; - // Copy all of the previous buffers registered with AddBuffer - // into the proto, with the given |field_id|. - virtual size_t Finalize(uint32_t field_id) = 0; - }; - virtual bool AppendToProto(ProtoAppender* appender); - - virtual void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead); - - std::string ToString() const { - std::string result; - AppendAsTraceFormat(&result); - return result; - } - - private: - DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormat); -}; - -const int kTraceMaxNumArgs = 2; - struct TraceEventHandle { uint32_t chunk_seq; // These numbers of bits must be kept consistent with @@ -90,14 +49,8 @@ class BASE_EXPORT TraceEvent { public: - union TraceValue { - bool as_bool; - unsigned long long as_uint; - long long as_int; - double as_double; - const void* as_pointer; - const char* as_string; - }; + // TODO(898794): Remove once all users have been updated. + using TraceValue = base::trace_event::TraceValue; TraceEvent(); @@ -110,11 +63,7 @@ const char* scope, unsigned long long id, unsigned long long bind_id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, + TraceArguments* args, unsigned int flags); ~TraceEvent(); @@ -142,11 +91,7 @@ const char* scope, unsigned long long id, unsigned long long bind_id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, + TraceArguments* args, unsigned int flags); void UpdateDuration(const TimeTicks& now, const ThreadTicks& thread_now); @@ -159,9 +104,12 @@ const ArgumentFilterPredicate& argument_filter_predicate) const; void AppendPrettyPrinted(std::ostringstream* out) const; + // TODO(898794): Remove once caller has been updated. static void AppendValueAsJSON(unsigned char type, TraceValue value, - std::string* out); + std::string* out) { + value.AppendAsJSON(type, out); + } TimeTicks timestamp() const { return timestamp_; } ThreadTicks thread_timestamp() const { return thread_timestamp_; } @@ -176,8 +124,8 @@ unsigned long long bind_id() const { return bind_id_; } // Exposed for unittesting: - const std::string* parameter_copy_storage() const { - return parameter_copy_storage_.get(); + const StringStorage& parameter_copy_storage() const { + return parameter_copy_storage_; } const unsigned char* category_group_enabled() const { @@ -186,12 +134,17 @@ const char* name() const { return name_; } - unsigned char arg_type(size_t index) const { return arg_types_[index]; } - const char* arg_name(size_t index) const { return arg_names_[index]; } - const TraceValue& arg_value(size_t index) const { return arg_values_[index]; } + size_t arg_size() const { return args_.size(); } + unsigned char arg_type(size_t index) const { return args_.types()[index]; } + const char* arg_name(size_t index) const { return args_.names()[index]; } + const TraceValue& arg_value(size_t index) const { + return args_.values()[index]; + } ConvertableToTraceFormat* arg_convertible_value(size_t index) { - return convertable_values_[index].get(); + return (arg_type(index) == TRACE_VALUE_TYPE_CONVERTABLE) + ? arg_value(index).as_convertable + : nullptr; } #if defined(OS_ANDROID) @@ -199,12 +152,7 @@ #endif private: - void InitArgs(int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<ConvertableToTraceFormat>* convertable_values, - unsigned int flags); + void InitArgs(TraceArguments* args); // Note: these are ordered by size (largest first) for optimal packing. TimeTicks timestamp_ = TimeTicks(); @@ -218,13 +166,10 @@ // The equivalence is checked with a static_assert() in trace_event_impl.cc. const char* scope_ = nullptr; unsigned long long id_ = 0u; - TraceValue arg_values_[kTraceMaxNumArgs]; - const char* arg_names_[kTraceMaxNumArgs]; - std::unique_ptr<ConvertableToTraceFormat> - convertable_values_[kTraceMaxNumArgs]; const unsigned char* category_group_enabled_ = nullptr; const char* name_ = nullptr; - std::unique_ptr<std::string> parameter_copy_storage_; + StringStorage parameter_copy_storage_; + TraceArguments args_; // Depending on TRACE_EVENT_FLAG_HAS_PROCESS_ID the event will have either: // tid: thread_id_, pid: current_process_id (default case). // tid: -1, pid: process_id_ (when flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID). @@ -234,7 +179,6 @@ }; unsigned int flags_ = 0; unsigned long long bind_id_ = 0; - unsigned char arg_types_[kTraceMaxNumArgs]; char phase_ = TRACE_EVENT_PHASE_BEGIN; DISALLOW_COPY_AND_ASSIGN(TraceEvent);
diff --git a/base/trace_event/trace_event_unittest.cc b/base/trace_event/trace_event_unittest.cc index 4b1c939..f80752a 100644 --- a/base/trace_event/trace_event_unittest.cc +++ b/base/trace_event/trace_event_unittest.cc
@@ -1698,10 +1698,10 @@ ASSERT_TRUE(event2); EXPECT_STREQ("name1", event1->name()); EXPECT_STREQ("name2", event2->name()); - EXPECT_TRUE(event1->parameter_copy_storage() != nullptr); - EXPECT_TRUE(event2->parameter_copy_storage() != nullptr); - EXPECT_GT(event1->parameter_copy_storage()->size(), 0u); - EXPECT_GT(event2->parameter_copy_storage()->size(), 0u); + EXPECT_FALSE(event1->parameter_copy_storage().empty()); + EXPECT_FALSE(event2->parameter_copy_storage().empty()); + EXPECT_GT(event1->parameter_copy_storage().size(), 0u); + EXPECT_GT(event2->parameter_copy_storage().size(), 0u); EndTraceAndFlush(); } @@ -1731,8 +1731,8 @@ ASSERT_TRUE(event2); EXPECT_STREQ("name1", event1->name()); EXPECT_STREQ("name2", event2->name()); - EXPECT_TRUE(event1->parameter_copy_storage() == nullptr); - EXPECT_TRUE(event2->parameter_copy_storage() == nullptr); + EXPECT_TRUE(event1->parameter_copy_storage().empty()); + EXPECT_TRUE(event2->parameter_copy_storage().empty()); EndTraceAndFlush(); } }
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc index a5308ea..c8b31a15 100644 --- a/base/trace_event/trace_log.cc +++ b/base/trace_event/trace_log.cc
@@ -107,19 +107,14 @@ if (!trace_event) return; - int num_args = 1; - unsigned char arg_type; - unsigned long long arg_value; - ::trace_event_internal::SetTraceValue(value, &arg_type, &arg_value); - + TraceArguments args(arg_name, value); trace_event->Reset( thread_id, TimeTicks(), ThreadTicks(), TRACE_EVENT_PHASE_METADATA, CategoryRegistry::kCategoryMetadata->state_ptr(), metadata_name, trace_event_internal::kGlobalScope, // scope trace_event_internal::kNoId, // id trace_event_internal::kNoId, // bind_id - num_args, &arg_name, &arg_type, &arg_value, nullptr, - TRACE_EVENT_FLAG_NONE); + &args, TRACE_EVENT_FLAG_NONE); } class AutoThreadLocalBoolean { @@ -328,14 +323,13 @@ // find the generation mismatch and delete this buffer soon. } -void TraceLog::SetAddTraceEventOverride( - const AddTraceEventOverrideCallback& override, - const OnFlushCallback& on_flush_callback) { - subtle::NoBarrier_Store(&trace_event_override_, - reinterpret_cast<subtle::AtomicWord>(override)); - subtle::NoBarrier_Store( - &on_flush_callback_, - reinterpret_cast<subtle::AtomicWord>(on_flush_callback)); +void TraceLog::SetAddTraceEventOverrides( + const AddTraceEventOverrideCallback& add_event_override, + const OnFlushCallback& on_flush_callback, + const UpdateDurationCallback& update_duration_callback) { + add_trace_event_override_.store(add_event_override); + on_flush_callback_.store(on_flush_callback); + update_duration_callback_.store(update_duration_callback); } struct TraceLog::RegisteredAsyncObserver { @@ -380,8 +374,6 @@ thread_shared_chunk_index_(0), generation_(0), use_worker_thread_(false), - trace_event_override_(0), - on_flush_callback_(0), filter_factory_for_testing_(nullptr) { CategoryRegistry::Initialize(); @@ -1025,8 +1017,7 @@ // This will flush the thread local buffer. delete thread_local_event_buffer_.Get(); - auto on_flush_callback = reinterpret_cast<OnFlushCallback>( - subtle::NoBarrier_Load(&on_flush_callback_)); + auto on_flush_callback = on_flush_callback_.load(std::memory_order_relaxed); if (on_flush_callback) { on_flush_callback(); } @@ -1090,21 +1081,12 @@ unsigned int flags) { int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); base::TimeTicks now = TRACE_TIME_TICKS_NOW(); + TraceArguments args(num_args, arg_names, arg_types, arg_values, + convertable_values); return AddTraceEventWithThreadIdAndTimestamp( - phase, - category_group_enabled, - name, - scope, - id, + phase, category_group_enabled, name, scope, id, trace_event_internal::kNoId, // bind_id - thread_id, - now, - num_args, - arg_names, - arg_types, - arg_values, - convertable_values, - flags); + thread_id, now, &args, flags); } TraceEventHandle TraceLog::AddTraceEventWithBindId( @@ -1122,21 +1104,11 @@ unsigned int flags) { int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); base::TimeTicks now = TRACE_TIME_TICKS_NOW(); + TraceArguments args(num_args, arg_names, arg_types, arg_values, + convertable_values); return AddTraceEventWithThreadIdAndTimestamp( - phase, - category_group_enabled, - name, - scope, - id, - bind_id, - thread_id, - now, - num_args, - arg_names, - arg_types, - arg_values, - convertable_values, - flags | TRACE_EVENT_FLAG_HAS_CONTEXT_ID); + phase, category_group_enabled, name, scope, id, bind_id, thread_id, now, + &args, flags | TRACE_EVENT_FLAG_HAS_CONTEXT_ID); } TraceEventHandle TraceLog::AddTraceEventWithProcessId( @@ -1153,21 +1125,12 @@ std::unique_ptr<ConvertableToTraceFormat>* convertable_values, unsigned int flags) { base::TimeTicks now = TRACE_TIME_TICKS_NOW(); + TraceArguments args(num_args, arg_names, arg_types, arg_values, + convertable_values); return AddTraceEventWithThreadIdAndTimestamp( - phase, - category_group_enabled, - name, - scope, - id, + phase, category_group_enabled, name, scope, id, trace_event_internal::kNoId, // bind_id - process_id, - now, - num_args, - arg_names, - arg_types, - arg_values, - convertable_values, - flags | TRACE_EVENT_FLAG_HAS_PROCESS_ID); + process_id, now, &args, flags | TRACE_EVENT_FLAG_HAS_PROCESS_ID); } // Handle legacy calls to AddTraceEventWithThreadIdAndTimestamp @@ -1186,21 +1149,78 @@ const unsigned long long* arg_values, std::unique_ptr<ConvertableToTraceFormat>* convertable_values, unsigned int flags) { + TraceArguments args(num_args, arg_names, arg_types, arg_values, + convertable_values); return AddTraceEventWithThreadIdAndTimestamp( - phase, - category_group_enabled, - name, - scope, - id, + phase, category_group_enabled, name, scope, id, trace_event_internal::kNoId, // bind_id - thread_id, - timestamp, - num_args, - arg_names, - arg_types, - arg_values, - convertable_values, - flags); + thread_id, timestamp, &args, flags); +} + +TraceEventHandle TraceLog::AddTraceEvent( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + TraceArguments* args, + unsigned int flags) { + int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); + base::TimeTicks now = TRACE_TIME_TICKS_NOW(); + return AddTraceEventWithThreadIdAndTimestamp( + phase, category_group_enabled, name, scope, id, + trace_event_internal::kNoId, // bind_id + thread_id, now, args, flags); +} + +TraceEventHandle TraceLog::AddTraceEventWithBindId( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + unsigned long long bind_id, + TraceArguments* args, + unsigned int flags) { + int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); + base::TimeTicks now = TRACE_TIME_TICKS_NOW(); + return AddTraceEventWithThreadIdAndTimestamp( + phase, category_group_enabled, name, scope, id, bind_id, thread_id, now, + args, flags | TRACE_EVENT_FLAG_HAS_CONTEXT_ID); +} + +TraceEventHandle TraceLog::AddTraceEventWithProcessId( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + int process_id, + TraceArguments* args, + unsigned int flags) { + base::TimeTicks now = TRACE_TIME_TICKS_NOW(); + return AddTraceEventWithThreadIdAndTimestamp( + phase, category_group_enabled, name, scope, id, + trace_event_internal::kNoId, // bind_id + process_id, now, args, flags | TRACE_EVENT_FLAG_HAS_PROCESS_ID); +} + +// Handle legacy calls to AddTraceEventWithThreadIdAndTimestamp +// with kNoId as bind_id +TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + int thread_id, + const TimeTicks& timestamp, + TraceArguments* args, + unsigned int flags) { + return AddTraceEventWithThreadIdAndTimestamp( + phase, category_group_enabled, name, scope, id, + trace_event_internal::kNoId, // bind_id + thread_id, timestamp, args, flags); } TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( @@ -1218,6 +1238,24 @@ const unsigned long long* arg_values, std::unique_ptr<ConvertableToTraceFormat>* convertable_values, unsigned int flags) { + TraceArguments args(num_args, arg_names, arg_types, arg_values, + convertable_values); + return AddTraceEventWithThreadIdAndTimestamp( + phase, category_group_enabled, name, scope, id, bind_id, thread_id, + timestamp, &args, flags); +} + +TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + unsigned long long bind_id, + int thread_id, + const TimeTicks& timestamp, + TraceArguments* args, + unsigned int flags) { TraceEventHandle handle = {0, 0, 0}; if (!*category_group_enabled) return handle; @@ -1290,29 +1328,19 @@ // acquiring the lock, which is not needed for ETW as it's already threadsafe. if (*category_group_enabled & TraceCategory::ENABLED_FOR_ETW_EXPORT) TraceEventETWExport::AddEvent(phase, category_group_enabled, name, id, - num_args, arg_names, arg_types, arg_values, - convertable_values); + args); #endif // OS_WIN - AddTraceEventOverrideCallback trace_event_override = - reinterpret_cast<AddTraceEventOverrideCallback>( - subtle::NoBarrier_Load(&trace_event_override_)); + auto trace_event_override = + add_trace_event_override_.load(std::memory_order_relaxed); if (trace_event_override) { - // If we have an override in place for events, rather than sending - // them to the tracelog, we don't have a way of going back and updating - // the duration of _COMPLETE events. Instead, we emit separate _BEGIN - // and _END events. - if (phase == TRACE_EVENT_PHASE_COMPLETE) - phase = TRACE_EVENT_PHASE_BEGIN; - TraceEvent new_trace_event(thread_id, offset_event_timestamp, thread_now, phase, category_group_enabled, name, scope, id, - bind_id, num_args, arg_names, arg_types, - arg_values, convertable_values, flags); + bind_id, args, flags); trace_event_override( &new_trace_event, - /*thread_will_flush=*/thread_local_event_buffer != nullptr); + /*thread_will_flush=*/thread_local_event_buffer != nullptr, &handle); return handle; } @@ -1322,8 +1350,7 @@ if (*category_group_enabled & TraceCategory::ENABLED_FOR_FILTERING) { auto new_trace_event = std::make_unique<TraceEvent>( thread_id, offset_event_timestamp, thread_now, phase, - category_group_enabled, name, scope, id, bind_id, num_args, arg_names, - arg_types, arg_values, convertable_values, flags); + category_group_enabled, name, scope, id, bind_id, args, flags); disabled_by_filters = true; ForEachCategoryFilter( @@ -1356,8 +1383,7 @@ } else { trace_event->Reset(thread_id, offset_event_timestamp, thread_now, phase, category_group_enabled, name, scope, id, bind_id, - num_args, arg_names, arg_types, arg_values, - convertable_values, flags); + args, flags); } #if defined(OS_ANDROID) @@ -1387,6 +1413,15 @@ const unsigned long long* arg_values, std::unique_ptr<ConvertableToTraceFormat>* convertable_values, unsigned int flags) { + TraceArguments args(num_args, arg_names, arg_types, arg_values, + convertable_values); + return AddMetadataEvent(category_group_enabled, name, &args, flags); +} + +void TraceLog::AddMetadataEvent(const unsigned char* category_group_enabled, + const char* name, + TraceArguments* args, + unsigned int flags) { HEAP_PROFILER_SCOPED_IGNORE; int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); ThreadTicks thread_now = ThreadNow(); @@ -1398,7 +1433,7 @@ trace_event_internal::kGlobalScope, // scope trace_event_internal::kNoId, // id trace_event_internal::kNoId, // bind_id - num_args, arg_names, arg_types, arg_values, convertable_values, flags); + args, flags); metadata_events_.push_back(std::move(trace_event)); } @@ -1500,29 +1535,10 @@ #endif // OS_WIN if (category_group_enabled_local & TraceCategory::ENABLED_FOR_RECORDING) { - AddTraceEventOverrideCallback trace_event_override = - reinterpret_cast<AddTraceEventOverrideCallback>( - subtle::NoBarrier_Load(&trace_event_override_)); - - // If we send events off to an override instead of the TraceBuffer, - // we don't have way of updating the prior event so we'll emit a - // separate _END event instead. - if (trace_event_override) { - TraceEvent new_trace_event( - static_cast<int>(base::PlatformThread::CurrentId()), now, thread_now, - TRACE_EVENT_PHASE_END, category_group_enabled, name, - trace_event_internal::kGlobalScope, - trace_event_internal::kNoId /* id */, - trace_event_internal::kNoId /* bind_id */, 0, nullptr, nullptr, - nullptr, nullptr, TRACE_EVENT_FLAG_NONE); - trace_event_override( - &new_trace_event, - /*thread_will_flush=*/thread_local_event_buffer_.Get() != nullptr); - -#if defined(OS_ANDROID) - new_trace_event.SendToATrace(); -#endif - + auto update_duration_callback = + update_duration_callback_.load(std::memory_order_relaxed); + if (update_duration_callback) { + update_duration_callback(handle, now, thread_now); return; } } @@ -1563,13 +1579,13 @@ const char* metadata_name, const char* arg_name, const T& value) { - auto trace_event_override = reinterpret_cast<AddTraceEventOverrideCallback>( - subtle::NoBarrier_Load(&trace_event_override_)); + auto trace_event_override = + add_trace_event_override_.load(std::memory_order_relaxed); if (trace_event_override) { TraceEvent trace_event; InitializeMetadataEvent(&trace_event, thread_id, metadata_name, arg_name, value); - trace_event_override(&trace_event, /*thread_will_flush=*/true); + trace_event_override(&trace_event, /*thread_will_flush=*/true, nullptr); } else { InitializeMetadataEvent( AddEventToThreadSharedChunkWhileLocked(nullptr, false), thread_id, @@ -1580,14 +1596,14 @@ void TraceLog::AddMetadataEventsWhileLocked() { lock_.AssertAcquired(); - auto trace_event_override = reinterpret_cast<AddTraceEventOverrideCallback>( - subtle::NoBarrier_Load(&trace_event_override_)); + auto trace_event_override = + add_trace_event_override_.load(std::memory_order_relaxed); // Move metadata added by |AddMetadataEvent| into the trace log. if (trace_event_override) { while (!metadata_events_.empty()) { trace_event_override(metadata_events_.back().get(), - /*thread_will_flush=*/true); + /*thread_will_flush=*/true, nullptr); metadata_events_.pop_back(); } } else { @@ -1809,16 +1825,10 @@ const char* name, const char* scope, unsigned long long id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* - convertable_values, + base::trace_event::TraceArguments* args, unsigned int flags) { return base::trace_event::TraceLog::GetInstance()->AddTraceEvent( - phase, category_group_enabled, name, scope, id, num_args, arg_names, - arg_types, arg_values, convertable_values, flags); + phase, category_group_enabled, name, scope, id, args, flags); } base::trace_event::TraceEventHandle AddTraceEventWithBindId( @@ -1828,16 +1838,10 @@ const char* scope, unsigned long long id, unsigned long long bind_id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* - convertable_values, + base::trace_event::TraceArguments* args, unsigned int flags) { return base::trace_event::TraceLog::GetInstance()->AddTraceEventWithBindId( - phase, category_group_enabled, name, scope, id, bind_id, num_args, - arg_names, arg_types, arg_values, convertable_values, flags); + phase, category_group_enabled, name, scope, id, bind_id, args, flags); } base::trace_event::TraceEventHandle AddTraceEventWithProcessId( @@ -1847,16 +1851,10 @@ const char* scope, unsigned long long id, int process_id, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* - convertable_values, + base::trace_event::TraceArguments* args, unsigned int flags) { return base::trace_event::TraceLog::GetInstance()->AddTraceEventWithProcessId( - phase, category_group_enabled, name, scope, id, process_id, num_args, - arg_names, arg_types, arg_values, convertable_values, flags); + phase, category_group_enabled, name, scope, id, process_id, args, flags); } base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( @@ -1867,18 +1865,12 @@ unsigned long long id, int thread_id, const base::TimeTicks& timestamp, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* - convertable_values, + base::trace_event::TraceArguments* args, unsigned int flags) { return base::trace_event::TraceLog::GetInstance() - ->AddTraceEventWithThreadIdAndTimestamp( - phase, category_group_enabled, name, scope, id, thread_id, timestamp, - num_args, arg_names, arg_types, arg_values, convertable_values, - flags); + ->AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled, + name, scope, id, thread_id, + timestamp, args, flags); } base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( @@ -1890,33 +1882,20 @@ unsigned long long bind_id, int thread_id, const base::TimeTicks& timestamp, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* - convertable_values, + base::trace_event::TraceArguments* args, unsigned int flags) { return base::trace_event::TraceLog::GetInstance() ->AddTraceEventWithThreadIdAndTimestamp( phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, num_args, arg_names, arg_types, arg_values, - convertable_values, flags); + timestamp, args, flags); } -void AddMetadataEvent( - const unsigned char* category_group_enabled, - const char* name, - int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* - convertable_values, - unsigned int flags) { +void AddMetadataEvent(const unsigned char* category_group_enabled, + const char* name, + base::trace_event::TraceArguments* args, + unsigned int flags) { return base::trace_event::TraceLog::GetInstance()->AddMetadataEvent( - category_group_enabled, name, num_args, arg_names, arg_types, arg_values, - convertable_values, flags); + category_group_enabled, name, args, flags); } int GetNumTracesRecorded() { @@ -1941,6 +1920,128 @@ now, thread_now); } +base::trace_event::TraceEventHandle AddTraceEvent( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* + convertable_values, + unsigned int flags) { + base::trace_event::TraceArguments args(num_args, arg_names, arg_types, + arg_values, convertable_values); + return base::trace_event::TraceLog::GetInstance()->AddTraceEvent( + phase, category_group_enabled, name, scope, id, &args, flags); +} + +base::trace_event::TraceEventHandle AddTraceEventWithBindId( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + unsigned long long bind_id, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* + convertable_values, + unsigned int flags) { + base::trace_event::TraceArguments args(num_args, arg_names, arg_types, + arg_values, convertable_values); + return base::trace_event::TraceLog::GetInstance()->AddTraceEventWithBindId( + phase, category_group_enabled, name, scope, id, bind_id, &args, flags); +} + +base::trace_event::TraceEventHandle AddTraceEventWithProcessId( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + int process_id, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* + convertable_values, + unsigned int flags) { + base::trace_event::TraceArguments args(num_args, arg_names, arg_types, + arg_values, convertable_values); + return base::trace_event::TraceLog::GetInstance()->AddTraceEventWithProcessId( + phase, category_group_enabled, name, scope, id, process_id, &args, flags); +} + +base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + int thread_id, + const base::TimeTicks& timestamp, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* + convertable_values, + unsigned int flags) { + base::trace_event::TraceArguments args(num_args, arg_names, arg_types, + arg_values, convertable_values); + return base::trace_event::TraceLog::GetInstance() + ->AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled, + name, scope, id, thread_id, + timestamp, &args, flags); +} + +base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + unsigned long long bind_id, + int thread_id, + const base::TimeTicks& timestamp, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* + convertable_values, + unsigned int flags) { + base::trace_event::TraceArguments args(num_args, arg_names, arg_types, + arg_values, convertable_values); + return base::trace_event::TraceLog::GetInstance() + ->AddTraceEventWithThreadIdAndTimestamp( + phase, category_group_enabled, name, scope, id, bind_id, thread_id, + timestamp, &args, flags); +} + +void AddMetadataEvent( + const unsigned char* category_group_enabled, + const char* name, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* + convertable_values, + unsigned int flags) { + base::trace_event::TraceArguments args(num_args, arg_names, arg_types, + arg_values, convertable_values); + return base::trace_event::TraceLog::GetInstance()->AddMetadataEvent( + category_group_enabled, name, &args, flags); +} + ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient( const char* category_group, const char* name) {
diff --git a/base/trace_event/trace_log.h b/base/trace_event/trace_log.h index 3f663234..1e0ad39 100644 --- a/base/trace_event/trace_log.h +++ b/base/trace_event/trace_log.h
@@ -8,6 +8,7 @@ #include <stddef.h> #include <stdint.h> +#include <atomic> #include <memory> #include <string> #include <unordered_map> @@ -186,14 +187,20 @@ // Cancels tracing and discards collected data. void CancelTracing(const OutputCallback& cb); - typedef void (*AddTraceEventOverrideCallback)(TraceEvent*, - bool thread_will_flush); - typedef void (*OnFlushCallback)(); - // The callback will be called up until the point where the flush is + using AddTraceEventOverrideCallback = void (*)(TraceEvent*, + bool thread_will_flush, + TraceEventHandle* handle); + using OnFlushCallback = void (*)(); + using UpdateDurationCallback = void (*)(TraceEventHandle handle, + const TimeTicks& now, + const ThreadTicks& thread_now); + // The callbacks will be called up until the point where the flush is // finished, i.e. must be callable until OutputCallback is called with // has_more_events==false. - void SetAddTraceEventOverride(const AddTraceEventOverrideCallback& override, - const OnFlushCallback& on_flush_callback); + void SetAddTraceEventOverrides( + const AddTraceEventOverrideCallback& add_event_override, + const OnFlushCallback& on_flush_callback, + const UpdateDurationCallback& update_duration_callback); // Called by TRACE_EVENT* macros, don't call this directly. // The name parameter is a category group for example: @@ -213,6 +220,58 @@ // Called by TRACE_EVENT* macros, don't call this directly. // If |copy| is set, |name|, |arg_name1| and |arg_name2| will be deep copied // into the event; see "Memory scoping note" and TRACE_EVENT_COPY_XXX above. + TraceEventHandle AddTraceEvent(char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + TraceArguments* args, + unsigned int flags); + TraceEventHandle AddTraceEventWithBindId( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + unsigned long long bind_id, + TraceArguments* args, + unsigned int flags); + TraceEventHandle AddTraceEventWithProcessId( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + int process_id, + TraceArguments* args, + unsigned int flags); + TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + int thread_id, + const TimeTicks& timestamp, + TraceArguments* args, + unsigned int flags); + TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + unsigned long long bind_id, + int thread_id, + const TimeTicks& timestamp, + TraceArguments* args, + unsigned int flags); + + // Adds a metadata event that will be written when the trace log is flushed. + void AddMetadataEvent(const unsigned char* category_group_enabled, + const char* name, + TraceArguments* args, + unsigned int flags); // TODO(898794): Remove methods below when all callers have been updated. TraceEventHandle AddTraceEvent( @@ -548,8 +607,9 @@ ArgumentFilterPredicate argument_filter_predicate_; subtle::AtomicWord generation_; bool use_worker_thread_; - subtle::AtomicWord trace_event_override_; - subtle::AtomicWord on_flush_callback_; + std::atomic<AddTraceEventOverrideCallback> add_trace_event_override_; + std::atomic<OnFlushCallback> on_flush_callback_; + std::atomic<UpdateDurationCallback> update_duration_callback_; FilterFactoryForTesting filter_factory_for_testing_;
diff --git a/base/trace_event/traced_value.cc b/base/trace_event/traced_value.cc index 4addbda..cf254fea 100644 --- a/base/trace_event/traced_value.cc +++ b/base/trace_event/traced_value.cc
@@ -435,7 +435,7 @@ std::unique_ptr<TracedValue::Writer> CreateWriter(size_t capacity) { TracedValue::WriterFactoryCallback callback = - g_writer_factory_callback.load(); + g_writer_factory_callback.load(std::memory_order_relaxed); if (callback) { return callback(capacity); }
diff --git a/build/OWNERS b/build/OWNERS index 918c4884..4c1aa29 100644 --- a/build/OWNERS +++ b/build/OWNERS
@@ -5,6 +5,7 @@ scottmg@chromium.org thakis@chromium.org brucedawson@chromium.org +thomasanderson@chromium.org tikuta@chromium.org # Clang build config changes @@ -12,7 +13,6 @@ per-file .gitignore=* per-file check_gn_headers_whitelist.txt=* -per-file install-build-deps.sh=thomasanderson@chromium.org per-file mac_toolchain.py=erikchen@chromium.org per-file mac_toolchain.py=justincohen@chromium.org per-file package_mac_toolchain.py=erikchen@chromium.org
diff --git a/build/android/PRESUBMIT.py b/build/android/PRESUBMIT.py index 5f384f6..c444619 100644 --- a/build/android/PRESUBMIT.py +++ b/build/android/PRESUBMIT.py
@@ -53,37 +53,39 @@ 'PYTHONPATH': build_android_dir, 'PYTHONDONTWRITEBYTECODE': '1', }) - output.extend(input_api.canned_checks.RunUnitTests( - input_api, - output_api, - unit_tests=[ - J('.', 'emma_coverage_stats_test.py'), - J('.', 'list_class_verification_failures_test.py'), - J('gyp', 'util', 'build_utils_test.py'), - J('gyp', 'util', 'md5_check_test.py'), - J('play_services', 'update_test.py'), - J('pylib', 'constants', 'host_paths_unittest.py'), - J('pylib', 'gtest', 'gtest_test_instance_test.py'), - J('pylib', 'instrumentation', - 'instrumentation_test_instance_test.py'), - J('pylib', 'local', 'device', - 'local_device_instrumentation_test_run_test.py'), - J('pylib', 'local', 'device', 'local_device_test_run_test.py'), - J('pylib', 'output', 'local_output_manager_test.py'), - J('pylib', 'output', 'noop_output_manager_test.py'), - J('pylib', 'output', 'remote_output_manager_test.py'), - J('pylib', 'results', 'json_results_test.py'), - J('pylib', 'symbols', 'apk_native_libs_unittest.py'), - J('pylib', 'symbols', 'elf_symbolizer_unittest.py'), - J('pylib', 'symbols', 'symbol_utils_unittest.py'), - J('pylib', 'utils', 'decorators_test.py'), - J('pylib', 'utils', 'device_dependencies_test.py'), - J('pylib', 'utils', 'dexdump_test.py'), - J('pylib', 'utils', 'proguard_test.py'), - J('pylib', 'utils', 'test_filter_test.py'), - J('.', 'convert_dex_profile_tests.py'), - ], - env=pylib_test_env)) + output.extend( + input_api.canned_checks.RunUnitTests( + input_api, + output_api, + unit_tests=[ + J('.', 'emma_coverage_stats_test.py'), + J('.', 'list_class_verification_failures_test.py'), + J('gyp', 'util', 'build_utils_test.py'), + J('gyp', 'util', 'md5_check_test.py'), + J('gyp', 'util', 'resource_utils_test.py'), + J('play_services', 'update_test.py'), + J('pylib', 'constants', 'host_paths_unittest.py'), + J('pylib', 'gtest', 'gtest_test_instance_test.py'), + J('pylib', 'instrumentation', + 'instrumentation_test_instance_test.py'), + J('pylib', 'local', 'device', + 'local_device_instrumentation_test_run_test.py'), + J('pylib', 'local', 'device', 'local_device_test_run_test.py'), + J('pylib', 'output', 'local_output_manager_test.py'), + J('pylib', 'output', 'noop_output_manager_test.py'), + J('pylib', 'output', 'remote_output_manager_test.py'), + J('pylib', 'results', 'json_results_test.py'), + J('pylib', 'symbols', 'apk_native_libs_unittest.py'), + J('pylib', 'symbols', 'elf_symbolizer_unittest.py'), + J('pylib', 'symbols', 'symbol_utils_unittest.py'), + J('pylib', 'utils', 'decorators_test.py'), + J('pylib', 'utils', 'device_dependencies_test.py'), + J('pylib', 'utils', 'dexdump_test.py'), + J('pylib', 'utils', 'proguard_test.py'), + J('pylib', 'utils', 'test_filter_test.py'), + J('.', 'convert_dex_profile_tests.py'), + ], + env=pylib_test_env)) return output
diff --git a/build/android/gyp/aar.py b/build/android/gyp/aar.py index c2eb3ea12..d0f357d 100755 --- a/build/android/gyp/aar.py +++ b/build/android/gyp/aar.py
@@ -70,6 +70,10 @@ data['assets'].append(name) elif name.startswith('jni/'): data['has_native_libraries'] = True + if 'native_libraries' in data: + data['native_libraries'].append(name) + else: + data['native_libraries'] = [name] elif name == 'classes.jar': data['has_classes_jar'] = True elif name == 'proguard.txt':
diff --git a/build/android/gyp/compile_resources.py b/build/android/gyp/compile_resources.py index f9c23fab..a6bcd2d 100755 --- a/build/android/gyp/compile_resources.py +++ b/build/android/gyp/compile_resources.py
@@ -248,14 +248,13 @@ return renamed_paths -def _ToAaptLocales(locale_whitelist, support_zh_hk): +def _ToAndroidLocales(locale_whitelist, support_zh_hk): """Converts the list of Chrome locales to aapt config locales.""" ret = set() for locale in locale_whitelist: - locale = resource_utils.CHROME_TO_ANDROID_LOCALE_MAP.get(locale, locale) + locale = resource_utils.ToAndroidLocaleName(locale) if locale is None or ('-' in locale and '-r' not in locale): - raise Exception('CHROME_TO_ANDROID_LOCALE_MAP needs updating.' - ' Found: %s' % locale) + raise Exception('Unsupported Chromium locale name: %s' % locale) ret.add(locale) # Always keep non-regional fall-backs. language = locale.split('-')[0] @@ -337,11 +336,6 @@ elif options.shared_resources: link_command.append('--shared-lib') - if options.locale_whitelist: - aapt_locales = _ToAaptLocales( - options.locale_whitelist, options.support_zh_hk) - link_command += ['-c', ','.join(aapt_locales)] - if options.no_xml_namespaces: link_command.append('--no-xml-namespaces') @@ -431,28 +425,65 @@ def _CreateKeepPredicate(resource_dirs, resource_blacklist_regex, - resource_blacklist_exceptions): - """Return a predicate lambda to determine which resource files to keep.""" - if resource_blacklist_regex == '': + resource_blacklist_exceptions, + android_locale_whitelist): + """Return a predicate lambda to determine which resource files to keep. + + Args: + resource_dirs: list of top-level resource directories. + resource_blacklist_regex: A regular expression describing all resources + to exclude, except if they are mip-maps, or if they are listed + in |resource_blacklist_exceptions|. + resource_blacklist_exceptions: A list of glob patterns corresponding + to exceptions to the |resource_blacklist_regex|. + android_locale_whitelist: An optional whitelist of Android locale names. + If set, any localized string resources that is not in this whitelist + will be removed. + Returns: + A lambda that takes a path, and returns true if the corresponding file + must be kept. + """ + if resource_blacklist_regex == '' and not android_locale_whitelist: # Do not extract dotfiles (e.g. ".gitkeep"). aapt ignores them anyways. return lambda path: os.path.basename(path)[0] != '.' - # Returns False only for non-filtered, non-mipmap, non-whitelisted drawables. - naive_predicate = lambda path: ( - not re.search(resource_blacklist_regex, path) or - re.search(r'[/-]mipmap[/-]', path) or - build_utils.MatchesGlob(path, resource_blacklist_exceptions)) + if resource_blacklist_regex != '': + # A simple predicate that only removes (returns False for) paths covered by + # the blacklist regex, except if they are mipmaps, or listed as exceptions. + naive_predicate = lambda path: ( + not re.search(resource_blacklist_regex, path) or + re.search(r'[/-]mipmap[/-]', path) or + build_utils.MatchesGlob(path, resource_blacklist_exceptions)) - # Build a set of all non-filtered drawables to ensure that we never exclude - # any drawable that does not exist in non-filtered densities. + # Build a set of all names from drawables kept by naive_predicate(). + # Used later to ensure that we never exclude drawables from densities + # that are filtered-out by naive_predicate(). non_filtered_drawables = set() for resource_dir in resource_dirs: for path in _IterFiles(resource_dir): if re.search(r'[/-]drawable[/-]', path) and naive_predicate(path): non_filtered_drawables.add(_ResourceNameFromPath(path)) - return lambda path: (naive_predicate(path) or - _ResourceNameFromPath(path) not in non_filtered_drawables) + # NOTE: Defined as a function because when using a lambda definition, + # 'git cl format' will expand everything on a very long line that is + # much larger than the column limit. + def drawable_predicate(path): + return (naive_predicate(path) + or _ResourceNameFromPath(path) not in non_filtered_drawables) + + if not android_locale_whitelist: + return drawable_predicate + + # A simple predicate that removes localized strings .xml files that are + # not part of |android_locale_whitelist|. + android_locale_whitelist = set(android_locale_whitelist) + + def is_bad_locale(path): + """Return true iff |path| is a resource for a non-whitelisted locale.""" + locale = resource_utils.FindLocaleInStringResourceFilePath(path) + return locale and locale not in android_locale_whitelist + + return lambda path: drawable_predicate(path) and not is_bad_locale(path) def _ConvertToWebP(webp_binary, png_files): @@ -540,9 +571,13 @@ renamed_paths = dict() renamed_paths.update(_DuplicateZhResources(dep_subdirs)) + # Create a function that selects which resource files should be packaged + # into the final output. Any file that does not pass the predicate will + # be removed below. keep_predicate = _CreateKeepPredicate( dep_subdirs, options.resource_blacklist_regex, - options.resource_blacklist_exceptions) + options.resource_blacklist_exceptions, + _ToAndroidLocales(options.locale_whitelist, options.support_zh_hk)) png_paths = [] for directory in dep_subdirs: for f in _IterFiles(directory):
diff --git a/build/android/gyp/create_app_bundle.py b/build/android/gyp/create_app_bundle.py index c787bbd..e8bbcb8 100755 --- a/build/android/gyp/create_app_bundle.py +++ b/build/android/gyp/create_app_bundle.py
@@ -178,8 +178,7 @@ return [src_path] locale = src_path[len(_LOCALES_SUBDIR):-4] - android_locale = resource_utils.CHROME_TO_ANDROID_LOCALE_MAP.get( - locale, locale) + android_locale = resource_utils.ToAndroidLocaleName(locale) # The locale format is <lang>-<region> or <lang>. Extract the language. pos = android_locale.find('-')
diff --git a/build/android/gyp/util/resource_utils.py b/build/android/gyp/util/resource_utils.py index 11a924e..35f9a38 100644 --- a/build/android/gyp/util/resource_utils.py +++ b/build/android/gyp/util/resource_utils.py
@@ -25,22 +25,122 @@ _SOURCE_ROOT, 'build', 'android', 'AndroidManifest.xml') -# A variation of this lists also exists in: +# A variation of these maps also exists in: # //base/android/java/src/org/chromium/base/LocaleUtils.java # //ui/android/java/src/org/chromium/base/LocalizationUtils.java -CHROME_TO_ANDROID_LOCALE_MAP = { - 'en-GB': 'en-rGB', - 'en-US': 'en-rUS', +_CHROME_TO_ANDROID_LOCALE_MAP = { 'es-419': 'es-rUS', 'fil': 'tl', 'he': 'iw', 'id': 'in', - 'pt-PT': 'pt-rPT', - 'pt-BR': 'pt-rBR', 'yi': 'ji', - 'zh-CN': 'zh-rCN', - 'zh-TW': 'zh-rTW', } +_ANDROID_TO_CHROMIUM_LANGUAGE_MAP = { + 'tl': 'fil', + 'iw': 'he', + 'in': 'id', + 'ji': 'yi', +} + + +def ToAndroidLocaleName(chromium_locale): + """Convert an Chromium locale name into a corresponding Android one.""" + # First handle the special cases, these are needed to deal with Android + # releases *before* 5.0/Lollipop. + android_locale = _CHROME_TO_ANDROID_LOCALE_MAP.get(chromium_locale) + if android_locale: + return android_locale + + # Format of Chromium locale name is '<lang>' or '<lang>-<region>' + # where <lang> is a 2 or 3 letter language code (ISO 639-1 or 639-2) + # and region is a capitalized locale region name. + lang, _, region = chromium_locale.partition('-') + if not region: + return lang + + # Translate newer language tags into obsolete ones. Only necessary if + # region is not None (e.g. 'he-IL' -> 'iw-rIL') + lang = _CHROME_TO_ANDROID_LOCALE_MAP.get(lang, lang) + + # Using '<lang>-r<region>' is now acceptable as a locale name for all + # versions of Android. + return '%s-r%s' % (lang, region) + + +# ISO 639 language code + optional ("-r" + capitalized region code). +# Note that before Android 5.0/Lollipop, only 2-letter ISO 639-1 codes +# are supported. +_RE_ANDROID_LOCALE_QUALIFIER_1 = re.compile(r'^([a-z]{2,3})(\-r([A-Z]+))?$') + +# Starting with Android 7.0/Nougat, BCP 47 codes are supported but must +# be prefixed with 'b+', and may include optional tags. e.g. 'b+en+US', +# 'b+ja+Latn', 'b+ja+JP+Latn' +_RE_ANDROID_LOCALE_QUALIFIER_2 = re.compile(r'^b\+([a-z]{2,3})(\+.+)?$') + +# Matches an all-uppercase region name. +_RE_ALL_UPPERCASE = re.compile(r'^[A-Z]+$') + + +def ToChromiumLocaleName(android_locale): + """Convert an Android locale name into a Chromium one.""" + lang = None + region = None + m = _RE_ANDROID_LOCALE_QUALIFIER_1.match(android_locale) + if m: + lang = m.group(1) + if m.group(2): + region = m.group(3) + else: + m = _RE_ANDROID_LOCALE_QUALIFIER_2.match(android_locale) + if m: + lang = m.group(1) + if m.group(2): + tags = m.group(2).split('+') + # First all-uppercase tag is a region. This deals with cases where + # a special tag is placed before it (e.g. 'cmn+Hant-TW') + for tag in tags: + if _RE_ALL_UPPERCASE.match(tag): + region = tag + break + + if not lang: + return None + + # Special case for es-rUS -> es-419 + if lang == 'es' and region == 'US': + return 'es-419' + + lang = _ANDROID_TO_CHROMIUM_LANGUAGE_MAP.get(lang, lang) + if not region: + return lang + + return '%s-%s' % (lang, region) + + +def IsAndroidLocaleQualifier(string): + """Returns true if |string| is a valid Android resource locale qualifier.""" + return (_RE_ANDROID_LOCALE_QUALIFIER_1.match(string) + or _RE_ANDROID_LOCALE_QUALIFIER_2.match(string)) + + +def FindLocaleInStringResourceFilePath(file_path): + """Return Android locale name of a string resource file path. + + Args: + file_path: A file path. + Returns: + If |file_path| is of the format '.../values-<locale>/<name>.xml', return + the value of <locale> (and Android locale qualifier). Otherwise return None. + """ + if not file_path.endswith('.xml'): + return None + prefix = 'values-' + dir_name = os.path.basename(os.path.dirname(file_path)) + if not dir_name.startswith(prefix): + return None + qualifier = dir_name[len(prefix):] + return qualifier if IsAndroidLocaleQualifier(qualifier) else None + # Represents a line from a R.txt file. _TextSymbolEntry = collections.namedtuple('RTextEntry', @@ -102,10 +202,16 @@ def _GetRTxtResourceNames(r_txt_path): """Parse an R.txt file and extract the set of resource names from it.""" - result = set() - for entry in _ParseTextSymbolsFile(r_txt_path): - result.add(entry.name) - return result + return {entry.name for entry in _ParseTextSymbolsFile(r_txt_path)} + + +def GetRTxtStringResourceNames(r_txt_path): + """Parse an R.txt file and the list of its string resource names.""" + return sorted({ + entry.name + for entry in _ParseTextSymbolsFile(r_txt_path) + if entry.resource_type == 'string' + }) class RJavaBuildOptions:
diff --git a/build/android/gyp/util/resource_utils_test.py b/build/android/gyp/util/resource_utils_test.py new file mode 100755 index 0000000..5988f795 --- /dev/null +++ b/build/android/gyp/util/resource_utils_test.py
@@ -0,0 +1,178 @@ +#!/usr/bin/env python +# coding: utf-8 +# 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. + +import collections +import os +import unittest +import sys + +import build_utils # pylint: disable=relative-import + +# Required because the following import needs build/android/gyp in the +# Python path to import util.build_utils. +_BUILD_ANDROID_GYP_ROOT = os.path.abspath( + os.path.join(os.path.dirname(__file__), '..')) +sys.path.insert(1, _BUILD_ANDROID_GYP_ROOT) + +import resource_utils # pylint: disable=relative-import + +_RES_STRINGS_1 = { + 'low_memory_error': 'Eelmist toimingut ei saa vähese mälu tõttu lõpetada', + 'opening_file_error': 'Valit. faili avamine ebaõnnestus', + 'copy_to_clipboard_failure_message': 'Lõikelauale kopeerimine ebaõnnestus' +} + +_EXPECTED_XML_1 = '''<?xml version="1.0" encoding="utf-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android"> +<string name="copy_to_clipboard_failure_message">"Lõikelauale kopeerimine ebaõnnestus"</string> +<string name="low_memory_error">"Eelmist toimingut ei saa vähese mälu tõttu lõpetada"</string> +<string name="opening_file_error">"Valit. faili avamine ebaõnnestus"</string> +</resources> +''' + +_XML_RESOURCES_PREFIX = r'''<?xml version="1.0" encoding="utf-8"?> +<resources xmlns:android="http://schemas.android.com/apk/res/android"> +''' + +_XML_RESOURCES_SUFFIX = '</resources>\n' + +# Extracted from one generated Chromium R.txt file, with string resource +# names shuffled randomly. +_TEST_R_TXT = r'''int anim abc_fade_in 0x7f050000 +int anim abc_fade_out 0x7f050001 +int anim abc_grow_fade_in_from_bottom 0x7f050002 +int array DefaultCookiesSettingEntries 0x7f120002 +int array DefaultCookiesSettingValues 0x7f120003 +int array DefaultGeolocationSettingEntries 0x7f120004 +int attr actionBarDivider 0x7f0100e7 +int attr actionBarStyle 0x7f0100e2 +int string AllowedDomainsForAppsDesc 0x7f0c0105 +int string AlternateErrorPagesEnabledDesc 0x7f0c0107 +int string AuthAndroidNegotiateAccountTypeDesc 0x7f0c0109 +int string AllowedDomainsForAppsTitle 0x7f0c0104 +int string AlternateErrorPagesEnabledTitle 0x7f0c0106 +int[] styleable SnackbarLayout { 0x0101011f, 0x7f010076, 0x7f0100ba } +int styleable SnackbarLayout_android_maxWidth 0 +int styleable SnackbarLayout_elevation 2 +''' + +# Names of string resources in _TEST_R_TXT, should be sorted! +_TEST_R_TXT_STRING_RESOURCE_NAMES = sorted([ + 'AllowedDomainsForAppsDesc', + 'AllowedDomainsForAppsTitle', + 'AlternateErrorPagesEnabledDesc', + 'AlternateErrorPagesEnabledTitle', + 'AuthAndroidNegotiateAccountTypeDesc', +]) + + +class ResourceUtilsTest(unittest.TestCase): + + def test_GetRTxtStringResourceNames(self): + with build_utils.TempDir() as tmp_dir: + tmp_file = os.path.join(tmp_dir, "test_R.txt") + with open(tmp_file, 'wt') as f: + f.write(_TEST_R_TXT) + + self.assertListEqual( + resource_utils.GetRTxtStringResourceNames(tmp_file), + _TEST_R_TXT_STRING_RESOURCE_NAMES) + + def test_IsAndroidLocaleQualifier(self): + good_locales = [ + 'en', + 'en-rUS', + 'fil', + 'fil-rPH', + 'iw', + 'iw-rIL', + 'b+en', + 'b+en+US', + 'b+ja+Latn', + 'b+ja+JP+Latn', + 'b+cmn+Hant-TW', + ] + bad_locales = [ + 'e', 'english', 'en-US', 'en_US', 'en-rus', 'b+e', 'b+english', 'b+ja+' + ] + for locale in good_locales: + self.assertTrue( + resource_utils.IsAndroidLocaleQualifier(locale), + msg="'%s' should be a good locale!" % locale) + + for locale in bad_locales: + self.assertFalse( + resource_utils.IsAndroidLocaleQualifier(locale), + msg="'%s' should be a bad locale!" % locale) + + def test_ToAndroidLocaleName(self): + _TEST_CHROMIUM_TO_ANDROID_LOCALE_MAP = { + 'en': 'en', + 'en-US': 'en-rUS', + 'en-FOO': 'en-rFOO', + 'fil': 'tl', + 'tl': 'tl', + 'he': 'iw', + 'he-IL': 'iw-rIL', + 'id': 'in', + 'id-BAR': 'in-rBAR', + 'yi': 'ji' + } + for chromium_locale, android_locale in \ + _TEST_CHROMIUM_TO_ANDROID_LOCALE_MAP.iteritems(): + result = resource_utils.ToAndroidLocaleName(chromium_locale) + self.assertEqual(result, android_locale) + + def test_ToChromiumLocaleName(self): + _TEST_ANDROID_TO_CHROMIUM_LOCALE_MAP = { + 'foo': 'foo', + 'foo-rBAR': 'foo-BAR', + 'b+foo': 'foo', + 'b+foo+BAR': 'foo-BAR', + 'b+foo+BAR+Whatever': 'foo-BAR', + 'b+foo+Whatever+BAR': 'foo-BAR', + 'b+foo+Whatever': 'foo', + 'en': 'en', + 'en-rUS': 'en-US', + 'en-US': None, + 'en-FOO': None, + 'en-rFOO': 'en-FOO', + 'es-rES': 'es-ES', + 'es-rUS': 'es-419', + 'tl': 'fil', + 'fil': 'fil', + 'iw': 'he', + 'iw-rIL': 'he-IL', + 'in': 'id', + 'in-rBAR': 'id-BAR', + 'id-rBAR': 'id-BAR', + } + for android_locale, chromium_locale in \ + _TEST_ANDROID_TO_CHROMIUM_LOCALE_MAP.iteritems(): + result = resource_utils.ToChromiumLocaleName(android_locale) + self.assertEqual(result, chromium_locale) + + def test_FindLocaleInStringResourceFilePath(self): + self.assertEqual( + None, + resource_utils.FindLocaleInStringResourceFilePath( + 'res/values/whatever.xml')) + self.assertEqual( + 'foo', + resource_utils.FindLocaleInStringResourceFilePath( + 'res/values-foo/whatever.xml')) + self.assertEqual( + 'foo-rBAR', + resource_utils.FindLocaleInStringResourceFilePath( + 'res/values-foo-rBAR/whatever.xml')) + self.assertEqual( + None, + resource_utils.FindLocaleInStringResourceFilePath( + 'res/values-foo/ignore-subdirs/whatever.xml')) + + +if __name__ == '__main__': + unittest.main()
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py index 75de58a..315cfcb7 100644 --- a/build/android/pylib/instrumentation/instrumentation_test_instance.py +++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -401,7 +401,11 @@ Returns: The test name as a string. """ - return '%s%s%s' % (test['class'], sep, test['method']) + test_name = '%s%s%s' % (test['class'], sep, test['method']) + assert ' *-:' not in test_name, ( + 'The test name must not contain any of the characters in " *-:". See ' + 'https://crbug.com/912199') + return test_name def GetTestNameWithoutParameterPostfix( @@ -440,7 +444,13 @@ """ display_name = GetTestName(test, sep=sep) if test.get('flags', [None])[0]: - display_name = '%s with %s' % (display_name, ' '.join(test['flags'])) + sanitized_flags = [x.replace('-', '_') for x in test['flags']] + display_name = '%s_with_%s' % (display_name, '_'.join(sanitized_flags)) + + assert ' *-:' not in display_name, ( + 'The test name must not contain any of the characters in " *-:". See ' + 'https://crbug.com/912199') + return display_name
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance_test.py b/build/android/pylib/instrumentation/instrumentation_test_instance_test.py index 646ac060..1d3b4d7 100755 --- a/build/android/pylib/instrumentation/instrumentation_test_instance_test.py +++ b/build/android/pylib/instrumentation/instrumentation_test_instance_test.py
@@ -652,7 +652,7 @@ self.assertEquals( instrumentation_test_instance.GetUniqueTestName( test, sep='.'), - 'org.chromium.TestA.testSimple with enable_features=abc') + 'org.chromium.TestA.testSimple_with_enable_features=abc') def testGetTestNameWithoutParameterPostfix(self): test = {
diff --git a/build/android/pylib/results/presentation/standard_gtest_merge.py b/build/android/pylib/results/presentation/standard_gtest_merge.py index 10754d9..29513da 100755 --- a/build/android/pylib/results/presentation/standard_gtest_merge.py +++ b/build/android/pylib/results/presentation/standard_gtest_merge.py
@@ -48,7 +48,8 @@ 'Either it ran for too long (hard timeout) or it didn\'t produce ' 'I/O for an extended period of time (I/O timeout)') elif state == u'COMPLETED': - json_data, err_msg = load_shard_json(index, jsons_to_merge) + json_data, err_msg = load_shard_json(index, result.get('task_id'), + jsons_to_merge) if json_data: # Set-like fields. for key in ('all_tests', 'disabled_tests', 'global_tags', 'links'): @@ -84,12 +85,13 @@ OUTPUT_JSON_SIZE_LIMIT = 100 * 1024 * 1024 # 100 MB -def load_shard_json(index, jsons_to_merge): +def load_shard_json(index, task_id, jsons_to_merge): """Reads JSON output of the specified shard. Args: - jsons_to_merge: List of json files to be merge. - index: The index of the shard to load data for. + output_dir: The directory in which to look for the JSON output to load. + index: The index of the shard to load data for, this is for old api. + task_id: The directory of the shard to load data for, this is for new api. Returns: A tuple containing: * The contents of path, deserialized into a python object. @@ -98,8 +100,9 @@ """ matching_json_files = [ j for j in jsons_to_merge - if (os.path.basename(j) == 'output.json' - and os.path.basename(os.path.dirname(j)) == str(index))] + if (os.path.basename(j) == 'output.json' and + (os.path.basename(os.path.dirname(j)) == str(index) or + os.path.basename(os.path.dirname(j)) == task_id))] if not matching_json_files: print >> sys.stderr, 'shard %s test output missing' % index
diff --git a/build/android/pylib/utils/test_filter.py b/build/android/pylib/utils/test_filter.py index b42c7390..35664a6 100644 --- a/build/android/pylib/utils/test_filter.py +++ b/build/android/pylib/utils/test_filter.py
@@ -9,9 +9,12 @@ _CMDLINE_NAME_SEGMENT_RE = re.compile( r' with(?:out)? \{[^\}]*\}') +class ConflictingPositiveFiltersException(Exception): + """Raised when both filter file and filter argument have positive filters.""" + def ParseFilterFile(input_lines): - """Converts test filter file contents into --gtest_filter argument. + """Converts test filter file contents to positive and negative pattern lists. See //testing/buildbot/filters/README.md for description of the syntax that |input_lines| are expected to follow. @@ -23,7 +26,7 @@ Args: input_lines: An iterable (e.g. a list or a file) containing input lines. Returns: - a string suitable for feeding as an argument of --gtest_filter parameter. + tuple containing the lists of positive patterns and negative patterns """ # Strip comments and whitespace from each line and filter non-empty lines. stripped_lines = (l.split('#', 1)[0].strip() for l in input_lines) @@ -31,13 +34,9 @@ # Split the tests into positive and negative patterns (gtest treats # every pattern after the first '-' sign as an exclusion). - positive_patterns = ':'.join(l for l in filter_lines if l[0] != '-') - negative_patterns = ':'.join(l[1:] for l in filter_lines if l[0] == '-') - if negative_patterns: - negative_patterns = '-' + negative_patterns - - # Join the filter lines into one, big --gtest_filter argument. - return positive_patterns + negative_patterns + positive_patterns = [l for l in filter_lines if l[0] != '-'] + negative_patterns = [l[1:] for l in filter_lines if l[0] == '-'] + return positive_patterns, negative_patterns def AddFilterOptions(parser): @@ -46,13 +45,7 @@ Args: parser: an argparse.ArgumentParser instance. """ - filter_group = parser.add_mutually_exclusive_group() - filter_group.add_argument( - '-f', '--test-filter', '--gtest_filter', '--gtest-filter', - dest='test_filter', - help='googletest-style filter string.', - default=os.environ.get('GTEST_FILTER')) - filter_group.add_argument( + parser.add_argument( # Deprecated argument. '--gtest-filter-file', # New argument. @@ -61,6 +54,12 @@ help='Path to file that contains googletest-style filter strings. ' 'See also //testing/buildbot/filters/README.md.') + filter_group = parser.add_mutually_exclusive_group() + filter_group.add_argument( + '-f', '--test-filter', '--gtest_filter', '--gtest-filter', + dest='test_filter', + help='googletest-style filter string.', + default=os.environ.get('GTEST_FILTER')) filter_group.add_argument( '--isolated-script-test-filter', help='isolated script filter string. ' @@ -72,15 +71,41 @@ Args: args: an argparse.Namespace instance resulting from a using parser to which the filter options above were added. + + Raises: + ConflictingPositiveFiltersException if both filter file and command line + specify positive filters. """ - parsed_filter = None + positive_patterns = [] + negative_patterns = [] if args.isolated_script_test_filter: args.test_filter = args.isolated_script_test_filter.replace('::', ':') if args.test_filter: parsed_filter = _CMDLINE_NAME_SEGMENT_RE.sub( '', args.test_filter.replace('#', '.')) - elif args.test_filter_file: - with open(args.test_filter_file, 'r') as f: - parsed_filter = ParseFilterFile(f) + split_filter = parsed_filter.split('-', 1) + positive = '' + negative = '' + if len(split_filter) == 1: + positive = split_filter[0] + else: + positive, negative = split_filter + positive_patterns = [f for f in positive.split(':') if f] + negative_patterns = [f for f in negative.split(':') if f] - return parsed_filter + + if args.test_filter_file: + with open(args.test_filter_file, 'r') as f: + positive_file_patterns, negative_file_patterns = ParseFilterFile(f) + if positive_file_patterns: + if positive_patterns: + raise ConflictingPositiveFiltersException( + 'Cannot specify positive pattern in both filter file and ' + + 'filter command line argument') + positive_patterns = positive_file_patterns + negative_patterns.extend(negative_file_patterns) + + final_filter = ':'.join(positive_patterns) + if negative_patterns: + final_filter += '-' + ':'.join(negative_patterns) + return final_filter
diff --git a/build/android/pylib/utils/test_filter_test.py b/build/android/pylib/utils/test_filter_test.py index c70a58f6..b91ced480 100755 --- a/build/android/pylib/utils/test_filter_test.py +++ b/build/android/pylib/utils/test_filter_test.py
@@ -5,6 +5,7 @@ import argparse import sys +import tempfile import unittest from pylib.utils import test_filter @@ -20,7 +21,7 @@ 'positive3' ] actual = test_filter.ParseFilterFile(input_lines) - expected = 'positive1:positive2:positive3' + expected = ['positive1', 'positive2', 'positive3'], [] self.assertEquals(expected, actual) def testParseFilterFile_onlyPositive(self): @@ -29,7 +30,7 @@ 'positive2' ] actual = test_filter.ParseFilterFile(input_lines) - expected = 'positive1:positive2' + expected = ['positive1', 'positive2'], [] self.assertEquals(expected, actual) def testParseFilterFile_onlyNegative(self): @@ -38,7 +39,7 @@ '-negative2' ] actual = test_filter.ParseFilterFile(input_lines) - expected = '-negative1:negative2' + expected = [], ['negative1', 'negative2'] self.assertEquals(expected, actual) def testParseFilterFile_positiveAndNegative(self): @@ -49,7 +50,7 @@ '-negative2' ] actual = test_filter.ParseFilterFile(input_lines) - expected = 'positive1:positive2-negative1:negative2' + expected = ['positive1', 'positive2'], ['negative1', 'negative2'] self.assertEquals(expected, actual) @@ -85,6 +86,63 @@ actual = test_filter.InitializeFilterFromArgs(args) self.assertEquals(actual, expected) + def testFilterArgWithPositiveFilterInFilterFile(self): + parser = argparse.ArgumentParser() + test_filter.AddFilterOptions(parser) + with tempfile.NamedTemporaryFile() as tmp_file: + tmp_file.write('positive1\npositive2\n-negative2\n-negative3\n') + tmp_file.seek(0) + args = parser.parse_args([ + '--test-filter=-negative1', + '--test-launcher-filter-file', + tmp_file.name]) + expected = 'positive1:positive2-negative1:negative2:negative3' + actual = test_filter.InitializeFilterFromArgs(args) + self.assertEquals(actual, expected) + + def testFilterFileWithPositiveFilterInFilterArg(self): + parser = argparse.ArgumentParser() + test_filter.AddFilterOptions(parser) + with tempfile.NamedTemporaryFile() as tmp_file: + tmp_file.write('-negative2\n-negative3\n') + tmp_file.seek(0) + args = parser.parse_args([ + '--test-filter', + 'positive1:positive2-negative1', + '--test-launcher-filter-file', + tmp_file.name]) + expected = 'positive1:positive2-negative1:negative2:negative3' + actual = test_filter.InitializeFilterFromArgs(args) + self.assertEquals(actual, expected) + + def testPositiveFilterInBothFileAndArg(self): + parser = argparse.ArgumentParser() + test_filter.AddFilterOptions(parser) + with tempfile.NamedTemporaryFile() as tmp_file: + tmp_file.write('positive1\n') + tmp_file.seek(0) + args = parser.parse_args([ + '--test-filter', + 'positive2', + '--test-launcher-filter-file', + tmp_file.name]) + with self.assertRaises(test_filter.ConflictingPositiveFiltersException): + test_filter.InitializeFilterFromArgs(args) + + def testFilterArgWithFilterFileAllNegative(self): + parser = argparse.ArgumentParser() + test_filter.AddFilterOptions(parser) + with tempfile.NamedTemporaryFile() as tmp_file: + tmp_file.write('-negative3\n-negative4\n') + tmp_file.seek(0) + args = parser.parse_args([ + '--test-filter=-negative1:negative2', + '--test-launcher-filter-file', + tmp_file.name]) + expected = '-negative1:negative2:negative3:negative4' + actual = test_filter.InitializeFilterFromArgs(args) + self.assertEquals(actual, expected) + if __name__ == '__main__': sys.exit(unittest.main())
diff --git a/build/android/resource_sizes.py b/build/android/resource_sizes.py index cc86811..b1d5fae8 100755 --- a/build/android/resource_sizes.py +++ b/build/android/resource_sizes.py
@@ -178,7 +178,7 @@ skip_extract_lib = not bool(int(m.group(1))) # Dex decompression overhead varies by Android version. - m = re.search(r'android:minSdkVersion\(\w+\)=\(type \w+\)(\w+)\n', output) + m = re.search(r'android:minSdkVersion\(\w+\)=\(type \w+\)(\w+)', output) sdk_version = int(m.group(1), 16) return sdk_version, skip_extract_lib
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index aee01f00..18460a4 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -448,6 +448,15 @@ args += [ "--use_proxy_hash" ] } + if (defined(invoker.enable_native_mocks) && invoker.enable_native_mocks) { + args += [ "--enable_proxy_mocks" ] + } + + if (defined(invoker.require_native_mocks) && + invoker.require_native_mocks) { + args += [ "--require_mocks" ] + } + if (defined(invoker.header_output)) { outputs += [ invoker.header_output ] args += [ @@ -1292,6 +1301,8 @@ _jni_srcjar_target = "${target_name}__final_jni" _outer_target_name = target_name generate_jni_registration(_jni_srcjar_target) { + enable_native_mocks = true + require_native_mocks = true target = ":$_outer_target_name" } @@ -3542,6 +3553,10 @@ # ignore_aidl: Whether to ignore .aidl files found with the .aar. # ignore_assets: Whether to ignore assets found in the .aar. # ignore_native_libraries: Whether to ignore .so files found in the .aar. + # See also extract_native_libraries. + # extract_native_libraries: Whether to extract .so files found in the .aar. + # If the file contains .so, either extract_native_libraries or + # ignore_native_libraries must be set. # create_srcjar: If false, does not create an R.java file. # TODO(jbudorick@): remove this arguments after crbug.com/522043 is fixed. # requires_android: Whether this target can only be used for compiling @@ -3562,6 +3577,8 @@ _ignore_assets = defined(invoker.ignore_assets) && invoker.ignore_assets _ignore_native_libraries = defined(invoker.ignore_native_libraries) && invoker.ignore_native_libraries + _extract_native_libraries = defined(invoker.extract_native_libraries) && + invoker.extract_native_libraries # Scan the AAR file and determine the resources and jar files. # Some libraries might not have resources; others might have two jars. @@ -3590,9 +3607,16 @@ "android_aar_prebuilt() assets not yet supported." + " Implement or use ignore_assets = true." + " http://crbug.com/643966") - assert(_ignore_native_libraries || !_scanned_files.has_native_libraries, - "android_aar_prebuilt() with .so files is not supported." + - " Use ignore_native_libraries = true to silence this error.") + assert( + !_scanned_files.has_native_libraries || + (_ignore_native_libraries || _extract_native_libraries), + "android_aar_prebuilt() contains .so files." + + " Please set ignore_native_libraries or extract_native_libraries.") + assert( + !(_ignore_native_libraries && _extract_native_libraries), + "ignore_native_libraries and extract_native_libraries cannot both be set.") + assert(!_scanned_files.has_native_libraries || + _scanned_files.native_libraries != []) assert(_scanned_files.has_classes_jar || _scanned_files.subjars == []) action_with_pydeps(_unpack_target_name) { @@ -3633,6 +3657,12 @@ if (_scanned_files.has_proguard_flags) { outputs += [ "${_output_path}/proguard.txt" ] } + + if (_extract_native_libraries && _scanned_files.has_native_libraries) { + outputs += get_path_info( + rebase_path(_scanned_files.native_libraries, "", _output_path), + "abspath") + } } # Create the android_resources target for resources.
diff --git a/build/config/chromeos/rules.gni b/build/config/chromeos/rules.gni index 5dc04ae..802f335 100644 --- a/build/config/chromeos/rules.gni +++ b/build/config/chromeos/rules.gni
@@ -12,7 +12,14 @@ # Ensure that if one is set, the other is as well. assert(cros_board == "" == (cros_sdk_version == "")) -is_chromeos_chrome = cros_board != "" +# The build is using the Simple Chrome "cros chrome-sdk" to target real hardware +# or a VM, not linux-chromeos. +# NOTE: Most test targets in Chrome expect to run under linux-chromeos, so some +# have compile-time asserts that intentionally fail when this build flag is set. +# Build and run the tests for linux-chromeos instead. +# https://chromium.googlesource.com/chromium/src/+/master/docs/chromeos_build_instructions.md +# https://chromium.googlesource.com/chromiumos/docs/+/master/simple_chrome_workflow.md +is_cros_chrome_sdk = cros_board != "" # Creates a script at $generated_script that can be used to launch a cros VM # and optionally run a test within it.
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index c00e7a1..13ca75e 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -93,12 +93,12 @@ auto_profile_path = "" # Optimize symbol files for maximizing goma cache hit rate. This is on by - # default when goma is enabled on Linux and Windows. + # default when goma is enabled on Android, Linux, and Windows. # But setting this to true may make it harder to debug binaries on Linux. # See below reference for detail. # https://chromium.googlesource.com/chromium/src/+/master/docs/linux_debugging.md#Source-level-debug-with-fdebug_compilation_dir strip_absolute_paths_from_debug_symbols = - ((is_linux || (is_win && use_lld)) && use_goma) || is_nacl + ((is_android || is_linux || (is_win && use_lld)) && use_goma) || is_nacl # Allow projects that wish to stay on C++11 to override Chromium's default. use_cxx11 = false @@ -1488,7 +1488,7 @@ # recognize. cflags += [ # Ignore warnings about MSVC optimization pragmas. - # TODO(thakis): Only for no_chromium_code? http://crbug.com/505314 + # TODO(thakis): Only for no_chromium_code? http://crbug.com/912662 "-Wno-ignored-pragma-optimize", ] if (is_fuchsia) {
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni index 0fa0f6e4..d1e1243 100644 --- a/build/config/compiler/compiler.gni +++ b/build/config/compiler/compiler.gni
@@ -13,7 +13,7 @@ if (is_chromeos) { import("//build/config/chromeos/rules.gni") } else { - is_chromeos_chrome = false + is_cros_chrome_sdk = false } if (is_android) { @@ -179,13 +179,14 @@ declare_args() { # Whether to use the gold linker from binutils instead of lld or bfd. - use_gold = !use_lld && !(is_chromecast && is_linux && - (current_cpu == "arm" || current_cpu == "mipsel")) && - ((is_linux && (current_cpu == "x64" || current_cpu == "x86" || - current_cpu == "arm" || current_cpu == "mipsel" || - current_cpu == "mips64el")) || - (is_android && (current_cpu == "x86" || current_cpu == "x64" || - current_cpu == "arm" || current_cpu == "arm64"))) + use_gold = + !use_lld && !(is_chromecast && is_linux && + (current_cpu == "arm" || current_cpu == "mipsel")) && + ((is_linux && (current_cpu == "x64" || current_cpu == "x86" || + current_cpu == "arm" || current_cpu == "arm64" || + current_cpu == "mipsel" || current_cpu == "mips64el")) || + (is_android && (current_cpu == "x86" || current_cpu == "x64" || + current_cpu == "arm" || current_cpu == "arm64"))) } # If it wasn't manually set, set to an appropriate default. @@ -205,7 +206,7 @@ # If you use is_win_fastlink = true or lld or clang then you can set # symbol_level = 2 when using goma. symbol_level = 1 - } else if (is_chromeos_chrome) { + } else if (is_cros_chrome_sdk) { # Use lower symbol level in Simple Chrome build for faster link time. # For Simple Chrome, this should take precedence over is_official_build, # turned on by --internal.
diff --git a/build/gn_run_binary.py b/build/gn_run_binary.py index d7f7165e..d1685a3 100644 --- a/build/gn_run_binary.py +++ b/build/gn_run_binary.py
@@ -8,13 +8,16 @@ python gn_run_binary.py <binary_name> [args ...] """ +import os import subprocess import sys # This script is designed to run binaries produced by the current build. We -# always prefix it with "./" to avoid picking up system versions that might +# may prefix it with "./" to avoid picking up system versions that might # also be on the path. -path = './' + sys.argv[1] +path = sys.argv[1] +if not os.path.isabs(path): + path = './' + path # The rest of the arguments are passed directly to the executable. args = [path] + sys.argv[2:]
diff --git a/cc/animation/keyframe_model.cc b/cc/animation/keyframe_model.cc index 13b2f10..2e3c8d9 100644 --- a/cc/animation/keyframe_model.cc +++ b/cc/animation/keyframe_model.cc
@@ -168,12 +168,70 @@ (ConvertMonotonicTimeToLocalTime(monotonic_time) + time_offset_); } -bool KeyframeModel::InEffect(base::TimeTicks monotonic_time) const { - return ConvertMonotonicTimeToLocalTime(monotonic_time) + time_offset_ >= - base::TimeDelta() || - (fill_mode_ == FillMode::BOTH || fill_mode_ == FillMode::BACKWARDS); +KeyframeModel::Phase KeyframeModel::CalculatePhase( + base::TimeDelta local_time) const { + base::TimeDelta before_active_boundary_time = + std::max(-time_offset_, base::TimeDelta()); + if (local_time < before_active_boundary_time || + (local_time == before_active_boundary_time && playback_rate_ < 0)) { + return KeyframeModel::Phase::BEFORE; + } + // Scaling the duration is against spec but needed to comply with the cc + // implementation. By spec (in blink) the playback rate is an Animation level + // concept but in cc it's per KeyframeModel. We grab the active time + // calculated here and later scale it with the playback rate in order to get a + // proper progress. Therefore we need to un-scale it here. This can be fixed + // once we scale the local time by playback rate. See + // https://crbug.com/912407. + base::TimeDelta active_duration = + curve_->Duration() * iterations_ / std::abs(playback_rate_); + // TODO(crbug.com/909794): By spec end time = max(start delay + duration + + // end delay, 0). The logic should be updated once "end delay" is supported. + base::TimeDelta active_after_boundary_time = + // Negative iterations_ represents "infinite iterations". + iterations_ >= 0 + ? std::max(-time_offset_ + active_duration, base::TimeDelta()) + : base::TimeDelta::Max(); + if (local_time > active_after_boundary_time || + (local_time == active_after_boundary_time && playback_rate_ > 0)) { + return KeyframeModel::Phase::AFTER; + } + return KeyframeModel::Phase::ACTIVE; } +base::Optional<base::TimeDelta> KeyframeModel::CalculateActiveTime( + base::TimeTicks monotonic_time) const { + base::TimeDelta local_time = ConvertMonotonicTimeToLocalTime(monotonic_time); + KeyframeModel::Phase phase = CalculatePhase(local_time); + DCHECK(playback_rate_); + switch (phase) { + case KeyframeModel::Phase::BEFORE: + if (fill_mode_ == FillMode::BACKWARDS || fill_mode_ == FillMode::BOTH) + return std::max(local_time + time_offset_, base::TimeDelta()); + return base::nullopt; + case KeyframeModel::Phase::ACTIVE: + return local_time + time_offset_; + case KeyframeModel::Phase::AFTER: + if (fill_mode_ == FillMode::FORWARDS || fill_mode_ == FillMode::BOTH) { + DCHECK_GE(iterations_, 0); + base::TimeDelta active_duration = + curve_->Duration() * iterations_ / std::abs(playback_rate_); + return std::max(std::min(local_time + time_offset_, active_duration), + base::TimeDelta()); + } + return base::nullopt; + default: + NOTREACHED(); + return base::nullopt; + } +} + +bool KeyframeModel::InEffect(base::TimeTicks monotonic_time) const { + return CalculateActiveTime(monotonic_time).has_value(); +} + +// TODO(yigu): Local time should be scaled by playback rate by spec. +// https://crbug.com/912407. base::TimeDelta KeyframeModel::ConvertMonotonicTimeToLocalTime( base::TimeTicks monotonic_time) const { // When waiting on receiving a start time, then our global clock is 'stuck' at @@ -190,17 +248,11 @@ base::TimeDelta KeyframeModel::TrimTimeToCurrentIteration( base::TimeTicks monotonic_time) const { - base::TimeDelta local_time = ConvertMonotonicTimeToLocalTime(monotonic_time); - return TrimLocalTimeToCurrentIteration(local_time); -} - -base::TimeDelta KeyframeModel::TrimLocalTimeToCurrentIteration( - base::TimeDelta local_time) const { - // Check for valid parameters DCHECK(playback_rate_); DCHECK_GE(iteration_start_, 0); - base::TimeDelta active_time = local_time + time_offset_; + DCHECK(InEffect(monotonic_time)); + base::TimeDelta active_time = CalculateActiveTime(monotonic_time).value(); base::TimeDelta start_offset = curve_->Duration() * iteration_start_; // Return start offset if we are before the start of the keyframe model @@ -218,10 +270,6 @@ base::TimeDelta active_duration = repeated_duration / std::abs(playback_rate_); - // Check if we are past active duration - if (iterations_ > 0 && active_time >= active_duration) - active_time = active_duration; - // Calculate the scaled active time base::TimeDelta scaled_active_time; if (playback_rate_ < 0) {
diff --git a/cc/animation/keyframe_model.h b/cc/animation/keyframe_model.h index 39557caa..b970ca6e 100644 --- a/cc/animation/keyframe_model.h +++ b/cc/animation/keyframe_model.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/macros.h" +#include "base/optional.h" #include "base/time/time.h" #include "cc/animation/animation_export.h" #include "cc/trees/element_id.h" @@ -55,6 +56,8 @@ enum class FillMode { NONE, FORWARDS, BACKWARDS, BOTH, AUTO }; + enum class Phase { BEFORE, ACTIVE, AFTER }; + static std::unique_ptr<KeyframeModel> Create( std::unique_ptr<AnimationCurve> curve, int keyframe_model_id, @@ -202,8 +205,9 @@ base::TimeDelta ConvertMonotonicTimeToLocalTime( base::TimeTicks monotonic_time) const; - base::TimeDelta TrimLocalTimeToCurrentIteration( - base::TimeDelta local_time) const; + KeyframeModel::Phase CalculatePhase(base::TimeDelta local_time) const; + base::Optional<base::TimeDelta> CalculateActiveTime( + base::TimeTicks monotonic_time) const; std::unique_ptr<AnimationCurve> curve_;
diff --git a/cc/animation/keyframe_model_unittest.cc b/cc/animation/keyframe_model_unittest.cc index 3757df9e..e205231 100644 --- a/cc/animation/keyframe_model_unittest.cc +++ b/cc/animation/keyframe_model_unittest.cc
@@ -350,7 +350,7 @@ std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1)); keyframe_model->set_start_time(TicksFromSecondsF(4)); keyframe_model->set_direction(KeyframeModel::Direction::REVERSE); - EXPECT_EQ(0, + EXPECT_EQ(1.0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.0)) .InSecondsF()); EXPECT_EQ(1.0, @@ -399,9 +399,6 @@ EXPECT_EQ(0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(1.0)) .InSecondsF()); - EXPECT_EQ(0, - keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(1.0)) - .InSecondsF()); } TEST(KeyframeModelTest, TrimTimeNegativeTimeOffset) { @@ -427,7 +424,7 @@ keyframe_model->set_time_offset(TimeDelta::FromMilliseconds(-4000)); keyframe_model->set_direction(KeyframeModel::Direction::REVERSE); - EXPECT_EQ(0, + EXPECT_EQ(1.0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.0)) .InSecondsF()); EXPECT_EQ(1.0, @@ -739,11 +736,12 @@ TEST(KeyframeModelTest, TrimTimePlaybackNormalReverse) { std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1, 2, -1)); - EXPECT_EQ(0, + EXPECT_EQ(2.0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(-1.0)) .InSecondsF()); - EXPECT_EQ(2, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0)) - .InSecondsF()); + EXPECT_EQ(2.0, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0)) + .InSecondsF()); EXPECT_EQ(1.5, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.5)) .InSecondsF()); @@ -764,11 +762,12 @@ TEST(KeyframeModelTest, TrimTimePlaybackSlowReverse) { std::unique_ptr<KeyframeModel> keyframe_model( CreateKeyframeModel(1, 2, -0.5)); - EXPECT_EQ(0, + EXPECT_EQ(2.0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(-1.0)) .InSecondsF()); - EXPECT_EQ(2, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0)) - .InSecondsF()); + EXPECT_EQ(2.0, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0)) + .InSecondsF()); EXPECT_EQ(1.75, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.5)) .InSecondsF()); @@ -799,11 +798,12 @@ TEST(KeyframeModelTest, TrimTimePlaybackFastReverse) { std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1, 2, -2)); - EXPECT_EQ(0, + EXPECT_EQ(2.0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(-1.0)) .InSecondsF()); - EXPECT_EQ(2, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0)) - .InSecondsF()); + EXPECT_EQ(2.0, + keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0)) + .InSecondsF()); EXPECT_EQ(1.5, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(0.25)) .InSecondsF()); @@ -927,7 +927,7 @@ TEST(KeyframeModelTest, TrimTimeAlternateTwoIterationsPlaybackFastReverse) { std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(2, 2, 2)); keyframe_model->set_direction(KeyframeModel::Direction::ALTERNATE_REVERSE); - EXPECT_EQ(0.0, + EXPECT_EQ(2.0, keyframe_model->TrimTimeToCurrentIteration(TicksFromSecondsF(-1.0)) .InSecondsF()); EXPECT_EQ(2.0, @@ -1193,9 +1193,12 @@ TEST(KeyframeModelTest, InEffectFillMode) { std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1)); keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); + // Effect before start is not InEffect EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + // Effect at start is InEffect EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); - EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); + // Effect at end is not InEffect + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); keyframe_model->set_fill_mode(KeyframeModel::FillMode::FORWARDS); EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); @@ -1205,6 +1208,29 @@ keyframe_model->set_fill_mode(KeyframeModel::FillMode::BACKWARDS); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); + + keyframe_model->set_fill_mode(KeyframeModel::FillMode::BOTH); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); +} + +TEST(KeyframeModelTest, InEffectFillModeNoneWithNegativePlaybackRate) { + std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1, 1, -1)); + keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); + + keyframe_model->set_fill_mode(KeyframeModel::FillMode::FORWARDS); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); + + keyframe_model->set_fill_mode(KeyframeModel::FillMode::BACKWARDS); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); keyframe_model->set_fill_mode(KeyframeModel::FillMode::BOTH); @@ -1213,27 +1239,63 @@ EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); } -TEST(KeyframeModelTest, InEffectFillModePlayback) { - std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(1, 1, -1)); +TEST(KeyframeModelTest, InEffectFillModeWithIterations) { + std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(2, 1)); keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); keyframe_model->set_fill_mode(KeyframeModel::FillMode::FORWARDS); EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); - EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); keyframe_model->set_fill_mode(KeyframeModel::FillMode::BACKWARDS); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); - EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); keyframe_model->set_fill_mode(KeyframeModel::FillMode::BOTH); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); +} + +TEST(KeyframeModelTest, InEffectFillModeWithInfiniteIterations) { + std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(-1, 1)); + keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); + + keyframe_model->set_fill_mode(KeyframeModel::FillMode::FORWARDS); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); + + keyframe_model->set_fill_mode(KeyframeModel::FillMode::BACKWARDS); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); + + keyframe_model->set_fill_mode(KeyframeModel::FillMode::BOTH); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); +} + +TEST(KeyframeModelTest, InEffectReverseWithIterations) { + std::unique_ptr<KeyframeModel> keyframe_model(CreateKeyframeModel(2, 1)); + keyframe_model->set_fill_mode(KeyframeModel::FillMode::NONE); + // KeyframeModel::direction_ doesn't affect InEffect. + keyframe_model->set_direction(KeyframeModel::Direction::REVERSE); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(-1.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(0.0))); + EXPECT_TRUE(keyframe_model->InEffect(TicksFromSecondsF(1.0))); + EXPECT_FALSE(keyframe_model->InEffect(TicksFromSecondsF(2.0))); } TEST(KeyframeModelTest, ToString) {
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc index cb7ee65c2..7eebde4 100644 --- a/cc/layers/heads_up_display_layer_impl.cc +++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -592,19 +592,20 @@ flags->setAntiAlias(true); flags->setTextSize(size); flags->setTypeface(typeface_); + SkFont font = flags->ToSkFont(); if (align == TextAlign::kCenter) { - auto width = flags->ToSkPaint().measureText(text.c_str(), text.length()); + auto width = + font.measureText(text.c_str(), text.length(), kUTF8_SkTextEncoding); x -= width * 0.5f; } else if (align == TextAlign::kRight) { - auto width = flags->ToSkPaint().measureText(text.c_str(), text.length()); + auto width = + font.measureText(text.c_str(), text.length(), kUTF8_SkTextEncoding); x -= width; } - auto sk_paint = flags->ToSkPaint(); - auto text_blob = SkTextBlob::MakeFromText( - text.c_str(), text.length(), - SkFont(sk_paint.refTypeface(), sk_paint.getTextSize())); - canvas->drawTextBlob(std::move(text_blob), x, y, *flags); + canvas->drawTextBlob( + SkTextBlob::MakeFromText(text.c_str(), text.length(), font), x, y, + *flags); } void HeadsUpDisplayLayerImpl::DrawText(PaintCanvas* canvas, @@ -954,8 +955,8 @@ label_flags.setTypeface(typeface_); label_flags.setColor(stroke_color); - const SkScalar label_text_width = label_flags.ToSkPaint().measureText( - label_text.c_str(), label_text.length()); + const SkScalar label_text_width = label_flags.ToSkFont().measureText( + label_text.c_str(), label_text.length(), kUTF8_SkTextEncoding); canvas->drawRect(SkRect::MakeWH(label_text_width + 2 * kPadding, kFontHeight + 2 * kPadding), label_flags);
diff --git a/cc/layers/layer.h b/cc/layers/layer.h index b90f455..b1dbfc56 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h
@@ -851,9 +851,6 @@ void UpdateScrollOffset(const gfx::ScrollOffset&); // Encapsulates all data, callbacks or interfaces received from the embedder. - // TODO(khushalsagar): This is only valid when PropertyTrees are built - // internally in cc. Update this for the SPv2 path where blink generates - // PropertyTrees. struct Inputs { explicit Inputs(int layer_id); ~Inputs();
diff --git a/cc/paint/discardable_image_map.cc b/cc/paint/discardable_image_map.cc index c9462f1..eeda858 100644 --- a/cc/paint/discardable_image_map.cc +++ b/cc/paint/discardable_image_map.cc
@@ -195,10 +195,10 @@ PaintOpType op_type = static_cast<PaintOpType>(op->type); if (op_type == PaintOpType::DrawImage) { auto* image_op = static_cast<DrawImageOp*>(op); - auto* sk_image = image_op->image.GetSkImage().get(); - AddImage(image_op->image, - SkRect::MakeIWH(sk_image->width(), sk_image->height()), - op_rect, ctm, image_op->flags.getFilterQuality()); + AddImage( + image_op->image, + SkRect::MakeIWH(image_op->image.width(), image_op->image.height()), + op_rect, ctm, image_op->flags.getFilterQuality()); } else if (op_type == PaintOpType::DrawImageRect) { auto* image_rect_op = static_cast<DrawImageRectOp*>(op); SkMatrix matrix = ctm; @@ -355,14 +355,16 @@ SkIRect src_irect; src_rect.roundOut(&src_irect); - // Make a note if any image was originally specified in a non-sRGB color - // space. - SkColorSpace* source_color_space = paint_image.color_space(); - color_stats_total_pixel_count_ += image_rect.size().GetCheckedArea(); - color_stats_total_image_count_++; - if (!source_color_space || source_color_space->isSRGB()) { - color_stats_srgb_pixel_count_ += image_rect.size().GetCheckedArea(); - color_stats_srgb_image_count_++; + if (!paint_image.IsPaintWorklet()) { + // Make a note if any image was originally specified in a non-sRGB color + // space. + SkColorSpace* source_color_space = paint_image.color_space(); + color_stats_total_pixel_count_ += image_rect.size().GetCheckedArea(); + color_stats_total_image_count_++; + if (!source_color_space || source_color_space->isSRGB()) { + color_stats_srgb_pixel_count_ += image_rect.size().GetCheckedArea(); + color_stats_srgb_image_count_++; + } } auto& rects = image_id_to_rects_[paint_image.stable_id()];
diff --git a/cc/paint/paint_image.h b/cc/paint/paint_image.h index d12ff5b9..4ba78f9 100644 --- a/cc/paint/paint_image.h +++ b/cc/paint/paint_image.h
@@ -184,6 +184,7 @@ bool IsLazyGenerated() const { return paint_worklet_input_ ? false : GetSkImage()->isLazyGenerated(); } + bool IsPaintWorklet() const { return !!paint_worklet_input_; } bool IsTextureBacked() const { return paint_worklet_input_ ? false : GetSkImage()->isTextureBacked(); }
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc index 8e007c4..7ea6952 100644 --- a/cc/paint/paint_op_buffer_unittest.cc +++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -1167,8 +1167,7 @@ SkTextBlobBuilder builder; int glyph_count = 5; - const auto& run = - builder.allocRun(font, glyph_count, 1.2f, 2.3f, &test_rects[0]); + const auto& run = builder.allocRun(font, glyph_count, 1.2f, 2.3f); // allocRun() allocates only the glyph buffer. std::fill(run.glyphs, run.glyphs + glyph_count, 0); return builder.make(); @@ -1179,13 +1178,12 @@ SkTextBlobBuilder builder; int glyph_count = 5; - const auto& run1 = - builder.allocRun(font, glyph_count, 1.2f, 2.3f, &test_rects[0]); + const auto& run1 = builder.allocRun(font, glyph_count, 1.2f, 2.3f); // allocRun() allocates only the glyph buffer. std::fill(run1.glyphs, run1.glyphs + glyph_count, 0); glyph_count = 16; - const auto& run2 = builder.allocRunPos(font, glyph_count, &test_rects[1]); + const auto& run2 = builder.allocRunPos(font, glyph_count); // allocRun() allocates the glyph buffer, and 2 scalars per glyph for the // pos buffer. std::fill(run2.glyphs, run2.glyphs + glyph_count, 0); @@ -1193,8 +1191,7 @@ font.setTypeface(test_typefaces[1][1]); glyph_count = 8; - const auto& run3 = - builder.allocRunPosH(font, glyph_count, 0, &test_rects[2]); + const auto& run3 = builder.allocRunPosH(font, glyph_count, 0); // allocRun() allocates the glyph buffer, and 1 scalar per glyph for the // pos buffer. std::fill(run3.glyphs, run3.glyphs + glyph_count, 0);
diff --git a/cc/raster/raster_source_unittest.cc b/cc/raster/raster_source_unittest.cc index b910052..c694083 100644 --- a/cc/raster/raster_source_unittest.cc +++ b/cc/raster/raster_source_unittest.cc
@@ -8,9 +8,11 @@ #include <memory> +#include "base/memory/scoped_refptr.h" #include "cc/raster/playback_image_provider.h" #include "cc/test/fake_recording_source.h" #include "cc/test/skia_common.h" +#include "cc/test/test_paint_worklet_input.h" #include "cc/test/test_skcanvas.h" #include "cc/tiles/software_image_decode_cache.h" #include "testing/gtest/include/gtest/gtest.h" @@ -184,6 +186,63 @@ } } +TEST(RasterSourceTest, MultiPaintWorkletImages) { + gfx::Size layer_bounds(512, 512); + + std::unique_ptr<FakeRecordingSource> recording_source = + FakeRecordingSource::CreateFilledRecordingSource(layer_bounds); + + scoped_refptr<TestPaintWorkletInput> input1 = + base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(32.0f, 32.0f)); + scoped_refptr<TestPaintWorkletInput> input2 = + base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(64.0f, 64.0f)); + scoped_refptr<TestPaintWorkletInput> input3 = + base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(100.0f, 100.0f)); + + PaintImage discardable_image[2][2]; + discardable_image[0][0] = CreatePaintWorkletPaintImage(input1); + discardable_image[0][1] = CreatePaintWorkletPaintImage(input2); + discardable_image[1][1] = CreatePaintWorkletPaintImage(input3); + + recording_source->add_draw_image(discardable_image[0][0], gfx::Point(0, 0)); + recording_source->add_draw_image(discardable_image[0][1], gfx::Point(260, 0)); + recording_source->add_draw_image(discardable_image[1][1], + gfx::Point(260, 260)); + recording_source->Rerecord(); + + scoped_refptr<RasterSource> raster = recording_source->CreateRasterSource(); + + // Tile sized iterators. These should find only one image. + { + std::vector<const DrawImage*> images; + raster->GetDiscardableImagesInRect(gfx::Rect(0, 0, 256, 256), &images); + EXPECT_EQ(1u, images.size()); + EXPECT_EQ(discardable_image[0][0], images[0]->paint_image()); + } + // Shifted tile sized iterators. These should find only one image. + { + std::vector<const DrawImage*> images; + raster->GetDiscardableImagesInRect(gfx::Rect(260, 260, 256, 256), &images); + EXPECT_EQ(1u, images.size()); + EXPECT_EQ(discardable_image[1][1], images[0]->paint_image()); + } + // Ensure there's no discardable pixel refs in the empty cell + { + std::vector<const DrawImage*> images; + raster->GetDiscardableImagesInRect(gfx::Rect(0, 256, 256, 256), &images); + EXPECT_EQ(0u, images.size()); + } + // Layer sized iterators. These should find three images. + { + std::vector<const DrawImage*> images; + raster->GetDiscardableImagesInRect(gfx::Rect(0, 0, 512, 512), &images); + EXPECT_EQ(3u, images.size()); + EXPECT_EQ(discardable_image[0][0], images[0]->paint_image()); + EXPECT_EQ(discardable_image[0][1], images[1]->paint_image()); + EXPECT_EQ(discardable_image[1][1], images[2]->paint_image()); + } +} + TEST(RasterSourceTest, PixelRefIteratorDiscardableRefsOneTile) { gfx::Size layer_bounds(512, 512);
diff --git a/cc/raster/single_thread_task_graph_runner.cc b/cc/raster/single_thread_task_graph_runner.cc index 0bb96a4..afb47e8 100644 --- a/cc/raster/single_thread_task_graph_runner.cc +++ b/cc/raster/single_thread_task_graph_runner.cc
@@ -29,7 +29,7 @@ const base::SimpleThread::Options& thread_options) { thread_.reset( new base::DelegateSimpleThread(this, thread_name, thread_options)); - thread_->Start(); + thread_->StartAsync(); } void SingleThreadTaskGraphRunner::Shutdown() {
diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc index 5ff45c1e..06f912e 100644 --- a/cc/test/layer_tree_pixel_test.cc +++ b/cc/test/layer_tree_pixel_test.cc
@@ -260,7 +260,8 @@ SkBitmap LayerTreePixelTest::CopyMailboxToBitmap( const gfx::Size& size, const gpu::Mailbox& mailbox, - const gpu::SyncToken& sync_token) { + const gpu::SyncToken& sync_token, + const gfx::ColorSpace& color_space) { SkBitmap bitmap; std::unique_ptr<gpu::GLInProcessContext> context = CreateTestInProcessContext(); @@ -291,9 +292,9 @@ gl->DeleteFramebuffers(1, &fbo); gl->DeleteTextures(1, &texture_id); - bitmap.allocN32Pixels(size.width(), size.height()); - // TODO(miu): Provide color space in this allocN32Pixels() call. - // http://crbug.com/758057 + EXPECT_TRUE(color_space.IsValid()); + bitmap.allocPixels(SkImageInfo::MakeN32Premul(size.width(), size.height(), + color_space.ToSkColorSpace())); uint8_t* out_pixels = static_cast<uint8_t*>(bitmap.getPixels());
diff --git a/cc/test/layer_tree_pixel_test.h b/cc/test/layer_tree_pixel_test.h index e96c555b..3c95b739 100644 --- a/cc/test/layer_tree_pixel_test.h +++ b/cc/test/layer_tree_pixel_test.h
@@ -16,6 +16,10 @@ class SkBitmap; +namespace gfx { +class ColorSpace; +} + namespace viz { class CopyOutputRequest; class CopyOutputResult; @@ -85,7 +89,8 @@ SkBitmap CopyMailboxToBitmap(const gfx::Size& size, const gpu::Mailbox& mailbox, - const gpu::SyncToken& sync_token); + const gpu::SyncToken& sync_token, + const gfx::ColorSpace& color_space); void Finish();
diff --git a/cc/test/skia_common.cc b/cc/test/skia_common.cc index 81b028f..e942b7a 100644 --- a/cc/test/skia_common.cc +++ b/cc/test/skia_common.cc
@@ -90,6 +90,15 @@ SkImageInfo::MakeN32Premul(size.width(), size.height())); } +PaintImage CreatePaintWorkletPaintImage( + scoped_refptr<PaintWorkletInput> input) { + auto paint_image = PaintImageBuilder::WithDefault() + .set_id(1) + .set_paint_worklet_input(std::move(input)) + .TakePaintImage(); + return paint_image; +} + PaintImage CreateDiscardablePaintImage(const gfx::Size& size, sk_sp<SkColorSpace> color_space, bool allocate_encoded_data,
diff --git a/cc/test/skia_common.h b/cc/test/skia_common.h index b6b9771a..1c05275 100644 --- a/cc/test/skia_common.h +++ b/cc/test/skia_common.h
@@ -25,6 +25,7 @@ namespace cc { class DisplayItemList; +class PaintWorkletInput; class SkottieWrapper; void DrawDisplayList(unsigned char* buffer, @@ -39,6 +40,8 @@ sk_sp<PaintImageGenerator> CreatePaintImageGenerator(const gfx::Size& size); +PaintImage CreatePaintWorkletPaintImage(scoped_refptr<PaintWorkletInput> input); + PaintImage CreateDiscardablePaintImage( const gfx::Size& size, sk_sp<SkColorSpace> color_space = nullptr,
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index e4b85c0..26503ead 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -747,7 +747,7 @@ // and cc needs to compute property trees from that. // In layer lists mode, blink sends cc property trees directly so they do not // need to be built here. Layer lists mode is used by BlinkGenPropertyTrees - // and SlimmingPaintV2. + // and CompositeAfterPaint. if (!IsUsingLayerLists()) { TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::BuildPropertyTrees"); Layer* root_scroll = @@ -1142,26 +1142,29 @@ SetLocalSurfaceIdAllocationFromParent( local_surface_id_allocation_from_parent); - bool changed = false; + bool device_viewport_size_changed = false; if (device_viewport_size_ != device_viewport_size) { device_viewport_size_ = device_viewport_size; - changed = true; + device_viewport_size_changed = true; } + bool painted_device_scale_factor_changed = false; + bool device_scale_factor_changed = false; if (settings_.use_painted_device_scale_factor) { DCHECK_EQ(device_scale_factor_, 1.f); if (painted_device_scale_factor_ != device_scale_factor) { painted_device_scale_factor_ = device_scale_factor; - changed = true; + painted_device_scale_factor_changed = true; } } else { DCHECK_EQ(painted_device_scale_factor_, 1.f); if (device_scale_factor_ != device_scale_factor) { device_scale_factor_ = device_scale_factor; - changed = true; + device_scale_factor_changed = true; } } - if (changed) { + if (device_viewport_size_changed || painted_device_scale_factor_changed || + device_scale_factor_changed) { SetPropertyTreesNeedRebuild(); SetNeedsCommit(); #if defined(OS_MACOSX) @@ -1173,7 +1176,11 @@ << "Invalid Surface Id State: !has_pushed " << !has_pushed_local_surface_id_from_parent_ << " new_id_request " << new_local_surface_id_request_ << " !valid_parent_id " - << !local_surface_id_allocation_from_parent_.IsValid(); + << !local_surface_id_allocation_from_parent_.IsValid() + << ". Changed state: device_viewport_size " + << device_viewport_size_changed << " painted_device_scale_factor " + << painted_device_scale_factor_changed << " device_scale_factor " + << device_scale_factor_changed; #endif } } @@ -1650,8 +1657,8 @@ ElementListType list_type, const FilterOperations& filters) { if (IsUsingLayerLists()) { - // In SPv2 we always have property trees and can set the filter - // directly on the effect node. + // In BlinkGenPropertyTrees/CompositeAfterPaint we always have property + // tree nodes and can set the filter directly on the effect node. property_trees_.effect_tree.OnFilterAnimated(element_id, filters); return; }
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 59f9e54..26fb7923 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -3469,8 +3469,8 @@ // We may not find an associated layer for the root or secondary root node - // that's fine, they're not associated with any elements on the page. We also - // won't find a layer for the inner viewport (in SPv2) since it doesn't - // require hit testing. + // won't find a layer for the inner viewport (in CompositeAfterPaint) since it + // doesn't require hit testing. DCHECK(layer || scroll_node->id == ScrollTree::kRootNodeId || scroll_node->id == ScrollTree::kSecondaryRootNodeId || scroll_node->scrolls_inner_viewport);
diff --git a/cc/trees/layer_tree_host_pixeltest_filters.cc b/cc/trees/layer_tree_host_pixeltest_filters.cc index 67e3b25..e5559ac 100644 --- a/cc/trees/layer_tree_host_pixeltest_filters.cc +++ b/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -481,22 +481,22 @@ background->AddChild(layer); // Add a slightly transparent blue layer. - scoped_refptr<SolidColorLayer> filter = - CreateSolidColorLayer(gfx::Rect(100, 0, 100, 200), SK_ColorBLUE); - filter->SetOpacity(0.137f); + SkColor transparent_blue = SkColorSetARGB(0x23, 0x00, 0x00, 0xFF); + scoped_refptr<SolidColorLayer> filter_layer = + CreateSolidColorLayer(gfx::Rect(100, 0, 100, 200), transparent_blue); // Add some rotation so that we can see that it blurs only under the layer. gfx::Transform transform_filter; transform_filter.RotateAboutZAxis(10.0); - filter->SetTransform(transform_filter); - - background->AddChild(filter); + filter_layer->SetTransform(transform_filter); // Add a blur filter to the blue layer. FilterOperations filters; filters.Append(FilterOperation::CreateBlurFilter( 5.0f, SkBlurImageFilter::kClamp_TileMode)); - filter->SetBackdropFilters(filters); + filter_layer->SetBackdropFilters(filters); + + background->AddChild(filter_layer); // Allow some fuzziness so that this doesn't fail when Skia makes minor // changes to blur or rectangle rendering.
diff --git a/cc/trees/layer_tree_host_pixeltest_readback.cc b/cc/trees/layer_tree_host_pixeltest_readback.cc index 17484e50..d6e39e34b 100644 --- a/cc/trees/layer_tree_host_pixeltest_readback.cc +++ b/cc/trees/layer_tree_host_pixeltest_readback.cc
@@ -125,12 +125,13 @@ gpu::Mailbox mailbox = result->GetTextureResult()->mailbox; gpu::SyncToken sync_token = result->GetTextureResult()->sync_token; + gfx::ColorSpace color_space = result->GetTextureResult()->color_space; EXPECT_EQ(result->GetTextureResult()->color_space, output_color_space_); std::unique_ptr<viz::SingleReleaseCallback> release_callback = result->TakeTextureOwnership(); const SkBitmap bitmap = - CopyMailboxToBitmap(result->size(), mailbox, sync_token); + CopyMailboxToBitmap(result->size(), mailbox, sync_token, color_space); release_callback->Run(gpu::SyncToken(), false); ReadbackResultAsBitmap(std::make_unique<viz::CopyOutputSkBitmapResult>(
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h index 89118ace..6c01aa1 100644 --- a/cc/trees/property_tree.h +++ b/cc/trees/property_tree.h
@@ -625,8 +625,8 @@ // respective property node. This will eventually allow simplifying logic in // various places that today has to map from element id to layer id, and then // from layer id to the respective property node. Completing that work is - // pending the launch of Slimming Paint v2 and reworking UI compositor logic - // to produce cc property trees and these maps. + // pending the launch of BlinkGenPropertyTrees and reworking UI compositor + // logic to produce cc property trees and these maps. base::flat_map<ElementId, int> element_id_to_effect_node_index; base::flat_map<ElementId, int> element_id_to_scroll_node_index; base::flat_map<ElementId, int> element_id_to_transform_node_index;
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 0ca0819..a430113 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -224,7 +224,6 @@ ] data_deps = [ "//chrome/app/version_assembly:version_assembly_manifest", - "//chrome/chrome_proxy", "//chrome/elevation_service", "//chrome/notification_helper", ]
diff --git a/chrome/VERSION b/chrome/VERSION index 67efd2f1..c9f9730 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=73 MINOR=0 -BUILD=3633 +BUILD=3637 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 84a2b69e..44419fe8 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -48,6 +48,7 @@ "$target_gen_dir/trichrome_chrome_apk/AndroidManifest.xml" app_hooks_impl = "java/src/org/chromium/chrome/browser/AppHooksImpl.java" +_chrome_version_java_file = "$target_gen_dir/templates/org/chromium/chrome/browser/ChromeVersionConstants.java" # Exclude it from JNI registration if VR is not enabled. chrome_jni_sources_blacklist = [] @@ -230,6 +231,7 @@ ":chrome_download_java_resources", ":chrome_public_android_manifest", ":chrome_public_apk_template_resources", + ":chrome_version_constants", ":document_tab_model_info_proto_java", ":partner_location_descriptor_proto_java", ":thumbnail_cache_entry_proto_java", @@ -249,6 +251,7 @@ "//chrome/android/webapk/libs/common:splash_java", "//chrome/android/webapk/libs/runtime_library:webapk_service_aidl_java", "//components/autofill/android:autofill_java", + "//components/autofill_assistant/browser:proto_java", "//components/background_task_scheduler:background_task_scheduler_java", "//components/background_task_scheduler:background_task_scheduler_task_ids_java", "//components/bookmarks/common/android:bookmarks_java", @@ -343,7 +346,6 @@ srcjar_deps = [ ":chrome_android_java_enums_srcjar", ":chrome_android_java_google_api_keys_srcjar", - ":chrome_version_srcjar", ":photo_picker_aidl", ":resource_id_javagen", "//chrome:assist_ranker_prediction_enum_javagen", @@ -372,6 +374,7 @@ "//components/ntp_snippets:ntp_snippets_java_enums_srcjar", "//components/ntp_tiles:ntp_tiles_enums_java", "//components/offline_pages/core:offline_page_model_enums_java", + "//components/password_manager/core/browser:password_manager_java_enums_srcjar", "//components/search_engines:search_engine_type_java", "//components/security_state/core:security_state_enums_java", "//components/signin/core/browser:investigated_scenario_java", @@ -383,7 +386,10 @@ android_manifest_for_lint = chrome_public_android_manifest # From java_sources.gni. - java_files = chrome_java_sources + [ app_hooks_impl ] + java_files = chrome_java_sources + [ + app_hooks_impl, + _chrome_version_java_file, + ] # Include sources from feed_java_sources.gni. java_files += feed_java_sources @@ -566,25 +572,12 @@ package_name = manifest_package } -chrome_version_java_dir = "$root_gen_dir/templates/chrome_version_java" -chrome_version_java_file = "$chrome_version_java_dir/org/chromium/chrome/browser/ChromeVersionConstants.java" -process_version("chrome_version_java") { +process_version("chrome_version_constants") { template_file = "java/ChromeVersionConstants.java.version" sources = [ branding_file_path, ] - output = chrome_version_java_file -} - -zip("chrome_version_srcjar") { - inputs = [ - chrome_version_java_file, - ] - output = "$target_gen_dir/$target_name.srcjar" - base_dir = chrome_version_java_dir - deps = [ - ":chrome_version_java", - ] + output = _chrome_version_java_file } # Files used for both chrome tests and VR/AR tests @@ -1823,7 +1816,12 @@ android_app_bundle("chrome_public_bundle") { bundle_name = "ChromePublic" base_module_target = ":chrome_public_base_module" - proguard_enabled = !is_java_debug + if (!is_java_debug) { + proguard_enabled = true + if (!experimental_use_r8) { + enable_multidex = true + } + } # Signing is very slow, only do that for official builds. sign_bundle = is_official_build
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedConfiguration.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedConfiguration.java index eb8afe04..d2187b5 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedConfiguration.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedConfiguration.java
@@ -59,6 +59,10 @@ /** Default value for triggering immediate pagination. */ public static final boolean TRIGGER_IMMEDIATE_PAGINATION_DEFAULT = false; + private static final String USE_TIMEOUT_SCHEDULER = "use_timeout_scheduler"; + /** Default value for the type of scheduler handling. */ + public static final boolean USE_TIMEOUT_SCHEDULER_DEFAULT = true; + private static final String VIEW_LOG_THRESHOLD = "view_log_threshold"; /** Default value for logging view threshold. */ public static final double VIEW_LOG_THRESHOLD_DEFAULT = 0.66d; @@ -139,6 +143,17 @@ TRIGGER_IMMEDIATE_PAGINATION_DEFAULT); } + /** + * @return Whether the Feed's session handling should use logic to deal with timeouts and + * placing new results below the fold. + */ + @VisibleForTesting + static boolean getUseTimeoutScheduler() { + return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean( + ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS, USE_TIMEOUT_SCHEDULER, + USE_TIMEOUT_SCHEDULER_DEFAULT); + } + /** @return How much of a card must be on screen to generate a UMA log view. */ @VisibleForTesting static double getViewLogThreshold() { @@ -166,6 +181,7 @@ .put(ConfigKey.SESSION_LIFETIME_MS, FeedConfiguration.getSessionLifetimeMs()) .put(ConfigKey.TRIGGER_IMMEDIATE_PAGINATION, FeedConfiguration.getTriggerImmediatePagination()) + .put(ConfigKey.USE_TIMEOUT_SCHEDULER, FeedConfiguration.getUseTimeoutScheduler()) .put(ConfigKey.VIEW_LOG_THRESHOLD, FeedConfiguration.getViewLogThreshold()) .build(); }
diff --git a/chrome/android/java/proguard.flags b/chrome/android/java/proguard.flags index e673817..85dc2b5 100644 --- a/chrome/android/java/proguard.flags +++ b/chrome/android/java/proguard.flags
@@ -5,14 +5,20 @@ # Fragments loaded by name via Fragment.instantiate(Context,String) # Not all fragments in this package are PreferenceFragments. E.g. HomepageEditor # is a normal Fragment. --keep public class org.chromium.chrome.browser.preferences.** extends android.app.Fragment +-keep public class org.chromium.chrome.browser.** extends android.app.Fragment { + public <init>(); +} # These classes aren't themselves referenced, but __ProcessService[0,1,2...] are # referenced, and we look up these services by appending a number onto the name # of the base class. Thus, we need to keep the base class name around so that # the child classes can be looked up. --keep class org.chromium.content.app.SandboxedProcessService --keep class org.chromium.content.app.PrivilegedProcessService +-keep class org.chromium.content.app.SandboxedProcessService { + public <init>(); +} +-keep class org.chromium.content.app.PrivilegedProcessService { + public <init>(); +} # SearchView is used in website_preferences_menu.xml and is constructed by # Android using reflection.
diff --git a/chrome/android/java/res/drawable-hdpi/infobar_multiple_downloads.png b/chrome/android/java/res/drawable-hdpi/infobar_multiple_downloads.png deleted file mode 100644 index c391f1b..0000000 --- a/chrome/android/java/res/drawable-hdpi/infobar_multiple_downloads.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/infobar_multiple_downloads.png b/chrome/android/java/res/drawable-mdpi/infobar_multiple_downloads.png deleted file mode 100644 index 904b3774..0000000 --- a/chrome/android/java/res/drawable-mdpi/infobar_multiple_downloads.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/infobar_multiple_downloads.png b/chrome/android/java/res/drawable-xhdpi/infobar_multiple_downloads.png deleted file mode 100644 index 71561df..0000000 --- a/chrome/android/java/res/drawable-xhdpi/infobar_multiple_downloads.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/infobar_multiple_downloads.png b/chrome/android/java/res/drawable-xxhdpi/infobar_multiple_downloads.png deleted file mode 100644 index 0f12de2f..0000000 --- a/chrome/android/java/res/drawable-xxhdpi/infobar_multiple_downloads.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/infobar_multiple_downloads.png b/chrome/android/java/res/drawable-xxxhdpi/infobar_multiple_downloads.png deleted file mode 100644 index 32ff86f..0000000 --- a/chrome/android/java/res/drawable-xxxhdpi/infobar_multiple_downloads.png +++ /dev/null Binary files differ
diff --git a/chrome/android/java/res/layout-sw600dp/location_bar.xml b/chrome/android/java/res/layout-sw600dp/location_bar.xml index 8d1ef7f1..8b98003 100644 --- a/chrome/android/java/res/layout-sw600dp/location_bar.xml +++ b/chrome/android/java/res/layout-sw600dp/location_bar.xml
@@ -8,31 +8,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> - <FrameLayout android:id="@+id/location_bar_icon" - android:layout_width="@dimen/location_bar_icon_width" - android:layout_height="match_parent" - android:layout_gravity="start|center_vertical"> - <ImageView android:id="@+id/navigation_button" - style="@style/LocationBarButton" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_gravity="center_vertical" - android:src="@drawable/ic_omnibox_page" - android:scaleType="center" - android:contentDescription="@string/accessibility_toolbar_btn_site_info"/> - <org.chromium.ui.widget.ChromeImageButton - android:id="@+id/security_button" - style="@style/LocationBarButton" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:scaleType="center" - android:layout_gravity="center" - android:alpha="0" - android:visibility="invisible" - app:tint="@color/dark_mode_tint" /> - </FrameLayout> - - <include layout="@layout/location_bar_status" /> + <include layout="@layout/location_status" /> <include android:id="@+id/url_bar"
diff --git a/chrome/android/java/res/layout-sw600dp/location_status.xml b/chrome/android/java/res/layout-sw600dp/location_status.xml new file mode 100644 index 0000000..15079c3 --- /dev/null +++ b/chrome/android/java/res/layout-sw600dp/location_status.xml
@@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. --> + +<!-- Layout for the LocationBar's StatusView for devices with >600dp min width --> +<merge + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + + <FrameLayout android:id="@+id/location_bar_icon" + android:layout_width="@dimen/location_bar_icon_width" + android:layout_height="match_parent" + android:layout_gravity="start|center_vertical"> + + <ImageView android:id="@+id/navigation_button" + style="@style/LocationBarButton" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="center_vertical" + android:src="@drawable/ic_omnibox_page" + android:scaleType="center" + android:contentDescription="@string/accessibility_toolbar_btn_site_info" /> + + <org.chromium.ui.widget.ChromeImageButton + android:id="@+id/security_button" + style="@style/LocationBarButton" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:scaleType="center" + android:layout_gravity="center" + android:alpha="0" + android:visibility="invisible" + app:tint="@color/dark_mode_tint" /> + + </FrameLayout> + + <include layout="@layout/location_bar_status" /> +</merge>
diff --git a/chrome/android/java/res/layout/autofill_name_fixflow.xml b/chrome/android/java/res/layout/autofill_name_fixflow.xml index 2af6d52d..c091f65 100644 --- a/chrome/android/java/res/layout/autofill_name_fixflow.xml +++ b/chrome/android/java/res/layout/autofill_name_fixflow.xml
@@ -10,42 +10,38 @@ android:layout_height="wrap_content" style="@style/AlertDialogContent" android:minHeight="36dp" - android:orientation="vertical" + android:layout_marginBottom="32dp" + android:layout_marginTop="6dp" + android:orientation="horizontal" android:gravity="center_vertical"> - <LinearLayout - android:layout_width="match_parent" + <org.chromium.chrome.browser.widget.CompatibilityTextInputLayout + android:id="@+id/cc_name" + android:labelFor="@+id/cc_name_edit" + android:focusableInTouchMode="true" + android:layout_width="0dp" + android:layout_weight="1" + android:layout_height="wrap_content"> + + <!-- TODO(crbug.com/900912): Fix and remove lint ignore --> + <EditText + tools:ignore="Autofill,LabelFor" + android:id="@+id/cc_name_edit" + android:hint="@string/autofill_card_holder_name" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:imeOptions="flagNoExtractUi" + android:inputType="textCapWords"/> + + </org.chromium.chrome.browser.widget.CompatibilityTextInputLayout> + + <ImageView + android:id="@+id/cc_name_tooltip_icon" + android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginBottom="14dp" - android:orientation="horizontal"> - - <org.chromium.chrome.browser.widget.CompatibilityTextInputLayout - android:id="@+id/cc_name" - android:labelFor="@+id/cc_name_edit" - android:layout_marginTop="6dp" - android:layout_width="0dp" - android:layout_weight="1" - android:layout_height="wrap_content"> - - <!-- TODO(crbug.com/900912): Fix and remove lint ignore --> - <EditText - tools:ignore="Autofill,LabelFor" - android:id="@+id/cc_name_edit" - android:hint="@string/autofill_card_holder_name" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:imeOptions="flagNoExtractUi" - android:inputType="textCapWords"/> - - </org.chromium.chrome.browser.widget.CompatibilityTextInputLayout> - - <ImageView - android:id="@+id/cc_name_tooltip_icon" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:padding="12dp" - android:src="@drawable/help_outline" - android:contentDescription="@string/learn_more" /> - </LinearLayout> + android:layout_marginTop="6dp" + android:src="@drawable/btn_info" + android:layout_gravity="center" + android:contentDescription="@string/learn_more" /> </LinearLayout>
diff --git a/chrome/android/java/res/layout/location_bar_base.xml b/chrome/android/java/res/layout/location_bar_base.xml index 20a6004..829752f 100644 --- a/chrome/android/java/res/layout/location_bar_base.xml +++ b/chrome/android/java/res/layout/location_bar_base.xml
@@ -10,34 +10,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> - <FrameLayout android:id="@+id/location_bar_icon" - android:layout_width="@dimen/location_bar_start_icon_width" - android:layout_height="match_parent" - android:paddingEnd="4dp" - android:visibility="gone" > - - <ImageView android:id="@+id/navigation_button" - style="@style/LocationBarButton" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_gravity="center" - android:scaleType="center" - android:contentDescription="@string/accessibility_toolbar_btn_site_info" /> - - <org.chromium.ui.widget.ChromeImageButton - android:id="@+id/security_button" - style="@style/LocationBarButton" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:scaleType="center" - android:layout_gravity="center" - android:alpha="0" - android:visibility="invisible" - app:tint="@color/dark_mode_tint" /> - - </FrameLayout> - - <include layout="@layout/location_bar_status" /> + <include layout="@layout/location_status" /> <include android:layout_width="match_parent"
diff --git a/chrome/android/java/res/layout/location_status.xml b/chrome/android/java/res/layout/location_status.xml new file mode 100644 index 0000000..f0acfc2 --- /dev/null +++ b/chrome/android/java/res/layout/location_status.xml
@@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. --> + +<!-- Layout for the LocationBar's StatusView for most devices --> +<merge + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + + <FrameLayout android:id="@+id/location_bar_icon" + android:layout_width="@dimen/location_bar_start_icon_width" + android:layout_height="match_parent" + android:paddingEnd="4dp" + android:visibility="gone" > + + <ImageView android:id="@+id/navigation_button" + style="@style/LocationBarButton" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="center" + android:scaleType="center" + android:contentDescription="@string/accessibility_toolbar_btn_site_info" /> + + <org.chromium.ui.widget.ChromeImageButton + android:id="@+id/security_button" + style="@style/LocationBarButton" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:scaleType="center" + android:layout_gravity="center" + android:alpha="0" + android:visibility="invisible" + app:tint="@color/dark_mode_tint" /> + + </FrameLayout> + + <include layout="@layout/location_bar_status" /> +</merge>
diff --git a/chrome/android/java/res/layout/sync_passphrase_types.xml b/chrome/android/java/res/layout/sync_passphrase_types.xml index d7b16c02..2332e5e 100644 --- a/chrome/android/java/res/layout/sync_passphrase_types.xml +++ b/chrome/android/java/res/layout/sync_passphrase_types.xml
@@ -13,10 +13,4 @@ android:id="@+id/passphrase_types" android:layout_width="match_parent" android:layout_height="wrap_content" /> - <org.chromium.ui.widget.TextViewWithClickableSpans - android:id="@+id/reset_sync_text" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="25dp" - android:visibility="gone" /> </LinearLayout>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml index 343cd0f..a24fc0f3 100644 --- a/chrome/android/java/res/values/dimens.xml +++ b/chrome/android/java/res/values/dimens.xml
@@ -404,7 +404,7 @@ <dimen name="custom_tabs_toolbar_horizontal_margin_no_close">8dp</dimen> <dimen name="toolbar_icon_height">24dp</dimen> <dimen name="min_toolbar_icon_side_padding">6dp</dimen> - <dimen name="custom_tabs_url_lite_separator_margin">3dp</dimen> + <dimen name="custom_tabs_url_lite_separator_margin">4dp</dimen> <dimen name="custom_tabs_url_text_size">12sp</dimen> <dimen name="custom_tabs_title_text_size">16sp</dimen> <dimen name="custom_tabs_bottom_bar_max_height">120dp</dimen> @@ -525,6 +525,7 @@ <dimen name="clear_text_button_end_padding">10dp</dimen> <dimen name="sync_promo_view_padding">16dp</dimen> <dimen name="open_new_tab_animation_y_translation">-20dp</dimen> + <dimen name="sync_passphrase_type_instructions_padding">25dp</dimen> <!-- Context Menu Dimensions --> <dimen name="context_menu_header_image_width_padding">15dp</dimen>
diff --git a/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_sheet.xml b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_sheet.xml index ba962e65..8ee07c6 100644 --- a/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_sheet.xml +++ b/chrome/android/java/res_autofill_assistant/layout/autofill_assistant_sheet.xml
@@ -77,7 +77,7 @@ android:layout_width="24dp" android:layout_height="24dp" android:layout_marginEnd="12dp" - android:src="@drawable/ic_bug_report_24dp" + app:srcCompat="@drawable/ic_bug_report_24dp" android:tint="@color/light_icon_color" android:background="?attr/selectableItemBackground" android:contentDescription="@string/menu_send_feedback" />
diff --git a/chrome/android/java/res_autofill_assistant/layout/init_screen.xml b/chrome/android/java/res_autofill_assistant/layout/init_screen.xml index 2691de0..98bfd0d 100644 --- a/chrome/android/java/res_autofill_assistant/layout/init_screen.xml +++ b/chrome/android/java/res_autofill_assistant/layout/init_screen.xml
@@ -94,7 +94,7 @@ <Space android:layout_width="0dp" android:layout_height="25dp"/> <!-- Terms and Conditions message and link --> - <FrameLayout + <LinearLayout android:layout_height="wrap_content" android:layout_width="match_parent" android:paddingStart="12dp" @@ -113,16 +113,17 @@ android:layout_gravity="center" android:textAppearance="@style/BlackBodyDefault" android:text="@string/autofill_assistant_google_terms_description" /> - </FrameLayout> + </LinearLayout> - - <!-- Horizontal layout for the buttons --> + <!-- Layout for the buttons --> + <Space android:layout_width="0dp" android:layout_height="32dp"/> <LinearLayout android:layout_width="match_parent" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" android:layout_height="wrap_content" android:gravity="bottom|center" - android:orientation="horizontal" - android:paddingTop="32dp"> + android:orientation="horizontal"> <!-- 'No' button --> <org.chromium.ui.widget.ButtonCompat @@ -140,6 +141,11 @@ android:text="@string/no_thanks" style="@style/TextButton" /> + <Space + android:layout_weight="1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + <!-- 'Yes' button --> <org.chromium.ui.widget.ButtonCompat android:id="@+id/button_init_ok"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/UrlConstants.java b/chrome/android/java/src/org/chromium/chrome/browser/UrlConstants.java index 87e906b..170cafe 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/UrlConstants.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/UrlConstants.java
@@ -78,5 +78,5 @@ "https://myactivity.google.com/myactivity/?utm_source=chrome_h"; public static final String EXPLORE_HOST = "explore"; - public static final String EXPLORE_URL = "chrome-native://explore"; + public static final String EXPLORE_URL = "chrome-native://explore/"; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowPrompt.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowPrompt.java index 49dea1aa..736bb1d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowPrompt.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillNameFixFlowPrompt.java
@@ -7,6 +7,8 @@ import android.content.Context; import android.support.v4.view.MarginLayoutParamsCompat; import android.support.v4.view.ViewCompat; +import android.text.Editable; +import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.inputmethod.EditorInfo; @@ -27,8 +29,7 @@ /** * Prompt that asks users to confirm user's name before saving card to Google. */ -public class AutofillNameFixFlowPrompt implements ModalDialogView.Controller { - +public class AutofillNameFixFlowPrompt implements TextWatcher, ModalDialogView.Controller { /** * An interface to handle the interaction with * an AutofillNameFixFlowPrompt object. @@ -69,7 +70,6 @@ mUserNameInput = (EditText) mDialogView.findViewById(R.id.cc_name_edit); mUserNameInput.setText(inferredName, BufferType.EDITABLE); - mUserNameInput.setSelection(inferredName.length()); mNameFixFlowTooltipIcon = (ImageView) mDialogView.findViewById(R.id.cc_name_tooltip_icon); mNameFixFlowTooltipIcon.setOnClickListener((view) -> onTooltipIconClicked()); @@ -103,12 +103,25 @@ mContext = activity; mModalDialogManager = activity.getModalDialogManager(); mModalDialogManager.showDialog(mDialogModel, ModalDialogManager.ModalDialogType.APP); + mUserNameInput.addTextChangedListener(this); } protected void dismiss(@DialogDismissalCause int dismissalCause) { mModalDialogManager.dismissDialog(mDialogModel, dismissalCause); } + @Override + public void afterTextChanged(Editable s) { + mDialogModel.set(ModalDialogProperties.POSITIVE_BUTTON_DISABLED, + mUserNameInput.getText().toString().trim().isEmpty()); + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) {} + /** * Handle tooltip icon clicked. If tooltip is already opened, don't show another. Otherwise * create a new one.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetCoordinator.java index bdf740d..2eb42d5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetCoordinator.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.autofill.keyboard_accessory; import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.CREDENTIALS; +import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.PASSWORD_SHEET_DATA; import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.SCROLL_LISTENER; import android.content.Context; @@ -18,6 +19,7 @@ import org.chromium.base.VisibleForTesting; import org.chromium.chrome.R; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Item; +import org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece; import org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetViewBinder.ItemViewHolder; import org.chromium.chrome.browser.modelutil.ListModel; import org.chromium.chrome.browser.modelutil.PropertyModel; @@ -29,10 +31,12 @@ * as bottom sheet below the keyboard accessory. */ public class PasswordAccessorySheetCoordinator implements KeyboardAccessoryData.Tab.Listener { - private final PropertyModel mModel = new PropertyModel.Builder(CREDENTIALS, SCROLL_LISTENER) - .with(CREDENTIALS, new ListModel<>()) - .with(SCROLL_LISTENER, null) - .build(); + private final PropertyModel mModel = + new PropertyModel.Builder(CREDENTIALS, PASSWORD_SHEET_DATA, SCROLL_LISTENER) + .with(CREDENTIALS, new ListModel<>()) + .with(PASSWORD_SHEET_DATA, new ListModel<>()) + .with(SCROLL_LISTENER, null) + .build(); private final PasswordAccessorySheetMediator mMediator; private final KeyboardAccessoryData.Tab mTab; @@ -123,7 +127,12 @@ } @VisibleForTesting - ListModel<Item> getModelForTesting() { - return mMediator.getModelForTesting(); + ListModel<Item> getItemsForTesting() { + return mModel.get(CREDENTIALS); + } + + @VisibleForTesting + ListModel<AccessorySheetDataPiece> getSheetDataPiecesForTesting() { + return mModel.get(PASSWORD_SHEET_DATA); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetMediator.java index 99c97a4..b289b52 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetMediator.java
@@ -5,16 +5,18 @@ package org.chromium.chrome.browser.autofill.keyboard_accessory; import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.CREDENTIALS; +import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.PASSWORD_SHEET_DATA; import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.SCROLL_LISTENER; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; -import org.chromium.base.VisibleForTesting; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.AccessorySheetData; +import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.FooterCommand; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Item; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.UserInfo; -import org.chromium.chrome.browser.modelutil.ListModel; +import org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece; +import org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece.Type; import org.chromium.chrome.browser.modelutil.PropertyModel; import org.chromium.chrome.browser.modelutil.PropertyModelChangeProcessor; @@ -32,6 +34,7 @@ @Override public void onItemAvailable(int typeId, AccessorySheetData accessorySheetData) { mModel.get(CREDENTIALS).set(convertToItems(accessorySheetData)); + mModel.get(PASSWORD_SHEET_DATA).set(splitIntoDataPieces(accessorySheetData)); } PasswordAccessorySheetMediator( @@ -58,12 +61,13 @@ for (UserInfo.Field field : userInfo.getFields()) { items.add(Item.createSuggestion(field.getDisplayText(), field.getA11yDescription(), field.isObfuscated(), - item -> field.triggerSelection(), userInfo.getFaviconProvider())); + field.isSelectable() ? (item -> field.triggerSelection()) : null, + userInfo.getFaviconProvider())); } } if (!accessorySheetData.getFooterCommands().isEmpty()) items.add(Item.createDivider()); - for (KeyboardAccessoryData.FooterCommand command : accessorySheetData.getFooterCommands()) { + for (FooterCommand command : accessorySheetData.getFooterCommands()) { items.add(Item.createOption( command.getDisplayText(), command.getDisplayText(), (i) -> command.execute())); } @@ -71,8 +75,18 @@ return items.toArray(new Item[0]); } - @VisibleForTesting - ListModel<Item> getModelForTesting() { - return mModel.get(CREDENTIALS); + private AccessorySheetDataPiece[] splitIntoDataPieces(AccessorySheetData accessorySheetData) { + if (accessorySheetData == null) return new AccessorySheetDataPiece[0]; + + List<AccessorySheetDataPiece> items = new ArrayList<>(); + items.add(new AccessorySheetDataPiece(accessorySheetData.getTitle(), Type.TITLE)); + for (UserInfo userInfo : accessorySheetData.getUserInfoList()) { + items.add(new AccessorySheetDataPiece(userInfo, Type.PASSWORD_INFO)); + } + for (FooterCommand command : accessorySheetData.getFooterCommands()) { + items.add(new AccessorySheetDataPiece(command, Type.FOOTER_COMMAND)); + } + + return items.toArray(new AccessorySheetDataPiece[0]); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetProperties.java index 757bbc0..b999e8d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetProperties.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetProperties.java
@@ -4,12 +4,21 @@ package org.chromium.chrome.browser.autofill.keyboard_accessory; +import static android.support.v7.widget.RecyclerView.OnScrollListener; + +import android.support.annotation.IntDef; import android.support.v7.widget.RecyclerView; +import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.AccessorySheetData; +import org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetViewBinder.ItemViewHolder; import org.chromium.chrome.browser.modelutil.ListModel; import org.chromium.chrome.browser.modelutil.PropertyModel.ReadableObjectPropertyKey; import org.chromium.chrome.browser.modelutil.PropertyModel.WritableObjectPropertyKey; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +// TODO(crbug.com/902425): Drop the "Password-" as soon as its used for other sheets. /** * This class holds properties that are used to build a model for the password accessory sheet * component. These properties store the state of the {@link PasswordAccessorySheetView} which is @@ -20,8 +29,50 @@ class PasswordAccessorySheetProperties { static final ReadableObjectPropertyKey<ListModel<KeyboardAccessoryData.Item>> CREDENTIALS = new ReadableObjectPropertyKey<>(); - static final WritableObjectPropertyKey<RecyclerView.OnScrollListener> SCROLL_LISTENER = + static final ReadableObjectPropertyKey<ListModel<AccessorySheetDataPiece>> PASSWORD_SHEET_DATA = + new ReadableObjectPropertyKey<>(); + static final WritableObjectPropertyKey<OnScrollListener> SCROLL_LISTENER = new WritableObjectPropertyKey<>(); + /** + * The {@link AccessorySheetData} has to be mapped to single items in a {@link RecyclerView}. + * This class allows to wrap the {@link AccessorySheetData} into small chunks that are organized + * in a {@link ListModel}. A specific {@link ItemViewHolder}s is defined for each piece. + */ + static class AccessorySheetDataPiece { + @IntDef({Type.TITLE, Type.PASSWORD_INFO, Type.FOOTER_COMMAND}) + @Retention(RetentionPolicy.SOURCE) + public @interface Type { + /** + * An item in title style used to display text. Non-interactive. + */ + int TITLE = 1; + /** + * A section with user credentials. + */ + int PASSWORD_INFO = 2; + /** + * A command at the end of the accessory sheet tab. + */ + int FOOTER_COMMAND = 3; + } + + private Object mDataPiece; + private @Type int mType; + + AccessorySheetDataPiece(Object dataPiece, @Type int type) { + mDataPiece = dataPiece; + mType = type; + } + + public static int getType(AccessorySheetDataPiece accessorySheetDataPiece) { + return accessorySheetDataPiece.mType; + } + + public Object getDataPiece() { + return mDataPiece; + } + } + private PasswordAccessorySheetProperties() {} }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java index e833c7c..e27a489 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
@@ -121,15 +121,14 @@ } @Override - public void scrollBy(float distanceXRatio, float distanceYRatio) { - if (mUiControllerAndroid != 0) { - nativeScrollBy(mUiControllerAndroid, distanceXRatio, distanceYRatio); - } + public void updateTouchableArea() { + if (mUiControllerAndroid != 0) nativeUpdateTouchableArea(mUiControllerAndroid); } @Override - public void updateTouchableArea() { - if (mUiControllerAndroid != 0) nativeUpdateTouchableArea(mUiControllerAndroid); + public void onUserInteractionInsideTouchableArea() { + if (mUiControllerAndroid != 0) + nativeOnUserInteractionInsideTouchableArea(mUiControllerAndroid); } @Override @@ -500,9 +499,8 @@ String[] parameterValues, String locale, String countryCode); private native void nativeStart(long nativeUiControllerAndroid, String initialUrl); private native void nativeDestroy(long nativeUiControllerAndroid); - private native void nativeScrollBy( - long nativeUiControllerAndroid, float distanceXRatio, float distanceYRatio); private native void nativeUpdateTouchableArea(long nativeUiControllerAndroid); + private native void nativeOnUserInteractionInsideTouchableArea(long nativeUiControllerAndroid); private native void nativeOnScriptSelected(long nativeUiControllerAndroid, String scriptPath); private native void nativeOnChoice(long nativeUiControllerAndroid, byte[] serverPayload); private native void nativeOnAddressSelected(long nativeUiControllerAndroid, String guid);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java index 24483aa..1bd81ecc8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiDelegate.java
@@ -429,7 +429,8 @@ public void show() { if (mFullContainer.getVisibility() != View.VISIBLE) { mTouchEventFilter.init(mClient, mActivity.getFullscreenManager(), - mActivity.getActivityTab().getWebContents()); + mActivity.getActivityTab().getWebContents(), + mActivity.getCompositorViewHolder()); mFullContainer.setVisibility(View.VISIBLE); mBottomBarBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/FirstRunScreen.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/FirstRunScreen.java index 6b37d36..87be18d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/FirstRunScreen.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/FirstRunScreen.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.autofill_assistant; import android.text.SpannableString; +import android.text.method.LinkMovementMethod; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -14,6 +15,7 @@ import org.chromium.base.Callback; import org.chromium.chrome.autofill_assistant.R; import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.customtabs.CustomTabActivity; import org.chromium.ui.text.NoUnderlineClickableSpan; import org.chromium.ui.text.SpanApplier; @@ -33,20 +35,15 @@ String termsString = activity.getApplicationContext().getString( R.string.autofill_assistant_google_terms_description); - NoUnderlineClickableSpan termsDescriptionSpan = new NoUnderlineClickableSpan( + NoUnderlineClickableSpan termsSpan = new NoUnderlineClickableSpan( (widget) - -> { - // TODO(crbug.com/806868) enable when the URL for our terms & - // conditions is up. - /* - CustomTabActivity.showInfoPage(context, - activity.getApplicationContext().getString( - R.string.autofill_assistant_google_terms_url)); - */ - }); + -> CustomTabActivity.showInfoPage(activity.getApplicationContext(), + activity.getApplicationContext().getString( + R.string.autofill_assistant_google_terms_url))); SpannableString spannableMessage = SpanApplier.applySpans( - termsString, new SpanApplier.SpanInfo("<link>", "</link>", termsDescriptionSpan)); + termsString, new SpanApplier.SpanInfo("<link>", "</link>", termsSpan)); termsTextView.setText(spannableMessage); + termsTextView.setMovementMethod(LinkMovementMethod.getInstance()); // Set focusable for accessibility. initView.findViewById(R.id.init).setFocusable(true);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/ui/TouchEventFilter.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/ui/TouchEventFilter.java index 10b98614..d7095291 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/ui/TouchEventFilter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/ui/TouchEventFilter.java
@@ -12,6 +12,7 @@ import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.support.annotation.ColorInt; +import android.support.annotation.IntDef; import android.util.AttributeSet; import android.util.TypedValue; import android.view.GestureDetector; @@ -28,6 +29,8 @@ import org.chromium.content_public.browser.GestureStateListener; import org.chromium.content_public.browser.WebContents; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -37,11 +40,36 @@ * A view that filters out touch events, letting through only the touch events events that are * within a specified touchable area. * - * <p>This view decides whether to forward touch events. It does not manipulate them. This works at - * the level of low-level touch events (up, down, move, cancel), not gestures. + * <p>This view decides whether to forward gestures to the views below or the compositor view. + * + * <p>When accessibility (touch exploration) is enabled, this view: + * <ul> + * <li>avoids covering the top and bottom controls, even when the full overlay is on + * <li>is fully visible and accessible as long as a touchable area is available. + * TODO(crbug.com/806868):restrict access when using touch exploration as well + * </ul> + * + * <p>TODO(crbug.com/806868): To better integrate with the layout, the event filtering and + * forwarding implemented in this view should likely be a {@link + * org.chromium.chrome.browser.compositor.layouts.eventfilter.EventFilter}, and part of a scene. */ public class TouchEventFilter extends View implements ChromeFullscreenManager.FullscreenListener, GestureStateListener { + /** A client of this view. */ + public interface Client { + /** Called after a certain number of unexpected taps. */ + void onUnexpectedTaps(); + + /** Asks for an update of the touchable area. */ + void updateTouchableArea(); + + /** + * Called when interaction within allowed touchable area was detected. The interaction + * could be any gesture. + */ + void onUserInteractionInsideTouchableArea(); + } + /** * Complain after there's been {@link TAP_TRACKING_COUNT} taps within * {@link @TAP_TRACKING_DURATION_MS} in the unallowed area. @@ -49,26 +77,27 @@ private static final int TAP_TRACKING_COUNT = 3; private static final long TAP_TRACKING_DURATION_MS = 15_000; - /** A client of this view. */ - public interface Client { - /** Called after a certain number of unexpected taps. */ - void onUnexpectedTaps(); + /** A mode that describes what's happening to the current gesture. */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({NO_GESTURE_MODE, TRACKING_GESTURE_MODE, FORWARDING_GESTURE_MODE}) + private @interface GestureMode {} - /** - * Scroll the browser view by the given distance. - * - * <p>Distances are floats between -1.0 and 1.0, with 1 corresponding to the size of the - * visible viewport. - */ - void scrollBy(float distanceXRatio, float distanceYRatio); + /** There's no current gesture. */ + private static final int NO_GESTURE_MODE = 0; - /** Asks for an update of the touchable area. */ - void updateTouchableArea(); - } + /** + * The current gesture is being tracked and buffered. The gesture might later on transition to + * forwarding mode or it might be abandoned. + */ + private static final int TRACKING_GESTURE_MODE = 1; + + /** The current gesture is being forwarded to the content view. */ + private static final int FORWARDING_GESTURE_MODE = 2; private Client mClient; private ChromeFullscreenManager mFullscreenManager; private GestureListenerManager mGestureListenerManager; + private View mCompositorView; private final List<RectF> mTouchableArea = new ArrayList<>(); private final Paint mGrayOut; private final Paint mClear; @@ -90,11 +119,28 @@ /** A single RectF instance used for drawing, to avoid creating many instances when drawing. */ private final RectF mDrawRect = new RectF(); - /** Detects gestures that happen outside of the allowed area. */ - private final GestureDetector mNonBrowserGesture; + /** + * Detects taps: {@link GestureDetector#onTouchEvent} returns {@code true} after a tap event. + */ + private final GestureDetector mTapDetector; - /** True while a gesture handled by {@link #mNonBrowserGesture} is in progress. */ - private boolean mNonBrowserGestureInProgress; + /** + * Detects scrolls and flings: {@link GestureDetector#onTouchEvent} returns {@code true} a + * scroll or fling event. + */ + private final GestureDetector mScrollDetector; + + /** The current state of the gesture filter. */ + @GestureMode + private int mCurrentGestureMode; + + /** + * A capture of the motion event that are part of the current gesture, kept around in case they + * need to be forwarded while {@code mCurrentGestureMode == TRACKING_GESTURE_MODE}. + * + * <p>Elements of this list must be recycled. Call {@link #cleanupCurrentGestureBuffer}. + */ + private List<MotionEvent> mCurrentGestureBuffer = new ArrayList<>(); /** Times, in millisecond, of unexpected taps detected outside of the allowed area. */ private final List<Long> mUnexpectedTapTimes = new ArrayList<>(); @@ -131,6 +177,8 @@ * <p>Margins are set when the top or bottom controller are fully shown. When they're shown * partially, during a scroll, margins are always 0. The drawing takes care of adapting. * + * <p>Always 0 unless accessibility is turned on. + * * <p>TODO(crbug.com/806868): Better integrate this filter with the view layout to make it * automatic. */ @@ -163,41 +211,45 @@ mClear = new Paint(); mClear.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); - // Handles gestures that happen outside of the allowed area. - mNonBrowserGesture = new GestureDetector(context, new SimpleOnGestureListener() { + setFullOverlay(false); + setPartialOverlay(false, Collections.emptyList()); + mTapDetector = new GestureDetector(context, new SimpleOnGestureListener() { @Override public boolean onSingleTapUp(MotionEvent e) { - onUnexpectedTap(e); - return true; - } - - @Override - public boolean onScroll(MotionEvent downEvent, MotionEvent moveEvent, float distanceX, - float distanceY) { - if (mPartialOverlayEnabled) - mClient.scrollBy(distanceX / getWidth(), distanceY / getVisualViewportHeight()); return true; } }); + mScrollDetector = new GestureDetector(context, new SimpleOnGestureListener() { + @Override + public boolean onScroll( + MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + return true; + } - setFullOverlay(false); - setPartialOverlay(false, Collections.emptyList()); + @Override + public boolean onFling( + MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + return true; + } + }); } /** Initializes dependencies. */ - public void init( - Client client, ChromeFullscreenManager fullscreenManager, WebContents webContents) { + public void init(Client client, ChromeFullscreenManager fullscreenManager, + WebContents webContents, View compositorView) { mClient = client; mFullscreenManager = fullscreenManager; mFullscreenManager.addListener(this); mGestureListenerManager = GestureListenerManager.fromWebContents(webContents); mGestureListenerManager.addListener(this); maybeUpdateVerticalMargins(); + mCompositorView = compositorView; } public void deInit() { mClient = null; + mCompositorView = null; if (mFullscreenManager != null) { mFullscreenManager.removeListener(this); mFullscreenManager = null; @@ -206,6 +258,7 @@ mGestureListenerManager.removeListener(this); mGestureListenerManager = null; } + cleanupCurrentGestureBuffer(); } /** Sets the color to be used for unusable areas. */ @@ -286,53 +339,163 @@ // Note that partial overlays have precedence over full overlays if (mPartialOverlayEnabled) return dispatchTouchEventWithPartialOverlay(event); if (mFullOverlayEnabled) return dispatchTouchEventWithFullOverlay(event); + return dispatchTouchEventWithNoOverlay(); + } + + private boolean dispatchTouchEventWithNoOverlay() { + if (mClient != null) { + mClient.onUserInteractionInsideTouchableArea(); + } return false; } + private boolean dispatchTouchEventWithFullOverlay(MotionEvent event) { + if (mTapDetector.onTouchEvent(event)) { + onUnexpectedTap(event); + } + return true; + } + + /** + * Let through or intercept gestures. + * + * <p>If the event starts a gesture, with ACTION_DOWN, within a touchable area, let the event + * through. + * + * <p>If the event starts a gesture outside a touchable area, forward it to the compositor once + * it's clear that it's a scroll, fling or multi-touch event - and not a tap event. + * + * @return true if the event was handled by this view, as defined for {@link + * View#dispatchTouchEvent} + */ private boolean dispatchTouchEventWithPartialOverlay(MotionEvent event) { - switch (event.getAction()) { - case MotionEvent.ACTION_SCROLL: - // Scrolling is always safe. Let it through. - return false; - case MotionEvent.ACTION_MOVE: - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - if (mNonBrowserGestureInProgress) { - // If a non-browser gesture, started with an ACTION_DOWN, is in progress, give - // it priority over everything else until the next ACTION_DOWN. - mNonBrowserGesture.onTouchEvent(event); - return true; - } - if (mBrowserScrolling) { - // Events sent to the browser triggered scrolling, which was reported to - // onScrollStarted. Direct all events to the browser until the next ACTION_DOWN - // to avoid interrupting that scroll. + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: // Starts a new gesture. + + // Reset is needed, as ACTION_DOWN can interrupt a running gesture + resetCurrentGesture(); + + if (shouldLetEventThrough(event)) { + mClient.onUserInteractionInsideTouchableArea(); + // This is the last we'll hear of this gesture unless it turns multi-touch. No + // need to track or forward it. return false; } - // fall through - - case MotionEvent.ACTION_DOWN: - // Only let through events if they're meant for the touchable area of the screen. - int yTop = getVisualViewportTop(); - int yBottom = getVisualViewportBottom(); - int height = yBottom - yTop; - boolean allowed = isInTouchableArea(((float) event.getX()) / getWidth(), - (((float) event.getY() - yTop + mBrowserScrollOffsetY + mOffsetY) - / height)); - if (!allowed) { - mNonBrowserGestureInProgress = mNonBrowserGesture.onTouchEvent(event); - return true; // handled + if (event.getPointerCount() > 0 && event.getPointerId(0) != 0) { + // We're being offered a previously let-through gesture, which turned + // multi-touch. This isn't a real gesture start. + return false; } - return false; // let it through + + // Track the gesture in case this is a tap, which we should handle, or a + // scroll/fling/pinch, which we should forward. + mCurrentGestureMode = TRACKING_GESTURE_MODE; + mCurrentGestureBuffer.add(MotionEvent.obtain(event)); + mScrollDetector.onTouchEvent(event); + mTapDetector.onTouchEvent(event); + return true; + + case MotionEvent.ACTION_MOVE: // Continues a gesture. + switch (mCurrentGestureMode) { + case TRACKING_GESTURE_MODE: + if (mScrollDetector.onTouchEvent(event)) { + // The current gesture is a scroll or a fling. Forward it. + startForwardingGesture(event); + return true; + } + + // Continue accumulating events. + mTapDetector.onTouchEvent(event); + mCurrentGestureBuffer.add(MotionEvent.obtain(event)); + return true; + + case FORWARDING_GESTURE_MODE: + mCompositorView.dispatchTouchEvent(event); + return true; + + default: + return true; + } + + case MotionEvent.ACTION_POINTER_DOWN: // Continues a multi-touch gesture + case MotionEvent.ACTION_POINTER_UP: + switch (mCurrentGestureMode) { + case TRACKING_GESTURE_MODE: + // The current gesture has just become a multi-touch gesture. Forward it. + startForwardingGesture(event); + return true; + + case FORWARDING_GESTURE_MODE: + mCompositorView.dispatchTouchEvent(event); + return true; + + default: + return true; + } + + case MotionEvent.ACTION_UP: // Ends a gesture + case MotionEvent.ACTION_CANCEL: + switch (mCurrentGestureMode) { + case TRACKING_GESTURE_MODE: + if (mTapDetector.onTouchEvent(event)) { + onUnexpectedTap(event); + } + resetCurrentGesture(); + return true; + + case FORWARDING_GESTURE_MODE: + mCompositorView.dispatchTouchEvent(event); + resetCurrentGesture(); + return true; + + default: + return true; + } default: - return super.dispatchTouchEvent(event); + return true; } } - private boolean dispatchTouchEventWithFullOverlay(MotionEvent event) { - mNonBrowserGesture.onTouchEvent(event); - return true; + /** Clears all information about the current gesture. */ + private void resetCurrentGesture() { + mCurrentGestureMode = NO_GESTURE_MODE; + cleanupCurrentGestureBuffer(); + } + + /** Clears {@link #mCurrentGestureStart}, recycling it if necessary. */ + private void cleanupCurrentGestureBuffer() { + for (MotionEvent event : mCurrentGestureBuffer) { + event.recycle(); + } + mCurrentGestureBuffer.clear(); + } + + /** Enables forwarding of the current gesture, starting with {@link currentEvent}. */ + private void startForwardingGesture(MotionEvent currentEvent) { + mCurrentGestureMode = FORWARDING_GESTURE_MODE; + for (MotionEvent event : mCurrentGestureBuffer) { + mCompositorView.dispatchTouchEvent(event); + } + cleanupCurrentGestureBuffer(); + mCompositorView.dispatchTouchEvent(currentEvent); + } + + /** + * Returns {@code true} if {@code event} is for a position in the touchable area + * or the top/bottom bar. + */ + private boolean shouldLetEventThrough(MotionEvent event) { + int yTop = getVisualViewportTop(); + int yBottom = getVisualViewportBottom(); + if (event.getY() < yTop || event.getY() > yBottom) { + // Let it through. The event is meant for the top or bottom bar UI controls, not the + // webpage. + return true; + } + int height = yBottom - yTop; + return isInTouchableArea(((float) event.getX()) / getWidth(), + (((float) event.getY() - yTop + mBrowserScrollOffsetY + mOffsetY) / height)); } /** Returns the origin of the visual viewport in this view. */ @@ -487,7 +650,7 @@ } /** - * Updates the vertical margins of the view. + * Updates the vertical margins of the view when accessibility is enabled. * * <p>When the controls are fully visible, the view covers has just the right margins to cover * only the web page. @@ -501,7 +664,8 @@ private void maybeUpdateVerticalMargins() { if (mFullscreenManager == null) return; - if (mFullscreenManager.areBrowserControlsFullyVisible()) { + if (mFullscreenManager.areBrowserControlsFullyVisible() + && AccessibilityUtil.isAccessibilityEnabled()) { setVerticalMargins(getTopBarHeight(), getBottomBarHeight()); } else { setVerticalMargins(0, 0);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java index c3e88b3..63d1a8a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -32,6 +32,7 @@ import org.chromium.base.SysUtils; import org.chromium.base.TraceEvent; +import org.chromium.base.compat.ApiHelperForO; import org.chromium.chrome.R; import org.chromium.chrome.browser.InsetObserverView; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardExtensionSizeManager; @@ -269,6 +270,10 @@ } }); handleSystemUiVisibilityChange(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + ApiHelperForO.setDefaultFocusHighlightEnabled(this, false); + } } private Point getViewportSize() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java index 9b56695..acc3cab 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java
@@ -16,6 +16,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver; @@ -312,6 +313,7 @@ if (mSuggestionsSetOnBottomSheet || !mModelPreparedForCurrentTab) return; maybeShowContentInSheet(); + RecordUserAction.record("ContextualSuggestions.ToolbarButtonClicked"); mCoordinator.showSuggestions(mSuggestionsSource); mCoordinator.expandBottomSheet(); } @@ -490,7 +492,7 @@ } @Override - public void onSheetClosed(int reason) { + public void onSheetClosed(@StateChangeReason int reason) { removeSuggestionsFromSheet(); } };
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java index d5c5bb7..32a69e7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -60,6 +60,7 @@ import org.chromium.chrome.browser.KeyboardShortcuts; import org.chromium.chrome.browser.LaunchIntentDispatcher; import org.chromium.chrome.browser.ServiceTabLauncher; +import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.WarmupManager; import org.chromium.chrome.browser.WebContentsFactory; import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate; @@ -1696,8 +1697,28 @@ if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_MODULE)) { return false; } + List<String> moduleManagedHosts = mIntentDataProvider.getExtraModuleManagedHosts(); Pattern urlsPattern = mIntentDataProvider.getExtraModuleManagedUrlsPattern(); - return !TextUtils.isEmpty(url) && urlsPattern != null && urlsPattern.matcher(url).matches(); + if (TextUtils.isEmpty(url) || moduleManagedHosts == null || moduleManagedHosts.isEmpty() + || urlsPattern == null) { + return false; + } + Uri parsed = Uri.parse(url); + String scheme = parsed.getScheme(); + if (!UrlConstants.HTTPS_SCHEME.equals(scheme)) { + return false; + } + String host = parsed.getHost(); + if (host == null) { + return false; + } + String pathAndQuery = url.substring(UrlUtilities.stripPath(url).length()); + for (String moduleManagedHost : moduleManagedHosts) { + if (host.equals(moduleManagedHost) && urlsPattern.matcher(pathAndQuery).matches()) { + return true; + } + } + return false; } private void maybeUpdateCctHeaderVisibility(String url) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java index be60507b0..07baebe8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -129,6 +129,10 @@ public static final String EXTRA_SEND_TO_EXTERNAL_DEFAULT_HANDLER = "android.support.customtabs.extra.SEND_TO_EXTERNAL_HANDLER"; + /** Key for the intent extra used to define an array list of module managed hosts. */ + /* package */ static final String EXTRA_MODULE_MANAGED_HOST_LIST = + "org.chromium.chrome.browser.customtabs.EXTRA_MODULE_MANAGED_HOST_LIST"; + /** Extra that defines the module managed URLs regex. */ /* package */ static final String EXTRA_MODULE_MANAGED_URLS_REGEX = "org.chromium.chrome.browser.customtabs.EXTRA_MODULE_MANAGED_URLS_REGEX"; @@ -171,6 +175,8 @@ @Nullable private final ComponentName mModuleComponentName; @Nullable + private final List<String> mModuleManagedHosts; + @Nullable private final Pattern mModuleManagedUrlsPattern; private final boolean mHideCctHeaderOnModuleManagedUrls; private final boolean mIsIncognito; @@ -300,6 +306,8 @@ String moduleClassName = IntentUtils.safeGetStringExtra(intent, EXTRA_MODULE_CLASS_NAME); if (modulePackageName != null && moduleClassName != null) { mModuleComponentName = new ComponentName(modulePackageName, moduleClassName); + mModuleManagedHosts = + IntentUtils.safeGetStringArrayListExtra(intent, EXTRA_MODULE_MANAGED_HOST_LIST); String moduleManagedUrlsRegex = IntentUtils.safeGetStringExtra(intent, EXTRA_MODULE_MANAGED_URLS_REGEX); mModuleManagedUrlsPattern = (moduleManagedUrlsRegex != null) @@ -309,6 +317,7 @@ intent, EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS, false); } else { mModuleComponentName = null; + mModuleManagedHosts = null; mModuleManagedUrlsPattern = null; mHideCctHeaderOnModuleManagedUrls = false; } @@ -796,6 +805,15 @@ } /** + * See {@link #EXTRA_MODULE_MANAGED_HOST_LIST}. + * @return The list of module managed hosts, or null if not specified. + */ + @Nullable + List<String> getExtraModuleManagedHosts() { + return mModuleManagedHosts; + } + + /** * @return the Intent this instance was created with. */ public Intent getIntent() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java index f8c218b2..8a57304 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -1081,13 +1081,20 @@ void showSignInToastIfNecessary(CustomTabsSessionToken session, Intent intent) { } /** - * Sends a callback using {@link CustomTabsCallback} about the first run result if necessary. + * Sends a callback using {@link CustomTabsCallback} with the first run result if necessary. * @param intent The initial VIEW intent that initiated first run. * @param resultOK Whether first run was successful. */ public void sendFirstRunCallbackIfNecessary(Intent intent, boolean resultOK) { } /** + * Sends a callback using {@link CustomTabsCallback} with the first run result if necessary. + * @param intentExtras The extras for the initial VIEW intent that initiated first run. + * @param resultOK Whether first run was successful. + */ + public void sendFirstRunCallbackIfNecessary(Bundle intentExtras, boolean resultOK) {} + + /** * Sends the navigation info that was captured to the client callback. * @param session The session to use for getting client callback. * @param url The current url for the tab.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java index 98d9611..bfb3203 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
@@ -997,17 +997,18 @@ incrementDownloadRetryCount(item.getId(), false); } nativeResumeDownload(getNativeDownloadManagerService(), item.getId(), - item.getDownloadInfo().isOffTheRecord()); + item.getDownloadInfo().isOffTheRecord(), hasUserGesture); } /** * Called to retry a download. May resume the current download or start a new one. * @param id The {@link ContentId} of the download to retry. * @param item The current download that needs to retry. + * @param hasUserGesture Whether the request was originated due to user gesture. */ - public void retryDownload(ContentId id, DownloadItem item) { + public void retryDownload(ContentId id, DownloadItem item, boolean hasUserGesture) { nativeRetryDownload(getNativeDownloadManagerService(), item.getId(), - item.getDownloadInfo().isOffTheRecord()); + item.getDownloadInfo().isOffTheRecord(), hasUserGesture); } /** @@ -1904,10 +1905,10 @@ private native long nativeInit(boolean isFullBrowserStarted); private native void nativeOpenDownload(long nativeDownloadManagerService, String downloadGuid, boolean isOffTheRecord, int source); - private native void nativeResumeDownload( - long nativeDownloadManagerService, String downloadGuid, boolean isOffTheRecord); - private native void nativeRetryDownload( - long nativeDownloadManagerService, String downloadGuid, boolean isOffTheRecord); + private native void nativeResumeDownload(long nativeDownloadManagerService, String downloadGuid, + boolean isOffTheRecord, boolean hasUserGesture); + private native void nativeRetryDownload(long nativeDownloadManagerService, String downloadGuid, + boolean isOffTheRecord, boolean hasUserGesture); private native void nativeCancelDownload( long nativeDownloadManagerService, String downloadGuid, boolean isOffTheRecord); private native void nativePauseDownload(long nativeDownloadManagerService, String downloadGuid,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/InvalidStateOfflineItemFilter.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/InvalidStateOfflineItemFilter.java index 8786bbb6..a39e467 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/InvalidStateOfflineItemFilter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/InvalidStateOfflineItemFilter.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.download.home.filter; +import org.chromium.chrome.browser.download.DownloadUtils; import org.chromium.components.offline_items_collection.OfflineItem; import org.chromium.components.offline_items_collection.OfflineItemState; @@ -20,7 +21,9 @@ // OfflineItemFilter implementation. @Override protected boolean isFilteredOut(OfflineItem item) { - if (item.externallyRemoved || item.isTransient) return true; + boolean inPrimaryDirectory = + DownloadUtils.isInPrimaryStorageDownloadDirectory(item.filePath); + if ((item.externallyRemoved && inPrimaryDirectory) || item.isTransient) return true; switch (item.state) { case OfflineItemState.CANCELLED:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/DownloadGlue.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/DownloadGlue.java index 70567e2a..79ab909 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/DownloadGlue.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/DownloadGlue.java
@@ -139,7 +139,8 @@ DownloadManagerService.getDownloadManagerService().resumeDownload( item.id, downloadItem, hasUserGesture); } else { - DownloadManagerService.getDownloadManagerService().retryDownload(item.id, downloadItem); + DownloadManagerService.getDownloadManagerService().retryDownload( + item.id, downloadItem, hasUserGesture); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBridge.java index ec6e9cd..bf3ff36 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBridge.java
@@ -25,6 +25,11 @@ public class ExploreSitesBridge { private static final String TAG = "ExploreSitesBridge"; + private static List<ExploreSitesCategory> sCatalogForTesting; + public static void setCatalogForTesting(List<ExploreSitesCategory> catalog) { + sCatalogForTesting = catalog; + } + /** * Fetches the catalog data for Explore page. * @@ -32,16 +37,27 @@ */ public static void getEspCatalog( Profile profile, Callback<List<ExploreSitesCategory>> callback) { + if (sCatalogForTesting != null) { + callback.onResult(sCatalogForTesting); + return; + } + List<ExploreSitesCategory> result = new ArrayList<>(); nativeGetEspCatalog(profile, result, callback); } public static void getSiteImage(Profile profile, int siteID, Callback<Bitmap> callback) { + if (sCatalogForTesting != null) { + callback.onResult(null); + } nativeGetIcon(profile, siteID, callback); } public static void getCategoryImage( Profile profile, int categoryID, int pixelSize, Callback<Bitmap> callback) { + if (sCatalogForTesting != null) { + callback.onResult(null); + } nativeGetCategoryImage(profile, categoryID, pixelSize, callback); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java index b7eb837..ce00a94 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java
@@ -5,10 +5,14 @@ package org.chromium.chrome.browser.explore_sites; import android.content.Context; +import android.os.Parcel; +import android.os.Parcelable; import android.support.annotation.IntDef; import android.support.annotation.Nullable; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.Base64; import android.view.View; import android.view.ViewGroup; @@ -25,8 +29,13 @@ import org.chromium.chrome.browser.native_page.NativePageHost; import org.chromium.chrome.browser.native_page.NativePageNavigationDelegateImpl; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.tab.EmptyTabObserver; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.widget.RoundedIconGenerator; +import org.chromium.content_public.browser.NavigationController; +import org.chromium.content_public.browser.NavigationEntry; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -41,6 +50,8 @@ private static final String TAG = "ExploreSitesPage"; private static final String CONTEXT_MENU_USER_ACTION_PREFIX = "ExploreSites"; private static final int INITIAL_SCROLL_POSITION = 3; + private static final String NAVIGATION_ENTRY_SCROLL_POSITION_KEY = + "ExploreSitesPageScrollPosition"; static final PropertyModel.WritableIntPropertyKey STATUS_KEY = new PropertyModel.WritableIntPropertyKey(); static final PropertyModel.WritableIntPropertyKey SCROLL_TO_CATEGORY_KEY = @@ -60,13 +71,18 @@ private TabModelSelector mTabModelSelector; private NativePageHost mHost; + private Tab mTab; + private TabObserver mTabObserver; private Profile mProfile; private ViewGroup mView; + private RecyclerView mRecyclerView; + private LinearLayoutManager mLayoutManager; private String mTitle; private PropertyModel mModel; private ContextMenuManager mContextMenuManager; private String mNavFragment; private boolean mHasFetchedNetworkCatalog; + private boolean mIsLoaded; /** * Create a new instance of the explore sites page. @@ -78,6 +94,19 @@ @Override protected void initialize(ChromeActivity activity, final NativePageHost host) { mHost = host; + mTab = mHost.getActiveTab(); + if (mTab != null) { + // We want to observe page load start so that we can store the recycler view layout + // state, for making "back" work correctly. + mTabObserver = new EmptyTabObserver() { + @Override + public void onPageLoadStarted(Tab tab, String url) { + saveLayoutManagerState(); + } + }; + mTab.addObserver(mTabObserver); + } + mTabModelSelector = activity.getTabModelSelector(); mTitle = activity.getString(R.string.explore_sites_title); mView = (ViewGroup) activity.getLayoutInflater().inflate( @@ -91,7 +120,7 @@ .build(); Context context = mView.getContext(); - LinearLayoutManager layoutManager = new LinearLayoutManager(context); + mLayoutManager = new LinearLayoutManager(context); int iconSizePx = context.getResources().getDimensionPixelSize(R.dimen.tile_view_icon_size); RoundedIconGenerator iconGenerator = new RoundedIconGenerator(iconSizePx, iconSizePx, iconSizePx / 2, @@ -109,15 +138,14 @@ host.getActiveTab().getWindowAndroid().addContextMenuCloseListener(mContextMenuManager); CategoryCardAdapter adapterDelegate = new CategoryCardAdapter( - mModel, layoutManager, iconGenerator, mContextMenuManager, navDelegate, mProfile); + mModel, mLayoutManager, iconGenerator, mContextMenuManager, navDelegate, mProfile); - RecyclerView recyclerView = - (RecyclerView) mView.findViewById(R.id.explore_sites_category_recycler); + mRecyclerView = (RecyclerView) mView.findViewById(R.id.explore_sites_category_recycler); RecyclerViewAdapter<CategoryCardViewHolderFactory.CategoryCardViewHolder, Void> adapter = new RecyclerViewAdapter<>(adapterDelegate, new CategoryCardViewHolderFactory()); - recyclerView.setLayoutManager(layoutManager); - recyclerView.setAdapter(adapter); + mRecyclerView.setLayoutManager(mLayoutManager); + mRecyclerView.setAdapter(adapter); ExploreSitesBridge.getEspCatalog(mProfile, this::translateToModel); RecordUserAction.record("Android.ExploreSitesPage.Open"); @@ -125,10 +153,10 @@ // TODO(chili): Set layout to be an observer of list model } - private void translateToModel(@Nullable List<ExploreSitesCategory> categoryList) { + void translateToModel(@Nullable List<ExploreSitesCategory> categoryList) { // If list is null or we received an empty catalog from network, show error. if (categoryList == null || (categoryList.isEmpty() && mHasFetchedNetworkCatalog)) { - mModel.set(STATUS_KEY, CatalogLoadingState.ERROR); + onUpdatedCatalog(false); return; } // If list is empty and we never fetched from network before, fetch from network. @@ -143,12 +171,16 @@ ListModel<ExploreSitesCategory> categoryListModel = mModel.get(CATEGORY_LIST_KEY); categoryListModel.set(categoryList); - if (mNavFragment != null) { + Parcelable savedScrollPosition = getLayoutManagerStateFromNavigationEntry(); + if (savedScrollPosition != null) { + mLayoutManager.onRestoreInstanceState(savedScrollPosition); + } else if (mNavFragment != null) { lookupCategoryAndScroll(); } else { mModel.set(SCROLL_TO_CATEGORY_KEY, Math.min(categoryListModel.size() - 1, INITIAL_SCROLL_POSITION)); } + mIsLoaded = true; } private void onUpdatedCatalog(Boolean hasFetchedCatalog) { @@ -156,9 +188,14 @@ ExploreSitesBridge.getEspCatalog(mProfile, this::translateToModel); } else { mModel.set(STATUS_KEY, CatalogLoadingState.ERROR); + mIsLoaded = true; } } + public boolean isLoadedForTests() { + return mIsLoaded; + } + @Override public String getHost() { return UrlConstants.EXPLORE_HOST; @@ -187,8 +224,57 @@ } } + /* Gets the state of layout manager as a marshalled Parcel that's Base64 Encoded. */ + private String getLayoutManagerState() { + Parcelable layoutManagerState = mLayoutManager.onSaveInstanceState(); + Parcel parcel = Parcel.obtain(); + layoutManagerState.writeToParcel(parcel, 0); + String marshalledState = Base64.encodeToString(parcel.marshall(), 0); + parcel.recycle(); + return marshalledState; + } + + /* Saves the state of the layout manager in the NavigationEntry for the current tab. */ + private void saveLayoutManagerState() { + if (mTab == null || mTab.getWebContents() == null) return; + + NavigationController controller = mTab.getWebContents().getNavigationController(); + int index = controller.getLastCommittedEntryIndex(); + NavigationEntry entry = controller.getEntryAtIndex(index); + if (entry == null) return; + + controller.setEntryExtraData( + index, NAVIGATION_ENTRY_SCROLL_POSITION_KEY, getLayoutManagerState()); + } + + /* + * Retrieves the layout manager state from the navigation entry and reconstitutes it into a + * Parcelable using LinearLayoutManager.SavedState.CREATOR. + */ + private Parcelable getLayoutManagerStateFromNavigationEntry() { + if (mTab.getWebContents() == null) return null; + + NavigationController controller = mTab.getWebContents().getNavigationController(); + int index = controller.getLastCommittedEntryIndex(); + String layoutManagerState = + controller.getEntryExtraData(index, NAVIGATION_ENTRY_SCROLL_POSITION_KEY); + if (TextUtils.isEmpty(layoutManagerState)) return null; + + byte[] parcelData = Base64.decode(layoutManagerState, 0); + Parcel parcel = Parcel.obtain(); + parcel.unmarshall(parcelData, 0, parcelData.length); + parcel.setDataPosition(0); + Parcelable scrollPosition = LinearLayoutManager.SavedState.CREATOR.createFromParcel(parcel); + parcel.recycle(); + + return scrollPosition; + } + @Override public void destroy() { + if (mTabObserver != null) { + mTab.removeObserver(mTabObserver); + } mHost.getActiveTab().getWindowAndroid().removeContextMenuCloseListener(mContextMenuManager); super.destroy(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/ResumableDelayedTaskRunner.java b/chrome/android/java/src/org/chromium/chrome/browser/invalidation/ResumableDelayedTaskRunner.java index fea0424a..8c0759f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/invalidation/ResumableDelayedTaskRunner.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/invalidation/ResumableDelayedTaskRunner.java
@@ -18,7 +18,7 @@ * {@code * * ResumableDelayedTaskRunner runner = new ResumableDelayedTaskRunner(); - * mEnableSessionInvalidationsTimer.setRunnable(task, delayMs); + * runner.setRunnable(task, delayMs); * runner.resume(); // Starts the count down. * runner.pause(); // Pauses the count down. * runner.resume(); // Resumes the count down.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/BaseNotificationController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/BaseNotificationController.java new file mode 100644 index 0000000..7a0f63b3 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/BaseNotificationController.java
@@ -0,0 +1,145 @@ +// 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. + +package org.chromium.chrome.browser.media.router.caf; + +import android.content.Intent; + +import com.google.android.gms.cast.CastDevice; +import com.google.android.gms.cast.MediaStatus; +import com.google.android.gms.cast.framework.media.RemoteMediaClient; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.media.ui.MediaNotificationInfo; +import org.chromium.chrome.browser.media.ui.MediaNotificationListener; +import org.chromium.chrome.browser.media.ui.MediaNotificationManager; +import org.chromium.services.media_session.MediaMetadata; + +/** Base controller for updating media notification for Casting and MediaFling. */ +public abstract class BaseNotificationController implements MediaNotificationListener { + private MediaNotificationInfo.Builder mNotificationBuilder; + protected final BaseSessionController mSessionController; + + public BaseNotificationController(BaseSessionController sessionController) { + mSessionController = sessionController; + } + + /** Called when session started. */ + public void onSessionStarted() { + mNotificationBuilder = + new MediaNotificationInfo.Builder() + .setPaused(false) + .setOrigin(mSessionController.getRouteCreationInfo().origin) + // TODO(zqzhang): the same session might have more than one tab id. Should + // we track the last foreground alive tab and update the notification with + // it? + .setTabId(mSessionController.getRouteCreationInfo().tabId) + .setPrivate(mSessionController.getRouteCreationInfo().isIncognito) + .setActions(MediaNotificationInfo.ACTION_STOP) + .setContentIntent(createContentIntent()) + .setNotificationSmallIcon(R.drawable.ic_notification_media_route) + .setDefaultNotificationLargeIcon(R.drawable.cast_playing_square) + .setId(getNotificationId()) + .setListener(this); + + updateNotificationMetadata(); + MediaNotificationManager.show(mNotificationBuilder.build()); + } + + /** Called when session ended. */ + public void onSessionEnded() { + MediaNotificationManager.clear(R.id.presentation_notification); + mNotificationBuilder = null; + } + + /** Called when media status updated. */ + public void onStatusUpdated() { + if (mNotificationBuilder == null) return; + if (!mSessionController.isConnected()) return; + + MediaStatus mediaStatus = mSessionController.getRemoteMediaClient().getMediaStatus(); + if (mediaStatus == null) return; + + int playerState = mediaStatus.getPlayerState(); + if (playerState == MediaStatus.PLAYER_STATE_PAUSED + || playerState == MediaStatus.PLAYER_STATE_PLAYING) { + mNotificationBuilder.setPaused(playerState != MediaStatus.PLAYER_STATE_PLAYING); + mNotificationBuilder.setActions( + MediaNotificationInfo.ACTION_STOP | MediaNotificationInfo.ACTION_PLAY_PAUSE); + } else { + mNotificationBuilder.setActions(MediaNotificationInfo.ACTION_STOP); + } + MediaNotificationManager.show(mNotificationBuilder.build()); + } + + /** Called when media metadata updated. */ + public void onMetadataUpdated() { + if (mNotificationBuilder == null) return; + updateNotificationMetadata(); + MediaNotificationManager.show(mNotificationBuilder.build()); + } + + private void updateNotificationMetadata() { + MediaMetadata notificationMetadata = new MediaMetadata("", "", ""); + mNotificationBuilder.setMetadata(notificationMetadata); + + if (!mSessionController.isConnected()) return; + + CastDevice castDevice = mSessionController.getSession().getCastDevice(); + if (castDevice != null) notificationMetadata.setTitle(castDevice.getFriendlyName()); + + RemoteMediaClient remoteMediaClient = mSessionController.getRemoteMediaClient(); + + com.google.android.gms.cast.MediaInfo info = remoteMediaClient.getMediaInfo(); + if (info == null) return; + + com.google.android.gms.cast.MediaMetadata metadata = info.getMetadata(); + if (metadata == null) return; + + String title = metadata.getString(com.google.android.gms.cast.MediaMetadata.KEY_TITLE); + if (title != null) notificationMetadata.setTitle(title); + + String artist = metadata.getString(com.google.android.gms.cast.MediaMetadata.KEY_ARTIST); + if (artist == null) { + artist = metadata.getString(com.google.android.gms.cast.MediaMetadata.KEY_ALBUM_ARTIST); + } + if (artist != null) notificationMetadata.setArtist(artist); + + String album = + metadata.getString(com.google.android.gms.cast.MediaMetadata.KEY_ALBUM_TITLE); + if (album != null) notificationMetadata.setAlbum(album); + } + + ///////////////////////////////////////////////////////////////////////////////////////////// + // MediaNotificationListener implementation. + + @Override + public void onPlay(int actionSource) { + if (!mSessionController.isConnected()) return; + + mSessionController.getRemoteMediaClient().play(); + } + + @Override + public void onPause(int actionSource) { + if (!mSessionController.isConnected()) return; + + mSessionController.getRemoteMediaClient().pause(); + } + + @Override + public void onStop(int actionSource) { + if (!mSessionController.isConnected()) return; + + mSessionController.endSession(); + } + + @Override + public void onMediaSessionAction(int action) {} + + // Abstract methods to be implemented by children. + public abstract Intent createContentIntent(); + + public abstract int getNotificationId(); +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/BaseSessionController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/BaseSessionController.java index e57a99f..cc2d0ef 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/BaseSessionController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/BaseSessionController.java
@@ -5,7 +5,6 @@ package org.chromium.chrome.browser.media.router.caf; import android.support.annotation.Nullable; -import android.support.annotation.VisibleForTesting; import com.google.android.gms.cast.CastDevice; import com.google.android.gms.cast.framework.CastSession; @@ -25,19 +24,16 @@ * * Has persistent lifecycle and always attaches itself to the current {@link CastSession}. */ -public class BaseSessionController { +public abstract class BaseSessionController { private static final String TAG = "BaseSessionCtrl"; private CastSession mCastSession; private final CafBaseMediaRouteProvider mProvider; private CreateRouteRequestInfo mRouteCreationInfo; - @VisibleForTesting - CafNotificationController mNotificationController; private final RemoteMediaClient.Callback mRemoteMediaClientCallback; public BaseSessionController(CafBaseMediaRouteProvider provider) { mProvider = provider; - mNotificationController = new CafNotificationController(this); mRemoteMediaClientCallback = new RemoteMediaClientCallback(); } @@ -72,9 +68,7 @@ return isConnected() ? mCastSession.getRemoteMediaClient() : null; } - public CafNotificationController getNotificationController() { - return mNotificationController; - } + public abstract BaseNotificationController getNotificationController(); public void endSession() { CastUtils.getCastContext().getSessionManager().endCurrentSession(/* stopCasting= */ true); @@ -133,12 +127,12 @@ /** Called when session started. */ public void onSessionStarted() { - mNotificationController.onSessionStarted(); + getNotificationController().onSessionStarted(); } /** Called when session ended. */ public void onSessionEnded() { - mNotificationController.onSessionEnded(); + getNotificationController().onSessionEnded(); mRouteCreationInfo = null; } @@ -172,11 +166,11 @@ } protected void onStatusUpdated() { - mNotificationController.onStatusUpdated(); + getNotificationController().onStatusUpdated(); } protected void onMetadataUpdated() { - mNotificationController.onMetadataUpdated(); + getNotificationController().onMetadataUpdated(); } @Nullable
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/CafNotificationController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/CafNotificationController.java index 878ca06..e95b792 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/CafNotificationController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/CafNotificationController.java
@@ -6,143 +6,29 @@ import android.content.Intent; -import com.google.android.gms.cast.CastDevice; -import com.google.android.gms.cast.MediaStatus; -import com.google.android.gms.cast.framework.media.RemoteMediaClient; - import org.chromium.chrome.R; -import org.chromium.chrome.browser.media.ui.MediaNotificationInfo; -import org.chromium.chrome.browser.media.ui.MediaNotificationListener; -import org.chromium.chrome.browser.media.ui.MediaNotificationManager; import org.chromium.chrome.browser.metrics.MediaNotificationUma; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.services.media_session.MediaMetadata; -/** Controller for updating media notification for Casting and MediaFling. */ -public class CafNotificationController implements MediaNotificationListener { - private MediaNotificationInfo.Builder mNotificationBuilder; - private final BaseSessionController mSessionController; - +/** NotificationController implementation for presentation. */ +public class CafNotificationController extends BaseNotificationController { public CafNotificationController(BaseSessionController sessionController) { - mSessionController = sessionController; + super(sessionController); } - /** Called when session started. */ - public void onSessionStarted() { + @Override + public Intent createContentIntent() { Intent contentIntent = Tab.createBringTabToFrontIntent(mSessionController.getRouteCreationInfo().tabId); if (contentIntent != null) { contentIntent.putExtra(MediaNotificationUma.INTENT_EXTRA_NAME, MediaNotificationUma.Source.PRESENTATION); } - mNotificationBuilder = - new MediaNotificationInfo.Builder() - .setPaused(false) - .setOrigin(mSessionController.getRouteCreationInfo().origin) - // TODO(zqzhang): the same session might have more than one tab id. Should - // we track the last foreground alive tab and update the notification with - // it? - .setTabId(mSessionController.getRouteCreationInfo().tabId) - .setPrivate(mSessionController.getRouteCreationInfo().isIncognito) - .setActions(MediaNotificationInfo.ACTION_STOP) - .setContentIntent(contentIntent) - .setNotificationSmallIcon(R.drawable.ic_notification_media_route) - .setDefaultNotificationLargeIcon(R.drawable.cast_playing_square) - .setId(R.id.presentation_notification) - .setListener(this); - - updateNotificationMetadata(); - MediaNotificationManager.show(mNotificationBuilder.build()); - } - - /** Called when session ended. */ - public void onSessionEnded() { - MediaNotificationManager.clear(R.id.presentation_notification); - mNotificationBuilder = null; - } - - /** Called when media status updated. */ - public void onStatusUpdated() { - if (mNotificationBuilder == null) return; - if (!mSessionController.isConnected()) return; - - MediaStatus mediaStatus = mSessionController.getRemoteMediaClient().getMediaStatus(); - if (mediaStatus == null) return; - - int playerState = mediaStatus.getPlayerState(); - if (playerState == MediaStatus.PLAYER_STATE_PAUSED - || playerState == MediaStatus.PLAYER_STATE_PLAYING) { - mNotificationBuilder.setPaused(playerState != MediaStatus.PLAYER_STATE_PLAYING); - mNotificationBuilder.setActions( - MediaNotificationInfo.ACTION_STOP | MediaNotificationInfo.ACTION_PLAY_PAUSE); - } else { - mNotificationBuilder.setActions(MediaNotificationInfo.ACTION_STOP); - } - MediaNotificationManager.show(mNotificationBuilder.build()); - } - - /** Called when media metadata updated. */ - public void onMetadataUpdated() { - if (mNotificationBuilder == null) return; - updateNotificationMetadata(); - MediaNotificationManager.show(mNotificationBuilder.build()); - } - - private void updateNotificationMetadata() { - MediaMetadata notificationMetadata = new MediaMetadata("", "", ""); - mNotificationBuilder.setMetadata(notificationMetadata); - - if (!mSessionController.isConnected()) return; - - CastDevice castDevice = mSessionController.getSession().getCastDevice(); - if (castDevice != null) notificationMetadata.setTitle(castDevice.getFriendlyName()); - - RemoteMediaClient remoteMediaClient = mSessionController.getRemoteMediaClient(); - - com.google.android.gms.cast.MediaInfo info = remoteMediaClient.getMediaInfo(); - if (info == null) return; - - com.google.android.gms.cast.MediaMetadata metadata = info.getMetadata(); - if (metadata == null) return; - - String title = metadata.getString(com.google.android.gms.cast.MediaMetadata.KEY_TITLE); - if (title != null) notificationMetadata.setTitle(title); - - String artist = metadata.getString(com.google.android.gms.cast.MediaMetadata.KEY_ARTIST); - if (artist == null) { - artist = metadata.getString(com.google.android.gms.cast.MediaMetadata.KEY_ALBUM_ARTIST); - } - if (artist != null) notificationMetadata.setArtist(artist); - - String album = - metadata.getString(com.google.android.gms.cast.MediaMetadata.KEY_ALBUM_TITLE); - if (album != null) notificationMetadata.setAlbum(album); - } - - ///////////////////////////////////////////////////////////////////////////////////////////// - // MediaNotificationListener implementation. - - @Override - public void onPlay(int actionSource) { - if (!mSessionController.isConnected()) return; - - mSessionController.getRemoteMediaClient().play(); + return contentIntent; } @Override - public void onPause(int actionSource) { - if (!mSessionController.isConnected()) return; - - mSessionController.getRemoteMediaClient().pause(); + public int getNotificationId() { + return R.id.presentation_notification; } - - @Override - public void onStop(int actionSource) { - if (!mSessionController.isConnected()) return; - - mSessionController.endSession(); - } - - @Override - public void onMediaSessionAction(int action) {} }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/CastSessionController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/CastSessionController.java index e470a477..abe6182 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/CastSessionController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/CastSessionController.java
@@ -25,10 +25,12 @@ private List<String> mNamespaces = new ArrayList<String>(); private CastListener mCastListener; + private CafNotificationController mNotificationController; public CastSessionController(CafBaseMediaRouteProvider provider) { super(provider); mCastListener = new CastListener(); + mNotificationController = new CafNotificationController(this); } public List<String> getNamespaces() { @@ -63,6 +65,11 @@ super.onSessionEnded(); } + @Override + public BaseNotificationController getNotificationController() { + return mNotificationController; + } + private class CastListener extends Cast.Listener { @Override public void onApplicationStatusChanged() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/remoting/FlingingControllerAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/remoting/FlingingControllerAdapter.java index 1bf003a7..ed990d57 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/remoting/FlingingControllerAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/remoting/FlingingControllerAdapter.java
@@ -18,15 +18,16 @@ public class FlingingControllerAdapter implements FlingingController, MediaController { private static final String TAG = "FlingCtrlAdptr"; + private final StreamPositionExtrapolator mStreamPositionExtrapolator; private final RemotingSessionController mSessionController; private final String mMediaUrl; private MediaStatusObserver mMediaStatusObserver; - private long mCachedApproximateCurrentTime; private boolean mLoaded; FlingingControllerAdapter(RemotingSessionController sessionController, String mediaUrl) { mSessionController = sessionController; mMediaUrl = mediaUrl; + mStreamPositionExtrapolator = new StreamPositionExtrapolator(); } //////////////////////////////////////////// @@ -52,11 +53,7 @@ @Override public long getApproximateCurrentTime() { - if (mSessionController.isConnected()) { - mCachedApproximateCurrentTime = - mSessionController.getRemoteMediaClient().getApproximateStreamPosition(); - } - return mCachedApproximateCurrentTime; + return mStreamPositionExtrapolator.getPosition(); } //////////////////////////////////////////// @@ -125,6 +122,7 @@ mSessionController.getRemoteMediaClient().seek(position).setResultCallback( this ::onMediaCommandResult); + mStreamPositionExtrapolator.onSeek(position); } //////////////////////////////////////////// @@ -134,9 +132,25 @@ public void onStatusUpdated() { if (mMediaStatusObserver == null) return; - MediaStatus mediaStatus = mSessionController.getRemoteMediaClient().getMediaStatus(); + RemoteMediaClient remoteMediaClient = mSessionController.getRemoteMediaClient(); + + MediaStatus mediaStatus = remoteMediaClient.getMediaStatus(); if (mediaStatus != null) { + if (mediaStatus.getPlayerState() == MediaStatus.PLAYER_STATE_IDLE + && mediaStatus.getIdleReason() == MediaStatus.IDLE_REASON_FINISHED) { + mLoaded = false; + mStreamPositionExtrapolator.onFinish(); + } else { + mStreamPositionExtrapolator.update(remoteMediaClient.getStreamDuration(), + remoteMediaClient.getApproximateStreamPosition(), + remoteMediaClient.isPlaying(), mediaStatus.getPlaybackRate()); + } + mMediaStatusObserver.onMediaStatusUpdate(new MediaStatusBridge(mediaStatus)); + + } else { + mLoaded = false; + mStreamPositionExtrapolator.clear(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingNotificationController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingNotificationController.java new file mode 100644 index 0000000..1aacb54 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingNotificationController.java
@@ -0,0 +1,36 @@ +// 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. + +package org.chromium.chrome.browser.media.router.caf.remoting; + +import android.content.Intent; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.media.router.caf.BaseNotificationController; +import org.chromium.chrome.browser.media.router.caf.BaseSessionController; +import org.chromium.chrome.browser.metrics.MediaNotificationUma; +import org.chromium.chrome.browser.tab.Tab; + +/** NotificationController implementation for remoting. */ +public class RemotingNotificationController extends BaseNotificationController { + public RemotingNotificationController(BaseSessionController sessionController) { + super(sessionController); + } + + @Override + public Intent createContentIntent() { + Intent contentIntent = + Tab.createBringTabToFrontIntent(mSessionController.getRouteCreationInfo().tabId); + if (contentIntent != null) { + contentIntent.putExtra(MediaNotificationUma.INTENT_EXTRA_NAME, + MediaNotificationUma.Source.MEDIA_FLING); + } + return contentIntent; + } + + @Override + public int getNotificationId() { + return R.id.remote_notification; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingSessionController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingSessionController.java index 9dc0331..6529ded 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingSessionController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingSessionController.java
@@ -9,6 +9,7 @@ import org.chromium.base.Log; import org.chromium.chrome.browser.media.router.CastSessionUtil; import org.chromium.chrome.browser.media.router.FlingingController; +import org.chromium.chrome.browser.media.router.caf.BaseNotificationController; import org.chromium.chrome.browser.media.router.caf.BaseSessionController; import org.chromium.chrome.browser.media.router.caf.CafBaseMediaRouteProvider; import org.chromium.chrome.browser.media.router.cast.remoting.RemotingMediaSource; @@ -18,8 +19,11 @@ private static final String TAG = "RmtSessionCtrl"; private FlingingControllerAdapter mFlingingControllerAdapter; + private RemotingNotificationController mNotificationController; + RemotingSessionController(CafBaseMediaRouteProvider provider) { super(provider); + mNotificationController = new RemotingNotificationController(this); } @Override @@ -52,4 +56,9 @@ public FlingingController getFlingingController() { return mFlingingControllerAdapter; } + + @Override + public BaseNotificationController getNotificationController() { + return mNotificationController; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/remoting/StreamPositionExtrapolator.java b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/remoting/StreamPositionExtrapolator.java new file mode 100644 index 0000000..3051e45 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/router/caf/remoting/StreamPositionExtrapolator.java
@@ -0,0 +1,70 @@ +// 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. + +package org.chromium.chrome.browser.media.router.caf.remoting; + +/** + * Class for extrapolating current playback position. The class occasionally receives updated + * playback position information from RemoteMediaClient, and extrapolates the current playback + * position. + */ +public class StreamPositionExtrapolator { + private static final String TAG = "MediaFling"; + + private long mDuration; + private long mLastKnownPosition; + private long mTimestamp; + private boolean mIsPlaying; + private double mPlaybackRate; + + public StreamPositionExtrapolator() { + clear(); + } + + public void clear() { + mDuration = 0; + mLastKnownPosition = 0; + mTimestamp = 0; + mIsPlaying = false; + mPlaybackRate = 1.0; + } + + /** Updates the extrapolator with latest playback state. */ + public void update(long duration, long position, boolean isPlaying, double playbackRate) { + mDuration = duration; + mLastKnownPosition = position; + mIsPlaying = isPlaying; + mPlaybackRate = playbackRate; + mTimestamp = System.currentTimeMillis(); + } + + /** Called when the remote media has finished. */ + public void onFinish() { + mIsPlaying = false; + mLastKnownPosition = mDuration; + mTimestamp = System.currentTimeMillis(); + } + + /** Called when a seek command is sent out. */ + public void onSeek(long position) { + mIsPlaying = false; + mLastKnownPosition = position; + mTimestamp = System.currentTimeMillis(); + } + + /** Returns the approximate position. */ + public long getPosition() { + if (mTimestamp == 0) return 0; + if (!mIsPlaying) return Math.max(mLastKnownPosition, 0); + + long interpolatedStreamPosition = mLastKnownPosition + + (long) (mPlaybackRate * (System.currentTimeMillis() - mTimestamp)); + if (mDuration >= 0) { + // Don't limit if mDuration is negative, which means the remote media is streamed + // instead of buffered. + interpolatedStreamPosition = Math.min(interpolatedStreamPosition, mDuration); + } + return Math.max(interpolatedStreamPosition, 0); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java index ce672b78..8ce1dc3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetArticleViewHolder.java
@@ -7,6 +7,7 @@ import android.support.annotation.LayoutRes; import org.chromium.base.VisibleForTesting; +import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; import org.chromium.chrome.browser.metrics.ImpressionTracker; import org.chromium.chrome.browser.native_page.ContextMenuManager; @@ -80,7 +81,11 @@ @Override public void onCardTapped() { - if (!mArticle.isContextual()) SuggestionsMetrics.recordCardTapped(); + if (mArticle.isContextual()) { + RecordUserAction.record("ContextualSuggestions.SuggestionClicked"); + } else { + SuggestionsMetrics.recordCardTapped(); + } int windowDisposition = WindowOpenDisposition.CURRENT_TAB; mUiDelegate.getEventReporter().onSuggestionOpened( mArticle, windowDisposition, mUiDelegate.getSuggestionsRanker());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/ManagePasswordsUIProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/ManagePasswordsUIProvider.java index feedf785..9b0c14c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/ManagePasswordsUIProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/ManagePasswordsUIProvider.java
@@ -16,8 +16,9 @@ * Mehod called from the main settings to show the UI to manage passwords. * * @param activity the activity from which to launch the settings page. + * @param referrer the place that requested to show the passwords settings. Used for metrics. */ - public void showManagePasswordsUI(Activity activity) { + public void showManagePasswordsUI(Activity activity, @ManagePasswordsReferrer int referrer) { if (activity == null) return; // Launch preference activity with SavePasswordsPreferences fragment. PreferencesLauncher.launchSettingsPage(activity, SavePasswordsPreferences.class);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java index d8ec9b10..f6fc919 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/MainPreferences.java
@@ -20,6 +20,7 @@ import org.chromium.chrome.browser.contextual_suggestions.ContextualSuggestionsEnabledStateUtils; import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; import org.chromium.chrome.browser.partnercustomizations.HomepageManager; +import org.chromium.chrome.browser.password_manager.ManagePasswordsReferrer; import org.chromium.chrome.browser.preferences.datareduction.DataReductionPreferences; import org.chromium.chrome.browser.preferences.developer.DeveloperPreferences; import org.chromium.chrome.browser.search_engines.TemplateUrl; @@ -255,7 +256,8 @@ private void updatePasswordsPreference() { Preference passwordsPreference = findPreference(PREF_SAVED_PASSWORDS); passwordsPreference.setOnPreferenceClickListener(preference -> { - AppHooks.get().createManagePasswordsUIProvider().showManagePasswordsUI(getActivity()); + AppHooks.get().createManagePasswordsUIProvider().showManagePasswordsUI( + getActivity(), ManagePasswordsReferrer.CHROME_SETTINGS); return true; }); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferencesLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferencesLauncher.java index bd2263d..fdff0ad 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferencesLauncher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferencesLauncher.java
@@ -14,6 +14,7 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.browser.AppHooks; +import org.chromium.chrome.browser.password_manager.ManagePasswordsReferrer; import org.chromium.chrome.browser.preferences.autofill.AutofillPaymentMethodsFragment; import org.chromium.chrome.browser.preferences.autofill.AutofillProfilesFragment; import org.chromium.chrome.browser.preferences.website.SettingsNavigationSource; @@ -115,12 +116,13 @@ } @CalledByNative - private static void showPasswordSettings(WebContents webContents) { + private static void showPasswordSettings( + WebContents webContents, @ManagePasswordsReferrer int referrer) { WindowAndroid window = webContents.getTopLevelNativeWindow(); if (window == null) return; WeakReference<Activity> currentActivity = window.getActivity(); AppHooks.get().createManagePasswordsUIProvider().showManagePasswordsUI( - currentActivity.get()); + currentActivity.get(), referrer); } private static void showSettingSubpage(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java index ab86ed7..2595808 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java
@@ -163,8 +163,8 @@ // This will call back into onConfirm() on success. ConfirmManagedSyncDataDialog.showSwitchFromManagedAccountDialog(this, mFragmentManager, mContext.getResources(), - SigninManager.extractDomainName(mOldAccountName), - mOldAccountName, mNewAccountName); + SigninManager.get().extractDomainName(mOldAccountName), mOldAccountName, + mNewAccountName); } else { // This will call back into onConfirm(boolean wipeData) on success. ConfirmImportSyncDataDialog.showNewInstance(mOldAccountName, mNewAccountName, @@ -192,7 +192,7 @@ } private void requestNewAccountManagementStatus() { - SigninManager.isUserManaged(mNewAccountName, this::setIsNewAccountManaged); + SigninManager.get().isUserManaged(mNewAccountName, this::setIsNewAccountManaged); } private void setIsNewAccountManaged(Boolean isManaged) { @@ -215,7 +215,7 @@ // This will call back into onConfirm on success. ConfirmManagedSyncDataDialog.showSignInToManagedAccountDialog( ConfirmSyncDataStateMachine.this, mFragmentManager, mContext.getResources(), - SigninManager.extractDomainName(mNewAccountName)); + SigninManager.get().extractDomainName(mNewAccountName)); } else { progress(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java index f46ac84..64523ba4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
@@ -7,6 +7,7 @@ import android.accounts.Account; import android.annotation.SuppressLint; import android.content.Context; +import android.content.SharedPreferences; import android.support.annotation.Nullable; import com.google.android.gms.auth.AccountChangeEvent; @@ -346,12 +347,6 @@ } } - @VisibleForTesting - public static void resetAccountRenameEventIndex() { - ContextUtils.getAppSharedPreferences() - .edit().putInt(ACCOUNT_RENAME_EVENT_INDEX_PREFS_KEY, 0).apply(); - } - public static boolean checkAndClearAccountsChangedPref() { if (ContextUtils.getAppSharedPreferences() .getBoolean(ACCOUNTS_CHANGED_PREFS_KEY, false)) { @@ -363,4 +358,13 @@ return false; } } + + @VisibleForTesting + public static void resetSharedPrefs() { + SharedPreferences.Editor editor = ContextUtils.getAppSharedPreferences().edit(); + editor.remove(ACCOUNT_RENAME_EVENT_INDEX_PREFS_KEY); + editor.remove(ACCOUNT_RENAMED_PREFS_KEY); + editor.remove(ACCOUNTS_CHANGED_PREFS_KEY); + editor.apply(); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java index 4180f286..7f65578 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
@@ -176,8 +176,10 @@ private static SigninManager sSigninManager; private static int sSignInAccessPoint = SigninAccessPoint.UNKNOWN; - private final Context mContext; private final long mNativeSigninManagerAndroid; + private final Context mContext; + private final AccountTrackerService mAccountTrackerService; + private final AndroidSyncSettings mAndroidSyncSettings; private final ObserverList<SignInStateObserver> mSignInStateObservers = new ObserverList<>(); private final ObserverList<SignInAllowedObserver> mSignInAllowedObservers = new ObserverList<>(); @@ -220,14 +222,26 @@ return sSigninManager; } + private SigninManager() { + this(ContextUtils.getApplicationContext(), AccountTrackerService.get(), + AndroidSyncSettings.get()); + } + @VisibleForTesting - SigninManager() { + SigninManager(Context context, AccountTrackerService accountTrackerService, + AndroidSyncSettings androidSyncSettings) { ThreadUtils.assertOnUiThread(); - mContext = ContextUtils.getApplicationContext(); + assert context != null; + assert accountTrackerService != null; + assert androidSyncSettings != null; + mContext = context; + mAccountTrackerService = accountTrackerService; + mAndroidSyncSettings = androidSyncSettings; + mNativeSigninManagerAndroid = nativeInit(); mSigninAllowedByPolicy = nativeIsSigninAllowedByPolicy(mNativeSigninManagerAndroid); - AccountTrackerService.get().addSystemAccountsSeededListener(this); + mAccountTrackerService.addSystemAccountsSeededListener(this); } /** @@ -396,7 +410,7 @@ } private void progressSignInFlowSeedSystemAccounts() { - if (AccountTrackerService.get().checkAndSeedSystemAccounts()) { + if (mAccountTrackerService.checkAndSeedSystemAccounts()) { progressSignInFlowCheckPolicy(); } else if (AccountIdProvider.getInstance().canBeUsed()) { mSignInState.mBlockedOnAccountSeeding = true; @@ -438,7 +452,8 @@ } @CalledByNative - private void onPolicyCheckedBeforeSignIn(String managementDomain) { + @VisibleForTesting + void onPolicyCheckedBeforeSignIn(String managementDomain) { assert mSignInState != null; if (managementDomain == null) { @@ -474,8 +489,8 @@ // Cache the signed-in account name. This must be done after the native call, otherwise // sync tries to start without being signed in natively and crashes. ChromeSigninController.get().setSignedInAccountName(mSignInState.mAccount.name); - AndroidSyncSettings.get().updateAccount(mSignInState.mAccount); - AndroidSyncSettings.get().enableChromeSync(); + mAndroidSyncSettings.updateAccount(mSignInState.mAccount); + mAndroidSyncSettings.enableChromeSync(); if (mSignInState.mCallback != null) { mSignInState.mCallback.onSignInComplete(); @@ -595,7 +610,8 @@ return nativeGetManagementDomain(mNativeSigninManagerAndroid); } - public void logInSignedInUser() { + @VisibleForTesting + void logInSignedInUser() { nativeLogInSignedInUser(mNativeSigninManagerAndroid); } @@ -652,7 +668,7 @@ assert mSignOutState != null; ChromeSigninController.get().setSignedInAccountName(null); - AndroidSyncSettings.get().updateAccount(null); + mAndroidSyncSettings.updateAccount(null); if (mSignOutState.mManagementDomain != null) { wipeProfileData(); @@ -660,7 +676,7 @@ wipeGoogleServiceWorkerCaches(); } - AccountTrackerService.get().invalidateAccountSeedStatus(true); + mAccountTrackerService.invalidateAccountSeedStatus(true); } private void wipeProfileData() { @@ -694,7 +710,8 @@ } @CalledByNative - private void onProfileDataWiped() { + @VisibleForTesting + protected void onProfileDataWiped() { // Should be set at start of sign-out flow. assert mSignOutState != null; @@ -735,7 +752,7 @@ * @param callback A callback to be called with true if the user is a managed user and false * otherwise. May be called synchronously from this function. */ - public static void isUserManaged(String email, final Callback<Boolean> callback) { + public void isUserManaged(String email, final Callback<Boolean> callback) { if (nativeShouldLoadPolicyForUser(email)) { nativeIsUserManaged(email, callback); } else { @@ -743,7 +760,7 @@ } } - public static String extractDomainName(String email) { + public String extractDomainName(String email) { return nativeExtractDomainName(email); } @@ -753,9 +770,6 @@ } // Native methods. - private static native String nativeExtractDomainName(String email); - private static native boolean nativeShouldLoadPolicyForUser(String username); - private static native void nativeIsUserManaged(String username, Callback<Boolean> callback); @VisibleForTesting native long nativeInit(); @VisibleForTesting @@ -784,4 +798,10 @@ native void nativeLogInSignedInUser(long nativeSigninManagerAndroid); @VisibleForTesting native boolean nativeIsSignedInOnNative(long nativeSigninManagerAndroid); + @VisibleForTesting + native boolean nativeShouldLoadPolicyForUser(String username); + @VisibleForTesting + native void nativeIsUserManaged(String username, Callback<Boolean> callback); + @VisibleForTesting + native String nativeExtractDomainName(String email); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java index 26543ec..4f6af6d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragment.java
@@ -24,7 +24,6 @@ import android.widget.ArrayAdapter; import android.widget.CheckedTextView; import android.widget.ListView; -import android.widget.TextView; import org.chromium.base.ContextUtils; import org.chromium.base.VisibleForTesting; @@ -34,6 +33,7 @@ import org.chromium.components.sync.PassphraseType; import org.chromium.ui.text.SpanApplier; import org.chromium.ui.text.SpanApplier.SpanInfo; +import org.chromium.ui.widget.TextViewWithClickableSpans; import java.text.DateFormat; import java.util.ArrayList; @@ -159,23 +159,30 @@ // Configure the passphrase type list ListView list = (ListView) v.findViewById(R.id.passphrase_types); - Adapter adapter = createAdapter(getCurrentTypeFromArguments()); - list.setAdapter(adapter); - list.setId(R.id.passphrase_type_list); - list.setOnItemClickListener(this); - list.setDividerHeight(0); + PassphraseType currentType = getCurrentTypeFromArguments(); - list.setSelection(adapter.getPositionForType(currentType)); // Configure the hint to reset the passphrase settings // Only show this hint if encryption has been set to use sync passphrase if (currentType == PassphraseType.CUSTOM_PASSPHRASE) { - TextView instructionsView = (TextView) v.findViewById(R.id.reset_sync_text); - instructionsView.setVisibility(View.VISIBLE); + TextViewWithClickableSpans instructionsView = + new TextViewWithClickableSpans(getActivity()); + instructionsView.setPadding(0, + getResources().getDimensionPixelSize( + R.dimen.sync_passphrase_type_instructions_padding), + 0, 0); instructionsView.setMovementMethod(LinkMovementMethod.getInstance()); instructionsView.setText(getResetText()); + list.addFooterView(instructionsView); } + Adapter adapter = createAdapter(currentType); + list.setAdapter(adapter); + list.setId(R.id.passphrase_type_list); + list.setOnItemClickListener(this); + list.setDividerHeight(0); + list.setSelection(adapter.getPositionForType(currentType)); + // Create and return the dialog return new AlertDialog.Builder(getActivity(), R.style.AlertDialogTheme) .setNegativeButton(R.string.cancel, this)
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java index ff726ad0..af97eb1c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/HomeButton.java
@@ -17,7 +17,11 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ActivityTabProvider; +import org.chromium.chrome.browser.ActivityTabProvider.ActivityTabTabObserver; +import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.partnercustomizations.HomepageManager; +import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.ui.widget.ChromeImageButton; @@ -33,6 +37,9 @@ /** A provider that notifies components when the theme color changes.*/ private ThemeColorProvider mThemeColorProvider; + /** The {@link sActivityTabTabObserver} used to know when the active page changed. */ + private ActivityTabTabObserver mActivityTabTabObserver; + public HomeButton(Context context, AttributeSet attrs) { super(context, attrs); @@ -51,6 +58,10 @@ mThemeColorProvider.removeObserver(this); mThemeColorProvider = null; } + if (mActivityTabTabObserver != null) { + mActivityTabTabObserver.destroy(); + mActivityTabTabObserver = null; + } } public void setThemeColorProvider(ThemeColorProvider themeColorProvider) { @@ -74,4 +85,25 @@ HomepageManager.getInstance().setPrefHomepageEnabled(false); return true; } + + public void setActivityTabProvider(ActivityTabProvider activityTabProvider) { + mActivityTabTabObserver = new ActivityTabTabObserver(activityTabProvider) { + @Override + public void onObservingDifferentTab(Tab tab) { + if (tab == null) return; + setEnabled(shouldEnableHome(tab)); + } + + @Override + public void onPageLoadFinished(Tab tab, String url) { + if (tab == null) return; + setEnabled(shouldEnableHome(tab)); + } + }; + } + + private static boolean shouldEnableHome(Tab tab) { + if (!FeatureUtilities.isBottomToolbarEnabled()) return true; + return !NewTabPage.isNTPUrl(tab.getUrl()); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java index 4cc3072..bc6988f2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BrowsingModeBottomToolbarCoordinator.java
@@ -85,6 +85,7 @@ mHomeButton = toolbarRoot.findViewById(R.id.home_button); mHomeButton.setOnClickListener(homeButtonListener); + mHomeButton.setActivityTabProvider(tabProvider); mShareButton = toolbarRoot.findViewById(R.id.share_button); mShareButton.setOnClickListener(shareButtonListener); @@ -142,7 +143,6 @@ mHomeButton.setThemeColorProvider(themeColorProvider); mShareButton.setThemeColorProvider(themeColorProvider); - mShareButton.setTabModelSelector(tabModelSelector); mSearchAccelerator.setThemeColorProvider(themeColorProvider); mTabSwitcherButtonCoordinator.setTabSwitcherListener(tabSwitcherListener);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java index 0189d3d..da6a11bd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java
@@ -10,11 +10,9 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.browser.ActivityTabProvider; -import org.chromium.chrome.browser.ActivityTabProvider.HintlessActivityTabObserver; +import org.chromium.chrome.browser.ActivityTabProvider.ActivityTabTabObserver; import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tabmodel.TabModelSelector; -import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver; import org.chromium.chrome.browser.toolbar.ThemeColorProvider; import org.chromium.chrome.browser.toolbar.ThemeColorProvider.ThemeColorObserver; import org.chromium.ui.widget.ChromeImageButton; @@ -26,14 +24,8 @@ /** A provider that notifies components when the theme color changes.*/ private ThemeColorProvider mThemeColorProvider; - /** The {@link HintlessActivityTabObserver} used to know when the activity tab changed. */ - private HintlessActivityTabObserver mHintlessActivityTabObserver; - - /** The {@link ActivityTabProvider} used to know when the activity tab changed. */ - private ActivityTabProvider mActivityTabProvider; - - /** A {@link TabModelSelector} used to know when a new page has loaded. */ - private TabModelSelectorTabObserver mTabModelSelectorTabObserver; + /** The {@link sActivityTabTabObserver} used to know when the active page changed. */ + private ActivityTabTabObserver mActivityTabTabObserver; public ShareButton(Context context, AttributeSet attrs) { super(context, attrs); @@ -45,19 +37,13 @@ } void setActivityTabProvider(ActivityTabProvider activityTabProvider) { - mActivityTabProvider = activityTabProvider; - mHintlessActivityTabObserver = new HintlessActivityTabObserver() { + mActivityTabTabObserver = new ActivityTabTabObserver(activityTabProvider) { @Override - public void onActivityTabChanged(Tab tab) { + public void onObservingDifferentTab(Tab tab) { if (tab == null) return; setEnabled(shouldEnableShare(tab)); } - }; - mActivityTabProvider.addObserverAndTrigger(mHintlessActivityTabObserver); - } - void setTabModelSelector(TabModelSelector tabModelSelector) { - mTabModelSelectorTabObserver = new TabModelSelectorTabObserver(tabModelSelector) { @Override public void onPageLoadFinished(Tab tab, String url) { if (tab == null) return; @@ -71,13 +57,9 @@ mThemeColorProvider.removeObserver(this); mThemeColorProvider = null; } - if (mTabModelSelectorTabObserver != null) { - mTabModelSelectorTabObserver.destroy(); - mTabModelSelectorTabObserver = null; - } - if (mActivityTabProvider != null) { - mActivityTabProvider.removeObserver(mHintlessActivityTabObserver); - mActivityTabProvider = null; + if (mActivityTabTabObserver != null) { + mActivityTabTabObserver.destroy(); + mActivityTabTabObserver = null; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tracing/TracingNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/tracing/TracingNotificationManager.java index 1103b8b..dcf31f3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tracing/TracingNotificationManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tracing/TracingNotificationManager.java
@@ -10,6 +10,7 @@ import android.app.NotificationManager; import android.content.Context; import android.os.Build; +import android.view.accessibility.AccessibilityManager; import org.chromium.base.ContextUtils; import org.chromium.base.VisibleForTesting; @@ -29,6 +30,7 @@ private static NotificationManagerProxy sNotificationManagerOverride; private static ChromeNotificationBuilder sTracingActiveNotificationBuilder; + private static int sTracingActiveNotificationBufferPercentage; // TODO(eseckler): Consider recording UMAs, see e.g. IncognitoNotificationManager. @@ -86,9 +88,10 @@ public static void showTracingActiveNotification() { Context context = ContextUtils.getApplicationContext(); String title = context.getResources().getString(R.string.tracing_active_notification_title); - int bufferUsagePercentage = 0; - String message = context.getResources().getString( - R.string.tracing_active_notification_message, bufferUsagePercentage); + sTracingActiveNotificationBufferPercentage = 0; + String message = + context.getResources().getString(R.string.tracing_active_notification_message, + sTracingActiveNotificationBufferPercentage); sTracingActiveNotificationBuilder = createNotificationBuilder() @@ -112,9 +115,20 @@ public static void updateTracingActiveNotification(float bufferUsagePercentage) { assert (sTracingActiveNotificationBuilder != null); Context context = ContextUtils.getApplicationContext(); + + // Don't update the notification if accessibility is enabled as this may interfere with + // selecting the stop button. + AccessibilityManager am = + (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE); + if (am.isEnabled() && am.isTouchExplorationEnabled()) return; + + int newPercentage = Math.round(bufferUsagePercentage * 100); + if (sTracingActiveNotificationBufferPercentage == newPercentage) return; + sTracingActiveNotificationBufferPercentage = newPercentage; + String message = context.getResources().getString(R.string.tracing_active_notification_message, - Math.round(bufferUsagePercentage * 100)); + sTracingActiveNotificationBufferPercentage); sTracingActiveNotificationBuilder.setContentText(message); showNotification(sTracingActiveNotificationBuilder.build());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java index 012a787..b4eb8a8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java
@@ -545,11 +545,18 @@ static String getSerializedShareTarget(String shareAction, String shareMethod, String shareEnctype, String shareParamsTitle, String shareParamsText, String shareParamsUrl, String shareParamsNames, String shareParamsAccepts) { - if (shareAction == null) return null; + if (TextUtils.isEmpty(shareAction)) return null; return String.format("action: \"%s\", method: \"%s\", enctype: \"%s\", title: \"%s\"" + "text: \"%s\", url: \"%s\", names: \"%s\", accepts: \"%s\"", - shareAction, shareMethod, shareEnctype, shareParamsTitle, shareParamsText, - shareParamsUrl, shareParamsNames, shareParamsAccepts); + shareAction, replaceNullWithEmpty(shareMethod), replaceNullWithEmpty(shareEnctype), + replaceNullWithEmpty(shareParamsTitle), replaceNullWithEmpty(shareParamsText), + replaceNullWithEmpty(shareParamsUrl), replaceNullWithEmpty(shareParamsNames), + replaceNullWithEmpty(shareParamsAccepts)); + } + + /** Returns the value if it is non-null. Returns an empty string otherwise. */ + private static String replaceNullWithEmpty(String value) { + return (value == null) ? "" : value; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java index 70e6377..1b15690 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateDataFetcher.java
@@ -112,8 +112,8 @@ iconUrlToMurmur2HashMap.put(iconUrl, murmur2Hash); } - String serializedShareTarget = WebApkInfo.getSerializedShareTarget( - shareAction, "", "", shareParamsTitle, shareParamsText, shareParamsUrl, "", ""); + String serializedShareTarget = WebApkInfo.getSerializedShareTarget(shareAction, null, null, + shareParamsTitle, shareParamsText, shareParamsUrl, null, null); WebApkInfo info = WebApkInfo.create(mOldInfo.id(), mOldInfo.uri().toString(), scopeUrl, new WebApkInfo.Icon(primaryIconBitmap), new WebApkInfo.Icon(badgeIconBitmap), null,
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 3db5e04..473096d 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -4009,6 +4009,9 @@ <message name="IDS_AUTOFILL_ASSISTANT_GOOGLE_TERMS_DESCRIPTION" desc="Message linking to the Google terms and conditions for Fast Checkout."> By continuing you agree to the Google terms and conditions for Fast Checkout. <ph name="BEGIN_LINK"><link></ph>Read more<ph name="END_LINK"></link></ph> </message> + <message name="IDS_AUTOFILL_ASSISTANT_GOOGLE_TERMS_URL" desc="URL for Google Autofill Assistant Terms of Service" translateable="false"> + http://support.google.com/assistant?p=fast_checkout + </message> </messages> </release> </grit>
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 0be14eeb..1d238c1a 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -880,6 +880,7 @@ "java/src/org/chromium/chrome/browser/media/router/MediaStatusBridge.java", "java/src/org/chromium/chrome/browser/media/router/MediaStatusObserver.java", "java/src/org/chromium/chrome/browser/media/router/MediaSink.java", + "java/src/org/chromium/chrome/browser/media/router/caf/BaseNotificationController.java", "java/src/org/chromium/chrome/browser/media/router/caf/BaseSessionController.java", "java/src/org/chromium/chrome/browser/media/router/caf/CastOptionsProvider.java", "java/src/org/chromium/chrome/browser/media/router/caf/CastSessionController.java", @@ -890,8 +891,10 @@ "java/src/org/chromium/chrome/browser/media/router/caf/CafNotificationController.java", "java/src/org/chromium/chrome/browser/media/router/caf/CreateRouteRequestInfo.java", "java/src/org/chromium/chrome/browser/media/router/caf/remoting/CafRemotingMediaRouteProvider.java", - "java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingSessionController.java", "java/src/org/chromium/chrome/browser/media/router/caf/remoting/FlingingControllerAdapter.java", + "java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingNotificationController.java", + "java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingSessionController.java", + "java/src/org/chromium/chrome/browser/media/router/caf/remoting/StreamPositionExtrapolator.java", "java/src/org/chromium/chrome/browser/media/router/cast/BaseMediaRouteProvider.java", "java/src/org/chromium/chrome/browser/media/router/cast/CastMediaRouteProvider.java", "java/src/org/chromium/chrome/browser/media/router/cast/CastMediaSource.java", @@ -1958,6 +1961,7 @@ "javatests/src/org/chromium/chrome/browser/download/ui/StubbedProvider.java", "javatests/src/org/chromium/chrome/browser/engagement/SiteEngagementServiceTest.java", "javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBridgeExperimentalTest.java", + "javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java", "javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java", "javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandlerTest.java", "javatests/src/org/chromium/chrome/browser/externalnav/IntentWithGesturesHandlerTest.java", @@ -2375,6 +2379,7 @@ "junit/src/org/chromium/chrome/browser/externalauth/ExternalAuthUtilsTest.java", "junit/src/org/chromium/chrome/browser/feedback/FeedbackCollectorTest.java", "junit/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencerTest.java", + "junit/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationUnitTest.java", "junit/src/org/chromium/chrome/browser/firstrun/ToSAckedReceiverTest.java", "junit/src/org/chromium/chrome/browser/fullscreen/BrowserStateBrowserControlsVisibilityDelegateTest.java", "junit/src/org/chromium/chrome/browser/fullscreen/TokenHolderTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardAccessoryViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardAccessoryViewTest.java index bb3595c..6b187f5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardAccessoryViewTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/KeyboardAccessoryViewTest.java
@@ -13,12 +13,11 @@ import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription; import static android.support.test.espresso.matcher.ViewMatchers.withText; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNull; - import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.core.AllOf.allOf; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.chromium.chrome.browser.autofill.keyboard_accessory.AccessoryAction.AUTOFILL_SUGGESTION;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingUiCaptureTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingUiCaptureTest.java index 180d84a..fd0135f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingUiCaptureTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingUiCaptureTest.java
@@ -26,6 +26,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.RetryOnFailure; import org.chromium.chrome.R; @@ -69,6 +70,7 @@ @MediumTest @DisableFeatures(ChromeFeatureList.AUTOFILL_KEYBOARD_ACCESSORY) @Feature({"KeyboardAccessory", "LTR", "UiCatalogue"}) + @DisabledTest // Test is flaky. (see https://crbug.com/913178) public void testCaptureKeyboardAccessoryWithPasswords() throws InterruptedException, TimeoutException { mHelper.loadTestPage(false); @@ -205,4 +207,4 @@ whenDisplayed(withId(R.id.keyboard_accessory_sheet)); onView(withParent(withId(R.id.keyboard_accessory_sheet))).check(this::waitUntilFilled); } -} \ No newline at end of file +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessoryIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessoryIntegrationTest.java index 8c274aab..8395ff7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessoryIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessoryIntegrationTest.java
@@ -18,6 +18,7 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; +import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.createEmptyCredentials; import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.createUserInfo; import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.selectTabAtPosition; import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.whenDisplayed; @@ -128,6 +129,11 @@ throws InterruptedException, TimeoutException { mHelper.loadTestPage(false); + // Focus the field to bring up the accessory. + mHelper.clickPasswordField(); + mHelper.waitForKeyboard(); + whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0)); + AccessorySheetData accessorySheetData = new AccessorySheetData("Passwords"); accessorySheetData.getUserInfoList().add( createUserInfo("mayapark@gmail.com", "SomeHiddenPassword")); @@ -136,11 +142,6 @@ "ExtremelyLongPasswordThatUsesQuiteSomeSpaceInTheSheet")); mHelper.sendCredentials(accessorySheetData); - // Focus the field to bring up the accessory. - mHelper.clickPasswordField(); - mHelper.waitForKeyboard(); - whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0)); - // Check that the provided elements are there. whenDisplayed(withText("Passwords")); whenDisplayed(withText("mayapark@gmail.com")); @@ -155,6 +156,12 @@ throws InterruptedException, TimeoutException { mHelper.loadTestPage(false); final AtomicReference<FooterCommand> clicked = new AtomicReference<>(); + + // Focus the field to bring up the accessory. + mHelper.clickPasswordField(); + mHelper.waitForKeyboard(); + whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0)); + AccessorySheetData accessorySheetData = new AccessorySheetData("No saved passwords for abc.com"); accessorySheetData.getFooterCommands().add( @@ -163,11 +170,6 @@ new FooterCommand("Manage passwords...", clicked::set)); mHelper.sendCredentials(accessorySheetData); - // Focus the field to bring up the accessory. - mHelper.clickPasswordField(); - mHelper.waitForKeyboard(); - whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0)); - // Scroll down and click the suggestion. whenDisplayed(withChild(withText("Suggest strong password..."))) .perform(scrollToPosition(2)); @@ -185,6 +187,11 @@ mHelper.loadTestPage(false); final AtomicReference<Field> clicked = new AtomicReference<>(); + // Focus the field to bring up the accessory. + mHelper.clickPasswordField(); + mHelper.waitForKeyboard(); + whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0)); + AccessorySheetData accessorySheetData = new AccessorySheetData("Passwords"); accessorySheetData.getUserInfoList().add( createUserInfo("mpark@abc.com", "ShorterPassword", clicked::set)); @@ -194,11 +201,6 @@ createUserInfo("mayapark@gmail.com", "SomeHiddenLongPassword")); mHelper.sendCredentials(accessorySheetData); - // Focus the field to bring up the accessory. - mHelper.clickPasswordField(); - mHelper.waitForKeyboard(); - whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0)); - // Click the suggestion. whenDisplayed(withText("mpark@abc.com")).perform(click()); @@ -216,14 +218,14 @@ // Focus the field to bring up the accessory. mHelper.clickPasswordField(); + mHelper.sendCredentials(createEmptyCredentials()); mHelper.waitForKeyboard(); // Click the tab to show the sheet and hide the keyboard. whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0)); mHelper.waitForKeyboardToDisappear(); whenDisplayed(withId(R.id.keyboard_accessory_sheet)); - onView(withText(containsString("No Saved passwords for this site"))) - .check(matches(isDisplayed())); + onView(withText(containsString("No Saved passwords"))).check(matches(isDisplayed())); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java index 1e237f0..9f0f0f2e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -36,7 +36,6 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; @@ -534,7 +533,6 @@ @Test @SmallTest @Feature({"AppBanners"}) - @DisabledTest(message = "crbug.com/903657") public void testAppInstalledModalNativeAppBannerCustomTab() throws Exception { mCustomTabActivityTestRule.startCustomTabActivityWithIntent( CustomTabsTestUtils.createMinimalCustomTabIntent( @@ -549,7 +547,7 @@ // The appinstalled event should fire (and cause the title to change). new TabTitleObserver(mCustomTabActivityTestRule.getActivity().getActivityTab(), - "Got appinstalled: listener, attr") + "Got userChoice: accepted") .waitForTitleUpdate(3); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsTest.java index 474700d..3061ca7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsTest.java
@@ -40,6 +40,7 @@ import org.chromium.chrome.browser.dependency_injection.ChromeAppModule; import org.chromium.chrome.browser.dependency_injection.ModuleFactoryOverrides; import org.chromium.chrome.browser.feature_engagement.TrackerFactory; +import org.chromium.chrome.browser.fullscreen.FullscreenManagerTestUtils; import org.chromium.chrome.browser.modelutil.ListObservable; import org.chromium.chrome.browser.modelutil.ListObservable.ListObserver; import org.chromium.chrome.browser.multiwindow.MultiWindowTestHelper; @@ -60,6 +61,7 @@ import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.chrome.test.util.RenderTestRule; +import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.chrome.test.util.browser.RecyclerViewTestUtils; import org.chromium.chrome.test.util.browser.compositor.layouts.DisableChromeAnimations; @@ -344,11 +346,44 @@ @Test @MediumTest @Feature({"ContextualSuggestions"}) - @DisabledTest(message = "https://crbug.com/890947") @EnableFeatures(ChromeFeatureList.CONTEXTUAL_SUGGESTIONS_BUTTON) - public void testInProductHelp() throws InterruptedException, TimeoutException { - assertTrue( - "Help bubble should be showing.", mMediator.getHelpBubbleForTesting().isShowing()); + @DisableFeatures(ChromeFeatureList.CONTEXTUAL_SUGGESTIONS_IPH_REVERSE_SCROLL) + public void testInProductHelp_DontRequireReverseScroll() throws Exception { + // IPH can only be shown after the animation completes. + ThreadUtils.runOnUiThreadBlocking( + () -> getToolbarPhone().endExperimentalButtonAnimationForTesting()); + + CriteriaHelper.pollUiThread(() -> mMediator.getHelpBubbleForTesting() != null && + mMediator.getHelpBubbleForTesting().isShowing(), + "Help bubble never shown."); + + ThreadUtils.runOnUiThreadBlocking(() -> mMediator.getHelpBubbleForTesting().dismiss()); + + Assert.assertEquals("Help bubble should be dimissed.", 1, + mFakeTracker.mDimissedCallbackHelper.getCallCount()); + } + + @Test + @MediumTest + @Feature({"ContextualSuggestions"}) + @EnableFeatures({ChromeFeatureList.CONTEXTUAL_SUGGESTIONS_BUTTON, + ChromeFeatureList.CONTEXTUAL_SUGGESTIONS_IPH_REVERSE_SCROLL}) + public void testInProductHelp_RequireReverseScroll() throws Exception { + // IPH can only be shown after the animation to show the toolbar button completes. + ThreadUtils.runOnUiThreadBlocking( + () -> getToolbarPhone().endExperimentalButtonAnimationForTesting()); + + Assert.assertNull("Help bubble should not be shown yet.", + mMediator.getHelpBubbleForTesting()); + + // Scroll the base page, hiding then reshowing the browser controls. + FullscreenManagerTestUtils.disableBrowserOverrides(); + FullscreenManagerTestUtils.waitForBrowserControlsToBeMoveable( + mActivityTestRule, mActivityTestRule.getActivity().getActivityTab()); + + CriteriaHelper.pollUiThread(() -> mMediator.getHelpBubbleForTesting() != null && + mMediator.getHelpBubbleForTesting().isShowing(), + "Help bubble never shown."); ThreadUtils.runOnUiThreadBlocking(() -> mMediator.getHelpBubbleForTesting().dismiss());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextual_suggestions/FakeTracker.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextual_suggestions/FakeTracker.java index 5342219..3b04209 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextual_suggestions/FakeTracker.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextual_suggestions/FakeTracker.java
@@ -49,7 +49,9 @@ } @Override - public void addOnInitializedCallback(Callback<Boolean> callback) {} + public void addOnInitializedCallback(Callback<Boolean> callback) { + callback.onResult(true); + } @Override public boolean wouldTriggerHelpUI(String feature) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java index 4d10231b..5932cc64 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -127,6 +127,7 @@ import org.chromium.content_public.browser.test.util.JavaScriptUtils; import org.chromium.content_public.browser.test.util.WebContentsUtils; import org.chromium.net.test.EmbeddedTestServer; +import org.chromium.net.test.ServerCertificate; import org.chromium.net.test.util.TestWebServer; import org.chromium.ui.base.PageTransition; import org.chromium.ui.mojom.WindowOpenDisposition; @@ -1150,13 +1151,14 @@ @EnableFeatures(ChromeFeatureList.CCT_MODULE) public void testCloseButtonBehaviourWithDynamicModule() throws InterruptedException, ExecutionException, TimeoutException { - String moduleManagedUrl1 = mTestServer.getURL( - "/chrome/test/data/android/about.html"); - String moduleManagedUrl2 = mTestServer.getURL( - "/chrome/test/data/android/simple.html"); + setupHttpsTestServerAndPages(); + String relativeUrl1 = "/chrome/test/data/android/about.html"; + String moduleManagedUrl1 = mTestServer.getURL(relativeUrl1); + String relativeUrl2 = "/chrome/test/data/android/simple.html"; + String moduleManagedUrl2 = mTestServer.getURL(relativeUrl2); - Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(moduleManagedUrl1, - "^(" + moduleManagedUrl1 + "|" + moduleManagedUrl2 + ")$"); + Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent( + moduleManagedUrl1, "^(" + relativeUrl1 + "|" + relativeUrl2 + ")$"); // Open CCT with moduleManagedUrl1 and navigate // moduleManagedUrl1 -> nav1.1 - nav1.2 -> modulemanagedUrl2 -> nav2.1 -> nav2.2 @@ -1209,6 +1211,7 @@ @SmallTest public void testCloseButtonBehaviourWithoutDynamicModule() throws InterruptedException, ExecutionException, TimeoutException { + setupHttpsTestServerAndPages(); String moduleManagedUrl1 = mTestServer.getURL( "/chrome/test/data/android/about.html"); String moduleManagedUrl2 = mTestServer.getURL( @@ -1247,8 +1250,9 @@ @SmallTest public void testCloseButtonBehaviourDynamicModuleLoadFails() throws InterruptedException, ExecutionException, TimeoutException { - String moduleManagedUrl = mTestServer.getURL( - "/chrome/test/data/android/about.html"); + setupHttpsTestServerAndPages(); + String relativeUrl = "/chrome/test/data/android/about.html"; + String moduleManagedUrl = mTestServer.getURL(relativeUrl); // Open CCT with moduleManagedUrl1 and navigate // moduleManagedUrl1 -> nav1.1 - nav1.2 @@ -1258,7 +1262,7 @@ new ComponentName(CustomTabsDynamicModuleTestUtils.FAKE_MODULE_PACKAGE_NAME, "ClassName"); Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent( - componentName, moduleManagedUrl, "^" + moduleManagedUrl+ "$"); + componentName, moduleManagedUrl, "^(" + relativeUrl + ")$"); mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity(); @@ -1285,6 +1289,7 @@ @SmallTest @EnableFeatures(ChromeFeatureList.CCT_MODULE) public void testSetTopBarContentView() throws Exception { + setupHttpsTestServerAndPages(); String moduleManagedUrl = mTestServer.getURL("/chrome/test/data/android/about.html"); Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(moduleManagedUrl, null); @@ -1306,6 +1311,7 @@ @SmallTest @EnableFeatures(ChromeFeatureList.CCT_MODULE) public void testSetTopBarContentView_secondCallIsNoOp() throws Exception { + setupHttpsTestServerAndPages(); String moduleManagedUrl = mTestServer.getURL("/chrome/test/data/android/about.html"); Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(moduleManagedUrl, null); @@ -1328,8 +1334,9 @@ Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent( InstrumentationRegistry.getTargetContext(), "https://www.google.com/search?q=london"); - intent.putExtra(CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_URLS_REGEX, - "^https://www.google.com/search.*"); + intent.putExtra( + CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_HOST_LIST, "www.google.com"); + intent.putExtra(CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_URLS_REGEX, "/search.*"); mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); waitForModuleLoading(); @@ -1346,9 +1353,11 @@ @SmallTest @DisableFeatures(ChromeFeatureList.CCT_MODULE) public void testSetTopBarContentView_featureDisabled_noTopBar() throws Exception { - String moduleManagedUrl = mTestServer.getURL("/chrome/test/data/android/about.html"); + setupHttpsTestServerAndPages(); + String relativeUrl = "/chrome/test/data/android/about.html"; + String moduleManagedUrl = mTestServer.getURL(relativeUrl); Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent( - moduleManagedUrl, "^(" + moduleManagedUrl + ")$"); + moduleManagedUrl, "^(" + relativeUrl + ")$"); mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); waitForModuleLoading(); @@ -1388,9 +1397,11 @@ @SmallTest @EnableFeatures(ChromeFeatureList.CCT_MODULE) public void testSetTopBarContentView_withModuleAndManagedUrls_topBarVisible() throws Exception { - String moduleManagedUrl = mTestServer.getURL("/chrome/test/data/android/about.html"); + setupHttpsTestServerAndPages(); + String relativeUrl = "/chrome/test/data/android/about.html"; + String moduleManagedUrl = mTestServer.getURL(relativeUrl); Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent( - moduleManagedUrl, "^(" + moduleManagedUrl + ")$"); + moduleManagedUrl, "^(" + relativeUrl + ")$"); mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); waitForModuleLoading(); @@ -1412,8 +1423,9 @@ Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent( InstrumentationRegistry.getTargetContext(), "https://www.google.com/search?q=london"); - intent.putExtra(CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_URLS_REGEX, - "^https://www.google.com/search.*"); + intent.putExtra( + CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_HOST_LIST, "www.google.com"); + intent.putExtra(CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_URLS_REGEX, "/search.*"); intent.putExtra( CustomTabIntentDataProvider.EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS, true); mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); @@ -1434,9 +1446,11 @@ @SmallTest @DisableFeatures(ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER) public void testSetTopBarContentView_featureDisabled_cctHeaderVisible() throws Exception { - String moduleManagedUrl = mTestServer.getURL("/chrome/test/data/android/about.html"); + setupHttpsTestServerAndPages(); + String relativeUrl = "/chrome/test/data/android/about.html"; + String moduleManagedUrl = mTestServer.getURL(relativeUrl); Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent( - moduleManagedUrl, "^(" + moduleManagedUrl + ")$"); + moduleManagedUrl, "^(" + relativeUrl + ")$"); intent.putExtra( CustomTabIntentDataProvider.EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS, true); mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); @@ -1456,10 +1470,39 @@ @Test @SmallTest @EnableFeatures({ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER}) - public void testSetTopBarContentView_withModuleAndExtras_cctHeaderHidden() throws Exception { - String moduleManagedUrl = mTestServer.getURL("/chrome/test/data/android/about.html"); + public void testSetTopBarContentView_notModuleManagedHost_cctHeaderVisible() throws Exception { + setupHttpsTestServerAndPages(); + String relativeUrl = "/chrome/test/data/android/about.html"; + String moduleManagedUrl = mTestServer.getURL(relativeUrl); Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent( - moduleManagedUrl, "^(" + moduleManagedUrl + ")$"); + moduleManagedUrl, "^(" + relativeUrl + ")$"); + intent.putExtra( + CustomTabIntentDataProvider.EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS, true); + intent.putExtra( + CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_HOST_LIST, "www.google.com"); + mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); + waitForModuleLoading(); + + ThreadUtils.runOnUiThread(() -> { + CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity(); + cctActivity.setTopBarContentView(new View(cctActivity)); + View toolbarView = cctActivity.findViewById(R.id.toolbar); + Assert.assertTrue( + "A custom tab toolbar is never shown", toolbarView instanceof CustomTabToolbar); + CustomTabToolbar toolbar = (CustomTabToolbar) toolbarView; + Assert.assertEquals(View.VISIBLE, toolbar.getVisibility()); + }); + } + + @Test + @SmallTest + @EnableFeatures({ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER}) + public void testSetTopBarContentView_withModuleAndExtras_cctHeaderHidden() throws Exception { + setupHttpsTestServerAndPages(); + String relativeUrl = "/chrome/test/data/android/about.html"; + String moduleManagedUrl = mTestServer.getURL(relativeUrl); + Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent( + moduleManagedUrl, "^(" + relativeUrl + ")$"); intent.putExtra( CustomTabIntentDataProvider.EXTRA_HIDE_CCT_HEADER_ON_MODULE_MANAGED_URLS, true); mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); @@ -3276,4 +3319,14 @@ } }); } + + private void setupHttpsTestServerAndPages() throws InterruptedException { + mTestServer.stopAndDestroyServer(); + // Module managed hosts only work with HTTPS. + mTestServer = EmbeddedTestServer.createAndStartHTTPSServer( + InstrumentationRegistry.getInstrumentation().getContext(), + ServerCertificate.CERT_OK); + mTestPage = mTestServer.getURL(TEST_PAGE); + mTestPage2 = mTestServer.getURL(TEST_PAGE_2); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleTestUtils.java index 984831f..01bc3e8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleTestUtils.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleTestUtils.java
@@ -5,12 +5,14 @@ package org.chromium.chrome.browser.customtabs; import static org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider.EXTRA_MODULE_CLASS_NAME; +import static org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_HOST_LIST; import static org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider.EXTRA_MODULE_PACKAGE_NAME; import static org.chromium.chrome.browser.customtabs.dynamicmodule.DynamicModuleNavigationEventObserver.PENDING_URL_KEY; import static org.chromium.chrome.browser.customtabs.dynamicmodule.DynamicModuleNavigationEventObserver.URL_KEY; import android.content.ComponentName; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.customtabs.CustomTabsCallback; @@ -29,6 +31,8 @@ import org.chromium.chrome.browser.document.ChromeLauncherActivity; import org.chromium.chrome.browser.externalauth.ExternalAuthUtils; +import java.util.ArrayList; +import java.util.Arrays; import java.util.concurrent.TimeoutException; /** @@ -210,6 +214,8 @@ intent.putExtra(EXTRA_MODULE_CLASS_NAME, componentName.getClassName()); if (managedUrlsRegex != null) { + intent.putStringArrayListExtra(EXTRA_MODULE_MANAGED_HOST_LIST, + new ArrayList<>(Arrays.asList(Uri.parse(url).getHost()))); intent.putExtra(CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_URLS_REGEX, managedUrlsRegex); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java new file mode 100644 index 0000000..4ff3cce --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
@@ -0,0 +1,129 @@ +// 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. + +package org.chromium.chrome.browser.explore_sites; + +import static android.support.test.espresso.Espresso.onView; + +import static org.hamcrest.Matchers.instanceOf; + +import android.annotation.TargetApi; +import android.os.Build; +import android.support.test.espresso.contrib.RecyclerViewActions; +import android.support.test.filters.SmallTest; +import android.support.v7.widget.RecyclerView; +import android.view.ViewGroup; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.UrlConstants; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +import org.chromium.chrome.test.util.RenderTestRule; +import org.chromium.chrome.test.util.browser.Features; +import org.chromium.content_public.browser.test.util.Criteria; +import org.chromium.content_public.browser.test.util.CriteriaHelper; + +import java.util.ArrayList; + +/** + * Simple test to demonstrate use of ScreenShooter rule. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags + .Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) + @Features.EnableFeatures(ChromeFeatureList.EXPLORE_SITES) + public class ExploreSitesPageTest { + ArrayList<ExploreSitesCategory> getTestingCatalog() { + final ArrayList<ExploreSitesCategory> categoryList = new ArrayList<>(); + for (int i = 0; i < 4; i++) { + ExploreSitesCategory category = + new ExploreSitesCategory(i, i, "Category #" + Integer.toString(i)); + for (int j = 0; j < 8; j++) { + ExploreSitesSite site = new ExploreSitesSite( + i * 8 + j, j, "Site #" + Integer.toString(j), "https://example.com/"); + category.addSite(site); + } + categoryList.add(category); + } + + return categoryList; + } + + @Rule + public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); + + @Rule + public RenderTestRule mRenderTestRule = + new RenderTestRule("chrome/test/data/android/render_tests"); + + private Tab mTab; + private ViewGroup mRecyclerView; + private ExploreSitesPage mEsp; + + @Before + public void setUp() throws Exception { + ExploreSitesBridge.setCatalogForTesting(getTestingCatalog()); + mActivityTestRule.startMainActivityWithURL("about:blank"); + + mActivityTestRule.loadUrl(UrlConstants.EXPLORE_URL); + mTab = mActivityTestRule.getActivity().getActivityTab(); + waitForEspLoaded(mTab); + + Assert.assertTrue(mTab.getNativePage() instanceof ExploreSitesPage); + mEsp = (ExploreSitesPage) mTab.getNativePage(); + mRecyclerView = mEsp.getView().findViewById(R.id.explore_sites_category_recycler); + } + + @After + public void tearDown() throws Exception { + ExploreSitesBridge.setCatalogForTesting(null); + } + + @Test + @SmallTest + @Feature({"ExploreSites", "RenderTest"}) + public void testScrolledLayout_withBack() throws Exception { + onView(instanceOf(RecyclerView.class)).perform(RecyclerViewActions.scrollToPosition(2)); + + mRenderTestRule.render(mRecyclerView, "recycler_layout"); + mActivityTestRule.loadUrl("about:blank"); + ThreadUtils.runOnUiThreadBlocking(() -> mActivityTestRule.getActivity().onBackPressed()); + mRenderTestRule.render(mRecyclerView, "recycler_layout_back"); + } + + @Test + @SmallTest + @Feature({"ExploreSites", "RenderTest"}) + public void testInitialLayout() throws Exception { + onView(instanceOf(RecyclerView.class)).perform(RecyclerViewActions.scrollToPosition(0)); + mRenderTestRule.render(mRecyclerView, "initial_layout"); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public static void waitForEspLoaded(final Tab tab) { + CriteriaHelper.pollUiThread(new Criteria("ESP never fully loaded") { + @Override + public boolean isSatisfied() { + if (tab.getNativePage() instanceof ExploreSitesPage) { + return ((ExploreSitesPage) tab.getNativePage()).isLoadedForTests(); + } else { + return false; + } + } + }); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedConfigurationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedConfigurationTest.java index 2bab354c..1af3334 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedConfigurationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedConfigurationTest.java
@@ -51,6 +51,7 @@ Assert.assertEquals(FeedConfiguration.SESSION_LIFETIME_MS_DEFAULT, FeedConfiguration.getSessionLifetimeMs()); Assert.assertFalse(FeedConfiguration.getTriggerImmediatePagination()); + Assert.assertTrue(FeedConfiguration.getUseTimeoutScheduler()); Assert.assertEquals(FeedConfiguration.VIEW_LOG_THRESHOLD_DEFAULT, FeedConfiguration.getViewLogThreshold(), ASSERT_EQUALS_DOUBLE_DELTA); } @@ -146,6 +147,16 @@ @Feature({"Feed"}) @CommandLineFlags. Add({"enable-features=InterestFeedContentSuggestions<Trial", "force-fieldtrials=Trial/Group", + "force-fieldtrial-params=Trial.Group:use_timeout_scheduler/false"}) + public void + testUseTimeoutScheduler() { + Assert.assertFalse(FeedConfiguration.getUseTimeoutScheduler()); + } + + @Test + @Feature({"Feed"}) + @CommandLineFlags. + Add({"enable-features=InterestFeedContentSuggestions<Trial", "force-fieldtrials=Trial/Group", "force-fieldtrial-params=Trial.Group:view_log_threshold/0.33"}) public void testViewLogThreshold() { Assert.assertEquals( @@ -177,6 +188,7 @@ configuration.getValueOrDefault(ConfigKey.SESSION_LIFETIME_MS, 0l)); Assert.assertFalse( configuration.getValueOrDefault(ConfigKey.TRIGGER_IMMEDIATE_PAGINATION, true)); + Assert.assertTrue(configuration.getValueOrDefault(ConfigKey.USE_TIMEOUT_SCHEDULER, false)); Assert.assertEquals(Double.valueOf(FeedConfiguration.VIEW_LOG_THRESHOLD_DEFAULT), configuration.getValueOrDefault(ConfigKey.VIEW_LOG_THRESHOLD, 0d), ASSERT_EQUALS_DOUBLE_DELTA);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java index 9f1b29c..a64f6cb 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java
@@ -68,6 +68,8 @@ @CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE) @Features.EnableFeatures(ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS) public class FeedNewTabPageTest { + private static final String TEST_FEED = + UrlUtils.getIsolatedTestFilePath("/chrome/test/data/android/feed/feed_large.gcl.bin"); private static final int ARTICLE_SECTION_HEADER_POSITION = 1; private static final int SIGNIN_PROMO_POSITION = 2; @@ -84,9 +86,6 @@ private EmbeddedTestServer mTestServer; private List<SiteSuggestion> mSiteSuggestions; - private static final String TEST_FEED = - UrlUtils.getIsolatedTestFilePath("/chrome/test/data/android/feed/feed_large.gcl.bin"); - @Before public void setUp() throws Exception { TestNetworkClient client = new TestNetworkClient(); @@ -126,6 +125,14 @@ .getSigninObserverForTesting(); RecyclerView recyclerView = (RecyclerView) mNtp.getStream().getView(); + // Prioritize RecyclerView's focusability so that the sign-in promo button and the action + // button don't get focused initially to avoid flakiness. + int descendantFocusability = recyclerView.getDescendantFocusability(); + ThreadUtils.runOnUiThreadBlocking((() -> { + recyclerView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); + recyclerView.requestFocus(); + })); + // Simulate sign in, scroll to the position where sign-in promo could be placed, and verify // that sign-in promo is not shown. ThreadUtils.runOnUiThreadBlocking(signinObserver::onSignedIn); @@ -142,17 +149,17 @@ .perform(RecyclerViewActions.scrollToPosition(SIGNIN_PROMO_POSITION)); onView(withId(R.id.signin_promo_view_container)).check(matches(isDisplayed())); - // Scroll to the article section header in case it is not visible. - onView(instanceOf(RecyclerView.class)) - .perform(RecyclerViewActions.scrollToPosition(ARTICLE_SECTION_HEADER_POSITION)); - // Hide articles and verify that the sign-in promo is not shown. - onView(withId(R.id.header_title)).perform(click()); + toggleHeader(recyclerView, false); onView(withId(R.id.signin_promo_view_container)).check(doesNotExist()); // Show articles and verify that the sign-in promo is shown. - onView(withId(R.id.header_title)).perform(click()); + toggleHeader(recyclerView, true); onView(withId(R.id.signin_promo_view_container)).check(matches(isDisplayed())); + + // Reset states. + ThreadUtils.runOnUiThreadBlocking( + () -> recyclerView.setDescendantFocusability(descendantFocusability)); } @Test @@ -194,9 +201,8 @@ @MediumTest @Feature({"FeedNewTabPage"}) public void testArticleSectionHeader() throws Exception { - // Disable the sign-in promo so the header is visible above the fold. - SignInPromo.setDisablePromoForTests(true); - final int expectedHeaderViewsCount = 2; + final int expectedCountWhenCollapsed = 2; + final int expectedCountWhenExpanded = 4; // 3 header views and the empty view. // Open a new tab. Tab tab1 = mActivityTestRule.loadUrlInNewTab(UrlConstants.NTP_URL); @@ -206,17 +212,15 @@ // Check header is expanded. Assert.assertTrue(firstHeader.isExpandable() && firstHeader.isExpanded()); - Assert.assertTrue(adapter1.getItemCount() > expectedHeaderViewsCount); + Assert.assertEquals(expectedCountWhenExpanded, adapter1.getItemCount()); Assert.assertTrue(getPreferenceForArticleSectionHeader()); // Toggle header on the current tab. - onView(withId(R.id.header_title)).perform(click()); - waitForView((ViewGroup) ntp1.getStream().getView(), - allOf(withId(R.id.header_status), withText(R.string.show))); + toggleHeader((ViewGroup) ntp1.getStream().getView(), false); // Check header is collapsed. Assert.assertTrue(firstHeader.isExpandable() && !firstHeader.isExpanded()); - Assert.assertEquals(expectedHeaderViewsCount, adapter1.getItemCount()); + Assert.assertEquals(expectedCountWhenCollapsed, adapter1.getItemCount()); Assert.assertFalse(getPreferenceForArticleSectionHeader()); // Open a second new tab. @@ -227,17 +231,15 @@ // Check header on the second tab is collapsed. Assert.assertTrue(secondHeader.isExpandable() && !secondHeader.isExpanded()); - Assert.assertEquals(expectedHeaderViewsCount, adapter2.getItemCount()); + Assert.assertEquals(expectedCountWhenCollapsed, adapter2.getItemCount()); Assert.assertFalse(getPreferenceForArticleSectionHeader()); // Toggle header on the second tab. - onView(withId(R.id.header_title)).perform(click()); - waitForView((ViewGroup) ntp2.getStream().getView(), - allOf(withId(R.id.header_status), withText(R.string.hide))); + toggleHeader((ViewGroup) ntp2.getStream().getView(), true); // Check header on the second tab is expanded. Assert.assertTrue(secondHeader.isExpandable() && secondHeader.isExpanded()); - Assert.assertTrue(adapter2.getItemCount() > expectedHeaderViewsCount); + Assert.assertEquals(expectedCountWhenExpanded, adapter2.getItemCount()); Assert.assertTrue(getPreferenceForArticleSectionHeader()); // Go back to the first tab and wait for a stable recycler view. @@ -245,11 +247,8 @@ // Check header on the first tab is expanded. Assert.assertTrue(firstHeader.isExpandable() && firstHeader.isExpanded()); - Assert.assertTrue(adapter1.getItemCount() > expectedHeaderViewsCount); + Assert.assertEquals(expectedCountWhenExpanded, adapter1.getItemCount()); Assert.assertTrue(getPreferenceForArticleSectionHeader()); - - // Reset state. - SignInPromo.setDisablePromoForTests(false); } @Test @@ -309,6 +308,21 @@ Pref.NTP_ARTICLES_SECTION_ENABLED, pref)); } + /** + * Toggles the header and checks whether the header has the right status. + * @param rootView The {@link ViewGroup} that contains the header view. + * @param expanded Whether the header should be expanded. + */ + private void toggleHeader(ViewGroup rootView, boolean expanded) { + onView(instanceOf(RecyclerView.class)) + .perform(RecyclerViewActions.scrollToPosition(ARTICLE_SECTION_HEADER_POSITION), + RecyclerViewActions.actionOnItemAtPosition( + ARTICLE_SECTION_HEADER_POSITION, click())); + waitForView(rootView, + allOf(withId(R.id.header_status), + withText(expanded ? R.string.hide : R.string.show))); + } + private boolean getPreferenceForArticleSectionHeader() throws Exception { return ThreadUtils.runOnUiThreadBlocking( () -> PrefServiceBridge.getInstance().getBoolean(Pref.NTP_ARTICLES_LIST_VISIBLE));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java index f4e66966..481525b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java
@@ -11,7 +11,6 @@ import android.content.Intent; import android.net.Uri; import android.os.Bundle; -import android.support.customtabs.CustomTabsIntent; import android.support.test.InstrumentationRegistry; import android.support.test.filters.MediumTest; import android.support.test.filters.SmallTest; @@ -35,7 +34,6 @@ import org.chromium.chrome.browser.locale.LocaleManager.SearchEnginePromoType; import org.chromium.chrome.browser.search_engines.TemplateUrl; import org.chromium.chrome.browser.search_engines.TemplateUrlService; -import org.chromium.chrome.browser.searchwidget.SearchActivity; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.MultiActivityTestRule; import org.chromium.content_public.browser.test.util.Criteria; @@ -67,103 +65,6 @@ @Test @SmallTest - @DisabledTest(message = "crbug.com/911316") - public void testGenericViewIntentGoesToFirstRun() { - final String asyncClassName = ChromeLauncherActivity.class.getName(); - runFirstRunRedirectTestForActivity(asyncClassName, () -> { - final Context context = InstrumentationRegistry.getTargetContext(); - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://test.com")); - intent.setPackage(context.getPackageName()); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); - }); - } - - @Test - @SmallTest - @DisabledTest(message = "crbug.com/911316") - public void testRedirectCustomTabActivityToFirstRun() { - final String asyncClassName = ChromeLauncherActivity.class.getName(); - runFirstRunRedirectTestForActivity(asyncClassName, () -> { - Context context = InstrumentationRegistry.getTargetContext(); - CustomTabsIntent customTabIntent = new CustomTabsIntent.Builder().build(); - customTabIntent.intent.setPackage(context.getPackageName()); - customTabIntent.intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - customTabIntent.launchUrl(context, Uri.parse("http://test.com")); - }); - } - - @Test - @SmallTest - @DisabledTest(message = "crbug.com/907548") - public void testRedirectChromeTabbedActivityToFirstRun() { - final String asyncClassName = ChromeTabbedActivity.class.getName(); - runFirstRunRedirectTestForActivity(asyncClassName, () -> { - final Context context = InstrumentationRegistry.getTargetContext(); - Intent intent = new Intent(); - intent.setClassName(context, asyncClassName); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); - }); - } - - @Test - @SmallTest - @DisabledTest(message = "crbug.com/911316") - public void testRedirectSearchActivityToFirstRun() { - final String asyncClassName = SearchActivity.class.getName(); - runFirstRunRedirectTestForActivity(asyncClassName, () -> { - final Context context = InstrumentationRegistry.getTargetContext(); - Intent intent = new Intent(); - intent.setClassName(context, asyncClassName); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); - }); - } - - /** - * Tests that an AsyncInitializationActivity subclass that attempts to be run without first - * having gone through First Run kicks the user out into the FRE. - * @param asyncClassName Name of the class to expect. - * @param runnable Runnable that launches the Activity. - */ - private void runFirstRunRedirectTestForActivity(String asyncClassName, Runnable runnable) { - final ActivityMonitor activityMonitor = new ActivityMonitor(asyncClassName, null, false); - final ActivityMonitor freMonitor = - new ActivityMonitor(FirstRunActivity.class.getName(), null, false); - final ActivityMonitor tabbedFREMonitor = - new ActivityMonitor(TabbedModeFirstRunActivity.class.getName(), null, false); - - Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); - instrumentation.addMonitor(activityMonitor); - instrumentation.addMonitor(freMonitor); - instrumentation.addMonitor(tabbedFREMonitor); - runnable.run(); - - // The original activity should be started because it was directly specified. - final Activity original = instrumentation.waitForMonitorWithTimeout( - activityMonitor, CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL); - Assert.assertNotNull(original); - CriteriaHelper.pollInstrumentationThread(new Criteria() { - @Override - public boolean isSatisfied() { - return original.isFinishing(); - } - }); - - // Because the AsyncInitializationActivity notices that the FRE hasn't been run yet, it - // redirects to it. Ideally, we would grab the Activity here, but it seems that the - // First Run Activity doesn't live long enough to be grabbed. - CriteriaHelper.pollInstrumentationThread(new Criteria() { - @Override - public boolean isSatisfied() { - return freMonitor.getHits() == 1 || tabbedFREMonitor.getHits() == 1; - } - }); - } - - @Test - @SmallTest public void testHelpPageSkipsFirstRun() { final ActivityMonitor customTabActivityMonitor = new ActivityMonitor(CustomTabActivity.class.getName(), null, false);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PasswordViewingTypeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PasswordViewingTypeTest.java index fb246aa..91af72f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PasswordViewingTypeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/PasswordViewingTypeTest.java
@@ -71,8 +71,7 @@ FakeAccountManagerDelegate.DISABLE_PROFILE_DATA_SOURCE); AccountManagerFacade.overrideAccountManagerFacadeForTests(mAccountManager); mAccount = AccountManagerFacade.createAccountFromName("account@example.com"); - AccountHolder.Builder accountHolder = - AccountHolder.builder(mAccount).password("password").alwaysAccept(true); + AccountHolder.Builder accountHolder = AccountHolder.builder(mAccount).alwaysAccept(true); mAccountManager.addAccountHolderBlocking(accountHolder.build()); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java index 7c5e890a..746bce5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/OAuth2TokenServiceIntegrationTest.java
@@ -87,6 +87,7 @@ mChromeSigninController.setSignedInAccountName(null); mOAuth2TokenService.validateAccounts(false); }); + SigninHelper.resetSharedPrefs(); } private void mapAccountNamesToIds() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java index dbc25be6..52373d4 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java
@@ -32,6 +32,7 @@ @Before public void setUp() { + SigninHelper.resetSharedPrefs(); mEventChecker = new MockChangeEventChecker(); mAccountManager = new FakeAccountManagerDelegate( @@ -42,6 +43,7 @@ @After public void tearDown() { AccountManagerFacade.resetAccountManagerFacadeForTests(); + SigninHelper.resetSharedPrefs(); } @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java index 40345f8..ee5c91a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java
@@ -126,7 +126,6 @@ // real account rename events instead of the mocks. MockChangeEventChecker eventChecker = new MockChangeEventChecker(); eventChecker.insertRenameEvent(oldAccount.name, newAccount.name); - SigninHelper.resetAccountRenameEventIndex(); SigninHelper.updateAccountRenameData(eventChecker); // Tell the fake content resolver that a rename had happen and copy over the sync
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java index 0ed2186..fc5879b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseTypeDialogFragmentTest.java
@@ -7,6 +7,7 @@ import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.widget.CheckedTextView; +import android.widget.HeaderViewListAdapter; import android.widget.ListView; import org.junit.Assert; @@ -57,7 +58,7 @@ @Feature({"Sync"}) public void testKeystoreEncryptionOptions() throws Exception { createFragment(PassphraseType.KEYSTORE_PASSPHRASE, true); - assertPassphraseTypeOptions( + assertPassphraseTypeOptions(false, new TypeOptions(PassphraseType.CUSTOM_PASSPHRASE, ENABLED, UNCHECKED), new TypeOptions(PassphraseType.KEYSTORE_PASSPHRASE, ENABLED, CHECKED)); } @@ -67,7 +68,7 @@ @Feature({"Sync"}) public void testCustomEncryptionOptions() throws Exception { createFragment(PassphraseType.CUSTOM_PASSPHRASE, true); - assertPassphraseTypeOptions( + assertPassphraseTypeOptions(true, new TypeOptions(PassphraseType.CUSTOM_PASSPHRASE, DISABLED, CHECKED), new TypeOptions(PassphraseType.KEYSTORE_PASSPHRASE, DISABLED, UNCHECKED)); } @@ -80,7 +81,7 @@ @FlakyTest(message = "crbug.com/588050") public void testFrozenImplicitEncryptionOptions() throws Exception { createFragment(PassphraseType.FROZEN_IMPLICIT_PASSPHRASE, true); - assertPassphraseTypeOptions( + assertPassphraseTypeOptions(true, new TypeOptions(PassphraseType.FROZEN_IMPLICIT_PASSPHRASE, DISABLED, CHECKED), new TypeOptions(PassphraseType.KEYSTORE_PASSPHRASE, DISABLED, UNCHECKED)); } @@ -90,7 +91,7 @@ @Feature({"Sync"}) public void testImplicitEncryptionOptions() throws Exception { createFragment(PassphraseType.IMPLICIT_PASSPHRASE, true); - assertPassphraseTypeOptions( + assertPassphraseTypeOptions(false, new TypeOptions(PassphraseType.CUSTOM_PASSPHRASE, ENABLED, UNCHECKED), new TypeOptions(PassphraseType.IMPLICIT_PASSPHRASE, ENABLED, CHECKED)); } @@ -100,7 +101,7 @@ @Feature({"Sync"}) public void testKeystoreEncryptionOptionsEncryptEverythingDisallowed() throws Exception { createFragment(PassphraseType.KEYSTORE_PASSPHRASE, false); - assertPassphraseTypeOptions( + assertPassphraseTypeOptions(false, new TypeOptions(PassphraseType.CUSTOM_PASSPHRASE, DISABLED, UNCHECKED), new TypeOptions(PassphraseType.KEYSTORE_PASSPHRASE, ENABLED, CHECKED)); } @@ -110,7 +111,7 @@ @Feature({"Sync"}) public void testImplicitEncryptionOptionsEncryptEverythingDisallowed() throws Exception { createFragment(PassphraseType.IMPLICIT_PASSPHRASE, false); - assertPassphraseTypeOptions( + assertPassphraseTypeOptions(false, new TypeOptions(PassphraseType.CUSTOM_PASSPHRASE, DISABLED, UNCHECKED), new TypeOptions(PassphraseType.IMPLICIT_PASSPHRASE, ENABLED, CHECKED)); } @@ -121,14 +122,19 @@ InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } - public void assertPassphraseTypeOptions(TypeOptions... optionsList) { + public void assertPassphraseTypeOptions(boolean hasFooter, TypeOptions... optionsList) { ListView listView = (ListView) mTypeFragment.getDialog().findViewById(R.id.passphrase_type_list); - Assert.assertEquals( - "Number of options doesn't match.", optionsList.length, listView.getCount()); - PassphraseTypeDialogFragment.Adapter adapter = - (PassphraseTypeDialogFragment.Adapter) listView.getAdapter(); + PassphraseTypeDialogFragment.Adapter adapter; + if (hasFooter) { + HeaderViewListAdapter headerAdapter = (HeaderViewListAdapter) listView.getAdapter(); + adapter = (PassphraseTypeDialogFragment.Adapter) headerAdapter.getWrappedAdapter(); + } else { + adapter = (PassphraseTypeDialogFragment.Adapter) listView.getAdapter(); + } + Assert.assertEquals( + "Number of options doesn't match.", optionsList.length, adapter.getCount()); for (int i = 0; i < optionsList.length; i++) { TypeOptions options = optionsList[i]; Assert.assertEquals(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/ChromeTabbedActivityXrTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/ChromeTabbedActivityXrTestRule.java index 2831f93..742be80 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/ChromeTabbedActivityXrTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/ChromeTabbedActivityXrTestRule.java
@@ -8,7 +8,6 @@ import org.junit.runners.model.Statement; import org.chromium.chrome.browser.vr.rules.XrActivityRestriction.SupportedActivity; -import org.chromium.chrome.browser.vr.util.XrTestRuleUtils; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; /** @@ -22,7 +21,6 @@ return super.apply(new Statement() { @Override public void evaluate() throws Throwable { - XrTestRuleUtils.maybeWorkaroundWebContentFlakiness(desc); startMainActivityOnBlankPage(); base.evaluate(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/CustomTabActivityXrTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/CustomTabActivityXrTestRule.java index a753e8f2..493d448 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/CustomTabActivityXrTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/CustomTabActivityXrTestRule.java
@@ -12,7 +12,6 @@ import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule; import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils; import org.chromium.chrome.browser.vr.rules.XrActivityRestriction.SupportedActivity; -import org.chromium.chrome.browser.vr.util.XrTestRuleUtils; /** * XR extension of CustomTabActivityTestRule. Applies CustomTabActivityTestRule then @@ -24,7 +23,6 @@ return super.apply(new Statement() { @Override public void evaluate() throws Throwable { - XrTestRuleUtils.maybeWorkaroundWebContentFlakiness(desc); startCustomTabActivityWithIntent(CustomTabsTestUtils.createMinimalCustomTabIntent( InstrumentationRegistry.getTargetContext(), "about:blank")); base.evaluate();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/WebappActivityXrTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/WebappActivityXrTestRule.java index fc58334a..76078ff 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/WebappActivityXrTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/rules/WebappActivityXrTestRule.java
@@ -8,7 +8,6 @@ import org.junit.runners.model.Statement; import org.chromium.chrome.browser.vr.rules.XrActivityRestriction.SupportedActivity; -import org.chromium.chrome.browser.vr.util.XrTestRuleUtils; import org.chromium.chrome.browser.webapps.WebappActivityTestRule; /** @@ -23,7 +22,6 @@ return super.apply(new Statement() { @Override public void evaluate() throws Throwable { - XrTestRuleUtils.maybeWorkaroundWebContentFlakiness(desc); startWebappActivity(); base.evaluate(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTestRuleUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTestRuleUtils.java index 453a8ae..dbab8c8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTestRuleUtils.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTestRuleUtils.java
@@ -58,7 +58,6 @@ public static void evaluateVrTestRuleImpl(final Statement base, final Description desc, final VrTestRule rule, final ChromeLaunchMethod launcher) throws Throwable { VrTestRuleUtils.ensureNoVrActivitiesDisplayed(); - VrTestRuleUtils.maybeWorkaroundWebContentFlakiness(desc); HeadTrackingUtils.checkForAndApplyHeadTrackingModeAnnotation(rule, desc); launcher.launch(); // Must be called after Chrome is started, as otherwise startService fails with an
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/XrTestRuleUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/XrTestRuleUtils.java index 61334f6..73c47f7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/XrTestRuleUtils.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/XrTestRuleUtils.java
@@ -4,16 +4,11 @@ package org.chromium.chrome.browser.vr.util; -import android.support.test.InstrumentationRegistry; -import android.support.test.uiautomator.UiDevice; - import org.junit.Assert; import org.junit.rules.RuleChain; import org.junit.rules.TestRule; -import org.junit.runner.Description; import org.chromium.base.test.params.ParameterSet; -import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.vr.rules.ChromeTabbedActivityXrTestRule; import org.chromium.chrome.browser.vr.rules.CustomTabActivityXrTestRule; import org.chromium.chrome.browser.vr.rules.WebappActivityXrTestRule; @@ -22,7 +17,6 @@ import org.chromium.chrome.browser.vr.rules.XrTestRule; import java.util.ArrayList; -import java.util.Arrays; import java.util.concurrent.Callable; /** @@ -84,28 +78,6 @@ } /** - * Works around https://crbug.com/908917, where web contents can be darker due to Android doing - * really weird things when some keyevents are input over adb. This normally isn't an issue, but - * can cause flakiness in RenderTests, so only apply the workaround to those. The issue gets - * resolved when there is touchscreen input, so perform a swipe that should be a no-op. - * - * This would ideally be worked around in the test runner, but attempts to do so have not been - * completely successful. - * - * @param desc The Description of the Rule currently being applied. - */ - public static void maybeWorkaroundWebContentFlakiness(Description desc) { - Feature annotation = desc.getAnnotation(Feature.class); - if (annotation == null) return; - if (!Arrays.asList(annotation.value()).contains("RenderTest")) return; - - UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); - uiDevice.drag(uiDevice.getDisplayWidth() / 2, uiDevice.getDisplayHeight() / 2, - uiDevice.getDisplayWidth() / 2, 3 * uiDevice.getDisplayHeight() / 4, - 10 /* steps */); - } - - /** * Converts XrActivityRestriction.SupportedActivity enum to strings. * * @param activity The SupportedActivity value to convert to a String.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtilsTest.java b/chrome/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtilsTest.java index 33cc181..09a5ca0 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtilsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtilsTest.java
@@ -25,7 +25,6 @@ @RunWith(ChromeJUnit4ClassRunner.class) public class ChromeSigninUtilsTest { private static final String FAKE_ACCOUNT_USERNAME = "test@google.com"; - private static final String FAKE_ACCOUNT_PASSWORD = "$3cr3t"; private static final String GOOGLE_ACCOUNT_USERNAME = "chromiumforandroid01@gmail.com"; private static final String GOOGLE_ACCOUNT_PASSWORD = "chromeforandroid"; private static final String GOOGLE_ACCOUNT_TYPE = "mail"; @@ -66,7 +65,7 @@ @Test @SmallTest public void testIsSignedInOnFakeOS() { - mSigninUtil.addFakeAccountToOs(FAKE_ACCOUNT_USERNAME, FAKE_ACCOUNT_PASSWORD); + mSigninUtil.addFakeAccountToOs(FAKE_ACCOUNT_USERNAME); Assert.assertFalse("Should not be signed in on app.", mSigninController.isSignedIn()); Assert.assertTrue("Should be signed in on OS with fake account.", mSigninUtil.isExistingFakeAccountOnOs(FAKE_ACCOUNT_USERNAME)); @@ -92,7 +91,7 @@ @SmallTest public void testIsSignedInOnFakeOSandApp() { mSigninUtil.addAccountToApp(FAKE_ACCOUNT_USERNAME); - mSigninUtil.addFakeAccountToOs(FAKE_ACCOUNT_USERNAME, FAKE_ACCOUNT_PASSWORD); + mSigninUtil.addFakeAccountToOs(FAKE_ACCOUNT_USERNAME); Assert.assertTrue("Should be signed in on app.", mSigninController.isSignedIn()); Assert.assertTrue("Should be signed in on OS with fake account.", mSigninUtil.isExistingFakeAccountOnOs(FAKE_ACCOUNT_USERNAME)); @@ -120,7 +119,7 @@ @EnormousTest @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) public void testIsSignedInOnFakeOSandGoogleOS() { - mSigninUtil.addFakeAccountToOs(FAKE_ACCOUNT_USERNAME, FAKE_ACCOUNT_PASSWORD); + mSigninUtil.addFakeAccountToOs(FAKE_ACCOUNT_USERNAME); mSigninUtil.addGoogleAccountToOs(GOOGLE_ACCOUNT_USERNAME, GOOGLE_ACCOUNT_PASSWORD, GOOGLE_ACCOUNT_TYPE); Assert.assertFalse("Should not be signed into app.", mSigninController.isSignedIn()); @@ -136,7 +135,7 @@ @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) public void testIsSignedInOnAppAndFakeOSandGoogleOS() { mSigninUtil.addAccountToApp(FAKE_ACCOUNT_USERNAME); - mSigninUtil.addFakeAccountToOs(FAKE_ACCOUNT_USERNAME, FAKE_ACCOUNT_PASSWORD); + mSigninUtil.addFakeAccountToOs(FAKE_ACCOUNT_USERNAME); mSigninUtil.addGoogleAccountToOs(GOOGLE_ACCOUNT_USERNAME, GOOGLE_ACCOUNT_PASSWORD, GOOGLE_ACCOUNT_TYPE); Assert.assertTrue("Should be signed into app.", mSigninController.isSignedIn());
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingControllerTest.java index 4444fb4..454593a 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingControllerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingControllerTest.java
@@ -20,6 +20,8 @@ import static org.chromium.chrome.browser.autofill.keyboard_accessory.AccessoryAction.GENERATE_PASSWORD_AUTOMATIC; import static org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryProperties.ACTIVE_TAB; import static org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryProperties.TABS; +import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece.Type.PASSWORD_INFO; +import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece.getType; import static org.chromium.chrome.browser.tab.Tab.INVALID_TAB_ID; import static org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType.FROM_BROWSER_ACTIONS; import static org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType.FROM_CLOSE; @@ -453,7 +455,7 @@ if (oldState.mPasswordAccessorySheet == null) return; // Having no password sheet is fine - it would be completely destroyed then. - assertThat(oldState.mPasswordAccessorySheet.getModelForTesting().size(), is(0)); + assertThat(oldState.mPasswordAccessorySheet.getItemsForTesting().size(), is(0)); } @Test @@ -641,10 +643,16 @@ } private String getFirstPassword(ManualFillingMediator mediator) { - assert mediator.getPasswordAccessorySheet() != null; - assert mediator.getPasswordAccessorySheet().getModelForTesting() != null; - assert mediator.getPasswordAccessorySheet().getModelForTesting().size() > 1; - // The 0th item is a divider, the 1st a title, the 2nd a username and 3rd a password. - return mediator.getPasswordAccessorySheet().getModelForTesting().get(3).getCaption(); + PasswordAccessorySheetCoordinator passwordSheet = mediator.getPasswordAccessorySheet(); + assert passwordSheet != null; + assert passwordSheet.getSheetDataPiecesForTesting() != null; + assert passwordSheet.getSheetDataPiecesForTesting().size() > 1; + assert getType(passwordSheet.getSheetDataPiecesForTesting().get(1)) == PASSWORD_INFO; + // The 1st element is a title, the 2nd the password info. + UserInfo info = + (UserInfo) passwordSheet.getSheetDataPiecesForTesting().get(1).getDataPiece(); + // The 1st field is the name, the 2nd the password. + assert info.getFields().size() > 1; + return info.getFields().get(1).getDisplayText(); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetControllerTest.java index cf0611d..fff2020 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetControllerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetControllerTest.java
@@ -13,6 +13,11 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece.Type.FOOTER_COMMAND; +import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece.Type.PASSWORD_INFO; +import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece.Type.TITLE; +import static org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece.getType; + import android.support.v7.widget.RecyclerView; import org.junit.Before; @@ -27,7 +32,12 @@ import org.chromium.base.metrics.test.ShadowRecordHistogram; import org.chromium.base.task.test.CustomShadowAsyncTask; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.AccessorySheetData; +import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.FooterCommand; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Item; +import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.PropertyProvider; +import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.UserInfo; +import org.chromium.chrome.browser.autofill.keyboard_accessory.PasswordAccessorySheetProperties.AccessorySheetDataPiece; import org.chromium.chrome.browser.modelutil.ListModel; import org.chromium.chrome.browser.modelutil.ListObservable; @@ -44,7 +54,8 @@ private ListObservable.ListObserver<Void> mMockItemListObserver; private PasswordAccessorySheetCoordinator mCoordinator; - private ListModel<Item> mModel; + private ListModel<Item> mItemList; + private ListModel<AccessorySheetDataPiece> mSheetDataPieces; @Before public void setUp() { @@ -52,7 +63,8 @@ MockitoAnnotations.initMocks(this); mCoordinator = new PasswordAccessorySheetCoordinator(RuntimeEnvironment.application, null); assertNotNull(mCoordinator); - mModel = mCoordinator.getModelForTesting(); + mItemList = mCoordinator.getItemsForTesting(); + mSheetDataPieces = mCoordinator.getSheetDataPiecesForTesting(); } @Test @@ -75,31 +87,27 @@ @Test public void testModelNotifiesAboutActionsChangedByProvider() { - final KeyboardAccessoryData - .PropertyProvider<KeyboardAccessoryData.AccessorySheetData> testProvider = - new KeyboardAccessoryData.PropertyProvider<>(); - final KeyboardAccessoryData.AccessorySheetData testData = - new KeyboardAccessoryData.AccessorySheetData("Passwords"); + final PropertyProvider<AccessorySheetData> testProvider = new PropertyProvider<>(); - mModel.addObserver(mMockItemListObserver); + mItemList.addObserver(mMockItemListObserver); mCoordinator.registerDataProvider(testProvider); // If the coordinator receives an initial items, the model should report an insertion. - testProvider.notifyObservers(testData); - verify(mMockItemListObserver).onItemRangeInserted(mModel, 0, 2); - assertThat(mModel.size(), is(2)); - assertThat(mModel.get(1).getCaption(), is(equalTo("Passwords"))); + testProvider.notifyObservers(new AccessorySheetData("Passwords")); + verify(mMockItemListObserver).onItemRangeInserted(mItemList, 0, 2); + assertThat(mItemList.size(), is(2)); + assertThat(mItemList.get(1).getCaption(), is(equalTo("Passwords"))); // If the coordinator receives a new set of items, the model should report a change. - testProvider.notifyObservers(testData); - verify(mMockItemListObserver).onItemRangeChanged(mModel, 0, 2, null); - assertThat(mModel.size(), is(2)); - assertThat(mModel.get(1).getCaption(), is(equalTo("Passwords"))); + testProvider.notifyObservers(new AccessorySheetData("Other Passwords")); + verify(mMockItemListObserver).onItemRangeChanged(mItemList, 0, 2, null); + assertThat(mItemList.size(), is(2)); + assertThat(mItemList.get(1).getCaption(), is(equalTo("Other Passwords"))); // If the coordinator receives an empty set of items, the model should report a deletion. testProvider.notifyObservers(null); - verify(mMockItemListObserver).onItemRangeRemoved(mModel, 0, 2); - assertThat(mModel.size(), is(0)); + verify(mMockItemListObserver).onItemRangeRemoved(mItemList, 0, 2); + assertThat(mItemList.size(), is(0)); // There should be no notification if no item are reported repeatedly. testProvider.notifyObservers(null); @@ -107,6 +115,55 @@ } @Test + public void testModelNotifiesAboutTabDataChangedByProvider() { + final PropertyProvider<AccessorySheetData> testProvider = new PropertyProvider<>(); + + mSheetDataPieces.addObserver(mMockItemListObserver); + mCoordinator.registerDataProvider(testProvider); + + // If the coordinator receives a set of initial items, the model should report an insertion. + testProvider.notifyObservers(new AccessorySheetData("Passwords")); + verify(mMockItemListObserver).onItemRangeInserted(mSheetDataPieces, 0, 1); + assertThat(mSheetDataPieces.size(), is(1)); + + // If the coordinator receives a new set of items, the model should report a change. + testProvider.notifyObservers(new AccessorySheetData("Other Passwords")); + verify(mMockItemListObserver).onItemRangeChanged(mSheetDataPieces, 0, 1, null); + assertThat(mSheetDataPieces.size(), is(1)); + + // If the coordinator receives an empty set of items, the model should report a deletion. + testProvider.notifyObservers(null); + verify(mMockItemListObserver).onItemRangeRemoved(mSheetDataPieces, 0, 1); + assertThat(mSheetDataPieces.size(), is(0)); + + // There should be no notification if no item are reported repeatedly. + testProvider.notifyObservers(null); + verifyNoMoreInteractions(mMockItemListObserver); + } + + @Test + public void testWrapsTabDataToElements() { + final PropertyProvider<AccessorySheetData> testProvider = new PropertyProvider<>(); + final AccessorySheetData testData = new AccessorySheetData("Passwords for this site"); + testData.getUserInfoList().add(new UserInfo(null)); + testData.getUserInfoList().get(0).addField(new UserInfo.Field("Name", "Name", false, null)); + testData.getUserInfoList().get(0).addField( + new UserInfo.Field("Password", "Password for Name", true, field -> {})); + testData.getFooterCommands().add(new FooterCommand("Manage passwords", result -> {})); + + mCoordinator.registerDataProvider(testProvider); + testProvider.notifyObservers(testData); + + assertThat(mSheetDataPieces.size(), is(3)); + assertThat(getType(mSheetDataPieces.get(0)), is(TITLE)); + assertThat(getType(mSheetDataPieces.get(1)), is(PASSWORD_INFO)); + assertThat(getType(mSheetDataPieces.get(2)), is(FOOTER_COMMAND)); + assertThat(mSheetDataPieces.get(0).getDataPiece(), is(equalTo("Passwords for this site"))); + assertThat(mSheetDataPieces.get(1).getDataPiece(), is(testData.getUserInfoList().get(0))); + assertThat(mSheetDataPieces.get(2).getDataPiece(), is(testData.getFooterCommands().get(0))); + } + + @Test public void testRecordsActionImpressionsWhenShown() { assertThat(getActionImpressions(AccessoryAction.MANAGE_PASSWORDS), is(0)); @@ -126,7 +183,7 @@ assertThat(getSuggestionsImpressions(AccessoryTabType.ALL, 0), is(0)); // If the tab is shown without interactive item, log "0" samples. - mModel.set(new Item[] {Item.createLabel("No passwords!", ""), Item.createDivider(), + mItemList.set(new Item[] {Item.createLabel("No passwords!", ""), Item.createDivider(), Item.createOption("Manage all passwords", "", null), Item.createOption("Generate password", "", null)}); mCoordinator.onTabShown(); @@ -135,7 +192,7 @@ assertThat(getSuggestionsImpressions(AccessoryTabType.ALL, 0), is(1)); // If the tab is shown with X interactive item, record "X" samples. - mModel.set(new Item[] {Item.createLabel("Your passwords", ""), + mItemList.set(new Item[] {Item.createLabel("Your passwords", ""), Item.createSuggestion("Interactive 1", "", false, (v) -> {}, null), Item.createSuggestion("Non-interactive 1", "", true, null, null), Item.createSuggestion("Interactive 2", "", false, (v) -> {}, null),
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationUnitTest.java new file mode 100644 index 0000000..73d7a00 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationUnitTest.java
@@ -0,0 +1,114 @@ +// 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. + +package org.chromium.chrome.browser.firstrun; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.UserManager; +import android.support.customtabs.CustomTabsIntent; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.Robolectric; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.ChromeTabbedActivity; +import org.chromium.chrome.browser.document.ChromeLauncherActivity; +import org.chromium.chrome.browser.searchwidget.SearchActivity; + +/** JUnit tests for first run triggering code. */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public final class FirstRunIntegrationUnitTest { + @Rule + public MockitoRule mMockitoRule = MockitoJUnit.rule(); + + private Context mContext; + private ShadowApplication mShadowApplication; + + @Before + public void setUp() throws InterruptedException { + mContext = RuntimeEnvironment.application; + mShadowApplication = ShadowApplication.getInstance(); + + UserManager userManager = Mockito.mock(UserManager.class); + Mockito.when(userManager.isDemoUser()).thenReturn(false); + mShadowApplication.setSystemService(Context.USER_SERVICE, userManager); + + FirstRunStatus.setFirstRunFlowComplete(false); + } + + /** + * Checks that either {@link FirstRunActivity} or {@link TabbedModeFirstRunActivity} + * was launched. + */ + private void assertFirstRunActivityLaunched() { + Intent launchedIntent = mShadowApplication.getNextStartedActivity(); + Assert.assertNotNull(launchedIntent); + + String launchedActivityClassName = launchedIntent.getComponent().getClassName(); + Assert.assertTrue(launchedActivityClassName.equals(FirstRunActivity.class.getName()) + || launchedActivityClassName.equals(TabbedModeFirstRunActivity.class.getName())); + } + + @Test + public void testGenericViewIntentGoesToFirstRun() { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://test.com")); + intent.setPackage(mContext.getPackageName()); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + Activity launcherActivity = + Robolectric.buildActivity(ChromeLauncherActivity.class, intent).create().get(); + assertFirstRunActivityLaunched(); + Assert.assertTrue(launcherActivity.isFinishing()); + } + + @Test + public void testRedirectCustomTabActivityToFirstRun() { + CustomTabsIntent customTabIntent = new CustomTabsIntent.Builder().build(); + customTabIntent.intent.setPackage(mContext.getPackageName()); + customTabIntent.intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + customTabIntent.launchUrl(mContext, Uri.parse("http://test.com")); + Intent launchedIntent = mShadowApplication.getNextStartedActivity(); + Assert.assertNotNull(launchedIntent); + + Activity launcherActivity = + Robolectric.buildActivity(ChromeLauncherActivity.class, launchedIntent) + .create() + .get(); + assertFirstRunActivityLaunched(); + Assert.assertTrue(launcherActivity.isFinishing()); + } + + @Test + public void testRedirectChromeTabbedActivityToFirstRun() { + Intent intent = new Intent(); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + Activity tabbedActivity = + Robolectric.buildActivity(ChromeTabbedActivity.class, intent).create().get(); + assertFirstRunActivityLaunched(); + Assert.assertTrue(tabbedActivity.isFinishing()); + } + + @Test + public void testRedirectSearchActivityToFirstRun() { + Intent intent = new Intent(); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + Activity searchActivity = + Robolectric.buildActivity(SearchActivity.class, intent).create().get(); + assertFirstRunActivityLaunched(); + Assert.assertTrue(searchActivity.isFinishing()); + } +}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/router/caf/BaseSessionControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/media/router/caf/BaseSessionControllerTest.java index b44cf9a..edad2c5 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/media/router/caf/BaseSessionControllerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/router/caf/BaseSessionControllerTest.java
@@ -62,7 +62,7 @@ @Mock private CafBaseMediaRouteProvider mProvider; @Mock - private CafNotificationController mNotificationController; + private BaseNotificationController mNotificationController; @Mock private MediaSource mSource; @Mock @@ -91,10 +91,9 @@ new MediaRouteSelector.Builder() .addControlCategory(CastMediaControlIntent.categoryForCast(APP_ID)) .build(); - mController = new BaseSessionController(mProvider); + mController = new TestSessionController(mProvider, mNotificationController); mRequestInfo = new CreateRouteRequestInfo(mSource, mSink, PRESENTATION_ID, ORIGIN, TAB_ID, false, 1, mMediaRouterHelper.getCastRoute()); - mController.mNotificationController = mNotificationController; doReturn(mSessionManager).when(mCastContext).getSessionManager(); doReturn(mRemoteMediaClient).when(mCastSession).getRemoteMediaClient(); @@ -211,4 +210,19 @@ callbackCaptor.getValue().onMetadataUpdated(); verify(mNotificationController).onMetadataUpdated(); } + + private static class TestSessionController extends BaseSessionController { + public BaseNotificationController mNotificationController; + + public TestSessionController(CafBaseMediaRouteProvider provider, + BaseNotificationController notificationController) { + super(provider); + mNotificationController = notificationController; + } + + @Override + public BaseNotificationController getNotificationController() { + return mNotificationController; + } + } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/router/caf/CastSessionControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/media/router/caf/CastSessionControllerTest.java index c475126..8c54cc3 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/media/router/caf/CastSessionControllerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/router/caf/CastSessionControllerTest.java
@@ -61,8 +61,6 @@ @Mock private CafMediaRouteProvider mProvider; @Mock - private CafNotificationController mNotificationController; - @Mock private MediaSource mSource; @Mock private MediaSink mSink; @@ -85,7 +83,6 @@ mContext = RuntimeEnvironment.application; mMediaRouterHelper = new MediaRouterTestHelper(); mController = spy(new CastSessionController(mProvider)); - mController.mNotificationController = mNotificationController; mController.initNestedFieldsForTesting(); doReturn(mRemoteMediaClient).when(mCastSession).getRemoteMediaClient();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java index 6718276..fa5d823 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java
@@ -4,26 +4,39 @@ package org.chromium.chrome.browser.signin; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import android.accounts.Account; +import android.content.Context; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Spy; import org.robolectric.annotation.Config; +import org.chromium.base.ContextUtils; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.sync.AndroidSyncSettings; import org.chromium.components.sync.test.util.MockSyncContentResolverDelegate; +import java.util.concurrent.atomic.AtomicInteger; + /** Tests for {@link SigninManager}. */ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) @@ -33,6 +46,11 @@ * Other native* methods can be overridden using Spy. */ static class TestableSigninManager extends SigninManager { + TestableSigninManager(Context context, AccountTrackerService accountTrackerService, + AndroidSyncSettings androidSyncSettings) { + super(context, accountTrackerService, androidSyncSettings); + } + @Override long nativeInit() { return 0; @@ -44,12 +62,17 @@ } } + private AccountTrackerService mAccountTrackerService; @Spy private TestableSigninManager mSigninManager; @Before public void setUp() { - mSigninManager = spy(new TestableSigninManager()); + mAccountTrackerService = mock(AccountTrackerService.class); + AndroidSyncSettings androidSyncSettings = mock(AndroidSyncSettings.class); + + mSigninManager = spy(new TestableSigninManager( + ContextUtils.getApplicationContext(), mAccountTrackerService, androidSyncSettings)); // SinginManager interacts with AndroidSyncSettings, but its not the focus // of this test. Using MockSyncContentResolver reduces burden of test setup. @@ -155,4 +178,60 @@ verify(mSigninManager, never()).nativeWipeProfileData(anyLong()); verify(mSigninManager, times(1)).nativeWipeGoogleServiceWorkerCaches(anyLong()); } + + @Test + public void callbackNotifiedWhenNoOperationIsInProgress() { + assertFalse(mSigninManager.isOperationInProgress()); + + AtomicInteger callCount = new AtomicInteger(0); + mSigninManager.runAfterOperationInProgress(callCount::incrementAndGet); + assertEquals(1, callCount.get()); + } + + @Test + public void callbackNotifiedOnSignout() { + doAnswer(invocation -> { + mSigninManager.onNativeSignOut(); + return null; + }).when(mSigninManager).nativeSignOut(anyLong(), anyInt()); + doReturn(null).when(mSigninManager).nativeGetManagementDomain(anyLong()); + doNothing().when(mSigninManager).nativeWipeGoogleServiceWorkerCaches(anyLong()); + + mSigninManager.signOut(SignoutReason.SIGNOUT_TEST); + assertTrue(mSigninManager.isOperationInProgress()); + AtomicInteger callCount = new AtomicInteger(0); + mSigninManager.runAfterOperationInProgress(callCount::incrementAndGet); + assertEquals(0, callCount.get()); + + mSigninManager.onProfileDataWiped(); + assertFalse(mSigninManager.isOperationInProgress()); + assertEquals(1, callCount.get()); + } + + @Test + public void callbackNotifiedOnSignin() { + // No need to seed accounts to the native code. + doReturn(true).when(mAccountTrackerService).checkAndSeedSystemAccounts(); + // Request that policy is loaded. It will pause sign-in until onPolicyCheckedBeforeSignIn is + // invoked. + doReturn(true).when(mSigninManager).nativeShouldLoadPolicyForUser(any()); + doNothing().when(mSigninManager).nativeCheckPolicyBeforeSignIn(anyLong(), any()); + + doReturn(true).when(mSigninManager).isSigninSupported(); + doNothing().when(mSigninManager).nativeOnSignInCompleted(anyLong(), any()); + doNothing().when(mSigninManager).logInSignedInUser(); + + mSigninManager.onFirstRunCheckDone(); // Allow sign-in. + + Account account = new Account("test@gmail.com", AccountManagerFacade.GOOGLE_ACCOUNT_TYPE); + mSigninManager.signIn(account, null, null); + assertTrue(mSigninManager.isOperationInProgress()); + AtomicInteger callCount = new AtomicInteger(0); + mSigninManager.runAfterOperationInProgress(callCount::incrementAndGet); + assertEquals(0, callCount.get()); + + mSigninManager.onPolicyCheckedBeforeSignIn(null); // Test user is unmanaged. + assertFalse(mSigninManager.isOperationInProgress()); + assertEquals(1, callCount.get()); + } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkInfoTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkInfoTest.java index f72600df3..4f16aa6 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkInfoTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkInfoTest.java
@@ -428,4 +428,14 @@ + "text: \"\", url: \"\", names: \"\", accepts: \"\"", serializedShareTarget); } + + // Test that getSerializedShareTarget() returns the same result for empty and null parameters. + @Test + public void testGetSerializedShareTargetNullValues() { + String serializedShareTarget1 = WebApkInfo.getSerializedShareTarget( + "action", "", "", "awesome title", "", "", "", ""); + String serializedShareTarget2 = WebApkInfo.getSerializedShareTarget( + "action", null, null, "awesome title", "", "", "", ""); + Assert.assertEquals(serializedShareTarget1, serializedShareTarget2); + } }
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index 859824b..2a9dbb0 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-73.0.3631.0_rc-r1.afdo.bz2 \ No newline at end of file +chromeos-chrome-amd64-73.0.3636.0_rc-r1.afdo.bz2 \ No newline at end of file
diff --git a/chrome/android/webapk/libs/client/src/org/chromium/webapk/lib/client/WebApkValidator.java b/chrome/android/webapk/libs/client/src/org/chromium/webapk/lib/client/WebApkValidator.java index 0ddbe20b..2b1fab0c 100644 --- a/chrome/android/webapk/libs/client/src/org/chromium/webapk/lib/client/WebApkValidator.java +++ b/chrome/android/webapk/libs/client/src/org/chromium/webapk/lib/client/WebApkValidator.java
@@ -40,6 +40,7 @@ private static final String MAPSLITE_PACKAGE_NAME = "com.google.android.apps.mapslite"; private static final String MAPSLITE_URL_PREFIX = "https://www.google.com/maps"; // Matches scope. + private static final boolean DEBUG = false; private static byte[] sExpectedSignature; private static byte[] sCommentSignedPublicKeyBytes; @@ -200,22 +201,28 @@ packageInfo = context.getPackageManager().getPackageInfo(webappPackageName, PackageManager.GET_SIGNATURES | PackageManager.GET_META_DATA); } catch (Exception e) { - e.printStackTrace(); - Log.d(TAG, "WebApk not found"); + if (DEBUG) { + e.printStackTrace(); + Log.d(TAG, "WebApk not found"); + } return false; } if (isNotWebApkQuick(packageInfo)) { return false; } if (sOverrideValidationForTesting) { - Log.d(TAG, "Ok! Looks like a WebApk (has start url) and validation is disabled."); + if (DEBUG) { + Log.d(TAG, "Ok! Looks like a WebApk (has start url) and validation is disabled."); + } return true; } if (verifyV1WebApk(packageInfo, webappPackageName)) { return true; } if (verifyMapsLite(packageInfo, webappPackageName)) { - Log.d(TAG, "Matches Maps Lite"); + if (DEBUG) { + Log.d(TAG, "Matches Maps Lite"); + } return true; } return verifyCommentSignedWebApk(packageInfo); @@ -239,7 +246,9 @@ } for (Signature signature : packageInfo.signatures) { if (Arrays.equals(sExpectedSignature, signature.toByteArray())) { - Log.d(TAG, "WebApk valid - signature match!"); + if (DEBUG) { + Log.d(TAG, "WebApk valid - signature match!"); + } return true; } } @@ -252,12 +261,16 @@ } String startUrl = packageInfo.applicationInfo.metaData.getString(START_URL); if (startUrl == null || !startUrl.startsWith(MAPSLITE_URL_PREFIX)) { - Log.d(TAG, "mapslite invalid startUrl prefix"); + if (DEBUG) { + Log.d(TAG, "mapslite invalid startUrl prefix"); + } return false; } String scope = packageInfo.applicationInfo.metaData.getString(SCOPE); if (scope == null || !scope.equals(MAPSLITE_URL_PREFIX)) { - Log.d(TAG, "mapslite invalid scope prefix"); + if (DEBUG) { + Log.d(TAG, "mapslite invalid scope prefix"); + } return false; } return true; @@ -303,7 +316,9 @@ result = v.verifySignature(commentSignedPublicKey); // TODO(scottkirkwood): remove this log once well tested. - Log.d(TAG, "File " + packageFilename + ": " + result); + if (DEBUG) { + Log.d(TAG, "File " + packageFilename + ": " + result); + } return result == WebApkVerifySignature.ERROR_OK; } catch (Exception e) { Log.e(TAG, "WebApk file error for file " + packageFilename, e);
diff --git a/chrome/app/OWNERS b/chrome/app/OWNERS index 827fc3a..91122cb 100644 --- a/chrome/app/OWNERS +++ b/chrome/app/OWNERS
@@ -17,6 +17,8 @@ per-file google_chrome_strings.grd=* per-file md_extensions_strings.grdp=* +per-file app_management_strings.grdp=file://chrome/browser/ui/webui/app_management/OWNERS + per-file media_router_strings.grdp=file://chrome/browser/media/router/OWNERS per-file onboarding_welcome_strings.grdp=file://chrome/browser/ui/webui/welcome/nux/OWNERS
diff --git a/chrome/app/app_management_strings.grdp b/chrome/app/app_management_strings.grdp new file mode 100644 index 0000000..badceea --- /dev/null +++ b/chrome/app/app_management_strings.grdp
@@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> + +<grit-part> + <message name="IDS_APP_MANAGEMENT_APP_LIST_TITLE" desc="Title of app list card on main app management page."> + Recently opened apps + </message> + <message name="IDS_APP_MANAGEMENT_MORE_APPS" desc="Label for more apps button at bottom of app list card."> + See more apps + </message> + <message name="IDS_APP_MANAGEMENT_SEARCH_PROMPT" desc="Prompt in search bar of main app management page."> + Search Settings + </message> + <message name="IDS_APP_MANAGEMENT_TITLE" desc="Title of the app management page."> + Apps + </message> +</grit-part>
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index bd840d8..6a160d6 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc
@@ -518,12 +518,10 @@ chrome_feature_list_creator_->CreateFeatureList(); PostFieldTrialInitialization(); - // Initializes the resouce bundle and determines the locale. + // Initializes the resource bundle and determines the locale. std::string actual_locale = LoadLocalState(chrome_feature_list_creator_.get(), is_running_tests); chrome_feature_list_creator_->SetApplicationLocale(actual_locale); - - tracing_sampler_profiler_->OnMessageLoopStarted(); } bool ChromeMainDelegate::ShouldCreateFeatureList() {
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index d4119a7..46296761 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -179,6 +179,9 @@ <!-- Bookmarks specific strings --> <part file="bookmarks_strings.grdp" /> + <!-- App Management specific strings --> + <part file="app_management_strings.grdp" /> + <!-- Media Router specific strings --> <part file="media_router_strings.grdp" /> @@ -3208,7 +3211,7 @@ </message> <if expr="chromeos"> <message name="IDS_UTILITY_PROCESS_CUPS_IPP_PARSER_SERVICE_NAME" desc="The name of the utility process used for parsing IPP requests out-of-process."> - CUPS IPP Parser + CUPS IPP Parser </message> <message name="IDS_UTILITY_PROCESS_IME_SERVICE_NAME" desc="The name of the utility process providing the input methods."> Chrome OS Input Method
diff --git a/chrome/app/settings_chromium_strings.grdp b/chrome/app/settings_chromium_strings.grdp index b4a76cb..8811407e 100644 --- a/chrome/app/settings_chromium_strings.grdp +++ b/chrome/app/settings_chromium_strings.grdp
@@ -59,9 +59,6 @@ <message name="IDS_SETTINGS_SPELLING_DESCRIPTION_UNIFIED_CONSENT" desc="Description of using a web serviced to help resolve spelling errors. It is important to convey that what the user types will be sent to Google."> To fix spelling errors, Chromium sends the text you type in text fields to Google </message> - <message name="IDS_SETTINGS_NON_PERSONALIZED_SERVICES_SECTION_DESC" desc="Brief explanation of the capability of Google services."> - Communicates with Google to improve browsing and Chromium - </message> <message name="IDS_SETTINGS_RESTART_TO_APPLY_CHANGES" desc="Description in the snackbar to restart Chrome and apply changes."> To apply your changes, relaunch Chromium </message>
diff --git a/chrome/app/settings_google_chrome_strings.grdp b/chrome/app/settings_google_chrome_strings.grdp index 375e3196..8dca4b1 100644 --- a/chrome/app/settings_google_chrome_strings.grdp +++ b/chrome/app/settings_google_chrome_strings.grdp
@@ -59,9 +59,6 @@ <message name="IDS_SETTINGS_SPELLING_DESCRIPTION_UNIFIED_CONSENT" desc="Description of using a web serviced to help resolve spelling errors. It is important to convey that what the user types will be sent to Google."> To fix spelling errors, Chrome sends the text you type in text fields to Google </message> - <message name="IDS_SETTINGS_NON_PERSONALIZED_SERVICES_SECTION_DESC" desc="Brief explanation of the capability of Google services."> - Communicates with Google to improve browsing and Chrome - </message> <message name="IDS_SETTINGS_RESTART_TO_APPLY_CHANGES" desc="Description in the snackbar to restart Chrome and apply changes."> To apply your changes, relaunch Chrome </message>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index aeb63838..24a9252 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -488,6 +488,12 @@ <message name="IDS_SETTINGS_CROSTINI_SHARED_PATHS" desc="Label for managing shared folders in Crostini."> Manage shared files & folders </message> + <message name="IDS_SETTINGS_CROSTINI_SHARED_USB_DEVICES_LABEL" desc="Label for managing shared USB devices."> + USB Device preferences + </message> + <message name="IDS_SETTINGS_CROSTINI_SHARED_USB_DEVICES_DESCRIPTION" desc="Description for managing shared USB devices."> + Share a USB device with Linux by turning the toggle on. Sharing will only last until the device is detached. + </message> <!-- Android Apps Page --> <message name="IDS_SETTINGS_ANDROID_APPS_TITLE" desc="The title of Google Play Store (Arc++ / Android Apps) section."> @@ -703,7 +709,7 @@ Remove </message> <message name="IDS_SETTINGS_CREDIT_CARD_CLEAR" desc="Label for a context menu item clears the locally cached credit card that is also saved on Google Payments. Clicking this will NOT remove the credit card from Google Payments."> - Clear copy + Clear copy </message> <message name="IDS_SETTINGS_EDIT_CREDIT_CARD_TITLE" desc="The title for the dialog that's shown when editing a card. This can be either credit, debit, or prepaid card.."> Edit card @@ -711,17 +717,14 @@ <message name="IDS_SETTINGS_ADD_CREDIT_CARD_TITLE" desc="The title for the dialog that's shown when entering the information for a new card. This can be either credit, debit, or prepaid card."> Add card </message> - <message name="IDS_SETTINGS_SINGLE_MIGRATABLE_CARD_LABEL" desc="Label for the field to migrate the locally cached credit card to Google Payments for single migratable card. Clicking this will upload migratable credit cards to Google Payments."> - Save card to use Google Pay - </message> - <message name="IDS_SETTINGS_MULTIPLE_MIGRATABLE_CARDS_LABEL" desc="Label for the field to migrate the locally cached credit cards to Google Payments for multiple migratable cards. Clicking this will upload migratable credit cards to Google Payments."> - Save cards to use Google Pay + <message name="IDS_SETTINGS_MIGRATABLE_CARDS_LABEL" desc="Label for the field to migrate the locally cached credit card to Google Payments. Clicking this will upload migratable credit cards to Google Payments."> + Save cards in your Google Account </message> <message name="IDS_SETTINGS_SINGLE_MIGRATABLE_CARD_INFO" desc="Display text under the save cards to Google Pay label. This text indicates one of local cards can only be used on this device."> - 1 of your cards can only be used on this device + Right now, you have one card that can only be used on this device </message> <message name="IDS_SETTINGS_MULTIPLE_MIGRATABLE_CARDS_INFO" desc="Display text under the save cards to Google Pay label. This text indicates user has multiple migratable cards on this device."> - Some of your cards can only be used on this device + Right now, you have some cards that can only be used on this device </message> <message name="IDS_SETTINGS_NAME_ON_CREDIT_CARD" desc="The title for the input that lets users modify the name on the credit card."> Name on card @@ -3576,21 +3579,9 @@ <message name="IDS_SETTINGS_SYNC_UNIFIED_CONSENT" desc="Name of the sync service when unified consent is enabled."> Sync and personalization </message> - <message name="IDS_SETTINGS_SYNC_DESCRIPTION" desc="Text explaining what the sync system does."> - Passwords, bookmarks, history, and more are synced to your account - </message> - <message name="IDS_SETTINGS_SYNC_DESCRIPTION_UNIFIED_CONSENT" desc="Text explaining what the sync system does, when unified consent is enabled."> - Your browsing data and activity, synced to your Google Account - </message> - <message name="IDS_SETTINGS_SYNC_SECTION_ACCESSIBILITY_LABEL" desc="Label for the button that toggles showing the sync settings. Only visible by screen reader software."> - Show sync settings - </message> <message name="IDS_SETTINGS_NON_PERSONALIZED_SERVICES_SECTION_LABEL" desc="Title for a section that shows options for various Google services"> Other Google services </message> - <message name="IDS_SETTINGS_NON_PERSONALIZED_SERVICES_SECTION_ACCESSIBILITY_LABEL" desc="Label for the button that toggles showing the google services settings. Only visible by screen reader software."> - Show Google services settings - </message> <message name="IDS_SETTINGS_SYNC_SYNC_AND_NON_PERSONALIZED_SERVICES" desc="The name of the settings page and the label of the button that takes the user to manage their sync and non-personalized services settings."> Sync and Google services </message>
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_MIGRATABLE_CARDS_LABEL.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MIGRATABLE_CARDS_LABEL.png.sha1 new file mode 100644 index 0000000..59c97cc --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MIGRATABLE_CARDS_LABEL.png.sha1
@@ -0,0 +1 @@ +28cebf10631fde5ff58e13ab25039bfb9c917f43 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_MULTIPLE_MIGRATABLE_CARDS_INFO.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MULTIPLE_MIGRATABLE_CARDS_INFO.png.sha1 new file mode 100644 index 0000000..59c97cc --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MULTIPLE_MIGRATABLE_CARDS_INFO.png.sha1
@@ -0,0 +1 @@ +28cebf10631fde5ff58e13ab25039bfb9c917f43 \ No newline at end of file
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn index a5ef2da..05dcbdc 100644 --- a/chrome/app/vector_icons/BUILD.gn +++ b/chrome/app/vector_icons/BUILD.gn
@@ -53,6 +53,7 @@ "forward_arrow_touch.icon", "generic_stop.icon", "globe.icon", + "google_g_logo.icon", "google_pay_logo.icon", "horizontal_menu.icon", "incognito.icon", @@ -125,7 +126,6 @@ if (is_mac) { icons += [ "default_favicon.icon", - "google_g_logo.icon", "new_tab_mac_touchbar.icon", ] }
diff --git a/chrome/app_shim/app_shim_controller.h b/chrome/app_shim/app_shim_controller.h index 402bcac..535b0684 100644 --- a/chrome/app_shim/app_shim_controller.h +++ b/chrome/app_shim/app_shim_controller.h
@@ -57,6 +57,7 @@ views_bridge_mac::mojom::BridgeFactoryAssociatedRequest request) override; void CreateContentNSViewBridgeFactory( content::mojom::NSViewBridgeFactoryAssociatedRequest request) override; + void CreateCommandDispatcherForWidget(uint64_t widget_id) override; void Hide() override; void UnhideWithoutActivation() override; void SetUserAttention(apps::AppShimAttentionType attention_type) override;
diff --git a/chrome/app_shim/app_shim_controller.mm b/chrome/app_shim/app_shim_controller.mm index 120b5bd..35dc669e 100644 --- a/chrome/app_shim/app_shim_controller.mm +++ b/chrome/app_shim/app_shim_controller.mm
@@ -11,6 +11,8 @@ #include "base/files/file_util.h" #include "base/strings/sys_string_conversions.h" #include "chrome/app_shim/app_shim_delegate.h" +#include "chrome/browser/ui/cocoa/browser_window_command_handler.h" +#include "chrome/browser/ui/cocoa/chrome_command_dispatcher_delegate.h" #include "chrome/browser/ui/cocoa/main_menu_builder.h" #include "content/public/browser/ns_view_bridge_factory_impl.h" #include "content/public/common/ns_view_bridge_factory.mojom.h" @@ -19,6 +21,7 @@ #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" #include "ui/base/l10n/l10n_util.h" #include "ui/views_bridge_mac/bridge_factory_impl.h" +#include "ui/views_bridge_mac/bridged_native_widget_impl.h" #include "ui/views_bridge_mac/mojo/bridge_factory.mojom.h" AppShimController::AppShimController( @@ -160,6 +163,16 @@ content::NSViewBridgeFactoryImpl::Get()->BindRequest(std::move(request)); } +void AppShimController::CreateCommandDispatcherForWidget(uint64_t widget_id) { + if (auto* bridge = views::BridgedNativeWidgetImpl::GetFromId(widget_id)) { + bridge->SetCommandDispatcher( + [[[ChromeCommandDispatcherDelegate alloc] init] autorelease], + [[[BrowserWindowCommandHandler alloc] init] autorelease]); + } else { + LOG(ERROR) << "Failed to find host for command dispatcher."; + } +} + void AppShimController::Hide() { [NSApp hide:nil]; } @@ -188,7 +201,7 @@ } void AppShimController::Close() { - [delegate_ terminateNow]; + [NSApp terminate:nil]; } bool AppShimController::SendFocusApp(apps::AppShimFocusType focus_type,
diff --git a/chrome/app_shim/app_shim_delegate.h b/chrome/app_shim/app_shim_delegate.h index 235e7c3..b4d4babb 100644 --- a/chrome/app_shim/app_shim_delegate.h +++ b/chrome/app_shim/app_shim_delegate.h
@@ -18,8 +18,6 @@ : NSObject<NSApplicationDelegate, NSUserInterfaceValidations> { @private AppShimController* appShimController_; // Weak, initially NULL. - BOOL terminateNow_; - BOOL terminateRequested_; std::vector<base::FilePath> filesToOpenAtStartup_; } @@ -36,10 +34,6 @@ // Takes an array of NSString*. - (void)openFiles:(NSArray*)filename; -// Terminate immediately. This is necessary as we override terminate: to send -// a QuitApp message. -- (void)terminateNow; - @end #endif // CHROME_APP_SHIM_APP_SHIM_DELEGATE_H_
diff --git a/chrome/app_shim/app_shim_delegate.mm b/chrome/app_shim/app_shim_delegate.mm index fb3d80e..40ff6f1e 100644 --- a/chrome/app_shim/app_shim_delegate.mm +++ b/chrome/app_shim/app_shim_delegate.mm
@@ -67,13 +67,11 @@ - (NSApplicationTerminateReply)applicationShouldTerminate: (NSApplication*)sender { - if (terminateNow_ || !appShimController_) - return NSTerminateNow; - - appShimController_->host()->QuitApp(); - // Wait for the channel to close before terminating. - terminateRequested_ = YES; - return NSTerminateLater; + // Send a last message to the host indicating that the host should close all + // associated browser windows. + if (appShimController_) + appShimController_->host()->QuitApp(); + return NSTerminateNow; } - (void)applicationWillHide:(NSNotification*)notification { @@ -86,16 +84,6 @@ appShimController_->host()->SetAppHidden(false); } -- (void)terminateNow { - if (terminateRequested_) { - [NSApp replyToApplicationShouldTerminate:NSTerminateNow]; - return; - } - - terminateNow_ = YES; - [NSApp terminate:nil]; -} - - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { return NO; }
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 2bae57e..31886e5f 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2589,12 +2589,19 @@ "accessibility/invert_bubble_prefs.h", "apps/app_service/app_icon_factory.cc", "apps/app_service/app_icon_factory.h", + "apps/app_service/app_icon_source.cc", + "apps/app_service/app_icon_source.h", "apps/app_service/app_service_proxy.cc", "apps/app_service/app_service_proxy.h", "apps/app_service/app_service_proxy_factory.cc", "apps/app_service/app_service_proxy_factory.h", "background/background_contents.cc", "background/background_contents.h", + "badging/badge_manager.cc", + "badging/badge_manager.h", + "badging/badge_manager_delegate.h", + "badging/badge_manager_factory.cc", + "badging/badge_manager_factory.h", "badging/badge_service_impl.cc", "badging/badge_service_impl.h", "banners/app_banner_infobar_delegate_desktop.cc",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index 06b02b1..9ac128a 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -84,6 +84,7 @@ "+services/shape_detection/public/mojom", "+services/video_capture/public", "+services/viz/privileged", + "+services/viz/public/interfaces", "+services/ws/common", "+services/ws/public", "+skia/ext",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index b81c82a..a6ed925 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -359,18 +359,11 @@ {kAccountConsistencyFeatureMethodParameter, kAccountConsistencyFeatureMethodDiceMigration}}; -const FeatureEntry::FeatureParam kAccountConsistencyDiceFixAuthErrors[] = { - {kAccountConsistencyFeatureMethodParameter, - kAccountConsistencyFeatureMethodDiceFixAuthErrors}}; - const FeatureEntry::FeatureVariation kAccountConsistencyFeatureVariations[] = { {"Dice", kAccountConsistencyDice, base::size(kAccountConsistencyDice), nullptr /* variation_id */}, {"Dice (migration)", kAccountConsistencyDiceMigration, - base::size(kAccountConsistencyDiceMigration), nullptr /* variation_id */}, - {"Dice (fix auth errors)", kAccountConsistencyDiceFixAuthErrors, - base::size(kAccountConsistencyDiceFixAuthErrors), - nullptr /* variation_id */}}; + base::size(kAccountConsistencyDiceMigration), nullptr /* variation_id */}}; #endif // BUILDFLAG(ENABLE_DICE_SUPPORT) const FeatureEntry::Choice kSimpleCacheBackendChoices[] = { @@ -870,10 +863,6 @@ #if defined(OS_ANDROID) {flag_descriptions::kAutoplayPolicyUserGestureRequired, switches::kAutoplayPolicy, switches::autoplay::kUserGestureRequiredPolicy}, -#else - {flag_descriptions::kAutoplayPolicyUserGestureRequiredForCrossOrigin, - switches::kAutoplayPolicy, - switches::autoplay::kUserGestureRequiredForCrossOriginPolicy}, #endif {flag_descriptions::kAutoplayPolicyDocumentUserActivation, switches::kAutoplayPolicy, @@ -1636,10 +1625,6 @@ kOsCrOS, FEATURE_VALUE_TYPE(app_list_features::kEnableBackgroundBlur), }, - {"enable-touchable-app-context-menu", - flag_descriptions::kTouchableAppContextMenuName, - flag_descriptions::kTouchableAppContextMenuDescription, kOsCrOS, - FEATURE_VALUE_TYPE(features::kTouchableAppContextMenu)}, {"enable-notification-indicator", flag_descriptions::kNotificationIndicatorName, flag_descriptions::kNotificationIndicatorDescription, kOsCrOS, @@ -2102,6 +2087,11 @@ flag_descriptions::kNewZipUnpackerDescription, kOsCrOS, SINGLE_DISABLE_VALUE_TYPE(chromeos::switches::kDisableNewZIPUnpacker)}, #endif // OS_CHROMEOS +#if defined(OS_CHROMEOS) + {"crostini-files", flag_descriptions::kCrostiniFilesName, + flag_descriptions::kCrostiniFilesDescription, kOsCrOS, + FEATURE_VALUE_TYPE(chromeos::features::kCrostiniFiles)}, +#endif // OS_CHROMEOS #if defined(OS_ANDROID) {"enable-credit-card-assist", flag_descriptions::kCreditCardAssistName, flag_descriptions::kCreditCardAssistDescription, kOsAndroid, @@ -2736,11 +2726,6 @@ SINGLE_VALUE_TYPE(switches::kEnableGoogleBrandedContextMenu)}, #endif // !OS_ANDROID && GOOGLE_CHROME_BUILD #if defined(OS_MACOSX) - {"enable-fullscreen-in-tab-detaching", - flag_descriptions::kTabDetachingInFullscreenName, - flag_descriptions::kTabDetachingInFullscreenDescription, kOsMac, - ENABLE_DISABLE_VALUE_TYPE(switches::kEnableFullscreenTabDetaching, - switches::kDisableFullscreenTabDetaching)}, {"enable-content-fullscreen", flag_descriptions::kContentFullscreenName, flag_descriptions::kContentFullscreenDescription, kOsMac, FEATURE_VALUE_TYPE(features::kContentFullscreen)}, @@ -3305,12 +3290,6 @@ FEATURE_VALUE_TYPE(features::kUseGoogleLocalNtp)}, #endif // !defined(OS_ANDROID) -#if defined(OS_MACOSX) - {"mac-rtl", flag_descriptions::kMacRTLName, - flag_descriptions::kMacRTLDescription, kOsMac, - FEATURE_VALUE_TYPE(features::kMacRTL)}, -#endif // defined(OS_MACOSX) - #if defined(OS_CHROMEOS) {"enable-stylus-virtual-keyboard", flag_descriptions::kEnableStylusVirtualKeyboardName, @@ -3479,11 +3458,6 @@ FEATURE_VALUE_TYPE(features::kSysInternals)}, #endif // defined(OS_CHROMEOS) - {"enable-improved-language-settings", - flag_descriptions::kImprovedLanguageSettingsName, - flag_descriptions::kImprovedLanguageSettingsDescription, kOsAll, - FEATURE_VALUE_TYPE(translate::kImprovedLanguageSettings)}, - {"enable-regional-locales-as-display-ui", flag_descriptions::kRegionalLocalesAsDisplayUIName, flag_descriptions::kRegionalLocalesAsDisplayUIDescription, kOsAll, @@ -3988,10 +3962,6 @@ {"ntp-icons", flag_descriptions::kNtpIconsName, flag_descriptions::kNtpIconsDescription, kOsDesktop, FEATURE_VALUE_TYPE(features::kNtpIcons)}, - - {"ntp-ui-md", flag_descriptions::kNtpUIMdName, - flag_descriptions::kNtpUIMdDescription, kOsDesktop, - FEATURE_VALUE_TYPE(features::kNtpUIMd)}, #endif // OS_WIN || OS_MACOSX || OS_LINUX #if defined(OS_ANDROID) @@ -4377,6 +4347,11 @@ {"enable-assistant-dsp", flag_descriptions::kEnableGoogleAssistantDspName, flag_descriptions::kEnableGoogleAssistantDspDescription, kOsCrOS, FEATURE_VALUE_TYPE(chromeos::assistant::features::kEnableDspHotword)}, + + {"enable-assistant-app-support", + flag_descriptions::kEnableAssistantAppSupportName, + flag_descriptions::kEnableAssistantAppSupportDescription, kOsCrOS, + FEATURE_VALUE_TYPE(chromeos::assistant::features::kAssistantAppSupport)}, #endif // defined(OS_CHROMEOS) {"enable-blink-heap-unified-garbage-collection", @@ -4444,6 +4419,22 @@ FEATURE_VALUE_TYPE( chromeos::assistant::features::kEnableStereoAudioInput)}, #endif // defined(OS_CHROMEOS) + +#if defined(OS_MACOSX) || defined(OS_CHROMEOS) + {"force-enable-system-aec", flag_descriptions::kForceEnableSystemAecName, + flag_descriptions::kForceEnableSystemAecDescription, kOsMac | kOsCrOS, + FEATURE_VALUE_TYPE(features::kForceEnableSystemAec)}, +#endif // defined(OS_MACOSX) || defined(OS_CHROMEOS) + +#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) + {"autofill-always-show-server-cards-in-sync-transport", + flag_descriptions::kAutofillAlwaysShowServerCardsInSyncTransportName, + flag_descriptions:: + kAutofillAlwaysShowServerCardsInSyncTransportDescription, + kOsMac | kOsWin | kOsLinux, + FEATURE_VALUE_TYPE( + autofill::features::kAutofillAlwaysShowServerCardsInSyncTransport)}, +#endif // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) }; class FlagsStateSingleton {
diff --git a/chrome/browser/accessibility/accessibility_extension_api.cc b/chrome/browser/accessibility/accessibility_extension_api.cc index 4ae3575..820eb3dd 100644 --- a/chrome/browser/accessibility/accessibility_extension_api.cc +++ b/chrome/browser/accessibility/accessibility_extension_api.cc
@@ -207,21 +207,8 @@ accessibility_private::SetSwitchAccessKeys::Params::Create(*args_); EXTENSION_FUNCTION_VALIDATE(params); - // For now, only accept key code if it represents an alphanumeric character. - std::set<int> key_codes; - for (auto key_code : params->key_codes) { - EXTENSION_FUNCTION_VALIDATE(key_code >= ui::VKEY_0 && - key_code <= ui::VKEY_Z); - key_codes.insert(key_code); - } + GetAccessibilityController()->SetSwitchAccessKeysToCapture(params->key_codes); - chromeos::AccessibilityManager* manager = - chromeos::AccessibilityManager::Get(); - - // AccessibilityManager can be null during system shut down, but no need to - // return error in this case, so just check that manager is not null. - if (manager) - manager->SetSwitchAccessKeys(key_codes); return RespondNow(NoArguments()); }
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc index 3008346c..40536bef 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -180,20 +180,18 @@ delete[] script_highlights; } -void UiControllerAndroid::ScrollBy( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - float distanceX, - float distanceY) { - ui_delegate_->ScrollBy(distanceX, distanceY); -} - void UiControllerAndroid::UpdateTouchableArea( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj) { ui_delegate_->UpdateTouchableArea(); } +void UiControllerAndroid::OnUserInteractionInsideTouchableArea( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcallerj) { + ui_delegate_->OnUserInteractionInsideTouchableArea(); +} + void UiControllerAndroid::OnScriptSelected( JNIEnv* env, const JavaParamRef<jobject>& jcaller,
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.h b/chrome/browser/android/autofill_assistant/ui_controller_android.h index be040ad..f240ec1 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.h +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.h
@@ -83,12 +83,11 @@ const base::android::JavaParamRef<jobject>& jcaller, const base::android::JavaParamRef<jstring>& initialUrlString); void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); - void ScrollBy(JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - float distanceX, - float distanceY); void UpdateTouchableArea(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); + void OnUserInteractionInsideTouchableArea( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller); void OnScriptSelected( JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller,
diff --git a/chrome/browser/android/download/download_manager_service.cc b/chrome/browser/android/download/download_manager_service.cc index 7d284aa8..aadb99c 100644 --- a/chrome/browser/android/download/download_manager_service.cc +++ b/chrome/browser/android/download/download_manager_service.cc
@@ -145,6 +145,19 @@ return reinterpret_cast<intptr_t>(service); } +DownloadManagerService::DownloadActionParams::DownloadActionParams( + DownloadAction download_action) + : action(download_action), has_user_gesture(false) {} + +DownloadManagerService::DownloadActionParams::DownloadActionParams( + DownloadAction download_action, + bool user_gesture) + : action(download_action), has_user_gesture(user_gesture) {} + +DownloadManagerService::DownloadActionParams::DownloadActionParams( + const DownloadActionParams& other) + : action(other.action), has_user_gesture(other.has_user_gesture) {} + DownloadManagerService::DownloadManagerService() : is_history_query_complete_(false), is_pending_downloads_loaded_(false), @@ -253,24 +266,28 @@ JNIEnv* env, jobject obj, const JavaParamRef<jstring>& jdownload_guid, - bool is_off_the_record) { + bool is_off_the_record, + bool has_user_gesture) { std::string download_guid = ConvertJavaStringToUTF8(env, jdownload_guid); if (is_pending_downloads_loaded_ || is_off_the_record) - ResumeDownloadInternal(download_guid, is_off_the_record); - else - EnqueueDownloadAction(download_guid, RESUME); + ResumeDownloadInternal(download_guid, is_off_the_record, has_user_gesture); + else { + EnqueueDownloadAction(download_guid, + DownloadActionParams(RESUME, has_user_gesture)); + } } void DownloadManagerService::RetryDownload( JNIEnv* env, jobject obj, const JavaParamRef<jstring>& jdownload_guid, - bool is_off_the_record) { + bool is_off_the_record, + bool has_user_gesture) { std::string download_guid = ConvertJavaStringToUTF8(env, jdownload_guid); if (is_pending_downloads_loaded_ || is_off_the_record) - RetryDownloadInternal(download_guid, is_off_the_record); + RetryDownloadInternal(download_guid, is_off_the_record, has_user_gesture); else - EnqueueDownloadAction(download_guid, RETRY); + EnqueueDownloadAction(download_guid, DownloadActionParams(RETRY)); } void DownloadManagerService::PauseDownload( @@ -282,7 +299,7 @@ if (is_pending_downloads_loaded_ || is_off_the_record) PauseDownloadInternal(download_guid, is_off_the_record); else - EnqueueDownloadAction(download_guid, PAUSE); + EnqueueDownloadAction(download_guid, DownloadActionParams(PAUSE)); } void DownloadManagerService::RemoveDownload( @@ -294,7 +311,7 @@ if (is_history_query_complete_ || is_off_the_record) RemoveDownloadInternal(download_guid, is_off_the_record); else - EnqueueDownloadAction(download_guid, REMOVE); + EnqueueDownloadAction(download_guid, DownloadActionParams(REMOVE)); } void DownloadManagerService::GetAllDownloads(JNIEnv* env, @@ -378,7 +395,7 @@ if (is_pending_downloads_loaded_ || is_off_the_record) CancelDownloadInternal(download_guid, is_off_the_record); else - EnqueueDownloadAction(download_guid, CANCEL); + EnqueueDownloadAction(download_guid, DownloadActionParams(CANCEL)); } void DownloadManagerService::OnHistoryQueryComplete() { @@ -432,7 +449,9 @@ } void DownloadManagerService::ResumeDownloadInternal( - const std::string& download_guid, bool is_off_the_record) { + const std::string& download_guid, + bool is_off_the_record, + bool has_user_gesture) { download::DownloadItem* item = GetDownload(download_guid, is_off_the_record); if (!item) { OnResumptionFailed(download_guid); @@ -443,14 +462,15 @@ return; } DownloadControllerBase::Get()->AboutToResumeDownload(item); - item->Resume(); + item->Resume(has_user_gesture); if (!resume_callback_for_testing_.is_null()) resume_callback_for_testing_.Run(true); } void DownloadManagerService::RetryDownloadInternal( const std::string& download_guid, - bool is_off_the_record) { + bool is_off_the_record, + bool has_user_gesture) { content::DownloadManager* manager = GetDownloadManager(is_off_the_record); if (!manager) return; @@ -461,7 +481,7 @@ // Try to resume first. if (item->CanResume()) { - item->Resume(); + item->Resume(has_user_gesture); return; } @@ -541,26 +561,26 @@ void DownloadManagerService::EnqueueDownloadAction( const std::string& download_guid, - DownloadAction action) { + const DownloadActionParams& params) { auto iter = pending_actions_.find(download_guid); if (iter == pending_actions_.end()) { - pending_actions_[download_guid] = action; + pending_actions_.insert(std::make_pair(download_guid, params)); return; } - switch (action) { + switch (params.action) { case RESUME: - if (iter->second == PAUSE) - iter->second = action; + if (iter->second.action == PAUSE) + iter->second = params; break; case PAUSE: - if (iter->second == RESUME) - iter->second = action; + if (iter->second.action == RESUME) + iter->second = params; break; case CANCEL: - iter->second = action; + iter->second = params; break; case REMOVE: - iter->second = action; + iter->second = params; break; default: NOTREACHED(); @@ -631,11 +651,11 @@ is_pending_downloads_loaded_ = true; for (auto iter = pending_actions_.begin(); iter != pending_actions_.end(); ++iter) { - DownloadAction action = iter->second; + DownloadActionParams params = iter->second; std::string download_guid = iter->first; - switch (action) { + switch (params.action) { case RESUME: - ResumeDownloadInternal(download_guid, false); + ResumeDownloadInternal(download_guid, false, params.has_user_gesture); break; case PAUSE: PauseDownloadInternal(download_guid, false); @@ -691,10 +711,11 @@ ConvertJavaStringToUTF8(env, jdownload_guid), 1, target_path.AddExtension("crdownload"), target_path, url_chain, GURL(), GURL(), GURL(), GURL(), "", "", base::Time(), base::Time(), - "", "", 0, -1, "", download::DownloadItem::INTERRUPTED, + "", "", 0, -1, 0, "", download::DownloadItem::INTERRUPTED, download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, - download::DOWNLOAD_INTERRUPT_REASON_CRASH, false, false, base::Time(), - false, std::vector<download::DownloadItem::ReceivedSlice>())); + download::DOWNLOAD_INTERRUPT_REASON_CRASH, false, false, false, + base::Time(), false, + std::vector<download::DownloadItem::ReceivedSlice>())); } // static
diff --git a/chrome/browser/android/download/download_manager_service.h b/chrome/browser/android/download/download_manager_service.h index 1d8de0a5..61f69d7 100644 --- a/chrome/browser/android/download/download_manager_service.h +++ b/chrome/browser/android/download/download_manager_service.h
@@ -80,13 +80,15 @@ void ResumeDownload(JNIEnv* env, jobject obj, const JavaParamRef<jstring>& jdownload_guid, - bool is_off_the_record); + bool is_off_the_record, + bool has_user_gesture); // Called to retry a download. void RetryDownload(JNIEnv* env, jobject obj, const JavaParamRef<jstring>& jdownload_guid, - bool is_off_the_record); + bool is_off_the_record, + bool has_user_gesture); // Called to cancel a download item that has GUID equal to |jdownload_guid|. // If the DownloadItem is not yet created, retry after a while. @@ -172,11 +174,13 @@ // Helper function to start the download resumption. void ResumeDownloadInternal(const std::string& download_guid, - bool is_off_the_record); + bool is_off_the_record, + bool has_user_gesture); // Helper function to retry the download. void RetryDownloadInternal(const std::string& download_guid, - bool is_off_the_record); + bool is_off_the_record, + bool has_user_gesture); // Helper function to cancel a download. void CancelDownloadInternal(const std::string& download_guid, @@ -230,11 +234,24 @@ int pending_get_downloads_actions_; enum DownloadAction { RESUME, RETRY, PAUSE, CANCEL, REMOVE, UNKNOWN }; - using PendingDownloadActions = std::map<std::string, DownloadAction>; + + // Holds params provided to the download function calls. + struct DownloadActionParams { + DownloadActionParams(DownloadAction download_action); + DownloadActionParams(DownloadAction download_action, bool user_gesture); + DownloadActionParams(const DownloadActionParams& other); + + ~DownloadActionParams() = default; + + DownloadAction action; + bool has_user_gesture; + }; + + using PendingDownloadActions = std::map<std::string, DownloadActionParams>; PendingDownloadActions pending_actions_; void EnqueueDownloadAction(const std::string& download_guid, - DownloadAction action); + const DownloadActionParams& params); ResumeCallback resume_callback_for_testing_;
diff --git a/chrome/browser/android/download/download_manager_service_unittest.cc b/chrome/browser/android/download/download_manager_service_unittest.cc index a8c7cf7..86ba05b 100644 --- a/chrome/browser/android/download/download_manager_service_unittest.cc +++ b/chrome/browser/android/download/download_manager_service_unittest.cc
@@ -78,7 +78,7 @@ JavaParamRef<jstring>( env, base::android::ConvertUTF8ToJavaString(env, download_guid).obj()), - false); + false, false); EXPECT_FALSE(success_); service_->OnHistoryQueryComplete(); while (!finished_)
diff --git a/chrome/browser/android/explore_sites/blacklist_site_task.cc b/chrome/browser/android/explore_sites/blacklist_site_task.cc index ccf0d7e0..981d4ef 100644 --- a/chrome/browser/android/explore_sites/blacklist_site_task.cc +++ b/chrome/browser/android/explore_sites/blacklist_site_task.cc
@@ -4,7 +4,9 @@ #include "chrome/browser/android/explore_sites/blacklist_site_task.h" +#include "base/time/clock.h" #include "chrome/browser/android/explore_sites/explore_sites_schema.h" +#include "components/offline_pages/core/offline_clock.h" #include "sql/database.h" #include "sql/meta_table.h" #include "sql/statement.h" @@ -33,7 +35,7 @@ return false; // Get current time as a unix time. - base::Time time_now = base::Time::Now(); + base::Time time_now = offline_pages::OfflineClock()->Now(); time_t unix_time = time_now.ToTimeT(); // Then insert the URL.
diff --git a/chrome/browser/android/explore_sites/explore_sites_store.cc b/chrome/browser/android/explore_sites/explore_sites_store.cc index 2129c208..2f5eba1 100644 --- a/chrome/browser/android/explore_sites/explore_sites_store.cc +++ b/chrome/browser/android/explore_sites/explore_sites_store.cc
@@ -14,7 +14,9 @@ #include "base/single_thread_task_runner.h" #include "base/task_runner_util.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" #include "chrome/browser/android/explore_sites/explore_sites_schema.h" +#include "components/offline_pages/core/offline_clock.h" #include "sql/database.h" namespace explore_sites { @@ -169,7 +171,7 @@ TRACE_EVENT_ASYNC_STEP_PAST0("explore_sites", "ExploreSitesStore", this, "Open"); - last_closing_time_ = base::Time::Now(); + last_closing_time_ = offline_pages::OfflineClock()->Now(); ReportStoreEvent(ExploreSitesStoreEvent::kClosed); initialization_status_ = InitializationStatus::NOT_INITIALIZED;
diff --git a/chrome/browser/android/explore_sites/history_statistics_reporter_unittest.cc b/chrome/browser/android/explore_sites/history_statistics_reporter_unittest.cc index 84a7446..25fdd73 100644 --- a/chrome/browser/android/explore_sites/history_statistics_reporter_unittest.cc +++ b/chrome/browser/android/explore_sites/history_statistics_reporter_unittest.cc
@@ -9,10 +9,12 @@ #include "base/test/bind_test_util.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/test_mock_time_task_runner.h" +#include "base/time/clock.h" #include "components/history/core/browser/history_database_params.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/test/history_service_test_util.h" #include "components/history/core/test/test_history_database.h" +#include "components/offline_pages/core/offline_clock.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/testing_pref_service.h" #include "testing/gtest/include/gtest/gtest.h" @@ -135,7 +137,7 @@ TEST_F(HistoryStatisticsReporterTest, HostAddedSimple) { ASSERT_TRUE(LoadHistory()); - base::Time time_now = base::Time::Now(); + base::Time time_now = offline_pages::OfflineClock()->Now(); history_service()->AddPage(GURL("http://www.google.com"), time_now, history::VisitSource::SOURCE_BROWSED); @@ -149,7 +151,7 @@ TEST_F(HistoryStatisticsReporterTest, HostAddedLongAgo) { ASSERT_TRUE(LoadHistory()); - base::Time time_now = base::Time::Now(); + base::Time time_now = offline_pages::OfflineClock()->Now(); base::Time time_29_days_ago = time_now - base::TimeDelta::FromDays(29); base::Time time_31_days_ago = time_now - base::TimeDelta::FromDays(31); @@ -169,7 +171,7 @@ TEST_F(HistoryStatisticsReporterTest, OneRunPerSession) { ASSERT_TRUE(LoadHistory()); - base::Time time_now = base::Time::Now(); + base::Time time_now = offline_pages::OfflineClock()->Now(); history_service()->AddPage(GURL("http://www.google.com"), time_now, history::VisitSource::SOURCE_BROWSED);
diff --git a/chrome/browser/android/preferences/preferences_launcher.cc b/chrome/browser/android/preferences/preferences_launcher.cc index f3268bc..be5185d5 100644 --- a/chrome/browser/android/preferences/preferences_launcher.cc +++ b/chrome/browser/android/preferences/preferences_launcher.cc
@@ -6,6 +6,7 @@ #include "base/android/jni_android.h" #include "chrome/browser/android/tab_android.h" +#include "components/password_manager/core/browser/manage_passwords_referrer.h" #include "content/public/browser/web_contents.h" #include "jni/PreferencesLauncher_jni.h" @@ -25,9 +26,11 @@ } void PreferencesLauncher::ShowPasswordSettings( - content::WebContents* web_contents) { + content::WebContents* web_contents, + password_manager::ManagePasswordsReferrer referrer) { Java_PreferencesLauncher_showPasswordSettings( - base::android::AttachCurrentThread(), web_contents->GetJavaWebContents()); + base::android::AttachCurrentThread(), web_contents->GetJavaWebContents(), + static_cast<int>(referrer)); } } // namespace android
diff --git a/chrome/browser/android/preferences/preferences_launcher.h b/chrome/browser/android/preferences/preferences_launcher.h index f1412c6..08fff388 100644 --- a/chrome/browser/android/preferences/preferences_launcher.h +++ b/chrome/browser/android/preferences/preferences_launcher.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_ANDROID_PREFERENCES_PREFERENCES_LAUNCHER_H_ #include "base/macros.h" +#include "components/password_manager/core/browser/manage_passwords_referrer.h" namespace content { class WebContents; @@ -24,7 +25,9 @@ content::WebContents* web_contents); // Opens the password settings page. - static void ShowPasswordSettings(content::WebContents* web_contents); + static void ShowPasswordSettings( + content::WebContents* web_contents, + password_manager::ManagePasswordsReferrer referrer); private: PreferencesLauncher() {}
diff --git a/chrome/browser/android/preferences/prefs.h b/chrome/browser/android/preferences/prefs.h index 5b80272a..3c60031 100644 --- a/chrome/browser/android/preferences/prefs.h +++ b/chrome/browser/android/preferences/prefs.h
@@ -12,7 +12,11 @@ #include "chrome/common/pref_names.h" #include "components/autofill/core/common/autofill_prefs.h" #include "components/dom_distiller/core/pref_names.h" +#include "components/feed/buildflags.h" +#if BUILDFLAG(ENABLE_FEED_IN_CHROME) #include "components/feed/core/pref_names.h" +#endif // BUILDFLAG(ENABLE_FEED_IN_CHROME) +#include "components/ntp_snippets/pref_names.h" #include "components/payments/core/payment_prefs.h" // A preference exposed to Java. @@ -41,8 +45,15 @@ prefs::kAllowDeletingBrowserHistory, contextual_suggestions::prefs::kContextualSuggestionsEnabled, prefs::kIncognitoModeAvailability, + +#if BUILDFLAG(ENABLE_FEED_IN_CHROME) feed::prefs::kEnableSnippets, feed::prefs::kArticlesListVisible, +#else // BUILDFLAG(ENABLE_FEED_IN_CHROME) + ntp_snippets::prefs::kEnableSnippets, + ntp_snippets::prefs::kArticlesListVisible, +#endif // BUILDFLAG(ENABLE_FEED_IN_CHROME) + dom_distiller::prefs::kReaderForAccessibility, prefs::kPromptForDownloadAndroid, prefs::kShowMissingSdCardErrorAndroid,
diff --git a/chrome/browser/android/preferences/prefs_unittest.cc b/chrome/browser/android/preferences/prefs_unittest.cc index 009426c..8d723d2 100644 --- a/chrome/browser/android/preferences/prefs_unittest.cc +++ b/chrome/browser/android/preferences/prefs_unittest.cc
@@ -34,10 +34,19 @@ GetPrefName(CONTEXTUAL_SUGGESTIONS_ENABLED)); EXPECT_EQ(prefs::kIncognitoModeAvailability, GetPrefName(INCOGNITO_MODE_AVAILABILITY)); + +#if BUILDFLAG(ENABLE_FEED_IN_CHROME) EXPECT_EQ(feed::prefs::kEnableSnippets, GetPrefName(NTP_ARTICLES_SECTION_ENABLED)); EXPECT_EQ(feed::prefs::kArticlesListVisible, GetPrefName(NTP_ARTICLES_LIST_VISIBLE)); +#else // BUILDFLAG(ENABLE_FEED_IN_CHROME) + EXPECT_EQ(ntp_snippets::prefs::kEnableSnippets, + GetPrefName(NTP_ARTICLES_SECTION_ENABLED)); + EXPECT_EQ(ntp_snippets::prefs::kArticlesListVisible, + GetPrefName(NTP_ARTICLES_LIST_VISIBLE)); +#endif // BUILDFLAG(ENABLE_FEED_IN_CHROME) + EXPECT_EQ(prefs::kPromptForDownloadAndroid, GetPrefName(PROMPT_FOR_DOWNLOAD_ANDROID)); EXPECT_EQ(dom_distiller::prefs::kReaderForAccessibility,
diff --git a/chrome/browser/android/resource_id.h b/chrome/browser/android/resource_id.h index 970fd9f..21c71700 100644 --- a/chrome/browser/android/resource_id.h +++ b/chrome/browser/android/resource_id.h
@@ -48,7 +48,7 @@ R.drawable.infobar_screen_share) DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_MIDI, R.drawable.infobar_midi) DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_MULTIPLE_DOWNLOADS, - R.drawable.infobar_multiple_downloads) + R.drawable.infobar_downloading) DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_NOTIFICATIONS, R.drawable.infobar_desktop_notifications) DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_PREVIEWS,
diff --git a/chrome/browser/android/signin/signin_manager_android.cc b/chrome/browser/android/signin/signin_manager_android.cc index c41e1e3..cd743d0 100644 --- a/chrome/browser/android/signin/signin_manager_android.cc +++ b/chrome/browser/android/signin/signin_manager_android.cc
@@ -368,6 +368,7 @@ static jboolean JNI_SigninManager_ShouldLoadPolicyForUser( JNIEnv* env, + const JavaParamRef<jobject>& obj, const JavaParamRef<jstring>& j_username) { std::string username = base::android::ConvertJavaStringToUTF8(env, j_username); @@ -376,6 +377,7 @@ static void JNI_SigninManager_IsUserManaged( JNIEnv* env, + const JavaParamRef<jobject>& obj, const JavaParamRef<jstring>& j_username, const JavaParamRef<jobject>& j_callback) { base::android::ScopedJavaGlobalRef<jobject> callback(env, j_callback); @@ -395,6 +397,7 @@ base::android::ScopedJavaLocalRef<jstring> JNI_SigninManager_ExtractDomainName( JNIEnv* env, + const JavaParamRef<jobject>& obj, const JavaParamRef<jstring>& j_email) { std::string email = base::android::ConvertJavaStringToUTF8(env, j_email); std::string domain = gaia::ExtractDomainName(email);
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index 79a30d3..e767e54 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm
@@ -26,7 +26,7 @@ #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" -#include "base/threading/thread_restrictions.h" +#include "base/threading/scoped_blocking_call.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h" #include "chrome/browser/apps/platform_apps/app_window_registry_util.h" @@ -179,7 +179,7 @@ // real, user-visible app bundle directory. (The alternatives give either the // framework's path or the initial app's path, which may be an app mode shim // or a unit test.) - base::AssertBlockingAllowedDeprecated(); + base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK); base::FilePath app_bundle_path = chrome::GetVersionedDirectory().DirName().DirName().DirName();
diff --git a/chrome/browser/apps/app_service/app_icon_source.cc b/chrome/browser/apps/app_service/app_icon_source.cc new file mode 100644 index 0000000..a209f9db --- /dev/null +++ b/chrome/browser/apps/app_service/app_icon_source.cc
@@ -0,0 +1,121 @@ +// Copyright (c) 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 "chrome/browser/apps/app_service/app_icon_source.h" + +#include <cmath> +#include <string> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/numerics/safe_conversions.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/url_constants.h" +#include "extensions/grit/extensions_browser_resources.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" +#include "url/gurl.h" + +namespace apps { + +namespace { + +float GetDeviceScaleFactor() { + display::Screen* screen = display::Screen::GetScreen(); + if (!screen) { + return 1.0f; + } + return screen->GetPrimaryDisplay().device_scale_factor(); +} + +int ConvertPxToDip(int px) { + return base::saturated_cast<int>( + std::floor(static_cast<float>(px) / GetDeviceScaleFactor())); +} + +void LoadDefaultImage(const content::URLDataSource::GotDataCallback& callback) { + base::StringPiece contents = + ui::ResourceBundle::GetSharedInstance().GetRawDataResourceForScale( + IDR_APP_DEFAULT_ICON, ui::SCALE_FACTOR_100P); + + base::RefCountedBytes* image_bytes = new base::RefCountedBytes(); + image_bytes->data().assign(contents.data(), + contents.data() + contents.size()); + callback.Run(image_bytes); +} + +void RunCallback(const content::URLDataSource::GotDataCallback& callback, + apps::mojom::IconValuePtr iv) { + if (!iv->compressed.has_value()) { + LoadDefaultImage(callback); + return; + } + base::RefCountedBytes* image_bytes = + new base::RefCountedBytes(iv->compressed.value()); + callback.Run(image_bytes); +} + +} // namespace + +AppIconSource::AppIconSource(Profile* profile) : profile_(profile) {} + +AppIconSource::~AppIconSource() = default; + +bool AppIconSource::AllowCaching() const { + // Should not be cached as caching is performed by proxy. + return false; +} + +std::string AppIconSource::GetMimeType(const std::string&) const { + // We need to explicitly return a mime type, otherwise if the user tries to + // drag the image they get no extension. + return "image/png"; +} + +std::string AppIconSource::GetSource() const { + return chrome::kChromeUIAppIconHost; +} + +void AppIconSource::StartDataRequest( + const std::string& path, + const content::ResourceRequestInfo::WebContentsGetter& wc_getter, + const content::URLDataSource::GotDataCallback& callback) { + std::string path_lower = base::ToLowerASCII(path); + std::vector<std::string> path_parts = base::SplitString( + path_lower, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + + // Check data exists, load default image if it doesn't. + if (path_lower.empty() || path_parts.size() < 2) { + LoadDefaultImage(callback); + return; + } + + // Check data is correct type, load default image if not. + const std::string app_id = path_parts[0]; + std::string size_param = path_parts[1]; + int size = 0; + if (!base::StringToInt(size_param, &size)) { + LoadDefaultImage(callback); + return; + } + int size_in_dip = ConvertPxToDip(size); + + apps::AppServiceProxy* app_service_proxy = + apps::AppServiceProxy::Get(profile_); + if (!app_service_proxy) { + LoadDefaultImage(callback); + return; + } + + app_service_proxy->LoadIcon(app_id, apps::mojom::IconCompression::kCompressed, + size_in_dip, + base::BindOnce(&RunCallback, callback)); +} + +} // namespace apps
diff --git a/chrome/browser/apps/app_service/app_icon_source.h b/chrome/browser/apps/app_service/app_icon_source.h new file mode 100644 index 0000000..41e3ae5 --- /dev/null +++ b/chrome/browser/apps/app_service/app_icon_source.h
@@ -0,0 +1,54 @@ +// Copyright (c) 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 CHROME_BROWSER_APPS_APP_SERVICE_APP_ICON_SOURCE_H_ +#define CHROME_BROWSER_APPS_APP_SERVICE_APP_ICON_SOURCE_H_ + +#include "base/macros.h" +#include "content/public/browser/url_data_source.h" + +class Profile; + +namespace apps { + +// AppIconSource serves app icons through the AppServiceProxy. +// Icons can be retrieved for any installed app. +// +// To request an icon a call must first be made to chrome://apps +// as the URLDataSource is first initialised in that page's handler. +// +// The format for requesting an icon is as follows: +// chrome://app-icon/<app_id>/<icon_size> +// +// Parameters: +// <app_id> = the id of the app +// <icon_size> = the desired size in DIP of the icon +// +// We attempt to load icons from the following sources in order: +// 1) The icon listed through the AppServiceProxy +// 2) The default icon if there are no matches + +class AppIconSource : public content::URLDataSource { + public: + explicit AppIconSource(Profile* profile); + ~AppIconSource() override; + + // content::URLDataSource implementation. + bool AllowCaching() const override; + std::string GetMimeType(const std::string&) const override; + std::string GetSource() const override; + void StartDataRequest( + const std::string& path, + const content::ResourceRequestInfo::WebContentsGetter& wc_getter, + const content::URLDataSource::GotDataCallback& callback) override; + + private: + Profile* profile_; + + DISALLOW_COPY_AND_ASSIGN(AppIconSource); +}; + +} // namespace apps + +#endif // CHROME_BROWSER_APPS_APP_SERVICE_APP_ICON_SOURCE_H_
diff --git a/chrome/browser/apps/app_service/built_in_chromeos_apps.cc b/chrome/browser/apps/app_service/built_in_chromeos_apps.cc index 569562e..8826a09 100644 --- a/chrome/browser/apps/app_service/built_in_chromeos_apps.cc +++ b/chrome/browser/apps/app_service/built_in_chromeos_apps.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/ui/app_list/internal_app/internal_app_item.h" #include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h" #include "chrome/browser/ui/app_list/search/internal_app_result.h" +#include "chrome/browser/ui/app_list/search/search_util.h" #include "chrome/services/app_service/public/mojom/types.mojom.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "ui/base/l10n/l10n_util.h" @@ -38,6 +39,10 @@ app->show_in_launcher = internal_app.show_in_launcher ? apps::mojom::OptionalBool::kTrue : apps::mojom::OptionalBool::kFalse; + app->show_in_search = internal_app.searchable + ? apps::mojom::OptionalBool::kTrue + : apps::mojom::OptionalBool::kFalse; + return app; } @@ -68,6 +73,16 @@ // TODO(crbug.com/826982): move source of truth for built-in apps from // ui/app_list to here when the AppService feature is enabled by default. for (const auto& internal_app : app_list::GetInternalAppList(profile_)) { + // TODO(crbug.com/826982): support the "continue reading" app? Or leave + // it specifically to the chrome/browser/ui/app_list/search code? If + // moved here, it might mean calling sync_sessions::SessionSyncService's + // SubscribeToForeignSessionsChanged. See also app_search_provider.cc's + // InternalDataSource. + if (internal_app.internal_app_name == + app_list::InternalAppName::kContinueReading) { + continue; + } + apps::mojom::AppPtr app = Convert(internal_app); if (!app.is_null()) { apps.push_back(std::move(app)); @@ -108,17 +123,17 @@ switch (launch_source) { case apps::mojom::LaunchSource::kUnknown: break; - case apps::mojom::LaunchSource::kFromAppList: + case apps::mojom::LaunchSource::kFromAppListGrid: InternalAppItem::RecordActiveHistogram(app_id); break; - case apps::mojom::LaunchSource::kFromAppListSearch: + case apps::mojom::LaunchSource::kFromAppListRecommendation: + app_list::InternalAppResult::RecordOpenHistogram(app_id); + break; + case apps::mojom::LaunchSource::kFromAppListQueryResult: + app_list::RecordHistogram(app_list::APP_SEARCH_RESULT); app_list::InternalAppResult::RecordOpenHistogram(app_id); break; } - // TODO(crbug.com/826982): we should also update a UMA histogram when an app - // result is *shown* in the app list search box, not just *launched*. - // - // See //chrome/browser/ui/app_list/search/internal_app_result.cc. app_list::OpenInternalApp(app_id, profile_, event_flags); }
diff --git a/chrome/browser/apps/app_service/extension_apps.cc b/chrome/browser/apps/app_service/extension_apps.cc index 9e5cc9f..b94eebe 100644 --- a/chrome/browser/apps/app_service/extension_apps.cc +++ b/chrome/browser/apps/app_service/extension_apps.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/extension_app_utils.h" +#include "chrome/browser/ui/app_list/search/search_util.h" #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" #include "chrome/common/extensions/extension_metrics.h" #include "chrome/services/app_service/public/mojom/types.mojom.h" @@ -43,9 +44,10 @@ switch (launch_source) { case apps::mojom::LaunchSource::kUnknown: return ash::LAUNCH_FROM_UNKNOWN; - case apps::mojom::LaunchSource::kFromAppList: + case apps::mojom::LaunchSource::kFromAppListGrid: return ash::LAUNCH_FROM_APP_LIST; - case apps::mojom::LaunchSource::kFromAppListSearch: + case apps::mojom::LaunchSource::kFromAppListRecommendation: + case apps::mojom::LaunchSource::kFromAppListQueryResult: return ash::LAUNCH_FROM_APP_LIST_SEARCH; } } @@ -125,10 +127,13 @@ switch (launch_source) { case apps::mojom::LaunchSource::kUnknown: break; - case apps::mojom::LaunchSource::kFromAppList: + case apps::mojom::LaunchSource::kFromAppListGrid: extensions::RecordAppListMainLaunch(extension); break; - case apps::mojom::LaunchSource::kFromAppListSearch: + case apps::mojom::LaunchSource::kFromAppListRecommendation: + break; + case apps::mojom::LaunchSource::kFromAppListQueryResult: + app_list::RecordHistogram(app_list::APP_SEARCH_RESULT); extensions::RecordAppListSearchLaunch(extension); break; } @@ -152,9 +157,12 @@ app->icon_key->s_key = extension->id(); app->icon_key->u_key = next_u_key_++; - app->show_in_launcher = app_list::ShouldShowInLauncher(extension, profile_) - ? apps::mojom::OptionalBool::kTrue - : apps::mojom::OptionalBool::kFalse; + auto show = app_list::ShouldShowInLauncher(extension, profile_) + ? apps::mojom::OptionalBool::kTrue + : apps::mojom::OptionalBool::kFalse; + app->show_in_launcher = show; + app->show_in_search = show; + return app; }
diff --git a/chrome/browser/apps/app_shim/app_shim_host_mac.cc b/chrome/browser/apps/app_shim/app_shim_host_mac.cc index dae35862..2faeb65 100644 --- a/chrome/browser/apps/app_shim/app_shim_host_mac.cc +++ b/chrome/browser/apps/app_shim/app_shim_host_mac.cc
@@ -175,3 +175,7 @@ views::BridgeFactoryHost* AppShimHost::GetViewsBridgeFactoryHost() const { return views_bridge_factory_host_.get(); } + +chrome::mojom::AppShim* AppShimHost::GetAppShim() const { + return app_shim_.get(); +}
diff --git a/chrome/browser/apps/app_shim/app_shim_host_mac.h b/chrome/browser/apps/app_shim/app_shim_host_mac.h index bc88b40..12d1850 100644 --- a/chrome/browser/apps/app_shim/app_shim_host_mac.h +++ b/chrome/browser/apps/app_shim/app_shim_host_mac.h
@@ -43,6 +43,10 @@ virtual void OnAppLaunchComplete(apps::AppShimLaunchResult result); // Invoked when the app is closed in the browser process. void OnAppClosed(); + + // TODO(ccameron): The following three function should directly call the + // AppShim mojo interface (they only don't due to tests that could be changed + // to mock the AppShim mojo interface). // Invoked when the app should be hidden. void OnAppHide(); // Invoked when a window becomes visible while the app is hidden. Ensures @@ -56,8 +60,13 @@ // to. base::FilePath GetProfilePath() const; std::string GetAppId() const; + + // Return the factory to use to create new widgets in the same process. views::BridgeFactoryHost* GetViewsBridgeFactoryHost() const; + // Return the app shim interface. + chrome::mojom::AppShim* GetAppShim() const; + protected: // AppShimHost is owned by itself. It will delete itself in Close (called on // channel error and OnAppClosed).
diff --git a/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc b/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc index 2dea5cbd..a7f4d2d 100644 --- a/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc +++ b/chrome/browser/apps/app_shim/app_shim_host_mac_unittest.cc
@@ -52,6 +52,7 @@ override {} void CreateContentNSViewBridgeFactory( content::mojom::NSViewBridgeFactoryAssociatedRequest request) override {} + void CreateCommandDispatcherForWidget(uint64_t widget_id) override {} void Hide() override {} void UnhideWithoutActivation() override {} void SetUserAttention(apps::AppShimAttentionType attention_type) override {}
diff --git a/chrome/browser/apps/app_shim/app_shim_host_manager_browsertest_mac.mm b/chrome/browser/apps/app_shim/app_shim_host_manager_browsertest_mac.mm index 3b5d28a..941d1b9 100644 --- a/chrome/browser/apps/app_shim/app_shim_host_manager_browsertest_mac.mm +++ b/chrome/browser/apps/app_shim/app_shim_host_manager_browsertest_mac.mm
@@ -60,6 +60,7 @@ override {} void CreateContentNSViewBridgeFactory( content::mojom::NSViewBridgeFactoryAssociatedRequest request) override {} + void CreateCommandDispatcherForWidget(uint64_t widget_id) override {} void Hide() override {} void UnhideWithoutActivation() override {} void SetUserAttention(apps::AppShimAttentionType attention_type) override {}
diff --git a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc index ce314d4..255aa01 100644 --- a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc +++ b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.cc
@@ -286,17 +286,15 @@ return host; } -views::BridgeFactoryHost* -ExtensionAppShimHandler::GetViewsBridgeFactoryHostForBrowser(Browser* browser) { +AppShimHost* ExtensionAppShimHandler::GetHostForBrowser(Browser* browser) { if (!features::HostWindowsInAppShimProcess()) return nullptr; const Extension* extension = apps::ExtensionAppShimHandler::MaybeGetAppForBrowser(browser); if (extension && extension->is_hosted_app()) { - AppShimHost* host = FindOrCreateHost( - Profile::FromBrowserContext(browser->profile()), extension->id()); - return host->GetViewsBridgeFactoryHost(); + return FindOrCreateHost(Profile::FromBrowserContext(browser->profile()), + extension->id()); } return nullptr; }
diff --git a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h index 9bbfcf4..d212b97 100644 --- a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h +++ b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h
@@ -37,10 +37,6 @@ class Extension; } // namespace extensions -namespace views { -class BridgeFactoryHost; -} // namespace views - namespace apps { // This app shim handler that handles events for app shims that correspond to an @@ -99,10 +95,11 @@ // needed. AppShimHost* FindOrCreateHost(Profile* profile, const std::string& app_id); - // Get the ViewBridgeFactoryHost, which may be used to create remote - // NSWindows, corresponding to a browser instance (or nullptr if none exists). - views::BridgeFactoryHost* GetViewsBridgeFactoryHostForBrowser( - Browser* browser); + // Get the AppShimHost corresponding to a browser instance, returning nullptr + // if none should exist. If no AppShimHost exists, but one should exist + // (e.g, because the app process is still launching), create one, which will + // bind to the app process when it finishes launching. + AppShimHost* GetHostForBrowser(Browser* browser); void SetHostedAppHidden(Profile* profile, const std::string& app_id,
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index dd569136..6c262089 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -2974,7 +2974,7 @@ ASSERT_TRUE(download->CanResume()); EXPECT_EQ(download::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, download->GetLastReason()); - download->Resume(); + download->Resume(false); } completion_observer->WaitForFinished(); @@ -3104,7 +3104,7 @@ ASSERT_TRUE(download->GetFullPath().empty()); EXPECT_EQ(download::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, download->GetLastReason()); - download->Resume(); + download->Resume(false); } completion_observer->WaitForFinished();
diff --git a/chrome/browser/apps/platform_apps/api/BUILD.gn b/chrome/browser/apps/platform_apps/api/BUILD.gn index bc4872e..98ecbe8 100644 --- a/chrome/browser/apps/platform_apps/api/BUILD.gn +++ b/chrome/browser/apps/platform_apps/api/BUILD.gn
@@ -10,7 +10,7 @@ assert(enable_extensions) function_registration("api_registration") { - sources = chrome_apps_api_schema_files + sources = chrome_apps_api_schema_files + chrome_apps_uncompiled_schema_files impl_dir = "//chrome/browser/apps/platform_apps/api" configs = [ "//build/config:precompiled_headers" ] bundle_name = "ChromeApps"
diff --git a/chrome/browser/apps/platform_apps/api/sync_file_system/sync_file_system_browsertest.cc b/chrome/browser/apps/platform_apps/api/sync_file_system/sync_file_system_browsertest.cc index d50c0ff..c3bb4a6 100644 --- a/chrome/browser/apps/platform_apps/api/sync_file_system/sync_file_system_browsertest.cc +++ b/chrome/browser/apps/platform_apps/api/sync_file_system/sync_file_system_browsertest.cc
@@ -29,7 +29,6 @@ namespace { -const char kGaiaId[] = "gaia_id"; const char kEmail[] = "email@example.com"; class FakeDriveServiceFactory @@ -137,6 +136,10 @@ run_loop.Run(); } + identity::IdentityManager* identity_manager() const { + return identity_test_env_->identity_manager(); + } + private: base::ScopedTempDir base_dir_; std::unique_ptr<leveldb::Env> in_memory_env_; @@ -175,10 +178,8 @@ // service. Wait for the completion and resume the app. WaitUntilIdle(); - AccountInfo info; - info.account_id = kGaiaId; - info.account_id = kEmail; - sync_engine()->OnPrimaryAccountCleared(info); + sync_engine()->OnPrimaryAccountCleared( + identity_manager()->GetPrimaryAccountInfo()); foo_created.Reply("resume"); ASSERT_TRUE(bar_created.WaitUntilSatisfied()); @@ -191,7 +192,8 @@ EXPECT_EQ(REMOTE_SERVICE_AUTHENTICATION_REQUIRED, sync_engine()->GetCurrentState()); - sync_engine()->OnPrimaryAccountSet(info); + sync_engine()->OnPrimaryAccountSet( + identity_manager()->GetPrimaryAccountInfo()); WaitUntilIdle(); bar_created.Reply("resume");
diff --git a/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc b/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc index b2c468e0..5727705 100644 --- a/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc +++ b/chrome/browser/autofill/autofill_captured_sites_interactive_uitest.cc
@@ -171,8 +171,8 @@ type == autofill::CREDIT_CARD_NAME_LAST) { card_.SetRawInfo(autofill::CREDIT_CARD_NAME_FULL, base::ASCIIToUTF16("")); - card_.SetRawInfo(type, base::UTF8ToUTF16(field_value)); } + card_.SetRawInfo(type, base::UTF8ToUTF16(field_value)); } else { profile_.SetRawInfo(type, base::UTF8ToUTF16(field_value)); }
diff --git a/chrome/browser/autofill/autofill_save_card_infobar_delegate_mobile_unittest.cc b/chrome/browser/autofill/autofill_save_card_infobar_delegate_mobile_unittest.cc index 544eeaf..7272fdd4 100644 --- a/chrome/browser/autofill/autofill_save_card_infobar_delegate_mobile_unittest.cc +++ b/chrome/browser/autofill/autofill_save_card_infobar_delegate_mobile_unittest.cc
@@ -50,8 +50,15 @@ std::unique_ptr<TestPersonalDataManager> personal_data_; private: - void UploadSaveCardCallback(const AutofillClient::UserProvidedCardDetails& - user_provided_card_details) { + void LocalSaveCardPromptCallback( + AutofillClient::SaveCardOfferUserDecision user_decision) { + personal_data_.get()->SaveImportedCreditCard(credit_card_to_save_); + } + + void UploadSaveCardPromptCallback( + AutofillClient::SaveCardOfferUserDecision user_decision, + const AutofillClient::UserProvidedCardDetails& + user_provided_card_details) { personal_data_.get()->SaveImportedCreditCard(credit_card_to_save_); } @@ -120,27 +127,24 @@ new AutofillSaveCardInfoBarDelegateMobile( is_uploading, /*should_request_name_from_user=*/false, credit_card, std::move(legal_message), - /*strike_database=*/nullptr, /*upload_save_card_callback=*/ base::BindOnce(&AutofillSaveCardInfoBarDelegateMobileTest:: - UploadSaveCardCallback, + UploadSaveCardPromptCallback, base::Unretained(this)), - /*local_save_card_callback=*/base::Closure(), - profile()->GetPrefs())); + /*local_save_card_callback=*/{}, profile()->GetPrefs())); return delegate; } // Local save infobar delegate: + credit_card_to_save_ = credit_card; std::unique_ptr<ConfirmInfoBarDelegate> delegate( new AutofillSaveCardInfoBarDelegateMobile( is_uploading, /*should_request_name_from_user=*/false, credit_card, std::move(legal_message), - /*strike_database=*/nullptr, - /*upload_save_card_callback=*/ - AutofillClient::UserAcceptedUploadCallback(), + /*upload_save_card_callback=*/{}, /*local_save_card_callback=*/ - base::Bind(base::IgnoreResult( - &TestPersonalDataManager::SaveImportedCreditCard), - base::Unretained(personal_data_.get()), credit_card), + base::BindOnce(&AutofillSaveCardInfoBarDelegateMobileTest:: + LocalSaveCardPromptCallback, + base::Unretained(this)), profile()->GetPrefs())); return delegate; }
diff --git a/chrome/browser/autofill/captured_sites_test_utils.cc b/chrome/browser/autofill/captured_sites_test_utils.cc index 0aabc156..ea34190 100644 --- a/chrome/browser/autofill/captured_sites_test_utils.cc +++ b/chrome/browser/autofill/captured_sites_test_utils.cc
@@ -557,6 +557,10 @@ type, "validateNoSavePasswordPrompt") == 0) { if (!ExecuteValidateNoSavePasswordPromptAction(*action)) return false; + } else if (base::CompareCaseInsensitiveASCII( + type, "validatePasswordSaveFallback") == 0) { + if (!ExecuteValidateSaveFallbackAction(*action)) + return false; } else if (base::CompareCaseInsensitiveASCII(type, "waitFor") == 0) { if (!ExecuteWaitForStateAction(*action)) return false; @@ -1063,6 +1067,13 @@ return true; } +bool TestRecipeReplayer::ExecuteValidateSaveFallbackAction( + const base::DictionaryValue& action) { + VLOG(1) << "Verify that Chrome shows the save fallback icon in the omnibox."; + EXPECT_TRUE(feature_action_executor()->WaitForSaveFallback()); + return true; +} + bool TestRecipeReplayer::ExecuteWaitForStateAction( const base::DictionaryValue& action) { // Extract the list of JavaScript assertions into a vector. @@ -1664,6 +1675,12 @@ return false; } +bool TestRecipeReplayChromeFeatureActionExecutor::WaitForSaveFallback() { + ADD_FAILURE() << "TestRecipeReplayChromeFeatureActionExecutor" + "::WaitForSaveFallback is not implemented!"; + return false; +} + bool TestRecipeReplayChromeFeatureActionExecutor:: HasChromeShownSavePasswordPrompt() { ADD_FAILURE() << "TestRecipeReplayChromeFeatureActionExecutor"
diff --git a/chrome/browser/autofill/captured_sites_test_utils.h b/chrome/browser/autofill/captured_sites_test_utils.h index b31b2ecb..041f84f 100644 --- a/chrome/browser/autofill/captured_sites_test_utils.h +++ b/chrome/browser/autofill/captured_sites_test_utils.h
@@ -164,6 +164,7 @@ const std::string& password); virtual bool SavePassword(); virtual bool UpdatePassword(); + virtual bool WaitForSaveFallback(); virtual bool HasChromeShownSavePasswordPrompt(); virtual bool HasChromeStoredCredential(const std::string& origin, const std::string& username, @@ -255,6 +256,7 @@ bool ExecuteValidateFieldValueAction(const base::DictionaryValue& action); bool ExecuteValidateNoSavePasswordPromptAction( const base::DictionaryValue& action); + bool ExecuteValidateSaveFallbackAction(const base::DictionaryValue& action); bool ExecuteWaitForStateAction(const base::DictionaryValue& action); bool GetTargetHTMLElementXpathFromAction(const base::DictionaryValue& action, std::string* xpath);
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc index b359210..226ed760 100644 --- a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc +++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
@@ -65,19 +65,17 @@ void BackgroundFetchDelegateImpl::Shutdown() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - if (client()) { - client()->OnDelegateShutdown(); - } } BackgroundFetchDelegateImpl::JobDetails::JobDetails(JobDetails&&) = default; BackgroundFetchDelegateImpl::JobDetails::JobDetails( + base::WeakPtr<Client> client, std::unique_ptr<content::BackgroundFetchDescription> fetch_description, const std::string& provider_namespace, bool is_off_the_record) - : offline_item(offline_items_collection::ContentId( + : client(std::move(client)), + offline_item(offline_items_collection::ContentId( provider_namespace, fetch_description->job_unique_id)), job_state(fetch_description->start_paused @@ -234,6 +232,7 @@ } void BackgroundFetchDelegateImpl::CreateDownloadJob( + base::WeakPtr<Client> client, std::unique_ptr<content::BackgroundFetchDescription> fetch_description) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -241,8 +240,8 @@ DCHECK(!job_details_map_.count(job_unique_id)); job_details_map_.emplace( job_unique_id, - JobDetails(std::move(fetch_description), provider_namespace_, - profile_->IsOffTheRecord())); + JobDetails(std::move(client), std::move(fetch_description), + provider_namespace_, profile_->IsOffTheRecord())); } void BackgroundFetchDelegateImpl::DownloadUrl( @@ -364,10 +363,9 @@ return; const std::string& job_unique_id = download_job_unique_id_iter->second; - - if (client()) { - client()->OnDownloadStarted(job_unique_id, download_guid, - std::move(response)); + if (auto client = GetClient(job_unique_id)) { + client->OnDownloadStarted(job_unique_id, download_guid, + std::move(response)); } } @@ -400,8 +398,9 @@ } UpdateOfflineItemAndUpdateObservers(&job_details); - if (client()) - client()->OnDownloadUpdated(job_unique_id, download_guid, bytes_downloaded); + if (job_details.client) + job_details.client->OnDownloadUpdated(job_unique_id, download_guid, + bytes_downloaded); } void BackgroundFetchDelegateImpl::OnDownloadFailed( @@ -428,9 +427,9 @@ return; } - if (client()) { - client()->OnDownloadComplete(job_unique_id, download_guid, - std::move(result)); + if (job_details.client) { + job_details.client->OnDownloadComplete(job_unique_id, download_guid, + std::move(result)); } job_details.current_fetch_guids.erase(download_guid); @@ -458,9 +457,9 @@ : result->file_size; UpdateOfflineItemAndUpdateObservers(&job_details); - if (client()) { - client()->OnDownloadComplete(job_unique_id, download_guid, - std::move(result)); + if (job_details.client) { + job_details.client->OnDownloadComplete(job_unique_id, download_guid, + std::move(result)); } job_details.current_fetch_guids.erase(download_guid); @@ -516,8 +515,8 @@ void BackgroundFetchDelegateImpl::OpenItem( offline_items_collection::LaunchLocation location, const offline_items_collection::ContentId& id) { - if (client()) - client()->OnUIActivated(id.id); + if (auto client = GetClient(id.id)) + client->OnUIActivated(id.id); } void BackgroundFetchDelegateImpl::RemoveItem( @@ -531,10 +530,11 @@ // Save a copy before Abort() deletes the reference. const std::string unique_id = job_unique_id; Abort(job_unique_id); - if (client()) { - client()->OnJobCancelled(unique_id, - blink::mojom::BackgroundFetchFailureReason:: - TOTAL_DOWNLOAD_SIZE_EXCEEDED); + + if (auto client = GetClient(unique_id)) { + client->OnJobCancelled(unique_id, + blink::mojom::BackgroundFetchFailureReason:: + TOTAL_DOWNLOAD_SIZE_EXCEEDED); } } @@ -544,8 +544,8 @@ const std::string unique_id = id.id; Abort(unique_id); - if (client()) { - client()->OnJobCancelled( + if (auto client = GetClient(unique_id)) { + client->OnJobCancelled( unique_id, blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI); } @@ -702,6 +702,16 @@ return; } - if (client()) - client()->GetUploadData(job_it->second, download_guid, std::move(callback)); + if (job_details.client) { + job_details.client->GetUploadData(job_it->second, download_guid, + std::move(callback)); + } +} + +base::WeakPtr<content::BackgroundFetchDelegate::Client> +BackgroundFetchDelegateImpl::GetClient(const std::string& job_unique_id) { + auto it = job_details_map_.find(job_unique_id); + if (it == job_details_map_.end()) + return nullptr; + return it->second.client; }
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.h b/chrome/browser/background_fetch/background_fetch_delegate_impl.h index 65f797d..f9de2e0 100644 --- a/chrome/browser/background_fetch/background_fetch_delegate_impl.h +++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.h
@@ -56,7 +56,8 @@ const url::Origin& origin, const content::ResourceRequestInfo::WebContentsGetter& wc_getter, GetPermissionForOriginCallback callback) override; - void CreateDownloadJob(std::unique_ptr<content::BackgroundFetchDescription> + void CreateDownloadJob(base::WeakPtr<Client> client, + std::unique_ptr<content::BackgroundFetchDescription> fetch_description) override; void DownloadUrl(const std::string& job_unique_id, const std::string& guid, @@ -144,6 +145,7 @@ JobDetails(JobDetails&&); JobDetails( + base::WeakPtr<Client> client, std::unique_ptr<content::BackgroundFetchDescription> fetch_description, const std::string& provider_namespace, bool is_off_the_record); @@ -157,6 +159,9 @@ kIncluded, }; + // The client to report the Background Fetch updates to. + base::WeakPtr<Client> client; + // Set of DownloadService GUIDs that are currently processed. They are // added by DownloadUrl and are removed when the fetch completes, fails, // or is cancelled. The GUID maps to whether the fetch has upload data. @@ -194,6 +199,9 @@ GetPermissionForOriginCallback callback, bool has_permission); + // Returns the client for a given |job_unique_id|. + base::WeakPtr<Client> GetClient(const std::string& job_unique_id); + // The profile this service is being created for. Profile* profile_;
diff --git a/chrome/browser/badging/badge_manager.cc b/chrome/browser/badging/badge_manager.cc new file mode 100644 index 0000000..9715dd4c --- /dev/null +++ b/chrome/browser/badging/badge_manager.cc
@@ -0,0 +1,43 @@ +// 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 "chrome/browser/badging/badge_manager.h" + +#include "base/logging.h" +#include "base/optional.h" + +namespace badging { + +BadgeManager::BadgeManager() = default; + +BadgeManager::~BadgeManager() = default; + +void BadgeManager::UpdateBadge(const extensions::ExtensionId& extension_id, + base::Optional<int> contents) { + auto it = badged_apps_.find(extension_id); + if (it != badged_apps_.end() && it->second == contents) + return; + + badged_apps_[extension_id] = contents; + + if (!delegate_) + return; + + delegate_->OnBadgeSet(extension_id, contents); +} + +void BadgeManager::ClearBadge(const extensions::ExtensionId& extension_id) { + auto removed = badged_apps_.erase(extension_id); + if (!removed || !delegate_) + return; + + delegate_->OnBadgeCleared(extension_id); +} + +void BadgeManager::SetDelegate(BadgeManagerDelegate* badge_manager_delegate) { + DCHECK(!delegate_); + delegate_ = badge_manager_delegate; +} + +} // namespace badging
diff --git a/chrome/browser/badging/badge_manager.h b/chrome/browser/badging/badge_manager.h new file mode 100644 index 0000000..83dd78e8 --- /dev/null +++ b/chrome/browser/badging/badge_manager.h
@@ -0,0 +1,48 @@ +// 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 CHROME_BROWSER_BADGING_BADGE_MANAGER_H_ +#define CHROME_BROWSER_BADGING_BADGE_MANAGER_H_ + +#include <map> +#include <string> + +#include "base/macros.h" +#include "base/optional.h" +#include "chrome/browser/badging/badge_manager_delegate.h" +#include "components/keyed_service/core/keyed_service.h" +#include "extensions/common/extension_id.h" + +class KeyedService; + +namespace badging { + +// Maintains a record of badge contents and dispatches badge changes to a +// delegate. +class BadgeManager : public KeyedService { + public: + BadgeManager(); + ~BadgeManager() override; + + // Records badge contents for an app and notifies the delegate if the badge + // contents have changed. + void UpdateBadge(const extensions::ExtensionId&, base::Optional<int>); + + // Clears badge contents for an app (if existing) and notifies the delegate. + void ClearBadge(const extensions::ExtensionId&); + + void SetDelegate(BadgeManagerDelegate*); + + private: + BadgeManagerDelegate* delegate_ = nullptr; + + // Maps extension id to badge contents. + std::map<extensions::ExtensionId, base::Optional<int>> badged_apps_; + + DISALLOW_COPY_AND_ASSIGN(BadgeManager); +}; + +} // namespace badging + +#endif // CHROME_BROWSER_BADGING_BADGE_MANAGER_H_
diff --git a/chrome/browser/badging/badge_manager_delegate.h b/chrome/browser/badging/badge_manager_delegate.h new file mode 100644 index 0000000..32f19ee --- /dev/null +++ b/chrome/browser/badging/badge_manager_delegate.h
@@ -0,0 +1,30 @@ +// 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 CHROME_BROWSER_BADGING_BADGE_MANAGER_DELEGATE_H_ +#define CHROME_BROWSER_BADGING_BADGE_MANAGER_DELEGATE_H_ + +#include <string> + +#include "base/optional.h" + +namespace badging { + +// BadgeManagerDelegate is reponsible for dispatching badge events that should +// be handled and reflected in the UI. +class BadgeManagerDelegate { + public: + virtual ~BadgeManagerDelegate() {} + + // Called when an app's badge has changed. + virtual void OnBadgeSet(const std::string& app_id, + base::Optional<int> contents) = 0; + + // Called when a app's badge has been cleared. + virtual void OnBadgeCleared(const std::string& app_id) = 0; +}; + +} // namespace badging + +#endif // CHROME_BROWSER_BADGING_BADGE_MANAGER_DELEGATE_H_
diff --git a/chrome/browser/badging/badge_manager_factory.cc b/chrome/browser/badging/badge_manager_factory.cc new file mode 100644 index 0000000..526eade --- /dev/null +++ b/chrome/browser/badging/badge_manager_factory.cc
@@ -0,0 +1,45 @@ +// 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 "chrome/browser/badging/badge_manager_factory.h" + +#include <memory> + +#include "base/bind.h" +#include "base/memory/ptr_util.h" +#include "base/memory/singleton.h" +#include "chrome/browser/badging/badge_manager.h" +#include "chrome/browser/profiles/profile.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/prefs/pref_service.h" + +namespace badging { + +// static +BadgeManager* BadgeManagerFactory::GetForProfile(Profile* profile) { + return static_cast<badging::BadgeManager*>( + GetInstance()->GetServiceForBrowserContext(profile, true)); +} + +// static +BadgeManagerFactory* BadgeManagerFactory::GetInstance() { + return base::Singleton<BadgeManagerFactory>::get(); +} + +BadgeManagerFactory::BadgeManagerFactory() + : BrowserContextKeyedServiceFactory( + "BadgeManager", + BrowserContextDependencyManager::GetInstance()) {} + +BadgeManagerFactory::~BadgeManagerFactory() {} + +KeyedService* BadgeManagerFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + // We don't actually need to use the BrowserContext - we just use the + // BrowserContextKeyedFactory contract to to keep BadgeManagers separate + // across profiles. + return new BadgeManager(); +} + +} // namespace badging
diff --git a/chrome/browser/badging/badge_manager_factory.h b/chrome/browser/badging/badge_manager_factory.h new file mode 100644 index 0000000..a0ae2ea --- /dev/null +++ b/chrome/browser/badging/badge_manager_factory.h
@@ -0,0 +1,45 @@ +// 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 CHROME_BROWSER_BADGING_BADGE_MANAGER_FACTORY_H_ +#define CHROME_BROWSER_BADGING_BADGE_MANAGER_FACTORY_H_ + +#include "base/macros.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +namespace base { +template <typename T> +struct DefaultSingletonTraits; +} + +class Profile; + +namespace badging { + +class BadgeManager; + +// Singleton that provides access to Profile specific BadgeManagers. +class BadgeManagerFactory : public BrowserContextKeyedServiceFactory { + public: + static BadgeManager* GetForProfile(Profile* profile); + + // Returns the BadgeManagerFactory singleton. + static BadgeManagerFactory* GetInstance(); + + private: + friend struct base::DefaultSingletonTraits<BadgeManagerFactory>; + + BadgeManagerFactory(); + ~BadgeManagerFactory() override; + + // BrowserContextKeyedServiceFactory + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* profile) const override; + + DISALLOW_COPY_AND_ASSIGN(BadgeManagerFactory); +}; + +} // namespace badging + +#endif // CHROME_BROWSER_BADGING_BADGE_MANAGER_FACTORY_H_
diff --git a/chrome/browser/badging/badge_manager_unittest.cc b/chrome/browser/badging/badge_manager_unittest.cc new file mode 100644 index 0000000..d1a504f9b --- /dev/null +++ b/chrome/browser/badging/badge_manager_unittest.cc
@@ -0,0 +1,180 @@ +// 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 "chrome/browser/badging/badge_manager.h" + +#include <utility> +#include <vector> + +#include "base/optional.h" +#include "chrome/browser/badging/badge_manager_delegate.h" +#include "chrome/browser/badging/badge_manager_factory.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "extensions/common/extension.h" +#include "extensions/common/extension_builder.h" +#include "extensions/common/extension_id.h" +#include "testing/gtest/include/gtest/gtest.h" + +using badging::BadgeManager; +using badging::BadgeManagerDelegate; +using badging::BadgeManagerFactory; + +namespace { + +typedef std::pair<std::string, base::Optional<int>> SetBadgeAction; + +const int kBadgeContents = 1; + +const extensions::ExtensionId kExtensionId("1"); + +} // namespace + +namespace badging { + +// Testing delegate that records badge changes. +class TestBadgeManagerDelegate : public BadgeManagerDelegate { + public: + TestBadgeManagerDelegate() = default; + ~TestBadgeManagerDelegate() override = default; + + void OnBadgeSet(const std::string& app_id, + base::Optional<int> contents) override { + set_badges_.push_back(std::make_pair(app_id, contents)); + } + + void OnBadgeCleared(const std::string& app_id) override { + cleared_badges_.push_back(app_id); + } + + std::vector<std::string>& cleared_badges() { return cleared_badges_; } + std::vector<SetBadgeAction>& set_badges() { return set_badges_; } + + private: + std::vector<std::string> cleared_badges_; + std::vector<SetBadgeAction> set_badges_; +}; + +class BadgeManagerUnittest : public ::testing::Test { + public: + BadgeManagerUnittest() = default; + ~BadgeManagerUnittest() override = default; + + void SetUp() override { + profile_.reset(new TestingProfile()); + delegate_ = std::make_unique<TestBadgeManagerDelegate>(); + badge_manager_ = + BadgeManagerFactory::GetInstance()->GetForProfile(profile_.get()); + badge_manager_->SetDelegate(delegate_.get()); + } + + void TearDown() override { profile_.reset(); } + + TestBadgeManagerDelegate* delegate() const { return delegate_.get(); } + + BadgeManager* badge_manager() const { return badge_manager_; } + + private: + std::unique_ptr<TestBadgeManagerDelegate> delegate_; + BadgeManager* badge_manager_; + content::TestBrowserThreadBundle thread_bundle_; + std::unique_ptr<TestingProfile> profile_; + + DISALLOW_COPY_AND_ASSIGN(BadgeManagerUnittest); +}; + +TEST_F(BadgeManagerUnittest, SetFlagBadgeForApp) { + badge_manager()->UpdateBadge(kExtensionId, base::nullopt); + + EXPECT_EQ(1UL, delegate()->set_badges().size()); + EXPECT_EQ(kExtensionId, delegate()->set_badges().front().first); + EXPECT_EQ(base::nullopt, delegate()->set_badges().front().second); +} + +TEST_F(BadgeManagerUnittest, SetBadgeForApp) { + badge_manager()->UpdateBadge(kExtensionId, kBadgeContents); + + EXPECT_EQ(1UL, delegate()->set_badges().size()); + EXPECT_EQ(kExtensionId, delegate()->set_badges().front().first); + EXPECT_EQ(kBadgeContents, delegate()->set_badges().front().second); +} + +TEST_F(BadgeManagerUnittest, SetBadgeForAppWithNoBadgeChange) { + badge_manager()->UpdateBadge(kExtensionId, kBadgeContents); + badge_manager()->UpdateBadge(kExtensionId, kBadgeContents); + + EXPECT_EQ(1UL, delegate()->set_badges().size()); + EXPECT_EQ(kExtensionId, delegate()->set_badges().front().first); + EXPECT_EQ(kBadgeContents, delegate()->set_badges().front().second); +} + +TEST_F(BadgeManagerUnittest, SetBadgeForMultipleApps) { + const extensions::ExtensionId otherId("other"); + int otherContents = 2; + + badge_manager()->UpdateBadge(kExtensionId, kBadgeContents); + badge_manager()->UpdateBadge(otherId, otherContents); + + EXPECT_EQ(2UL, delegate()->set_badges().size()); + + EXPECT_EQ(kExtensionId, delegate()->set_badges()[0].first); + EXPECT_EQ(kBadgeContents, delegate()->set_badges()[0].second); + + EXPECT_EQ(otherId, delegate()->set_badges()[1].first); + EXPECT_EQ(otherContents, delegate()->set_badges()[1].second); +} + +TEST_F(BadgeManagerUnittest, SetBadgeForAppAfterClear) { + badge_manager()->UpdateBadge(kExtensionId, kBadgeContents); + badge_manager()->ClearBadge(kExtensionId); + badge_manager()->UpdateBadge(kExtensionId, kBadgeContents); + + EXPECT_EQ(2UL, delegate()->set_badges().size()); + + EXPECT_EQ(kExtensionId, delegate()->set_badges()[0].first); + EXPECT_EQ(kBadgeContents, delegate()->set_badges()[0].second); + + EXPECT_EQ(kExtensionId, delegate()->set_badges()[1].first); + EXPECT_EQ(kBadgeContents, delegate()->set_badges()[1].second); +} + +TEST_F(BadgeManagerUnittest, ClearBadgeForBadgedApp) { + badge_manager()->UpdateBadge(kExtensionId, kBadgeContents); + + badge_manager()->ClearBadge(kExtensionId); + + EXPECT_EQ(1UL, delegate()->cleared_badges().size()); + EXPECT_EQ(kExtensionId, delegate()->cleared_badges().front()); +} + +TEST_F(BadgeManagerUnittest, ClearBadgeForNonBadgedApp) { + badge_manager()->ClearBadge(kExtensionId); + EXPECT_EQ(0UL, delegate()->cleared_badges().size()); +} + +TEST_F(BadgeManagerUnittest, BadgingMultipleProfiles) { + std::unique_ptr<Profile> other_profile = std::make_unique<TestingProfile>(); + auto* other_badge_manager = + BadgeManagerFactory::GetInstance()->GetForProfile(other_profile.get()); + auto other_delegate = std::make_unique<TestBadgeManagerDelegate>(); + other_badge_manager->SetDelegate(other_delegate.get()); + + other_badge_manager->UpdateBadge(kExtensionId, base::nullopt); + other_badge_manager->UpdateBadge(kExtensionId, kBadgeContents); + other_badge_manager->UpdateBadge(kExtensionId, base::nullopt); + other_badge_manager->ClearBadge(kExtensionId); + + badge_manager()->ClearBadge(kExtensionId); + + EXPECT_EQ(3UL, other_delegate->set_badges().size()); + EXPECT_EQ(0UL, delegate()->set_badges().size()); + + EXPECT_EQ(1UL, other_delegate->cleared_badges().size()); + EXPECT_EQ(0UL, delegate()->cleared_badges().size()); + + EXPECT_EQ(kExtensionId, other_delegate->set_badges().back().first); + EXPECT_EQ(base::nullopt, other_delegate->set_badges().back().second); +} + +} // namespace badging
diff --git a/chrome/browser/badging/badge_service_impl.cc b/chrome/browser/badging/badge_service_impl.cc index b8c88c1..09431eb5 100644 --- a/chrome/browser/badging/badge_service_impl.cc +++ b/chrome/browser/badging/badge_service_impl.cc
@@ -4,21 +4,68 @@ #include "chrome/browser/badging/badge_service_impl.h" +#include <memory> +#include <string> +#include <utility> + +#include "base/logging.h" +#include "base/optional.h" +#include "base/strings/string_util.h" +#include "chrome/browser/badging/badge_manager.h" +#include "chrome/browser/badging/badge_manager_factory.h" +#include "chrome/browser/extensions/extension_util.h" +#include "chrome/browser/profiles/profile.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" +#include "extensions/common/extension.h" #include "mojo/public/cpp/bindings/strong_binding.h" -BadgeServiceImpl::BadgeServiceImpl() = default; +BadgeServiceImpl::BadgeServiceImpl(content::RenderFrameHost* render_frame_host, + content::BrowserContext* browser_context, + badging::BadgeManager* badge_manager) + : render_frame_host_(render_frame_host), + browser_context_(browser_context), + badge_manager_(badge_manager) {} BadgeServiceImpl::~BadgeServiceImpl() = default; // static -void BadgeServiceImpl::Create(blink::mojom::BadgeServiceRequest request) { - mojo::MakeStrongBinding(std::make_unique<BadgeServiceImpl>(), - std::move(request)); +void BadgeServiceImpl::Create(blink::mojom::BadgeServiceRequest request, + content::RenderFrameHost* render_frame_host) { + auto* browser_context = + content::WebContents::FromRenderFrameHost(render_frame_host) + ->GetBrowserContext(); + auto* badge_manager = + badging::BadgeManagerFactory::GetInstance()->GetForProfile( + Profile::FromBrowserContext(browser_context)); + mojo::MakeStrongBinding( + std::make_unique<BadgeServiceImpl>(render_frame_host, browser_context, + badge_manager), + std::move(request)); } void BadgeServiceImpl::SetBadge() { - NOTIMPLEMENTED(); + const extensions::Extension* extension = ExtensionFromLastUrl(); + + if (!extension) + return; + + badge_manager_->UpdateBadge(extension->id(), base::nullopt); } void BadgeServiceImpl::ClearBadge() { - NOTIMPLEMENTED(); + const extensions::Extension* extension = ExtensionFromLastUrl(); + + if (!extension) + return; + + badge_manager_->ClearBadge(extension->id()); +} + +// private +const extensions::Extension* BadgeServiceImpl::ExtensionFromLastUrl() { + DCHECK(render_frame_host_); + DCHECK(browser_context_); + + return extensions::util::GetInstalledPwaForUrl( + browser_context_, render_frame_host_->GetLastCommittedURL()); }
diff --git a/chrome/browser/badging/badge_service_impl.h b/chrome/browser/badging/badge_service_impl.h index 3770305..37ac367 100644 --- a/chrome/browser/badging/badge_service_impl.h +++ b/chrome/browser/badging/badge_service_impl.h
@@ -5,20 +5,49 @@ #ifndef CHROME_BROWSER_BADGING_BADGE_SERVICE_IMPL_H_ #define CHROME_BROWSER_BADGING_BADGE_SERVICE_IMPL_H_ +#include <memory> +#include <string> + #include "base/optional.h" +#include "extensions/common/extension_id.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "third_party/blink/public/platform/modules/badging/badging.mojom.h" +namespace badging { +class BadgeManager; +} + +namespace content { +class RenderFrameHost; +class BrowserContext; +} // namespace content + +namespace extensions { +class Extension; +} + +// Desktop implementation of the BadgeService mojo service. class BadgeServiceImpl : public blink::mojom::BadgeService { public: - BadgeServiceImpl(); + explicit BadgeServiceImpl(content::RenderFrameHost*, + content::BrowserContext*, + badging::BadgeManager*); ~BadgeServiceImpl() override; - static void Create(mojo::InterfaceRequest<BadgeService> request); + static void Create(blink::mojom::BadgeServiceRequest request, + content::RenderFrameHost* render_frame_host); // blink::mojom::BadgeService overrides. + // TODO(crbug.com/719176): Support non-flag badges. void SetBadge() override; void ClearBadge() override; + + private: + const extensions::Extension* ExtensionFromLastUrl(); + + content::RenderFrameHost* render_frame_host_; + content::BrowserContext* browser_context_; + badging::BadgeManager* badge_manager_; }; #endif // CHROME_BROWSER_BADGING_BADGE_SERVICE_IMPL_H_
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index cd59664c..96cc832 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -220,6 +220,7 @@ <include name="IDR_APP_MANAGEMENT_APP_JS" file="resources\app_management\app.js" type="BINDATA" /> <include name="IDR_APP_MANAGEMENT_BROWSER_PROXY_HTML" file="resources\app_management\browser_proxy.html" type="BINDATA" /> <include name="IDR_APP_MANAGEMENT_BROWSER_PROXY_JS" file="resources\app_management\browser_proxy.js" type="BINDATA" /> + <include name="IDR_APP_MANAGEMENT_FAKE_PAGE_HANDLER_JS" file="resources\app_management\fake_page_handler.js" type="BINDATA" /> <include name="IDR_APP_MANAGEMENT_INDEX_HTML" file="resources\app_management\index.html" type="BINDATA" /> <include name="IDR_APP_MANAGEMENT_MAIN_VIEW_HTML" file="resources\app_management\main_view.html" type="BINDATA" /> <include name="IDR_APP_MANAGEMENT_MAIN_VIEW_JS" file="resources\app_management\main_view.js" type="BINDATA" />
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index cbf7170..6ca2b2b 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -252,6 +252,7 @@ #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/client_certificate_delegate.h" #include "content/public/browser/file_url_loader.h" +#include "content/public/browser/gpu_data_manager.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/navigation_throttle.h" #include "content/public/browser/overlay_window.h" @@ -309,6 +310,7 @@ #include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/mojom/connector.mojom.h" #include "services/service_manager/sandbox/sandbox_type.h" +#include "services/viz/public/interfaces/constants.mojom.h" #include "storage/browser/fileapi/external_mount_points.h" #include "third_party/blink/public/platform/modules/installedapp/installed_app_provider.mojom.h" #include "third_party/blink/public/platform/modules/webshare/webshare.mojom.h" @@ -1298,7 +1300,7 @@ Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext()); host->AddFilter(new ChromeRenderMessageFilter(id, profile)); #if BUILDFLAG(ENABLE_EXTENSIONS) - host->AddFilter(new cast::CastTransportHostFilter(profile)); + host->AddFilter(new cast::CastTransportHostFilter()); #endif #if BUILDFLAG(ENABLE_PRINTING) host->AddFilter(new printing::PrintingMessageFilter(id, profile)); @@ -2208,6 +2210,8 @@ command_line->AppendSwitchASCII(switches::kMashServiceName, identity.name()); } + if (identity.name() == viz::mojom::kVizServiceName) + content::GpuDataManager::GetInstance()->AppendGpuCommandLine(command_line); // TODO(crbug.com/906954): whitelist flags to copy. if (copy_switches) { for (const auto& sw : base::CommandLine::ForCurrentProcess()->GetSwitches()) @@ -4366,7 +4370,7 @@ #endif #if !defined(OS_ANDROID) - frame_interfaces_->AddInterface( + frame_interfaces_parameterized_->AddInterface( base::BindRepeating(&BadgeServiceImpl::Create)); #endif @@ -4730,9 +4734,12 @@ std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>> interceptors; #if BUILDFLAG(ENABLE_OFFLINE_PAGES) - interceptors.push_back( - std::make_unique<offline_pages::OfflinePageURLLoaderRequestInterceptor>( - navigation_ui_data, frame_tree_node_id)); + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { + // NetworkService cases only. + interceptors.push_back( + std::make_unique<offline_pages::OfflinePageURLLoaderRequestInterceptor>( + navigation_ui_data, frame_tree_node_id)); + } #endif return interceptors; }
diff --git a/chrome/browser/chrome_navigation_browsertest.cc b/chrome/browser/chrome_navigation_browsertest.cc index 55b4dec..6afd220 100644 --- a/chrome/browser/chrome_navigation_browsertest.cc +++ b/chrome/browser/chrome_navigation_browsertest.cc
@@ -31,6 +31,7 @@ #include "content/public/browser/reload_type.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" @@ -57,6 +58,7 @@ // tests don't time out. command_line->AppendSwitch(switches::kDisableRendererBackgrounding); + embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data"); ASSERT_TRUE(embedded_test_server()->Start()); } @@ -1026,6 +1028,55 @@ } } +// Test which verifies that a noopener link/window.open() properly focus the +// newly opened tab. See https://crbug.com/912348. +IN_PROC_BROWSER_TEST_F(ChromeNavigationBrowserTest, + NoopenerCorrectlyFocusesNewTab) { + content::WebContents* main_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + // Navigate to a test page with links. + { + content::TestNavigationObserver observer(main_contents); + ui_test_utils::NavigateToURL( + browser(), + embedded_test_server()->GetURL("/click-noreferrer-links.html")); + observer.Wait(); + EXPECT_TRUE(observer.last_navigation_succeeded()); + } + + // Click a link with noopener that navigates in a new window. + content::WebContents* link_web_contents = nullptr; + { + ui_test_utils::WindowedTabAddedNotificationObserver tab_added_observer( + content::NotificationService::AllSources()); + EXPECT_TRUE( + content::ExecJs(main_contents, "clickSameSiteNoOpenerTargetedLink();")); + tab_added_observer.Wait(); + link_web_contents = tab_added_observer.GetTab(); + } + + EXPECT_NE(main_contents, link_web_contents); + EXPECT_TRUE(link_web_contents->GetRenderWidgetHostView()->HasFocus()); + + // Execute window.open() with noopener. + content::WebContents* open_web_contents = nullptr; + { + ui_test_utils::WindowedTabAddedNotificationObserver tab_added_observer( + content::NotificationService::AllSources()); + EXPECT_TRUE(content::ExecJs( + main_contents, content::JsReplace("window.open($1, 'bar', 'noopener');", + embedded_test_server()->GetURL( + "a.com", "/title1.html")))); + tab_added_observer.Wait(); + open_web_contents = tab_added_observer.GetTab(); + } + + EXPECT_NE(main_contents, open_web_contents); + EXPECT_NE(link_web_contents, open_web_contents); + EXPECT_TRUE(open_web_contents->GetRenderWidgetHostView()->HasFocus()); +} + // TODO(csharrison): These tests should become tentative WPT, once the feature // is enabled by default. using NavigationConsumingTest = ChromeNavigationBrowserTest;
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 33248ee..f36ae5d 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -166,6 +166,7 @@ "//components/ukm/content", "//components/user_manager", "//components/viz/host", + "//components/webdata/common:common", "//google_apis/drive", "//services/identity/public/cpp", "//services/metrics/public/cpp:ukm_builders", @@ -292,8 +293,8 @@ "accessibility/select_to_speak_event_handler_delegate.h", "accessibility/spoken_feedback_event_rewriter_delegate.cc", "accessibility/spoken_feedback_event_rewriter_delegate.h", - "accessibility/switch_access_event_handler.cc", - "accessibility/switch_access_event_handler.h", + "accessibility/switch_access_event_handler_delegate.cc", + "accessibility/switch_access_event_handler_delegate.h", "accessibility/switch_access_panel.cc", "accessibility/switch_access_panel.h", "account_manager/account_manager_migrator.cc",
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc index db6ed30a..85b9cfa7 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc +++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -38,7 +38,7 @@ #include "chrome/browser/chromeos/accessibility/dictation_chromeos.h" #include "chrome/browser/chromeos/accessibility/magnification_manager.h" #include "chrome/browser/chromeos/accessibility/select_to_speak_event_handler_delegate.h" -#include "chrome/browser/chromeos/accessibility/switch_access_event_handler.h" +#include "chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" @@ -354,6 +354,7 @@ prefs->GetBoolean(ash::prefs::kAccessibilityLargeCursorEnabled) || prefs->GetBoolean(ash::prefs::kAccessibilitySpokenFeedbackEnabled) || prefs->GetBoolean(ash::prefs::kAccessibilitySelectToSpeakEnabled) || + prefs->GetBoolean(ash::prefs::kAccessibilitySwitchAccessEnabled) || prefs->GetBoolean(ash::prefs::kAccessibilityHighContrastEnabled) || prefs->GetBoolean(ash::prefs::kAccessibilityAutoclickEnabled) || prefs->GetBoolean(ash::prefs::kShouldAlwaysShowAccessibilityMenu) || @@ -889,22 +890,30 @@ return; } EnableSwitchAccessAfterChromeVoxMetric(false); + switch_access_loader_->SetProfile(profile_, base::RepeatingClosure()); } if (switch_access_enabled_ == enabled) return; switch_access_enabled_ = enabled; + AccessibilityStatusEventDetails details(ACCESSIBILITY_TOGGLE_SWITCH_ACCESS, + enabled); + NotifyAccessibilityStatusChanged(details); + if (enabled) { + // Construct a delegate to connect Switch Access and its EventHandler in + // ash. Do this before loading Switch Access so the keys_to_capture will + // be properly set. + switch_access_event_handler_delegate_ = + std::make_unique<SwitchAccessEventHandlerDelegate>(); switch_access_loader_->Load( profile_, base::BindRepeating(&AccessibilityManager::PostLoadSwitchAccess, weak_ptr_factory_.GetWeakPtr())); - switch_access_event_handler_.reset( - new chromeos::SwitchAccessEventHandler()); } else { switch_access_loader_->Unload(); - switch_access_event_handler_.reset(nullptr); + switch_access_event_handler_delegate_.reset(nullptr); } } @@ -1418,11 +1427,6 @@ extension_registry_observer_.Add(registry); } -void AccessibilityManager::SetSwitchAccessKeys(const std::set<int>& key_codes) { - if (switch_access_enabled_) - switch_access_event_handler_->SetKeysToCapture(key_codes); -} - bool AccessibilityManager::ToggleDictation() { if (!profile_) return false;
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h index 2d73455..22ddd6b 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_manager.h +++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -33,6 +33,7 @@ class Browser; class Profile; +class SwitchAccessEventHandlerDelegate; namespace gfx { class Rect; @@ -43,7 +44,6 @@ class AccessibilityExtensionLoader; class DictationChromeos; class SelectToSpeakEventHandlerDelegate; -class SwitchAccessEventHandler; enum AccessibilityNotificationType { ACCESSIBILITY_MANAGER_SHUTDOWN, @@ -53,6 +53,7 @@ ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFIER, ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK, ACCESSIBILITY_TOGGLE_SELECT_TO_SPEAK, + ACCESSIBILITY_TOGGLE_SWITCH_ACCESS, ACCESSIBILITY_TOGGLE_VIRTUAL_KEYBOARD, ACCESSIBILITY_TOGGLE_MONO_AUDIO, ACCESSIBILITY_TOGGLE_CARET_HIGHLIGHT, @@ -272,9 +273,6 @@ return keyboard_listener_extension_id_; } - // Set the keys to be captured by Switch Access. - void SetSwitchAccessKeys(const std::set<int>& key_codes); - // Starts or stops dictation (type what you speak). bool ToggleDictation(); @@ -441,8 +439,8 @@ std::unique_ptr<AccessibilityExtensionLoader> switch_access_loader_; - std::unique_ptr<chromeos::SwitchAccessEventHandler> - switch_access_event_handler_; + std::unique_ptr<SwitchAccessEventHandlerDelegate> + switch_access_event_handler_delegate_; // Ash's mojom::AccessibilityController used to request Ash's a11y feature. ash::mojom::AccessibilityControllerPtr accessibility_controller_;
diff --git a/chrome/browser/chromeos/accessibility/switch_access_browsertest.cc b/chrome/browser/chromeos/accessibility/switch_access_browsertest.cc index e86c9a1f..1753a42 100644 --- a/chrome/browser/chromeos/accessibility/switch_access_browsertest.cc +++ b/chrome/browser/chromeos/accessibility/switch_access_browsertest.cc
@@ -2,17 +2,33 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ash/public/interfaces/accessibility_controller.mojom.h" #include "base/command_line.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/ui/browser.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/interactive_test_utils.h" #include "chromeos/chromeos_switches.h" +#include "content/public/common/service_manager_connection.h" #include "content/public/test/browser_test_utils.h" +#include "services/service_manager/public/cpp/connector.h" #include "ui/accessibility/accessibility_switches.h" namespace chromeos { +namespace { + +ash::mojom::AccessibilityControllerPtr GetAccessibilityController() { + // Connect to the accessibility mojo interface in ash. + ash::mojom::AccessibilityControllerPtr controller; + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->BindInterface(ash::mojom::kServiceName, &controller); + return controller; +} + +} // namespace + class SwitchAccessTest : public InProcessBrowserTest { public: void SendVirtualKeyPress(ui::KeyboardCode key) { @@ -20,14 +36,13 @@ nullptr, key, false, false, false, false))); } - void EnableSwitchAccess(const std::set<int>& key_codes = {'1', '2', '3', - '4'}) { + void EnableSwitchAccess(const std::vector<int>& key_codes) { base::CommandLine::ForCurrentProcess()->AppendSwitch( ::switches::kEnableExperimentalAccessibilitySwitchAccess); AccessibilityManager* manager = AccessibilityManager::Get(); manager->SetSwitchAccessEnabled(true); - manager->SetSwitchAccessKeys(key_codes); + GetAccessibilityController()->SetSwitchAccessKeysToCapture(key_codes); EXPECT_TRUE(manager->IsSwitchAccessEnabled()); }
diff --git a/chrome/browser/chromeos/accessibility/switch_access_event_handler.cc b/chrome/browser/chromeos/accessibility/switch_access_event_handler.cc deleted file mode 100644 index db2bf4d3..0000000 --- a/chrome/browser/chromeos/accessibility/switch_access_event_handler.cc +++ /dev/null
@@ -1,63 +0,0 @@ -// Copyright 2017 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 "chrome/browser/chromeos/accessibility/switch_access_event_handler.h" - -#include "ash/shell.h" -#include "base/logging.h" -#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" -#include "chrome/browser/chromeos/accessibility/event_handler_common.h" -#include "chrome/common/extensions/extension_constants.h" -#include "extensions/browser/extension_host.h" -#include "ui/events/event.h" - -namespace chromeos { - -SwitchAccessEventHandler::SwitchAccessEventHandler() { - if (ash::Shell::HasInstance()) - ash::Shell::Get()->AddPreTargetHandler(this); -} - -SwitchAccessEventHandler::~SwitchAccessEventHandler() { - if (ash::Shell::HasInstance()) - ash::Shell::Get()->RemovePreTargetHandler(this); -} - -void SwitchAccessEventHandler::SetKeysToCapture( - const std::set<int>& key_codes) { - captured_keys_ = key_codes; -} - -void SwitchAccessEventHandler::OnKeyEvent(ui::KeyEvent* event) { - DCHECK(event); - - if (!event->HasNativeEvent()) - return; - - ui::KeyboardCode key_code = event->key_code(); - if (captured_keys_.find(key_code) != captured_keys_.end()) { - CancelEvent(event); - DispatchKeyEventToSwitchAccess(*event); - } -} - -void SwitchAccessEventHandler::CancelEvent(ui::Event* event) { - DCHECK(event); - if (event->cancelable()) { - event->SetHandled(); - event->StopPropagation(); - } -} - -void SwitchAccessEventHandler::DispatchKeyEventToSwitchAccess( - const ui::KeyEvent& event) { - extensions::ExtensionHost* host = - GetAccessibilityExtensionHost(extension_misc::kSwitchAccessExtensionId); - if (!host) - return; - - ForwardKeyToExtension(event, host); -} - -} // namespace chromeos
diff --git a/chrome/browser/chromeos/accessibility/switch_access_event_handler.h b/chrome/browser/chromeos/accessibility/switch_access_event_handler.h deleted file mode 100644 index e52af0cc..0000000 --- a/chrome/browser/chromeos/accessibility/switch_access_event_handler.h +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2017 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 CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_SWITCH_ACCESS_EVENT_HANDLER_H_ -#define CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_SWITCH_ACCESS_EVENT_HANDLER_H_ - -#include <set> - -#include "base/macros.h" -#include "ui/events/event_handler.h" - -namespace chromeos { - -// When Switch Access is enabled, intercepts a few keys before the rest of the -// OS has a chance to handle them, as a method for controlling the entire OS -// with a small number of switches. The key events do not propagate to the rest -// of the system. -// -// This class just intercepts the keys and forwards them to the component -// extension. -class SwitchAccessEventHandler : public ui::EventHandler { - public: - SwitchAccessEventHandler(); - ~SwitchAccessEventHandler() override; - - void SetKeysToCapture(const std::set<int>& key_codes); - - private: - // EventHandler: - void OnKeyEvent(ui::KeyEvent* event) override; - - void CancelEvent(ui::Event* event); - void DispatchKeyEventToSwitchAccess(const ui::KeyEvent& event); - - std::set<int> captured_keys_; - - DISALLOW_COPY_AND_ASSIGN(SwitchAccessEventHandler); -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_SWITCH_ACCESS_EVENT_HANDLER_H_
diff --git a/chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.cc b/chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.cc new file mode 100644 index 0000000..8ff054a --- /dev/null +++ b/chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.cc
@@ -0,0 +1,46 @@ +// 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 "chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.h" + +#include "ash/public/interfaces/constants.mojom.h" +#include "chrome/browser/chromeos/accessibility/event_handler_common.h" +#include "chrome/common/extensions/extension_constants.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/common/service_manager_connection.h" +#include "extensions/browser/extension_host.h" +#include "services/service_manager/public/cpp/connector.h" +#include "ui/events/event.h" + +SwitchAccessEventHandlerDelegate::SwitchAccessEventHandlerDelegate() + : binding_(this) { + // Connect to ash's AccessibilityController interface. + ash::mojom::AccessibilityControllerPtr accessibility_controller; + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->BindInterface(ash::mojom::kServiceName, &accessibility_controller); + + // Set this object as the SwitchAccessEventHandlerDelegate. + ash::mojom::SwitchAccessEventHandlerDelegatePtr ptr; + binding_.Bind(mojo::MakeRequest(&ptr)); + accessibility_controller->SetSwitchAccessEventHandlerDelegate(std::move(ptr)); +} + +SwitchAccessEventHandlerDelegate::~SwitchAccessEventHandlerDelegate() = default; + +void SwitchAccessEventHandlerDelegate::DispatchKeyEvent( + std::unique_ptr<ui::Event> event) { + // We can only call the Switch Access extension on the UI thread, make sure we + // don't ever try to run this code on some other thread. + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK(event->IsKeyEvent()); + + extensions::ExtensionHost* host = chromeos::GetAccessibilityExtensionHost( + extension_misc::kSwitchAccessExtensionId); + if (!host) + return; + + const ui::KeyEvent* key_event = event->AsKeyEvent(); + chromeos::ForwardKeyToExtension(*key_event, host); +}
diff --git a/chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.h b/chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.h new file mode 100644 index 0000000..a2141ae --- /dev/null +++ b/chrome/browser/chromeos/accessibility/switch_access_event_handler_delegate.h
@@ -0,0 +1,32 @@ +// 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 CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_SWITCH_ACCESS_EVENT_HANDLER_DELEGATE_H_ +#define CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_SWITCH_ACCESS_EVENT_HANDLER_DELEGATE_H_ + +#include "ash/public/interfaces/accessibility_controller.mojom.h" +#include "base/macros.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "ui/events/event.h" + +// SwitchAccessEventHandlerDelegate receives mouse and key events and forwards +// them to the Switch Access extension in Chrome. The SwitchAccessEventHandler +// in the Ash process handles events and passes them to this delegate via a Mojo +// interface defined in accessibility_controller.mojom. +class SwitchAccessEventHandlerDelegate + : public ash::mojom::SwitchAccessEventHandlerDelegate { + public: + SwitchAccessEventHandlerDelegate(); + ~SwitchAccessEventHandlerDelegate() override; + + private: + // ash::mojom::SwitchAccessEventHandlerDelegate: + void DispatchKeyEvent(std::unique_ptr<ui::Event> event) override; + + mojo::Binding<ash::mojom::SwitchAccessEventHandlerDelegate> binding_; + + DISALLOW_COPY_AND_ASSIGN(SwitchAccessEventHandlerDelegate); +}; + +#endif // CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_SWITCH_ACCESS_EVENT_HANDLER_DELEGATE_H_
diff --git a/chrome/browser/chromeos/account_manager/account_manager_migrator.cc b/chrome/browser/chromeos/account_manager/account_manager_migrator.cc index d664033..d60cc03 100644 --- a/chrome/browser/chromeos/account_manager/account_manager_migrator.cc +++ b/chrome/browser/chromeos/account_manager/account_manager_migrator.cc
@@ -4,14 +4,196 @@ #include "chrome/browser/chromeos/account_manager/account_manager_migrator.h" +#include <map> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "base/bind.h" #include "base/logging.h" +#include "base/memory/scoped_refptr.h" #include "base/no_destructor.h" +#include "base/sequence_checker.h" +#include "base/stl_util.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/account_mapper_util.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/account_reconcilor_factory.h" +#include "chrome/browser/signin/account_tracker_service_factory.h" +#include "chrome/browser/web_data_service_factory.h" +#include "chromeos/account_manager/account_manager.h" +#include "chromeos/account_manager/account_manager_factory.h" #include "chromeos/chromeos_switches.h" +#include "components/account_id/account_id.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/signin/core/browser/account_reconcilor.h" +#include "components/signin/core/browser/account_tracker_service.h" +#include "components/signin/core/browser/webdata/token_web_data.h" +#include "components/webdata/common/web_data_service_consumer.h" namespace chromeos { -AccountManagerMigrator::AccountManagerMigrator() = default; +namespace { + +AccountManager::AccountKey GetDeviceAccount(const Profile* profile) { + const user_manager::User* user = + ProfileHelper::Get()->GetUserByProfile(profile); + const AccountId& account_id = user->GetAccountId(); + switch (account_id.GetAccountType()) { + case AccountType::ACTIVE_DIRECTORY: + return AccountManager::AccountKey{ + account_id.GetObjGuid(), + account_manager::AccountType::ACCOUNT_TYPE_ACTIVE_DIRECTORY}; + case AccountType::GOOGLE: + return AccountManager::AccountKey{ + account_id.GetGaiaId(), + account_manager::AccountType::ACCOUNT_TYPE_GAIA}; + case AccountType::UNKNOWN: + NOTREACHED(); + return AccountManager::AccountKey{ + std::string(), + account_manager::AccountType::ACCOUNT_TYPE_UNSPECIFIED}; + } +} + +std::string RemoveAccountIdPrefix(const std::string& prefixed_account_id) { + return prefixed_account_id.substr(10 /* length of "AccountId-" */); +} + +class DeviceAccountMigration : public AccountMigrationRunner::Step, + public WebDataServiceConsumer { + public: + DeviceAccountMigration(AccountManager::AccountKey device_account, + AccountManager* account_manager, + AccountTrackerService* account_tracker_service, + scoped_refptr<TokenWebData> token_web_data) + : AccountMigrationRunner::Step("DeviceAccountMigration"), + account_manager_(account_manager), + account_mapper_util_(account_tracker_service), + token_web_data_(token_web_data), + device_account_(device_account), + weak_factory_(this) {} + ~DeviceAccountMigration() override = default; + + void Run(base::OnceCallback<void(bool)> callback) override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + callback_ = std::move(callback); + + account_manager_->GetAccounts(base::BindOnce( + &DeviceAccountMigration::OnGetAccounts, weak_factory_.GetWeakPtr())); + } + + private: + // Callback for |AccountManager::GetAccounts|. Checks the list of accounts in + // Account Manager and early exists if the Device Account has already been + // migrated. + void OnGetAccounts(std::vector<AccountManager::AccountKey> accounts) { + if (base::ContainsValue(accounts, device_account_)) { + FinishWithSuccess(); + return; + } + + switch (device_account_.account_type) { + case account_manager::AccountType::ACCOUNT_TYPE_ACTIVE_DIRECTORY: + MigrateActiveDirectoryAccount(); + break; + case account_manager::AccountType::ACCOUNT_TYPE_GAIA: + MigrateGaiaAccount(); + break; + case account_manager::AccountType::ACCOUNT_TYPE_UNSPECIFIED: + NOTREACHED(); + break; + } + } + + void MigrateActiveDirectoryAccount() { + // TODO(sinhak): Migrate Active Directory account. + FinishWithSuccess(); + } + + void MigrateGaiaAccount() { token_web_data_->GetAllTokens(this); } + + // WebDataServiceConsumer override. + void OnWebDataServiceRequestDone( + WebDataServiceBase::Handle handle, + std::unique_ptr<WDTypedResult> result) override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (!result) { + LOG(ERROR) << "Could not load the token database. Aborting."; + FinishWithFailure(); + return; + } + + DCHECK(result->GetType() == TOKEN_RESULT); + const WDResult<TokenResult>* token_result = + static_cast<const WDResult<TokenResult>*>(result.get()); + + const std::map<std::string, std::string>& token_map = + token_result->GetValue().tokens; + + bool is_success = false; + for (auto it = token_map.begin(); it != token_map.end(); ++it) { + std::string account_id = RemoveAccountIdPrefix(it->first); + if (device_account_ != + account_mapper_util_.OAuthAccountIdToAccountKey(account_id)) { + continue; + } + + account_manager_->UpsertToken(device_account_, it->second /* token */); + is_success = true; + break; + } + + if (is_success) { + DVLOG(1) << "Device Account migrated."; + FinishWithSuccess(); + } else { + LOG(ERROR) << "Could not find a refresh token for the Device Account."; + FinishWithFailure(); + } + } + + void FinishWithSuccess() { + DCHECK(callback_); + std::move(callback_).Run(true); + } + + void FinishWithFailure() { + DCHECK(callback_); + std::move(callback_).Run(false); + } + + // A non-owning pointer to |AccountManager|. + AccountManager* const account_manager_; + + // For translating between OAuth account ids and + // |AccountManager::AccountKey|. + AccountMapperUtil account_mapper_util_; + + // Current storage of LSTs. + scoped_refptr<TokenWebData> token_web_data_; + + // Device Account on Chrome OS. + const AccountManager::AccountKey device_account_; + + // Callback to invoke at the end of this |Step|, with the final result of the + // operation. + base::OnceCallback<void(bool)> callback_; + + SEQUENCE_CHECKER(sequence_checker_); + + base::WeakPtrFactory<DeviceAccountMigration> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(DeviceAccountMigration); +}; + +} // namespace + +AccountManagerMigrator::AccountManagerMigrator(Profile* profile) + : profile_(profile), weak_factory_(this) {} AccountManagerMigrator::~AccountManagerMigrator() = default; @@ -21,13 +203,51 @@ if (!chromeos::switches::IsAccountManagerEnabled()) return; - // TODO(sinhak): Migrate Device Account. + chromeos::AccountManagerFactory* factory = + g_browser_process->platform_part()->GetAccountManagerFactory(); + chromeos::AccountManager* account_manager = + factory->GetAccountManager(profile_->GetPath().value()); + + AccountTrackerService* account_tracker_service = + AccountTrackerServiceFactory::GetForProfile(profile_); + + scoped_refptr<TokenWebData> token_web_data = + WebDataServiceFactory::GetTokenWebDataForProfile( + profile_, ServiceAccessType::EXPLICIT_ACCESS); + + migration_runner_.AddStep(std::make_unique<DeviceAccountMigration>( + GetDeviceAccount(profile_), account_manager, account_tracker_service, + token_web_data)); + // TODO(sinhak): Migrate Secondary Accounts in Chrome content area. // TODO(sinhak): Migrate Secondary Accounts in ARC. // TODO(sinhak): Store success state in Preferences. - // TODO(sinhak): Gather UMA stats. // TODO(sinhak): Verify Device Account LST state. - // TODO(sinhak): Enable account reconciliation. + + migration_runner_.Run( + base::BindOnce(&AccountManagerMigrator::OnMigrationRunComplete, + weak_factory_.GetWeakPtr())); +} + +AccountMigrationRunner::Status AccountManagerMigrator::GetStatus() const { + return migration_runner_.GetStatus(); +} + +void AccountManagerMigrator::OnMigrationRunComplete( + const AccountMigrationRunner::MigrationResult& result) { + DCHECK_NE(AccountMigrationRunner::Status::kNotStarted, + migration_runner_.GetStatus()); + DCHECK_NE(AccountMigrationRunner::Status::kRunning, + migration_runner_.GetStatus()); + // TODO(sinhak): Gather UMA stats. + + // Migration could have finished with a failure but we need to start account + // reconciliation anyways. This may cause us to lose Chrome content area + // Secondary Accounts but if we do not enable reconciliation, users will not + // be able to add any account to Chrome content area which is a much worse + // experience than losing Chrome content area Secondary Accounts. + AccountReconcilorFactory::GetForProfile(profile_)->Initialize( + true /* start_reconcile_if_tokens_available */); } // static @@ -46,13 +266,21 @@ AccountManagerMigratorFactory::AccountManagerMigratorFactory() : BrowserContextKeyedServiceFactory( "AccountManagerMigrator", - BrowserContextDependencyManager::GetInstance()) {} + BrowserContextDependencyManager::GetInstance()) { + // Stores the LSTs, that need to be copied over to |AccountManager|. + DependsOn(WebDataServiceFactory::GetInstance()); + // For translating between account identifiers. + DependsOn(AccountTrackerServiceFactory::GetInstance()); + // Account reconciliation is paused for the duration of migration and needs to + // be re-enabled once migration is done. + DependsOn(AccountReconcilorFactory::GetInstance()); +} AccountManagerMigratorFactory::~AccountManagerMigratorFactory() = default; KeyedService* AccountManagerMigratorFactory::BuildServiceInstanceFor( content::BrowserContext* context) const { - return new AccountManagerMigrator(); + return new AccountManagerMigrator(Profile::FromBrowserContext(context)); } } // namespace chromeos
diff --git a/chrome/browser/chromeos/account_manager/account_manager_migrator.h b/chrome/browser/chromeos/account_manager/account_manager_migrator.h index bd12609..a33e24c 100644 --- a/chrome/browser/chromeos/account_manager/account_manager_migrator.h +++ b/chrome/browser/chromeos/account_manager/account_manager_migrator.h
@@ -6,9 +6,13 @@ #define CHROME_BROWSER_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MANAGER_MIGRATOR_H_ #include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/chromeos/account_manager/account_migration_runner.h" #include "components/keyed_service/content/browser_context_keyed_service_factory.h" #include "components/keyed_service/core/keyed_service.h" +class Profile; + namespace base { template <typename T> class NoDestructor; @@ -18,13 +22,26 @@ class AccountManagerMigrator : public KeyedService { public: - AccountManagerMigrator(); + explicit AccountManagerMigrator(Profile* profile); ~AccountManagerMigrator() override; // Starts migrating accounts to Chrome OS Account Manager. void Start(); + // Gets the current status of migration. + AccountMigrationRunner::Status GetStatus() const; + private: + void OnMigrationRunComplete( + const AccountMigrationRunner::MigrationResult& result); + + // A non-owning pointer to |Profile|. + Profile* const profile_; + + // Used for running migration steps. + chromeos::AccountMigrationRunner migration_runner_; + + base::WeakPtrFactory<AccountManagerMigrator> weak_factory_; DISALLOW_COPY_AND_ASSIGN(AccountManagerMigrator); };
diff --git a/chrome/browser/chromeos/arc/auth/arc_auth_service.cc b/chrome/browser/chromeos/arc/auth/arc_auth_service.cc index 1a44e74b..da95578c 100644 --- a/chrome/browser/chromeos/arc/auth/arc_auth_service.cc +++ b/chrome/browser/chromeos/arc/auth/arc_auth_service.cc
@@ -461,6 +461,20 @@ if (!arc::IsArcProvisioned(profile_)) return; + // We may have received |OnTokenUpserted| for a variety of cases where a valid + // Gaia LST is not available for the account: The account could have just been + // migrated to Account Manager with a dummy initial token, the LST update + // could be an update to mark the LST as invalid etc. In all of these cases, + // we should ignore the notification. If and when Account Manager gets updated + // with a valid token, we would receive another notification and we can + // process the account update then. See |AccountManager::IsTokenAvailable| for + // details. + if (!account_manager_->IsTokenAvailable(account_key)) { + VLOG(1) << "Ignoring account update due to lack of a valid token: " + << account_key; + return; + } + auto* instance = ARC_GET_INSTANCE_FOR_METHOD(arc_bridge_service_->auth(), OnAccountUpdated); if (!instance) @@ -482,6 +496,9 @@ void ArcAuthService::OnAccountRemoved(const AccountInfo& account_info) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!chromeos::switches::IsAccountManagerEnabled()) + return; + DCHECK(!account_info.gaia.empty()); DCHECK(!IsPrimaryAccount(chromeos::AccountManager::AccountKey{ account_info.gaia /* id */, chromeos::account_manager::AccountType::
diff --git a/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc b/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc index 6cb9414..4a9458e 100644 --- a/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc +++ b/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc
@@ -39,6 +39,7 @@ #include "chrome/test/base/testing_profile.h" #include "chromeos/account_manager/account_manager.h" #include "chromeos/account_manager/account_manager_factory.h" +#include "chromeos/chromeos_switches.h" #include "chromeos/cryptohome/cryptohome_parameters.h" #include "components/account_id/account_id.h" #include "components/arc/arc_bridge_service.h" @@ -71,6 +72,7 @@ constexpr char kFakeGaiaId[] = "1234567890"; constexpr char kSecondaryAccountEmail[] = "email.111@gmail.com"; constexpr char kFakeAuthCode[] = "fake-auth-code"; +constexpr char kFakeToken[] = "fake-token"; std::string GetFakeAuthTokenResponse() { return base::StringPrintf(R"({ "token" : "%s"})", kFakeAuthCode); @@ -138,10 +140,13 @@ mojom::ArcSignInStatus sign_in_status() const { return status_; } - int num_account_upserted_calls_ = 0; - std::string last_upserted_account_; - int num_account_removed_calls_ = 0; - std::string last_removed_account_; + int num_account_upserted_calls() const { return num_account_upserted_calls_; } + + std::string last_upserted_account() const { return last_upserted_account_; } + + int num_account_removed_calls() const { return num_account_removed_calls_; } + + std::string last_removed_account() const { return last_removed_account_; } private: void OnAccountInfoResponse(base::OnceClosure done_closure, @@ -157,6 +162,11 @@ mojom::AccountInfoPtr account_info_; base::OnceClosure done_closure_; + int num_account_upserted_calls_ = 0; + std::string last_upserted_account_; + int num_account_removed_calls_ = 0; + std::string last_removed_account_; + base::WeakPtrFactory<FakeAuthInstance> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(FakeAuthInstance); }; @@ -253,16 +263,9 @@ identity_test_environment_adaptor_->identity_test_env(); identity_test_env->SetAutomaticIssueOfAccessTokens(true); identity_test_env->MakePrimaryAccountAvailable(kFakeUserName); - - chromeos::AccountManagerFactory* factory = - g_browser_process->platform_part()->GetAccountManagerFactory(); - chromeos::AccountManager* account_manager = - factory->GetAccountManager(profile_->GetPath().value()); - account_manager->Initialize( - temp_dir_.GetPath(), test_shared_loader_factory_, - base::BindRepeating([](const base::RepeatingClosure& closure) -> void { - closure.Run(); - })); + identity_test_env->identity_manager() + ->GetAccountsMutator() + ->LoadAccountsFromDisk(kFakeUserName); profile()->GetPrefs()->SetBoolean(prefs::kArcSignedIn, true); profile()->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, true); @@ -273,9 +276,18 @@ auth_service_ = ArcAuthService::GetForBrowserContext(profile()); DCHECK(auth_service_); + chromeos::AccountManagerFactory* factory = + g_browser_process->platform_part()->GetAccountManagerFactory(); + chromeos::AccountManager* account_manager = + factory->GetAccountManager(profile()->GetPath().value()); test_shared_loader_factory_ = base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &test_url_loader_factory_); + account_manager->Initialize( + profile()->GetPath(), test_shared_loader_factory_, + base::BindRepeating([](const base::RepeatingClosure& closure) -> void { + closure.Run(); + })); auth_service_->SetURLLoaderFactoryForTesting(test_shared_loader_factory_); // It is non-trivial to navigate through the merge session in a testing // context; currently we just skip it. @@ -443,26 +455,76 @@ auth_instance().sign_in_status()); } -IN_PROC_BROWSER_TEST_F(ArcAuthServiceTest, AccountUpsertsArePropagated) { - SetAccountAndProfile(user_manager::USER_TYPE_REGULAR); - AccountInfo account_info = SeedAccountInfo(kSecondaryAccountEmail); +// Tests that need Chrome OS Account Manager feature to be enabled. +// TODO(crbug.com/912537): Merge them in ArcAuthServiceTest when Account Manager +// is enabled by default on Chrome OS. +class ArcAuthServiceAccountManagerTest : public ArcAuthServiceTest { + public: + ArcAuthServiceAccountManagerTest() = default; + ~ArcAuthServiceAccountManagerTest() override = default; - EXPECT_EQ(0, auth_instance().num_account_upserted_calls_); + void SetUp() override { + scoped_feature_list_.InitAndEnableFeature( + chromeos::switches::kAccountManager); + ArcAuthServiceTest::SetUp(); + } + + AccountInfo SetupGaiaAccount(const std::string& email, + const std::string& token) { + SetAccountAndProfile(user_manager::USER_TYPE_REGULAR); + AccountInfo account_info = SeedAccountInfo(email); + + chromeos::AccountManagerFactory* factory = + g_browser_process->platform_part()->GetAccountManagerFactory(); + account_manager_ = factory->GetAccountManager(profile()->GetPath().value()); + account_manager_->UpsertToken( + chromeos::AccountManager::AccountKey{ + account_info.gaia, + chromeos::account_manager::AccountType::ACCOUNT_TYPE_GAIA}, + token); + base::RunLoop().RunUntilIdle(); + return account_info; + } + + chromeos::AccountManager* account_manager() { return account_manager_; } + + private: + base::test::ScopedFeatureList scoped_feature_list_; + + // Non-owned pointer. + chromeos::AccountManager* account_manager_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(ArcAuthServiceAccountManagerTest); +}; + +IN_PROC_BROWSER_TEST_F(ArcAuthServiceAccountManagerTest, + AccountUpsertsArePropagated) { + AccountInfo account_info = + SetupGaiaAccount(kSecondaryAccountEmail, kFakeToken); + + // Don't bother checking |initial_num_calls|. AccountManager has a quirk that + // if you insert an account into it "too soon" (before it has been fully + // initialized), it notifies its observers twice for the inserted account. + // This case can only be triggered by tests. + const int initial_num_calls = auth_instance().num_account_upserted_calls(); chromeos::AccountManager::AccountKey account_key{ account_info.gaia, chromeos::account_manager::AccountType::ACCOUNT_TYPE_GAIA}; - auth_service().OnTokenUpserted(account_key); + account_manager()->UpsertToken(account_key, "new-token"); - EXPECT_EQ(1, auth_instance().num_account_upserted_calls_); - EXPECT_EQ(kSecondaryAccountEmail, auth_instance().last_upserted_account_); + // Expect exactly one call for the account insertion above. + EXPECT_EQ(1, + auth_instance().num_account_upserted_calls() - initial_num_calls); + EXPECT_EQ(kSecondaryAccountEmail, auth_instance().last_upserted_account()); } -IN_PROC_BROWSER_TEST_F(ArcAuthServiceTest, AccountRemovalsArePropagated) { +IN_PROC_BROWSER_TEST_F(ArcAuthServiceAccountManagerTest, + AccountRemovalsArePropagated) { SetAccountAndProfile(user_manager::USER_TYPE_REGULAR); SeedAccountInfo(kSecondaryAccountEmail); - EXPECT_EQ(0, auth_instance().num_account_removed_calls_); + EXPECT_EQ(0, auth_instance().num_account_removed_calls()); AccountTrackerService* account_tracker_service = AccountTrackerServiceFactory::GetInstance()->GetForProfile(profile()); @@ -472,8 +534,28 @@ account_tracker_service->RemoveAccount(account_id); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, auth_instance().num_account_removed_calls_); - EXPECT_EQ(kSecondaryAccountEmail, auth_instance().last_removed_account_); + EXPECT_EQ(1, auth_instance().num_account_removed_calls()); + EXPECT_EQ(kSecondaryAccountEmail, auth_instance().last_removed_account()); +} + +IN_PROC_BROWSER_TEST_F(ArcAuthServiceAccountManagerTest, + AccountUpsertsAreNotPropagatedForInvalidTokens) { + const AccountInfo account_info = + SetupGaiaAccount(kSecondaryAccountEmail, kFakeToken); + + // Don't bother checking |initial_num_calls|. AccountManager has a quirk that + // if you insert an account into it "too soon" (before it has been fully + // initialized), it notifies its observers twice for the inserted account. + // This case can only be triggered by tests. + const int initial_num_calls = auth_instance().num_account_upserted_calls(); + + chromeos::AccountManager::AccountKey account_key{ + account_info.gaia, + chromeos::account_manager::AccountType::ACCOUNT_TYPE_GAIA}; + account_manager()->UpsertToken(account_key, + chromeos::AccountManager::kInvalidToken); + + EXPECT_EQ(auth_instance().num_account_upserted_calls(), initial_num_calls); } class ArcRobotAccountAuthServiceTest : public ArcAuthServiceTest {
diff --git a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc index 020a9a1..8e424ff 100644 --- a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc +++ b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc
@@ -155,6 +155,7 @@ input_method::InputMethodEngineBase::MouseButtonEvent button) override {} void OnMenuItemActivated(const std::string& component_id, const std::string& menu_id) override {} + void OnScreenProjectionChanged(bool is_projected) override {} private: ArcInputMethodManagerService* const owner_;
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller.cc b/chrome/browser/chromeos/child_accounts/screen_time_controller.cc index 614939a8..d66402c 100644 --- a/chrome/browser/chromeos/child_accounts/screen_time_controller.cc +++ b/chrome/browser/chromeos/child_accounts/screen_time_controller.cc
@@ -40,8 +40,10 @@ // static void ScreenTimeController::RegisterProfilePrefs(PrefRegistrySimple* registry) { - registry->RegisterDictionaryPref(prefs::kUsageTimeLimit); + // TODO(agawronska): Move preference registration when implementing PAC. + registry->RegisterDictionaryPref(prefs::kParentAccessCodeConfig); registry->RegisterDictionaryPref(prefs::kScreenTimeLastState); + registry->RegisterDictionaryPref(prefs::kUsageTimeLimit); } ScreenTimeController::ScreenTimeController(content::BrowserContext* context)
diff --git a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.cc b/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.cc index 29202b15..0017288f 100644 --- a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.cc +++ b/chrome/browser/chromeos/child_accounts/usage_time_limit_processor.cc
@@ -395,13 +395,15 @@ usage_limit_entry->last_updated > time_limit_override_->created_at) return false; + base::Time last_reset_time = ConvertPolicyTime(LockOverrideResetTime(), 0); bool usage_limit_enforced_previously = previous_state_->is_time_usage_limit_enabled && previous_state_->remaining_usage <= base::TimeDelta::FromMinutes(0); bool override_created_after_usage_limit_start = !previous_state_->time_usage_limit_started.is_null() && time_limit_override_->created_at > - previous_state_->time_usage_limit_started; + previous_state_->time_usage_limit_started && + time_limit_override_->created_at >= last_reset_time; return usage_limit_enforced_previously && override_created_after_usage_limit_start; } @@ -474,7 +476,7 @@ return base::nullopt; internal::Weekday current_usage_limit_day = - current_time_ > ConvertPolicyTime(UsageLimitResetTime(), 0) + current_time_ >= ConvertPolicyTime(UsageLimitResetTime(), 0) ? current_weekday_ : internal::WeekdayShift(current_weekday_, -1); return time_usage_limit_->entries[current_usage_limit_day]; @@ -719,9 +721,8 @@ } } - // Minimum time when the time usage quota could end. Not calculated when - // time usage limit has already finished. If there is no active time usage - // limit on the current day, we search on the following days. + // Minimum time when the current time usage quota could end. Not calculated + // when time usage limit has already finished. if (time_usage_limit_ && !active_time_usage_limit_ && !overridden_usage_limit_ && !active_time_window_limit_) { // If there is an active time usage, we just look when it would lock the @@ -733,22 +734,24 @@ next_change = quota_ends; *out_next_active = ActivePolicies::kUsageLimit; } - } else { - // Look for the next time usage, and calculate when the minimum time it - // could end. - for (int i = 0; i < static_cast<int>(internal::Weekday::kCount); i++) { - base::Optional<internal::TimeUsageLimitEntry> usage_limit_entry = - time_usage_limit_ - ->entries[internal::WeekdayShift(current_weekday_, i)]; - if (usage_limit_entry) { - base::Time quota_ends = ConvertPolicyTime(UsageLimitResetTime(), i) + - usage_limit_entry->usage_quota; - if (IsBefore(quota_ends, next_change)) { - next_change = quota_ends; - *out_next_active = ActivePolicies::kUsageLimit; - } - break; + } + } + + // Look for the next time usage, and calculate the minimum time when it could + // end. + if (time_usage_limit_) { + for (int i = 1; i < static_cast<int>(internal::Weekday::kCount); i++) { + base::Optional<internal::TimeUsageLimitEntry> usage_limit_entry = + time_usage_limit_ + ->entries[internal::WeekdayShift(current_weekday_, i)]; + if (usage_limit_entry) { + base::Time quota_ends = ConvertPolicyTime(UsageLimitResetTime(), i) + + usage_limit_entry->usage_quota; + if (IsBefore(quota_ends, next_change)) { + next_change = quota_ends; + *out_next_active = ActivePolicies::kUsageLimit; } + break; } } }
diff --git a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor_unittest.cc b/chrome/browser/chromeos/child_accounts/usage_time_limit_processor_unittest.cc index 4cc65c6c..9c12188 100644 --- a/chrome/browser/chromeos/child_accounts/usage_time_limit_processor_unittest.cc +++ b/chrome/browser/chromeos/child_accounts/usage_time_limit_processor_unittest.cc
@@ -1378,6 +1378,198 @@ AssertEqState(expected_state_four, state_four); } +// Test if consecutive locked all day usage limits work properly. +TEST_F(UsageTimeLimitProcessorTest, + GetStateConsecutiveLockedAllDayAfterUnlock) { + std::unique_ptr<icu::TimeZone> timezone(icu::TimeZone::createTimeZone("BRT")); + + // Setup policy. + std::string last_updated = CreatePolicyTimestamp("1 Jan 2018 8:00 BRT"); + std::unique_ptr<base::DictionaryValue> policy = + CreateTimeLimitPolicy(CreateTime(6, 0)); + AddTimeUsageLimit(policy.get(), kWednesday, base::TimeDelta::FromHours(0), + last_updated); + AddTimeUsageLimit(policy.get(), kThursday, base::TimeDelta::FromHours(0), + last_updated); + AddTimeUsageLimit(policy.get(), kFriday, base::TimeDelta::FromHours(0), + last_updated); + + // Check that the device is locked. + base::Time time_one = TimeFromString("Wed, 3 Jan 2018 7:00 BRT"); + State state_one = GetState(policy, base::TimeDelta::FromHours(0), time_one, + time_one, timezone.get(), base::nullopt); + + State expected_state_one; + expected_state_one.is_locked = true; + expected_state_one.active_policy = ActivePolicies::kUsageLimit; + expected_state_one.is_time_usage_limit_enabled = true; + expected_state_one.remaining_usage = base::TimeDelta::FromMinutes(0); + expected_state_one.time_usage_limit_started = time_one; + expected_state_one.next_state_change_time = + TimeFromString("Thu, 4 Jan 2018 6:00 BRT"); + expected_state_one.next_state_active_policy = ActivePolicies::kUsageLimit; + expected_state_one.next_unlock_time = + TimeFromString("Thu, 4 Jan 2018 6:00 BRT"); + expected_state_one.last_state_changed = base::Time(); + + AssertEqState(expected_state_one, state_one); + + AddOverride(policy.get(), kUnlock, + CreatePolicyTimestamp("Wed, 3 Jan 2018 7:30 BRT")); + + // Check that the device is unlocked because of the override. + base::Time time_two = TimeFromString("Wed, 3 Jan 2018 8:00 BRT"); + State state_two = GetState(policy, base::TimeDelta::FromHours(0), time_two, + time_two, timezone.get(), state_one); + + State expected_state_two; + expected_state_two.is_locked = false; + expected_state_two.active_policy = ActivePolicies::kOverride; + expected_state_two.is_time_usage_limit_enabled = true; + expected_state_two.remaining_usage = base::TimeDelta::FromMinutes(0); + expected_state_two.time_usage_limit_started = time_one; + expected_state_two.next_state_change_time = + TimeFromString("Thu, 4 Jan 2018 6:00 BRT"); + expected_state_two.next_state_active_policy = ActivePolicies::kUsageLimit; + expected_state_two.last_state_changed = time_two; + + AssertEqState(expected_state_two, state_two); + + // Check that the device is locked. + base::Time time_three = TimeFromString("Thu, 4 Jan 2018 8:00 BRT"); + State state_three = + GetState(policy, base::TimeDelta::FromHours(0), time_three, time_three, + timezone.get(), state_two); + + State expected_state_three; + expected_state_three.is_locked = true; + expected_state_three.active_policy = ActivePolicies::kUsageLimit; + expected_state_three.is_time_usage_limit_enabled = true; + expected_state_three.remaining_usage = base::TimeDelta::FromMinutes(0); + expected_state_three.time_usage_limit_started = time_one; + expected_state_three.next_state_change_time = + TimeFromString("Fri, 5 Jan 2018 6:00 BRT"); + expected_state_three.next_state_active_policy = ActivePolicies::kUsageLimit; + expected_state_three.next_unlock_time = + TimeFromString("Fri, 5 Jan 2018 6:00 BRT"); + expected_state_three.last_state_changed = time_three; + + AssertEqState(expected_state_three, state_three); + + // Check that the device is locked. + base::Time time_four = TimeFromString("Fri, 5 Jan 2018 8:00 BRT"); + State state_four = GetState(policy, base::TimeDelta::FromHours(0), time_four, + time_four, timezone.get(), state_three); + + State expected_state_four; + expected_state_four.is_locked = true; + expected_state_four.active_policy = ActivePolicies::kUsageLimit; + expected_state_four.is_time_usage_limit_enabled = true; + expected_state_four.remaining_usage = base::TimeDelta::FromMinutes(0); + expected_state_four.time_usage_limit_started = time_one; + expected_state_four.next_state_change_time = + TimeFromString("Sat, 6 Jan 2018 6:00 BRT"); + expected_state_four.next_state_active_policy = + ActivePolicies::kNoActivePolicy; + expected_state_four.next_unlock_time = + TimeFromString("Sat, 6 Jan 2018 6:00 BRT"); + expected_state_four.last_state_changed = time_three; + + AssertEqState(expected_state_four, state_four); + + // Check that the device is unlocked. + base::Time time_five = TimeFromString("Sat, 6 Jan 2018 6:00 BRT"); + State state_five = GetState(policy, base::TimeDelta::FromHours(0), time_five, + time_five, timezone.get(), state_four); + + State expected_state_five; + expected_state_five.is_locked = false; + expected_state_five.active_policy = ActivePolicies::kNoActivePolicy; + expected_state_five.is_time_usage_limit_enabled = false; + expected_state_five.next_state_change_time = + TimeFromString("Wed, 10 Jan 2018 6:00 BRT"); + expected_state_five.next_state_active_policy = ActivePolicies::kUsageLimit; + expected_state_five.last_state_changed = time_five; + + AssertEqState(expected_state_five, state_five); +} + +// Test if unlock work after two consecutive daily limit. +TEST_F(UsageTimeLimitProcessorTest, GetStateUnlockConsecutiveLockedAllDay) { + std::unique_ptr<icu::TimeZone> timezone(icu::TimeZone::createTimeZone("BRT")); + + // Setup policy. + std::string last_updated = CreatePolicyTimestamp("1 Jan 2018 8:00 BRT"); + std::unique_ptr<base::DictionaryValue> policy = + CreateTimeLimitPolicy(CreateTime(6, 0)); + AddTimeUsageLimit(policy.get(), kWednesday, base::TimeDelta::FromHours(0), + last_updated); + AddTimeUsageLimit(policy.get(), kThursday, base::TimeDelta::FromHours(0), + last_updated); + + // Check that the device is locked. + base::Time time_one = TimeFromString("Wed, 3 Jan 2018 7:00 BRT"); + State state_one = GetState(policy, base::TimeDelta::FromHours(0), time_one, + time_one, timezone.get(), base::nullopt); + + State expected_state_one; + expected_state_one.is_locked = true; + expected_state_one.active_policy = ActivePolicies::kUsageLimit; + expected_state_one.is_time_usage_limit_enabled = true; + expected_state_one.remaining_usage = base::TimeDelta::FromMinutes(0); + expected_state_one.time_usage_limit_started = time_one; + expected_state_one.next_state_change_time = + TimeFromString("Thu, 4 Jan 2018 6:00 BRT"); + expected_state_one.next_state_active_policy = ActivePolicies::kUsageLimit; + expected_state_one.next_unlock_time = + TimeFromString("Thu, 4 Jan 2018 6:00 BRT"); + expected_state_one.last_state_changed = base::Time(); + + AssertEqState(expected_state_one, state_one); + + // Check that the device is locked. + base::Time time_two = TimeFromString("Thu, 4 Jan 2018 6:00 BRT"); + State state_two = GetState(policy, base::TimeDelta::FromHours(0), time_two, + time_two, timezone.get(), state_one); + + State expected_state_two; + expected_state_two.is_locked = true; + expected_state_two.active_policy = ActivePolicies::kUsageLimit; + expected_state_two.is_time_usage_limit_enabled = true; + expected_state_two.remaining_usage = base::TimeDelta::FromMinutes(0); + expected_state_two.time_usage_limit_started = time_one; + expected_state_two.next_state_change_time = + TimeFromString("Fri, 5 Jan 2018 6:00 BRT"); + expected_state_two.next_state_active_policy = ActivePolicies::kNoActivePolicy; + expected_state_two.next_unlock_time = + TimeFromString("Fri, 5 Jan 2018 6:00 BRT"); + expected_state_two.last_state_changed = base::Time(); + + AssertEqState(expected_state_two, state_two); + + AddOverride(policy.get(), kUnlock, + CreatePolicyTimestamp("Thu, 4 Jan 2018 7:30 BRT")); + + // Check that the device is unlocked. + base::Time time_three = TimeFromString("Thu, 4 Jan 2018 8:00 BRT"); + State state_three = + GetState(policy, base::TimeDelta::FromHours(0), time_three, time_three, + timezone.get(), state_two); + + State expected_state_three; + expected_state_three.is_locked = false; + expected_state_three.active_policy = ActivePolicies::kOverride; + expected_state_three.is_time_usage_limit_enabled = true; + expected_state_three.remaining_usage = base::TimeDelta::FromMinutes(0); + expected_state_three.time_usage_limit_started = time_one; + expected_state_three.next_state_change_time = + TimeFromString("Wed, 10 Jan 2018 6:00 BRT"); + expected_state_three.next_state_active_policy = ActivePolicies::kUsageLimit; + expected_state_three.last_state_changed = time_three; + + AssertEqState(expected_state_three, state_three); +} + // Test GetExpectedResetTime with an empty policy. TEST_F(UsageTimeLimitProcessorTest, GetExpectedResetTimeWithEmptyPolicy) { std::unique_ptr<icu::TimeZone> timezone(icu::TimeZone::createTimeZone("GMT"));
diff --git a/chrome/browser/chromeos/crostini/crostini_registry_service.cc b/chrome/browser/chromeos/crostini/crostini_registry_service.cc index ffe06eb..58d0ac3 100644 --- a/chrome/browser/chromeos/crostini/crostini_registry_service.cc +++ b/chrome/browser/chromeos/crostini/crostini_registry_service.cc
@@ -46,6 +46,7 @@ constexpr char kAppContainerNameKey[] = "container_name"; constexpr char kAppCommentKey[] = "comment"; constexpr char kAppMimeTypesKey[] = "mime_types"; +constexpr char kAppKeywordsKey[] = "keywords"; constexpr char kAppNameKey[] = "name"; constexpr char kAppNoDisplayKey[] = "no_display"; constexpr char kAppScaledKey[] = "scaled"; @@ -116,6 +117,22 @@ return result; } +base::Value LocaleStringsProtoToDictionary( + const App::LocaleStrings& repeated_locale_string) { + base::Value result(base::Value::Type::DICTIONARY); + for (const auto& strings_with_locale : repeated_locale_string.values()) { + const std::string& locale = strings_with_locale.locale(); + + std::string locale_with_dashes(locale); + std::replace(locale_with_dashes.begin(), locale_with_dashes.end(), '_', + '-'); + if (!locale.empty() && !l10n_util::IsValidLocaleSyntax(locale_with_dashes)) + continue; + result.SetKey(locale, ProtoToList(strings_with_locale.value())); + } + return result; +} + // This is the companion to CrostiniRegistryService::SetCurrentTime(). base::Time GetTime(const base::Value& pref, const char* key) { if (!pref.is_dict()) @@ -300,6 +317,16 @@ pref_.FindKeyOfType(kAppMimeTypesKey, base::Value::Type::LIST)); } +std::set<std::string> CrostiniRegistryService::Registration::Keywords() const { + if (is_terminal_app_) { + std::set<std::string> result = {"linux", "terminal", "crostini"}; + result.insert( + l10n_util::GetStringUTF8(IDS_CROSTINI_TERMINAL_APP_SEARCH_TERMS)); + return result; + } + return LocalizedList(kAppKeywordsKey); +} + bool CrostiniRegistryService::Registration::NoDisplay() const { if (pref_.is_none()) return false; @@ -376,6 +403,31 @@ return std::string(); } +std::set<std::string> CrostiniRegistryService::Registration::LocalizedList( + base::StringPiece key) const { + if (pref_.is_none()) + return {}; + const base::Value* dict = + pref_.FindKeyOfType(key, base::Value::Type::DICTIONARY); + if (!dict) + return {}; + + std::string current_locale = + l10n_util::NormalizeLocale(g_browser_process->GetApplicationLocale()); + std::vector<std::string> locales; + l10n_util::GetParentLocales(current_locale, &locales); + // We use an empty locale as fallback. + locales.push_back(std::string()); + + for (const std::string& locale : locales) { + const base::Value* value = + dict->FindKeyOfType(locale, base::Value::Type::LIST); + if (value) + return ListToStringSet(value); + } + return {}; +} + CrostiniRegistryService::CrostiniRegistryService(Profile* profile) : profile_(profile), prefs_(profile->GetPrefs()), @@ -677,6 +729,8 @@ pref_registration.SetKey(kAppCommentKey, ProtoToDictionary(app.comment())); pref_registration.SetKey(kAppMimeTypesKey, ProtoToList(app.mime_types())); + pref_registration.SetKey(kAppKeywordsKey, + LocaleStringsProtoToDictionary(app.keywords())); pref_registration.SetKey(kAppNoDisplayKey, base::Value(app.no_display())); pref_registration.SetKey(kAppStartupWMClassKey, base::Value(app.startup_wm_class()));
diff --git a/chrome/browser/chromeos/crostini/crostini_registry_service.h b/chrome/browser/chromeos/crostini/crostini_registry_service.h index 05fd19768..34f030b 100644 --- a/chrome/browser/chromeos/crostini/crostini_registry_service.h +++ b/chrome/browser/chromeos/crostini/crostini_registry_service.h
@@ -83,6 +83,7 @@ std::string Name() const; std::string Comment() const; std::set<std::string> MimeTypes() const; + std::set<std::string> Keywords() const; bool NoDisplay() const; base::Time InstallTime() const; @@ -97,6 +98,7 @@ private: std::string LocalizedString(base::StringPiece key) const; + std::set<std::string> LocalizedList(base::StringPiece key) const; // The pref can only be null when the registration is for the Terminal app. // If we do have a pref for the Terminal app, it contains only the last
diff --git a/chrome/browser/chromeos/crostini/crostini_registry_service_unittest.cc b/chrome/browser/chromeos/crostini/crostini_registry_service_unittest.cc index 4fbadb5..68362d7 100644 --- a/chrome/browser/chromeos/crostini/crostini_registry_service_unittest.cc +++ b/chrome/browser/chromeos/crostini/crostini_registry_service_unittest.cc
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/simple_test_clock.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/crostini/crostini_test_helper.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/test/base/testing_profile.h" @@ -81,6 +82,8 @@ std::string container_name = "awesomecontainer"; std::map<std::string, std::string> name = {{"", "Vim"}}; std::map<std::string, std::string> comment = {{"", "Edit text files"}}; + std::map<std::string, std::set<std::string>> keywords = { + {"", {"very", "awesome"}}}; std::set<std::string> mime_types = {"text/plain", "text/x-python"}; bool no_display = true; @@ -108,6 +111,14 @@ entry->set_value(localized_comment.second); } + for (const auto& localized_keywords : keywords) { + auto* keywords_with_locale = app->mutable_keywords()->add_values(); + keywords_with_locale->set_locale(localized_keywords.first); + for (const auto& localized_keyword : localized_keywords.second) { + keywords_with_locale->add_value(localized_keyword); + } + } + for (const std::string& mime_type : mime_types) app->add_mime_types(mime_type); @@ -120,6 +131,7 @@ EXPECT_EQ(result->ContainerName(), container_name); EXPECT_EQ(result->Name(), name[""]); EXPECT_EQ(result->Comment(), comment[""]); + EXPECT_EQ(result->Keywords(), keywords[""]); EXPECT_EQ(result->MimeTypes(), mime_types); EXPECT_EQ(result->NoDisplay(), no_display); } @@ -451,4 +463,37 @@ EXPECT_FALSE(registration.value().IsScaled()); } +TEST_F(CrostiniRegistryServiceTest, SetAndGetRegistrationKeywords) { + std::map<std::string, std::set<std::string>> keywords = { + {"", {"very", "awesome"}}, + {"fr", {"sum", "ward"}}, + {"ge", {"extra", "average"}}, + {"te", {"not", "terrible"}}}; + std::string app_id = + CrostiniTestHelper::GenerateAppId("app", "vm", "container"); + ApplicationList app_list = + CrostiniTestHelper::BasicAppList("app", "vm", "container"); + + for (const auto& localized_keywords : keywords) { + auto* keywords_with_locale = + app_list.mutable_apps(0)->mutable_keywords()->add_values(); + keywords_with_locale->set_locale(localized_keywords.first); + for (const auto& localized_keyword : localized_keywords.second) { + keywords_with_locale->add_value(localized_keyword); + } + } + service()->UpdateApplicationList(app_list); + + base::Optional<CrostiniRegistryService::Registration> result = + service()->GetRegistration(app_id); + g_browser_process->SetApplicationLocale(""); + EXPECT_EQ(result->Keywords(), keywords[""]); + g_browser_process->SetApplicationLocale("fr"); + EXPECT_EQ(result->Keywords(), keywords["fr"]); + g_browser_process->SetApplicationLocale("ge"); + EXPECT_EQ(result->Keywords(), keywords["ge"]); + g_browser_process->SetApplicationLocale("te"); + EXPECT_EQ(result->Keywords(), keywords["te"]); +} + } // namespace crostini
diff --git a/chrome/browser/chromeos/crostini/crostini_share_path.cc b/chrome/browser/chromeos/crostini/crostini_share_path.cc index 655c2ee6..affe64a 100644 --- a/chrome/browser/chromeos/crostini/crostini_share_path.cc +++ b/chrome/browser/chromeos/crostini/crostini_share_path.cc
@@ -329,11 +329,32 @@ std::vector<base::FilePath> result; if (!base::FeatureList::IsEnabled(chromeos::features::kCrostiniFiles)) return result; + PrefService* pref_service = profile_->GetPrefs(); const base::ListValue* shared_paths = - profile_->GetPrefs()->GetList(prefs::kCrostiniSharedPaths); - for (const auto& path : *shared_paths) { - result.emplace_back(base::FilePath(path.GetString())); + pref_service->GetList(prefs::kCrostiniSharedPaths); + // Paths in <cryptohome>/Downloads need to be migrated to + // <cryptohome>/MyFiles/Downloads. + bool swap_for_migrate_required = false; + base::ListValue migrated_paths; + for (const auto& shared_path : *shared_paths) { + base::FilePath path(shared_path.GetString()); + base::FilePath migrated; + if (file_manager::util::MigrateFromDownloadsToMyFiles(profile_, path, + &migrated)) { + swap_for_migrate_required = true; + path = migrated; + } + migrated_paths.AppendString(path.value()); + result.emplace_back(path); } + + // If any paths were modified during migration, update prefs. + if (swap_for_migrate_required) { + ListPrefUpdate update(pref_service, crostini::prefs::kCrostiniSharedPaths); + base::ListValue* shared_paths = update.Get(); + shared_paths->Swap(&migrated_paths); + } + return result; }
diff --git a/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc b/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc index 0babf3d..0001a67 100644 --- a/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc +++ b/chrome/browser/chromeos/crostini/crostini_share_path_unittest.cc
@@ -567,4 +567,80 @@ run_loop()->Run(); } +TEST_F(CrostiniSharePathTest, GetPersistedSharedPaths) { + base::ListValue shared_paths = base::ListValue(); + base::FilePath downloads_file = profile()->GetPath().Append("Downloads/file"); + shared_paths.AppendString(downloads_file.value()); + base::FilePath not_downloads("/not/downloads"); + shared_paths.AppendString(not_downloads.value()); + std::string prefstr; + // CrostiniFiles disabled, MyFilesVolume disabled. + // Result is empty, prefs unchanged. + { + base::test::ScopedFeatureList features; + features.InitWithFeatures({}, {chromeos::features::kCrostiniFiles, + chromeos::features::kMyFilesVolume}); + storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem( + file_manager::util::GetDownloadsMountPointName(profile())); + profile()->GetPrefs()->Set(prefs::kCrostiniSharedPaths, shared_paths); + std::vector<base::FilePath> paths = + crostini_share_path()->GetPersistedSharedPaths(); + EXPECT_EQ(paths.size(), 0U); + const base::ListValue* prefs = + profile()->GetPrefs()->GetList(prefs::kCrostiniSharedPaths); + EXPECT_EQ(prefs->GetSize(), 2U); + prefs->GetString(0, &prefstr); + EXPECT_EQ(prefstr, downloads_file.value()); + prefs->GetString(1, &prefstr); + EXPECT_EQ(prefstr, not_downloads.value()); + } + // CrostiniFiles enabled, MyFilesVolume disabled. + // Return prefs unchanged. + { + base::test::ScopedFeatureList features; + features.InitWithFeatures({chromeos::features::kCrostiniFiles}, + {chromeos::features::kMyFilesVolume}); + storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem( + file_manager::util::GetDownloadsMountPointName(profile())); + profile()->GetPrefs()->Set(prefs::kCrostiniSharedPaths, shared_paths); + std::vector<base::FilePath> paths = + crostini_share_path()->GetPersistedSharedPaths(); + EXPECT_EQ(paths.size(), 2U); + EXPECT_EQ(paths[0], downloads_file); + EXPECT_EQ(paths[1], not_downloads); + const base::ListValue* prefs = + profile()->GetPrefs()->GetList(prefs::kCrostiniSharedPaths); + EXPECT_EQ(prefs->GetSize(), 2U); + prefs->GetString(0, &prefstr); + EXPECT_EQ(prefstr, downloads_file.value()); + prefs->GetString(1, &prefstr); + EXPECT_EQ(prefstr, not_downloads.value()); + } + // CrostiniFiles enabled, MyFilesVolume enabled. + // Migrate prefs and return. + { + base::test::ScopedFeatureList features; + features.InitWithFeatures({chromeos::features::kCrostiniFiles, + chromeos::features::kMyFilesVolume}, + {}); + storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem( + file_manager::util::GetDownloadsMountPointName(profile())); + profile()->GetPrefs()->Set(prefs::kCrostiniSharedPaths, shared_paths); + base::FilePath myfiles_file = + profile()->GetPath().Append("MyFiles/Downloads/file"); + std::vector<base::FilePath> paths = + crostini_share_path()->GetPersistedSharedPaths(); + EXPECT_EQ(paths.size(), 2U); + EXPECT_EQ(paths[0], myfiles_file); + EXPECT_EQ(paths[1], not_downloads); + const base::ListValue* prefs = + profile()->GetPrefs()->GetList(prefs::kCrostiniSharedPaths); + EXPECT_EQ(prefs->GetSize(), 2U); + prefs->GetString(0, &prefstr); + EXPECT_EQ(prefstr, myfiles_file.value()); + prefs->GetString(1, &prefstr); + EXPECT_EQ(prefstr, not_downloads.value()); + } +} + } // namespace crostini
diff --git a/chrome/browser/chromeos/crostini/crostini_test_helper.cc b/chrome/browser/chromeos/crostini/crostini_test_helper.cc index 3caafaf..2b3428af 100644 --- a/chrome/browser/chromeos/crostini/crostini_test_helper.cc +++ b/chrome/browser/chromeos/crostini/crostini_test_helper.cc
@@ -59,6 +59,18 @@ UpdateRegistry(); } +void CrostiniTestHelper::UpdateAppKeywords( + vm_tools::apps::App& app, + const std::map<std::string, std::set<std::string>>& keywords) { + for (const auto& keywords_entry : keywords) { + auto* strings_with_locale = app.mutable_keywords()->add_values(); + strings_with_locale->set_locale(keywords_entry.first); + for (const auto& curr_keyword : keywords_entry.second) { + strings_with_locale->add_value(curr_keyword); + } + } +} + // static void CrostiniTestHelper::EnableCrostini(Profile* profile) { profile->GetPrefs()->SetBoolean(crostini::prefs::kCrostiniEnabled, true);
diff --git a/chrome/browser/chromeos/crostini/crostini_test_helper.h b/chrome/browser/chromeos/crostini/crostini_test_helper.h index 3abf8aa..10eff19 100644 --- a/chrome/browser/chromeos/crostini/crostini_test_helper.h +++ b/chrome/browser/chromeos/crostini/crostini_test_helper.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_TEST_HELPER_H_ #define CHROME_BROWSER_CHROMEOS_CROSTINI_CROSTINI_TEST_HELPER_H_ +#include <map> #include <string> #include "chrome/browser/chromeos/crostini/crostini_util.h" @@ -34,6 +35,10 @@ void AddApp(const vm_tools::apps::App& app); // Removes the |i|th app from the current list of apps. void RemoveApp(int i); + // Updates the Keywords field in an app + void UpdateAppKeywords( + vm_tools::apps::App& app, + const std::map<std::string, std::set<std::string>>& keywords); // Set/unset the the CrostiniEnabled pref static void EnableCrostini(Profile* profile);
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc index 7147d9d..ced5d18d 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
@@ -22,11 +22,13 @@ #include "chrome/browser/chromeos/file_manager/path_util.h" #include "chrome/browser/chromeos/file_manager/snapshot_manager.h" #include "chrome/browser/chromeos/file_manager/volume_manager.h" +#include "chrome/browser/chromeos/fileapi/external_file_url_util.h" #include "chrome/browser/chromeos/fileapi/file_system_backend.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/extensions/api/file_manager_private.h" #include "components/drive/chromeos/file_system_interface.h" #include "components/drive/drive.pb.h" +#include "components/drive/drive_api_util.h" #include "components/drive/file_errors.h" #include "content/public/browser/child_process_security_policy.h" #include "storage/browser/fileapi/file_system_context.h" @@ -112,6 +114,12 @@ std::unique_ptr<GetSelectedFileInfoParams> params, const base::FilePath& local_file_path); +void ContinueGetSelectedFileInfoWithDriveFsMetadata( + Profile* profile, + std::unique_ptr<GetSelectedFileInfoParams> params, + drive::FileError error, + drivefs::mojom::FileMetadataPtr metadata); + // Part of GetSelectedFileInfo(). void GetSelectedFileInfoInternal( Profile* profile, @@ -127,11 +135,19 @@ // the selected path does not point to a native local path (e.g., Drive, // MTP, or provided file system), we should resolve the path. switch (params->local_path_option) { - case NO_LOCAL_PATH_RESOLUTION: + case NO_LOCAL_PATH_RESOLUTION: { // Pass empty local path. params->selected_files.emplace_back(file_path, base::FilePath()); + + GURL external_file_url = + chromeos::CreateExternalFileURLFromPath(profile, file_path); + if (!external_file_url.is_empty()) { + params->selected_files.back().url.emplace( + std::move(external_file_url)); + } break; - case NEED_LOCAL_PATH_FOR_OPENING: + } + case NEED_LOCAL_PATH_FOR_OPENING: { GetFileNativeLocalPathForOpening( profile, file_path, @@ -139,7 +155,8 @@ profile, base::Passed(¶ms))); return; // Remaining work is done in ContinueGetSelectedFileInfo. - case NEED_LOCAL_PATH_FOR_SAVING: + } + case NEED_LOCAL_PATH_FOR_SAVING: { GetFileNativeLocalPathForSaving( profile, file_path, @@ -147,8 +164,26 @@ profile, base::Passed(¶ms))); return; // Remaining work is done in ContinueGetSelectedFileInfo. + } } } else { + // Hosted docs can only accessed by navigating to their URLs. Get the + // metadata for the file from DriveFS and populate the |url| field in the + // SelectedFileInfo. + if (drive::util::HasHostedDocumentExtension(file_path)) { + auto* integration_service = + drive::util::GetIntegrationServiceByProfile(profile); + base::FilePath drive_mount_relative_path; + if (integration_service && integration_service->GetDriveFsInterface() && + integration_service->GetRelativeDrivePath( + file_path, &drive_mount_relative_path)) { + integration_service->GetDriveFsInterface()->GetMetadata( + drive_mount_relative_path, + base::BindOnce(&ContinueGetSelectedFileInfoWithDriveFsMetadata, + profile, std::move(params))); + return; + } + } params->selected_files.emplace_back(file_path, file_path); } } @@ -170,6 +205,24 @@ GetSelectedFileInfoInternal(profile, std::move(params)); } +// Part of GetSelectedFileInfo(). +void ContinueGetSelectedFileInfoWithDriveFsMetadata( + Profile* profile, + std::unique_ptr<GetSelectedFileInfoParams> params, + drive::FileError error, + drivefs::mojom::FileMetadataPtr metadata) { + const int index = params->selected_files.size(); + const auto& path = params->file_paths[index]; + params->selected_files.emplace_back(path, path); + if (metadata && + metadata->type == drivefs::mojom::FileMetadata::Type::kHosted && + !metadata->alternate_url.empty()) { + params->selected_files.back().url.emplace( + std::move(metadata->alternate_url)); + } + GetSelectedFileInfoInternal(profile, std::move(params)); +} + } // namespace void FillIconSet(file_manager_private::IconSet* output,
diff --git a/chrome/browser/chromeos/extensions/input_method_api.cc b/chrome/browser/chromeos/extensions/input_method_api.cc index 8d2f3f9..d17ef2ef 100644 --- a/chrome/browser/chromeos/extensions/input_method_api.cc +++ b/chrome/browser/chromeos/extensions/input_method_api.cc
@@ -65,6 +65,8 @@ extensions::api::input_method_private::GetSurroundingText; namespace GetSetting = extensions::api::input_method_private::GetSetting; namespace SetSetting = extensions::api::input_method_private::SetSetting; +namespace OnSettingsChanged = + extensions::api::input_method_private::OnSettingsChanged; namespace { @@ -378,6 +380,20 @@ Profile::FromBrowserContext(browser_context())->GetPrefs(), prefs::kLanguageInputMethodSpecificSettings); update->SetPath({params->engine_id, params->key}, params->value->Clone()); + + // The router will only send the event to extensions that are listening. + extensions::EventRouter* router = + extensions::EventRouter::Get(browser_context()); + if (router->HasEventListener(OnSettingsChanged::kEventName)) { + auto event = std::make_unique<extensions::Event>( + extensions::events::INPUT_METHOD_PRIVATE_ON_SETTINGS_CHANGED, + OnSettingsChanged::kEventName, + OnSettingsChanged::Create(params->engine_id, params->key, + params->value->Clone()), + context_); + router->BroadcastEvent(std::move(event)); + } + return RespondNow(NoArguments()); #endif }
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index 29bd53ecb..ad82d779 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -469,15 +469,8 @@ TestCase("closeQuickView"), TestCase("cantOpenQuickViewWithMultipleFiles"))); -// TODO(https://crbug.com/911661) Flaky time outs on Linux Chromium OS ASan -// LSan bot. -#if defined(ADDRESS_SANITIZER) -#define MAYBE_DirectoryTreeContextMenu DISABLED_DirectoryTreeContextMenu -#else -#define MAYBE_DirectoryTreeContextMenu DirectoryTreeContextMenu -#endif WRAPPED_INSTANTIATE_TEST_CASE_P( - MAYBE_DirectoryTreeContextMenu, /* directory_tree_context_menu.js */ + DirectoryTreeContextMenu, /* directory_tree_context_menu.js */ FilesAppBrowserTest, ::testing::Values( TestCase("dirCopyWithContextMenu"), @@ -508,6 +501,7 @@ TestCase("dirRenameWithKeyboard").InGuestMode(), TestCase("dirRenameWithKeyboard").EnableMyFilesVolume(), TestCase("dirRenameWithoutChangingCurrent"), + TestCase("dirRenameWithoutChangingCurrent").EnableMyFilesVolume(), TestCase("dirRenameToEmptyString"), TestCase("dirRenameToEmptyString").InGuestMode(), TestCase("dirRenameToEmptyString").EnableMyFilesVolume(), @@ -752,7 +746,23 @@ TestCase("saveFileDialogDrive").WithBrowser(), TestCase("saveFileDialogDrive").WithBrowser().EnableMyFilesVolume(), TestCase("saveFileDialogDrive").WithBrowser().InIncognito(), - TestCase("openFileDialogDriveHostedDoc").WithBrowser(), + TestCase("openFileDialogDriveFromBrowser") + .WithBrowser() + .EnableDriveFs(), + TestCase("openFileDialogDriveFromBrowser") + .WithBrowser() + .DisableDriveFs(), + TestCase("openFileDialogDriveHostedDoc").WithBrowser().EnableDriveFs(), + TestCase("openFileDialogDriveHostedDoc").WithBrowser().DisableDriveFs(), + TestCase("openFileDialogDriveHostedNeedsFile") + .WithBrowser() + .EnableDriveFs(), + TestCase("saveFileDialogDriveHostedNeedsFile") + .WithBrowser() + .EnableDriveFs(), + TestCase("openFileDialogDriveHostedNeedsFile") + .WithBrowser() + .DisableDriveFs(), TestCase("openFileDialogCancelDrive").WithBrowser().DisableDriveFs(), TestCase("openFileDialogCancelDrive").WithBrowser().EnableDriveFs(), TestCase("openFileDialogEscapeDrive").WithBrowser().DisableDriveFs(),
diff --git a/chrome/browser/chromeos/file_manager/file_manager_jstest.cc b/chrome/browser/chromeos/file_manager/file_manager_jstest.cc index 64cb909..2576930 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_jstest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_jstest.cc
@@ -55,8 +55,7 @@ } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, DirectoryTreeTest) { - RunTest(base::FilePath( - FILE_PATH_LITERAL("foreground/js/ui/directory_tree_unittest.html"))); + RunGeneratedTest("/foreground/js/ui/directory_tree_unittest.html"); } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileTableTest) { @@ -109,23 +108,21 @@ } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, MetadataCacheSet) { - RunTest(base::FilePath(FILE_PATH_LITERAL( - "foreground/js/metadata/metadata_cache_set_unittest.html"))); + RunGeneratedTest("/foreground/js/metadata/metadata_cache_set_unittest.html"); } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, MultiMetadataProvider) { - RunTest(base::FilePath(FILE_PATH_LITERAL( - "foreground/js/metadata/multi_metadata_provider_unittest.html"))); + RunGeneratedTest( + "/foreground/js/metadata/multi_metadata_provider_unittest.html"); } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ListThumbnailLoader) { - RunTest(base::FilePath( - FILE_PATH_LITERAL("foreground/js/list_thumbnail_loader_unittest.html"))); + RunGeneratedTest("/foreground/js/list_thumbnail_loader_unittest.html"); } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileSystemMetadataProvider) { - RunTest(base::FilePath(FILE_PATH_LITERAL( - "foreground/js/metadata/file_system_metadata_provider_unittest.html"))); + RunGeneratedTest( + "/foreground/js/metadata/file_system_metadata_provider_unittest.html"); } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ExternalMetadataProvider) { @@ -134,13 +131,12 @@ } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ContentMetadataProvider) { - RunTest(base::FilePath(FILE_PATH_LITERAL( - "foreground/js/metadata/content_metadata_provider_unittest.html"))); + RunGeneratedTest( + "/foreground/js/metadata/content_metadata_provider_unittest.html"); } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, MetadataModel) { - RunTest(base::FilePath(FILE_PATH_LITERAL( - "foreground/js/metadata/metadata_model_unittest.html"))); + RunGeneratedTest("/foreground/js/metadata/metadata_model_unittest.html"); } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ThumbnailModel) { @@ -148,8 +144,7 @@ } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ExifParser) { - RunTest(base::FilePath(FILE_PATH_LITERAL( - "foreground/js/metadata/exif_parser_unittest.html"))); + RunGeneratedTest("/foreground/js/metadata/exif_parser_unittest.html"); } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ImageOrientation) { @@ -161,8 +156,7 @@ } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FilesTooltip) { - RunTest(base::FilePath( - FILE_PATH_LITERAL("foreground/elements/files_tooltip_unittest.html"))); + RunGeneratedTest("/foreground/elements/files_tooltip_unittest.html"); } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, SpinnerController) {
diff --git a/chrome/browser/chromeos/file_manager/path_util.cc b/chrome/browser/chromeos/file_manager/path_util.cc index 11100c6..cc53910 100644 --- a/chrome/browser/chromeos/file_manager/path_util.cc +++ b/chrome/browser/chromeos/file_manager/path_util.cc
@@ -176,6 +176,23 @@ return false; } +bool MigrateFromDownloadsToMyFiles(Profile* profile, + const base::FilePath& old_path, + base::FilePath* new_path) { + const base::FilePath old_base = + profile->GetPath().Append(kFolderNameDownloads); + const base::FilePath new_base = GetDownloadsFolderForProfile(profile); + if (new_base == old_base) + return false; + base::FilePath relative; + if (old_path == old_base || + old_base.AppendRelativePath(old_path, &relative)) { + *new_path = new_base.Append(relative); + return old_path != *new_path; + } + return false; +} + std::string GetDownloadsMountPointName(Profile* profile) { // To distinguish profiles in multi-profile session, we append user name hash // to "Downloads". Note that some profiles (like login or test profiles)
diff --git a/chrome/browser/chromeos/file_manager/path_util.h b/chrome/browser/chromeos/file_manager/path_util.h index df2b75e..4ad9490 100644 --- a/chrome/browser/chromeos/file_manager/path_util.h +++ b/chrome/browser/chromeos/file_manager/path_util.h
@@ -47,6 +47,17 @@ const base::FilePath& old_path, base::FilePath* new_path); +// Converts |old_path| in <cryptohome>/Downloads[/*] to |new_path| in +// <cryptohome/MyFiles/Downloads[*]. Returns true if path is changed else +// returns false if |old_path| was not inside Downloads, and |new_path| is +// undefined. +// +// Introduced in M73. This code updates values stored in prefs. +// TODO(crbug.com/911946) Remove this when no users are running M72 or earlier. +bool MigrateFromDownloadsToMyFiles(Profile* profile, + const base::FilePath& old_path, + base::FilePath* new_path); + // The canonical mount point name for "Downloads" folder. std::string GetDownloadsMountPointName(Profile* profile);
diff --git a/chrome/browser/chromeos/file_manager/path_util_unittest.cc b/chrome/browser/chromeos/file_manager/path_util_unittest.cc index bf53948..0049b08 100644 --- a/chrome/browser/chromeos/file_manager/path_util_unittest.cc +++ b/chrome/browser/chromeos/file_manager/path_util_unittest.cc
@@ -226,6 +226,56 @@ chromeos::disks::DiskMountManager::Shutdown(); } +TEST(FileManagerPathUtilTest, MigrateFromDownlaodsToMyFiles) { + content::TestBrowserThreadBundle thread_bundle; + base::FilePath home("/home/chronos/u-0123456789abcdef"); + base::FilePath result; + TestingProfile profile(home); + base::FilePath downloads = home.Append("Downloads"); + base::FilePath file = home.Append("Downloads/file.txt"); + base::FilePath inhome = home.Append("NotDownloads"); + base::FilePath myfiles = home.Append("MyFiles"); + base::FilePath myfilesFile = home.Append("MyFiles/file.txt"); + base::FilePath myfilesDownloads = home.Append("MyFiles/Downloads"); + base::FilePath myfilesDownloadsFile = + home.Append("MyFiles/Downloads/file.txt"); + base::FilePath other("/some/other/path"); + chromeos::ScopedSetRunningOnChromeOSForTesting fake_release(kLsbRelease, + base::Time()); + // MyFilesVolume disabled, no changes. + { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature(chromeos::features::kMyFilesVolume); + EXPECT_FALSE(MigrateFromDownloadsToMyFiles(&profile, downloads, &result)); + EXPECT_FALSE(MigrateFromDownloadsToMyFiles(&profile, file, &result)); + EXPECT_FALSE(MigrateFromDownloadsToMyFiles(&profile, inhome, &result)); + EXPECT_FALSE(MigrateFromDownloadsToMyFiles(&profile, myfiles, &result)); + EXPECT_FALSE(MigrateFromDownloadsToMyFiles(&profile, myfilesFile, &result)); + EXPECT_FALSE( + MigrateFromDownloadsToMyFiles(&profile, myfilesDownloads, &result)); + EXPECT_FALSE( + MigrateFromDownloadsToMyFiles(&profile, myfilesDownloadsFile, &result)); + EXPECT_FALSE(MigrateFromDownloadsToMyFiles(&profile, other, &result)); + } + // MyFilesVolume enabled, migrate paths under Downloads. + { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(chromeos::features::kMyFilesVolume); + EXPECT_TRUE(MigrateFromDownloadsToMyFiles(&profile, downloads, &result)); + EXPECT_EQ(result, myfilesDownloads); + EXPECT_TRUE(MigrateFromDownloadsToMyFiles(&profile, file, &result)); + EXPECT_EQ(result, myfilesDownloadsFile); + EXPECT_FALSE(MigrateFromDownloadsToMyFiles(&profile, inhome, &result)); + EXPECT_FALSE(MigrateFromDownloadsToMyFiles(&profile, myfiles, &result)); + EXPECT_FALSE(MigrateFromDownloadsToMyFiles(&profile, myfilesFile, &result)); + EXPECT_FALSE( + MigrateFromDownloadsToMyFiles(&profile, myfilesDownloads, &result)); + EXPECT_FALSE( + MigrateFromDownloadsToMyFiles(&profile, myfilesDownloadsFile, &result)); + EXPECT_FALSE(MigrateFromDownloadsToMyFiles(&profile, other, &result)); + } +} + TEST(FileManagerPathUtilTest, MultiProfileDownloadsFolderMigration) { content::TestBrowserThreadBundle thread_bundle; TestingProfile profile;
diff --git a/chrome/browser/chromeos/file_manager/url_util.cc b/chrome/browser/chromeos/file_manager/url_util.cc index 6eff30d4..22337d5 100644 --- a/chrome/browser/chromeos/file_manager/url_util.cc +++ b/chrome/browser/chromeos/file_manager/url_util.cc
@@ -23,6 +23,7 @@ const char kNativePath[] = "nativePath"; const char kNativeOrDrivePath[] = "nativeOrDrivePath"; const char kAnyPath[] = "anyPath"; +const char kAnyPathOrUrl[] = "anyPathOrUrl"; // Returns a file manager URL for the given |path|. GURL GetFileManagerUrl(const char* path) { @@ -129,6 +130,9 @@ case ui::SelectFileDialog::FileTypeInfo::ANY_PATH: arg_value.SetString(kAllowedPaths, kAnyPath); break; + case ui::SelectFileDialog::FileTypeInfo::ANY_PATH_OR_URL: + arg_value.SetString(kAllowedPaths, kAnyPathOrUrl); + break; } } else if (base::FeatureList::IsEnabled(chromeos::features::kDriveFs)) { arg_value.SetString(kAllowedPaths, kNativeOrDrivePath);
diff --git a/chrome/browser/chromeos/fileapi/external_file_url_util.cc b/chrome/browser/chromeos/fileapi/external_file_url_util.cc index 1c49bfe..d422a98 100644 --- a/chrome/browser/chromeos/fileapi/external_file_url_util.cc +++ b/chrome/browser/chromeos/fileapi/external_file_url_util.cc
@@ -9,14 +9,10 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" -#include "chrome/browser/chromeos/drive/drive_integration_service.h" -#include "chrome/browser/chromeos/drive/file_system_util.h" #include "chrome/browser/chromeos/file_manager/app_id.h" #include "chrome/browser/chromeos/file_manager/fileapi_util.h" #include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/profiles/profile.h" -#include "chromeos/components/drivefs/mojom/drivefs.mojom.h" -#include "components/drive/drive_api_util.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" @@ -27,24 +23,6 @@ using content::BrowserThread; namespace chromeos { -namespace { - -void ExtractHostedFileUrl(base::OnceCallback<void(GURL)> callback, - drive::FileError error, - drivefs::mojom::FileMetadataPtr metadata) { - if (error != drive::FILE_ERROR_OK) { - std::move(callback).Run({}); - return; - } - if (metadata->type != drivefs::mojom::FileMetadata::Type::kHosted) { - std::move(callback).Run({}); - return; - } - GURL hosted_url(metadata->alternate_url); - std::move(callback).Run(hosted_url.is_valid() ? hosted_url : GURL()); -} - -} // namespace bool IsExternalFileURLType(storage::FileSystemType type) { return type == storage::kFileSystemTypeDrive || @@ -100,51 +78,4 @@ return FileSystemURLToExternalFileURL(file_system_url); } -void ResolveExternalFileUrlFromPath(Profile* profile, - const base::FilePath& path, - base::OnceCallback<void(GURL)> callback) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - GURL raw_file_system_url; - if (!file_manager::util::ConvertAbsoluteFilePathToFileSystemUrl( - profile, path, file_manager::kFileManagerAppId, - &raw_file_system_url)) { - std::move(callback).Run({}); - return; - } - - const storage::FileSystemURL file_system_url = - file_manager::util::GetFileSystemContextForExtensionId( - profile, file_manager::kFileManagerAppId) - ->CrackURL(raw_file_system_url); - if (!file_system_url.is_valid()) { - std::move(callback).Run({}); - return; - } - - auto external_file_url = FileSystemURLToExternalFileURL(file_system_url); - if (!external_file_url.is_empty()) { - std::move(callback).Run(std::move(external_file_url)); - return; - } - - if (file_system_url.type() != storage::kFileSystemTypeDriveFs || - !drive::util::HasHostedDocumentExtension(path)) { - std::move(callback).Run({}); - return; - } - - drive::DriveIntegrationService* integration_service = - drive::util::GetIntegrationServiceByProfile(profile); - base::FilePath mount_relative_path; - if (!integration_service || !integration_service->GetDriveFsInterface() || - !integration_service->GetRelativeDrivePath(path, &mount_relative_path)) { - std::move(callback).Run({}); - return; - } - integration_service->GetDriveFsInterface()->GetMetadata( - mount_relative_path, - base::BindOnce(&ExtractHostedFileUrl, std::move(callback))); -} - } // namespace chromeos
diff --git a/chrome/browser/chromeos/fileapi/external_file_url_util.h b/chrome/browser/chromeos/fileapi/external_file_url_util.h index e6373b2..117e12a0 100644 --- a/chrome/browser/chromeos/fileapi/external_file_url_util.h +++ b/chrome/browser/chromeos/fileapi/external_file_url_util.h
@@ -42,15 +42,6 @@ GURL CreateExternalFileURLFromPath(Profile* profile, const base::FilePath& path); -// Obtains, from a file path (e.g. /special/drive-xxx/root/sample.txt), an -// external file URL (e.g. external:drive/root/sample.txt), if the |path| points -// an external location (drive, MTP, or FSP), or its hosted file URL if |path| -// refers to a hosted doc (e.g. gdoc) in DriveFS. If neither condition applies, -// |callback| is invoked with an empty GURL. -void ResolveExternalFileUrlFromPath(Profile* profile, - const base::FilePath& path, - base::OnceCallback<void(GURL)> callback); - } // namespace chromeos #endif // CHROME_BROWSER_CHROMEOS_FILEAPI_EXTERNAL_FILE_URL_UTIL_H_
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.cc b/chrome/browser/chromeos/input_method/input_method_engine.cc index 96cf6c9..2fbf64409 100644 --- a/chrome/browser/chromeos/input_method/input_method_engine.cc +++ b/chrome/browser/chromeos/input_method/input_method_engine.cc
@@ -66,7 +66,10 @@ InputMethodEngine::CandidateWindowProperty::~CandidateWindowProperty() {} InputMethodEngine::InputMethodEngine() - : candidate_window_(new ui::CandidateWindow()), window_visible_(false) {} + : candidate_window_(new ui::CandidateWindow()), + window_visible_(false), + is_mirroring_(false), + is_casting_(false) {} InputMethodEngine::~InputMethodEngine() {} @@ -221,6 +224,20 @@ keyboard_client->HideKeyboard(ash::mojom::HideReason::kUser); } +void InputMethodEngine::SetMirroringEnabled(bool mirroring_enabled) { + if (mirroring_enabled != is_mirroring_) { + is_mirroring_ = mirroring_enabled; + observer_->OnScreenProjectionChanged(is_mirroring_ || is_casting_); + } +} + +void InputMethodEngine::SetCastingEnabled(bool casting_enabled) { + if (casting_enabled != is_casting_) { + is_casting_ = casting_enabled; + observer_->OnScreenProjectionChanged(is_mirroring_ || is_casting_); + } +} + void InputMethodEngine::EnableInputView() { input_method::InputMethodManager::Get() ->GetActiveIMEState()
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.h b/chrome/browser/chromeos/input_method/input_method_engine.h index 01fda72..40bcf26a 100644 --- a/chrome/browser/chromeos/input_method/input_method_engine.h +++ b/chrome/browser/chromeos/input_method/input_method_engine.h
@@ -97,6 +97,8 @@ void PropertyActivate(const std::string& property_name) override; void CandidateClicked(uint32_t index) override; void HideInputView() override; + void SetMirroringEnabled(bool mirroring_enabled) override; + void SetCastingEnabled(bool casting_enabled) override; // This function returns the current property of the candidate window. // The caller can use the returned value as the default property and @@ -152,6 +154,12 @@ // Mapping of candidate id to index. std::map<int, int> candidate_indexes_; + + // Whether the screen is in mirroring mode. + bool is_mirroring_; + + // Whether the desktop is being casted. + bool is_casting_; }; } // namespace chromeos
diff --git a/chrome/browser/chromeos/input_method/input_method_engine_unittest.cc b/chrome/browser/chromeos/input_method/input_method_engine_unittest.cc index d20c681..f436f3e9 100644 --- a/chrome/browser/chromeos/input_method/input_method_engine_unittest.cc +++ b/chrome/browser/chromeos/input_method/input_method_engine_unittest.cc
@@ -117,6 +117,7 @@ const std::vector<gfx::Rect>& bounds) override { calls_bitmap_ |= ONCOMPOSITIONBOUNDSCHANGED; } + void OnScreenProjectionChanged(bool is_projected) override {} void OnReset(const std::string& engine_id) override { calls_bitmap_ |= RESET; engine_id_ = engine_id;
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc index 8a388d8..978eb3a 100644 --- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc +++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
@@ -130,7 +130,7 @@ } void InputMethodManagerImpl::StateImpl::InitFrom(const StateImpl& other) { - previous_input_method = other.previous_input_method; + last_used_input_method = other.last_used_input_method; current_input_method = other.current_input_method; active_input_method_ids = other.active_input_method_ids; @@ -156,8 +156,8 @@ << (profile ? profile->GetProfileUserName() : std::string("NULL")) << " #################\n"; - os << "previous_input_method: '" - << previous_input_method.GetPreferredKeyboardLayout() << "'\n"; + os << "last_used_input_method: '" + << last_used_input_method.GetPreferredKeyboardLayout() << "'\n"; os << "current_input_method: '" << current_input_method.GetPreferredKeyboardLayout() << "'\n"; os << "active_input_method_ids (size=" << active_input_method_ids.size() @@ -535,7 +535,7 @@ pending_input_method_id = input_method_id; if (descriptor->id() != current_input_method.id()) { - previous_input_method = current_input_method; + last_used_input_method = current_input_method; current_input_method = *descriptor; notify_menu = true; } @@ -822,22 +822,21 @@ current_input_method.id()); } -void InputMethodManagerImpl::StateImpl::SwitchToPreviousInputMethod() { +void InputMethodManagerImpl::StateImpl::SwitchToLastUsedInputMethod() { if (!CanCycleInputMethod()) return; - if (previous_input_method.id().empty() || - previous_input_method.id() == current_input_method.id()) { + if (last_used_input_method.id().empty() || + last_used_input_method.id() == current_input_method.id()) { SwitchToNextInputMethod(); return; } std::vector<std::string>::const_iterator iter = - std::find(active_input_method_ids.begin(), - active_input_method_ids.end(), - previous_input_method.id()); + std::find(active_input_method_ids.begin(), active_input_method_ids.end(), + last_used_input_method.id()); if (iter == active_input_method_ids.end()) { - // previous_input_method is not supported. + // last_used_input_method is not supported. SwitchToNextInputMethod(); return; }
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.h b/chrome/browser/chromeos/input_method/input_method_manager_impl.h index 42ee467..94b652d 100644 --- a/chrome/browser/chromeos/input_method/input_method_manager_impl.h +++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.h
@@ -104,7 +104,7 @@ void SetInputMethodLoginDefaultFromVPD(const std::string& locale, const std::string& layout) override; void SwitchToNextInputMethod() override; - void SwitchToPreviousInputMethod() override; + void SwitchToLastUsedInputMethod() override; InputMethodDescriptor GetCurrentInputMethod() const override; bool ReplaceEnabledInputMethods( const std::vector<std::string>& new_active_input_method_ids) override; @@ -120,7 +120,7 @@ Profile* const profile; // The input method which was/is selected. - InputMethodDescriptor previous_input_method; + InputMethodDescriptor last_used_input_method; InputMethodDescriptor current_input_method; // The active input method ids cache.
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc index 87e5caa..ec7414f9fa 100644 --- a/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc +++ b/chrome/browser/chromeos/input_method/input_method_manager_impl_unittest.cc
@@ -999,7 +999,7 @@ manager_->RemoveObserver(&observer); } -TEST_F(InputMethodManagerImplTest, TestPreviousInputMethod) { +TEST_F(InputMethodManagerImplTest, TestLastUsedInputMethod) { TestObserver observer; InitComponentExtension(); manager_->AddObserver(&observer); @@ -1016,17 +1016,17 @@ EXPECT_EQ(ImeIdFromEngineId("xkb:us:intl:eng"), manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); EXPECT_EQ("us(intl)", keyboard_->last_layout_); - manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(); + manager_->GetActiveIMEState()->SwitchToLastUsedInputMethod(); EXPECT_TRUE(observer.last_show_message_); EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); EXPECT_EQ("us", keyboard_->last_layout_); - manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(); + manager_->GetActiveIMEState()->SwitchToLastUsedInputMethod(); EXPECT_TRUE(observer.last_show_message_); EXPECT_EQ(ImeIdFromEngineId("xkb:us:intl:eng"), manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); EXPECT_EQ("us(intl)", keyboard_->last_layout_); - manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(); + manager_->GetActiveIMEState()->SwitchToLastUsedInputMethod(); EXPECT_TRUE(observer.last_show_message_); EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); @@ -1041,12 +1041,12 @@ EXPECT_EQ(ImeIdFromEngineId("xkb:us:altgr-intl:eng"), manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); EXPECT_EQ("us(altgr-intl)", keyboard_->last_layout_); - manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(); + manager_->GetActiveIMEState()->SwitchToLastUsedInputMethod(); EXPECT_TRUE(observer.last_show_message_); EXPECT_EQ(ImeIdFromEngineId("xkb:us:intl:eng"), manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); EXPECT_EQ("us(intl)", keyboard_->last_layout_); - manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(); + manager_->GetActiveIMEState()->SwitchToLastUsedInputMethod(); EXPECT_TRUE(observer.last_show_message_); EXPECT_EQ(ImeIdFromEngineId("xkb:us:altgr-intl:eng"), manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); @@ -1069,8 +1069,8 @@ EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); - // Switching to previous does nothing. - manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(); + // Switching to last-used does nothing. + manager_->GetActiveIMEState()->SwitchToLastUsedInputMethod(); EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), manager_->GetActiveIMEState()->GetCurrentInputMethod().id()); }
diff --git a/chrome/browser/chromeos/input_method/mock_input_method_engine.cc b/chrome/browser/chromeos/input_method/mock_input_method_engine.cc index bf8f79d5..95ecaa8 100644 --- a/chrome/browser/chromeos/input_method/mock_input_method_engine.cc +++ b/chrome/browser/chromeos/input_method/mock_input_method_engine.cc
@@ -52,6 +52,10 @@ void MockInputMethodEngine::HideInputView() {} +void MockInputMethodEngine::SetMirroringEnabled(bool mirroring_enabled) {} + +void MockInputMethodEngine::SetCastingEnabled(bool casting_enabled) {} + void MockInputMethodEngine::FocusIn( const IMEEngineHandlerInterface::InputContext& input_context) {}
diff --git a/chrome/browser/chromeos/input_method/mock_input_method_engine.h b/chrome/browser/chromeos/input_method/mock_input_method_engine.h index 6eda6dcc..8c1571cf 100644 --- a/chrome/browser/chromeos/input_method/mock_input_method_engine.h +++ b/chrome/browser/chromeos/input_method/mock_input_method_engine.h
@@ -60,6 +60,8 @@ uint32_t offset_pos) override; void SetCompositionBounds(const std::vector<gfx::Rect>& bounds) override; void HideInputView() override; + void SetMirroringEnabled(bool mirroring_enabled) override; + void SetCastingEnabled(bool casting_enabled) override; std::string last_activated_property() const { return last_activated_property_;
diff --git a/chrome/browser/chromeos/lock_screen_apps/lock_screen_profile_creator_impl_unittest.cc b/chrome/browser/chromeos/lock_screen_apps/lock_screen_profile_creator_impl_unittest.cc index 388a495..ecbf76f 100644 --- a/chrome/browser/chromeos/lock_screen_apps/lock_screen_profile_creator_impl_unittest.cc +++ b/chrome/browser/chromeos/lock_screen_apps/lock_screen_profile_creator_impl_unittest.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/command_line.h" #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/ref_counted.h" @@ -30,11 +31,13 @@ #include "chrome/test/base/testing_profile.h" #include "components/arc/arc_service_manager.h" #include "components/arc/arc_session.h" +#include "components/crx_file/id_util.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/common/safe_browsing_prefs.h" #include "content/public/test/test_browser_thread_bundle.h" #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" +#include "extensions/common/switches.h" #include "extensions/common/value_builder.h" #include "testing/gtest/include/gtest/gtest.h" @@ -208,6 +211,9 @@ ~LockScreenProfileCreatorImplTest() override {} void SetUp() override { + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + extensions::switches::kWhitelistedExtensionID, + crx_file::id_util::GenerateId("test_app")); ASSERT_TRUE(user_data_dir_.CreateUniqueTempDir()); auto profile_manager = @@ -275,6 +281,7 @@ return extensions::ExtensionBuilder() .SetManifest(manifest_builder.Build()) + .SetID(crx_file::id_util::GenerateId("test_app")) .Build(); }
diff --git a/chrome/browser/chromeos/login/configuration_keys.cc b/chrome/browser/chromeos/login/configuration_keys.cc index d7bf773..d22894c 100644 --- a/chrome/browser/chromeos/login/configuration_keys.cc +++ b/chrome/browser/chromeos/login/configuration_keys.cc
@@ -82,6 +82,10 @@ // to perform specific enrollment-time actions (e.g. create robot accounts). const char kRestoreAfterRollback[] = "enrollmentRestoreAfterRollback"; +// String value containing an enrollment token that would be used during +// enrollment to identify organization device is enrolled into. +const char kEnrollmentToken[] = "enrollmentToken"; + // String value indicating which license type should automatically be used if // license selection is done on a client side. const char kEnrollmentLicenseType[] = "enrollmentLicenseType"; @@ -123,6 +127,8 @@ ConfigurationHandlerSide::HANDLER_CPP}, {kDeviceRequisition, ValueType::STRING, ConfigurationHandlerSide::HANDLER_CPP}, + {kEnrollmentToken, ValueType::STRING, + ConfigurationHandlerSide::HANDLER_CPP}, {kEnrollmentLicenseType, ValueType::STRING, ConfigurationHandlerSide::HANDLER_CPP}, {kEnrollmentLocation, ValueType::STRING, @@ -158,10 +164,8 @@ clone.RemoveKey(key.key); } } - valid = valid && clone.DictEmpty(); - for (const auto& item : clone.DictItems()) { - LOG(ERROR) << "Unknown configuration key " << item.first; - } + for (const auto& item : clone.DictItems()) + LOG(WARNING) << "Unknown configuration key " << item.first; return valid; }
diff --git a/chrome/browser/chromeos/login/configuration_keys.h b/chrome/browser/chromeos/login/configuration_keys.h index d163fd6b..8bc2ffc 100644 --- a/chrome/browser/chromeos/login/configuration_keys.h +++ b/chrome/browser/chromeos/login/configuration_keys.h
@@ -35,6 +35,7 @@ extern const char kWizardAutoEnroll[]; extern const char kRestoreAfterRollback[]; +extern const char kEnrollmentToken[]; extern const char kEnrollmentLicenseType[]; extern const char kEnrollmentAssetId[]; extern const char kEnrollmentLocation[];
diff --git a/chrome/browser/chromeos/login/easy_unlock/chrome_proximity_auth_client.cc b/chrome/browser/chromeos/login/easy_unlock/chrome_proximity_auth_client.cc index ebc74d0e..b60214e 100644 --- a/chrome/browser/chromeos/login/easy_unlock/chrome_proximity_auth_client.cc +++ b/chrome/browser/chromeos/login/easy_unlock/chrome_proximity_auth_client.cc
@@ -24,7 +24,6 @@ #include "components/cryptauth/cryptauth_client_impl.h" #include "components/cryptauth/cryptauth_device_manager.h" #include "components/cryptauth/cryptauth_enrollment_manager.h" -#include "components/cryptauth/local_device_data_provider.h" #include "components/prefs/pref_service.h" #include "components/version_info/version_info.h" #include "services/identity/public/cpp/identity_manager.h" @@ -120,14 +119,7 @@ } std::string ChromeProximityAuthClient::GetLocalDevicePublicKey() { - if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) { - return GetDeviceSyncClient()->GetLocalDeviceMetadata()->public_key(); - } else { - cryptauth::LocalDeviceDataProvider provider(GetCryptAuthService()); - std::string local_public_key; - provider.GetLocalDeviceData(&local_public_key, nullptr); - return local_public_key; - } + return GetDeviceSyncClient()->GetLocalDeviceMetadata()->public_key(); } cryptauth::CryptAuthService* ChromeProximityAuthClient::GetCryptAuthService() {
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.cc index f1b8c61..c0ae7d1 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.cc
@@ -47,7 +47,6 @@ #include "components/cryptauth/cryptauth_enrollment_manager.h" #include "components/cryptauth/cryptauth_enrollment_utils.h" #include "components/cryptauth/cryptauth_gcm_manager_impl.h" -#include "components/cryptauth/local_device_data_provider.h" #include "components/cryptauth/remote_device_loader.h" #include "components/cryptauth/secure_message_delegate_impl.h" #include "components/gcm_driver/gcm_profile_service.h" @@ -248,11 +247,8 @@ // When EasyUnlock is enabled, only one EasyUnlock host should exist. DCHECK(remote_devices.size() == 1u); - SetProximityAuthDevices( - GetAccountId(), remote_devices, - base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi) - ? device_sync_client_->GetLocalDeviceMetadata() - : base::nullopt); + SetProximityAuthDevices(GetAccountId(), remote_devices, + device_sync_client_->GetLocalDeviceMetadata()); // We need to store a copy of |local_and_remote_devices| in the TPM, so it can // be retrieved on the sign-in screen when a user session has not been started @@ -307,9 +303,9 @@ std::unique_ptr<base::ListValue> beacon_seed_list(new base::ListValue()); for (const auto& beacon_seed : device.beacon_seeds()) { std::string b64_beacon_seed; - base::Base64UrlEncode(beacon_seed.SerializeAsString(), - base::Base64UrlEncodePolicy::INCLUDE_PADDING, - &b64_beacon_seed); + base::Base64UrlEncode( + multidevice::ToCryptAuthSeed(beacon_seed).SerializeAsString(), + base::Base64UrlEncodePolicy::INCLUDE_PADDING, &b64_beacon_seed); beacon_seed_list->AppendString(b64_beacon_seed); } @@ -321,7 +317,7 @@ // This differentiates the local device from the remote device. bool unlock_key = device.GetSoftwareFeatureState( - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST) == + multidevice::SoftwareFeature::kSmartLockHost) == multidevice::SoftwareFeatureState::kEnabled; dict->SetBoolean(key_names::kKeyUnlockKey, unlock_key); @@ -530,7 +526,7 @@ device_sync_client_->GetSyncedDevices()) { multidevice::SoftwareFeatureState better_together_host_state = remote_device_ref.GetSoftwareFeatureState( - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + multidevice::SoftwareFeature::kBetterTogetherHost); // If there's any valid Better Together host, don't support legacy mode. if (better_together_host_state == multidevice::SoftwareFeatureState::kSupported || @@ -541,7 +537,7 @@ multidevice::SoftwareFeatureState easy_unlock_host_state = remote_device_ref.GetSoftwareFeatureState( - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST); + multidevice::SoftwareFeature::kSmartLockHost); if (easy_unlock_host_state == multidevice::SoftwareFeatureState::kSupported || easy_unlock_host_state == multidevice::SoftwareFeatureState::kEnabled) { @@ -828,7 +824,7 @@ multidevice::RemoteDeviceRefList unlock_keys; for (const auto& remote_device : device_sync_client_->GetSyncedDevices()) { bool unlock_key = remote_device.GetSoftwareFeatureState( - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST) == + multidevice::SoftwareFeature::kSmartLockHost) == multidevice::SoftwareFeatureState::kEnabled; if (unlock_key) unlock_keys.push_back(remote_device);
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.h b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.h index 6e0fd0e..91d7528 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.h +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.h
@@ -30,7 +30,6 @@ namespace cryptauth { class CryptAuthDeviceManager; class CryptAuthEnrollmentManager; -class LocalDeviceDataProvider; class RemoteDeviceLoader; } // namespace cryptauth @@ -185,10 +184,6 @@ // Loads the RemoteDevice instances from CryptAuth and local data. std::unique_ptr<cryptauth::RemoteDeviceLoader> remote_device_loader_; - // Provides local device information from CryptAuth. - std::unique_ptr<cryptauth::LocalDeviceDataProvider> - local_device_data_provider_; - // If a new RemoteDevice was synced while the screen is locked, we defer // loading the RemoteDevice until the screen is unlocked. For security, // this deferment prevents the lock screen from being changed by a network
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.cc index d9c5d62..8df7f61b 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.cc
@@ -115,9 +115,9 @@ // than outside the user session (sign-in). RemoteDevices are serialized as // protocol buffers inside the user session, but we have a custom serialization // scheme for sign-in due to slightly different data requirements. -std::vector<cryptauth::BeaconSeed> DeserializeBeaconSeeds( +std::vector<multidevice::BeaconSeed> DeserializeBeaconSeeds( const std::string& serialized_beacon_seeds) { - std::vector<cryptauth::BeaconSeed> beacon_seeds; + std::vector<multidevice::BeaconSeed> beacon_seeds; JSONStringValueDeserializer deserializer(serialized_beacon_seeds); std::string error; @@ -155,7 +155,8 @@ continue; } - beacon_seeds.push_back(beacon_seed); + beacon_seeds.push_back( + chromeos::multidevice::FromCryptAuthSeed(beacon_seed)); } PA_LOG(VERBOSE) << "Deserialized " << beacon_seeds.size() << " BeaconSeeds."; @@ -518,13 +519,13 @@ continue; } - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState> + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState> software_features; - software_features[cryptauth::SoftwareFeature::EASY_UNLOCK_HOST] = + software_features[multidevice::SoftwareFeature::kSmartLockHost] = device.unlock_key ? multidevice::SoftwareFeatureState::kEnabled : multidevice::SoftwareFeatureState::kNotSupported; - std::vector<cryptauth::BeaconSeed> beacon_seeds; + std::vector<multidevice::BeaconSeed> beacon_seeds; if (!device.serialized_beacon_seeds.empty()) { PA_LOG(VERBOSE) << "Deserializing BeaconSeeds: " << device.serialized_beacon_seeds; @@ -579,9 +580,9 @@ for (const auto& remote_device : remote_devices) { if (base::ContainsKey(remote_device.software_features, - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST) && + multidevice::SoftwareFeature::kSmartLockHost) && remote_device.software_features.at( - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST) == + multidevice::SoftwareFeature::kSmartLockHost) == multidevice::SoftwareFeatureState::kEnabled) { if (!unlock_key_id.empty()) { PA_LOG(ERROR) << "Only one of the devices should be an unlock key.";
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_user_login_flow.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_user_login_flow.cc index 2729509..fc6acf6 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_user_login_flow.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_user_login_flow.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_user_login_flow.h" +#include "base/metrics/histogram_macros.h" #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" @@ -31,6 +32,9 @@ } bool EasyUnlockUserLoginFlow::HandleLoginFailure(const AuthFailure& failure) { + UMA_HISTOGRAM_ENUMERATION( + "SmartLock.AuthResult.SignIn.Failure.UserControllerAuth", + failure.reason(), AuthFailure::FailureReason::NUM_FAILURE_REASONS); Profile* profile = ProfileHelper::GetSigninProfile(); EasyUnlockService* service = EasyUnlockService::Get(profile); if (!service)
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc b/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc index ceea5c8..1789ade 100644 --- a/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc +++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc
@@ -236,7 +236,14 @@ elapsed_timer_.reset(new base::ElapsedTimer()); view_->Show(); CreateEnrollmentHelper(); - enrollment_helper_->EnrollUsingAttestation(); + if (enrollment_config_.mode == + policy::EnrollmentConfig::MODE_ATTESTATION_ENROLLMENT_TOKEN) { + view_->ShowEnrollmentSpinnerScreen(); + enrollment_helper_->EnrollUsingEnrollmentToken( + enrollment_config_.enrollment_token); + } else { + enrollment_helper_->EnrollUsingAttestation(); + } } void EnrollmentScreen::OnLoginDone(const std::string& user,
diff --git a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc index c0d6a07a..c1fb80c 100644 --- a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc +++ b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
@@ -626,14 +626,9 @@ } void SetUpCommandLine(base::CommandLine* command_line) override { - const ::testing::TestInfo* const test_info = - ::testing::UnitTest::GetInstance()->current_test_info(); - const std::string filename = std::string(test_info->name()) + ".json"; - // File name is based on the test name. base::FilePath file; - ASSERT_TRUE(chromeos::test_utils::GetTestDataPath("oobe_configuration", - filename, &file)); + ASSERT_TRUE(GetTestFileName(".json", &file)); command_line->AppendSwitchPath(chromeos::switches::kFakeOobeConfiguration, file); @@ -641,10 +636,19 @@ command_line->AppendSwitch(chromeos::switches::kEnableOfflineDemoMode); command_line->AppendSwitchASCII(switches::kArcAvailability, "officially-supported"); - EnterpriseEnrollmentTestBase::SetUpCommandLine(command_line); } + // Stores a name of the configuration (actual test name followed by |prefix|) + // to |file|. + // Returns true iff |file| exists. + bool GetTestFileName(const std::string& suffix, base::FilePath* file) { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + const std::string filename = std::string(test_info->name()) + suffix; + return test_utils::GetTestDataPath("oobe_configuration", filename, file); + } + // Overridden from InProcessBrowserTest: void SetUpOnMainThread() override { // Set up fake networks. @@ -672,6 +676,19 @@ EnterpriseEnrollmentTestBase::TearDownOnMainThread(); } + // Set up expectations for token enrollment. + void ExpectTokenEnrollment() { + AddEnrollmentSetupFunction( + [](EnterpriseEnrollmentHelperMock* enrollment_helper) { + EXPECT_CALL(*enrollment_helper, + EnrollUsingEnrollmentToken( + "00000000-1111-2222-3333-444444444444")) + .WillOnce(InvokeWithoutArgs([enrollment_helper]() { + enrollment_helper->status_consumer()->OnDeviceEnrolled(""); + })); + }); + } + protected: // Owned by DBusThreadManagerSetter chromeos::FakeUpdateEngineClient* fake_update_engine_client_; @@ -1097,4 +1114,16 @@ EXPECT_EQ(policy_manager->GetDeviceRequisition(), "some_requisition"); } +// Check that configuration allows to skip Update screen and get to Enrollment +// screen. +IN_PROC_BROWSER_TEST_F(EnterpriseEnrollmentConfigurationTest, + TestEnrollUsingToken) { + ExpectTokenEnrollment(); + DisableAttributePromptUpdate(); + LoadConfiguration(); + OobeScreenWaiter(OobeScreen::SCREEN_OOBE_ENROLLMENT).Wait(); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(IsStepDisplayed("success")); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/lock/DEPS b/chrome/browser/chromeos/login/lock/DEPS deleted file mode 100644 index fe6ff907..0000000 --- a/chrome/browser/chromeos/login/lock/DEPS +++ /dev/null
@@ -1,6 +0,0 @@ -specific_include_rules = { - # TODO(jdufault): This code is deprecated and will be removed. - "webui_screen_locker\.h": [ - "+ash/login/ui/lock_window.h", - ], -}
diff --git a/chrome/browser/chromeos/login/lock/webui_screen_locker.cc b/chrome/browser/chromeos/login/lock/webui_screen_locker.cc index d0e807e..951ffe6 100644 --- a/chrome/browser/chromeos/login/lock/webui_screen_locker.cc +++ b/chrome/browser/chromeos/login/lock/webui_screen_locker.cc
@@ -6,6 +6,7 @@ #include "ash/public/cpp/ash_pref_names.h" #include "ash/public/cpp/ash_switches.h" +#include "ash/public/cpp/lock_screen_widget_factory.h" #include "base/command_line.h" #include "base/feature_list.h" #include "base/metrics/histogram_macros.h" @@ -47,6 +48,7 @@ #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/views/controls/webview/webview.h" +#include "ui/views/widget/widget.h" namespace { @@ -117,6 +119,9 @@ screen_locker_(screen_locker), network_state_helper_(new login::NetworkStateHelper), weak_factory_(this) { + // This class is a View, and contained in a view hierarchy, but also owned. + // Use set_owned_by_client() so it isn't deleted by Views. + set_owned_by_client(); set_should_emit_login_prompt_visible(false); display::Screen::GetScreen()->AddObserver(this); DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this); @@ -125,11 +130,6 @@ WebUIScreenLocker::~WebUIScreenLocker() { DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this); display::Screen::GetScreen()->RemoveObserver(this); - // In case of shutdown, lock_window_ may be deleted before WebUIScreenLocker. - if (lock_window_) { - lock_window_->RemoveObserver(this); - lock_window_->Close(); - } // If LockScreen() was called, we need to clear the signin screen handler // delegate set in ShowSigninScreen so that it no longer points to us. if (login_display_.get() && GetOobeUI()) @@ -138,21 +138,23 @@ ClearLockScreenAppFocusCyclerDelegate(); RequestPreload(); + + // This has to be after calls to GetOobeUI(). + lock_widget_.reset(); } void WebUIScreenLocker::LockScreen() { gfx::Rect bounds = display::Screen::GetScreen()->GetPrimaryDisplay().bounds(); lock_time_ = base::TimeTicks::Now(); - lock_window_ = new ash::LockWindow(); - lock_window_->AddObserver(this); + lock_widget_ = ash::CreateLockScreenWidget(); Init(); content::WebContentsObserver::Observe(web_view()->GetWebContents()); - lock_window_->SetContentsView(this); - lock_window_->SetBounds(bounds); - lock_window_->Show(); + lock_widget_->SetContentsView(this); + lock_widget_->SetBounds(bounds); + lock_widget_->Show(); LoadURL(GURL(kLoginURL)); OnLockWindowReady(); @@ -199,7 +201,7 @@ } gfx::NativeWindow WebUIScreenLocker::GetNativeWindow() const { - return lock_window_->GetNativeWindow(); + return lock_widget_->GetNativeWindow(); } void WebUIScreenLocker::FocusUserPod() { @@ -319,14 +321,6 @@ } //////////////////////////////////////////////////////////////////////////////// -// WidgetObserver: - -void WebUIScreenLocker::OnWidgetDestroying(views::Widget* widget) { - lock_window_->RemoveObserver(this); - lock_window_ = nullptr; -} - -//////////////////////////////////////////////////////////////////////////////// // PowerManagerClient::Observer: void WebUIScreenLocker::LidEventReceived(PowerManagerClient::LidState state,
diff --git a/chrome/browser/chromeos/login/lock/webui_screen_locker.h b/chrome/browser/chromeos/login/lock/webui_screen_locker.h index cdbe01c..ba0c3b87 100644 --- a/chrome/browser/chromeos/login/lock/webui_screen_locker.h +++ b/chrome/browser/chromeos/login/lock/webui_screen_locker.h
@@ -10,7 +10,6 @@ #include <memory> #include <string> -#include "ash/login/ui/lock_window.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" @@ -22,13 +21,15 @@ #include "chromeos/dbus/power_manager_client.h" #include "content/public/browser/web_contents_observer.h" #include "ui/display/display_observer.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_observer.h" namespace content { class WebUI; } +namespace views { +class Widget; +} + namespace chromeos { class ScreenLocker; @@ -42,7 +43,6 @@ class WebUIScreenLocker : public WebUILoginView, public ScreenLocker::Delegate, public LoginDisplay::Delegate, - public views::WidgetObserver, public PowerManagerClient::Observer, public display::DisplayObserver, public content::WebContentsObserver { @@ -97,9 +97,6 @@ void ResetAutoLoginTimer() override; void Signout() override; - // WidgetObserver: - void OnWidgetDestroying(views::Widget* widget) override; - // PowerManagerClient::Observer: void SuspendImminent(power_manager::SuspendImminent::Reason reason) override; void SuspendDone(const base::TimeDelta& sleep_duration) override; @@ -134,8 +131,8 @@ // The ScreenLocker that owns this instance. ScreenLocker* screen_locker_ = nullptr; - // The screen locker window. - ash::LockWindow* lock_window_ = nullptr; + // The screen locker widget. + std::unique_ptr<views::Widget> lock_widget_; // Sign-in Screen controller instance (owns login screens). std::unique_ptr<SignInScreenController> signin_screen_controller_;
diff --git a/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc b/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc index 638e9bb..252e834d 100644 --- a/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc +++ b/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc
@@ -29,7 +29,6 @@ base::TimeDelta::FromMilliseconds(200); constexpr base::TimeDelta kLoginDisplayHostCheckFrequency = base::TimeDelta::FromMilliseconds(200); -} // namespace // Waits for js condition to be fulfilled. class JsConditionWaiter { @@ -130,6 +129,8 @@ ScopedQuickUnlockPrivateGetAuthTokenFunctionObserver); }; +} // namespace + class OobeInteractiveUITest : public OobeBaseTest, public extensions::QuickUnlockPrivateGetAuthTokenFunction::TestObserver,
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index 7158f93..94da5839 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -2112,6 +2112,18 @@ if (restore_after_rollback_value && restore_after_rollback_value->GetBool()) effective_config.mode = policy::EnrollmentConfig::MODE_ENROLLED_ROLLBACK; + // If enrollment token is specified via OOBE configuration use corresponding + // configuration. + auto* enrollment_token = oobe_configuration_.FindKeyOfType( + configuration::kEnrollmentToken, base::Value::Type::STRING); + if (enrollment_token && !enrollment_token->GetString().empty()) { + effective_config.mode = + policy::EnrollmentConfig::MODE_ATTESTATION_ENROLLMENT_TOKEN; + effective_config.auth_mechanism = + policy::EnrollmentConfig::AUTH_MECHANISM_ATTESTATION; + effective_config.enrollment_token = enrollment_token->GetString(); + } + EnrollmentScreen* screen = EnrollmentScreen::Get(screen_manager()); screen->SetParameters(effective_config, shark_controller_.get()); UpdateStatusAreaVisibilityForScreen(OobeScreen::SCREEN_OOBE_ENROLLMENT);
diff --git a/chrome/browser/chromeos/policy/enrollment_config.h b/chrome/browser/chromeos/policy/enrollment_config.h index f611ca3..092f1f6 100644 --- a/chrome/browser/chromeos/policy/enrollment_config.h +++ b/chrome/browser/chromeos/policy/enrollment_config.h
@@ -156,6 +156,9 @@ // The realm the device is joined to (if managed by AD). std::string management_realm; + // Enrollment token to use for authentication (for USB-enrollment). + std::string enrollment_token; + // The authentication mechanism to use. // TODO(drcrash): Change to best available once ZTE is everywhere. AuthMechanism auth_mechanism = AUTH_MECHANISM_INTERACTIVE;
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc index 6c09887..ad04f9a6 100644 --- a/chrome/browser/chromeos/preferences.cc +++ b/chrome/browser/chromeos/preferences.cc
@@ -304,7 +304,7 @@ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF | PrefRegistry::PUBLIC); registry->RegisterBooleanPref( ash::prefs::kAccessibilitySwitchAccessEnabled, false, - user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF | PrefRegistry::PUBLIC); registry->RegisterBooleanPref( ash::prefs::kShouldAlwaysShowAccessibilityMenu, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
diff --git a/chrome/browser/chromeos/tether/tether_service_unittest.cc b/chrome/browser/chromeos/tether/tether_service_unittest.cc index f5039e8..7f72b1c 100644 --- a/chrome/browser/chromeos/tether/tether_service_unittest.cc +++ b/chrome/browser/chromeos/tether/tether_service_unittest.cc
@@ -23,6 +23,7 @@ #include "chromeos/chromeos_features.h" #include "chromeos/chromeos_switches.h" #include "chromeos/components/multidevice/remote_device_test_util.h" +#include "chromeos/components/multidevice/software_feature.h" #include "chromeos/components/tether/fake_notification_presenter.h" #include "chromeos/components/tether/fake_tether_component.h" #include "chromeos/components/tether/fake_tether_host_fetcher.h" @@ -79,7 +80,7 @@ chromeos::multidevice::RemoteDeviceRefBuilder() .SetSupportsMobileHotspot(true) .SetSoftwareFeatureState( - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, + chromeos::multidevice::SoftwareFeature::kBetterTogetherHost, chromeos::multidevice::SoftwareFeatureState::kSupported) .Build()); }
diff --git a/chrome/browser/devtools/device/android_device_manager.cc b/chrome/browser/devtools/device/android_device_manager.cc index 8a7cb18a..2d6c4ed 100644 --- a/chrome/browser/devtools/device/android_device_manager.cc +++ b/chrome/browser/devtools/device/android_device_manager.cc
@@ -339,16 +339,15 @@ const DeviceProviders& providers, const DescriptorsCallback& callback) { // Don't keep counted reference on calling thread; - DevicesRequest* request = new DevicesRequest(callback); - // Avoid destruction while sending requests - request->AddRef(); + scoped_refptr<DevicesRequest> request = + base::WrapRefCounted(new DevicesRequest(callback)); for (auto it = providers.begin(); it != providers.end(); ++it) { device_task_runner->PostTask( FROM_HERE, base::BindOnce(&DeviceProvider::QueryDevices, *it, base::Bind(&DevicesRequest::ProcessSerials, request, *it))); } - device_task_runner->ReleaseSoon(FROM_HERE, request); + device_task_runner->ReleaseSoon(FROM_HERE, std::move(request)); } private: @@ -554,10 +553,7 @@ void AndroidDeviceManager::SetDeviceProviders( const DeviceProviders& providers) { for (auto it = providers_.begin(); it != providers_.end(); ++it) { - (*it)->AddRef(); - DeviceProvider* raw_ptr = it->get(); - *it = nullptr; - handler_thread_->message_loop()->ReleaseSoon(FROM_HERE, raw_ptr); + handler_thread_->message_loop()->ReleaseSoon(FROM_HERE, std::move(*it)); } providers_ = providers; }
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc index f324829..c9cf0a2 100644 --- a/chrome/browser/download/download_browsertest.cc +++ b/chrome/browser/download/download_browsertest.cc
@@ -3274,7 +3274,7 @@ EXPECT_NE(DownloadItem::CANCELLED, download_item->GetState()); download_item->Pause(); EXPECT_TRUE(download_item->IsPaused()); - download_item->Resume(); + download_item->Resume(false); EXPECT_FALSE(download_item->IsPaused()); EXPECT_NE(DownloadItem::CANCELLED, download_item->GetState()); download_item->Cancel(true); @@ -3360,7 +3360,7 @@ error_injector.get(), download::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); ASSERT_TRUE(download); - download->Resume(); + download->Resume(false); completion_observer->WaitForFinished(); EXPECT_EQ( @@ -3383,7 +3383,7 @@ error_injector.get(), download::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE); ASSERT_TRUE(download); - download->Resume(); + download->Resume(true); completion_observer->WaitForFinished(); EXPECT_EQ( @@ -3410,7 +3410,7 @@ // Prompts the user initially because of the kPromptForDownload preference. EXPECT_TRUE(DidShowFileChooser()); - download->Resume(); + download->Resume(true); completion_observer->WaitForFinished(); EXPECT_EQ( @@ -3439,7 +3439,7 @@ std::unique_ptr<content::DownloadTestObserver> completion_observer( CreateWaiter(browser(), 1)); - download->Resume(); + download->Resume(true); completion_observer->WaitForFinished(); // Automatic resumption causes download target determination to be run @@ -3474,7 +3474,7 @@ // Resuming should cause the download to be interrupted again due to the // errors we are injecting. - download->Resume(); + download->Resume(false); resumable_observer->WaitForFinished(); ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState()); ASSERT_EQ(download::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, @@ -3485,7 +3485,7 @@ // No errors this time. The download should complete successfully. EXPECT_FALSE(completion_observer->IsFinished()); completion_observer->StartObserving(); - download->Resume(); + download->Resume(false); completion_observer->WaitForFinished(); EXPECT_EQ(DownloadItem::COMPLETE, download->GetState());
diff --git a/chrome/browser/download/download_commands_unittest.cc b/chrome/browser/download/download_commands_unittest.cc index fd315a8..81ee95f 100644 --- a/chrome/browser/download/download_commands_unittest.cc +++ b/chrome/browser/download/download_commands_unittest.cc
@@ -155,7 +155,7 @@ TEST_F(DownloadCommandsTest, DoResume) { // Resume. - EXPECT_CALL(item(), Resume()).Times(1); + EXPECT_CALL(item(), Resume(true)).Times(1); commands().ExecuteCommand(DownloadCommands::RESUME); }
diff --git a/chrome/browser/download/download_item_model.cc b/chrome/browser/download/download_item_model.cc index faf7a2f..6e5d7f0 100644 --- a/chrome/browser/download/download_item_model.cc +++ b/chrome/browser/download/download_item_model.cc
@@ -442,7 +442,7 @@ } void DownloadItemModel::Resume() { - download_->Resume(); + download_->Resume(true /* has_user_gesture */); } void DownloadItemModel::Cancel(bool user_cancel) {
diff --git a/chrome/browser/download/download_offline_content_provider.cc b/chrome/browser/download/download_offline_content_provider.cc index 5a4ae26de..e499bed 100644 --- a/chrome/browser/download/download_offline_content_provider.cc +++ b/chrome/browser/download/download_offline_content_provider.cc
@@ -85,7 +85,7 @@ bool has_user_gesture) { download::DownloadItem* item = manager_->GetDownloadByGuid(id.id); if (item) - item->Resume(); + item->Resume(has_user_gesture); } void DownloadOfflineContentProvider::GetItemById(
diff --git a/chrome/browser/download/download_prefs.cc b/chrome/browser/download/download_prefs.cc index a845af5..d4f13a8 100644 --- a/chrome/browser/download/download_prefs.cc +++ b/chrome/browser/download/download_prefs.cc
@@ -136,6 +136,13 @@ file_manager::util::MigratePathFromOldFormat( profile_, current, &migrated)) { prefs->SetFilePath(path_pref[i], migrated); + + // In M73 migrate /home/chronos/u-<hash>/Downloads to + // /home/chronos/u-<hash>/MyFiles/Downloads. This code can be removed + // when M72 and earlier is no longer supported. + } else if (file_manager::util::MigrateFromDownloadsToMyFiles( + profile_, current, &migrated)) { + prefs->SetFilePath(path_pref[i], migrated); } }
diff --git a/chrome/browser/download/notification/download_item_notification_unittest.cc b/chrome/browser/download/notification/download_item_notification_unittest.cc index c14b74b..e11255e9 100644 --- a/chrome/browser/download/notification/download_item_notification_unittest.cc +++ b/chrome/browser/download/notification/download_item_notification_unittest.cc
@@ -178,7 +178,7 @@ download_item_->NotifyObserversDownloadUpdated(); // Resumes and makes sure the DownloadItem::Resume() is called. - EXPECT_CALL(*download_item_, Resume()).Times(1); + EXPECT_CALL(*download_item_, Resume(true)).Times(1); EXPECT_CALL(*download_item_, IsPaused()).WillRepeatedly(Return(false)); download_item_notification_->Click(0, base::nullopt); download_item_->NotifyObserversDownloadUpdated();
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc index 406f36bc..a5fb36a 100644 --- a/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc +++ b/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc
@@ -217,13 +217,12 @@ void DeclarativeContentCssConditionTracker::TrackForWebContents( content::WebContents* contents) { - per_web_contents_tracker_[contents] = - make_linked_ptr(new PerWebContentsTracker( - contents, - base::Bind(&Delegate::RequestEvaluation, base::Unretained(delegate_)), - base::Bind(&DeclarativeContentCssConditionTracker:: - DeletePerWebContentsTracker, - base::Unretained(this)))); + per_web_contents_tracker_[contents] = std::make_unique<PerWebContentsTracker>( + contents, + base::Bind(&Delegate::RequestEvaluation, base::Unretained(delegate_)), + base::Bind( + &DeclarativeContentCssConditionTracker::DeletePerWebContentsTracker, + base::Unretained(this))); // Note: the condition is always false until we receive OnWatchedPageChange, // so there's no need to evaluate it here. }
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.h b/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.h index e4845c1..028c569f 100644 --- a/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.h +++ b/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.h
@@ -14,7 +14,6 @@ #include "base/callback.h" #include "base/containers/hash_tables.h" #include "base/macros.h" -#include "base/memory/linked_ptr.h" #include "chrome/browser/extensions/api/declarative_content/content_predicate_evaluator.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" @@ -153,7 +152,7 @@ tracked_predicates_; // Maps WebContents to the tracker for that WebContents state. - std::map<content::WebContents*, linked_ptr<PerWebContentsTracker>> + std::map<content::WebContents*, std::unique_ptr<PerWebContentsTracker>> per_web_contents_tracker_; // Manages our notification registrations.
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker.cc index a72640d..faef055e 100644 --- a/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker.cc +++ b/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker.cc
@@ -190,13 +190,12 @@ void DeclarativeContentIsBookmarkedConditionTracker::TrackForWebContents( content::WebContents* contents) { - per_web_contents_tracker_[contents] = - make_linked_ptr(new PerWebContentsTracker( - contents, - base::Bind(&Delegate::RequestEvaluation, base::Unretained(delegate_)), - base::Bind(&DeclarativeContentIsBookmarkedConditionTracker:: + per_web_contents_tracker_[contents] = std::make_unique<PerWebContentsTracker>( + contents, + base::Bind(&Delegate::RequestEvaluation, base::Unretained(delegate_)), + base::Bind(&DeclarativeContentIsBookmarkedConditionTracker:: DeletePerWebContentsTracker, - base::Unretained(this)))); + base::Unretained(this))); } void DeclarativeContentIsBookmarkedConditionTracker::OnWebContentsNavigation(
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker.h b/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker.h index e8307fc5..ab38810 100644 --- a/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker.h +++ b/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker.h
@@ -10,7 +10,6 @@ #include "base/callback.h" #include "base/macros.h" -#include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" #include "base/scoped_observer.h" #include "chrome/browser/extensions/api/declarative_content/content_predicate_evaluator.h" @@ -150,8 +149,8 @@ Delegate* const delegate_; // Maps WebContents to the tracker for that WebContents state. - std::map<content::WebContents*, - linked_ptr<PerWebContentsTracker>> per_web_contents_tracker_; + std::map<content::WebContents*, std::unique_ptr<PerWebContentsTracker>> + per_web_contents_tracker_; // Count of the number of extensive bookmarks changes in progress (e.g. due to // sync). The rules need only be evaluated once after the extensive changes
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.cc index 0552501f..78586f8 100644 --- a/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.cc +++ b/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.cc
@@ -180,14 +180,12 @@ void DeclarativeContentPageUrlConditionTracker::TrackForWebContents( content::WebContents* contents) { - per_web_contents_tracker_[contents] = - make_linked_ptr(new PerWebContentsTracker( - contents, - &url_matcher_, - base::Bind(&Delegate::RequestEvaluation, base::Unretained(delegate_)), - base::Bind(&DeclarativeContentPageUrlConditionTracker:: + per_web_contents_tracker_[contents] = std::make_unique<PerWebContentsTracker>( + contents, &url_matcher_, + base::Bind(&Delegate::RequestEvaluation, base::Unretained(delegate_)), + base::Bind(&DeclarativeContentPageUrlConditionTracker:: DeletePerWebContentsTracker, - base::Unretained(this)))); + base::Unretained(this))); per_web_contents_tracker_[contents]->UpdateMatchesForCurrentUrl(true); }
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.h b/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.h index 82fe962..daf77cc 100644 --- a/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.h +++ b/chrome/browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker.h
@@ -11,7 +11,6 @@ #include "base/callback.h" #include "base/macros.h" -#include "base/memory/linked_ptr.h" #include "chrome/browser/extensions/api/declarative_content/content_predicate_evaluator.h" #include "components/url_matcher/url_matcher.h" #include "content/public/browser/web_contents_observer.h" @@ -136,8 +135,8 @@ tracked_predicates_; // Maps WebContents to the tracker for that WebContents state. - std::map<content::WebContents*, - linked_ptr<PerWebContentsTracker>> per_web_contents_tracker_; + std::map<content::WebContents*, std::unique_ptr<PerWebContentsTracker>> + per_web_contents_tracker_; DISALLOW_COPY_AND_ASSIGN(DeclarativeContentPageUrlConditionTracker); };
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc index f2e042c..3584296 100644 --- a/chrome/browser/extensions/api/downloads/downloads_api.cc +++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -1218,7 +1218,7 @@ } // Note that if the item isn't paused, this will be a no-op, and the extension // call will seem successful. - download_item->Resume(); + download_item->Resume(user_gesture()); RecordApiFunctions(DOWNLOADS_FUNCTION_RESUME); return RespondNow(NoArguments()); }
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc index 24b6417..0e303565 100644 --- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc +++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -4268,7 +4268,7 @@ // Downloads that are restarted on resumption trigger another download target // determination. RemoveFilenameDeterminer(host); - item->Resume(); + item->Resume(true); // Errors caught before filename determination is complete are delayed until // after filename determination so that, on resumption, filename determination
diff --git a/chrome/browser/extensions/api/identity/identity_api.cc b/chrome/browser/extensions/api/identity/identity_api.cc index cad20ee0..0f6accc6 100644 --- a/chrome/browser/extensions/api/identity/identity_api.cc +++ b/chrome/browser/extensions/api/identity/identity_api.cc
@@ -159,11 +159,8 @@ bool IdentityAPI::AreExtensionsRestrictedToPrimaryAccount() { #if BUILDFLAG(ENABLE_DICE_SUPPORT) - if (!signin::DiceMethodGreaterOrEqual( - AccountConsistencyModeManager::GetMethodForProfile(profile_), - signin::AccountConsistencyMethod::kDiceMigration)) { + if (!AccountConsistencyModeManager::IsDiceEnabledForProfile(profile_)) return true; - } return !base::FeatureList::IsEnabled(kExtensionsAllAccountsFeature); #else return true;
diff --git a/chrome/browser/extensions/api/identity/identity_api_unittest.cc b/chrome/browser/extensions/api/identity/identity_api_unittest.cc index ffb0cc7..8432fb2 100644 --- a/chrome/browser/extensions/api/identity/identity_api_unittest.cc +++ b/chrome/browser/extensions/api/identity/identity_api_unittest.cc
@@ -30,7 +30,7 @@ } { - ScopedAccountConsistencyDiceFixAuthErrors scoped_dice_fix_errors; + ScopedAccountConsistencyDiceMigration scoped_dice_migration; TestingProfile profile; IdentityAPI api(&profile); EXPECT_TRUE(api.AreExtensionsRestrictedToPrimaryAccount());
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc index 05d31c6..d1585d6 100644 --- a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc +++ b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
@@ -44,6 +44,8 @@ extensions::api::input_method_private::OnCompositionBoundsChanged; namespace NotifyImeMenuItemActivated = extensions::api::input_method_private::NotifyImeMenuItemActivated; +namespace OnScreenProjectionChanged = + extensions::api::input_method_private::OnScreenProjectionChanged; using ui::IMEEngineHandlerInterface; using input_method::InputMethodEngineBase; using chromeos::InputMethodEngine; @@ -166,6 +168,20 @@ input_ime::OnMenuItemActivated::kEventName, std::move(args)); } + void OnScreenProjectionChanged(bool is_projected) override { + if (extension_id_.empty() || + !HasListener(OnScreenProjectionChanged::kEventName)) { + return; + } + // Note: this is a private API event. + std::unique_ptr<base::ListValue> args(new base::ListValue()); + args->Append(std::make_unique<base::Value>(is_projected)); + + DispatchEventToExtension( + extensions::events::INPUT_METHOD_PRIVATE_ON_SCREEN_PROJECTION_CHANGED, + OnScreenProjectionChanged::kEventName, std::move(args)); + } + void OnCompositionBoundsChanged( const std::vector<gfx::Rect>& bounds) override { if (extension_id_.empty() ||
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc index babc823c..edb24bcb 100644 --- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc +++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
@@ -581,7 +581,8 @@ FROM_HERE, {BrowserThread::UI}, base::BindOnce(&WebRtcLoggingHandlerHost::StartEventLogging, webrtc_logging_handler_host, params->peer_connection_id, - params->max_log_size_bytes, params->web_app_id, callback)); + params->max_log_size_bytes, params->output_period_ms, + params->web_app_id, callback)); return true; }
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc index 9c7353c..547855e3 100644 --- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc +++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc
@@ -48,11 +48,14 @@ using extensions::WebrtcLoggingPrivateStoreFunction; using extensions::WebrtcLoggingPrivateUploadFunction; using extensions::WebrtcLoggingPrivateUploadStoredFunction; +using webrtc_event_logging::kMaxOutputPeriodMs; using webrtc_event_logging::kMaxRemoteLogFileSizeBytes; using webrtc_event_logging::kStartRemoteLoggingFailureAlreadyLogging; using webrtc_event_logging::kStartRemoteLoggingFailureFeatureDisabled; using webrtc_event_logging::kStartRemoteLoggingFailureMaxSizeTooLarge; using webrtc_event_logging::kStartRemoteLoggingFailureMaxSizeTooSmall; +using webrtc_event_logging::kStartRemoteLoggingFailureOutputPeriodMsIsNegative; +using webrtc_event_logging::kStartRemoteLoggingFailureOutputPeriodMsTooLarge; using webrtc_event_logging:: kStartRemoteLoggingFailureUnknownOrInactivePeerConnection; using webrtc_event_logging::kStartRemoteLoggingFailureUnlimitedSizeDisallowed; @@ -325,6 +328,7 @@ // TODO(crbug.com/829419): Return success/failure of the executed function. void StartEventLogging(const std::string& peerConnectionId, int maxLogSizeBytes, + int outputPeriodMs, int webAppId, bool expect_success, const std::string& expected_error = std::string()) { @@ -334,6 +338,7 @@ AppendTabIdAndUrl(¶ms); params.AppendString(peerConnectionId); params.AppendInteger(maxLogSizeBytes); + params.AppendInteger(outputPeriodMs); params.AppendInteger(webAppId); if (expect_success) { @@ -699,7 +704,8 @@ // from Finch *not* engaged, working in a profile where the policy is // configured). class WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled - : public WebrtcLoggingPrivateApiStartEventLoggingTestBase { + : public WebrtcLoggingPrivateApiStartEventLoggingTestBase, + public testing::WithParamInterface<bool> { public: ~WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled() override = default; @@ -710,15 +716,16 @@ }; // Also covers StartEventLoggingForLegalWebAppIdSucceeds scenario. -IN_PROC_BROWSER_TEST_F( +IN_PROC_BROWSER_TEST_P( WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled, StartEventLoggingForKnownPeerConnectionSucceeds) { const std::string peer_connection_id = "id"; SetUpPeerConnection(peer_connection_id); const int max_size_bytes = kMaxRemoteLogFileSizeBytes; constexpr bool expect_success = true; - StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId, - expect_success); + const int output_period_ms = GetParam() ? kMaxOutputPeriodMs : 0; + StartEventLogging(peer_connection_id, max_size_bytes, output_period_ms, + kWebAppId, expect_success); } IN_PROC_BROWSER_TEST_F( @@ -730,7 +737,7 @@ constexpr bool expect_success = false; const std::string error_message = kStartRemoteLoggingFailureUnlimitedSizeDisallowed; - StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId, + StartEventLogging(peer_connection_id, max_size_bytes, 0, kWebAppId, expect_success, error_message); } @@ -742,7 +749,7 @@ const int max_size_bytes = 1; constexpr bool expect_success = false; const std::string error_message = kStartRemoteLoggingFailureMaxSizeTooSmall; - StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId, + StartEventLogging(peer_connection_id, max_size_bytes, 0, kWebAppId, expect_success, error_message); } @@ -754,12 +761,38 @@ const int max_size_bytes = kMaxRemoteLogFileSizeBytes + 1; constexpr bool expect_success = false; const std::string error_message = kStartRemoteLoggingFailureMaxSizeTooLarge; - StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId, + StartEventLogging(peer_connection_id, max_size_bytes, 0, kWebAppId, expect_success, error_message); } IN_PROC_BROWSER_TEST_F( WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled, + StartEventLoggingWithNegativeOutputPeriodMsFails) { + const std::string peer_connection_id = "id"; + SetUpPeerConnection(peer_connection_id); + const int output_period_ms = -1; + constexpr bool expect_success = false; + const std::string error_message = + kStartRemoteLoggingFailureOutputPeriodMsIsNegative; + StartEventLogging(peer_connection_id, kMaxRemoteLogFileSizeBytes, + output_period_ms, kWebAppId, expect_success, error_message); +} + +IN_PROC_BROWSER_TEST_F( + WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled, + StartEventLoggingWithTooLargeOutputPeriodMsFails) { + const std::string peer_connection_id = "id"; + SetUpPeerConnection(peer_connection_id); + const int output_period_ms = kMaxOutputPeriodMs + 1; + constexpr bool expect_success = false; + const std::string error_message = + kStartRemoteLoggingFailureOutputPeriodMsTooLarge; + StartEventLogging(peer_connection_id, kMaxRemoteLogFileSizeBytes, + output_period_ms, kWebAppId, expect_success, error_message); +} + +IN_PROC_BROWSER_TEST_F( + WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled, StartEventLoggingForNeverAddedPeerConnectionFails) { // Note that manager->PeerConnectionAdded() is not called. const std::string peer_connection_id = "id"; @@ -767,7 +800,7 @@ constexpr bool expect_success = false; const std::string error_message = kStartRemoteLoggingFailureUnknownOrInactivePeerConnection; - StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId, + StartEventLogging(peer_connection_id, max_size_bytes, 0, kWebAppId, expect_success, error_message); } @@ -782,7 +815,7 @@ constexpr bool expect_success = false; const std::string error_message = kStartRemoteLoggingFailureUnknownOrInactivePeerConnection; - StartEventLogging(peer_connection_id_2, max_size_bytes, kWebAppId, + StartEventLogging(peer_connection_id_2, max_size_bytes, 0, kWebAppId, expect_success, error_message); } @@ -797,7 +830,7 @@ // First call succeeds. { constexpr bool expect_success = true; - StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId, + StartEventLogging(peer_connection_id, max_size_bytes, 0, kWebAppId, expect_success); } @@ -805,7 +838,7 @@ { constexpr bool expect_success = false; const std::string error_message = kStartRemoteLoggingFailureAlreadyLogging; - StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId, + StartEventLogging(peer_connection_id, max_size_bytes, 0, kWebAppId, expect_success, error_message); } } @@ -822,7 +855,7 @@ constexpr bool expect_success = false; const std::string error_message = webrtc_event_logging::kStartRemoteLoggingFailureIllegalWebAppId; - StartEventLogging(peer_connection_id, max_size_bytes, web_app_id, + StartEventLogging(peer_connection_id, max_size_bytes, 0, web_app_id, expect_success, error_message); } @@ -838,10 +871,15 @@ constexpr bool expect_success = false; const std::string error_message = webrtc_event_logging::kStartRemoteLoggingFailureIllegalWebAppId; - StartEventLogging(peer_connection_id, max_size_bytes, web_app_id, + StartEventLogging(peer_connection_id, max_size_bytes, 0, web_app_id, expect_success, error_message); } +INSTANTIATE_TEST_CASE_P( + _, + WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled, + ::testing::Bool()); + // Testing with either the feature or the policy disabled (not both). class WebrtcLoggingPrivateApiStartEventLoggingTestFeatureOrPolicyDisabled : public WebrtcLoggingPrivateApiStartEventLoggingTestBase, @@ -875,7 +913,7 @@ const int max_size_bytes = kMaxRemoteLogFileSizeBytes; constexpr bool expect_success = false; const std::string error_message = kStartRemoteLoggingFailureFeatureDisabled; - StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId, + StartEventLogging(peer_connection_id, max_size_bytes, 0, kWebAppId, expect_success, error_message); } @@ -916,7 +954,7 @@ const int max_size_bytes = kMaxRemoteLogFileSizeBytes; constexpr bool expect_success = false; const std::string error_message = kStartRemoteLoggingFailureFeatureDisabled; - StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId, + StartEventLogging(peer_connection_id, max_size_bytes, 0, kWebAppId, expect_success, error_message); }
diff --git a/chrome/browser/extensions/extension_context_menu_model.cc b/chrome/browser/extensions/extension_context_menu_model.cc index 486aa57d..baaaa68 100644 --- a/chrome/browser/extensions/extension_context_menu_model.cc +++ b/chrome/browser/extensions/extension_context_menu_model.cc
@@ -254,16 +254,25 @@ case UNINSTALL: return !IsExtensionRequiredByPolicy(extension, profile_); case PAGE_ACCESS_CANT_ACCESS: - // This menu item, by design, is never enabled. - return false; - // The following, if they are present, are always enabled. - case TOGGLE_VISIBILITY: - case MANAGE_EXTENSIONS: case PAGE_ACCESS_SUBMENU: case PAGE_ACCESS_RUN_ON_CLICK: case PAGE_ACCESS_RUN_ON_SITE: case PAGE_ACCESS_RUN_ON_ALL_SITES: - case PAGE_ACCESS_LEARN_MORE: + case PAGE_ACCESS_LEARN_MORE: { + content::WebContents* web_contents = GetActiveWebContents(); + if (!web_contents) + return false; + // TODO(devlin): This can lead to some fun race-like conditions, where the + // menu is constructed during navigation. Since we get the URL both here + // and in execution of the command, there's a chance we'll find two + // different URLs. This would be solved if we maintained the URL that the + // menu was showing for. + const GURL& url = web_contents->GetLastCommittedURL(); + return IsPageAccessCommandEnabled(*extension, url, command_id); + } + // The following, if they are present, are always enabled. + case TOGGLE_VISIBILITY: + case MANAGE_EXTENSIONS: return true; default: NOTREACHED() << "Unknown command" << command_id; @@ -443,6 +452,49 @@ return PAGE_ACCESS_RUN_ON_CLICK; } +bool ExtensionContextMenuModel::IsPageAccessCommandEnabled( + const Extension& extension, + const GURL& url, + int command_id) const { + // The "Can't access this site" entry is, by design, always disabled. + if (command_id == PAGE_ACCESS_CANT_ACCESS) + return false; + + ScriptingPermissionsModifier modifier(profile_, &extension); + DCHECK(modifier.CanAffectExtension()); + + ScriptingPermissionsModifier::SiteAccess site_access = + modifier.GetSiteAccess(url); + + // Verify the extension wants access to the page - that's the only time these + // commands should be shown. + DCHECK(site_access.has_site_access || site_access.withheld_site_access || + extension.permissions_data()->HasAPIPermission( + APIPermission::kActiveTab)); + + switch (command_id) { + case PAGE_ACCESS_SUBMENU: + case PAGE_ACCESS_LEARN_MORE: + case PAGE_ACCESS_RUN_ON_CLICK: + // These are always enabled. + return true; + case PAGE_ACCESS_RUN_ON_SITE: + // The "on this site" option is only enabled if the extension wants to + // always run on the site without user interaction. + return site_access.has_site_access || site_access.withheld_site_access; + case PAGE_ACCESS_RUN_ON_ALL_SITES: + // The "on all sites" option is only enabled if the extension wants to be + // able to run everywhere. + return site_access.has_all_sites_access || + site_access.withheld_all_sites_access; + default: + break; + } + + NOTREACHED() << "Unexpected command id: " << command_id; + return false; +} + void ExtensionContextMenuModel::CreatePageAccessSubmenu( const Extension* extension) { content::WebContents* web_contents = GetActiveWebContents(); @@ -457,7 +509,11 @@ ScriptingPermissionsModifier::SiteAccess site_access = modifier.GetSiteAccess(url); - if (!site_access.has_site_access && !site_access.withheld_site_access) { + bool has_active_tab = extension->permissions_data()->HasAPIPermission( + APIPermission::kActiveTab); + bool wants_site_access = + site_access.has_site_access || site_access.withheld_site_access; + if (!wants_site_access && !has_active_tab) { AddItemWithStringId(PAGE_ACCESS_CANT_ACCESS, IDS_EXTENSIONS_CONTEXT_MENU_CANT_ACCESS_PAGE); return; @@ -466,35 +522,25 @@ const int kRadioGroup = 0; page_access_submenu_ = std::make_unique<ui::SimpleMenuModel>(this); - // Only show the access controls if the extension either has or wants access - // to the site. - if (site_access.has_site_access || site_access.withheld_site_access) { - // Always show at least "on click" and "on this site" options. - page_access_submenu_->AddRadioItemWithStringId( - PAGE_ACCESS_RUN_ON_CLICK, - IDS_EXTENSIONS_CONTEXT_MENU_PAGE_ACCESS_RUN_ON_CLICK, kRadioGroup); - page_access_submenu_->AddRadioItem( - PAGE_ACCESS_RUN_ON_SITE, - l10n_util::GetStringFUTF16( - IDS_EXTENSIONS_CONTEXT_MENU_PAGE_ACCESS_RUN_ON_SITE, - url_formatter::StripWWW(base::UTF8ToUTF16( - url::Origin::Create(web_contents->GetLastCommittedURL()) - .host()))), - kRadioGroup); + // Add the three options for "on click", "on this site", "on all sites". + // Though we always add these three, some may be disabled. + page_access_submenu_->AddRadioItemWithStringId( + PAGE_ACCESS_RUN_ON_CLICK, + IDS_EXTENSIONS_CONTEXT_MENU_PAGE_ACCESS_RUN_ON_CLICK, kRadioGroup); + page_access_submenu_->AddRadioItem( + PAGE_ACCESS_RUN_ON_SITE, + l10n_util::GetStringFUTF16( + IDS_EXTENSIONS_CONTEXT_MENU_PAGE_ACCESS_RUN_ON_SITE, + url_formatter::StripWWW(base::UTF8ToUTF16( + url::Origin::Create(web_contents->GetLastCommittedURL()) + .host()))), + kRadioGroup); + page_access_submenu_->AddRadioItemWithStringId( + PAGE_ACCESS_RUN_ON_ALL_SITES, + IDS_EXTENSIONS_CONTEXT_MENU_PAGE_ACCESS_RUN_ON_ALL_SITES, kRadioGroup); - // Only show "on all sites" if the extension has or wants an all-sites-like - // permission. - if (site_access.has_all_sites_access || - site_access.withheld_all_sites_access) { - page_access_submenu_->AddRadioItemWithStringId( - PAGE_ACCESS_RUN_ON_ALL_SITES, - IDS_EXTENSIONS_CONTEXT_MENU_PAGE_ACCESS_RUN_ON_ALL_SITES, - kRadioGroup); - } - - page_access_submenu_->AddSeparator(ui::NORMAL_SEPARATOR); - } - + // Add the learn more link. + page_access_submenu_->AddSeparator(ui::NORMAL_SEPARATOR); page_access_submenu_->AddItemWithStringId( PAGE_ACCESS_LEARN_MORE, IDS_EXTENSIONS_CONTEXT_MENU_PAGE_ACCESS_LEARN_MORE);
diff --git a/chrome/browser/extensions/extension_context_menu_model.h b/chrome/browser/extensions/extension_context_menu_model.h index 2c1a0df..4ec65a1 100644 --- a/chrome/browser/extensions/extension_context_menu_model.h +++ b/chrome/browser/extensions/extension_context_menu_model.h
@@ -14,6 +14,7 @@ class Browser; class ExtensionAction; +class GURL; class Profile; namespace content { @@ -124,6 +125,11 @@ MenuEntries GetCurrentPageAccess(const Extension* extension, content::WebContents* web_contents) const; + // Returns true if the given page access command is enabled in the menu. + bool IsPageAccessCommandEnabled(const Extension& extension, + const GURL& url, + int command_id) const; + void HandlePageAccessCommand(int command_id, const Extension* extension) const;
diff --git a/chrome/browser/extensions/extension_context_menu_model_unittest.cc b/chrome/browser/extensions/extension_context_menu_model_unittest.cc index 9e3b35c..255c750c 100644 --- a/chrome/browser/extensions/extension_context_menu_model_unittest.cc +++ b/chrome/browser/extensions/extension_context_menu_model_unittest.cc
@@ -185,6 +185,12 @@ class ExtensionContextMenuModelTest : public ExtensionServiceTestBase { public: + enum class CommandState { + kAbsent, // The command is not present in the menu. + kEnabled, // The command is present, and enabled. + kDisabled, // The command is present, and disabled. + }; + ExtensionContextMenuModelTest(); // Build an extension to pass to the menu constructor, with the action @@ -206,10 +212,9 @@ // associated with it. content::WebContents* AddTab(const GURL& url); - // Returns true if the |menu| has the given |command| in the page access - // submenu. - bool HasPageAccessCommand(const ExtensionContextMenuModel& menu, - int command) const; + // Returns the current state for the specified page access |command|. + CommandState GetPageAccessCommandState(const ExtensionContextMenuModel& menu, + int command) const; // Returns true if the |menu| has the page access submenu at all. bool HasPageAccessSubmenu(const ExtensionContextMenuModel& menu) const; @@ -297,21 +302,28 @@ return raw_contents; } -bool ExtensionContextMenuModelTest::HasPageAccessCommand( +ExtensionContextMenuModelTest::CommandState +ExtensionContextMenuModelTest::GetPageAccessCommandState( const ExtensionContextMenuModel& menu, int command) const { int submenu_index = menu.GetIndexOfCommandId(ExtensionContextMenuModel::PAGE_ACCESS_SUBMENU); if (submenu_index == -1) - return false; + return CommandState::kAbsent; ui::MenuModel* submenu = menu.GetSubmenuModelAt(submenu_index); DCHECK(submenu); ui::MenuModel** menu_to_search = &submenu; int index_unused = 0; - return ui::MenuModel::GetModelAndIndexForCommandId(command, menu_to_search, - &index_unused); + if (!ui::MenuModel::GetModelAndIndexForCommandId(command, menu_to_search, + &index_unused)) { + return CommandState::kAbsent; + } + + // The command is present; determine if it's enabled. + return menu.IsCommandIdEnabled(command) ? CommandState::kEnabled + : CommandState::kDisabled; } bool ExtensionContextMenuModelTest::HasPageAccessSubmenu( @@ -942,6 +954,8 @@ GURL current_url; // The set of page access menu entries that should be present. std::set<Entries> expected_entries; + // The set of page access menu entries that should be enabled. + std::set<Entries> enabled_entries; // The selected page access menu entry. base::Optional<Entries> selected_entry; } test_cases[] = { @@ -950,11 +964,13 @@ {"https://google.com/maps", "https://google.com/maps", GURL("https://google.com/maps"), + {kOnClick, kOnSite, kOnAllSites}, {kOnClick, kOnSite}, kOnSite}, {"https://google.com/maps", base::nullopt, GURL("https://google.com/maps"), + {kOnClick, kOnSite, kOnAllSites}, {kOnClick, kOnSite}, kOnClick}, // We should display the page access controls if the extension wants to @@ -962,13 +978,14 @@ {"https://google.com/maps", "https://google.com/maps", GURL("https://google.com"), + {kOnClick, kOnSite, kOnAllSites}, {kOnClick, kOnSite}, kOnSite}, - // Only the learn more link should be visible if the extension cannot run - // on the origin. + // The menu should be hidden if the extension cannot run on the origin. {"https://google.com/maps", "https://google.com/maps", GURL("https://mail.google.com"), + {}, {}}, // An extension with all hosts granted should display the all sites // controls, even if it didn't request all sites. @@ -976,26 +993,31 @@ "*://*/*", GURL("https://mail.google.com"), {kOnClick, kOnSite, kOnAllSites}, + {kOnClick, kOnSite, kOnAllSites}, kOnAllSites}, // Subdomain pattern tests. {"https://*.google.com/*", "https://*.google.com/*", GURL("https://google.com"), + {kOnClick, kOnSite, kOnAllSites}, {kOnClick, kOnSite}, kOnSite}, {"https://*.google.com/*", base::nullopt, GURL("https://google.com"), + {kOnClick, kOnSite, kOnAllSites}, {kOnClick, kOnSite}, kOnClick}, {"https://*.google.com/*", "https://*.google.com/*", GURL("https://mail.google.com"), + {kOnClick, kOnSite, kOnAllSites}, {kOnClick, kOnSite}, kOnSite}, {"https://*.google.com/*", "https://google.com/*", GURL("https://mail.google.com"), + {kOnClick, kOnSite, kOnAllSites}, {kOnClick, kOnSite}, kOnClick}, // On sites the extension doesn't want to run on, no controls should be @@ -1009,6 +1031,7 @@ {"https://*.google.com/*", "https://*.example.com/*", GURL("https://example.com"), + {kOnClick, kOnSite, kOnAllSites}, {kOnClick, kOnSite}, kOnSite}, // All-hosts like permissions should be treated as if the extension @@ -1017,42 +1040,53 @@ "https://*/maps", GURL("https://google.com/maps"), {kOnClick, kOnSite, kOnAllSites}, + {kOnClick, kOnSite, kOnAllSites}, kOnAllSites}, {"https://*/maps", "https://google.com/*", GURL("https://google.com/maps"), {kOnClick, kOnSite, kOnAllSites}, + {kOnClick, kOnSite, kOnAllSites}, kOnSite}, {"https://*/maps", "https://*/maps", GURL("https://google.com"), {kOnClick, kOnSite, kOnAllSites}, + {kOnClick, kOnSite, kOnAllSites}, kOnAllSites}, {"https://*/maps", "https://*/maps", GURL("https://chromium.org"), {kOnClick, kOnSite, kOnAllSites}, + {kOnClick, kOnSite, kOnAllSites}, kOnAllSites}, {"https://*.com/*", "https://*.com/*", GURL("https://google.com"), {kOnClick, kOnSite, kOnAllSites}, + {kOnClick, kOnSite, kOnAllSites}, kOnAllSites}, {"https://*.com/*", "https://*.com/*", GURL("https://maps.google.com"), {kOnClick, kOnSite, kOnAllSites}, + {kOnClick, kOnSite, kOnAllSites}, kOnAllSites}, // Even with an all-hosts like pattern, we shouldn't show access controls // if the extension can't run on the origin (though we show the learn more // option). - {"https://*.com/*", "https://*.com/*", GURL("https://chromium.org"), {}}, + {"https://*.com/*", + "https://*.com/*", + GURL("https://chromium.org"), + {}, + {}}, // No access controls should ever show for restricted pages, like // chrome:-scheme pages or the webstore. - {"<all_urls>", "<all_urls>", GURL("chrome://extensions"), {}}, + {"<all_urls>", "<all_urls>", GURL("chrome://extensions"), {}, {}}, {"<all_urls>", "<all_urls>", ExtensionsClient::Get()->GetWebstoreBaseURL(), + {}, {}}, }; @@ -1109,15 +1143,23 @@ } // The learn more option should be visible whenever the menu is. - EXPECT_TRUE(HasPageAccessCommand(menu, kLearnMore)); + EXPECT_EQ(CommandState::kEnabled, + GetPageAccessCommandState(menu, kLearnMore)); + + auto get_expected_state = [test_case](Entries command) { + if (!test_case.expected_entries.count(command)) + return CommandState::kAbsent; + return test_case.enabled_entries.count(command) ? CommandState::kEnabled + : CommandState::kDisabled; + }; // Verify the menu options are what we expect. - EXPECT_EQ(test_case.expected_entries.count(kOnClick), - HasPageAccessCommand(menu, kOnClick)); - EXPECT_EQ(test_case.expected_entries.count(kOnSite), - HasPageAccessCommand(menu, kOnSite)); - EXPECT_EQ(test_case.expected_entries.count(kOnAllSites), - HasPageAccessCommand(menu, kOnAllSites)); + EXPECT_EQ(get_expected_state(kOnClick), + GetPageAccessCommandState(menu, kOnClick)); + EXPECT_EQ(get_expected_state(kOnSite), + GetPageAccessCommandState(menu, kOnSite)); + EXPECT_EQ(get_expected_state(kOnAllSites), + GetPageAccessCommandState(menu, kOnAllSites)); auto should_command_be_checked = [test_case](int command) { return test_case.selected_entry && *test_case.selected_entry == command; @@ -1145,6 +1187,42 @@ } } +TEST_F(ExtensionContextMenuModelTest, PageAccessWithActiveTab) { + // This test relies on the click-to-script feature. + auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>(); + scoped_feature_list->InitAndEnableFeature( + extensions_features::kRuntimeHostPermissions); + InitializeEmptyExtensionService(); + + // For laziness. + using Entries = ExtensionContextMenuModel::MenuEntries; + const Entries kOnClick = Entries::PAGE_ACCESS_RUN_ON_CLICK; + const Entries kOnSite = Entries::PAGE_ACCESS_RUN_ON_SITE; + const Entries kOnAllSites = Entries::PAGE_ACCESS_RUN_ON_ALL_SITES; + const Entries kLearnMore = Entries::PAGE_ACCESS_LEARN_MORE; + + // Add an extension that has activeTab. Note: we add permission for b.com so + // that the extension is seen as affectable by the runtime host permissions + // feature; otherwise the page access menu entry is omitted entirely. + // TODO(devlin): Should we change that? + scoped_refptr<const Extension> extension = + ExtensionBuilder("extension") + .AddPermissions({"activeTab", "http://b.com/*"}) + .Build(); + InitializeAndAddExtension(*extension); + + AddTab(GURL("https://a.com")); + + ExtensionContextMenuModel menu(extension.get(), GetBrowser(), + ExtensionContextMenuModel::VISIBLE, nullptr); + EXPECT_EQ(CommandState::kEnabled, GetPageAccessCommandState(menu, kOnClick)); + EXPECT_EQ(CommandState::kDisabled, GetPageAccessCommandState(menu, kOnSite)); + EXPECT_EQ(CommandState::kDisabled, + GetPageAccessCommandState(menu, kOnAllSites)); + EXPECT_EQ(CommandState::kEnabled, + GetPageAccessCommandState(menu, kLearnMore)); +} + TEST_F(ExtensionContextMenuModelTest, TestTogglingAccessWithSpecificSitesWithUnrequestedUrl) { // This test relies on the click-to-script feature. @@ -1188,13 +1266,18 @@ // a.com... EXPECT_TRUE(HasPageAccessSubmenu(menu)); EXPECT_FALSE(HasCantAccessPageEntry(menu)); - EXPECT_TRUE(HasPageAccessCommand(menu, kOnClick)); - EXPECT_TRUE(HasPageAccessCommand(menu, kOnSite)); - EXPECT_FALSE(HasPageAccessCommand(menu, kOnAllSites)); - EXPECT_TRUE(HasPageAccessCommand(menu, kLearnMore)); + + EXPECT_EQ(CommandState::kEnabled, + GetPageAccessCommandState(menu, kOnClick)); + EXPECT_EQ(CommandState::kEnabled, GetPageAccessCommandState(menu, kOnSite)); + EXPECT_EQ(CommandState::kDisabled, + GetPageAccessCommandState(menu, kOnAllSites)); + EXPECT_EQ(CommandState::kEnabled, + GetPageAccessCommandState(menu, kLearnMore)); EXPECT_TRUE(menu.IsCommandIdChecked(kOnSite)); EXPECT_FALSE(menu.IsCommandIdChecked(kOnClick)); + EXPECT_FALSE(menu.IsCommandIdChecked(kOnAllSites)); } const GURL b_com("https://b.com"); @@ -1222,10 +1305,13 @@ ExtensionContextMenuModel::VISIBLE, nullptr); EXPECT_TRUE(HasPageAccessSubmenu(menu)); EXPECT_FALSE(HasCantAccessPageEntry(menu)); - EXPECT_TRUE(HasPageAccessCommand(menu, kOnClick)); - EXPECT_TRUE(HasPageAccessCommand(menu, kOnSite)); - EXPECT_FALSE(HasPageAccessCommand(menu, kOnAllSites)); - EXPECT_TRUE(HasPageAccessCommand(menu, kLearnMore)); + EXPECT_EQ(CommandState::kEnabled, + GetPageAccessCommandState(menu, kOnClick)); + EXPECT_EQ(CommandState::kEnabled, GetPageAccessCommandState(menu, kOnSite)); + EXPECT_EQ(CommandState::kDisabled, + GetPageAccessCommandState(menu, kOnAllSites)); + EXPECT_EQ(CommandState::kEnabled, + GetPageAccessCommandState(menu, kLearnMore)); EXPECT_TRUE(menu.IsCommandIdChecked(kOnSite)); EXPECT_FALSE(menu.IsCommandIdChecked(kOnClick)); @@ -1279,9 +1365,10 @@ ExtensionContextMenuModel menu(extension.get(), GetBrowser(), ExtensionContextMenuModel::VISIBLE, nullptr); - EXPECT_TRUE(HasPageAccessCommand(menu, kOnClick)); - EXPECT_TRUE(HasPageAccessCommand(menu, kOnSite)); - EXPECT_FALSE(HasPageAccessCommand(menu, kOnAllSites)); + EXPECT_EQ(CommandState::kEnabled, GetPageAccessCommandState(menu, kOnClick)); + EXPECT_EQ(CommandState::kEnabled, GetPageAccessCommandState(menu, kOnSite)); + EXPECT_EQ(CommandState::kDisabled, + GetPageAccessCommandState(menu, kOnAllSites)); EXPECT_TRUE(menu.IsCommandIdChecked(kOnSite)); EXPECT_FALSE(menu.IsCommandIdChecked(kOnClick)); @@ -1325,8 +1412,8 @@ const ExtensionContextMenuModel::MenuEntries kLearnMore = ExtensionContextMenuModel::PAGE_ACCESS_LEARN_MORE; - EXPECT_TRUE(HasPageAccessCommand(menu, kLearnMore)); - EXPECT_TRUE(menu.IsCommandIdEnabled(kLearnMore)); + EXPECT_EQ(CommandState::kEnabled, + GetPageAccessCommandState(menu, kLearnMore)); menu.ExecuteCommand(kLearnMore, 0); EXPECT_EQ(2, browser->tab_strip_model()->count());
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc index 52e01ba..ffff05f 100644 --- a/chrome/browser/extensions/extension_service_unittest.cc +++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -146,6 +146,7 @@ #include "testing/platform_test.h" #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" +#include "url/origin.h" // The blacklist tests rely on the safe-browsing database. #if defined(SAFE_BROWSING_DB_LOCAL) @@ -4888,7 +4889,8 @@ // "known" origins. IndexedDBContext* idb_context = BrowserContext::GetDefaultStoragePartition( profile())->GetIndexedDBContext(); - base::FilePath idb_path = idb_context->GetFilePathForTesting(ext_url); + base::FilePath idb_path = + idb_context->GetFilePathForTesting(url::Origin::Create(ext_url)); EXPECT_TRUE(base::CreateDirectory(idb_path)); EXPECT_TRUE(base::DirectoryExists(idb_path)); idb_context->ResetCachesForTesting(); @@ -5031,7 +5033,8 @@ // "known" origins. IndexedDBContext* idb_context = BrowserContext::GetDefaultStoragePartition( profile())->GetIndexedDBContext(); - base::FilePath idb_path = idb_context->GetFilePathForTesting(origin1); + base::FilePath idb_path = + idb_context->GetFilePathForTesting(url::Origin::Create(origin1)); EXPECT_TRUE(base::CreateDirectory(idb_path)); EXPECT_TRUE(base::DirectoryExists(idb_path)); idb_context->ResetCachesForTesting();
diff --git a/chrome/browser/favicon/content_favicon_driver_browsertest.cc b/chrome/browser/favicon/content_favicon_driver_browsertest.cc index efc0766..07f3dbb 100644 --- a/chrome/browser/favicon/content_favicon_driver_browsertest.cc +++ b/chrome/browser/favicon/content_favicon_driver_browsertest.cc
@@ -713,7 +713,7 @@ // Observe the message for a blocked favicon. content::ConsoleObserverDelegate console_observer(web_contents(), - "*insecure*"); + "*icon.png*"); web_contents()->SetDelegate(&console_observer); // Observe if the favicon URL is requested.
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 86e7dad..e8c735992 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -232,6 +232,11 @@ "expiry_milestone": 76 }, { + "name": "autofill-always-show-server-cards-in-sync-transport", + "owners": [ "sebsg" ], + "expiry_milestone": 74 + }, + { "name": "autofill-cache-query-responses", "owners": [ "rogerm" ], "expiry_milestone": 72 @@ -457,6 +462,11 @@ "expiry_milestone": 76 }, { + "name": "crostini-files", + "owners": [ "joelhockey", "nverne", "benwells" ], + "expiry_milestone": 76 + }, + { "name": "crostini-usb-support", "owners": [ "jopra", "nverne", "benwells" ], "expiry_milestone": 76 @@ -527,11 +537,6 @@ "expiry_milestone": 76 }, { - "name": "disable-crostini-files", - "owners": [ "joelhockey", "nverne", "benwells" ], - "expiry_milestone": 76 - }, - { "name": "disable-eol-notification", // "owners": [ "your-team" ], "expiry_milestone": 76 @@ -774,6 +779,11 @@ "expiry_milestone": 76 }, { + "name": "enable-assistant-app-support", + "owners": [ "croissant-eng" ], + "expiry_milestone": 76 + }, + { "name": "enable-assistant-dsp", "owners": [ "croissant-eng" ], "expiry_milestone": 76 @@ -1204,11 +1214,6 @@ "expiry_milestone": 76 }, { - "name": "enable-fullscreen-in-tab-detaching", - // "owners": [ "your-team" ], - "expiry_milestone": 76 - }, - { "name": "enable-future-v8-vm-features", // "owners": [ "your-team" ], "expiry_milestone": 76 @@ -2220,6 +2225,11 @@ "expiry_milestone": 76 }, { + "name": "force-enable-system-aec", + "owners": [ "grunell" ], + "expiry_milestone": 80 + }, + { "name": "force-pnacl-subzero", // "owners": [ "your-team" ], "expiry_milestone": 76 @@ -2525,11 +2535,6 @@ "expiry_milestone": 73 }, { - "name": "ntp-ui-md", - "owners": [ "kmilka", "ramyan" ], - "expiry_milestone": 73 - }, - { "name": "num-raster-threads", // "owners": [ "your-team" ], "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 26a9ec48..c8f037b 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -88,6 +88,11 @@ const char kAsyncImageDecodingDescription[] = "Enables asynchronous decoding of images from raster for web content"; +extern const char kAutofillAlwaysShowServerCardsInSyncTransportName[] = + "AlwaysShowServerCardsInSyncTransport"; +extern const char kAutofillAlwaysShowServerCardsInSyncTransportDescription[] = + "Always show server cards when in sync transport mode for wallet data"; + const char kAutofillCacheQueryResponsesName[] = "Cache Autofill Query Responses"; const char kAutofillCacheQueryResponsesDescription[] = @@ -1138,11 +1143,6 @@ const char kIgnorePreviewsBlacklistDescription[] = "Ignore decisions made by the PreviewsBlockList"; -const char kImprovedLanguageSettingsName[] = "Improved Language Settings"; -const char kImprovedLanguageSettingsDescription[] = - "Set of changes for Language Settings. These changes are intended to fix " - "the major bugs related to Language Settings."; - const char kInProductHelpDemoModeChoiceName[] = "In-Product Help Demo Mode"; const char kInProductHelpDemoModeChoiceDescription[] = "Selects the In-Product Help demo mode."; @@ -1318,10 +1318,6 @@ "Show Material Design icons on the New Tab Page, instead of Most Visited " "tiles. Implicitly enables 'ntp-ui-md'."; -const char kNtpUIMdName[] = "New Tab Page Material Design UI"; -const char kNtpUIMdDescription[] = - "Updates the New Tab Page with Material Design elements."; - const char kNumRasterThreadsName[] = "Number of raster threads"; const char kNumRasterThreadsDescription[] = "Specify the number of raster threads."; @@ -1913,11 +1909,6 @@ "Refine the position of a touch gesture in order to compensate for touches " "having poor resolution compared to a mouse."; -const char kTouchableAppContextMenuName[] = "Touchable App Context Menu"; -const char kTouchableAppContextMenuDescription[] = - "Enable the touchable app context menu, which enlarges app context menus " - "in the Launcher and Shelf to make room for new features."; - const char kTouchDragDropName[] = "Touch initiated drag and drop"; const char kTouchDragDropDescription[] = "Touch drag and drop can be initiated through long press on a draggable " @@ -3040,9 +3031,6 @@ "Create native windows the app shim process, instead of of the browser " "process."; -const char kMacRTLName[] = "Enable RTL"; -const char kMacRTLDescription[] = "Mirrors the UI for RTL language users"; - const char kMacTouchBarName[] = "Hardware Touch Bar"; const char kMacTouchBarDescription[] = "Control the use of the Touch Bar."; @@ -3059,11 +3047,6 @@ const char kMacViewsTaskManagerDescription[] = "Controls whether to use the Toolkit-Views based Task Manager."; -const char kTabDetachingInFullscreenName[] = - "Allow tab detaching in fullscreen"; -const char kTabDetachingInFullscreenDescription[] = - "Allow tabs to detach from the tabstrip when in fullscreen mode on Mac."; - const char kTextSuggestionsTouchBarName[] = "Text Suggestions Touch Bar"; const char kTextSuggestionsTouchBarDescription[] = "Enable text suggestions touch bar for textfields."; @@ -3283,6 +3266,10 @@ const char kEnableAssistantVoiceMatchDescription[] = "Enable the Assistant Voice Match feature"; +const char kEnableAssistantAppSupportName[] = "Enable Assistant App Support"; +const char kEnableAssistantAppSupportDescription[] = + "Enable the Assistant App Support feature"; + const char kEnableBackgroundBlurName[] = "Enable background blur."; const char kEnableBackgroundBlurDescription[] = "Enables background blur for the Peeking Launcher and Tab Switcher."; @@ -3709,6 +3696,16 @@ #endif // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) +#if defined(OS_MACOSX) || defined(OS_CHROMEOS) + +const char kForceEnableSystemAecName[] = "Force enable system AEC"; +const char kForceEnableSystemAecDescription[] = + "Use system echo canceller instead of WebRTC echo canceller. If there is " + "no system echo canceller available, getUserMedia with echo cancellation " + "enabled will fail."; + +#endif // defined(OS_MACOSX) || defined(OS_CHROMEOS) + const char kExperimentalUiName[] = "Use all upcoming UI features"; const char kExperimentalUiDescription[] = "Use all upcoming UI features.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 2128b41a..f7e5f41 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -80,6 +80,9 @@ extern const char kAsyncImageDecodingName[]; extern const char kAsyncImageDecodingDescription[]; +extern const char kAutofillAlwaysShowServerCardsInSyncTransportName[]; +extern const char kAutofillAlwaysShowServerCardsInSyncTransportDescription[]; + extern const char kAutofillCacheQueryResponsesName[]; extern const char kAutofillCacheQueryResponsesDescription[]; @@ -690,9 +693,6 @@ extern const char kIgnorePreviewsBlacklistName[]; extern const char kIgnorePreviewsBlacklistDescription[]; -extern const char kImprovedLanguageSettingsName[]; -extern const char kImprovedLanguageSettingsDescription[]; - extern const char kInProductHelpDemoModeChoiceName[]; extern const char kInProductHelpDemoModeChoiceDescription[]; @@ -807,9 +807,6 @@ extern const char kNtpIconsName[]; extern const char kNtpIconsDescription[]; -extern const char kNtpUIMdName[]; -extern const char kNtpUIMdDescription[]; - extern const char kNumRasterThreadsName[]; extern const char kNumRasterThreadsDescription[]; extern const char kNumRasterThreadsOne[]; @@ -1149,9 +1146,6 @@ extern const char kTouchAdjustmentName[]; extern const char kTouchAdjustmentDescription[]; -extern const char kTouchableAppContextMenuName[]; -extern const char kTouchableAppContextMenuDescription[]; - extern const char kTouchDragDropName[]; extern const char kTouchDragDropDescription[]; @@ -1807,9 +1801,6 @@ extern const char kCreateAppWindowsInAppShimProcessName[]; extern const char kCreateAppWindowsInAppShimProcessDescription[]; -extern const char kMacRTLName[]; -extern const char kMacRTLDescription[]; - extern const char kMacTouchBarName[]; extern const char kMacTouchBarDescription[]; @@ -1822,9 +1813,6 @@ extern const char kMacViewsTaskManagerName[]; extern const char kMacViewsTaskManagerDescription[]; -extern const char kTabDetachingInFullscreenName[]; -extern const char kTabDetachingInFullscreenDescription[]; - extern const char kTextSuggestionsTouchBarName[]; extern const char kTextSuggestionsTouchBarDescription[]; @@ -1976,6 +1964,9 @@ extern const char kEnableAssistantVoiceMatchName[]; extern const char kEnableAssistantVoiceMatchDescription[]; +extern const char kEnableAssistantAppSupportName[]; +extern const char kEnableAssistantAppSupportDescription[]; + extern const char kEnableBackgroundBlurName[]; extern const char kEnableBackgroundBlurDescription[]; @@ -2234,6 +2225,13 @@ #endif // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) +#if defined(OS_MACOSX) || defined(OS_CHROMEOS) + +extern const char kForceEnableSystemAecName[]; +extern const char kForceEnableSystemAecDescription[]; + +#endif // defined(OS_MACOSX) || defined(OS_CHROMEOS) + // Feature flags -------------------------------------------------------------- #if defined(DCHECK_IS_CONFIGURABLE)
diff --git a/chrome/browser/media/cast_transport_host_filter.cc b/chrome/browser/media/cast_transport_host_filter.cc index d982f2d4..f1f895d 100644 --- a/chrome/browser/media/cast_transport_host_filter.cc +++ b/chrome/browser/media/cast_transport_host_filter.cc
@@ -8,17 +8,15 @@ #include "base/task/post_task.h" #include "base/threading/thread_task_runner_handle.h" -#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/browser_process.h" #include "chrome/common/cast_messages.h" #include "components/net_log/chrome_net_log.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/storage_partition.h" #include "content/public/common/service_manager_connection.h" #include "media/cast/net/cast_transport.h" #include "media/cast/net/udp_transport_impl.h" #include "mojo/public/cpp/bindings/interface_request.h" -#include "net/url_request/url_request_context.h" #include "services/device/public/mojom/constants.mojom.h" #include "services/device/public/mojom/wake_lock_provider.mojom.h" #include "services/service_manager/public/cpp/connector.h" @@ -122,11 +120,8 @@ namespace cast { -CastTransportHostFilter::CastTransportHostFilter(Profile* profile) - : BrowserMessageFilter(CastMsgStart), weak_factory_(this) { - content::ScopedAllowGetURLRequestContext scoped_allow_get_url_request_context; - url_request_context_getter_ = profile->GetRequestContext(); -} +CastTransportHostFilter::CastTransportHostFilter() + : BrowserMessageFilter(CastMsgStart), weak_factory_(this) {} CastTransportHostFilter::~CastTransportHostFilter() {} @@ -179,8 +174,8 @@ } auto udp_transport = std::make_unique<media::cast::UdpTransportImpl>( - url_request_context_getter_->GetURLRequestContext()->net_log(), - base::ThreadTaskRunnerHandle::Get(), local_end_point, remote_end_point, + g_browser_process->net_log(), base::ThreadTaskRunnerHandle::Get(), + local_end_point, remote_end_point, base::BindRepeating(&CastTransportHostFilter::OnStatusChanged, weak_factory_.GetWeakPtr(), channel_id)); udp_transport->SetUdpOptions(options);
diff --git a/chrome/browser/media/cast_transport_host_filter.h b/chrome/browser/media/cast_transport_host_filter.h index 1be94ba..c0e814f 100644 --- a/chrome/browser/media/cast_transport_host_filter.h +++ b/chrome/browser/media/cast_transport_host_filter.h
@@ -19,16 +19,13 @@ #include "media/cast/cast_sender.h" #include "media/cast/logging/logging_defines.h" #include "media/cast/net/cast_transport.h" -#include "net/url_request/url_request_context_getter.h" #include "services/device/public/mojom/wake_lock.mojom.h" -class Profile; - namespace cast { class CastTransportHostFilter : public content::BrowserMessageFilter { public: - explicit CastTransportHostFilter(Profile* profile); + CastTransportHostFilter(); // Used by unit test only. void InitializeNoOpWakeLockForTesting(); @@ -115,8 +112,6 @@ // channel ID as the key. std::multimap<int32_t, int32_t> stream_id_map_; - scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; - base::WeakPtrFactory<CastTransportHostFilter> weak_factory_; DISALLOW_COPY_AND_ASSIGN(CastTransportHostFilter);
diff --git a/chrome/browser/media/cast_transport_host_filter_unittest.cc b/chrome/browser/media/cast_transport_host_filter_unittest.cc index 1c3722e..fc21319be 100644 --- a/chrome/browser/media/cast_transport_host_filter_unittest.cc +++ b/chrome/browser/media/cast_transport_host_filter_unittest.cc
@@ -8,7 +8,6 @@ #include "base/time/default_tick_clock.h" #include "chrome/browser/media/cast_transport_host_filter.h" #include "chrome/common/cast_messages.h" -#include "chrome/test/base/testing_profile.h" #include "content/public/test/test_browser_thread_bundle.h" #include "media/cast/logging/logging_defines.h" #include "net/base/ip_address.h" @@ -21,7 +20,7 @@ CastTransportHostFilterTest() : browser_thread_bundle_( content::TestBrowserThreadBundle::IO_MAINLOOP) { - filter_ = new cast::CastTransportHostFilter(&profile_); + filter_ = new cast::CastTransportHostFilter(); static_cast<cast::CastTransportHostFilter*>(filter_.get()) ->InitializeNoOpWakeLockForTesting(); // 127.0.0.1:7 is the local echo service port, which @@ -38,7 +37,6 @@ base::DictionaryValue options_; content::TestBrowserThreadBundle browser_thread_bundle_; - TestingProfile profile_; scoped_refptr<content::BrowserMessageFilter> filter_; net::IPEndPoint receive_endpoint_; };
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager.cc b/chrome/browser/media/webrtc/webrtc_event_log_manager.cc index abc9acb..0accb7a7 100644 --- a/chrome/browser/media/webrtc/webrtc_event_log_manager.cc +++ b/chrome/browser/media/webrtc/webrtc_event_log_manager.cc
@@ -32,25 +32,44 @@ public: ~PeerConnectionTrackerProxyImpl() override = default; - void SetWebRtcEventLoggingState(const WebRtcEventLogPeerConnectionKey& key, - bool event_logging_enabled) override { + void EnableWebRtcEventLogging(const WebRtcEventLogPeerConnectionKey& key, + int output_period_ms) override { base::PostTaskWithTraits( FROM_HERE, {BrowserThread::UI}, base::BindOnce( - &PeerConnectionTrackerProxyImpl::SetWebRtcEventLoggingStateInternal, - key, event_logging_enabled)); + &PeerConnectionTrackerProxyImpl::EnableWebRtcEventLoggingInternal, + key, output_period_ms)); + } + + void DisableWebRtcEventLogging( + const WebRtcEventLogPeerConnectionKey& key) override { + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::UI}, + base::BindOnce( + &PeerConnectionTrackerProxyImpl::DisableWebRtcEventLoggingInternal, + key)); } private: - static void SetWebRtcEventLoggingStateInternal( + static void EnableWebRtcEventLoggingInternal( WebRtcEventLogPeerConnectionKey key, - bool event_logging_enabled) { + int output_period_ms) { DCHECK_CURRENTLY_ON(BrowserThread::UI); RenderProcessHost* host = RenderProcessHost::FromID(key.render_process_id); if (!host) { return; // The host has been asynchronously removed; not a problem. } - host->SetWebRtcEventLogOutput(key.lid, event_logging_enabled); + host->EnableWebRtcEventLogOutput(key.lid, output_period_ms); + } + + static void DisableWebRtcEventLoggingInternal( + WebRtcEventLogPeerConnectionKey key) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + RenderProcessHost* host = RenderProcessHost::FromID(key.render_process_id); + if (!host) { + return; // The host has been asynchronously removed; not a problem. + } + host->DisableWebRtcEventLogOutput(key.lid); } }; @@ -334,6 +353,7 @@ int render_process_id, const std::string& peer_connection_id, size_t max_file_size_bytes, + int output_period_ms, size_t web_app_id, base::OnceCallback<void(bool, const std::string&, const std::string&)> reply) { @@ -372,7 +392,7 @@ base::Unretained(this), render_process_id, browser_context_id, peer_connection_id, browser_context->GetPath(), max_file_size_bytes, - web_app_id, std::move(reply))); + output_period_ms, web_app_id, std::move(reply))); } void WebRtcEventLogManager::ClearCacheForBrowserContext( @@ -500,7 +520,9 @@ const base::FilePath& file_path) { DCHECK(task_runner_->RunsTasksInCurrentSequence()); - OnLoggingTargetStarted(LoggingTarget::kLocalLogging, peer_connection); + constexpr int kLogOutputPeriodMsForLocalLogging = 0; // No batching. + OnLoggingTargetStarted(LoggingTarget::kLocalLogging, peer_connection, + kLogOutputPeriodMsForLocalLogging); if (local_logs_observer_) { local_logs_observer_->OnLocalLogStarted(peer_connection, file_path); @@ -518,13 +540,13 @@ } } -void WebRtcEventLogManager::OnRemoteLogStarted( - PeerConnectionKey key, - const base::FilePath& file_path) { +void WebRtcEventLogManager::OnRemoteLogStarted(PeerConnectionKey key, + const base::FilePath& file_path, + int output_period_ms) { DCHECK(task_runner_->RunsTasksInCurrentSequence()); - OnLoggingTargetStarted(LoggingTarget::kRemoteLogging, key); + OnLoggingTargetStarted(LoggingTarget::kRemoteLogging, key, output_period_ms); if (remote_logs_observer_) { - remote_logs_observer_->OnRemoteLogStarted(key, file_path); + remote_logs_observer_->OnRemoteLogStarted(key, file_path, output_period_ms); } } @@ -538,7 +560,8 @@ } void WebRtcEventLogManager::OnLoggingTargetStarted(LoggingTarget target, - PeerConnectionKey key) { + PeerConnectionKey key, + int output_period_ms) { DCHECK(task_runner_->RunsTasksInCurrentSequence()); auto it = peer_connections_with_event_logging_enabled_in_webrtc_.find(key); if (it != peer_connections_with_event_logging_enabled_in_webrtc_.end()) { @@ -548,7 +571,7 @@ // This is the first client for WebRTC event logging - let WebRTC know // that it should start informing us of events. peer_connections_with_event_logging_enabled_in_webrtc_.emplace(key, target); - pc_tracker_proxy_->SetWebRtcEventLoggingState(key, true); + pc_tracker_proxy_->EnableWebRtcEventLogging(key, output_period_ms); } } @@ -566,7 +589,7 @@ // it's time to stop receiving notifications for it from WebRTC. if (it->second == 0u) { peer_connections_with_event_logging_enabled_in_webrtc_.erase(it); - pc_tracker_proxy_->SetWebRtcEventLoggingState(key, false); + pc_tracker_proxy_->DisableWebRtcEventLogging(key); } } @@ -780,6 +803,7 @@ const std::string& peer_connection_id, const base::FilePath& browser_context_dir, size_t max_file_size_bytes, + int output_period_ms, size_t web_app_id, base::OnceCallback<void(bool, const std::string&, const std::string&)> reply) { @@ -789,8 +813,8 @@ std::string error_message; const bool result = remote_logs_manager_.StartRemoteLogging( render_process_id, browser_context_id, peer_connection_id, - browser_context_dir, max_file_size_bytes, web_app_id, &log_id, - &error_message); + browser_context_dir, max_file_size_bytes, output_period_ms, web_app_id, + &log_id, &error_message); // |log_id| set only if successful; |error_message| set only if unsuccessful. DCHECK_EQ(result, !log_id.empty());
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager.h b/chrome/browser/media/webrtc/webrtc_event_log_manager.h index bef65f3..1f30e1af 100644 --- a/chrome/browser/media/webrtc/webrtc_event_log_manager.h +++ b/chrome/browser/media/webrtc/webrtc_event_log_manager.h
@@ -59,9 +59,13 @@ class PeerConnectionTrackerProxy { public: virtual ~PeerConnectionTrackerProxy() = default; - virtual void SetWebRtcEventLoggingState( + + virtual void EnableWebRtcEventLogging( const WebRtcEventLogPeerConnectionKey& key, - bool event_logging_enabled) = 0; + int output_period_ms) = 0; + + virtual void DisableWebRtcEventLogging( + const WebRtcEventLogPeerConnectionKey& key) = 0; }; // Ensures that no previous instantiation of the class was performed, then @@ -132,6 +136,7 @@ int render_process_id, const std::string& peer_connection_id, size_t max_file_size_bytes, + int output_period_ms, size_t web_app_id, base::OnceCallback<void(bool, const std::string&, const std::string&)> reply); @@ -220,10 +225,13 @@ // WebRtcRemoteEventLogsObserver implementation: void OnRemoteLogStarted(PeerConnectionKey key, - const base::FilePath& file_path) override; + const base::FilePath& file_path, + int output_period_ms) override; void OnRemoteLogStopped(PeerConnectionKey key) override; - void OnLoggingTargetStarted(LoggingTarget target, PeerConnectionKey key); + void OnLoggingTargetStarted(LoggingTarget target, + PeerConnectionKey key, + int output_period_ms); void OnLoggingTargetStopped(LoggingTarget target, PeerConnectionKey key); void StartListeningForPrefChangeForBrowserContext( @@ -281,6 +289,7 @@ const std::string& peer_connection_id, const base::FilePath& browser_context_dir, size_t max_file_size_bytes, + int output_period_ms, size_t web_app_id, base::OnceCallback<void(bool, const std::string&, const std::string&)> reply);
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager_common.cc b/chrome/browser/media/webrtc/webrtc_event_log_manager_common.cc index 63f04b3..2a41b64 100644 --- a/chrome/browser/media/webrtc/webrtc_event_log_manager_common.cc +++ b/chrome/browser/media/webrtc/webrtc_event_log_manager_common.cc
@@ -49,6 +49,10 @@ const char kStartRemoteLoggingFailureMaxSizeTooSmall[] = "Max size too small."; const char kStartRemoteLoggingFailureMaxSizeTooLarge[] = "Excessively large max log size."; +const char kStartRemoteLoggingFailureOutputPeriodMsIsNegative[] = + "Negative output period (ms)."; +const char kStartRemoteLoggingFailureOutputPeriodMsTooLarge[] = + "Excessively large output period (ms)."; const char kStartRemoteLoggingFailureIllegalWebAppId[] = "Illegal web-app ID."; const char kStartRemoteLoggingFailureUnknownOrInactivePeerConnection[] = "Unknown or inactive peer connection.";
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager_common.h b/chrome/browser/media/webrtc/webrtc_event_log_manager_common.h index f00455c..8eb54a3 100644 --- a/chrome/browser/media/webrtc/webrtc_event_log_manager_common.h +++ b/chrome/browser/media/webrtc/webrtc_event_log_manager_common.h
@@ -32,6 +32,8 @@ extern const size_t kMaxRemoteLogFileSizeBytes; +extern const int kMaxOutputPeriodMs; + // Maximum size for a response from Crash, which is the upload ID. extern const size_t kWebRtcEventLogMaxUploadIdBytes; @@ -100,6 +102,8 @@ extern const char kStartRemoteLoggingFailureUnlimitedSizeDisallowed[]; extern const char kStartRemoteLoggingFailureMaxSizeTooSmall[]; extern const char kStartRemoteLoggingFailureMaxSizeTooLarge[]; +extern const char kStartRemoteLoggingFailureOutputPeriodMsIsNegative[]; +extern const char kStartRemoteLoggingFailureOutputPeriodMsTooLarge[]; extern const char kStartRemoteLoggingFailureIllegalWebAppId[]; extern const char kStartRemoteLoggingFailureUnknownOrInactivePeerConnection[]; extern const char kStartRemoteLoggingFailureAlreadyLogging[]; @@ -215,7 +219,8 @@ class WebRtcRemoteEventLogsObserver { public: virtual void OnRemoteLogStarted(WebRtcEventLogPeerConnectionKey key, - const base::FilePath& file_path) = 0; + const base::FilePath& file_path, + int output_period_ms) = 0; virtual void OnRemoteLogStopped(WebRtcEventLogPeerConnectionKey key) = 0; protected:
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager_remote.cc b/chrome/browser/media/webrtc/webrtc_event_log_manager_remote.cc index 0109063..336dabd 100644 --- a/chrome/browser/media/webrtc/webrtc_event_log_manager_remote.cc +++ b/chrome/browser/media/webrtc/webrtc_event_log_manager_remote.cc
@@ -28,6 +28,8 @@ // issue where we read the entire file into memory. const size_t kMaxRemoteLogFileSizeBytes = 50000000u; +const int kMaxOutputPeriodMs = 60000; + namespace { const base::TimeDelta kDefaultProactivePruningDelta = base::TimeDelta::FromMinutes(5); @@ -393,6 +395,7 @@ const std::string& peer_connection_id, const base::FilePath& browser_context_dir, size_t max_file_size_bytes, + int output_period_ms, size_t web_app_id, std::string* log_id, std::string* error_message) { @@ -402,7 +405,8 @@ DCHECK(error_message); DCHECK(error_message->empty()); - if (!AreLogParametersValid(max_file_size_bytes, web_app_id, error_message)) { + if (!AreLogParametersValid(max_file_size_bytes, output_period_ms, web_app_id, + error_message)) { // |error_message| will have been set by AreLogParametersValid(). DCHECK(!error_message->empty()) << "AreLogParametersValid() reported an " "error without an error message."; @@ -442,7 +446,7 @@ } return StartWritingLog(key, browser_context_dir, max_file_size_bytes, - web_app_id, log_id, error_message); + output_period_ms, web_app_id, log_id, error_message); } bool WebRtcRemoteEventLogManager::EventLogWrite(const PeerConnectionKey& key, @@ -632,6 +636,7 @@ bool WebRtcRemoteEventLogManager::AreLogParametersValid( size_t max_file_size_bytes, + int output_period_ms, size_t web_app_id, std::string* error_message) const { DCHECK(task_runner_->RunsTasksInCurrentSequence()); @@ -654,6 +659,18 @@ return false; } + if (output_period_ms < 0) { + LOG(WARNING) << "Output period (ms) must be non-negative."; + *error_message = kStartRemoteLoggingFailureOutputPeriodMsIsNegative; + return false; + } + + if (output_period_ms > kMaxOutputPeriodMs) { + LOG(WARNING) << "Output period (ms) exceeds maximum allowed."; + *error_message = kStartRemoteLoggingFailureOutputPeriodMsTooLarge; + return false; + } + if (web_app_id < kMinWebRtcEventLogWebAppId || web_app_id > kMaxWebRtcEventLogWebAppId) { LOG(WARNING) << "Illegal web-app identifier."; @@ -922,6 +939,7 @@ const PeerConnectionKey& key, const base::FilePath& browser_context_dir, size_t max_file_size_bytes, + int output_period_ms, size_t web_app_id, std::string* log_id_out, std::string* error_message_out) { @@ -968,7 +986,8 @@ const auto it = active_logs_.emplace(key, std::move(log_file)); DCHECK(it.second); - observer_->OnRemoteLogStarted(key, it.first->second->path()); + observer_->OnRemoteLogStarted(key, it.first->second->path(), + output_period_ms); *log_id_out = log_id; return true;
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager_remote.h b/chrome/browser/media/webrtc/webrtc_event_log_manager_remote.h index 373cfa8..14bf28dd 100644 --- a/chrome/browser/media/webrtc/webrtc_event_log_manager_remote.h +++ b/chrome/browser/media/webrtc/webrtc_event_log_manager_remote.h
@@ -112,6 +112,7 @@ const std::string& peer_connection_id, const base::FilePath& browser_context_dir, size_t max_file_size_bytes, + int output_period_ms, size_t web_app_id, std::string* log_id, std::string* error_message); @@ -181,6 +182,7 @@ // If valid, returns true. Otherwise, false, and |error_message| gets // a relevant error. bool AreLogParametersValid(size_t max_file_size_bytes, + int output_period_ms, size_t web_app_id, std::string* error_message) const; @@ -245,6 +247,7 @@ bool StartWritingLog(const PeerConnectionKey& key, const base::FilePath& browser_context_dir, size_t max_file_size_bytes, + int output_period_ms, size_t web_app_id, std::string* log_id_out, std::string* error_message_out);
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc b/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc index 5949fd9..218bc722 100644 --- a/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc +++ b/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc
@@ -82,9 +82,8 @@ #if !defined(OS_ANDROID) auto SaveFilePathTo(base::Optional<base::FilePath>* output) { - return [output](PeerConnectionKey ignored_key, base::FilePath file_path) { - *output = file_path; - }; + return [output](PeerConnectionKey ignored_key, base::FilePath file_path, + int output_period_ms = 0) { *output = file_path; }; } auto SaveKeyAndFilePathTo(base::Optional<PeerConnectionKey>* key_output, @@ -229,8 +228,8 @@ class MockWebRtcRemoteEventLogsObserver : public WebRtcRemoteEventLogsObserver { public: ~MockWebRtcRemoteEventLogsObserver() override = default; - MOCK_METHOD2(OnRemoteLogStarted, - void(PeerConnectionKey, const base::FilePath&)); + MOCK_METHOD3(OnRemoteLogStarted, + void(PeerConnectionKey, const base::FilePath&, int)); MOCK_METHOD1(OnRemoteLogStopped, void(PeerConnectionKey)); }; @@ -443,6 +442,7 @@ bool StartRemoteLogging(const PeerConnectionKey& key, const std::string& peer_connection_id, size_t max_size_bytes, + int output_period_ms, size_t web_app_id, std::string* log_id_output = nullptr, std::string* error_message_output = nullptr) { @@ -451,7 +451,8 @@ std::string error_message; event_log_manager_->StartRemoteLogging( - key.render_process_id, peer_connection_id, max_size_bytes, web_app_id, + key.render_process_id, peer_connection_id, max_size_bytes, + output_period_ms, web_app_id, ReplyClosure(&result, &log_id, &error_message)); WaitForReply(); @@ -473,19 +474,10 @@ bool StartRemoteLogging(const PeerConnectionKey& key, const std::string& peer_connection_id, - size_t max_size_bytes, - std::string* log_id_output = nullptr, - std::string* error_message_output = nullptr) { - return StartRemoteLogging(key, peer_connection_id, max_size_bytes, - kWebAppId, log_id_output, error_message_output); - } - - bool StartRemoteLogging(const PeerConnectionKey& key, - const std::string& peer_connection_id, std::string* log_id_output = nullptr, std::string* error_message_output = nullptr) { return StartRemoteLogging(key, peer_connection_id, - kMaxRemoteLogFileSizeBytes, kWebAppId, + kMaxRemoteLogFileSizeBytes, 0, kWebAppId, log_id_output, error_message_output); } @@ -493,7 +485,8 @@ std::string* log_id_output = nullptr, std::string* error_message_output = nullptr) { return StartRemoteLogging(key, GetUniqueId(key), kMaxRemoteLogFileSizeBytes, - kWebAppId, log_id_output, error_message_output); + 0, kWebAppId, log_id_output, + error_message_output); } void ClearCacheForBrowserContext( @@ -873,7 +866,7 @@ const PeerConnectionKey& key, bool pending) { base::Optional<base::FilePath> file_path; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&file_path))); EXPECT_TRUE(PeerConnectionAdded(key)); EXPECT_TRUE(StartRemoteLogging(key)); @@ -1189,9 +1182,12 @@ ~PeerConnectionTrackerProxyForTesting() override = default; - void SetWebRtcEventLoggingState(const PeerConnectionKey& key, - bool event_logging_enabled) override { - test_->SetWebRtcEventLoggingState(key, event_logging_enabled); + void EnableWebRtcEventLogging(const PeerConnectionKey& key, + int output_period_ms) override { + test_->SetWebRtcEventLoggingState(key, true); + } + void DisableWebRtcEventLogging(const PeerConnectionKey& key) override { + test_->SetWebRtcEventLoggingState(key, false); } private: @@ -1899,7 +1895,7 @@ TEST_F(WebRtcEventLogManagerTest, OnRemoteLogStartedNotCalledIfRemoteLoggingNotEnabled) { - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(_, _)).Times(0); + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(_, _, _)).Times(0); const auto key = GetPeerConnectionKey(rph_.get(), kLid); ASSERT_TRUE(PeerConnectionAdded(key)); } @@ -1915,7 +1911,7 @@ TEST_F(WebRtcEventLogManagerTest, OnRemoteLogStartedCalledIfRemoteLoggingEnabled) { const auto key = GetPeerConnectionKey(rph_.get(), kLid); - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _)).Times(1); + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)).Times(1); ASSERT_TRUE(PeerConnectionAdded(key)); ASSERT_TRUE(StartRemoteLogging(key)); } @@ -1983,8 +1979,8 @@ ASSERT_TRUE(PeerConnectionAdded(key, id)); std::string error_message; EXPECT_FALSE(StartRemoteLogging(key, id, - kWebRtcEventLogManagerUnlimitedFileSize, - nullptr, &error_message)); + kWebRtcEventLogManagerUnlimitedFileSize, 0, + kWebAppId, nullptr, &error_message)); EXPECT_EQ(error_message, kStartRemoteLoggingFailureUnlimitedSizeDisallowed); } @@ -1993,7 +1989,8 @@ const auto key = GetPeerConnectionKey(rph_.get(), kLid); const std::string id = "id"; // For explicitness' sake. ASSERT_TRUE(PeerConnectionAdded(key, id)); - EXPECT_TRUE(StartRemoteLogging(key, id, kMaxRemoteLogFileSizeBytes)); + EXPECT_TRUE( + StartRemoteLogging(key, id, kMaxRemoteLogFileSizeBytes, 0, kWebAppId)); } TEST_F(WebRtcEventLogManagerTest, @@ -2006,8 +2003,8 @@ const std::string id = "id"; // For explicitness' sake. ASSERT_TRUE(PeerConnectionAdded(key, id)); std::string error_message; - EXPECT_FALSE( - StartRemoteLogging(key, id, min_size - 1, nullptr, &error_message)); + EXPECT_FALSE(StartRemoteLogging(key, id, min_size - 1, 0, kWebAppId, nullptr, + &error_message)); EXPECT_EQ(error_message, kStartRemoteLoggingFailureMaxSizeTooSmall); } @@ -2017,12 +2014,37 @@ const std::string id = "id"; // For explicitness' sake. ASSERT_TRUE(PeerConnectionAdded(key, id)); std::string error_message; - EXPECT_FALSE(StartRemoteLogging(key, id, kMaxRemoteLogFileSizeBytes + 1, - nullptr, &error_message)); + EXPECT_FALSE(StartRemoteLogging(key, id, kMaxRemoteLogFileSizeBytes + 1, 0, + kWebAppId, nullptr, &error_message)); EXPECT_EQ(error_message, kStartRemoteLoggingFailureMaxSizeTooLarge); } TEST_F(WebRtcEventLogManagerTest, + StartRemoteLoggingReturnsFalseIfOutputPeriodMsIsNegative) { + const auto key = GetPeerConnectionKey(rph_.get(), kLid); + const std::string id = "id"; // For explicitness' sake. + ASSERT_TRUE(PeerConnectionAdded(key, id)); + std::string error_message; + constexpr int output_period_ms = -1; + EXPECT_FALSE(StartRemoteLogging(key, id, kMaxRemoteLogFileSizeBytes, + output_period_ms, kWebAppId, nullptr, + &error_message)); + EXPECT_EQ(error_message, kStartRemoteLoggingFailureOutputPeriodMsIsNegative); +} + +TEST_F(WebRtcEventLogManagerTest, + StartRemoteLoggingReturnsFalseIfExcessivelyLargeOutputPeriodMs) { + const auto key = GetPeerConnectionKey(rph_.get(), kLid); + const std::string id = "id"; // For explicitness' sake. + ASSERT_TRUE(PeerConnectionAdded(key, id)); + std::string error_message; + EXPECT_FALSE(StartRemoteLogging(key, id, kMaxRemoteLogFileSizeBytes, + kMaxOutputPeriodMs + 1, kWebAppId, nullptr, + &error_message)); + EXPECT_EQ(error_message, kStartRemoteLoggingFailureOutputPeriodMsTooLarge); +} + +TEST_F(WebRtcEventLogManagerTest, StartRemoteLoggingReturnsFalseIfPeerConnectionAlreadyClosed) { const auto key = GetPeerConnectionKey(rph_.get(), kLid); const std::string id = "id"; // For explicitness' sake. @@ -2065,7 +2087,7 @@ const auto key = GetPeerConnectionKey(rph_.get(), kLid); base::Optional<base::FilePath> file_path; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&file_path))); const std::string pc_id = "pc_id"; // For explicitness' sake. @@ -2093,7 +2115,7 @@ TEST_F(WebRtcEventLogManagerTest, StartRemoteLoggingCreatesEmptyFile) { base::Optional<base::FilePath> file_path; const auto key = GetPeerConnectionKey(rph_.get(), kLid); - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .Times(1) .WillOnce(Invoke(SaveFilePathTo(&file_path))); @@ -2121,7 +2143,7 @@ base::Optional<base::FilePath> file_paths[kLogsNum]; for (size_t i = 0; i < kLogsNum; ++i) { const auto key = GetPeerConnectionKey(rphs[i].get(), kLid); - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .Times(1) .WillOnce(Invoke(SaveFilePathTo(&file_paths[i]))); } @@ -2159,7 +2181,7 @@ // Make sure the logs get written to separate files. base::Optional<base::FilePath> file_paths[2]; for (size_t i = 0; i < 2; ++i) { - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(keys[i], _)) + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(keys[i], _, _)) .Times(1) .WillOnce(Invoke(SaveFilePathTo(&file_paths[i]))); } @@ -2176,7 +2198,7 @@ OnWebRtcEventLogWriteWritesToTheRemoteBoundFile) { base::Optional<base::FilePath> file_path; const auto key = GetPeerConnectionKey(rph_.get(), kLid); - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .Times(1) .WillOnce(Invoke(SaveFilePathTo(&file_path))); @@ -2202,7 +2224,7 @@ .WillOnce(Invoke(SaveFilePathTo(&local_path))); base::Optional<base::FilePath> remote_path; - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .Times(1) .WillOnce(Invoke(SaveFilePathTo(&remote_path))); @@ -2228,7 +2250,7 @@ const auto key = GetPeerConnectionKey(rph_.get(), kLid); base::Optional<base::FilePath> file_path; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&file_path))); ASSERT_TRUE(PeerConnectionAdded(key)); @@ -2253,13 +2275,14 @@ RemoteLogFileSizeLimitNotExceededSingleWrite) { const auto key = GetPeerConnectionKey(rph_.get(), kLid); base::Optional<base::FilePath> file_path; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&file_path))); const std::string log = "tpyo"; ASSERT_TRUE(PeerConnectionAdded(key)); - ASSERT_TRUE(StartRemoteLogging(key, GetUniqueId(key), GzippedSize(log) - 1)); + ASSERT_TRUE(StartRemoteLogging(key, GetUniqueId(key), GzippedSize(log) - 1, 0, + kWebAppId)); // Failure is reported, because not everything could be written. The file // will also be closed. @@ -2277,14 +2300,15 @@ RemoteLogFileSizeLimitNotExceededMultipleWrites) { const auto key = GetPeerConnectionKey(rph_.get(), kLid); base::Optional<base::FilePath> file_path; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&file_path))); const std::string log1 = "abcabc"; const std::string log2 = "defghijklmnopqrstuvwxyz"; ASSERT_TRUE(PeerConnectionAdded(key)); - ASSERT_TRUE(StartRemoteLogging(key, GetUniqueId(key), 1 + GzippedSize(log1))); + ASSERT_TRUE(StartRemoteLogging(key, GetUniqueId(key), 1 + GzippedSize(log1), + 0, kWebAppId)); // First write works. ASSERT_EQ(OnWebRtcEventLogWrite(key, log1), std::make_pair(false, true)); @@ -2305,7 +2329,7 @@ std::vector<base::Optional<base::FilePath>> file_paths(keys.size()); for (size_t i = 0; i < keys.size(); ++i) { - ON_CALL(remote_observer_, OnRemoteLogStarted(keys[i], _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(keys[i], _, _)) .WillByDefault(Invoke(SaveFilePathTo(&file_paths[i]))); ASSERT_TRUE(PeerConnectionAdded(keys[i])); ASSERT_TRUE(StartRemoteLogging(keys[i])); @@ -2348,7 +2372,7 @@ std::vector<base::Optional<base::FilePath>> file_paths(keys.size()); for (size_t i = 0; i < keys.size(); ++i) { - ON_CALL(remote_observer_, OnRemoteLogStarted(keys[i], _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(keys[i], _, _)) .WillByDefault(Invoke(SaveFilePathTo(&file_paths[i]))); ASSERT_TRUE(PeerConnectionAdded(keys[i])); ASSERT_TRUE(StartRemoteLogging(keys[i])); @@ -2379,14 +2403,14 @@ std::vector<PeerConnectionKey> keys; for (size_t i = 0; i < base::size(logs); ++i) { keys.push_back(GetPeerConnectionKey(rph_.get(), i)); - ON_CALL(remote_observer_, OnRemoteLogStarted(keys[i], _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(keys[i], _, _)) .WillByDefault(Invoke(SaveFilePathTo(&file_paths[i]))); } for (size_t i = 0; i < keys.size(); ++i) { ASSERT_TRUE(PeerConnectionAdded(keys[i])); ASSERT_TRUE(StartRemoteLogging(keys[i], GetUniqueId(keys[i]), - GzippedSize(logs[i]))); + GzippedSize(logs[i]), 0, kWebAppId)); } for (size_t i = 0; i < keys.size(); ++i) { @@ -2403,13 +2427,14 @@ TEST_F(WebRtcEventLogManagerTest, RemoteLogFileClosedWhenCapacityReached) { const auto key = GetPeerConnectionKey(rph_.get(), kLid); base::Optional<base::FilePath> file_path; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&file_path))); const std::string log = "Let X equal X."; ASSERT_TRUE(PeerConnectionAdded(key)); - ASSERT_TRUE(StartRemoteLogging(key, GetUniqueId(key), GzippedSize(log))); + ASSERT_TRUE(StartRemoteLogging(key, GetUniqueId(key), GzippedSize(log), 0, + kWebAppId)); ASSERT_TRUE(file_path); EXPECT_CALL(remote_observer_, OnRemoteLogStopped(key)).Times(1); @@ -2461,7 +2486,7 @@ TEST_F(WebRtcEventLogManagerTest, GracefullyHandleFailureToStartRemoteLogFile) { // WebRTC logging will not be turned on. - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(_, _)).Times(0); + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(_, _, _)).Times(0); EXPECT_CALL(remote_observer_, OnRemoteLogStopped(_)).Times(0); // Remove write permissions from the directory. @@ -2489,11 +2514,11 @@ for (int i = 0; i < kMaxActiveRemoteLogFiles; ++i) { const auto key = GetPeerConnectionKey(rph_.get(), i); - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _)).Times(1); + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)).Times(1); ASSERT_TRUE(StartRemoteLogging(key)); } - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(_, _)).Times(0); + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(_, _, _)).Times(0); const auto new_key = GetPeerConnectionKey(rph_.get(), kMaxActiveRemoteLogFiles); EXPECT_FALSE(StartRemoteLogging(new_key)); @@ -2506,8 +2531,9 @@ for (int i = 0; i < kMaxActiveRemoteLogFiles; ++i) { const auto key = GetPeerConnectionKey(rph_.get(), i); ASSERT_TRUE(PeerConnectionAdded(key)); - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _)).Times(1); - ASSERT_TRUE(StartRemoteLogging(key, GetUniqueId(key), GzippedSize(log))); + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)).Times(1); + ASSERT_TRUE(StartRemoteLogging(key, GetUniqueId(key), GzippedSize(log), 0, + kWebAppId)); } // By writing to one of the logs until it reaches capacity, we fill it, @@ -2519,7 +2545,7 @@ // We now have room for one additional log. const auto new_key = GetPeerConnectionKey(rph_.get(), kMaxActiveRemoteLogFiles); - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(new_key, _)).Times(1); + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(new_key, _, _)).Times(1); ASSERT_TRUE(PeerConnectionAdded(new_key)); ASSERT_TRUE(StartRemoteLogging(new_key)); } @@ -2529,7 +2555,7 @@ for (int i = 0; i < kMaxActiveRemoteLogFiles; ++i) { const auto key = GetPeerConnectionKey(rph_.get(), i); ASSERT_TRUE(PeerConnectionAdded(key)); - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _)).Times(1); + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)).Times(1); ASSERT_TRUE(StartRemoteLogging(key)); } @@ -2541,7 +2567,7 @@ // We now have room for one additional log. const auto last_key = GetPeerConnectionKey(rph_.get(), kMaxActiveRemoteLogFiles); - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(last_key, _)).Times(1); + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(last_key, _, _)).Times(1); ASSERT_TRUE(PeerConnectionAdded(last_key)); ASSERT_TRUE(StartRemoteLogging(last_key)); } @@ -2715,7 +2741,7 @@ const auto key = GetPeerConnectionKey(rph_.get(), 1); base::Optional<base::FilePath> log_file; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&log_file))); ASSERT_TRUE(PeerConnectionAdded(key)); ASSERT_TRUE(StartRemoteLogging(key)); @@ -2744,7 +2770,7 @@ const auto key = GetPeerConnectionKey(rph_.get(), 1); base::Optional<base::FilePath> log_file; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&log_file))); ASSERT_TRUE(PeerConnectionAdded(key)); ASSERT_TRUE(StartRemoteLogging(key)); @@ -2778,7 +2804,7 @@ // The tracked peer connection's log is not uploaded when finished, because // another peer connection is still active. base::Optional<base::FilePath> log_file; - ON_CALL(remote_observer_, OnRemoteLogStarted(tracked, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(tracked, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&log_file))); ASSERT_TRUE(PeerConnectionAdded(tracked)); ASSERT_TRUE(StartRemoteLogging(tracked)); @@ -2868,7 +2894,7 @@ base::Optional<base::FilePath> file_path; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&file_path))); ASSERT_TRUE(PeerConnectionAdded(key)); ASSERT_TRUE(StartRemoteLogging(key)); @@ -3118,7 +3144,7 @@ .WillByDefault(Invoke(SaveFilePathTo(&local_log_file_path))); base::Optional<base::FilePath> remote_log_file_path; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&remote_log_file_path))); ASSERT_TRUE(EnableLocalLogging()); @@ -3174,7 +3200,7 @@ const auto key = GetPeerConnectionKey(rph_.get(), kLid); base::Optional<base::FilePath> file_path; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&file_path))); ASSERT_TRUE(PeerConnectionAdded(key)); @@ -3285,7 +3311,7 @@ const auto key = GetPeerConnectionKey(rph_.get(), kLid); ASSERT_TRUE(PeerConnectionAdded(key)); EXPECT_FALSE(StartRemoteLogging(key, GetUniqueId(key), - kMaxRemoteLogFileSizeBytes, web_app_id)); + kMaxRemoteLogFileSizeBytes, 0, web_app_id)); } TEST_F(WebRtcEventLogManagerTest, @@ -3296,7 +3322,7 @@ const auto key = GetPeerConnectionKey(rph_.get(), kLid); ASSERT_TRUE(PeerConnectionAdded(key)); EXPECT_FALSE(StartRemoteLogging(key, GetUniqueId(key), - kMaxRemoteLogFileSizeBytes, web_app_id)); + kMaxRemoteLogFileSizeBytes, 0, web_app_id)); } TEST_F(WebRtcEventLogManagerTest, @@ -3305,7 +3331,7 @@ const auto key = GetPeerConnectionKey(rph_.get(), kLid); ASSERT_TRUE(PeerConnectionAdded(key)); EXPECT_TRUE(StartRemoteLogging(key, GetUniqueId(key), - kMaxRemoteLogFileSizeBytes, web_app_id)); + kMaxRemoteLogFileSizeBytes, 0, web_app_id)); } TEST_F(WebRtcEventLogManagerTest, @@ -3314,7 +3340,7 @@ const auto key = GetPeerConnectionKey(rph_.get(), kLid); ASSERT_TRUE(PeerConnectionAdded(key)); EXPECT_TRUE(StartRemoteLogging(key, GetUniqueId(key), - kMaxRemoteLogFileSizeBytes, web_app_id)); + kMaxRemoteLogFileSizeBytes, 0, web_app_id)); } // Only one remote-bound event log allowed per @@ -3327,10 +3353,10 @@ const auto key = GetPeerConnectionKey(rph_.get(), kLid); ASSERT_TRUE(PeerConnectionAdded(key)); - EXPECT_TRUE(StartRemoteLogging(key, GetUniqueId(key), - kMaxRemoteLogFileSizeBytes, web_app_ids[0])); - EXPECT_FALSE(StartRemoteLogging(key, GetUniqueId(key), - kMaxRemoteLogFileSizeBytes, web_app_ids[1])); + EXPECT_TRUE(StartRemoteLogging( + key, GetUniqueId(key), kMaxRemoteLogFileSizeBytes, 0, web_app_ids[0])); + EXPECT_FALSE(StartRemoteLogging( + key, GetUniqueId(key), kMaxRemoteLogFileSizeBytes, 0, web_app_ids[1])); } TEST_F(WebRtcEventLogManagerTest, @@ -3338,13 +3364,14 @@ const auto key = GetPeerConnectionKey(rph_.get(), kLid); base::Optional<base::FilePath> file_path; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&file_path))); ASSERT_TRUE(PeerConnectionAdded(key)); const size_t expected_web_app_id = kWebAppId; - ASSERT_TRUE(StartRemoteLogging( - key, GetUniqueId(key), kMaxRemoteLogFileSizeBytes, expected_web_app_id)); + ASSERT_TRUE(StartRemoteLogging(key, GetUniqueId(key), + kMaxRemoteLogFileSizeBytes, 0, + expected_web_app_id)); ASSERT_TRUE(file_path); const size_t written_web_app_id = @@ -3384,7 +3411,7 @@ const auto key = GetPeerConnectionKey(rph_.get(), kLid); ASSERT_TRUE(PeerConnectionAdded(key)); base::Optional<base::FilePath> file_path; - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .Times(1) .WillOnce(Invoke(SaveFilePathTo(&file_path))); ASSERT_TRUE(StartRemoteLogging(key)); @@ -3455,7 +3482,7 @@ const auto key = GetPeerConnectionKey(rph_.get(), kLid); ASSERT_TRUE(PeerConnectionAdded(key)); base::Optional<base::FilePath> file_path; - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .Times(1) .WillOnce(Invoke(SaveFilePathTo(&file_path))); ASSERT_TRUE(StartRemoteLogging(key)); @@ -3825,7 +3852,7 @@ allow_remote_logging); base::Optional<base::FilePath> log_file; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&log_file))); ASSERT_TRUE(PeerConnectionAdded(key)); ASSERT_TRUE(allow_remote_logging) @@ -3897,7 +3924,7 @@ const auto key = GetPeerConnectionKey(rph.get(), kLid); base::Optional<base::FilePath> log_file; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&log_file))); ASSERT_TRUE(PeerConnectionAdded(key)); ASSERT_TRUE(allow_remote_logging) @@ -3938,7 +3965,7 @@ const auto key = GetPeerConnectionKey(rph.get(), kLid); base::Optional<base::FilePath> log_file; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&log_file))); ASSERT_TRUE(PeerConnectionAdded(key)); ASSERT_TRUE(allow_remote_logging) @@ -4052,7 +4079,7 @@ ASSERT_TRUE(PeerConnectionAdded(key)); base::Optional<base::FilePath> log_file; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&log_file))); ASSERT_TRUE(StartRemoteLogging(key)); ASSERT_TRUE(log_file); @@ -4074,7 +4101,7 @@ const auto key = GetPeerConnectionKey(rph_.get(), 1); base::Optional<base::FilePath> log_file; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&log_file))); ASSERT_TRUE(PeerConnectionAdded(key)); ASSERT_TRUE(StartRemoteLogging(key)); @@ -4098,7 +4125,7 @@ const auto key = GetPeerConnectionKey(rph_.get(), 1); base::Optional<base::FilePath> log_file; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&log_file))); ASSERT_TRUE(PeerConnectionAdded(key)); ASSERT_TRUE(StartRemoteLogging(key)); @@ -4123,7 +4150,7 @@ const auto key = GetPeerConnectionKey(rph_.get(), 1); base::Optional<base::FilePath> log_file; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&log_file))); ASSERT_TRUE(PeerConnectionAdded(key)); ASSERT_TRUE(StartRemoteLogging(key)); @@ -4231,7 +4258,7 @@ const auto key = GetPeerConnectionKey(rph_.get(), 1); base::Optional<base::FilePath> log_file; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&log_file))); ASSERT_TRUE(PeerConnectionAdded(key)); ASSERT_TRUE(StartRemoteLogging(key)); @@ -4317,10 +4344,11 @@ const auto key = GetPeerConnectionKey(rph_.get(), kLid); base::Optional<base::FilePath> log_file; - ON_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + ON_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .WillByDefault(Invoke(SaveFilePathTo(&log_file))); ASSERT_TRUE(PeerConnectionAdded(key)); - ASSERT_TRUE(StartRemoteLogging(key, GetUniqueId(key), GzippedSize(log) - 1)); + ASSERT_TRUE(StartRemoteLogging(key, GetUniqueId(key), GzippedSize(log) - 1, 0, + kWebAppId)); ASSERT_TRUE(log_file); std::list<WebRtcLogFileInfo> empty_list; @@ -4381,7 +4409,7 @@ ASSERT_TRUE(PeerConnectionAdded(key)); base::Optional<base::FilePath> path; - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .Times(1) .WillOnce(Invoke(SaveFilePathTo(&path))); ASSERT_TRUE(StartRemoteLogging(key)); @@ -4404,7 +4432,7 @@ ASSERT_TRUE(PeerConnectionAdded(key)); base::Optional<base::FilePath> path; - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .Times(1) .WillOnce(Invoke(SaveFilePathTo(&path))); ASSERT_TRUE(StartRemoteLogging(key)); @@ -4436,7 +4464,7 @@ ASSERT_TRUE(PeerConnectionAdded(key)); base::Optional<base::FilePath> path; - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .Times(1) .WillOnce(Invoke(SaveFilePathTo(&path))); ASSERT_TRUE(StartRemoteLogging(key)); @@ -4469,7 +4497,7 @@ ASSERT_TRUE(PeerConnectionAdded(key)); base::Optional<base::FilePath> log_path; - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .Times(1) .WillOnce(Invoke(SaveFilePathTo(&log_path))); ASSERT_TRUE(StartRemoteLogging(key)); @@ -4522,7 +4550,7 @@ ASSERT_TRUE(PeerConnectionAdded(key)); base::Optional<base::FilePath> log_path; - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .Times(1) .WillOnce(Invoke(SaveFilePathTo(&log_path))); ASSERT_TRUE(StartRemoteLogging(key)); @@ -4572,7 +4600,7 @@ ASSERT_TRUE(PeerConnectionAdded(key)); base::Optional<base::FilePath> log_path; - EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _)) + EXPECT_CALL(remote_observer_, OnRemoteLogStarted(key, _, _)) .Times(1) .WillOnce(Invoke(SaveFilePathTo(&log_path))); ASSERT_TRUE(StartRemoteLogging(key));
diff --git a/chrome/browser/media/webrtc/webrtc_logging_handler_host.cc b/chrome/browser/media/webrtc/webrtc_logging_handler_host.cc index a32752a..0404c2ae 100644 --- a/chrome/browser/media/webrtc/webrtc_logging_handler_host.cc +++ b/chrome/browser/media/webrtc/webrtc_logging_handler_host.cc
@@ -272,12 +272,13 @@ void WebRtcLoggingHandlerHost::StartEventLogging( const std::string& peer_connection_id, size_t max_log_size_bytes, + int output_period_ms, size_t web_app_id, const StartEventLoggingCallback& callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); WebRtcEventLogManager::GetInstance()->StartRemoteLogging( - render_process_id_, peer_connection_id, max_log_size_bytes, web_app_id, - callback); + render_process_id_, peer_connection_id, max_log_size_bytes, + output_period_ms, web_app_id, callback); } #if defined(OS_LINUX) || defined(OS_CHROMEOS)
diff --git a/chrome/browser/media/webrtc/webrtc_logging_handler_host.h b/chrome/browser/media/webrtc/webrtc_logging_handler_host.h index abbf535..235fb09 100644 --- a/chrome/browser/media/webrtc/webrtc_logging_handler_host.h +++ b/chrome/browser/media/webrtc/webrtc_logging_handler_host.h
@@ -141,6 +141,7 @@ // This function must be called on the UI thread. void StartEventLogging(const std::string& peer_connection_id, size_t max_log_size_bytes, + int output_period_ms, size_t web_app_id, const StartEventLoggingCallback& callback);
diff --git a/chrome/browser/memory/memory_kills_monitor.cc b/chrome/browser/memory/memory_kills_monitor.cc index 5a6a896..48ef1c3e6 100644 --- a/chrome/browser/memory/memory_kills_monitor.cc +++ b/chrome/browser/memory/memory_kills_monitor.cc
@@ -184,7 +184,7 @@ non_joinable_options.joinable = false; non_joinable_worker_thread_ = std::make_unique<base::DelegateSimpleThread>( this, "memory_kills_monitor", non_joinable_options); - non_joinable_worker_thread_->Start(); + non_joinable_worker_thread_->StartAsync(); monitoring_started_.Set(); }
diff --git a/chrome/browser/net/chrome_url_request_context_getter.cc b/chrome/browser/net/chrome_url_request_context_getter.cc index b0c374c..180fa7de 100644 --- a/chrome/browser/net/chrome_url_request_context_getter.cc +++ b/chrome/browser/net/chrome_url_request_context_getter.cc
@@ -70,7 +70,6 @@ FactoryForIsolatedApp( const ProfileIOData* profile_io_data, const StoragePartitionDescriptor& partition_descriptor, - ChromeURLRequestContextGetter* main_context, std::unique_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> protocol_handler_interceptor, content::ProtocolHandlerMap* protocol_handlers, @@ -80,7 +79,6 @@ : profile_io_data_(profile_io_data), partition_descriptor_(partition_descriptor), io_thread_(g_browser_process->io_thread()), - main_request_context_getter_(main_context), protocol_handler_interceptor_(std::move(protocol_handler_interceptor)), request_interceptors_(std::move(request_interceptors)), network_context_request_(std::move(network_context_request)), @@ -95,10 +93,9 @@ // factory is actually destroyed. Thus it is safe to destructively pass // state onwards. return profile_io_data_->GetIsolatedAppRequestContext( - io_thread_, main_request_context_getter_->GetURLRequestContext(), - partition_descriptor_, std::move(protocol_handler_interceptor_), - &protocol_handlers_, std::move(request_interceptors_), - std::move(network_context_request_), + io_thread_, partition_descriptor_, + std::move(protocol_handler_interceptor_), &protocol_handlers_, + std::move(request_interceptors_), std::move(network_context_request_), std::move(network_context_params_)); } @@ -106,8 +103,6 @@ const ProfileIOData* const profile_io_data_; const StoragePartitionDescriptor partition_descriptor_; IOThread* io_thread_; - scoped_refptr<ChromeURLRequestContextGetter> - main_request_context_getter_; std::unique_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> protocol_handler_interceptor_; content::ProtocolHandlerMap protocol_handlers_; @@ -251,12 +246,9 @@ content::URLRequestInterceptorScopedVector request_interceptors, network::mojom::NetworkContextRequest network_context_request, network::mojom::NetworkContextParamsPtr network_context_params) { - content::ScopedAllowGetURLRequestContext scoped_allow_get_url_request_context; - ChromeURLRequestContextGetter* main_context = - static_cast<ChromeURLRequestContextGetter*>(profile->GetRequestContext()); return ChromeURLRequestContextGetter::CreateAndInit( std::make_unique<FactoryForIsolatedApp>( - profile_io_data, partition_descriptor, main_context, + profile_io_data, partition_descriptor, std::move(protocol_handler_interceptor), protocol_handlers, std::move(request_interceptors), std::move(network_context_request), std::move(network_context_params)));
diff --git a/chrome/browser/net/network_context_configuration_browsertest.cc b/chrome/browser/net/network_context_configuration_browsertest.cc index d67aef3c..8606ab3 100644 --- a/chrome/browser/net/network_context_configuration_browsertest.cc +++ b/chrome/browser/net/network_context_configuration_browsertest.cc
@@ -86,6 +86,12 @@ #include "base/mac/mac_util.h" #endif +#if BUILDFLAG(ENABLE_EXTENSIONS) +#include "chrome/browser/extensions/chrome_test_extension_loader.h" +#include "extensions/browser/browsertest_util.h" +#include "extensions/test/test_extension_dir.h" +#endif + namespace { const char kCacheRandomPath[] = "/cacherandom"; @@ -650,6 +656,68 @@ EXPECT_EQ("cookie", *simple_loader_helper.response_body()); } +#if BUILDFLAG(ENABLE_EXTENSIONS) +std::unique_ptr<net::test_server::HttpResponse> EchoCookieHeader( + const net::test_server::HttpRequest& request) { + auto response = std::make_unique<net::test_server::BasicHttpResponse>(); + auto it = request.headers.find("Cookie"); + if (it != request.headers.end()) + response->set_content(it->second); + response->AddCustomHeader("Access-Control-Allow-Origin", "*"); + return response; +} + +IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, + ThirdPartyCookiesAllowedForExtensions) { + if (IsRestartStateWithInProcessNetworkService()) + return; + + // Loading an extension only makes sense for profile contexts. + if (GetParam().network_context_type != NetworkContextType::kProfile && + GetParam().network_context_type != + NetworkContextType::kIncognitoProfile) { + return; + } + net::EmbeddedTestServer test_server; + net::test_server::RegisterDefaultHandlers(&test_server); + test_server.RegisterRequestHandler(base::BindRepeating(&EchoCookieHeader)); + ASSERT_TRUE(test_server.Start()); + + GetPrefService()->SetBoolean(prefs::kBlockThirdPartyCookies, true); + SetCookie(CookieType::kFirstParty, CookiePersistenceType::kPersistent); + + extensions::TestExtensionDir extension_dir; + extension_dir.WriteManifest(R"({ + "name": "Cookie Test", + "manifest_version": 2, + "version": "1.0", + "background": { + "scripts": ["background.js"] + }, + "incognito": "split", + "permissions": ["<all_urls>"] + })"); + extension_dir.WriteFile(FILE_PATH_LITERAL("background.js"), ""); + extensions::ChromeTestExtensionLoader loader(browser()->profile()); + loader.set_allow_incognito_access(true); + scoped_refptr<const extensions::Extension> extension = + loader.LoadExtension(extension_dir.UnpackedPath()); + ASSERT_TRUE(extension); + + GURL url = test_server.GetURL("/echocookieheader"); + std::string script = R"((url => { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.onload = () => domAutomationController.send(xhr.responseText); + xhr.send(); + }))"; + std::string result = + extensions::browsertest_util::ExecuteScriptInBackgroundPage( + GetProfile(), extension->id(), script + "('" + url.spec() + "')"); + EXPECT_EQ("cookie", result); +} +#endif + IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, BasicRequest) { if (IsRestartStateWithInProcessNetworkService()) return;
diff --git a/chrome/browser/net/profile_network_context_service.cc b/chrome/browser/net/profile_network_context_service.cc index a65063b..e44e56dd 100644 --- a/chrome/browser/net/profile_network_context_service.cc +++ b/chrome/browser/net/profile_network_context_service.cc
@@ -367,6 +367,9 @@ ->matching_scheme_cookies_allowed_schemes.push_back( extensions::kExtensionScheme); } + network_context_params->cookie_manager_params + ->third_party_cookies_allowed_schemes.push_back( + extensions::kExtensionScheme); #endif ContentSettingsForOneType settings;
diff --git a/chrome/browser/notifications/OWNERS b/chrome/browser/notifications/OWNERS index 8d106f95..82f60d8f 100644 --- a/chrome/browser/notifications/OWNERS +++ b/chrome/browser/notifications/OWNERS
@@ -9,7 +9,6 @@ per-file *_mac*=rsesek@chromium.org # Windows files -per-file *_win*=chengx@chromium.org per-file *_win*=finnur@chromium.org per-file *permission_context*=file://chrome/browser/permissions/PERMISSIONS_OWNERS
diff --git a/chrome/browser/notifications/notification_platform_bridge_win.cc b/chrome/browser/notifications/notification_platform_bridge_win.cc index 06d9206..43332a8f 100644 --- a/chrome/browser/notifications/notification_platform_bridge_win.cc +++ b/chrome/browser/notifications/notification_platform_bridge_win.cc
@@ -391,6 +391,7 @@ hr = notifier->Show(toast.Get()); if (FAILED(hr)) { LogDisplayHistogram(DisplayStatus::SHOWING_TOAST_FAILED); + base::UmaHistogramSparse("Notifications.Windows.ShowFailedErrorCode", hr); DLOG(ERROR) << "Unable to display the notification " << std::hex << hr; } else { LogDisplayHistogram(DisplayStatus::SUCCESS); @@ -740,6 +741,8 @@ ¬ifier_); if (FAILED(hr)) { LogDisplayHistogram(DisplayStatus::CREATE_TOAST_NOTIFIER_WITH_ID_FAILED); + base::UmaHistogramSparse( + "Notifications.Windows.CreateToastManagerErrorCode", hr); DLOG(ERROR) << "Unable to create the ToastNotifier " << std::hex << hr; } return hr;
diff --git a/chrome/browser/notifications/win/OWNERS b/chrome/browser/notifications/win/OWNERS index 1c89641..118c023 100644 --- a/chrome/browser/notifications/win/OWNERS +++ b/chrome/browser/notifications/win/OWNERS
@@ -1,4 +1,3 @@ -chengx@chromium.org finnur@chromium.org per-file notification_helper*=file://chrome/notification_helper/OWNERS
diff --git a/chrome/browser/offline_pages/android/background_scheduler_bridge.cc b/chrome/browser/offline_pages/android/background_scheduler_bridge.cc index 556f7c43..9aebb16 100644 --- a/chrome/browser/offline_pages/android/background_scheduler_bridge.cc +++ b/chrome/browser/offline_pages/android/background_scheduler_bridge.cc
@@ -57,8 +57,7 @@ DVLOG(2) << "resource_coordinator: " << coordinator; if (!coordinator) return; - coordinator->StopProcessing( - Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED); + coordinator->CancelProcessing(); } BackgroundSchedulerBridge::BackgroundSchedulerBridge() = default;
diff --git a/chrome/browser/offline_pages/android/offline_page_model_factory.cc b/chrome/browser/offline_pages/android/offline_page_model_factory.cc index 17e3ad89..3096336 100644 --- a/chrome/browser/offline_pages/android/offline_page_model_factory.cc +++ b/chrome/browser/offline_pages/android/offline_page_model_factory.cc
@@ -73,8 +73,7 @@ OfflinePageModelTaskified* model = new OfflinePageModelTaskified( std::move(metadata_store), std::move(archive_manager), - std::move(download_manager), background_task_runner, - base::DefaultClock::GetInstance()); + std::move(download_manager), background_task_runner); CctOriginObserver::AttachToOfflinePageModel(model);
diff --git a/chrome/browser/offline_pages/offline_page_request_handler.cc b/chrome/browser/offline_pages/offline_page_request_handler.cc index 9619e08..da7bc69 100644 --- a/chrome/browser/offline_pages/offline_page_request_handler.cc +++ b/chrome/browser/offline_pages/offline_page_request_handler.cc
@@ -16,6 +16,7 @@ #include "base/task/post_task.h" #include "base/task_runner_util.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/offline_pages/offline_page_model_factory.h" @@ -23,6 +24,7 @@ #include "chrome/browser/offline_pages/offline_page_utils.h" #include "chrome/browser/profiles/profile_manager.h" #include "components/offline_pages/core/client_namespace_constants.h" +#include "components/offline_pages/core/offline_clock.h" #include "components/offline_pages/core/offline_page_model.h" #include "components/offline_pages/core/request_header/offline_page_header.h" #include "components/previews/core/previews_experiments.h" @@ -622,7 +624,7 @@ // If the page is being loaded on a slow network, only use the offline page // if it was created within the past day. if (network_state_ == NetworkState::PROHIBITIVELY_SLOW_NETWORK && - base::Time::Now() - GetCurrentOfflinePage().creation_time > + OfflineClock()->Now() - GetCurrentOfflinePage().creation_time > previews::params::OfflinePreviewFreshnessDuration()) { ReportRequestResult(RequestResult::PAGE_NOT_FRESH, network_state_); delegate_->FallbackToDefault();
diff --git a/chrome/browser/offline_pages/offline_page_request_handler_unittest.cc b/chrome/browser/offline_pages/offline_page_request_handler_unittest.cc index 6875aa3a..5a558305ef 100644 --- a/chrome/browser/offline_pages/offline_page_request_handler_unittest.cc +++ b/chrome/browser/offline_pages/offline_page_request_handler_unittest.cc
@@ -675,8 +675,8 @@ file_name += base::IntToString(file_name_sequence_num_++); file_name += ".mht"; temp_file_path_ = temp_dir_.GetPath().AppendASCII(file_name); - ASSERT_TRUE(base::WriteFile(temp_file_path_, content.c_str(), - content.length()) != -1); + ASSERT_NE(base::WriteFile(temp_file_path_, content.c_str(), content.length()), + -1); callback.Run(); } @@ -975,8 +975,7 @@ return std::unique_ptr<KeyedService>(new OfflinePageModelTaskified( std::move(metadata_store), std::move(archive_manager), - std::move(download_manager), task_runner, - base::DefaultClock::GetInstance())); + std::move(download_manager), task_runner)); } // static
diff --git a/chrome/browser/offline_pages/offline_page_request_job.cc b/chrome/browser/offline_pages/offline_page_request_job.cc index 944a29a..93d57017 100644 --- a/chrome/browser/offline_pages/offline_page_request_job.cc +++ b/chrome/browser/offline_pages/offline_page_request_job.cc
@@ -2,14 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <string> +#include <utility> + #include "chrome/browser/offline_pages/offline_page_request_job.h" #include "base/logging.h" #include "base/strings/stringprintf.h" #include "base/supports_user_data.h" +#include "base/time/clock.h" #include "base/time/time.h" #include "chrome/browser/offline_pages/offline_page_utils.h" #include "chrome/browser/renderer_host/chrome_navigation_ui_data.h" +#include "components/offline_pages/core/offline_clock.h" #include "content/public/browser/resource_request_info.h" #include "content/public/common/resource_type.h" #include "net/url_request/url_request.h" @@ -125,7 +130,7 @@ } info->headers = redirect_headers; - info->request_time = base::Time::Now(); + info->request_time = OfflineClock()->Now(); info->response_time = info->request_time; }
diff --git a/chrome/browser/offline_pages/offline_page_utils.cc b/chrome/browser/offline_pages/offline_page_utils.cc index a23e41f..1e431b04 100644 --- a/chrome/browser/offline_pages/offline_page_utils.cc +++ b/chrome/browser/offline_pages/offline_page_utils.cc
@@ -17,6 +17,7 @@ #include "base/strings/string_util.h" #include "base/task/post_task.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" #include "base/time/time.h" #include "build/build_config.h" #include "chrome/browser/net/net_error_tab_helper.h" @@ -29,6 +30,7 @@ #include "components/offline_pages/core/background/save_page_request.h" #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/client_policy_controller.h" +#include "components/offline_pages/core/offline_clock.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/offline_page_item.h" #include "components/offline_pages/core/offline_page_model.h" @@ -125,7 +127,7 @@ // samples in seconds rather than milliseconds. UMA_HISTOGRAM_CUSTOM_COUNTS( "OfflinePages.DownloadRequestTimeSinceDuplicateRequested", - (base::Time::Now() - latest_request_time).InSeconds(), + (OfflineClock()->Now() - latest_request_time).InSeconds(), base::TimeDelta::FromSeconds(1).InSeconds(), base::TimeDelta::FromDays(7).InSeconds(), 50); @@ -320,7 +322,7 @@ // samples in seconds rather than milliseconds. UMA_HISTOGRAM_CUSTOM_COUNTS( "OfflinePages.DownloadRequestTimeSinceDuplicateSaved", - (base::Time::Now() - latest_saved_time).InSeconds(), + (OfflineClock()->Now() - latest_saved_time).InSeconds(), base::TimeDelta::FromSeconds(1).InSeconds(), base::TimeDelta::FromDays(7).InSeconds(), 50);
diff --git a/chrome/browser/offline_pages/offline_page_utils_unittest.cc b/chrome/browser/offline_pages/offline_page_utils_unittest.cc index dd66bb2..01b1ae7 100644 --- a/chrome/browser/offline_pages/offline_page_utils_unittest.cc +++ b/chrome/browser/offline_pages/offline_page_utils_unittest.cc
@@ -18,6 +18,7 @@ #include "base/test/scoped_feature_list.h" #include "base/test/simple_test_clock.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" #include "base/time/time.h" #include "build/build_config.h" #include "chrome/browser/offline_pages/offline_page_model_factory.h" @@ -30,10 +31,12 @@ #include "components/offline_pages/core/background/request_coordinator.h" #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/model/offline_page_model_taskified.h" +#include "components/offline_pages/core/offline_clock.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/offline_page_model.h" #include "components/offline_pages/core/offline_page_test_archiver.h" #include "components/offline_pages/core/offline_page_types.h" +#include "components/offline_pages/core/test_scoped_offline_clock.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/web_contents.h" #include "content/public/test/test_browser_thread_bundle.h" @@ -105,13 +108,14 @@ // OfflinePageTestArchiver::Observer implementation: void SetLastPathCreatedByArchiver(const base::FilePath& file_path) override; + TestScopedOfflineClock* clock() { return &clock_; } TestingProfile* profile() { return &profile_; } content::WebContents* web_contents() const { return web_contents_.get(); } int64_t offline_id() const { return offline_id_; } int64_t last_cache_size() { return last_cache_size_; } - void CreateCachedOfflinePages(base::SimpleTestClock* clock); + void CreateCachedOfflinePages(); private: void CreateOfflinePages(); @@ -120,6 +124,7 @@ const GURL& url, const base::FilePath& file_name); + TestScopedOfflineClock clock_; content::TestBrowserThreadBundle browser_thread_bundle_; int64_t offline_id_; GURL url_; @@ -142,6 +147,9 @@ content::WebContents::CreateParams(profile())); OfflinePageTabHelper::CreateForWebContents(web_contents_.get()); + // Reset the value of the test clock. + clock_.SetNow(base::Time::Now()); + // Set up the factory for testing. OfflinePageModelFactory::GetInstance()->SetTestingFactoryAndUse( &profile_, base::BindRepeating(&BuildTestOfflinePageModel)); @@ -237,40 +245,39 @@ RunUntilIdle(); } -void OfflinePageUtilsTest::CreateCachedOfflinePages( - base::SimpleTestClock* clock) { +void OfflinePageUtilsTest::CreateCachedOfflinePages() { // Add 4 temporary pages to the model used for test cases. And setting current // time as the 00:00:00 time anchor. offline_pages::ClientId client_id; client_id.name_space = kBookmarkNamespace; - clock->SetNow(base::Time::Now()); + clock()->SetNow(base::Time::Now()); // Time 01:00:00. - clock->Advance(base::TimeDelta::FromHours(1)); + clock()->Advance(base::TimeDelta::FromHours(1)); std::unique_ptr<OfflinePageTestArchiver> archiver(BuildArchiver( kTestPage1Url, base::FilePath(FILE_PATH_LITERAL("page1.mhtml")))); client_id.id = kTestPage1ClientId; SavePage(kTestPage1Url, client_id, std::move(archiver)); // time 02:00:00. - clock->Advance(base::TimeDelta::FromHours(1)); + clock()->Advance(base::TimeDelta::FromHours(1)); archiver = BuildArchiver(kTestPage2Url, base::FilePath(FILE_PATH_LITERAL("page2.mhtml"))); client_id.id = kTestPage2ClientId; SavePage(kTestPage2Url, client_id, std::move(archiver)); // time 03:00:00. - clock->Advance(base::TimeDelta::FromHours(1)); + clock()->Advance(base::TimeDelta::FromHours(1)); archiver = BuildArchiver(kTestPage3Url, base::FilePath(FILE_PATH_LITERAL("page3.mhtml"))); client_id.id = kTestPage3ClientId; SavePage(kTestPage3Url, client_id, std::move(archiver)); // Add a temporary page to test boundary at 10:00:00. - clock->Advance(base::TimeDelta::FromHours(7)); + clock()->Advance(base::TimeDelta::FromHours(7)); archiver = BuildArchiver(kTestPage4Url, base::FilePath(FILE_PATH_LITERAL("page4.mhtml"))); client_id.id = kTestPage4ClientId; SavePage(kTestPage4Url, client_id, std::move(archiver)); // Reset clock->to 03:00:00. - clock->SetNow(clock->Now() - base::TimeDelta::FromHours(7)); + clock()->Advance(base::TimeDelta::FromHours(-7)); } std::unique_ptr<OfflinePageTestArchiver> OfflinePageUtilsTest::BuildArchiver( @@ -385,35 +392,24 @@ } TEST_F(OfflinePageUtilsTest, TestGetCachedOfflinePageSizeBetween) { - // Set a test clock before adding cached offline pages. // The clock will be at 03:00:00 after adding pages. - OfflinePageModel* model = - OfflinePageModelFactory::GetForBrowserContext(profile()); - base::SimpleTestClock clock; - static_cast<OfflinePageModelTaskified*>(model)->SetClockForTesting(&clock); - CreateCachedOfflinePages(&clock); + CreateCachedOfflinePages(); // Advance the clock so that we don't hit the time check boundary. - clock.Advance(base::TimeDelta::FromMinutes(5)); + clock()->Advance(base::TimeDelta::FromMinutes(5)); // Get the size of cached offline pages between 01:05:00 and 03:05:00. bool ret = OfflinePageUtils::GetCachedOfflinePageSizeBetween( profile(), base::Bind(&OfflinePageUtilsTest::OnSizeInBytesCalculated, AsWeakPtr()), - clock.Now() - base::TimeDelta::FromHours(2), clock.Now()); + clock()->Now() - base::TimeDelta::FromHours(2), clock()->Now()); RunUntilIdle(); EXPECT_TRUE(ret); EXPECT_EQ(kTestFileSize * 2, last_cache_size()); } TEST_F(OfflinePageUtilsTest, TestGetCachedOfflinePageSizeNoPageInModel) { - // Set a test clock. - OfflinePageModel* model = - OfflinePageModelFactory::GetForBrowserContext(profile()); - base::SimpleTestClock clock; - static_cast<OfflinePageModelTaskified*>(model)->SetClockForTesting(&clock); - - clock.Advance(base::TimeDelta::FromHours(3)); + clock()->Advance(base::TimeDelta::FromHours(3)); // Get the size of cached offline pages between 01:00:00 and 03:00:00. // Since no temporary pages were added to the model, the cache size should be @@ -421,67 +417,52 @@ bool ret = OfflinePageUtils::GetCachedOfflinePageSizeBetween( profile(), base::Bind(&OfflinePageUtilsTest::OnSizeInBytesCalculated, AsWeakPtr()), - clock.Now() - base::TimeDelta::FromHours(2), clock.Now()); + clock()->Now() - base::TimeDelta::FromHours(2), clock()->Now()); RunUntilIdle(); EXPECT_TRUE(ret); EXPECT_EQ(0, last_cache_size()); } TEST_F(OfflinePageUtilsTest, TestGetCachedOfflinePageSizeNoPageInRange) { - // Set a test clock before adding cached offline pages. // The clock will be at 03:00:00 after adding pages. - OfflinePageModel* model = - OfflinePageModelFactory::GetForBrowserContext(profile()); - base::SimpleTestClock clock; - static_cast<OfflinePageModelTaskified*>(model)->SetClockForTesting(&clock); - CreateCachedOfflinePages(&clock); + CreateCachedOfflinePages(); // Advance the clock so that we don't hit the time check boundary. - clock.Advance(base::TimeDelta::FromMinutes(5)); + clock()->Advance(base::TimeDelta::FromMinutes(5)); // Get the size of cached offline pages between 03:04:00 and 03:05:00. bool ret = OfflinePageUtils::GetCachedOfflinePageSizeBetween( profile(), base::Bind(&OfflinePageUtilsTest::OnSizeInBytesCalculated, AsWeakPtr()), - clock.Now() - base::TimeDelta::FromMinutes(1), clock.Now()); + clock()->Now() - base::TimeDelta::FromMinutes(1), clock()->Now()); RunUntilIdle(); EXPECT_TRUE(ret); EXPECT_EQ(0, last_cache_size()); } TEST_F(OfflinePageUtilsTest, TestGetCachedOfflinePageSizeAllPagesInRange) { - // Set a test clock before adding cached offline pages. // The clock will be at 03:00:00 after adding pages. - OfflinePageModel* model = - OfflinePageModelFactory::GetForBrowserContext(profile()); - base::SimpleTestClock clock; - static_cast<OfflinePageModelTaskified*>(model)->SetClockForTesting(&clock); - CreateCachedOfflinePages(&clock); + CreateCachedOfflinePages(); // Advance the clock to 23:00:00. - clock.Advance(base::TimeDelta::FromHours(20)); + clock()->Advance(base::TimeDelta::FromHours(20)); // Get the size of cached offline pages between -01:00:00 and 23:00:00. bool ret = OfflinePageUtils::GetCachedOfflinePageSizeBetween( profile(), base::Bind(&OfflinePageUtilsTest::OnSizeInBytesCalculated, AsWeakPtr()), - clock.Now() - base::TimeDelta::FromHours(24), clock.Now()); + clock()->Now() - base::TimeDelta::FromHours(24), clock()->Now()); RunUntilIdle(); EXPECT_TRUE(ret); EXPECT_EQ(kTestFileSize * 4, last_cache_size()); } TEST_F(OfflinePageUtilsTest, TestGetCachedOfflinePageSizeAllPagesInvalidRange) { - // Set a test clock before adding cached offline pages. // The clock will be at 03:00:00 after adding pages. - OfflinePageModel* model = - OfflinePageModelFactory::GetForBrowserContext(profile()); - base::SimpleTestClock clock; - static_cast<OfflinePageModelTaskified*>(model)->SetClockForTesting(&clock); - CreateCachedOfflinePages(&clock); + CreateCachedOfflinePages(); // Advance the clock to 23:00:00. - clock.Advance(base::TimeDelta::FromHours(20)); + clock()->Advance(base::TimeDelta::FromHours(20)); // Get the size of cached offline pages between 23:00:00 and -01:00:00, which // is an invalid range, the return value will be false and there will be no @@ -489,19 +470,14 @@ bool ret = OfflinePageUtils::GetCachedOfflinePageSizeBetween( profile(), base::Bind(&OfflinePageUtilsTest::OnSizeInBytesCalculated, AsWeakPtr()), - clock.Now(), clock.Now() - base::TimeDelta::FromHours(24)); + clock()->Now(), clock()->Now() - base::TimeDelta::FromHours(24)); RunUntilIdle(); EXPECT_FALSE(ret); } TEST_F(OfflinePageUtilsTest, TestGetCachedOfflinePageSizeEdgeCase) { - // Set a test clock before adding cached offline pages. // The clock will be at 03:00:00 after adding pages. - OfflinePageModel* model = - OfflinePageModelFactory::GetForBrowserContext(profile()); - base::SimpleTestClock clock; - static_cast<OfflinePageModelTaskified*>(model)->SetClockForTesting(&clock); - CreateCachedOfflinePages(&clock); + CreateCachedOfflinePages(); // Get the size of cached offline pages between 02:00:00 and 03:00:00, since // we are using a [begin_time, end_time) range so there will be only 1 page @@ -509,7 +485,7 @@ bool ret = OfflinePageUtils::GetCachedOfflinePageSizeBetween( profile(), base::Bind(&OfflinePageUtilsTest::OnSizeInBytesCalculated, AsWeakPtr()), - clock.Now() - base::TimeDelta::FromHours(1), clock.Now()); + clock()->Now() - base::TimeDelta::FromHours(1), clock()->Now()); RunUntilIdle(); EXPECT_TRUE(ret); EXPECT_EQ(kTestFileSize * 1, last_cache_size());
diff --git a/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.cc b/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.cc index f5f8cf67..79ff55d 100644 --- a/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.cc +++ b/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.cc
@@ -6,7 +6,9 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" +#include "base/time/clock.h" #include "chrome/common/pref_names.h" +#include "components/offline_pages/core/offline_clock.h" #include "components/offline_pages/core/offline_store_utils.h" namespace offline_pages { @@ -148,7 +150,7 @@ tracking_day_midnight_ = prefs_->GetTime(prefs::kOfflineUsageTrackingDay); // For the very first run, initialize to current time. if (tracking_day_midnight_.is_null()) - tracking_day_midnight_ = Now().LocalMidnight(); + tracking_day_midnight_ = OfflineClock()->Now().LocalMidnight(); unused_days_count_ = prefs_->GetInteger(prefs::kOfflineUsageUnusedCount); started_days_count_ = prefs_->GetInteger(prefs::kOfflineUsageStartedCount); @@ -203,7 +205,7 @@ } bool OfflineMetricsCollectorImpl::UpdatePastDaysIfNeeded() { - base::Time current_midnight = Now().LocalMidnight(); + base::Time current_midnight = OfflineClock()->Now().LocalMidnight(); // 1. If days_since_last_update <= 0, continue to accumulate the current day. // 2. If days_since_last_update == 1, stats are recorded and initialized for // the current day. @@ -264,14 +266,4 @@ return true; } -base::Time OfflineMetricsCollectorImpl::Now() const { - if (testing_clock_) - return testing_clock_->Now(); - return base::Time::Now(); -} - -void OfflineMetricsCollectorImpl::SetClockForTesting(base::Clock* clock) { - testing_clock_ = clock; -} - } // namespace offline_pages
diff --git a/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.h b/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.h index f9bf70c9..87bb12c 100644 --- a/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.h +++ b/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.h
@@ -95,8 +95,6 @@ void OnPrefetchedPageOpened() override; void ReportAccumulatedStats() override; - void SetClockForTesting(base::Clock* clock); - private: void EnsureLoaded(); void SaveToPrefs(); @@ -151,9 +149,6 @@ // of profile's PrefetchService. PrefService* prefs_ = nullptr; - // Used in tests, managed by the test, outlives this object. - base::Clock* testing_clock_ = nullptr; - DISALLOW_COPY_AND_ASSIGN(OfflineMetricsCollectorImpl); };
diff --git a/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl_unittest.cc b/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl_unittest.cc index 3d785a0..6a772e8 100644 --- a/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl_unittest.cc +++ b/chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl_unittest.cc
@@ -9,8 +9,10 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/simple_test_clock.h" +#include "base/time/clock.h" #include "chrome/common/pref_names.h" #include "components/offline_pages/core/offline_store_utils.h" +#include "components/offline_pages/core/test_scoped_offline_clock.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/testing_pref_service.h" #include "testing/gtest/include/gtest/gtest.h" @@ -29,7 +31,7 @@ void SetUp() override { base::Time epoch; ASSERT_TRUE(base::Time::FromUTCString("1 Jan 1994 GMT", &epoch)); - test_clock().SetNow(epoch.LocalMidnight()); + test_clock()->SetNow(epoch.LocalMidnight()); OfflineMetricsCollectorImpl::RegisterPrefs(pref_service_.registry()); Reload(); } @@ -38,10 +40,9 @@ void Reload() { collector_ = std::make_unique<OfflineMetricsCollectorImpl>(&prefs()); - collector_->SetClockForTesting(&test_clock()); } - base::SimpleTestClock& test_clock() { return test_clock_; } + TestScopedOfflineClock* test_clock() { return &test_clock_; } PrefService& prefs() { return pref_service_; } OfflineMetricsCollector* collector() const { return collector_.get(); } const base::HistogramTester& histograms() const { return histogram_tester_; } @@ -71,11 +72,11 @@ "OfflinePages.OfflineUsage.NotOfflineResilient", count); } - protected: - base::SimpleTestClock test_clock_; + private: TestingPrefServiceSimple pref_service_; std::unique_ptr<OfflineMetricsCollectorImpl> collector_; base::HistogramTester histogram_tester_; + TestScopedOfflineClock test_clock_; DISALLOW_COPY_AND_ASSIGN(OfflineMetricsCollectorTest); }; @@ -110,7 +111,7 @@ EXPECT_EQ(false, prefs().GetBoolean(prefs::kOfflineUsageStartObserved)); EXPECT_EQ(false, prefs().GetBoolean(prefs::kOfflineUsageOfflineObserved)); EXPECT_EQ(false, prefs().GetBoolean(prefs::kOfflineUsageOnlineObserved)); - base::Time start = test_clock().Now(); + base::Time start = test_clock()->Now(); collector()->OnAppStartupOrResume(); @@ -187,7 +188,7 @@ // Restore from Prefs keeps accumulated state, counters and timestamp. TEST_F(OfflineMetricsCollectorTest, RestoreFromPrefs) { - base::Time start = test_clock().Now(); + base::Time start = test_clock()->Now(); collector()->OnSuccessfulNavigationOnline(); EXPECT_EQ(false, prefs().GetBoolean(prefs::kOfflineUsageStartObserved)); EXPECT_EQ(false, prefs().GetBoolean(prefs::kOfflineUsageOfflineObserved)); @@ -265,7 +266,7 @@ } TEST_F(OfflineMetricsCollectorTest, ChangesWithinDay) { - base::Time start = test_clock().Now(); + base::Time start = test_clock()->Now(); collector()->OnAppStartupOrResume(); collector()->OnSuccessfulNavigationOnline(); EXPECT_EQ(true, prefs().GetBoolean(prefs::kOfflineUsageStartObserved)); @@ -273,8 +274,7 @@ EXPECT_EQ(true, prefs().GetBoolean(prefs::kOfflineUsageOnlineObserved)); // Move time ahead but still same day. - base::Time later1Hour = start + base::TimeDelta::FromHours(1); - test_clock().SetNow(later1Hour); + test_clock()->Advance(base::TimeDelta::FromHours(1)); collector()->OnSuccessfulNavigationOffline(); // Timestamp shouldn't change. EXPECT_EQ(GetTimestampFromPrefs(), start); @@ -292,13 +292,13 @@ } TEST_F(OfflineMetricsCollectorTest, MultipleDays) { - base::Time start = test_clock().Now(); + // Clock starts at epoch.LocalMidnight() collector()->OnAppStartupOrResume(); ExpectNotResilientOfflineUsageTotalCount(0); - base::Time nextDay = start + base::TimeDelta::FromHours(25); - test_clock().SetNow(nextDay); + // Advance the clock to the next day + test_clock()->Advance(base::TimeDelta::FromHours(25)); collector()->OnAppStartupOrResume(); // 1 day 'started' counter, another is being tracked as current day... @@ -312,8 +312,8 @@ ExpectNotResilientOfflineUsageBucketCount(DailyUsageType::kStarted, 1); ExpectNotResilientOfflineUsageTotalCount(1); - base::Time skip4Days = nextDay + base::TimeDelta::FromHours(24 * 4); - test_clock().SetNow(skip4Days); + // Skip the next 4 days within the virtual clock + test_clock()->Advance(base::TimeDelta::FromDays(4)); collector()->OnSuccessfulNavigationOnline(); // 2 days started, 3 days skipped ('unused'). EXPECT_EQ(2, prefs().GetInteger(prefs::kOfflineUsageStartedCount)); @@ -345,24 +345,24 @@ } TEST_F(OfflineMetricsCollectorTest, OverDayBoundaryPrefetch) { - base::Time start = test_clock().Now(); + // Clock starts at epoch.LocalMidnight() collector()->OnPrefetchEnabled(); - test_clock().SetNow(start + base::TimeDelta::FromDays(1)); + test_clock()->Advance(base::TimeDelta::FromDays(1)); collector()->OnPrefetchEnabled(); - test_clock().SetNow(start + base::TimeDelta::FromDays(2)); + test_clock()->Advance(base::TimeDelta::FromDays(1)); collector()->OnSuccessfulPagePrefetch(); - test_clock().SetNow(start + base::TimeDelta::FromDays(3)); + test_clock()->Advance(base::TimeDelta::FromDays(1)); collector()->OnPrefetchedPageOpened(); - test_clock().SetNow(start + base::TimeDelta::FromDays(4)); + test_clock()->Advance(base::TimeDelta::FromDays(1)); collector()->OnPrefetchEnabled(); collector()->OnSuccessfulPagePrefetch(); collector()->OnPrefetchedPageOpened(); - test_clock().SetNow(start + base::TimeDelta::FromDays(6)); + test_clock()->Advance(base::TimeDelta::FromDays(1)); collector()->OnPrefetchEnabled(); // Force collector to report stats and observe them reported correctly.
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl.cc b/chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl.cc index a9d904a..ae282f8f 100644 --- a/chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl.cc +++ b/chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl.cc
@@ -4,9 +4,13 @@ #include "chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl.h" +#include "base/time/clock.h" +#include "base/time/default_tick_clock.h" +#include "base/time/tick_clock.h" #include "base/time/time.h" #include "chrome/browser/offline_pages/prefetch/prefetch_background_task_scheduler.h" #include "chrome/common/pref_names.h" +#include "components/offline_pages/core/offline_clock.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/prefetch/prefetch_prefs.h" #include "components/prefs/pref_registry_simple.h" @@ -30,7 +34,7 @@ PrefetchBackgroundTaskHandlerImpl::PrefetchBackgroundTaskHandlerImpl( PrefService* prefs) - : prefs_(prefs) {} + : prefs_(prefs), tick_clock_(base::DefaultTickClock::GetInstance()) {} PrefetchBackgroundTaskHandlerImpl::~PrefetchBackgroundTaskHandlerImpl() = default; @@ -58,10 +62,11 @@ std::unique_ptr<net::BackoffEntry> result; if (value) { result = net::BackoffEntrySerializer::DeserializeFromValue( - *value, &kPrefetchBackoffPolicy, clock_, base::Time::Now()); + *value, &kPrefetchBackoffPolicy, tick_clock_, OfflineClock()->Now()); } if (!result) - return std::make_unique<net::BackoffEntry>(&kPrefetchBackoffPolicy, clock_); + return std::make_unique<net::BackoffEntry>(&kPrefetchBackoffPolicy, + tick_clock_); return result; } @@ -82,7 +87,7 @@ // Erase the existing delay but retain the failure count so that the next // time we run if backoff is requested again we will continue the exponential // backoff from where we left off. - current->SetCustomReleaseTime(base::TimeTicks::Now()); + current->SetCustomReleaseTime(tick_clock_->NowTicks()); UpdateBackoff(current.get()); } @@ -93,7 +98,7 @@ // Set a custom delay to be a 1 day interval. After the day passes, the next // backoff value will be back to the initial 30s delay. current->SetCustomReleaseTime( - base::TimeTicks::Now() + + tick_clock_->NowTicks() + base::TimeDelta::FromDays(kDefaultSuspensionDays)); UpdateBackoff(current.get()); } @@ -108,15 +113,15 @@ } void PrefetchBackgroundTaskHandlerImpl::SetTickClockForTesting( - const base::TickClock* clock) { - clock_ = clock; + const base::TickClock* tick_clock) { + tick_clock_ = tick_clock; } void PrefetchBackgroundTaskHandlerImpl::UpdateBackoff( net::BackoffEntry* backoff) { std::unique_ptr<base::Value> value = net::BackoffEntrySerializer::SerializeToValue(*backoff, - base::Time::Now()); + OfflineClock()->Now()); prefs_->Set(prefetch_prefs::kBackoff, *value); }
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl.h b/chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl.h index 2da5b659..cd74191a 100644 --- a/chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl.h +++ b/chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl.h
@@ -8,7 +8,6 @@ #include <memory> #include "base/macros.h" -#include "base/time/tick_clock.h" #include "components/offline_pages/core/prefetch/prefetch_background_task_handler.h" class PrefService; @@ -56,14 +55,14 @@ int GetAdditionalBackoffSeconds() const override; // This is used to construct the backoff value. - void SetTickClockForTesting(const base::TickClock* clock); + void SetTickClockForTesting(const base::TickClock* tick_clock); private: std::unique_ptr<net::BackoffEntry> GetCurrentBackoff() const; void UpdateBackoff(net::BackoffEntry* backoff); PrefService* prefs_; - const base::TickClock* clock_ = nullptr; + const base::TickClock* tick_clock_; DISALLOW_COPY_AND_ASSIGN(PrefetchBackgroundTaskHandlerImpl); };
diff --git a/chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl_unittest.cc b/chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl_unittest.cc index 023961e..37787f0 100644 --- a/chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl_unittest.cc +++ b/chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl_unittest.cc
@@ -5,7 +5,9 @@ #include "chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl.h" #include "base/test/test_mock_time_task_runner.h" +#include "base/time/clock.h" #include "chrome/test/base/testing_profile.h" +#include "components/offline_pages/core/offline_clock.h" #include "components/prefs/pref_service.h" #include "content/public/test/test_browser_thread_bundle.h" #include "net/base/backoff_entry.h" @@ -45,7 +47,7 @@ }; PrefetchBackgroundTaskHandlerImplTest::PrefetchBackgroundTaskHandlerImplTest() - : task_runner_(new base::TestMockTimeTaskRunner(base::Time::Now(), + : task_runner_(new base::TestMockTimeTaskRunner(OfflineClock()->Now(), base::TimeTicks::Now())) { task_handler_ = CreateHandler(); }
diff --git a/chrome/browser/offline_pages/test_offline_page_model_builder.cc b/chrome/browser/offline_pages/test_offline_page_model_builder.cc index 8c7cab1b..4702fa9e 100644 --- a/chrome/browser/offline_pages/test_offline_page_model_builder.cc +++ b/chrome/browser/offline_pages/test_offline_page_model_builder.cc
@@ -52,8 +52,7 @@ return std::unique_ptr<KeyedService>(new OfflinePageModelTaskified( std::move(metadata_store), std::move(archive_manager), - std::move(stub_download_manager), task_runner, - base::DefaultClock::GetInstance())); + std::move(stub_download_manager), task_runner)); } } // namespace offline_pages
diff --git a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc index e23dbc3..12a8aa94 100644 --- a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc
@@ -208,6 +208,8 @@ const char kHistogramPageLoadNetworkBytes[] = "PageLoad.Experimental.Bytes.Network"; const char kHistogramPageLoadCacheBytes[] = "PageLoad.Experimental.Bytes.Cache"; +const char kHistogramPageLoadNetworkBytesIncludingHeaders[] = + "PageLoad.Experimental.Bytes.NetworkIncludingHeaders"; const char kHistogramLoadTypeTotalBytesForwardBack[] = "PageLoad.Experimental.Bytes.Total.LoadType.ForwardBackNavigation"; @@ -263,6 +265,7 @@ num_network_resources_(0), cache_bytes_(0), network_bytes_(0), + network_bytes_including_headers_(0), redirect_chain_size_(0) {} CorePageLoadMetricsObserver::~CorePageLoadMetricsObserver() {} @@ -772,6 +775,14 @@ } } +void CorePageLoadMetricsObserver::OnResourceDataUseObserved( + const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>& + resources) { + for (auto const& resource : resources) { + network_bytes_including_headers_ += resource->delta_bytes; + } +} + // This method records values for metrics that were not recorded during any // other event, or records failure status for metrics that have not been // collected yet. This is meant to be called at the end of a page lifetime, for @@ -869,6 +880,8 @@ network_bytes_); PAGE_BYTES_HISTOGRAM(internal::kHistogramPageLoadCacheBytes, cache_bytes_); PAGE_BYTES_HISTOGRAM(internal::kHistogramPageLoadTotalBytes, total_bytes); + PAGE_BYTES_HISTOGRAM(internal::kHistogramPageLoadNetworkBytesIncludingHeaders, + network_bytes_including_headers_); switch (GetPageLoadType(transition_)) { case LOAD_TYPE_RELOAD:
diff --git a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h index 445d181..bae38aea 100644 --- a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h
@@ -67,6 +67,7 @@ extern const char kHistogramPageLoadTotalBytes[]; extern const char kHistogramPageLoadNetworkBytes[]; extern const char kHistogramPageLoadCacheBytes[]; +extern const char kHistogramPageLoadNetworkBytesIncludingHeaders[]; extern const char kHistogramLoadTypeTotalBytesForwardBack[]; extern const char kHistogramLoadTypeNetworkBytesForwardBack[]; @@ -211,6 +212,9 @@ void OnUserInput(const blink::WebInputEvent& event) override; void OnLoadedResource(const page_load_metrics::ExtraRequestCompleteInfo& extra_request_complete_info) override; + void OnResourceDataUseObserved( + const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>& + resources) override; void OnLargestImagePaintInMainFrameDocument( const page_load_metrics::mojom::PageLoadTiming& timing, const page_load_metrics::PageLoadExtraInfo& info) override; @@ -245,11 +249,15 @@ int num_cache_resources_; int num_network_resources_; - // The number of body (not header) prefilter bytes consumed by requests for - // the page. + // The number of body (not header) prefilter bytes consumed by completed + // requests for the page. int64_t cache_bytes_; int64_t network_bytes_; + // The number of prefilter bytes consumed by completed and partial network + // requests for the page. + int64_t network_bytes_including_headers_; + // Size of the redirect chain, which excludes the first URL. int redirect_chain_size_;
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc index 73ff960..5f99a11 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -25,6 +25,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/browser/translate/chrome_translate_client.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" #include "chrome/browser/ui/passwords/password_generation_popup_controller_impl.h" @@ -39,7 +40,6 @@ #include "components/browser_sync/profile_sync_service.h" #include "components/password_manager/content/browser/bad_message.h" #include "components/password_manager/content/browser/content_password_manager_driver.h" -#include "components/password_manager/content/browser/form_submission_tracker_util.h" #include "components/password_manager/content/browser/password_manager_internals_service_factory.h" #include "components/password_manager/content/browser/password_requirements_service_factory.h" #include "components/password_manager/core/browser/browser_save_password_progress_logger.h" @@ -59,6 +59,7 @@ #include "components/sessions/content/content_record_password_state.h" #include "components/sync/driver/sync_service.h" #include "components/sync/driver/sync_user_settings.h" +#include "components/translate/core/browser/translate_manager.h" #include "components/ukm/content/source_url_recorder.h" #include "components/version_info/version_info.h" #include "content/public/browser/browser_context.h" @@ -66,7 +67,6 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/ssl_status.h" @@ -648,14 +648,6 @@ content::NavigationHandle* navigation_handle) { // Logging has no sense on WebUI sites. log_manager_->SetSuspended(web_contents()->GetWebUI() != nullptr); - int current_process_id = - navigation_handle->GetStartingSiteInstance()->GetProcess()->GetID(); - content::RenderFrameHost* current_frame_host = - web_contents()->FindFrameByFrameTreeNodeId( - navigation_handle->GetFrameTreeNodeId(), current_process_id); - password_manager::NotifyOnStartNavigation( - navigation_handle, driver_factory_->GetDriverForFrame(current_frame_host), - &password_manager_); } gfx::RectF ChromePasswordManagerClient::GetBoundsInScreenSpace( @@ -858,6 +850,16 @@ } } +std::string ChromePasswordManagerClient::GetPageLanguage() const { + // TODO(crbug.com/912597): iOS vs other platforms extracts language from + // the top level frame vs whatever frame directly holds the form. + auto* translate_manager = + ChromeTranslateClient::GetManagerFromWebContents(web_contents()); + if (translate_manager) + return translate_manager->GetLanguageState().original_language(); + return std::string(); +} + const password_manager::CredentialsFilter* ChromePasswordManagerClient::GetStoreResultFilter() const { return &credentials_filter_; @@ -896,7 +898,8 @@ void ChromePasswordManagerClient::NavigateToManagePasswordsPage( password_manager::ManagePasswordsReferrer referrer) { #if defined(OS_ANDROID) - chrome::android::PreferencesLauncher::ShowPasswordSettings(web_contents()); + chrome::android::PreferencesLauncher::ShowPasswordSettings(web_contents(), + referrer); #else ::NavigateToManagePasswordsPage( chrome::FindBrowserWithWebContents(web_contents()), referrer);
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.h b/chrome/browser/password_manager/chrome_password_manager_client.h index 79867b1..6772d311 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.h +++ b/chrome/browser/password_manager/chrome_password_manager_client.h
@@ -15,6 +15,7 @@ #include "components/autofill/content/common/autofill_driver.mojom.h" #include "components/password_manager/content/browser/content_credential_manager.h" #include "components/password_manager/content/browser/content_password_manager_driver_factory.h" +#include "components/password_manager/core/browser/manage_passwords_referrer.h" #include "components/password_manager/core/browser/password_manager.h" #include "components/password_manager/core/browser/password_manager_client.h" #include "components/password_manager/core/browser/password_manager_client_helper.h" @@ -104,6 +105,7 @@ bool IsMainFrameSecure() const override; const GURL& GetLastCommittedEntryURL() const override; void AnnotateNavigationEntry(bool has_password_field) override; + std::string GetPageLanguage() const override; const password_manager::CredentialsFilter* GetStoreResultFilter() const override; const password_manager::LogManager* GetLogManager() const override;
diff --git a/chrome/browser/password_manager/generated_password_saved_infobar_delegate_android.cc b/chrome/browser/password_manager/generated_password_saved_infobar_delegate_android.cc index 3a19abcb..23753c2 100644 --- a/chrome/browser/password_manager/generated_password_saved_infobar_delegate_android.cc +++ b/chrome/browser/password_manager/generated_password_saved_infobar_delegate_android.cc
@@ -13,6 +13,7 @@ #include "chrome/grit/generated_resources.h" #include "components/infobars/core/infobar.h" #include "components/infobars/core/infobar_manager.h" +#include "components/password_manager/core/browser/manage_passwords_referrer.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" #include "components/password_manager/core/browser/password_manager_constants.h" #include "components/strings/grit/components_strings.h" @@ -24,7 +25,9 @@ void GeneratedPasswordSavedInfoBarDelegateAndroid::OnInlineLinkClicked() { chrome::android::PreferencesLauncher::ShowPasswordSettings( - InfoBarService::WebContentsFromInfoBar(infobar())); + InfoBarService::WebContentsFromInfoBar(infobar()), + password_manager::ManagePasswordsReferrer:: + kPasswordGenerationConfirmation); } GeneratedPasswordSavedInfoBarDelegateAndroid::
diff --git a/chrome/browser/password_manager/password_accessory_controller_impl.cc b/chrome/browser/password_manager/password_accessory_controller_impl.cc index 40ec623..3f73c74 100644 --- a/chrome/browser/password_manager/password_accessory_controller_impl.cc +++ b/chrome/browser/password_manager/password_accessory_controller_impl.cc
@@ -188,7 +188,9 @@ UMA_HISTOGRAM_ENUMERATION("KeyboardAccessory.AccessoryActionSelected", metrics::AccessoryAction::MANAGE_PASSWORDS, metrics::AccessoryAction::COUNT); - chrome::android::PreferencesLauncher::ShowPasswordSettings(web_contents_); + chrome::android::PreferencesLauncher::ShowPasswordSettings( + web_contents_, + password_manager::ManagePasswordsReferrer::kPasswordsAccessorySheet); } }
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc index af4a7a0..4559238 100644 --- a/chrome/browser/password_manager/password_manager_browsertest.cc +++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -2048,35 +2048,44 @@ } IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, NoPromptOnBack) { - // Go to a successful landing page through submitting first, so that it is - // reachable through going back, and the remembered page transition is form - // submit. There is no need to submit non-empty strings. - NavigateToFile("/password/password_form.html"); + for (bool new_parser_enabled : {false, true}) { + base::test::ScopedFeatureList scoped_feature_list; + if (new_parser_enabled) { + scoped_feature_list.InitAndEnableFeature( + features::kNewPasswordFormParsing); + } else { + scoped_feature_list.InitAndDisableFeature( + features::kNewPasswordFormParsing); + } + // Go to a successful landing page through submitting first, so that it is + // reachable through going back, and the remembered page transition is form + // submit. There is no need to submit non-empty strings. + NavigateToFile("/password/password_form.html"); - NavigationObserver dummy_submit_observer(WebContents()); - std::string just_submit = - "document.getElementById('input_submit_button').click()"; - ASSERT_TRUE(content::ExecuteScript(WebContents(), just_submit)); - dummy_submit_observer.Wait(); + NavigationObserver dummy_submit_observer(WebContents()); + std::string just_submit = + "document.getElementById('input_submit_button').click()"; + ASSERT_TRUE(content::ExecuteScript(WebContents(), just_submit)); + dummy_submit_observer.Wait(); - // Now go to a page with a form again, fill the form, and go back instead of - // submitting it. - NavigateToFile("/password/dummy_submit.html"); + // Now go to a page with a form again, fill the form, and go back instead of + // submitting it. + NavigateToFile("/password/dummy_submit.html"); - NavigationObserver observer(WebContents()); - std::unique_ptr<BubbleObserver> prompt_observer( - new BubbleObserver(WebContents())); - // The (dummy) submit is necessary to provisionally save the typed password. A - // user typing in the password field would not need to submit to provisionally - // save it, but the script cannot trigger that just by assigning to the - // field's value. - std::string fill_and_back = - "document.getElementById('password_field').value = 'random';" - "document.getElementById('input_submit_button').click();" - "window.history.back();"; - ASSERT_TRUE(content::ExecuteScript(WebContents(), fill_and_back)); - observer.Wait(); - EXPECT_FALSE(prompt_observer->IsSavePromptShownAutomatically()); + NavigationObserver observer(WebContents()); + BubbleObserver prompt_observer(WebContents()); + // The (dummy) submit is necessary to provisionally save the typed password. + // A user typing in the password field would not need to submit to + // provisionally save it, but the script cannot trigger that just by + // assigning to the field's value. + std::string fill_and_back = + "document.getElementById('password_field').value = 'random';" + "document.getElementById('input_submit_button').click();" + "window.history.back();"; + ASSERT_TRUE(content::ExecuteScript(WebContents(), fill_and_back)); + observer.Wait(); + EXPECT_FALSE(prompt_observer.IsSavePromptShownAutomatically()); + } } // Regression test for http://crbug.com/452306
diff --git a/chrome/browser/password_manager/password_manager_captured_sites_interactive_uitest.cc b/chrome/browser/password_manager/password_manager_captured_sites_interactive_uitest.cc index 4e2834f3..79c8e31 100644 --- a/chrome/browser/password_manager/password_manager_captured_sites_interactive_uitest.cc +++ b/chrome/browser/password_manager/password_manager_captured_sites_interactive_uitest.cc
@@ -19,6 +19,9 @@ namespace { +constexpr base::TimeDelta kWaitForSaveFallbackInterval = + base::TimeDelta::FromSeconds(5); + struct TestParams { std::string scenarioDir; std::string siteName; @@ -140,6 +143,14 @@ return false; } + bool WaitForSaveFallback() override { + BubbleObserver bubble_observer(WebContents()); + if (bubble_observer.WaitForFallbackForSaving(kWaitForSaveFallbackInterval)) + return true; + ADD_FAILURE() << "Chrome did not show the save fallback icon!"; + return false; + } + bool HasChromeShownSavePasswordPrompt() override { BubbleObserver bubble_observer(WebContents()); return bubble_observer.IsSavePromptShownAutomatically();
diff --git a/chrome/browser/password_manager/password_manager_test_base.cc b/chrome/browser/password_manager/password_manager_test_base.cc index c1872ef..728b556 100644 --- a/chrome/browser/password_manager/password_manager_test_base.cc +++ b/chrome/browser/password_manager/password_manager_test_base.cc
@@ -93,6 +93,8 @@ void WaitForFallbackForSaving(); + bool WaitForFallbackForSaving(const base::TimeDelta timeout); + bool was_prompt_automatically_shown() { return was_prompt_automatically_shown_; } @@ -185,6 +187,25 @@ run_loop_->Run(); } +bool CustomManagePasswordsUIController::WaitForFallbackForSaving( + const base::TimeDelta timeout = base::TimeDelta::Max()) { + // If the browser is currently showing the save fallback, return true + // without waiting. + if (BubbleIsManualFallbackForSaving()) + return true; + + base::RunLoop run_loop; + wait_for_fallback_ = true; + run_loop_ = &run_loop; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, run_loop_->QuitClosure(), timeout); + run_loop_->Run(); + bool shownFallbackForSaving = !wait_for_fallback_; + run_loop_ = nullptr; + wait_for_fallback_ = false; + return shownFallbackForSaving; +} + void CustomManagePasswordsUIController::OnPasswordSubmitted( std::unique_ptr<password_manager::PasswordFormManagerForUI> form_manager) { ManagePasswordsUIController::OnPasswordSubmitted(std::move(form_manager)); @@ -390,10 +411,11 @@ controller->WaitForState(password_manager::ui::PENDING_PASSWORD_STATE); } -void BubbleObserver::WaitForFallbackForSaving() const { +bool BubbleObserver::WaitForFallbackForSaving( + const base::TimeDelta timeout) const { CustomManagePasswordsUIController* controller = static_cast<CustomManagePasswordsUIController*>(passwords_ui_controller_); - controller->WaitForFallbackForSaving(); + return controller->WaitForFallbackForSaving(timeout); } PasswordManagerBrowserTestBase::PasswordManagerBrowserTestBase()
diff --git a/chrome/browser/password_manager/password_manager_test_base.h b/chrome/browser/password_manager/password_manager_test_base.h index 0970c28..d99f96c 100644 --- a/chrome/browser/password_manager/password_manager_test_base.h +++ b/chrome/browser/password_manager/password_manager_test_base.h
@@ -116,10 +116,12 @@ // PasswordManagerBrowserTestBase. void WaitForAutomaticSavePrompt() const; - // Returns once the fallback for saving becomes available. + // Returns true if the browser shows the fallback for saving password within + // the allotted timeout. // |web_contents| must be the custom one returned by // PasswordManagerBrowserTestBase. - void WaitForFallbackForSaving() const; + bool WaitForFallbackForSaving( + const base::TimeDelta timeout = base::TimeDelta::Max()) const; private: ManagePasswordsUIController* const passwords_ui_controller_;
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index 57792b1f..e6d4a6ca 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -1347,6 +1347,11 @@ SCHEMA_STRICT, SimpleSchemaValidatingPolicyHandler::RECOMMENDED_PROHIBITED, SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED)); + handlers->AddHandler(std::make_unique<SimpleSchemaValidatingPolicyHandler>( + key::kParentAccessCodeConfig, prefs::kParentAccessCodeConfig, + chrome_schema, SCHEMA_STRICT, + SimpleSchemaValidatingPolicyHandler::RECOMMENDED_PROHIBITED, + SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED)); #endif // defined(OS_CHROMEOS) #if BUILDFLAG(ENABLE_PLUGINS)
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index 22291f7..c485d1da 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc
@@ -3956,6 +3956,7 @@ POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true), nullptr); UpdateProviderPolicy(policies); + keyboard_client->FlushForTesting(); EXPECT_TRUE(keyboard_client->is_keyboard_enabled()); ClearEnableFlag(keyboard::mojom::KeyboardEnableFlag::kTouchEnabled); EXPECT_TRUE(keyboard_client->is_keyboard_enabled()); @@ -3966,6 +3967,7 @@ POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(false), nullptr); UpdateProviderPolicy(policies); + keyboard_client->FlushForTesting(); EXPECT_FALSE(keyboard_client->is_keyboard_enabled()); SetEnableFlag(keyboard::mojom::KeyboardEnableFlag::kTouchEnabled); EXPECT_FALSE(keyboard_client->is_keyboard_enabled()); @@ -6663,12 +6665,15 @@ { constexpr size_t kMaxFileSizeBytes = 1000 * 1000; + constexpr int kOutputPeriodMs = 1000; + base::RunLoop run_loop; // Test focus - remote-bound logging allowed if and only if the policy // is configured to allow it. webrtc_event_log_manager->StartRemoteLogging( - render_process_id, kPeerConnectionId, kMaxFileSizeBytes, kWebAppId, + render_process_id, kPeerConnectionId, kMaxFileSizeBytes, + kOutputPeriodMs, kWebAppId, BlockingBoolExpectingReplyWithExtras(&run_loop, remote_logging_allowed)); run_loop.Run();
diff --git a/chrome/browser/policy/test/policy_testserver.py b/chrome/browser/policy/test/policy_testserver.py index 91ca854..ce5a6c1 100644 --- a/chrome/browser/policy/test/policy_testserver.py +++ b/chrome/browser/policy/test/policy_testserver.py
@@ -420,26 +420,15 @@ Returns: A tuple of HTTP status code and response data to send to the client. """ - enrollment_token = self.CheckEnrollmentToken() policy = self.server.GetPolicies() - if enrollment_token: - if ((not policy['token_enrollment']) or - (not policy['token_enrollment']['token']) or - (not policy['token_enrollment']['username'])): - return (500, 'Error in config - no token-based enrollment') - if policy['token_enrollment']['token'] != enrollment_token: - return (403, 'Invalid enrollment token') - username = policy['token_enrollment']['username'] - else: - # Check the auth token and device ID. - auth = self.CheckGoogleLogin() - if not auth: - return (403, 'No authorization') + # Check the auth token and device ID. + auth = self.CheckGoogleLogin() + if not auth: + return (403, 'No authorization') - if ('managed_users' not in policy): - return (500, 'Error in config - no managed users') - username = self.server.ResolveUser(auth) - + if ('managed_users' not in policy): + return (500, 'Error in config - no managed users') + username = self.server.ResolveUser(auth) if ('*' not in policy['managed_users'] and username not in policy['managed_users']): return (403, 'Unmanaged') @@ -470,7 +459,25 @@ ENTERPRISE_ENROLLMENT_CERTIFICATE: return(403, 'Invalid certificate type for registration') - return self.RegisterDeviceAndSendResponse(req.device_register_request, None) + register_req = req.device_register_request + username = None + + if (register_req.flavor == dm.DeviceRegisterRequest. + FLAVOR_ENROLLMENT_ATTESTATION_USB_ENROLLMENT): + enrollment_token = self.CheckEnrollmentToken() + policy = self.server.GetPolicies() + if not enrollment_token: + return (401, 'Missing enrollment token.') + + if ((not policy['token_enrollment']) or + (not policy['token_enrollment']['token']) or + (not policy['token_enrollment']['username'])): + return (500, 'Error in config - no token-based enrollment') + if policy['token_enrollment']['token'] != enrollment_token: + return (403, 'Invalid enrollment token') + username = policy['token_enrollment']['username'] + + return self.RegisterDeviceAndSendResponse(register_req, username) def RegisterDeviceAndSendResponse(self, msg, username): """Registers a device and send a response to the client.
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index e5413161..6927681f 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc
@@ -713,7 +713,6 @@ net::URLRequestContext* ProfileIOData::GetIsolatedAppRequestContext( IOThread* io_thread, - net::URLRequestContext* main_context, const StoragePartitionDescriptor& partition_descriptor, std::unique_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> protocol_handler_interceptor,
diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h index 0118c716..0d720e6 100644 --- a/chrome/browser/profiles/profile_io_data.h +++ b/chrome/browser/profiles/profile_io_data.h
@@ -127,7 +127,6 @@ virtual net::CookieStore* GetExtensionsCookieStore() const = 0; net::URLRequestContext* GetIsolatedAppRequestContext( IOThread* io_thread, - net::URLRequestContext* main_context, const StoragePartitionDescriptor& partition_descriptor, std::unique_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> protocol_handler_interceptor,
diff --git a/chrome/browser/resource_coordinator/tab_activity_watcher.cc b/chrome/browser/resource_coordinator/tab_activity_watcher.cc index a38717a..35a20ef 100644 --- a/chrome/browser/resource_coordinator/tab_activity_watcher.cc +++ b/chrome/browser/resource_coordinator/tab_activity_watcher.cc
@@ -42,6 +42,16 @@ base::TimeDelta::FromDays(1), 50) namespace resource_coordinator { +namespace { + +// Returns an int64_t number as label_id or query_id. The number is generated +// incrementally from 1. +int64_t NewInt64ForLabelIdOrQueryId() { + static int64_t id = 0; + return ++id; +} + +} // namespace // Per-WebContents helper class that observes its WebContents, notifying // TabActivityWatcher when interesting events occur. Also provides @@ -56,7 +66,7 @@ // Calculates the tab reactivation score for a background tab. Returns nullopt // if the score could not be calculated, e.g. because the tab is in the // foreground. - base::Optional<float> CalculateReactivationScore(bool also_log_to_ukm) { + base::Optional<float> CalculateReactivationScore() { if (web_contents()->IsBeingDestroyed() || backgrounded_time_.is_null()) return base::nullopt; @@ -65,34 +75,22 @@ const auto mru = GetMRUFeatures(); const int lru_index = mru.total - mru.index - 1; - // If the least recently used index is greater than both numbers, then we - // don't need to score or log the tab; directly return instead. - if (lru_index >= GetNumOldestTabsToScoreWithTabRanker() && - lru_index >= GetNumOldestTabsToLogWithTabRanker()) { + // If the least recently used index is greater than or equal to N, which + // means the tab is not in the oldest N list, we should simply skip it. + // The N is defaulted as kMaxInt so that all tabs are scored. + if (lru_index >= GetNumOldestTabsToScoreWithTabRanker()) return base::nullopt; - } base::Optional<tab_ranker::TabFeatures> tab = GetTabFeatures(mru); if (!tab.has_value()) return base::nullopt; - if (also_log_to_ukm && lru_index < GetNumOldestTabsToLogWithTabRanker()) { - // A new label_id_ is generated for this query. - // The same label_id_ will be logged with ForegroundedOrClosed event later - // on so that TabFeatures can be paired with ForegroundedOrClosed. - label_id_ = static_cast<int64_t>( - base::RandGenerator(std::numeric_limits<uint64_t>::max() - 1) + 1); - TabActivityWatcher::GetInstance()->tab_metrics_logger_->LogTabMetrics( - ukm_source_id_, tab.value(), web_contents(), label_id_); - } - - if (lru_index < GetNumOldestTabsToScoreWithTabRanker()) { - float score; - if (TabActivityWatcher::GetInstance()->predictor_.ScoreTab( - tab.value(), &score) == tab_ranker::TabRankerResult::kSuccess) - return score; - } - + float score = 0.0f; + const tab_ranker::TabRankerResult result = + TabActivityWatcher::GetInstance()->predictor_.ScoreTab(tab.value(), + &score); + if (result == tab_ranker::TabRankerResult::kSuccess) + return score; return base::nullopt; } @@ -164,6 +162,24 @@ } } + // Logs current TabFeatures; skips if current tab is foregrounded. + void LogCurrentTabFeatures() { + if (backgrounded_time_.is_null()) + return; + const base::Optional<tab_ranker::TabFeatures> tab = + GetTabFeatures(mru_features_); + if (!tab.has_value()) + return; + + // A new label_id_ is generated for this query. + // The same label_id_ will be logged with ForegroundedOrClosed event later + // on so that TabFeatures can be paired with ForegroundedOrClosed. + label_id_ = NewInt64ForLabelIdOrQueryId(); + + TabActivityWatcher::GetInstance()->tab_metrics_logger_->LogTabMetrics( + ukm_source_id_, tab.value(), web_contents(), label_id_); + } + // Sets foregrounded_time_ to NowTicks() so this becomes the // most-recently-used tab. void TabWindowActivated() { foregrounded_time_ = NowTicks(); } @@ -505,17 +521,35 @@ TabActivityWatcher::~TabActivityWatcher() = default; base::Optional<float> TabActivityWatcher::CalculateReactivationScore( - content::WebContents* web_contents, - bool also_log_to_ukm) { + content::WebContents* web_contents) { WebContentsData* web_contents_data = WebContentsData::FromWebContents(web_contents); if (!web_contents_data) return base::nullopt; - return web_contents_data->CalculateReactivationScore(also_log_to_ukm); + return web_contents_data->CalculateReactivationScore(); } -void TabActivityWatcher::SetQueryIdForTabMetricsLogger(int64_t query_id) { - tab_metrics_logger_->set_query_id(query_id); +void TabActivityWatcher::LogOldestNTabFeatures() { + const int oldest_n_to_log = GetNumOldestTabsToLogWithTabRanker(); + if (oldest_n_to_log <= 0) + return; + + // Set query_id so that all TabFeatures logged in this query can be joined. + tab_metrics_logger_->set_query_id(NewInt64ForLabelIdOrQueryId()); + + std::vector<WebContentsData*> web_contents_data = GetSortedWebContentsData(); + const int contents_data_size = web_contents_data.size(); + // Only log oldest n tabs which are tabs + // from web_contents_data.size() - 1 + // to web_contents_data.size() - oldest_n_to_log. + const int last_index_to_log = + std::max(contents_data_size - oldest_n_to_log, 0); + for (int i = contents_data_size - 1; i >= last_index_to_log; --i) { + // Set correct mru_features_. + web_contents_data[i]->mru_features_.index = i; + web_contents_data[i]->mru_features_.total = contents_data_size; + web_contents_data[i]->LogCurrentTabFeatures(); + } } void TabActivityWatcher::OnBrowserSetLastActive(Browser* browser) { @@ -600,37 +634,41 @@ return instance.get(); } +std::vector<TabActivityWatcher::WebContentsData*> +TabActivityWatcher::GetSortedWebContentsData() { + // Put all web_contents_data into a vector. + std::vector<WebContentsData*> web_contents_data; + for (Browser* browser : *BrowserList::GetInstance()) { + // Ignore incognito browsers. + if (browser->profile()->IsOffTheRecord()) + continue; + + const int count = browser->tab_strip_model()->count(); + + for (int i = 0; i < count; i++) { + auto* const other = WebContentsData::FromWebContents( + browser->tab_strip_model()->GetWebContentsAt(i)); + if (other) + web_contents_data.push_back(other); + } + } + + // Sort all web_contents_data by MoreRecentlyUsed. + std::sort(web_contents_data.begin(), web_contents_data.end(), + WebContentsData::MoreRecentlyUsed); + return web_contents_data; +} // When a WillCloseAllTabs is invoked, all MRU index of that tab_strip_model // is calculated and saved at that point. void TabActivityWatcher::WillCloseAllTabs(TabStripModel* tab_strip_model) { if (tab_strip_model) { - // Put all web_contents_data into a vector. - std::vector<WebContentsData*> web_contents_data; - for (Browser* browser : *BrowserList::GetInstance()) { - // Ignore incognito browsers. - if (browser->profile()->IsOffTheRecord()) - continue; - - const int count = browser->tab_strip_model()->count(); - - for (int i = 0; i < count; i++) { - auto* other = WebContentsData::FromWebContents( - browser->tab_strip_model()->GetWebContentsAt(i)); - if (other) - web_contents_data.push_back(other); - } - } - - // Sort all web_contents_data by MoreRecentlyUsed. - std::sort(web_contents_data.begin(), web_contents_data.end(), - WebContentsData::MoreRecentlyUsed); - + std::vector<WebContentsData*> web_contents_data = + GetSortedWebContentsData(); // Assign index for each web_contents_data. const std::size_t total_tabs = web_contents_data.size(); for (std::size_t i = 0; i < total_tabs; ++i) { - WebContentsData* const contents_i = web_contents_data[i]; - contents_i->mru_features_.index = i; - contents_i->mru_features_.total = total_tabs; + web_contents_data[i]->mru_features_.index = i; + web_contents_data[i]->mru_features_.total = total_tabs; } // Add will_be_closed tabs to |all_closing_tabs_| set.
diff --git a/chrome/browser/resource_coordinator/tab_activity_watcher.h b/chrome/browser/resource_coordinator/tab_activity_watcher.h index af001def..39bffed 100644 --- a/chrome/browser/resource_coordinator/tab_activity_watcher.h +++ b/chrome/browser/resource_coordinator/tab_activity_watcher.h
@@ -34,13 +34,10 @@ // value indicates a higher likelihood of being reactivated. // Returns the score if the tab could be scored. base::Optional<float> CalculateReactivationScore( - content::WebContents* web_contents, - bool also_log_to_ukm = false); + content::WebContents* web_contents); - // Generates a new query_id for logging CalculateReactivationScore calls. - // This function is called inside TabManager::GetSortedLifecycleUnits when - // reactivation scores are queried for all tabs. - void SetQueryIdForTabMetricsLogger(int64_t query_id); + // Log TabFeatures for oldest n tabs. + void LogOldestNTabFeatures(); // Returns the single instance, creating it if necessary. static TabActivityWatcher* GetInstance(); @@ -52,6 +49,9 @@ // TODO(michaelpg): Merge this into TabLifecycleUnit. class WebContentsData; + // Returns all WebContentsData* sorted by MoreRecentlyUsed. + std::vector<WebContentsData*> GetSortedWebContentsData(); + // Called When A Tab is closed, log necessary metrics and erase the // |web_contents_data| pointer in |all_closing_tabs_|. void OnTabClosed(WebContentsData* web_contents_data);
diff --git a/chrome/browser/resource_coordinator/tab_activity_watcher_browsertest.cc b/chrome/browser/resource_coordinator/tab_activity_watcher_browsertest.cc index b8259cc..1ba5e9d6 100644 --- a/chrome/browser/resource_coordinator/tab_activity_watcher_browsertest.cc +++ b/chrome/browser/resource_coordinator/tab_activity_watcher_browsertest.cc
@@ -494,17 +494,16 @@ } // Test the query time logging is correct. -IN_PROC_BROWSER_TEST_F(TabActivityWatcherUkmTest, - LogInCalculateReactivationScore) { +IN_PROC_BROWSER_TEST_F(TabActivityWatcherUkmTest, LogOldestNTabFeatures) { // Set Feature params for this test. // (1) background log is disabled, so that only query time logging and // corresponding labels should be logged. - // (2) number of oldest tabs to log is set to 2, so that foreground tab should - // not be logged. + // (2) number of oldest tabs to log is set to 1, so that only 1 tab should be + // logged. base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeatureWithParameters( features::kTabRanker, - {{"number_of_oldest_tabs_to_log_with_TabRanker", "2"}, + {{"number_of_oldest_tabs_to_log_with_TabRanker", "1"}, {"disable_background_log_with_TabRanker", "true"}}); // Use test clock so tabs have non-zero backgrounded times. @@ -523,14 +522,7 @@ browser()->tab_strip_model()->ActivateTabAt(0, kIsUserGesture); test_clock.Advance(base::TimeDelta::FromMinutes(1)); - // Score tab_0 will fail because tab_0 is current foreground tab. - base::Optional<float> tab_0 = - TabActivityWatcher::GetInstance()->CalculateReactivationScore( - browser()->tab_strip_model()->GetWebContentsAt(0), true); - EXPECT_FALSE(tab_0.has_value()); - - // No metrics should be logged till now. - EXPECT_EQ(0, ukm_entry_checker_->NumNewEntriesRecorded(kEntryName)); + // Foregrounded event should be logged for tab@0 EXPECT_EQ(1, ukm_entry_checker_->NumNewEntriesRecorded(kFOCEntryName)); { SCOPED_TRACE(""); @@ -541,16 +533,11 @@ {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 0}}); } - // Set query_id. - const int64_t query_id = 1234; - TabActivityWatcher::GetInstance()->SetQueryIdForTabMetricsLogger(query_id); + // No tab metrics should be logged till now. + EXPECT_EQ(0, ukm_entry_checker_->NumNewEntriesRecorded(kEntryName)); - // tab@1 is scored successfully. - base::Optional<float> tab_1 = - TabActivityWatcher::GetInstance()->CalculateReactivationScore( - browser()->tab_strip_model()->GetWebContentsAt(1), true); - EXPECT_TRUE(tab_1.has_value()); - int64_t label_id_1 = 0; + // Call LogQueryTimeTabFeatures should log the oldest tab which is tab@1. + TabActivityWatcher::GetInstance()->LogOldestNTabFeatures(); { SCOPED_TRACE(""); // tab feature of tab@1 should be logged correctly. @@ -560,14 +547,11 @@ [TabManager_TabMetrics::kNumReactivationBeforeName] = 0; expected_tab_feature_values[TabManager_TabMetrics::kTotalTabCountName] = 3; expected_tab_feature_values[TabManager_TabMetrics::kWindowTabCountName] = 3; - expected_tab_feature_values[TabManager_TabMetrics::kQueryIdName] = query_id; + expected_tab_feature_values[TabManager_TabMetrics::kLabelIdName] = 2; + expected_tab_feature_values[TabManager_TabMetrics::kQueryIdName] = 1; ukm_entry_checker_->ExpectNewEntry(kEntryName, test_urls_[1], expected_tab_feature_values); - // Get label_id_1 for later verification. - label_id_1 = - GetLatestMetricValue(kEntryName, TabManager_TabMetrics::kLabelIdName); - EXPECT_NE(label_id_1, 0); } // Reactivate tab@1 should log a ForegroundedOrClosed event with LabelId as @@ -579,16 +563,12 @@ ukm_entry_checker_->ExpectNewEntry( kFOCEntryName, test_urls_[1], {{TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 1}, - {TabManager_Background_ForegroundedOrClosed::kLabelIdName, label_id_1}, + {TabManager_Background_ForegroundedOrClosed::kLabelIdName, 2}, {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 0}}); } - // tab@2 is scored successfully. - base::Optional<float> tab_2 = - TabActivityWatcher::GetInstance()->CalculateReactivationScore( - browser()->tab_strip_model()->GetWebContentsAt(2), true); - EXPECT_TRUE(tab_2.has_value()); - int64_t label_id_2 = 0; + // Call LogQueryTimeTabFeatures should log the oldest tab which is tab@2. + TabActivityWatcher::GetInstance()->LogOldestNTabFeatures(); { SCOPED_TRACE(""); // tab feature of tab@2 should be logged correctly. @@ -598,14 +578,11 @@ [TabManager_TabMetrics::kNumReactivationBeforeName] = 0; expected_tab_feature_values[TabManager_TabMetrics::kTotalTabCountName] = 3; expected_tab_feature_values[TabManager_TabMetrics::kWindowTabCountName] = 3; - expected_tab_feature_values[TabManager_TabMetrics::kQueryIdName] = query_id; + expected_tab_feature_values[TabManager_TabMetrics::kLabelIdName] = 4; + expected_tab_feature_values[TabManager_TabMetrics::kQueryIdName] = 3; ukm_entry_checker_->ExpectNewEntry(kEntryName, test_urls_[2], expected_tab_feature_values); - // Get label_id_2 for later verification. - label_id_2 = - GetLatestMetricValue(kEntryName, TabManager_TabMetrics::kLabelIdName); - EXPECT_NE(label_id_2, 0); } // No ForegroundedOrClosed event is logged for tab@1 because it's foregrounded @@ -617,7 +594,7 @@ ukm_entry_checker_->ExpectNewEntry( kFOCEntryName, test_urls_[2], {{TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 0}, - {TabManager_Background_ForegroundedOrClosed::kLabelIdName, label_id_2}, + {TabManager_Background_ForegroundedOrClosed::kLabelIdName, 4}, {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 0}}); // Close Browser should log a ForegroundedOrClosed event for tab@0 with @@ -636,7 +613,7 @@ base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeatureWithParameters( features::kTabRanker, - {{"number_of_oldest_tabs_to_log_with_TabRanker", "2"}, + {{"number_of_oldest_tabs_to_log_with_TabRanker", "1"}, {"disable_background_log_with_TabRanker", "true"}}); ui_test_utils::NavigateToURL(browser(), test_urls_[0]); @@ -644,23 +621,17 @@ // No TabMetrics events are logged till now. EXPECT_EQ(0u, ukm_entry_checker_->NumEntries(kEntryName)); - // Score tab_0 will succeed. - base::Optional<float> tab_0 = - TabActivityWatcher::GetInstance()->CalculateReactivationScore( - browser()->tab_strip_model()->GetWebContentsAt(0), true); - EXPECT_TRUE(tab_0.has_value()); - int64_t label_id_0 = 0; + // Log tab_0. + TabActivityWatcher::GetInstance()->LogOldestNTabFeatures(); { SCOPED_TRACE(""); UkmMetricMap expected_metrics = kBasicMetricValues; expected_metrics[TabManager_TabMetrics::kNavigationEntryCountName] = 2; + expected_metrics[TabManager_TabMetrics::kLabelIdName] = 2; + expected_metrics[TabManager_TabMetrics::kQueryIdName] = 1; // tab feature of tab@0 should be logged correctly. ukm_entry_checker_->ExpectNewEntry(kEntryName, test_urls_[0], expected_metrics); - // Get label_id_0 for later verification. - label_id_0 = - GetLatestMetricValue(kEntryName, TabManager_TabMetrics::kLabelIdName); - EXPECT_NE(label_id_0, 0); } // Discard the first tab. @@ -677,27 +648,22 @@ UkmMetricMap expected_metrics = { {TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 1}, {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 1}, - {TabManager_Background_ForegroundedOrClosed::kLabelIdName, label_id_0}}; + {TabManager_Background_ForegroundedOrClosed::kLabelIdName, 2}}; ukm_entry_checker_->ExpectNewEntry(kFOCEntryName, test_urls_[0], expected_metrics); } - // Score tab_1 will succeed. - base::Optional<float> tab_1 = - TabActivityWatcher::GetInstance()->CalculateReactivationScore( - browser()->tab_strip_model()->GetWebContentsAt(1), true); - EXPECT_TRUE(tab_1.has_value()); - int64_t label_id_1 = 0; + // Log tab_1. + TabActivityWatcher::GetInstance()->LogOldestNTabFeatures(); { SCOPED_TRACE(""); // tab feature of tab@1 should be logged correctly. + UkmMetricMap expected_metrics = kBasicMetricValues; + expected_metrics[TabManager_TabMetrics::kLabelIdName] = 4; + expected_metrics[TabManager_TabMetrics::kQueryIdName] = 3; ukm_entry_checker_->ExpectNewEntry(kEntryName, test_urls_[1], - kBasicMetricValues); - // Get label_id_1 for later verification. - label_id_1 = - GetLatestMetricValue(kEntryName, TabManager_TabMetrics::kLabelIdName); - EXPECT_NE(label_id_0, 0); + expected_metrics); } // Discard the second tab. @@ -713,7 +679,7 @@ UkmMetricMap expected_metrics = { {TabManager_Background_ForegroundedOrClosed::kIsForegroundedName, 0}, {TabManager_Background_ForegroundedOrClosed::kIsDiscardedName, 1}, - {TabManager_Background_ForegroundedOrClosed::kLabelIdName, label_id_1}}; + {TabManager_Background_ForegroundedOrClosed::kLabelIdName, 4}}; ukm_entry_checker_->ExpectNewEntry(kFOCEntryName, test_urls_[1], expected_metrics);
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc index f62c3f2..93f3f47b1 100644 --- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc +++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
@@ -446,6 +446,15 @@ LifecycleUnit::SortKey TabLifecycleUnitSource::TabLifecycleUnit::GetSortKey() const { + if (base::FeatureList::IsEnabled(features::kTabRanker)) { + const base::Optional<float> reactivation_score = + resource_coordinator::TabActivityWatcher::GetInstance() + ->CalculateReactivationScore(web_contents()); + if (reactivation_score.has_value()) + return SortKey(reactivation_score.value(), last_focused_time_); + return SortKey(SortKey::kMaxScore, last_focused_time_); + } + return SortKey(last_focused_time_); }
diff --git a/chrome/browser/resource_coordinator/tab_manager.cc b/chrome/browser/resource_coordinator/tab_manager.cc index 56e58ec..673928c 100644 --- a/chrome/browser/resource_coordinator/tab_manager.cc +++ b/chrome/browser/resource_coordinator/tab_manager.cc
@@ -98,10 +98,6 @@ : lifecycle_unit(lifecycle_unit), sort_key(lifecycle_unit->GetSortKey()) {} - LifecycleUnitAndSortKey(LifecycleUnit* lifecycle_unit, - const LifecycleUnit::SortKey& key) - : lifecycle_unit(lifecycle_unit), sort_key(key) {} - bool operator<(const LifecycleUnitAndSortKey& other) const { return sort_key < other.sort_key; } @@ -113,23 +109,6 @@ LifecycleUnit::SortKey sort_key; }; -// Helper function that sorts |lifecycle_units_and_sort_keys|, and returns -// a LifecycleUnitVector. -LifecycleUnitVector SortedLifecycleUnitsFrom( - std::vector<LifecycleUnitAndSortKey>* lifecycle_units_and_sort_keys) { - std::sort(lifecycle_units_and_sort_keys->begin(), - lifecycle_units_and_sort_keys->end()); - - LifecycleUnitVector sorted_lifecycle_units; - sorted_lifecycle_units.reserve(lifecycle_units_and_sort_keys->size()); - for (auto& lifecycle_unit_and_sort_key : *lifecycle_units_and_sort_keys) { - sorted_lifecycle_units.push_back( - lifecycle_unit_and_sort_key.lifecycle_unit); - } - - return sorted_lifecycle_units; -} - std::unique_ptr<base::trace_event::ConvertableToTraceFormat> DataAsTraceValue( TabManager::BackgroundTabLoadingMode mode, size_t num_of_pending_navigations, @@ -302,12 +281,25 @@ for (auto* lifecycle_unit : lifecycle_units_) lifecycle_units_and_sort_keys.emplace_back(lifecycle_unit); - return SortedLifecycleUnitsFrom(&lifecycle_units_and_sort_keys); + std::sort(lifecycle_units_and_sort_keys.begin(), + lifecycle_units_and_sort_keys.end()); + + LifecycleUnitVector sorted_lifecycle_units; + sorted_lifecycle_units.reserve(lifecycle_units_and_sort_keys.size()); + for (auto& lifecycle_unit_and_sort_key : lifecycle_units_and_sort_keys) { + sorted_lifecycle_units.push_back( + lifecycle_unit_and_sort_key.lifecycle_unit); + } + + return sorted_lifecycle_units; } void TabManager::DiscardTab(LifecycleUnitDiscardReason reason) { - if (reason == LifecycleUnitDiscardReason::URGENT) + if (reason == LifecycleUnitDiscardReason::URGENT) { stats_collector_->RecordWillDiscardUrgently(GetNumAliveTabs()); + resource_coordinator::TabActivityWatcher::GetInstance() + ->LogOldestNTabFeatures(); + } #if defined(OS_CHROMEOS) // Call Chrome OS specific low memory handling process. @@ -670,12 +662,7 @@ LifecycleUnitDiscardReason reason) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - const LifecycleUnitVector sorted_lifecycle_units = - base::FeatureList::IsEnabled(features::kTabRanker) - ? GetSortedLifecycleUnitsFromTabRanker() - : GetSortedLifecycleUnits(); - - for (LifecycleUnit* lifecycle_unit : sorted_lifecycle_units) { + for (LifecycleUnit* lifecycle_unit : GetSortedLifecycleUnits()) { DecisionDetails decision_details; if (lifecycle_unit->CanDiscard(reason, &decision_details) && lifecycle_unit->Discard(reason)) { @@ -1178,34 +1165,4 @@ return true; } -LifecycleUnitVector TabManager::GetSortedLifecycleUnitsFromTabRanker() { - // Set query_id if TabRanker is enabled. - const int64_t query_id = static_cast<int64_t>(base::RandUint64()); - resource_coordinator::TabActivityWatcher::GetInstance() - ->SetQueryIdForTabMetricsLogger(query_id); - - std::vector<LifecycleUnitAndSortKey> lifecycle_units_and_sort_keys; - lifecycle_units_and_sort_keys.reserve(lifecycle_units_.size()); - for (auto* lifecycle_unit : lifecycle_units_) { - TabLifecycleUnitExternal* tab_lifecycle_unit_external = - lifecycle_unit->AsTabLifecycleUnitExternal(); - // For now, all LifecycleUnits are TabLifecycleUnitExternals. - DCHECK(tab_lifecycle_unit_external); - - base::Optional<float> reactivation_score = - resource_coordinator::TabActivityWatcher::GetInstance() - ->CalculateReactivationScore( - tab_lifecycle_unit_external->GetWebContents(), true); - - float score = reactivation_score.has_value() - ? reactivation_score.value() - : LifecycleUnit::SortKey::kMaxScore; - lifecycle_units_and_sort_keys.emplace_back( - lifecycle_unit, - LifecycleUnit::SortKey(score, lifecycle_unit->GetLastFocusedTime())); - } - - return SortedLifecycleUnitsFrom(&lifecycle_units_and_sort_keys); -} - } // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tab_manager.h b/chrome/browser/resource_coordinator/tab_manager.h index 29fd2d4..f562d3f1 100644 --- a/chrome/browser/resource_coordinator/tab_manager.h +++ b/chrome/browser/resource_coordinator/tab_manager.h
@@ -471,13 +471,6 @@ // Indicates if TabManager should proactively discard tabs. bool ShouldProactivelyDiscardTabs(); - // Returns the LifecycleUnits managed by this, similar to - // GetSortedLifecycleUnits. The result is sorted based on - // (reactivation_score_from_tab_ranker, last_activity_time). - // TODO(charleszhao): This is only used for TabRanker experiment and should be - // cleaned up once the experiment is done. https://crbug.com/908959. - LifecycleUnitVector GetSortedLifecycleUnitsFromTabRanker(); - // LifecycleUnits managed by this. LifecycleUnitSet lifecycle_units_;
diff --git a/chrome/browser/resources/app_management/BUILD.gn b/chrome/browser/resources/app_management/BUILD.gn index 42a110cf..a3f99ff 100644 --- a/chrome/browser/resources/app_management/BUILD.gn +++ b/chrome/browser/resources/app_management/BUILD.gn
@@ -9,6 +9,7 @@ deps = [ ":app", ":browser_proxy", + ":fake_page_handler", ":main_view", ] } @@ -23,6 +24,7 @@ js_library("browser_proxy") { deps = [ ":externs", + ":fake_page_handler", "//ui/webui/resources/js:cr", ] } @@ -36,6 +38,13 @@ ] } +js_library("fake_page_handler") { + deps = [ + ":externs", + "//ui/webui/resources/js:cr", + ] +} + js_library("main_view") { deps = [] }
diff --git a/chrome/browser/resources/app_management/browser_proxy.html b/chrome/browser/resources/app_management/browser_proxy.html index 5ec9fbea..0cda55070 100644 --- a/chrome/browser/resources/app_management/browser_proxy.html +++ b/chrome/browser/resources/app_management/browser_proxy.html
@@ -1,4 +1,5 @@ <link rel="import" href="chrome://resources/html/cr.html"> <script src="browser_proxy.js"></script> +<script src="fake_page_handler.js"></script> <script src="chrome://resources/js/mojo_bindings_lite.js"></script> <script src="app_management.mojom-lite.js"></script>
diff --git a/chrome/browser/resources/app_management/browser_proxy.js b/chrome/browser/resources/app_management/browser_proxy.js index c3427e55..9876c58 100644 --- a/chrome/browser/resources/app_management/browser_proxy.js +++ b/chrome/browser/resources/app_management/browser_proxy.js
@@ -7,11 +7,21 @@ constructor() { /** @type {appManagement.mojom.PageCallbackRouter} */ this.callbackRouter = new appManagement.mojom.PageCallbackRouter(); - /** @type {appManagement.mojom.PageHandlerProxy} */ - this.handler = new appManagement.mojom.PageHandlerProxy(); - const factory = appManagement.mojom.PageHandlerFactory.getProxy(); - factory.createPageHandler( - this.callbackRouter.createProxy(), this.handler.createRequest()); + + /** @type {appManagement.mojom.PageHandlerInterface} */ + this.handler = null; + + const urlParams = new URLSearchParams(window.location.search); + const useFake = urlParams.get('fakeBackend'); + if (useFake) { + this.handler = new app_management.FakePageHandler( + this.callbackRouter.createProxy()); + } else { + this.handler = new appManagement.mojom.PageHandlerProxy(); + const factory = appManagement.mojom.PageHandlerFactory.getProxy(); + factory.createPageHandler( + this.callbackRouter.createProxy(), this.handler.createRequest()); + } } }
diff --git a/chrome/browser/resources/app_management/fake_page_handler.js b/chrome/browser/resources/app_management/fake_page_handler.js new file mode 100644 index 0000000..dc66470 --- /dev/null +++ b/chrome/browser/resources/app_management/fake_page_handler.js
@@ -0,0 +1,27 @@ +// 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. + +cr.define('app_management', function() { + /** @implements {appManagement.mojom.PageHandlerInterface} */ + class FakePageHandler { + constructor(page) { + /** @type {appManagement.mojom.PageInterface} */ + this.page = page; + } + + getApps() { + const fakeAppIdList = [ + 'ahfgeienlihckogmohjhadlkjgocpleb', + 'aohghmighlieiainnegkcijnfilokake', + 'blpcfgokakmgnkcojhhkbfbldkacnbeo', + 'pjkljhegncpnkpknbcohdijeoejaedia', + 'aapocclcgogkmnckokdopfmhonfmgoek', + ]; + + this.page.onAppsAdded(fakeAppIdList); + } + } + + return {FakePageHandler: FakePageHandler}; +});
diff --git a/chrome/browser/resources/app_management/main_view.html b/chrome/browser/resources/app_management/main_view.html index 70f02de..cd6d891 100644 --- a/chrome/browser/resources/app_management/main_view.html +++ b/chrome/browser/resources/app_management/main_view.html
@@ -1,17 +1,84 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html"> +<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <dom-module id="app-management-main-view"> <template> <style> - cr-toolbar { - color: rgba(0, 0, 0, 0.54); - } + :host { + --primary-text-color: rgba(0, 0, 0, 0.87); + --secondary-text-color: rgba(0, 0, 0, 0.54); + --card-title-text-color: rgba(90, 90, 90, 1); + } + + cr-toolbar { + color: var(--secondary-text-color); + } + + #app-list { + @apply --cr-card-elevation; + background-color: #fff; + border-radius: var(--cr-card-border-radius); + font-size: 13px; + margin: 24px auto; + width: 676px; + } + + #app-list-title { + color: var(--card-title-text-color); + font-weight: 400; + padding: 16px 24px; + } + + .app-list-item { + align-items: center; + border-top: 1px solid rgba(0, 0, 0, 0.12); + color: var(--primary-text-color); + display: flex; + flex-direction: row; + font-weight: 400; + height: 64px; + } + + #app-icon { + height: 32px; + margin-inline-end: 20px; + margin-inline-start: 24px; + width: 32px; + } + + #app-title { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + } + + #subpage-arrow { + margin-inline-end: 8px; + padding: 12px; + } + + #more-apps { + border-top: 1px solid rgba(0, 0, 0, 0.12); + color: var(--secondary-text-color); + padding: 16px 24px; + } </style> - <cr-toolbar page-name="Apps" - search-prompt="Search Settings"> + <cr-toolbar page-name="$i18n{title}" search-prompt="$i18n{searchPrompt}"> </cr-toolbar> + <div id="app-list"> + <div id="app-list-title">$i18n{appListTitle}</div> + <template is="dom-repeat" items="[[apps_]]"> + <div class="app-list-item"> + <img id="app-icon" src="[[iconUrlFromId_(item)]]"> + <div id="app-title">[[item]]</div> + <img id="subpage-arrow" + src="chrome://resources/images/arrow_right.svg"> + </div> + </template> + <div id="more-apps">$i18n{moreApps}</div> + </div> </template> <script src="chrome://apps/main_view.js"></script> </dom-module>
diff --git a/chrome/browser/resources/app_management/main_view.js b/chrome/browser/resources/app_management/main_view.js index 74989dcc..6d6d966 100644 --- a/chrome/browser/resources/app_management/main_view.js +++ b/chrome/browser/resources/app_management/main_view.js
@@ -4,4 +4,27 @@ Polymer({ is: 'app-management-main-view', + + properties: { + apps_: { + type: Array, + } + }, + + attached: function() { + const callbackRouter = + app_management.BrowserProxy.getInstance().callbackRouter; + this.listenerIds_ = + [callbackRouter.onAppsAdded.addListener((ids) => this.apps_ = ids)]; + }, + + detached: function() { + const callbackRouter = + app_management.BrowserProxy.getInstance().callbackRouter; + this.listenerIds_.forEach((id) => callbackRouter.removeListener(id)); + }, + + iconUrlFromId_: function(id) { + return `chrome://extension-icon/${id}/128/1`; + } });
diff --git a/chrome/browser/resources/cast/cast.js b/chrome/browser/resources/cast/cast.js index 79b6dc3c..3cb9c147 100644 --- a/chrome/browser/resources/cast/cast.js +++ b/chrome/browser/resources/cast/cast.js
@@ -3,29 +3,29 @@ // found in the LICENSE file. window.addEventListener('load', function init() { - var extensionView = document.querySelector('extensionview'); + const extensionView = document.querySelector('extensionview'); /** * @param {string} str * @return {!Array<string>} */ - var splitUrlOnHash = function(str) { + const splitUrlOnHash = function(str) { str = str || ''; - var pos = str.indexOf('#'); + const pos = str.indexOf('#'); return (pos !== -1) ? [str.substr(0, pos), str.substr(pos + 1)] : [str, '']; }; new MutationObserver(function() { - var newHash = splitUrlOnHash(extensionView.getAttribute('src'))[1]; - var oldHash = window.location.hash.substr(1); + const newHash = splitUrlOnHash(extensionView.getAttribute('src'))[1]; + const oldHash = window.location.hash.substr(1); if (newHash !== oldHash) { window.location.hash = newHash; } }).observe(extensionView, {attributes: true}); window.addEventListener('hashchange', function() { - var newHash = window.location.hash.substr(1); - var extensionViewSrcParts = + const newHash = window.location.hash.substr(1); + const extensionViewSrcParts = splitUrlOnHash(extensionView.getAttribute('src')); if (newHash !== extensionViewSrcParts[1] && newHash.startsWith('offers')) { extensionView.load(extensionViewSrcParts[0] + '#' + newHash);
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/injected/event_watcher_test.unitjs b/chrome/browser/resources/chromeos/chromevox/chromevox/injected/event_watcher_test.unitjs index 6aefaf5..7c7e329f 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox/injected/event_watcher_test.unitjs +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/injected/event_watcher_test.unitjs
@@ -84,7 +84,8 @@ } }; -TEST_F('ChromeVoxEventWatcherUnitTest', 'ButtonFocusFeedback', function() { +// Flaky on Chromium OS: https://crbug.com/912390. +TEST_F('ChromeVoxEventWatcherUnitTest', 'DISABLED_ButtonFocusFeedback', function() { this.loadHtml('<div> <button id="alpha">Alpha</button> </div>'); this.setFocus('alpha'); this.waitForCalm(this.assertSpoken, 'Alpha Button'); @@ -280,7 +281,8 @@ /** * Test feedback when the items of a list box receive focus. */ -TEST_F('ChromeVoxEventWatcherUnitTest', 'ListBoxOptionFeedback', function() { +// Flaky on Chromium OS: https://crbug.com/912390. +TEST_F('ChromeVoxEventWatcherUnitTest', 'DISABLED_ListBoxOptionFeedback', function() { this.loadHtml('<div>' + '<p id="before">My listbox</p>' + '<div id="listbox" role="listbox">' +
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/injected/live_regions_test.unitjs b/chrome/browser/resources/chromeos/chromevox/chromevox/injected/live_regions_test.unitjs index 7dc563ff..c7a6ad4 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox/injected/live_regions_test.unitjs +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/injected/live_regions_test.unitjs
@@ -112,7 +112,7 @@ /** * Test modifying an existing status live region. */ -TEST_F('ChromeVoxLiveRegionsUnitTest', 'ModifyStatusLiveRegion', function() { +TEST_F('ChromeVoxLiveRegionsUnitTest', 'DISABLED_ModifyStatusLiveRegion', function() { var region = document.createElement('div'); region.innerHTML = '<div id="status" role="status">Gamma</div>'; document.body.appendChild(region);
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js index 3017995f..fdfd1da 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js +++ b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js
@@ -294,7 +294,8 @@ this.navigation_.disabled = false; this.offlineAdUi_.onBeforeShow(); - this.showStep(data.attestationBased ? STEP_WORKING : STEP_SIGNIN); + if (!this.currentStep_) + this.showStep(data.attestationBased ? STEP_WORKING : STEP_SIGNIN); }, onBeforeHide: function() {
diff --git a/chrome/browser/resources/chromeos/multidevice_setup/BUILD.gn b/chrome/browser/resources/chromeos/multidevice_setup/BUILD.gn index 470e0c0..e067eac 100644 --- a/chrome/browser/resources/chromeos/multidevice_setup/BUILD.gn +++ b/chrome/browser/resources/chromeos/multidevice_setup/BUILD.gn
@@ -26,12 +26,14 @@ ] extra_deps = [ + "//chromeos/components/multidevice/mojom:mojom_js", "//chromeos/services/device_sync/public/mojom:mojom_js", "//chromeos/services/multidevice_setup/public/mojom:mojom_js", "//mojo/public/mojom/base:base_js", ] externs_list = [ + "$root_gen_dir/chromeos/components/multidevice/mojom/multidevice_types.mojom.externs.js", "$root_gen_dir/chromeos/services/device_sync/public/mojom/device_sync.mojom.externs.js", "$root_gen_dir/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.externs.js", "$root_gen_dir/mojo/public/mojom/base/time.mojom.externs.js",
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js b/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js index fb58ec00..5f65858 100644 --- a/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js +++ b/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js
@@ -1258,14 +1258,14 @@ var bar = $('bar'); bar.style.left = selectedListItem.offsetLeft + 'px'; bar.style.width = selectedListItem.offsetWidth + 'px'; - - var wallpapersDataModel = new cr.ui.ArrayDataModel([]); - var selectedItem = null; // Cancel any ongoing wallpaper request if user clicks on another category. if (this.wallpaperRequest_) { this.wallpaperRequest_.abort(); this.wallpaperRequest_ = null; } + // Always start with the top when showing a new category. + this.wallpaperGrid_.scrollTop = 0; + if (selectedListItem.custom) { var wallpapersDataModel = new cr.ui.ArrayDataModel([]); if (loadTimeData.getBoolean('isOEMDefaultWallpaper')) {
diff --git a/chrome/browser/resources/conflicts/about_conflicts.js b/chrome/browser/resources/conflicts/about_conflicts.js index 9e3042dc..eb75054 100644 --- a/chrome/browser/resources/conflicts/about_conflicts.js +++ b/chrome/browser/resources/conflicts/about_conflicts.js
@@ -6,7 +6,7 @@ * This variable structure is here to document the structure that the template * expects to correctly populate the page. */ -var moduleListDataFormat = { +const moduleListDataFormat = { 'moduleList': [{ 'type_description': 'The type of module (string), defaults to blank for regular modules', @@ -29,8 +29,8 @@ */ function renderTemplate(moduleListData) { // This is the javascript code that processes the template: - var input = new JsEvalContext(moduleListData); - var output = $('modulesTemplate'); + const input = new JsEvalContext(moduleListData); + const output = $('modulesTemplate'); jstProcess(input, output); }
diff --git a/chrome/browser/resources/cryptotoken/.eslintrc.js b/chrome/browser/resources/cryptotoken/.eslintrc.js deleted file mode 100644 index 0dcb0cf9..0000000 --- a/chrome/browser/resources/cryptotoken/.eslintrc.js +++ /dev/null
@@ -1,8 +0,0 @@ -// Copyright 2017 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. - -// This makes "async function" not an error. -module.exports = { - parserOptions: {ecmaVersion: 2017}, -};
diff --git a/chrome/browser/resources/device_log_ui/device_log_ui.js b/chrome/browser/resources/device_log_ui/device_log_ui.js index 7472d8e6f..1f69c779 100644 --- a/chrome/browser/resources/device_log_ui/device_log_ui.js +++ b/chrome/browser/resources/device_log_ui/device_log_ui.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -var DeviceLogUI = (function() { +const DeviceLogUI = (function() { 'use strict'; /** @@ -11,9 +11,9 @@ * @param {string} level A string that represents log level. * @return {HTMLSpanElement} The created span element. */ - var createLevelTag = function(level) { - var levelClassName = 'log-level-' + level.toLowerCase(); - var tag = document.createElement('span'); + const createLevelTag = function(level) { + const levelClassName = 'log-level-' + level.toLowerCase(); + const tag = document.createElement('span'); tag.textContent = level; tag.className = 'level-tag ' + levelClassName; return tag; @@ -25,9 +25,9 @@ * @param {string} level A string that represents log type. * @return {HTMLSpanElement} The created span element. */ - var createTypeTag = function(type) { - var typeClassName = 'log-type-' + type.toLowerCase(); - var tag = document.createElement('span'); + const createTypeTag = function(type) { + const typeClassName = 'log-type-' + type.toLowerCase(); + const tag = document.createElement('span'); tag.textContent = type; tag.className = 'type-tag ' + typeClassName; return tag; @@ -41,23 +41,23 @@ * @return {?HTMLParagraphElement} The created p element that represents * the log entry, or null if the entry should be skipped. */ - var createLogEntryText = function(logEntry) { - var level = logEntry['level']; - var levelCheckbox = 'log-level-' + level.toLowerCase(); + const createLogEntryText = function(logEntry) { + const level = logEntry['level']; + const levelCheckbox = 'log-level-' + level.toLowerCase(); if ($(levelCheckbox) && !$(levelCheckbox).checked) return null; - var type = logEntry['type']; - var typeCheckbox = 'log-type-' + type.toLowerCase(); + const type = logEntry['type']; + const typeCheckbox = 'log-type-' + type.toLowerCase(); if ($(typeCheckbox) && !$(typeCheckbox).checked) return null; - var res = document.createElement('p'); - var textWrapper = document.createElement('span'); - var fileinfo = ''; + const res = document.createElement('p'); + const textWrapper = document.createElement('span'); + let fileinfo = ''; if ($('log-fileinfo').checked) fileinfo = logEntry['file']; - var timestamp = ''; + let timestamp = ''; if ($('log-timedetail').checked) timestamp = logEntry['timestamp']; else @@ -76,11 +76,11 @@ * @param {Array<string>} logEntries An array of strings that represent log * log events in JSON format. */ - var createEventLog = function(logEntries) { - var container = $('log-container'); + const createEventLog = function(logEntries) { + const container = $('log-container'); container.textContent = ''; - for (var i = 0; i < logEntries.length; ++i) { - var entry = createLogEntryText(JSON.parse(logEntries[i])); + for (let i = 0; i < logEntries.length; ++i) { + const entry = createLogEntryText(JSON.parse(logEntries[i])); if (entry) container.appendChild(entry); } @@ -91,11 +91,11 @@ * * @param {Object} data A JSON structure of event log entries. */ - var getLogCallback = function(data) { + const getLogCallback = function(data) { try { createEventLog(JSON.parse(data)); } catch (e) { - var container = $('log-container'); + const container = $('log-container'); container.textContent = 'No log entries'; } }; @@ -103,15 +103,15 @@ /** * Requests a log update. */ - var requestLog = function() { + const requestLog = function() { chrome.send('DeviceLog.getLog'); }; /** * Sets refresh rate if the interval is found in the url. */ - var setRefresh = function() { - var interval = parseQueryParams(window.location)['refresh']; + const setRefresh = function() { + const interval = parseQueryParams(window.location)['refresh']; if (interval && interval != '') setInterval(requestLog, parseInt(interval) * 1000); }; @@ -127,9 +127,9 @@ $('log-level-debug').checked = false; // Show all types by default. - var checkboxes = document.querySelectorAll( + let checkboxes = document.querySelectorAll( '#log-checkbox-container input[type="checkbox"][id*="log-type"]'); - for (var i = 0; i < checkboxes.length; ++i) + for (let i = 0; i < checkboxes.length; ++i) checkboxes[i].checked = true; $('log-fileinfo').checked = false; @@ -138,7 +138,7 @@ $('log-refresh').onclick = requestLog; checkboxes = document.querySelectorAll( '#log-checkbox-container input[type="checkbox"]'); - for (var i = 0; i < checkboxes.length; ++i) + for (let i = 0; i < checkboxes.length; ++i) checkboxes[i].onclick = requestLog; setRefresh();
diff --git a/chrome/browser/resources/download_internals/download_internals.js b/chrome/browser/resources/download_internals/download_internals.js index d46a210..0c86bb3 100644 --- a/chrome/browser/resources/download_internals/download_internals.js +++ b/chrome/browser/resources/download_internals/download_internals.js
@@ -6,24 +6,24 @@ 'use strict'; /** @type {!downloadInternals.DownloadInternalsBrowserProxy} */ - var browserProxy = + const browserProxy = downloadInternals.DownloadInternalsBrowserProxyImpl.getInstance(); /** @type {!Array<ServiceEntry>} */ - var ongoingServiceEntries = []; + const ongoingServiceEntries = []; /** @type {!Array<ServiceEntry>} */ - var finishedServiceEntries = []; + const finishedServiceEntries = []; /** @type {!Array<ServiceRequest>} */ - var serviceRequests = []; + const serviceRequests = []; /** * @param {!Array<ServiceEntry>} list A list to remove the entry from. * @param {string} guid The guid to remove from the list. */ function removeGuidFromList(list, guid) { - var index = list.findIndex(entry => entry.guid == guid); + const index = list.findIndex(entry => entry.guid == guid); if (index != -1) list.splice(index, 1); } @@ -35,7 +35,7 @@ * @param {!ServiceEntry} newEntry The new entry. */ function addOrUpdateEntryByGuid(list, newEntry) { - var index = list.findIndex(entry => entry.guid == newEntry.guid); + const index = list.findIndex(entry => entry.guid == newEntry.guid); if (index != -1) list[index] = newEntry; else @@ -43,10 +43,10 @@ } function updateEntryTables() { - var ongoingInput = new JsEvalContext({entries: ongoingServiceEntries}); + const ongoingInput = new JsEvalContext({entries: ongoingServiceEntries}); jstProcess(ongoingInput, $('download-service-ongoing-entries-info')); - var finishedInput = new JsEvalContext({entries: finishedServiceEntries}); + const finishedInput = new JsEvalContext({entries: finishedServiceEntries}); jstProcess(finishedInput, $('download-service-finished-entries-info')); } @@ -65,8 +65,8 @@ * the download service. */ function onServiceDownloadsAvailable(entries) { - for (var i = 0; i < entries.length; i++) { - var entry = entries[i]; + for (let i = 0; i < entries.length; i++) { + const entry = entries[i]; if (entry.state == ServiceEntryState.COMPLETE) { finishedServiceEntries.unshift(entry); } else { @@ -109,7 +109,7 @@ */ function onServiceRequestMade(request) { serviceRequests.unshift(request); - var input = new JsEvalContext({requests: serviceRequests}); + const input = new JsEvalContext({requests: serviceRequests}); jstProcess(input, $('download-service-request-info')); }
diff --git a/chrome/browser/resources/download_internals/download_internals_browser_proxy.js b/chrome/browser/resources/download_internals/download_internals_browser_proxy.js index a79453a..0d870c7 100644 --- a/chrome/browser/resources/download_internals/download_internals_browser_proxy.js +++ b/chrome/browser/resources/download_internals/download_internals_browser_proxy.js
@@ -6,7 +6,7 @@ * Contains the possible states a ServiceEntry can be in. * @enum {string} */ -var ServiceEntryState = { +const ServiceEntryState = { NEW: 'NEW', AVAILABLE: 'AVAILABLE', ACTIVE: 'ACTIVE', @@ -18,7 +18,7 @@ * Contains the possible states a ServiceEntry's driver can be in. * @enum {string} */ -var DriverEntryState = { +const DriverEntryState = { IN_PROGRESS: 'IN_PROGRESS', COMPLETE: 'COMPLETE', CANCELLED: 'CANCELLED', @@ -29,7 +29,7 @@ * Contains the possible results a ServiceEntry can have. * @enum {string} */ -var ServiceEntryResult = { +const ServiceEntryResult = { SUCCEED: 'SUCCEED', FAIL: 'FAIL', ABORT: 'ABORT', @@ -44,7 +44,7 @@ * Contains the possible results of a ServiceRequest. * @enum {string} */ -var ServiceRequestResult = { +const ServiceRequestResult = { ACCEPTED: 'ACCEPTED', BACKOFF: 'BACKOFF', UNEXPECTED_CLIENT: 'UNEXPECTED_CLIENT', @@ -61,7 +61,7 @@ * fileMonitorStatus: string * }} */ -var ServiceStatus; +let ServiceStatus; /** * @typedef {{ @@ -78,7 +78,7 @@ * } * }} */ -var ServiceEntry; +let ServiceEntry; /** * @typedef {{ @@ -87,7 +87,7 @@ * result: !ServiceRequestResult * }} */ -var ServiceRequest; +let ServiceRequest; cr.define('downloadInternals', function() { /** @interface */
diff --git a/chrome/browser/resources/engagement/site_engagement.js b/chrome/browser/resources/engagement/site_engagement.js index 25dbd5b..570c0c9 100644 --- a/chrome/browser/resources/engagement/site_engagement.js +++ b/chrome/browser/resources/engagement/site_engagement.js
@@ -6,17 +6,17 @@ // Allow a function to be provided by tests, which will be called when // the page has been populated with site engagement details. -var whenPageIsPopulatedForTest; +let whenPageIsPopulatedForTest; /** @type {function()} */ -var disableAutoupdateForTests; +let disableAutoupdateForTests; /** @type {mojom.SiteEngagementDetailsProviderPtr} */ -var uiHandler; +let uiHandler; (function() { -var resolvePageIsPopulated = null; -var pageIsPopulatedPromise = new Promise((resolve, reject) => { +let resolvePageIsPopulated = null; +const pageIsPopulatedPromise = new Promise((resolve, reject) => { resolvePageIsPopulated = resolve; }); @@ -31,29 +31,29 @@ mojo.makeRequest(uiHandler).handle); /** @type {?HTMLElement} */ - var engagementTableBody = $('engagement-table-body'); + const engagementTableBody = $('engagement-table-body'); /** @type {?number} */ - var updateInterval = null; + let updateInterval = null; /** @type {?Array<!mojom.SiteEngagementDetails>} */ - var info = null; + let info = null; /** @type {string} */ - var sortKey = 'totalScore'; + let sortKey = 'totalScore'; /** @type {boolean} */ - var sortReverse = true; + let sortReverse = true; // Set table header sort handlers. - var engagementTableHeader = $('engagement-table-header'); - var headers = engagementTableHeader.children; - for (var i = 0; i < headers.length; i++) { + const engagementTableHeader = $('engagement-table-header'); + const headers = engagementTableHeader.children; + for (let i = 0; i < headers.length; i++) { headers[i].addEventListener('click', (e) => { - var newSortKey = e.target.getAttribute('sort-key'); + const newSortKey = e.target.getAttribute('sort-key'); if (sortKey == newSortKey) { sortReverse = !sortReverse; } else { sortKey = newSortKey; sortReverse = false; } - var oldSortColumn = document.querySelector('.sort-column'); + const oldSortColumn = document.querySelector('.sort-column'); oldSortColumn.classList.remove('sort-column'); e.target.classList.add('sort-column'); if (sortReverse) @@ -70,10 +70,10 @@ * @return {HTMLElement} */ function createRow(info) { - var originCell = createElementWithClassName('td', 'origin-cell'); + const originCell = createElementWithClassName('td', 'origin-cell'); originCell.textContent = info.origin.url; - var baseScoreInput = + const baseScoreInput = createElementWithClassName('input', 'base-score-input'); baseScoreInput.addEventListener( 'change', handleBaseScoreChange.bind(undefined, info.origin)); @@ -81,23 +81,23 @@ baseScoreInput.addEventListener('blur', enableAutoupdate); baseScoreInput.value = info.baseScore; - var baseScoreCell = createElementWithClassName('td', 'base-score-cell'); + const baseScoreCell = createElementWithClassName('td', 'base-score-cell'); baseScoreCell.appendChild(baseScoreInput); - var bonusScoreCell = createElementWithClassName('td', 'bonus-score-cell'); + const bonusScoreCell = createElementWithClassName('td', 'bonus-score-cell'); bonusScoreCell.textContent = info.installedBonus; - var totalScoreCell = createElementWithClassName('td', 'total-score-cell'); + const totalScoreCell = createElementWithClassName('td', 'total-score-cell'); totalScoreCell.textContent = info.totalScore; - var engagementBar = createElementWithClassName('div', 'engagement-bar'); + const engagementBar = createElementWithClassName('div', 'engagement-bar'); engagementBar.style.width = (info.totalScore * 4) + 'px'; - var engagementBarCell = + const engagementBarCell = createElementWithClassName('td', 'engagement-bar-cell'); engagementBarCell.appendChild(engagementBar); - var row = /** @type {HTMLElement} */ (document.createElement('tr')); + const row = /** @type {HTMLElement} */ (document.createElement('tr')); row.appendChild(originCell); row.appendChild(baseScoreCell); row.appendChild(bonusScoreCell); @@ -131,7 +131,7 @@ * @param {Event} e */ function handleBaseScoreChange(origin, e) { - var baseScoreInput = e.target; + const baseScoreInput = e.target; uiHandler.setSiteEngagementBaseScoreForUrl(origin, baseScoreInput.value); baseScoreInput.barCellRef.style.width = (baseScoreInput.value * 4) + 'px'; baseScoreInput.blur(); @@ -161,8 +161,8 @@ * positive number otherwise. */ function compareTableItem(sortKey, a, b) { - var val1 = a[sortKey]; - var val2 = b[sortKey]; + const val1 = a[sortKey]; + const val2 = b[sortKey]; // Compare the hosts of the origin ignoring schemes. if (sortKey == 'origin')
diff --git a/chrome/browser/resources/hangout_services/manifest.json b/chrome/browser/resources/hangout_services/manifest.json index 9a8ec04e..163319d 100644 --- a/chrome/browser/resources/hangout_services/manifest.json +++ b/chrome/browser/resources/hangout_services/manifest.json
@@ -5,7 +5,7 @@ "name": "Google Hangouts", // Note: Always update the version number when this file is updated. Chrome // triggers extension preferences update on the version increase. - "version": "1.3.10", + "version": "1.3.11", "manifest_version": 2, "externally_connectable": { "matches": [
diff --git a/chrome/browser/resources/hangout_services/thunk.js b/chrome/browser/resources/hangout_services/thunk.js index 188c6e6..471f7ac0 100644 --- a/chrome/browser/resources/hangout_services/thunk.js +++ b/chrome/browser/resources/hangout_services/thunk.js
@@ -182,10 +182,11 @@ } else if (method == 'logging.startEventLogging') { const peerConnectionId = message['peerConnectionId'] || ''; const maxLogSizeBytes = message['maxLogSizeBytes'] || 0; + const outputPeriodMs = message['outputPeriodMs'] || 0; const webAppId = message['webAppId'] || 0; chrome.webrtcLoggingPrivate.startEventLogging( - requestInfo, origin, peerConnectionId, maxLogSizeBytes, webAppId, - doSendResponse); + requestInfo, origin, peerConnectionId, maxLogSizeBytes, + outputPeriodMs, webAppId, doSendResponse); return true; } else if (method == 'setAudioExperiments') { const experiments = message['experiments'];
diff --git a/chrome/browser/resources/local_ntp/icons/close.svg b/chrome/browser/resources/local_ntp/icons/close.svg new file mode 100644 index 0000000..e74a981 --- /dev/null +++ b/chrome/browser/resources/local_ntp/icons/close.svg
@@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><defs><style>.a{fill:none;stroke:#4d4d4d;stroke-miterlimit:10;stroke-width:3px;}</style></defs><title>Untitled-2</title><line class="a" x1="3.5" y1="3.5" x2="21" y2="21"/><line class="a" x1="3.5" y1="21" x2="21" y2="3.5"/></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/local_ntp/icons/copy.svg b/chrome/browser/resources/local_ntp/icons/copy.svg new file mode 100644 index 0000000..affb359 --- /dev/null +++ b/chrome/browser/resources/local_ntp/icons/copy.svg
@@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48"><defs><style>.a{fill:#666;}.b{fill:none;stroke:#666;stroke-miterlimit:10;stroke-width:4px;}</style></defs><title>Untitled-1</title><path class="a" d="M35.25,14a.76.76,0,0,1,.75.75v25.5a.76.76,0,0,1-.75.75H18.75a.76.76,0,0,1-.75-.75V14.75a.76.76,0,0,1,.75-.75h16.5m0-4H18.75A4.77,4.77,0,0,0,14,14.75v25.5A4.77,4.77,0,0,0,18.75,45h16.5A4.77,4.77,0,0,0,40,40.25V14.75A4.77,4.77,0,0,0,35.25,10Z"/><path class="b" d="M9,38V9.75A4.77,4.77,0,0,1,13.75,5H32.91"/></svg> \ No newline at end of file
diff --git a/chrome/browser/resources/local_ntp/icons/facebook.svg b/chrome/browser/resources/local_ntp/icons/facebook.svg new file mode 100644 index 0000000..02a8ebc8 --- /dev/null +++ b/chrome/browser/resources/local_ntp/icons/facebook.svg
@@ -0,0 +1,12 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="48px" height="48px" + viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#3A589B;} + .st1{fill:#FFFFFF;} +</style> +<path class="st0" d="M43.5,48h-39C2,48,0,46,0,43.5v-39C0,2,2,0,4.5,0h39C46,0,48,2,48,4.5v39C48,46,46,48,43.5,48z"/> +<g> + <path class="st1" d="M39.4,29.4l0.9-7.3h-7.2v-4.7c0-2.1,0.6-3.5,3.6-3.5h3.8V7.5c-0.7-0.1-2.9-0.3-5.6-0.3c-5.5,0-9.3,3.4-9.3,9.6 + v5.3h-6.2v7.3h6.2V48h7.5V29.4H39.4z"/> +</g> +</svg> \ No newline at end of file
diff --git a/chrome/browser/resources/local_ntp/icons/mail.svg b/chrome/browser/resources/local_ntp/icons/mail.svg new file mode 100644 index 0000000..d6655dac --- /dev/null +++ b/chrome/browser/resources/local_ntp/icons/mail.svg
@@ -0,0 +1,11 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="48px" height="48px" viewBox="0 0 48 48"> +<style type="text/css"> + .st0{fill:#9DA6AA;} + .st1{fill:#FFFFFF;} + .st2{fill:none;stroke:#9DA6AA;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;} +</style> +<path class="st0" d="M43.5,48h-39C2,48,0,46,0,43.5v-39C0,2,2,0,4.5,0h39C46,0,48,2,48,4.5v39C48,46,46,48,43.5,48z"/> +<path class="st1" d="M35.9,12.8H12.1c-2.2,0-4,1.8-4,4v14.4c0,2.2,1.8,4,4,4h23.8c2.2,0,4-1.8,4-4V16.8 + C39.9,14.6,38.1,12.8,35.9,12.8z"/> +<polyline class="st2" points="35.4,17.2 24,26.1 12.6,17.2 "/> +</svg> \ No newline at end of file
diff --git a/chrome/browser/resources/local_ntp/icons/twitter.svg b/chrome/browser/resources/local_ntp/icons/twitter.svg new file mode 100644 index 0000000..fb3570a --- /dev/null +++ b/chrome/browser/resources/local_ntp/icons/twitter.svg
@@ -0,0 +1,12 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="48px" height="48px" viewBox="0 0 48 48"> +<style type="text/css"> + .st0{fill:#3AAAE1;} + .st1{fill:#FFFFFF;} +</style> +<path class="st0" d="M43.5,48h-39C2,48,0,46,0,43.5v-39C0,2,2,0,4.5,0h39C46,0,48,2,48,4.5v39C48,46,46,48,43.5,48z"/> +<path class="st1" d="M39.3,15.5c-1.1,0.5-2.3,0.8-3.5,0.9c1.2-0.7,2.2-1.9,2.6-3.3c-1.1,0.7-2.5,1.2-3.8,1.5 + c-1.1-1.1-2.6-1.9-4.4-1.9c-3.3,0-6,2.7-6,6c0,0.5,0.1,0.9,0.1,1.3c-4.9-0.3-9.4-2.6-12.4-6.3c-0.5,0.9-0.8,1.9-0.8,3 + c0,2,1.1,3.9,2.7,5c-1,0-1.9-0.3-2.7-0.8v0.1c0,2.9,2,5.3,4.8,5.9c-0.5,0.1-1.1,0.2-1.6,0.2c-0.4,0-0.8-0.1-1.1-0.1 + c0.8,2.4,3,4.1,5.6,4.2c-2,1.6-4.7,2.5-7.4,2.5c-0.5,0-1,0-1.4-0.1c2.7,1.7,5.8,2.7,9.2,2.7c11,0,17-9.1,17-17c0-0.3,0-0.5,0-0.8 + C37.5,17.7,38.5,16.7,39.3,15.5L39.3,15.5z"/> +</svg> \ No newline at end of file
diff --git a/chrome/browser/resources/local_ntp/local_ntp.css b/chrome/browser/resources/local_ntp/local_ntp.css index 0ebaae0..abfe9f8 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.css +++ b/chrome/browser/resources/local_ntp/local_ntp.css
@@ -128,6 +128,10 @@ display: none; } +#logo-doodle { + text-align: center; +} + #logo-default, #logo-doodle { opacity: 0; @@ -140,16 +144,23 @@ visibility: visible; } -#logo-doodle-button, +#logo-doodle-container, #logo-doodle-iframe { display: none; } -#logo-doodle-button.show-logo, +#logo-doodle-button { + cursor: pointer; +} + #logo-doodle-iframe.show-logo { display: block; } +#logo-doodle-container.show-logo { + display: inline-block; +} + #logo-doodle-image { outline: none; } @@ -188,16 +199,18 @@ display: none; } -#logo-doodle-button { +#logo-doodle-container { /* An image logo is allowed to spill into the margin below, so it's not a * real bottom margin. If the image extends further than that margin, it * is cropped. */ margin: 0 auto; max-height: calc(var(--logo-height) + var(--logo-margin-bottom)); overflow: hidden; + position: relative; + text-align: text-center; } -.non-white-bg #logo-doodle-button, +.non-white-bg #logo-doodle-container, .non-white-bg #logo-doodle-iframe { display: none; } @@ -292,32 +305,21 @@ } #fakebox { - background-color: #fff; - border-radius: 2px; - box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08); + background-color: rgb(241, 243, 244); + border-radius: 22px; cursor: text; font-size: 18px; height: 44px; line-height: 36px; - margin: 0 calc(var(--tile-margin) / 2 + 1px) 0 calc(var(--tile-margin) / 2); - outline: none; - position: relative; - transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1); -} - -.md #fakebox { - background-color: rgb(241, 243, 244); - border-radius: 22px; - box-shadow: none; margin: 0 auto; max-width: 560px; opacity: 1; - transition: background-color 300ms ease-in-out; + position: relative; /* Transition should be similar to .mv-tile/.md-tile opacity transition. */ - transition: opacity 200ms; + transition: background-color 300ms ease-in-out, opacity 200ms } -.md #fakebox:hover { +#fakebox:hover { background-color: rgb(232, 234, 237); } @@ -325,50 +327,33 @@ display: none; } -#fakebox:hover, -body.fakebox-focused #fakebox { - box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.08); -} - -.md #fakebox:hover, -body.md.fakebox-focused #fakebox { - box-shadow: none; -} - #fakebox > input { bottom: 0; box-sizing: border-box; left: 0; margin: 0; opacity: 0; - padding-left: 8px; + padding-left: 20px; position: absolute; top: 0; width: 100%; } -.md #fakebox > input { - padding-left: 20px; -} - html[dir=rtl] #fakebox > input { padding-left: 0; - padding-right: 8px; - right: 0; -} - -html[dir=rtl] .md #fakebox > input { padding-right: 20px; + right: 0; } #fakebox-text { bottom: 4px; - color: rgba(0, 0, 0, 0.42); - font-family: arial, sans-serif; - font-size: 16px; - left: 13px; + color: rgb(128, 134, 139); + font-family: 'Roboto', arial, sans-serif; + font-size: 14px; + left: 0; margin-top: 1px; overflow: hidden; + padding-left: 20px; position: absolute; right: 13px; text-align: initial; @@ -379,20 +364,8 @@ white-space: nowrap; } -.md #fakebox-text { - color: rgb(128, 134, 139); - font-family: 'Roboto', arial, sans-serif; - font-size: 14px; - left: 0; - padding-left: 20px; -} - html[dir=rtl] #fakebox-text { left: auto; - right: 13px; -} - -html[dir=rtl] .md #fakebox-text { padding-right: 20px; right: 0; } @@ -400,23 +373,15 @@ #fakebox-cursor { background: #333; bottom: 12px; - left: 13px; + left: 20px; position: absolute; top: 12px; visibility: hidden; width: 1px; } -.md #fakebox-cursor { - left: 20px; -} - html[dir=rtl] #fakebox-cursor { left: auto; - right: 13px; -} - -html[dir=rtl] .md #fakebox-cursor { right: 20px; } @@ -425,25 +390,18 @@ background-size: 24px 24px; bottom: 0; cursor: pointer; + margin-right: 12px; padding: 22px 12px 0; position: absolute; right: 0; top: 0; - width: 41px; -} - -.md #fakebox-microphone { - margin-right: 12px; width: 28px; } html[dir=rtl] #fakebox-microphone { left: 0; - right: auto; -} - -html[dir=rtl] .md #fakebox-microphone { margin-left: 12px; + right: auto; } @keyframes blink { @@ -665,6 +623,134 @@ display: none; } +/** TODO(crbug.com/903398): Move doodle styling and logic to dedicated files. */ +#ddlsb { + border-radius: 6px; + cursor: pointer; + display: inline-block; + height: 26px; + opacity: 0.8; + position: absolute; + width: 26px; +} + +#ddlsb:hover { + opacity: 1; +} + +#ddlsb-img { + height: 22px; + left: 2px; + position: absolute; + top: 2px; + width: 22px; +} + +#ddlsd { + background: #fff; + border: none; + border-radius: 8px; + box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.2); + left: 0; + margin: auto; + min-height: 100px; + padding: 22px; + position: absolute; + right: 0; + text-align: left; + top: 30%; + width: 300px; + z-index: 9001; +} + +#ddlsd::backdrop { + background-color: rgba(255, 255, 255, 0.9); +} + +#ddlsd button { + border: none; + cursor: pointer; +} + +#ddlsd button:hover { + opacity: 0.8; +} + +#ddlsd-title { + color: #212121; + font-size: 22px; + padding: 0 40px 16px 0; +} + +#ddlsd-close { + background: url(icons/close.svg) no-repeat; + height: 24px; + position: absolute; + right: 22px; + top: 22px; + width: 24px; +} + +#ddlsd-fbb { + background: url(icons/facebook.svg) no-repeat center; +} + +#ddlsd-twb { + background: url(icons/twitter.svg) no-repeat center; +} + +#ddlsd-emb { + background: url(icons/mail.svg) no-repeat center; +} + +#ddlsd-text { + border: 2px solid #aaa; + border-color: rgba(0, 0, 0, 0.15); + border-radius: 4px; + color: #555; + display: inline-block; + font-size: 14px; + padding: 12px; + width: 100%; +} + +#ddlsd-copy { + background: url(icons/copy.svg) no-repeat center; + background-size: contain; + display: inline-block; + float: right; + height: 36px; + margin: 5px; + width: 36px; +} + +.ddlsd-sbtn { + background-size: contain; + border-radius: 4px; + display: inline-block; + height: 48px; + margin: 0 4px; + width: 48px; +} + +#ddlsd-hr { + background: #ccc; + border: 0; + height: 2px; + margin: 15px 0; +} + +#ddlsd-link { + margin: 6px; + overflow: hidden; +} + +#ddlsd-text-ctr { + display: block; + overflow: hidden; + padding-right: 36px; +} + #attribution { bottom: 0; color: var(--text-color-light); @@ -886,3 +972,70 @@ text-decoration: none; transition: background-color 200ms; } + +#promo { + bottom: 16px; + left: 0; + pointer-events: none; + position: fixed; + right: 0; + text-align: center; + transition: bottom 400ms; +} + +#promo.float-down { + bottom: -50px; +} + +#promo > div { + background-color: #FFF; + border: 1px solid rgb(218, 220, 224); + border-radius: 16px; + box-sizing: border-box; + color: rgb(95, 99, 104); + display: inline-block; + font-family: 'Roboto', arial, sans-serif; + font-size: 12px; + line-height: 32px; + margin-bottom: 0; + max-width: 505px; + overflow: hidden; + padding: 0 16px; + pointer-events: all; + text-overflow: ellipsis; + white-space: nowrap; +} + +/** + * Hide the promo if the window is too small: + * max-width = promo.max-width (505px) + 2 * edit gear icon (16px + 28px + 8px) + * max-height = ntp-contents.max-height (628px) + promo div height (16px + 22px) + */ +@media only screen and (max-width: 609px), + screen and (max-height: 666px) { + #promo > div { + display: none; + } +} + +#promo > div > a { + color: rgb(51, 103, 214) !important; + text-decoration: none; +} + +#promo > div > a:visited { + color: rgb(51, 103, 214) !important; +} + +#promo > div > img { + border-radius: 50%; + height: 24px; + margin: 0 8px 0 -12px; + object-fit: cover; + vertical-align: middle; + width: 24px; +} + +#promo.notice-hide { + display: none; +}
diff --git a/chrome/browser/resources/local_ntp/local_ntp.html b/chrome/browser/resources/local_ntp/local_ntp.html index e8c2a26..edaf4df 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.html +++ b/chrome/browser/resources/local_ntp/local_ntp.html
@@ -40,9 +40,11 @@ <div id="logo-non-white" title="Google"></div> <!-- A doodle, if any: its link and image. --> <div id="logo-doodle"> - <button id="logo-doodle-button"> - <img id="logo-doodle-image" tabindex="-1"></img> - </button> + <div id="logo-doodle-container"> + <button id="logo-doodle-button"> + <img id="logo-doodle-image" tabindex="-1"></img> + </button> + </div> <iframe id="logo-doodle-iframe" scrolling="no"></iframe> <!-- A spinner, visible on dark-themed NTPs, prompting the doodle --> <button id="logo-doodle-notifier"> @@ -122,6 +124,24 @@ </div> </dialog> + <!-- TODO(crbug.com/896461): Add a11y to doodle sharing. --> + <dialog id="ddlsd"> + <div id="ddlsd-title"></div> + <button id="ddlsd-close" title="Close"></button> + <div id="ddlsd-content"> + <button id="ddlsd-fbb" class="ddlsd-sbtn" title="Facebook"></button> + <button id="ddlsd-twb" class="ddlsd-sbtn" title="Twitter"></button> + <button id="ddlsd-emb" class="ddlsd-sbtn" title="Email"></button> + <hr id="ddlsd-hr"> + <div id="ddlsd-link"> + <button id="ddlsd-copy" title="Copy"></button> + <span id="ddlsd-text-ctr"> + <input type="text" id="ddlsd-text" dir="ltr" title="Share Link"> + </span> + </div> + </div> + </dialog> + <dialog id="bg-sel-menu"> <div id="bg-sel-title-bar"> <div id="bg-sel-back-circle" tabindex="0" role="button">
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js index 03c5e5f..a448042 100644 --- a/chrome/browser/resources/local_ntp/local_ntp.js +++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -95,7 +95,6 @@ HIDE_NOTIFICATION: 'notice-hide', INITED: 'inited', // Reveals the <body> once init() is done. LEFT_ALIGN_ATTRIBUTION: 'left-align-attribution', - MATERIAL_DESIGN: 'md', // Applies Material Design styles to the page MATERIAL_DESIGN_ICONS: 'md-icons', // Applies Material Design styles to Most Visited. // Vertically centers the most visited section for a non-Google provided page. @@ -116,6 +115,16 @@ ATTRIBUTION_TEXT: 'attribution-text', CUSTOM_LINKS_EDIT_IFRAME: 'custom-links-edit', CUSTOM_LINKS_EDIT_IFRAME_DIALOG: 'custom-links-edit-dialog', + DOODLE_SHARE_BUTTON: 'ddlsb', + DOODLE_SHARE_BUTTON_IMG: 'ddlsb-img', + DOODLE_SHARE_DIALOG: 'ddlsd', + DOODLE_SHARE_DIALOG_CLOSE_BUTTON: 'ddlsd-close', + DOODLE_SHARE_DIALOG_COPY_LINK_BUTTON: 'ddlsd-copy', + DOODLE_SHARE_DIALOG_FACEBOOK_BUTTON: 'ddlsd-fbb', + DOODLE_SHARE_DIALOG_LINK: 'ddlsd-text', + DOODLE_SHARE_DIALOG_MAIL_BUTTON: 'ddlsd-emb', + DOODLE_SHARE_DIALOG_TITLE: 'ddlsd-title', + DOODLE_SHARE_DIALOG_TWITTER_BUTTON: 'ddlsd-twb', ERROR_NOTIFICATION: 'error-notice', ERROR_NOTIFICATION_CONTAINER: 'error-notice-container', ERROR_NOTIFICATION_LINK: 'error-notice-link', @@ -129,6 +138,7 @@ LOGO_DOODLE: 'logo-doodle', LOGO_DOODLE_IMAGE: 'logo-doodle-image', LOGO_DOODLE_IFRAME: 'logo-doodle-iframe', + LOGO_DOODLE_CONTAINER: 'logo-doodle-container', LOGO_DOODLE_BUTTON: 'logo-doodle-button', LOGO_DOODLE_NOTIFIER: 'logo-doodle-notifier', MOST_VISITED: 'most-visited', @@ -137,6 +147,7 @@ NOTIFICATION_CLOSE_BUTTON: 'mv-notice-x', NOTIFICATION_MESSAGE: 'mv-msg', NTP_CONTENTS: 'ntp-contents', + PROMO: 'promo', RESTORE_ALL_LINK: 'mv-restore', TILES: 'mv-tiles', TILES_IFRAME: 'mv-single', @@ -232,6 +243,13 @@ /** + * The ID of the doodle app for Facebook. Used to share doodles to Facebook. + * @type {number} + */ +const FACEBOOK_APP_ID = 738026486351791; + + +/** * The last blacklisted tile rid if any, which by definition should not be * filler. * @type {?number} @@ -672,6 +690,11 @@ * @param {!Element} notificationContainer The notification container element. */ function floatUpNotification(notification, notificationContainer) { + // Show middle-slot promo if one is present. + if ($(IDS.PROMO) !== null) { + $(IDS.PROMO).classList.add(CLASSES.HIDE_NOTIFICATION); + } + // Hide pre-existing notification if it was different type. Clear timeout and // replace it with the new timeout and new message if it was the same type. if (delayedHideNotification) { @@ -706,6 +729,11 @@ if (!notificationContainer.classList.contains(CLASSES.FLOAT_UP)) return; + // Hide middle-slot promo if one is present. + if ($(IDS.PROMO) !== null) { + $(IDS.PROMO).classList.remove(CLASSES.HIDE_NOTIFICATION); + } + // Clear the timeout to hide the notification. if (delayedHideNotification) { delayedHideNotification.clear(); @@ -863,6 +891,9 @@ promoScript.id = 'promo-loader'; promoScript.src = 'chrome-search://local-ntp/promo.js'; document.body.appendChild(promoScript); + promoScript.onload = function() { + injectPromo(promo); + }; } if (configData.isCustomLinksEnabled) { $(customBackgrounds.IDS.CUSTOM_LINKS_RESTORE_DEFAULT) @@ -923,19 +954,9 @@ function enableMDIcons() { $(IDS.MOST_VISITED).classList.add(CLASSES.MATERIAL_DESIGN_ICONS); $(IDS.TILES).classList.add(CLASSES.MATERIAL_DESIGN_ICONS); - enableMD(); animations.addRippleAnimations(); } - -/** - * Enables Material Design styles for all NTP components except Most Visited. - */ -function enableMD() { - document.body.classList.add(CLASSES.MATERIAL_DESIGN); -} - - /** * Prepares the New Tab Page by adding listeners, the most visited pages * section, and Google-specific elements for a Google-provided page. @@ -990,8 +1011,6 @@ if (configData.isGooglePage) { if (configData.isMDIconsEnabled || configData.isCustomLinksEnabled) { enableMDIcons(); - } else if (configData.isMDUIEnabled) { - enableMD(); } if (configData.isCustomLinksEnabled) { @@ -1235,6 +1254,21 @@ /** + * Injects a middle-slot promo into the page. Called asynchronously, so that it + * doesn't block the main page load. + */ +function injectPromo(promo) { + if (promo.promoHtml == '') + return; + + let promoContainer = document.createElement('div'); + promoContainer.id = IDS.PROMO; + promoContainer.innerHTML += promo.promoHtml; + $(IDS.NTP_CONTENTS).appendChild(promoContainer); +} + + +/** * Injects the One Google Bar into the page. Called asynchronously, so that it * doesn't block the main page load. */ @@ -1384,8 +1418,8 @@ (logoDoodleIframe.src === targetDoodle.metadata.fullPageUrl); } else { var logoDoodleImage = $(IDS.LOGO_DOODLE_IMAGE); - var logoDoodleButton = $(IDS.LOGO_DOODLE_BUTTON); - return logoDoodleButton.classList.contains(CLASSES.SHOW_LOGO) && + var logoDoodleContainer = $(IDS.LOGO_DOODLE_CONTAINER); + return logoDoodleContainer.classList.contains(CLASSES.SHOW_LOGO) && ((logoDoodleImage.src === targetDoodle.image) || (logoDoodleImage.src === targetDoodle.metadata.animatedUrl)); } @@ -1426,11 +1460,11 @@ if (targetDoodle.metadata !== null && !cachedInteractiveOffline) { applyDoodleMetadata(); if (targetDoodle.metadata.type === LOGO_TYPE.INTERACTIVE) { - $(IDS.LOGO_DOODLE_BUTTON).classList.remove(CLASSES.SHOW_LOGO); + $(IDS.LOGO_DOODLE_CONTAINER).classList.remove(CLASSES.SHOW_LOGO); $(IDS.LOGO_DOODLE_IFRAME).classList.add(CLASSES.SHOW_LOGO); } else { $(IDS.LOGO_DOODLE_IMAGE).src = targetDoodle.image; - $(IDS.LOGO_DOODLE_BUTTON).classList.add(CLASSES.SHOW_LOGO); + $(IDS.LOGO_DOODLE_CONTAINER).classList.add(CLASSES.SHOW_LOGO); $(IDS.LOGO_DOODLE_IFRAME).classList.remove(CLASSES.SHOW_LOGO); // Log the impression in Chrome metrics. @@ -1518,10 +1552,13 @@ var applyDoodleMetadata = function() { - var logoDoodleButton = $(IDS.LOGO_DOODLE_BUTTON); var logoDoodleImage = $(IDS.LOGO_DOODLE_IMAGE); + var logoDoodleButton = $(IDS.LOGO_DOODLE_BUTTON); var logoDoodleIframe = $(IDS.LOGO_DOODLE_IFRAME); + var logoDoodleShareButton = null; + var logoDoodleShareDialog = null; + switch (targetDoodle.metadata.type) { case LOGO_TYPE.SIMPLE: logoDoodleImage.title = targetDoodle.metadata.altText; @@ -1539,6 +1576,9 @@ window.location = getDoodleTargetUrl(); }; + + insertShareButton(); + updateShareDialog(); break; case LOGO_TYPE.ANIMATED: @@ -1578,6 +1618,9 @@ window.location = getDoodleTargetUrl(); }; + + insertShareButton(); + updateShareDialog(); }; break; @@ -1595,6 +1638,126 @@ } }; +/** + * Creates a share button for static/animated doodles which opens the share + * dialog upon click. + */ +var insertShareButton = function() { + // Terminates early if share button data are missing or incomplete. + if (!targetDoodle.metadata || !targetDoodle.metadata.shareButtonX || + !targetDoodle.metadata.shareButtonY || + !targetDoodle.metadata.shareButtonBg || + !targetDoodle.metadata.shareButtonIcon) { + return; + } + var shareDialog = $(IDS.DOODLE_SHARE_DIALOG); + + var shareButtonWrapper = document.createElement('button'); + shareButtonWrapper.id = IDS.DOODLE_SHARE_BUTTON; + var shareButtonImg = document.createElement('img'); + shareButtonImg.id = IDS.DOODLE_SHARE_BUTTON_IMG; + shareButtonWrapper.appendChild(shareButtonImg); + + shareButtonWrapper.style.left = targetDoodle.metadata.shareButtonX + 'px'; + shareButtonWrapper.style.top = targetDoodle.metadata.shareButtonY + 'px'; + + // Alpha-less background color represented as an RGB HEX string. + // Share button opacity represented as a double between 0 to 1. + // Final background color is an RGBA HEX string created by combining + // both. + var backgroundColor = targetDoodle.metadata.shareButtonBg; + if (!!targetDoodle.metadata.shareButtonOpacity || + targetDoodle.metadata.shareButtonOpacity == 0) { + var backgroundOpacityHex = + parseInt(targetDoodle.metadata.shareButtonOpacity * 255, 10) + .toString(16); + backgroundColor += backgroundOpacityHex; + } + + shareButtonWrapper.style.backgroundColor = backgroundColor; + shareButtonImg.src = + 'data:image/png;base64,' + targetDoodle.metadata.shareButtonIcon; + shareButtonWrapper.onclick = function() { + shareDialog.showModal(); + }; + + var oldButton = $(IDS.DOODLE_SHARE_BUTTON); + if (oldButton) { + oldButton.remove(); + } + + var logoContainer = $(IDS.LOGO_DOODLE_CONTAINER); + if (logoContainer) { + logoContainer.appendChild(shareButtonWrapper); + } +}; + +/** + * Initiates the buttons on the doodle share dialog. Also updates the doodle + * title and short link. + */ +var updateShareDialog = function() { + var shareDialog = $(IDS.DOODLE_SHARE_DIALOG); + var shareDialogTitle = $(IDS.DOODLE_SHARE_DIALOG_TITLE); + var closeButton = $(IDS.DOODLE_SHARE_DIALOG_CLOSE_BUTTON); + var facebookButton = $(IDS.DOODLE_SHARE_DIALOG_FACEBOOK_BUTTON); + var twitterButton = $(IDS.DOODLE_SHARE_DIALOG_TWITTER_BUTTON); + var mailButton = $(IDS.DOODLE_SHARE_DIALOG_MAIL_BUTTON); + var copyButton = $(IDS.DOODLE_SHARE_DIALOG_COPY_LINK_BUTTON); + var linkText = $(IDS.DOODLE_SHARE_DIALOG_LINK); + + if (!targetDoodle.metadata || !targetDoodle.metadata.shortLink || + !targetDoodle.metadata.altText) { + return; + } + + var closeDialog = function() { + shareDialog.close(); + }; + + closeButton.onclick = closeDialog; + shareDialog.onclick = function(e) { + if (e.target == shareDialog) { + closeDialog(); + } + }; + + var title = targetDoodle.metadata.altText; + + shareDialogTitle.innerHTML = title; + var shortLink = targetDoodle.metadata.shortLink; + + facebookButton.onclick = function() { + var url = 'https://www.facebook.com/dialog/share' + + '?app_id=' + FACEBOOK_APP_ID + + '&href=' + encodeURIComponent(shortLink) + + '&hashtag=' + encodeURIComponent('#GoogleDoodle'); + window.open(url); + }; + + twitterButton.onclick = function() { + var url = 'https://twitter.com/intent/tweet' + + '?text=' + encodeURIComponent(title + '\n' + shortLink); + window.open(url); + }; + + mailButton.onclick = function() { + var url = 'mailto:?subject=' + encodeURIComponent(title) + + '&body=' + encodeURIComponent(shortLink); + document.location.href = url; + }; + + linkText.value = shortLink; + linkText.onclick = function() { + linkText.select(); + }; + linkText.setAttribute('readonly', true); + copyButton.onclick = function() { + linkText.select(); + document.execCommand('copy'); + }; +}; + return { init: init, // Exposed for testing. @@ -1606,4 +1769,4 @@ if (!window.localNTPUnitTest) { LocalNTP().listen(); -} +} \ No newline at end of file
diff --git a/chrome/browser/resources/md_bookmarks/.eslintrc.js b/chrome/browser/resources/md_bookmarks/.eslintrc.js index e9a7f15..847d6e995 100644 --- a/chrome/browser/resources/md_bookmarks/.eslintrc.js +++ b/chrome/browser/resources/md_bookmarks/.eslintrc.js
@@ -7,9 +7,6 @@ 'browser': true, 'es6': true, }, - 'parserOptions': { - 'ecmaVersion': 2017, - }, 'rules': { 'no-var': 'error', },
diff --git a/chrome/browser/resources/md_bookmarks/bookmarks.html b/chrome/browser/resources/md_bookmarks/bookmarks.html index a12bb061..b6e08ba 100644 --- a/chrome/browser/resources/md_bookmarks/bookmarks.html +++ b/chrome/browser/resources/md_bookmarks/bookmarks.html
@@ -1,5 +1,5 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" $i18n{dark}> <head> <meta charset="utf8"> <title>$i18n{title}</title> @@ -26,5 +26,6 @@ <script src="chrome://resources/js/load_time_data.js"></script> <script src="chrome://bookmarks/strings.js"></script> <link rel="import" href="chrome://bookmarks/app.html"> + <link rel="import" href="chrome://resources/html/dark_mode.html"> </body> </html>
diff --git a/chrome/browser/resources/md_bookmarks/command_manager.html b/chrome/browser/resources/md_bookmarks/command_manager.html index 528aa077..deae2183 100644 --- a/chrome/browser/resources/md_bookmarks/command_manager.html +++ b/chrome/browser/resources/md_bookmarks/command_manager.html
@@ -33,7 +33,7 @@ <template> <cr-action-menu on-mousedown="onMenuMousedown_"> <template is="dom-repeat" items="[[menuCommands_]]" as="command"> - <button slot="item" class="dropdown-item" + <button class="dropdown-item" command$="[[command]]" hidden$="[[!isCommandVisible_(command, menuIds_)]]" disabled$="[[!isCommandEnabled_(command, menuIds_)]]"
diff --git a/chrome/browser/resources/md_downloads/downloads.html b/chrome/browser/resources/md_downloads/downloads.html index a3a71bb..a308ca34 100644 --- a/chrome/browser/resources/md_downloads/downloads.html +++ b/chrome/browser/resources/md_downloads/downloads.html
@@ -1,5 +1,6 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading" + $i18n{dark}> <head> <meta charset="utf-8"> <title>$i18n{title}</title> @@ -47,5 +48,6 @@ <link rel="import" href="chrome://downloads/i18n_setup.html"> <link rel="import" href="chrome://downloads/manager.html"> <script src="chrome://downloads/downloads.js"></script> + <link rel="import" href="chrome://resources/html/dark_mode.html"> </body> </html>
diff --git a/chrome/browser/resources/md_downloads/item.js b/chrome/browser/resources/md_downloads/item.js index ec430af..f08f18b 100644 --- a/chrome/browser/resources/md_downloads/item.js +++ b/chrome/browser/resources/md_downloads/item.js
@@ -95,11 +95,11 @@ ], /** @private {mdDownloads.mojom.PageHandlerInterface} */ - browserProxy_: null, + mojoHandler_: null, /** @override */ ready: function() { - this.browserProxy_ = downloads.BrowserProxy.getInstance().handler; + this.mojoHandler_ = downloads.BrowserProxy.getInstance().handler; this.content = this.$.content; }, @@ -355,12 +355,12 @@ /** @private */ onCancelTap_: function() { - this.browserProxy_.cancel(this.data.id); + this.mojoHandler_.cancel(this.data.id); }, /** @private */ onDiscardDangerousTap_: function() { - this.browserProxy_.discardDangerous(this.data.id); + this.mojoHandler_.discardDangerous(this.data.id); }, /** @@ -369,7 +369,7 @@ */ onDragStart_: function(e) { e.preventDefault(); - this.browserProxy_.drag(this.data.id); + this.mojoHandler_.drag(this.data.id); }, /** @@ -378,35 +378,35 @@ */ onFileLinkTap_: function(e) { e.preventDefault(); - this.browserProxy_.openFileRequiringGesture(this.data.id); + this.mojoHandler_.openFileRequiringGesture(this.data.id); }, /** @private */ onPauseOrResumeTap_: function() { if (this.isInProgress_) - this.browserProxy_.pause(this.data.id); + this.mojoHandler_.pause(this.data.id); else - this.browserProxy_.resume(this.data.id); + this.mojoHandler_.resume(this.data.id); }, /** @private */ onRemoveTap_: function() { - this.browserProxy_.remove(this.data.id); + this.mojoHandler_.remove(this.data.id); }, /** @private */ onRetryTap_: function() { - this.browserProxy_.retryDownload(this.data.id); + this.mojoHandler_.retryDownload(this.data.id); }, /** @private */ onSaveDangerousTap_: function() { - this.browserProxy_.saveDangerousRequiringGesture(this.data.id); + this.mojoHandler_.saveDangerousRequiringGesture(this.data.id); }, /** @private */ onShowTap_: function() { - this.browserProxy_.show(this.data.id); + this.mojoHandler_.show(this.data.id); }, });
diff --git a/chrome/browser/resources/md_downloads/manager.js b/chrome/browser/resources/md_downloads/manager.js index cfa31a8..95f2b416 100644 --- a/chrome/browser/resources/md_downloads/manager.js +++ b/chrome/browser/resources/md_downloads/manager.js
@@ -50,8 +50,11 @@ 'itemsChanged_(items_.*)', ], + /** @private {mdDownloads.mojom.PageCallbackRouter} */ + mojoEventTarget_: null, + /** @private {mdDownloads.mojom.PageHandlerInterface} */ - browserProxy_: null, + mojoHandler_: null, /** @private {?downloads.SearchService} */ searchService_: null, @@ -64,29 +67,30 @@ /** @override */ created: function() { - this.browserProxy_ = downloads.BrowserProxy.getInstance().handler; + const browserProxy = downloads.BrowserProxy.getInstance(); + this.mojoEventTarget_ = browserProxy.callbackRouter; + this.mojoHandler_ = browserProxy.handler; this.searchService_ = downloads.SearchService.getInstance(); }, /** @override */ attached: function() { document.documentElement.classList.remove('loading'); - const callbackRouter = - downloads.BrowserProxy.getInstance().callbackRouter; this.listenerIds_ = [ - callbackRouter.clearAll.addListener(this.clearAll_.bind(this)), - callbackRouter.insertItems.addListener(this.insertItems_.bind(this)), - callbackRouter.removeItem.addListener(this.removeItem_.bind(this)), - callbackRouter.updateItem.addListener(this.updateItem_.bind(this)), + this.mojoEventTarget_.clearAll.addListener(this.clearAll_.bind(this)), + this.mojoEventTarget_.insertItems.addListener( + this.insertItems_.bind(this)), + this.mojoEventTarget_.removeItem.addListener( + this.removeItem_.bind(this)), + this.mojoEventTarget_.updateItem.addListener( + this.updateItem_.bind(this)), ]; }, /** @override */ detached: function() { - const callbackRouter = - downloads.BrowserProxy.getInstance().callbackRouter; this.listenerIds_.forEach( - id => assert(callbackRouter.removeListener(id))); + id => assert(this.mojoEventTarget_.removeListener(id))); }, /** @private */ @@ -182,9 +186,9 @@ */ onCommand_: function(e) { if (e.command.id == 'clear-all-command') - this.browserProxy_.clearAll(); + this.mojoHandler_.clearAll(); else if (e.command.id == 'undo-command') - this.browserProxy_.undo(); + this.mojoHandler_.undo(); else if (e.command.id == 'find-command') this.$.toolbar.onFindCommand(); },
diff --git a/chrome/browser/resources/md_downloads/search_service.js b/chrome/browser/resources/md_downloads/search_service.js index 6940b680..a25b325 100644 --- a/chrome/browser/resources/md_downloads/search_service.js +++ b/chrome/browser/resources/md_downloads/search_service.js
@@ -9,7 +9,7 @@ this.searchTerms_ = []; /** @private {mdDownloads.mojom.PageHandlerInterface} */ - this.browserProxy_ = downloads.BrowserProxy.getInstance().handler; + this.mojoHandler_ = downloads.BrowserProxy.getInstance().handler; } /** @@ -24,14 +24,14 @@ /** Instructs the browser to clear all finished downloads. */ clearAll() { if (loadTimeData.getBoolean('allowDeletingHistory')) { - this.browserProxy_.clearAll(); + this.mojoHandler_.clearAll(); this.search(''); } } /** Loads more downloads with the current search terms. */ loadMore() { - this.browserProxy_.getDownloads(this.searchTerms_); + this.mojoHandler_.getDownloads(this.searchTerms_); } /**
diff --git a/chrome/browser/resources/md_downloads/toolbar.html b/chrome/browser/resources/md_downloads/toolbar.html index 03b5da2..1d8f572 100644 --- a/chrome/browser/resources/md_downloads/toolbar.html +++ b/chrome/browser/resources/md_downloads/toolbar.html
@@ -49,11 +49,11 @@ </paper-icon-button-light> </cr-toolbar> <cr-action-menu id="moreActionsMenu"> - <button slot="item" class="dropdown-item clear-all" + <button class="dropdown-item clear-all" on-click="onClearAllTap_"> $i18n{clearAll} </button> - <button slot="item" class="dropdown-item" + <button class="dropdown-item" on-click="onOpenDownloadsFolderTap_"> $i18n{openDownloadsFolder} </button>
diff --git a/chrome/browser/resources/md_downloads/toolbar.js b/chrome/browser/resources/md_downloads/toolbar.js index 263e818..a6b87df 100644 --- a/chrome/browser/resources/md_downloads/toolbar.js +++ b/chrome/browser/resources/md_downloads/toolbar.js
@@ -21,11 +21,11 @@ }, /** @private {?mdDownloads.mojom.PageHandlerInterface} */ - browserProxy_: null, + mojoHandler_: null, /** @override */ ready: function() { - this.browserProxy_ = downloads.BrowserProxy.getInstance().handler; + this.mojoHandler_ = downloads.BrowserProxy.getInstance().handler; }, /** @return {boolean} Whether removal can be undone. */ @@ -55,7 +55,7 @@ /** @private */ onClearAllTap_: function() { assert(this.canClearAll()); - this.browserProxy_.clearAll(); + this.mojoHandler_.clearAll(); this.$.moreActionsMenu.close(); }, @@ -77,7 +77,7 @@ /** @private */ onOpenDownloadsFolderTap_: function() { - this.browserProxy_.openDownloadsFolderRequiringGesture(); + this.mojoHandler_.openDownloadsFolderRequiringGesture(); this.$.moreActionsMenu.close(); },
diff --git a/chrome/browser/resources/md_extensions/extensions.html b/chrome/browser/resources/md_extensions/extensions.html index bd5a7e11..4e921eb8 100644 --- a/chrome/browser/resources/md_extensions/extensions.html +++ b/chrome/browser/resources/md_extensions/extensions.html
@@ -1,6 +1,6 @@ <!doctype html> <html dir="$i18n{textdirection}" lang="$i18n{language}" - class="loading $i18n{loadTimeClasses}"> + class="loading $i18n{loadTimeClasses}" $i18n{dark}> <head> <meta charset="utf8"> <title>$i18n{title}</title> @@ -46,5 +46,6 @@ <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> <link rel="import" href="chrome://extensions/manager.html"> + <link rel="import" href="chrome://resources/html/dark_mode.html"> </body> </html>
diff --git a/chrome/browser/resources/md_extensions/runtime_host_permissions.html b/chrome/browser/resources/md_extensions/runtime_host_permissions.html index 4134878..ca5b79f9 100644 --- a/chrome/browser/resources/md_extensions/runtime_host_permissions.html +++ b/chrome/browser/resources/md_extensions/runtime_host_permissions.html
@@ -96,11 +96,11 @@ </template> <cr-action-menu id="hostActionMenu" on-close="onActionMenuClose_"> - <button slot="item" class="dropdown-item" id="action-menu-edit" + <button class="dropdown-item" id="action-menu-edit" on-click="onActionMenuEditClick_"> $i18n{hostPermissionsEdit} </button> - <button slot="item" class="dropdown-item" id="action-menu-remove" + <button class="dropdown-item" id="action-menu-remove" on-click="onActionMenuRemoveClick_"> $i18n{remove} </button>
diff --git a/chrome/browser/resources/md_history/BUILD.gn b/chrome/browser/resources/md_history/BUILD.gn index 4523731..70fca5d 100644 --- a/chrome/browser/resources/md_history/BUILD.gn +++ b/chrome/browser/resources/md_history/BUILD.gn
@@ -76,7 +76,7 @@ "//ui/webui/resources/js:icon", "//ui/webui/resources/js:load_time_data", "//ui/webui/resources/js:util", - "//ui/webui/resources/js/cr/ui:focus_row", + "//ui/webui/resources/js/cr/ui:focus_row_behavior", ] }
diff --git a/chrome/browser/resources/md_history/history.html b/chrome/browser/resources/md_history/history.html index 6ed8535..daa1ec1 100644 --- a/chrome/browser/resources/md_history/history.html +++ b/chrome/browser/resources/md_history/history.html
@@ -1,5 +1,5 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" $i18n{dark}> <head> <meta charset="utf8"> <title>$i18n{title}</title> @@ -97,6 +97,7 @@ <link rel="import" href="chrome://history/constants.html"> <script src="chrome://history/strings.js"></script> <script src="chrome://history/history.js"></script> + <link rel="import" href="chrome://resources/html/dark_mode.html"> <link rel="import" href="chrome://history/app.html" async id="bundle"> </body>
diff --git a/chrome/browser/resources/md_history/history_item.html b/chrome/browser/resources/md_history/history_item.html index b86322b..03903e2 100644 --- a/chrome/browser/resources/md_history/history_item.html +++ b/chrome/browser/resources/md_history/history_item.html
@@ -7,7 +7,7 @@ <link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> -<link rel="import" href="chrome://resources/html/cr/ui/focus_row.html"> +<link rel="import" href="chrome://resources/html/cr/ui/focus_row_behavior.html"> <link rel="import" href="chrome://resources/html/icon.html"> <link rel="import" href="chrome://resources/html/util.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> @@ -176,10 +176,11 @@ <div id="date-accessed" class="card-title"> [[cardTitle_(numberOfItems, item.dateRelativeDay, searchTerm)]] </div> - <div id="item-container" + <div id="item-container" focus-row-container on-mousedown="onItemMousedown_" on-click="onItemClick_"> <cr-checkbox id="checkbox" checked="[[selected]]" unresolved + focus-row-control focus-type="cr-checkbox" on-mousedown="onCheckboxClick_" on-keydown="onCheckboxClick_" on-change="onCheckboxChange_" class="no-label" hidden="[[selectionNotAllowed_]]" @@ -191,6 +192,7 @@ <div class="website-icon" id="icon"></div> <div id="title-and-domain"> <a href="[[item.url]]" id="title" class="website-title" + focus-row-control focus-type="link" title="[[item.title]]" on-click="onLinkClick_" on-contextmenu="onLinkRightClick_"> <history-searched-label title="[[item.title]]" @@ -201,7 +203,7 @@ <div id="star-container"> <template is="dom-if" if="[[item.starred]]" notify-dom-change> <paper-icon-button-light id="bookmark-star-container"> - <button id="bookmark-star" + <button id="bookmark-star" focus-row-control focus-type="star" title="$i18n{removeBookmark}" on-click="onRemoveBookmarkTap_"> <iron-icon icon="cr:star"></iron-icon> </button> @@ -210,7 +212,7 @@ </div> <paper-icon-button-light id="menu-button-container" class="more-vert-button"> - <button id="menu-button" + <button id="menu-button" focus-row-control focus-type="cr-menu-button" title="$i18n{actionMenuDescription}" on-click="onMenuButtonTap_" aria-haspopup="menu"> <div></div>
diff --git a/chrome/browser/resources/md_history/history_item.js b/chrome/browser/resources/md_history/history_item.js index dec3d68..8d85ef1 100644 --- a/chrome/browser/resources/md_history/history_item.js +++ b/chrome/browser/resources/md_history/history_item.js
@@ -2,77 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -class HistoryFocusRow extends cr.ui.FocusRow { - /** - * @param {!Element} root - * @param {?Element} boundary - * @param {cr.ui.FocusRowDelegate} delegate - */ - constructor(root, boundary, delegate) { - super(root, boundary, delegate); - this.addItems(); - } - - /** @override */ - getCustomEquivalent(sampleElement) { - let equivalent; - - if (this.getTypeForElement(sampleElement) == 'star') - equivalent = this.getFirstFocusable('title'); - - return equivalent || super.getCustomEquivalent(sampleElement); - } - - addItems() { - this.destroy(); - - assert(this.addItem('checkbox', '#checkbox')); - assert(this.addItem('title', '#title')); - assert(this.addItem('menu-button', '#menu-button')); - - this.addItem('star', '#bookmark-star'); - } -} - cr.define('md_history', function() { - /** @implements {cr.ui.FocusRowDelegate} */ - class FocusRowDelegate { - /** @param {{lastFocused: Object}} historyItemElement */ - constructor(historyItemElement) { - this.historyItemElement = historyItemElement; - } - - /** - * @override - * @param {!cr.ui.FocusRow} row - * @param {!Event} e - */ - onFocus(row, e) { - this.historyItemElement.lastFocused = e.path[0]; - } - - /** - * @override - * @param {!cr.ui.FocusRow} row The row that detected a keydown. - * @param {!Event} e - * @return {boolean} Whether the event was handled. - */ - onKeydown(row, e) { - // Allow Home and End to move the history list. - if (e.key == 'Home' || e.key == 'End') - return true; - - // Prevent iron-list from changing the focus on enter. - if (e.key == 'Enter') - e.stopPropagation(); - - return false; - } - } - const HistoryItem = Polymer({ is: 'history-item', + behaviors: [cr.ui.FocusRowBehavior], + properties: { // Underlying HistoryEntry data for this item. Contains read-only fields // from the history backend, as well as fields computed by history-list. @@ -125,10 +60,12 @@ // Search term used to obtain this history-item. searchTerm: String, - }, - /** @private {?HistoryFocusRow} */ - row_: null, + overrideCustomEquivalent: { + type: Boolean, + value: true, + }, + }, /** @private {boolean} */ mouseDown_: false, @@ -139,65 +76,15 @@ /** @override */ attached: function() { Polymer.RenderStatus.afterNextRender(this, function() { - this.row_ = new HistoryFocusRow( - this.$['main-container'], null, new FocusRowDelegate(this)); - this.row_.makeActive(this.ironListTabIndex == 0); - // Adding listeners asynchronously to reduce blocking time, since these // history items are items in a potentially long list. - this.listen(this, 'focus', 'onFocus_'); - this.listen(this, 'blur', 'onBlur_'); - this.listen(this, 'dom-change', 'onDomChange_'); this.listen(this.$.checkbox, 'keydown', 'onCheckboxKeydown_'); }); }, /** @override */ detached: function() { - this.unlisten(this, 'focus', 'onFocus_'); - this.unlisten(this, 'dom-change', 'onDomChange_'); this.unlisten(this.$.checkbox, 'keydown', 'onCheckboxKeydown_'); - if (this.row_) - this.row_.destroy(); - }, - - /** - * @param {!Event} e The focus event - * @private - */ - onFocus_: function(e) { - // Don't change the focus while the mouse is down, as it prevents text - // selection. Not changing focus here is acceptable because the checkbox - // will be focused in onItemClick_() anyway. - if (this.mouseDown_) - return; - - // If focus is being restored from outside the item and the event is fired - // by the list item itself, focus the first control so that the user can - // tab through all the controls. When the user shift-tabs back to the row, - // or focus is restored to the row from a dropdown on the last item, the - // last child item will be focused before the row itself. Since this is - // the desired behavior, do not shift focus to the first item in these - // cases. - const restoreFocusToFirst = - this.listBlurred && e.composedPath()[0] === this; - - if (this.lastFocused && !restoreFocusToFirst) - this.row_.getEquivalentElement(this.lastFocused).focus(); - else - this.row_.getFirstFocusable().focus(); - this.listBlurred = false; - }, - - /** - * @param {!Event} e - * @private - */ - onBlur_: function(e) { - const node = - e.relatedTarget ? /** @type {!Node} */ (e.relatedTarget) : null; - if (!this.parentNode.contains(node)) - this.listBlurred = true; }, /** @param {!KeyboardEvent} e */ @@ -207,22 +94,6 @@ }, /** - * @private - */ - ironListTabIndexChanged_: function() { - if (this.row_) - this.row_.makeActive(this.ironListTabIndex == 0); - }, - - /** - * @private - */ - onDomChange_: function() { - if (this.row_) - this.row_.addItems(); - }, - - /** * Toggle item selection whenever the checkbox or any non-interactive part * of the item is clicked. * @param {MouseEvent} e @@ -279,10 +150,6 @@ * @private */ onItemMousedown_: function(e) { - this.mouseDown_ = true; - listenOnce(document, 'mouseup', () => { - this.mouseDown_ = false; - }); // Prevent shift clicking a checkbox from selecting text. if (e.shiftKey) e.preventDefault(); @@ -389,6 +256,9 @@ * @private */ cardTitle_: function(numberOfItems, historyDate, search) { + if (this.item === undefined) + return ''; + if (!search) return this.item.dateRelativeDay; return HistoryItem.searchResultsTitle(numberOfItems, search); @@ -400,6 +270,17 @@ el.setAttribute('title', new Date(this.item.time).toString()); this.unlisten(el, 'mouseover', 'addTimeTitle_'); }, + + /** + * @param {!Element} sampleElement An element to find an equivalent for. + * @return {?Element} An equivalent element to focus, or null to use the + * default element. + */ + getCustomEquivalent(sampleElement) { + return sampleElement.getAttribute('focus-type') === 'star' ? + this.$.title : + null; + }, }); /**
diff --git a/chrome/browser/resources/md_history/history_list.html b/chrome/browser/resources/md_history/history_list.html index f66987e..46cc926 100644 --- a/chrome/browser/resources/md_history/history_list.html +++ b/chrome/browser/resources/md_history/history_list.html
@@ -79,13 +79,13 @@ <cr-lazy-render id="sharedMenu"> <template> <cr-action-menu aria-label="$i18n{actionMenuDescription}"> - <button id="menuMoreButton" slot="item" class="dropdown-item" + <button id="menuMoreButton" class="dropdown-item" hidden="[[!canSearchMoreFromSite_( searchedTerm, actionMenuModel_.item.domain)]]" on-click="onMoreFromSiteTap_"> $i18n{moreFromSite} </button> - <button id="menuRemoveButton" slot="item" class="dropdown-item" + <button id="menuRemoveButton" class="dropdown-item" hidden="[[!canDeleteHistory_]]" on-click="onRemoveFromHistoryTap_"> $i18n{removeFromHistory}
diff --git a/chrome/browser/resources/md_history/history_list.js b/chrome/browser/resources/md_history/history_list.js index 81fcacb0d..a2d089a7 100644 --- a/chrome/browser/resources/md_history/history_list.js +++ b/chrome/browser/resources/md_history/history_list.js
@@ -432,7 +432,7 @@ */ needsTimeGap_: function(item, index) { const length = this.historyData_.length; - if (index >= length - 1 || length == 0) + if (index === undefined || index >= length - 1 || length == 0) return false; const currentItem = this.historyData_[index]; @@ -454,7 +454,7 @@ */ isCardStart_: function(item, i) { const length = this.historyData_.length; - if (length == 0 || i > length - 1) + if (i === undefined || length == 0 || i > length - 1) return false; return i == 0 || this.historyData_[i].dateRelativeDay != @@ -470,7 +470,7 @@ */ isCardEnd_: function(item, i) { const length = this.historyData_.length; - if (length == 0 || i > length - 1) + if (i === undefined || length == 0 || i > length - 1) return false; return i == length - 1 || this.historyData_[i].dateRelativeDay !=
diff --git a/chrome/browser/resources/md_history/synced_device_manager.html b/chrome/browser/resources/md_history/synced_device_manager.html index 0679f90..c9eba5a3 100644 --- a/chrome/browser/resources/md_history/synced_device_manager.html +++ b/chrome/browser/resources/md_history/synced_device_manager.html
@@ -92,11 +92,11 @@ <cr-lazy-render id="menu"> <template> <cr-action-menu> - <button id="menuOpenButton" slot="item" class="dropdown-item" + <button id="menuOpenButton" class="dropdown-item" on-click="onOpenAllTap_"> $i18n{openAll} </button> - <button id="menuDeleteButton" slot="item" class="dropdown-item" + <button id="menuDeleteButton" class="dropdown-item" on-click="onDeleteSessionTap_"> $i18n{deleteSession} </button>
diff --git a/chrome/browser/resources/md_user_manager/user_manager.html b/chrome/browser/resources/md_user_manager/user_manager.html index 1c306c2..e1a1b36 100644 --- a/chrome/browser/resources/md_user_manager/user_manager.html +++ b/chrome/browser/resources/md_user_manager/user_manager.html
@@ -2,7 +2,8 @@ <html build="$i18n{buildType}" dir="$i18n{textdirection}" lang="$i18n{language}" - screen="$i18n{screenType}"> + screen="$i18n{screenType}" + $i18n{dark}> <head> <meta charset="utf-8"> <meta name="google" value="notranslate"> @@ -362,5 +363,6 @@ </user-manager-pages> <link rel="import" href="chrome://resources/html/i18n_template.html"> <script src="user_manager.js"></script> + <link rel="import" href="chrome://resources/html/dark_mode.html"> </body> </html>
diff --git a/chrome/browser/resources/omnibox/omnibox.css b/chrome/browser/resources/omnibox/omnibox.css index 360e7a9..883fb30 100644 --- a/chrome/browser/resources/omnibox/omnibox.css +++ b/chrome/browser/resources/omnibox/omnibox.css
@@ -4,7 +4,8 @@ @import url(omnibox_column_widths.css); -.details-and-table { +output-results-group:not([hidden]) { + display: inline-block; margin-bottom: 60px; } @@ -47,7 +48,7 @@ table { background-color: white; border: 2px solid #ccc; - border-collapse: collapse; + border-spacing: 0; font-family: monospace; font-size: 12px; min-width: 900px; @@ -97,15 +98,15 @@ font-size: 0; } -.filtered-hidden { - display: none; -} - .filtered-highlighted { background-color: lightskyblue; /* TODO(manukh) This is a placholder color until other ui changes occur. */ } +.filtered-highlighted-nested { + background-color: #d0ffd0; +} + .toggle input, .toggle input:not(:checked) ~ .toggle-on, .toggle input:checked ~ .toggle-off { @@ -125,3 +126,39 @@ .toggle span:hover { background-color: #f0f0f0; } + +tbody tr:hover pre { + white-space: pre-wrap; + overflow-y: auto; +} + +tbody pre.json * { + white-space: inherit; +} + +pre.json { + padding: 0 5px; +} + +pre.json .key { + color: purple; + font-weight: bold; +} + +pre.json .string { + color: green; +} + +pre.json .number { + color: blue; +} + +pre.json .boolean { + color: slateblue; + font-weight: bold; +} + +pre.json .null { + color: magenta; + font-weight: bold; +}
diff --git a/chrome/browser/resources/omnibox/omnibox.html b/chrome/browser/resources/omnibox/omnibox.html index 8eb2a58..7a485ab 100644 --- a/chrome/browser/resources/omnibox/omnibox.html +++ b/chrome/browser/resources/omnibox/omnibox.html
@@ -73,12 +73,12 @@ </label> </p> <div class="section"> - <button id="copy-text" title="Copy visible table in text format. This is affected by the visibility of ouput; i.e. toggling `Show all details` affects what will be copied.">Copy as text</button> + <button id="copy-text" title="Copy visible table in text format. This is affected by the visibility of ouput; i.e. toggling 'Show all details' affects what will be copied.">Copy as text</button> <button id="copy-json" title="Copy responses in JSON format. This is not affected by the visibility of output and will copy responses in their entirety.">Copy as JSON</button> </div> <div class="section"> - <input id="filter-text" type="text" size="60" placeholder="Filter output"> + <input id="filter-text" type="text" size="60" placeholder="Enter filter text (e.g. 'google', 'is:starred', 'not:deletable')" title="Checks each cell individually; i.e. filter text should not span multiple columns. Supports fuzzyness; each character of filter text must be present in the cell, either adjacent to the previous matched character, or at the start of a new word. Words are defined as being delimited by either capital letters, groups of digits, or non alpha characters. E.g. 'abc' matches 'abc', 'a big cat', 'a-bigCat', 'a very big cat', and 'an amBer cat'; but does not match 'abigcat' or 'an amber cat'. 'green rainbow' is matched by 'gre rain', but not by 'gre bow'. One exception is the first character, which may be matched mid-word. E.g. 'een rain' can also match 'green rainbow'. Boolean properties can be searched for via the property name prefixed by 'is:' or 'not:'. Boolean property names are: 'Can Be Default', 'Starred', 'Has Tab Match', 'Del', 'Prev', and 'Done'."> <label class="toggle left-20"> <input id="filter-hide" type="checkbox"> <span class="toggle-off">Highlight</span> @@ -93,10 +93,9 @@ </template> <template id="details-and-table-template"> - <div class="details-and-table"> - <div class="details"></div> - <table class="table"></table> - </div> + <link rel="stylesheet" href="omnibox.css"> + <div id="details"></div> + <table id="table"></table> </template> <template id="details-template">
diff --git a/chrome/browser/resources/omnibox/omnibox.js b/chrome/browser/resources/omnibox/omnibox.js index 4eb415ad8..eac28d93 100644 --- a/chrome/browser/resources/omnibox/omnibox.js +++ b/chrome/browser/resources/omnibox/omnibox.js
@@ -90,14 +90,13 @@ omniboxInputs.addEventListener( 'display-inputs-changed', event => omniboxOutput.updateDisplayInputs(event.detail)); - omniboxInputs.addEventListener( - 'copy-request', - event => event.detail === 'text' ? - omniboxOutput.copyDelegate.copyTextOutput() : - omniboxOutput.copyDelegate.copyJsonOutput()); + omniboxInputs.addEventListener('copy-request', event => { + event.detail === 'text' ? omniboxOutput.copyDelegate.copyTextOutput() : + omniboxOutput.copyDelegate.copyJsonOutput(); + }); omniboxInputs.addEventListener( 'filter-input-changed', - event => omniboxOutput.filterDelegate.filter( + event => omniboxOutput.filter( event.detail.filterText, event.detail.filterHide)); }); })();
diff --git a/chrome/browser/resources/omnibox/omnibox_element.js b/chrome/browser/resources/omnibox/omnibox_element.js index f88f6ce..1e6a2749 100644 --- a/chrome/browser/resources/omnibox/omnibox_element.js +++ b/chrome/browser/resources/omnibox/omnibox_element.js
@@ -25,7 +25,7 @@ * @return {!Element} */ $$(id) { - return OmniboxElement.getById_(id, (this.shadowRoot)); + return OmniboxElement.getById_(id, this.shadowRoot); } /**
diff --git a/chrome/browser/resources/omnibox/omnibox_inputs.js b/chrome/browser/resources/omnibox/omnibox_inputs.js index 6465947..eb2ed80a 100644 --- a/chrome/browser/resources/omnibox/omnibox_inputs.js +++ b/chrome/browser/resources/omnibox/omnibox_inputs.js
@@ -23,11 +23,6 @@ let DisplayInputs; class OmniboxInputs extends OmniboxElement { - /** @return {string} */ - static get is() { - return 'omnibox-inputs'; - } - constructor() { super('omnibox-inputs-template'); } @@ -122,4 +117,4 @@ } } -window.customElements.define(OmniboxInputs.is, OmniboxInputs); +window.customElements.define('omnibox-inputs', OmniboxInputs);
diff --git a/chrome/browser/resources/omnibox/omnibox_output.js b/chrome/browser/resources/omnibox/omnibox_output.js index 944121a..1d62ff23 100644 --- a/chrome/browser/resources/omnibox/omnibox_output.js +++ b/chrome/browser/resources/omnibox/omnibox_output.js
@@ -3,6 +3,12 @@ // found in the LICENSE file. cr.define('omnibox_output', function() { + /** @param {!Element} element*/ + function clearChildren(element) { + while (element.firstChild) + element.firstChild.remove(); + } + /** * Details how to display an autocomplete result data field. * @typedef {{ @@ -11,6 +17,7 @@ * propertyName: string, * displayAlways: boolean, * tooltip: string, + * className: string, * }} */ let PresentationInfoRecord; @@ -170,40 +177,17 @@ } ]; - /** - * In addition to representing the rendered HTML element, OmniboxOutput also - * provides a single public interface to interact with the output: - * 1. Render tables from responses (RenderDelegate) - * 2. Control visibility based on display options (TODO) - * 3. Control visibility and coloring based on search text (FilterDelegate) - * 4. Export and copy output (CopyDelegate) - * 5. Preserve inputs and reset inputs to default (TODO) - * 6. Export and import inputs (TODO) - * With regards to interacting with RenderDelegate, OmniboxOutput tracks and - * aggregates responses from the C++ autocomplete controller. Typically, the - * C++ controller returns 3 sets of results per query, unless a new query is - * submitted before all 3 responses. OmniboxController also triggers - * appending to and clearing of OmniboxOutput when appropriate (e.g., upon - * receiving a new response or a change in display inputs). - */ class OmniboxOutput extends OmniboxElement { - /** @return {string} */ - static get is() { - return 'omnibox-output'; - } - constructor() { super('omnibox-output-template'); - /** @type {!RenderDelegate} */ - this.renderDelegate = new RenderDelegate(this.$$('contents')); /** @type {!CopyDelegate} */ this.copyDelegate = new CopyDelegate(this); - /** @type {!FilterDelegate} */ - this.filterDelegate = new FilterDelegate(this); /** @type {!Array<!mojom.OmniboxResult>} */ this.responses = []; + /** @private {!Array<!OutputResultsGroup>} */ + this.resultsGroups_ = []; /** @private {!QueryInputs} */ this.queryInputs_ = /** @type {!QueryInputs} */ ({}); /** @private {!DisplayInputs} */ @@ -213,93 +197,74 @@ /** @param {!QueryInputs} queryInputs */ updateQueryInputs(queryInputs) { this.queryInputs_ = queryInputs; - this.refresh_(); } /** @param {!DisplayInputs} displayInputs */ updateDisplayInputs(displayInputs) { this.displayInputs_ = displayInputs; - this.refresh_(); + this.updateVisibility_(); } clearAutocompleteResponses() { this.responses = []; - this.refresh_(); + this.resultsGroups_ = []; + clearChildren(this.$$('contents')); } /** @param {!mojom.OmniboxResult} response */ addAutocompleteResponse(response) { this.responses.push(response); - this.refresh_(); - } - /** @private */ - refresh_() { - this.renderDelegate.refresh( - this.queryInputs_, this.responses, this.displayInputs_); - } + const resultsGroup = + OutputResultsGroup.create(response, this.queryInputs_.cursorPosition); + this.resultsGroups_.push(resultsGroup); + this.$$('contents').appendChild(resultsGroup); - /** @return {!Array<!OutputMatch>} */ - get matches() { - return this.renderDelegate.matches; - } - } - - // Responsible for rendering the output HTML. - class RenderDelegate { - /** @param {!Element} containerElement */ - constructor(containerElement) { - /** @private {!Element} */ - this.containerElement_ = containerElement; + this.updateVisibility_(); } /** - * @param {!QueryInputs} queryInputs - * @param {!Array<!mojom.OmniboxResult>} responses - * @param {!DisplayInputs} displayInputs + * Show or hide various output elements depending on display inputs. + * 1) Show non-last result groups only if showIncompleteResults is true. + * 2) Show the details section above each table if showDetails or + * showIncompleteResults are true. + * 3) Show individual results when showAllProviders is true. + * 4) Show certain columns and headers only if they showDetails is true. + * @private */ - refresh(queryInputs, responses, displayInputs) { - if (!responses.length) - return; + updateVisibility_() { + // Show non-last result groups only if showIncompleteResults is true. + this.resultsGroups_.forEach( + (resultsGroup, index) => resultsGroup.hidden = + !this.displayInputs_.showIncompleteResults && + index !== this.resultsGroups_.length - 1); - /** @private {!Array<OutputResultsGroup>} */ - this.resultsGroup_; - - if (displayInputs.showIncompleteResults) { - this.resultsGroup_ = responses.map( - response => - new OutputResultsGroup(response, queryInputs.cursorPosition)); - } else { - const lastResponse = responses[responses.length - 1]; - this.resultsGroup_ = - [new OutputResultsGroup(lastResponse, queryInputs.cursorPosition)]; - } - - this.clearOutput_(); - this.resultsGroup_.forEach( - resultsGroup => - this.containerElement_.appendChild(resultsGroup.render( - displayInputs.showDetails, - displayInputs.showIncompleteResults, - displayInputs.showAllProviders))); + this.resultsGroups_.forEach(resultsGroup => { + resultsGroup.updateVisibility( + this.displayInputs_.showIncompleteResults, + this.displayInputs_.showDetails, + this.displayInputs_.showAllProviders); + }); } - /** @private */ - clearOutput_() { - const contents = this.containerElement_; - // Clears all children. - while (contents.firstChild) - contents.removeChild(contents.firstChild); - } - - /** @return {string} */ - get visibletableText() { - return this.containerElement_.innerText; + /** + * @param {string} filterText + * @param {boolean} filterHide + */ + filter(filterText, filterHide) { + this.matches.forEach(match => match.filter(filterText, filterHide)); } /** @return {!Array<!OutputMatch>} */ get matches() { - return this.resultsGroup_.flatMap(resultsGroup => resultsGroup.matches); + return this.resultsGroups_.flatMap(resultsGroup => resultsGroup.matches); + } + + /** @return {string} */ + get visibleTableText() { + return this.resultsGroups_ + .flatMap(resultsGroup => resultsGroup.visibleText) + .reduce((prev, cur) => `${prev}${cur}\n`, ''); } } @@ -312,70 +277,81 @@ * results. Each of these lists is tracked and rendered by OutputResultsTable * below. */ - class OutputResultsGroup { + class OutputResultsGroup extends OmniboxElement { /** * @param {!mojom.OmniboxResult} resultsGroup * @param {number} cursorPosition + * @return {!OutputResultsGroup} */ - constructor(resultsGroup, cursorPosition) { - /** @struct */ + static create(resultsGroup, cursorPosition) { + const outputResultsGroup = new OutputResultsGroup(); + outputResultsGroup.setResultsGroup(resultsGroup, cursorPosition); + return outputResultsGroup; + } + + constructor() { + super('details-and-table-template'); + } + + /** + * @param {!mojom.OmniboxResult} resultsGroup + * @param {number} cursorPosition + */ + setResultsGroup(resultsGroup, cursorPosition) { + /** + * @type {{cursorPosition: number, time: number, done: boolean, host: + * string, isTypedHost: boolean}} + */ this.details = { - cursorPosition, + cursorPosition: cursorPosition, time: resultsGroup.timeSinceOmniboxStartedMs, done: resultsGroup.done, host: resultsGroup.host, isTypedHost: resultsGroup.isTypedHost }; + /** @type {!Array<!OutputHeader>} */ + this.headers = PROPERTY_OUTPUT_ORDER.map(property => { + return OutputHeader.create( + property.header, property.propertyName, property.url, + property.tooltip); + }); /** @type {!OutputResultsTable} */ this.combinedResults = - new OutputResultsTable(resultsGroup.combinedResults); + OutputResultsTable.create(resultsGroup.combinedResults); /** @type {!Array<!OutputResultsTable>} */ this.individualResultsList = resultsGroup.resultsByProvider .map(resultsWrapper => resultsWrapper.results) .filter(results => results.length > 0) - .map(results => new OutputResultsTable(results)); + .map(OutputResultsTable.create); + if (this.hasAdditionalProperties) + this.headers.push(OutputHeader.create( + 'Additional Properties', 'additional-properties', '', '')); + this.render_(); } /** * Creates a HTML Node representing this data. - * @param {boolean} showDetails - * @param {boolean} showIncompleteResults - * @param {boolean} showAllProviders - * @return {!Element} + * @private */ - render(showDetails, showIncompleteResults, showAllProviders) { - const detailsAndTable = - OmniboxElement.getTemplate('details-and-table-template'); - if (showDetails || showIncompleteResults) { - detailsAndTable.querySelector('.details') - .appendChild(this.renderDetails_()); - } + render_() { + clearChildren(this); - const showAdditionalPropertiesColumn = - this.showAdditionalPropertiesColumn_(showDetails); + /** @private {!Array<!Element>} */ + this.innerHeaders_ = []; - detailsAndTable.querySelector('.table').appendChild( - OutputResultsTable.renderHeader( - showDetails, showAdditionalPropertiesColumn)); - detailsAndTable.querySelector('.table').appendChild( - this.combinedResults.render(showDetails)); - if (showAllProviders) { - this.individualResultsList.forEach(individualResults => { - detailsAndTable.querySelector('.table').appendChild( - individualResults.renderInnerHeader( - showDetails, showAdditionalPropertiesColumn)); - detailsAndTable.querySelector('.table').appendChild( - individualResults.render(showDetails)); - }); - } - return detailsAndTable; + this.$$('details').appendChild(this.renderDetails_()); + this.$$('table').appendChild(this.renderHeader_()); + this.$$('table').appendChild(this.combinedResults); + this.individualResultsList.forEach(results => { + const innerHeader = this.renderInnerHeader_(results); + this.innerHeaders_.push(innerHeader); + this.$$('table').appendChild(innerHeader); + this.$$('table').appendChild(results); + }); } - /** - * @private - * @return {!Element} - */ + /** @private @return {!Element} */ renderDetails_() { const details = OmniboxElement.getTemplate('details-template'); details.querySelector('.cursor-position').textContent = @@ -388,16 +364,66 @@ return details; } + /** @private @return {!Element} */ + renderHeader_() { + const head = document.createElement('thead'); + const row = document.createElement('tr'); + this.headers.forEach(cell => row.appendChild(cell)); + head.appendChild(row); + return head; + } + /** * @private + * @param {!OutputResultsTable} results + * @return {!Element} + */ + renderInnerHeader_(results) { + const head = document.createElement('thead'); + const row = document.createElement('tr'); + const cell = document.createElement('th'); + // Reserve 1 more column for showing the additional properties column. + cell.colSpan = PROPERTY_OUTPUT_ORDER.length + 1; + cell.textContent = results.innerHeaderText; + row.appendChild(cell); + head.appendChild(row); + return head; + } + + /** + * @param {boolean} showIncompleteResults * @param {boolean} showDetails + * @param {boolean} showAllProviders + */ + updateVisibility(showIncompleteResults, showDetails, showAllProviders) { + // Show the details section above each table if showDetails or + // showIncompleteResults are true. + this.$$('details').hidden = !showDetails && !showIncompleteResults; + + // Show individual results when showAllProviders is true. + this.individualResultsList.forEach( + individualResults => individualResults.hidden = !showAllProviders); + this.innerHeaders_.forEach( + innerHeader => innerHeader.hidden = !showAllProviders); + + // Show certain column headers only if they showDetails is true. + PROPERTY_OUTPUT_ORDER.forEach((displayProperty, index) => { + this.headers[index].hidden = + !showDetails && !displayProperty.displayAlways; + }); + + // Show certain columns only if they showDetails is true. + this.matches.forEach(match => match.updateVisibility(showDetails)); + } + + /** + * @private * @return {boolean} */ - showAdditionalPropertiesColumn_(showDetails) { - return showDetails && - (this.combinedResults.hasAdditionalProperties || - this.individualResultsList.some( - results => results.hasAdditionalProperties)); + get hasAdditionalProperties() { + return this.combinedResults.hasAdditionalProperties || + this.individualResultsList.some( + results => results.hasAdditionalProperties); } /** @return {!Array<!OutputMatch>} */ @@ -406,67 +432,52 @@ .concat(this.individualResultsList) .flatMap(results => results.matches); } + + /** @return {!Array<string>} */ + get visibleText() { + return Array.from(this.shadowRoot.querySelectorAll(':host > :not(style)')) + .map(child => child.innerText); + } } /** * Helps track and render a list of results. Each result is tracked and * rendered by OutputMatch below. */ - class OutputResultsTable { - /** @param {!Array<!mojom.AutocompleteMatch>} results */ - constructor(results) { + class OutputResultsTable extends HTMLTableSectionElement { + /** + * @param {!Array<!mojom.AutocompleteMatch>} results + * @return {!OutputResultsTable} + */ + static create(results) { + /** + * TODO (manukh): Remove all 4 occurances of suppressing type checking at + * document.createElement invocations once the Closure Compiler is + * updated. It currently supports the deprecated signature where the 2nd + * paramter is of type string. + * @suppress {checkTypes} + */ + const resultsTable = new OutputResultsTable(); + resultsTable.results = results; + return resultsTable; + } + + constructor() { + super(); /** @type {!Array<!OutputMatch>} */ - this.matches = results.map(match => new OutputMatch(match)); + this.matches = []; } - /** - * @param {boolean} showDetails - * @param {boolean} showAdditionalPropertiesColumn - * @return {Element} - */ - static renderHeader(showDetails, showAdditionalPropertiesColumn) { - const head = document.createElement('thead'); - const row = document.createElement('tr'); - const cells = - OutputMatch.displayedProperties(showDetails) - .map( - ({header, url, tooltip}) => - OutputMatch.renderHeaderCell(header, url, tooltip)); - if (showAdditionalPropertiesColumn) - cells.push(OutputMatch.renderHeaderCell('Additional Properties')); - cells.forEach(cell => row.appendChild(cell)); - head.appendChild(row); - return head; + /** @param {!Array<!mojom.AutocompleteMatch>} results */ + set results(results) { + this.matches.forEach(match => match.remove()); + this.matches = results.map(OutputMatch.create); + this.matches.forEach(this.appendChild.bind(this)); } - /** - * Creates a HTML Node representing this data. - * @param {boolean} showDetails - * @return {!Element} - */ - render(showDetails) { - const body = document.createElement('tbody'); - this.matches.forEach( - match => body.appendChild(match.render(showDetails))); - return body; - } - - /** - * @param {boolean} showDetails - * @param {boolean} showAdditionalPropertiesColumn - * @return {!Element} - */ - renderInnerHeader(showDetails, showAdditionalPropertiesColumn) { - const head = document.createElement('thead'); - const row = document.createElement('tr'); - const cell = document.createElement('th'); - // Reserve 1 more column if showing the additional properties column. - cell.colSpan = OutputMatch.displayedProperties(showDetails).length + - showAdditionalPropertiesColumn; - cell.textContent = this.matches[0].properties.providerName.value; - row.appendChild(cell); - head.appendChild(row); - return head; + /** @return {string} */ + get innerHeaderText() { + return this.matches[0].providerName; } /** @return {boolean} */ @@ -476,83 +487,83 @@ } /** Helps track and render a single match. */ - class OutputMatch { + class OutputMatch extends HTMLTableRowElement { + /** + * @param {!mojom.AutocompleteMatch} match + * @return {!OutputMatch} + */ + static create(match) { + /** @suppress {checkTypes} */ + const outputMatch = new OutputMatch(); + outputMatch.match = match; + return outputMatch; + } + /** @param {!mojom.AutocompleteMatch} match */ - constructor(match) { - /** @dict */ + set match(match) { + /** @type {!Object} */ this.properties = {}; - let unconsumedProperties = {}; + /** @type {string} */ + this.providerName = match.providerName; + const unconsumedProperties = {}; Object.entries(match).forEach(propertyNameValueTuple => { - // TODO(manukh) replace with destructuring when the styleguide is - // updated - // https://chromium-review.googlesource.com/c/chromium/src/+/1271915 const propertyName = propertyNameValueTuple[0]; const propertyValue = propertyNameValueTuple[1]; if (PROPERTY_OUTPUT_ORDER.some( property => property.propertyName === propertyName)) { this.properties[propertyName] = - OutputProperty.constructProperty(propertyName, propertyValue); + OutputProperty.create(propertyName, propertyValue); } else { unconsumedProperties[propertyName] = propertyValue; } }); /** @type {!OutputProperty} */ - this.additionalProperties = OutputProperty.constructProperty( - 'additionalProperties', unconsumedProperties); + this.additionalProperties = + OutputProperty.create('additionalProperties', unconsumedProperties); - /** @type {!Element} */ - this.associatedElement; + this.render_(); + } + + /** @private */ + render_() { + clearChildren(this); + PROPERTY_OUTPUT_ORDER + .map(property => this.properties[property.propertyName]) + .forEach(cell => this.appendChild(cell)); + if (this.hasAdditionalProperties) + this.appendChild(this.additionalProperties); + } + + /** @param {boolean} showDetails */ + updateVisibility(showDetails) { + // Show certain columns only if they showDetails is true. + PROPERTY_OUTPUT_ORDER.forEach(displayProperty => { + this.properties[displayProperty.propertyName].hidden = + !showDetails && !displayProperty.displayAlways; + }); } /** - * Creates a HTML Node representing this data. - * @param {boolean} showDetails - * @return {!Element} + * @param {string} filterText + * @param {boolean} filterHide */ - render(showDetails) { - const row = document.createElement('tr'); - OutputMatch.displayedProperties(showDetails) - .map(property => this.properties[property.propertyName].render()) - .forEach(cell => row.appendChild(cell)); + filter(filterText, filterHide) { + this.hidden = false; + this.classList.remove('filtered-highlighted'); + this.allProperties_.forEach( + property => property.classList.remove('filtered-highlighted-nested')); - if (showDetails && this.hasAdditionalProperties) - row.appendChild(this.additionalProperties.render()); + if (!filterText) + return; - this.associatedElement = row; - return this.associatedElement; - } - - /** - * @param {string} name - * @param {string=} url - * @param {string=} tooltip - * @return {!Element} - */ - static renderHeaderCell(name, url, tooltip) { - const cell = document.createElement('th'); - if (url) { - const link = document.createElement('a'); - link.textContent = name; - link.href = url; - cell.appendChild(link); - } else { - cell.textContent = name; - } - cell.className = - 'column-' + name.replace(/[A-Z]/g, c => '-' + c.toLowerCase()); - cell.title = tooltip || ''; - return cell; - } - - /** - * @return {!Array<!PresentationInfoRecord>} Array representing which - * columns need to be displayed. - */ - static displayedProperties(showDetails) { - return showDetails ? - PROPERTY_OUTPUT_ORDER : - PROPERTY_OUTPUT_ORDER.filter(property => property.displayAlways); + const matchedProperties = this.allProperties_.filter( + property => FilterUtil.filterText(property.text, filterText)); + const isMatch = matchedProperties.length > 0; + this.hidden = filterHide && !isMatch; + this.classList.toggle('filtered-highlighted', !filterHide && isMatch); + matchedProperties.forEach( + property => property.classList.add('filtered-highlighted-nested')); } /** @@ -560,144 +571,234 @@ * needs to be displayed for this match. */ get hasAdditionalProperties() { - return Object.keys(this.additionalProperties).length > 0; + return Object.keys(this.additionalProperties.value).length > 0; } - /** @return !Array<!OutputProperty> */ - get allProperties() { + /** @private @return !Array<!OutputProperty> */ + get allProperties_() { return Object.values(this.properties).concat(this.additionalProperties); } } - /** @abstract */ - class OutputProperty { + class OutputHeader extends HTMLTableCellElement { /** - * @param {string} name - * @param {*} value + * @param {string} text + * @param {string} propertyName + * @param {string=} url + * @param {string=} tooltip + * @return {!OutputHeader} */ - constructor(name, value) { - /** @type {string} */ - this.name = name; - /** @type {*} */ - this.value = value; + static create(text, propertyName, url, tooltip) { + /** @suppress {checkTypes} */ + const header = new OutputHeader(); + header.classList.add( + 'column-' + + propertyName.replace(/[A-Z]/g, c => '-' + c.toLowerCase())); + header.setContents(text, url); + header.tooltip = tooltip; + return header; + } + + constructor() { + super(); + /** @private {!Element} */ + this.div_ = document.createElement('div'); + this.appendChild(this.div_); + /** @private {!Element} */ + this.link_ = document.createElement('a'); + } + + /** @param {string=} tooltip */ + set tooltip(tooltip) { + this.title = tooltip || ''; } /** + * @param {string} text + * @param {string=} url + */ + setContents(text, url) { + if (url) { + this.textContent = ''; + this.link_.textContent = text; + this.link_.href = url; + this.appendChild(this.link_); + } else { + this.textContent = text; + this.link_.remove(); + } + } + } + + /** @abstract */ + class OutputProperty extends HTMLTableCellElement { + /** * @param {string} name - * @param {*} value + * @param {!Object} value * @return {!OutputProperty} */ - static constructProperty(name, value) { - if (typeof value === 'boolean') - return new OutputBooleanProperty(name, value); - if (typeof value === 'object') + static create(name, value) { + let property; + if (typeof value === 'boolean') { + property = new OutputBooleanProperty(); + } else if (typeof value === 'object') { // We check if the first element has key and value properties. if (value && value[0] && value[0].key && value[0].value) - return new OutputKeyValueTuplesProperty(name, value); + property = new OutputKeyValueTuplesProperty(); else - return new OutputJsonProperty(name, value); - const LINK_REGEX = /^(http|https|ftp|chrome|file):\/\//; - if (LINK_REGEX.test(value)) - return new OutputLinkProperty(name, value); - return new OutputTextProperty(name, value); + property = new OutputJsonProperty(); + } else if (/^(http|https|ftp|chrome|file):\/\//.test(value)) { + property = new OutputLinkProperty(); + } else { + property = new OutputTextProperty(); + } + + property.name = name; + property.value = value; + return property; } - /** - * @abstract - * @return {!Element} - */ - render() {} + /** @return {!Object} */ + get value() { + return this.value_; + } + + /** @param {!Object} value */ + set value(value) { + /** @private {!Object} */ + this.value_ = value; + /** @override */ + this.render_(); + } + + /** @abstract @private */ + render_() {} /** @return {string} */ get text() { - return this.value + ''; + return this.value_ + ''; } } class OutputBooleanProperty extends OutputProperty { - /** - * @override - * @return {!Element} - */ - render() { - const cell = document.createElement('td'); - const icon = document.createElement('div'); - icon.className = this.value ? 'check-mark' : 'x-mark'; - icon.textContent = this.value; - cell.appendChild(icon); - return cell; - } - } - - class OutputKeyValueTuplesProperty extends OutputProperty { - /** - * @override - * @return {!Element} - */ - render() { - const cell = document.createElement('td'); - const pre = document.createElement('pre'); - pre.textContent = this.text; - cell.appendChild(pre); - return cell; + constructor() { + super(); + /** @private {!Element} */ + this.icon_ = document.createElement('div'); + this.appendChild(this.icon_); } - /** - * @override - * @return {string} - */ + /** @private @override */ + render_() { + this.icon_.classList.toggle('check-mark', !!this.value); + this.icon_.classList.toggle('x-mark', !this.value); + } + get text() { - return this.value.reduce( - (prev, {key, value}) => `${prev}${key}: ${value}\n`, ''); + return (this.value_ ? 'is: ' : 'not: ') + this.name; } } class OutputJsonProperty extends OutputProperty { - /** - * @override - * @return {!Element} - */ - render() { - const cell = document.createElement('td'); - const pre = document.createElement('pre'); - pre.textContent = this.text; - cell.appendChild(pre); - return cell; + constructor() { + super(); + /** @private {!Element} */ + this.pre_ = document.createElement('pre'); + this.pre_.classList.add('json'); + this.appendChild(this.pre_); + } + + /** @private @override */ + render_() { + clearChildren(this.pre_); + this.text.split(/("(?:[^"\\]|\\.)*":?|\w+)/) + .map( + word => OutputJsonProperty.renderJsonWord( + word, OutputJsonProperty.classifyJsonWord(word))) + .forEach(jsonSpan => this.pre_.appendChild(jsonSpan)); + } + + /** @override @return {string} */ + get text() { + return JSON.stringify(this.value_, null, 2); } /** - * @override - * @return {string} + * @param {string} word + * @param {string|undefined} cls + * @return {!Element} */ + static renderJsonWord(word, cls) { + const span = document.createElement('span'); + if (cls) + span.classList.add(cls); + span.textContent = word; + return span; + } + + /** + * @param {string} word + * @return {string|undefined} + */ + static classifyJsonWord(word) { + if (/^\d+$/.test(word)) + return 'number'; + if (/^"[^]*":$/.test(word)) + return 'key'; + if (/^"[^]*"$/.test(word)) + return 'string'; + if (/true|false/.test(word)) + return 'boolean'; + if (/null/.test(word)) + return 'null'; + } + } + + class OutputKeyValueTuplesProperty extends OutputJsonProperty { + /** @private @override */ + render_() { + clearChildren(this.pre_); + this.value.forEach(({key, value}) => { + this.pre_.appendChild( + OutputJsonProperty.renderJsonWord(key + ': ', 'key')); + this.pre_.appendChild( + OutputJsonProperty.renderJsonWord(value + '\n', 'number')); + }); + } + + /** @override @return {string} */ get text() { - return JSON.stringify(this.value, null, 2); + return this.value_.reduce( + (prev, {key, value}) => `${prev}${key}: ${value}\n`, ''); } } class OutputLinkProperty extends OutputProperty { - /** - * @override - * @return {!Element} - */ - render() { - const cell = document.createElement('td'); - const link = document.createElement('a'); - link.textContent = this.value; - link.href = this.value; - cell.appendChild(link); - return cell; + constructor() { + super(); + /** @private {!Element} */ + this.link_ = document.createElement('a'); + this.appendChild(this.link_); + } + + /** @private @override */ + render_() { + this.link_.textContent = this.value_; + this.link_.href = this.value_; } } class OutputTextProperty extends OutputProperty { - /** - * @override - * @return {!Element} - */ - render() { - const cell = document.createElement('td'); - cell.textContent = this.value; - return cell; + constructor() { + super(); + /** @private {!Element} */ + this.div_ = document.createElement('div'); + this.appendChild(this.div_); + } + + /** @private @override */ + render_() { + this.div_.textContent = this.value_; } } @@ -710,7 +811,7 @@ } copyTextOutput() { - this.copy_(this.omniboxOutput_.renderDelegate.visibletableText); + this.copy_(this.omniboxOutput_.visibleTableText); } copyJsonOutput() { @@ -728,37 +829,10 @@ } /** Responsible for highlighting and hiding rows using filter text. */ - class FilterDelegate { - /** @param {!omnibox_output.OmniboxOutput} omniboxOutput */ - constructor(omniboxOutput) { - /** @private {!omnibox_output.OmniboxOutput} */ - this.omniboxOutput_ = omniboxOutput; - } - + class FilterUtil { /** - * @param {string} filterText - * @param {boolean} filterHide - */ - filter(filterText, filterHide) { - this.omniboxOutput_.matches.filter(match => match.associatedElement) - .forEach(match => { - const row = match.associatedElement; - row.classList.remove('filtered-hidden'); - row.classList.remove('filtered-highlighted'); - - if (!filterText) - return; - - const isMatch = FilterDelegate.filterMatch_(match, filterText); - row.classList.toggle('filtered-hidden', filterHide && !isMatch); - row.classList.toggle( - 'filtered-highlighted', !filterHide && isMatch); - }); - } - - /** - * Checks if a omnibox match fuzzy-matches a filter string. Each character - * of filterText must be present in the match text, either adjacent to the + * Checks if a string fuzzy-matches a filter string. Each character + * of filterText must be present in the search text, either adjacent to the * previous matched character, or at the start of a new word (see * textToWords_). * E.g. `abc` matches `abc`, `a big cat`, `a-bigCat`, `a very big cat`, and @@ -766,24 +840,24 @@ * `green rainbow` is matched by `gre rain`, but not by `gre bow`. * One exception is the first character, which may be matched mid-word. * E.g. `een rain` can also match `green rainbow`. - * @private - * @param {!OutputMatch} match + * @param {string} searchText * @param {string} filterText * @return {boolean} */ - static filterMatch_(match, filterText) { - const regexFilter = Array.from(filterText).join('(.*\\.)?'); - return match.allProperties - .map(property => property.text) - .map(text => FilterDelegate.textToWords_(text).join('.')) - .some(text => text.match(regexFilter)); + static filterText(searchText, filterText) { + const regexFilter = + Array.from(filterText) + .map(word => word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')) + .join('(.*\\.)?'); + const words = FilterUtil.textToWords_(searchText).join('.'); + return words.match(new RegExp(regexFilter, 'i')) !== null; } /** * Splits a string into words, delimited by either capital letters, groups * of digits, or non alpha characters. * E.g., `https://google.com/the-dog-ate-134pies` will be split to: - * https, :, /, /, google, ., com, /, the, -, dog, -, ate, -, 134, pies + * https, :, /, /, google, ., com, /, the, -, dog, -, ate, -, 134, pies * We don't use `Array.split`, because we want to group digits, e.g. 134. * @private * @param {string} text @@ -794,7 +868,23 @@ } } - window.customElements.define(OmniboxOutput.is, OmniboxOutput); + customElements.define('omnibox-output', OmniboxOutput); + customElements.define('output-results-group', OutputResultsGroup); + customElements.define( + 'output-results-table', OutputResultsTable, {extends: 'tbody'}); + customElements.define('output-match', OutputMatch, {extends: 'tr'}); + customElements.define('output-haeder', OutputHeader, {extends: 'th'}); + customElements.define( + 'output-boolean-property', OutputBooleanProperty, {extends: 'td'}); + customElements.define( + 'output-json-property', OutputJsonProperty, {extends: 'td'}); + customElements.define( + 'output-key-value-tuple-property', OutputKeyValueTuplesProperty, + {extends: 'td'}); + customElements.define( + 'output-link-property', OutputLinkProperty, {extends: 'td'}); + customElements.define( + 'output-text-property', OutputTextProperty, {extends: 'td'}); return {OmniboxOutput: OmniboxOutput}; });
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js index 8053a8fd5..d5e6985 100644 --- a/chrome/browser/resources/pdf/pdf_viewer.js +++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -141,7 +141,8 @@ this.metrics.onDocumentOpened(); // Parse open pdf parameters. - this.paramsParser_ = new OpenPDFParamsParser(this.postMessage_.bind(this)); + this.paramsParser_ = new OpenPDFParamsParser( + message => this.pluginController_.postMessage(message)); const toolbarEnabled = this.paramsParser_.getUiUrlParams(this.originalUrl_).toolbar && !this.isPrintPreview_; @@ -173,7 +174,11 @@ 1.0; this.viewport_ = new Viewport( window, this.sizer_, this.viewportChanged_.bind(this), - this.beforeZoom_.bind(this), this.afterZoom_.bind(this), + () => this.currentController_.beforeZoom(), + () => { + this.currentController_.afterZoom(); + this.zoomManager_.onPdfZoomChange(); + }, this.setUserInitiated_.bind(this), getScrollbarWidth(), defaultZoom, topToolbarHeight); @@ -187,8 +192,6 @@ // references it. this.plugin_.id = 'plugin'; this.plugin_.type = 'application/x-google-chrome-pdf'; - this.plugin_.addEventListener( - 'message', this.handlePluginMessage_.bind(this), false); // Handle scripting messages from outside the extension that wish to interact // with it. We also send a message indicating that extension has loaded and @@ -219,6 +222,10 @@ } document.body.appendChild(this.plugin_); + this.pluginController_ = + new PluginController(this.plugin_, this, this.viewport_); + this.currentController_ = this.pluginController_; + // Setup the button event listeners. this.zoomToolbar_ = $('zoom-toolbar'); this.zoomToolbar_.addEventListener( @@ -240,10 +247,11 @@ if (toolbarEnabled) { this.toolbar_ = $('toolbar'); this.toolbar_.hidden = false; - this.toolbar_.addEventListener('save', this.save_.bind(this)); - this.toolbar_.addEventListener('print', this.print_.bind(this)); + this.toolbar_.addEventListener('save', () => this.save()); this.toolbar_.addEventListener( - 'rotate-right', this.rotateClockwise_.bind(this)); + 'print', () => this.currentController_.print()); + this.toolbar_.addEventListener( + 'rotate-right', () => this.currentController_.rotateClockwise()); this.toolbar_.docTitle = getFilenameFromURL(this.originalUrl_); } @@ -410,7 +418,7 @@ return; case 65: // 'a' key. if (e.ctrlKey || e.metaKey) { - this.postMessage_({type: 'selectAll'}); + this.pluginController_.postMessage({type: 'selectAll'}); // Since we do selection ourselves. e.preventDefault(); } @@ -423,7 +431,7 @@ return; case 219: // Left bracket key. if (e.ctrlKey) - this.rotateCounterClockwise_(); + this.currentController_.rotateCounterClockwise(); return; case 220: // Backslash key. if (e.ctrlKey) @@ -431,7 +439,7 @@ return; case 221: // Right bracket key. if (e.ctrlKey) - this.rotateClockwise_(); + this.currentController_.rotateClockwise(); return; } @@ -465,28 +473,6 @@ }, /** - * Rotate the plugin clockwise. - * - * @private - */ - rotateClockwise_: function() { - this.metrics.onRotation(); - this.viewport_.rotateClockwise(1); - this.postMessage_({type: 'rotateClockwise'}); - }, - - /** - * Rotate the plugin counter-clockwise. - * - * @private - */ - rotateCounterClockwise_: function() { - this.metrics.onRotation(); - this.viewport_.rotateClockwise(3); - this.postMessage_({type: 'rotateCounterclockwise'}); - }, - - /** * Request to change the viewport fitting type. * * @param {CustomEvent} e Event received with the new FittingType as detail. @@ -508,26 +494,6 @@ }, /** - * Notify the plugin to print. - * - * @private - */ - print_: function() { - this.postMessage_({type: 'print'}); - }, - - /** - * Notify the plugin to save. - * - * @private - */ - save_: function() { - const newToken = createToken(); - this.pendingTokens_.add(newToken); - this.postMessage_({type: 'save', token: newToken}); - }, - - /** * Sends a 'documentLoaded' message to the PDFScriptingAPI if the document has * finished loading. * @@ -598,9 +564,8 @@ * message being received from the plugin. * * @param {number} progress the progress as a percentage. - * @private */ - updateProgress_: function(progress) { + updateProgress: function(progress) { if (this.toolbar_) this.toolbar_.loadProgress = progress; @@ -658,224 +623,11 @@ * @private */ onPasswordSubmitted_: function(event) { - this.postMessage_( + this.pluginController_.postMessage( {type: 'getPasswordComplete', password: event.detail.password}); }, /** - * Post a message to the PPAPI plugin. Some messages will cause an async reply - * to be received through handlePluginMessage_(). - * - * @param {Object} message Message to post. - * @private - */ - postMessage_: function(message) { - this.plugin_.postMessage(message); - }, - - /** - * An event handler for handling message events received from the plugin. - * - * @param {MessageObject} message a message event. - * @private - */ - handlePluginMessage_: function(message) { - switch (message.data.type.toString()) { - case 'beep': - // Beeps are annoying, so just track count for now. - this.beepCount_ += 1; - break; - case 'documentDimensions': - this.documentDimensions_ = message.data; - this.isUserInitiatedEvent_ = false; - this.viewport_.setDocumentDimensions(this.documentDimensions_); - this.isUserInitiatedEvent_ = true; - // If we received the document dimensions, the password was good so we - // can dismiss the password screen. - if (this.passwordScreen_.active) - this.passwordScreen_.close(); - - if (this.pageIndicator_) - this.pageIndicator_.initialFadeIn(); - - if (this.toolbar_) { - this.toolbar_.docLength = - this.documentDimensions_.pageDimensions.length; - } - break; - case 'email': - const href = 'mailto:' + message.data.to + '?cc=' + message.data.cc + - '&bcc=' + message.data.bcc + '&subject=' + message.data.subject + - '&body=' + message.data.body; - window.location.href = href; - break; - case 'getPassword': - // If the password screen isn't up, put it up. Otherwise we're - // responding to an incorrect password so deny it. - if (!this.passwordScreen_.active) - this.passwordScreen_.show(); - else - this.passwordScreen_.deny(); - break; - case 'getSelectedTextReply': - this.sendScriptingMessage_(message.data); - break; - case 'goToPage': - this.viewport_.goToPage(message.data.page); - break; - case 'loadProgress': - this.updateProgress_(message.data.progress); - break; - case 'navigate': - // If in print preview, always open a new tab. - if (this.isPrintPreview_) { - this.navigator_.navigate( - message.data.url, - Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB); - } else { - this.navigator_.navigate(message.data.url, message.data.disposition); - } - break; - case 'printPreviewLoaded': - this.isPrintPreviewLoadingFinished_ = true; - this.sendDocumentLoadedMessage_(); - break; - case 'setScrollPosition': - this.viewport_.scrollTo(/** @type {!PartialPoint} */ (message.data)); - break; - case 'scrollBy': - this.viewport_.scrollBy(/** @type {!Point} */ (message.data)); - break; - case 'cancelStreamUrl': - chrome.mimeHandlerPrivate.abortStream(); - break; - case 'metadata': - if (message.data.title) { - document.title = message.data.title; - } else { - document.title = getFilenameFromURL(this.originalUrl_); - } - this.bookmarks_ = message.data.bookmarks; - if (this.toolbar_) { - this.toolbar_.docTitle = document.title; - this.toolbar_.bookmarks = this.bookmarks; - } - break; - case 'setIsSelecting': - this.viewportScroller_.setEnableScrolling(message.data.isSelecting); - break; - case 'getNamedDestinationReply': - this.paramsParser_.onNamedDestinationReceived(message.data.pageNumber); - break; - case 'formFocusChange': - this.isFormFieldFocused_ = message.data.focused; - break; - case 'saveData': - this.saveData_(message.data); - break; - case 'consumeSaveToken': - if (!this.pendingTokens_.delete(message.data.token)) - throw new Error('Internal error: save token not found.'); - break; - } - }, - - /** - * Saves a pdf file buffer received from the plugin. - * - * @param {SaveDataMessageData} messageData data of the message event. - * @private - */ - saveData_: function(messageData) { - if (!loadTimeData.getBoolean('pdfFormSaveEnabled')) - throw new Error('Internal error: save not enabled.'); - - // Verify a token that was created by this instance is included to avoid - // being spammed. - if (!this.pendingTokens_.delete(messageData.token)) - throw new Error('Internal error: save token not found, abort save.'); - - // Verify the file size and the first bytes to make sure it's a PDF. Cap at - // 100 MB. This cap should be kept in sync with and is also enforced in - // pdf/out_of_process_instance.cc. - const MIN_FILE_SIZE = '%PDF1.0'.length; - const MAX_FILE_SIZE = 100 * 1000 * 1000; - - const bufView = new Uint8Array(messageData.dataToSave); - if (bufView.length > MAX_FILE_SIZE) - throw new Error(`File too large to be saved: ${bufView.length} bytes.`); - if (bufView.length < MIN_FILE_SIZE || - String.fromCharCode(bufView[0], bufView[1], bufView[2], bufView[3]) != - '%PDF') { - throw new Error('Not a PDF file.'); - } - - // Make sure file extension is .pdf, avoids dangerous extensions. - let fileName = messageData.fileName; - if (!fileName.toLowerCase().endsWith('.pdf')) - fileName = fileName + '.pdf'; - - const a = document.createElement('a'); - a.download = fileName; - const blob = new Blob([messageData.dataToSave], {type: 'application/pdf'}); - a.href = URL.createObjectURL(blob); - a.click(); - URL.revokeObjectURL(a.href); - }, - - /** - * A callback that's called before the zoom changes. Notify the plugin to stop - * reacting to scroll events while zoom is taking place to avoid flickering. - * - * @private - */ - beforeZoom_: function() { - this.postMessage_({type: 'stopScrolling'}); - - if (this.viewport_.pinchPhase == Viewport.PinchPhase.PINCH_START) { - const position = this.viewport_.position; - const zoom = this.viewport_.zoom; - const pinchPhase = this.viewport_.pinchPhase; - this.postMessage_({ - type: 'viewport', - userInitiated: true, - zoom: zoom, - xOffset: position.x, - yOffset: position.y, - pinchPhase: pinchPhase - }); - } - }, - - /** - * A callback that's called after the zoom changes. Notify the plugin of the - * zoom change and to continue reacting to scroll events. - * - * @private - */ - afterZoom_: function() { - const position = this.viewport_.position; - const zoom = this.viewport_.zoom; - const pinchVector = this.viewport_.pinchPanVector || {x: 0, y: 0}; - const pinchCenter = this.viewport_.pinchCenter || {x: 0, y: 0}; - const pinchPhase = this.viewport_.pinchPhase; - - this.postMessage_({ - type: 'viewport', - userInitiated: this.isUserInitiatedEvent_, - zoom: zoom, - xOffset: position.x, - yOffset: position.y, - pinchPhase: pinchPhase, - pinchX: pinchCenter.x, - pinchY: pinchCenter.y, - pinchVectorX: pinchVector.x, - pinchVectorY: pinchVector.y - }); - this.zoomManager_.onPdfZoomChange(); - }, - - /** * A callback that sets |isUserInitiatedEvent_| to |userInitiated|. * * @param {boolean} userInitiated The value to set |isUserInitiatedEvent_| to. @@ -1024,7 +776,7 @@ case 'getSelectedText': case 'print': case 'selectAll': - this.postMessage_(message.data); + this.pluginController_.postMessage(message.data); break; } }, @@ -1042,7 +794,7 @@ switch (message.data.type.toString()) { case 'loadPreviewPage': - this.postMessage_(message.data); + this.pluginController_.postMessage(message.data); return true; case 'resetPrintPreviewMode': this.loadState_ = LoadState.LOADING; @@ -1067,7 +819,7 @@ this.pageIndicator_.pageLabels = message.data.pageNumbers; - this.postMessage_({ + this.pluginController_.postMessage({ type: 'resetPrintPreviewMode', url: message.data.url, grayscale: message.data.grayscale, @@ -1132,5 +884,398 @@ */ get bookmarks() { return this.bookmarks_; - } + }, + + /** + * Sets document dimensions from the current controller. + * + * @param {{height: number, width: number, pageDimensions: Array}} + * documentDimensions + */ + setDocumentDimensions: function(documentDimensions) { + this.documentDimensions_ = documentDimensions; + this.isUserInitiatedEvent_ = false; + this.viewport_.setDocumentDimensions(this.documentDimensions_); + this.isUserInitiatedEvent_ = true; + // If we received the document dimensions, the password was good so we + // can dismiss the password screen. + if (this.passwordScreen_.active) + this.passwordScreen_.close(); + + if (this.pageIndicator_) + this.pageIndicator_.initialFadeIn(); + + if (this.toolbar_) { + this.toolbar_.docLength = this.documentDimensions_.pageDimensions.length; + } + }, + + /** + * Handles a beep request from the current controller. + */ + handleBeep: function() { + // Beeps are annoying, so just track count for now. + this.beepCount_ += 1; + }, + + /** + * Handles a password request from the current controller. + */ + handlePasswordRequest: function() { + // If the password screen isn't up, put it up. Otherwise we're + // responding to an incorrect password so deny it. + if (!this.passwordScreen_.active) + this.passwordScreen_.show(); + else + this.passwordScreen_.deny(); + }, + + /** + * Handles a selected text reply from the current controller. + * @param {string} selectedText + */ + handleSelectedTextReply: function(selectedText) { + this.sendScriptingMessage_({ + type: 'getSelectedTextReply', + selectedText: selectedText, + }); + }, + + /** + * Handles a navigation request from the current controller. + * + * @param {string} url + * @param {string} disposition + */ + handleNavigate: function(url, disposition) { + // If in print preview, always open a new tab. + if (this.isPrintPreview_) { + this.navigator_.navigate( + message.data.url, Navigator.WindowOpenDisposition.NEW_BACKGROUND_TAB); + } else { + this.navigator_.navigate(url, disposition); + } + }, + + /** + * Handles a notification that print preview has loaded from the + * current controller. + */ + handlePrintPreviewLoaded: function() { + this.isPrintPreviewLoadingFinished_ = true; + this.sendDocumentLoadedMessage_(); + }, + + /** + * Sets document metadata from the current controller. + * @param {string} title + * @param {Array} bookmarks + */ + setDocumentMetadata: function(title, bookmarks) { + if (title) { + document.title = title; + } else { + document.title = getFilenameFromURL(this.originalUrl_); + } + this.bookmarks_ = bookmarks; + if (this.toolbar_) { + this.toolbar_.docTitle = document.title; + this.toolbar_.bookmarks = this.bookmarks; + } + }, + + /** + * Sets the is selecting flag from the current controller. + * @param {boolean} isSelecting + */ + setIsSelecting: function(isSelecting) { + this.viewportScroller_.setEnableScrolling(message.data.isSelecting); + }, + + /** + * Sets the form field focused flag from the current controller. + * @param {boolean} focused + */ + setIsFormFieldFocused: function(focused) { + this.isFormFieldFocused_ = focused; + }, + + /** + * Saves the current PDF document to disk. + */ + save: async function() { + const result = await this.currentController_.save(); + if (result == null) { + // The content controller handled the save internally. + return; + } + + // Make sure file extension is .pdf, avoids dangerous extensions. + let fileName = result.fileName; + if (!fileName.toLowerCase().endsWith('.pdf')) + fileName = fileName + '.pdf'; + + const a = document.createElement('a'); + a.download = fileName; + const blob = new Blob([result.dataToSave], {type: 'application/pdf'}); + a.href = URL.createObjectURL(blob); + a.click(); + URL.revokeObjectURL(a.href); + }, }; + +/** @abstract */ +class ContentController { + constructor() {} + + /** + * A callback that's called before the zoom changes. + */ + beforeZoom() {} + + /** + * A callback that's called after the zoom changes. + */ + afterZoom() {} + + /** + * Rotates the document 90 degrees in the clockwise direction. + * @abstract + */ + rotateClockwise() {} + + /** + * Rotates the document 90 degrees in the counter clockwise direction. + * @abstract + */ + rotateCounterClockwise() {} + + /** + * Triggers printing of the current document. + * @abstract + */ + print() {} + + /** + * Requests that the current document be saved. + * @return {Promise<{fileName: string, dataToSave: ArrayBuffer}} + * @abstract + */ + save() {} +} + +class PluginController extends ContentController { + /** + * @param {HTMLEmbedElement} plugin + * @param {PDFViewer} viewer + * @param {Viewport} viewport + */ + constructor(plugin, viewer, viewport) { + super(); + this.plugin_ = plugin; + this.viewer_ = viewer; + this.viewport_ = viewport; + + /** @private {!Map<string, Function>} */ + this.pendingTokens_ = new Map(); + this.plugin_.addEventListener( + 'message', e => this.handlePluginMessage_(e), false); + } + + /** + * Notify the plugin to stop reacting to scroll events while zoom is taking + * place to avoid flickering. + * @override + */ + beforeZoom() { + this.postMessage({type: 'stopScrolling'}); + + if (this.viewport_.pinchPhase == Viewport.PinchPhase.PINCH_START) { + const position = this.viewport_.position; + const zoom = this.viewport_.zoom; + const pinchPhase = this.viewport_.pinchPhase; + this.postMessage({ + type: 'viewport', + userInitiated: true, + zoom: zoom, + xOffset: position.x, + yOffset: position.y, + pinchPhase: pinchPhase + }); + } + } + + /** + * Notify the plugin of the zoom change and to continue reacting to scroll + * events. + * @override + */ + afterZoom() { + const position = this.viewport_.position; + const zoom = this.viewport_.zoom; + const pinchVector = this.viewport_.pinchPanVector || {x: 0, y: 0}; + const pinchCenter = this.viewport_.pinchCenter || {x: 0, y: 0}; + const pinchPhase = this.viewport_.pinchPhase; + + this.postMessage({ + type: 'viewport', + userInitiated: this.viewer_.isUserInitiatedEvent_, + zoom: zoom, + xOffset: position.x, + yOffset: position.y, + pinchPhase: pinchPhase, + pinchX: pinchCenter.x, + pinchY: pinchCenter.y, + pinchVectorX: pinchVector.x, + pinchVectorY: pinchVector.y + }); + } + + // TODO(dstockwell): this method should be private, add controller APIs that + // map to all of the existing usage. crbug.com/913279 + /** + * Post a message to the PPAPI plugin. Some messages will cause an async reply + * to be received through handlePluginMessage_(). + * + * @param {Object} message Message to post. + */ + postMessage(message) { + this.plugin_.postMessage(message); + } + + /** @override */ + rotateClockwise() { + this.viewer_.metrics.onRotation(); + this.viewport_.rotateClockwise(1); + this.postMessage({type: 'rotateClockwise'}); + } + + /** @override */ + rotateCounterClockwise() { + this.viewer_.metrics.onRotation(); + this.viewport_.rotateClockwise(3); + this.postMessage({type: 'rotateCounterclockwise'}); + } + + /** @override */ + print() { + this.postMessage({type: 'print'}); + } + + /** @override */ + save() { + return new Promise(resolve => { + const newToken = createToken(); + this.pendingTokens_.set(newToken, resolve); + const force = false; + this.postMessage({type: 'save', token: newToken}); + }); + } + + /** + * An event handler for handling message events received from the plugin. + * + * @param {MessageObject} message a message event. + * @private + */ + handlePluginMessage_(message) { + switch (message.data.type.toString()) { + case 'beep': + this.viewer_.handleBeep(); + break; + case 'documentDimensions': + viewer.setDocumentDimensions(message.data); + break; + case 'email': + const href = 'mailto:' + message.data.to + '?cc=' + message.data.cc + + '&bcc=' + message.data.bcc + '&subject=' + message.data.subject + + '&body=' + message.data.body; + window.location.href = href; + break; + case 'getPassword': + this.viewer_.handlePasswordRequest(); + break; + case 'getSelectedTextReply': + this.viewer_.handleSelectedTextReply(message.data.selectedText); + break; + case 'goToPage': + this.viewport_.goToPage(message.data.page); + break; + case 'loadProgress': + this.viewer_.updateProgress(message.data.progress); + break; + case 'navigate': + this.viewer_.handleNavigate(message.data.url, message.data.disposition); + break; + case 'printPreviewLoaded': + this.viewer_.handlePrintPreviewLoaded(); + break; + case 'setScrollPosition': + this.viewport_.scrollTo(/** @type {!PartialPoint} */ (message.data)); + break; + case 'scrollBy': + this.viewport_.scrollBy(/** @type {!Point} */ (message.data)); + break; + case 'cancelStreamUrl': + chrome.mimeHandlerPrivate.abortStream(); + break; + case 'metadata': + this.viewer_.setDocumentMetadata( + message.data.title, message.data.bookmarks); + break; + case 'setIsSelecting': + this.viewer_.setIsSelecting(message.data.isSelecting); + break; + case 'getNamedDestinationReply': + this.paramsParser_.onNamedDestinationReceived(message.data.pageNumber); + break; + case 'formFocusChange': + this.viewer_.setIsFormFieldFocused(message.data.focused); + break; + case 'saveData': + this.saveData_(message.data); + break; + case 'consumeSaveToken': + const resolve = this.pendingTokens_.get(message.data.token); + if (!this.pendingTokens_.delete(message.data.token)) + throw new Error('Internal error: save token not found.'); + resolve(null); + break; + } + } + + /** + * Handles the pdf file buffer received from the plugin. + * + * @param {SaveDataMessageData} messageData data of the message event. + * @private + */ + saveData_(messageData) { + if (!(loadTimeData.getBoolean('pdfFormSaveEnabled'))) + throw new Error('Internal error: save not enabled.'); + + // Verify a token that was created by this instance is included to avoid + // being spammed. + const resolve = this.pendingTokens_.get(messageData.token); + if (!this.pendingTokens_.delete(messageData.token)) + throw new Error('Internal error: save token not found, abort save.'); + + // Verify the file size and the first bytes to make sure it's a PDF. Cap at + // 100 MB. This cap should be kept in sync with and is also enforced in + // pdf/out_of_process_instance.cc. + const MIN_FILE_SIZE = '%PDF1.0'.length; + const MAX_FILE_SIZE = 100 * 1000 * 1000; + + const buffer = messageData.dataToSave; + const bufView = new Uint8Array(buffer); + if (bufView.length > MAX_FILE_SIZE) + throw new Error(`File too large to be saved: ${bufView.length} bytes.`); + if (bufView.length < MIN_FILE_SIZE || + String.fromCharCode(bufView[0], bufView[1], bufView[2], bufView[3]) != + '%PDF') { + throw new Error('Not a PDF file.'); + } + + resolve(messageData); + } +}
diff --git a/chrome/browser/resources/print_preview/print_preview_new.html b/chrome/browser/resources/print_preview/print_preview_new.html index 2917106..e85a24c1 100644 --- a/chrome/browser/resources/print_preview/print_preview_new.html +++ b/chrome/browser/resources/print_preview/print_preview_new.html
@@ -1,5 +1,5 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" $i18n{dark}> <head> <meta charset="utf-8"> <style> @@ -22,5 +22,6 @@ <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> <link rel="import" href="new/app.html"> + <link rel="import" href="chrome://resources/html/dark_mode.html"> </body> </html>
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn index 173d4320..00510f6 100644 --- a/chrome/browser/resources/settings/BUILD.gn +++ b/chrome/browser/resources/settings/BUILD.gn
@@ -70,7 +70,6 @@ "a11y_page:closure_compile", "about_page:closure_compile", "android_apps_page:closure_compile", - "animation:closure_compile", "appearance_page:closure_compile", "autofill_page:closure_compile", "basic_page:closure_compile", @@ -109,7 +108,6 @@ deps = [ ":extension_control_browser_proxy", ":find_shortcut_behavior", - ":focus_row_behavior", ":global_scroll_target_behavior", ":lifetime_browser_proxy", ":open_window_proxy", @@ -135,12 +133,6 @@ ] } -js_library("focus_row_behavior") { - deps = [ - "//ui/webui/resources/js/cr/ui:focus_row", - ] -} - js_library("global_scroll_target_behavior") { deps = [ ":route",
diff --git a/chrome/browser/resources/settings/about_page/about_page.js b/chrome/browser/resources/settings/about_page/about_page.js index 256b624..c85fa71b 100644 --- a/chrome/browser/resources/settings/about_page/about_page.js +++ b/chrome/browser/resources/settings/about_page/about_page.js
@@ -10,7 +10,12 @@ Polymer({ is: 'settings-about-page', - behaviors: [WebUIListenerBehavior, MainPageBehavior, I18nBehavior], + behaviors: [ + WebUIListenerBehavior, + settings.MainPageBehavior, + settings.RouteObserverBehavior, + I18nBehavior, + ], properties: { /** @private {?UpdateStatusChangedEvent} */ @@ -198,6 +203,20 @@ } }, + /** + * @param {!settings.Route} newRoute + * @param {settings.Route} oldRoute + */ + currentRouteChanged: function(newRoute, oldRoute) { + settings.MainPageBehavior.currentRouteChanged.call( + this, newRoute, oldRoute); + }, + + // Override settings.MainPageBehavior method. + containsRoute: function(route) { + return !route || settings.routes.ABOUT.contains(route); + }, + /** @private */ startListening_: function() { this.addWebUIListener( @@ -638,8 +657,4 @@ // </if> return this.showUpdateStatus_; }, - - focusSection: function() { - this.$$('settings-section[section="about"]').show(); - }, });
diff --git a/chrome/browser/resources/settings/animation/BUILD.gn b/chrome/browser/resources/settings/animation/BUILD.gn deleted file mode 100644 index b26ab18..0000000 --- a/chrome/browser/resources/settings/animation/BUILD.gn +++ /dev/null
@@ -1,28 +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. - -import("//third_party/closure_compiler/compile_js.gni") - -js_type_check("closure_compile") { - deps = [ - ":animation", - ":fade_animations", - ] -} - -js_library("animation") { - deps = [ - "//ui/webui/resources/js:cr", - "//ui/webui/resources/js/cr:event_target", - ] - externs_list = [ "$externs_path/web_animations.js" ] -} - -js_library("fade_animations") { - deps = [ - ":animation", - "//third_party/polymer/v1_0/components-chromium/neon-animation:neon-animation-behavior-extracted", - ] - externs_list = [ "$externs_path/web_animations.js" ] -}
diff --git a/chrome/browser/resources/settings/animation/animation.html b/chrome/browser/resources/settings/animation/animation.html deleted file mode 100644 index f35052f..0000000 --- a/chrome/browser/resources/settings/animation/animation.html +++ /dev/null
@@ -1,3 +0,0 @@ -<link rel="import" href="chrome://resources/html/cr.html"> -<link rel="import" href="chrome://resources/html/cr/event_target.html"> -<script src="animation.js"></script>
diff --git a/chrome/browser/resources/settings/animation/animation.js b/chrome/browser/resources/settings/animation/animation.js deleted file mode 100644 index cd5a8c5e..0000000 --- a/chrome/browser/resources/settings/animation/animation.js +++ /dev/null
@@ -1,89 +0,0 @@ -// Copyright 2016 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. - -/** - * @fileoverview Simplified API wrapping native Web Animations with some sugar. - * A compromise between the draft spec and Chrome's evolving support. This API - * will be changed (or removed) as Chrome support evolves. - */ -cr.define('settings.animation', function() { - 'use strict'; - - /** Default timing constants. */ - const Timing = { - DURATION: 250, - EASING: 'cubic-bezier(0.4, 0, 0.2, 1)', // Fast out, slow in. - }; - - /** - * Offers a small subset of the v1 Animation interface. The underlying - * animation can be reversed, canceled or immediately finished. - * @see https://www.w3.org/TR/web-animations-1/#animation - */ - class Animation extends cr.EventTarget { - /** - * @param {!Element} el The element to animate. - * @param {!Array<!Object>|!Object<!Array>|!Object<string>} keyframes - * Keyframes, as in Element.prototype.animate. - * @param {number|!KeyframeEffectOptions=} opt_options Duration or options - * object, as in Element.prototype.animate. - */ - constructor(el, keyframes, opt_options) { - super(); - - // Disallow direct usage of the underlying animation. - this.animation_ = el.animate(keyframes, opt_options); - - /** @type {!Promise} */ - this.finished = new Promise((resolve, reject) => { - // If we were implementing the full spec, we'd have to support - // removing or resetting these listeners. - this.animation_.addEventListener('finish', e => { - resolve(); - // According to the spec, queue a task to fire the event after - // resolving the promise. - this.queueDispatch_(e); - }); - this.animation_.addEventListener('cancel', e => { - // clang-format off - reject(new - /** - * @see https://heycam.github.io/webidl/#es-DOMException-call - * @type {function (new:DOMException, string, string)} - */( - DOMException - )('', 'AbortError')); - // clang-format on - this.queueDispatch_(e); - }); - }); - } - - finish() { - assert(this.animation_); - this.animation_.finish(); - } - - cancel() { - assert(this.animation_); - this.animation_.cancel(); - } - - /** - * @param {!Event} e - * @private - */ - queueDispatch_(e) { - setTimeout(() => { - this.dispatchEvent(e); - this.animation_ = undefined; - }); - } - } - - return { - Animation: Animation, - Timing: Timing, - }; -});
diff --git a/chrome/browser/resources/settings/animation/fade_animations.html b/chrome/browser/resources/settings/animation/fade_animations.html deleted file mode 100644 index b42fef5..0000000 --- a/chrome/browser/resources/settings/animation/fade_animations.html +++ /dev/null
@@ -1,3 +0,0 @@ -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animation-behavior.html"> -<link rel="import" href="animation.html"> -<script src="fade_animations.js"></script>
diff --git a/chrome/browser/resources/settings/animation/fade_animations.js b/chrome/browser/resources/settings/animation/fade_animations.js deleted file mode 100644 index ef5060a..0000000 --- a/chrome/browser/resources/settings/animation/fade_animations.js +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2017 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. - -/** - * @fileoverview Defines fade animations similar to Polymer's fade-in-animation - * and fade-out-animation, but with Settings-specific timings. - */ -Polymer({ - is: 'settings-fade-in-animation', - - behaviors: [Polymer.NeonAnimationBehavior], - - configure: function(config) { - const node = config.node; - this._effect = new KeyframeEffect( - node, - [ - {'opacity': '0'}, - {'opacity': '1'}, - ], - /** @type {!KeyframeEffectOptions} */ ({ - duration: settings.animation.Timing.DURATION, - easing: settings.animation.Timing.EASING, - fill: 'both', - })); - return this._effect; - } -}); - -Polymer({ - is: 'settings-fade-out-animation', - - behaviors: [Polymer.NeonAnimationBehavior], - - configure: function(config) { - const node = config.node; - this._effect = new KeyframeEffect( - node, - [ - {'opacity': '1'}, - {'opacity': '0'}, - ], - /** @type {!KeyframeEffectOptions} */ ({ - duration: settings.animation.Timing.DURATION, - easing: settings.animation.Timing.EASING, - fill: 'both', - })); - return this._effect; - } -});
diff --git a/chrome/browser/resources/settings/autofill_page/BUILD.gn b/chrome/browser/resources/settings/autofill_page/BUILD.gn index feb6b084..3a7615a 100644 --- a/chrome/browser/resources/settings/autofill_page/BUILD.gn +++ b/chrome/browser/resources/settings/autofill_page/BUILD.gn
@@ -79,8 +79,8 @@ js_library("password_list_item") { deps = [ ":show_password_behavior", - "..:focus_row_behavior", "//ui/webui/resources/js:load_time_data", + "//ui/webui/resources/js/cr/ui:focus_row_behavior", ] }
diff --git a/chrome/browser/resources/settings/autofill_page/autofill_section.html b/chrome/browser/resources/settings/autofill_page/autofill_section.html index 77e48e1fb..fa0257a 100644 --- a/chrome/browser/resources/settings/autofill_page/autofill_section.html +++ b/chrome/browser/resources/settings/autofill_page/autofill_section.html
@@ -88,9 +88,9 @@ </div> </div> <cr-action-menu id="addressSharedMenu"> - <button id="menuEditAddress" slot="item" class="dropdown-item" + <button id="menuEditAddress" class="dropdown-item" on-click="onMenuEditAddressTap_">$i18n{edit}</button> - <button id="menuRemoveAddress" slot="item" class="dropdown-item" + <button id="menuRemoveAddress" class="dropdown-item" on-click="onMenuRemoveAddressTap_">$i18n{removeAddress}</button> </cr-action-menu> <template is="dom-if" if="[[showAddressDialog_]]" restamp>
diff --git a/chrome/browser/resources/settings/autofill_page/password_list_item.html b/chrome/browser/resources/settings/autofill_page/password_list_item.html index 20a9580..d117558 100644 --- a/chrome/browser/resources/settings/autofill_page/password_list_item.html +++ b/chrome/browser/resources/settings/autofill_page/password_list_item.html
@@ -1,8 +1,8 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html"> +<link rel="import" href="chrome://resources/html/cr/ui/focus_row_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> -<link rel="import" href="../focus_row_behavior.html"> <link rel="import" href="../settings_shared_css.html"> <link rel="import" href="../site_favicon.html"> <link rel="import" href="passwords_shared_css.html">
diff --git a/chrome/browser/resources/settings/autofill_page/password_list_item.js b/chrome/browser/resources/settings/autofill_page/password_list_item.js index 0c97de35..eb7b74c0 100644 --- a/chrome/browser/resources/settings/autofill_page/password_list_item.js +++ b/chrome/browser/resources/settings/autofill_page/password_list_item.js
@@ -11,7 +11,7 @@ is: 'password-list-item', behaviors: [ - FocusRowBehavior, + cr.ui.FocusRowBehavior, ShowPasswordBehavior, ],
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_section.html b/chrome/browser/resources/settings/autofill_page/passwords_section.html index 8705de3..8e5a2d2 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_section.html +++ b/chrome/browser/resources/settings/autofill_page/passwords_section.html
@@ -122,17 +122,17 @@ </div> </div> <cr-action-menu id="menu"> - <button id="menuEditPassword" slot="item" class="dropdown-item" + <button id="menuEditPassword" class="dropdown-item" on-click="onMenuEditPasswordTap_">$i18n{passwordViewDetails}</button> - <button id="menuRemovePassword" slot="item" class="dropdown-item" + <button id="menuRemovePassword" class="dropdown-item" on-click="onMenuRemovePasswordTap_">$i18n{removePassword}</button> </cr-action-menu> <cr-action-menu id="exportImportMenu"> - <button id="menuImportPassword" slot="item" class="dropdown-item" + <button id="menuImportPassword" class="dropdown-item" on-click="onImportTap_" hidden="[[!showImportPasswords_]]"> $i18n{import} </button> - <button id="menuExportPassword" slot="item" class="dropdown-item" + <button id="menuExportPassword" class="dropdown-item" on-click="onExportTap_" hidden="[[!showExportPasswords_]]"> $i18n{exportMenuItem} </button>
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_shared_css.html b/chrome/browser/resources/settings/autofill_page/passwords_shared_css.html index 3dcec5c3..9c26b98d 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_shared_css.html +++ b/chrome/browser/resources/settings/autofill_page/passwords_shared_css.html
@@ -17,6 +17,10 @@ flex: 1; } + .website-column > a { + color: var(--google-grey-900); + } + .username-column { flex: 1; margin: 0 8px; @@ -50,7 +54,7 @@ } site-favicon { - margin-inline-end: 8px; + margin-inline-end: 16px; min-width: 16px; } </style>
diff --git a/chrome/browser/resources/settings/autofill_page/payments_section.html b/chrome/browser/resources/settings/autofill_page/payments_section.html index 2a98ce1..2b69e16 100644 --- a/chrome/browser/resources/settings/autofill_page/payments_section.html +++ b/chrome/browser/resources/settings/autofill_page/payments_section.html
@@ -75,7 +75,7 @@ prefs.autofill.credit_card_enabled.value)]]" on-click="onMigrateCreditCardsClick_" actionable> <div class="start"> - [[migrateCreditCardsLabel_]] + $i18n{migrateCreditCardsLabel} <div class="secondary"> [[migratableCreditCardsInfo_]] </div> @@ -133,12 +133,12 @@ </div> </div> <cr-action-menu id="creditCardSharedMenu"> - <button id="menuEditCreditCard" slot="item" class="dropdown-item" + <button id="menuEditCreditCard" class="dropdown-item" on-click="onMenuEditCreditCardTap_">$i18n{edit}</button> - <button id="menuRemoveCreditCard" slot="item" class="dropdown-item" + <button id="menuRemoveCreditCard" class="dropdown-item" hidden$="[[!activeCreditCard.metadata.isLocal]]" on-click="onMenuRemoveCreditCardTap_">$i18n{removeCreditCard}</button> - <button id="menuClearCreditCard" slot="item" class="dropdown-item" + <button id="menuClearCreditCard" class="dropdown-item" on-click="onMenuClearCreditCardTap_" hidden$="[[!activeCreditCard.metadata.isCached]]"> $i18n{clearCreditCard}
diff --git a/chrome/browser/resources/settings/autofill_page/payments_section.js b/chrome/browser/resources/settings/autofill_page/payments_section.js index 2166bfa9..97c08970 100644 --- a/chrome/browser/resources/settings/autofill_page/payments_section.js +++ b/chrome/browser/resources/settings/autofill_page/payments_section.js
@@ -122,9 +122,6 @@ showCreditCardDialog_: Boolean, /** @private */ - migrateCreditCardsLabel_: String, - - /** @private */ migratableCreditCardsInfo_: String, /** @@ -472,11 +469,6 @@ if (numberOfMigratableCreditCard == 0) return false; - // Update the display label depends on the number of migratable credit - // cards. - this.migrateCreditCardsLabel_ = numberOfMigratableCreditCard == 1 ? - this.i18n('migrateCreditCardsLabelSingle') : - this.i18n('migrateCreditCardsLabelMultiple'); // Update the display text depends on the number of migratable credit cards. this.migratableCreditCardsInfo_ = numberOfMigratableCreditCard == 1 ? this.i18n('migratableCardsInfoSingle') :
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.js b/chrome/browser/resources/settings/basic_page/basic_page.js index 4b593c3c..3ca50418 100644 --- a/chrome/browser/resources/settings/basic_page/basic_page.js +++ b/chrome/browser/resources/settings/basic_page/basic_page.js
@@ -9,7 +9,11 @@ Polymer({ is: 'settings-basic-page', - behaviors: [MainPageBehavior, WebUIListenerBehavior], + behaviors: [ + settings.MainPageBehavior, + settings.RouteObserverBehavior, + WebUIListenerBehavior, + ], properties: { /** Preferences state. */ @@ -132,7 +136,6 @@ }, /** - * Overrides MainPageBehaviorImpl from MainPageBehavior. * @param {!settings.Route} newRoute * @param {settings.Route} oldRoute */ @@ -151,7 +154,14 @@ assert(!this.hasExpandedSection_); } - MainPageBehaviorImpl.currentRouteChanged.call(this, newRoute, oldRoute); + settings.MainPageBehavior.currentRouteChanged.call( + this, newRoute, oldRoute); + }, + + // Override settings.MainPageBehavior method. + containsRoute: function(route) { + return !route || settings.routes.BASIC.contains(route) || + settings.routes.ADVANCED.contains(route); }, /** @@ -163,12 +173,6 @@ return visibility !== false; }, - focusSection: function() { - const section = this.getSection(settings.getCurrentRoute().section); - assert(section); - section.show(); - }, - /** * Queues a task to search the basic sections, then another for the advanced * sections.
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.html b/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.html index ec8924ff..c0fe09ce 100644 --- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.html +++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_device_list_item.html
@@ -39,11 +39,11 @@ </button> </paper-icon-button-light> <cr-action-menu id="dotsMenu"> - <button slot="item" class="dropdown-item" + <button class="dropdown-item" on-click="onConnectActionTap_"> [[getConnectActionText_(device.connected)]] </button> - <button slot="item" class="dropdown-item" on-click="onRemoveTap_"> + <button class="dropdown-item" on-click="onRemoveTap_"> $i18n{bluetoothRemove} </button> </cr-action-menu>
diff --git a/chrome/browser/resources/settings/controls/settings_slider.html b/chrome/browser/resources/settings/controls/settings_slider.html index b30ee91..76c8c6e7 100644 --- a/chrome/browser/resources/settings/controls/settings_slider.html +++ b/chrome/browser/resources/settings/controls/settings_slider.html
@@ -54,7 +54,7 @@ <div class="outer"> <cr-slider id="slider" disabled$="[[disableSlider_]]" ticks="[[ticks]]" on-value-changed="onSliderChanged_" max="[[max]]" min="[[min]]" - update-value-instantly="[[updateValueInstantly]]"> + on-dragging-changed="onSliderChanged_"> </cr-slider> <div id="labels" disabled$="[[disableSlider_]]"> <div id="label-begin">[[labelMin]]</div>
diff --git a/chrome/browser/resources/settings/controls/settings_slider.js b/chrome/browser/resources/settings/controls/settings_slider.js index 0b62ed330..f84e582e 100644 --- a/chrome/browser/resources/settings/controls/settings_slider.js +++ b/chrome/browser/resources/settings/controls/settings_slider.js
@@ -57,6 +57,7 @@ updateValueInstantly: { type: Boolean, value: true, + observer: 'onSliderChanged_', }, loaded_: Boolean, @@ -95,6 +96,10 @@ onSliderChanged_: function() { if (!this.loaded_) return; + + if (this.$.slider.dragging && !this.updateValueInstantly) + return; + const sliderValue = this.$.slider.value; let newValue; @@ -143,6 +148,9 @@ const tickValue = this.getTickValueAtIndex_(this.$.slider.value); if (this.$.slider.dragging && this.pref.value != tickValue) { + if (!this.updateValueInstantly) + return; + // The value changed outside settings-slider but we're still holding the // knob, so set the value back to where the knob was. // Async so we don't confuse Polymer's data binding.
diff --git a/chrome/browser/resources/settings/crostini_page/BUILD.gn b/chrome/browser/resources/settings/crostini_page/BUILD.gn index e031d87..42963d83 100644 --- a/chrome/browser/resources/settings/crostini_page/BUILD.gn +++ b/chrome/browser/resources/settings/crostini_page/BUILD.gn
@@ -9,6 +9,7 @@ ":crostini_browser_proxy", ":crostini_page", ":crostini_shared_paths", + ":crostini_shared_usb_devices", ":crostini_subpage", ] } @@ -37,6 +38,14 @@ ] } +js_library("crostini_shared_usb_devices") { + deps = [ + ":crostini_browser_proxy", + "..:route", + "../prefs:prefs_behavior", + ] +} + js_library("crostini_subpage") { deps = [ ":crostini_browser_proxy",
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_page.html b/chrome/browser/resources/settings/crostini_page/crostini_page.html index ce4edcb..32c230c5 100644 --- a/chrome/browser/resources/settings/crostini_page/crostini_page.html +++ b/chrome/browser/resources/settings/crostini_page/crostini_page.html
@@ -12,6 +12,7 @@ <link rel="import" href="crostini_browser_proxy.html"> <link rel="import" href="crostini_subpage.html"> <link rel="import" href="crostini_shared_paths.html"> +<link rel="import" href="crostini_shared_usb_devices.html"> <dom-module id="settings-crostini-page"> <template> @@ -70,6 +71,18 @@ </settings-crostini-shared-paths> </settings-subpage> </template> + + <template is="dom-if" route-path="/crostini/sharedUsbDevices"> + <settings-subpage + associated-control="[[$$('#crostini')]]" + page-title="$i18n{crostiniSharedUsbDevicesLabel}"> + <div class="settings-box first"> + <div class="label">$i18n{crostiniSharedUsbDevicesDescription}</div> + </div> + <settings-crostini-shared-usb-devices prefs="{{prefs}}"> + </settings-crostini-shared-usb-devices> + </settings-subpage> + </template> </settings-animated-pages> </template>
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_page.js b/chrome/browser/resources/settings/crostini_page/crostini_page.js index 4b5dec45..b91bb3d3 100644 --- a/chrome/browser/resources/settings/crostini_page/crostini_page.js +++ b/chrome/browser/resources/settings/crostini_page/crostini_page.js
@@ -36,6 +36,11 @@ settings.routes.CROSTINI_SHARED_PATHS.path, '#crostini .subpage-arrow button'); } + if (settings.routes.CROSTINI_SHARED_USB_DEVICES) { + map.set( + settings.routes.CROSTINI_SHARED_USB_DEVICES.path, + '#crostini .subpage-arrow button'); + } return map; }, },
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_shared_usb_devices.html b/chrome/browser/resources/settings/crostini_page/crostini_shared_usb_devices.html new file mode 100644 index 0000000..5fc76f6 --- /dev/null +++ b/chrome/browser/resources/settings/crostini_page/crostini_shared_usb_devices.html
@@ -0,0 +1,27 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="../prefs/prefs_behavior.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> +<link rel="import" href="../settings_shared_css.html"> + +<dom-module id="settings-crostini-shared-usb-devices"> + <template> + <style include="settings-shared"></style> + <style> + .toggle-container { + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: space-between; + } + </style> + <template is="dom-repeat" + items="{{prefs.crostini.shared_usb_devices.value}}" as="usb"> + <div class="toggle-container settings-box"> + <div class="label">[[usb.name]]</div> + <cr-toggle class="toggle" checked="{{usb.shared}}"></cr-toggle> + </div> + </template> + </template> + <script src="crostini_shared_usb_devices.js"></script> +</dom-module>
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_shared_usb_devices.js b/chrome/browser/resources/settings/crostini_page/crostini_shared_usb_devices.js new file mode 100644 index 0000000..02951ec --- /dev/null +++ b/chrome/browser/resources/settings/crostini_page/crostini_shared_usb_devices.js
@@ -0,0 +1,23 @@ +// 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. + +/** + * @fileoverview + * 'crostini-shared-usb-devices' is the settings shared usb devices subpage for + * Crostini. + */ + +Polymer({ + is: 'settings-crostini-shared-usb-devices', + + behaviors: [PrefsBehavior], + + properties: { + /** Preferences state. */ + prefs: { + type: Object, + notify: true, + }, + }, +});
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_subpage.html b/chrome/browser/resources/settings/crostini_page/crostini_subpage.html index 7c0d74b..f6fc52b 100644 --- a/chrome/browser/resources/settings/crostini_page/crostini_subpage.html +++ b/chrome/browser/resources/settings/crostini_page/crostini_subpage.html
@@ -2,6 +2,7 @@ <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="crostini_browser_proxy.html"> <link rel="import" href="../i18n_setup.html"> <link rel="import" href="../prefs/prefs_behavior.html"> @@ -10,14 +11,23 @@ <dom-module id="settings-crostini-subpage"> <template> <style include="settings-shared"></style> - <div id="crostini-shared-paths" class="settings-box" + <div id="crostini-shared-paths" class="settings-box first" actionable on-click="onSharedPathsTap_"> <div class="start">$i18n{crostiniSharedPaths}</div> <paper-icon-button-light class="subpage-arrow"> <button aria-label="$i18n{crostiniSharedPaths}"></button> </paper-icon-button-light> </div> - <div id="remove" class="settings-box first" + <template is="dom-if" if="[[enableCrostiniUsbDeviceSupport_]]"> + <div id="crostini-shared-usb-devices" class="settings-box" + actionable on-click="onSharedUsbDevicesTap_"> + <div class="start">$i18n{crostiniSharedUsbDevicesLabel}</div> + <paper-icon-button-light class="subpage-arrow"> + <button aria-label="$i18n{crostiniSharedUsbDevicesLabel}"></button> + </paper-icon-button-light> + </div> + </template> + <div id="remove" class="settings-box" actionable on-click="onRemoveTap_"> <div class="start">$i18n{crostiniRemove}</div> <paper-icon-button-light class="subpage-arrow">
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_subpage.js b/chrome/browser/resources/settings/crostini_page/crostini_subpage.js index e16d7b62d..7d8ac3c 100644 --- a/chrome/browser/resources/settings/crostini_page/crostini_subpage.js +++ b/chrome/browser/resources/settings/crostini_page/crostini_subpage.js
@@ -18,6 +18,18 @@ type: Object, notify: true, }, + + /** + * Whether CrostiniUsbSupport flag is enabled. + * @private {boolean} + */ + enableCrostiniUsbDeviceSupport_: { + type: Boolean, + value: function() { + return loadTimeData.getBoolean('enableCrostiniUsbDeviceSupport'); + }, + }, + }, observers: ['onCrostiniEnabledChanged_(prefs.crostini.enabled.value)'], @@ -43,4 +55,9 @@ onSharedPathsTap_: function(event) { settings.navigateTo(settings.routes.CROSTINI_SHARED_PATHS); }, + + /** @private */ + onSharedUsbDevicesTap_: function(event) { + settings.navigateTo(settings.routes.CROSTINI_SHARED_USB_DEVICES); + }, });
diff --git a/chrome/browser/resources/settings/focus_row_behavior.html b/chrome/browser/resources/settings/focus_row_behavior.html deleted file mode 100644 index 3ccc883..0000000 --- a/chrome/browser/resources/settings/focus_row_behavior.html +++ /dev/null
@@ -1,2 +0,0 @@ -<link rel="import" href="chrome://resources/html/cr/ui/focus_row.html"> -<script src="focus_row_behavior.js"></script>
diff --git a/chrome/browser/resources/settings/focus_row_behavior.js b/chrome/browser/resources/settings/focus_row_behavior.js deleted file mode 100644 index 5593e53d..0000000 --- a/chrome/browser/resources/settings/focus_row_behavior.js +++ /dev/null
@@ -1,284 +0,0 @@ -// Copyright 2017 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. - -/** @implements {cr.ui.FocusRowDelegate} */ -class FocusRowDelegate { - /** @param {{lastFocused: Object}} listItem */ - constructor(listItem) { - /** @private */ - this.listItem_ = listItem; - } - - /** - * This function gets called when the [focus-row-control] element receives - * the focus event. - * @override - * @param {!cr.ui.FocusRow} row - * @param {!Event} e - */ - onFocus(row, e) { - this.listItem_.lastFocused = e.path[0]; - } - - /** - * @override - * @param {!cr.ui.FocusRow} row The row that detected a keydown. - * @param {!Event} e - * @return {boolean} Whether the event was handled. - */ - onKeydown(row, e) { - // Prevent iron-list from changing the focus on enter. - if (e.key == 'Enter') - e.stopPropagation(); - - return false; - } -} - -/** @extends {cr.ui.FocusRow} */ -class VirtualFocusRow extends cr.ui.FocusRow { - /** - * @param {!Element} root - * @param {cr.ui.FocusRowDelegate} delegate - */ - constructor(root, delegate) { - super(root, /* boundary */ null, delegate); - } -} - -/** - * Any element that is being used as an iron-list row item can extend this - * behavior, which encapsulates focus controls of mouse and keyboards. - * To use this behavior: - * - The parent element should pass a "last-focused" attribute double-bound - * to the row items, to track the last-focused element across rows, and - * a "list-blurred" attribute double-bound to the row items, to track - * whether the list of row items has been blurred. - * - There must be a container in the extending element with the - * [focus-row-container] attribute that contains all focusable controls. - * - On each of the focusable controls, there must be a [focus-row-control] - * attribute, and a [focus-type=] attribute unique for each control. - * - * @polymerBehavior - */ -const FocusRowBehavior = { - properties: { - /** @private {VirtualFocusRow} */ - row_: Object, - - /** @private {boolean} */ - mouseFocused_: Boolean, - - /** @type {Element} */ - lastFocused: { - type: Object, - notify: true, - }, - - /** - * This is different from tabIndex, since the template only does a one-way - * binding on both attributes, and the behavior actually make use of this - * fact. For example, when a control within a row is focused, it will have - * tabIndex = -1 and ironListTabIndex = 0. - * @type {number} - */ - ironListTabIndex: { - type: Number, - observer: 'ironListTabIndexChanged_', - }, - - listBlurred: { - type: Boolean, - notify: true, - }, - }, - - /** @private {?Element} */ - firstControl_: null, - - /** @private {!Array<!MutationObserver>} */ - controlObservers_: [], - - /** @override */ - attached: function() { - this.classList.add('no-outline'); - - Polymer.RenderStatus.afterNextRender(this, function() { - const rowContainer = this.root.querySelector('[focus-row-container]'); - assert(!!rowContainer); - this.row_ = new VirtualFocusRow(rowContainer, new FocusRowDelegate(this)); - this.ironListTabIndexChanged_(); - this.addItems_(); - - // Adding listeners asynchronously to reduce blocking time, since this - // behavior will be used by items in potentially long lists. - this.listen(this, 'focus', 'onFocus_'); - this.listen(this, 'dom-change', 'addItems_'); - this.listen(this, 'mousedown', 'onMouseDown_'); - this.listen(this, 'blur', 'onBlur_'); - }); - }, - - /** @override */ - detached: function() { - this.unlisten(this, 'focus', 'onFocus_'); - this.unlisten(this, 'dom-change', 'addItems_'); - this.unlisten(this, 'mousedown', 'onMouseDown_'); - this.unlisten(this, 'blur', 'onBlur_'); - this.removeObservers_(); - if (this.row_) - this.row_.destroy(); - }, - - /** @private */ - updateFirstControl_: function() { - const newFirstControl = this.row_.getFirstFocusable(); - if (newFirstControl === this.firstControl_) - return; - - if (this.firstControl_) - this.unlisten(this.firstControl_, 'keydown', 'onFirstControlKeydown_'); - this.firstControl_ = newFirstControl; - if (this.firstControl_) { - this.listen( - /** @type {!Element} */ (this.firstControl_), 'keydown', - 'onFirstControlKeydown_'); - } - }, - - /** @private */ - removeObservers_: function() { - if (this.firstControl_) - this.unlisten(this.firstControl_, 'keydown', 'onFirstControlKeydown_'); - if (this.controlObservers_.length > 0) - this.controlObservers_.forEach(observer => { - observer.disconnect(); - }); - this.controlObservers_ = []; - }, - - /** @private */ - addItems_: function() { - if (this.row_) { - this.removeObservers_(); - this.row_.destroy(); - - const controls = this.root.querySelectorAll('[focus-row-control]'); - - controls.forEach(control => { - this.row_.addItem( - control.getAttribute('focus-type'), - /** @type {!HTMLElement} */ - (cr.ui.FocusRow.getFocusableElement(control))); - this.addMutationObservers_(assert(control)); - }); - this.updateFirstControl_(); - } - }, - - /** - * @return {!MutationObserver} - * @private - */ - createObserver_: function() { - return new MutationObserver(mutations => { - const mutation = mutations[0]; - if (mutation.attributeName === 'style' && mutation.oldValue) { - const newStyle = - window.getComputedStyle(/** @type {!Element} */ (mutation.target)); - const oldDisplayValue = mutation.oldValue.match(/^display:(.*)(?=;)/); - const oldVisibilityValue = - mutation.oldValue.match(/^visibility:(.*)(?=;)/); - // Return early if display and visibility have not changed. - if (oldDisplayValue && newStyle.display === oldDisplayValue[1].trim() && - oldVisibilityValue && - newStyle.visibility === oldVisibilityValue[1].trim()) { - return; - } - } - this.updateFirstControl_(); - }); - }, - - /** - * The first focusable control changes if hidden, disabled, or style.display - * changes for the control or any of its ancestors. Add mutation observers to - * watch for these changes in order to ensure the first control keydown - * listener is always on the correct element. - * @param {!Element} control - * @private - */ - addMutationObservers_: function(control) { - let current = control; - while (current && current != this.root) { - const currentObserver = this.createObserver_(); - currentObserver.observe(current, { - attributes: true, - attributeFilter: ['hidden', 'disabled', 'style'], - attributeOldValue: true, - }); - this.controlObservers_.push(currentObserver); - current = current.parentNode; - } - }, - - /** - * This function gets called when the row itself receives the focus event. - * @param {!Event} e The focus event - * @private - */ - onFocus_: function(e) { - if (this.mouseFocused_) { - this.mouseFocused_ = false; // Consume and reset flag. - return; - } - - // If focus is being restored from outside the item and the event is fired - // by the list item itself, focus the first control so that the user can tab - // through all the controls. When the user shift-tabs back to the row, or - // focus is restored to the row from a dropdown on the last item, the last - // child item will be focused before the row itself. Since this is the - // desired behavior, do not shift focus to the first item in these cases. - const restoreFocusToFirst = - this.listBlurred && e.composedPath()[0] === this; - - if (this.lastFocused && !restoreFocusToFirst) { - this.row_.getEquivalentElement(this.lastFocused).focus(); - } else { - const firstFocusable = assert(this.firstControl_); - firstFocusable.focus(); - } - this.listBlurred = false; - }, - - /** @param {!KeyboardEvent} e */ - onFirstControlKeydown_: function(e) { - if (e.shiftKey && e.key === 'Tab') - this.focus(); - }, - - /** @private */ - ironListTabIndexChanged_: function() { - if (this.row_) - this.row_.makeActive(this.ironListTabIndex == 0); - }, - - /** @private */ - onMouseDown_: function() { - this.mouseFocused_ = true; // Set flag to not do any control-focusing. - }, - - /** - * @param {!Event} e - * @private - */ - onBlur_: function(e) { - this.mouseFocused_ = false; // Reset flag since it's not active anymore. - - const node = - e.relatedTarget ? /** @type {!Node} */ (e.relatedTarget) : null; - if (!this.parentNode.contains(node)) - this.listBlurred = true; - }, -};
diff --git a/chrome/browser/resources/settings/internet_page/internet_known_networks_page.html b/chrome/browser/resources/settings/internet_page/internet_known_networks_page.html index 82af6ee..a49f2ce 100644 --- a/chrome/browser/resources/settings/internet_page/internet_known_networks_page.html +++ b/chrome/browser/resources/settings/internet_page/internet_known_networks_page.html
@@ -85,15 +85,15 @@ </div> <cr-action-menu id="dotsMenu"> - <button slot="item" class="dropdown-item" hidden="[[!showAddPreferred_]]" + <button class="dropdown-item" hidden="[[!showAddPreferred_]]" on-click="onAddPreferredTap_"> $i18n{knownNetworksMenuAddPreferred} </button> - <button slot="item" class="dropdown-item" + <button class="dropdown-item" hidden="[[!showRemovePreferred_]]" on-click="onRemovePreferredTap_"> $i18n{knownNetworksMenuRemovePreferred} </button> - <button slot="item" class="dropdown-item" disabled="[[!enableForget_]]" + <button class="dropdown-item" disabled="[[!enableForget_]]" on-click="onForgetTap_"> $i18n{knownNetworksMenuForget} </button>
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.html b/chrome/browser/resources/settings/languages_page/languages_page.html index 948ac4ecd1..bada7752 100644 --- a/chrome/browser/resources/settings/languages_page/languages_page.html +++ b/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -324,7 +324,7 @@ <cr-action-menu class$="[[getMenuClass_(prefs.translate.enabled.value)]]"> <if expr="chromeos or is_win"> - <cr-checkbox id="uiLanguageItem" slot="item" + <cr-checkbox id="uiLanguageItem" class="dropdown-item" checked="[[isProspectiveUILanguage_( detailLanguage_.language.code, @@ -338,7 +338,7 @@ </iron-icon> </cr-checkbox> </if> - <cr-checkbox id="offerTranslations" slot="item" + <cr-checkbox id="offerTranslations" class="dropdown-item" checked="[[detailLanguage_.translateEnabled]]" on-change="onTranslateCheckboxChange_" @@ -347,26 +347,26 @@ detailLanguage_.language, languages.translateTarget)]]"> $i18n{offerToTranslateInThisLanguage} </cr-checkbox> - <hr slot="item"> - <button slot="item" class="dropdown-item" role="menuitem" + <hr> + <button class="dropdown-item" role="menuitem" on-click="onMoveToTopTap_" hidden="[[isNthLanguage_( 0, detailLanguage_, languages.enabled.*)]]"> $i18n{moveToTop} </button> - <button slot="item" class="dropdown-item" role="menuitem" + <button class="dropdown-item" role="menuitem" on-click="onMoveUpTap_" hidden="[[!showMoveUp_(detailLanguage_, languages.enabled.*)]]"> $i18n{moveUp} </button> - <button slot="item" class="dropdown-item" role="menuitem" + <button class="dropdown-item" role="menuitem" on-click="onMoveDownTap_" hidden="[[!showMoveDown_( detailLanguage_, languages.enabled.*)]]"> $i18n{moveDown} </button> - <button slot="item" class="dropdown-item" role="menuitem" + <button class="dropdown-item" role="menuitem" on-click="onRemoveLanguageTap_" hidden="[[!detailLanguage_.removable]]"> $i18n{removeLanguage}
diff --git a/chrome/browser/resources/settings/on_startup_page/BUILD.gn b/chrome/browser/resources/settings/on_startup_page/BUILD.gn index 60ffd9a..7f02756 100644 --- a/chrome/browser/resources/settings/on_startup_page/BUILD.gn +++ b/chrome/browser/resources/settings/on_startup_page/BUILD.gn
@@ -52,10 +52,10 @@ js_library("startup_url_entry") { deps = [ ":startup_urls_page_browser_proxy", - "..:focus_row_behavior", "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu", "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render", "//ui/webui/resources/js:cr", "//ui/webui/resources/js:icon", + "//ui/webui/resources/js/cr/ui:focus_row_behavior", ] }
diff --git a/chrome/browser/resources/settings/on_startup_page/startup_url_entry.html b/chrome/browser/resources/settings/on_startup_page/startup_url_entry.html index 02b1ccc2..f7e8b86 100644 --- a/chrome/browser/resources/settings/on_startup_page/startup_url_entry.html +++ b/chrome/browser/resources/settings/on_startup_page/startup_url_entry.html
@@ -2,10 +2,10 @@ <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html"> <link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html"> +<link rel="import" href="chrome://resources/html/cr/ui/focus_row_behavior.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="startup_urls_page_browser_proxy.html"> -<link rel="import" href="../focus_row_behavior.html"> <link rel="import" href="../settings_shared_css.html"> <link rel="import" href="../site_favicon.html"> @@ -31,10 +31,10 @@ <cr-lazy-render id="menu"> <template> <cr-action-menu> - <button slot="item" class="dropdown-item" on-click="onEditTap_"> + <button class="dropdown-item" on-click="onEditTap_"> $i18n{edit} </button> - <button slot="item" class="dropdown-item" id="remove" + <button class="dropdown-item" id="remove" on-click="onRemoveTap_"> $i18n{onStartupRemove} </button>
diff --git a/chrome/browser/resources/settings/on_startup_page/startup_url_entry.js b/chrome/browser/resources/settings/on_startup_page/startup_url_entry.js index f4ea18d1..c3c9e3d 100644 --- a/chrome/browser/resources/settings/on_startup_page/startup_url_entry.js +++ b/chrome/browser/resources/settings/on_startup_page/startup_url_entry.js
@@ -20,7 +20,7 @@ Polymer({ is: 'settings-startup-url-entry', - behaviors: [FocusRowBehavior], + behaviors: [cr.ui.FocusRowBehavior], properties: { editable: {
diff --git a/chrome/browser/resources/settings/people_page/account_manager.html b/chrome/browser/resources/settings/people_page/account_manager.html index f910659..5d56124 100644 --- a/chrome/browser/resources/settings/people_page/account_manager.html +++ b/chrome/browser/resources/settings/people_page/account_manager.html
@@ -62,7 +62,7 @@ <div class="clear settings-box"></div> <cr-action-menu> - <button slot="item" class="dropdown-item" + <button class="dropdown-item" on-click="onRemoveAccountTap_"> $i18n{removeAccountLabel} </button>
diff --git a/chrome/browser/resources/settings/people_page/sync_account_control.html b/chrome/browser/resources/settings/people_page/sync_account_control.html index 74dce2d..2323420 100644 --- a/chrome/browser/resources/settings/people_page/sync_account_control.html +++ b/chrome/browser/resources/settings/people_page/sync_account_control.html
@@ -211,19 +211,19 @@ <template is="dom-if" if="[[!syncStatus.signedIn]]" restamp> <cr-action-menu id="menu" auto-reposition> <template is="dom-repeat" items="[[storedAccounts_]]"> - <button class="dropdown-item" on-click="onAccountTap_" slot="item"> + <button class="dropdown-item" on-click="onAccountTap_"> <img class="account-icon small" alt="" src="[[getAccountImageSrc_(item.avatarImage)]]"> <span>[[item.email]]</span> </button> </template> - <button class="dropdown-item" on-click="onSigninTap_" slot="item" + <button class="dropdown-item" on-click="onSigninTap_" disabled="[[syncStatus.setupInProgress]]" id="sign-in-item"> <img class="account-icon small" alt="" src="chrome://theme/IDR_PROFILE_AVATAR_PLACEHOLDER_LARGE"> <span>$i18n{useAnotherAccount}</span> </button> - <button class="dropdown-item" on-click="onSignoutTap_" slot="item" + <button class="dropdown-item" on-click="onSignoutTap_" disabled="[[syncStatus.setupInProgress]]" id="sign-out-item"> <iron-icon icon="settings:exit-to-app"></iron-icon> <span>$i18n{peopleSignOut}</span>
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html index 5ec5906..e510860 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.html +++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -3,13 +3,11 @@ <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/html/util.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> -<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html"> <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html"> <link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html"> <link rel="import" href="chrome://resources/cr_elements/cr_radio_button/cr_radio_button.html"> <link rel="import" href="chrome://resources/cr_elements/cr_radio_group/cr_radio_group.html"> <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> @@ -27,8 +25,8 @@ <dom-module id="settings-sync-page"> <template> <style include="settings-shared iron-flex"> - #sync-section-toggle:not([actionable]) { - opacity: var(--cr-disabled-opacity); + h2 { + font-size: var(--cr-title-text_-_font-size); } #create-password-box { @@ -151,22 +149,11 @@ </div> </template> - <div class="settings-box two-line" id="sync-section-toggle" - actionable$="[[!syncSectionDisabled_]]" - on-click="toggleExpandButton_" - hidden="[[!shouldShowSyncControls_(unifiedConsentEnabled, - syncStatus.disabled)]]"> - <div class="start"> - <div>$i18n{sync}</div> - <div class="secondary">$i18n{syncDescription}</div> - </div> - <cr-expand-button expanded="{{syncSectionOpened_}}" - disabled$="[[syncSectionDisabled_]]" alt="$i18n{syncExpandA11yLabel}"> - </cr-expand-button> + <div class="settings-box first" hidden="[[!unifiedConsentEnabled]]"> + <h2 class="start">$i18n{sync}</h2> </div> - <iron-collapse id="sync-section" opened="[[syncSectionOpened_]]" - hidden="[[syncSectionDisabled_]]"> + <div id="sync-section" hidden="[[syncSectionDisabled_]]"> <div id="[[pages_.SPINNER]]" class="settings-box first" hidden$="[[!isStatus_(pages_.SPINNER, pageStatus_)]]"> $i18n{syncLoading} @@ -467,27 +454,15 @@ </div> </div> - </iron-collapse> + </div> <template is="dom-if" if="[[unifiedConsentEnabled]]"> - <div class="settings-box two-line" id="personalize-section-toggle" - actionable on-click="toggleExpandButton_"> - <div class="start"> - <div>$i18n{nonPersonalizedServicesSectionLabel}</div> - <div class="secondary"> - $i18n{nonPersonalizedServicesSectionDesc} - </div> - </div> - <cr-expand-button expanded="{{personalizeSectionOpened_}}" - alt="$i18n{nonPersonalizedServicesExpandA11yLabel}"> - </cr-expand-button> + <div class="settings-box first"> + <h2>$i18n{nonPersonalizedServicesSectionLabel}</h2> </div> - <iron-collapse id="personalize-section" - opened="[[personalizeSectionOpened_]]"> - <settings-personalization-options class="list-frame" prefs="{{prefs}}" - page-visibility="[[pageVisibility]]" - unified-consent-enabled="[[unifiedConsentEnabled]]" - </settings-personalization-options> - </iron-collapse> + <settings-personalization-options class="list-frame" prefs="{{prefs}}" + page-visibility="[[pageVisibility]]" + unified-consent-enabled="[[unifiedConsentEnabled]]"> + </settings-personalization-options> </template> <if expr="not chromeos">
diff --git a/chrome/browser/resources/settings/people_page/sync_page.js b/chrome/browser/resources/settings/people_page/sync_page.js index 69e5698..0822a2da 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.js +++ b/chrome/browser/resources/settings/people_page/sync_page.js
@@ -142,19 +142,6 @@ computed: 'computeSyncSectionDisabled_(' + 'unifiedConsentEnabled, syncStatus.signedIn, syncStatus.disabled, ' + 'syncStatus.hasError, syncStatus.statusAction)', - observer: 'onSyncSectionDisabledChanged_', - }, - - /** @private */ - personalizeSectionOpened_: { - type: Boolean, - value: true, - }, - - /** @private */ - syncSectionOpened_: { - type: Boolean, - value: true, }, /** @private */ @@ -564,31 +551,6 @@ settings.navigateTo(settings.routes.BASIC); }, - /** @private */ - onSyncSectionDisabledChanged_: function() { - this.syncSectionOpened_ = !this.syncSectionDisabled_; - }, - - /** - * Toggles the expand button within the element being listened to. - * @param {!Event} e - * @private - */ - toggleExpandButton_: function(e) { - // The expand button handles toggling itself. - const expandButtonTag = 'CR-EXPAND-BUTTON'; - if (e.target.tagName == expandButtonTag) - return; - - if (!e.currentTarget.hasAttribute('actionable')) - return; - - /** @type {!CrExpandButtonElement} */ - const expandButton = e.currentTarget.querySelector(expandButtonTag); - assert(expandButton); - expandButton.expanded = !expandButton.expanded; - }, - /** * When unified-consent enabled, the non-toggle items on the bottom of sync * section should be wrapped with 'list-frame' in order to be indented @@ -649,15 +611,6 @@ return !this.unifiedConsentEnabled && this.syncPrefs !== undefined && !!this.syncPrefs.passphraseRequired; }, - - /** - * @return {boolean} - * @private - */ - shouldShowSyncControls_: function() { - return !!this.unifiedConsentEnabled && this.syncStatus !== undefined && - !this.syncStatus.disabled; - }, }); })();
diff --git a/chrome/browser/resources/settings/printing_page/cups_printers_list.html b/chrome/browser/resources/settings/printing_page/cups_printers_list.html index 602b2917..d303fa05 100644 --- a/chrome/browser/resources/settings/printing_page/cups_printers_list.html +++ b/chrome/browser/resources/settings/printing_page/cups_printers_list.html
@@ -15,10 +15,10 @@ </style> <cr-action-menu> - <button slot="item" class="dropdown-item" on-click="onEditTap_"> + <button class="dropdown-item" on-click="onEditTap_"> $i18n{editPrinter} </button> - <button slot="item" class="dropdown-item" on-click="onRemoveTap_"> + <button class="dropdown-item" on-click="onRemoveTap_"> $i18n{removePrinter} </button> </cr-action-menu>
diff --git a/chrome/browser/resources/settings/route.js b/chrome/browser/resources/settings/route.js index a063a7c6..df4e50f 100644 --- a/chrome/browser/resources/settings/route.js +++ b/chrome/browser/resources/settings/route.js
@@ -17,6 +17,7 @@ * CROSTINI: (undefined|!settings.Route), * CROSTINI_DETAILS: (undefined|!settings.Route), * CROSTINI_SHARED_PATHS: (undefined|!settings.Route), + * CROSTINI_SHARED_USB_DEVICES: (undefined|!settings.Route), * APPEARANCE: (undefined|!settings.Route), * AUTOFILL: (undefined|!settings.Route), * BASIC: (undefined|!settings.Route), @@ -270,6 +271,8 @@ r.CROSTINI = r.BASIC.createSection('/crostini', 'crostini'); r.CROSTINI_DETAILS = r.CROSTINI.createChild('/crostini/details'); r.CROSTINI_SHARED_PATHS = r.CROSTINI.createChild('/crostini/sharedPaths'); + r.CROSTINI_SHARED_USB_DEVICES = + r.CROSTINI.createChild('/crostini/sharedUsbDevices'); } // </if>
diff --git a/chrome/browser/resources/settings/search_engines_page/BUILD.gn b/chrome/browser/resources/settings/search_engines_page/BUILD.gn index 1a6231d..62369124 100644 --- a/chrome/browser/resources/settings/search_engines_page/BUILD.gn +++ b/chrome/browser/resources/settings/search_engines_page/BUILD.gn
@@ -27,11 +27,11 @@ js_library("search_engine_entry") { deps = [ ":search_engines_browser_proxy", - "..:focus_row_behavior", "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:cr", "//ui/webui/resources/js:icon", + "//ui/webui/resources/js/cr/ui:focus_row_behavior", "//ui/webui/resources/js/cr/ui:focus_without_ink", ] } @@ -40,11 +40,11 @@ deps = [ ":search_engines_browser_proxy", "..:extension_control_browser_proxy", - "..:focus_row_behavior", "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:cr", "//ui/webui/resources/js:icon", + "//ui/webui/resources/js/cr/ui:focus_row_behavior", ] }
diff --git a/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.html b/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.html index 13113c7..f3a4f14 100644 --- a/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.html +++ b/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.html
@@ -2,9 +2,9 @@ <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> +<link rel="import" href="chrome://resources/html/cr/ui/focus_row_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="../extension_control_browser_proxy.html"> -<link rel="import" href="../focus_row_behavior.html"> <link rel="import" href="search_engine_entry_css.html"> <link rel="import" href="../settings_shared_css.html"> <link rel="import" href="../site_favicon.html"> @@ -35,11 +35,11 @@ </button> </paper-icon-button-light> <cr-action-menu> - <button slot="item" class="dropdown-item" on-click="onManageTap_" + <button class="dropdown-item" on-click="onManageTap_" id="manage"> $i18n{searchEnginesManageExtension} </button> - <button slot="item" class="dropdown-item" on-click="onDisableTap_" + <button class="dropdown-item" on-click="onDisableTap_" id="disable"> $i18n{disable} </button>
diff --git a/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.js b/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.js index 865ac581..08fbda7 100644 --- a/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.js +++ b/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.js
@@ -14,7 +14,7 @@ engine: Object, }, - behaviors: [FocusRowBehavior], + behaviors: [cr.ui.FocusRowBehavior], /** @private {?settings.ExtensionControlBrowserProxy} */ browserProxy_: null,
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engine_entry.html b/chrome/browser/resources/settings/search_engines_page/search_engine_entry.html index 951befd1..3dba8205 100644 --- a/chrome/browser/resources/settings/search_engines_page/search_engine_entry.html +++ b/chrome/browser/resources/settings/search_engines_page/search_engine_entry.html
@@ -3,10 +3,10 @@ <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/html/assert.html"> +<link rel="import" href="chrome://resources/html/cr/ui/focus_row_behavior.html"> <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="../controls/extension_controlled_indicator.html"> -<link rel="import" href="../focus_row_behavior.html"> <link rel="import" href="search_engine_entry_css.html"> <link rel="import" href="search_engines_browser_proxy.html"> <link rel="import" href="../settings_shared_css.html"> @@ -52,15 +52,15 @@ </button> </paper-icon-button-light> <cr-action-menu> - <button slot="item" class="dropdown-item" on-click="onMakeDefaultTap_" + <button class="dropdown-item" on-click="onMakeDefaultTap_" hidden$="[[!engine.canBeDefault]]" id="makeDefault"> $i18n{searchEnginesMakeDefault} </button> - <button slot="item" class="dropdown-item" on-click="onEditTap_" + <button class="dropdown-item" on-click="onEditTap_" hidden$="[[!engine.canBeEdited]]" id="edit"> $i18n{edit} </button> - <button slot="item" class="dropdown-item" on-click="onDeleteTap_" + <button class="dropdown-item" on-click="onDeleteTap_" hidden$="[[!engine.canBeRemoved]]" id="delete"> $i18n{searchEnginesRemoveFromList} </button>
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engine_entry.js b/chrome/browser/resources/settings/search_engines_page/search_engine_entry.js index d9bba763..22bc07bd 100644 --- a/chrome/browser/resources/settings/search_engines_page/search_engine_entry.js +++ b/chrome/browser/resources/settings/search_engines_page/search_engine_entry.js
@@ -9,7 +9,7 @@ Polymer({ is: 'settings-search-engine-entry', - behaviors: [FocusRowBehavior], + behaviors: [cr.ui.FocusRowBehavior], properties: { /** @type {!SearchEngine} */
diff --git a/chrome/browser/resources/settings/settings.html b/chrome/browser/resources/settings/settings.html index 40207595..a3ac40fe4 100644 --- a/chrome/browser/resources/settings/settings.html +++ b/chrome/browser/resources/settings/settings.html
@@ -1,5 +1,6 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading" + $i18n{dark}> <head> <meta charset="utf-8"> <title>$i18n{settings}</title> @@ -26,5 +27,6 @@ <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="settings_ui/settings_ui.html"> + <link rel="import" href="chrome://resources/html/dark_mode.html"> </body> </html>
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.html b/chrome/browser/resources/settings/settings_main/settings_main.html index 095b6eec..aa5cb321 100644 --- a/chrome/browser/resources/settings/settings_main/settings_main.html +++ b/chrome/browser/resources/settings/settings_main/settings_main.html
@@ -47,7 +47,9 @@ show-crostini="[[showCrostini]]" show-multidevice="[[showMultidevice]]" have-play-store-app="[[havePlayStoreApp]]" - on-subpage-expand="onSubpageExpand_" + on-showing-section="onShowingSection_" + on-subpage-expand="onShowingSubpage_" + on-showing-main-page="onShowingMainPage_" in-search-mode="[[inSearchMode_]]" advanced-toggle-expanded="{{advancedToggleExpanded}}"> </settings-basic-page>
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.js b/chrome/browser/resources/settings/settings_main/settings_main.js index 7a375bc..cea0a69 100644 --- a/chrome/browser/resources/settings/settings_main/settings_main.js +++ b/chrome/browser/resources/settings/settings_main/settings_main.js
@@ -83,23 +83,6 @@ havePlayStoreApp: Boolean, }, - /** @override */ - attached: function() { - this.listen(this, 'freeze-scroll', 'onFreezeScroll_'); - this.listen(this, 'lazy-loaded', 'onLazyLoaded_'); - }, - - /** @private */ - onLazyLoaded_: function() { - Polymer.dom.flush(); - this.updateOverscrollForPage_(); - }, - - /** @override */ - detached: function() { - this.unlisten(this, 'freeze-scroll', 'onFreezeScroll_'); - }, - /** @private */ overscrollChanged_: function() { if (!this.overscroll_ && this.boundScroll_) { @@ -108,8 +91,9 @@ this.boundScroll_ = null; } else if (this.overscroll_ && !this.boundScroll_) { this.boundScroll_ = () => { - if (!this.ignoreScroll_) + if (!this.freezeOverscroll_) { this.setOverscroll_(0); + } }; this.offsetParent.addEventListener('scroll', this.boundScroll_); window.addEventListener('resize', this.boundScroll_); @@ -137,46 +121,11 @@ }, /** - * Enables or disables user scrolling, via overscroll: hidden. Room for the - * hidden scrollbar is added to prevent the page width from changing back and - * forth. Also freezes the overscroll height. - * @param {!Event} e |e.detail| is true to freeze, false to unfreeze. - * @private - */ - onFreezeScroll_: function(e) { - if (e.detail) { - // Update the overscroll and ignore scroll events. - this.setOverscroll_(this.overscrollHeight_()); - this.ignoreScroll_ = true; - - // Prevent scrolling the container. - const scrollerWidth = this.offsetParent.clientWidth; - this.offsetParent.style.overflow = 'hidden'; - const scrollbarWidth = this.offsetParent.clientWidth - scrollerWidth; - this.offsetParent.style.width = 'calc(100% - ' + scrollbarWidth + 'px)'; - } else { - this.ignoreScroll_ = false; - this.offsetParent.style.overflow = ''; - this.offsetParent.style.width = ''; - } - }, - - /** @param {!settings.Route} newRoute */ - currentRouteChanged: function(newRoute) { - this.updatePagesShown_(); - }, - - /** @private */ - onSubpageExpand_: function() { - this.updatePagesShown_(); - }, - - /** * Updates the hidden state of the about and settings pages based on the * current route. - * @private + * @param {!settings.Route} newRoute */ - updatePagesShown_: function() { + currentRouteChanged: function(newRoute) { const inAbout = settings.routes.ABOUT.contains(settings.getCurrentRoute()); this.showPages_ = {about: inAbout, settings: !inAbout}; @@ -184,57 +133,35 @@ loadTimeData.getStringF( 'settingsAltPageTitle', loadTimeData.getString('aboutPageTitle')) : loadTimeData.getString('settings'); + }, + /** @private */ + onShowingSubpage_: function() { + this.freezeOverscroll_ = true; + }, - // Calculate and set the overflow padding. - this.updateOverscrollForPage_(); - - // Wait for any other changes, then calculate the overflow padding again. - setTimeout(() => { - // Ensure any dom-if reflects the current properties. - Polymer.dom.flush(); - this.updateOverscrollForPage_(); - }); + /** @private */ + onShowingMainPage_: function() { + this.freezeOverscroll_ = false; }, /** - * Calculates the necessary overscroll and sets the overscroll to that value - * (at minimum). For the About page, this just zeroes the overscroll. + * A handler for the 'showing-section' event fired from settings-basic-page, + * indicating that a section should be scrolled into view as a result of a + * navigation. + * @param {!CustomEvent} e * @private */ - updateOverscrollForPage_: function() { - if (this.showPages_.about || this.inSearchMode_) { - // Set overscroll directly to remove any existing overscroll that - // setOverscroll_ would otherwise preserve. - this.overscroll_ = 0; - return; - } - this.setOverscroll_(this.overscrollHeight_()); - }, - - /** - * Return the height that the overscroll padding should be set to. - * This is used to determine how much padding to apply to the end of the - * content so that the last element may align with the top of the content - * area. - * @return {number} - * @private - */ - overscrollHeight_: function() { - const route = settings.getCurrentRoute(); - if (!route.section || route.isSubpage() || this.showPages_.about) - return 0; - - const page = this.getPage_(route); - const section = page && page.getSection(route.section); - if (!section || !section.offsetParent) - return 0; - + onShowingSection_: function(e) { + const section = e.detail; + // Calculate the height that the overscroll padding should be set to, so + // that the given section is displayed at the top of the viewport. // Find the distance from the section's top to the overscroll. const sectionTop = section.offsetParent.offsetTop + section.offsetTop; const distance = this.$.overscroll.offsetTop - sectionTop; - - return Math.max(0, this.offsetParent.clientHeight - distance); + const overscroll = Math.max(0, this.offsetParent.clientHeight - distance); + this.setOverscroll_(overscroll); + section.scrollIntoView(); }, /** @@ -295,10 +222,4 @@ }, 0); }); }, - - focusSection: function() { - this.$$(this.showPages_.settings ? 'settings-basic-page' : - 'settings-about-page') - .focusSection(); - }, });
diff --git a/chrome/browser/resources/settings/settings_page/BUILD.gn b/chrome/browser/resources/settings/settings_page/BUILD.gn index 9114c55..937513c 100644 --- a/chrome/browser/resources/settings/settings_page/BUILD.gn +++ b/chrome/browser/resources/settings/settings_page/BUILD.gn
@@ -18,10 +18,10 @@ deps = [ ":settings_section", "..:route", - "../animation:animation", "//ui/webui/resources/js:assert", "//ui/webui/resources/js:util", ] + externs_list = [ "$externs_path/pending.js" ] } js_library("settings_animated_pages") { @@ -37,10 +37,6 @@ } js_library("settings_section") { - deps = [ - "../animation:animation", - ] - externs_list = [ "$externs_path/web_animations.js" ] } js_library("settings_subpage") { @@ -49,7 +45,6 @@ "..:find_shortcut_behavior", "..:route", "//third_party/polymer/v1_0/components-chromium/iron-resizable-behavior:iron-resizable-behavior-extracted", - "//third_party/polymer/v1_0/components-chromium/neon-animation:neon-animatable-behavior-extracted", "//ui/webui/resources/js:assert", "//ui/webui/resources/js/cr/ui:focus_without_ink", ]
diff --git a/chrome/browser/resources/settings/settings_page/main_page_behavior.js b/chrome/browser/resources/settings/settings_page/main_page_behavior.js index 49ef81a1..b4ed16a 100644 --- a/chrome/browser/resources/settings/settings_page/main_page_behavior.js +++ b/chrome/browser/resources/settings/settings_page/main_page_behavior.js
@@ -2,391 +2,372 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +cr.exportPath('settings'); + /** - * Responds to route changes by expanding, collapsing, or scrolling to sections - * on the page. Expanded sections take up the full height of the container. At - * most one section should be expanded at any given time. - * @polymerBehavior MainPageBehavior + * @enum {string} + * A categorization of every possible Settings URL, necessary for implementing + * a finite state machine. */ -const MainPageBehaviorImpl = { - properties: { +settings.RouteState = { + // Initial state before anything has loaded yet. + INITIAL: 'initial', + // A dialog that has a dedicated URL (e.g. /importData). + DIALOG: 'dialog', + // A section (basically a scroll position within the top level page, e.g, + // /appearance. + SECTION: 'section', + // A subpage, or sub-subpage e.g, /searchEngins. + SUBPAGE: 'subpage', + // The top level Settings page, '/'. + TOP_LEVEL: 'top-level', +}; + +cr.define('settings', function() { + const RouteState = settings.RouteState; + + /** + * @param {?settings.Route} route + * @return {!settings.RouteState} + */ + function classifyRoute(route) { + if (!route) + return RouteState.INITIAL; + if (route === settings.routes.BASIC || route === settings.routes.ABOUT) + return RouteState.TOP_LEVEL; + if (route.isSubpage()) + return RouteState.SUBPAGE; + if (route.isNavigableDialog) + return RouteState.DIALOG; + return RouteState.SECTION; + } + + /** + * Responds to route changes by expanding, collapsing, or scrolling to + * sections on the page. Expanded sections take up the full height of the + * container. At most one section should be expanded at any given time. + * @polymerBehavior + */ + const MainPageBehavior = { + properties: { + /** + * Whether a search operation is in progress or previous search results + * are being displayed. + * @private {boolean} + */ + inSearchMode: { + type: Boolean, + value: false, + observer: 'inSearchModeChanged_', + }, + }, + + /** @type {?HTMLElement} */ + scroller: null, + /** - * Help CSS to alter style during the horizontal swipe animation. - * Note that this is unrelated to the |currentAnimation_| (which refers to - * the vertical expand animation). + * A map holding all valid state transitions. + * @private {!Map<!settings.RouteState, !settings.RouteState>} */ - isSubpageAnimating: { - reflectToAttribute: true, - type: Boolean, + validTransitions_: (function() { + const allStates = new Set([ + RouteState.DIALOG, + RouteState.SECTION, + RouteState.SUBPAGE, + RouteState.TOP_LEVEL, + ]); + + return new Map([ + [RouteState.INITIAL, allStates], + [ + RouteState.DIALOG, new Set([ + RouteState.SECTION, + RouteState.SUBPAGE, + RouteState.TOP_LEVEL, + ]) + ], + [RouteState.SECTION, allStates], + [RouteState.SUBPAGE, allStates], + [RouteState.TOP_LEVEL, allStates], + ]); + })(), + + /** @override */ + attached: function() { + this.scroller = this.domHost ? this.domHost.parentNode : document.body; }, /** - * Whether a search operation is in progress or previous search results are - * being displayed. - * @private {boolean} + * Method to be defined by users of MainPageBehavior. + * @param {!settings.Route} route + * @return {boolean} Whether the given route is part of |this| page. */ - inSearchMode: { - type: Boolean, - value: false, - observer: 'inSearchModeChanged_', + containsRoute: function(route) { + return false; }, - }, - /** @type {?HTMLElement} The scrolling container. */ - scroller: null, + /** + * @param {boolean} current + * @param {boolean} previous + * @private + */ + inSearchModeChanged_: function(current, previous) { + // Ignore 1st occurrence which happens while the element is being + // initialized. + if (previous === undefined) + return; - listeners: {'neon-animation-finish': 'onNeonAnimationFinish_'}, + if (!this.inSearchMode) { + const route = settings.getCurrentRoute(); + if (this.containsRoute(route) && + classifyRoute(route) === RouteState.SECTION) { + // Re-fire the showing-section event to trigger settings-main + // recalculation of the overscroll, now that sections are not + // hidden-by-search. + this.fire('showing-section', this.getSection(route.section)); + } + } + }, - /** @override */ - attached: function() { - this.scroller = this.domHost ? this.domHost.parentNode : document.body; - }, + /** + * @param {!settings.Route} route + * @return {boolean} + * @private + */ + shouldExpandAdvanced_: function(route) { + return this.tagName == 'SETTINGS-BASIC-PAGE' && + settings.routes.ADVANCED && settings.routes.ADVANCED.contains(route); + }, - /** - * Remove the is-animating attribute once the animation is complete. - * This may catch animations finishing more often than needed, which is not - * known to cause any issues (e.g. when animating from a shallower page to a - * deeper page; or when transitioning to the main page). - * @private - */ - onNeonAnimationFinish_: function() { - this.isSubpageAnimating = false; - }, + /** + * Finds the settings section corresponding to the given route. If the + * section is lazily loaded it force-renders it. + * Note: If the section resides within "advanced" settings, a + * 'hide-container' event is fired (necessary to avoid flashing). Callers + * are responsible for firing a 'show-container' event. + * @param {!settings.Route} route + * @return {!Promise<!SettingsSectionElement>} + * @private + */ + ensureSectionForRoute_: function(route) { + const section = this.getSection(route.section); + if (section != null) + return Promise.resolve(section); - /** - * @param {!settings.Route} newRoute - * @param {settings.Route} oldRoute - */ - currentRouteChanged: function(newRoute, oldRoute) { - const oldRouteWasSection = !!oldRoute && !!oldRoute.parent && - !!oldRoute.section && oldRoute.parent.section != oldRoute.section; + // TODO(dpapad): Remove condition when Polymer 2 migration is complete. + // The function to use to wait for <dom-if>s to render. + const waitFn = Polymer.DomIf ? + Polymer.RenderStatus.beforeNextRender.bind(null, this) : + requestAnimationFrame; - if (this.scroller) { - // When navigating from a section to the root route, we just need to - // scroll to the top, and can early exit afterwards. - if (oldRouteWasSection && newRoute == settings.routes.BASIC) { - this.scroller.scrollTop = 0; + return new Promise(resolve => { + if (this.shouldExpandAdvanced_(route)) { + this.fire('hide-container'); + waitFn(() => { + this.$$('#advancedPageTemplate').get().then(() => { + resolve(this.getSection(route.section)); + }); + }); + } else { + waitFn(() => { + resolve(this.getSection(route.section)); + }); + } + }); + }, + + /** + * @param {!settings.Route} route + * @private + */ + enterSubpage_: function(route) { + this.lastScrollTop_ = this.scroller.scrollTop; + this.scroller.scrollTop = 0; + this.classList.add('showing-subpage'); + this.fire('subpage-expand'); + this.ensureSectionForRoute_(route).then(section => { + section.classList.add('expanded'); + // Fire event used by a11y tests only. + this.fire('settings-section-expanded'); + + this.fire('show-container'); + }); + }, + + /** + * @param {!settings.Route} oldRoute + * @private + */ + enterMainPage_: function(oldRoute) { + const oldSection = this.getSection(oldRoute.section); + oldSection.classList.remove('expanded'); + this.classList.remove('showing-subpage'); + requestAnimationFrame(() => { + if (settings.lastRouteChangeWasPopstate()) { + this.scroller.scrollTop = this.lastScrollTop_; + } + this.fire('showing-main-page'); + }); + }, + + /** + * @param {!settings.Route} route + * @private + */ + scrollToSection_: function(route) { + this.ensureSectionForRoute_(route).then(section => { + if (!this.inSearchMode) { + this.fire('showing-section', section); + } + this.fire('show-container'); + }); + }, + + /** + * Detects which state transition is appropriate for the given new/old + * routes. + * @param {!settings.Route} newRoute + * @param {settings.Route} oldRoute + * @private + */ + getStateTransition_(newRoute, oldRoute) { + const containsNew = this.containsRoute(newRoute); + const containsOld = this.containsRoute(oldRoute); + + if (!containsNew && !containsOld) { + // Nothing to do, since none of the old/new routes belong to this page. + return null; + } + + // Case where going from |this| page to an unrelated page. For example: + // |this| is settings-basic-page AND + // oldRoute is /searchEngines AND + // newRoute is /help. + if (containsOld && !containsNew) { + return [classifyRoute(oldRoute), RouteState.TOP_LEVEL]; + } + + // Case where return from an unrelated page to |this| page. For example: + // |this| is settings-basic-page AND + // oldRoute is /help AND + // newRoute is /searchEngines + if (!containsOld && containsNew) { + return [RouteState.TOP_LEVEL, classifyRoute(newRoute)]; + } + + // Case where transitioning between routes that both belong to |this| + // page. + return [classifyRoute(oldRoute), classifyRoute(newRoute)]; + }, + + /** + * @param {!settings.Route} newRoute + * @param {settings.Route} oldRoute + */ + currentRouteChanged(newRoute, oldRoute) { + const transition = this.getStateTransition_(newRoute, oldRoute); + if (transition === null) + return; + + const oldState = transition[0]; + const newState = transition[1]; + assert(this.validTransitions_.get(oldState).has(newState)); + + if (oldState == RouteState.TOP_LEVEL) { + if (newState == RouteState.SECTION) { + this.scrollToSection_(newRoute); + } else if (newState == RouteState.SUBPAGE) { + this.enterSubpage_(newRoute); + } + // Nothing to do here for the case of RouteState.DIALOG or TOP_LEVEL. + // The latter happens when navigating from '/?search=foo' to '/' + // (clearing search results). return; } - // When navigating to the About page, we need to scroll to the top, and - // still do the rest of section management. - if (newRoute == settings.routes.ABOUT) - this.scroller.scrollTop = 0; - } - - // Scroll to the section except for back/forward. Also scroll for any - // in-page back/forward navigations (from a section or the root page). - // Also always scroll when coming from either the About or root page. - const scrollToSection = !settings.lastRouteChangeWasPopstate() || - oldRouteWasSection || oldRoute == settings.routes.BASIC || - oldRoute == settings.routes.ABOUT; - - // TODO(dschuyler): This doesn't set the flag in the case of going to or - // from the main page. It seems sensible to set the flag in those cases, - // unfortunately bug 708465 happens. Figure out why that is and then set - // this flag more broadly. - if (oldRoute && oldRoute.isSubpage() && newRoute.isSubpage()) - this.isSubpageAnimating = true; - - // For previously uncreated pages (including on first load), allow the page - // to render before scrolling to or expanding the section. - if (!oldRoute) { - this.fire('hide-container'); - setTimeout(() => { - this.fire('show-container'); - this.tryTransitionToSection_(scrollToSection, true); - }); - } else if (this.scrollHeight == 0) { - setTimeout(this.tryTransitionToSection_.bind(this, scrollToSection)); - } else { - this.tryTransitionToSection_(scrollToSection); - } - }, - - /** - * When exiting search mode, we need to make another attempt to scroll to - * the correct section, since it has just been re-rendered. - * @private - */ - inSearchModeChanged_: function(inSearchMode) { - if (!this.isAttached) - return; - - if (!inSearchMode) - this.tryTransitionToSection_(!settings.lastRouteChangeWasPopstate()); - }, - - /** - * If possible, transitions to the current route's section (by expanding or - * scrolling to it). If another transition is running, finishes or cancels - * that one, then schedules this function again. This ensures the current - * section is quickly shown, without getting the page into a broken state -- - * if currentRoute changes in between calls, just transition to the new route. - * @param {boolean} scrollToSection - * @param {boolean=} immediate Whether to instantly expand instead of animate. - * @private - */ - tryTransitionToSection_: function(scrollToSection, immediate) { - const currentRoute = settings.getCurrentRoute(); - const currentSection = this.getSection(currentRoute.section); - - // If an animation is already playing, try finishing or canceling it. - if (this.currentAnimation_) { - this.maybeStopCurrentAnimation_(); - // Either way, this function will be called again once the current - // animation ends. - return; - } - - let promise; - const expandedSection = /** @type {?SettingsSectionElement} */ ( - this.$$('settings-section.expanded')); - if (expandedSection) { - // If the section shouldn't be expanded, collapse it. - if (!currentRoute.isSubpage() || expandedSection != currentSection) { - promise = this.collapseSection_(expandedSection); - } else { - // Scroll to top while sliding to another subpage. - this.scroller.scrollTop = 0; - } - } else if (currentSection) { - // Expand the section into a subpage or scroll to it on the main page. - if (currentRoute.isSubpage()) { - if (immediate) - this.expandSectionImmediate_(currentSection); - else - promise = this.expandSection_(currentSection); - } else if (scrollToSection) { - currentSection.show(); - } - } else if ( - this.tagName == 'SETTINGS-BASIC-PAGE' && settings.routes.ADVANCED && - settings.routes.ADVANCED.contains(currentRoute) && - // Need to exclude routes that correspond to 'non-sectioned' children of - // ADVANCED, otherwise tryTransitionToSection_ will recurse endlessly. - !currentRoute.isNavigableDialog) { - assert(currentRoute.section); - // Hide the container again while Advanced Page template is being loaded. - this.fire('hide-container'); - promise = this.$$('#advancedPageTemplate').get(); - } - - // When this animation ends, another may be necessary. Call this function - // again after the promise resolves. - if (promise) { - promise.then(this.tryTransitionToSection_.bind(this, scrollToSection)) - .then(() => { - this.fire('show-container'); - }); - } - }, - - /** - * If the current animation is inconsistent with the current route, stops the - * animation by finishing or canceling it so the new route can be animated to. - * @private - */ - maybeStopCurrentAnimation_: function() { - const currentRoute = settings.getCurrentRoute(); - const animatingSection = /** @type {?SettingsSectionElement} */ ( - this.$$('settings-section.expanding, settings-section.collapsing')); - assert(animatingSection); - - if (animatingSection.classList.contains('expanding')) { - // Cancel the animation to go back to the main page if the animating - // section shouldn't be expanded. - if (animatingSection.section != currentRoute.section || - !currentRoute.isSubpage()) { - this.currentAnimation_.cancel(); - } - // Otherwise, let the expand animation continue. - return; - } - - assert(animatingSection.classList.contains('collapsing')); - if (!currentRoute.isSubpage()) - return; - - // If the collapsing section actually matches the current route's section, - // we can just cancel the animation to re-expand the section. - if (animatingSection.section == currentRoute.section) { - this.currentAnimation_.cancel(); - return; - } - - // The current route is a subpage, so that section needs to expand. - // Immediately finish the current collapse animation so that can happen. - this.currentAnimation_.finish(); - }, - - /** - * Immediately expand the card in |section| to fill the page. - * @param {!SettingsSectionElement} section - * @private - */ - expandSectionImmediate_: function(section) { - assert(this.scroller); - section.immediateExpand(this.scroller); - this.finishedExpanding_(section); - // TODO(scottchen): iron-list inside subpages need this to render correctly. - this.fire('resize'); - }, - - /** - * Animates the card in |section|, expanding it to fill the page. - * @param {!SettingsSectionElement} section - * @return {!Promise} Resolved when the transition is finished or canceled. - * @private - */ - expandSection_: function(section) { - assert(this.scroller); - if (!section.canAnimateExpand()) { - // Try to wait for the section to be created. - return new Promise(function(resolve, reject) { - setTimeout(resolve); - }); - } - - // Save the scroller position before freezing it. - this.origScrollTop_ = this.scroller.scrollTop; - this.fire('freeze-scroll', true); - - // Freeze the section's height so its card can be removed from the flow. - section.setFrozen(true); - - this.currentAnimation_ = section.animateExpand(this.scroller); - - return this.currentAnimation_.finished - .then( - () => { - this.finishedExpanding_(section); - }, - () => { - // The animation was canceled; restore the section and scroll - // position. - section.setFrozen(false); - this.scroller.scrollTop = this.origScrollTop_; - }) - .then(() => { - this.fire('freeze-scroll', false); - this.currentAnimation_ = null; - }); - }, - - /** @private */ - finishedExpanding_: function(section) { - // Hide other sections and scroll to the top of the subpage. - this.classList.add('showing-subpage'); - this.toggleOtherSectionsHidden_(section.section, true); - this.scroller.scrollTop = 0; - section.setFrozen(false); - - // Notify that the page is fully expanded. - this.fire('subpage-expand'); - }, - - /** - * Animates the card in |section|, collapsing it back into its section. - * @param {!SettingsSectionElement} section - * @return {!Promise} Resolved when the transition is finished or canceled. - */ - collapseSection_: function(section) { - assert(this.scroller); - assert(section.classList.contains('expanded')); - - // Don't animate the collapse if we are transitioning between Basic/Advanced - // and About, since the section won't be visible. - const needAnimate = - settings.routes.ABOUT.contains(settings.getCurrentRoute()) == - (section.domHost.tagName == 'SETTINGS-ABOUT-PAGE'); - - // Animate the collapse if the section knows the original height, except - // when switching between Basic/Advanced and About. - const shouldAnimateCollapse = needAnimate && section.canAnimateCollapse(); - if (shouldAnimateCollapse) { - this.fire('freeze-scroll', true); - // Do the initial collapse setup, which takes the section out of the flow, - // before showing everything. - section.setUpAnimateCollapse(this.scroller); - } else { - section.classList.remove('expanded'); - } - - // Show everything. - this.toggleOtherSectionsHidden_(section.section, false); - this.classList.remove('showing-subpage'); - - if (!shouldAnimateCollapse) { - // Finish by restoring the section into the page. - section.setFrozen(false); - return Promise.resolve(); - } - - // Play the actual collapse animation. - return new Promise((resolve, reject) => { - // Wait for the other sections to show up so we can scroll properly. - setTimeout(() => { - const newSection = settings.getCurrentRoute().section && - this.getSection(settings.getCurrentRoute().section); - - // Scroll to the new section or the original position. - if (newSection && !settings.lastRouteChangeWasPopstate() && - !settings.getCurrentRoute().isSubpage()) { - newSection.scrollIntoView(); - } else { - this.scroller.scrollTop = this.origScrollTop_; + if (oldState == RouteState.SECTION) { + if (newState == RouteState.SECTION) { + this.scrollToSection_(newRoute); + } else if (newState == RouteState.SUBPAGE) { + this.enterSubpage_(newRoute); + } else if (newState == RouteState.TOP_LEVEL) { + this.scroller.scrollTop = 0; } + // Nothing to do here for the case of RouteState.DIALOG. + return; + } - this.currentAnimation_ = section.animateCollapse( - /** @type {!HTMLElement} */ (this.scroller)); + if (oldState == RouteState.SUBPAGE) { + if (newState == RouteState.SECTION) { + this.enterMainPage_(oldRoute); - this.currentAnimation_.finished - .catch(() => { - // The collapse was canceled, so the page is showing a subpage - // still. - this.fire('subpage-expand'); - }) - .then(() => { - // Clean up after the animation succeeds or cancels. - section.setFrozen(false); - section.classList.remove('collapsing'); - this.fire('freeze-scroll', false); - this.currentAnimation_ = null; - resolve(); - }); - }); - }); - }, + // Scroll to the corresponding section, only if the user explicitly + // navigated to a section (via the menu). + if (!settings.lastRouteChangeWasPopstate()) { + this.scrollToSection_(newRoute); + } + } else if (newState == RouteState.SUBPAGE) { + // Handle case where the two subpages belong to + // different sections, but are linked to each other. For example + // /storage and /accounts (in ChromeOS). + if (!oldRoute.contains(newRoute) && !newRoute.contains(oldRoute)) { + this.enterMainPage_(oldRoute); + this.enterSubpage_(newRoute); + return; + } - /** - * Hides or unhides the sections not being expanded. - * @param {string} sectionName The section to keep visible. - * @param {boolean} hidden Whether the sections should be hidden. - * @private - */ - toggleOtherSectionsHidden_: function(sectionName, hidden) { - const sections = - Polymer.dom(this.root).querySelectorAll('settings-section'); - for (let i = 0; i < sections.length; i++) - sections[i].hidden = hidden && (sections[i].section != sectionName); - }, + // Handle case of subpage to sub-subpage navigation. + if (oldRoute.contains(newRoute)) { + this.scroller.scrollTop = 0; + return; + } + // When going from a sub-subpage to its parent subpage, scroll + // position is automatically restored, because we focus the + // sub-subpage entry point. + } else if (newState == RouteState.TOP_LEVEL) { + this.enterMainPage_(oldRoute); + } else if (newState == RouteState.DIALOG) { + // The only known case currently for such a transition is from + // /storage to /clearBrowserData. + this.enterMainPage_(oldRoute); + } + return; + } - /** - * Helper function to get a section from the local DOM. - * @param {string} section Section name of the element to get. - * @return {?SettingsSectionElement} - */ - getSection: function(section) { - if (!section) - return null; - return /** @type {?SettingsSectionElement} */ ( - this.$$('settings-section[section="' + section + '"]')); - }, -}; + if (oldState == RouteState.INITIAL) { + if (newState == RouteState.SECTION) { + this.scrollToSection_(newRoute); + } else if (newState == RouteState.SUBPAGE) { + this.enterSubpage_(newRoute); + } + // Nothing to do here for the case of RouteState.DIALOG and TOP_LEVEL. + return; + } -/** @polymerBehavior */ -const MainPageBehavior = [ - settings.RouteObserverBehavior, - MainPageBehaviorImpl, -]; + if (oldState == RouteState.DIALOG) { + if (newState == RouteState.SUBPAGE) { + // The only known case currently for such a transition is from + // /clearBrowserData back to /storage. + this.enterSubpage_(newRoute); + } + // Nothing to do for all other cases. + } + }, + + /** + * TODO(dpapad): Rename this to |querySection| to distinguish it from + * ensureSectionForRoute_() which force-renders the section as needed. + * Helper function to get a section from the local DOM. + * @param {string} section Section name of the element to get. + * @return {?SettingsSectionElement} + */ + getSection: function(section) { + if (!section) + return null; + return /** @type {?SettingsSectionElement} */ ( + this.$$(`settings-section[section="${section}"]`)); + }, + }; + + return {MainPageBehavior: MainPageBehavior}; +});
diff --git a/chrome/browser/resources/settings/settings_page/settings_animated_pages.html b/chrome/browser/resources/settings/settings_page/settings_animated_pages.html index 10c922d3..5cf2385 100644 --- a/chrome/browser/resources/settings/settings_page/settings_animated_pages.html +++ b/chrome/browser/resources/settings/settings_page/settings_animated_pages.html
@@ -5,36 +5,15 @@ <link rel="import" href="chrome://resources/html/cr/ui.html"> <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html"> <link rel="import" href="chrome://resources/html/util.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/slide-from-left-animation.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/slide-from-right-animation.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/slide-left-animation.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/slide-right-animation.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animated-pages.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animation-runner-behavior.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/web-animations.html"> -<link rel="import" href="../animation/fade_animations.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html"> <link rel="import" href="../route.html"> <dom-module id="settings-animated-pages"> <template> - <style> - :host { - display: block; - } - - neon-animated-pages { - position: static; - } - - neon-animated-pages ::slotted(.iron-selected) { - position: static; - } - </style> - <neon-animated-pages id="animatedPages" attr-for-selected="route-path" + <iron-pages id="animatedPages" attr-for-selected="route-path" on-iron-select="onIronSelect_"> <slot></slot> - </neon-animated-pages> + </iron-pages> </template> <script src="settings_animated_pages.js"></script> </dom-module>
diff --git a/chrome/browser/resources/settings/settings_page/settings_animated_pages.js b/chrome/browser/resources/settings/settings_page/settings_animated_pages.js index 1fe497b..5f0612e 100644 --- a/chrome/browser/resources/settings/settings_page/settings_animated_pages.js +++ b/chrome/browser/resources/settings/settings_page/settings_animated_pages.js
@@ -39,10 +39,6 @@ focusConfig: Object, }, - listeners: { - 'neon-animation-finish': 'onNeonAnimationFinish_', - }, - /** * The last "previous" route reported by the router. * @private {?settings.Route} @@ -56,30 +52,32 @@ Polymer.dom(this).observeNodes(this.lightDomChanged_.bind(this)); }, - /** @private */ - onNeonAnimationFinish_: function() { - if (settings.lastRouteChangeWasPopstate()) - return; - - // Set initial focus when navigating to a subpage for a11y. - let subPage = /** @type {SettingsSubpageElement} */ ( - this.querySelector('settings-subpage.iron-selected')); - if (subPage) - subPage.initialFocus(); - }, - /** * @param {!Event} e * @private */ onIronSelect_: function(e) { - if (!this.focusConfig || !this.previousRoute_) - return; + // Call initialFocus() on the selected subpage, only if: + // 1) Not a direct navigation (such that the search box stays focused), and + // 2) Not a "back" navigation, in which case the anchor element should be + // focused (further below in this function). + if (!!this.previousRoute_ && !settings.lastRouteChangeWasPopstate()) { + const subpage = this.querySelector('settings-subpage.iron-selected'); + if (!!subpage) { + subpage.initialFocus(); + return; + } + } // Don't attempt to focus any anchor element, unless last navigation was a // 'pop' (backwards) navigation. - if (!settings.lastRouteChangeWasPopstate()) + if (!settings.lastRouteChangeWasPopstate()) { return; + } + + if (!this.focusConfig || !this.previousRoute_) { + return; + } const subpagePaths = []; if (settings.routes.SITE_SETTINGS_COOKIES) @@ -98,6 +96,7 @@ // Only handle iron-select events from neon-animatable elements and the // given whitelist of settings-subpage instances. + // TODO(dpapad): Remove neon-animatable here. const whitelist = ['settings-subpage#site-settings', 'neon-animatable']; whitelist.push.apply( whitelist, @@ -119,11 +118,7 @@ cr.ui.focusWithoutInk(/** @type {!Element} */ (pathConfig)); }; } - // neon-animatable has "display: none" until the animation finishes, - // so calling focus() on any of its children has no effect until - // "display:none" is removed. Therefore, don't set focus from within - // the currentRouteChanged callback. - listenOnce(this, 'neon-animation-finish', handler); + handler(); } }, @@ -159,8 +154,6 @@ if (newRoute.section == this.section && newRoute.isSubpage()) { this.switchToSubpage_(newRoute, oldRoute); } else { - this.$.animatedPages.exitAnimation = 'settings-fade-out-animation'; - this.$.animatedPages.entryAnimation = 'settings-fade-in-animation'; this.$.animatedPages.selected = 'default'; } }, @@ -180,40 +173,6 @@ } this.ensureSubpageInstance_(); - - if (oldRoute) { - if (oldRoute.isSubpage() && newRoute.depth > oldRoute.depth) { - const isRtl = loadTimeData.getString('textdirection') == 'rtl'; - const exit = isRtl ? 'right' : 'left'; - const entry = isRtl ? 'left' : 'right'; - this.$.animatedPages.exitAnimation = 'slide-' + exit + '-animation'; - this.$.animatedPages.entryAnimation = - 'slide-from-' + entry + '-animation'; - } else if (oldRoute.depth > newRoute.depth) { - const isRtl = loadTimeData.getString('textdirection') == 'rtl'; - const exit = isRtl ? 'left' : 'right'; - const entry = isRtl ? 'right' : 'left'; - this.$.animatedPages.exitAnimation = 'slide-' + exit + '-animation'; - this.$.animatedPages.entryAnimation = - 'slide-from-' + entry + '-animation'; - } else { - // The old route is not a subpage or is at the same level, so just fade. - this.$.animatedPages.exitAnimation = 'settings-fade-out-animation'; - this.$.animatedPages.entryAnimation = 'settings-fade-in-animation'; - - if (!oldRoute.isSubpage()) { - // Set the height the expand animation should start at before - // beginning the transition to the new subpage. - // TODO(michaelpg): Remove MainPageBehavior's dependency on this - // height being set. - this.style.height = this.clientHeight + 'px'; - this.async(function() { - this.style.height = ''; - }); - } - } - } - this.$.animatedPages.selected = newRoute.path; },
diff --git a/chrome/browser/resources/settings/settings_page/settings_section.html b/chrome/browser/resources/settings/settings_page/settings_section.html index a6336040..a2cdddc9 100644 --- a/chrome/browser/resources/settings/settings_page/settings_section.html +++ b/chrome/browser/resources/settings/settings_page/settings_section.html
@@ -2,7 +2,6 @@ <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/html/util.html"> -<link rel="import" href="../animation/animation.html"> <dom-module id="settings-section"> <template> @@ -33,35 +32,13 @@ padding-top: 8px; } - #card { + :host(:not(.expanded)) #card { @apply --cr-card-elevation; background-color: white; border-radius: var(--cr-card-border-radius); flex: 1; } - :host(.expanded) #card { - border-radius: 0; - } - - :host(.expanding) #card, - :host(.collapsing) #card, - :host(.expanded) #card { - @apply --cr-card-elevation; - overflow: hidden; - /* A stacking context constrains sliding sub-pages to the card. */ - z-index: 0; - } - - :host(:not(.expanding):not(.expanded)) #card { - /* Keep the fading-out neon-animatable inside the card. */ - position: relative; - } - - :host(.expanded) #header { - display: none; - } - :host([hidden-by-search]) { display: none; }
diff --git a/chrome/browser/resources/settings/settings_page/settings_section.js b/chrome/browser/resources/settings/settings_page/settings_section.js index e7f9d560..dbd3635 100644 --- a/chrome/browser/resources/settings/settings_page/settings_section.js +++ b/chrome/browser/resources/settings/settings_page/settings_section.js
@@ -45,249 +45,6 @@ value: false, reflectToAttribute: true, }, - - /** - * Original height of the collapsed section, used as the target height when - * collapsing after being expanded. - * TODO(michaelpg): Get the height dynamically when collapsing using the - * card's main page. - * @private - */ - collapsedHeight_: { - type: Number, - value: NaN, - }, - }, - - /** - * Freezes the section's height so its card can be removed from the flow - * without affecting the layout of the surrounding sections. - * @param {boolean} frozen True to freeze, false to unfreeze. - */ - setFrozen: function(frozen) { - const card = this.$.card; - if (frozen) { - this.style.height = this.clientHeight + 'px'; - - const cardHeight = card.offsetHeight; - const cardWidth = card.offsetWidth; - // If the section is not displayed yet (e.g., navigated directly to a - // sub-page), cardHeight and cardWidth are 0, so do not set the height or - // width explicitly. - if (cardHeight && cardWidth) { - card.style.height = cardHeight + 'px'; - card.style.width = cardWidth + 'px'; - } - - // Place the section's card at its current position but removed from the - // flow. - card.style.top = card.getBoundingClientRect().top + 'px'; - this.classList.add('frozen'); - } else { - // Restore the section to its normal height. - if (!this.classList.contains('frozen')) - return; - this.classList.remove('frozen'); - this.$.card.style.top = ''; - this.$.card.style.height = ''; - this.$.card.style.width = ''; - this.style.height = ''; - } - }, - - /** - * Calling this method fires the 'settings-section-expanded event'. - */ - setExpanded_: function() { - this.classList.add('expanded'); - this.fire('settings-section-expanded'); - }, - - /** - * @return {boolean} True if the section is currently rendered and not - * already expanded or transitioning. - */ - canAnimateExpand: function() { - return !this.classList.contains('expanding') && - !this.classList.contains('expanded') && this.$.card.clientHeight > 0; - }, - - immediateExpand: function(container) { - // Target position is the container's top edge in the viewport. - const containerTop = container.getBoundingClientRect().top; - - this.$.card.position = 'fixed'; - this.$.card.top = containerTop + 'px'; - this.$.card.height = 'calc(100% - ' + containerTop + 'px)'; - - this.setExpanded_(); - }, - - /** - * Animates the section expanding to fill the container. The section is fixed - * in the viewport during the animation, making it safe to adjust the rest of - * the DOM after calling this. The section adds the "expanding" class while - * the animation plays and "expanded" after it finishes. - * - * @param {!HTMLElement} container The scrolling container to fill. - * @return {!settings.animation.Animation} - */ - animateExpand: function(container) { - // Set the section's height so its card can be removed from the flow - // without affecting the surrounding sections during the animation. - this.collapsedHeight_ = this.clientHeight; - this.style.height = this.collapsedHeight_ + 'px'; - - this.classList.add('expanding'); - - // Start the card in place, at its distance from the container's padding. - const startTop = this.$.card.getBoundingClientRect().top + 'px'; - const startHeight = this.$.card.clientHeight + 'px'; - - // Target position is the container's top edge in the viewport. - const containerTop = container.getBoundingClientRect().top; - const endTop = containerTop + 'px'; - // The card should stretch from the bottom of the toolbar to the bottom of - // the page. calc(100% - top) lets the card resize if the window resizes. - const endHeight = 'calc(100% - ' + containerTop + 'px)'; - - const animation = - this.animateCard_('fixed', startTop, endTop, startHeight, endHeight); - // The empty onRejected function prevents the promise from skipping forward - // to the next then() with a rejection callback. - animation.finished.then(this.setExpanded_.bind(this), () => {}).then(() => { - // Unset these changes whether the animation finished or canceled. - this.classList.remove('expanding'); - this.style.height = ''; - }); - return animation; - }, - - /** - * @return {boolean} True if the section is currently expanded and we know - * what the collapsed height should be. - */ - canAnimateCollapse: function() { - return this.classList.contains('expanded') && this.clientHeight > 0 && - !Number.isNaN(this.collapsedHeight_); - }, - - /** - * Prepares for the animation before the other sections become visible. - * Call before animateCollapse(). - * @param {!HTMLElement} container - */ - setUpAnimateCollapse: function(container) { - // Prepare the dimensions and set position: fixed. - this.$.card.style.width = this.$.card.clientWidth + 'px'; - this.$.card.style.height = this.$.card.clientHeight + 'px'; - this.$.card.style.top = container.getBoundingClientRect().top + 'px'; - this.$.card.style.position = 'fixed'; - - // The section can now collapse back into its original height the page so - // the other sections appear in the right places. - this.classList.remove('expanded'); - this.classList.add('collapsing'); - this.style.height = this.collapsedHeight_ + 'px'; - }, - - /** - * Collapses an expanded section's card back into position in the main page. - * Call after calling animateCollapse(), unhiding other content and scrolling. - * @param {!HTMLElement} container The scrolling container the card fills. - * @return {!settings.animation.Animation} - */ - animateCollapse: function(container) { - // Make the card position: absolute, so scrolling is less of a crapshoot. - // First find the current distance between this section and the card using - // fixed coordinates; the absolute distance will be the same. - const fixedCardTop = this.$.card.getBoundingClientRect().top; - const fixedSectionTop = this.getBoundingClientRect().top; - const distance = fixedCardTop - fixedSectionTop; - - // The target position is right below our header. - const headerStyle = getComputedStyle(this.$.header); - const cardTargetTop = this.$.header.offsetHeight + - parseFloat(headerStyle.marginBottom) + - parseFloat(headerStyle.marginTop); - - // Start the card at its current height and distance from our top. - const startTop = distance + 'px'; - const startHeight = this.$.card.style.height; - - // End at the bottom of our header. - const endTop = cardTargetTop + 'px'; - const endHeight = (this.collapsedHeight_ - cardTargetTop) + 'px'; - - // The card no longer needs position: fixed. - this.$.card.style.position = ''; - - // Collapse this section, animate the card into place, and remove its - // other properties. - const animation = - this.animateCard_('absolute', startTop, endTop, startHeight, endHeight); - this.$.card.style.width = ''; - this.$.card.style.height = ''; - this.$.card.style.top = ''; - - animation.finished - .then( - () => { - this.classList.remove('expanded'); - }, - function() {}) - .then(() => { - // The card now determines the section's height automatically. - this.style.height = ''; - this.classList.remove('collapsing'); - }); - return animation; - }, - - show: function() { - this.setAttribute('tabindex', '-1'); - this.focus(); - this.scrollIntoView(); - listenOnce(this, ['blur', 'pointerdown'], () => { - this.removeAttribute('tabindex'); - }); - }, - - /** - * Helper function to animate the card's position and height. - * @param {string} position CSS position property. - * @param {string} startTop Initial top value. - * @param {string} endTop Target top value. - * @param {string} startHeight Initial height value. - * @param {string} endHeight Target height value. - * @return {!settings.animation.Animation} - * @private - */ - animateCard_: function(position, startTop, endTop, startHeight, endHeight) { - // Width does not change. - const width = this.$.card.clientWidth + 'px'; - - const startFrame = { - position: position, - width: width, - top: startTop, - height: startHeight, - }; - - const endFrame = { - position: position, - width: width, - top: endTop, - height: endHeight, - }; - - const options = /** @type {!KeyframeEffectOptions} */ ({ - duration: settings.animation.Timing.DURATION, - easing: settings.animation.Timing.EASING, - }); - - return new settings.animation.Animation( - this.$.card, [startFrame, endFrame], options); }, /**
diff --git a/chrome/browser/resources/settings/settings_page/settings_subpage.html b/chrome/browser/resources/settings/settings_page/settings_subpage.html index b940d7f..28304ec 100644 --- a/chrome/browser/resources/settings/settings_page/settings_subpage.html +++ b/chrome/browser/resources/settings/settings_page/settings_subpage.html
@@ -3,7 +3,6 @@ <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-resizable-behavior/iron-resizable-behavior.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable-behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-ripple/paper-ripple.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html"> @@ -17,8 +16,16 @@ <template> <style include="settings-shared"> :host { + background-color: white; + bottom: 0; display: block; + left: 0; + min-height: fit-content; padding-bottom: 60px; + position: absolute; + right: 0; + top: 0; + @apply --cr-card-elevation; } #headerLine {
diff --git a/chrome/browser/resources/settings/settings_page/settings_subpage.js b/chrome/browser/resources/settings/settings_page/settings_subpage.js index 0459c70..8877a90a 100644 --- a/chrome/browser/resources/settings/settings_page/settings_subpage.js +++ b/chrome/browser/resources/settings/settings_page/settings_subpage.js
@@ -12,8 +12,6 @@ is: 'settings-subpage', behaviors: [ - // TODO(michaelpg): phase out NeonAnimatableBehavior. - Polymer.NeonAnimatableBehavior, Polymer.IronResizableBehavior, settings.FindShortcutBehavior, settings.RouteObserverBehavior,
diff --git a/chrome/browser/resources/settings/settings_page_css.html b/chrome/browser/resources/settings/settings_page_css.html index 413bc57..f14faa6 100644 --- a/chrome/browser/resources/settings/settings_page_css.html +++ b/chrome/browser/resources/settings/settings_page_css.html
@@ -23,6 +23,10 @@ height: 100%; } + :host(.showing-subpage) settings-section:not(.expanded) { + display: none; + } + :host > div > :not(.expanded) { /* The margin and padding here are doing two things: make the total * separation 24px; and make scrollIntoView align the section header @@ -34,13 +38,6 @@ .expanded { min-height: 100%; } - - .expanding, - .collapsing { - /* Must be lower than the cr-toolbar's z-index. - * See settings_ui.html. */ - z-index: 1; - } </style> </template> </dom-module>
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd index 225b9e2c..83686579 100644 --- a/chrome/browser/resources/settings/settings_resources.grd +++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -107,18 +107,6 @@ <structure name="IDR_SETTINGS_CATEGORY_SETTING_EXCEPTIONS_JS" file="site_settings/category_setting_exceptions.js" type="chrome_html" /> - <structure name="IDR_SETTINGS_ANIMATION_ANIMATION_HTML" - file="animation/animation.html" - type="chrome_html" /> - <structure name="IDR_SETTINGS_ANIMATION_ANIMATION_JS" - file="animation/animation.js" - type="chrome_html" /> - <structure name="IDR_SETTINGS_ANIMATION_FADE_ANIMATIONS_HTML" - file="animation/fade_animations.html" - type="chrome_html" /> - <structure name="IDR_SETTINGS_ANIMATION_FADE_ANIMATIONS_JS" - file="animation/fade_animations.js" - type="chrome_html" /> <structure name="IDR_SETTINGS_CR_SETTINGS_ANIMATED_PAGES_HTML" file="settings_page/settings_animated_pages.html" type="chrome_html" /> @@ -299,12 +287,6 @@ <structure name="IDR_SETTINGS_GLOBAL_SCROLL_TARGET_BEHAVIOR_JS" file="global_scroll_target_behavior.js" type="chrome_html" /> - <structure name="IDR_SETTINGS_FOCUS_ROW_BEHAVIOR_HTML" - file="focus_row_behavior.html" - type="chrome_html" /> - <structure name="IDR_SETTINGS_FOCUS_ROW_BEHAVIOR_JS" - file="focus_row_behavior.js" - type="chrome_html" /> <structure name="IDR_SETTINGS_CHANGE_PASSWORD_BROWSER_PROXY_HTML" file="change_password_page/change_password_browser_proxy.html" type="chrome_html" /> @@ -1252,6 +1234,12 @@ <structure name="IDR_SETTINGS_CROSTINI_SHARED_PATHS_JS" file="crostini_page/crostini_shared_paths.js" type="chrome_html" /> + <structure name="IDR_SETTINGS_CROSTINI_SHARED_USB_DEVICES_HTML" + file="crostini_page/crostini_shared_usb_devices.html" + type="chrome_html" /> + <structure name="IDR_SETTINGS_CROSTINI_SHARED_USB_DEVICES_JS" + file="crostini_page/crostini_shared_usb_devices.js" + type="chrome_html" /> <structure name="IDR_SETTINGS_CROSTINI_BROWSER_PROXY_JS" file="crostini_page/crostini_browser_proxy.js" type="chrome_html"
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html index 430570e..862a60fa 100644 --- a/chrome/browser/resources/settings/settings_shared_css.html +++ b/chrome/browser/resources/settings/settings_shared_css.html
@@ -64,11 +64,6 @@ margin-inline-start: var(--cr-icon-ripple-margin); } - neon-animatable { - display: flex; - flex-direction: column; - } - /* For "Advanced" toggle button. */ paper-button[toggles][active] { background-color: var(--paper-grey-300);
diff --git a/chrome/browser/resources/settings/settings_ui/settings_ui.js b/chrome/browser/resources/settings/settings_ui/settings_ui.js index 8bd9c109..9c1551c 100644 --- a/chrome/browser/resources/settings/settings_ui/settings_ui.js +++ b/chrome/browser/resources/settings/settings_ui/settings_ui.js
@@ -280,16 +280,18 @@ * @private */ onMenuClose_: function() { - if (this.$.drawer.wasCanceled()) { - // Add tab index so that the container can be focused. - this.$.container.setAttribute('tabindex', '-1'); - this.$.container.focus(); - - listenOnce(this.$.container, ['blur', 'pointerdown'], () => { - this.$.container.removeAttribute('tabindex'); - }); - } else { - this.$.main.focusSection(); + if (!this.$.drawer.wasCanceled()) { + // If a navigation happened, MainPageBehavior#currentRouteChanged handles + // focusing the corresponding section. + return; } + + // Add tab index so that the container can be focused. + this.$.container.setAttribute('tabindex', '-1'); + this.$.container.focus(); + + listenOnce(this.$.container, ['blur', 'pointerdown'], () => { + this.$.container.removeAttribute('tabindex'); + }); }, });
diff --git a/chrome/browser/resources/settings/site_settings/BUILD.gn b/chrome/browser/resources/settings/site_settings/BUILD.gn index d6a1c9d..8397b44 100644 --- a/chrome/browser/resources/settings/site_settings/BUILD.gn +++ b/chrome/browser/resources/settings/site_settings/BUILD.gn
@@ -153,10 +153,10 @@ deps = [ ":cookie_info", ":local_data_browser_proxy", - "..:focus_row_behavior", "//ui/webui/resources/js:cr", "//ui/webui/resources/js:i18n_behavior", "//ui/webui/resources/js:icon", + "//ui/webui/resources/js/cr/ui:focus_row_behavior", ] } @@ -223,10 +223,10 @@ deps = [ ":constants", ":site_settings_behavior", - "..:focus_row_behavior", "..:route", "//ui/webui/resources/cr_elements/policy:cr_policy_pref_indicator", "//ui/webui/resources/js:cr", + "//ui/webui/resources/js/cr/ui:focus_row_behavior", ] }
diff --git a/chrome/browser/resources/settings/site_settings/protocol_handlers.html b/chrome/browser/resources/settings/site_settings/protocol_handlers.html index 0e2436e..5585ac7 100644 --- a/chrome/browser/resources/settings/site_settings/protocol_handlers.html +++ b/chrome/browser/resources/settings/site_settings/protocol_handlers.html
@@ -61,11 +61,11 @@ </template> <cr-action-menu> - <button slot="item" class="dropdown-item" on-click="onDefaultClick_" + <button class="dropdown-item" on-click="onDefaultClick_" id="defaultButton" hidden$="[[actionMenuModel_.is_default]]"> $i18n{handlerSetDefault} </button> - <button slot="item" class="dropdown-item" on-click="onRemoveClick_" + <button class="dropdown-item" on-click="onRemoveClick_" id="removeButton"> $i18n{handlerRemove} </button>
diff --git a/chrome/browser/resources/settings/site_settings/site_data_entry.html b/chrome/browser/resources/settings/site_settings/site_data_entry.html index 57b51aa5..27b5081b 100644 --- a/chrome/browser/resources/settings/site_settings/site_data_entry.html +++ b/chrome/browser/resources/settings/site_settings/site_data_entry.html
@@ -2,9 +2,9 @@ <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> +<link rel="import" href="chrome://resources/html/cr/ui/focus_row_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> -<link rel="import" href="../focus_row_behavior.html"> <link rel="import" href="../settings_shared_css.html"> <link rel="import" href="../site_favicon.html"> <link rel="import" href="cookie_info.html">
diff --git a/chrome/browser/resources/settings/site_settings/site_data_entry.js b/chrome/browser/resources/settings/site_settings/site_data_entry.js index 31a5961..0c5e30c2 100644 --- a/chrome/browser/resources/settings/site_settings/site_data_entry.js +++ b/chrome/browser/resources/settings/site_settings/site_data_entry.js
@@ -11,7 +11,7 @@ is: 'site-data-entry', behaviors: [ - FocusRowBehavior, + cr.ui.FocusRowBehavior, I18nBehavior, ],
diff --git a/chrome/browser/resources/settings/site_settings/site_entry.html b/chrome/browser/resources/settings/site_settings/site_entry.html index d2492539..fffb85e 100644 --- a/chrome/browser/resources/settings/site_settings/site_entry.html +++ b/chrome/browser/resources/settings/site_settings/site_entry.html
@@ -123,7 +123,7 @@ <cr-lazy-render id="menu"> <template> <cr-action-menu> - <button slot="item" class="dropdown-item" role="menuitem" + <button class="dropdown-item" role="menuitem" on-click="onConfirmResetSettings_"> Reset permissions </button>
diff --git a/chrome/browser/resources/settings/site_settings/site_list.html b/chrome/browser/resources/settings/site_settings/site_list.html index 4c3410f1..8dea483 100644 --- a/chrome/browser/resources/settings/site_settings/site_list.html +++ b/chrome/browser/resources/settings/site_settings/site_list.html
@@ -40,24 +40,24 @@ </div> <cr-action-menu> - <button slot="item" class="dropdown-item" id="allow" + <button class="dropdown-item" id="allow" on-click="onAllowTap_" hidden$="[[!showAllowAction_]]"> $i18n{siteSettingsActionAllow} </button> - <button slot="item" class="dropdown-item" id="block" + <button class="dropdown-item" id="block" on-click="onBlockTap_" hidden$="[[!showBlockAction_]]"> $i18n{siteSettingsActionBlock} </button> - <button slot="item" class="dropdown-item" id="sessionOnly" + <button class="dropdown-item" id="sessionOnly" on-click="onSessionOnlyTap_" hidden$="[[!showSessionOnlyActionForSite_(actionMenuSite_)]]"> $i18n{siteSettingsActionSessionOnly} </button> - <button slot="item" class="dropdown-item" id="edit" + <button class="dropdown-item" id="edit" on-click="onEditTap_"> $i18n{edit} </button> - <button slot="item" class="dropdown-item" id="reset" + <button class="dropdown-item" id="reset" on-click="onResetTap_"> $i18n{siteSettingsActionReset} </button>
diff --git a/chrome/browser/resources/settings/site_settings/site_list_entry.html b/chrome/browser/resources/settings/site_settings/site_list_entry.html index 5136958..d7df7709 100644 --- a/chrome/browser/resources/settings/site_settings/site_list_entry.html +++ b/chrome/browser/resources/settings/site_settings/site_list_entry.html
@@ -2,10 +2,10 @@ <link rel="import" href="chrome://resources/cr_elements/icons.html"> <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html"> +<link rel="import" href="chrome://resources/html/cr/ui/focus_row_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/web-animations.html"> -<link rel="import" href="../focus_row_behavior.html"> <link rel="import" href="../i18n_setup.html"> <link rel="import" href="../icons.html"> <link rel="import" href="../route.html">
diff --git a/chrome/browser/resources/settings/site_settings/site_list_entry.js b/chrome/browser/resources/settings/site_settings/site_list_entry.js index 68436f2..f972964 100644 --- a/chrome/browser/resources/settings/site_settings/site_list_entry.js +++ b/chrome/browser/resources/settings/site_settings/site_list_entry.js
@@ -11,7 +11,7 @@ behaviors: [ SiteSettingsBehavior, - FocusRowBehavior, + cr.ui.FocusRowBehavior, ], properties: {
diff --git a/chrome/browser/resources/settings/site_settings/usb_devices.html b/chrome/browser/resources/settings/site_settings/usb_devices.html index 1c6c79d8..27a4f9c4 100644 --- a/chrome/browser/resources/settings/site_settings/usb_devices.html +++ b/chrome/browser/resources/settings/site_settings/usb_devices.html
@@ -43,7 +43,7 @@ </template> <cr-action-menu> - <button id="removeButton" slot="item" class="dropdown-item" + <button id="removeButton" class="dropdown-item" on-click="onRemoveTap_"> $i18n{handlerRemove} </button>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/BUILD.gn b/chrome/browser/resources/welcome/onboarding_welcome/BUILD.gn index fc918b2..bfaba34 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/BUILD.gn +++ b/chrome/browser/resources/welcome/onboarding_welcome/BUILD.gn
@@ -55,6 +55,7 @@ ":navigation_behavior", ":welcome_browser_proxy", "./set_as_default/:nux_set_as_default_proxy", + "./shared:bookmark_proxy", "./shared:nux_types", "//ui/webui/resources/cr_elements/cr_view_manager:cr_view_manager", "//ui/webui/resources/js:cr",
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/BUILD.gn b/chrome/browser/resources/welcome/onboarding_welcome/email/BUILD.gn index 8bfac0ad..cb447f4 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/email/BUILD.gn +++ b/chrome/browser/resources/welcome/onboarding_welcome/email/BUILD.gn
@@ -13,6 +13,7 @@ js_library("nux_email") { deps = [ + ":email_chooser", "../:navigation_behavior", "../shared:nux_types", ] @@ -23,6 +24,7 @@ ":nux_email_proxy", "../:navigation_behavior", "../shared:bookmark_proxy", + "../shared:module_metrics_proxy", "../shared:nux_types", "//third_party/polymer/v1_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer-extracted", "//ui/webui/resources/js:cr",
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.html b/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.html index 332e83a6..ba8b7929 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.html
@@ -1,8 +1,8 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> -<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> +<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-announcer/iron-a11y-announcer.html"> @@ -46,13 +46,6 @@ url(chrome://welcome/images/outlook_1x.png) 1x, url(chrome://welcome/images/outlook_2x.png) 2x); } - - iron-icon[icon='cr:chevron-right'] { - height: 20px; - margin-left: 6px; - margin-right: -10px; - width: 20px; - } </style> <template is="dom-repeat" items="[[emailList_]]">
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.js b/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.js index 0d0aa1d..2223513 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/email/email_chooser.js
@@ -27,8 +27,6 @@ */ emailList_: Array, - bookmarkBarWasShown: Boolean, - /** @private */ finalized_: Boolean, @@ -38,7 +36,6 @@ /** @private {?nuxEmail.EmailProviderModel} */ selectedEmailProvider_: { type: Object, - value: () => null, observer: 'onSelectedEmailProviderChange_', }, }, @@ -49,6 +46,18 @@ /** @private {nux.BookmarkProxy} */ bookmarkProxy_: null, + /** @private {nux.BookmarkBarManager} */ + bookmarkBarManager_: null, + + /** @private {boolean} */ + wasBookmarkBarShownOnInit_: false, + + /** @private {Promise} */ + listInitialized_: null, + + /** @private {?nux.ModuleMetricsManager} */ + metricsManager_: null, + /** @override */ attached: function() { Polymer.RenderStatus.afterNextRender(this, function() { @@ -60,49 +69,61 @@ ready: function() { this.emailProxy_ = nux.NuxEmailProxyImpl.getInstance(); this.bookmarkProxy_ = nux.BookmarkProxyImpl.getInstance(); + this.bookmarkBarManager_ = nux.BookmarkBarManager.getInstance(); + this.metricsManager_ = + new nux.ModuleMetricsManager(nux.EmailMetricsProxyImpl.getInstance()); - this.emailProxy_.recordPageInitialized(); - this.emailProxy_.getEmailList().then(list => { + this.listInitialized_ = this.emailProxy_.getEmailList().then(list => { this.emailList_ = list; - - // Pre-select fist email provider. - this.selectedEmailProvider_ = this.emailList_[0]; }); window.addEventListener('beforeunload', () => { - // Only need to clean up if user didn't interact with the buttons. if (this.finalized_) return; - - if (this.selectedEmailProvider_) { - // TODO(hcarmona): metrics. - this.revertBookmark_(); - this.bookmarkProxy_.toggleBookmarkBar(this.bookmarkBarWasShown); - } - - this.emailProxy_.recordFinalize(); + this.cleanUp_(); + this.metricsManager_.recordNavigatedAway(); }); }, /** Initializes the section when navigated to. */ initializeSection: function() { + this.wasBookmarkBarShownOnInit_ = this.bookmarkBarManager_.getShown(); + this.metricsManager_.recordPageInitialized(); this.finalized_ = false; - if (this.selectedEmailProvider_) { - this.addBookmark_(this.selectedEmailProvider_); - this.bookmarkProxy_.toggleBookmarkBar(true); - } + + assert(this.listInitialized_); + this.listInitialized_.then(() => { + // If selectedEmailProvider_ was never initialized, and not explicitly + // cancelled by the user at some point (in which case it would be null), + // then default to the first option. + if (this.selectedEmailProvider_ === undefined) { + this.selectedEmailProvider_ = this.emailList_[0]; + } + + if (this.selectedEmailProvider_) { + this.addBookmark_(this.selectedEmailProvider_); + } + }); }, /** Finalizes the section when navigated away from. */ finalizeSection: function() { if (this.finalized_) return; + this.cleanUp_(); + this.metricsManager_.recordBrowserBackOrForward(); + }, + /** + * Removes any bookarks and hides the bookmark bar when finalizing. + * @private + */ + cleanUp_: function() { + this.finalized_ = true; if (this.selectedEmailProvider_) { - // TODO(hcarmona): metrics? this.revertBookmark_(); - this.bookmarkProxy_.toggleBookmarkBar(this.bookmarkBarWasShown); + this.bookmarkBarManager_.setShown(this.wasBookmarkBarShownOnInit_); } }, @@ -117,7 +138,7 @@ else this.selectedEmailProvider_ = e.model.item; - this.emailProxy_.recordClickedOption(); + this.metricsManager_.recordClickedOption(); }, /** @@ -159,7 +180,7 @@ emailProvider.bookmarkId = 'pending'; this.emailProxy_.cacheBookmarkIcon(emailProvider.id); - this.bookmarkProxy_.toggleBookmarkBar(true); + this.bookmarkBarManager_.setShown(true); this.bookmarkProxy_.addBookmark( { title: emailProvider.name, @@ -202,7 +223,7 @@ if (newEmail) this.addBookmark_(newEmail); else - this.bookmarkProxy_.toggleBookmarkBar(this.bookmarkBarWasShown); + this.bookmarkBarManager_.setShown(this.wasBookmarkBarShownOnInit_); // Announcements are mutually exclusive, so keeping separate. if (prevEmail && newEmail) { @@ -216,10 +237,8 @@ /** @private */ onNoThanksClicked_: function() { - this.finalized_ = true; - this.revertBookmark_(); - this.bookmarkProxy_.toggleBookmarkBar(this.bookmarkBarWasShown); - this.emailProxy_.recordNoThanks(); + this.cleanUp_(); + this.metricsManager_.recordNoThanks(); welcome.navigateToNextStep(); }, @@ -228,15 +247,13 @@ this.finalized_ = true; this.emailProxy_.recordProviderSelected( this.selectedEmailProvider_.id, this.emailList_.length); - this.emailProxy_.recordGetStarted(); - // TODO(scottchen): store the selected email provider URL somewhere to - // redirect to at the end. + this.metricsManager_.recordGetStarted(); welcome.navigateToNextStep(); }, /** @private */ onActionButtonClicked_: function() { if (this.$$('.action-button').disabled) - this.emailProxy_.recordClickedDisabledButton(); + this.metricsManager_.recordClickedDisabledButton(); }, });
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.html b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.html index bbe60e487..e03bcd23 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.html
@@ -2,7 +2,6 @@ <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="../navigation_behavior.html"> -<link rel="import" href="../shared/bookmark_proxy.html"> <link rel="import" href="email_chooser.html"> <dom-module id="nux-email"> @@ -29,10 +28,6 @@ margin: 0; margin-bottom: 48px; } - - #emailChooser { - color: var(--google-grey-900); - } </style> <div class="email-ask"> <div class="email-logo" alt=""></div>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.js b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.js index 4fa520cc..9bbb70e7 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email.js
@@ -12,36 +12,11 @@ indicatorModel: Object, }, - /** - * This element can receive an |onRouteChange| notification after it's - * detached. This will make it no-op. - * @private - */ - isDetached_: false, - - /** @override */ - detached: function() { - this.isDetached_ = true; + onRouteEnter: function() { + this.$.emailChooser.initializeSection(); }, - /** - * Elements can override onRouteChange to handle route changes. - * Overrides function in behavior. - * @param {!welcome.Routes} route - * @param {number} step - */ - onRouteChange: function(route, step) { - if (`step-${step}` == this.id) { - nux.BookmarkProxyImpl.getInstance().isBookmarkBarShown().then( - bookmarkBarShown => { - if (this.isDetached_) - return; - - this.$.emailChooser.bookmarkBarWasShown = bookmarkBarShown; - this.$.emailChooser.initializeSection(); - }); - } else { - this.$.emailChooser.finalizeSection(); - } + onRouteExit: function() { + this.$.emailChooser.finalizeSection(); }, });
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.html b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.html index c794af8..ee62604 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.html
@@ -1,3 +1,4 @@ <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://welcome/shared/i18n_setup.html"> -<script src="nux_email_proxy.js"></script> \ No newline at end of file +<link rel="import" href="chrome://welcome/shared/module_metrics_proxy.html"> +<script src="nux_email_proxy.js"></script>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.js b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.js index 4cfefe1..ec7ba19 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/email/nux_email_proxy.js
@@ -3,40 +3,10 @@ // found in the LICENSE file. cr.define('nux', function() { - // The metrics name corresponding to Nux EmailProvidersInteraction histogram. - const INTERACTION_METRIC_NAME = - 'FirstRun.NewUserExperience.EmailProvidersInteraction'; - - const SELECTION_METRIC_NAME = + const EMAIL_SELECTION_METRIC_NAME = 'FirstRun.NewUserExperience.EmailProvidersSelection'; - /** - * NuxEmailProvidersInteractions enum. - * These values are persisted to logs and should not be renumbered or re-used. - * See tools/metrics/histograms/enums.xml. - * @enum {number} - */ - const NuxEmailProvidersInteractions = { - PageShown: 0, - DidNothingAndNavigatedAway: 1, - DidNothingAndChoseSkip: 2, - ChoseAnOptionAndNavigatedAway: 3, - ChoseAnOptionAndChoseSkip: 4, - ChoseAnOptionAndChoseNext: 5, - ClickedDisabledNextButtonAndNavigatedAway: 6, - ClickedDisabledNextButtonAndChoseSkip: 7, - ClickedDisabledNextButtonAndChoseNext: 8, - }; - - /** - * The number of enum values in NuxEmailProvidersInteractions. This should - * be kept in sync with the enum count in tools/metrics/histograms/enums.xml. - * @type {number} - */ - const INTERACTION_METRIC_COUNT = - Object.keys(NuxEmailProvidersInteractions).length; - /** @interface */ class NuxEmailProxy { /** @@ -55,35 +25,17 @@ /** @return {number} */ getSavedProvider() {} - recordPageInitialized() {} - - recordClickedOption() {} - - recordClickedDisabledButton() {} - /** * @param {number} providerId This should match one of the histogram enum * value for NuxEmailProvidersSelections. * @param {number} length */ recordProviderSelected(providerId, length) {} - - recordNoThanks() {} - - recordGetStarted() {} - - recordFinalize() {} } /** @implements {nux.NuxEmailProxy} */ class NuxEmailProxyImpl { constructor() { - /** @private {string} */ - this.firstPart = ''; - - /** @private {string} */ - this.lastPart = ''; - /** @private {number} */ this.savedProvider_; } @@ -104,63 +56,12 @@ } /** @override */ - recordPageInitialized() { - chrome.metricsPrivate.recordEnumerationValue( - INTERACTION_METRIC_NAME, NuxEmailProvidersInteractions.PageShown, - INTERACTION_METRIC_COUNT); - - // These two flags are used at the end to determine what to record in - // metrics. Their values should map to first or last half of an enum - // name within NuxEmailProvidersInteractions. - this.firstPart = 'DidNothing'; - this.lastPart = 'AndNavigatedAway'; - } - - /** @override */ - recordClickedOption() { - // Only overwrite this.firstPart if it's not overwritten already - if (this.firstPart == 'DidNothing') - this.firstPart = 'ChoseAnOption'; - } - - /** @override */ - recordClickedDisabledButton() { - // Only overwrite this.firstPart if it's not overwritten already - if (this.firstPart == 'DidNothing') - this.firstPart = 'ClickedDisabledNextButton'; - } - - /** @override */ recordProviderSelected(providerId, length) { this.savedProvider_ = providerId; chrome.metricsPrivate.recordEnumerationValue( - SELECTION_METRIC_NAME, providerId, + EMAIL_SELECTION_METRIC_NAME, providerId, loadTimeData.getInteger('email_providers_enum_count')); } - - /** @override */ - recordNoThanks() { - this.lastPart = 'AndChoseSkip'; - this.recordFinalize(); - } - - /** @override */ - recordGetStarted() { - this.lastPart = 'AndChoseNext'; - this.recordFinalize(); - } - - /** @override */ - recordFinalize() { - let finalValue = this.firstPart + this.lastPart; - - // TODO(hcarmona): revisit this metric. - let metric = NuxEmailProvidersInteractions[finalValue]; - if (metric) { - chrome.metricsPrivate.recordEnumerationValue( - INTERACTION_METRIC_NAME, metric, INTERACTION_METRIC_COUNT); - } - } } cr.addSingletonGetter(NuxEmailProxyImpl);
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/BUILD.gn b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/BUILD.gn index edbcb37..505478a 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/BUILD.gn +++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/BUILD.gn
@@ -13,7 +13,10 @@ js_library("apps_chooser") { deps = [ + ":nux_google_apps_proxy", "../shared:bookmark_proxy", + "../shared:module_metrics_proxy", + "../shared:step_indicator", "//third_party/polymer/v1_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer-extracted", "//ui/webui/resources/js:cr", "//ui/webui/resources/js:i18n_behavior", @@ -23,10 +26,8 @@ js_library("nux_google_apps") { deps = [ ":apps_chooser", - ":nux_google_apps_proxy", "../:navigation_behavior", "../shared:nux_types", - "../shared:step_indicator", ] }
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.html b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.html index c9753e3..e2f36f2 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.html
@@ -1,19 +1,22 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/cr_elements/icons.html"> +<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-announcer/iron-a11y-announcer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> -<link rel="import" href="chrome://welcome/google_apps/nux_google_apps_proxy.html"> -<link rel="import" href="chrome://welcome/shared/bookmark_proxy.html"> -<link rel="import" href="chrome://welcome/shared/chooser_shared_css.html"> +<link rel="import" href="../navigation_behavior.html"> +<link rel="import" href="../shared/bookmark_proxy.html"> +<link rel="import" href="../shared/chooser_shared_css.html"> +<link rel="import" href="../shared/step_indicator.html"> +<link rel="import" href="nux_google_apps_proxy.html"> <dom-module id="apps-chooser"> <template> - <style include="chooser-shared-css"> + <style include="chooser-shared-css paper-button-style"> .gmail { content: -webkit-image-set( url(chrome://welcome/images/gmail_1x.png) 1x, @@ -62,6 +65,18 @@ <iron-icon icon="cr:check"></iron-icon> </button> </template> + + <div class="button-bar"> + <paper-button on-click="onNoThanksClicked_"> + $i18n{skip} + </paper-button> + <step-indicator model="[[indicatorModel]]"></step-indicator> + <paper-button class="action-button" disabled$="[[!hasAppsSelected_]]" + on-click="onGetStartedClicked_"> + $i18n{next} + <iron-icon icon="cr:chevron-right"></iron-icon> + </paper-button> + </div> </template> <script src="apps_chooser.js"></script> </dom-module>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js index 88ab76e7..b8234d5 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/apps_chooser.js
@@ -30,27 +30,40 @@ behaviors: [I18nBehavior], properties: { + /** @type {nux.stepIndicatorModel} */ + indicatorModel: Object, + /** * @type {!Array<!nuxGoogleApps.AppItem>} * @private */ appList_: Array, - bookmarkBarWasShown: Boolean, - - hasAppsSelected: { + hasAppsSelected_: { type: Boolean, notify: true, value: true, }, }, + /** @private */ + finalized_: false, + /** @private {nux.NuxGoogleAppsProxy} */ appsProxy_: null, /** @private {nux.BookmarkProxy} */ bookmarkProxy_: null, + /** @private {nux.BookmarkBarManager} */ + bookmarkBarManager_: null, + + /** @private {?nux.ModuleMetricsManager} */ + metricsManager_: null, + + /** @private {boolean} */ + wasBookmarkBarShownOnInit_: false, + /** @override */ attached: function() { Polymer.RenderStatus.afterNextRender(this, () => { @@ -62,10 +75,54 @@ ready() { this.appsProxy_ = nux.NuxGoogleAppsProxyImpl.getInstance(); this.bookmarkProxy_ = nux.BookmarkProxyImpl.getInstance(); + this.bookmarkBarManager_ = nux.BookmarkBarManager.getInstance(); + this.metricsManager_ = new nux.ModuleMetricsManager( + nux.GoogleAppsMetricsProxyImpl.getInstance()); + + window.addEventListener('beforeunload', () => { + if (this.finalized_) + return; + this.cleanUp_(); + this.metricsManager_.recordNavigatedAway(); + }); + }, + + initializeSection() { + this.finalized_ = false; + this.metricsManager_.recordPageInitialized(); + this.populateAllBookmarks(); + }, + + finalizeSection() { + if (this.finalized_) + return; + this.cleanUp_(); + this.metricsManager_.recordBrowserBackOrForward(); + }, + + /** @private */ + onNoThanksClicked_: function() { + this.cleanUp_(); + this.metricsManager_.recordNoThanks(); + welcome.navigateToNextStep(); + }, + + /** @private */ + onGetStartedClicked_: function() { + this.finalized_ = true; + this.appList_.forEach(app => { + if (app.selected) { + this.appsProxy_.recordProviderSelected(app.id); + } + }); + this.metricsManager_.recordGetStarted(); + welcome.navigateToNextStep(); }, /** Called when bookmarks should be created for all selected apps. */ populateAllBookmarks() { + this.wasBookmarkBarShownOnInit_ = this.bookmarkBarManager_.getShown(); + if (this.appList_) { this.appList_.forEach(app => this.updateBookmark(app)); } else { @@ -82,15 +139,21 @@ } }, - /** Called when bookmarks should be removed for all selected apps. */ - removeAllBookmarks() { + /** + * Called when bookmarks should be removed for all selected apps. + * @private + */ + cleanUp_() { + this.finalized_ = true; + if (!this.appList_) return; // No apps to remove. let removedBookmarks = false; this.appList_.forEach(app => { if (app.selected && app.bookmarkId) { - // Don't call |updateBookmark| b/c we want to save the selection. + // Don't call |updateBookmark| b/c we want to save the selection in the + // event of a browser back/forward. this.bookmarkProxy_.removeBookmark(app.bookmarkId); app.bookmarkId = null; removedBookmarks = true; @@ -98,7 +161,7 @@ }); // Only update and announce if we removed bookmarks. if (removedBookmarks) { - this.bookmarkProxy_.toggleBookmarkBar(this.bookmarkBarWasShown); + this.bookmarkBarManager_.setShown(this.wasBookmarkBarShownOnInit_); this.fire('iron-announce', {text: this.i18n('bookmarksRemoved')}); } }, @@ -109,7 +172,7 @@ */ updateBookmark(item) { if (item.selected && !item.bookmarkId) { - this.bookmarkProxy_.toggleBookmarkBar(true); + this.bookmarkBarManager_.setShown(true); this.bookmarkProxy_.addBookmark( { title: item.name, @@ -137,6 +200,9 @@ e.model.set('item.selected', !item.selected); this.updateBookmark(item); this.updateHasAppsSelected(); + + this.metricsManager_.recordClickedOption(); + // Announcements should NOT be in |updateBookmark| because there should be a // different utterance when all app bookmarks are added/removed. if (item.selected) @@ -162,12 +228,13 @@ }, /** - * Updates the value of hasAppsSelected. + * Updates the value of hasAppsSelected_. * @private */ updateHasAppsSelected: function() { - this.hasAppsSelected = this.appList_ && this.appList_.some(a => a.selected); - if (!this.hasAppsSelected) - this.bookmarkProxy_.toggleBookmarkBar(this.bookmarkBarWasShown); + this.hasAppsSelected_ = + this.appList_ && this.appList_.some(a => a.selected); + if (!this.hasAppsSelected_) + this.bookmarkBarManager_.setShown(this.wasBookmarkBarShownOnInit_); }, });
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html index 272ef13..b0612cac 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.html
@@ -1,21 +1,14 @@ <link rel="import" href="chrome://resources/html/polymer.html"> -<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="../navigation_behavior.html"> -<link rel="import" href="../shared/bookmark_proxy.html"> -<link rel="import" href="../shared/step_indicator.html"> <link rel="import" href="apps_chooser.html"> -<link rel="import" href="nux_google_apps_proxy.html"> <dom-module id="nux-google-apps"> <template> - <style include="paper-button-style"> + <style> .apps-ask { - margin-left: auto; - margin-right: auto; - width: fit-content; + text-align: center; } .chrome-logo { @@ -23,58 +16,25 @@ url(chrome://welcome/images/google_apps_1x.png) 1x, url(chrome://welcome/images/google_apps_2x.png) 2x); height: 38px; + margin: auto; margin-bottom: 16px; - margin-left: auto; - margin-right: auto; width: 42px; } h1 { - color: var(--cr-primary-text-color); - font-size: 24px; + color: var(--google-grey-900); + font-size: 1.5rem; font-weight: 500; + margin: 0; margin-bottom: 48px; - opacity: .8; - text-align: center; - } - - apps-chooser { - color: var(--cr-primary-text-color); - font-size: 14px; - margin-bottom: 64px; - } - - .button-bar { - display: flex; - justify-content: space-between; - } - - iron-icon[icon='cr:chevron-right'] { - height: 20px; - margin-left: 6px; - margin-right: -10px; - width: 20px; } </style> <div class="apps-ask"> - <div class="chrome-logo"></div> + <div class="chrome-logo" alt=""></div> <h1>$i18n{googleAppsDescription}</h1> - - <apps-chooser id="appChooser" has-apps-selected="{{hasAppsSelected_}}"> + <apps-chooser id="appChooser" indicator-model="[[indicatorModel]]"> </apps-chooser> - - <div class="button-bar"> - <paper-button on-click="onNoThanksClicked_"> - $i18n{skip} - </paper-button> - <step-indicator model="[[indicatorModel]]"></step-indicator> - <paper-button class="action-button" disabled$="[[!hasAppsSelected_]]" - on-click="onGetStartedClicked_"> - $i18n{next} - <iron-icon icon="cr:chevron-right"></iron-icon> - </paper-button> - </div> </div> </template> <script src="nux_google_apps.js"></script>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.js b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.js index f4ef4c3..c0db602 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps.js
@@ -8,59 +8,15 @@ behaviors: [welcome.NavigationBehavior], properties: { - /** @private */ - hasAppsSelected_: Boolean, - /** @type {nux.stepIndicatorModel} */ indicatorModel: Object, }, - /** @private */ - finalized_: false, - - /** @override */ - ready: function() { - window.addEventListener('beforeunload', () => { - if (this.finalized_) - return; - // TODO(hcarmona): Add metrics. - this.$.appChooser.removeAllBookmarks(); - }); + onRouteEnter: function() { + this.$.appChooser.initializeSection(); }, - /** - * Elements can override onRouteChange to handle route changes. - * Overrides function in behavior. - * @param {!welcome.Routes} route - * @param {number} step - */ - onRouteChange: function(route, step) { - if (`step-${step}` == this.id) { - this.finalized_ = false; - nux.BookmarkProxyImpl.getInstance().isBookmarkBarShown().then( - bookmarkBarShown => { - this.$.appChooser.bookmarkBarWasShown = bookmarkBarShown; - }); - this.$.appChooser.populateAllBookmarks(); - } else { - if (this.finalized_) - return; - // TODO(hcarmona): Add metrics? - this.$.appChooser.removeAllBookmarks(); - } - }, - - /** @private */ - onNoThanksClicked_: function() { - // TODO(hcarmona): Add metrics. - this.$.appChooser.removeAllBookmarks(); - welcome.navigateToNextStep(); - }, - - /** @private */ - onGetStartedClicked_: function() { - // TODO(hcarmona): Add metrics. - this.finalized_ = true; - welcome.navigateToNextStep(); + onRouteExit: function() { + this.$.appChooser.finalizeSection(); }, });
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps_proxy.js b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps_proxy.js index 8ecc1087..9ea9b07 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps_proxy.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/google_apps/nux_google_apps_proxy.js
@@ -3,6 +3,26 @@ // found in the LICENSE file. cr.define('nux', function() { + // The metrics name corresponding to Nux EmailProvidersInteraction histogram. + const GOOGLE_APPS_SELECTION_METRIC_NAME = + 'FirstRun.NewUserExperience.GoogleAppsSelection'; + + /** + * NuxGoogleAppsSelections enum. + * These values are persisted to logs and should not be renumbered or + * re-used. + * See tools/metrics/histograms/enums.xml. + * @enum {number} + */ + const NuxGoogleAppsSelections = { + Gmail_DEPRECATED: 0, + YouTube: 1, + Maps: 2, + Translate: 3, + News: 4, + ChromeWebStore: 5, + }; + /** @interface */ class NuxGoogleAppsProxy { /** @@ -17,6 +37,12 @@ * @return {!Promise<!Array<!nux.BookmarkListItem>>} */ getGoogleAppsList() {} + + /** + * @param {number} providerId This should match one of the histogram enum + * value for NuxGoogleAppsSelections. + */ + recordProviderSelected(providerId) {} } /** @implements {nux.NuxGoogleAppsProxy} */ @@ -30,6 +56,13 @@ getGoogleAppsList() { return cr.sendWithPromise('getGoogleAppsList'); } + + /** @override */ + recordProviderSelected(providerId) { + chrome.metricsPrivate.recordEnumerationValue( + GOOGLE_APPS_SELECTION_METRIC_NAME, providerId, + Object.keys(NuxGoogleAppsSelections).length); + } } cr.addSingletonGetter(NuxGoogleAppsProxyImpl);
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/navigation_behavior.js b/chrome/browser/resources/welcome/onboarding_welcome/navigation_behavior.js index c05b43b..9da918e 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/navigation_behavior.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/navigation_behavior.js
@@ -52,14 +52,36 @@ /** @type {!Set<!PolymerElement>} */ const routeObservers = new Set(); + /** @type {?PolymerElement} */ + let currentRouteElement; + // Notifies all the elements that extended NavigationBehavior. function notifyObservers() { + if (currentRouteElement) { + (/** @type {{onRouteExit: Function}} */ (currentRouteElement)) + .onRouteExit(); + currentRouteElement = null; + } + const route = /** @type {!welcome.Routes} */ (history.state.route); const step = history.state.step; routeObservers.forEach((observer) => { (/** @type {{onRouteChange: Function}} */ (observer)) .onRouteChange(route, step); + + // Modules are only attached to DOM if they're for the current route, so + // as long as the id of an element matches up to the current step, it + // means that element is for the current route. + if (observer.id == `step-${step}`) { + currentRouteElement = observer; + } }); + + // If currentRouteElement is not null, it means there was a new route. + if (currentRouteElement) { + (/** @type {{onRouteEnter: Function}} */ (currentRouteElement)) + .onRouteEnter(); + } } // Notifies all elements when browser history is popped. @@ -95,18 +117,35 @@ notifyObservers(); } - /** @polymerBehavior */ + /** + * Elements can override onRoute(Change|Enter|Exit) to handle route changes. + * Order of hooks being called: + * 1) onRouteExit() on the old route + * 2) onRouteChange() on all subscribed routes + * 3) onRouteEnter() on the new route + * + * @polymerBehavior + */ const NavigationBehavior = { /** @override */ attached: function() { assert(!routeObservers.has(this)); routeObservers.add(this); + const route = /** @type {!welcome.Routes} */ (history.state.route); + const step = history.state.step; + // history state was set when page loaded, so when the element first // attaches, call the route-change handler to initialize first. - this.onRouteChange( - /** @type {!welcome.Routes} */ (history.state.route), - history.state.step); + this.onRouteChange(route, step); + + // Modules are only attached to DOM if they're for the current route, so + // as long as the id of an element matches up to the current step, it + // means that element is for the current route. + if (this.id == `step-${step}`) { + currentRouteElement = this; + this.onRouteEnter(); + } }, /** @override */ @@ -115,11 +154,14 @@ }, /** - * Elements can override onRouteChange to handle route changes. * @param {!welcome.Routes} route * @param {number} step */ onRouteChange: function(route, step) {}, + + onRouteEnter: function() {}, + + onRouteExit: function() {}, }; return {
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd b/chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd index 69cd40d..de6e2fd 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd +++ b/chrome/browser/resources/welcome/onboarding_welcome/onboarding_welcome_resources.grd
@@ -91,6 +91,12 @@ <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_I18N_SETUP_HTML" file="shared\i18n_setup.html" type="chrome_html" /> + <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_MODULE_METRICS_PROXY_HTML" + file="shared\module_metrics_proxy.html" + type="chrome_html" /> + <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_MODULE_METRICS_PROXY_JS" + file="shared\module_metrics_proxy.js" + type="chrome_html" /> <structure name="IDR_WELCOME_ONBOARDING_WELCOME_SHARED_ONBOARDING_BACKGROUND_HTML" file="shared\onboarding_background.html" type="chrome_html" />
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/shared/BUILD.gn b/chrome/browser/resources/welcome/onboarding_welcome/shared/BUILD.gn index cbc5a669..d2c36998 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/shared/BUILD.gn +++ b/chrome/browser/resources/welcome/onboarding_welcome/shared/BUILD.gn
@@ -22,6 +22,13 @@ ] } +js_library("module_metrics_proxy") { + deps = [ + "//ui/webui/resources/js:cr", + ] + externs_list = [ "$externs_path/metrics_private.js" ] +} + js_library("nux_types") { deps = [ "//ui/webui/resources/js:cr",
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/shared/bookmark_proxy.js b/chrome/browser/resources/welcome/onboarding_welcome/shared/bookmark_proxy.js index d178982..d7a4da7 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/shared/bookmark_proxy.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/shared/bookmark_proxy.js
@@ -55,8 +55,38 @@ cr.addSingletonGetter(BookmarkProxyImpl); + // Wrapper for bookmark proxy to keep some additional states. + class BookmarkBarManager { + constructor() { + /** @private {nux.BookmarkProxy} */ + this.proxy_ = BookmarkProxyImpl.getInstance(); + + /** @private {boolean} */ + this.isBarShown_ = false; + + /** @type {!Promise} */ + this.initialized = this.proxy_.isBookmarkBarShown().then(shown => { + this.isBarShown_ = shown; + }); + } + + /** @return {boolean} */ + getShown() { + return this.isBarShown_; + } + + /** @param {boolean} show */ + setShown(show) { + this.isBarShown_ = show; + this.proxy_.toggleBookmarkBar(show); + } + } + + cr.addSingletonGetter(BookmarkBarManager); + return { BookmarkProxy: BookmarkProxy, BookmarkProxyImpl: BookmarkProxyImpl, + BookmarkBarManager: BookmarkBarManager, }; });
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/shared/chooser_shared_css.html b/chrome/browser/resources/welcome/onboarding_welcome/shared/chooser_shared_css.html index f2c00eb..6e9a3ac 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/shared/chooser_shared_css.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/shared/chooser_shared_css.html
@@ -6,6 +6,7 @@ <template> <style> :host { + color: var(--google-grey-900); display: block; white-space: nowrap; } @@ -98,6 +99,13 @@ justify-content: space-between; margin-top: 64px; } + + iron-icon[icon='cr:chevron-right'] { + height: 20px; + margin-left: 6px; + margin-right: -10px; + width: 20px; + } </style> </template> </dom-module>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/shared/module_metrics_proxy.html b/chrome/browser/resources/welcome/onboarding_welcome/shared/module_metrics_proxy.html new file mode 100644 index 0000000..5c10f794 --- /dev/null +++ b/chrome/browser/resources/welcome/onboarding_welcome/shared/module_metrics_proxy.html
@@ -0,0 +1,2 @@ +<link rel="import" href="chrome://resources/html/cr.html"> +<script src="module_metrics_proxy.js"></script>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/shared/module_metrics_proxy.js b/chrome/browser/resources/welcome/onboarding_welcome/shared/module_metrics_proxy.js new file mode 100644 index 0000000..f2bf5d5 --- /dev/null +++ b/chrome/browser/resources/welcome/onboarding_welcome/shared/module_metrics_proxy.js
@@ -0,0 +1,260 @@ +// 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. + +cr.define('nux', function() { + /** @interface */ + class ModuleMetricsProxy { + recordPageShown() {} + + recordDidNothingAndNavigatedAway() {} + + recordDidNothingAndChoseSkip() {} + + recordDidNothingAndChoseNext() {} + + recordChoseAnOptionAndNavigatedAway() {} + + recordChoseAnOptionAndChoseSkip() {} + + recordChoseAnOptionAndChoseNext() {} + + recordClickedDisabledNextButtonAndNavigatedAway() {} + + recordClickedDisabledNextButtonAndChoseSkip() {} + + recordClickedDisabledNextButtonAndChoseNext() {} + + recordNavigatedAwayThroughBrowserHistory() {} + } + + /** @implements {nux.ModuleMetricsProxy} */ + class ModuleMetricsProxyImpl { + /** + * @param {string} histogramName The histogram that will record the module + * navigation metrics. + */ + constructor(histogramName, interactions) { + /** @private {string} */ + this.interactionMetric_ = histogramName; + this.interactions_ = interactions; + } + + /** @override */ + recordPageShown() { + chrome.metricsPrivate.recordEnumerationValue( + this.interactionMetric_, this.interactions_.PageShown, + Object.keys(this.interactions_).length); + } + + /** @override */ + recordDidNothingAndNavigatedAway() { + chrome.metricsPrivate.recordEnumerationValue( + this.interactionMetric_, + this.interactions_.DidNothingAndNavigatedAway, + Object.keys(this.interactions_).length); + } + + /** @override */ + recordDidNothingAndChoseSkip() { + chrome.metricsPrivate.recordEnumerationValue( + this.interactionMetric_, this.interactions_.DidNothingAndChoseSkip, + Object.keys(this.interactions_).length); + } + + /** @override */ + recordDidNothingAndChoseNext() { + chrome.metricsPrivate.recordEnumerationValue( + this.interactionMetric_, this.interactions_.DidNothingAndChoseNext, + Object.keys(this.interactions_).length); + } + + /** @override */ + recordChoseAnOptionAndNavigatedAway() { + chrome.metricsPrivate.recordEnumerationValue( + this.interactionMetric_, + this.interactions_.ChoseAnOptionAndNavigatedAway, + Object.keys(this.interactions_).length); + } + + /** @override */ + recordChoseAnOptionAndChoseSkip() { + chrome.metricsPrivate.recordEnumerationValue( + this.interactionMetric_, this.interactions_.ChoseAnOptionAndChoseSkip, + Object.keys(this.interactions_).length); + } + + /** @override */ + recordChoseAnOptionAndChoseNext() { + chrome.metricsPrivate.recordEnumerationValue( + this.interactionMetric_, this.interactions_.ChoseAnOptionAndChoseNext, + Object.keys(this.interactions_).length); + } + + /** @override */ + recordClickedDisabledNextButtonAndNavigatedAway() { + chrome.metricsPrivate.recordEnumerationValue( + this.interactionMetric_, + this.interactions_.ClickedDisabledNextButtonAndNavigatedAway, + Object.keys(this.interactions_).length); + } + + /** @override */ + recordClickedDisabledNextButtonAndChoseSkip() { + chrome.metricsPrivate.recordEnumerationValue( + this.interactionMetric_, + this.interactions_.ClickedDisabledNextButtonAndChoseSkip, + Object.keys(this.interactions_).length); + } + + /** @override */ + recordClickedDisabledNextButtonAndChoseNext() { + chrome.metricsPrivate.recordEnumerationValue( + this.interactionMetric_, + this.interactions_.ClickedDisabledNextButtonAndChoseNext, + Object.keys(this.interactions_).length); + } + + /** @override */ + recordNavigatedAwayThroughBrowserHistory() { + chrome.metricsPrivate.recordEnumerationValue( + this.interactionMetric_, + this.interactions_.NavigatedAwayThroughBrowserHistory, + Object.keys(this.interactions_).length); + } + } + + class ModuleMetricsManager { + /** @param {nux.ModuleMetricsProxy} metricsProxy */ + constructor(metricsProxy) { + this.metricsProxy_ = metricsProxy; + + this.options_ = { + didNothing: { + andNavigatedAway: metricsProxy.recordDidNothingAndNavigatedAway, + andChoseSkip: metricsProxy.recordDidNothingAndChoseSkip, + andChoseNext: metricsProxy.recordDidNothingAndChoseNext, + }, + choseAnOption: { + andNavigatedAway: metricsProxy.recordChoseAnOptionAndNavigatedAway, + andChoseSkip: metricsProxy.recordChoseAnOptionAndChoseSkip, + andChoseNext: metricsProxy.recordChoseAnOptionAndChoseNext, + }, + clickedDisabledNextButton: { + andNavigatedAway: + metricsProxy.recordClickedDisabledNextButtonAndNavigatedAway, + andChoseSkip: + metricsProxy.recordClickedDisabledNextButtonAndChoseSkip, + andChoseNext: + metricsProxy.recordClickedDisabledNextButtonAndChoseNext, + }, + }; + + this.firstPart = this.options_.didNothing; + } + + recordPageInitialized() { + this.metricsProxy_.recordPageShown(); + this.firstPart = this.options_.didNothing; + } + + recordClickedOption() { + // Only overwrite this.firstPart if it's not overwritten already + if (this.firstPart == this.options_.didNothing) + this.firstPart = this.options_.choseAnOption; + } + + recordClickedDisabledButton() { + // Only overwrite this.firstPart if it's not overwritten already + if (this.firstPart == this.options_.didNothing) + this.firstPart = this.options_.clickedDisabledNextButton; + } + + recordNoThanks() { + this.firstPart.andChoseSkip.call(this.metricsProxy_); + } + + recordGetStarted() { + this.firstPart.andChoseNext.call(this.metricsProxy_); + } + + recordNavigatedAway() { + this.firstPart.andNavigatedAway.call(this.metricsProxy_); + } + + recordBrowserBackOrForward() { + this.metricsProxy_.recordNavigatedAwayThroughBrowserHistory(); + } + } + + return { + ModuleMetricsProxy: ModuleMetricsProxy, + ModuleMetricsProxyImpl: ModuleMetricsProxyImpl, + ModuleMetricsManager: ModuleMetricsManager, + }; +}); + +// This is done outside |cr.define| because the closure compiler wants a fully +// qualified name for |nux.ModuleMetricsProxyImpl|. +nux.EmailMetricsProxyImpl = class extends nux.ModuleMetricsProxyImpl { + constructor() { + /** + * NuxEmailProvidersInteractions enum. + * These values are persisted to logs and should not be renumbered or + * re-used. + * See tools/metrics/histograms/enums.xml. + * @enum {number} + */ + const NuxEmailProvidersInteractions = { + PageShown: 0, + DidNothingAndNavigatedAway: 1, + DidNothingAndChoseSkip: 2, + ChoseAnOptionAndNavigatedAway: 3, + ChoseAnOptionAndChoseSkip: 4, + ChoseAnOptionAndChoseNext: 5, + ClickedDisabledNextButtonAndNavigatedAway: 6, + ClickedDisabledNextButtonAndChoseSkip: 7, + ClickedDisabledNextButtonAndChoseNext: 8, + DidNothingAndChoseNext: 9, + NavigatedAwayThroughBrowserHistory: 10, + }; + + super( + 'FirstRun.NewUserExperience.EmailProvidersInteraction', + NuxEmailProvidersInteractions); + } +}; + +nux.GoogleAppsMetricsProxyImpl = class extends nux.ModuleMetricsProxyImpl { + constructor() { + /** + * NuxGoogleAppsInteractions enum. + * These values are persisted to logs and should not be renumbered or + * re-used. + * See tools/metrics/histograms/enums.xml. + * @enum {number} + */ + const NuxGoogleAppsInteractions = { + PageShown: 0, + NotUsed_DEPRECATED: 1, + GetStarted_DEPRECATED: 2, + DidNothingAndNavigatedAway: 3, + DidNothingAndChoseSkip: 4, + ChoseAnOptionAndNavigatedAway: 5, + ChoseAnOptionAndChoseSkip: 6, + ChoseAnOptionAndChoseNext: 7, + ClickedDisabledNextButtonAndNavigatedAway: 8, + ClickedDisabledNextButtonAndChoseSkip: 9, + ClickedDisabledNextButtonAndChoseNext: 10, + DidNothingAndChoseNext: 11, + NavigatedAwayThroughBrowserHistory: 12, + }; + + super( + 'FirstRun.NewUserExperience.GoogleAppsProvidersInteraction', + NuxGoogleAppsInteractions); + } +}; + +cr.addSingletonGetter(nux.EmailMetricsProxyImpl); +cr.addSingletonGetter(nux.GoogleAppsMetricsProxyImpl);
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/signin_view.js b/chrome/browser/resources/welcome/onboarding_welcome/signin_view.js index 521f5bc..a78c04ef 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/signin_view.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/signin_view.js
@@ -46,12 +46,7 @@ /** @private */ onNoThanksClick_: function() { // It's safe to assume sign-view is always going to be the last step, so - // either go to the target url directly, or go to NTP directly. - const targetUrl = this.getTargetUrl_(); - if (targetUrl) { - this.welcomeBrowserProxy_.goToURL(targetUrl); - } else { - this.welcomeBrowserProxy_.goToNewTabPage(); - } + // go to the target url directly. If there's no target, it lands on NTP. + this.welcomeBrowserProxy_.handleUserDecline(this.getTargetUrl_()); } });
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.html b/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.html index 451ba5ef..b9cdeca 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.html
@@ -10,6 +10,7 @@ <link rel="import" href="navigation_behavior.html"> <link rel="import" href="set_as_default/nux_set_as_default.html"> <link rel="import" href="set_as_default/nux_set_as_default_proxy.html"> +<link rel="import" href="shared/bookmark_proxy.html"> <link rel="import" href="shared/i18n_setup.html"> <link rel="import" href="signin_view.html">
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.js b/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.js index 8fd75be..4ab89be 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/welcome_app.js
@@ -98,8 +98,8 @@ }; // If the route changed, initialize the steps of modules for that route. - if (this.currentRoute_ != route && route != welcome.Routes.LANDING) { - this.initializeModules(this.modules_[route]).then(setStep); + if (this.currentRoute_ != route) { + this.initializeModules(route).then(setStep); } else { setStep(); } @@ -107,45 +107,55 @@ this.currentRoute_ = route; }, - /** @param {!Array<string>} modules Array of valid DOM element names. */ - initializeModules: function(modules) { - assert(modules); // modules should be defined if on a valid route. + /** @param {welcome.Routes} route */ + initializeModules: function(route) { + // Remove all views except landing. + this.$.viewManager + .querySelectorAll('[slot="view"]:not([id="step-landing"])') + .forEach(element => element.remove()); - // Wait until the default-browser state is known before anything - // initializes. - return this.defaultCheckPromise_.promise.then(canSetDefault => { - if (!canSetDefault) - modules = modules.filter(module => module != 'nux-set-as-default'); + // If it is on landing route, end here. + if (route == welcome.Routes.LANDING) { + return Promise.resolve(); + } - // Remove all views except landing. - this.$.viewManager - .querySelectorAll('[slot="view"]:not([id="step-landing"])') - .forEach(element => { - element.remove(); + let modules = this.modules_[route]; + assert(modules); // Modules should be defined if on a valid route. + + // Wait until the default-browser state and bookmark visibility are known + // before anything initializes. + return Promise + .all([ + this.defaultCheckPromise_.promise, + nux.BookmarkBarManager.getInstance().initialized, + ]) + .then(args => { + const canSetDefault = args[0]; + if (!canSetDefault) + modules = modules.filter(module => module != 'nux-set-as-default'); + + const indicatorElementCount = modules.reduce((count, module) => { + return count += MODULES_NEEDING_INDICATOR.has(module) ? 1 : 0; + }, 0); + + let indicatorActiveCount = 0; + modules.forEach((elementTagName, index) => { + // Makes sure the module specified by the feature configuration is + // whitelisted. + assert(MODULES_WHITELIST.has(elementTagName)); + + const element = document.createElement(elementTagName); + element.id = 'step-' + (index + 1); + element.setAttribute('slot', 'view'); + this.$.viewManager.appendChild(element); + + if (MODULES_NEEDING_INDICATOR.has(elementTagName)) { + element.indicatorModel = { + total: indicatorElementCount, + active: indicatorActiveCount++, + }; + } }); - - const indicatorElementCount = modules.reduce((count, module) => { - return count += MODULES_NEEDING_INDICATOR.has(module) ? 1 : 0; - }, 0); - - let indicatorActiveCount = 0; - modules.forEach((elementTagName, index) => { - // Makes sure the module specified by the feature configuration is - // whitelisted. - assert(MODULES_WHITELIST.has(elementTagName)); - - const element = document.createElement(elementTagName); - element.id = 'step-' + (index + 1); - element.setAttribute('slot', 'view'); - this.$.viewManager.appendChild(element); - - if (MODULES_NEEDING_INDICATOR.has(elementTagName)) { - element.indicatorModel = { - total: indicatorElementCount, - active: indicatorActiveCount++, - }; - } - }); - }); + }); }, });
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/welcome_browser_proxy.js b/chrome/browser/resources/welcome/onboarding_welcome/welcome_browser_proxy.js index dc7380c1..fd2b128 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/welcome_browser_proxy.js +++ b/chrome/browser/resources/welcome/onboarding_welcome/welcome_browser_proxy.js
@@ -14,6 +14,12 @@ /** @param {?string} redirectUrl the URL to go to, after signing in. */ handleActivateSignIn(redirectUrl) {} + /** + * @param {?string} redirectUrl the URL to go to after backend records the + * user declining signin. + */ + handleUserDecline(redirectUrl) {} + /** @param {boolean=} replace */ goToNewTabPage(replace) {} @@ -29,6 +35,11 @@ } /** @override */ + handleUserDecline(redirectUrl) { + chrome.send('handleUserDecline', redirectUrl ? [redirectUrl] : []); + } + + /** @override */ goToNewTabPage(replace) { if (replace) window.location.replace('chrome://newtab');
diff --git a/chrome/browser/rlz/chrome_rlz_tracker_delegate.cc b/chrome/browser/rlz/chrome_rlz_tracker_delegate.cc index 346c93a..35faa15 100644 --- a/chrome/browser/rlz/chrome_rlz_tracker_delegate.cc +++ b/chrome/browser/rlz/chrome_rlz_tracker_delegate.cc
@@ -188,6 +188,10 @@ on_homepage_search_callback_ = callback; } +bool ChromeRLZTrackerDelegate::ShouldUpdateExistingAccessPointRlz() { + return true; +} + void ChromeRLZTrackerDelegate::Observe( int type, const content::NotificationSource& source,
diff --git a/chrome/browser/rlz/chrome_rlz_tracker_delegate.h b/chrome/browser/rlz/chrome_rlz_tracker_delegate.h index f1774e7..a6ee8bf2 100644 --- a/chrome/browser/rlz/chrome_rlz_tracker_delegate.h +++ b/chrome/browser/rlz/chrome_rlz_tracker_delegate.h
@@ -46,6 +46,7 @@ bool ClearReferral() override; void SetOmniboxSearchCallback(const base::Closure& callback) override; void SetHomepageSearchCallback(const base::Closure& callback) override; + bool ShouldUpdateExistingAccessPointRlz() override; // content::NotificationObserver implementation: void Observe(int type,
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc index 8d673af..fcd6211 100644 --- a/chrome/browser/search/local_ntp_source.cc +++ b/chrome/browser/search/local_ntp_source.cc
@@ -93,6 +93,10 @@ const char kPromoScriptFilename[] = "promo.js"; const char kDoodleScriptFilename[] = "doodle.js"; const char kIntegrityFormat[] = "integrity=\"sha256-%s\""; +const char kSimpleShareDoodleUrl[] = + "https://www.gstatic.com/logo/dev/ddljson_simple_share_button.json"; +const char kAnimatedShareDoodleUrl[] = + "https://www.gstatic.com/logo/dev/ddljson_animated_share_button.json"; const struct Resource{ const char* filename; @@ -162,8 +166,7 @@ if (is_google) { AddString(translated_strings.get(), "searchboxPlaceholder", - features::IsMDUIEnabled() ? IDS_GOOGLE_SEARCH_BOX_EMPTY_HINT_MD - : IDS_GOOGLE_SEARCH_BOX_EMPTY_HINT); + IDS_GOOGLE_SEARCH_BOX_EMPTY_HINT_MD); // Custom Backgrounds AddString(translated_strings.get(), "customizeBackground", @@ -375,6 +378,16 @@ return result; } +std::unique_ptr<base::DictionaryValue> ConvertPromoDataToDict( + const base::Optional<PromoData>& promo) { + auto result = std::make_unique<base::DictionaryValue>(); + if (promo.has_value()) + result->SetString("promoHtml", promo->promo_html); + else + result->SetString("promoHtml", std::string()); + return result; +} + std::string ConvertLogoImageToBase64(const EncodedLogo& logo) { std::string base64; base::Base64Encode(logo.encoded_image->data(), &base64); @@ -407,6 +420,16 @@ result->SetInteger("iframeHeightPx", meta.iframe_height_px); result->SetString("logUrl", meta.log_url.spec()); result->SetString("ctaLogUrl", meta.cta_log_url.spec()); + result->SetString("shortLink", meta.short_link.spec()); + + if (meta.share_button_x >= 0 && meta.share_button_y >= 0 && + !meta.share_button_icon.empty() && !meta.share_button_bg.empty()) { + result->SetInteger("shareButtonX", meta.share_button_x); + result->SetInteger("shareButtonY", meta.share_button_y); + result->SetDouble("shareButtonOpacity", meta.share_button_opacity); + result->SetString("shareButtonIcon", meta.share_button_icon); + result->SetString("shareButtonBg", meta.share_button_bg); + } GURL full_page_url = meta.full_page_url; if (base::GetFieldTrialParamByFeatureAsBool( @@ -515,8 +538,6 @@ content::BrowserAccessibilityState::GetInstance() ->IsAccessibleBrowser()); - config_data.SetBoolean("isMDUIEnabled", features::IsMDUIEnabled()); - config_data.SetBoolean("isMDIconsEnabled", features::IsMDIconsEnabled()); if (is_google) { @@ -824,6 +845,7 @@ // TODO(crbug/909931): There's no need to fetch the promo on each load, // we can sometimes use cached data. + promo_requests_.emplace_back(base::TimeTicks::Now(), callback); promo_service_->Refresh(); return; @@ -905,10 +927,23 @@ if (net::GetValueForKeyInQuery(path_url, "force-doodle", &force_doodle_param)) { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - command_line->AppendSwitchASCII( - search_provider_logos::switches::kGoogleDoodleUrl, - "https://www.gstatic.com/chrome/ntp/doodle_test/ddljson_desktop" + - force_doodle_param + ".json"); + + // TODO(crbug.com/896461): Add share button to ddljson_desktop0.json and + // ddljson_desktop1.json then update links below. + if (force_doodle_param == "0") { + command_line->AppendSwitchASCII( + search_provider_logos::switches::kGoogleDoodleUrl, + kSimpleShareDoodleUrl); + } else if (force_doodle_param == "1") { + command_line->AppendSwitchASCII( + search_provider_logos::switches::kGoogleDoodleUrl, + kAnimatedShareDoodleUrl); + } else { + command_line->AppendSwitchASCII( + search_provider_logos::switches::kGoogleDoodleUrl, + "https://www.gstatic.com/chrome/ntp/doodle_test/ddljson_desktop" + + force_doodle_param + ".json"); + } } callback.Run(base::RefCountedString::TakeString(&html)); @@ -1151,6 +1186,8 @@ void LocalNtpSource::OnPromoDataUpdated() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + ServePromo(promo_service_->promo_data()); } void LocalNtpSource::OnPromoServiceShuttingDown() { @@ -1191,6 +1228,34 @@ one_google_bar_requests_.clear(); } +void LocalNtpSource::ServePromo(const base::Optional<PromoData>& data) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + if (promo_requests_.empty()) + return; + + scoped_refptr<base::RefCountedString> result; + std::string js; + base::JSONWriter::Write(*ConvertPromoDataToDict(data), &js); + js = "var promo = " + js + ";"; + result = base::RefCountedString::TakeString(&js); + + base::TimeTicks now = base::TimeTicks::Now(); + for (const auto& request : promo_requests_) { + request.callback.Run(result); + base::TimeDelta delta = now - request.start_time; + UMA_HISTOGRAM_MEDIUM_TIMES("NewTabPage.Promos.RequestLatency", delta); + if (result) { + UMA_HISTOGRAM_MEDIUM_TIMES("NewTabPage.Promos.RequestLatency.Success", + delta); + } else { + UMA_HISTOGRAM_MEDIUM_TIMES("NewTabPage.Promos.RequestLatency.Failure", + delta); + } + } + promo_requests_.clear(); +} + LocalNtpSource::NtpBackgroundRequest::NtpBackgroundRequest( base::TimeTicks start_time, const content::URLDataSource::GotDataCallback& callback) @@ -1210,3 +1275,12 @@ const OneGoogleBarRequest&) = default; LocalNtpSource::OneGoogleBarRequest::~OneGoogleBarRequest() = default; + +LocalNtpSource::PromoRequest::PromoRequest( + base::TimeTicks start_time, + const content::URLDataSource::GotDataCallback& callback) + : start_time(start_time), callback(callback) {} + +LocalNtpSource::PromoRequest::PromoRequest(const PromoRequest&) = default; + +LocalNtpSource::PromoRequest::~PromoRequest() = default;
diff --git a/chrome/browser/search/local_ntp_source.h b/chrome/browser/search/local_ntp_source.h index 5f80d43..b7858d9 100644 --- a/chrome/browser/search/local_ntp_source.h +++ b/chrome/browser/search/local_ntp_source.h
@@ -26,6 +26,7 @@ #endif struct OneGoogleBarData; +struct PromoData; class NtpBackgroundService; class OneGoogleBarService; class PromoService; @@ -119,6 +120,8 @@ void ServeOneGoogleBar(const base::Optional<OneGoogleBarData>& data); + void ServePromo(const base::Optional<PromoData>& data); + Profile* const profile_; std::vector<NtpBackgroundRequest> ntp_background_collections_requests_; @@ -138,6 +141,8 @@ ScopedObserver<OneGoogleBarService, OneGoogleBarServiceObserver> one_google_bar_service_observer_; + std::vector<PromoRequest> promo_requests_; + PromoService* promo_service_; ScopedObserver<PromoService, PromoServiceObserver> promo_service_observer_;
diff --git a/chrome/browser/search/ntp_features.cc b/chrome/browser/search/ntp_features.cc index 08c6708..4d8c98c1 100644 --- a/chrome/browser/search/ntp_features.cc +++ b/chrome/browser/search/ntp_features.cc
@@ -20,15 +20,10 @@ base::FEATURE_ENABLED_BY_DEFAULT}; // If enabled, the user will see the Most Visited tiles updated with Material -// Design elements. Implicitly enables |kNtpUIMd|. +// Design elements. const base::Feature kNtpIcons{"NewTabPageIcons", base::FEATURE_ENABLED_BY_DEFAULT}; -// If enabled, the user will see the New Tab Page updated with Material Design -// elements. -const base::Feature kNtpUIMd{"NewTabPageUIMd", - base::FEATURE_ENABLED_BY_DEFAULT}; - // If enabled, the user will sometimes see promos on the NTP. const base::Feature kPromosOnLocalNtp{"PromosOnLocalNtp", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -57,14 +52,4 @@ base::FeatureList::IsEnabled(features::kExperimentalUi); } -bool IsMDUIEnabled() { - return base::FeatureList::IsEnabled(kNtpUIMd) || - // MD UI changes are implicitly enabled if Material Design icons, - // custom link, or custom backgrounds are enabled. - base::FeatureList::IsEnabled(kNtpIcons) || - base::FeatureList::IsEnabled(kNtpBackgrounds) || - base::FeatureList::IsEnabled(ntp_tiles::kNtpCustomLinks) || - base::FeatureList::IsEnabled(features::kExperimentalUi); -} - } // namespace features
diff --git a/chrome/browser/search/ntp_features.h b/chrome/browser/search/ntp_features.h index e9b36ae..b397c43b 100644 --- a/chrome/browser/search/ntp_features.h +++ b/chrome/browser/search/ntp_features.h
@@ -15,7 +15,6 @@ extern const base::Feature kDoodlesOnLocalNtp; extern const base::Feature kNtpBackgrounds; extern const base::Feature kNtpIcons; -extern const base::Feature kNtpUIMd; extern const base::Feature kPromosOnLocalNtp; extern const base::Feature kSearchSuggestionsOnLocalNtp; extern const base::Feature kUseGoogleLocalNtp; @@ -29,9 +28,6 @@ // Returns whether the Material Design UI for Most Visited is enabled. bool IsMDIconsEnabled(); -// Returns whether the Material Design UI is enabled on the New Tab Page. -bool IsMDUIEnabled(); - } // namespace features #endif // CHROME_BROWSER_SEARCH_NTP_FEATURES_H_
diff --git a/chrome/browser/search/promos/promo_service.h b/chrome/browser/search/promos/promo_service.h index 3a0be73..37d6599 100644 --- a/chrome/browser/search/promos/promo_service.h +++ b/chrome/browser/search/promos/promo_service.h
@@ -53,7 +53,7 @@ // Requests an asynchronous refresh from the network. After the update // completes, OnPromoDataUpdated will be called on the observers. - void Refresh(); + virtual void Refresh(); // Add/remove observers. All observers must unregister themselves before the // PromoService is destroyed. @@ -62,8 +62,10 @@ GURL GetLoadURLForTesting() const; - private: + protected: void PromoDataLoaded(Status status, const base::Optional<PromoData>& data); + + private: void LoadDone(std::unique_ptr<std::string> response_body); void JsonParsed(std::unique_ptr<base::Value> value); void JsonParseFailed(const std::string& message);
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc index 4cd122a1..a5b38fa 100644 --- a/chrome/browser/sessions/session_restore.cc +++ b/chrome/browser/sessions/session_restore.cc
@@ -45,7 +45,6 @@ #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/startup/startup_browser_creator.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/tabs/tab_strip_model_observer.h" #include "chrome/common/extensions/extension_metrics.h" #include "chrome/common/url_constants.h" #include "components/keep_alive_registry/keep_alive_types.h" @@ -62,7 +61,6 @@ #include "content/public/browser/session_storage_namespace.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_observer.h" #include "content/public/common/page_state.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/extension_set.h" @@ -87,83 +85,6 @@ search::IsInstantNTP(active_tab); } -// WebContentsDestructionChecker crashes if the WebContents that it's observing -// gets destroyed. -// TODO(crbug.com/850626): Remove after bug is fixed. -class WebContentsDestructionChecker : public content::WebContentsObserver { - public: - explicit WebContentsDestructionChecker(content::WebContents* contents) - : WebContentsObserver(contents) {} - ~WebContentsDestructionChecker() override = default; - - const WebContents* contents() const { return web_contents(); } - - // content::WebContentsObserver: - void WebContentsDestroyed() override { - LOG(FATAL) << "Restored WebContents " << web_contents() << " destroyed"; - } - - private: - DISALLOW_COPY_AND_ASSIGN(WebContentsDestructionChecker); -}; - -// TabStripRestoreObserver watches the next WebContents that's added to a -// TabStripModel and crashes if it's closed or detached. -// TODO(crbug.com/850626): Remove after bug is fixed. -class TabStripRestoreObserver : public TabStripModelObserver { - public: - explicit TabStripRestoreObserver(TabStripModel* tab_strip) - : tab_strip_(tab_strip) { - DCHECK(tab_strip_); - tab_strip_->AddObserver(this); - } - ~TabStripRestoreObserver() override { tab_strip_->RemoveObserver(this); } - - // TabStripModelObserver: - void OnTabStripModelChanged( - TabStripModel* tab_strip_model, - const TabStripModelChange& change, - const TabStripSelectionChange& selection) override { - if (change.type() == TabStripModelChange::kInserted) { - for (const auto& delta : change.deltas()) - OnTabInserted(delta.insert.contents); - return; - } - - if (change.type() == TabStripModelChange::kRemoved) { - for (const auto& delta : change.deltas()) - OnTabRemoved(delta.remove.contents, delta.remove.will_be_deleted); - return; - } - } - - private: - // Creates checker if needed. - void OnTabInserted(content::WebContents* contents) { - if (destruction_checker_) - return; - - destruction_checker_ = - std::make_unique<WebContentsDestructionChecker>(contents); - } - - void OnTabRemoved(content::WebContents* contents, bool will_be_deleted) { - if (!destruction_checker_) - return; - - if (contents == destruction_checker_->contents()) - LOG(FATAL) << "Restored WebContents " << contents - << (will_be_deleted ? " closing" : " detached"); - } - - TabStripModel* tab_strip_; // owned by caller - - // Initialized after a WebContents is inserted into the strip. - std::unique_ptr<WebContentsDestructionChecker> destruction_checker_; - - DISALLOW_COPY_AND_ASSIGN(TabStripRestoreObserver); -}; - // Pointers to SessionRestoreImpls which are currently restoring the session. std::set<SessionRestoreImpl*>* active_session_restorers = nullptr; @@ -661,9 +582,6 @@ ->RecreateSessionStorage(tab.session_storage_persistent_id); } - // TODO(crbug.com/850626): Remove this after bug is fixed. - TabStripRestoreObserver tab_strip_observer(browser->tab_strip_model()); - WebContents* web_contents = chrome::AddRestoredTab( browser, tab.navigations, tab_index, selected_index, tab.extension_app_id, is_selected_tab, tab.pinned, true, @@ -715,8 +633,6 @@ browser->window()->Show(); browser->set_is_session_restore(false); - - browser->tab_strip_model()->GetActiveWebContents()->SetInitialFocus(); } // Appends the urls in |urls| to |browser|.
diff --git a/chrome/browser/signin/about_signin_internals_factory.cc b/chrome/browser/signin/about_signin_internals_factory.cc index d151549b..da255be8 100644 --- a/chrome/browser/signin/about_signin_internals_factory.cc +++ b/chrome/browser/signin/about_signin_internals_factory.cc
@@ -12,11 +12,9 @@ #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_error_controller_factory.h" -#include "chrome/browser/signin/signin_manager_factory.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/signin/core/browser/about_signin_internals.h" -#include "components/signin/core/browser/signin_manager.h" AboutSigninInternalsFactory::AboutSigninInternalsFactory() : BrowserContextKeyedServiceFactory( @@ -27,7 +25,6 @@ DependsOn(GaiaCookieManagerServiceFactory::GetInstance()); DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance()); DependsOn(SigninErrorControllerFactory::GetInstance()); - DependsOn(SigninManagerFactory::GetInstance()); } AboutSigninInternalsFactory::~AboutSigninInternalsFactory() {} @@ -56,7 +53,6 @@ ProfileOAuth2TokenServiceFactory::GetForProfile(profile), AccountTrackerServiceFactory::GetForProfile(profile), IdentityManagerFactory::GetForProfile(profile), - SigninManagerFactory::GetForProfile(profile), SigninErrorControllerFactory::GetForProfile(profile), GaiaCookieManagerServiceFactory::GetForProfile(profile), AccountConsistencyModeManager::GetMethodForProfile(profile));
diff --git a/chrome/browser/signin/account_consistency_mode_manager.cc b/chrome/browser/signin/account_consistency_mode_manager.cc index ff2c9946..3837772 100644 --- a/chrome/browser/signin/account_consistency_mode_manager.cc +++ b/chrome/browser/signin/account_consistency_mode_manager.cc
@@ -30,8 +30,6 @@ "AccountConsistency", base::FEATURE_ENABLED_BY_DEFAULT}; const char kAccountConsistencyFeatureMethodParameter[] = "method"; const char kAccountConsistencyFeatureMethodMirror[] = "mirror"; -const char kAccountConsistencyFeatureMethodDiceFixAuthErrors[] = - "dice_fix_auth_errors"; const char kAccountConsistencyFeatureMethodDiceMigration[] = "dice_migration"; const char kAccountConsistencyFeatureMethodDice[] = "dice"; @@ -59,15 +57,6 @@ }; #endif -// Returns the default account consistency for guest profiles. -AccountConsistencyMethod GetMethodForNonRegularProfile() { -#if BUILDFLAG(ENABLE_DICE_SUPPORT) - return AccountConsistencyMethod::kDiceFixAuthErrors; -#else - return AccountConsistencyMethod::kDisabled; -#endif -} - } // namespace bool AccountConsistencyModeManager::ignore_missing_oauth_client_for_testing_ = @@ -144,7 +133,7 @@ AccountConsistencyMethod AccountConsistencyModeManager::GetMethodForProfile( Profile* profile) { if (profile->IsOffTheRecord()) - return GetMethodForNonRegularProfile(); + return AccountConsistencyMethod::kDisabled; return AccountConsistencyModeManager::GetForProfile(profile) ->GetAccountConsistencyMethod(); @@ -210,7 +199,7 @@ Profile* profile) { if (profile->GetProfileType() != Profile::ProfileType::REGULAR_PROFILE) { DCHECK_EQ(Profile::ProfileType::GUEST_PROFILE, profile->GetProfileType()); - return GetMethodForNonRegularProfile(); + return AccountConsistencyMethod::kDisabled; } #if BUILDFLAG(ENABLE_MIRROR) @@ -236,16 +225,11 @@ #if BUILDFLAG(ENABLE_DICE_SUPPORT) AccountConsistencyMethod method = AccountConsistencyMethod::kDiceMigration; - if (method_value == kAccountConsistencyFeatureMethodDiceFixAuthErrors) - method = AccountConsistencyMethod::kDiceFixAuthErrors; - else if (method_value == kAccountConsistencyFeatureMethodDiceMigration) + if (method_value == kAccountConsistencyFeatureMethodDiceMigration) method = AccountConsistencyMethod::kDiceMigration; else if (method_value == kAccountConsistencyFeatureMethodDice) method = AccountConsistencyMethod::kDice; - if (method == AccountConsistencyMethod::kDiceFixAuthErrors) - return method; - DCHECK(signin::DiceMethodGreaterOrEqual( method, AccountConsistencyMethod::kDiceMigration)); @@ -253,20 +237,20 @@ // TODO(droger): remove this once legacy supervised users are no longer // supported. if (profile->IsLegacySupervised()) - return AccountConsistencyMethod::kDiceFixAuthErrors; + return AccountConsistencyMethod::kDisabled; bool can_enable_dice_for_build = ignore_missing_oauth_client_for_testing_ || google_apis::HasOAuthClientConfigured(); if (!can_enable_dice_for_build) { LOG(WARNING) << "Desktop Identity Consistency cannot be enabled as no " "OAuth client ID and client secret have been configured."; - return AccountConsistencyMethod::kDiceFixAuthErrors; + return AccountConsistencyMethod::kDisabled; } if (!profile->GetPrefs()->GetBoolean(prefs::kSigninAllowed)) { VLOG(1) << "Desktop Identity Consistency disabled as sign-in to Chrome" "is not allowed"; - return AccountConsistencyMethod::kDiceFixAuthErrors; + return AccountConsistencyMethod::kDisabled; } if (method == AccountConsistencyMethod::kDiceMigration &&
diff --git a/chrome/browser/signin/account_consistency_mode_manager.h b/chrome/browser/signin/account_consistency_mode_manager.h index bcc495f7..18dd7b4 100644 --- a/chrome/browser/signin/account_consistency_mode_manager.h +++ b/chrome/browser/signin/account_consistency_mode_manager.h
@@ -29,7 +29,6 @@ // Account consistency method feature values. extern const char kAccountConsistencyFeatureMethodMirror[]; -extern const char kAccountConsistencyFeatureMethodDiceFixAuthErrors[]; extern const char kAccountConsistencyFeatureMethodDiceMigration[]; extern const char kAccountConsistencyFeatureMethodDice[];
diff --git a/chrome/browser/signin/account_consistency_mode_manager_unittest.cc b/chrome/browser/signin/account_consistency_mode_manager_unittest.cc index 954cce0daf..330512df 100644 --- a/chrome/browser/signin/account_consistency_mode_manager_unittest.cc +++ b/chrome/browser/signin/account_consistency_mode_manager_unittest.cc
@@ -60,7 +60,6 @@ bool expect_dice_enabled; } test_cases[] = { #if BUILDFLAG(ENABLE_DICE_SUPPORT) - {signin::AccountConsistencyMethod::kDiceFixAuthErrors, false, false}, {signin::AccountConsistencyMethod::kDiceMigration, false, false}, {signin::AccountConsistencyMethod::kDice, false, true}, #else @@ -115,7 +114,7 @@ EXPECT_FALSE( profile.GetPrefs()->GetBoolean(prefs::kSigninAllowedOnNextStartup)); // Dice should be disabled. - EXPECT_EQ(signin::AccountConsistencyMethod::kDiceFixAuthErrors, + EXPECT_EQ(signin::AccountConsistencyMethod::kDisabled, manager.GetAccountConsistencyMethod()); } } @@ -136,7 +135,7 @@ EXPECT_TRUE( profile.GetPrefs()->GetBoolean(prefs::kSigninAllowedOnNextStartup)); // Dice should be disabled. - EXPECT_EQ(signin::AccountConsistencyMethod::kDiceFixAuthErrors, + EXPECT_EQ(signin::AccountConsistencyMethod::kDisabled, manager.GetAccountConsistencyMethod()); } @@ -169,16 +168,6 @@ AccountConsistencyModeManager::SetDiceMigrationOnStartup(profile.GetPrefs(), true); - - { - // Migration does not happen if Dice is not enabled. - ScopedAccountConsistencyDiceFixAuthErrors scoped_dice_fix_errors; - AccountConsistencyModeManager manager(&profile); - EXPECT_TRUE(manager.IsReadyForDiceMigration(&profile)); - EXPECT_NE(signin::AccountConsistencyMethod::kDice, - manager.GetAccountConsistencyMethod()); - } - { // Migration happens. ScopedAccountConsistencyDiceMigration scoped_dice_migration; @@ -233,7 +222,7 @@ EXPECT_FALSE( AccountConsistencyModeManager::GetForProfile(incognito_profile)); EXPECT_EQ( - signin::AccountConsistencyMethod::kDiceFixAuthErrors, + signin::AccountConsistencyMethod::kDisabled, AccountConsistencyModeManager::GetMethodForProfile(incognito_profile)); } @@ -246,7 +235,7 @@ EXPECT_FALSE( AccountConsistencyModeManager::IsDiceEnabledForProfile(profile.get())); EXPECT_EQ( - signin::AccountConsistencyMethod::kDiceFixAuthErrors, + signin::AccountConsistencyMethod::kDisabled, AccountConsistencyModeManager::GetMethodForProfile(profile.get())); } @@ -259,7 +248,7 @@ EXPECT_FALSE( AccountConsistencyModeManager::IsDiceEnabledForProfile(profile.get())); EXPECT_EQ( - signin::AccountConsistencyMethod::kDiceFixAuthErrors, + signin::AccountConsistencyMethod::kDisabled, AccountConsistencyModeManager::GetMethodForProfile(profile.get())); } }
diff --git a/chrome/browser/signin/account_reconcilor_factory.cc b/chrome/browser/signin/account_reconcilor_factory.cc index 977660a..1cbedb96 100644 --- a/chrome/browser/signin/account_reconcilor_factory.cc +++ b/chrome/browser/signin/account_reconcilor_factory.cc
@@ -24,7 +24,10 @@ #if defined(OS_CHROMEOS) #include "base/metrics/histogram_macros.h" #include "base/time/time.h" +#include "chrome/browser/chromeos/account_manager/account_manager_migrator.h" +#include "chrome/browser/chromeos/account_manager/account_migration_runner.h" #include "chrome/browser/lifetime/application_lifetime.h" +#include "chromeos/chromeos_switches.h" #include "components/user_manager/user_manager.h" #include "google_apis/gaia/google_service_auth_error.h" #endif @@ -68,7 +71,42 @@ private: DISALLOW_COPY_AND_ASSIGN(ChromeOSChildAccountReconcilorDelegate); }; -#endif + +// An |AccountReconcilorDelegate| for Chrome OS that is exactly the same as +// |MirrorAccountReconcilorDelegate|, except that it does not begin account +// reconciliation until accounts have been migrated to Chrome OS Account +// Manager. +// TODO(sinhak): Remove this when all users have been migrated to Chrome OS +// Account Manager. +class ChromeOSAccountReconcilorDelegate + : public signin::MirrorAccountReconcilorDelegate { + public: + ChromeOSAccountReconcilorDelegate( + identity::IdentityManager* identity_manager, + chromeos::AccountManagerMigrator* account_migrator) + : signin::MirrorAccountReconcilorDelegate(identity_manager), + account_migrator_(account_migrator) {} + ~ChromeOSAccountReconcilorDelegate() override = default; + + private: + // AccountReconcilorDelegate: + bool IsReconcileEnabled() const override { + if (!MirrorAccountReconcilorDelegate::IsReconcileEnabled()) { + return false; + } + + const chromeos::AccountMigrationRunner::Status status = + account_migrator_->GetStatus(); + return status != chromeos::AccountMigrationRunner::Status::kNotStarted && + status != chromeos::AccountMigrationRunner::Status::kRunning; + } + + // A non-owning pointer. + const chromeos::AccountManagerMigrator* const account_migrator_; + + DISALLOW_COPY_AND_ASSIGN(ChromeOSAccountReconcilorDelegate); +}; +#endif // defined(OS_CHROMEOS) } // namespace @@ -122,12 +160,21 @@ return std::make_unique<ChromeOSChildAccountReconcilorDelegate>( IdentityManagerFactory::GetForProfile(profile)); } + + // TODO(sinhak): Remove the if-condition (and use + // |MirrorAccountReconcilorDelegate|) when all Chrome OS users have been + // migrated to Account Manager. + if (chromeos::switches::IsAccountManagerEnabled()) { + return std::make_unique<ChromeOSAccountReconcilorDelegate>( + IdentityManagerFactory::GetForProfile(profile), + chromeos::AccountManagerMigratorFactory::GetForBrowserContext( + profile)); + } #endif return std::make_unique<signin::MirrorAccountReconcilorDelegate>( IdentityManagerFactory::GetForProfile(profile)); case signin::AccountConsistencyMethod::kDisabled: - case signin::AccountConsistencyMethod::kDiceFixAuthErrors: return std::make_unique<signin::AccountReconcilorDelegate>(); case signin::AccountConsistencyMethod::kDiceMigration:
diff --git a/chrome/browser/signin/chrome_signin_helper_unittest.cc b/chrome/browser/signin/chrome_signin_helper_unittest.cc index 44f1055..9983954 100644 --- a/chrome/browser/signin/chrome_signin_helper_unittest.cc +++ b/chrome/browser/signin/chrome_signin_helper_unittest.cc
@@ -68,7 +68,7 @@ #if BUILDFLAG(ENABLE_DICE_SUPPORT) // Tests that Dice response headers are removed after being processed. TEST_F(ChromeSigninHelperTest, RemoveDiceSigninHeader) { - ScopedAccountConsistencyDiceFixAuthErrors scoped_dice_fix_auth_errors; + ScopedAccountConsistencyDiceMigration scoped_dice_migration; // Create a response with the Dice header. test_request_delegate_ = std::make_unique<net::TestDelegate>();
diff --git a/chrome/browser/signin/dice_browsertest.cc b/chrome/browser/signin/dice_browsertest.cc index 44fdc05b..61681f4 100644 --- a/chrome/browser/signin/dice_browsertest.cc +++ b/chrome/browser/signin/dice_browsertest.cc
@@ -651,13 +651,6 @@ : DiceBrowserTestBase(AccountConsistencyMethod::kDice, kMainGmailEmail) {} }; -class DiceFixAuthErrorsBrowserTest : public DiceBrowserTestBase { - public: - DiceFixAuthErrorsBrowserTest() - : DiceBrowserTestBase(AccountConsistencyMethod::kDiceFixAuthErrors, - kMainGmailEmail) {} -}; - // Checks that signin on Gaia triggers the fetch for a refresh token. IN_PROC_BROWSER_TEST_F(DiceBrowserTest, Signin) { EXPECT_EQ(0, reconcilor_started_count_); @@ -820,130 +813,6 @@ WaitForReconcilorUnblockedCount(0); } -// Checks that signin on Gaia does not trigger the fetch of refresh token when -// there is no authentication error. -IN_PROC_BROWSER_TEST_F(DiceFixAuthErrorsBrowserTest, SigninNoAuthError) { - // Start from a signed-in state. - SetupSignedInAccounts(); - syncer::SyncPrefs(browser()->profile()->GetPrefs()).SetFirstSetupComplete(); - - // Navigate to Gaia and sign in. - NavigateToURL(kSigninURL); - - // Check that the Dice request header was not sent. - EXPECT_EQ(kNoDiceRequestHeader, dice_request_header_); - EXPECT_EQ(0, reconcilor_blocked_count_); - WaitForReconcilorUnblockedCount(0); -} - -// Checks that signin on Gaia does not triggers the fetch for a refresh token -// when the user is not signed into Chrome. -IN_PROC_BROWSER_TEST_F(DiceFixAuthErrorsBrowserTest, NotSignedInChrome) { - // Setup authentication error. - syncer::SyncPrefs(browser()->profile()->GetPrefs()).SetSyncAuthError(true); - syncer::SyncPrefs(browser()->profile()->GetPrefs()).SetFirstSetupComplete(); - - // Navigate to Gaia and sign in. - NavigateToURL(kSigninURL); - - // Check that the Dice request header was not sent. - EXPECT_EQ(kNoDiceRequestHeader, dice_request_header_); - EXPECT_EQ(0, reconcilor_blocked_count_); - WaitForReconcilorUnblockedCount(0); -} - -// Checks that a refresh token is not requested when accounts don't match. -IN_PROC_BROWSER_TEST_F(DiceFixAuthErrorsBrowserTest, SigninAccountMismatch) { - // Sign in to Chrome with secondary account, with authentication error. - SigninManager* signin_manager = GetSigninManager(); - signin_manager->StartSignInWithRefreshToken( - "existing_refresh_token", kSecondaryGaiaID, kSecondaryEmail, "password", - SigninManager::OAuthTokenFetchedCallback()); - ASSERT_TRUE( - GetTokenService()->RefreshTokenIsAvailable(GetSecondaryAccountID())); - ASSERT_EQ(GetSecondaryAccountID(), - signin_manager->GetAuthenticatedAccountId()); - syncer::SyncPrefs(browser()->profile()->GetPrefs()).SetSyncAuthError(true); - syncer::SyncPrefs(browser()->profile()->GetPrefs()).SetFirstSetupComplete(); - - // Navigate to Gaia and sign in with the main account (account mismatch). - NavigateToURL(kSigninURL); - - // Check that the Dice request header was sent. - std::string client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id(); - EXPECT_EQ(base::StringPrintf("version=%s,client_id=%s,device_id=%s," - "sync_account_id=%s,signin_mode=sync_account," - "signout_mode=no_confirmation", - signin::kDiceProtocolVersion, client_id.c_str(), - GetDeviceId().c_str(), - GetSecondaryAccountID().c_str()), - dice_request_header_); - - // Check that the token was not requested and the authenticated account did - // not change. - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(token_requested_); - EXPECT_FALSE(refresh_token_available_); - EXPECT_EQ(GetSecondaryAccountID(), - GetSigninManager()->GetAuthenticatedAccountId()); - EXPECT_EQ(1, reconcilor_blocked_count_); - WaitForReconcilorUnblockedCount(1); -} - -// Checks that signin on Gaia triggers the fetch for a refresh token when there -// is an authentication error and the user is re-authenticating on the web. -// This test is similar to DiceBrowserTest.Reauth. -IN_PROC_BROWSER_TEST_F(DiceFixAuthErrorsBrowserTest, ReauthFixAuthError) { - // Start from a signed-in state with authentication error. - SetupSignedInAccounts(); - syncer::SyncPrefs(browser()->profile()->GetPrefs()).SetSyncAuthError(true); - syncer::SyncPrefs(browser()->profile()->GetPrefs()).SetFirstSetupComplete(); - - // Navigate to Gaia and sign in again with the main account. - NavigateToURL(kSigninURL); - - // Check that the Dice request header was sent. - std::string client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id(); - EXPECT_EQ( - base::StringPrintf("version=%s,client_id=%s,device_id=%s," - "sync_account_id=%s,signin_mode=sync_account," - "signout_mode=no_confirmation", - signin::kDiceProtocolVersion, client_id.c_str(), - GetDeviceId().c_str(), GetMainAccountID().c_str()), - dice_request_header_); - - // Check that the token was requested and added to the token service. - SendRefreshTokenResponse(); - EXPECT_EQ(GetMainAccountID(), - GetSigninManager()->GetAuthenticatedAccountId()); - - // Old token must not be revoked (see http://crbug.com/865189). - EXPECT_EQ(0, token_revoked_notification_count_); - - EXPECT_EQ(1, reconcilor_blocked_count_); - WaitForReconcilorUnblockedCount(1); -} - -// Checks that the Dice signout flow is disabled. -IN_PROC_BROWSER_TEST_F(DiceFixAuthErrorsBrowserTest, Signout) { - // Start from a signed-in state. - SetupSignedInAccounts(); - - // Signout from main account on the web. - SignOutWithDice(kMainAccount); - - // Check that the user is still signed in Chrome. - EXPECT_EQ(GetMainAccountID(), - GetSigninManager()->GetAuthenticatedAccountId()); - EXPECT_TRUE(GetTokenService()->RefreshTokenIsAvailable(GetMainAccountID())); - EXPECT_TRUE( - GetTokenService()->RefreshTokenIsAvailable(GetSecondaryAccountID())); - EXPECT_EQ(0, token_revoked_notification_count_); - EXPECT_EQ(0, token_revoked_count_); - EXPECT_EQ(0, reconcilor_blocked_count_); - WaitForReconcilorUnblockedCount(0); -} - // Tests that Sync is enabled if the ENABLE_SYNC response is received after the // refresh token. IN_PROC_BROWSER_TEST_F(DiceBrowserTest, EnableSyncAfterToken) { @@ -1076,6 +945,13 @@ EXPECT_TRUE(GetSigninManager()->GetAccountIdForAuthInProgress().empty()); EXPECT_FALSE(GetTokenService()->RefreshTokenIsAvailable(GetMainAccountID())); EXPECT_TRUE(GetAccountTrackerService()->GetAccounts().empty()); + + // Navigate to Gaia and sign in. + NavigateToURL(kSigninURL); + // Check that the Dice request header was not sent. + EXPECT_EQ(kNoDiceRequestHeader, dice_request_header_); + EXPECT_EQ(0, reconcilor_blocked_count_); + WaitForReconcilorUnblockedCount(0); } // Checks that Dice is disabled in incognito mode.
diff --git a/chrome/browser/signin/dice_response_handler.cc b/chrome/browser/signin/dice_response_handler.cc index faca3c9..4d70fb41 100644 --- a/chrome/browser/signin/dice_response_handler.cc +++ b/chrome/browser/signin/dice_response_handler.cc
@@ -254,6 +254,8 @@ DCHECK(account_tracker_service_); DCHECK(account_reconcilor_); DCHECK(about_signin_internals_); + DCHECK(signin::DiceMethodGreaterOrEqual( + account_consistency_, signin::AccountConsistencyMethod::kDiceMigration)); } DiceResponseHandler::~DiceResponseHandler() {} @@ -261,9 +263,6 @@ void DiceResponseHandler::ProcessDiceHeader( const signin::DiceResponseParams& dice_params, std::unique_ptr<ProcessDiceHeaderDelegate> delegate) { - DCHECK(signin::DiceMethodGreaterOrEqual( - account_consistency_, - signin::AccountConsistencyMethod::kDiceFixAuthErrors)); DCHECK(delegate); switch (dice_params.user_intention) { case signin::DiceAction::SIGNIN: { @@ -295,26 +294,6 @@ return token_fetchers_.size(); } -bool DiceResponseHandler::CanGetTokenForAccount(const std::string& gaia_id, - const std::string& email) { - if (signin::DiceMethodGreaterOrEqual( - account_consistency_, - signin::AccountConsistencyMethod::kDiceMigration)) { - return true; - } - - // When using kDiceFixAuthErrors, only get a token if the account matches - // the current Chrome account. - DCHECK_EQ(signin::AccountConsistencyMethod::kDiceFixAuthErrors, - account_consistency_); - std::string account = - account_tracker_service_->PickAccountIdForAccount(gaia_id, email); - bool can_get_token = (identity_manager_->GetPrimaryAccountId() == account); - VLOG_IF(1, !can_get_token) - << "[Dice] Dropping Dice signin response for " << account; - return can_get_token; -} - void DiceResponseHandler::ProcessDiceSigninHeader( const std::string& gaia_id, const std::string& email, @@ -326,11 +305,6 @@ VLOG(1) << "Start processing Dice signin response"; RecordDiceResponseHeader(kSignin); - if (!CanGetTokenForAccount(gaia_id, email)) { - RecordDiceFetchTokenResult(kFetchAbort); - return; - } - for (auto it = token_fetchers_.begin(); it != token_fetchers_.end(); ++it) { if ((it->get()->gaia_id() == gaia_id) && (it->get()->email() == email) && (it->get()->authorization_code() == authorization_code)) { @@ -368,11 +342,6 @@ void DiceResponseHandler::ProcessDiceSignoutHeader( const std::vector<signin::DiceResponseParams::AccountInfo>& account_infos) { VLOG(1) << "Start processing Dice signout response"; - if (account_consistency_ == - signin::AccountConsistencyMethod::kDiceFixAuthErrors) { - // Ignore signout responses when using kDiceFixAuthErrors. - return; - } std::string primary_account = identity_manager_->GetPrimaryAccountId(); bool primary_account_signed_out = false; @@ -442,8 +411,6 @@ bool is_under_advanced_protection) { const std::string& email = token_fetcher->email(); const std::string& gaia_id = token_fetcher->gaia_id(); - if (!CanGetTokenForAccount(gaia_id, email)) - return; VLOG(1) << "[Dice] OAuth success for email " << email; bool should_enable_sync = token_fetcher->should_enable_sync(); std::string account_id =
diff --git a/chrome/browser/signin/dice_response_handler_unittest.cc b/chrome/browser/signin/dice_response_handler_unittest.cc index bf46f82b..b1700301 100644 --- a/chrome/browser/signin/dice_response_handler_unittest.cc +++ b/chrome/browser/signin/dice_response_handler_unittest.cc
@@ -141,7 +141,6 @@ about_signin_internals_(&token_service_, &account_tracker_service_, identity_test_env_.identity_manager(), - &signin_manager_, &signin_error_controller_, &cookie_service_, signin::AccountConsistencyMethod::kDice), @@ -156,7 +155,7 @@ SigninManager::RegisterProfilePrefs(pref_service_.registry()); auto account_reconcilor_delegate = std::make_unique<signin::DiceAccountReconcilorDelegate>( - &signin_client_, signin::AccountConsistencyMethod::kDisabled); + &signin_client_, signin::AccountConsistencyMethod::kDiceMigration); account_reconcilor_ = std::make_unique<AccountReconcilor>( &token_service_, identity_test_env_.identity_manager(), &signin_client_, nullptr, std::move(account_reconcilor_delegate)); @@ -720,112 +719,6 @@ EXPECT_EQ("refresh_token", GetRefreshToken(account_id_2)); } -// Checks that no auth error fix happens if the user is signed out. -TEST_F(DiceResponseHandlerTest, FixAuthErrorSignedOut) { - InitializeDiceResponseHandler( - signin::AccountConsistencyMethod::kDiceFixAuthErrors); - DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNIN); - const auto& account_info = dice_params.signin_info->account_info; - ASSERT_FALSE(identity_manager()->HasAccountWithRefreshToken( - account_tracker_service_.PickAccountIdForAccount(account_info.gaia_id, - account_info.email))); - dice_response_handler_->ProcessDiceHeader( - dice_params, std::make_unique<TestProcessDiceHeaderDelegate>(this)); - // Check that a GaiaAuthFetcher has not been created. - ASSERT_THAT(signin_client_.consumer_, testing::IsNull()); -} - -// Checks that the token is not stored if the user signs out during the token -// request. -TEST_F(DiceResponseHandlerTest, FixAuthErrorSignOutDuringRequest) { - InitializeDiceResponseHandler( - signin::AccountConsistencyMethod::kDiceFixAuthErrors); - // User is signed in to Chrome. - DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNIN); - const auto& dice_account_info = dice_params.signin_info->account_info; - AccountInfo account_info = - identity_test_env_.MakePrimaryAccountAvailable(dice_account_info.email); - EXPECT_TRUE( - identity_manager()->HasAccountWithRefreshToken(account_info.account_id)); - EXPECT_TRUE(identity_manager()->HasPrimaryAccount()); - // Start re-authentication on the web. - dice_response_handler_->ProcessDiceHeader( - dice_params, std::make_unique<TestProcessDiceHeaderDelegate>(this)); - // Check that a GaiaAuthFetcher has been created. - ASSERT_THAT(signin_client_.consumer_, testing::NotNull()); - // Sign out. - identity_test_env_.ClearPrimaryAccount(); - // Simulate GaiaAuthFetcher success. - signin_client_.consumer_->OnClientOAuthSuccess( - GaiaAuthConsumer::ClientOAuthResult("refresh_token", "access_token", 10, - false /* is_child_account */, - false /* is_advanced_protection*/)); - // Check that the token has not been inserted in the token service. - EXPECT_FALSE( - identity_manager()->HasAccountWithRefreshToken(account_info.account_id)); -} - -// Checks that the token is fixed if the Chrome account matches the web account. -TEST_F(DiceResponseHandlerTest, FixAuthError) { - InitializeDiceResponseHandler( - signin::AccountConsistencyMethod::kDiceFixAuthErrors); - // User is signed in to Chrome. - DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNIN); - const auto& dice_account_info = dice_params.signin_info->account_info; - AccountInfo account_info = - identity_test_env_.MakePrimaryAccountAvailable(dice_account_info.email); - EXPECT_TRUE( - identity_manager()->HasAccountWithRefreshToken(account_info.account_id)); - EXPECT_TRUE(identity_manager()->HasPrimaryAccount()); - // Start re-authentication on the web. - dice_response_handler_->ProcessDiceHeader( - dice_params, std::make_unique<TestProcessDiceHeaderDelegate>(this)); - // Check that a GaiaAuthFetcher has been created. - ASSERT_THAT(signin_client_.consumer_, testing::NotNull()); - // We need to listen for new token notifications, since there is no way to - // check the actual value of the token in the token service. - std::unique_ptr<DiceTestTokenServiceObserver> token_service_observer = - std::make_unique<DiceTestTokenServiceObserver>(account_info.gaia); - ScopedObserver<ProfileOAuth2TokenService, DiceTestTokenServiceObserver> - scoped_token_service_observer(token_service_observer.get()); - scoped_token_service_observer.Add(&token_service_); - // Simulate GaiaAuthFetcher success. - signin_client_.consumer_->OnClientOAuthSuccess( - GaiaAuthConsumer::ClientOAuthResult("refresh_token", "access_token", 10, - false /* is_child_account */, - false /* is_advanced_protection*/)); - // Check that the token has not been inserted in the token service. - EXPECT_TRUE( - identity_manager()->HasAccountWithRefreshToken(account_info.account_id)); - EXPECT_TRUE(token_service_observer->token_received()); - // Check that the reconcilor was blocked and unblocked. - EXPECT_EQ(1, reconcilor_blocked_count_); - EXPECT_EQ(1, reconcilor_unblocked_count_); -} - -// Tests that the Dice Signout response is ignored when kDiceFixAuthErrors is -// used. -TEST_F(DiceResponseHandlerTest, FixAuthErroDoesNotSignout) { - InitializeDiceResponseHandler( - signin::AccountConsistencyMethod::kDiceFixAuthErrors); - DiceResponseParams dice_params = MakeDiceParams(DiceAction::SIGNOUT); - const auto& dice_account_info = dice_params.signout_info->account_infos[0]; - // User is signed in to Chrome, and has some refresh token for a secondary - // account. - AccountInfo account_info = - identity_test_env_.MakePrimaryAccountAvailable(dice_account_info.email); - EXPECT_TRUE( - identity_manager()->HasAccountWithRefreshToken(account_info.account_id)); - EXPECT_TRUE(identity_manager()->HasPrimaryAccount()); - // Receive signout response for the main account. - dice_response_handler_->ProcessDiceHeader( - dice_params, std::make_unique<TestProcessDiceHeaderDelegate>(this)); - // User is not signed out from Chrome. - EXPECT_TRUE( - identity_manager()->HasAccountWithRefreshToken(account_info.account_id)); - EXPECT_TRUE(identity_manager()->HasPrimaryAccount()); -} - // Tests that the DiceResponseHandler is created for a normal profile but not // for an incognito profile. TEST(DiceResponseHandlerFactoryTest, NotInIncognito) {
diff --git a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc index eacc8176..8db5d36 100644 --- a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc +++ b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc
@@ -719,8 +719,7 @@ AddAuthTokenManually("AccountId-12345", "refresh_token"); AddAuthTokenManually("AccountId-67890", "refresh_token"); - InitializeOAuth2ServiceDelegate( - signin::AccountConsistencyMethod::kDiceFixAuthErrors); + InitializeOAuth2ServiceDelegate(signin::AccountConsistencyMethod::kDisabled); oauth2_service_delegate_->LoadCredentials(/*primary_account_id=*/""); base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/signin/process_dice_header_delegate_impl.cc b/chrome/browser/signin/process_dice_header_delegate_impl.cc index 84d65c9..df05cd8 100644 --- a/chrome/browser/signin/process_dice_header_delegate_impl.cc +++ b/chrome/browser/signin/process_dice_header_delegate_impl.cc
@@ -42,20 +42,13 @@ redirect_url_(redirect_url) { DCHECK(web_contents); DCHECK(identity_manager_); + DCHECK(signin::DiceMethodGreaterOrEqual( + account_consistency_, signin::AccountConsistencyMethod::kDiceMigration)); } ProcessDiceHeaderDelegateImpl::~ProcessDiceHeaderDelegateImpl() = default; bool ProcessDiceHeaderDelegateImpl::ShouldEnableSync() { - if (!signin::DiceMethodGreaterOrEqual( - account_consistency_, - signin::AccountConsistencyMethod::kDiceMigration)) { - // Dice migration not enabled. - VLOG(1) - << "Do not start sync after web sign-in [DICE migration not enabled]."; - return false; - } - if (identity_manager_->HasPrimaryAccount()) { VLOG(1) << "Do not start sync after web sign-in [already authenticated]."; return false;
diff --git a/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc b/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc index 21136c4..ffee071f 100644 --- a/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc +++ b/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc
@@ -21,8 +21,6 @@ namespace { // Constants defined for a better formatting of the test tables: -const signin::AccountConsistencyMethod kDiceFixAuthErrors = - signin::AccountConsistencyMethod::kDiceFixAuthErrors; const signin::AccountConsistencyMethod kDice = signin::AccountConsistencyMethod::kDice; const signin::AccountConsistencyMethod kDiceMigration = @@ -132,14 +130,10 @@ TestConfiguration kEnableSyncTestCases[] = { // clang-format off // AccountConsistency | signed_in | signin_tab | callback_called | show_ntp - {kDiceFixAuthErrors, false, false, false, false}, - {kDiceFixAuthErrors, false, true, false, false}, {kDiceMigration, false, false, false, false}, {kDiceMigration, false, true, true, true}, {kDice, false, false, false, false}, {kDice, false, true, true, true}, - {kDiceFixAuthErrors, true, false, false, false}, - {kDiceFixAuthErrors, true, false, false, false}, {kDiceMigration, true, false, false, false}, {kDiceMigration, true, false, false, false}, {kDice, true, false, false, false}, @@ -179,14 +173,10 @@ TestConfiguration kHandleTokenExchangeFailureTestCases[] = { // clang-format off // AccountConsistency | signed_in | signin_tab | callback_called | show_ntp - {kDiceFixAuthErrors, false, false, false, false}, - {kDiceFixAuthErrors, false, true, false, false}, {kDiceMigration, false, false, false, false}, {kDiceMigration, false, true, true, true}, {kDice, false, false, true, false}, {kDice, false, true, true, true}, - {kDiceFixAuthErrors, true, false, false, false}, - {kDiceFixAuthErrors, true, false, false, false}, {kDiceMigration, true, false, false, false}, {kDiceMigration, true, false, false, false}, {kDice, true, false, true, false},
diff --git a/chrome/browser/signin/scoped_account_consistency.cc b/chrome/browser/signin/scoped_account_consistency.cc index c6ddd5f..884e39a 100644 --- a/chrome/browser/signin/scoped_account_consistency.cc +++ b/chrome/browser/signin/scoped_account_consistency.cc
@@ -20,7 +20,7 @@ DCHECK_NE(AccountConsistencyMethod::kDisabled, method); #if !BUILDFLAG(ENABLE_DICE_SUPPORT) DCHECK_NE(AccountConsistencyMethod::kDice, method); - DCHECK_NE(AccountConsistencyMethod::kDiceFixAuthErrors, method); + DCHECK_NE(AccountConsistencyMethod::kDiceMigration, method); #endif #if BUILDFLAG(ENABLE_MIRROR) @@ -37,9 +37,6 @@ case AccountConsistencyMethod::kMirror: feature_value = kAccountConsistencyFeatureMethodMirror; break; - case AccountConsistencyMethod::kDiceFixAuthErrors: - feature_value = kAccountConsistencyFeatureMethodDiceFixAuthErrors; - break; case AccountConsistencyMethod::kDiceMigration: feature_value = kAccountConsistencyFeatureMethodDiceMigration; break;
diff --git a/chrome/browser/signin/scoped_account_consistency.h b/chrome/browser/signin/scoped_account_consistency.h index 283479f..06d09a6a 100644 --- a/chrome/browser/signin/scoped_account_consistency.h +++ b/chrome/browser/signin/scoped_account_consistency.h
@@ -40,8 +40,6 @@ // ScopedAccountConsistencyMirror: SCOPED_ACCOUNT_CONSISTENCY_SPECIALIZATION(Mirror); -// ScopedAccountConsistencyDiceFixAuthErrors: -SCOPED_ACCOUNT_CONSISTENCY_SPECIALIZATION(DiceFixAuthErrors); // ScopedAccountConsistencyDiceMigration: SCOPED_ACCOUNT_CONSISTENCY_SPECIALIZATION(DiceMigration); // ScopedAccountConsistencyDice:
diff --git a/chrome/browser/signin/signin_profile_attributes_updater.cc b/chrome/browser/signin/signin_profile_attributes_updater.cc index e7e8e1d7..6ba517a 100644 --- a/chrome/browser/signin/signin_profile_attributes_updater.cc +++ b/chrome/browser/signin/signin_profile_attributes_updater.cc
@@ -18,10 +18,18 @@ SigninErrorController* signin_error_controller, const base::FilePath& profile_path) : signin_error_controller_(signin_error_controller), + signin_manager_(signin_manager), profile_path_(profile_path), signin_error_controller_observer_(this), signin_manager_observer_(this) { + // Some tests don't have a ProfileManager, disable this service. + if (!g_browser_process->profile_manager()) + return; + + signin_manager_observer_.Add(signin_manager_); signin_error_controller_observer_.Add(signin_error_controller); + + UpdateProfileAttributes(); // TODO(crbug.com/908457): Call OnErrorChanged() here, to catch any change // that happened since the construction of SigninErrorController. Profile // metrics depend on this bug and must be fixed first. @@ -34,11 +42,31 @@ signin_manager_observer_.RemoveAll(); } -void SigninProfileAttributesUpdater::OnErrorChanged() { - // Some tests don't have a ProfileManager. - if (g_browser_process->profile_manager() == nullptr) +void SigninProfileAttributesUpdater::UpdateProfileAttributes() { + ProfileAttributesEntry* entry; + ProfileManager* profile_manager = g_browser_process->profile_manager(); + if (!profile_manager->GetProfileAttributesStorage() + .GetProfileAttributesWithPath(profile_path_, &entry)) { return; + } + std::string old_gaia_id = entry->GetGAIAId(); + + if (signin_manager_->IsAuthenticated()) { + AccountInfo account_info = signin_manager_->GetAuthenticatedAccountInfo(); + entry->SetAuthInfo(account_info.gaia, + base::UTF8ToUTF16(account_info.email)); + } else { + entry->SetLocalAuthCredentials(std::string()); + entry->SetAuthInfo(std::string(), base::string16()); + entry->SetIsSigninRequired(false); + } + + if (old_gaia_id != entry->GetGAIAId()) + ProfileMetrics::UpdateReportedProfilesStatistics(profile_manager); +} + +void SigninProfileAttributesUpdater::OnErrorChanged() { ProfileAttributesEntry* entry; if (!g_browser_process->profile_manager() ->GetProfileAttributesStorage() @@ -49,34 +77,12 @@ entry->SetIsAuthError(signin_error_controller_->HasError()); } -#if !defined(OS_CHROMEOS) void SigninProfileAttributesUpdater::GoogleSigninSucceeded( const AccountInfo& account_info) { - ProfileAttributesEntry* entry; - ProfileManager* profile_manager = g_browser_process->profile_manager(); - if (!profile_manager->GetProfileAttributesStorage() - .GetProfileAttributesWithPath(profile_path_, &entry)) { - return; - } - - entry->SetAuthInfo(account_info.gaia, base::UTF8ToUTF16(account_info.email)); - ProfileMetrics::UpdateReportedProfilesStatistics(profile_manager); + UpdateProfileAttributes(); } void SigninProfileAttributesUpdater::GoogleSignedOut( const AccountInfo& account_info) { - ProfileAttributesEntry* entry; - bool has_entry = g_browser_process->profile_manager() - ->GetProfileAttributesStorage() - .GetProfileAttributesWithPath(profile_path_, &entry); - - // If sign out occurs because Sync setup was in progress and the Profile got - // deleted, then the profile's no longer in the ProfileAttributesStorage. - if (!has_entry) - return; - - entry->SetLocalAuthCredentials(std::string()); - entry->SetAuthInfo(std::string(), base::string16()); - entry->SetIsSigninRequired(false); + UpdateProfileAttributes(); } -#endif // !defined(OS_CHROMEOS)
diff --git a/chrome/browser/signin/signin_profile_attributes_updater.h b/chrome/browser/signin/signin_profile_attributes_updater.h index 699593c..f79937f 100644 --- a/chrome/browser/signin/signin_profile_attributes_updater.h +++ b/chrome/browser/signin/signin_profile_attributes_updater.h
@@ -29,17 +29,18 @@ // KeyedService: void Shutdown() override; + // Updates the profile attributes on signin and signout events. + void UpdateProfileAttributes(); + // SigninErrorController::Observer: void OnErrorChanged() override; -// These observer methods are never called on ChromeOS. -#if !defined(OS_CHROMEOS) // SigninManagerBase::Observer: void GoogleSigninSucceeded(const AccountInfo& account_info) override; void GoogleSignedOut(const AccountInfo& account_info) override; -#endif SigninErrorController* signin_error_controller_; + SigninManagerBase* signin_manager_; const base::FilePath profile_path_; ScopedObserver<SigninErrorController, SigninProfileAttributesUpdater> signin_error_controller_observer_;
diff --git a/chrome/browser/signin/signin_profile_attributes_updater_unittest.cc b/chrome/browser/signin/signin_profile_attributes_updater_unittest.cc new file mode 100644 index 0000000..9384be65 --- /dev/null +++ b/chrome/browser/signin/signin_profile_attributes_updater_unittest.cc
@@ -0,0 +1,138 @@ +// 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 "chrome/browser/signin/signin_profile_attributes_updater.h" + +#include "base/bind.h" +#include "base/files/file_path.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/profiles/profile_attributes_entry.h" +#include "chrome/browser/profiles/profile_attributes_storage.h" +#include "chrome/browser/signin/account_tracker_service_factory.h" +#include "chrome/browser/signin/chrome_signin_client_factory.h" +#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h" +#include "chrome/browser/signin/fake_signin_manager_builder.h" +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/browser/signin/test_signin_client_builder.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "components/signin/core/browser/account_tracker_service.h" +#include "components/signin/core/browser/fake_profile_oauth2_token_service.h" +#include "components/signin/core/browser/signin_manager.h" +#include "components/sync_preferences/pref_service_syncable.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "google_apis/gaia/google_service_auth_error.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +#if defined(OS_CHROMEOS) +// Returns a SigninManager that authenticated at creation. +std::unique_ptr<KeyedService> BuildAuthenticatedSigninManager( + content::BrowserContext* context) { + std::unique_ptr<KeyedService> signin_manager = + BuildFakeSigninManagerForTesting(context); + static_cast<SigninManagerBase*>(signin_manager.get()) + ->SetAuthenticatedAccountInfo("gaia", "example@email.com"); + return signin_manager; +} +#endif + +} // namespace + +class SigninProfileAttributesUpdaterTest : public testing::Test { + public: + SigninProfileAttributesUpdaterTest() + : profile_manager_(TestingBrowserProcess::GetGlobal()) {} + + void SetUp() override { + testing::Test::SetUp(); + + ASSERT_TRUE(profile_manager_.SetUp()); + TestingProfile::TestingFactories testing_factories; + testing_factories.emplace_back( + ChromeSigninClientFactory::GetInstance(), + base::BindRepeating(&signin::BuildTestSigninClient)); + testing_factories.emplace_back( + ProfileOAuth2TokenServiceFactory::GetInstance(), + base::BindRepeating(&BuildFakeProfileOAuth2TokenService)); +#if defined(OS_CHROMEOS) + testing_factories.emplace_back( + SigninManagerFactory::GetInstance(), + base::BindRepeating(BuildAuthenticatedSigninManager)); +#endif + std::string name = "profile_name"; + profile_ = profile_manager_.CreateTestingProfile( + name, /*prefs=*/nullptr, base::UTF8ToUTF16(name), 0, std::string(), + std::move(testing_factories)); + ASSERT_TRUE(profile_); + } + + content::TestBrowserThreadBundle thread_bundle_; + TestingProfileManager profile_manager_; + TestingProfile* profile_ = nullptr; // Owned by the profile manager. +}; + +#if !defined(OS_CHROMEOS) +// Tests that the browser state info is updated on signin and signout. +// ChromeOS does not support signout. +TEST_F(SigninProfileAttributesUpdaterTest, SigninSignout) { + ProfileAttributesEntry* entry; + ASSERT_TRUE(profile_manager_.profile_attributes_storage() + ->GetProfileAttributesWithPath(profile_->GetPath(), &entry)); + ASSERT_FALSE(entry->IsAuthenticated()); + + // Signin. + AccountTrackerService* account_tracker = + AccountTrackerServiceFactory::GetForProfile(profile_); + SigninManager* signin_manager = SigninManagerFactory::GetForProfile(profile_); + std::string account_id = + account_tracker->SeedAccountInfo("gaia", "example@email.com"); + signin_manager->OnExternalSigninCompleted("example@email.com"); + EXPECT_TRUE(entry->IsAuthenticated()); + EXPECT_EQ("gaia", entry->GetGAIAId()); + EXPECT_EQ("example@email.com", base::UTF16ToUTF8(entry->GetUserName())); + + // Signout. + signin_manager->SignOut(signin_metrics::SIGNOUT_TEST, + signin_metrics::SignoutDelete::IGNORE_METRIC); + EXPECT_FALSE(entry->IsAuthenticated()); +} +#endif // !defined(OS_CHROMEOS) + +// Tests that the browser state info is updated on auth error change. +TEST_F(SigninProfileAttributesUpdaterTest, AuthError) { + ProfileAttributesEntry* entry; + ASSERT_TRUE(profile_manager_.profile_attributes_storage() + ->GetProfileAttributesWithPath(profile_->GetPath(), &entry)); + + AccountTrackerService* account_tracker = + AccountTrackerServiceFactory::GetForProfile(profile_); + FakeProfileOAuth2TokenService* token_service = + static_cast<FakeProfileOAuth2TokenService*>( + ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)); + std::string account_id = + account_tracker->SeedAccountInfo("gaia", "example@email.com"); + token_service->UpdateCredentials(account_id, "token"); +#if !defined(OS_CHROMEOS) + // ChromeOS is signed in at creation. + SigninManagerFactory::GetForProfile(profile_)->OnExternalSigninCompleted( + "example@email.com"); +#endif + EXPECT_TRUE(entry->IsAuthenticated()); + EXPECT_FALSE(entry->IsAuthError()); + + // Set auth error. + token_service->UpdateAuthErrorForTesting( + account_id, + GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); + EXPECT_TRUE(entry->IsAuthError()); + + // Remove auth error. + token_service->UpdateAuthErrorForTesting( + account_id, GoogleServiceAuthError::AuthErrorNone()); + EXPECT_FALSE(entry->IsAuthError()); +}
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc index fa920506..cbc792bb 100644 --- a/chrome/browser/ssl/ssl_browsertest.cc +++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -1347,52 +1347,6 @@ AuthState::RAN_INSECURE_CONTENT); } -// Checks that a console message is printed when a subresource is -// loaded over broken HTTPS. The test will: -// 1. Navigate to a site with broken SSL (example.test) -// 2. Click through the interstitial -// 3. Navigate to another site with an iframe to example.test -// 4. Check that console message has been printed -IN_PROC_BROWSER_TEST_P(SSLUITest, TestBrokenHTTPSConsoleMessage) { - ASSERT_TRUE(https_server_.Start()); - ASSERT_TRUE(https_server_mismatched_.Start()); - - WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); - ASSERT_TRUE(tab); - content::ConsoleObserverDelegate console_observer( - tab, - "Mixed Content: The page at * attempted to load subresource at * over " - "broken HTTPS."); - tab->SetDelegate(&console_observer); - - GURL url = https_server_mismatched_.GetURL("/ssl/blank_page.html"); - GURL::Replacements replacements; - replacements.SetHostStr("example.test"); - url = url.ReplaceComponents(replacements); - // Navigate to a page with a certificate error and click through the - // interstitial. - ui_test_utils::NavigateToURL(browser(), url); - CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID, - AuthState::SHOWING_INTERSTITIAL); - ProceedThroughInterstitial(tab); - - net::HostPortPair pair("example.test", - https_server_mismatched_.host_port_pair().port()); - std::string replacement_path; - GetFilePathWithHostAndPortReplacement("/ssl/blank_page.html", pair, - &replacement_path); - - ui_test_utils::NavigateToURL(browser(), - https_server_.GetURL(replacement_path)); - - ASSERT_FALSE(IsShowingInterstitial(tab)); - - console_observer.Wait(); - EXPECT_TRUE(base::MatchPattern(console_observer.message(), - "Mixed Content: The page at * attempted to " - "load subresource at * over broken HTTPS.")); -} - namespace { // A WebContentsObserver that allows the user to wait for a same-document
diff --git a/chrome/browser/supervised_user/OWNERS b/chrome/browser/supervised_user/OWNERS index e856a98..33a7a97 100644 --- a/chrome/browser/supervised_user/OWNERS +++ b/chrome/browser/supervised_user/OWNERS
@@ -1,3 +1,5 @@ +escordeiro@chromium.org +menegola@chromium.org pam@chromium.org treib@chromium.org
diff --git a/chrome/browser/sync/test/integration/sessions_helper.cc b/chrome/browser/sync/test/integration/sessions_helper.cc index 35943a1f..6971a52 100644 --- a/chrome/browser/sync/test/integration/sessions_helper.cc +++ b/chrome/browser/sync/test/integration/sessions_helper.cc
@@ -199,6 +199,12 @@ .GoForward(); } +bool ExecJs(int browser_index, int tab_index, const std::string& script) { + return content::ExecJs( + test()->GetBrowser(browser_index)->tab_strip_model()->GetWebContentsAt(0), + script); +} + bool WaitForTabsToLoad(int browser_index, const std::vector<GURL>& urls) { int tab_index = 0; for (const auto& url : urls) {
diff --git a/chrome/browser/sync/test/integration/sessions_helper.h b/chrome/browser/sync/test/integration/sessions_helper.h index 302be9c..4ef7934 100644 --- a/chrome/browser/sync/test/integration/sessions_helper.h +++ b/chrome/browser/sync/test/integration/sessions_helper.h
@@ -117,6 +117,9 @@ // one; if this isn't possible, does nothing void NavigateTabForward(int browser_index); +// Runs Javascript within a specified tab. +bool ExecJs(int browser_index, int tab_index, const std::string& script); + // Wait for a session change to |web_contents| to propagate to the model // associator. Will return true once |url| has been found, or false if it times // out while waiting.
diff --git a/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc b/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc index 502bc3f6..bb38eaf 100644 --- a/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc
@@ -4,6 +4,7 @@ #include "base/macros.h" #include "base/run_loop.h" +#include "base/strings/stringprintf.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/sessions/session_service.h" @@ -40,6 +41,7 @@ using fake_server::SessionsHierarchy; using sessions_helper::CheckInitialState; using sessions_helper::CloseTab; +using sessions_helper::ExecJs; using sessions_helper::GetLocalWindows; using sessions_helper::GetSessionData; using sessions_helper::MoveTab; @@ -217,6 +219,45 @@ } IN_PROC_BROWSER_TEST_F(SingleClientSessionsSyncTest, + JavascriptHistoryReplaceState) { + // Executing Javascript requires HTTP pages with an origin. + ASSERT_TRUE(embedded_test_server()->Start()); + const std::string url1 = + embedded_test_server()->GetURL("/sync/simple.html").spec(); + const std::string url2 = + embedded_test_server()->GetURL("/replaced_history.html").spec(); + + ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(CheckInitialState(0)); + + ASSERT_TRUE(OpenTab(0, GURL(url1))); + WaitForHierarchyOnServer(SessionsHierarchy({{url1}})); + + ASSERT_TRUE( + ExecJs(/*browser_index=*/0, /*tab_index=*/0, + base::StringPrintf("history.replaceState({}, 'page 2', '%s')", + url2.c_str()))); + + WaitForHierarchyOnServer(SessionsHierarchy({{url2}})); + + // Fetch the tab from the server for further verification. + const std::vector<sync_pb::SyncEntity> entities = + GetFakeServer()->GetSyncEntitiesByModelType(syncer::SESSIONS); + const sync_pb::TabNavigation* tab_navigation = nullptr; + for (const sync_pb::SyncEntity& entity : entities) { + if (entity.specifics().session().tab().navigation_size() == 1 && + entity.specifics().session().tab().navigation(0).virtual_url() == + url2) { + tab_navigation = &entity.specifics().session().tab().navigation(0); + } + } + + ASSERT_NE(nullptr, tab_navigation); + EXPECT_TRUE(tab_navigation->has_replaced_navigation()); + EXPECT_EQ(url1, tab_navigation->replaced_navigation().first_committed_url()); +} + +IN_PROC_BROWSER_TEST_F(SingleClientSessionsSyncTest, SessionsWithoutHistorySync) { ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; // If the user disables history sync on settings, but still enables tab sync,
diff --git a/chrome/browser/sync/test/integration/two_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/two_client_wallet_sync_test.cc index 5db75376..787f3fc 100644 --- a/chrome/browser/sync/test/integration/two_client_wallet_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_wallet_sync_test.cc
@@ -5,7 +5,6 @@ #include "base/macros.h" #include "chrome/browser/sync/test/integration/sync_test.h" #include "chrome/browser/sync/test/integration/wallet_helper.h" -#include "components/autofill/core/browser/autofill_metadata.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/personal_data_manager.h" @@ -18,7 +17,6 @@ namespace { -using autofill::AutofillMetadata; using autofill::AutofillProfile; using autofill::CreditCard; using autofill::PersonalDataManager; @@ -28,8 +26,6 @@ using wallet_helper::GetCreditCard; using wallet_helper::GetLocalProfiles; using wallet_helper::GetPersonalDataManager; -using wallet_helper::GetServerAddressesMetadata; -using wallet_helper::GetServerCardsMetadata; using wallet_helper::GetServerCreditCards; using wallet_helper::GetServerProfiles; using wallet_helper::kDefaultBillingAddressID; @@ -588,113 +584,6 @@ EXPECT_EQ(guid, local_addresses[0]->guid()); } -IN_PROC_BROWSER_TEST_P(TwoClientWalletSyncTest, - DeleteServerCardMetadataWhenDataGetsRemoved) { - InitWithDefaultFeatures(); - - GetFakeServer()->SetWalletData( - {CreateSyncWalletCard(/*name=*/"card-1", /*last_four=*/"0001", - kDefaultBillingAddressID), - CreateSyncWalletAddress(/*name=*/"address-1", /*company=*/"Company-1"), - CreateDefaultSyncPaymentsCustomerData()}); - ASSERT_TRUE(SetupSync()); - - // Grab the current card on the first client. - std::vector<CreditCard*> credit_cards = GetServerCreditCards(0); - ASSERT_EQ(1u, credit_cards.size()); - CreditCard card = *credit_cards[0]; - - // Remove the card from the data. - GetFakeServer()->SetWalletData( - {CreateSyncWalletAddress(/*name=*/"address-1", /*company=*/"Company-1"), - CreateDefaultSyncPaymentsCustomerData()}); - - // Simulate using the card locally, only to force an update when committing - // a change. - ASSERT_EQ(1u, card.use_count()); - card.set_use_count(2); - card.set_use_date(kLaterTime); - UpdateServerCardMetadata(0, card); - - // Wait for the change to propagate. - EXPECT_TRUE(AutofillWalletChecker(0, 1).Wait()); - - EXPECT_EQ(0U, GetServerCreditCards(0).size()); - EXPECT_EQ(0U, GetServerCreditCards(1).size()); - - // Also check the DB directly that there is no _metadata_. - std::map<std::string, AutofillMetadata> cards_metadata_0; - GetServerCardsMetadata(0, &cards_metadata_0); - EXPECT_EQ(0U, cards_metadata_0.size()); - std::map<std::string, AutofillMetadata> cards_metadata_1; - GetServerCardsMetadata(1, &cards_metadata_1); - EXPECT_EQ(0U, cards_metadata_1.size()); - - // Double check that cards data & metadata is intact. - EXPECT_EQ(1U, GetServerProfiles(0).size()); - EXPECT_EQ(1U, GetServerProfiles(1).size()); - std::map<std::string, AutofillMetadata> addresses_metadata_0; - GetServerAddressesMetadata(0, &addresses_metadata_0); - EXPECT_EQ(1U, addresses_metadata_0.size()); - std::map<std::string, AutofillMetadata> addresses_metadata_1; - GetServerAddressesMetadata(1, &addresses_metadata_1); - EXPECT_EQ(1U, addresses_metadata_1.size()); -} - -IN_PROC_BROWSER_TEST_P(TwoClientWalletSyncTest, - DeleteServerAddressMetadataWhenDataGetsRemoved) { - InitWithDefaultFeatures(); - - GetFakeServer()->SetWalletData( - {CreateSyncWalletCard(/*name=*/"card-1", /*last_four=*/"0001", - kDefaultBillingAddressID), - CreateSyncWalletAddress(/*name=*/"address-1", /*company=*/"Company-1"), - CreateDefaultSyncPaymentsCustomerData()}); - ASSERT_TRUE(SetupSync()); - - // Grab the current address on the first client. - std::vector<AutofillProfile*> server_addresses = GetServerProfiles(0); - ASSERT_EQ(1u, server_addresses.size()); - AutofillProfile address = *server_addresses[0]; - - // Remove the address from the data. - GetFakeServer()->SetWalletData( - {CreateSyncWalletCard(/*name=*/"card-1", /*last_four=*/"0001", - kDefaultBillingAddressID), - CreateDefaultSyncPaymentsCustomerData()}); - - // Simulate using the address locally, only to force an update when committing - // a change. - ASSERT_EQ(1u, address.use_count()); - address.set_use_count(2); - address.set_use_date(kLaterTime); - UpdateServerAddressMetadata(0, address); - - // Wait for the change to propagate. - EXPECT_TRUE(AutofillWalletChecker(0, 1).Wait()); - - EXPECT_EQ(0U, GetServerProfiles(0).size()); - EXPECT_EQ(0U, GetServerProfiles(1).size()); - - // Also check the DB directly that there is no _metadata_. - std::map<std::string, AutofillMetadata> addresses_metadata_0; - GetServerAddressesMetadata(0, &addresses_metadata_0); - EXPECT_EQ(0U, addresses_metadata_0.size()); - std::map<std::string, AutofillMetadata> addresses_metadata_1; - GetServerAddressesMetadata(1, &addresses_metadata_1); - EXPECT_EQ(0U, addresses_metadata_1.size()); - - // Double check that cards data & metadata is intact. - EXPECT_EQ(1U, GetServerCreditCards(0).size()); - EXPECT_EQ(1U, GetServerCreditCards(1).size()); - std::map<std::string, AutofillMetadata> cards_metadata_0; - GetServerCardsMetadata(0, &cards_metadata_0); - EXPECT_EQ(1U, cards_metadata_0.size()); - std::map<std::string, AutofillMetadata> cards_metadata_1; - GetServerCardsMetadata(1, &cards_metadata_1); - EXPECT_EQ(1U, cards_metadata_1.size()); -} - INSTANTIATE_TEST_CASE_P(USS, TwoClientWalletSyncTest, ::testing::Values(false, true));
diff --git a/chrome/browser/sync/test/integration/wallet_helper.cc b/chrome/browser/sync/test/integration/wallet_helper.cc index 3ad640b..8c67be36 100644 --- a/chrome/browser/sync/test/integration/wallet_helper.cc +++ b/chrome/browser/sync/test/integration/wallet_helper.cc
@@ -17,7 +17,6 @@ #include "chrome/browser/sync/test/integration/sync_test.h" #include "chrome/browser/web_data_service_factory.h" #include "components/autofill/core/browser/autofill_data_util.h" -#include "components/autofill/core/browser/autofill_metadata.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/payments/payments_customer_data.h" #include "components/autofill/core/browser/personal_data_manager.h" @@ -25,7 +24,6 @@ #include "components/keyed_service/core/service_access_type.h" #include "components/sync/driver/sync_driver_switches.h" -using autofill::AutofillMetadata; using autofill::AutofillProfile; using autofill::AutofillTable; using autofill::AutofillWebDataService; @@ -180,22 +178,6 @@ ->SetPaymentsCustomerData(&customer_data); } -void GetServerCardsMetadataOnDBSequence( - AutofillWebDataService* wds, - std::map<std::string, AutofillMetadata>* cards_metadata) { - DCHECK(wds->GetDBTaskRunner()->RunsTasksInCurrentSequence()); - AutofillTable::FromWebDatabase(wds->GetDatabase()) - ->GetServerCardsMetadata(cards_metadata); -} - -void GetServerAddressesMetadataOnDBSequence( - AutofillWebDataService* wds, - std::map<std::string, AutofillMetadata>* addresses_metadata) { - DCHECK(wds->GetDBTaskRunner()->RunsTasksInCurrentSequence()); - AutofillTable::FromWebDatabase(wds->GetDatabase()) - ->GetServerAddressesMetadata(addresses_metadata); -} - } // namespace namespace wallet_helper { @@ -262,27 +244,6 @@ WaitForCurrentTasksToComplete(wds->GetDBTaskRunner()); } -void GetServerCardsMetadata( - int profile, - std::map<std::string, AutofillMetadata>* cards_metadata) { - scoped_refptr<AutofillWebDataService> wds = GetProfileWebDataService(profile); - wds->GetDBTaskRunner()->PostTask( - FROM_HERE, base::BindOnce(&GetServerCardsMetadataOnDBSequence, - base::Unretained(wds.get()), cards_metadata)); - WaitForCurrentTasksToComplete(wds->GetDBTaskRunner()); -} - -void GetServerAddressesMetadata( - int profile, - std::map<std::string, AutofillMetadata>* addresses_metadata) { - scoped_refptr<AutofillWebDataService> wds = GetProfileWebDataService(profile); - wds->GetDBTaskRunner()->PostTask( - FROM_HERE, - base::BindOnce(&GetServerAddressesMetadataOnDBSequence, - base::Unretained(wds.get()), addresses_metadata)); - WaitForCurrentTasksToComplete(wds->GetDBTaskRunner()); -} - sync_pb::SyncEntity CreateDefaultSyncWalletCard() { return CreateSyncWalletCard(kDefaultCardID, kDefaultCardLastFour, kDefaultBillingAddressID);
diff --git a/chrome/browser/sync/test/integration/wallet_helper.h b/chrome/browser/sync/test/integration/wallet_helper.h index 0f658da3..a566ff3 100644 --- a/chrome/browser/sync/test/integration/wallet_helper.h +++ b/chrome/browser/sync/test/integration/wallet_helper.h
@@ -13,7 +13,6 @@ #include "testing/gtest/include/gtest/gtest.h" namespace autofill { -struct AutofillMetadata; class AutofillProfile; class AutofillWebDataService; class CreditCard; @@ -63,14 +62,6 @@ int profile, const autofill::AutofillProfile& server_address); -void GetServerCardsMetadata( - int profile, - std::map<std::string, autofill::AutofillMetadata>* cards_metadata); - -void GetServerAddressesMetadata( - int profile, - std::map<std::string, autofill::AutofillMetadata>* addresses_metadata); - sync_pb::SyncEntity CreateDefaultSyncWalletCard(); sync_pb::SyncEntity CreateSyncWalletCard(const std::string& name,
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 04412c96..b2813cb 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -2961,6 +2961,7 @@ "views/frame/opaque_browser_frame_view.h", "views/frame/opaque_browser_frame_view_layout.cc", "views/frame/opaque_browser_frame_view_layout.h", + "views/frame/opaque_browser_frame_view_layout_delegate.cc", "views/frame/opaque_browser_frame_view_layout_delegate.h", "views/frame/opaque_browser_frame_view_linux.cc", "views/frame/opaque_browser_frame_view_linux.h", @@ -3232,6 +3233,8 @@ "app_list/page_break_app_item.h", "app_list/page_break_constants.cc", "app_list/page_break_constants.h", + "app_list/search/app_service_app_result.cc", + "app_list/search/app_service_app_result.h", "app_list/search/arc_app_result.cc", "app_list/search/arc_app_result.h", "app_list/search/crostini_app_result.cc",
diff --git a/chrome/browser/ui/app_list/app_service_app_item.cc b/chrome/browser/ui/app_list/app_service_app_item.cc index 407cb652..e8c5a43 100644 --- a/chrome/browser/ui/app_list/app_service_app_item.cc +++ b/chrome/browser/ui/app_list/app_service_app_item.cc
@@ -47,7 +47,8 @@ void AppServiceAppItem::Activate(int event_flags) { apps::AppServiceProxy* proxy = apps::AppServiceProxy::Get(profile()); if (proxy) { - proxy->Launch(id(), event_flags, apps::mojom::LaunchSource::kFromAppList, + proxy->Launch(id(), event_flags, + apps::mojom::LaunchSource::kFromAppListGrid, GetController()->GetAppListDisplayId()); } }
diff --git a/chrome/browser/ui/app_list/search/app_search_provider.cc b/chrome/browser/ui/app_list/search/app_search_provider.cc index 073d435..1b684b4 100644 --- a/chrome/browser/ui/app_list/search/app_search_provider.cc +++ b/chrome/browser/ui/app_list/search/app_search_provider.cc
@@ -26,6 +26,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/clock.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service.h" @@ -44,11 +45,13 @@ #include "chrome/browser/ui/app_list/chrome_app_list_item.h" #include "chrome/browser/ui/app_list/extension_app_utils.h" #include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h" +#include "chrome/browser/ui/app_list/search/app_service_app_result.h" #include "chrome/browser/ui/app_list/search/arc_app_result.h" #include "chrome/browser/ui/app_list/search/crostini_app_result.h" #include "chrome/browser/ui/app_list/search/extension_app_result.h" #include "chrome/browser/ui/app_list/search/internal_app_result.h" #include "chrome/browser/ui/app_list/search/search_result_ranker/app_search_result_ranker.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" #include "components/sync/base/model_type.h" @@ -71,9 +74,6 @@ // Relevance threshold to use when Crostini has not yet been enabled. This value // is somewhat arbitrary, but is roughly equivalent to the 'ter' in 'terminal'. constexpr double kCrostiniTerminalRelevanceThreshold = 0.8; -// These are added to the localized values for convenience. The leading space -// is as we just append this to the localized version of 'Linux'. -constexpr char kExtraCrostiniTerminalKeywords[] = " linux terminal crostini"; // Adds |app_result| to |results| only in case no duplicate apps were already // added. Duplicate means the same app but for different domain, Chrome and @@ -165,13 +165,18 @@ bool MatchSearchableText(const TokenizedString& query) { if (searchable_text_.empty()) return false; - if (!tokenized_indexed_searchable_text_) { - tokenized_indexed_searchable_text_ = - std::make_unique<TokenizedString>(searchable_text_); - } + if (tokenized_indexed_searchable_text_.empty()) + for (const base::string16& curr_text : searchable_text_) { + tokenized_indexed_searchable_text_.push_back( + std::make_unique<TokenizedString>(curr_text)); + } TokenizedStringMatch match; - match.Calculate(query, *tokenized_indexed_searchable_text_); - return match.relevance() > relevance_threshold(); + for (auto& curr_text : tokenized_indexed_searchable_text_) { + match.Calculate(query, *curr_text); + if (match.relevance() > relevance_threshold()) + return true; + } + return false; } AppSearchProvider::DataSource* data_source() { return data_source_; } @@ -186,9 +191,12 @@ bool searchable() const { return searchable_; } void set_searchable(bool searchable) { searchable_ = searchable; } - const base::string16& searchable_text() const { return searchable_text_; } - void set_searchable_text(const base::string16& searchable_text) { - searchable_text_ = searchable_text; + const std::vector<base::string16>& searchable_text() const { + return searchable_text_; + } + void AddSearchableText(const base::string16& searchable_text) { + DCHECK(tokenized_indexed_searchable_text_.empty()); + searchable_text_.push_back(searchable_text); } // Relevance must exceed the threshold to appear as a search result. Exact @@ -203,14 +211,15 @@ private: AppSearchProvider::DataSource* data_source_; std::unique_ptr<TokenizedString> tokenized_indexed_name_; - std::unique_ptr<TokenizedString> tokenized_indexed_searchable_text_; + std::vector<std::unique_ptr<TokenizedString>> + tokenized_indexed_searchable_text_; const std::string id_; const base::string16 name_; const base::Time last_launch_time_; const base::Time install_time_; bool recommendable_ = true; bool searchable_ = true; - base::string16 searchable_text_; + std::vector<base::string16> searchable_text_; float relevance_threshold_ = 0.f; // Set to true in case app was installed internally, by sync, policy or as a // default app. @@ -247,6 +256,57 @@ namespace { +class AppServiceDataSource : public AppSearchProvider::DataSource { + public: + AppServiceDataSource(Profile* profile, AppSearchProvider* owner) + : AppSearchProvider::DataSource(profile, owner) { + // TODO(crbug.com/826982): observe the cache for apps being installed and + // uninstalled, and in the callback, call RefreshAppsAndUpdateResultsXxx(). + } + + ~AppServiceDataSource() override = default; + + // AppSearchProvider::DataSource overrides: + void AddApps(AppSearchProvider::Apps* apps_vector) override { + apps::AppServiceProxy* proxy = apps::AppServiceProxy::Get(profile()); + if (!proxy) { + return; + } + proxy->Cache().ForEachApp( + [this, apps_vector](const apps::AppUpdate& update) { + if (update.ShowInSearch() != apps::mojom::OptionalBool::kTrue) { + return; + } + + // TODO(crbug.com/826982): add the "can load in incognito" concept to + // the App Service and use it here, similar to ExtensionDataSource. + + apps_vector->emplace_back(std::make_unique<AppSearchProvider::App>( + this, update.AppId(), + // TODO(crbug.com/826982): add the "short name" concept to the App + // Service, and use it here. + update.Name(), + // TODO(crbug.com/826982): add the "last launch time" and "install + // time" concepts to the App Service, and use them here. + base::Time(), base::Time(), + // TODO(crbug.com/826982): add the "installed internally" concept + // to the App Service, and use it here. + true)); + }); + } + + std::unique_ptr<AppResult> CreateResult( + const std::string& app_id, + AppListControllerDelegate* list_controller, + bool is_recommended) override { + return std::make_unique<AppServiceAppResult>( + profile(), app_id, list_controller, is_recommended); + } + + private: + DISALLOW_COPY_AND_ASSIGN(AppServiceDataSource); +}; + class ExtensionDataSource : public AppSearchProvider::DataSource, public extensions::ExtensionRegistryObserver { public: @@ -392,8 +452,11 @@ class InternalDataSource : public AppSearchProvider::DataSource { public: - InternalDataSource(Profile* profile, AppSearchProvider* owner) - : AppSearchProvider::DataSource(profile, owner) { + InternalDataSource(Profile* profile, + AppSearchProvider* owner, + bool just_continue_reading) + : AppSearchProvider::DataSource(profile, owner), + just_continue_reading_(just_continue_reading) { sync_sessions::SessionSyncService* service = SessionSyncServiceFactory::GetInstance()->GetForProfile(profile); if (!service) @@ -420,6 +483,8 @@ if (!service || !service->GetOpenTabsUIDelegate()) { continue; } + } else if (just_continue_reading_) { + continue; } apps->emplace_back(std::make_unique<AppSearchProvider::App>( @@ -430,7 +495,7 @@ apps->back()->set_recommendable(internal_app.recommendable); apps->back()->set_searchable(internal_app.searchable); if (internal_app.searchable_string_resource_id != 0) { - apps->back()->set_searchable_text(l10n_util::GetStringUTF16( + apps->back()->AddSearchableText(l10n_util::GetStringUTF16( internal_app.searchable_string_resource_id)); } } @@ -445,6 +510,15 @@ } private: + // Whether InternalDataSource provides just the kInternalAppIdContinueReading + // app. If true, other internal apps are provided by AppServiceDataSource. + // + // TODO(crbug.com/826982): move the "foreign session updated subscription" + // into the App Service? Or if, in terms of UI, "continue reading" is exposed + // only in the app list search UI, it might make more sense to leave it in + // this code. See also built_in_chromeos_apps.cc. + bool just_continue_reading_; + std::unique_ptr<base::CallbackList<void()>::Subscription> foreign_session_updated_subscription_; @@ -475,16 +549,14 @@ if (registration.NoDisplay()) continue; // Eventually it would be nice to use additional data points, for example - // the 'Keywords' desktop entry field and the executable file name. + // the executable file name. apps->emplace_back(std::make_unique<AppSearchProvider::App>( this, app_id, registration.Name(), registration.LastLaunchTime(), registration.InstallTime(), false /* installed_internally */)); + for (const std::string& keyword : registration.Keywords()) + apps->back()->AddSearchableText(base::UTF8ToUTF16(keyword)); if (app_id == crostini::kCrostiniTerminalId) { - base::string16 searchable_text = - l10n_util::GetStringUTF16(IDS_CROSTINI_TERMINAL_APP_SEARCH_TERMS); - searchable_text += base::UTF8ToUTF16(kExtraCrostiniTerminalKeywords); - apps->back()->set_searchable_text(searchable_text); // Until it's been installed, the Terminal is hidden and requires // a few characters before being shown in search results. if (!crostini::IsCrostiniEnabled(profile())) { @@ -535,16 +607,25 @@ chromeos::ProfileHelper::IsEphemeralUserProfile(profile))), refresh_apps_factory_(this), update_results_factory_(this) { - data_sources_.emplace_back( - std::make_unique<ExtensionDataSource>(profile, this)); - if (arc::IsArcAllowedForProfile(profile)) - data_sources_.emplace_back(std::make_unique<ArcDataSource>(profile, this)); - if (crostini::IsCrostiniUIAllowedForProfile(profile)) { + bool app_service_enabled = + base::FeatureList::IsEnabled(features::kAppService); + if (app_service_enabled) { data_sources_.emplace_back( - std::make_unique<CrostiniDataSource>(profile, this)); + std::make_unique<AppServiceDataSource>(profile, this)); + } else { + data_sources_.emplace_back( + std::make_unique<ExtensionDataSource>(profile, this)); + if (arc::IsArcAllowedForProfile(profile)) { + data_sources_.emplace_back( + std::make_unique<ArcDataSource>(profile, this)); + } + if (crostini::IsCrostiniUIAllowedForProfile(profile)) { + data_sources_.emplace_back( + std::make_unique<CrostiniDataSource>(profile, this)); + } } data_sources_.emplace_back( - std::make_unique<InternalDataSource>(profile, this)); + std::make_unique<InternalDataSource>(profile, this, app_service_enabled)); } AppSearchProvider::~AppSearchProvider() {} @@ -601,7 +682,7 @@ base::string16 title = app->name(); if (app->id() == kInternalAppIdContinueReading) { if (HasRecommendableForeignTab(profile_, &title, nullptr)) - app->set_searchable_text(title); + app->AddSearchableText(title); else continue; }
diff --git a/chrome/browser/ui/app_list/search/app_service_app_result.cc b/chrome/browser/ui/app_list/search/app_service_app_result.cc new file mode 100644 index 0000000..b0a7001 --- /dev/null +++ b/chrome/browser/ui/app_list/search/app_service_app_result.cc
@@ -0,0 +1,98 @@ +// 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 "chrome/browser/ui/app_list/search/app_service_app_result.h" + +#include "ash/public/cpp/app_list/app_list_config.h" +#include "ash/public/cpp/app_list/app_list_types.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/ui/app_list/app_list_client_impl.h" +#include "chrome/browser/ui/app_list/search/internal_app_result.h" +#include "extensions/common/extension.h" + +namespace app_list { + +AppServiceAppResult::AppServiceAppResult(Profile* profile, + const std::string& app_id, + AppListControllerDelegate* controller, + bool is_recommendation) + : AppResult(profile, app_id, controller, is_recommendation), + weak_ptr_factory_(this) { + auto app_type = apps::mojom::AppType::kUnknown; + apps::AppServiceProxy* proxy = apps::AppServiceProxy::Get(profile); + + if (proxy) { + app_type = proxy->Cache().GetAppType(app_id); + + proxy->LoadIcon( + app_id, apps::mojom::IconCompression::kUncompressed, + AppListConfig::instance().GetPreferredIconDimension(display_type()), + base::BindOnce(&AppServiceAppResult::OnLoadIcon, + weak_ptr_factory_.GetWeakPtr(), false)); + + if (display_type() == ash::SearchResultDisplayType::kRecommendation) { + proxy->LoadIcon( + app_id, apps::mojom::IconCompression::kUncompressed, + AppListConfig::instance().suggestion_chip_icon_dimension(), + base::BindOnce(&AppServiceAppResult::OnLoadIcon, + weak_ptr_factory_.GetWeakPtr(), true)); + } + } + + switch (app_type) { + case apps::mojom::AppType::kBuiltIn: + set_id(app_id); + // TODO(crbug.com/826982): Is this SetResultType call necessary?? Does + // anyone care about the kInternalApp vs kInstalledApp distinction? + SetResultType(ResultType::kInternalApp); + // TODO(crbug.com/826982): Move this from the App Service caller to + // callee, closer to where other histograms are updated in + // BuiltInChromeOsApps::Launch?? + InternalAppResult::RecordShowHistogram(app_id); + break; + case apps::mojom::AppType::kExtension: + // TODO(crbug.com/826982): why do we pass the URL and not the app_id?? + // Can we replace this by the simpler "set_id(app_id)", and therefore + // pull that out of the switch? + set_id(extensions::Extension::GetBaseURLFromExtensionId(app_id).spec()); + break; + default: + set_id(app_id); + break; + } +} + +AppServiceAppResult::~AppServiceAppResult() = default; + +void AppServiceAppResult::Open(int event_flags) { + apps::AppServiceProxy* proxy = apps::AppServiceProxy::Get(profile()); + if (proxy) { + auto launch_source = + (display_type() == ash::SearchResultDisplayType::kRecommendation) + ? apps::mojom::LaunchSource::kFromAppListRecommendation + : apps::mojom::LaunchSource::kFromAppListQueryResult; + + proxy->Launch(app_id(), event_flags, launch_source, + controller()->GetAppListDisplayId()); + } +} + +void AppServiceAppResult::ExecuteLaunchCommand(int event_flags) { + Open(event_flags); +} + +void AppServiceAppResult::OnLoadIcon(bool chip, + apps::mojom::IconValuePtr icon_value) { + if (icon_value->icon_compression != + apps::mojom::IconCompression::kUncompressed) { + return; + } + if (chip) { + SetChipIcon(icon_value->uncompressed); + } else { + SetIcon(icon_value->uncompressed); + } +} + +} // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/app_service_app_result.h b/chrome/browser/ui/app_list/search/app_service_app_result.h new file mode 100644 index 0000000..dd99bfd --- /dev/null +++ b/chrome/browser/ui/app_list/search/app_service_app_result.h
@@ -0,0 +1,43 @@ +// 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 CHROME_BROWSER_UI_APP_LIST_SEARCH_APP_SERVICE_APP_RESULT_H_ +#define CHROME_BROWSER_UI_APP_LIST_SEARCH_APP_SERVICE_APP_RESULT_H_ + +#include "base/memory/weak_ptr.h" +#include "chrome/browser/ui/app_list/search/app_result.h" +#include "chrome/services/app_service/public/mojom/types.mojom.h" + +class AppListControllerDelegate; +class Profile; + +namespace app_list { + +class AppServiceAppResult : public AppResult { + public: + AppServiceAppResult(Profile* profile, + const std::string& app_id, + AppListControllerDelegate* controller, + bool is_recommendation); + ~AppServiceAppResult() override; + + private: + // ChromeSearchResult overrides: + void Open(int event_flags) override; + + // AppContextMenuDelegate overrides: + void ExecuteLaunchCommand(int event_flags) override; + + void OnLoadIcon(bool chip, apps::mojom::IconValuePtr icon_value); + + // TODO(crbug.com/826982): implement context menus. + + base::WeakPtrFactory<AppServiceAppResult> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(AppServiceAppResult); +}; + +} // namespace app_list + +#endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_APP_SERVICE_APP_RESULT_H_
diff --git a/chrome/browser/ui/app_list/search/tests/app_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/tests/app_search_provider_unittest.cc index 7106989b..51b07588 100644 --- a/chrome/browser/ui/app_list/search/tests/app_search_provider_unittest.cc +++ b/chrome/browser/ui/app_list/search/tests/app_search_provider_unittest.cc
@@ -427,7 +427,7 @@ EXPECT_EQ(kSettingsInternalName, RunQuery("Set")); } -TEST_F(AppSearchProviderTest, Crostini) { +TEST_F(AppSearchProviderTest, CrostiniTerminal) { CreateSearch(); // Crostini UI is not allowed yet. @@ -454,10 +454,30 @@ EXPECT_EQ("", RunQuery("li")); EXPECT_EQ("Terminal", RunQuery("lin")); EXPECT_EQ("Terminal", RunQuery("linux")); - EXPECT_EQ("", RunQuery("cro")); + EXPECT_EQ("", RunQuery("cr")); + EXPECT_EQ("Terminal", RunQuery("cro")); EXPECT_EQ("Terminal", RunQuery("cros")); } +TEST_F(AppSearchProviderTest, CrostiniApp) { + // This both allows Crostini UI and enables Crostini. + crostini::CrostiniTestHelper crostini_test_helper(profile()); + CreateSearch(); + + // Search based on keywords and name + auto testApp = crostini_test_helper.BasicApp("goodApp"); + std::map<std::string, std::set<std::string>> keywords; + keywords[""] = {"wow", "amazing", "excellent app"}; + crostini_test_helper.UpdateAppKeywords(testApp, keywords); + crostini_test_helper.AddApp(testApp); + EXPECT_EQ("goodApp", RunQuery("wow")); + EXPECT_EQ("goodApp", RunQuery("amazing")); + EXPECT_EQ("goodApp", RunQuery("excellent app")); + EXPECT_EQ("goodApp", RunQuery("good")); + EXPECT_EQ("", RunQuery("wow amazing")); + EXPECT_EQ("", RunQuery("terrible")); +} + enum class TestExtensionInstallType { CONTROLLED_BY_POLICY, CHROME_COMPONENT,
diff --git a/chrome/browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc b/chrome/browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc index bef3dee6..f5e2d77a 100644 --- a/chrome/browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc +++ b/chrome/browser/ui/ash/accessibility/accessibility_controller_client_unittest.cc
@@ -45,6 +45,10 @@ void SetSelectToSpeakState(ash::mojom::SelectToSpeakState state) override {} void SetSelectToSpeakEventHandlerDelegate( ash::mojom::SelectToSpeakEventHandlerDelegatePtr delegate) override {} + void SetSwitchAccessEventHandlerDelegate( + ash::mojom::SwitchAccessEventHandlerDelegatePtr delegate) override {} + void SetSwitchAccessKeysToCapture( + const std::vector<int>& keys_to_capture) override {} void ToggleDictationFromSource( ash::mojom::DictationToggleSource source) override {}
diff --git a/chrome/browser/ui/ash/ime_controller_client.cc b/chrome/browser/ui/ash/ime_controller_client.cc index c7a26ee..3be4f82 100644 --- a/chrome/browser/ui/ash/ime_controller_client.cc +++ b/chrome/browser/ui/ash/ime_controller_client.cc
@@ -87,11 +87,11 @@ state->SwitchToNextInputMethod(); } -void ImeControllerClient::SwitchToPreviousIme() { +void ImeControllerClient::SwitchToLastUsedIme() { InputMethodManager::State* state = input_method_manager_->GetActiveIMEState().get(); if (state) - state->SwitchToPreviousInputMethod(); + state->SwitchToLastUsedInputMethod(); } void ImeControllerClient::SwitchImeById(const std::string& id, @@ -113,6 +113,20 @@ keyboard->SetCapsLockEnabled(caps_enabled); } +void ImeControllerClient::UpdateMirroringState(bool mirroring_enabled) { + ui::IMEEngineHandlerInterface* ime_engine = + ui::IMEBridge::Get()->GetCurrentEngineHandler(); + if (ime_engine) + ime_engine->SetMirroringEnabled(mirroring_enabled); +} + +void ImeControllerClient::UpdateCastingState(bool casting_enabled) { + ui::IMEEngineHandlerInterface* ime_engine = + ui::IMEBridge::Get()->GetCurrentEngineHandler(); + if (ime_engine) + ime_engine->SetCastingEnabled(casting_enabled); +} + void ImeControllerClient::OverrideKeyboardKeyset( chromeos::input_method::mojom::ImeKeyset keyset, OverrideKeyboardKeysetCallback callback) {
diff --git a/chrome/browser/ui/ash/ime_controller_client.h b/chrome/browser/ui/ash/ime_controller_client.h index 2e1e25ff..997c31d0 100644 --- a/chrome/browser/ui/ash/ime_controller_client.h +++ b/chrome/browser/ui/ash/ime_controller_client.h
@@ -38,10 +38,12 @@ // ash::mojom::ImeControllerClient: void SwitchToNextIme() override; - void SwitchToPreviousIme() override; + void SwitchToLastUsedIme() override; void SwitchImeById(const std::string& id, bool show_message) override; void ActivateImeMenuItem(const std::string& key) override; void SetCapsLockEnabled(bool caps_enabled) override; + void UpdateMirroringState(bool mirroring_enabled) override; + void UpdateCastingState(bool casting_enabled) override; void OverrideKeyboardKeyset(chromeos::input_method::mojom::ImeKeyset keyset, OverrideKeyboardKeysetCallback callback) override;
diff --git a/chrome/browser/ui/ash/ime_controller_client_unittest.cc b/chrome/browser/ui/ash/ime_controller_client_unittest.cc index eb0dc95..4f83f8c 100644 --- a/chrome/browser/ui/ash/ime_controller_client_unittest.cc +++ b/chrome/browser/ui/ash/ime_controller_client_unittest.cc
@@ -85,7 +85,7 @@ return InputMethodUtil::GetFallbackInputMethodDescriptor(); } void SwitchToNextInputMethod() override { ++next_input_method_count_; } - void SwitchToPreviousInputMethod() override { + void SwitchToLastUsedInputMethod() override { ++previous_input_method_count_; } @@ -328,7 +328,7 @@ TEST_F(ImeControllerClientTest, SwitchToPreviousIme) { ImeControllerClient client(&input_method_manager_); - client.SwitchToPreviousIme(); + client.SwitchToLastUsedIme(); EXPECT_EQ(1, input_method_manager_.state_->previous_input_method_count_); }
diff --git a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc index ad66d32..9ef2d85f 100644 --- a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc +++ b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc
@@ -378,6 +378,9 @@ // See crbug.com/755354. IN_PROC_BROWSER_TEST_F(KeyboardControllerStateTest, DisablingKeyboardGoesToInitialState) { + if (::features::IsMultiProcessMash()) + return; + auto* controller = keyboard::KeyboardController::Get(); controller->LoadKeyboardWindowInBackground();
diff --git a/chrome/browser/ui/ash/ksv/keyboard_shortcut_viewer_metadata_unittest.cc b/chrome/browser/ui/ash/ksv/keyboard_shortcut_viewer_metadata_unittest.cc index 25edd58..d5b7705 100644 --- a/chrome/browser/ui/ash/ksv/keyboard_shortcut_viewer_metadata_unittest.cc +++ b/chrome/browser/ui/ash/ksv/keyboard_shortcut_viewer_metadata_unittest.cc
@@ -22,7 +22,7 @@ // The total number of Ash accelerators. constexpr int kAshAcceleratorsTotalNum = 101; // The hash of Ash accelerators. -constexpr char kAshAcceleratorsHash[] = "5fb453f20fff60b7c085057ac30f3dd7"; +constexpr char kAshAcceleratorsHash[] = "56daf349457b3dfaf54b804dbc6779a1"; #if defined(GOOGLE_CHROME_BUILD) // Internal builds add an extra accelerator for the Feedback app. // The total number of Chrome accelerators (available on Chrome OS).
diff --git a/chrome/browser/ui/autofill/autofill_popup_layout_model.cc b/chrome/browser/ui/autofill/autofill_popup_layout_model.cc index b9e125ad..15961fd 100644 --- a/chrome/browser/ui/autofill/autofill_popup_layout_model.cc +++ b/chrome/browser/ui/autofill/autofill_popup_layout_model.cc
@@ -233,6 +233,10 @@ return gfx::CreateVectorIcon(kKeyIcon, kIconSize, gfx::kChromeIconGrey); if (icon_str == base::ASCIIToUTF16("globeIcon")) return gfx::CreateVectorIcon(kGlobeIcon, kIconSize, gfx::kChromeIconGrey); + if (icon_str == base::ASCIIToUTF16("google")) { + return gfx::CreateVectorIcon(kGoogleGLogoIcon, kIconSize, + gfx::kPlaceholderColor); + } // For other suggestion entries, get icon from PNG files. int icon_id = GetIconResourceID(icon_str);
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc index d60e06b..2c116d1 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -24,6 +24,7 @@ #include "chrome/browser/ssl/insecure_sensitive_input_driver_factory.h" #include "chrome/browser/ssl/security_state_tab_helper.h" #include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/browser/translate/chrome_translate_client.h" #include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h" #include "chrome/browser/ui/autofill/create_card_unmask_prompt_view.h" #include "chrome/browser/ui/autofill/credit_card_scanner_controller.h" @@ -54,6 +55,7 @@ #include "components/signin/core/browser/signin_buildflags.h" #include "components/signin/core/browser/signin_header_helper.h" #include "components/signin/core/browser/signin_metrics.h" +#include "components/translate/core/browser/translate_manager.h" #include "components/ukm/content/source_url_recorder.h" #include "components/user_prefs/user_prefs.h" #include "content/public/browser/navigation_entry.h" @@ -179,6 +181,16 @@ return security_info.security_level; } +std::string ChromeAutofillClient::GetPageLanguage() const { + // TODO(crbug.com/912597): iOS vs other platforms extracts language from + // the top level frame vs whatever frame directly holds the form. + auto* translate_manager = + ChromeTranslateClient::GetManagerFromWebContents(web_contents()); + if (translate_manager) + return translate_manager->GetLanguageState().original_language(); + return std::string(); +} + void ChromeAutofillClient::ShowAutofillSettings( bool show_credit_card_settings) { #if defined(OS_ANDROID) @@ -247,8 +259,8 @@ autofill::ManageMigrationUiController::CreateForWebContents(web_contents()); autofill::ManageMigrationUiController* controller = autofill::ManageMigrationUiController::FromWebContents(web_contents()); - controller->ShowCreditCardIcon(tip_message, migratable_credit_cards, - delete_local_card_callback); + controller->UpdateCreditCardIcon(tip_message, migratable_credit_cards, + delete_local_card_callback); #endif } @@ -263,7 +275,7 @@ void ChromeAutofillClient::ConfirmSaveCreditCardLocally( const CreditCard& card, bool show_prompt, - base::OnceClosure callback) { + LocalSaveCardPromptCallback callback) { #if defined(OS_ANDROID) DCHECK(show_prompt); InfoBarService::FromWebContents(web_contents()) @@ -271,9 +283,8 @@ std::make_unique<AutofillSaveCardInfoBarDelegateMobile>( /*upload=*/false, /*should_request_name_from_user=*/false, card, std::make_unique<base::DictionaryValue>(), - GetLegacyStrikeDatabase(), /*upload_save_card_callback=*/ - UserAcceptedUploadCallback(), + AutofillClient::UploadSaveCardPromptCallback(), /*local_save_card_callback=*/std::move(callback), GetPrefs()))); #else // Do lazy initialization of SaveCardBubbleControllerImpl. @@ -307,16 +318,17 @@ bool should_request_name_from_user, bool should_request_expiration_date_from_user, bool show_prompt, - UserAcceptedUploadCallback callback) { + UploadSaveCardPromptCallback callback) { #if defined(OS_ANDROID) DCHECK(show_prompt); std::unique_ptr<AutofillSaveCardInfoBarDelegateMobile> save_card_info_bar_delegate_mobile = std::make_unique<AutofillSaveCardInfoBarDelegateMobile>( /*upload=*/true, should_request_name_from_user, card, - std::move(legal_message), GetLegacyStrikeDatabase(), + std::move(legal_message), /*upload_save_card_callback=*/std::move(callback), - /*local_save_card_callback=*/base::Closure(), GetPrefs()); + /*local_save_card_callback=*/ + AutofillClient::LocalSaveCardPromptCallback(), GetPrefs()); if (save_card_info_bar_delegate_mobile->LegalMessagesParsedSuccessfully()) { InfoBarService::FromWebContents(web_contents()) ->AddInfoBar(CreateSaveCardInfoBarMobile(
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.h b/chrome/browser/ui/autofill/chrome_autofill_client.h index d070914..78f1626 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.h +++ b/chrome/browser/ui/autofill/chrome_autofill_client.h
@@ -63,6 +63,8 @@ ukm::SourceId GetUkmSourceId() override; AddressNormalizer* GetAddressNormalizer() override; security_state::SecurityLevel GetSecurityLevelForUmaHistograms() override; + std::string GetPageLanguage() const override; + void ShowAutofillSettings(bool show_credit_card_settings) override; void ShowUnmaskPrompt(const CreditCard& card, UnmaskCardReason reason, @@ -80,9 +82,10 @@ MigrationDeleteCardCallback delete_local_card_callback) override; void ConfirmSaveAutofillProfile(const AutofillProfile& profile, base::OnceClosure callback) override; - void ConfirmSaveCreditCardLocally(const CreditCard& card, - bool show_prompt, - base::OnceClosure callback) override; + void ConfirmSaveCreditCardLocally( + const CreditCard& card, + bool show_prompt, + LocalSaveCardPromptCallback callback) override; #if defined(OS_ANDROID) void ConfirmAccountNameFixFlow( base::OnceCallback<void(const base::string16&)> callback) override; @@ -93,7 +96,7 @@ bool should_request_name_from_user, bool should_request_expiration_date_from_user, bool show_prompt, - UserAcceptedUploadCallback callback) override; + UploadSaveCardPromptCallback callback) override; void ConfirmCreditCardFillAssist(const CreditCard& card, base::OnceClosure callback) override; bool HasCreditCardScanFeature() override;
diff --git a/chrome/browser/ui/autofill/local_card_migration_controller_observer.h b/chrome/browser/ui/autofill/local_card_migration_controller_observer.h index aca9fe42..f5e3f326 100644 --- a/chrome/browser/ui/autofill/local_card_migration_controller_observer.h +++ b/chrome/browser/ui/autofill/local_card_migration_controller_observer.h
@@ -5,9 +5,16 @@ #ifndef CHROME_BROWSER_UI_AUTOFILL_LOCAL_CARD_MIGRATION_CONTROLLER_OBSERVER_H_ #define CHROME_BROWSER_UI_AUTOFILL_LOCAL_CARD_MIGRATION_CONTROLLER_OBSERVER_H_ +// The observer interface that listens for events in local card migration +// related controllers. class LocalCardMigrationControllerObserver { public: + // Called when the user declined the offer dialog, navigated away with + // feedback credit card icon or finished with the feedback dialog. virtual void OnMigrationNoLongerAvailable() = 0; + // Called after the user clicked the save button. Will trigger the + // credit card icon animation. + virtual void OnMigrationStarted() = 0; protected: virtual ~LocalCardMigrationControllerObserver() = default;
diff --git a/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.cc b/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.cc index a4efd9d..8e2958a 100644 --- a/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.cc +++ b/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.cc
@@ -59,21 +59,22 @@ return; } + view_state_ = LocalCardMigrationDialogState::kOffered; + // Need to create the icon first otherwise the dialog will not be shown. + UpdateIcon(); local_card_migration_dialog_ = CreateLocalCardMigrationDialogView(this, web_contents()); start_migrating_cards_callback_ = std::move(start_migrating_cards_callback); migratable_credit_cards_ = migratable_credit_cards; - view_state_ = LocalCardMigrationDialogState::kOffered; - // If the credit card icon is being shown, remove the icon. - UpdateIcon(); local_card_migration_dialog_->ShowDialog(); + UpdateIcon(); dialog_is_visible_duration_timer_ = base::ElapsedTimer(); AutofillMetrics::LogLocalCardMigrationDialogOfferMetric( AutofillMetrics::LOCAL_CARD_MIGRATION_DIALOG_SHOWN); } -void LocalCardMigrationDialogControllerImpl::ShowCreditCardIcon( +void LocalCardMigrationDialogControllerImpl::UpdateCreditCardIcon( const base::string16& tip_message, const std::vector<MigratableCreditCard>& migratable_credit_cards, AutofillClient::MigrationDeleteCardCallback delete_local_card_callback) { @@ -98,8 +99,8 @@ void LocalCardMigrationDialogControllerImpl::ShowFeedbackDialog() { local_card_migration_dialog_ = CreateLocalCardMigrationDialogView(this, web_contents()); - UpdateIcon(); local_card_migration_dialog_->ShowDialog(); + UpdateIcon(); } void LocalCardMigrationDialogControllerImpl::ShowErrorDialog() { @@ -109,6 +110,11 @@ local_card_migration_dialog_->ShowDialog(); } +void LocalCardMigrationDialogControllerImpl::AddObserver( + LocalCardMigrationControllerObserver* observer) { + observer_list_.AddObserver(observer); +} + LocalCardMigrationDialogState LocalCardMigrationDialogControllerImpl::GetViewState() const { return view_state_; @@ -137,6 +143,7 @@ AutofillMetrics::LOCAL_CARD_MIGRATION_DIALOG_CLOSED_SAVE_BUTTON_CLICKED); std::move(start_migrating_cards_callback_).Run(selected_cards_guids); + NotifyMigrationStarted(); } void LocalCardMigrationDialogControllerImpl::OnCancelButtonClicked() { @@ -149,12 +156,18 @@ prefs::SetLocalCardMigrationPromptPreviouslyCancelled(pref_service_, true); start_migrating_cards_callback_.Reset(); + NotifyMigrationNoLongerAvailable(); +} + +void LocalCardMigrationDialogControllerImpl::OnDoneButtonClicked() { + NotifyMigrationNoLongerAvailable(); } void LocalCardMigrationDialogControllerImpl::OnViewCardsButtonClicked() { // TODO(crbug.com/867194): Add metrics. constexpr int kPaymentsProfileUserIndex = 0; OpenUrl(payments::GetManageInstrumentsUrl(kPaymentsProfileUserIndex)); + NotifyMigrationNoLongerAvailable(); } void LocalCardMigrationDialogControllerImpl::OnLegalMessageLinkClicked( @@ -188,6 +201,8 @@ void LocalCardMigrationDialogControllerImpl::OnDialogClosed() { if (local_card_migration_dialog_) local_card_migration_dialog_ = nullptr; + + UpdateIcon(); } bool LocalCardMigrationDialogControllerImpl::AllCardsInvalid() const { @@ -213,7 +228,7 @@ void LocalCardMigrationDialogControllerImpl::OpenUrl(const GURL& url) { web_contents()->OpenURL(content::OpenURLParams( - url, content::Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB, + url, content::Referrer(), WindowOpenDisposition::NEW_POPUP, ui::PAGE_TRANSITION_LINK, false)); } @@ -234,6 +249,19 @@ }) != migratable_credit_cards_.end(); } +void LocalCardMigrationDialogControllerImpl:: + NotifyMigrationNoLongerAvailable() { + for (LocalCardMigrationControllerObserver& observer : observer_list_) { + observer.OnMigrationNoLongerAvailable(); + } +} + +void LocalCardMigrationDialogControllerImpl::NotifyMigrationStarted() { + for (LocalCardMigrationControllerObserver& observer : observer_list_) { + observer.OnMigrationStarted(); + } +} + WEB_CONTENTS_USER_DATA_KEY_IMPL(LocalCardMigrationDialogControllerImpl) } // namespace autofill
diff --git a/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.h b/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.h index 6c48f74..b937a06 100644 --- a/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.h +++ b/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.h
@@ -8,7 +8,9 @@ #include <memory> #include "base/macros.h" +#include "base/observer_list.h" #include "base/timer/elapsed_timer.h" +#include "chrome/browser/ui/autofill/local_card_migration_controller_observer.h" #include "components/autofill/core/browser/autofill_client.h" #include "components/autofill/core/browser/ui/local_card_migration_dialog_controller.h" #include "content/public/browser/web_contents_observer.h" @@ -35,9 +37,9 @@ AutofillClient::LocalCardMigrationCallback start_migrating_cards_callback); - // When migration is finished, show a credit card icon in the omnibox. Also - // passes |tip_message|, and |migratable_credit_cards| to controller. - void ShowCreditCardIcon( + // When migration is finished, update the credit card icon. Also passes + // |tip_message|, and |migratable_credit_cards| to controller. + void UpdateCreditCardIcon( const base::string16& tip_message, const std::vector<MigratableCreditCard>& migratable_credit_cards, AutofillClient::MigrationDeleteCardCallback delete_local_card_callback); @@ -52,6 +54,8 @@ // error dialog containing an error message. void ShowErrorDialog(); + void AddObserver(LocalCardMigrationControllerObserver* observer); + // LocalCardMigrationDialogController: LocalCardMigrationDialogState GetViewState() const override; const std::vector<MigratableCreditCard>& GetCardList() const override; @@ -60,6 +64,7 @@ void OnSaveButtonClicked( const std::vector<std::string>& selected_cards_guids) override; void OnCancelButtonClicked() override; + void OnDoneButtonClicked() override; void OnViewCardsButtonClicked() override; void OnLegalMessageLinkClicked(const GURL& url) override; void DeleteCard(const std::string& deleted_card_guid) override; @@ -81,8 +86,13 @@ void UpdateIcon(); + // The dialog is showing cards of which the migration failed. We will show + // the "Almost done" dialog in this case. bool HasFailedCard() const; + void NotifyMigrationNoLongerAvailable(); + void NotifyMigrationStarted(); + LocalCardMigrationDialog* local_card_migration_dialog_ = nullptr; PrefService* pref_service_; @@ -113,6 +123,11 @@ // feedback dialogs after migration process is finished. base::string16 tip_message_; + // Contains observer listening to user's interactions with the dialog. The + // observer is responsible for setting flow step upon these interactions. + base::ObserverList<LocalCardMigrationControllerObserver>::Unchecked + observer_list_; + WEB_CONTENTS_USER_DATA_KEY_DECL(); DISALLOW_COPY_AND_ASSIGN(LocalCardMigrationDialogControllerImpl);
diff --git a/chrome/browser/ui/autofill/manage_migration_ui_controller.cc b/chrome/browser/ui/autofill/manage_migration_ui_controller.cc index ff1f0ab..d96611a 100644 --- a/chrome/browser/ui/autofill/manage_migration_ui_controller.cc +++ b/chrome/browser/ui/autofill/manage_migration_ui_controller.cc
@@ -18,11 +18,13 @@ autofill::LocalCardMigrationBubbleControllerImpl::FromWebContents( web_contents); bubble_controller_->AddObserver(this); + autofill::LocalCardMigrationDialogControllerImpl::CreateForWebContents( web_contents); dialog_controller_ = autofill::LocalCardMigrationDialogControllerImpl::FromWebContents( web_contents); + dialog_controller_->AddObserver(this); } ManageMigrationUiController::~ManageMigrationUiController() {} @@ -43,20 +45,21 @@ std::move(start_migrating_cards_callback)); } -void ManageMigrationUiController::ShowCreditCardIcon( +void ManageMigrationUiController::UpdateCreditCardIcon( const base::string16& tip_message, const std::vector<MigratableCreditCard>& migratable_credit_cards, AutofillClient::MigrationDeleteCardCallback delete_local_card_callback) { if (!dialog_controller_) return; - DCHECK_EQ(flow_step_, LocalCardMigrationFlowStep::OFFER_DIALOG); - flow_step_ = LocalCardMigrationFlowStep::CREDIT_CARD_ICON; + DCHECK_EQ(flow_step_, LocalCardMigrationFlowStep::MIGRATION_RESULT_PENDING); + flow_step_ = LocalCardMigrationFlowStep::MIGRATION_FINISHED; // Show error dialog when the vector is an empty vector, which indicates // Payments Rpc failure. show_error_dialog_ = migratable_credit_cards.empty(); - dialog_controller_->ShowCreditCardIcon(tip_message, migratable_credit_cards, - delete_local_card_callback); + + dialog_controller_->UpdateCreditCardIcon(tip_message, migratable_credit_cards, + delete_local_card_callback); } void ManageMigrationUiController::OnUserClickedCreditCardIcon() { @@ -65,12 +68,11 @@ ReshowBubble(); break; } - case LocalCardMigrationFlowStep::CREDIT_CARD_ICON: { + case LocalCardMigrationFlowStep::MIGRATION_FINISHED: { show_error_dialog_ ? ShowErrorDialog() : ShowFeedbackDialog(); break; } default: { - NOTREACHED(); break; } } @@ -81,8 +83,8 @@ } bool ManageMigrationUiController::IsIconVisible() const { - return flow_step_ == LocalCardMigrationFlowStep::PROMO_BUBBLE || - flow_step_ == LocalCardMigrationFlowStep::CREDIT_CARD_ICON; + DCHECK_NE(flow_step_, LocalCardMigrationFlowStep::UNKNOWN); + return flow_step_ != LocalCardMigrationFlowStep::NOT_SHOWN; } LocalCardMigrationBubble* ManageMigrationUiController::GetBubbleView() const { @@ -103,6 +105,10 @@ flow_step_ = LocalCardMigrationFlowStep::NOT_SHOWN; } +void ManageMigrationUiController::OnMigrationStarted() { + flow_step_ = LocalCardMigrationFlowStep::MIGRATION_RESULT_PENDING; +} + void ManageMigrationUiController::ReshowBubble() { if (!bubble_controller_) return; @@ -115,7 +121,7 @@ if (!dialog_controller_) return; - DCHECK_EQ(flow_step_, LocalCardMigrationFlowStep::CREDIT_CARD_ICON); + DCHECK_EQ(flow_step_, LocalCardMigrationFlowStep::MIGRATION_FINISHED); flow_step_ = LocalCardMigrationFlowStep::ERROR_DIALOG; dialog_controller_->ShowErrorDialog(); } @@ -124,7 +130,7 @@ if (!dialog_controller_) return; - DCHECK_EQ(flow_step_, LocalCardMigrationFlowStep::CREDIT_CARD_ICON); + DCHECK_EQ(flow_step_, LocalCardMigrationFlowStep::MIGRATION_FINISHED); flow_step_ = LocalCardMigrationFlowStep::FEEDBACK_DIALOG; dialog_controller_->ShowFeedbackDialog(); }
diff --git a/chrome/browser/ui/autofill/manage_migration_ui_controller.h b/chrome/browser/ui/autofill/manage_migration_ui_controller.h index c450943..22936ed4 100644 --- a/chrome/browser/ui/autofill/manage_migration_ui_controller.h +++ b/chrome/browser/ui/autofill/manage_migration_ui_controller.h
@@ -25,9 +25,13 @@ // Should show the dialog that offers users to migrate credit cards to // Payments server. OFFER_DIALOG, - // Should show the credit card icon when migration is finished and the - // feedback dialog is ready. - CREDIT_CARD_ICON, + // Migration is in process and result is pending after users click the save + // button. + // Should show credit card icon and the animation. + MIGRATION_RESULT_PENDING, + // Migration is finished. Should show the credit card icon when migration + // is finished and the feedback dialog is ready. + MIGRATION_FINISHED, // Should show the feedback dialog containing the migration results of cards // that the user selected to upload after the user clicking the credit card // icon. @@ -53,7 +57,7 @@ AutofillClient::LocalCardMigrationCallback start_migrating_cards_callback); - void ShowCreditCardIcon( + void UpdateCreditCardIcon( const base::string16& tip_message, const std::vector<MigratableCreditCard>& migratable_credit_cards, AutofillClient::MigrationDeleteCardCallback delete_local_card_callback); @@ -70,6 +74,7 @@ // LocalCardMigrationControllerObserver: void OnMigrationNoLongerAvailable() override; + void OnMigrationStarted() override; protected: explicit ManageMigrationUiController(content::WebContents* web_contents);
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc index 71a76c6..6d4972fd 100644 --- a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc +++ b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.cc
@@ -8,7 +8,7 @@ #include <utility> #include "base/strings/utf_string_conversions.h" -#include "chrome/browser/autofill/legacy_strike_database_factory.h" +#include "chrome/browser/autofill/personal_data_manager_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/account_consistency_mode_manager.h" #include "chrome/browser/signin/identity_manager_factory.h" @@ -27,7 +27,7 @@ #include "chrome/common/url_constants.h" #include "components/autofill/core/browser/autofill_experiments.h" #include "components/autofill/core/browser/autofill_metrics.h" -#include "components/autofill/core/browser/legacy_strike_database.h" +#include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_constants.h" #include "components/autofill/core/common/autofill_features.h" @@ -48,12 +48,15 @@ : content::WebContentsObserver(web_contents), web_contents_(web_contents), pref_service_( - user_prefs::UserPrefs::Get(web_contents->GetBrowserContext())), - weak_ptr_factory_(this) { + user_prefs::UserPrefs::Get(web_contents->GetBrowserContext())) { security_state::SecurityInfo security_info; SecurityStateTabHelper::FromWebContents(web_contents) ->GetSecurityInfo(&security_info); security_level_ = security_info.security_level; + + personal_data_manager_ = + PersonalDataManagerFactory::GetInstance()->GetForProfile( + Profile::FromBrowserContext(web_contents->GetBrowserContext())); } SaveCardBubbleControllerImpl::~SaveCardBubbleControllerImpl() { @@ -64,7 +67,7 @@ void SaveCardBubbleControllerImpl::OfferLocalSave( const CreditCard& card, bool show_bubble, - base::OnceClosure save_card_callback) { + AutofillClient::LocalSaveCardPromptCallback save_card_prompt_callback) { // Don't show the bubble if it's already visible. if (save_card_bubble_view_) return; @@ -76,7 +79,7 @@ legal_message_lines_.clear(); card_ = card; - local_save_card_callback_ = std::move(save_card_callback); + local_save_card_prompt_callback_ = std::move(save_card_prompt_callback); current_bubble_type_ = BubbleType::LOCAL_SAVE; if (show_bubble_) { ShowBubble(); @@ -86,7 +89,7 @@ should_request_expiration_date_from_user_, pref_service_->GetInteger( prefs::kAutofillAcceptSaveCreditCardPromptState), - GetSecurityLevel()); + GetSecurityLevel(), GetSyncState()); } else { ShowIconOnly(); } @@ -98,7 +101,7 @@ bool should_request_name_from_user, bool should_request_expiration_date_from_user, bool show_bubble, - AutofillClient::UserAcceptedUploadCallback save_card_callback) { + AutofillClient::UploadSaveCardPromptCallback save_card_prompt_callback) { // Don't show the bubble if it's already visible. if (save_card_bubble_view_) return; @@ -122,7 +125,7 @@ should_request_expiration_date_from_user_, pref_service_->GetInteger( prefs::kAutofillAcceptSaveCreditCardPromptState), - GetSecurityLevel()); + GetSecurityLevel(), GetSyncState()); } if (!LegalMessageLine::Parse(*legal_message, &legal_message_lines_, @@ -133,12 +136,12 @@ should_request_expiration_date_from_user_, pref_service_->GetInteger( prefs::kAutofillAcceptSaveCreditCardPromptState), - GetSecurityLevel()); + GetSecurityLevel(), GetSyncState()); return; } card_ = card; - upload_save_card_callback_ = std::move(save_card_callback); + upload_save_card_prompt_callback_ = std::move(save_card_prompt_callback); current_bubble_type_ = BubbleType::UPLOAD_SAVE; if (show_bubble_) @@ -190,7 +193,7 @@ should_request_expiration_date_from_user_, pref_service_->GetInteger( prefs::kAutofillAcceptSaveCreditCardPromptState), - GetSecurityLevel()); + GetSecurityLevel(), GetSyncState()); } ShowBubble(); @@ -310,7 +313,7 @@ switch (current_bubble_type_) { case BubbleType::UPLOAD_SAVE: { - DCHECK(!upload_save_card_callback_.is_null()); + DCHECK(!upload_save_card_prompt_callback_.is_null()); base::string16 name_provided_by_user; if (!user_provided_card_details.cardholder_name.empty()) { @@ -325,17 +328,18 @@ base::TrimWhitespace(user_provided_card_details.cardholder_name, base::TRIM_ALL, &name_provided_by_user); } - std::move(upload_save_card_callback_).Run(user_provided_card_details); + std::move(upload_save_card_prompt_callback_) + .Run(AutofillClient::ACCEPTED, user_provided_card_details); break; } case BubbleType::LOCAL_SAVE: - DCHECK(!local_save_card_callback_.is_null()); + DCHECK(!local_save_card_prompt_callback_.is_null()); // Show an animated card saved confirmation message next time // UpdateIcon() is called. can_animate_ = base::FeatureList::IsEnabled( features::kAutofillSaveCardSignInAfterLocalSave); - std::move(local_save_card_callback_).Run(); + std::move(local_save_card_prompt_callback_).Run(AutofillClient::ACCEPTED); break; case BubbleType::MANAGE_CARDS: AutofillMetrics::LogManageCardsPromptMetric( @@ -367,7 +371,7 @@ should_request_expiration_date_from_user_, pref_service_->GetInteger( prefs::kAutofillAcceptSaveCreditCardPromptState), - GetSecurityLevel()); + GetSecurityLevel(), GetSyncState()); pref_service_->SetInteger( prefs::kAutofillAcceptSaveCreditCardPromptState, prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_ACCEPTED); @@ -375,39 +379,28 @@ } void SaveCardBubbleControllerImpl::OnCancelButton() { - // Should only be applicable for non-material UI, - // as Harmony dialogs do not have [No thanks] buttons. - const BubbleType previous_bubble_type = current_bubble_type_; - current_bubble_type_ = BubbleType::INACTIVE; - upload_save_card_callback_.Reset(); - local_save_card_callback_.Reset(); - - if (previous_bubble_type == BubbleType::LOCAL_SAVE || - previous_bubble_type == BubbleType::UPLOAD_SAVE) { + if (current_bubble_type_ == BubbleType::LOCAL_SAVE || + current_bubble_type_ == BubbleType::UPLOAD_SAVE) { AutofillMetrics::LogSaveCardPromptMetric( AutofillMetrics::SAVE_CARD_PROMPT_END_DENIED, is_upload_save_, is_reshow_, should_request_name_from_user_, should_request_expiration_date_from_user_, pref_service_->GetInteger( prefs::kAutofillAcceptSaveCreditCardPromptState), - GetSecurityLevel()); + GetSecurityLevel(), GetSyncState()); pref_service_->SetInteger( prefs::kAutofillAcceptSaveCreditCardPromptState, prefs::PREVIOUS_SAVE_CREDIT_CARD_PROMPT_USER_DECISION_DENIED); - if (show_bubble_ && - base::FeatureList::IsEnabled( - features::kAutofillSaveCreditCardUsesStrikeSystem)) { - // If save was cancelled and the bubble was actually shown (NOT just the - // icon), count that as a strike against offering save in the future. - LegacyStrikeDatabase* strike_database = GetLegacyStrikeDatabase(); - strike_database->AddStrike( - strike_database->GetKeyForCreditCardSave( - base::UTF16ToUTF8(card_.LastFourDigits())), - base::BindRepeating( - &SaveCardBubbleControllerImpl::OnStrikeChangeComplete, - weak_ptr_factory_.GetWeakPtr())); + + if (current_bubble_type_ == BubbleType::LOCAL_SAVE) { + std::move(local_save_card_prompt_callback_).Run(AutofillClient::DECLINED); + } else { // BubbleType::UPLOAD_SAVE + std::move(upload_save_card_prompt_callback_) + .Run(AutofillClient::DECLINED, {}); } } + + current_bubble_type_ = BubbleType::INACTIVE; } void SaveCardBubbleControllerImpl::OnLegalMessageLinkClicked(const GURL& url) { @@ -418,7 +411,7 @@ should_request_expiration_date_from_user_, pref_service_->GetInteger( prefs::kAutofillAcceptSaveCreditCardPromptState), - GetSecurityLevel()); + GetSecurityLevel(), GetSyncState()); } void SaveCardBubbleControllerImpl::OnManageCardsClicked() { @@ -495,8 +488,6 @@ const BubbleType previous_bubble_type = current_bubble_type_; current_bubble_type_ = BubbleType::INACTIVE; - upload_save_card_callback_.Reset(); - local_save_card_callback_.Reset(); bool bubble_was_visible = save_card_bubble_view_; if (bubble_was_visible) { save_card_bubble_view_->Hide(); @@ -515,20 +506,15 @@ should_request_expiration_date_from_user_, pref_service_->GetInteger( prefs::kAutofillAcceptSaveCreditCardPromptState), - GetSecurityLevel()); - if (base::FeatureList::IsEnabled( - features::kAutofillSaveCreditCardUsesStrikeSystem) && - show_bubble_) { - // If the save offer was ignored and the bubble was actually shown (NOT - // just the icon), count that as a strike against offering save in the - // future. - LegacyStrikeDatabase* strike_database = GetLegacyStrikeDatabase(); - strike_database->AddStrike( - strike_database->GetKeyForCreditCardSave( - base::UTF16ToUTF8(card_.LastFourDigits())), - base::BindRepeating( - &SaveCardBubbleControllerImpl::OnStrikeChangeComplete, - weak_ptr_factory_.GetWeakPtr())); + GetSecurityLevel(), GetSyncState()); + + if (previous_bubble_type == BubbleType::LOCAL_SAVE) { + DCHECK(!local_save_card_prompt_callback_.is_null()); + std::move(local_save_card_prompt_callback_).Run(AutofillClient::IGNORED); + } else { // BubbleType::UPLOAD_SAVE + DCHECK(!upload_save_card_prompt_callback_.is_null()); + std::move(upload_save_card_prompt_callback_) + .Run(AutofillClient::IGNORED, {}); } } } @@ -553,22 +539,13 @@ account_info_ = identity_manager->GetPrimaryAccountInfo(); } -LegacyStrikeDatabase* SaveCardBubbleControllerImpl::GetLegacyStrikeDatabase() { - Profile* profile = GetProfile(); - // No need to return a LegacyStrikeDatabase in incognito mode. We don't allow - // saving of Autofill data while in incognito, so an incognito code path - // should never get this far. - DCHECK(profile && !profile->IsOffTheRecord()); - return LegacyStrikeDatabaseFactory::GetForProfile(profile); -} - void SaveCardBubbleControllerImpl::ShowBubble() { DCHECK(current_bubble_type_ != BubbleType::INACTIVE); // Upload save callback should not be null for UPLOAD_SAVE state. - DCHECK(!(upload_save_card_callback_.is_null() && + DCHECK(!(upload_save_card_prompt_callback_.is_null() && current_bubble_type_ == BubbleType::UPLOAD_SAVE)); // Local save callback should not be null for LOCAL_SAVE state. - DCHECK(!(local_save_card_callback_.is_null() && + DCHECK(!(local_save_card_prompt_callback_.is_null() && current_bubble_type_ == BubbleType::LOCAL_SAVE)); DCHECK(!save_card_bubble_view_); @@ -596,7 +573,7 @@ should_request_expiration_date_from_user_, pref_service_->GetInteger( prefs::kAutofillAcceptSaveCreditCardPromptState), - GetSecurityLevel()); + GetSecurityLevel(), GetSyncState()); break; case BubbleType::MANAGE_CARDS: AutofillMetrics::LogManageCardsPromptMetric( @@ -616,10 +593,10 @@ void SaveCardBubbleControllerImpl::ShowIconOnly() { DCHECK(current_bubble_type_ != BubbleType::INACTIVE); // Upload save callback should not be null for UPLOAD_SAVE state. - DCHECK(!(upload_save_card_callback_.is_null() && + DCHECK(!(upload_save_card_prompt_callback_.is_null() && current_bubble_type_ == BubbleType::UPLOAD_SAVE)); // Local save callback should not be null for LOCAL_SAVE state. - DCHECK(!(local_save_card_callback_.is_null() && + DCHECK(!(local_save_card_prompt_callback_.is_null() && current_bubble_type_ == BubbleType::LOCAL_SAVE)); DCHECK(!save_card_bubble_view_); @@ -638,7 +615,7 @@ should_request_expiration_date_from_user_, pref_service_->GetInteger( prefs::kAutofillAcceptSaveCreditCardPromptState), - GetSecurityLevel()); + GetSecurityLevel(), GetSyncState()); break; case BubbleType::MANAGE_CARDS: case BubbleType::SIGN_IN_PROMO: @@ -661,17 +638,15 @@ ui::PAGE_TRANSITION_LINK, false)); } -void SaveCardBubbleControllerImpl::OnStrikeChangeComplete( - const int num_strikes) { - if (observer_for_testing_) - observer_for_testing_->OnSCBCStrikeChangeComplete(); -} - security_state::SecurityLevel SaveCardBubbleControllerImpl::GetSecurityLevel() const { return security_level_; } +AutofillSyncSigninState SaveCardBubbleControllerImpl::GetSyncState() const { + return personal_data_manager_->GetSyncSigninState(); +} + WEB_CONTENTS_USER_DATA_KEY_IMPL(SaveCardBubbleControllerImpl) } // namespace autofill
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.h b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.h index 6c2e2dd..1ba178a 100644 --- a/chrome/browser/ui/autofill/save_card_bubble_controller_impl.h +++ b/chrome/browser/ui/autofill/save_card_bubble_controller_impl.h
@@ -11,6 +11,7 @@ #include "chrome/browser/ui/autofill/save_card_ui.h" #include "components/autofill/core/browser/autofill_client.h" #include "components/autofill/core/browser/credit_card.h" +#include "components/autofill/core/browser/sync_utils.h" #include "components/autofill/core/browser/ui/save_card_bubble_controller.h" #include "components/security_state/core/security_state.h" #include "components/signin/core/browser/account_info.h" @@ -22,7 +23,6 @@ namespace autofill { enum class BubbleType; -class LegacyStrikeDatabase; // Implementation of per-tab class to control the save credit card bubble and // Omnibox icon. @@ -37,35 +37,35 @@ public: virtual void OnBubbleShown() = 0; virtual void OnBubbleClosed() = 0; - virtual void OnSCBCStrikeChangeComplete() = 0; }; ~SaveCardBubbleControllerImpl() override; // Sets up the controller and offers to save the |card| locally. - // |save_card_callback| will be invoked if and when the Save button is - // pressed. If |show_bubble| is true, pops up the offer-to-save bubble; - // otherwise, only the omnibox icon is displayed. - void OfferLocalSave(const CreditCard& card, - bool show_bubble, - base::OnceClosure save_card_callback); + // |save_card_prompt_callback| will be invoked once the user makes a decision + // with respect to the offer-to-save prompt. If |show_bubble| is true, pops up + // the offer-to-save bubble; otherwise, only the omnibox icon is displayed. + void OfferLocalSave( + const CreditCard& card, + bool show_bubble, + AutofillClient::LocalSaveCardPromptCallback save_card_prompt_callback); // Sets up the controller and offers to upload the |card| to Google Payments. - // |save_card_callback| will be invoked if and when the Save button is - // pressed. The contents of |legal_message| will be displayed in the bubble. - // A textfield confirming the cardholder name will appear in the bubble if - // |should_request_name_from_user| is true. A pair of dropdowns for entering - // the expiration date will appear in the bubble if - // |should_request_expiration_date_from_user| is true. If |show_bubble| is - // true, pops up the offer-to-save bubble; otherwise, only the omnibox icon is - // displayed. + // |save_card_prompt_callback| will be invoked once the user makes a decision + // with respect to the offer-to-save prompt. The contents of |legal_message| + // will be displayed in the bubble. A textfield confirming the cardholder name + // will appear in the bubble if |should_request_name_from_user| is true. A + // pair of dropdowns for entering the expiration date will appear in the + // bubble if |should_request_expiration_date_from_user| is true. If + // |show_bubble| is true, pops up the offer-to-save bubble; otherwise, only + // the omnibox icon is displayed. void OfferUploadSave( const CreditCard& card, std::unique_ptr<base::DictionaryValue> legal_message, bool should_request_name_from_user, bool should_request_expiration_from_user, bool show_bubble, - AutofillClient::UserAcceptedUploadCallback save_card_callback); + AutofillClient::UploadSaveCardPromptCallback save_card_prompt_callback); // Sets up the controller for the sign in promo and shows the bubble. // This bubble is only shown after a local save is accepted and if @@ -134,15 +134,15 @@ // Gets the security level of the page. virtual security_state::SecurityLevel GetSecurityLevel() const; + // Gets the current sync state. + virtual AutofillSyncSigninState GetSyncState() const; + private: friend class content::WebContentsUserData<SaveCardBubbleControllerImpl>; friend class SaveCardBubbleViewsBrowserTestBase; void FetchAccountInfo(); - // Fetches the Autofill LegacyStrikeDatabase for the current profile. - LegacyStrikeDatabase* GetLegacyStrikeDatabase(); - // Displays both the offer-to-save bubble and is associated omnibox icon. void ShowBubble(); @@ -152,10 +152,6 @@ // Update the visibility and toggled state of the Omnibox save card icon. void UpdateIcon(); - // Used for browsertests. Gives the |observer_for_testing_| a notification - // a strike change has been made. - void OnStrikeChangeComplete(const int num_strikes); - void OpenUrl(const GURL& url); // For testing. @@ -166,6 +162,9 @@ // The web_contents associated with this controller. content::WebContents* web_contents_; + // Should outlive this object. + PersonalDataManager* personal_data_manager_; + // Is true only if the card saved animation can be shown. bool can_animate_ = false; @@ -179,17 +178,19 @@ // Weak reference to read & write |kAutofillAcceptSaveCreditCardPromptState|. PrefService* pref_service_; - // Callback to run if user presses Save button in the upload save bubble. Will - // return the cardholder name provided/confirmed by the user if it was - // requested. Will also return the expiration month and year provided by the - // user if the expiration date was requested. If both callbacks are null then - // no bubble is available to show and the icon is not visible. - AutofillClient::UserAcceptedUploadCallback upload_save_card_callback_; + // Callback to run once the user makes a decision with respect to the credit + // card upload offer-to-save prompt. Will return the cardholder name + // provided/confirmed by the user if it was requested. Will also return the + // expiration month and year provided by the user if the expiration date was + // requested. If both callbacks are null then no bubble is available to show + // and the icon is not visible. + AutofillClient::UploadSaveCardPromptCallback + upload_save_card_prompt_callback_; - // Callback to run if user presses Save button in the local save bubble. If - // both callbacks return true for .is_null() then no bubble is available to - // show and the icon is not visible. - base::OnceClosure local_save_card_callback_; + // Callback to run once the user makes a decision with respect to the local + // credit card offer-to-save prompt. If both callbacks return true for + // .is_null() then no bubble is available to show and the icon is not visible. + AutofillClient::LocalSaveCardPromptCallback local_save_card_prompt_callback_; // Governs whether the upload or local save version of the UI should be shown. bool is_upload_save_ = false; @@ -229,8 +230,6 @@ // Observer for when a bubble is created. Initialized only during tests. ObserverForTest* observer_for_testing_ = nullptr; - base::WeakPtrFactory<SaveCardBubbleControllerImpl> weak_ptr_factory_; - WEB_CONTENTS_USER_DATA_KEY_DECL(); DISALLOW_COPY_AND_ASSIGN(SaveCardBubbleControllerImpl);
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc b/chrome/browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc index 3aca1eae..8d4b4ef 100644 --- a/chrome/browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc +++ b/chrome/browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc
@@ -22,6 +22,7 @@ #include "components/autofill/core/browser/autofill_metrics.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/credit_card.h" +#include "components/autofill/core/browser/sync_utils.h" #include "components/autofill/core/browser/test_autofill_clock.h" #include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_prefs.h" @@ -67,6 +68,10 @@ return security_level_; } + AutofillSyncSigninState GetSyncState() const override { + return AutofillSyncSigninState::kSignedInAndSyncFeature; + } + private: security_state::SecurityLevel security_level_ = security_state::SecurityLevel::NONE; @@ -171,9 +176,11 @@ }; static void UploadSaveCardCallback( + AutofillClient::SaveCardOfferUserDecision user_decision, const AutofillClient::UserProvidedCardDetails& user_provided_card_details) {} - static void LocalSaveCardCallback() {} + static void LocalSaveCardCallback( + AutofillClient::SaveCardOfferUserDecision user_decision) {} DISALLOW_COPY_AND_ASSIGN(SaveCardBubbleControllerImplTest); };
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 5033fa2..1f3c2ce 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -228,7 +228,6 @@ #endif // OS_WIN #if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/fileapi/external_file_url_util.h" #include "chrome/browser/ui/settings_window_manager_chromeos.h" #endif @@ -939,7 +938,8 @@ // TODO(beng): figure out how to juggle this. gfx::NativeWindow parent_window = window_->GetNativeWindow(); ui::SelectFileDialog::FileTypeInfo file_types; - file_types.allowed_paths = ui::SelectFileDialog::FileTypeInfo::ANY_PATH; + file_types.allowed_paths = + ui::SelectFileDialog::FileTypeInfo::ANY_PATH_OR_URL; select_file_dialog_->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE, base::string16(), directory, @@ -1986,31 +1986,14 @@ void* params) { profile_->set_last_selected_directory(file_info.file_path.DirName()); - GURL url = net::FilePathToFileURL(file_info.local_path); + GURL url = std::move(file_info.url) + .value_or(net::FilePathToFileURL(file_info.local_path)); if (url.is_empty()) return; -#if defined(OS_CHROMEOS) - chromeos::ResolveExternalFileUrlFromPath( - profile_, file_info.file_path, - base::BindOnce( - [](base::WeakPtr<Browser> weak_this, GURL url, GURL external_url) { - if (!weak_this) - return; - - if (!external_url.is_empty()) - url = std::move(external_url); - - weak_this->OpenURL(OpenURLParams(url, Referrer(), - WindowOpenDisposition::CURRENT_TAB, - ui::PAGE_TRANSITION_TYPED, false)); - }, - weak_factory_.GetWeakPtr(), std::move(url))); -#else OpenURL(OpenURLParams(url, Referrer(), WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false)); -#endif } ///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/cocoa/l10n_util.h b/chrome/browser/ui/cocoa/l10n_util.h index ee3b21e..d4d79ea6 100644 --- a/chrome/browser/ui/cocoa/l10n_util.h +++ b/chrome/browser/ui/cocoa/l10n_util.h
@@ -8,7 +8,6 @@ #import <Cocoa/Cocoa.h> #include <stddef.h> -#include "base/feature_list.h" #include "base/strings/string16.h" namespace cocoa_l10n_util { @@ -28,55 +27,15 @@ // coordinates. CGFloat VerticallyReflowGroup(NSArray* views); -// Like |base::ReplaceStringPlaceholders(const base::string16&, -// const base::string16&, size_t*)|, but for a NSString formatString. -NSString* ReplaceNSStringPlaceholders(NSString* formatString, - const base::string16& a, - size_t* offset); - // Generates a tooltip string for a given URL and title. NSString* TooltipForURLAndTitle(NSString* url, NSString* title); -// Returns whether both: -// 1) Mac RTL support is enabled via the MacRTL feature; -// 2) The browser UI is in RTL mode. -// If MacRTL becomes the default, this function can be replaced with -// uses of base::i18n::IsRTL(). -bool ShouldDoExperimentalRTLLayout(); - -// Returns true if ShouldDoExperimentalRTLLayout() is true and the OS is -// 10.12 or above. macOS 10.12 is the first OS where the native stoplight -// buttons are reversed in RTL, so manually reversing them in previous -// OSes would make Chrome stick out. -bool ShouldFlipWindowControlsInRTL(); - // Set or clear the keys in NSUserDefaults which control UI direction based on // whether direction is forced by a Chrome flag. This should be early in // Chrome's launch, before any views or windows have been created, because it's // cached by AppKit. void ApplyForcedRTL(); -// Returns NSImageLeading when available (10.12+), otherwise -// NSImageLeft for LTR and NSImageRight in RTL. -NSCellImagePosition LeadingCellImagePosition(); -// Returns NSImageTrailing when available (10.12+), otherwise -// NSImageRight for LTR and NSImageLeft in RTL. -NSCellImagePosition TrailingCellImagePosition(); -// Returns NSMinXEdge for LTR and NSMaxXEdge for RTL. -NSRectEdge LeadingEdge(); -// Returns NSMaxXEdge for LTR and NSMinXEdge for RTL. -NSRectEdge TrailingEdge(); - -// Returns an autoreleased image containing |image| flipped -// across the x axis. -NSImage* FlippedImage(NSImage* image); - -// In RTL, mirrors all subviews of |view|. Additionally, -// reverses horizontal margin autoresizing masks. -// This method is *not* recursive. -// In LTR, this is a no-op. -void FlipAllSubviewsIfNecessary(NSView* view); - } // namespace cocoa_l10n_util #endif // CHROME_BROWSER_UI_COCOA_L10N_UTIL_H_
diff --git a/chrome/browser/ui/cocoa/l10n_util.mm b/chrome/browser/ui/cocoa/l10n_util.mm index 7e0cab95..3b8df667 100644 --- a/chrome/browser/ui/cocoa/l10n_util.mm +++ b/chrome/browser/ui/cocoa/l10n_util.mm
@@ -9,7 +9,6 @@ #include "base/mac/mac_util.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" -#include "chrome/common/chrome_features.h" #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h" namespace cocoa_l10n_util { @@ -70,13 +69,6 @@ return localVerticalShift; } -NSString* ReplaceNSStringPlaceholders(NSString* formatString, - const base::string16& a, - size_t* offset) { - return base::SysUTF16ToNSString(base::ReplaceStringPlaceholders( - base::SysNSStringToUTF16(formatString), a, offset)); -} - NSString* TooltipForURLAndTitle(NSString* url, NSString* title) { if ([title length] == 0) return url; @@ -86,14 +78,6 @@ return [NSString stringWithFormat:@"%@\n%@", title, url]; } -bool ShouldDoExperimentalRTLLayout() { - return base::i18n::IsRTL() && base::FeatureList::IsEnabled(features::kMacRTL); -} - -bool ShouldFlipWindowControlsInRTL() { - return ShouldDoExperimentalRTLLayout() && base::mac::IsAtLeastOS10_12(); -} - void ApplyForcedRTL() { NSUserDefaults* defaults = NSUserDefaults.standardUserDefaults; @@ -116,86 +100,4 @@ } } -// TODO(lgrey): Remove these when deployment target is 10.12. -#if defined(MAC_OS_X_VERSION_10_12) && \ - (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12) -#warning LeadingCellImagePosition/TrailingCellImagePosition \ - should be removed since the deployment target is >= 10.12 -#endif - -NSCellImagePosition LeadingCellImagePosition() { -#if defined(MAC_OS_X_VERSION_10_12) && \ - MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 - if (@available(macOS 10.12, *)) { - return NSImageLeading; - } -#endif - return ShouldDoExperimentalRTLLayout() ? NSImageRight : NSImageLeft; -} -NSCellImagePosition TrailingCellImagePosition() { -#if defined(MAC_OS_X_VERSION_10_12) && \ - MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 - if (@available(macOS 10.12, *)) { - return NSImageTrailing; - } -#endif - return ShouldDoExperimentalRTLLayout() ? NSImageLeft : NSImageRight; -} - -NSRectEdge LeadingEdge() { - return ShouldDoExperimentalRTLLayout() ? NSMaxXEdge : NSMinXEdge; -} - -NSRectEdge TrailingEdge() { - return ShouldDoExperimentalRTLLayout() ? NSMinXEdge : NSMaxXEdge; -} - -// Adapted from Apple's RTL docs (goo.gl/cBaFnT) -NSImage* FlippedImage(NSImage* image) { - const NSSize size = [image size]; - NSImage* flipped_image = [[[NSImage alloc] initWithSize:size] autorelease]; - - [flipped_image lockFocus]; - [[NSGraphicsContext currentContext] - setImageInterpolation:NSImageInterpolationHigh]; - - NSAffineTransform* transform = [NSAffineTransform transform]; - [transform translateXBy:size.width yBy:0]; - [transform scaleXBy:-1 yBy:1]; - [transform concat]; - - [image drawAtPoint:NSZeroPoint - fromRect:NSMakeRect(0, 0, size.width, size.height) - operation:NSCompositeSourceOver - fraction:1.0]; - - [flipped_image unlockFocus]; - - return flipped_image; -} - -void FlipAllSubviewsIfNecessary(NSView* view) { - if (!ShouldDoExperimentalRTLLayout()) - return; - CGFloat width = NSWidth([view frame]); - for (NSView* subview in [view subviews]) { - NSRect subviewFrame = [subview frame]; - subviewFrame.origin.x = - width - NSWidth(subviewFrame) - NSMinX(subviewFrame); - [subview setFrame:subviewFrame]; - BOOL hasMinXMargin = subview.autoresizingMask & NSViewMinXMargin; - BOOL hasMaxXMargin = subview.autoresizingMask & NSViewMaxXMargin; - if (hasMinXMargin && hasMaxXMargin) { - // No-op. Skip reversing autoresizing mask if both horizontal margins - // are flexible. - } else if (hasMinXMargin) { - subview.autoresizingMask &= ~NSViewMinXMargin; - subview.autoresizingMask |= NSViewMaxXMargin; - } else if (hasMaxXMargin) { - subview.autoresizingMask &= ~NSViewMaxXMargin; - subview.autoresizingMask |= NSViewMinXMargin; - } - } -} - } // namespace cocoa_l10n_util
diff --git a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm index 425698b4..634bf29 100644 --- a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm +++ b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm
@@ -97,12 +97,11 @@ } void RenderViewContextMenuMac::InitToolkitMenu() { - if (params_.selection_text.empty() || - params_.input_field_type == - blink::WebContextMenuData::kInputFieldTypePassword) + if (params_.input_field_type == + blink::WebContextMenuData::kInputFieldTypePassword) return; - if (params_.link_url.is_empty()) { + if (!params_.selection_text.empty() && params_.link_url.is_empty()) { // In case the user has selected a word that triggers spelling suggestions, // show the dictionary lookup under the group that contains the command to // “Add to Dictionary.”
diff --git a/chrome/browser/ui/input_method/input_method_engine_base.h b/chrome/browser/ui/input_method/input_method_engine_base.h index 7bedd1a..0755b34 100644 --- a/chrome/browser/ui/input_method/input_method_engine_base.h +++ b/chrome/browser/ui/input_method/input_method_engine_base.h
@@ -122,6 +122,8 @@ // Called when a menu item for this IME is interacted with. virtual void OnMenuItemActivated(const std::string& component_id, const std::string& menu_id) = 0; + + virtual void OnScreenProjectionChanged(bool is_projected) = 0; #endif // defined(OS_CHROMEOS) };
diff --git a/chrome/browser/ui/login/login_handler.cc b/chrome/browser/ui/login/login_handler.cc index 1108d1a..7834a0e 100644 --- a/chrome/browser/ui/login/login_handler.cc +++ b/chrome/browser/ui/login/login_handler.cc
@@ -341,7 +341,8 @@ base::BindOnce(&LoginHandler::RemoveObservers, this)); // Delete this object once all InvokeLaters have been called. - BrowserThread::ReleaseSoon(BrowserThread::IO, FROM_HERE, this); + BrowserThread::ReleaseSoon(BrowserThread::IO, FROM_HERE, + base::WrapRefCounted(this)); } void LoginHandler::AddObservers() {
diff --git a/chrome/browser/ui/passwords/manage_passwords_view_utils.cc b/chrome/browser/ui/passwords/manage_passwords_view_utils.cc index 0a600f3..1c601fa 100644 --- a/chrome/browser/ui/passwords/manage_passwords_view_utils.cc +++ b/chrome/browser/ui/passwords/manage_passwords_view_utils.cc
@@ -73,7 +73,7 @@ const autofill::PasswordForm& form) { base::string16 federation; if (!form.federation_origin.opaque()) - federation = base::UTF8ToUTF16(form.federation_origin.host()); + federation = GetDisplayFederation(form); if (form.display_name.empty()) return std::make_pair(form.username_value, std::move(federation)); @@ -152,6 +152,11 @@ : form.username_value; } +base::string16 GetDisplayFederation(const autofill::PasswordForm& form) { + return url_formatter::FormatOriginForSecurityDisplay( + form.federation_origin, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC); +} + bool IsSyncingAutosignSetting(Profile* profile) { const browser_sync::ProfileSyncService* sync_service = ProfileSyncServiceFactory::GetForProfile(profile); @@ -182,6 +187,8 @@ return "password_generation_confirmation"; case ManagePasswordsReferrer::kProfileChooser: return "profile_chooser"; + case ManagePasswordsReferrer::kPasswordsAccessorySheet: + NOTREACHED(); } NOTREACHED();
diff --git a/chrome/browser/ui/passwords/manage_passwords_view_utils.h b/chrome/browser/ui/passwords/manage_passwords_view_utils.h index 2d32a2fd..5c5dd2b 100644 --- a/chrome/browser/ui/passwords/manage_passwords_view_utils.h +++ b/chrome/browser/ui/passwords/manage_passwords_view_utils.h
@@ -70,6 +70,9 @@ // Returns an username in the form that should be shown in the bubble. base::string16 GetDisplayUsername(const autofill::PasswordForm& form); +// Returns |federation_origin| in a human-readable format. +base::string16 GetDisplayFederation(const autofill::PasswordForm& form); + // Check if |profile| syncing the Auto sign-in settings (by checking that user // syncs the PRIORITY_PREFERENCE). The view appearance might depend on it. bool IsSyncingAutosignSetting(Profile* profile);
diff --git a/chrome/browser/ui/search/local_ntp_browsertest.cc b/chrome/browser/ui/search/local_ntp_browsertest.cc index faaa1f17..cbaef19 100644 --- a/chrome/browser/ui/search/local_ntp_browsertest.cc +++ b/chrome/browser/ui/search/local_ntp_browsertest.cc
@@ -595,7 +595,7 @@ LocalNTPCustomLinksTest() : LocalNTPTest( /*enabled_features=*/{features::kUseGoogleLocalNtp, - features::kNtpUIMd, features::kNtpIcons, + features::kNtpIcons, ntp_tiles::kNtpCustomLinks}, /*disabled_features=*/{}) {}
diff --git a/chrome/browser/ui/search/local_ntp_doodle_browsertest.cc b/chrome/browser/ui/search/local_ntp_doodle_browsertest.cc index 9c6ff43..46a1a344 100644 --- a/chrome/browser/ui/search/local_ntp_doodle_browsertest.cc +++ b/chrome/browser/ui/search/local_ntp_doodle_browsertest.cc
@@ -103,6 +103,46 @@ return base::nullopt; } + void TeardownWindowOpenTest(content::WebContents* tab) { + ASSERT_TRUE(content::ExecuteScript(tab, "window.open = windowOpenOld")); + } + + void SetupWindowOpenTest(content::WebContents* tab) { + ASSERT_TRUE(content::ExecuteScript(tab, + "var windowOpenOld = window.open; " + "window.open = (w) => { openedWindow = " + "w };")); + } + + base::Optional<std::string> GetWindowOpenURL(content::WebContents* tab) { + std::string target_url; + if (instant_test_utils::GetStringFromJS(tab, "openedWindow", &target_url)) { + return target_url; + } + return base::nullopt; + } + + bool ElementExists(content::WebContents* tab, const std::string& id) { + return ExecuteBooleanJS( + tab, base::StringPrintf("!!document.getElementById(%s)", + base::GetQuotedJSONString(id).c_str())); + } + + bool DialogIsOpen(content::WebContents* tab, const std::string& id) { + return ExecuteBooleanJS( + tab, + base::StringPrintf("!!document.getElementById(%s).hasAttribute('open')", + base::GetQuotedJSONString(id).c_str())); + } + + bool ExecuteBooleanJS(content::WebContents* tab, const std::string& js) { + bool value; + if (instant_test_utils::GetBoolFromJS(tab, js, &value)) { + return value; + } + return false; + } + base::Optional<std::string> GetComputedStyle(content::WebContents* tab, const std::string& id, const std::string& css_name) { @@ -299,8 +339,8 @@ EXPECT_THAT(GetDimension(active_tab, "fakebox", "top"), Eq(kFakeboxTopPx)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0)); - EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-button"), - Eq<std::string>("block")); + EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"), + Eq<std::string>("inline-block")); EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"), Eq<std::string>("none")); EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "title"), @@ -343,7 +383,7 @@ EXPECT_THAT(GetDimension(active_tab, "fakebox", "top"), Eq(kFakeboxTopPx)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0)); - EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-button"), + EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"), Eq<std::string>("none")); EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"), Eq<std::string>("block")); @@ -418,8 +458,8 @@ EXPECT_THAT(GetDimension(active_tab, "fakebox", "top"), Eq(kFakeboxTopPx)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0)); - EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-button"), - Eq<std::string>("block")); + EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"), + Eq<std::string>("inline-block")); EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"), Eq<std::string>("none")); EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "title"), @@ -465,7 +505,7 @@ EXPECT_THAT(GetDimension(active_tab, "fakebox", "top"), Eq(kFakeboxTopPx)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0)); - EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-button"), + EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"), Eq<std::string>("none")); EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"), Eq<std::string>("block")); @@ -501,7 +541,7 @@ EXPECT_THAT(GetDimension(active_tab, "fakebox", "top"), Eq(kFakeboxTopPx)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0)); - EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-button"), + EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"), Eq<std::string>("none")); EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"), Eq<std::string>("block")); @@ -542,8 +582,8 @@ EXPECT_THAT(GetDimension(active_tab, "fakebox", "top"), Eq(kFakeboxTopPx)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0)); - EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-button"), - Eq<std::string>("block")); + EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"), + Eq<std::string>("inline-block")); EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"), Eq<std::string>("none")); EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "src"), @@ -596,8 +636,8 @@ EXPECT_THAT(GetDimension(active_tab, "fakebox", "top"), Eq(kFakeboxTopPx)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0)); - EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-button"), - Eq<std::string>("block")); + EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"), + Eq<std::string>("inline-block")); EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"), Eq<std::string>("none")); @@ -616,6 +656,256 @@ histograms.ExpectTotalCount("NewTabPage.LogoShownTime2", 1); } +IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldAppendShareButtonWhenCached) { + EncodedLogo cached_logo; + cached_logo.encoded_image = MakeRefPtr(kCachedB64); + cached_logo.metadata.mime_type = "image/png"; + cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/"); + cached_logo.metadata.alt_text = "Chromium"; + cached_logo.metadata.short_link = GURL("https://g.co"); + cached_logo.metadata.share_button_x = 12; + cached_logo.metadata.share_button_y = 39; + cached_logo.metadata.share_button_opacity = 0.8; + cached_logo.metadata.share_button_icon = "sbimg"; + cached_logo.metadata.share_button_bg = "#ffff00"; + + EXPECT_CALL(*logo_service(), GetLogoPtr(_)) + .WillRepeatedly(DoAll( + ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo), + ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt))); + + // Open a new blank tab, then go to NTP and listen for console messages. + content::WebContents* active_tab = + local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); + content::ConsoleObserverDelegate console_observer(active_tab, "*"); + active_tab->SetDelegate(&console_observer); + base::HistogramTester histograms; + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); + + EXPECT_TRUE(ElementExists(active_tab, "ddlsb")); + EXPECT_TRUE(ElementExists(active_tab, "ddlsb-img")); + EXPECT_THAT(GetComputedStyle(active_tab, "ddlsb", "left"), + Eq<std::string>("12px")); + EXPECT_THAT(GetComputedStyle(active_tab, "ddlsb", "top"), + Eq<std::string>("39px")); + EXPECT_THAT(GetComputedStyle(active_tab, "ddlsb", "background-color"), + Eq<std::string>("rgba(255, 255, 0, 0.8)")); + EXPECT_THAT(GetElementProperty(active_tab, "ddlsb-img", "src"), + Eq<std::string>("data:image/png;base64,sbimg")); +} + +IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, + ShouldNotAppendShareButtonWhenCacheEmpty) { + EncodedLogo cached_logo; + cached_logo.encoded_image = MakeRefPtr(kCachedB64); + cached_logo.metadata.mime_type = "image/png"; + cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/"); + cached_logo.metadata.alt_text = "Chromium"; + cached_logo.metadata.short_link = GURL("https://g.co"); + cached_logo.metadata.share_button_x = -1; + cached_logo.metadata.share_button_y = -1; + cached_logo.metadata.share_button_opacity = 0; + cached_logo.metadata.share_button_icon = ""; + cached_logo.metadata.share_button_bg = ""; + + EXPECT_CALL(*logo_service(), GetLogoPtr(_)) + .WillRepeatedly(DoAll( + ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo), + ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt))); + + // Open a new blank tab, then go to NTP and listen for console messages. + content::WebContents* active_tab = + local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); + content::ConsoleObserverDelegate console_observer(active_tab, "*"); + active_tab->SetDelegate(&console_observer); + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); + + EXPECT_FALSE(ElementExists(active_tab, "ddlsb")); + EXPECT_FALSE(ElementExists(active_tab, "ddlsb-img")); +} + +IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, + ShouldNotAppendShareButtonWhenCacheIncomplete) { + EncodedLogo cached_logo; + cached_logo.encoded_image = MakeRefPtr(kCachedB64); + cached_logo.metadata.mime_type = "image/png"; + cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/"); + cached_logo.metadata.alt_text = "Chromium"; + cached_logo.metadata.short_link = GURL("https://g.co"); + cached_logo.metadata.share_button_x = 12; + cached_logo.metadata.share_button_y = 36; + cached_logo.metadata.share_button_opacity = 0.8; + cached_logo.metadata.share_button_icon = ""; + cached_logo.metadata.share_button_bg = "#ffff00"; + + EXPECT_CALL(*logo_service(), GetLogoPtr(_)) + .WillRepeatedly(DoAll( + ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo), + ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt))); + + // Open a new blank tab, then go to NTP and listen for console messages. + content::WebContents* active_tab = + local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); + content::ConsoleObserverDelegate console_observer(active_tab, "*"); + active_tab->SetDelegate(&console_observer); + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); + + EXPECT_FALSE(ElementExists(active_tab, "ddlsb")); + EXPECT_FALSE(ElementExists(active_tab, "ddlsb-img")); +} + +IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, + ShouldShowShareDialogWhenShareButtonClicked) { + EncodedLogo cached_logo; + cached_logo.encoded_image = MakeRefPtr(kCachedB64); + cached_logo.metadata.mime_type = "image/png"; + cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/"); + cached_logo.metadata.alt_text = "Chromium"; + cached_logo.metadata.short_link = GURL("https://g.co"); + cached_logo.metadata.share_button_x = 12; + cached_logo.metadata.share_button_y = 36; + cached_logo.metadata.share_button_opacity = 0.8; + cached_logo.metadata.share_button_icon = "sbimg"; + cached_logo.metadata.share_button_bg = "#ffff00"; + + EXPECT_CALL(*logo_service(), GetLogoPtr(_)) + .WillRepeatedly(DoAll( + ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo), + ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt))); + + // Open a new blank tab, then go to NTP and listen for console messages. + content::WebContents* active_tab = + local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); + content::ConsoleObserverDelegate console_observer(active_tab, "*"); + active_tab->SetDelegate(&console_observer); + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); + + EXPECT_FALSE(DialogIsOpen(active_tab, "ddlsd")); + ASSERT_TRUE(content::ExecuteScript( + active_tab, "document.getElementById('ddlsb').click();")); + EXPECT_TRUE(DialogIsOpen(active_tab, "ddlsd")); + + // Check title + std::string title; + ASSERT_TRUE(instant_test_utils::GetStringFromJS( + active_tab, "document.getElementById('ddlsd-title').innerHTML", &title)); + EXPECT_THAT(title, Eq<std::string>(cached_logo.metadata.alt_text)); + + // Check share link inside textbox + std::string link; + ASSERT_TRUE(instant_test_utils::GetStringFromJS( + active_tab, "document.getElementById('ddlsd-text').value", &link)); + EXPECT_THAT(link, Eq<std::string>("https://g.co/")); + + ASSERT_TRUE(content::ExecuteScript( + active_tab, "document.getElementById('ddlsd-close').click();")); + EXPECT_FALSE(DialogIsOpen(active_tab, "ddlsd")); +} + +IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldOpenFacebookInShareDialog) { + EncodedLogo cached_logo; + cached_logo.encoded_image = MakeRefPtr(kCachedB64); + cached_logo.metadata.mime_type = "image/png"; + cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/"); + cached_logo.metadata.alt_text = "Chromium"; + cached_logo.metadata.short_link = GURL("https://g.co"); + cached_logo.metadata.share_button_x = 12; + cached_logo.metadata.share_button_y = 36; + cached_logo.metadata.share_button_opacity = 0.8; + cached_logo.metadata.share_button_icon = "sbimg"; + cached_logo.metadata.share_button_bg = "#ffff00"; + + EXPECT_CALL(*logo_service(), GetLogoPtr(_)) + .WillRepeatedly(DoAll( + ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo), + ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt))); + + // Open a new blank tab, then go to NTP and listen for console messages. + content::WebContents* active_tab = + local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); + + ASSERT_TRUE(content::ExecuteScript( + active_tab, "document.getElementById('ddlsb').click();")); + EXPECT_TRUE(DialogIsOpen(active_tab, "ddlsd")); + SetupWindowOpenTest(active_tab); + ASSERT_TRUE(content::ExecuteScript( + active_tab, "document.getElementById('ddlsd-fbb').click();")); + EXPECT_THAT(GetWindowOpenURL(active_tab), + Eq<std::string>( + "https://www.facebook.com/dialog/share?app_id=738026486351791" + "&href=https%3A%2F%2Fg.co%2F&hashtag=%23GoogleDoodle")); +} + +IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldOpenTwitterInShareDialog) { + EncodedLogo cached_logo; + cached_logo.encoded_image = MakeRefPtr(kCachedB64); + cached_logo.metadata.mime_type = "image/png"; + cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/"); + cached_logo.metadata.alt_text = "Chromium"; + cached_logo.metadata.short_link = GURL("https://g.co"); + cached_logo.metadata.share_button_x = 12; + cached_logo.metadata.share_button_y = 36; + cached_logo.metadata.share_button_opacity = 0.8; + cached_logo.metadata.share_button_icon = "sbimg"; + cached_logo.metadata.share_button_bg = "#ffff00"; + + EXPECT_CALL(*logo_service(), GetLogoPtr(_)) + .WillRepeatedly(DoAll( + ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo), + ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt))); + + // Open a new blank tab, then go to NTP and listen for console messages. + content::WebContents* active_tab = + local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); + + ASSERT_TRUE(content::ExecuteScript( + active_tab, "document.getElementById('ddlsb').click();")); + EXPECT_TRUE(DialogIsOpen(active_tab, "ddlsd")); + SetupWindowOpenTest(active_tab); + ASSERT_TRUE(content::ExecuteScript( + active_tab, "document.getElementById('ddlsd-twb').click();")); + EXPECT_THAT(GetWindowOpenURL(active_tab), + Eq<std::string>("https://twitter.com/intent/tweet" + "?text=Chromium%0Ahttps%3A%2F%2Fg.co%2F")); +} + +IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldCopyLinkInShareDialog) { + EncodedLogo cached_logo; + cached_logo.encoded_image = MakeRefPtr(kCachedB64); + cached_logo.metadata.mime_type = "image/png"; + cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/"); + cached_logo.metadata.alt_text = "Chromium"; + cached_logo.metadata.short_link = GURL("https://g.co"); + cached_logo.metadata.share_button_x = 12; + cached_logo.metadata.share_button_y = 36; + cached_logo.metadata.share_button_opacity = 0.8; + cached_logo.metadata.share_button_icon = "sbimg"; + cached_logo.metadata.share_button_bg = "#ffff00"; + + EXPECT_CALL(*logo_service(), GetLogoPtr(_)) + .WillRepeatedly(DoAll( + ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo), + ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt))); + + // Open a new blank tab, then go to NTP and listen for console messages. + content::WebContents* active_tab = + local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); + + ASSERT_TRUE(content::ExecuteScript( + active_tab, "document.getElementById('ddlsb').click();")); + EXPECT_TRUE(DialogIsOpen(active_tab, "ddlsd")); + + ASSERT_TRUE(content::ExecuteScript( + active_tab, "document.getElementById('ddlsd-copy').click();")); + std::string short_link; + ASSERT_TRUE(instant_test_utils::GetStringFromJS( + active_tab, "window.getSelection().toString()", &short_link)); + EXPECT_EQ("https://g.co/", short_link); +} + IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldAnimateLogoWhenClicked) { EncodedLogo cached_logo; cached_logo.encoded_image = MakeRefPtr(kCachedB64); @@ -639,8 +929,8 @@ EXPECT_THAT(GetDimension(active_tab, "fakebox", "top"), Eq(kFakeboxTopPx)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(0.0)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0)); - EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-button"), - Eq<std::string>("block")); + EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-container"), + Eq<std::string>("inline-block")); EXPECT_THAT(GetComputedDisplay(active_tab, "logo-doodle-iframe"), Eq<std::string>("none")); @@ -669,6 +959,42 @@ histograms.ExpectBucketCount("NewTabPage.LogoClick", kLogoClickCta, 1); } +IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, + ShouldAddShareButtonInAnimatedDoodle) { + EncodedLogo cached_logo; + cached_logo.encoded_image = MakeRefPtr(kCachedB64); + cached_logo.metadata.mime_type = "image/png"; + cached_logo.metadata.type = LogoType::ANIMATED; + cached_logo.metadata.animated_url = GURL("data:image/png;base64,cached++"); + cached_logo.metadata.on_click_url = GURL("https://www.chromium.org/"); + cached_logo.metadata.alt_text = "alt text"; + cached_logo.metadata.short_link = GURL("https://g.co"); + cached_logo.metadata.share_button_x = 12; + cached_logo.metadata.share_button_y = 36; + cached_logo.metadata.share_button_opacity = 0.8; + cached_logo.metadata.share_button_icon = "sbimg"; + cached_logo.metadata.share_button_bg = "#ffff00"; + + EXPECT_CALL(*logo_service(), GetLogoPtr(_)) + .WillRepeatedly(DoAll( + ReturnCachedLogo(LogoCallbackReason::DETERMINED, cached_logo), + ReturnFreshLogo(LogoCallbackReason::REVALIDATED, base::nullopt))); + + // Open a new blank tab, then go to NTP. + content::WebContents* active_tab = + local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); + base::HistogramTester histograms; + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); + + // Share button should not be present pre-CTA click + EXPECT_FALSE(ElementExists(active_tab, "ddlsb")); + ASSERT_TRUE(content::ExecuteScript( + active_tab, "document.getElementById('logo-doodle-button').click();")); + + // Share button is only added post-CTA click when the animation is playing + EXPECT_TRUE(ElementExists(active_tab, "ddlsb")); +} + std::string WaitForDdllogResponse(content::WebContents* tab, int expected_ddllog_count) { std::string response;
diff --git a/chrome/browser/ui/search/local_ntp_promos_browsertest.cc b/chrome/browser/ui/search/local_ntp_promos_browsertest.cc new file mode 100644 index 0000000..0c2afd9 --- /dev/null +++ b/chrome/browser/ui/search/local_ntp_promos_browsertest.cc
@@ -0,0 +1,126 @@ +// 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 <memory> +#include <string> +#include <utility> + +#include "base/bind.h" +#include "base/json/string_escape.h" +#include "base/memory/ref_counted_memory.h" +#include "base/optional.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/stringprintf.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/search/ntp_features.h" +#include "chrome/browser/search/promos/promo_service.h" +#include "chrome/browser/search/promos/promo_service_factory.h" +#include "chrome/browser/search_provider_logos/logo_service_factory.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/search/instant_test_utils.h" +#include "chrome/browser/ui/search/local_ntp_test_utils.h" +#include "chrome/common/url_constants.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/search_provider_logos/logo_service.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/test_navigation_observer.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "url/gurl.h" + +using testing::_; +using testing::DoAll; +using testing::Eq; +using testing::IsEmpty; + +class MockPromoService : public PromoService { + public: + MockPromoService() : PromoService(nullptr, nullptr) {} + + void Refresh() override { PromoDataLoaded(Status::OK, promo_data_); } + + void set_promo_data(const PromoData& promo_data) { promo_data_ = promo_data; } + + private: + PromoData promo_data_; +}; + +class LocalNTPPromoTest : public InProcessBrowserTest { + protected: + LocalNTPPromoTest() {} + + MockPromoService* promo_service() { + return static_cast<MockPromoService*>( + PromoServiceFactory::GetForProfile(browser()->profile())); + } + + private: + void SetUp() override { + feature_list_.InitWithFeatures( + {features::kUseGoogleLocalNtp, features::kPromosOnLocalNtp}, {}); + InProcessBrowserTest::SetUp(); + } + + void SetUpInProcessBrowserTestFixture() override { + will_create_browser_context_services_subscription_ = + BrowserContextDependencyManager::GetInstance() + ->RegisterWillCreateBrowserContextServicesCallbackForTesting( + base::BindRepeating( + &LocalNTPPromoTest::OnWillCreateBrowserContextServices, + base::Unretained(this))); + } + + static std::unique_ptr<KeyedService> CreatePromoService( + content::BrowserContext* context) { + return std::make_unique<MockPromoService>(); + } + + void OnWillCreateBrowserContextServices(content::BrowserContext* context) { + PromoServiceFactory::GetInstance()->SetTestingFactory( + context, base::BindRepeating(&LocalNTPPromoTest::CreatePromoService)); + } + + base::test::ScopedFeatureList feature_list_; + + std::unique_ptr< + base::CallbackList<void(content::BrowserContext*)>::Subscription> + will_create_browser_context_services_subscription_; +}; + +IN_PROC_BROWSER_TEST_F(LocalNTPPromoTest, PromoInjectedIntoPage) { + PromoData promo; + promo.promo_html = "<div>promo</div>"; + promo_service()->set_promo_data(promo); + + // Open a new blank tab, then go to NTP and listen for console messages. + content::WebContents* active_tab = + local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); + content::ConsoleObserverDelegate console_observer(active_tab, "*"); + active_tab->SetDelegate(&console_observer); + local_ntp_test_utils::NavigateToNTPAndWaitUntilLoaded(browser(), + /*delay=*/1000); + + bool result; + EXPECT_TRUE(instant_test_utils::GetBoolFromJS( + active_tab, "$('promo').innerHTML === '<div>promo</div>'", &result)); + ASSERT_TRUE(result); +} + +IN_PROC_BROWSER_TEST_F(LocalNTPPromoTest, NoPromoInjectedIntoPage) { + // Open a new blank tab, then go to NTP and listen for console messages. + content::WebContents* active_tab = + local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); + content::ConsoleObserverDelegate console_observer(active_tab, "*"); + active_tab->SetDelegate(&console_observer); + local_ntp_test_utils::NavigateToNTPAndWaitUntilLoaded(browser(), + /*delay=*/1000); + + bool result; + EXPECT_TRUE(instant_test_utils::GetBoolFromJS( + active_tab, "$('promo') === null", &result)); + ASSERT_TRUE(result); +}
diff --git a/chrome/browser/ui/startup/startup_browser_creator_interactive_uitest.cc b/chrome/browser/ui/startup/startup_browser_creator_interactive_uitest.cc index ee39eeb8..f308d40 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_interactive_uitest.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_interactive_uitest.cc
@@ -10,6 +10,8 @@ #include "base/threading/thread_restrictions.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/chrome_browser_main.h" +#include "chrome/browser/chrome_browser_main_extra_parts.h" #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/sessions/session_restore.h" @@ -17,12 +19,17 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/startup/startup_browser_creator.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" -typedef InProcessBrowserTest StartupBrowserCreatorTest; +#if defined(USE_AURA) +#include "ui/aura/window.h" +#endif + +using StartupBrowserCreatorTest = InProcessBrowserTest; // Chrome OS doesn't support multiprofile. // And BrowserWindow::IsActive() always returns false in tests on MAC. @@ -100,3 +107,60 @@ EXPECT_FALSE(new_browser->window()->IsActive()); } #endif // !OS_MACOSX && !OS_CHROMEOS + +#if defined(USE_AURA) +class StartupPagePrefSetterMainExtraParts : public ChromeBrowserMainExtraParts { + public: + explicit StartupPagePrefSetterMainExtraParts(const std::vector<GURL>& urls) + : urls_(urls) {} + + // ChromeBrowserMainExtraParts: + void PreBrowserStart() override { + Profile* profile = + g_browser_process->profile_manager()->GetActiveUserProfile(); + + SessionStartupPref pref_urls(SessionStartupPref::URLS); + pref_urls.urls = std::move(urls_); + SessionStartupPref::SetStartupPref(profile, pref_urls); + } + + private: + std::vector<GURL> urls_; + DISALLOW_COPY_AND_ASSIGN(StartupPagePrefSetterMainExtraParts); +}; + +class StartupPageTest : public InProcessBrowserTest { + public: + StartupPageTest() { + // Don't open about:blank since we want to test startup urls. + set_open_about_blank_on_browser_launch(false); + } + ~StartupPageTest() override = default; + + // InProcessBrowserTest: + void CreatedBrowserMainParts( + content::BrowserMainParts* browser_main_parts) override { + const std::vector<GURL> urls = {ui_test_utils::GetTestUrl( + base::FilePath(FILE_PATH_LITERAL("focus")), + base::FilePath(FILE_PATH_LITERAL("page_with_focus.html")))}; + + ChromeBrowserMainParts* chrome_browser_main_parts = + static_cast<ChromeBrowserMainParts*>(browser_main_parts); + chrome_browser_main_parts->AddParts( + new StartupPagePrefSetterMainExtraParts(urls)); + } + + private: + DISALLOW_COPY_AND_ASSIGN(StartupPageTest); +}; + +IN_PROC_BROWSER_TEST_F(StartupPageTest, StartupPageFocus) { + // Browser window should be active. + EXPECT_TRUE(browser()->window()->IsActive()); + + // Focus should land in the content area. + content::WebContents* contents = + browser()->tab_strip_model()->GetActiveWebContents(); + EXPECT_TRUE(contents->GetContentNativeView()->HasFocus()); +} +#endif // defined(USE_AURA)
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index a01d10a8..4ba26e26 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -135,6 +135,7 @@ #include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h" #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h" #include "chrome/browser/extensions/tab_helper.h" +#include "chrome/browser/web_applications/web_app_provider.h" #include "extensions/browser/view_type_utils.h" #endif @@ -334,6 +335,7 @@ #if BUILDFLAG(ENABLE_EXTENSIONS) extensions::TabHelper::CreateForWebContents(web_contents); + web_app::WebAppProvider::CreateTabHelper(web_contents); #endif #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc index 90067933..5ebae227 100644 --- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc +++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
@@ -918,13 +918,6 @@ RemoveAllChildViews(true /* delete_children */); rows_.clear(); - // Create one container to wrap the "regular" (non-footer) rows. - views::View* body_container = new views::View(); - views::BoxLayout* body_layout = body_container->SetLayoutManager( - std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); - body_layout->set_main_axis_alignment( - views::BoxLayout::MAIN_AXIS_ALIGNMENT_START); - int line_number = 0; bool has_footer = false; @@ -967,29 +960,39 @@ if (has_footer) break; - body_container->AddChildView(rows_.back()); line_number++; } - scroll_view_ = new views::ScrollView(); - scroll_view_->set_hide_horizontal_scrollbar(true); - scroll_view_->SetContents(body_container); - scroll_view_->set_draw_overflow_indicator(false); - scroll_view_->ClipHeightTo(0, body_container->GetPreferredSize().height()); + if (rows_.size()) { + // Create a container to wrap the "regular" (non-footer) rows. + views::View* body_container = new views::View(); + views::BoxLayout* body_layout = body_container->SetLayoutManager( + std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); + body_layout->set_main_axis_alignment( + views::BoxLayout::MAIN_AXIS_ALIGNMENT_START); + for (auto* row : rows_) { + body_container->AddChildView(row); + } - // Use an additional container to apply padding outside the scroll view, so - // that the padding area is stationary. This ensures that the rounded corners - // appear properly; on Mac, the clipping path will not apply properly to a - // scrollable area. - // NOTE: GetContentsVerticalPadding is guaranteed to return a size which - // accommodates the rounded corners. - views::View* padding_wrapper = new views::View(); - padding_wrapper->SetBorder( - views::CreateEmptyBorder(gfx::Insets(GetContentsVerticalPadding(), 0))); - padding_wrapper->SetLayoutManager(std::make_unique<views::FillLayout>()); - padding_wrapper->AddChildView(scroll_view_); - AddChildView(padding_wrapper); - layout_->SetFlexForView(padding_wrapper, 1); + scroll_view_ = new views::ScrollView(); + scroll_view_->set_hide_horizontal_scrollbar(true); + scroll_view_->SetContents(body_container); + scroll_view_->set_draw_overflow_indicator(false); + scroll_view_->ClipHeightTo(0, body_container->GetPreferredSize().height()); + + // Use an additional container to apply padding outside the scroll view, so + // that the padding area is stationary. This ensures that the rounded + // corners appear properly; on Mac, the clipping path will not apply + // properly to a scrollable area. NOTE: GetContentsVerticalPadding is + // guaranteed to return a size which accommodates the rounded corners. + views::View* padding_wrapper = new views::View(); + padding_wrapper->SetBorder( + views::CreateEmptyBorder(gfx::Insets(GetContentsVerticalPadding(), 0))); + padding_wrapper->SetLayoutManager(std::make_unique<views::FillLayout>()); + padding_wrapper->AddChildView(scroll_view_); + AddChildView(padding_wrapper); + layout_->SetFlexForView(padding_wrapper, 1); + } // All the remaining rows (where index >= |line_number|) are part of the // footer. This needs to be in its own container because it should not be
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.cc b/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.cc index 1a4ac00..eebb87b 100644 --- a/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.cc +++ b/chrome/browser/ui/views/autofill/local_card_migration_dialog_view.cc
@@ -65,14 +65,19 @@ message_id = IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_TITLE_FIX; break; } + auto title = std::make_unique<views::Label>(l10n_util::GetStringUTF16(message_id)); constexpr int kMigrationDialogTitleFontSize = 8; + title->SetBorder(views::CreateEmptyBorder( + /*top=*/0, /*left=*/kMigrationDialogInsets.left(), /*bottom=*/0, + /*right=*/kMigrationDialogInsets.right())); title->SetFontList(gfx::FontList().Derive(kMigrationDialogTitleFontSize, gfx::Font::NORMAL, gfx::Font::Weight::MEDIUM)); title->SetEnabledColor(gfx::kGoogleGrey900); constexpr int kMigrationDialogTitleLineHeight = 20; + title->SetMultiLine(true); title->SetLineHeight(kMigrationDialogTitleLineHeight); return title; } @@ -370,6 +375,7 @@ return true; case LocalCardMigrationDialogState::kFinished: case LocalCardMigrationDialogState::kActionRequired: + controller_->OnDoneButtonClicked(); return true; } }
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_error_dialog_view.cc b/chrome/browser/ui/views/autofill/local_card_migration_error_dialog_view.cc index b8706949..4fc656c 100644 --- a/chrome/browser/ui/views/autofill/local_card_migration_error_dialog_view.cc +++ b/chrome/browser/ui/views/autofill/local_card_migration_error_dialog_view.cc
@@ -82,6 +82,11 @@ } } +bool LocalCardMigrationErrorDialogView::Cancel() { + controller_->OnDoneButtonClicked(); + return true; +} + bool LocalCardMigrationErrorDialogView::Close() { // Close the dialog if the user exits the browser when dialog is visible. return true;
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_error_dialog_view.h b/chrome/browser/ui/views/autofill/local_card_migration_error_dialog_view.h index 243900b..80d2248 100644 --- a/chrome/browser/ui/views/autofill/local_card_migration_error_dialog_view.h +++ b/chrome/browser/ui/views/autofill/local_card_migration_error_dialog_view.h
@@ -38,6 +38,7 @@ ui::ModalType GetModalType() const override; bool ShouldShowCloseButton() const override; int GetDialogButtons() const override; + bool Cancel() override; bool Close() override; void Init() override; void WindowClosing() override;
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_icon_view.cc b/chrome/browser/ui/views/autofill/local_card_migration_icon_view.cc index a5a9ff98..7de1455 100644 --- a/chrome/browser/ui/views/autofill/local_card_migration_icon_view.cc +++ b/chrome/browser/ui/views/autofill/local_card_migration_icon_view.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/ui/views/autofill/local_card_migration_bubble_views.h" #include "chrome/browser/ui/views/autofill/local_card_migration_dialog_view.h" #include "chrome/grit/generated_resources.h" +#include "components/strings/grit/components_strings.h" #include "ui/base/l10n/l10n_util.h" namespace autofill { @@ -20,13 +21,16 @@ LocalCardMigrationIconView::LocalCardMigrationIconView( CommandUpdater* command_updater, Browser* browser, - PageActionIconView::Delegate* delegate) + PageActionIconView::Delegate* delegate, + const gfx::FontList& font_list) : PageActionIconView(command_updater, IDC_MIGRATE_LOCAL_CREDIT_CARD_FOR_PAGE, - delegate), + delegate, + font_list), browser_(browser) { DCHECK(delegate); set_id(VIEW_ID_MIGRATE_LOCAL_CREDIT_CARD_BUTTON); + SetUpForInOutAnimation(); } LocalCardMigrationIconView::~LocalCardMigrationIconView() {} @@ -36,19 +40,18 @@ if (!controller) return nullptr; - switch (controller->GetFlowStep()) { - case LocalCardMigrationFlowStep::PROMO_BUBBLE: { + LocalCardMigrationFlowStep step = controller->GetFlowStep(); + DCHECK_NE(step, LocalCardMigrationFlowStep::UNKNOWN); + switch (step) { + case LocalCardMigrationFlowStep::PROMO_BUBBLE: return static_cast<LocalCardMigrationBubbleViews*>( controller->GetBubbleView()); - } - case LocalCardMigrationFlowStep::CREDIT_CARD_ICON: { + case LocalCardMigrationFlowStep::NOT_SHOWN: + case LocalCardMigrationFlowStep::MIGRATION_RESULT_PENDING: + return nullptr; + default: return static_cast<LocalCardMigrationDialogView*>( controller->GetDialogView()); - } - default: { - NOTREACHED(); - return nullptr; - } } } @@ -56,14 +59,46 @@ if (!GetWebContents()) return false; - const bool was_visible = visible(); - // |controller| may be nullptr due to lazy initialization. ManageMigrationUiController* controller = GetController(); bool enabled = controller && controller->IsIconVisible(); enabled &= SetCommandEnabled(enabled); SetVisible(enabled); - return was_visible != visible(); + + if (visible()) { + switch (controller->GetFlowStep()) { + // When the dialog is about to show, trigger the ink drop animation + // so that the credit card icon in "selected" state by default. This needs + // to be manually set since the migration dialog is not anchored at the + // credit card icon. + case LocalCardMigrationFlowStep::OFFER_DIALOG: { + AnimateInkDrop(views::InkDropState::ACTIVATED, /*event=*/nullptr); + break; + } + case LocalCardMigrationFlowStep::MIGRATION_RESULT_PENDING: { + AnimateInkDrop(views::InkDropState::HIDDEN, /*event=*/nullptr); + // Disable the credit card icon so it does not update if user clicks + // on it. + SetEnabled(false); + AnimateIn(IDS_AUTOFILL_LOCAL_CARD_MIGRATION_ANIMATION_LABEL); + break; + } + case LocalCardMigrationFlowStep::MIGRATION_FINISHED: { + UnpauseAnimation(); + SetEnabled(true); + break; + } + default: + break; + } + } else { + // Handle corner cases where users navigate away or close the tab. + UnpauseAnimation(); + } + + // Need to return true since in both MIGRATION_RESULT_PENDING and + // MIGRATION_FINISHED cases the credit card icon is visible. + return true; } void LocalCardMigrationIconView::OnExecuting( @@ -78,6 +113,12 @@ return l10n_util::GetStringUTF16(IDS_TOOLTIP_MIGRATE_LOCAL_CARD); } +// Override the function to remove the extra trailing space in icon after +// animation finishes. +bool LocalCardMigrationIconView::ShouldShowSeparator() const { + return false; +} + ManageMigrationUiController* LocalCardMigrationIconView::GetController() const { if (!browser_) return nullptr; @@ -89,4 +130,20 @@ return autofill::ManageMigrationUiController::FromWebContents(web_contents); } +void LocalCardMigrationIconView::AnimationProgressed( + const gfx::Animation* animation) { + IconLabelBubbleView::AnimationProgressed(animation); + + // Pause the animation when the animation text is completely shown. If the + // user navigates to other tab when the animation is in progress, don't pause + // the animation. + constexpr double animation_text_full_length_shown_state = 0.5; + if (GetController() && + GetController()->GetFlowStep() == + LocalCardMigrationFlowStep::MIGRATION_RESULT_PENDING && + GetAnimationValue() >= animation_text_full_length_shown_state) { + PauseAnimation(); + } +} + } // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/local_card_migration_icon_view.h b/chrome/browser/ui/views/autofill/local_card_migration_icon_view.h index eb44aaa..669007b 100644 --- a/chrome/browser/ui/views/autofill/local_card_migration_icon_view.h +++ b/chrome/browser/ui/views/autofill/local_card_migration_icon_view.h
@@ -21,7 +21,8 @@ public: LocalCardMigrationIconView(CommandUpdater* command_updater, Browser* browser, - PageActionIconView::Delegate* delegate); + PageActionIconView::Delegate* delegate, + const gfx::FontList& font_list); ~LocalCardMigrationIconView() override; // PageActionIconView: @@ -29,6 +30,9 @@ bool Update() override; base::string16 GetTextForTooltipAndAccessibleName() const override; + // IconLabelBubbleView: + bool ShouldShowSeparator() const override; + protected: // PageActionIconView: void OnExecuting(PageActionIconView::ExecuteSource execute_source) override; @@ -37,6 +41,9 @@ private: ManageMigrationUiController* GetController() const; + // IconLabelBubbleView: + void AnimationProgressed(const gfx::Animation* animation) override; + // Used to do nullptr check when getting the controller. Browser* const browser_;
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.cc index 402585d..a9ac43e 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.cc +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.cc
@@ -151,7 +151,7 @@ event_waiter_->OnEvent(DialogEvent::RECEIVED_UPLOAD_CARD_RESPONSE); } -void SaveCardBubbleViewsBrowserTestBase::OnCCSMStrikeChangeComplete() { +void SaveCardBubbleViewsBrowserTestBase::OnStrikeChangeComplete() { if (event_waiter_) event_waiter_->OnEvent(DialogEvent::STRIKE_CHANGE_COMPLETE); } @@ -166,11 +166,6 @@ event_waiter_->OnEvent(DialogEvent::BUBBLE_CLOSED); } -void SaveCardBubbleViewsBrowserTestBase::OnSCBCStrikeChangeComplete() { - if (event_waiter_) - event_waiter_->OnEvent(DialogEvent::STRIKE_CHANGE_COMPLETE); -} - void SaveCardBubbleViewsBrowserTestBase::SetUpInProcessBrowserTestFixture() { will_create_browser_context_services_subscription_ = BrowserContextDependencyManager::GetInstance()
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h index cd60775..f20f143 100644 --- a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h +++ b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h
@@ -70,12 +70,11 @@ void OnReceivedGetUploadDetailsResponse() override; void OnSentUploadCardRequest() override; void OnReceivedUploadCardResponse() override; - void OnCCSMStrikeChangeComplete() override; + void OnStrikeChangeComplete() override; // SaveCardBubbleControllerImpl::ObserverForTest: void OnBubbleShown() override; void OnBubbleClosed() override; - void OnSCBCStrikeChangeComplete() override; // BrowserTestBase: void SetUpInProcessBrowserTestFixture() override;
diff --git a/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.cc b/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.cc index 0408eb0..e303351 100644 --- a/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.cc +++ b/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.cc
@@ -31,6 +31,7 @@ #include "ui/gfx/image/image_skia_operations.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/views/border.h" +#include "ui/views/bubble/bubble_border.h" #include "ui/views/bubble/bubble_frame_view.h" #include "ui/views/bubble/tooltip_icon.h" #include "ui/views/controls/button/label_button.h" @@ -46,6 +47,7 @@ namespace autofill { namespace { +const int kTooltipBubbleWidth = 320; const int kTooltipIconSize = 12; } // namespace @@ -57,6 +59,21 @@ : SaveCardBubbleViews(anchor_view, anchor_point, web_contents, controller) { } +views::View* SaveCardOfferBubbleViews::CreateExtraView() { + if (!base::FeatureList::IsEnabled( + features::kAutofillSaveCardImprovedUserConsent)) { + return nullptr; + } + + auto* upload_explanation_tooltip = + new views::TooltipIcon(l10n_util::GetStringUTF16( + IDS_AUTOFILL_SAVE_CARD_PROMPT_UPLOAD_EXPLANATION_TOOLTIP)); + upload_explanation_tooltip->set_bubble_width(kTooltipBubbleWidth); + upload_explanation_tooltip->set_anchor_point_arrow( + views::BubbleBorder::Arrow::TOP_RIGHT); + return upload_explanation_tooltip; +} + views::View* SaveCardOfferBubbleViews::CreateFootnoteView() { if (controller()->GetLegalMessageLines().empty()) return nullptr;
diff --git a/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.h b/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.h index d3235d7..9e8b84c 100644 --- a/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.h +++ b/chrome/browser/ui/views/autofill/save_card_offer_bubble_views.h
@@ -35,6 +35,7 @@ SaveCardBubbleController* controller); // BubbleDialogDelegateView: + views::View* CreateExtraView() override; views::View* CreateFootnoteView() override; bool Accept() override; base::string16 GetDialogButtonLabel(ui::DialogButton button) const override;
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc index 43bc3f6..21ff876 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -971,12 +971,14 @@ int y = 0; int h = height(); if (index == GetBookmarkButtonCount()) { - if (index == 0) { + if (index != 0) + x = GetBookmarkButton(index - 1)->bounds().right(); + else if (managed_bookmarks_button_->visible()) + x = managed_bookmarks_button_->bounds().right(); + else if (apps_page_shortcut_->visible()) + x = apps_page_shortcut_->bounds().right(); + else x = kBookmarkBarHorizontalMargin; - } else { - x = GetBookmarkButton(index - 1)->x() + - GetBookmarkButton(index - 1)->width(); - } } else { x = GetBookmarkButton(index)->x(); }
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc b/chrome/browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc index 05f2edc5..4b5ad5c 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_sign_in_delegate_browsertest.cc
@@ -43,7 +43,7 @@ return false; #else return AccountConsistencyModeManager::GetMethodForProfile(profile) == - signin::AccountConsistencyMethod::kDiceFixAuthErrors; + signin::AccountConsistencyMethod::kDisabled; #endif }
diff --git a/chrome/browser/ui/views/feature_promos/feature_promo_bubble_view.cc b/chrome/browser/ui/views/feature_promos/feature_promo_bubble_view.cc index c8f22f0..0ad3327 100644 --- a/chrome/browser/ui/views/feature_promos/feature_promo_bubble_view.cc +++ b/chrome/browser/ui/views/feature_promos/feature_promo_bubble_view.cc
@@ -8,11 +8,13 @@ #include "base/strings/string_number_conversions.h" #include "chrome/browser/themes/theme_properties.h" +#include "chrome/browser/ui/views/chrome_layout_provider.h" #include "components/variations/variations_associated_data.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/theme_provider.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/text_utils.h" +#include "ui/views/bubble/bubble_frame_view.h" #include "ui/views/controls/label.h" #include "ui/views/event_monitor.h" #include "ui/views/layout/box_layout.h" @@ -28,6 +30,9 @@ // user stops hovering over it. constexpr base::TimeDelta kDelayShort = base::TimeDelta::FromSeconds(1); +// The insets from the bubble border to the text inside. +constexpr gfx::Insets kBubbleContentsInsets(12, 16); + } // namespace FeaturePromoBubbleView::FeaturePromoBubbleView( @@ -73,7 +78,7 @@ ThemeProperties::COLOR_FEATURE_PROMO_BUBBLE_TEXT); auto box_layout = std::make_unique<views::BoxLayout>( - views::BoxLayout::kVertical, gfx::Insets(), 0); + views::BoxLayout::kVertical, kBubbleContentsInsets, 0); box_layout->set_main_axis_alignment( views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER); box_layout->set_cross_axis_alignment( @@ -90,10 +95,16 @@ set_shadow(views::BubbleBorder::BIG_SHADOW); } + set_margins(gfx::Insets()); + set_title_margins(gfx::Insets()); + set_color(background_color); views::Widget* widget = views::BubbleDialogDelegateView::CreateBubble(this); + GetBubbleFrameView()->bubble_border()->SetCornerRadius( + ChromeLayoutProvider::Get()->GetCornerRadiusMetric(views::EMPHASIS_HIGH)); + widget->Show(); if (activation_action == ActivationAction::ACTIVATE) StartAutoCloseTimer(kDelayDefault);
diff --git a/chrome/browser/ui/views/frame/browser_frame_mac.mm b/chrome/browser/ui/views/frame/browser_frame_mac.mm index 76c5c34..4855004 100644 --- a/chrome/browser/ui/views/frame/browser_frame_mac.mm +++ b/chrome/browser/ui/views/frame/browser_frame_mac.mm
@@ -6,6 +6,7 @@ #import "base/mac/foundation_util.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/apps/app_shim/app_shim_host_mac.h" #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h" #include "chrome/browser/global_keyboard_shortcuts_mac.h" #include "chrome/browser/media/router/media_router_feature.h" @@ -26,7 +27,9 @@ #include "content/public/browser/native_web_keyboard_event.h" #import "ui/base/cocoa/window_size_constants.h" #include "ui/base/l10n/l10n_util.h" +#import "ui/views/cocoa/bridged_native_widget_host_impl.h" #import "ui/views_bridge_mac/bridged_native_widget_impl.h" +#include "ui/views_bridge_mac/mojo/bridge_factory.mojom.h" #include "ui/views_bridge_mac/mojo/bridged_native_widget.mojom.h" #include "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom.h" #import "ui/views_bridge_mac/native_widget_mac_nswindow.h" @@ -34,6 +37,13 @@ namespace { +AppShimHost* GetHostForBrowser(Browser* browser) { + auto* shim_handler = apps::ExtensionAppShimHandler::Get(); + if (!shim_handler) + return nullptr; + return shim_handler->GetHostForBrowser(browser); +} + bool ShouldHandleKeyboardEvent(const content::NativeWebKeyboardEvent& event) { // |event.skip_in_browser| is true when it shouldn't be handled by the browser // if it was ignored by the renderer. See http://crbug.com/25000. @@ -330,20 +340,21 @@ } views::BridgeFactoryHost* BrowserFrameMac::GetBridgeFactoryHost() { - auto* shim_handler = apps::ExtensionAppShimHandler::Get(); - if (!shim_handler) - return nullptr; - return shim_handler->GetViewsBridgeFactoryHostForBrowser( - browser_view_->browser()); + if (auto* host = GetHostForBrowser(browser_view_->browser())) + return host->GetViewsBridgeFactoryHost(); + return nullptr; } void BrowserFrameMac::OnWindowInitialized() { - // TODO(ccameron): Window-level hotkeys need to be wired up across processes. - // https://crbug.com/895168 if (bridge_impl()) { bridge_impl()->SetCommandDispatcher( [[[ChromeCommandDispatcherDelegate alloc] init] autorelease], [[[BrowserWindowCommandHandler alloc] init] autorelease]); + } else { + if (auto* host = GetHostForBrowser(browser_view_->browser())) { + host->GetAppShim()->CreateCommandDispatcherForWidget( + bridge_host()->bridged_native_widget_id()); + } } }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_views.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_views.cc index 3d7e8beb..e7812b6 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_views.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_views.cc
@@ -25,13 +25,11 @@ namespace chrome { -BrowserNonClientFrameView* CreateBrowserNonClientFrameView( +namespace { + +OpaqueBrowserFrameView* CreateOpaqueBrowserFrameView( BrowserFrame* frame, BrowserView* browser_view) { -#if defined(OS_WIN) - if (frame->ShouldUseNativeFrame()) - return new GlassBrowserFrameView(frame, browser_view); -#endif #if BUILDFLAG(ENABLE_NATIVE_WINDOW_NAV_BUTTONS) std::unique_ptr<views::NavButtonProvider> nav_button_provider; #if defined(OS_LINUX) && !defined(OS_CHROMEOS) @@ -52,4 +50,19 @@ new OpaqueBrowserFrameViewLayout()); } +} // namespace + +BrowserNonClientFrameView* CreateBrowserNonClientFrameView( + BrowserFrame* frame, + BrowserView* browser_view) { +#if defined(OS_WIN) + if (frame->ShouldUseNativeFrame()) + return new GlassBrowserFrameView(frame, browser_view); +#endif + OpaqueBrowserFrameView* view = + CreateOpaqueBrowserFrameView(frame, browser_view); + view->InitViews(); + return view; +} + } // namespace chrome
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 561558a2..e260e197 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -127,6 +127,7 @@ #include "components/signin/core/browser/account_consistency_method.h" #include "components/translate/core/browser/language_state.h" #include "components/version_info/channel.h" +#include "components/web_modal/web_contents_modal_dialog_manager.h" #include "content/public/browser/download_manager.h" #include "content/public/browser/keyboard_event_processing_result.h" #include "content/public/browser/notification_service.h" @@ -305,6 +306,15 @@ return false; } +bool IsShowingWebContentsModalDialog(content::WebContents* web_contents) { + if (!web_contents) + return false; + + const web_modal::WebContentsModalDialogManager* manager = + web_modal::WebContentsModalDialogManager::FromWebContents(web_contents); + return manager && manager->IsDialogActive(); +} + // A view targeter for the overlay view, which makes sure the overlay view // itself is never a target for events, but its children (i.e. top_container) // may be. @@ -671,28 +681,13 @@ return; } - // Showing the window doesn't make the browser window active right away. - // This can cause SetFocusToLocationBar() to skip setting focus to the - // location bar. To avoid this we explicilty let SetFocusToLocationBar() - // know that it's ok to steal focus. - force_location_bar_focus_ = true; - - // Setting the focus doesn't work when the window is invisible, so any focus - // initialization that happened before this will be lost. - // - // We really "should" restore the focus whenever the window becomes unhidden, - // but I think initializing is the only time where this can happen where - // there is some focus change we need to pick up, and this is easier than - // plumbing through an un-hide message all the way from the frame. - // - // If we do find there are cases where we need to restore the focus on show, - // that should be added and this should be removed. - RestoreFocus(); + // Only set |restore_focus_on_activation_| when it is not set so that restore + // focus on activation only happen once for the very first Show() call. + if (!restore_focus_on_activation_.has_value()) + restore_focus_on_activation_ = true; frame_->Show(); - force_location_bar_focus_ = false; - browser()->OnWindowDidShow(); MaybeShowInvertBubbleView(this); @@ -1109,7 +1104,7 @@ // even if the widget doens't have a focus. Either cases, we need to ignore // this when the browser window isn't active. #if defined(OS_WIN) || defined(OS_CHROMEOS) - if (!force_location_bar_focus_ && !IsActive()) + if (!IsActive()) return; #endif @@ -2115,10 +2110,21 @@ void BrowserView::OnWidgetActivationChanged(views::Widget* widget, bool active) { if (browser_->window()) { - if (active) + if (active) { + if (restore_focus_on_activation_.has_value() && + restore_focus_on_activation_.value()) { + restore_focus_on_activation_ = false; + + // Set initial focus change on the first activation if there is no + // tab modal dialog. + if (!IsShowingWebContentsModalDialog(GetActiveWebContents())) + RestoreFocus(); + } + BrowserList::SetLastActive(browser_.get()); - else + } else { BrowserList::NotifyBrowserNoLongerActive(browser_.get()); + } } if (!extension_keybinding_registry_ &&
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index f4cba3e..093b829 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -13,6 +13,7 @@ #include "base/compiler_specific.h" #include "base/gtest_prod_util.h" #include "base/macros.h" +#include "base/optional.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "build/build_config.h" @@ -796,9 +797,11 @@ views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_; - // If this flag is set then SetFocusToLocationBar() will set focus to the - // location bar even if the browser window is not active. - bool force_location_bar_focus_ = false; + // Whether OnWidgetActivationChanged should RestoreFocus. If this is set and + // is true, OnWidgetActivationChanged will call RestoreFocus. This is set + // to true when not set in Show() so that RestoreFocus on activation only + // happens for very first Show() calls. + base::Optional<bool> restore_focus_on_activation_; // This is non-null on Chrome OS only. std::unique_ptr<TopControlsSlideController> top_controls_slide_controller_;
diff --git a/chrome/browser/ui/views/frame/browser_view_interactive_uitest.cc b/chrome/browser/ui/views/frame/browser_view_interactive_uitest.cc index 70fd57a..5145e4ab 100644 --- a/chrome/browser/ui/views/frame/browser_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/frame/browser_view_interactive_uitest.cc
@@ -17,6 +17,7 @@ #if defined(OS_MACOSX) #include "chrome/browser/ui/browser_commands_mac.h" +#include "chrome/test/base/interactive_test_utils.h" #endif using views::FocusManager; @@ -28,12 +29,17 @@ BrowserViewTest() = default; ~BrowserViewTest() override = default; - void InitPrefSettings() { + void SetUpOnMainThread() override { #if defined(OS_MACOSX) // Set the preference to true so we expect to see the top view in // fullscreen mode. PrefService* prefs = browser()->profile()->GetPrefs(); prefs->SetBoolean(prefs::kShowFullscreenToolbar, true); + + // Ensure that the browser window is activated. BrowserView::Show calls + // into BridgedNativeWidgetImpl::SetVisibilityState and makeKeyAndOrderFront + // there somehow does not change the window's key status on bot. + ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); #endif } @@ -45,7 +51,6 @@ IN_PROC_BROWSER_TEST_F(BrowserViewTest, FullscreenClearsFocus) { BrowserView* browser_view = static_cast<BrowserView*>(browser()->window()); - InitPrefSettings(); LocationBarView* location_bar_view = browser_view->GetLocationBarView(); FocusManager* focus_manager = browser_view->GetFocusManager(); @@ -64,7 +69,6 @@ // correctly in browser fullscreen mode. IN_PROC_BROWSER_TEST_F(BrowserViewTest, BrowserFullscreenShowTopView) { BrowserView* browser_view = static_cast<BrowserView*>(browser()->window()); - InitPrefSettings(); // The top view should always show up in regular mode. EXPECT_FALSE(browser_view->IsFullscreen());
diff --git a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view.cc b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view.cc index 51d889d..fa7609c 100644 --- a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view.cc
@@ -20,8 +20,7 @@ OpaqueBrowserFrameViewLayout* layout, std::unique_ptr<views::NavButtonProvider> nav_button_provider) : OpaqueBrowserFrameView(frame, browser_view, layout), - nav_button_provider_(std::move(nav_button_provider)) { -} + nav_button_provider_(std::move(nav_button_provider)) {} DesktopLinuxBrowserFrameView::~DesktopLinuxBrowserFrameView() {} @@ -34,6 +33,11 @@ OpaqueBrowserFrameView::Layout(); } +DesktopLinuxBrowserFrameView::FrameButtonStyle +DesktopLinuxBrowserFrameView::GetFrameButtonStyle() const { + return FrameButtonStyle::kImageButton; +} + void DesktopLinuxBrowserFrameView::MaybeUpdateCachedFrameButtonImages() { DrawFrameButtonParams params{ GetTopAreaHeight() - layout()->FrameTopThickness(!IsMaximized()), @@ -52,13 +56,16 @@ for (size_t state = 0; state < views::Button::STATE_COUNT; state++) { views::Button::ButtonState button_state = static_cast<views::Button::ButtonState>(state); - GetButtonFromDisplayType(type)->SetImage( + views::Button* button = GetButtonFromDisplayType(type); + DCHECK_EQ(std::string(views::ImageButton::kViewClassName), + button->GetClassName()); + static_cast<views::ImageButton*>(button)->SetImage( button_state, nav_button_provider_->GetImage(type, button_state)); } } } -views::ImageButton* DesktopLinuxBrowserFrameView::GetButtonFromDisplayType( +views::Button* DesktopLinuxBrowserFrameView::GetButtonFromDisplayType( chrome::FrameButtonDisplayType type) { switch (type) { case chrome::FrameButtonDisplayType::kMinimize:
diff --git a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view.h b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view.h index 7d710d4..c14a9aa 100644 --- a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view.h +++ b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view.h
@@ -21,6 +21,7 @@ protected: // OpaqueBrowserFrameView: void Layout() override; + FrameButtonStyle GetFrameButtonStyle() const override; private: struct DrawFrameButtonParams { @@ -37,8 +38,7 @@ // Returns one of |{minimize,maximize,restore,close}_button_| // corresponding to |type|. - views::ImageButton* GetButtonFromDisplayType( - chrome::FrameButtonDisplayType type); + views::Button* GetButtonFromDisplayType(chrome::FrameButtonDisplayType type); std::unique_ptr<views::NavButtonProvider> nav_button_provider_;
diff --git a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.cc b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.cc index 3126eb1f..7a2c6e2 100644 --- a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.cc +++ b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.cc
@@ -44,9 +44,3 @@ spacing += nav_button_provider_->GetInterNavButtonSpacing(); return spacing; } - -bool DesktopLinuxBrowserFrameViewLayout::ShouldDrawImageMirrored( - views::ImageButton* button, - ButtonAlignment alignment) const { - return false; -}
diff --git a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.h b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.h index bf51f0c..a998bc4c 100644 --- a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.h +++ b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout.h
@@ -23,8 +23,6 @@ int GetWindowCaptionSpacing(views::FrameButton button_id, bool leading_spacing, bool is_leading_button) const override; - bool ShouldDrawImageMirrored(views::ImageButton* button, - ButtonAlignment alignment) const override; private: views::NavButtonProvider* nav_button_provider_;
diff --git a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout_unittest.cc b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout_unittest.cc index e42c5aff..f3785f6 100644 --- a/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout_unittest.cc +++ b/chrome/browser/ui/views/frame/desktop_linux_browser_frame_view_layout_unittest.cc
@@ -131,7 +131,6 @@ auto layout = std::make_unique<DesktopLinuxBrowserFrameViewLayout>( nav_button_provider_.get()); layout->set_delegate(delegate_.get()); - layout->set_extra_caption_y(0); layout->set_forced_window_caption_spacing_for_test(0); widget_ = new views::Widget; widget_->Init(CreateParams(views::Widget::InitParams::TYPE_POPUP));
diff --git a/chrome/browser/ui/views/frame/hosted_app_button_container.cc b/chrome/browser/ui/views/frame/hosted_app_button_container.cc index a2c54a61..8d11494 100644 --- a/chrome/browser/ui/views/frame/hosted_app_button_container.cc +++ b/chrome/browser/ui/views/frame/hosted_app_button_container.cc
@@ -181,15 +181,7 @@ : scoped_widget_observer_(this), browser_view_(browser_view), active_color_(active_color), - inactive_color_(inactive_color), - hosted_app_origin_text_(new HostedAppOriginText(browser_view->browser())), - content_settings_container_(new ContentSettingsContainer(this)), - browser_actions_container_( - new BrowserActionsContainer(browser_view->browser(), - nullptr, - this, - false /* interactive */)), - app_menu_button_(new HostedAppMenuButton(browser_view)) { + inactive_color_(inactive_color) { DCHECK(browser_view_); DCHECK(browser_view_->browser() ->hosted_app_controller() @@ -208,11 +200,13 @@ layout.set_cross_axis_alignment( views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); - AddChildView(hosted_app_origin_text_); + hosted_app_origin_text_ = AddChildView( + std::make_unique<HostedAppOriginText>(browser_view->browser())); + content_settings_container_ = + AddChildView(std::make_unique<ContentSettingsContainer>(this)); views::SetHitTestComponent(content_settings_container_, static_cast<int>(HTCLIENT)); - AddChildView(content_settings_container_); UpdateContentSettingViewsVisibility(); PageActionIconContainerView::Params params; @@ -225,15 +219,19 @@ params.browser = browser_view_->browser(); params.command_updater = browser_view_->browser()->command_controller(); params.page_action_icon_delegate = this; - page_action_icon_container_view_ = new PageActionIconContainerView(params); + page_action_icon_container_view_ = + AddChildView(std::make_unique<PageActionIconContainerView>(params)); views::SetHitTestComponent(page_action_icon_container_view_, static_cast<int>(HTCLIENT)); - AddChildView(page_action_icon_container_view_); + browser_actions_container_ = + AddChildView(std::make_unique<BrowserActionsContainer>( + browser_view->browser(), nullptr, this, false /* interactive */)); views::SetHitTestComponent(browser_actions_container_, static_cast<int>(HTCLIENT)); - AddChildView(browser_actions_container_); - AddChildView(app_menu_button_); + + app_menu_button_ = + AddChildView(std::make_unique<HostedAppMenuButton>(browser_view)); UpdateChildrenColor();
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc index 7b608159..a018152 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -46,6 +46,8 @@ #include "ui/views/resources/grit/views_resources.h" #include "ui/views/views_delegate.h" #include "ui/views/window/frame_background.h" +#include "ui/views/window/frame_caption_button.h" +#include "ui/views/window/vector_icons/vector_icons.h" #include "ui/views/window/window_shape.h" #if defined(OS_LINUX) @@ -119,10 +121,6 @@ OpaqueBrowserFrameViewLayout* layout) : BrowserNonClientFrameView(frame, browser_view), layout_(layout), - minimize_button_(nullptr), - maximize_button_(nullptr), - restore_button_(nullptr), - close_button_(nullptr), window_icon_(nullptr), window_title_(nullptr), frame_background_(new views::FrameBackground()) { @@ -133,34 +131,49 @@ platform_observer_.reset(OpaqueBrowserFrameViewPlatformSpecific::Create( this, layout_, ThemeServiceFactory::GetForProfile(browser_view->browser()->profile()))); +} - minimize_button_ = InitWindowCaptionButton(IDR_MINIMIZE, - IDR_MINIMIZE_H, - IDR_MINIMIZE_P, - IDR_MINIMIZE_BUTTON_MASK, - IDS_ACCNAME_MINIMIZE, - VIEW_ID_MINIMIZE_BUTTON); - maximize_button_ = InitWindowCaptionButton(IDR_MAXIMIZE, - IDR_MAXIMIZE_H, - IDR_MAXIMIZE_P, - IDR_MAXIMIZE_BUTTON_MASK, - IDS_ACCNAME_MAXIMIZE, - VIEW_ID_MAXIMIZE_BUTTON); - restore_button_ = InitWindowCaptionButton(IDR_RESTORE, - IDR_RESTORE_H, - IDR_RESTORE_P, - IDR_RESTORE_BUTTON_MASK, - IDS_ACCNAME_RESTORE, - VIEW_ID_RESTORE_BUTTON); - close_button_ = InitWindowCaptionButton(IDR_CLOSE, - IDR_CLOSE_H, - IDR_CLOSE_P, - IDR_CLOSE_BUTTON_MASK, - IDS_ACCNAME_CLOSE, - VIEW_ID_CLOSE_BUTTON); +OpaqueBrowserFrameView::~OpaqueBrowserFrameView() {} + +void OpaqueBrowserFrameView::InitViews() { + if (GetFrameButtonStyle() == FrameButtonStyle::kMdButton) { + minimize_button_ = CreateFrameCaptionButton( + views::CAPTION_BUTTON_ICON_MINIMIZE, HTMINBUTTON, + views::kWindowControlMinimizeIcon); + maximize_button_ = CreateFrameCaptionButton( + views::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, HTMAXBUTTON, + views::kWindowControlMaximizeIcon); + restore_button_ = + CreateFrameCaptionButton(views::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE, + HTMAXBUTTON, views::kWindowControlRestoreIcon); + close_button_ = + CreateFrameCaptionButton(views::CAPTION_BUTTON_ICON_CLOSE, HTMAXBUTTON, + views::kWindowControlCloseIcon); + } else if (GetFrameButtonStyle() == FrameButtonStyle::kImageButton) { + minimize_button_ = + CreateImageButton(IDR_MINIMIZE, IDR_MINIMIZE_H, IDR_MINIMIZE_P, + IDR_MINIMIZE_BUTTON_MASK, VIEW_ID_MINIMIZE_BUTTON); + maximize_button_ = + CreateImageButton(IDR_MAXIMIZE, IDR_MAXIMIZE_H, IDR_MAXIMIZE_P, + IDR_MAXIMIZE_BUTTON_MASK, VIEW_ID_MAXIMIZE_BUTTON); + restore_button_ = + CreateImageButton(IDR_RESTORE, IDR_RESTORE_H, IDR_RESTORE_P, + IDR_RESTORE_BUTTON_MASK, VIEW_ID_RESTORE_BUTTON); + close_button_ = + CreateImageButton(IDR_CLOSE, IDR_CLOSE_H, IDR_CLOSE_P, + IDR_CLOSE_BUTTON_MASK, VIEW_ID_CLOSE_BUTTON); + } + InitWindowCaptionButton(minimize_button_, IDS_ACCNAME_MINIMIZE, + VIEW_ID_MINIMIZE_BUTTON); + InitWindowCaptionButton(maximize_button_, IDS_ACCNAME_MAXIMIZE, + VIEW_ID_MAXIMIZE_BUTTON); + InitWindowCaptionButton(restore_button_, IDS_ACCNAME_RESTORE, + VIEW_ID_RESTORE_BUTTON); + InitWindowCaptionButton(close_button_, IDS_ACCNAME_CLOSE, + VIEW_ID_CLOSE_BUTTON); // Initializing the TabIconView is expensive, so only do it if we need to. - if (browser_view->ShouldShowWindowIcon()) { + if (browser_view()->ShouldShowWindowIcon()) { window_icon_ = new TabIconView(this, this); window_icon_->set_is_light(true); window_icon_->set_id(VIEW_ID_WINDOW_ICON); @@ -168,8 +181,8 @@ window_icon_->Update(); } - window_title_ = new views::Label(browser_view->GetWindowTitle()); - window_title_->SetVisible(browser_view->ShouldShowWindowTitle()); + window_title_ = new views::Label(browser_view()->GetWindowTitle()); + window_title_->SetVisible(browser_view()->ShouldShowWindowTitle()); // Readability is ensured by |GetReadableFrameForegroundColor()|. window_title_->SetAutoColorReadabilityEnabled(false); window_title_->SetSubpixelRenderingEnabled(false); @@ -178,17 +191,15 @@ AddChildView(window_title_); extensions::HostedAppBrowserController* controller = - browser_view->browser()->hosted_app_controller(); + browser_view()->browser()->hosted_app_controller(); if (controller && controller->ShouldShowHostedAppButtonContainer()) { set_hosted_app_button_container(new HostedAppButtonContainer( - frame, browser_view, GetReadableFrameForegroundColor(kActive), + frame(), browser_view(), GetReadableFrameForegroundColor(kActive), GetReadableFrameForegroundColor(kInactive))); AddChildView(hosted_app_button_container()); } } -OpaqueBrowserFrameView::~OpaqueBrowserFrameView() {} - /////////////////////////////////////////////////////////////////////////////// // OpaqueBrowserFrameView, BrowserNonClientFrameView implementation: @@ -472,6 +483,15 @@ return BrowserNonClientFrameView::EverHasVisibleBackgroundTabShapes(); } +OpaqueBrowserFrameView::FrameButtonStyle +OpaqueBrowserFrameView::GetFrameButtonStyle() const { +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + return FrameButtonStyle::kMdButton; +#else + return FrameButtonStyle::kImageButton; +#endif +} + /////////////////////////////////////////////////////////////////////////////// // OpaqueBrowserFrameView, protected: @@ -481,11 +501,12 @@ if (frame()->IsFullscreen()) return; // Nothing is visible, so don't bother to paint. - SkColor frame_color = GetFrameColor(); + const SkColor frame_color = GetFrameColor(); + const bool active = ShouldPaintAsActive(); window_title_->SetEnabledColor(GetReadableFrameForegroundColor(kUseCurrent)); frame_background_->set_frame_color(frame_color); frame_background_->set_use_custom_frame(frame()->UseCustomFrame()); - frame_background_->set_is_active(ShouldPaintAsActive()); + frame_background_->set_is_active(active); frame_background_->set_incognito(browser_view()->IsIncognito()); frame_background_->set_theme_image(GetFrameImage()); const int y_inset = @@ -496,6 +517,28 @@ frame_background_->set_theme_overlay_image(GetFrameOverlayImage()); frame_background_->set_top_area_height(GetTopAreaHeight()); + if (GetFrameButtonStyle() == FrameButtonStyle::kMdButton) { + views::FrameCaptionButton::ColorMode color_mode = + views::FrameCaptionButton::ColorMode::kDefault; + extensions::HostedAppBrowserController* controller = + browser_view()->browser()->hosted_app_controller(); + if (controller) { + color_mode = controller->GetThemeColor() + ? views::FrameCaptionButton::ColorMode::kThemed + : views::FrameCaptionButton::ColorMode::kDefault; + } + for (auto* button : + {minimize_button_, maximize_button_, restore_button_, close_button_}) { + DCHECK_EQ(std::string(views::FrameCaptionButton::kViewClassName), + button->GetClassName()); + views::FrameCaptionButton* frame_caption_button = + static_cast<views::FrameCaptionButton*>(button); + frame_caption_button->set_paint_as_active(active); + frame_caption_button->SetBackgroundColor(frame_color); + frame_caption_button->SetColorMode(color_mode); + } + } + if (IsFrameCondensed()) PaintMaximizedFrameBorder(canvas); else @@ -522,13 +565,22 @@ /////////////////////////////////////////////////////////////////////////////// // OpaqueBrowserFrameView, private: -views::ImageButton* OpaqueBrowserFrameView::InitWindowCaptionButton( - int normal_image_id, - int hot_image_id, - int pushed_image_id, - int mask_image_id, - int accessibility_string_id, - ViewID view_id) { +views::Button* OpaqueBrowserFrameView::CreateFrameCaptionButton( + views::CaptionButtonIcon icon_type, + int ht_component, + const gfx::VectorIcon& icon_image) { + views::FrameCaptionButton* button = + new views::FrameCaptionButton(this, icon_type, ht_component); + button->SetImage(button->icon(), views::FrameCaptionButton::ANIMATE_NO, + icon_image); + return button; +} + +views::Button* OpaqueBrowserFrameView::CreateImageButton(int normal_image_id, + int hot_image_id, + int pushed_image_id, + int mask_image_id, + ViewID view_id) { views::ImageButton* button = new views::ImageButton(this); const ui::ThemeProvider* tp = frame()->GetThemeProvider(); button->SetImage(views::Button::STATE_NORMAL, @@ -538,24 +590,31 @@ button->SetImage(views::Button::STATE_PRESSED, tp->GetImageSkiaNamed(pushed_image_id)); if (browser_view()->IsBrowserTypeNormal()) { - // Get a custom processed version of the theme's background image so that it - // appears to draw contiguously across all of the caption buttons. + // Get a custom processed version of the theme's background image so + // that it appears to draw contiguously across all of the caption + // buttons. const gfx::Size normal_image_size = GetThemeImageSize(normal_image_id); const gfx::ImageSkia processed_bg_image = GetProcessedBackgroundImageForCaptionButon(view_id, normal_image_size); // SetBackgroundImage immediately uses the provided ImageSkia pointer - // (&processed_bg_image) to create a local copy, so it's safe for this to be - // locally scoped. + // (&processed_bg_image) to create a local copy, so it's safe for this + // to be locally scoped. button->SetBackgroundImage( tp->GetColor(ThemeProperties::COLOR_BUTTON_BACKGROUND), (processed_bg_image.isNull() ? nullptr : &processed_bg_image), tp->GetImageSkiaNamed(mask_image_id)); } + return button; +} + +void OpaqueBrowserFrameView::InitWindowCaptionButton( + views::Button* button, + int accessibility_string_id, + ViewID view_id) { button->SetAccessibleName(l10n_util::GetStringUTF16(accessibility_string_id)); button->set_id(view_id); AddChildView(button); - return button; } gfx::Size OpaqueBrowserFrameView::GetThemeImageSize(int image_id) {
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h index 856e7ab..22d7e04 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
@@ -16,6 +16,7 @@ #include "ui/views/controls/button/button.h" #include "ui/views/controls/button/menu_button_listener.h" #include "ui/views/linux_ui/linux_ui.h" +#include "ui/views/window/caption_button_types.h" #include "ui/views/window/non_client_view.h" class BrowserView; @@ -27,8 +28,12 @@ enum class FrameButtonDisplayType; } +namespace gfx { +struct VectorIcon; +} + namespace views { -class ImageButton; +class Button; class FrameBackground; class Label; } @@ -47,6 +52,11 @@ OpaqueBrowserFrameViewLayout* layout); ~OpaqueBrowserFrameView() override; + // Creates and adds child views. Should be called after + // OpaqueBrowserFrameView is constructed. This is not called from the + // constructor because it relies on virtual method calls. + void InitViews(); + // BrowserNonClientFrameView: gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const override; int GetTopInset(bool restored) const override; @@ -81,7 +91,7 @@ bool ShouldTabIconViewAnimate() const override; gfx::ImageSkia GetFaviconForTabIconView() override; - // OpaqueBrowserFrameViewLayoutDelegate implementation: + // OpaqueBrowserFrameViewLayoutDelegate: bool ShouldShowWindowIcon() const override; bool ShouldShowWindowTitle() const override; base::string16 GetWindowTitle() const override; @@ -99,12 +109,13 @@ bool UseCustomFrame() const override; bool IsFrameCondensed() const override; bool EverHasVisibleBackgroundTabShapes() const override; + FrameButtonStyle GetFrameButtonStyle() const override; protected: - views::ImageButton* minimize_button() const { return minimize_button_; } - views::ImageButton* maximize_button() const { return maximize_button_; } - views::ImageButton* restore_button() const { return restore_button_; } - views::ImageButton* close_button() const { return close_button_; } + views::Button* minimize_button() const { return minimize_button_; } + views::Button* maximize_button() const { return maximize_button_; } + views::Button* restore_button() const { return restore_button_; } + views::Button* close_button() const { return close_button_; } // views::View: void OnPaint(gfx::Canvas* canvas) override; @@ -117,14 +128,25 @@ private: friend class HostedAppOpaqueBrowserFrameViewTest; - // Creates, adds and returns a new image button with |this| as its listener. + // Creates and returns a FrameCaptionButton with |this| as its listener. // Memory is owned by the caller. - views::ImageButton* InitWindowCaptionButton(int normal_image_id, - int hot_image_id, - int pushed_image_id, - int mask_image_id, - int accessibility_string_id, - ViewID view_id); + views::Button* CreateFrameCaptionButton(views::CaptionButtonIcon icon_type, + int ht_component, + const gfx::VectorIcon& icon_image); + + // Creates and returns an ImageButton with |this| as its listener. + // Memory is owned by the caller. + views::Button* CreateImageButton(int normal_image_id, + int hot_image_id, + int pushed_image_id, + int mask_image_id, + ViewID view_id); + + // Initializes state on |button| common to both FrameCaptionButtons and + // ImageButtons. + void InitWindowCaptionButton(views::Button* button, + int accessibility_string_id, + ViewID view_id); // Returns the size of the custom image specified by |image_id| in the frame's // ThemeProvider. @@ -177,10 +199,10 @@ OpaqueBrowserFrameViewLayout* layout_; // Window controls. - views::ImageButton* minimize_button_; - views::ImageButton* maximize_button_; - views::ImageButton* restore_button_; - views::ImageButton* close_button_; + views::Button* minimize_button_; + views::Button* maximize_button_; + views::Button* restore_button_; + views::Button* close_button_; // The window icon and title. TabIconView* window_icon_;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc index 4ee8653..d33ce22 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
@@ -17,18 +17,13 @@ #include "ui/gfx/font.h" #include "ui/views/controls/button/image_button.h" #include "ui/views/controls/label.h" +#include "ui/views/window/caption_button_layout_constants.h" +#include "ui/views/window/frame_caption_button.h" namespace { constexpr int kCaptionButtonHeight = 18; -#if defined(OS_LINUX) && !defined(OS_CHROMEOS) -// Default spacing around window caption buttons. -constexpr int kCaptionButtonSpacing = 2; -#else -constexpr int kCaptionButtonSpacing = 0; -#endif - } // namespace /////////////////////////////////////////////////////////////////////////////// @@ -69,7 +64,6 @@ minimum_size_for_buttons_(0), placed_leading_button_(false), placed_trailing_button_(false), - extra_caption_y_(kCaptionButtonSpacing), forced_window_caption_spacing_(-1), minimize_button_(nullptr), maximize_button_(nullptr), @@ -180,10 +174,9 @@ // Maximized buttons start at window top, since the window has no border. This // offset is for the image (the actual clickable bounds extend all the way to // the top to take Fitts' Law into account). - const int frame = !restored && delegate_->IsFrameCondensed() - ? FrameBorderThickness(false) - : views::NonClientFrameView::kFrameShadowThickness; - return frame + extra_caption_y_; + return !restored && delegate_->IsFrameCondensed() + ? FrameBorderThickness(false) + : views::NonClientFrameView::kFrameShadowThickness; } int OpaqueBrowserFrameViewLayout::CaptionButtonY( @@ -239,7 +232,6 @@ } if (forced_window_caption_spacing_ >= 0) return forced_window_caption_spacing_; - return kCaptionButtonSpacing; } return 0; } @@ -272,17 +264,10 @@ (restored || !delegate_->IsFrameCondensed()); } -bool OpaqueBrowserFrameViewLayout::ShouldDrawImageMirrored( - views::ImageButton* button, - ButtonAlignment alignment) const { - return alignment == ALIGN_LEADING && !placed_leading_button_ && - button == close_button_; -} - /////////////////////////////////////////////////////////////////////////////// // OpaqueBrowserFrameViewLayout, private: -void OpaqueBrowserFrameViewLayout::LayoutWindowControls(views::View* host) { +void OpaqueBrowserFrameViewLayout::LayoutWindowControls() { // Keep a list of all buttons that we don't show. std::vector<views::FrameButton> buttons_not_shown; buttons_not_shown.push_back(views::FRAME_BUTTON_MAXIMIZE); @@ -291,12 +276,12 @@ if (delegate_->ShouldShowCaptionButtons()) { for (const auto& button : leading_buttons_) { - ConfigureButton(host, button, ALIGN_LEADING); + ConfigureButton(button, ALIGN_LEADING); base::Erase(buttons_not_shown, button); } for (const auto& button : base::Reversed(trailing_buttons_)) { - ConfigureButton(host, button, ALIGN_TRAILING); + ConfigureButton(button, ALIGN_TRAILING); base::Erase(buttons_not_shown, button); } } @@ -305,7 +290,7 @@ HideButton(button); } -void OpaqueBrowserFrameViewLayout::LayoutTitleBar(views::View* host) { +void OpaqueBrowserFrameViewLayout::LayoutTitleBar() { bool use_hidden_icon_location = true; int size = delegate_->GetIconSize(); @@ -379,32 +364,31 @@ } } -void OpaqueBrowserFrameViewLayout::ConfigureButton(views::View* host, - views::FrameButton button_id, +void OpaqueBrowserFrameViewLayout::ConfigureButton(views::FrameButton button_id, ButtonAlignment alignment) { switch (button_id) { case views::FRAME_BUTTON_MINIMIZE: { minimize_button_->SetVisible(true); - SetBoundsForButton(button_id, host, minimize_button_, alignment); + SetBoundsForButton(button_id, minimize_button_, alignment); break; } case views::FRAME_BUTTON_MAXIMIZE: { // When the window is restored, we show a maximized button; otherwise, we // show a restore button. bool is_restored = !delegate_->IsMaximized() && !delegate_->IsMinimized(); - views::ImageButton* invisible_button = is_restored ? - restore_button_ : maximize_button_; + views::Button* invisible_button = + is_restored ? restore_button_ : maximize_button_; invisible_button->SetVisible(false); - views::ImageButton* visible_button = is_restored ? - maximize_button_ : restore_button_; + views::Button* visible_button = + is_restored ? maximize_button_ : restore_button_; visible_button->SetVisible(true); - SetBoundsForButton(button_id, host, visible_button, alignment); + SetBoundsForButton(button_id, visible_button, alignment); break; } case views::FRAME_BUTTON_CLOSE: { close_button_->SetVisible(true); - SetBoundsForButton(button_id, host, close_button_, alignment); + SetBoundsForButton(button_id, close_button_, alignment); break; } } @@ -427,28 +411,36 @@ void OpaqueBrowserFrameViewLayout::SetBoundsForButton( views::FrameButton button_id, - views::View* host, - views::ImageButton* button, + views::Button* button, ButtonAlignment alignment) { - int caption_y = CaptionButtonY(GetButtonDisplayType(button_id), false); - - gfx::Size button_size = button->GetPreferredSize(); - - button->SetImageAlignment( - (alignment == ALIGN_LEADING) ? - views::ImageButton::ALIGN_RIGHT : views::ImageButton::ALIGN_LEFT, - views::ImageButton::ALIGN_BOTTOM); + const int caption_y = CaptionButtonY(GetButtonDisplayType(button_id), false); // There should always be the same number of non-shadow pixels visible to the // side of the caption buttons. In maximized mode we extend buttons to the // screen top and the rightmost button to the screen right (or leftmost button // to the screen left, for left-aligned buttons) to obey Fitts' Law. - bool is_frame_condensed = delegate_->IsFrameCondensed(); + const bool is_frame_condensed = delegate_->IsFrameCondensed(); - // When we are the first button on the leading side and are the close - // button, we must flip ourselves, because the close button assets have - // a little notch to fit in the rounded frame. - button->SetDrawImageMirrored(ShouldDrawImageMirrored(button, alignment)); + gfx::Size button_size = button->GetPreferredSize(); + if (delegate_->GetFrameButtonStyle() == + OpaqueBrowserFrameViewLayoutDelegate::FrameButtonStyle::kMdButton) { + DCHECK_EQ(std::string(views::FrameCaptionButton::kViewClassName), + button->GetClassName()); + button_size = GetCaptionButtonLayoutSize( + is_frame_condensed + ? views::CaptionButtonLayoutSize::kBrowserCaptionMaximized + : views::CaptionButtonLayoutSize::kBrowserCaptionRestored); + button->SetPreferredSize(button_size); + } else if (delegate_->GetFrameButtonStyle() == + OpaqueBrowserFrameViewLayoutDelegate::FrameButtonStyle:: + kImageButton) { + DCHECK_EQ(std::string(views::ImageButton::kViewClassName), + button->GetClassName()); + static_cast<views::ImageButton*>(button)->SetImageAlignment( + (alignment == ALIGN_LEADING) ? views::ImageButton::ALIGN_RIGHT + : views::ImageButton::ALIGN_LEFT, + views::ImageButton::ALIGN_BOTTOM); + } TopAreaPadding top_area_padding = GetTopAreaPadding(); @@ -516,32 +508,16 @@ // all the views which are part of it. switch (id) { case VIEW_ID_MINIMIZE_BUTTON: - if (view) { - DCHECK_EQ(std::string(views::ImageButton::kViewClassName), - view->GetClassName()); - } - minimize_button_ = static_cast<views::ImageButton*>(view); + minimize_button_ = static_cast<views::Button*>(view); break; case VIEW_ID_MAXIMIZE_BUTTON: - if (view) { - DCHECK_EQ(std::string(views::ImageButton::kViewClassName), - view->GetClassName()); - } - maximize_button_ = static_cast<views::ImageButton*>(view); + maximize_button_ = static_cast<views::Button*>(view); break; case VIEW_ID_RESTORE_BUTTON: - if (view) { - DCHECK_EQ(std::string(views::ImageButton::kViewClassName), - view->GetClassName()); - } - restore_button_ = static_cast<views::ImageButton*>(view); + restore_button_ = static_cast<views::Button*>(view); break; case VIEW_ID_CLOSE_BUTTON: - if (view) { - DCHECK_EQ(std::string(views::ImageButton::kViewClassName), - view->GetClassName()); - } - close_button_ = static_cast<views::ImageButton*>(view); + close_button_ = static_cast<views::Button*>(view); break; case VIEW_ID_WINDOW_ICON: window_icon_ = view; @@ -584,8 +560,8 @@ placed_leading_button_ = false; placed_trailing_button_ = false; - LayoutWindowControls(host); - LayoutTitleBar(host); + LayoutWindowControls(); + LayoutTitleBar(); // Any buttons/icon/title were laid out based on the frame border thickness, // but the tabstrip bounds need to be based on the non-client border thickness
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h index 0bbc661..1e678ff0c 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h
@@ -17,7 +17,7 @@ class OpaqueBrowserFrameViewLayoutDelegate; namespace views { -class ImageButton; +class Button; class Label; } @@ -116,10 +116,6 @@ bool leading_spacing, bool is_leading_button) const; - void set_extra_caption_y(int extra_caption_y) { - extra_caption_y_ = extra_caption_y; - } - void set_forced_window_caption_spacing_for_test( int forced_window_caption_spacing) { forced_window_caption_spacing_ = forced_window_caption_spacing; @@ -156,9 +152,6 @@ virtual TopAreaPadding GetTopAreaPadding(bool has_leading_buttons, bool has_trailing_buttons) const; - virtual bool ShouldDrawImageMirrored(views::ImageButton* button, - ButtonAlignment alignment) const; - OpaqueBrowserFrameViewLayoutDelegate* delegate_; // The leading and trailing x positions of the empty space available for @@ -172,20 +165,17 @@ private: // Layout various sub-components of this view. - void LayoutWindowControls(views::View* host); - void LayoutTitleBar(views::View* host); + void LayoutWindowControls(); + void LayoutTitleBar(); - void ConfigureButton(views::View* host, - views::FrameButton button_id, - ButtonAlignment align); + void ConfigureButton(views::FrameButton button_id, ButtonAlignment align); // Sets the visibility of all buttons associated with |button_id| to false. void HideButton(views::FrameButton button_id); // Adds a window caption button to either the leading or trailing side. void SetBoundsForButton(views::FrameButton button_id, - views::View* host, - views::ImageButton* button, + views::Button* button, ButtonAlignment align); // Internal implementation of ViewAdded() and ViewRemoved(). @@ -216,19 +206,15 @@ bool placed_leading_button_; bool placed_trailing_button_; - // Extra offset from the top of the frame to the top of the window control - // buttons. Configurable based on platform and whether we are under test. - int extra_caption_y_; - // Extra offset between the individual window caption buttons. Set only in // testing, otherwise, its value will be -1. int forced_window_caption_spacing_; // Window controls. - views::ImageButton* minimize_button_; - views::ImageButton* maximize_button_; - views::ImageButton* restore_button_; - views::ImageButton* close_button_; + views::Button* minimize_button_; + views::Button* maximize_button_; + views::Button* restore_button_; + views::Button* close_button_; views::View* window_icon_; views::Label* window_title_;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.cc new file mode 100644 index 0000000..c93e0b8 --- /dev/null +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.cc
@@ -0,0 +1,10 @@ +// 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 "chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h" + +OpaqueBrowserFrameViewLayoutDelegate::FrameButtonStyle +OpaqueBrowserFrameViewLayoutDelegate::GetFrameButtonStyle() const { + return FrameButtonStyle::kImageButton; +}
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h index 178bb9e1..1df5630c 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_delegate.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_UI_VIEWS_FRAME_OPAQUE_BROWSER_FRAME_VIEW_LAYOUT_DELEGATE_H_ #define CHROME_BROWSER_UI_VIEWS_FRAME_OPAQUE_BROWSER_FRAME_VIEW_LAYOUT_DELEGATE_H_ +#include "base/strings/string16.h" + namespace gfx { class Size; } @@ -13,6 +15,14 @@ // Browser{,Frame,View}. class OpaqueBrowserFrameViewLayoutDelegate { public: + enum class FrameButtonStyle { + // MD-styled button with a vector image, of class FrameCaptionButton. + kMdButton, + + // Regular old ImageButton. + kImageButton, + }; + // Controls the visual placement of the window icon/title in non-tabstrip // mode. virtual bool ShouldShowWindowIcon() const = 0; @@ -62,6 +72,9 @@ // for either active or inactive windows. virtual bool EverHasVisibleBackgroundTabShapes() const = 0; + // Indicates the type of the frame buttons. + virtual FrameButtonStyle GetFrameButtonStyle() const; + protected: virtual ~OpaqueBrowserFrameViewLayoutDelegate() {} };
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc index b6df427..bbe047e 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
@@ -96,7 +96,6 @@ delegate_.reset(new TestLayoutDelegate); auto layout = std::make_unique<OpaqueBrowserFrameViewLayout>(); layout->set_delegate(delegate_.get()); - layout->set_extra_caption_y(0); layout->set_forced_window_caption_spacing_for_test(0); widget_ = new views::Widget; widget_->Init(CreateParams(views::Widget::InitParams::TYPE_POPUP)); @@ -347,18 +346,6 @@ } } -TEST_F(OpaqueBrowserFrameViewLayoutTest, MaximizedWithYOffset) { - // Tests the layout of a basic chrome window with the caption buttons slightly - // offset from the top of the screen (as they are on Linux). - layout_manager_->set_extra_caption_y(2); - delegate_->set_maximized(true); - root_view_->Layout(); - - ExpectCaptionButtons(false, 2); - ExpectTabStripAndMinimumSize(false); - ExpectWindowIcon(false); -} - TEST_F(OpaqueBrowserFrameViewLayoutTest, WindowButtonsOnLeft) { // Tests the layout of a chrome window with caption buttons on the left. std::vector<views::FrameButton> leading_buttons;
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index fe7c0dd2..5660ad2 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -239,7 +239,7 @@ page_action_icons_.push_back(translate_icon_view_); if (browser_) { local_card_migration_icon_view_ = new autofill::LocalCardMigrationIconView( - command_updater(), browser_, this); + command_updater(), browser_, this, font_list); page_action_icons_.push_back(local_card_migration_icon_view_); }
diff --git a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc index a162e6b..2504077b 100644 --- a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc +++ b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc
@@ -32,8 +32,10 @@ MediaRouterDialogControllerViews::~MediaRouterDialogControllerViews() { Reset(); - if (CastDialogView::GetCurrentDialogWidget()) - CastDialogView::GetCurrentDialogWidget()->RemoveObserver(this); + if (dialog_widget_) { + dialog_widget_->RemoveObserver(this); + dialog_widget_ = nullptr; + } } // static @@ -64,7 +66,8 @@ CastDialogView::ShowDialogTopCentered(ui_.get(), browser, dialog_creation_time); } - CastDialogView::GetCurrentDialogWidget()->AddObserver(this); + dialog_widget_ = CastDialogView::GetCurrentDialogWidget(); + dialog_widget_->AddObserver(this); if (dialog_creation_callback_) dialog_creation_callback_.Run(); } @@ -86,13 +89,10 @@ } void MediaRouterDialogControllerViews::OnWidgetClosing(views::Widget* widget) { - DCHECK_EQ(CastDialogView::GetCurrentDialogWidget(), widget); + DCHECK_EQ(dialog_widget_, widget); Reset(); -} - -void MediaRouterDialogControllerViews::OnWidgetDestroying( - views::Widget* widget) { - widget->RemoveObserver(this); + dialog_widget_->RemoveObserver(this); + dialog_widget_ = nullptr; } void MediaRouterDialogControllerViews::SetDialogCreationCallbackForTesting(
diff --git a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.h b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.h index 4b10303..004353a 100644 --- a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.h +++ b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.h
@@ -34,7 +34,6 @@ // views::WidgetObserver: void OnWidgetClosing(views::Widget* widget) override; - void OnWidgetDestroying(views::Widget* widget) override; // Sets a callback to be called whenever a dialog is created. void SetDialogCreationCallbackForTesting(base::RepeatingClosure callback); @@ -53,6 +52,10 @@ base::RepeatingClosure dialog_creation_callback_; + // This is not null while there is a dialog shown and |this| is observing the + // widget. + views::Widget* dialog_widget_ = nullptr; + WEB_CONTENTS_USER_DATA_KEY_DECL(); DISALLOW_COPY_AND_ASSIGN(MediaRouterDialogControllerViews);
diff --git a/chrome/browser/ui/views/page_action/zoom_view.cc b/chrome/browser/ui/views/page_action/zoom_view.cc index a5bd5f91..ed140cfe 100644 --- a/chrome/browser/ui/views/page_action/zoom_view.cc +++ b/chrome/browser/ui/views/page_action/zoom_view.cc
@@ -41,7 +41,7 @@ if (can_show_bubble) return true; - if (ZoomBubbleView::GetZoomBubble()) + if (HasAssociatedBubble()) return true; DCHECK(GetWebContents()); @@ -50,6 +50,18 @@ return zoom_controller && !zoom_controller->IsAtDefaultZoom(); } +bool ZoomView::HasAssociatedBubble() const { + if (!GetBubble()) + return false; + + // Bubbles may be hosted in their own widget so use their anchor view as a + // more reliable way of determining whether this icon belongs to the same + // browser window. + if (!GetBubble()->GetAnchorView()) + return false; + return GetBubble()->GetAnchorView()->GetWidget() == GetWidget(); +} + void ZoomView::ZoomChangedForActiveTab(bool can_show_bubble) { content::WebContents* web_contents = GetWebContents(); if (!web_contents) @@ -80,7 +92,8 @@ } } else { SetVisible(false); - ZoomBubbleView::CloseCurrentBubble(); + if (HasAssociatedBubble()) + ZoomBubbleView::CloseCurrentBubble(); } }
diff --git a/chrome/browser/ui/views/page_action/zoom_view.h b/chrome/browser/ui/views/page_action/zoom_view.h index 1b53112..b007e15 100644 --- a/chrome/browser/ui/views/page_action/zoom_view.h +++ b/chrome/browser/ui/views/page_action/zoom_view.h
@@ -34,6 +34,7 @@ private: bool ShouldBeVisible(bool can_show_bubble) const; + bool HasAssociatedBubble() const; // The delegate used to get whether omnibox input is in progress. LocationBarView::Delegate* location_bar_delegate_;
diff --git a/chrome/browser/ui/views/page_action/zoom_view_browsertest.cc b/chrome/browser/ui/views/page_action/zoom_view_browsertest.cc new file mode 100644 index 0000000..915cdb5 --- /dev/null +++ b/chrome/browser/ui/views/page_action/zoom_view_browsertest.cc
@@ -0,0 +1,50 @@ +// 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 "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/frame/toolbar_button_provider.h" +#include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h" +#include "chrome/browser/ui/views/page_action/page_action_icon_container_view.h" +#include "chrome/test/base/in_process_browser_test.h" + +using ZoomViewBrowserTest = InProcessBrowserTest; + +// https://crbug.com/900134: Zoom icons in inactive windows should not be +// visible when zoom is reset back to default. +IN_PROC_BROWSER_TEST_F(ZoomViewBrowserTest, SharedPageVisibility) { + views::View* zoom_icon = + BrowserView::GetBrowserViewForBrowser(browser()) + ->toolbar_button_provider() + ->GetPageActionIconContainerView() + ->GetPageActionIconView(PageActionIconType::kZoom); + views::View* second_zoom_icon = + BrowserView::GetBrowserViewForBrowser(CreateBrowser(browser()->profile())) + ->toolbar_button_provider() + ->GetPageActionIconContainerView() + ->GetPageActionIconView(PageActionIconType::kZoom); + + // Initially no icon. + EXPECT_FALSE(ZoomBubbleView::GetZoomBubble()); + EXPECT_FALSE(zoom_icon->visible()); + EXPECT_FALSE(second_zoom_icon->visible()); + + // Zooming in one browser should show the icon in all browsers on the same + // URL. + chrome::Zoom(browser(), content::PAGE_ZOOM_IN); + EXPECT_TRUE(ZoomBubbleView::GetZoomBubble()); + EXPECT_TRUE(zoom_icon->visible()); + EXPECT_TRUE(second_zoom_icon->visible()); + + ZoomBubbleView::CloseCurrentBubble(); + EXPECT_FALSE(ZoomBubbleView::GetZoomBubble()); + + // Clearing the zoom should clear the icon for all browsers on the URL except + // the one where the interaction occured because the bubble is showing there. + chrome::Zoom(browser(), content::PAGE_ZOOM_RESET); + EXPECT_TRUE(ZoomBubbleView::GetZoomBubble()); + EXPECT_TRUE(zoom_icon->visible()); + EXPECT_FALSE(second_zoom_icon->visible()); +}
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_icon_views.cc b/chrome/browser/ui/views/passwords/manage_passwords_icon_views.cc index 5b370213..16091d6 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_icon_views.cc +++ b/chrome/browser/ui/views/passwords/manage_passwords_icon_views.cc
@@ -79,20 +79,6 @@ return result; } -bool ManagePasswordsIconViews::OnKeyPressed(const ui::KeyEvent& event) { - // Space is always ignored because otherwise the bubble appears with the - // default button down. Releasing the space is equivalent to clicking this - // button. - if (event.key_code() == ui::VKEY_SPACE) - return true; - if (event.key_code() == ui::VKEY_RETURN && IsBubbleShowing()) { - // If the bubble's open, the icon should transfer its focus to the bubble. - // If it still somehow got this key event, the bubble shouldn't be reopened. - return true; - } - return PageActionIconView::OnKeyPressed(event); -} - const gfx::VectorIcon& ManagePasswordsIconViews::GetVectorIcon() const { return kKeyIcon; }
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_icon_views.h b/chrome/browser/ui/views/passwords/manage_passwords_icon_views.h index 06bfdc30..fa76ea0 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_icon_views.h +++ b/chrome/browser/ui/views/passwords/manage_passwords_icon_views.h
@@ -32,7 +32,6 @@ bool Update() override; void OnExecuting(PageActionIconView::ExecuteSource source) override; bool OnMousePressed(const ui::MouseEvent& event) override; - bool OnKeyPressed(const ui::KeyEvent& event) override; const gfx::VectorIcon& GetVectorIcon() const override; base::string16 GetTextForTooltipAndAccessibleName() const override;
diff --git a/chrome/browser/ui/views/passwords/password_items_view.cc b/chrome/browser/ui/views/passwords/password_items_view.cc index e06f443..a14df04e 100644 --- a/chrome/browser/ui/views/passwords/password_items_view.cc +++ b/chrome/browser/ui/views/passwords/password_items_view.cc
@@ -128,9 +128,8 @@ base::string16 text = form.federation_origin.opaque() ? form.password_value - : l10n_util::GetStringFUTF16( - federation_message_id, - base::UTF8ToUTF16(form.federation_origin.host())); + : l10n_util::GetStringFUTF16(federation_message_id, + GetDisplayFederation(form)); auto label = std::make_unique<views::Label>(text, CONTEXT_BODY_TEXT_LARGE, STYLE_SECONDARY); label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
diff --git a/chrome/browser/ui/views/passwords/password_pending_view.cc b/chrome/browser/ui/views/passwords/password_pending_view.cc index 5fa8190..21c4b5c 100644 --- a/chrome/browser/ui/views/passwords/password_pending_view.cc +++ b/chrome/browser/ui/views/passwords/password_pending_view.cc
@@ -110,10 +110,13 @@ password_label->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT); int labels_width = std::max(username_label->GetPreferredSize().width(), password_label->GetPreferredSize().width()); + int fields_height = std::max(username_field->GetPreferredSize().height(), + password_field->GetPreferredSize().height()); layout->AddView(username_label.release(), 1, 1, views::GridLayout::LEADING, views::GridLayout::FILL, labels_width, 0); - layout->AddView(username_field); + layout->AddView(username_field, 1, 1, views::GridLayout::FILL, + views::GridLayout::FILL, 0, fields_height); layout->AddPaddingRow(views::GridLayout::kFixedSize, ChromeLayoutProvider::Get()->GetDistanceMetric( @@ -127,7 +130,8 @@ layout->StartRow(views::GridLayout::kFixedSize, type); layout->AddView(password_label.release(), 1, 1, views::GridLayout::LEADING, views::GridLayout::FILL, labels_width, 0); - layout->AddView(password_field); + layout->AddView(password_field, 1, 1, views::GridLayout::FILL, + views::GridLayout::FILL, 0, fields_height); // The eye icon is also added to the layout if it was passed. if (password_view_button) { layout->AddView(password_view_button); @@ -419,6 +423,11 @@ return true; } +void PasswordPendingView::AddedToWidget() { + static_cast<views::Label*>(GetBubbleFrameView()->title()) + ->SetAllowCharacterBreak(true); +} + void PasswordPendingView::TogglePasswordVisibility() { if (!are_passwords_revealed_ && !model()->RevealPasswords()) return;
diff --git a/chrome/browser/ui/views/passwords/password_pending_view.h b/chrome/browser/ui/views/passwords/password_pending_view.h index 30b58341..7933911 100644 --- a/chrome/browser/ui/views/passwords/password_pending_view.h +++ b/chrome/browser/ui/views/passwords/password_pending_view.h
@@ -57,6 +57,9 @@ bool Cancel() override; bool Close() override; + // View: + void AddedToWidget() override; + void TogglePasswordVisibility(); void UpdateUsernameAndPasswordInModel(); void ReplaceWithPromo();
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc index c57a3f0d..1a45401 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -59,7 +59,6 @@ #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" -#include "components/browser_sync/profile_sync_service.h" #include "components/prefs/pref_service.h" #include "components/signin/core/browser/account_tracker_service.h" #include "components/signin/core/browser/gaia_cookie_manager_service.h" @@ -69,6 +68,7 @@ #include "components/signin/core/browser/signin_manager.h" #include "components/signin/core/browser/signin_metrics.h" #include "components/signin/core/browser/signin_pref_names.h" +#include "components/sync/driver/sync_service_utils.h" #include "components/vector_icons/vector_icons.h" #include "content/public/browser/render_widget_host_view.h" #include "services/identity/public/cpp/identity_manager.h" @@ -672,8 +672,7 @@ break; case sync_ui_util::UNRECOVERABLE_ERROR: if (ProfileSyncServiceFactory::GetForProfile(browser_->profile())) { - browser_sync::ProfileSyncService::SyncEvent( - browser_sync::ProfileSyncService::STOP_FROM_OPTIONS); + syncer::RecordSyncEvent(syncer::STOP_FROM_OPTIONS); } // GetPrimaryAccountMutator() might return nullptr on some platforms.
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc index eaed0bf..e90717a6 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc
@@ -487,7 +487,6 @@ // Shows the |ProfileChooserView| when a supervised user is the active profile. IN_PROC_BROWSER_TEST_F(ProfileChooserViewExtensionsTest, DISABLED_InvokeUi_SupervisedUser) { - ScopedAccountConsistencyDiceFixAuthErrors scoped_account_consistency; ShowAndVerifyUi(); }
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc index 05653070..10742cd 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -1479,7 +1479,7 @@ } // namespace -#if defined(OS_CHROMEOS) || defined(OS_LINUX) +#if !defined(OS_CHROMEOS) && defined(OS_LINUX) // TODO(sky,sad): Disabled as it fails due to resize locks with a real // compositor. crbug.com/331924 #define MAYBE_DragAllToSeparateWindow DISABLED_DragAllToSeparateWindow @@ -1551,7 +1551,7 @@ } // namespace -#if defined(OS_CHROMEOS) || defined(OS_LINUX) +#if !defined(OS_CHROMEOS) && defined(OS_LINUX) // TODO(sky,sad): Disabled as it fails due to resize locks with a real // compositor. crbug.com/331924 #define MAYBE_DragAllToSeparateWindowAndCancel \ @@ -2592,11 +2592,15 @@ TabStrip* tab_strip = GetTabStripForBrowser(browser()); EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); - // Move to the first tab and drag it enough so that it detaches. + // Move to the first tab and drag it enough so that it detaches. Drag it + // slightly more horizontally so that it does not generate a swipe down + // gesture that minimizes the detached browser window. gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); ASSERT_TRUE(PressInput(tab_0_center)); + const int touch_move_delta = GetDetachY(tab_strip); ASSERT_TRUE(DragInputToNotifyWhenDone( - tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), + tab_0_center.x() + touch_move_delta + 5, + tab_0_center.y() + touch_move_delta, base::Bind(&PressSecondFingerWhileDetachedStep2, this, gfx::Point(tab_0_center.x(), tab_0_center.y() + 2 * GetDetachY(tab_strip)))));
diff --git a/chrome/browser/ui/views/tabs/tab_icon.cc b/chrome/browser/ui/views/tabs/tab_icon.cc index 2272e98..d82e8a3 100644 --- a/chrome/browser/ui/views/tabs/tab_icon.cc +++ b/chrome/browser/ui/views/tabs/tab_icon.cc
@@ -151,9 +151,6 @@ if (NetworkStateIsAnimated(network_state_)) return true; - if (!UseNewLoadingAnimation()) - return false; - if (LoadingAnimationNeedsRepaint()) return true; @@ -185,20 +182,14 @@ } void TabIcon::StepLoadingAnimation(const base::TimeDelta& elapsed_time) { - // The old loading animation only updates elapsed time while it's loading. - // This is used as a starting point for PaintThrobberSpinningAfterWaiting(). - if (UseNewLoadingAnimation() || network_state_ == TabNetworkState::kWaiting) - waiting_state_.elapsed_time = elapsed_time; + waiting_state_.elapsed_time = elapsed_time; UpdatePendingAnimationState(); if (LoadingAnimationNeedsRepaint()) SchedulePaint(); - // TODO(pbos): Revisit this, ideally we should always be able to paint on a - // layer. - if (UseNewLoadingAnimation()) - RefreshLayer(); + RefreshLayer(); } void TabIcon::SetBackgroundColor(SkColor bg_color) { @@ -446,8 +437,6 @@ void TabIcon::MaybePaintFaviconPlaceholder(gfx::Canvas* canvas, const gfx::Rect& bounds) { - if (!UseNewLoadingAnimation()) - return; if (!animation_state_.favicon_placeholder_alpha) return; cc::PaintFlags flags; @@ -469,16 +458,14 @@ const gfx::Rect& bounds) { // While loading, the favicon (or placeholder) isn't drawn until it has // started fading in. - if (UseNewLoadingAnimation() && !animation_state_.favicon_fade_in_progress) + if (!animation_state_.favicon_fade_in_progress) return; if (icon.isNull()) return; cc::PaintFlags flags; - double fade_in_progress = UseNewLoadingAnimation() - ? *animation_state_.favicon_fade_in_progress - : 1.0; + double fade_in_progress = *animation_state_.favicon_fade_in_progress; flags.setAlpha(fade_in_progress * SK_AlphaOPAQUE); // Drop in the new favicon from the top while it's fading in. const int offset = round((fade_in_progress - 1.0) * 4.0); @@ -495,9 +482,6 @@ } void TabIcon::MaybeStartFaviconFadeIn() { - if (!UseNewLoadingAnimation()) - return; - if (pending_animation_state_.favicon_fade_in_progress) return; @@ -537,11 +521,6 @@ void TabIcon::SetNetworkState(TabNetworkState network_state, float load_progress) { - if (!UseNewLoadingAnimation()) { - network_state_ = network_state; - return; - } - if (network_state_ != network_state) { TabNetworkState old_state = network_state_; network_state_ = network_state;
diff --git a/chrome/browser/ui/views/tabs/tab_unittest.cc b/chrome/browser/ui/views/tabs/tab_unittest.cc index fc90aef3..60e53b8 100644 --- a/chrome/browser/ui/views/tabs/tab_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_unittest.cc
@@ -20,7 +20,6 @@ #include "chrome/browser/ui/views/tabs/tab_icon.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/browser/ui/views/tabs/tab_style.h" -#include "chrome/common/chrome_features.h" #include "chrome/grit/theme_resources.h" #include "chrome/test/views/chrome_views_test_base.h" #include "testing/gtest/include/gtest/gtest.h" @@ -34,12 +33,6 @@ using views::Widget; -namespace { -bool UsingNewLoadingAnimation() { - return base::FeatureList::IsEnabled(features::kNewTabLoadingAnimation); -} -} // namespace - class FakeTabController : public TabController { public: FakeTabController() {} @@ -616,12 +609,10 @@ EXPECT_TRUE(icon->layer()); data.network_state = TabNetworkState::kNone; tab.SetData(data); - if (UsingNewLoadingAnimation()) { - // The post-loading animation should still be playing (loading bar fades - // out). - EXPECT_TRUE(icon->ShowingLoadingAnimation()); - FinishRunningLoadingAnimations(icon); - } + // The post-loading animation should still be playing (loading bar fades out). + EXPECT_TRUE(icon->ShowingLoadingAnimation()); + + FinishRunningLoadingAnimations(icon); EXPECT_FALSE(icon->ShowingLoadingAnimation()); // Simulate a tab that should hide throbber. @@ -651,12 +642,9 @@ EXPECT_TRUE(icon->layer()); data.network_state = TabNetworkState::kNone; tab.SetData(data); - if (UsingNewLoadingAnimation()) { - // The post-loading animation should still be playing (loading bar fades - // out). - EXPECT_TRUE(icon->ShowingLoadingAnimation()); - FinishRunningLoadingAnimations(icon); - } + // The post-loading animation should still be playing (loading bar fades out). + EXPECT_TRUE(icon->ShowingLoadingAnimation()); + FinishRunningLoadingAnimations(icon); EXPECT_FALSE(icon->ShowingLoadingAnimation()); // After loading is done, simulate another resource starting to load. @@ -725,8 +713,6 @@ } TEST_F(TabTest, LoadingProgressMonotonicallyIncreases) { - if (!UsingNewLoadingAnimation()) - return; Widget widget; InitWidget(&widget); @@ -759,9 +745,6 @@ } TEST_F(TabTest, LoadingProgressGoesTo100PercentAfterLoadingIsDone) { - if (!UsingNewLoadingAnimation()) - return; - Widget widget; InitWidget(&widget);
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc b/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc index b00df68..8f3c1c9 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc
@@ -199,17 +199,18 @@ void ToolbarViewTest::RunToolbarCycleFocusTest(Browser* browser) { gfx::NativeWindow window = browser->window()->GetNativeWindow(); views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window); - views::FocusManager* focus_manager = widget->GetFocusManager(); - CommandUpdater* updater = browser->command_controller(); - - // Send focus to the toolbar as if the user pressed Alt+Shift+T. - updater->ExecuteCommand(IDC_FOCUS_TOOLBAR); // Test relies on browser window activation, while platform such as Linux's // window activation is asynchronous. views::test::WidgetActivationWaiter waiter(widget, true); waiter.Wait(); + // Send focus to the toolbar as if the user pressed Alt+Shift+T. This should + // happen after the browser window activation. + CommandUpdater* updater = browser->command_controller(); + updater->ExecuteCommand(IDC_FOCUS_TOOLBAR); + + views::FocusManager* focus_manager = widget->GetFocusManager(); views::View* first_view = focus_manager->GetFocusedView(); std::vector<int> ids;
diff --git a/chrome/browser/ui/webui/app_management/app_management_ui.cc b/chrome/browser/ui/webui/app_management/app_management_ui.cc index bbdaf085..7a278a2a 100644 --- a/chrome/browser/ui/webui/app_management/app_management_ui.cc +++ b/chrome/browser/ui/webui/app_management/app_management_ui.cc
@@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/feature_list.h" +#include "chrome/browser/apps/app_service/app_icon_source.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/app_management/app_management_page_handler.h" #include "chrome/common/chrome_features.h" @@ -15,6 +16,7 @@ #include "chrome/grit/browser_resources.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" +#include "content/public/browser/url_data_source.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "ui/base/resource/resource_bundle.h" @@ -25,6 +27,11 @@ content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUIAppLauncherPageHost); + source->AddLocalizedString("appListTitle", IDS_APP_MANAGEMENT_APP_LIST_TITLE); + source->AddLocalizedString("moreApps", IDS_APP_MANAGEMENT_MORE_APPS); + source->AddLocalizedString("searchPrompt", IDS_APP_MANAGEMENT_SEARCH_PROMPT); + source->AddLocalizedString("title", IDS_APP_MANAGEMENT_TITLE); + source->AddResourcePath("app_management.mojom-lite.js", IDR_APP_MANAGEMENT_MOJO_LITE_JS); source->AddResourcePath("app.html", IDR_APP_MANAGEMENT_APP_HTML); @@ -33,6 +40,8 @@ IDR_APP_MANAGEMENT_BROWSER_PROXY_HTML); source->AddResourcePath("browser_proxy.js", IDR_APP_MANAGEMENT_BROWSER_PROXY_JS); + source->AddResourcePath("fake_page_handler.js", + IDR_APP_MANAGEMENT_FAKE_PAGE_HANDLER_JS); source->AddResourcePath("main_view.html", IDR_APP_MANAGEMENT_MAIN_VIEW_HTML); source->AddResourcePath("main_view.js", IDR_APP_MANAGEMENT_MAIN_VIEW_JS); @@ -60,6 +69,12 @@ AddHandlerToRegistry(base::BindRepeating( &AppManagementUI::BindPageHandlerFactory, base::Unretained(this))); + + // Make the chrome://app-icon/ resource available. + if (profile) { + content::URLDataSource::Add(profile, + std::make_unique<apps::AppIconSource>(profile)); + } } AppManagementUI::~AppManagementUI() = default;
diff --git a/chrome/browser/ui/webui/dark_mode_handler.cc b/chrome/browser/ui/webui/dark_mode_handler.cc index f8c81ded..91ffae2 100644 --- a/chrome/browser/ui/webui/dark_mode_handler.cc +++ b/chrome/browser/ui/webui/dark_mode_handler.cc
@@ -20,17 +20,6 @@ using ui::NativeTheme; -std::unique_ptr<base::DictionaryValue> GetDataSourceUpdate(bool use_dark) { - auto update = std::make_unique<base::DictionaryValue>(); - update->SetKey("dark", base::Value(use_dark ? "dark" : "")); - update->SetKey("darkMode", base::Value(use_dark)); - return update; -} - -bool IsFeatureEnabled() { - return base::FeatureList::IsEnabled(features::kWebUIDarkMode); -} - } // namespace DarkModeHandler::~DarkModeHandler() {} @@ -47,23 +36,17 @@ content::WebUIDataSource* source, NativeTheme* theme, Profile* profile) { - const bool enabled = IsFeatureEnabled(); - auto update = GetDataSourceUpdate(enabled && theme->SystemDarkModeEnabled()); - source->AddLocalizedStrings(*update); - if (enabled) { - auto handler = base::WrapUnique(new DarkModeHandler(theme, profile)); - handler->source_name_ = source->GetSource(); - web_ui->AddMessageHandler(std::move(handler)); - } + auto handler = base::WrapUnique(new DarkModeHandler(theme, profile)); + source->AddLocalizedStrings(*handler->GetDataSourceUpdate()); + handler->source_name_ = source->GetSource(); + web_ui->AddMessageHandler(std::move(handler)); } DarkModeHandler::DarkModeHandler(NativeTheme* theme, Profile* profile) : theme_(theme), profile_(profile), - using_dark_(theme->SystemDarkModeEnabled()), - observer_(this) { - CHECK(IsFeatureEnabled()); -} + using_dark_(IsDarkModeEnabled()), + observer_(this) {} void DarkModeHandler::RegisterMessages() { web_ui()->RegisterMessageCallback( @@ -77,24 +60,34 @@ NotifyIfChanged(); } -void DarkModeHandler::OnJavascriptAllowed() { - observer_.Add(theme_); -} - void DarkModeHandler::OnJavascriptDisallowed() { observer_.RemoveAll(); } void DarkModeHandler::HandleObserveDarkMode(const base::ListValue* /*args*/) { AllowJavascript(); + observer_.Add(theme_); +} + +bool DarkModeHandler::IsDarkModeEnabled() const { + return base::FeatureList::IsEnabled(features::kWebUIDarkMode) && + theme_->SystemDarkModeEnabled(); +} + +std::unique_ptr<base::DictionaryValue> DarkModeHandler::GetDataSourceUpdate() + const { + auto update = std::make_unique<base::DictionaryValue>(); + update->SetKey("dark", base::Value(using_dark_ ? "dark" : "")); + update->SetKey("darkMode", base::Value(using_dark_)); + return update; } void DarkModeHandler::NotifyIfChanged() { - bool use_dark = theme_->SystemDarkModeEnabled(); + bool use_dark = IsDarkModeEnabled(); if (use_dark == using_dark_) return; using_dark_ = use_dark; FireWebUIListener("dark-mode-changed", base::Value(use_dark)); content::WebUIDataSource::Update(profile_, source_name_, - GetDataSourceUpdate(use_dark)); + GetDataSourceUpdate()); }
diff --git a/chrome/browser/ui/webui/dark_mode_handler.h b/chrome/browser/ui/webui/dark_mode_handler.h index 56475ff..4eafcadd 100644 --- a/chrome/browser/ui/webui/dark_mode_handler.h +++ b/chrome/browser/ui/webui/dark_mode_handler.h
@@ -55,7 +55,6 @@ private: // content::WebUIMessageHandler: void RegisterMessages() override; - void OnJavascriptAllowed() override; void OnJavascriptDisallowed() override; // ui::NativeThemeObserver: @@ -64,6 +63,13 @@ // Handles the "observeDarkMode" message. No arguments. Protected for testing. void HandleObserveDarkMode(const base::ListValue* args); + // Generates a dictionary with "dark" and "darkMode" i18n keys based on + // |using_dark_|. Called initialize and on each change for notifications. + std::unique_ptr<base::DictionaryValue> GetDataSourceUpdate() const; + + // Whether the feature is enabled and the system is in dark mode. + bool IsDarkModeEnabled() const; + // Fire a webui listener notification if dark mode actually changed. void NotifyIfChanged();
diff --git a/chrome/browser/ui/webui/dark_mode_handler_unittest.cc b/chrome/browser/ui/webui/dark_mode_handler_unittest.cc index ff6bcb58..e19432f 100644 --- a/chrome/browser/ui/webui/dark_mode_handler_unittest.cc +++ b/chrome/browser/ui/webui/dark_mode_handler_unittest.cc
@@ -69,17 +69,49 @@ std::unique_ptr<content::TestWebUIDataSource> source_; }; -TEST_F(DarkModeHandlerTest, WebUIDarkModeDisabled) { +TEST_F(DarkModeHandlerTest, WebUIDarkModeDisabledLightMode) { features()->InitAndDisableFeature(features::kWebUIDarkMode); + theme()->SetDarkMode(false); InitializeHandler(); - EXPECT_EQ(web_ui()->GetHandlersForTesting()->size(), 0u); + EXPECT_EQ(web_ui()->GetHandlersForTesting()->size(), 1u); EXPECT_EQ(web_ui()->call_data().size(), 0u); EXPECT_FALSE(IsSourceDark()); } +TEST_F(DarkModeHandlerTest, WebUIDarkModeDisabledDarkMode) { + features()->InitAndDisableFeature(features::kWebUIDarkMode); + theme()->SetDarkMode(true); + + InitializeHandler(); + + EXPECT_EQ(web_ui()->GetHandlersForTesting()->size(), 1u); + EXPECT_EQ(web_ui()->call_data().size(), 0u); + + // Even if in dark mode, if the feature's disabled we shouldn't be telling the + // page to be dark. + EXPECT_FALSE(IsSourceDark()); +} + +TEST_F(DarkModeHandlerTest, WebUIDarkModeDisabledNoNotifications) { + features()->InitAndDisableFeature(features::kWebUIDarkMode); + theme()->SetDarkMode(false); + + InitializeHandler(); + + EXPECT_EQ(web_ui()->GetHandlersForTesting()->size(), 1u); + EXPECT_EQ(web_ui()->call_data().size(), 0u); + EXPECT_FALSE(IsSourceDark()); + + theme()->SetDarkMode(true); + theme()->NotifyObservers(); + + EXPECT_EQ(web_ui()->call_data().size(), 0u); + EXPECT_FALSE(IsSourceDark()); +} + TEST_F(DarkModeHandlerTest, WebUIDarkModeEnabledInLightMode) { features()->InitAndEnableFeature(features::kWebUIDarkMode); theme()->SetDarkMode(false);
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc index 1b75606..d4f9622 100644 --- a/chrome/browser/ui/webui/extensions/extensions_ui.cc +++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/chrome_extension_browser_constants.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/dark_mode_handler.h" #include "chrome/browser/ui/webui/metrics_handler.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" @@ -358,6 +359,7 @@ base::Bind(&ExtensionsUI::OnDevModeChanged, base::Unretained(this))); source = CreateMdExtensionsSource(*in_dev_mode_); + DarkModeHandler::Initialize(web_ui, source); #if defined(OS_CHROMEOS) auto kiosk_app_handler = std::make_unique<chromeos::KioskAppsHandler>(
diff --git a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc index de7b26e..d7ad70fa7 100644 --- a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc +++ b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc
@@ -12,6 +12,7 @@ #include "base/stl_util.h" #include "base/strings/string16.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/dark_mode_handler.h" #include "chrome/browser/ui/webui/md_bookmarks/bookmarks_message_handler.h" #include "chrome/browser/ui/webui/metrics_handler.h" #include "chrome/browser/ui/webui/plural_string_handler.h" @@ -225,8 +226,9 @@ MdBookmarksUI::MdBookmarksUI(content::WebUI* web_ui) : WebUIController(web_ui) { // Set up the chrome://bookmarks/ source. Profile* profile = Profile::FromWebUI(web_ui); - content::WebUIDataSource::Add(profile, - CreateMdBookmarksUIHTMLSource(profile)); + auto* source = CreateMdBookmarksUIHTMLSource(profile); + DarkModeHandler::Initialize(web_ui, source); + content::WebUIDataSource::Add(profile, source); auto plural_string_handler = std::make_unique<PluralStringHandler>(); plural_string_handler->AddLocalizedString(
diff --git a/chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc b/chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc index c2e5180..2a7523ae 100644 --- a/chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc +++ b/chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc
@@ -240,7 +240,7 @@ CountDownloadsDOMEvents(DOWNLOADS_DOM_EVENT_RESUME); download::DownloadItem* file = GetDownloadByStringId(id); if (file) - file->Resume(); + file->Resume(true); } void MdDownloadsDOMHandler::Remove(const std::string& id) {
diff --git a/chrome/browser/ui/webui/md_downloads/md_downloads_ui.cc b/chrome/browser/ui/webui/md_downloads/md_downloads_ui.cc index d7b0c80..d838e7a 100644 --- a/chrome/browser/ui/webui/md_downloads/md_downloads_ui.cc +++ b/chrome/browser/ui/webui/md_downloads/md_downloads_ui.cc
@@ -13,6 +13,7 @@ #include "base/values.h" #include "chrome/browser/defaults.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/dark_mode_handler.h" #include "chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.h" #include "chrome/browser/ui/webui/metrics_handler.h" #include "chrome/browser/ui/webui/theme_source.h" @@ -160,6 +161,7 @@ // Set up the chrome://downloads/ source. content::WebUIDataSource* source = CreateDownloadsUIHTMLSource(profile); + DarkModeHandler::Initialize(web_ui, source); content::WebUIDataSource::Add(profile, source); content::URLDataSource::Add(profile, std::make_unique<ThemeSource>(profile));
diff --git a/chrome/browser/ui/webui/md_history_ui.cc b/chrome/browser/ui/webui/md_history_ui.cc index 607573b..8527217 100644 --- a/chrome/browser/ui/webui/md_history_ui.cc +++ b/chrome/browser/ui/webui/md_history_ui.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/ui/webui/browsing_history_handler.h" +#include "chrome/browser/ui/webui/dark_mode_handler.h" #include "chrome/browser/ui/webui/foreign_session_handler.h" #include "chrome/browser/ui/webui/history_login_handler.h" #include "chrome/browser/ui/webui/metrics_handler.h" @@ -203,6 +204,7 @@ Profile* profile = Profile::FromWebUI(web_ui); content::WebUIDataSource* data_source = CreateMdHistoryUIHTMLSource(profile, use_test_title_); + DarkModeHandler::Initialize(web_ui, data_source); content::WebUIDataSource::Add(profile, data_source); web_ui->AddMessageHandler(std::make_unique<BrowsingHistoryHandler>());
diff --git a/chrome/browser/ui/webui/media/media_engagement_ui.cc b/chrome/browser/ui/webui/media/media_engagement_ui.cc index 4a8a58c2..ff5f4edc 100644 --- a/chrome/browser/ui/webui/media/media_engagement_ui.cc +++ b/chrome/browser/ui/webui/media/media_engagement_ui.cc
@@ -95,8 +95,6 @@ return "no-user-gesture-required"; case content::AutoplayPolicy::kUserGestureRequired: return "user-gesture-required"; - case content::AutoplayPolicy::kUserGestureRequiredForCrossOrigin: - return "user-gesture-required-for-cross-origin"; case content::AutoplayPolicy::kDocumentUserActivationRequired: return "document-user-activation-required"; }
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc index e64492f..3f94d87 100644 --- a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc +++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
@@ -79,8 +79,9 @@ base::PostTaskWithTraitsAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, - base::BindOnce(&printing::GetSettingsOnBlockingPool, printer->id(), - basic_info, nullptr), + base::BindOnce( + &printing::GetSettingsOnBlockingPool, printer->id(), basic_info, + printing::PrinterSemanticCapsAndDefaults::Papers(), nullptr), base::BindOnce(&CapabilitiesFetched, std::move(policies), std::move(cb))); }
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc index 45be6a0..0240b9d 100644 --- a/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc +++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc
@@ -29,7 +29,8 @@ } std::unique_ptr<base::DictionaryValue> FetchCapabilitiesAsync( - const std::string& device_name) { + const std::string& device_name, + const printing::PrinterSemanticCapsAndDefaults::Papers& additional_papers) { base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK); scoped_refptr<printing::PrintBackend> print_backend( printing::PrintBackend::CreateInstance(nullptr)); @@ -47,7 +48,7 @@ } return printing::GetSettingsOnBlockingPool(device_name, basic_info, - print_backend); + additional_papers, print_backend); } std::string GetDefaultPrinterAsync() { @@ -96,9 +97,13 @@ GetCapabilityCallback cb) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + // TODO(thestig): Fetch custom paper sizes. + printing::PrinterSemanticCapsAndDefaults::Papers additional_papers; + base::PostTaskWithTraitsAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, - base::BindOnce(&FetchCapabilitiesAsync, device_name), std::move(cb)); + base::BindOnce(&FetchCapabilitiesAsync, device_name, additional_papers), + std::move(cb)); } void LocalPrinterHandlerDefault::StartPrint(
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc index 7592dad..9621a9c 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -28,6 +28,7 @@ #include "chrome/browser/printing/print_preview_data_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/chrome_pages.h" +#include "chrome/browser/ui/webui/dark_mode_handler.h" #include "chrome/browser/ui/webui/metrics_handler.h" #include "chrome/browser/ui/webui/print_preview/print_preview_handler.h" #include "chrome/browser/ui/webui/theme_source.h" @@ -532,7 +533,9 @@ handler_(CreatePrintPreviewHandlers(web_ui)) { // Set up the chrome://print/ data source. Profile* profile = Profile::FromWebUI(web_ui); - content::WebUIDataSource::Add(profile, CreatePrintPreviewUISource(profile)); + content::WebUIDataSource* source = CreatePrintPreviewUISource(profile); + DarkModeHandler::Initialize(web_ui, source); + content::WebUIDataSource::Add(profile, source); // Set up the chrome://theme/ source. content::URLDataSource::Add(profile, std::make_unique<ThemeSource>(profile));
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index 55bfa5a..64210f2 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -449,6 +449,10 @@ {"crostiniEnable", IDS_SETTINGS_TURN_ON}, {"crostiniRemove", IDS_SETTINGS_CROSTINI_REMOVE}, {"crostiniSharedPaths", IDS_SETTINGS_CROSTINI_SHARED_PATHS}, + {"crostiniSharedUsbDevicesLabel", + IDS_SETTINGS_CROSTINI_SHARED_USB_DEVICES_LABEL}, + {"crostiniSharedUsbDevicesDescription", + IDS_SETTINGS_CROSTINI_SHARED_USB_DEVICES_DESCRIPTION}, }; AddLocalizedStringsBulk(html_source, localized_strings, arraysize(localized_strings)); @@ -457,6 +461,10 @@ l10n_util::GetStringFUTF16( IDS_SETTINGS_CROSTINI_SUBTEXT, GetHelpUrlWithBoard(chrome::kLinuxAppsLearnMoreURL))); + + html_source->AddBoolean( + "enableCrostiniUsbDeviceSupport", + base::FeatureList::IsEnabled(chromeos::features::kCrostiniUsbSupport)); } void AddAndroidAppStrings(content::WebUIDataSource* html_source) { @@ -1433,10 +1441,7 @@ {"creditCardExpired", IDS_SETTINGS_CREDIT_CARD_EXPIRED}, {"editCreditCardTitle", IDS_SETTINGS_EDIT_CREDIT_CARD_TITLE}, {"addCreditCardTitle", IDS_SETTINGS_ADD_CREDIT_CARD_TITLE}, - {"migrateCreditCardsLabelSingle", - IDS_SETTINGS_SINGLE_MIGRATABLE_CARD_LABEL}, - {"migrateCreditCardsLabelMultiple", - IDS_SETTINGS_MULTIPLE_MIGRATABLE_CARDS_LABEL}, + {"migrateCreditCardsLabel", IDS_SETTINGS_MIGRATABLE_CARDS_LABEL}, {"migratableCardsInfoSingle", IDS_SETTINGS_SINGLE_MIGRATABLE_CARD_INFO}, {"migratableCardsInfoMultiple", IDS_SETTINGS_MULTIPLE_MIGRATABLE_CARDS_INFO}, @@ -1721,16 +1726,8 @@ {"sync", unified_consent::IsUnifiedConsentFeatureEnabled() ? IDS_SETTINGS_SYNC_UNIFIED_CONSENT : IDS_SETTINGS_SYNC}, - {"syncDescription", unified_consent::IsUnifiedConsentFeatureEnabled() - ? IDS_SETTINGS_SYNC_DESCRIPTION_UNIFIED_CONSENT - : IDS_SETTINGS_SYNC_DESCRIPTION}, {"nonPersonalizedServicesSectionLabel", IDS_SETTINGS_NON_PERSONALIZED_SERVICES_SECTION_LABEL}, - {"nonPersonalizedServicesSectionDesc", - IDS_SETTINGS_NON_PERSONALIZED_SERVICES_SECTION_DESC}, - {"nonPersonalizedServicesExpandA11yLabel", - IDS_SETTINGS_NON_PERSONALIZED_SERVICES_SECTION_ACCESSIBILITY_LABEL}, - {"syncExpandA11yLabel", IDS_SETTINGS_SYNC_SECTION_ACCESSIBILITY_LABEL}, {"syncAndNonPersonalizedServices", IDS_SETTINGS_SYNC_SYNC_AND_NON_PERSONALIZED_SERVICES}, {"syncPageTitle", unified_consent::IsUnifiedConsentFeatureEnabled()
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc index e81b5bd6..b5ad8df 100644 --- a/chrome/browser/ui/webui/settings/md_settings_ui.cc +++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -17,6 +17,7 @@ #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" +#include "chrome/browser/ui/webui/dark_mode_handler.h" #include "chrome/browser/ui/webui/metrics_handler.h" #include "chrome/browser/ui/webui/settings/about_handler.h" #include "chrome/browser/ui/webui/settings/appearance_handler.h" @@ -430,6 +431,8 @@ AddLocalizedStrings(html_source, profile); + DarkModeHandler::Initialize(web_ui, html_source); + content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(), html_source); }
diff --git a/chrome/browser/ui/webui/settings/people_handler.cc b/chrome/browser/ui/webui/settings/people_handler.cc index 65050f0..a6fae20 100644 --- a/chrome/browser/ui/webui/settings/people_handler.cc +++ b/chrome/browser/ui/webui/settings/people_handler.cc
@@ -8,19 +8,15 @@ #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/command_line.h" #include "base/compiler_specific.h" #include "base/i18n/time_formatting.h" #include "base/json/json_reader.h" -#include "base/json/json_writer.h" #include "base/metrics/histogram_macros.h" #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_metrics.h" -#include "chrome/browser/profiles/profile_window.h" -#include "chrome/browser/signin/chrome_signin_helper.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_error_controller_factory.h" @@ -35,12 +31,9 @@ #include "chrome/browser/ui/singleton_tabs.h" #include "chrome/browser/ui/webui/signin/login_ui_service.h" #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" -#include "components/autofill/core/common/autofill_constants.h" #include "components/autofill/core/common/autofill_prefs.h" -#include "components/browser_sync/profile_sync_service.h" #include "components/prefs/pref_service.h" #include "components/signin/core/browser/account_consistency_method.h" #include "components/signin/core/browser/profile_oauth2_token_service.h" @@ -50,6 +43,8 @@ #include "components/signin/core/browser/signin_pref_names.h" #include "components/strings/grit/components_strings.h" #include "components/sync/base/passphrase_enums.h" +#include "components/sync/driver/sync_service.h" +#include "components/sync/driver/sync_service_utils.h" #include "components/sync/driver/sync_user_settings.h" #include "components/unified_consent/feature.h" #include "components/unified_consent/unified_consent_metrics.h" @@ -57,8 +52,6 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" #include "google_apis/gaia/gaia_auth_util.h" -#include "google_apis/gaia/gaia_constants.h" -#include "net/base/url_util.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" @@ -70,6 +63,7 @@ #include "chrome/browser/ui/webui/profile_helper.h" #include "components/signin/core/browser/signin_manager.h" #endif + #if BUILDFLAG(ENABLE_DICE_SUPPORT) #include "chrome/browser/profiles/profile_avatar_icon_util.h" #include "chrome/browser/signin/account_consistency_mode_manager.h" @@ -79,7 +73,6 @@ #include "ui/gfx/image/image.h" #endif -using browser_sync::ProfileSyncService; using content::WebContents; using l10n_util::GetStringFUTF16; using l10n_util::GetStringUTF16; @@ -309,8 +302,8 @@ // This is intentionally not using GetSyncService(), to go around the // Profile::IsSyncAllowed() check. - ProfileSyncService* sync_service( - ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile_)); + syncer::SyncService* sync_service = + ProfileSyncServiceFactory::GetSyncServiceForBrowserContext(profile_); if (sync_service) sync_service_observer_.Add(sync_service); @@ -353,7 +346,7 @@ force_new_tab = true; } - ProfileSyncService* service = GetSyncService(); + syncer::SyncService* service = GetSyncService(); if (service && service->HasUnrecoverableError()) { // When the user has an unrecoverable error, they first have to sign out and // then sign in again. @@ -450,7 +443,7 @@ } void PeopleHandler::SyncStartupCompleted() { - ProfileSyncService* service = GetSyncService(); + syncer::SyncService* service = GetSyncService(); DCHECK(service->IsEngineInitialized()); // Stop a timer to handle timeout in waiting for checking network connection. @@ -461,9 +454,10 @@ PushSyncPrefs(); } -ProfileSyncService* PeopleHandler::GetSyncService() const { +syncer::SyncService* PeopleHandler::GetSyncService() const { return profile_->IsSyncAllowed() - ? ProfileSyncServiceFactory::GetForProfile(profile_) + ? ProfileSyncServiceFactory::GetSyncServiceForBrowserContext( + profile_) : nullptr; } @@ -477,9 +471,9 @@ autofill::prefs::SetPaymentsIntegrationEnabled( profile_->GetPrefs(), configuration.payments_integration_enabled); - // Start configuring the ProfileSyncService using the configuration passed - // to us from the JS layer. - ProfileSyncService* service = GetSyncService(); + // Start configuring the SyncService using the configuration passed to us from + // the JS layer. + syncer::SyncService* service = GetSyncService(); // If the sync engine has shutdown for some reason, just close the sync // dialog. @@ -585,9 +579,9 @@ const base::Value* callback_id = nullptr; ParseConfigurationArguments(args, &configuration, &callback_id); - // Start configuring the ProfileSyncService using the configuration passed - // to us from the JS layer. - ProfileSyncService* service = GetSyncService(); + // Start configuring the SyncService using the configuration passed to us from + // the JS layer. + syncer::SyncService* service = GetSyncService(); // If the sync engine has shutdown for some reason, just close the sync // dialog. @@ -597,7 +591,7 @@ return; } - // Don't allow "encrypt all" if the ProfileSyncService doesn't allow it. + // Don't allow "encrypt all" if the SyncService doesn't allow it. // The UI is hidden, but the user may have enabled it e.g. by fiddling with // the web inspector. if (!service->GetUserSettings()->IsEncryptEverythingAllowed()) @@ -659,7 +653,7 @@ void PeopleHandler::HandleShowSetupUI(const base::ListValue* args) { AllowJavascript(); - ProfileSyncService* service = GetSyncService(); + syncer::SyncService* service = GetSyncService(); if (unified_consent::IsUnifiedConsentFeatureEnabled()) { if (service && !sync_blocker_) @@ -763,7 +757,7 @@ // Should only be called if the user is not already signed in, has a auth // error, or a unrecoverable sync error requiring re-auth. - ProfileSyncService* service = GetSyncService(); + syncer::SyncService* service = GetSyncService(); DCHECK(IsProfileAuthNeededOrHasErrors() || (service && service->HasUnrecoverableError())); @@ -782,7 +776,7 @@ SigninManagerFactory::GetForProfile(profile_); if (signin_manager->IsAuthenticated()) { if (GetSyncService()) - ProfileSyncService::SyncEvent(ProfileSyncService::STOP_FROM_OPTIONS); + syncer::RecordSyncEvent(syncer::STOP_FROM_OPTIONS); signin_metrics::SignoutDelete delete_metric = delete_profile ? signin_metrics::SignoutDelete::DELETED @@ -833,7 +827,7 @@ // Clear the sync startup tracker, since the setup wizard is being closed. sync_startup_tracker_.reset(); - ProfileSyncService* sync_service = GetSyncService(); + syncer::SyncService* sync_service = GetSyncService(); // LoginUIService can be nullptr if page is brought up in incognito mode // (i.e. if the user is running in guest mode in cros and brings up settings). @@ -847,8 +841,7 @@ sync_service->GetAuthError().state() == GoogleServiceAuthError::NONE))) { if (configuring_sync_) { - ProfileSyncService::SyncEvent( - ProfileSyncService::CANCEL_DURING_CONFIGURE); + syncer::RecordSyncEvent(syncer::CANCEL_DURING_CONFIGURE); // If the user clicked "Cancel" while setting up sync, disable sync // because we don't want the sync engine to remain in the @@ -888,7 +881,7 @@ return; WebContents* web_contents = web_ui()->GetWebContents(); if (web_contents) { - ProfileSyncService* service = GetSyncService(); + syncer::SyncService* service = GetSyncService(); const GURL current_url = web_contents->GetVisibleURL(); if (service && current_url == chrome::GetSettingsUrl(chrome::kSyncSetupSubPage)) { @@ -959,8 +952,8 @@ // This is intentionally not using GetSyncService(), in order to access more // nuanced information, since GetSyncService() returns nullptr if anything // makes Profile::IsSyncAllowed() false. - ProfileSyncService* service = - ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile_); + syncer::SyncService* service = + ProfileSyncServiceFactory::GetSyncServiceForBrowserContext(profile_); bool disallowed_by_policy = service && service->HasDisableReason( syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY); @@ -1003,7 +996,7 @@ return; #endif - ProfileSyncService* service = GetSyncService(); + syncer::SyncService* service = GetSyncService(); // The sync service may be nullptr if it has been just disabled by policy. if (!service || !service->IsEngineInitialized()) { return; @@ -1117,7 +1110,7 @@ // doesn't see the sign in promo even if they sign out later on. signin::SetUserSkippedPromo(profile_); - ProfileSyncService* service = GetSyncService(); + syncer::SyncService* service = GetSyncService(); // The sync service may be nullptr if it has been just disabled by policy. if (!service || service->GetUserSettings()->IsFirstSetupComplete()) return; @@ -1126,8 +1119,8 @@ base::FilePath profile_file_path = profile_->GetPath(); ProfileMetrics::LogProfileSyncSignIn(profile_file_path); - // We're done configuring, so notify ProfileSyncService that it is OK to - // start syncing. + // We're done configuring, so notify SyncService that it is OK to start + // syncing. sync_blocker_.reset(); service->GetUserSettings()->SetFirstSetupComplete(); FireWebUIListener("sync-settings-saved");
diff --git a/chrome/browser/ui/webui/settings/people_handler.h b/chrome/browser/ui/webui/settings/people_handler.h index 6af3d98..d11337fc 100644 --- a/chrome/browser/ui/webui/settings/people_handler.h +++ b/chrome/browser/ui/webui/settings/people_handler.h
@@ -30,10 +30,6 @@ class LoginUIService; -namespace browser_sync { -class ProfileSyncService; -} // namespace browser_sync - namespace content { class WebUI; } // namespace content @@ -43,6 +39,7 @@ } // namespace signin_metrics namespace syncer { +class SyncService; class SyncSetupInProgressHandle; } // namespace syncer @@ -155,9 +152,9 @@ // correspond to the status of sync. std::unique_ptr<base::DictionaryValue> GetSyncStatusDictionary(); - // Helper routine that gets the ProfileSyncService associated with the parent + // Helper routine that gets the SyncService associated with the parent // profile. - browser_sync::ProfileSyncService* GetSyncService() const; + syncer::SyncService* GetSyncService() const; // Returns the LoginUIService for the parent profile. LoginUIService* GetLoginUIService() const; @@ -224,12 +221,12 @@ bool IsProfileAuthNeededOrHasErrors(); // If we're directly loading the sync setup page, we acquire a - // SetupInProgressHandle early in order to prevent a lapse in - // ProfileSyncService's "SetupInProgress" status. This lapse previously - // occured between when the sync confirmation dialog was closed and when the - // sync setup page hadn't yet fired the SyncSetupShowSetupUI event. - // InitializeSyncBlocker is responsible for checking if we're navigating to - // the setup page and acquiring the sync_blocker. + // SetupInProgressHandle early in order to prevent a lapse in SyncService's + // "SetupInProgress" status. This lapse previously occurred between when the + // sync confirmation dialog was closed and when the sync setup page hadn't yet + // fired the SyncSetupShowSetupUI event. InitializeSyncBlocker is responsible + // for checking if we're navigating to the setup page and acquiring the + // |sync_blocker_|. void InitializeSyncBlocker(); // Weak pointer. @@ -256,8 +253,7 @@ // Manages observer lifetimes. ScopedObserver<identity::IdentityManager, PeopleHandler> identity_manager_observer_; - ScopedObserver<browser_sync::ProfileSyncService, PeopleHandler> - sync_service_observer_; + ScopedObserver<syncer::SyncService, PeopleHandler> sync_service_observer_; #if BUILDFLAG(ENABLE_DICE_SUPPORT) ScopedObserver<AccountTrackerService, PeopleHandler>
diff --git a/chrome/browser/ui/webui/settings/people_handler_unittest.cc b/chrome/browser/ui/webui/settings/people_handler_unittest.cc index cf8c82a..91da24a 100644 --- a/chrome/browser/ui/webui/settings/people_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
@@ -1042,7 +1042,7 @@ : unified_consent::UnifiedConsentFeatureState::kDisabled); ScopedAccountConsistency dice( dice_enabled ? signin::AccountConsistencyMethod::kDice - : signin::AccountConsistencyMethod::kDiceFixAuthErrors); + : signin::AccountConsistencyMethod::kDiceMigration); // Setup the profile. std::unique_ptr<TestingProfile> profile =
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc index ed0e79f..f74d567 100644 --- a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc +++ b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
@@ -33,10 +33,10 @@ #include "chrome/browser/signin/account_consistency_mode_manager.h" #include "chrome/browser/signin/account_tracker_service_factory.h" #include "chrome/browser/signin/chrome_device_id_helper.h" +#include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/signin/local_auth.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_error_controller_factory.h" -#include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/signin/signin_promo.h" #include "chrome/browser/signin/signin_util.h" #include "chrome/browser/sync/profile_sync_service_factory.h" @@ -72,6 +72,8 @@ #include "google_apis/gaia/gaia_auth_util.h" #include "google_apis/gaia/gaia_urls.h" #include "net/base/url_util.h" +#include "services/identity/public/cpp/identity_manager.h" +#include "services/identity/public/cpp/primary_account_mutator.h" #include "ui/base/l10n/l10n_util.h" #if defined(OS_WIN) @@ -258,9 +260,9 @@ AccountTrackerServiceFactory::GetForProfile(profile_)->SeedAccountInfo( gaia_id_, email_); - SigninManager* signin_manager = SigninManagerFactory::GetForProfile(profile_); - std::string primary_email = - signin_manager->GetAuthenticatedAccountInfo().email; + identity::IdentityManager* identity_manager = + IdentityManagerFactory::GetForProfile(profile_); + std::string primary_email = identity_manager->GetPrimaryAccountInfo().email; if (gaia::AreEmailsSame(email_, primary_email) && (reason == signin_metrics::Reason::REASON_REAUTHENTICATION || reason == signin_metrics::Reason::REASON_UNLOCK) && @@ -303,7 +305,11 @@ if (reason == signin_metrics::Reason::REASON_REAUTHENTICATION || reason == signin_metrics::Reason::REASON_UNLOCK) { - signin_manager->MergeSigninCredentialIntoCookieJar(); + // GetPrimaryAccountMutator() returns nullptr on platforms not supporting + // mutation of the primary account (e.g. ChromeOS). + auto* account_mutator = identity_manager->GetPrimaryAccountMutator(); + if (account_mutator) + account_mutator->LegacyMergeSigninCredentialIntoCookieJar(); } LogSigninReason(reason); } else { @@ -685,8 +691,8 @@ case signin_metrics::Reason::REASON_REAUTHENTICATION: case signin_metrics::Reason::REASON_UNLOCK: { std::string primary_username = - SigninManagerFactory::GetForProfile(profile) - ->GetAuthenticatedAccountInfo() + IdentityManagerFactory::GetForProfile(profile) + ->GetPrimaryAccountInfo() .email; if (!gaia::AreEmailsSame(default_email, primary_username)) can_offer_for = CAN_OFFER_SIGNIN_FOR_SECONDARY_ACCOUNT;
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_impl.h b/chrome/browser/ui/webui/signin/inline_login_handler_impl.h index d1f2979..f44827d 100644 --- a/chrome/browser/ui/webui/signin/inline_login_handler_impl.h +++ b/chrome/browser/ui/webui/signin/inline_login_handler_impl.h
@@ -130,7 +130,7 @@ DISALLOW_COPY_AND_ASSIGN(InlineLoginHandlerImpl); }; -// Handles details of signing the user in with SigninManager and turning on +// Handles details of signing the user in with IdentityManager and turning on // sync after InlineLoginHandlerImpl has acquired the auth tokens from GAIA. // This is a separate class from InlineLoginHandlerImpl because the full signin // process is asynchronous and can outlive the signin UI.
diff --git a/chrome/browser/ui/webui/signin/md_user_manager_ui.cc b/chrome/browser/ui/webui/signin/md_user_manager_ui.cc index 350714cd..7c65f834 100644 --- a/chrome/browser/ui/webui/signin/md_user_manager_ui.cc +++ b/chrome/browser/ui/webui/signin/md_user_manager_ui.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_shortcut_manager.h" #include "chrome/browser/signin/signin_util.h" +#include "chrome/browser/ui/webui/dark_mode_handler.h" #include "chrome/browser/ui/webui/signin/signin_create_profile_handler.h" #include "chrome/browser/ui/webui/signin/signin_utils.h" #include "chrome/browser/ui/webui/signin/user_manager_screen_handler.h" @@ -41,8 +42,11 @@ GetLocalizedStrings(&localized_strings); Profile* profile = Profile::FromWebUI(web_ui); + // Set up the chrome://md-user-manager/ source. - content::WebUIDataSource::Add(profile, CreateUIDataSource(localized_strings)); + auto* md_user_source = CreateUIDataSource(localized_strings); + DarkModeHandler::Initialize(web_ui, md_user_source); + content::WebUIDataSource::Add(profile, md_user_source); // Set up the chrome://theme/ source content::URLDataSource::Add(profile, std::make_unique<ThemeSource>(profile));
diff --git a/chrome/browser/ui/webui/welcome/welcome_handler.cc b/chrome/browser/ui/webui/welcome/welcome_handler.cc index 9991832..383e5dd 100644 --- a/chrome/browser/ui/webui/welcome/welcome_handler.cc +++ b/chrome/browser/ui/webui/welcome/welcome_handler.cc
@@ -24,13 +24,20 @@ WelcomeHandler::WelcomeHandler(content::WebUI* web_ui) : profile_(Profile::FromWebUI(web_ui)), login_ui_service_(LoginUIServiceFactory::GetForProfile(profile_)), - result_(WelcomeResult::DEFAULT) { + result_(WelcomeResult::DEFAULT), + is_redirected_welcome_impression_(false) { login_ui_service_->AddObserver(this); } WelcomeHandler::~WelcomeHandler() { login_ui_service_->RemoveObserver(this); + // If this instance is spawned due to being redirected back to welcome page + // by the onboarding logic, there's no need to log sign-in metrics again. + if (is_redirected_welcome_impression_) { + return; + } + // We log that an impression occurred at destruct-time. This can't be done at // construct-time on some platforms because this page is shown immediately // after a new installation of Chrome and loads while the user is deciding @@ -42,6 +49,14 @@ WelcomeResult::WELCOME_RESULT_MAX); } +bool WelcomeHandler::isValidRedirectUrl() { + GURL current_url = web_ui()->GetWebContents()->GetVisibleURL(); + + return current_url == kWelcomeReturningUserUrl || + current_url.spec().find(kWelcomeEmailInterstitial) != + std::string::npos; +} + // Override from LoginUIService::Observer. void WelcomeHandler::OnSyncConfirmationUIClosed( LoginUIService::SyncConfirmationUIClosedResult result) { @@ -51,10 +66,7 @@ // When signed in from NUX onboarding flow, it's possible to come back to // chrome://welcome/... after closing sync-confirmation UI. If current URL // matches such a case, do not navigate away. - GURL current_url = web_ui()->GetWebContents()->GetVisibleURL(); - if (current_url != kWelcomeReturningUserUrl && - current_url.spec().find(kWelcomeEmailInterstitial) == - std::string::npos) { + if (!is_redirected_welcome_impression_) { GoToNewTabPage(); } } @@ -94,11 +106,26 @@ result_ = (result_ == WelcomeResult::ATTEMPTED) ? WelcomeResult::ATTEMPTED_DECLINED : WelcomeResult::DECLINED; - GoToNewTabPage(); + + if (args->GetSize() == 1U) { + std::string url_string; + CHECK(args->GetString(0, &url_string)); + GURL redirect_url = GURL(url_string); + DCHECK(redirect_url.is_valid()); + + GoToURL(redirect_url); + } else { + GoToNewTabPage(); + } } // Override from WebUIMessageHandler. void WelcomeHandler::RegisterMessages() { + // Check if this instance of WelcomeHandler is spawned by onboarding flow + // redirecting users back to welcome page. This is done here instead of + // constructor, because web_ui hasn't loaded yet at that time. + is_redirected_welcome_impression_ = isValidRedirectUrl(); + web_ui()->RegisterMessageCallback( "handleActivateSignIn", base::BindRepeating(&WelcomeHandler::HandleActivateSignIn, @@ -110,7 +137,11 @@ } void WelcomeHandler::GoToNewTabPage() { - NavigateParams params(GetBrowser(), GURL(chrome::kChromeUINewTabURL), + WelcomeHandler::GoToURL(GURL(chrome::kChromeUINewTabURL)); +} + +void WelcomeHandler::GoToURL(GURL url) { + NavigateParams params(GetBrowser(), url, ui::PageTransition::PAGE_TRANSITION_LINK); params.source_contents = web_ui()->GetWebContents(); Navigate(¶ms);
diff --git a/chrome/browser/ui/webui/welcome/welcome_handler.h b/chrome/browser/ui/webui/welcome/welcome_handler.h index 7959b417..e34e4b8 100644 --- a/chrome/browser/ui/webui/welcome/welcome_handler.h +++ b/chrome/browser/ui/webui/welcome/welcome_handler.h
@@ -11,6 +11,7 @@ class Browser; class Profile; +class GURL; // Handles actions on Welcome page. class WelcomeHandler : public content::WebUIMessageHandler, @@ -47,6 +48,8 @@ void HandleActivateSignIn(const base::ListValue* args); void HandleUserDecline(const base::ListValue* args); void GoToNewTabPage(); + void GoToURL(GURL url); + bool isValidRedirectUrl(); Browser* GetBrowser(); @@ -54,6 +57,10 @@ LoginUIService* login_ui_service_; WelcomeResult result_; + // Indicates whether this WelcomeHandler instance is spawned due to users + // being redirected back to welcome page as part of the onboarding flow. + bool is_redirected_welcome_impression_; + DISALLOW_COPY_AND_ASSIGN(WelcomeHandler); };
diff --git a/chrome/browser/vr/test/xr_browser_test.cc b/chrome/browser/vr/test/xr_browser_test.cc index 04ad641..b8fa97e 100644 --- a/chrome/browser/vr/test/xr_browser_test.cc +++ b/chrome/browser/vr/test/xr_browser_test.cc
@@ -4,6 +4,7 @@ #include <cstring> +#include "base/base_paths.h" #include "base/bind.h" #include "base/callback.h" #include "base/command_line.h" @@ -11,6 +12,7 @@ #include "base/environment.h" #include "base/files/file_path.h" #include "base/files/file_util.h" +#include "base/path_service.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" #include "base/threading/platform_thread.h" @@ -43,25 +45,39 @@ XrBrowserTestBase::~XrBrowserTestBase() = default; -// We need an std::string that is an absolute file path, which requires -// platform-specific logic since Windows uses std::wstring instead of -// std::string for FilePaths, but SetVar only accepts std::string. +// Returns an std::string consisting of the given path relative to the test +// executable's path, e.g. if the executable is in out/Debug and the given path +// is "test", the returned string should be out/Debug/test. +std::string MakeExecutableRelative(const char* path) { + base::FilePath executable_path; + EXPECT_TRUE( + base::PathService::Get(base::BasePathKey::FILE_EXE, &executable_path)); + executable_path = executable_path.DirName(); + // We need an std::string that is an absolute file path, which requires + // platform-specific logic since Windows uses std::wstring instead of + // std::string for FilePaths, but SetVar only accepts std::string. #ifdef OS_WIN -#define MAKE_ABSOLUTE(x) \ - base::WideToUTF8( \ - base::MakeAbsoluteFilePath(base::FilePath(base::UTF8ToWide(x))).value()) + return base::WideToUTF8( + base::MakeAbsoluteFilePath( + executable_path.Append(base::FilePath(base::UTF8ToWide(path)))) + .value()); #else -#define MAKE_ABSOLUTE(x) base::MakeAbsoluteFilePath(base::FilePath(x)).value() + return base::MakeAbsoluteFilePath( + executable_path.Append(base::FilePath(path))) + .value(); #endif +} void XrBrowserTestBase::SetUp() { // Set the environment variable to use the mock OpenVR client. - EXPECT_TRUE(env_->SetVar(kVrOverrideEnvVar, MAKE_ABSOLUTE(kVrOverrideVal))) - << "Failed to set OpenVR mock client location environment variable"; EXPECT_TRUE( - env_->SetVar(kVrConfigPathEnvVar, MAKE_ABSOLUTE(kVrConfigPathVal))) + env_->SetVar(kVrOverrideEnvVar, MakeExecutableRelative(kVrOverrideVal))) + << "Failed to set OpenVR mock client location environment variable"; + EXPECT_TRUE(env_->SetVar(kVrConfigPathEnvVar, + MakeExecutableRelative(kVrConfigPathVal))) << "Failed to set OpenVR config location environment variable"; - EXPECT_TRUE(env_->SetVar(kVrLogPathEnvVar, MAKE_ABSOLUTE(kVrLogPathVal))) + EXPECT_TRUE( + env_->SetVar(kVrLogPathEnvVar, MakeExecutableRelative(kVrLogPathVal))) << "Failed to set OpenVR log location environment variable"; // Set any command line flags that subclasses have set, e.g. enabling WebVR
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index 394e13f..3b9fe79 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -33,6 +33,8 @@ "web_app_install_manager.h", "web_app_registrar.cc", "web_app_registrar.h", + "web_app_tab_helper.cc", + "web_app_tab_helper.h", "web_app_utils.cc", "web_app_utils.h", ]
diff --git a/chrome/browser/web_applications/components/BUILD.gn b/chrome/browser/web_applications/components/BUILD.gn index 4d1dfad..ec2c12d8 100644 --- a/chrome/browser/web_applications/components/BUILD.gn +++ b/chrome/browser/web_applications/components/BUILD.gn
@@ -24,6 +24,8 @@ "web_app_shortcut_mac.mm", "web_app_shortcut_win.cc", "web_app_shortcut_win.h", + "web_app_tab_helper_base.cc", + "web_app_tab_helper_base.h", # TODO(nigeltao): move these two files from # //chrome/browser/web_applications/components to a stand-alone
diff --git a/chrome/browser/web_applications/components/web_app_tab_helper_base.cc b/chrome/browser/web_applications/components/web_app_tab_helper_base.cc new file mode 100644 index 0000000..09a7dbf --- /dev/null +++ b/chrome/browser/web_applications/components/web_app_tab_helper_base.cc
@@ -0,0 +1,45 @@ +// 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 "chrome/browser/web_applications/components/web_app_tab_helper_base.h" + +#include "content/public/browser/navigation_handle.h" + +namespace web_app { + +WEB_CONTENTS_USER_DATA_KEY_IMPL(WebAppTabHelperBase) + +WebAppTabHelperBase::WebAppTabHelperBase(content::WebContents* web_contents) + : content::WebContentsObserver(web_contents) {} + +WebAppTabHelperBase::~WebAppTabHelperBase() = default; + +void WebAppTabHelperBase::SetAppId(const AppId& app_id) { + app_id_ = app_id; +} + +void WebAppTabHelperBase::ResetAppId() { + app_id_.clear(); +} + +void WebAppTabHelperBase::DidFinishNavigation( + content::NavigationHandle* navigation_handle) { + if (!navigation_handle->IsInMainFrame() || !navigation_handle->HasCommitted()) + return; + + const AppId app_id = GetAppId(navigation_handle->GetURL()); + SetAppId(app_id); +} + +void WebAppTabHelperBase::DidCloneToNewWebContents( + content::WebContents* old_web_contents, + content::WebContents* new_web_contents) { + // When the WebContents that this is attached to is cloned, give the new clone + // a WebAppTabHelperBase. + WebAppTabHelperBase* new_tab_helper = CloneForWebContents(new_web_contents); + // Clone common state: + new_tab_helper->SetAppId(app_id()); +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_tab_helper_base.h b/chrome/browser/web_applications/components/web_app_tab_helper_base.h new file mode 100644 index 0000000..c68ae31 --- /dev/null +++ b/chrome/browser/web_applications/components/web_app_tab_helper_base.h
@@ -0,0 +1,64 @@ +// 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 CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_TAB_HELPER_BASE_H_ +#define CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_TAB_HELPER_BASE_H_ + +#include "base/macros.h" +#include "chrome/browser/web_applications/components/web_app_helpers.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" + +namespace content { +class WebContents; +} + +namespace web_app { + +// Per-tab web app helper. Allows to associate a tab (web page) with a web app +// (or legacy bookmark app). +class WebAppTabHelperBase + : public content::WebContentsObserver, + public content::WebContentsUserData<WebAppTabHelperBase> { + public: + ~WebAppTabHelperBase() override; + + const AppId& app_id() const { return app_id_; } + + // Set app_id on web app installation or tab restore. + void SetAppId(const AppId& app_id); + // Clear app_id on web app uninstallation. + void ResetAppId(); + + // content::WebContentsObserver: + void DidFinishNavigation( + content::NavigationHandle* navigation_handle) override; + void DidCloneToNewWebContents( + content::WebContents* old_web_contents, + content::WebContents* new_web_contents) override; + + protected: + // See documentation in WebContentsUserData class comment. + explicit WebAppTabHelperBase(content::WebContents* web_contents); + friend class content::WebContentsUserData<WebAppTabHelperBase>; + WEB_CONTENTS_USER_DATA_KEY_DECL(); + + // Clone |this| tab helper (preserving a derived type). + virtual WebAppTabHelperBase* CloneForWebContents( + content::WebContents* web_contents) const = 0; + + // Gets AppId from derived platform-specific TabHelper and updates + // app_id_ with it. + virtual AppId GetAppId(const GURL& url) = 0; + + private: + // WebApp associated with this tab. Empty string if no app associated. + AppId app_id_; + + DISALLOW_COPY_AND_ASSIGN(WebAppTabHelperBase); +}; + +} // namespace web_app + +#endif // CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_TAB_HELPER_BASE_H_
diff --git a/chrome/browser/web_applications/extensions/BUILD.gn b/chrome/browser/web_applications/extensions/BUILD.gn index 0db631c..57a3815 100644 --- a/chrome/browser/web_applications/extensions/BUILD.gn +++ b/chrome/browser/web_applications/extensions/BUILD.gn
@@ -12,6 +12,8 @@ "bookmark_app_installation_task.h", "bookmark_app_installer.cc", "bookmark_app_installer.h", + "bookmark_app_tab_helper.cc", + "bookmark_app_tab_helper.h", "bookmark_app_util.cc", "bookmark_app_util.h", "pending_bookmark_app_manager.cc", @@ -42,6 +44,7 @@ sources = [ "bookmark_app_installation_task_unittest.cc", "bookmark_app_installer_unittest.cc", + "bookmark_app_util_unittest.cc", "pending_bookmark_app_manager_unittest.cc", "web_app_extension_ids_map_unittest.cc", ]
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc b/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc index c3f9e0f6..d52b70c 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc +++ b/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/web_applications/components/web_app_constants.h" #include "chrome/browser/web_applications/components/web_app_data_retriever.h" #include "chrome/browser/web_applications/extensions/bookmark_app_installer.h" +#include "chrome/browser/web_applications/extensions/bookmark_app_tab_helper.h" #include "chrome/common/web_application_info.h" #include "content/public/browser/browser_thread.h" #include "extensions/common/constants.h"
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_tab_helper.cc b/chrome/browser/web_applications/extensions/bookmark_app_tab_helper.cc new file mode 100644 index 0000000..b8f98f9 --- /dev/null +++ b/chrome/browser/web_applications/extensions/bookmark_app_tab_helper.cc
@@ -0,0 +1,58 @@ +// 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 "chrome/browser/web_applications/extensions/bookmark_app_tab_helper.h" + +#include "chrome/browser/extensions/extension_util.h" +#include "chrome/browser/web_applications/components/web_app_helpers.h" +#include "chrome/browser/web_applications/extensions/bookmark_app_util.h" +#include "chrome/common/chrome_features.h" +#include "extensions/common/extension.h" +#include "url/gurl.h" + +namespace extensions { + +BookmarkAppTabHelper::BookmarkAppTabHelper(content::WebContents* web_contents) + : WebAppTabHelperBase(web_contents) {} + +BookmarkAppTabHelper::~BookmarkAppTabHelper() = default; + +// static +BookmarkAppTabHelper* BookmarkAppTabHelper::CreateForWebContents( + content::WebContents* web_contents) { + // Do nothing if already exists. + if (FromWebContents(web_contents)) + return nullptr; + + auto tab_helper = std::make_unique<BookmarkAppTabHelper>(web_contents); + BookmarkAppTabHelper* result = tab_helper.get(); + web_contents->SetUserData(UserDataKey(), std::move(tab_helper)); + return result; +} + +web_app::WebAppTabHelperBase* BookmarkAppTabHelper::CloneForWebContents( + content::WebContents* web_contents) const { + BookmarkAppTabHelper* new_tab_helper = + BookmarkAppTabHelper::CreateForWebContents(web_contents); + return new_tab_helper; +} + +web_app::AppId BookmarkAppTabHelper::GetAppId(const GURL& url) { + content::BrowserContext* browser_context = + web_contents()->GetBrowserContext(); + + const Extension* extension = nullptr; + + if (base::FeatureList::IsEnabled(::features::kDesktopPWAWindowing)) + extension = util::GetInstalledPwaForUrl(browser_context, url); + + if (!extension) { + // Check if there is a shortcut app for this |url|. + extension = GetInstalledShortcutForUrl(browser_context, url); + } + + return extension ? extension->id() : web_app::AppId(); +} + +} // namespace extensions
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_tab_helper.h b/chrome/browser/web_applications/extensions/bookmark_app_tab_helper.h new file mode 100644 index 0000000..a3a93f0c --- /dev/null +++ b/chrome/browser/web_applications/extensions/bookmark_app_tab_helper.h
@@ -0,0 +1,40 @@ +// 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 CHROME_BROWSER_WEB_APPLICATIONS_EXTENSIONS_BOOKMARK_APP_TAB_HELPER_H_ +#define CHROME_BROWSER_WEB_APPLICATIONS_EXTENSIONS_BOOKMARK_APP_TAB_HELPER_H_ + +#include "base/macros.h" +#include "chrome/browser/web_applications/components/web_app_tab_helper_base.h" + +namespace content { +class WebContents; +} + +namespace extensions { + +// Allows to associate a tab with bookmark app. +class BookmarkAppTabHelper : public web_app::WebAppTabHelperBase { + public: + explicit BookmarkAppTabHelper(content::WebContents* web_contents); + ~BookmarkAppTabHelper() override; + + // Should only be called through WebAppProvider::CreateTabHelper which ensures + // the right tab helper is created based on the DesktopPWAsWithoutExtensions + // feature. + static BookmarkAppTabHelper* CreateForWebContents( + content::WebContents* web_contents); + + // TabHelper: + web_app::WebAppTabHelperBase* CloneForWebContents( + content::WebContents* web_contents) const override; + web_app::AppId GetAppId(const GURL& url) override; + + private: + DISALLOW_COPY_AND_ASSIGN(BookmarkAppTabHelper); +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_WEB_APPLICATIONS_EXTENSIONS_BOOKMARK_APP_TAB_HELPER_H_
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_util.cc b/chrome/browser/web_applications/extensions/bookmark_app_util.cc index d75c6432..57fdcc8 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_util.cc +++ b/chrome/browser/web_applications/extensions/bookmark_app_util.cc
@@ -4,7 +4,11 @@ #include "chrome/browser/web_applications/extensions/bookmark_app_util.h" +#include "base/strings/string_piece.h" #include "base/values.h" +#include "chrome/browser/web_applications/extensions/bookmark_app_util.h" +#include "chrome/common/chrome_features.h" +#include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "content/public/browser/browser_context.h" #include "extensions/browser/extension_prefs.h" @@ -70,4 +74,34 @@ return false; } +bool IsInNavigationScopeForLaunchUrl(const GURL& launch_url, const GURL& url) { + // Drop any "suffix" components after the path (Resolve "."): + const GURL nav_scope = launch_url.GetWithoutFilename(); + + const int scope_str_length = nav_scope.spec().size(); + return base::StringPiece(nav_scope.spec()) == + base::StringPiece(url.spec()).substr(0, scope_str_length); +} + +const Extension* GetInstalledShortcutForUrl( + content::BrowserContext* browser_context, + const GURL& url) { + const ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context); + for (scoped_refptr<const Extension> app : + ExtensionRegistry::Get(browser_context)->enabled_extensions()) { + if (!app->from_bookmark()) + continue; + if (!BookmarkAppIsLocallyInstalled(prefs, app.get())) + continue; + // Skip PWAs. + if (UrlHandlers::CanBookmarkAppHandleUrl(app.get(), url)) + continue; + + const GURL launch_url = AppLaunchInfo::GetLaunchWebURL(app.get()); + if (IsInNavigationScopeForLaunchUrl(launch_url, url)) + return app.get(); + } + return nullptr; +} + } // namespace extensions
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_util.h b/chrome/browser/web_applications/extensions/bookmark_app_util.h index f8c94146..95b49e8 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_util.h +++ b/chrome/browser/web_applications/extensions/bookmark_app_util.h
@@ -39,6 +39,16 @@ bool BookmarkOrHostedAppInstalled(content::BrowserContext* browser_context, const GURL& url); +// Generates a scope based on |launch_url| and checks if the |url| falls under +// it. https://www.w3.org/TR/appmanifest/#navigation-scope +bool IsInNavigationScopeForLaunchUrl(const GURL& launch_url, const GURL& url); + +// Finds the first Shortcut App (a non-PWA Bookmark App) with |url| in its +// scope, returns nullptr if there are none. +const Extension* GetInstalledShortcutForUrl( + content::BrowserContext* browser_context, + const GURL& url); + } // namespace extensions #endif // CHROME_BROWSER_WEB_APPLICATIONS_EXTENSIONS_BOOKMARK_APP_UTIL_H_
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_util_unittest.cc b/chrome/browser/web_applications/extensions/bookmark_app_util_unittest.cc new file mode 100644 index 0000000..51d53313 --- /dev/null +++ b/chrome/browser/web_applications/extensions/bookmark_app_util_unittest.cc
@@ -0,0 +1,98 @@ +// 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 "chrome/browser/web_applications/extensions/bookmark_app_util.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace extensions { + +// See additional test coverage for edge cases in GURLTest.GetWithoutFilename. +TEST(BookmarkAppUtil, IsInNavigationScopeForLaunchUrl_UrlArgumentVariations) { + const GURL launch_url = GURL("https://mail.google.com/mail/u/0"); + + // Not in scope. + EXPECT_FALSE(IsInNavigationScopeForLaunchUrl( + launch_url, GURL("https://mail.google.com"))); + EXPECT_FALSE(IsInNavigationScopeForLaunchUrl( + launch_url, GURL("https://mail.google.com/mail/"))); + + // The scope itself. + EXPECT_TRUE(IsInNavigationScopeForLaunchUrl( + launch_url, GURL("https://mail.google.com/mail/u/"))); + // No match if no trailing '/' in path. + EXPECT_FALSE(IsInNavigationScopeForLaunchUrl( + launch_url, GURL("https://mail.google.com/mail/u"))); + + // Regular sub-path. + EXPECT_TRUE(IsInNavigationScopeForLaunchUrl( + launch_url, GURL("https://mail.google.com/mail/u/0/"))); + + // With a ref. + EXPECT_TRUE(IsInNavigationScopeForLaunchUrl( + launch_url, GURL("https://mail.google.com/mail/u/0/#inbox"))); + + // A launch URL with trailing '/' resolves to itself. + const GURL launch_url2 = GURL("https://example.com/path/subpath/"); + EXPECT_TRUE(IsInNavigationScopeForLaunchUrl( + launch_url2, GURL("https://example.com/path/subpath/page.html"))); + EXPECT_FALSE(IsInNavigationScopeForLaunchUrl( + launch_url2, GURL("https://example.com/path/subpath2/"))); + + // With a query. + EXPECT_TRUE(IsInNavigationScopeForLaunchUrl( + GURL("https://example.com/path/subpath"), + GURL("https://example.com/path/query?parameter"))); +} + +TEST(BookmarkAppUtil, IsInNavigationScopeForLaunchUrl_LaunchUrlVariations) { + // With a query. + EXPECT_TRUE(IsInNavigationScopeForLaunchUrl( + GURL("https://example.com/path/query?parameter"), + GURL("https://example.com/path/subpath"))); + EXPECT_FALSE(IsInNavigationScopeForLaunchUrl( + GURL("https://example.com/path/query?parameter"), + GURL("https://example.com/query"))); + + EXPECT_TRUE(IsInNavigationScopeForLaunchUrl( + GURL("https://example.com/path/query/?parameter"), + GURL("https://example.com/path/query/"))); + EXPECT_FALSE(IsInNavigationScopeForLaunchUrl( + GURL("https://example.com/path/query/?parameter"), + GURL("https://example.com/path/subpath/"))); + + // With a ref. + EXPECT_TRUE(IsInNavigationScopeForLaunchUrl( + GURL("https://example.com/path/#ref"), + GURL("https://example.com/path/subpath"))); + EXPECT_FALSE(IsInNavigationScopeForLaunchUrl( + GURL("https://example.com/path/#ref"), GURL("https://example.com/#ref"))); + + // With a ref and query. + EXPECT_TRUE(IsInNavigationScopeForLaunchUrl( + GURL("https://example.com/path/?query=param#ref"), + GURL("https://example.com/path/subpath"))); + EXPECT_FALSE(IsInNavigationScopeForLaunchUrl( + GURL("https://example.com/path/?query=param#ref"), + GURL("https://example.com/subpath"))); + + EXPECT_TRUE(IsInNavigationScopeForLaunchUrl( + GURL("https://example.com/path/#ref?query=param"), + GURL("https://example.com/path/subpath"))); + EXPECT_FALSE(IsInNavigationScopeForLaunchUrl( + GURL("https://example.com/path/#ref?query=param"), + GURL("https://example.com/subpath"))); +} + +TEST(BookmarkAppUtil, IsInNavigationScopeForLaunchUrl_Extensions) { + // The Crosh extension. + const GURL extension_launch_url = GURL( + "chrome-extension://nkoccljplnhpfnfiajclkommnmllphnl/html/crosh.html"); + EXPECT_TRUE(IsInNavigationScopeForLaunchUrl( + extension_launch_url, + GURL("chrome-extension://nkoccljplnhpfnfiajclkommnmllphnl/html/path"))); +} + +} // namespace extensions
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc index 9a493716..5223c36 100644 --- a/chrome/browser/web_applications/web_app_provider.cc +++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/web_applications/bookmark_apps/bookmark_app_install_manager.h" #include "chrome/browser/web_applications/components/web_app_constants.h" #include "chrome/browser/web_applications/components/web_app_helpers.h" +#include "chrome/browser/web_applications/extensions/bookmark_app_tab_helper.h" #include "chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h" #include "chrome/browser/web_applications/extensions/web_app_extension_ids_map.h" #include "chrome/browser/web_applications/external_web_apps.h" @@ -27,6 +28,7 @@ #include "chrome/browser/web_applications/web_app_install_manager.h" #include "chrome/browser/web_applications/web_app_provider_factory.h" #include "chrome/browser/web_applications/web_app_registrar.h" +#include "chrome/browser/web_applications/web_app_tab_helper.h" #include "chrome/browser/web_applications/web_app_utils.h" #include "chrome/common/chrome_features.h" #include "content/public/browser/notification_source.h" @@ -105,6 +107,17 @@ } // static +WebAppTabHelperBase* WebAppProvider::CreateTabHelper( + content::WebContents* web_contents) { + if (base::FeatureList::IsEnabled(features::kDesktopPWAsWithoutExtensions)) + WebAppTabHelper::CreateForWebContents(web_contents); + else + extensions::BookmarkAppTabHelper::CreateForWebContents(web_contents); + + return WebAppTabHelperBase::FromWebContents(web_contents); +} + +// static bool WebAppProvider::CanInstallWebApp(content::WebContents* web_contents) { auto* provider = WebAppProvider::GetForWebContents(web_contents); if (!provider || !provider->install_manager_)
diff --git a/chrome/browser/web_applications/web_app_provider.h b/chrome/browser/web_applications/web_app_provider.h index 468c7b91..62f5d79c 100644 --- a/chrome/browser/web_applications/web_app_provider.h +++ b/chrome/browser/web_applications/web_app_provider.h
@@ -30,6 +30,7 @@ // Forward declarations of generalized interfaces. class PendingAppManager; class InstallManager; +class WebAppTabHelperBase; // Forward declarations for new extension-independent subsystems. class WebAppDatabase; @@ -59,6 +60,8 @@ ~WebAppProvider() override; static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); + static WebAppTabHelperBase* CreateTabHelper( + content::WebContents* web_contents); // Returns true if a bookmark can be installed for a given |web_contents|. static bool CanInstallWebApp(content::WebContents* web_contents);
diff --git a/chrome/browser/web_applications/web_app_tab_helper.cc b/chrome/browser/web_applications/web_app_tab_helper.cc new file mode 100644 index 0000000..2520c52 --- /dev/null +++ b/chrome/browser/web_applications/web_app_tab_helper.cc
@@ -0,0 +1,39 @@ +// 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 "chrome/browser/web_applications/web_app_tab_helper.h" + +namespace web_app { + +WebAppTabHelper::WebAppTabHelper(content::WebContents* web_contents) + : WebAppTabHelperBase(web_contents) {} + +WebAppTabHelper::~WebAppTabHelper() = default; + +// static +WebAppTabHelper* WebAppTabHelper::CreateForWebContents( + content::WebContents* web_contents) { + // Do nothing if already exists. + if (FromWebContents(web_contents)) + return nullptr; + + auto tab_helper = std::make_unique<WebAppTabHelper>(web_contents); + WebAppTabHelper* result = tab_helper.get(); + web_contents->SetUserData(UserDataKey(), std::move(tab_helper)); + return result; +} + +WebAppTabHelperBase* WebAppTabHelper::CloneForWebContents( + content::WebContents* web_contents) const { + WebAppTabHelper* new_tab_helper = + WebAppTabHelper::CreateForWebContents(web_contents); + return new_tab_helper; +} + +AppId WebAppTabHelper::GetAppId(const GURL& url) { + // TODO(loyso): Implement it. + return AppId(); +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_tab_helper.h b/chrome/browser/web_applications/web_app_tab_helper.h new file mode 100644 index 0000000..333573d --- /dev/null +++ b/chrome/browser/web_applications/web_app_tab_helper.h
@@ -0,0 +1,40 @@ +// 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 CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_TAB_HELPER_H_ +#define CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_TAB_HELPER_H_ + +#include "base/macros.h" +#include "chrome/browser/web_applications/components/web_app_tab_helper_base.h" + +namespace content { +class WebContents; +} + +namespace web_app { + +// Allows to associate a tab with web app. +class WebAppTabHelper : public WebAppTabHelperBase { + public: + explicit WebAppTabHelper(content::WebContents* web_contents); + ~WebAppTabHelper() override; + + // Should only be called through WebAppProvider::CreateTabHelper which ensures + // the right tab helper is created based on the DesktopPWAsWithoutExtensions + // feature. + static WebAppTabHelper* CreateForWebContents( + content::WebContents* web_contents); + + // TabHelper: + WebAppTabHelperBase* CloneForWebContents( + content::WebContents* web_contents) const override; + AppId GetAppId(const GURL& url) override; + + private: + DISALLOW_COPY_AND_ASSIGN(WebAppTabHelper); +}; + +} // namespace web_app + +#endif // CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_TAB_HELPER_H_
diff --git a/chrome/chrome_proxy/BUILD.gn b/chrome/chrome_proxy/BUILD.gn deleted file mode 100644 index b5181a5..0000000 --- a/chrome/chrome_proxy/BUILD.gn +++ /dev/null
@@ -1,33 +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. - -assert(is_win) - -import("//chrome/process_version_rc_template.gni") - -process_version_rc_template("chrome_proxy_version") { - sources = [ - "chrome_proxy.ver", - ] - output = "$target_gen_dir/chrome_proxy_version.rc" -} - -executable("chrome_proxy") { - deps = [ - ":chrome_proxy_version", - "//base", - "//chrome/app/version_assembly:chrome_exe_manifest", - ] - - data_deps = [ - "//chrome/app/version_assembly:version_assembly_manifest", - ] - - sources = [ - "chrome_proxy_main_win.cc", - ] - - configs -= [ "//build/config/win:console" ] - configs += [ "//build/config/win:windowed" ] -}
diff --git a/chrome/chrome_proxy/OWNERS b/chrome/chrome_proxy/OWNERS deleted file mode 100644 index bdf488e5a4..0000000 --- a/chrome/chrome_proxy/OWNERS +++ /dev/null
@@ -1,4 +0,0 @@ -alancutter@chromium.org -mgiuca@chromium.org - -# COMPONENT: UI>Browser>WebAppInstalls
diff --git a/chrome/chrome_proxy/chrome_proxy.ver b/chrome/chrome_proxy/chrome_proxy.ver deleted file mode 100644 index 32083b1..0000000 --- a/chrome/chrome_proxy/chrome_proxy.ver +++ /dev/null
@@ -1,2 +0,0 @@ -INTERNAL_NAME=chrome_proxy -ORIGINAL_FILENAME=chrome_proxy.exe
diff --git a/chrome/chrome_proxy/chrome_proxy_main_win.cc b/chrome/chrome_proxy/chrome_proxy_main_win.cc deleted file mode 100644 index 2f0ac83..0000000 --- a/chrome/chrome_proxy/chrome_proxy_main_win.cc +++ /dev/null
@@ -1,52 +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 <windows.h> - -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "base/process/launch.h" - -namespace { - -constexpr base::FilePath::CharType kChromeExecutable[] = - FILE_PATH_LITERAL("chrome.exe"); - -constexpr base::FilePath::CharType kChromeProxyExecutable[] = - FILE_PATH_LITERAL("chrome_proxy.exe"); - -} // namespace - -int WINAPI wWinMain(HINSTANCE instance, - HINSTANCE prev_instance, - wchar_t* /*command_line*/, - int show_command) { - base::CommandLine::Init(0, nullptr); - - logging::LoggingSettings logging_settings; - logging_settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; - logging::InitLogging(logging_settings); - - base::FilePath chrome_dir; - CHECK(base::PathService::Get(base::DIR_EXE, &chrome_dir)); - base::CommandLine chrome_command_line(chrome_dir.Append(kChromeExecutable)); - - // Forward all command line arguments. - const std::vector<base::string16>& argv = - base::CommandLine::ForCurrentProcess()->argv(); - // The first one is always the current executable path. - CHECK(argv.size() > 0); - CHECK_EQ(base::FilePath(argv[0]).BaseName().value(), kChromeProxyExecutable); - for (size_t i = 1; i < argv.size(); ++i) - chrome_command_line.AppendArgNative(argv[i]); - - base::LaunchOptions launch_options; - launch_options.current_directory = chrome_dir; - launch_options.grant_foreground_privilege = true; - CHECK(base::LaunchProcess(chrome_command_line, launch_options).IsValid()); - - return 0; -}
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 8d597172..7cd22aa 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -334,9 +334,6 @@ base::FEATURE_ENABLED_BY_DEFAULT}; #if defined(OS_MACOSX) -// Enables RTL layout in macOS top chrome. -const base::Feature kMacRTL{"MacRTL", base::FEATURE_ENABLED_BY_DEFAULT}; - // Uses NSFullSizeContentViewWindowMask where available instead of adding our // own views to the window frame. This is a temporary kill switch, it can be // removed once we feel okay about leaving it on. @@ -387,7 +384,7 @@ #if !defined(OS_ANDROID) const base::Feature kNewTabLoadingAnimation{"NewTabLoadingAnimation", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; #endif // !OS_ANDROID #if defined(OS_POSIX)
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 51317bb9c..ab140dc 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -224,7 +224,6 @@ extern const base::Feature kLsdPermissionPrompt; #if defined(OS_MACOSX) -COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kMacRTL; COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kMacFullSizeContentView; #endif
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 4d602b6..ba84703 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -823,10 +823,6 @@ // Disable the toolkit-views App Info dialog for Mac. const char kDisableAppInfoDialogMac[] = "disable-app-info-dialog-mac"; -// Disables tab detaching in fullscreen mode on Mac. -const char kDisableFullscreenTabDetaching[] = - "disable-fullscreen-tab-detaching"; - // Disables app shim creation for hosted apps on Mac. const char kDisableHostedAppShimCreation[] = "disable-hosted-app-shim-creation"; @@ -844,9 +840,6 @@ // chrome://apps and chrome://extensions and is already enabled on non-mac. const char kEnableAppInfoDialogMac[] = "enable-app-info-dialog-mac"; -// Enables tab detaching in fullscreen mode on Mac. -const char kEnableFullscreenTabDetaching[] = "enable-fullscreen-tab-detaching"; - // Enables the fullscreen toolbar to reveal itself for tab strip changes. const char kEnableFullscreenToolbarReveal[] = "enable-fullscreen-toolbar-reveal";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 8907cb8..560c525 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -251,12 +251,10 @@ #if defined(OS_MACOSX) extern const char kAppsKeepChromeAliveInTests[]; extern const char kDisableAppInfoDialogMac[]; -extern const char kDisableFullscreenTabDetaching[]; extern const char kDisableHostedAppShimCreation[]; extern const char kDisableHostedAppsInWindows[]; extern const char kDisableMacViewsNativeAppWindows[]; extern const char kEnableAppInfoDialogMac[]; -extern const char kEnableFullscreenTabDetaching[]; extern const char kEnableFullscreenToolbarReveal[]; extern const char kEnableHostedAppsInWindows[]; extern const char kEnableUserMetrics[];
diff --git a/chrome/common/extensions/api/input_method_private.json b/chrome/common/extensions/api/input_method_private.json index fbef854..b960ff1e 100644 --- a/chrome/common/extensions/api/input_method_private.json +++ b/chrome/common/extensions/api/input_method_private.json
@@ -388,6 +388,7 @@ { "type": "function", "name": "callback", + "optional": true, "description": "Callback to notify that the new value has been set", "parameters": [] } @@ -508,6 +509,38 @@ "description": "Describes the text field that has acquired focus." } ] + }, { + "name": "onSettingsChanged", + "type": "function", + "description": "This event is sent when the settings for any input method changed. It is sent to all extensions that are listening to this event, and enabled by the user.", + "parameters": [ + { + "name": "engineID", + "type": "string", + "description": "ID of the engine that changed" + }, + { + "name": "key", + "type": "string", + "description": "The setting that changed" + }, + { + "name": "value", + "type": "any", + "description": "The new value of the setting" + } + ] + }, { + "name": "onScreenProjectionChanged", + "type": "function", + "description": "This event is sent when the screen is being mirrored or the desktop is being cast.", + "parameters": [ + { + "name": "isProjected", + "type": "boolean", + "description": "Whether the screen is projected." + } + ] } ] }
diff --git a/chrome/common/extensions/api/webrtc_logging_private.idl b/chrome/common/extensions/api/webrtc_logging_private.idl index 108460d..bbcc055 100644 --- a/chrome/common/extensions/api/webrtc_logging_private.idl +++ b/chrome/common/extensions/api/webrtc_logging_private.idl
@@ -162,13 +162,18 @@ // Start remote-bound event logging for a specific peer connection, // indicated by its ID, for which remote-bound event logging was not active. // If successful, the callback will carry the ID of the log. - // |webAppId| must be a number between 1 and 99 (inclusive), which will be - // incorporated into the uploaded log, so as to help distinugish logs - // captured by different web-apps. + // * |webAppId| must be a number between 1 and 99 (inclusive), which will be + // incorporated into the uploaded log, so as to help distinugish logs + // captured by different web-apps. + // * |outputPeriodMs| refers to the time between emissions of logs. + // Only non-negative values are allowed. If set to zero, logs will be + // produced as soon as an event occurs. If positive, events will be + // batched together and emitted approximately every |outputPeriodMs| ms. static void startEventLogging(RequestInfo request, DOMString securityOrigin, DOMString peerConnectionId, long maxLogSizeBytes, + long outputPeriodMs, long webAppId, StartEventLoggingCallback callback);
diff --git a/chrome/common/mac/app_shim.mojom b/chrome/common/mac/app_shim.mojom index 8b7a80a..af9fd6c9 100644 --- a/chrome/common/mac/app_shim.mojom +++ b/chrome/common/mac/app_shim.mojom
@@ -34,6 +34,11 @@ associated content.mojom.NSViewBridgeFactory& content_ns_views_bridge_factory); + // Initialize the command handler for the specified BridgedNativeWidget. This + // method exists at this scope (as opposed to in views_bridge_mac) because it + // creates chrome-scoped objects that implement views_bridge_mac interfaces. + CreateCommandDispatcherForWidget(uint64 widget_id); + // Instructs the shim to hide the app. Hide();
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index f11b4cd0..ce96f61 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -889,6 +889,10 @@ const char kNTLMShareAuthenticationEnabled[] = "network_file_shares.ntlm_share_authentication.enabled"; +// Dictionary pref containing configuration used to verify Parent Access Code. +// Controlled by ParentAccessCodeConfig policy. +const char kParentAccessCodeConfig[] = "child_user.parent_access_code.config"; + // List of preconfigured network file shares. const char kNetworkFileSharesPreconfiguredShares[] = "network_file_shares.preconfigured_shares";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index c0a3735..292b0db 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -286,6 +286,7 @@ extern const char kNTLMShareAuthenticationEnabled[]; extern const char kNetworkFileSharesPreconfiguredShares[]; extern const char kMostRecentlyUsedNetworkFileShareURL[]; +extern const char kParentAccessCodeConfig[]; #endif // defined(OS_CHROMEOS) extern const char kShowHomeButton[]; extern const char kSpeechRecognitionFilterProfanities[];
diff --git a/chrome/common/safe_browsing/BUILD.gn b/chrome/common/safe_browsing/BUILD.gn index b93eeae..ff231da 100644 --- a/chrome/common/safe_browsing/BUILD.gn +++ b/chrome/common/safe_browsing/BUILD.gn
@@ -34,8 +34,16 @@ "archive_analyzer_results.h", ] deps = [ + ":binary_feature_extractor", + ":download_type_util", + ":file_type_policies", "//base", + "//base:i18n", + "//crypto", ] + if (is_mac) { + deps += [ ":disk_image_type_sniffer_mac" ] + } public_deps = [ "//components/safe_browsing:csd_proto", ] @@ -101,6 +109,28 @@ ] } + source_set("binary_feature_extractor") { + sources = [ + "binary_feature_extractor.cc", + "binary_feature_extractor.h", + "binary_feature_extractor_mac.cc", + "binary_feature_extractor_win.cc", + "mach_o_image_reader_mac.cc", + "mach_o_image_reader_mac.h", + "pe_image_reader_win.cc", + "pe_image_reader_win.h", + ] + if (is_posix) { + sources += [ "binary_feature_extractor_posix.cc" ] + } + + public_deps = [ + "//base", + "//components/safe_browsing:csd_proto", + "//crypto", + ] + } + source_set("mock_binary_feature_extractor") { testonly = true @@ -110,7 +140,7 @@ ] deps = [ - ":safe_browsing", + ":binary_feature_extractor", "//testing/gmock", ] } @@ -121,34 +151,20 @@ ":file_type_policies", ] - if (is_mac) { - deps += [ ":disk_image_type_sniffer_mac" ] - } - if (safe_browsing_mode == 1) { sources = [ - "binary_feature_extractor.cc", - "binary_feature_extractor.h", - "binary_feature_extractor_mac.cc", - "binary_feature_extractor_win.cc", "ipc_protobuf_message_macros.h", "ipc_protobuf_message_null_macros.h", - "mach_o_image_reader_mac.cc", - "mach_o_image_reader_mac.h", - "pe_image_reader_win.cc", - "pe_image_reader_win.h", "protobuf_message_log_macros.h", "protobuf_message_read_macros.h", "protobuf_message_write_macros.h", "zip_analyzer.cc", "zip_analyzer.h", ] - if (is_posix) { - sources += [ "binary_feature_extractor_posix.cc" ] - } deps += [ ":archive_analyzer_results", + ":binary_feature_extractor", ":download_type_util", ":rar_analyzer", "//components/safe_browsing:features",
diff --git a/chrome/common/safe_browsing/archive_analyzer_results.cc b/chrome/common/safe_browsing/archive_analyzer_results.cc index dc1f071a..2dfcdef 100644 --- a/chrome/common/safe_browsing/archive_analyzer_results.cc +++ b/chrome/common/safe_browsing/archive_analyzer_results.cc
@@ -7,8 +7,79 @@ #include "chrome/common/safe_browsing/archive_analyzer_results.h" +#include "base/files/file.h" +#include "base/i18n/streaming_utf8_validator.h" +#include "base/memory/scoped_refptr.h" +#include "base/stl_util.h" +#include "build/build_config.h" +#include "chrome/common/safe_browsing/archive_analyzer_results.h" +#include "chrome/common/safe_browsing/binary_feature_extractor.h" +#include "chrome/common/safe_browsing/download_type_util.h" +#include "chrome/common/safe_browsing/file_type_policies.h" +#include "crypto/secure_hash.h" +#include "crypto/sha2.h" + +#if defined(OS_MACOSX) +#include <mach-o/fat.h> +#include <mach-o/loader.h> +#include "base/containers/span.h" +#include "chrome/common/safe_browsing/disk_image_type_sniffer_mac.h" +#include "chrome/common/safe_browsing/mach_o_image_reader_mac.h" +#endif // OS_MACOSX + namespace safe_browsing { +namespace { + +void SetLengthAndDigestForContainedFile( + const base::FilePath& path, + base::File* temp_file, + ClientDownloadRequest::ArchivedBinary* archived_binary) { + std::string file_basename(path.BaseName().AsUTF8Unsafe()); + if (base::StreamingUtf8Validator::Validate(file_basename)) + archived_binary->set_file_basename(file_basename); + archived_binary->set_length(temp_file->GetLength()); + + std::unique_ptr<crypto::SecureHash> hasher = + crypto::SecureHash::Create(crypto::SecureHash::SHA256); + + const size_t kReadBufferSize = 4096; + char block[kReadBufferSize]; + + temp_file->Seek(base::File::Whence::FROM_BEGIN, 0); + while (true) { + int bytes_read = temp_file->ReadAtCurrentPos(block, kReadBufferSize); + + if (bytes_read <= 0) + break; + + hasher->Update(block, bytes_read); + } + + uint8_t digest[crypto::kSHA256Length]; + hasher->Finish(digest, base::size(digest)); + archived_binary->mutable_digests()->set_sha256(digest, base::size(digest)); +} + +void AnalyzeContainedBinary( + const scoped_refptr<BinaryFeatureExtractor>& binary_feature_extractor, + base::File* temp_file, + ClientDownloadRequest::ArchivedBinary* archived_binary) { + if (!binary_feature_extractor->ExtractImageFeaturesFromFile( + temp_file->Duplicate(), BinaryFeatureExtractor::kDefaultOptions, + archived_binary->mutable_image_headers(), + archived_binary->mutable_signature()->mutable_signed_data())) { + archived_binary->clear_image_headers(); + archived_binary->clear_signature(); + } else if (!archived_binary->signature().signed_data_size()) { + // No SignedData blobs were extracted, so clear the + // signature field. + archived_binary->clear_signature(); + } +} + +} // namespace + ArchiveAnalyzerResults::ArchiveAnalyzerResults() : success(false), has_executable(false), has_archive(false) {} @@ -17,4 +88,82 @@ ArchiveAnalyzerResults::~ArchiveAnalyzerResults() {} -} // namespace safe_browsing \ No newline at end of file +void UpdateArchiveAnalyzerResultsWithFile(base::FilePath path, + base::File* file, + bool is_encrypted, + ArchiveAnalyzerResults* results) { + scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor( + new BinaryFeatureExtractor()); + bool current_entry_is_executable; + +#if defined(OS_MACOSX) + uint32_t magic; + file->Read(0, reinterpret_cast<char*>(&magic), sizeof(uint32_t)); + + char dmg_header[DiskImageTypeSnifferMac::AppleDiskImageTrailerSize()]; + file->Read(0, dmg_header, + DiskImageTypeSnifferMac::AppleDiskImageTrailerSize()); + + current_entry_is_executable = + FileTypePolicies::GetInstance()->IsCheckedBinaryFile(path) || + MachOImageReader::IsMachOMagicValue(magic) || + DiskImageTypeSnifferMac::IsAppleDiskImageTrailer( + base::span<const uint8_t>( + reinterpret_cast<const uint8_t*>(dmg_header), + DiskImageTypeSnifferMac::AppleDiskImageTrailerSize())); + + // We can skip checking the trailer if we already know the file is executable. + if (!current_entry_is_executable) { + char trailer[DiskImageTypeSnifferMac::AppleDiskImageTrailerSize()]; + file->Seek(base::File::Whence::FROM_END, + DiskImageTypeSnifferMac::AppleDiskImageTrailerSize()); + file->ReadAtCurrentPos( + trailer, DiskImageTypeSnifferMac::AppleDiskImageTrailerSize()); + current_entry_is_executable = + DiskImageTypeSnifferMac::IsAppleDiskImageTrailer( + base::span<const uint8_t>( + reinterpret_cast<const uint8_t*>(trailer), + DiskImageTypeSnifferMac::AppleDiskImageTrailerSize())); + } + +#else + current_entry_is_executable = + FileTypePolicies::GetInstance()->IsCheckedBinaryFile(path); +#endif // OS_MACOSX + + if (FileTypePolicies::GetInstance()->IsArchiveFile(path)) { + DVLOG(2) << "Downloaded a zipped archive: " << path.value(); + results->has_archive = true; + results->archived_archive_filenames.push_back(path.BaseName()); + ClientDownloadRequest::ArchivedBinary* archived_archive = + results->archived_binary.Add(); + archived_archive->set_download_type(ClientDownloadRequest::ARCHIVE); + archived_archive->set_is_encrypted(is_encrypted); + SetLengthAndDigestForContainedFile(path, file, archived_archive); + } else if (current_entry_is_executable) { +#if defined(OS_MACOSX) + // This check prevents running analysis on .app files since they are + // really just directories and will cause binary feature extraction + // to fail. + if (path.Extension().compare(".app") == 0) { + DVLOG(2) << "Downloaded a zipped .app directory: " << path.value(); + } else { +#endif // OS_MACOSX + DVLOG(2) << "Downloaded a zipped executable: " << path.value(); + results->has_executable = true; + ClientDownloadRequest::ArchivedBinary* archived_binary = + results->archived_binary.Add(); + archived_binary->set_is_encrypted(is_encrypted); + archived_binary->set_download_type( + download_type_util::GetDownloadType(path)); + SetLengthAndDigestForContainedFile(path, file, archived_binary); + AnalyzeContainedBinary(binary_feature_extractor, file, archived_binary); +#if defined(OS_MACOSX) + } +#endif // OS_MACOSX + } else { + DVLOG(3) << "Ignoring non-binary file: " << path.value(); + } +} + +} // namespace safe_browsing
diff --git a/chrome/common/safe_browsing/archive_analyzer_results.h b/chrome/common/safe_browsing/archive_analyzer_results.h index 1a612fa3..374bfac 100644 --- a/chrome/common/safe_browsing/archive_analyzer_results.h +++ b/chrome/common/safe_browsing/archive_analyzer_results.h
@@ -14,6 +14,10 @@ #include "build/build_config.h" #include "components/safe_browsing/proto/csd.pb.h" +namespace base { +class File; +} + namespace safe_browsing { struct ArchiveAnalyzerResults { @@ -34,6 +38,13 @@ ~ArchiveAnalyzerResults(); }; +// Updates |results| with the results of inspecting |file|, given that it will +// be extracted to |path|. +void UpdateArchiveAnalyzerResultsWithFile(base::FilePath path, + base::File* file, + bool is_encrypted, + ArchiveAnalyzerResults* results); + } // namespace safe_browsing #endif // CHROME_COMMON_SAFE_BROWSING_ARCHIVE_ANALYZER_RESULTS_H_
diff --git a/chrome/common/safe_browsing/zip_analyzer.cc b/chrome/common/safe_browsing/zip_analyzer.cc index 037473084..e9071ec 100644 --- a/chrome/common/safe_browsing/zip_analyzer.cc +++ b/chrome/common/safe_browsing/zip_analyzer.cc
@@ -10,163 +10,19 @@ #include <memory> #include <set> -#include "base/i18n/streaming_utf8_validator.h" #include "base/logging.h" #include "base/macros.h" -#include "base/metrics/histogram_macros.h" #include "build/build_config.h" #include "chrome/common/safe_browsing/archive_analyzer_results.h" -#include "chrome/common/safe_browsing/binary_feature_extractor.h" -#include "chrome/common/safe_browsing/download_type_util.h" -#include "chrome/common/safe_browsing/file_type_policies.h" #include "components/safe_browsing/proto/csd.pb.h" -#include "crypto/secure_hash.h" -#include "crypto/sha2.h" #include "third_party/zlib/google/zip_reader.h" -#if defined(OS_MACOSX) -#include <mach-o/fat.h> -#include <mach-o/loader.h> -#include "base/containers/span.h" -#include "chrome/common/safe_browsing/disk_image_type_sniffer_mac.h" -#include "chrome/common/safe_browsing/mach_o_image_reader_mac.h" -#endif // OS_MACOSX - namespace safe_browsing { namespace zip_analyzer { -namespace { - -// A writer delegate that computes a SHA-256 hash digest over the data while -// writing it to a file. -class HashingFileWriter : public zip::FileWriterDelegate { - public: - explicit HashingFileWriter(base::File* file); - - // zip::FileWriterDelegate methods: - bool WriteBytes(const char* data, int num_bytes) override; - - void ComputeDigest(uint8_t* digest, size_t digest_length); - - private: - std::unique_ptr<crypto::SecureHash> sha256_; - - DISALLOW_COPY_AND_ASSIGN(HashingFileWriter); -}; - -HashingFileWriter::HashingFileWriter(base::File* file) - : zip::FileWriterDelegate(file), - sha256_(crypto::SecureHash::Create(crypto::SecureHash::SHA256)) {} - -bool HashingFileWriter::WriteBytes(const char* data, int num_bytes) { - if (!zip::FileWriterDelegate::WriteBytes(data, num_bytes)) - return false; - sha256_->Update(data, num_bytes); - return true; -} - -void HashingFileWriter::ComputeDigest(uint8_t* digest, size_t digest_length) { - sha256_->Finish(digest, digest_length); -} - -#if defined(OS_MACOSX) -bool StringIsMachOMagic(std::string bytes) { - if (bytes.length() < sizeof(uint32_t)) - return false; - - uint32_t magic; - memcpy(&magic, bytes.c_str(), sizeof(uint32_t)); - - return MachOImageReader::IsMachOMagicValue(magic); -} -#endif // OS_MACOSX - -void SetLengthAndDigestForContainedFile( - const base::FilePath& file_path, - zip::ZipReader* reader, - base::File* temp_file, - ClientDownloadRequest::ArchivedBinary* archived_binary) { - std::string file_basename(file_path.BaseName().AsUTF8Unsafe()); - if (base::StreamingUtf8Validator::Validate(file_basename)) - archived_binary->set_file_basename(file_basename); - archived_binary->set_download_type( - download_type_util::GetDownloadType(file_path)); - archived_binary->set_length(reader->current_entry_info()->original_size()); - HashingFileWriter writer(temp_file); - if (reader->ExtractCurrentEntry(&writer, - std::numeric_limits<uint64_t>::max())) { - uint8_t digest[crypto::kSHA256Length]; - writer.ComputeDigest(&digest[0], base::size(digest)); - archived_binary->mutable_digests()->set_sha256(&digest[0], - base::size(digest)); - } -} - -void AnalyzeContainedBinary( - const scoped_refptr<BinaryFeatureExtractor>& binary_feature_extractor, - base::File* temp_file, - ClientDownloadRequest::ArchivedBinary* archived_binary) { - if (!binary_feature_extractor->ExtractImageFeaturesFromFile( - temp_file->Duplicate(), BinaryFeatureExtractor::kDefaultOptions, - archived_binary->mutable_image_headers(), - archived_binary->mutable_signature()->mutable_signed_data())) { - archived_binary->clear_image_headers(); - archived_binary->clear_signature(); - } else if (!archived_binary->signature().signed_data_size()) { - // No SignedData blobs were extracted, so clear the signature field. - archived_binary->clear_signature(); - } -} - -// Helper class to get a certain size trailer of the extracted file. Extracts -// the file into memory, retaining only the last |trailer_size_bytes| bytes. -class TrailerWriterDelegate : public zip::WriterDelegate { - public: - explicit TrailerWriterDelegate(size_t trailer_size_bytes); - - // zip::WriterDelegate implementation: - bool PrepareOutput() override { return true; } - bool WriteBytes(const char* data, int num_bytes) override; - void SetTimeModified(const base::Time& time) override {} - - const std::string& trailer() { return trailer_; } - - private: - size_t trailer_size_bytes_; - std::string trailer_; -}; - -TrailerWriterDelegate::TrailerWriterDelegate(size_t trailer_size_bytes) - : trailer_size_bytes_(trailer_size_bytes), trailer_() {} - -bool TrailerWriterDelegate::WriteBytes(const char* data, int num_bytes) { - // TODO(drubery): WriterDelegate::WriteBytes should probably have |num_bytes| - // by a size_t. Investigate how difficult it would be to migrate - // implementations of WriterDelegate over. - base::CheckedNumeric<size_t> num_bytes_size(num_bytes); - if (!num_bytes_size.IsValid()) - return false; - - if (num_bytes_size.ValueOrDie() >= trailer_size_bytes_) { - trailer_ = std::string(data + num_bytes - trailer_size_bytes_, - trailer_size_bytes_); - } else { - trailer_.append(data, num_bytes); - if (trailer_.size() > trailer_size_bytes_) { - trailer_ = trailer_.substr(trailer_.size() - trailer_size_bytes_); - } - } - return true; -} - -} // namespace - void AnalyzeZipFile(base::File zip_file, base::File temp_file, ArchiveAnalyzerResults* results) { - std::set<base::FilePath> archived_archive_filenames; - scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor( - new BinaryFeatureExtractor()); zip::ZipReader reader; if (!reader.OpenFromPlatformFile(zip_file.GetPlatformFile())) { DVLOG(1) << "Failed to open zip file"; @@ -174,9 +30,6 @@ } bool advanced = true; -#if defined(OS_MACOSX) - bool zip_has_app_directory = false; -#endif // OS_MACOSX for (; reader.HasMore(); advanced = reader.AdvanceToNextEntry()) { if (!advanced) { DVLOG(1) << "Could not advance to next entry, aborting zip scan."; @@ -186,91 +39,17 @@ DVLOG(1) << "Failed to open current entry in zip file"; continue; } - const base::FilePath& file = reader.current_entry_info()->file_path(); - bool current_entry_is_executable; -#if defined(OS_MACOSX) - std::string magic; - reader.ExtractCurrentEntryToString(sizeof(uint32_t), &magic); - - std::string dmg_header; - reader.ExtractCurrentEntryToString( - DiskImageTypeSnifferMac::AppleDiskImageTrailerSize(), &dmg_header); - - current_entry_is_executable = - FileTypePolicies::GetInstance()->IsCheckedBinaryFile(file) || - StringIsMachOMagic(magic) || - DiskImageTypeSnifferMac::IsAppleDiskImageTrailer( - base::span<const uint8_t>( - reinterpret_cast<const uint8_t*>(dmg_header.c_str()), - dmg_header.size())); - - // We can skip checking the trailer if we already know the file is - // executable. - if (!current_entry_is_executable) { - TrailerWriterDelegate trailer_writer( - DiskImageTypeSnifferMac::AppleDiskImageTrailerSize()); - reader.ExtractCurrentEntry( - &trailer_writer, - FileTypePolicies::GetInstance()->GetMaxFileSizeToAnalyze("dmg")); - const std::string& trailer = trailer_writer.trailer(); - current_entry_is_executable = - DiskImageTypeSnifferMac::IsAppleDiskImageTrailer( - base::span<const uint8_t>( - reinterpret_cast<const uint8_t*>(trailer.data()), - trailer.size())); - } -#else - current_entry_is_executable = - FileTypePolicies::GetInstance()->IsCheckedBinaryFile(file); -#endif // OS_MACOSX - - if (FileTypePolicies::GetInstance()->IsArchiveFile(file)) { - DVLOG(2) << "Downloaded a zipped archive: " << file.value(); - results->has_archive = true; - archived_archive_filenames.insert(file.BaseName()); - ClientDownloadRequest::ArchivedBinary* archived_archive = - results->archived_binary.Add(); - archived_archive->set_download_type(ClientDownloadRequest::ARCHIVE); - archived_archive->set_is_encrypted( - reader.current_entry_info()->is_encrypted()); - SetLengthAndDigestForContainedFile(file, &reader, &temp_file, - archived_archive); - } else if (current_entry_is_executable) { -#if defined(OS_MACOSX) - // This check prevents running analysis on .app files since they are - // really just directories and will cause binary feature extraction - // to fail. - if (file.Extension().compare(".app") == 0) { - DVLOG(2) << "Downloaded a zipped .app directory: " << file.value(); - zip_has_app_directory = true; - } else { -#endif // OS_MACOSX - DVLOG(2) << "Downloaded a zipped executable: " << file.value(); - results->has_executable = true; - ClientDownloadRequest::ArchivedBinary* archived_binary = - results->archived_binary.Add(); - archived_binary->set_is_encrypted( - reader.current_entry_info()->is_encrypted()); - SetLengthAndDigestForContainedFile(file, &reader, &temp_file, - archived_binary); - AnalyzeContainedBinary(binary_feature_extractor, &temp_file, - archived_binary); -#if defined(OS_MACOSX) - } -#endif // OS_MACOSX - } else { - DVLOG(3) << "Ignoring non-binary file: " << file.value(); - } + // Clear the |temp_file| between extractions. + temp_file.Seek(base::File::Whence::FROM_BEGIN, 0); + temp_file.SetLength(0); + zip::FileWriterDelegate writer(&temp_file); + reader.ExtractCurrentEntry(&writer, std::numeric_limits<uint64_t>::max()); + UpdateArchiveAnalyzerResultsWithFile( + reader.current_entry_info()->file_path(), &temp_file, + reader.current_entry_info()->is_encrypted(), results); } -#if defined(OS_MACOSX) - UMA_HISTOGRAM_BOOLEAN( - "SBClientDownload." - "ZipFileContainsAppDirectory", - zip_has_app_directory); -#endif // OS_MACOSX - results->archived_archive_filenames.assign(archived_archive_filenames.begin(), - archived_archive_filenames.end()); + results->success = true; }
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index 8c22f2a6..e96b5a9 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -19,6 +19,8 @@ const char kChromeUIAboutHost[] = "about"; const char kChromeUIAboutURL[] = "chrome://about/"; const char kChromeUIAccessibilityHost[] = "accessibility"; +const char kChromeUIAppIconHost[] = "app-icon"; +const char kChromeUIAppIconURL[] = "chrome://app-icon/"; const char kChromeUIAppLauncherPageHost[] = "apps"; const char kChromeUIAppListStartPageURL[] = "chrome://app-list/"; const char kChromeUIAppsURL[] = "chrome://apps/"; @@ -291,6 +293,7 @@ #if defined(OS_CHROMEOS) const char kAccessibilitySubPage[] = "accessibility"; const char kBluetoothSubPage[] = "bluetoothDevices"; +const char kCrostiniSharedUsbDevicesSubPage[] = "crostini/sharedUsbDevices"; const char kDateTimeSubPage[] = "dateTime"; const char kDisplaySubPage[] = "display"; const char kHelpSubPage[] = "help";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index c1de504..597d61b 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -26,6 +26,8 @@ extern const char kChromeUIAboutHost[]; extern const char kChromeUIAboutURL[]; extern const char kChromeUIAccessibilityHost[]; +extern const char kChromeUIAppIconHost[]; +extern const char kChromeUIAppIconURL[]; extern const char kChromeUIAppLauncherPageHost[]; extern const char kChromeUIAppListStartPageURL[]; extern const char kChromeUIAppsURL[]; @@ -284,6 +286,7 @@ #if defined(OS_CHROMEOS) extern const char kAccessibilitySubPage[]; extern const char kBluetoothSubPage[]; +extern const char kCrostiniSharedUsbDevicesSubPage[]; extern const char kDateTimeSubPage[]; extern const char kDisplaySubPage[]; extern const char kHelpSubPage[];
diff --git a/chrome/credential_provider/gaiacp/scoped_user_profile.cc b/chrome/credential_provider/gaiacp/scoped_user_profile.cc index f57d221..79ff67d9 100644 --- a/chrome/credential_provider/gaiacp/scoped_user_profile.cc +++ b/chrome/credential_provider/gaiacp/scoped_user_profile.cc
@@ -29,6 +29,13 @@ const wchar_t kRegAccountsPath[] = L"Software\\Chromium\\Accounts"; #endif // defined(GOOGLE_CHROME_BUILD) +// Retry count when attempting to determine if the user's OS profile has +// been created. In slow envrionments, like VMs used for testing, it may +// take some time to create the OS profile so checks are done periodically. +// Ideally the OS would send out a notification when a profile is created and +// retrying would not be needed, but this notification does not exist. +const int kWaitForProfileCreationRetryCount = 30; + std::string GetEncryptedRefreshToken( base::win::ScopedHandle::Handle logon_handle, const base::DictionaryValue& properties) { @@ -216,8 +223,8 @@ wchar_t profile_dir[MAX_PATH]; bool created = false; - for (int i = 0; i < 10; ++i) { - Sleep(1000); + for (int i = 0; i < kWaitForProfileCreationRetryCount; ++i) { + ::Sleep(1000); DWORD length = base::size(profile_dir); if (::GetUserProfileDirectoryW(token_.Get(), profile_dir, &length)) { LOGFN(INFO) << "GetUserProfileDirectoryW " << i << " " << profile_dir; @@ -243,8 +250,8 @@ kRegAccountsPath); LOGFN(INFO) << "HKU\\" << key_name; - for (int i = 0; i < 10; ++i) { - Sleep(1000); + for (int i = 0; i < kWaitForProfileCreationRetryCount; ++i) { + ::Sleep(1000); LONG sts = key.Create(HKEY_USERS, key_name, KEY_READ | KEY_WRITE); if (sts == ERROR_SUCCESS) { LOGFN(INFO) << "Registry hive created " << i;
diff --git a/chrome/installer/mac/sign_app.sh.in b/chrome/installer/mac/sign_app.sh.in index 89b0028..23ad384 100644 --- a/chrome/installer/mac/sign_app.sh.in +++ b/chrome/installer/mac/sign_app.sh.in
@@ -63,6 +63,15 @@ app_mode_loader_app="${framework}/Resources/app_mode_loader.app" app_mode_loader="${app_mode_loader_app}/Contents/MacOS/app_mode_loader" +libraries_dir="${framework}/Libraries" +libraries=( + "${libraries_dir}/libEGL.dylib" + "${libraries_dir}/libGLESv2.dylib" + "${libraries_dir}/libswiftshader_libEGL.dylib" + "${libraries_dir}/libswiftshader_libGLESv2.dylib" + "${libraries_dir}/WidevineCdm/_platform_specific/mac_x64/libwidevinecdm.dylib" +) + # Embed the supplied provisioning profile. if [[ -z "${is_development}" ]]; then cp "${provisioning_profile}" "${contents_dir}/embedded.provisionprofile" @@ -109,6 +118,12 @@ codesign --verify --verbose=6 --strict "${framework}" codesign --verify --verbose=6 --deep "${helper_app}" +for library in "${libraries[@]}"; do + if [ -f "${library}" ]; then + codesign --verify --verbose=6 --deep "${library}" + fi +done + # Verify with spctl, which uses the same rules that Gatekeeper does for # validation. This is unreliable on 10.11 where syspolicyd caches assessments # and becomes confused when a bundle's CFExecutableName changes
diff --git a/chrome/installer/mac/sign_versioned_dir.sh.in b/chrome/installer/mac/sign_versioned_dir.sh.in index 7a853e3..2a784e2 100644 --- a/chrome/installer/mac/sign_versioned_dir.sh.in +++ b/chrome/installer/mac/sign_versioned_dir.sh.in
@@ -92,6 +92,15 @@ app_mode_loader_app="${framework}/Resources/app_mode_loader.app" app_mode_loader="${app_mode_loader_app}/Contents/MacOS/app_mode_loader" +libraries_dir="${framework}/Libraries" +libraries=( + "${libraries_dir}/libEGL.dylib" + "${libraries_dir}/libGLESv2.dylib" + "${libraries_dir}/libswiftshader_libEGL.dylib" + "${libraries_dir}/libswiftshader_libGLESv2.dylib" + "${libraries_dir}/WidevineCdm/_platform_specific/mac_x64/libwidevinecdm.dylib" +) + codesign_with_options "${crashpad_handler}" \ "${enforcement_flags_helpers}" \ "crashpad_handler" @@ -119,6 +128,15 @@ "${enforcement_flags_helpers}" \ "${xpc_bundle_id}" +# Sign the other Libraries. Some of these could be missing, if they are +# excluded from the build via GN args, so do test for their presence first. +for library in "${libraries[@]}"; do + if [ -f "${library}" ]; then + # No ${enforcement_flags_helpers} since they only apply to executables. + codesign_with_options "${library}" "" "$(basename "$library" .dylib)" + fi +done + # The framework is a dylib, so ${enforcement_flags_helpers} are meaningless. codesign_with_options "${framework}" "" "com.google.Chrome.framework" @@ -134,3 +152,9 @@ codesign_display_and_verify "${framework}" --deep --no-strict codesign_display_and_verify "${framework}" --strict codesign_display_and_verify "${helper_app}" --deep + +for library in "${libraries[@]}"; do + if [ -f "${library}" ]; then + codesign_display_and_verify "${library}" --deep + fi +done
diff --git a/chrome/installer/mini_installer/BUILD.gn b/chrome/installer/mini_installer/BUILD.gn index fc89ee275..931761f 100644 --- a/chrome/installer/mini_installer/BUILD.gn +++ b/chrome/installer/mini_installer/BUILD.gn
@@ -91,7 +91,6 @@ write_runtime_deps = chrome_runtime_deps data_deps = [ "//chrome", - "//chrome/chrome_proxy", ] }
diff --git a/chrome/installer/mini_installer/chrome.release b/chrome/installer/mini_installer/chrome.release index b236b680..01f69e5 100644 --- a/chrome/installer/mini_installer/chrome.release +++ b/chrome/installer/mini_installer/chrome.release
@@ -7,7 +7,6 @@ # Chrome Application dir entries, sorted alphabetically. # chrome.exe: %(ChromeDir)s\ -chrome_proxy.exe: %(ChromeDir)s\ # # Chrome version dir assembly manifest. # The name of this file must match the name of the version dir, so we cannot
diff --git a/chrome/installer/setup/install_worker.cc b/chrome/installer/setup/install_worker.cc index 36d8741db..b60cdef 100644 --- a/chrome/installer/setup/install_worker.cc +++ b/chrome/installer/setup/install_worker.cc
@@ -721,16 +721,14 @@ bool AppendPostInstallTasks(const InstallerState& installer_state, const base::FilePath& setup_path, - const base::FilePath& src_path, - const base::FilePath& temp_path, const base::Version* current_version, const base::Version& new_version, WorkItemList* post_install_task_list) { DCHECK(post_install_task_list); HKEY root = installer_state.root_key(); - const base::FilePath& target_path = installer_state.target_path(); - base::FilePath new_chrome_exe(target_path.Append(kChromeNewExe)); + base::FilePath new_chrome_exe( + installer_state.target_path().Append(installer::kChromeNewExe)); // Append work items that will only be executed if this was an update. // We update the 'opv' value with the current version that is active, @@ -781,12 +779,6 @@ root, clients_key, KEY_WOW64_32KEY, google_update::kRegRenameCmdField, product_rename_cmd.GetCommandLineString(), true); - // Delay deploying the new chrome_proxy while chrome is running. - in_use_update_work_items->AddCopyTreeWorkItem( - src_path.Append(kChromeProxyExe).value(), - target_path.Append(kChromeProxyNewExe).value(), temp_path.value(), - WorkItem::ALWAYS); - post_install_task_list->AddWorkItem(in_use_update_work_items.release()); } @@ -807,13 +799,6 @@ regular_update_work_items->AddDeleteRegValueWorkItem( root, clients_key, KEY_WOW64_32KEY, google_update::kRegRenameCmdField); - // Only copy chrome_proxy.exe directly when chrome.exe isn't in use to avoid - // different versions getting mixed up between the two binaries. - regular_update_work_items->AddCopyTreeWorkItem( - src_path.Append(kChromeProxyExe).value(), - target_path.Append(kChromeProxyExe).value(), temp_path.value(), - WorkItem::ALWAYS); - post_install_task_list->AddWorkItem(regular_update_work_items.release()); } @@ -954,8 +939,8 @@ AddUpdateBrandCodeWorkItem(installer_state, install_list); // Append the tasks that run after the installation. - AppendPostInstallTasks(installer_state, setup_path, src_path, temp_path, - current_version, new_version, install_list); + AppendPostInstallTasks(installer_state, setup_path, current_version, + new_version, install_list); } void AddNativeNotificationWorkItems(
diff --git a/chrome/installer/setup/install_worker.h b/chrome/installer/setup/install_worker.h index b8e6c0d..223badd0 100644 --- a/chrome/installer/setup/install_worker.h +++ b/chrome/installer/setup/install_worker.h
@@ -62,10 +62,9 @@ // |current_version| can be NULL to indicate no Chrome is currently installed. bool AppendPostInstallTasks(const InstallerState& installer_state, const base::FilePath& setup_path, - const base::FilePath& src_path, - const base::FilePath& temp_path, const base::Version* current_version, const base::Version& new_version, + const base::FilePath& temp_path, WorkItemList* post_install_task_list); // Builds the complete WorkItemList used to build the set of installation steps
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc index 7adefe1..e49e3b3 100644 --- a/chrome/installer/setup/setup_main.cc +++ b/chrome/installer/setup/setup_main.cc
@@ -402,12 +402,11 @@ // This function is called when --rename-chrome-exe option is specified on // setup.exe command line. This function assumes an in-use update has happened -// for Chrome so there should be files called new_chrome.exe and -// new_chrome_proxy.exe on the file system and a key called 'opv' in the -// registry. This function will move new_chrome.exe to chrome.exe, -// new_chrome_proxy.exe to chrome_proxy.exe and delete 'opv' key in one atomic -// operation. This function also deletes elevation policies associated with the -// old version if they exist. |setup_exe| is the path to the current executable. +// for Chrome so there should be a file called new_chrome.exe on the file +// system and a key called 'opv' in the registry. This function will move +// new_chrome.exe to chrome.exe and delete 'opv' key in one atomic operation. +// This function also deletes elevation policies associated with the old version +// if they exist. |setup_exe| is the path to the current executable. installer::InstallStatus RenameChromeExecutables( const base::FilePath& setup_exe, const InstallationState& original_state, @@ -416,12 +415,6 @@ base::FilePath chrome_exe(target_path.Append(installer::kChromeExe)); base::FilePath chrome_new_exe(target_path.Append(installer::kChromeNewExe)); base::FilePath chrome_old_exe(target_path.Append(installer::kChromeOldExe)); - base::FilePath chrome_proxy_exe( - target_path.Append(installer::kChromeProxyExe)); - base::FilePath chrome_proxy_new_exe( - target_path.Append(installer::kChromeProxyNewExe)); - base::FilePath chrome_proxy_old_exe( - target_path.Append(installer::kChromeProxyOldExe)); // Create a temporary backup directory on the same volume as chrome.exe so // that moving in-use files doesn't lead to trouble. @@ -445,16 +438,6 @@ WorkItem::ALWAYS_MOVE); install_list->AddDeleteTreeWorkItem(chrome_new_exe, temp_path.path()); - // Move chrome_proxy.exe to old_chrome_proxy.exe, then move - // new_chrome_proxy.exe to chrome_proxy.exe. - install_list->AddMoveTreeWorkItem( - chrome_proxy_exe.value(), chrome_proxy_old_exe.value(), - temp_path.path().value(), WorkItem::ALWAYS_MOVE); - install_list->AddMoveTreeWorkItem( - chrome_proxy_new_exe.value(), chrome_proxy_exe.value(), - temp_path.path().value(), WorkItem::ALWAYS_MOVE); - install_list->AddDeleteTreeWorkItem(chrome_proxy_new_exe, temp_path.path()); - // Add work items to delete Chrome's "opv", "cpv", and "cmd" values. // TODO(grt): Clean this up; https://crbug.com/577816. HKEY reg_root = installer_state->root_key(); @@ -471,8 +454,6 @@ // old_chrome.exe is still in use in most cases, so ignore failures here. install_list->AddDeleteTreeWorkItem(chrome_old_exe, temp_path.path()) ->set_best_effort(true); - install_list->AddDeleteTreeWorkItem(chrome_proxy_old_exe, temp_path.path()) - ->set_best_effort(true); installer::InstallStatus ret = installer::RENAME_SUCCESSFUL; if (install_list->Do()) {
diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc index e3f9cc4..b6142a7b 100644 --- a/chrome/installer/util/util_constants.cc +++ b/chrome/installer/util/util_constants.cc
@@ -196,9 +196,6 @@ const wchar_t kChromeExe[] = L"chrome.exe"; const wchar_t kChromeNewExe[] = L"new_chrome.exe"; const wchar_t kChromeOldExe[] = L"old_chrome.exe"; -const wchar_t kChromeProxyExe[] = L"chrome_proxy.exe"; -const wchar_t kChromeProxyNewExe[] = L"new_chrome_proxy.exe"; -const wchar_t kChromeProxyOldExe[] = L"old_chrome_proxy.exe"; const wchar_t kCmdOnOsUpgrade[] = L"on-os-upgrade"; const wchar_t kCmdStoreDMToken[] = L"store-dmtoken"; const wchar_t kEulaSentinelFile[] = L"EULA Accepted";
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h index a6f41d10..c16065e 100644 --- a/chrome/installer/util/util_constants.h +++ b/chrome/installer/util/util_constants.h
@@ -206,9 +206,6 @@ extern const wchar_t kChromeExe[]; extern const wchar_t kChromeNewExe[]; extern const wchar_t kChromeOldExe[]; -extern const wchar_t kChromeProxyExe[]; -extern const wchar_t kChromeProxyNewExe[]; -extern const wchar_t kChromeProxyOldExe[]; extern const wchar_t kCmdOnOsUpgrade[]; extern const wchar_t kCmdStoreDMToken[]; extern const wchar_t kEulaSentinelFile[];
diff --git a/chrome/notification_helper/OWNERS b/chrome/notification_helper/OWNERS index ae9c4f8..0d991fbf 100644 --- a/chrome/notification_helper/OWNERS +++ b/chrome/notification_helper/OWNERS
@@ -1,4 +1,3 @@ -chengx@chromium.org finnur@chromium.org grt@chromium.org robliao@chromium.org
diff --git a/chrome/renderer/content_settings_observer.cc b/chrome/renderer/content_settings_observer.cc index 944f7f4..f9653b3 100644 --- a/chrome/renderer/content_settings_observer.cc +++ b/chrome/renderer/content_settings_observer.cc
@@ -96,7 +96,7 @@ return CONTENT_SETTING_DEFAULT; } -bool IsScriptDisabledForPreview(const content::RenderFrame* render_frame) { +bool IsScriptDisabledForPreview(content::RenderFrame* render_frame) { return render_frame->GetPreviewsState() & content::NOSCRIPT_ON; }
diff --git a/chrome/renderer/extensions/extension_localization_peer.cc b/chrome/renderer/extensions/extension_localization_peer.cc index c1b6170..b5d16f6 100644 --- a/chrome/renderer/extensions/extension_localization_peer.cc +++ b/chrome/renderer/extensions/extension_localization_peer.cc
@@ -25,8 +25,8 @@ public: explicit StringData(const std::string& data) : data_(data) {} - const char* payload() const override { return data_.data(); } - int length() const override { return data_.size(); } + const char* payload() override { return data_.data(); } + int length() override { return data_.size(); } private: const std::string data_; @@ -115,8 +115,7 @@ original_peer_->OnCompletedRequest(status); } -scoped_refptr<base::TaskRunner> ExtensionLocalizationPeer::GetTaskRunner() - const { +scoped_refptr<base::TaskRunner> ExtensionLocalizationPeer::GetTaskRunner() { return original_peer_->GetTaskRunner(); }
diff --git a/chrome/renderer/extensions/extension_localization_peer.h b/chrome/renderer/extensions/extension_localization_peer.h index 595fdbce..62c3f05 100644 --- a/chrome/renderer/extensions/extension_localization_peer.h +++ b/chrome/renderer/extensions/extension_localization_peer.h
@@ -46,7 +46,7 @@ void OnTransferSizeUpdated(int transfer_size_diff) override; void OnCompletedRequest( const network::URLLoaderCompletionStatus& status) override; - scoped_refptr<base::TaskRunner> GetTaskRunner() const override; + scoped_refptr<base::TaskRunner> GetTaskRunner() override; private: friend class ExtensionLocalizationPeerTest;
diff --git a/chrome/renderer/extensions/extension_localization_peer_unittest.cc b/chrome/renderer/extensions/extension_localization_peer_unittest.cc index e8226ae3..438ca90 100644 --- a/chrome/renderer/extensions/extension_localization_peer_unittest.cc +++ b/chrome/renderer/extensions/extension_localization_peer_unittest.cc
@@ -80,7 +80,7 @@ MOCK_METHOD1(OnTransferSizeUpdated, void(int transfer_size_diff)); MOCK_METHOD1(OnCompletedRequest, void(const network::URLLoaderCompletionStatus& status)); - scoped_refptr<base::TaskRunner> GetTaskRunner() const override { + scoped_refptr<base::TaskRunner> GetTaskRunner() override { NOTREACHED(); return nullptr; }
diff --git a/chrome/renderer/security_filter_peer.cc b/chrome/renderer/security_filter_peer.cc index 391c63e..335bb02 100644 --- a/chrome/renderer/security_filter_peer.cc +++ b/chrome/renderer/security_filter_peer.cc
@@ -115,7 +115,7 @@ original_peer_->OnCompletedRequest(ok_status); } -scoped_refptr<base::TaskRunner> SecurityFilterPeer::GetTaskRunner() const { +scoped_refptr<base::TaskRunner> SecurityFilterPeer::GetTaskRunner() { return original_peer_->GetTaskRunner(); }
diff --git a/chrome/renderer/security_filter_peer.h b/chrome/renderer/security_filter_peer.h index 7254eef..81e94a8 100644 --- a/chrome/renderer/security_filter_peer.h +++ b/chrome/renderer/security_filter_peer.h
@@ -44,7 +44,7 @@ void OnTransferSizeUpdated(int transfer_size_diff) override; void OnCompletedRequest( const network::URLLoaderCompletionStatus& status) override; - scoped_refptr<base::TaskRunner> GetTaskRunner() const override; + scoped_refptr<base::TaskRunner> GetTaskRunner() override; private: SecurityFilterPeer(std::unique_ptr<content::RequestPeer> peer,
diff --git a/chrome/renderer/supervised_user/OWNERS b/chrome/renderer/supervised_user/OWNERS index b2674f18..33a7a97 100644 --- a/chrome/renderer/supervised_user/OWNERS +++ b/chrome/renderer/supervised_user/OWNERS
@@ -1,4 +1,5 @@ escordeiro@chromium.org +menegola@chromium.org pam@chromium.org treib@chromium.org
diff --git a/chrome/service/cloud_print/printer_job_handler.cc b/chrome/service/cloud_print/printer_job_handler.cc index e672f06..887236dc 100644 --- a/chrome/service/cloud_print/printer_job_handler.cc +++ b/chrome/service/cloud_print/printer_job_handler.cc
@@ -256,18 +256,14 @@ void PrinterJobHandler::OnJobSpoolSucceeded(const PlatformJobId& job_id) { DCHECK(CurrentlyOnPrintThread()); - job_spooler_->AddRef(); - print_thread_.task_runner()->ReleaseSoon(FROM_HERE, job_spooler_.get()); - job_spooler_ = NULL; + print_thread_.task_runner()->ReleaseSoon(FROM_HERE, std::move(job_spooler_)); job_handler_task_runner_->PostTask( FROM_HERE, base::BindOnce(&PrinterJobHandler::JobSpooled, this, job_id)); } void PrinterJobHandler::OnJobSpoolFailed() { DCHECK(CurrentlyOnPrintThread()); - job_spooler_->AddRef(); - print_thread_.task_runner()->ReleaseSoon(FROM_HERE, job_spooler_.get()); - job_spooler_ = NULL; + print_thread_.task_runner()->ReleaseSoon(FROM_HERE, std::move(job_spooler_)); VLOG(1) << "CP_CONNECTOR: Job failed (spool failed)"; job_handler_task_runner_->PostTask( FROM_HERE,
diff --git a/chrome/services/app_service/public/cpp/app_registry_cache.cc b/chrome/services/app_service/public/cpp/app_registry_cache.cc index 83053dcd..b1546ea 100644 --- a/chrome/services/app_service/public/cpp/app_registry_cache.cc +++ b/chrome/services/app_service/public/cpp/app_registry_cache.cc
@@ -77,4 +77,12 @@ } } +apps::mojom::AppType AppRegistryCache::GetAppType(const std::string& app_id) { + auto iter = states_.find(app_id); + if (iter != states_.end()) { + return iter->second->app_type; + } + return apps::mojom::AppType::kUnknown; +} + } // namespace apps
diff --git a/chrome/services/app_service/public/cpp/app_registry_cache.h b/chrome/services/app_service/public/cpp/app_registry_cache.h index 710cc18..7e1bab8 100644 --- a/chrome/services/app_service/public/cpp/app_registry_cache.h +++ b/chrome/services/app_service/public/cpp/app_registry_cache.h
@@ -69,6 +69,8 @@ // merges the cached states with the deltas. void OnApps(std::vector<apps::mojom::AppPtr> deltas); + apps::mojom::AppType GetAppType(const std::string& app_id); + // Calls f, a void-returning function whose arguments are (const // apps::AppUpdate&), on each app in the cache. The AppUpdate (a // state-and-delta) is equivalent to the delta being "all unknown" or "no
diff --git a/chrome/services/app_service/public/cpp/app_update.cc b/chrome/services/app_service/public/cpp/app_update.cc index db04497d..c15b24c 100644 --- a/chrome/services/app_service/public/cpp/app_update.cc +++ b/chrome/services/app_service/public/cpp/app_update.cc
@@ -27,6 +27,9 @@ if (delta->show_in_launcher != apps::mojom::OptionalBool::kUnknown) { state->show_in_launcher = delta->show_in_launcher; } + if (delta->show_in_search != apps::mojom::OptionalBool::kUnknown) { + state->show_in_search = delta->show_in_search; + } // When adding new fields to the App Mojo type, this function should also be // updated. @@ -97,4 +100,15 @@ (delta_->show_in_launcher != state_->show_in_launcher); } +apps::mojom::OptionalBool AppUpdate::ShowInSearch() const { + return (delta_->show_in_search != apps::mojom::OptionalBool::kUnknown) + ? delta_->show_in_search + : state_->show_in_search; +} + +bool AppUpdate::ShowInSearchChanged() const { + return (delta_->show_in_search != apps::mojom::OptionalBool::kUnknown) && + (delta_->show_in_search != state_->show_in_search); +} + } // namespace apps
diff --git a/chrome/services/app_service/public/cpp/app_update.h b/chrome/services/app_service/public/cpp/app_update.h index ac875ac8..2a7aa0f 100644 --- a/chrome/services/app_service/public/cpp/app_update.h +++ b/chrome/services/app_service/public/cpp/app_update.h
@@ -58,6 +58,9 @@ apps::mojom::OptionalBool ShowInLauncher() const; bool ShowInLauncherChanged() const; + apps::mojom::OptionalBool ShowInSearch() const; + bool ShowInSearchChanged() const; + private: const apps::mojom::AppPtr& state_; const apps::mojom::AppPtr& delta_;
diff --git a/chrome/services/app_service/public/cpp/app_update_unittest.cc b/chrome/services/app_service/public/cpp/app_update_unittest.cc index f66929d..26dfdde 100644 --- a/chrome/services/app_service/public/cpp/app_update_unittest.cc +++ b/chrome/services/app_service/public/cpp/app_update_unittest.cc
@@ -135,4 +135,24 @@ EXPECT_FALSE(u.IconKey().is_null()); EXPECT_EQ(apps::mojom::IconType::kExtension, u.IconKey()->icon_type); EXPECT_FALSE(u.IconKeyChanged()); + + // ShowInSearch tests. + + EXPECT_EQ(apps::mojom::OptionalBool::kUnknown, u.ShowInSearch()); + EXPECT_FALSE(u.ShowInSearchChanged()); + + state->show_in_search = apps::mojom::OptionalBool::kFalse; + + EXPECT_EQ(apps::mojom::OptionalBool::kFalse, u.ShowInSearch()); + EXPECT_FALSE(u.ShowInSearchChanged()); + + delta->show_in_search = apps::mojom::OptionalBool::kTrue; + + EXPECT_EQ(apps::mojom::OptionalBool::kTrue, u.ShowInSearch()); + EXPECT_TRUE(u.ShowInSearchChanged()); + + apps::AppUpdate::Merge(state.get(), delta); + + EXPECT_EQ(apps::mojom::OptionalBool::kTrue, u.ShowInSearch()); + EXPECT_FALSE(u.ShowInSearchChanged()); }
diff --git a/chrome/services/app_service/public/mojom/types.mojom b/chrome/services/app_service/public/mojom/types.mojom index 85c2f71..5dfbd67 100644 --- a/chrome/services/app_service/public/mojom/types.mojom +++ b/chrome/services/app_service/public/mojom/types.mojom
@@ -16,7 +16,11 @@ Readiness readiness; string? name; IconKey? icon_key; + + // TODO(nigeltao): be more principled, instead of ad hoc show_in_xxx and + // show_in_yyy fields? OptionalBool show_in_launcher; + OptionalBool show_in_search; // When adding new fields, also update the Merge method and other helpers in // chrome/services/app_service/public/cpp/app_update.* @@ -76,6 +80,7 @@ enum LaunchSource { kUnknown, - kFromAppList, - kFromAppListSearch, + kFromAppListGrid, // Grid of apps, not the search box. + kFromAppListRecommendation, // Query-less recommendations (smaller icons). + kFromAppListQueryResult, // Query-dependent results (larger icons). };
diff --git a/chrome/services/file_util/public/cpp/sandboxed_zip_analyzer_unittest.cc b/chrome/services/file_util/public/cpp/sandboxed_zip_analyzer_unittest.cc index 2de40db..6fc4074 100644 --- a/chrome/services/file_util/public/cpp/sandboxed_zip_analyzer_unittest.cc +++ b/chrome/services/file_util/public/cpp/sandboxed_zip_analyzer_unittest.cc
@@ -382,9 +382,6 @@ "mach_o/zipped-app-two-executables-one-signed.zip"), &results); - EXPECT_THAT(histograms.GetAllSamples(kAppInZipHistogramName), - testing::ElementsAre(base::Bucket(/*bucket=*/true, /*count=*/1))); - EXPECT_TRUE(results.success); EXPECT_TRUE(results.has_executable); EXPECT_FALSE(results.has_archive);
diff --git a/chrome/services/isolated_xr_device/OWNERS b/chrome/services/isolated_xr_device/OWNERS index b19eacaf..d11cbac2 100644 --- a/chrome/services/isolated_xr_device/OWNERS +++ b/chrome/services/isolated_xr_device/OWNERS
@@ -1,6 +1,9 @@ billorr@chromium.org -mthiesse@chromium.org ddorwin@chromium.org +klausw@chromium.org per-file manifest.json=set noparent per-file manifest.json=file://ipc/SECURITY_OWNERS + +# TEAM: xr-dev@chromium.org +# COMPONENT: Internals>XR
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 7f7a6e27..f705736 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -481,7 +481,6 @@ "$root_gen_dir/ui/login/login_resources.pak", "$root_out_dir/chromevox_test_data/", "$root_out_dir/content_shell.pak", - "$root_out_dir/locales/", "$root_out_dir/resources/chromeos/", ] @@ -913,6 +912,7 @@ "../browser/ui/search/local_ntp_doodle_browsertest.cc", "../browser/ui/search/local_ntp_js_browsertest.cc", "../browser/ui/search/local_ntp_one_google_bar_browsertest.cc", + "../browser/ui/search/local_ntp_promos_browsertest.cc", "../browser/ui/search/local_ntp_voice_search_browsertest.cc", "../browser/ui/search/new_tab_page_navigation_throttle_browsertest.cc", "../browser/ui/search_engines/search_engine_tab_helper_browsertest.cc", @@ -1546,6 +1546,7 @@ "../browser/ui/views/media_router/media_router_ui_browsertest.cc", "../browser/ui/views/media_router/presentation_receiver_window_view_browsertest.cc", "../browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc", + "../browser/ui/views/page_action/zoom_view_browsertest.cc", "../browser/ui/views/page_info/page_info_bubble_view_browsertest.cc", "../browser/ui/views/passwords/password_bubble_browsertest.cc", "../browser/ui/views/passwords/password_dialog_view_browsertest.cc", @@ -2693,6 +2694,7 @@ "../browser/signin/chrome_signin_status_metrics_provider_delegate_unittest.cc", "../browser/signin/chrome_signin_url_loader_throttle_unittest.cc", "../browser/signin/local_auth_unittest.cc", + "../browser/signin/signin_profile_attributes_updater_unittest.cc", "../browser/signin/signin_status_metrics_provider_chromeos_unittest.cc", "../browser/signin/test_signin_client_builder.cc", "../browser/signin/test_signin_client_builder.h", @@ -3062,6 +3064,9 @@ } else { # !is_android sources += [ + # Badging isn't supported on Android. + "../browser/badging/badge_manager_unittest.cc", + # Bookmark export/import are handled via the BookmarkColumns # ContentProvider. "../browser/bookmarks/bookmark_html_writer_unittest.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java index 3106da3c..26abd7b 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java
@@ -71,13 +71,13 @@ /** * Adds a fake account to the OS. */ - public void addFakeAccountToOs(String username, String password) { + public void addFakeAccountToOs(String username) { if (TextUtils.isEmpty(username)) { throw new IllegalArgumentException("ERROR: must specify account"); } Account account = new Account(username, GOOGLE_ACCOUNT_TYPE); - AccountHolder accountHolder = AccountHolder.builder(account).password(password).build(); + AccountHolder accountHolder = AccountHolder.builder(account).build(); mFakeAccountManagerDelegate.addAccountHolderBlocking(accountHolder); }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java index 75f34fc..60512e5 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
@@ -12,6 +12,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.chrome.browser.signin.AccountTrackerService; import org.chromium.chrome.browser.signin.OAuth2TokenService; +import org.chromium.chrome.browser.signin.SigninHelper; import org.chromium.components.signin.AccountIdProvider; import org.chromium.components.signin.AccountManagerFacade; import org.chromium.components.signin.ChromeSigninController; @@ -47,6 +48,7 @@ AccountManagerFacade.overrideAccountManagerFacadeForTests(sAccountManager); overrideAccountIdProvider(); resetSigninState(); + SigninHelper.resetSharedPrefs(); } /** @@ -59,6 +61,7 @@ } sAddedAccounts.clear(); resetSigninState(); + SigninHelper.resetSharedPrefs(); } /** @@ -83,8 +86,7 @@ AccountHolder accountHolder = AccountHolder.builder(account).alwaysAccept(true).build(); sAccountManager.addAccountHolderBlocking(accountHolder); sAddedAccounts.add(accountHolder); - ThreadUtils.runOnUiThreadBlocking( - () -> AccountTrackerService.get().invalidateAccountSeedStatus(true)); + ThreadUtils.runOnUiThreadBlocking(SigninTestUtil::seedAccounts); return account; } @@ -95,11 +97,23 @@ Account account = addTestAccount(); ThreadUtils.runOnUiThreadBlocking(() -> { ChromeSigninController.get().setSignedInAccountName(DEFAULT_ACCOUNT); - AccountTrackerService.get().invalidateAccountSeedStatus(true); + seedAccounts(); }); return account; } + private static void seedAccounts() { + AccountIdProvider accountIdProvider = AccountIdProvider.getInstance(); + Account[] accounts = sAccountManager.getAccountsSyncNoThrow(); + String[] accountNames = new String[accounts.length]; + String[] accountIds = new String[accounts.length]; + for (int i = 0; i < accounts.length; i++) { + accountNames[i] = accounts[i].name; + accountIds[i] = accountIdProvider.getAccountId(accounts[i].name); + } + AccountTrackerService.get().syncForceRefreshForTest(accountIds, accountNames); + } + private static void overrideAccountIdProvider() { ThreadUtils.runOnUiThreadBlocking(() -> { AccountIdProvider.setInstanceForTest(new AccountIdProvider() {
diff --git a/chrome/test/chromedriver/chrome/version.cc b/chrome/test/chromedriver/chrome/version.cc index 69ebe42..93c492fb 100644 --- a/chrome/test/chromedriver/chrome/version.cc +++ b/chrome/test/chromedriver/chrome/version.cc
@@ -13,6 +13,8 @@ } // namespace +const int kMinimumSupportedChromeMajorVersion = + kMinimumSupportedChromeVersion[0]; const int kMinimumSupportedChromeBuildNo = kMinimumSupportedChromeVersion[2]; std::string GetMinimumSupportedChromeVersion() {
diff --git a/chrome/test/chromedriver/chrome/version.h b/chrome/test/chromedriver/chrome/version.h index 1618b97..1b4113e 100644 --- a/chrome/test/chromedriver/chrome/version.h +++ b/chrome/test/chromedriver/chrome/version.h
@@ -8,6 +8,7 @@ #include <string> extern const int kMinimumSupportedChromeBuildNo; +extern const int kMinimumSupportedChromeMajorVersion; std::string GetMinimumSupportedChromeVersion();
diff --git a/chrome/test/chromedriver/chrome_launcher.cc b/chrome/test/chromedriver/chrome_launcher.cc index 8bbaa71..17b2abe 100644 --- a/chrome/test/chromedriver/chrome_launcher.cc +++ b/chrome/test/chromedriver/chrome_launcher.cc
@@ -158,8 +158,11 @@ LOG(WARNING) << "excluding remote-debugging-port switch is not supported"; } if (switches.HasSwitch("user-data-dir")) { - *user_data_dir = - base::FilePath(switches.GetSwitchValueNative("user-data-dir")); + base::FilePath::StringType userDataDir = + switches.GetSwitchValueNative("user-data-dir"); + if (userDataDir.empty()) + return Status(kInvalidArgument, "user data dir can not be empty"); + *user_data_dir = base::FilePath(userDataDir); } else { command.AppendArg("data:,"); if (!user_data_dir_temp_dir->CreateUniqueTempDir()) @@ -201,7 +204,8 @@ const SyncWebSocketFactory& socket_factory, const Capabilities* capabilities, int wait_time, - std::unique_ptr<DevToolsHttpClient>* user_client) { + std::unique_ptr<DevToolsHttpClient>* user_client, + bool* retry) { std::unique_ptr<DeviceMetrics> device_metrics; if (capabilities && capabilities->device_metrics) device_metrics.reset(new DeviceMetrics(*capabilities->device_metrics)); @@ -245,14 +249,20 @@ browser_info->android_package.c_str())); } + *retry = true; if (cmd_line->HasSwitch("disable-build-check")) { LOG(WARNING) << "You are using an unsupported command-line switch: " "--disable-build-check. Please don't report bugs that " "cannot be reproduced with this switch removed."; - } else if (browser_info->build_no < kMinimumSupportedChromeBuildNo) { - return Status( - kSessionNotCreated, - "Chrome version must be >= " + GetMinimumSupportedChromeVersion()); + } else if (browser_info->major_version < + kMinimumSupportedChromeMajorVersion || + browser_info->major_version > + (kMinimumSupportedChromeMajorVersion + 3)) { + *retry = false; + return Status(kSessionNotCreated, + base::StringPrintf("Chrome version must be between %d and %d", + kMinimumSupportedChromeMajorVersion, + kMinimumSupportedChromeMajorVersion + 3)); } while (base::TimeTicks::Now() < deadline) { @@ -314,9 +324,10 @@ std::unique_ptr<Chrome>* chrome) { Status status(kOk); std::unique_ptr<DevToolsHttpClient> devtools_http_client; + bool retry = true; status = WaitForDevToolsAndCheckVersion( capabilities.debugger_address, factory, socket_factory, &capabilities, 60, - &devtools_http_client); + &devtools_http_client, &retry); if (status.IsError()) { return Status(kUnknownError, "cannot connect to chrome at " + capabilities.debugger_address.ToString(), @@ -354,6 +365,7 @@ Status status = Status(kOk); std::vector<std::string> extension_bg_pages; int devtools_port = 0; + bool retry = true; if (capabilities.switches.HasSwitch("remote-debugging-port")) { std::string port_switch = @@ -452,7 +464,10 @@ if (status.IsOk()) { status = WaitForDevToolsAndCheckVersion( NetAddress(devtools_port), factory, socket_factory, &capabilities, 1, - &devtools_http_client); + &devtools_http_client, &retry); + if (!retry) { + break; + } } if (status.IsOk()) { break; @@ -571,9 +586,10 @@ } std::unique_ptr<DevToolsHttpClient> devtools_http_client; + bool retry = true; status = WaitForDevToolsAndCheckVersion(NetAddress(devtools_port), factory, socket_factory, &capabilities, 60, - &devtools_http_client); + &devtools_http_client, &retry); if (status.IsError()) { device->TearDown(); return status; @@ -625,10 +641,10 @@ #endif std::unique_ptr<DevToolsHttpClient> devtools_http_client; - status = - WaitForDevToolsAndCheckVersion(NetAddress(0), factory, socket_factory, - &capabilities, 1, &devtools_http_client); - + bool retry = true; + status = WaitForDevToolsAndCheckVersion(NetAddress(0), factory, + socket_factory, &capabilities, 1, + &devtools_http_client, &retry); std::unique_ptr<DevToolsClient> devtools_websocket_client; status = CreateBrowserwideDevToolsClientAndConnect( NetAddress(0), capabilities.perf_logging_prefs, socket_factory,
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py index d724bae..20ae6d8c 100755 --- a/chrome/test/chromedriver/test/run_py_tests.py +++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -1762,33 +1762,58 @@ self._driver.FindElement('id', 'top') thread.join() + @staticmethod + def MakeRedImageTestScript(png_data_in_base64): + """Used by the takeElementScreenshot* tests to load the PNG image via a data + URI, analyze it, and PASS/FAIL depending on whether all the pixels are all + rgb(255,0,0).""" + return ( + """ + const resolve = arguments[arguments.length - 1]; + const image = new Image(); + image.onload = () => { + var canvas = document.createElement('canvas'); + canvas.width = image.width; + canvas.height = image.height; + var context = canvas.getContext('2d'); + context.drawImage(image, 0, 0); + const pixels = + context.getImageData(0, 0, image.width, image.height).data; + for (let i = 0; i < pixels.length; i += 4) { + if (pixels[i + 0] != 255 || // Red + pixels[i + 1] != 0 || // Green + pixels[i + 2] != 0) { // Blue + resolve('FAIL: Bad pixel at offset ' + i + ': rgb(' + + pixels.slice(i, i + 3).join(',') + ')'); + return; + } + } + resolve('PASS'); + }; + image.src = 'data:image/png;base64,%s'; + """ % png_data_in_base64.replace("'", "\\'")) + def testTakeElementScreenshot(self): self._driver.Load(self.GetHttpUrlForFile( '/chromedriver/page_with_redbox.html')) - elementScreenshot = self._driver.FindElement( + elementScreenshotPNGBase64 = self._driver.FindElement( 'id', 'box').TakeElementScreenshot() - self.assertIsNotNone(elementScreenshot) - dataActualScreenshot = base64.b64decode(elementScreenshot) - filenameOfGoldenScreenshot = os.path.join(chrome_paths.GetTestData(), - 'chromedriver/goldenScreenshots', - 'redboxScreenshot.png') - imageGoldenScreenshot = open(filenameOfGoldenScreenshot, 'rb').read() - self.assertEquals(imageGoldenScreenshot, dataActualScreenshot) + self.assertIsNotNone(elementScreenshotPNGBase64) + analysisResult = self._driver.ExecuteAsyncScript( + ChromeDriverTest.MakeRedImageTestScript(elementScreenshotPNGBase64)) + self.assertEquals('PASS', analysisResult) def testTakeElementScreenshotInIframe(self): self._driver.Load(self.GetHttpUrlForFile( '/chromedriver/page_with_iframe_redbox.html')) frame = self._driver.FindElement('id', 'frm') self._driver.SwitchToFrame(frame) - elementScreenshot = self._driver.FindElement( + elementScreenshotPNGBase64 = self._driver.FindElement( 'id', 'box').TakeElementScreenshot() - self.assertIsNotNone(elementScreenshot) - dataActualScreenshot = base64.b64decode(elementScreenshot) - filenameOfGoldenScreenshot = os.path.join(chrome_paths.GetTestData(), - 'chromedriver/goldenScreenshots', - 'redboxScreenshot.png') - imageGoldenScreenshot= open(filenameOfGoldenScreenshot, 'rb').read() - self.assertEquals(imageGoldenScreenshot, dataActualScreenshot) + self.assertIsNotNone(elementScreenshotPNGBase64) + analysisResult = self._driver.ExecuteAsyncScript( + ChromeDriverTest.MakeRedImageTestScript(elementScreenshotPNGBase64)) + self.assertEquals('PASS', analysisResult) def testGenerateTestReport(self): self._driver.Load(self.GetHttpUrlForFile(
diff --git a/chrome/test/chromedriver/window_commands.cc b/chrome/test/chromedriver/window_commands.cc index 97d96e0..86f4d808 100644 --- a/chrome/test/chromedriver/window_commands.cc +++ b/chrome/test/chromedriver/window_commands.cc
@@ -263,6 +263,29 @@ return web_view->DispatchTouchEvents(events); } +Status WindowViewportSize(Session* session, + WebView* web_view, + int* innerWidth, + int* innerHeight) { + std::unique_ptr<base::Value> value; + base::ListValue args; + Status status = + web_view->CallFunction(std::string(), + "function() {" + " return {" + " view_width: Math.floor(window.innerWidth)," + " view_height: Math.floor(window.innerHeight)};" + "}", + args, &value); + if (!status.IsOk()) + return status; + base::DictionaryValue* view_attrib; + value->GetAsDictionary(&view_attrib); + view_attrib->GetInteger("view_width", innerWidth); + view_attrib->GetInteger("view_height", innerHeight); + return Status(kOk); +} + } // namespace Status ExecuteWindowCommand(const WindowCommand& command, @@ -1001,11 +1024,37 @@ return Status(kInvalidArgument, "'y' must be an int"); action->SetInteger("x", x); action->SetInteger("y", y); + + std::string origin; + if (action_item->HasKey("origin")) { + if (!action_item->GetString("origin", &origin)) { + const base::DictionaryValue* origin_dict; + if (!action_item->GetDictionary("origin", &origin_dict)) + return Status(kInvalidArgument, + "'origin' must be either a string or a dictionary"); + std::string element_id; + if (!origin_dict->GetString(GetElementKey(), &element_id)) + return Status(kInvalidArgument, "'element' is missing"); + std::unique_ptr<base::DictionaryValue> origin_result = + std::make_unique<base::DictionaryValue>(); + origin_result->SetString(GetElementKey(), element_id); + action->SetDictionary("origin", std::move(origin_result)); + } else { + if (origin != "viewport" && origin != "pointer") + return Status(kInvalidArgument, + "if 'origin' is a string, it must be either " + "'viewport' or 'pointer'"); + action->SetString("origin", origin); + } + } else { + action->SetString("origin", "viewport"); + } + int duration; if (action_item->HasKey("duration")) { if (!action_item->GetInteger("duration", &duration) || duration < 0) { return Status(kInvalidArgument, - "duration must be a non-negative int"); + "'duration' must be a non-negative int"); } action->SetInteger("duration", duration); } @@ -1014,7 +1063,7 @@ if (action_item->HasKey("duration")) { if (!action_item->GetInteger("duration", &duration) || duration < 0) { return Status(kInvalidArgument, - "duration must be a non-negative int"); + "'duration' must be a non-negative int"); } action->SetInteger("duration", duration); } @@ -1032,8 +1081,15 @@ std::unique_ptr<base::Value>* value, Timeout* timeout) { // extract action sequence + const base::DictionaryValue* actions_dict; const base::ListValue* actions_input; - if (!params.GetList("actions", &actions_input)) + + // TODO(lanwei): The below line will be removed after this pull request is + // merged, https://github.com/web-platform-tests/wpt/pull/14345. + if (!params.GetDictionary("actions", &actions_dict)) + actions_dict = ¶ms; + + if (!actions_dict->GetList("actions", &actions_input)) return Status(kInvalidArgument, "'actions' must be an array"); // the processed actions @@ -1161,7 +1217,44 @@ if (action_type == "pointerMove") { mouse_action->GetDouble("x", &x); mouse_action->GetDouble("y", &y); + const base::DictionaryValue* origin_dict; + if (mouse_action->HasKey("origin") && + mouse_action->GetDictionary("origin", &origin_dict)) { + std::string element_id; + origin_dict->GetString(GetElementKey(), &element_id); + WebRect region; + Status status = + GetElementRegion(session, web_view, element_id, ®ion); + if (status.IsError()) + return status; + WebPoint region_offset; + status = ScrollElementRegionIntoView( + session, web_view, element_id, region, true /* center */, + std::string(), ®ion_offset); + if (status.IsError()) + return status; + int innerWidth, innerHeight; + status = WindowViewportSize(session, web_view, &innerWidth, + &innerHeight); + if (status.IsError()) + return status; + int left = std::max( + 0, + std::min(region_offset.x, region_offset.x + region.Width())); + int right = std::min( + innerWidth, + std::max(region_offset.x, region_offset.x + region.Width())); + int top = std::max( + 0, + std::min(region_offset.y, region_offset.y + region.Height())); + int bottom = std::min( + innerHeight, + std::max(region_offset.y, region_offset.y + region.Height())); + x += (left + right) / 2; + y += (top + bottom) / 2; + } } + std::string button_type; int click_count = 0; if (action_type == "pointerDown" || action_type == "pointerUp") {
diff --git a/chrome/test/data/android/render_tests/ExploreSitesPageTest.initial_layout.Nexus_5-19.png b/chrome/test/data/android/render_tests/ExploreSitesPageTest.initial_layout.Nexus_5-19.png new file mode 100644 index 0000000..19482c3 --- /dev/null +++ b/chrome/test/data/android/render_tests/ExploreSitesPageTest.initial_layout.Nexus_5-19.png Binary files differ
diff --git a/chrome/test/data/android/render_tests/ExploreSitesPageTest.recycler_layout.Nexus_5-19.png b/chrome/test/data/android/render_tests/ExploreSitesPageTest.recycler_layout.Nexus_5-19.png new file mode 100644 index 0000000..570ceca --- /dev/null +++ b/chrome/test/data/android/render_tests/ExploreSitesPageTest.recycler_layout.Nexus_5-19.png Binary files differ
diff --git a/chrome/test/data/android/render_tests/ExploreSitesPageTest.recycler_layout_back.Nexus_5-19.png b/chrome/test/data/android/render_tests/ExploreSitesPageTest.recycler_layout_back.Nexus_5-19.png new file mode 100644 index 0000000..3c7a473 --- /dev/null +++ b/chrome/test/data/android/render_tests/ExploreSitesPageTest.recycler_layout_back.Nexus_5-19.png Binary files differ
diff --git a/chrome/test/data/chromedriver/goldenScreenshots/redboxScreenshot.png b/chrome/test/data/chromedriver/goldenScreenshots/redboxScreenshot.png deleted file mode 100644 index 5f2118b..0000000 --- a/chrome/test/data/chromedriver/goldenScreenshots/redboxScreenshot.png +++ /dev/null Binary files differ
diff --git a/chrome/test/data/extensions/api_test/input_method/settings/background.js b/chrome/test/data/extensions/api_test/input_method/settings/background.js index a04b033..8519253 100644 --- a/chrome/test/data/extensions/api_test/input_method/settings/background.js +++ b/chrome/test/data/extensions/api_test/input_method/settings/background.js
@@ -75,5 +75,35 @@ }); }); }); + }, + // Test OnSettingsChanged event gets raised when a new key is added. + function eventRaisedWhenSettingToInitialValue() { + const listener = (ime, key, value) => { + chrome.test.assertEq('ime', ime); + chrome.test.assertEq('key', key); + chrome.test.assertEq('value', value); + chrome.test.succeed(); + + chrome.inputMethodPrivate.onSettingsChanged.removeListener(listener); + }; + + chrome.inputMethodPrivate.onSettingsChanged.addListener(listener); + chrome.inputMethodPrivate.setSetting('ime', 'key', 'value'); + }, + // Test OnSettingsChanged event gets raised when a key is changed. + function eventRaisedWhenSettingChanged() { + const listener = (ime, key, value) => { + chrome.test.assertEq('ime', ime); + chrome.test.assertEq('key', key); + chrome.test.assertEq('value2', value); + chrome.test.succeed(); + + chrome.inputMethodPrivate.onSettingsChanged.removeListener(listener); + }; + + chrome.inputMethodPrivate.setSetting('ime', 'key', 'value1', () => { + chrome.inputMethodPrivate.onSettingsChanged.addListener(listener); + chrome.inputMethodPrivate.setSetting('ime', 'key', 'value2'); + }); } ]);
diff --git a/chrome/test/data/local_ntp/local_ntp_browsertest.js b/chrome/test/data/local_ntp/local_ntp_browsertest.js index 76b2111..a9e196d3 100644 --- a/chrome/test/data/local_ntp/local_ntp_browsertest.js +++ b/chrome/test/data/local_ntp/local_ntp_browsertest.js
@@ -73,32 +73,6 @@ window.chrome.embeddedSearch.newTabPage.mostVisited[0].rid)); }; -/** - * Tests that the GM2 style is applied when the flag is enabled. - */ -test.localNtp.testMDApplied = function() { - // Turn off voice search to avoid reinitializing the speech object - configData.isVoiceSearchEnabled = false; - - configData.isMDUIEnabled = true; - initLocalNTP(/*isGooglePage=*/true); - assertTrue(document.body.classList.contains('md')); -} - -/** - * Tests that the GM2 style is not applied when the flag is disabled. - */ -test.localNtp.testMDNotApplied = function() { - // Turn off voice search to avoid reinitializing the speech object - configData.isVoiceSearchEnabled = false; - - configData.isMDUIEnabled = false; - configData.isMDIconsEnabled = false; - configData.isCustomLinksEnabled = false; - initLocalNTP(/*isGooglePage=*/true); - assertFalse(document.body.classList.contains('md')); -} - // ****************************** ADVANCED TESTS ****************************** // Advanced tests are controlled from the native side. The helpers here are
diff --git a/chrome/test/data/policy/PRESUBMIT.py b/chrome/test/data/policy/PRESUBMIT.py new file mode 100644 index 0000000..9de3540 --- /dev/null +++ b/chrome/test/data/policy/PRESUBMIT.py
@@ -0,0 +1,21 @@ +# 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. + +def RunOtherPresubmit(function_name, input_api, output_api): + # Apply the same PRESUBMIT for components/policy/resources. + presubmit_path = ( + input_api.change.RepositoryRoot() + \ + '/components/policy/resources/PRESUBMIT.py') + presubmit_content = input_api.ReadFile(presubmit_path) + global_vars = {} + exec(presubmit_content, global_vars) + return global_vars[function_name](input_api, output_api) + +def CheckChangeOnUpload(input_api, output_api): + return RunOtherPresubmit("CheckChangeOnUpload", input_api, output_api) + + + +def CheckChangeOnCommit(input_api, output_api): + return RunOtherPresubmit("CheckChangeOnCommit", input_api, output_api) \ No newline at end of file
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index c6e3cad..c9dfd97 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -4125,6 +4125,28 @@ ] }, + "ParentAccessCodeConfig": { + "os": ["chromeos"], + "test_policy": { "ParentAccessCodeConfig": { + "current_config": { + "shared_secret": "oOA9nX02LdhYdOzwMsGof+QA3wUKP4YMNlk9S/W3o+w=", + "access_code_ttl": 600, + "clock_drift_tolerance": 300 + }, + "future_config": { + "shared_secret": "KMsoIjnpvcWmiU1GHchp2blR96mNyJwS", + "access_code_ttl": 600, + "clock_drift_tolerance": 300 + }, + "old_configs": [{ + "shared_secret": "sTr6jqMTJGCbLhWI5plFTQb/VsqxwX2Q", + "access_code_ttl": 600, + "clock_drift_tolerance": 300 + }] + }}, + "pref_mappings": [{ "pref": "child_user.parent_access_code.config" }] + }, + "----- Chrome Frame policies -------------------------------------------": {}, "ChromeFrameRendererSettings": {
diff --git a/chrome/test/data/sync/simple.html b/chrome/test/data/sync/simple.html new file mode 100644 index 0000000..70db0f2 --- /dev/null +++ b/chrome/test/data/sync/simple.html
@@ -0,0 +1,4 @@ +<html> +<head><title>OK</title></head> +<body></body> +</html>
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 96231ce..b4c18b3 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -10,6 +10,7 @@ sources = [ "cr_elements/cr_elements_focus_test.js", + "cr_focus_row_behavior_interactive_test.js", "md_bookmarks/md_bookmarks_focus_test.js", "md_history/md_history_focus_test.js", "print_preview/print_preview_interactive_ui_tests.js", @@ -77,7 +78,6 @@ "settings/a11y/sign_out_a11y_test.js", "settings/a11y/tts_subpage_a11y_test.js", "settings/advanced_page_browsertest.js", - "settings/animation_browsertest.js", "settings/autofill_browsertest.js", "settings/basic_page_browsertest.js", "settings/cr_settings_browsertest.js",
diff --git a/chrome/test/data/webui/cr_elements/cr_action_menu_test.js b/chrome/test/data/webui/cr_elements/cr_action_menu_test.js index c6518e6..0f8c896b 100644 --- a/chrome/test/data/webui/cr_elements/cr_action_menu_test.js +++ b/chrome/test/data/webui/cr_elements/cr_action_menu_test.js
@@ -28,10 +28,10 @@ document.body.innerHTML = ` <button id="dots">...</button> <cr-action-menu> - <button slot="item" class="dropdown-item">Un</button> - <hr slot="item"> - <button slot="item" class="dropdown-item">Dos</button> - <button slot="item" class="dropdown-item">Tres</button> + <button class="dropdown-item">Un</button> + <hr> + <button class="dropdown-item">Dos</button> + <button class="dropdown-item">Tres</button> </cr-action-menu> `; @@ -57,6 +57,10 @@ MockInteractions.keyDownOn(menu, 'ArrowUp', [], 'ArrowUp'); } + function enter() { + MockInteractions.keyDownOn(menu, 'Enter', [], 'Enter'); + } + test('close event bubbles', function() { menu.showAt(dots); const whenFired = test_util.eventToPromise('close', menu); @@ -121,13 +125,31 @@ assertEquals(items[items.length - 1], getDeepActiveElement()); }); - test('can navigate to dynamically added items', function() { + test('pressing enter when no focus', function() { + if (cr.isWindows || cr.isMac) + return testFocusAfterClosing('Enter'); + + // First item is selected + menu.showAt(dots); + assertEquals(menu, document.activeElement); + enter(); + assertEquals(items[0], getDeepActiveElement()); + }); + + test('pressing enter when when item has focus', function() { + menu.showAt(dots); + down(); + enter(); + assertEquals(items[0], getDeepActiveElement()); + }); + + test('can navigate to dynamically added items', async function() { // Can modify children after attached() and before showAt(). const item = document.createElement('button'); item.classList.add('dropdown-item'); - item.setAttribute('slot', 'item'); menu.insertBefore(item, items[0]); menu.showAt(dots); + await PolymerTest.flushTasks(); down(); assertEquals(item, getDeepActiveElement()); @@ -210,25 +232,20 @@ assertEquals(items[0], getDeepActiveElement()); }); - test('items automatically given accessibility role', function() { + test('items automatically given accessibility role', async function() { const newItem = document.createElement('button'); - newItem.setAttribute('slot', 'item'); newItem.classList.add('dropdown-item'); items[1].setAttribute('role', 'checkbox'); menu.showAt(dots); - return PolymerTest.flushTasks() - .then(() => { - assertEquals('menuitem', items[0].getAttribute('role')); - assertEquals('checkbox', items[1].getAttribute('role')); + await PolymerTest.flushTasks(); + assertEquals('menuitem', items[0].getAttribute('role')); + assertEquals('checkbox', items[1].getAttribute('role')); - menu.insertBefore(newItem, items[0]); - return PolymerTest.flushTasks(); - }) - .then(() => { - assertEquals('menuitem', newItem.getAttribute('role')); - }); + menu.insertBefore(newItem, items[0]); + await PolymerTest.flushTasks(); + assertEquals('menuitem', newItem.getAttribute('role')); }); test('positioning', function() { @@ -404,10 +421,10 @@ <div id="inner-container"> <button id="dots">...</button> <cr-action-menu> - <button slot="item" class="dropdown-item">Un</button> + <button class="dropdown-item">Un</button> <hr> - <button slot="item" class="dropdown-item">Dos</button> - <button slot="item" class="dropdown-item">Tres</button> + <button class="dropdown-item">Dos</button> + <button class="dropdown-item">Tres</button> </cr-action-menu> </div> </div>
diff --git a/chrome/test/data/webui/cr_elements/cr_slider_test.js b/chrome/test/data/webui/cr_elements/cr_slider_test.js index fb50c43..fb32fcb 100644 --- a/chrome/test/data/webui/cr_elements/cr_slider_test.js +++ b/chrome/test/data/webui/cr_elements/cr_slider_test.js
@@ -149,28 +149,6 @@ assertEquals(100, crSlider.value); }); - test('update value instantly both off and on', () => { - crSlider.updateValueInstantly = false; - assertEquals(0, crSlider.value); - pointerDown(.5); - assertEquals(0, crSlider.value); - pointerUp(); - assertEquals(50, crSlider.value); - - // Once |updateValueInstantly| is turned on, |value| should start updating - // again during drag. - pointerDown(0); - assertEquals(50, crSlider.value); - crSlider.updateValueInstantly = true; - pointerMove(0); - assertEquals(0, crSlider.value); - crSlider.updateValueInstantly = false; - pointerMove(.4); - assertEquals(0, crSlider.value); - pointerUp(); - assertEquals(40, crSlider.value); - }); - test('snaps to closest value', () => { crSlider.snaps = true; pointerDown(.501);
diff --git a/chrome/test/data/webui/cr_focus_row_behavior_interactive_test.js b/chrome/test/data/webui/cr_focus_row_behavior_interactive_test.js new file mode 100644 index 0000000..abe4dbc --- /dev/null +++ b/chrome/test/data/webui/cr_focus_row_behavior_interactive_test.js
@@ -0,0 +1,47 @@ +// 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. + +/** @const {string} Path to source root. */ +const ROOT_PATH = '../../../../'; + +// Polymer BrowserTest fixture. +GEN_INCLUDE( + [ROOT_PATH + 'chrome/test/data/webui/polymer_interactive_ui_test.js']); + +/** + * Test fixture for FocusRowBehavior. + * @constructor + * @extends {PolymerInteractiveUITest} + */ +function CrFocusRowBehaviorTest() {} + +CrFocusRowBehaviorTest.prototype = { + __proto__: PolymerInteractiveUITest.prototype, + + /** @override */ + browsePreload: 'chrome://resources/html/cr/ui/focus_row_behavior.html', + + /** @override */ + extraLibraries: PolymerTest.getLibraries(ROOT_PATH).concat([ + ROOT_PATH + 'ui/webui/resources/js/util.js', + 'cr_focus_row_behavior_test.js', + 'settings/test_util.js', + ]), + + /** @override */ + setUp: function() { + PolymerTest.prototype.setUp.call(this); + // We aren't loading the main document. + this.accessibilityAuditConfig.ignoreSelectors('humanLangMissing', 'html'); + + // TODO(michaelpg): Re-enable after bringing in fix for + // https://github.com/PolymerElements/paper-slider/issues/131. + this.accessibilityAuditConfig.ignoreSelectors( + 'badAriaAttributeValue', 'paper-slider'); + }, +}; + +TEST_F('CrFocusRowBehaviorTest', 'FocusTest', function() { + mocha.run(); +});
diff --git a/chrome/test/data/webui/cr_focus_row_behavior_test.js b/chrome/test/data/webui/cr_focus_row_behavior_test.js new file mode 100644 index 0000000..e7d679e8 --- /dev/null +++ b/chrome/test/data/webui/cr_focus_row_behavior_test.js
@@ -0,0 +1,110 @@ +// Copyright 2017 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. + +suite('cr-focus-row-behavior-test', function() { + /** @type {FocusableIronListItemElement} */ let testElement; + + suiteSetup(function() { + document.body.innerHTML = ` + <dom-module id="button-three"> + <template> + <button> + fake button three + </button> + </template> + </dom-module> + + <dom-module id="focus-row-element"> + <template> + <div id="container" focus-row-container> + <span>fake text</span> + <button id="control" focus-row-control focus-type='fake-btn'> + fake button + </button> + <button id="controlTwo" focus-row-control focus-type='fake-btn-two'> + fake button two + </button> + <button-three focus-row-control focus-type='fake-btn-three'> + </button-three> + </div> + </template> + </dom-module> + `; + + Polymer({ + is: 'button-three', + + /** @return {!Element} */ + getFocusableElement: function() { + return this.$$('button'); + }, + }); + + Polymer({ + is: 'focus-row-element', + behaviors: [cr.ui.FocusRowBehavior], + }); + }); + + setup(function(done) { + PolymerTest.clearBody(); + + testElement = document.createElement('focus-row-element'); + document.body.appendChild(testElement); + + // Block until FocusRowBehavior.attached finishes running async setup. + Polymer.RenderStatus.afterNextRender(this, function() { + done(); + }); + }); + + test('item passes focus to first focusable child', function() { + let focused = false; + testElement.$.control.addEventListener('focus', function() { + focused = true; + }); + testElement.fire('focus'); + assertTrue(focused); + }); + + test('will focus a similar item that was last focused', function() { + const lastButton = document.createElement('button'); + lastButton.setAttribute('focus-type', 'fake-btn-two'); + testElement.lastFocused = lastButton; + + let focused = false; + testElement.$.controlTwo.addEventListener('focus', function() { + focused = true; + }); + testElement.fire('focus'); + assertTrue(focused); + }); + + test('mouse clicks on the row does not focus the controls', function() { + let focused = false; + testElement.$.control.addEventListener('focus', function() { + focused = true; + }); + MockInteractions.down(testElement); + MockInteractions.up(testElement); + testElement.click(); + // iron-list is responsible for firing 'focus' after taps, but is not used + // in the test, so its necessary to manually fire 'focus' after tap. + testElement.fire('focus'); + assertFalse(focused); + }); + + test('when focus-override is defined, returned element gains focus', () => { + const lastButton = document.createElement('button'); + lastButton.setAttribute('focus-type', 'fake-btn-three'); + testElement.lastFocused = lastButton; + + const wait = test_util.eventToPromise('focus', testElement); + testElement.fire('focus'); + return wait.then(() => { + const button = getDeepActiveElement(); + assertEquals('fake button three', button.textContent.trim()); + }); + }); +});
diff --git a/chrome/test/data/webui/md_bookmarks/.eslintrc.js b/chrome/test/data/webui/md_bookmarks/.eslintrc.js index a8aaea1..4cbd5cf8 100644 --- a/chrome/test/data/webui/md_bookmarks/.eslintrc.js +++ b/chrome/test/data/webui/md_bookmarks/.eslintrc.js
@@ -3,9 +3,6 @@ // found in the LICENSE file. module.exports = { - 'parserOptions': { - 'ecmaVersion': 2017, - }, 'rules': { 'no-var': 'error', },
diff --git a/chrome/test/data/webui/md_downloads/.eslintrc.js b/chrome/test/data/webui/md_downloads/.eslintrc.js index 93b7337b..25e21f9 100644 --- a/chrome/test/data/webui/md_downloads/.eslintrc.js +++ b/chrome/test/data/webui/md_downloads/.eslintrc.js
@@ -7,9 +7,6 @@ 'browser': true, 'es6': true, }, - 'parserOptions': { - 'ecmaVersion': 2017, - }, 'rules': { 'no-var': 'error', },
diff --git a/chrome/test/data/webui/md_downloads/downloads_browsertest.js b/chrome/test/data/webui/md_downloads/downloads_browsertest.js index 7266e1c..c0406d0 100644 --- a/chrome/test/data/webui/md_downloads/downloads_browsertest.js +++ b/chrome/test/data/webui/md_downloads/downloads_browsertest.js
@@ -72,6 +72,7 @@ ROOT_PATH + 'ui/webui/resources/js/cr.js', ROOT_PATH + 'chrome/browser/resources/md_downloads/constants.js', '../test_browser_proxy.js', + 'test_support.js', 'manager_tests.js', ]), };
diff --git a/chrome/test/data/webui/md_downloads/manager_tests.js b/chrome/test/data/webui/md_downloads/manager_tests.js index 1fdbc8c..8fa1cb4 100644 --- a/chrome/test/data/webui/md_downloads/manager_tests.js +++ b/chrome/test/data/webui/md_downloads/manager_tests.js
@@ -3,114 +3,22 @@ // found in the LICENSE file. suite('manager tests', function() { - const DOWNLOAD_DATA_TEMPLATE = Object.freeze({ - byExtId: '', - byExtName: '', - dangerType: downloads.DangerType.NOT_DANGEROUS, - dateString: '', - fileExternallyRemoved: false, - filePath: '/some/file/path', - fileName: 'download 1', - fileUrl: 'file:///some/file/path', - id: '', - lastReasonText: '', - otr: false, - percent: 100, - progressStatusText: '', - resume: false, - retry: false, - return: false, - sinceString: 'Today', - started: Date.now() - 10000, - state: downloads.States.COMPLETE, - total: -1, - url: 'http://permission.site', - }); - - /** @implements {mdDownloads.mojom.PageHandlerInterface} */ - class TestDownloadsProxy extends TestBrowserProxy { - /** @param {!mdDownloads.mojom.PageHandlerCallbackRouter} */ - constructor(pageRouterProxy) { - super(['remove']); - - /** @private {!mdDownloads.mojom.PageHandlerCallbackRouter} */ - this.pageRouterProxy_ = pageRouterProxy; - } - - /** @override */ - remove(id) { - this.pageRouterProxy_.removeItem(id); - this.pageRouterProxy_.flushForTesting().then( - () => this.methodCalled('remove', id)); - } - - /** @override */ - getDownloads(searchTerms) {} - - /** @override */ - openFileRequiringGesture(id) {} - - /** @override */ - drag(id) {} - - /** @override */ - saveDangerousRequiringGesture(id) {} - - /** @override */ - discardDangerous(id) {} - - /** @override */ - retryDownload(id) {} - - /** @override */ - show(id) {} - - /** @override */ - pause(id) {} - - /** @override */ - resume(id) {} - - /** @override */ - undo() {} - - /** @override */ - cancel(id) {} - - /** @override */ - clearAll() {} - - /** @override */ - openDownloadsFolderRequiringGesture() {} - } - - /** - * @param {Object=} config - * @return {!downloads.Data} - */ - function createDownload(config) { - if (!config) - config = {}; - - return Object.assign({}, DOWNLOAD_DATA_TEMPLATE, config); - } - /** @type {!downloads.Manager} */ let manager; - /** @type {!mdDownloads.mojom.PageInterface} */ + /** @type {!mdDownloads.mojom.PageHandlerCallbackRouter} */ let pageRouterProxy; /** @type {TestDownloadsProxy} */ - let testPageHandlerProxy; + let testBrowserProxy; setup(function() { - pageRouterProxy = - downloads.BrowserProxy.getInstance().callbackRouter.createProxy(); - testPageHandlerProxy = new TestDownloadsProxy(pageRouterProxy); - downloads.BrowserProxy.getInstance().handler = testPageHandlerProxy; - PolymerTest.clearBody(); + + testBrowserProxy = new TestDownloadsProxy(); + pageRouterProxy = testBrowserProxy.pageRouterProxy; + downloads.BrowserProxy.instance_ = testBrowserProxy; + manager = document.createElement('downloads-manager'); document.body.appendChild(manager); assertEquals(manager, downloads.Manager.get()); @@ -166,7 +74,7 @@ }); test('update', function() { - let dangerousDownload = Object.assign({}, DOWNLOAD_DATA_TEMPLATE, { + let dangerousDownload = createDownload({ dangerType: downloads.DangerType.DANGEROUS_FILE, state: downloads.States.DANGEROUS, }); @@ -202,7 +110,7 @@ const item = manager.$$('downloads-item'); item.$.remove.click(); - return testPageHandlerProxy.whenCalled('remove'); + return testBrowserProxy.handler.whenCalled('remove'); }) .then(() => { Polymer.dom.flush();
diff --git a/chrome/test/data/webui/md_downloads/test_support.js b/chrome/test/data/webui/md_downloads/test_support.js new file mode 100644 index 0000000..847d228 --- /dev/null +++ b/chrome/test/data/webui/md_downloads/test_support.js
@@ -0,0 +1,114 @@ +// 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. + +class TestDownloadsProxy { + constructor() { + /** @type {mdDownloads.mojom.PageCallbackRouter} */ + this.callbackRouter = new mdDownloads.mojom.PageCallbackRouter(); + + /** @type {!mdDownloads.mojom.PageInterface} */ + this.pageRouterProxy = this.callbackRouter.createProxy(); + + /** @type {mdDownloads.mojom.PageHandlerInterface} */ + this.handler = new TestDownloadsMojoHandler(this.pageRouterProxy); + } +} + +/** @implements {mdDownloads.mojom.PageHandlerInterface} */ +class TestDownloadsMojoHandler { + /** @param {mdDownloads.mojom.PageInterface} */ + constructor(pageRouterProxy) { + /** @private {mdDownloads.mojom.PageInterface} */ + this.pageRouterProxy_ = pageRouterProxy; + + /** @private {TestBrowserProxy} */ + this.callTracker_ = new TestBrowserProxy(['remove']); + } + + /** + * @param {string} methodName + * @return {!Promise} + */ + whenCalled(methodName) { + return this.callTracker_.whenCalled(methodName); + } + + /** @override */ + async remove(id) { + this.pageRouterProxy_.removeItem(id); + await this.pageRouterProxy_.flushForTesting(); + this.callTracker_.methodCalled('remove', id); + } + + /** @override */ + getDownloads(searchTerms) {} + + /** @override */ + openFileRequiringGesture(id) {} + + /** @override */ + drag(id) {} + + /** @override */ + saveDangerousRequiringGesture(id) {} + + /** @override */ + discardDangerous(id) {} + + /** @override */ + retryDownload(id) {} + + /** @override */ + show(id) {} + + /** @override */ + pause(id) {} + + /** @override */ + resume(id) {} + + /** @override */ + undo() {} + + /** @override */ + cancel(id) {} + + /** @override */ + clearAll() {} + + /** @override */ + openDownloadsFolderRequiringGesture() {} +} + +/** + * @param {Object=} config + * @return {!downloads.Data} + */ +function createDownload(config) { + return Object.assign( + { + byExtId: '', + byExtName: '', + dangerType: downloads.DangerType.NOT_DANGEROUS, + dateString: '', + fileExternallyRemoved: false, + filePath: '/some/file/path', + fileName: 'download 1', + fileUrl: 'file:///some/file/path', + id: '', + lastReasonText: '', + otr: false, + percent: 100, + progressStatusText: '', + resume: false, + retry: false, + return: false, + sinceString: 'Today', + started: Date.now() - 10000, + state: downloads.States.COMPLETE, + total: -1, + url: 'http://permission.site', + }, + config || {}); +}
diff --git a/chrome/test/data/webui/promise_resolver_test.html b/chrome/test/data/webui/promise_resolver_test.html index 2df51627..202031d 100644 --- a/chrome/test/data/webui/promise_resolver_test.html +++ b/chrome/test/data/webui/promise_resolver_test.html
@@ -4,24 +4,41 @@ <script> function testMembersReadOnly() { - var resolver = new PromiseResolver; + const resolver = new PromiseResolver; assertThrows(function() { resolver.promise = new Promise; }); assertThrows(function() { resolver.resolve = function() {}; }); assertThrows(function() { resolver.reject = function() {}; }); } function testResolves(done) { - var resolver = new PromiseResolver; + const resolver = new PromiseResolver; resolver.promise.then(done); resolver.resolve(); } function testRejects(done) { - var resolver = new PromiseResolver; + const resolver = new PromiseResolver; resolver.promise.catch(done); resolver.reject(); } +function testisFulfilled() { + const resolver1 = new PromiseResolver; + assertFalse(resolver1.isFulfilled); + resolver1.resolve(); + assertTrue(resolver1.isFulfilled); + + const resolver2 = new PromiseResolver; + assertFalse(resolver2.isFulfilled); + resolver2.resolve(true); + assertTrue(resolver2.isFulfilled); + + const resolver3 = new PromiseResolver; + assertFalse(resolver3.isFulfilled); + resolver3.reject(new Error); + assertTrue(resolver3.isFulfilled); +} + </script> </body> </html>
diff --git a/chrome/test/data/webui/settings/animation_browsertest.js b/chrome/test/data/webui/settings/animation_browsertest.js deleted file mode 100644 index 71de43c..0000000 --- a/chrome/test/data/webui/settings/animation_browsertest.js +++ /dev/null
@@ -1,150 +0,0 @@ -// Copyright 2016 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. - -/** @fileoverview Tests for settings.animation. */ - -/** @const {string} Path to root from chrome/test/data/webui/settings/. */ -const ROOT_PATH = '../../../../../'; - -/** - * @constructor - * @extends testing.Test - */ -function SettingsAnimationBrowserTest() {} - -SettingsAnimationBrowserTest.prototype = { - __proto__: testing.Test.prototype, - - /** @override */ - browsePreload: 'chrome://settings/animation/animation.html', - - /** @override */ - extraLibraries: [ - ROOT_PATH + 'third_party/mocha/mocha.js', - '../mocha_adapter.js', - ], - - /** @override */ - isAsync: true, - - /** @override */ - runAccessibilityChecks: false, -}; - -TEST_F('SettingsAnimationBrowserTest', 'Animation', function() { - const self = this; - - const Animation = settings.animation.Animation; - - const onFinishBeforePromise = function() { - assertNotReached('Animation fired finish event before resolving promise'); - }; - - const onCancelUnexpectedly = function() { - assertNotReached('Animation should have finished, but fired cancel event'); - }; - - // Register mocha tests. - suite('settings.animation.Animation', function() { - let div; - let keyframes; - let options; - - setup(function() { - keyframes = [ - { - height: '100px', - easing: 'ease-in', - }, - { - height: '200px', - } - ]; - - options = { - duration: 1000, - // Use fill: both so we can test the animation start and end states. - fill: 'both', - }; - - div = document.createElement('div'); - document.body.appendChild(div); - }); - - teardown(function() { - div.remove(); - }); - - test('Animation plays', function(done) { - const animation = new Animation(div, keyframes, options); - animation.addEventListener('cancel', onCancelUnexpectedly); - animation.addEventListener('finish', onFinishBeforePromise); - - requestAnimationFrame(function() { - expectEquals(100, div.clientHeight); - - animation.finished.then(function() { - expectEquals(200, div.clientHeight); - animation.removeEventListener('finish', onFinishBeforePromise); - animation.addEventListener('finish', function() { - done(); - }); - }); - }); - }); - - test('Animation finishes', function(done) { - // Absurdly large duration to ensure we call finish() before the - // animation finishes automatically. - options.duration = 24 * 60 * 60 * 1000; - const animation = new Animation(div, keyframes, options); - animation.addEventListener('cancel', onCancelUnexpectedly); - animation.addEventListener('finish', onFinishBeforePromise); - - // TODO(michaelpg): rAF seems more appropriate, but crbug.com/620160. - setTimeout(function() { - expectEquals(100, div.clientHeight); - - animation.finish(); - - // The promise should resolve before the finish event is scheduled. - animation.finished.then(function() { - expectEquals(200, div.clientHeight); - animation.removeEventListener('finish', onFinishBeforePromise); - animation.addEventListener('finish', function() { - done(); - }); - }); - }); - }); - - test('Animation cancels', function(done) { - // Absurdly large finite value to ensure we call cancel() before the - // animation finishes automatically. - options.duration = Number.MAX_VALUE; - const animation = new Animation(div, keyframes, options); - animation.addEventListener('cancel', onCancelUnexpectedly); - animation.addEventListener('finish', onFinishBeforePromise); - - // TODO(michaelpg): rAF seems more appropriate, but crbug.com/620160. - setTimeout(function() { - expectEquals(100, div.clientHeight); - - animation.cancel(); - - // The promise should be rejected before the cancel event is scheduled. - animation.finished.catch(function() { - expectEquals(0, div.clientHeight); - animation.removeEventListener('cancel', onCancelUnexpectedly); - animation.addEventListener('cancel', function() { - done(); - }); - }); - }); - }); - }); - - // Run all registered tests. - mocha.run(); -});
diff --git a/chrome/test/data/webui/settings/cr_settings_interactive_ui_tests.js b/chrome/test/data/webui/settings/cr_settings_interactive_ui_tests.js index e58d13b..d3a26c2 100644 --- a/chrome/test/data/webui/settings/cr_settings_interactive_ui_tests.js +++ b/chrome/test/data/webui/settings/cr_settings_interactive_ui_tests.js
@@ -42,31 +42,6 @@ }, }; -/** - * Test fixture for FocusRowBehavior. - * @constructor - * @extends {CrSettingsInteractiveUITest} - */ -function CrSettingsFocusRowBehavior() {} - -CrSettingsFocusRowBehavior.prototype = { - __proto__: CrSettingsInteractiveUITest.prototype, - - /** @override */ - browsePreload: 'chrome://settings/focus_row_behavior.html', - - /** @override */ - extraLibraries: CrSettingsInteractiveUITest.prototype.extraLibraries.concat([ - ROOT_PATH + 'ui/webui/resources/js/util.js', - 'focus_row_behavior_test.js', - 'test_util.js', - ]), -}; - -TEST_F('CrSettingsFocusRowBehavior', 'FocusTest', function() { - mocha.run(); -}); - /** * Test fixture for Sync Page.
diff --git a/chrome/test/data/webui/settings/crostini_page_test.js b/chrome/test/data/webui/settings/crostini_page_test.js index a757455..d8e43488 100644 --- a/chrome/test/data/webui/settings/crostini_page_test.js +++ b/chrome/test/data/webui/settings/crostini_page_test.js
@@ -8,17 +8,19 @@ /** @type {?TestCrostiniBrowserProxy} */ let crostiniBrowserProxy = null; -const setCrostiniPrefs = function(enabled, opt_sharedPaths) { +function setCrostiniPrefs(enabled, opt_sharedPaths, opt_sharedUsbDevices) { crostiniPage.prefs = { crostini: { enabled: {value: enabled}, - shared_paths: {value: opt_sharedPaths || []} + shared_paths: {value: opt_sharedPaths || []}, + shared_usb_devices: {value: opt_sharedUsbDevices || []}, } }; crostiniBrowserProxy.enabled = enabled; crostiniBrowserProxy.sharedPaths = opt_sharedPaths || []; + crostiniBrowserProxy.sharedUsbDevices = opt_sharedUsbDevices || []; Polymer.dom.flush(); -}; +} suite('CrostiniPageTests', function() { setup(function() { @@ -138,8 +140,7 @@ test('Sanity', function() { assertEquals( - 2, - Polymer.dom(subpage.root).querySelectorAll('.settings-box').length); + 2, subpage.shadowRoot.querySelectorAll('.settings-box').length); }); test('Remove', function() { @@ -150,9 +151,52 @@ return flushAsync().then(() => { Polymer.dom.flush(); assertEquals( - 1, - Polymer.dom(subpage.root).querySelectorAll('.settings-box').length); + 1, subpage.shadowRoot.querySelectorAll('.settings-box').length); }); }); }); + + suite('SubPageSharedUsbDevices', function() { + let subpage; + + setup(function() { + setCrostiniPrefs(true, [], [ + {'shared': true, 'guid': '0001', 'name': 'usb_dev1'}, + {'shared': false, 'guid': '0002', 'name': 'usb_dev2'}, + {'shared': true, 'guid': '0003', 'name': 'usb_dev3'} + ]); + return flushAsync() + .then(() => { + settings.navigateTo(settings.routes.CROSTINI_SHARED_USB_DEVICES); + return flushAsync(); + }) + .then(() => { + subpage = crostiniPage.$$('settings-crostini-shared-usb-devices'); + assertTrue(!!subpage); + }); + }); + + test('USB devices are shown', function() { + assertEquals( + 3, subpage.shadowRoot.querySelectorAll('.settings-box').length); + }); + + test('USB shared pref is updated by toggling', function() { + assertTrue(!!subpage.$$('.settings-box .toggle')); + subpage.$$('.toggle').click(); + return flushAsync() + .then(() => { + Polymer.dom.flush(); + assertEquals( + crostiniBrowserProxy.sharedUsbDevices[0].shared, false); + + subpage.$$('.toggle').click(); + return flushAsync(); + }) + .then(() => { + Polymer.dom.flush(); + assertEquals(crostiniBrowserProxy.sharedUsbDevices[0].shared, true); + }); + }); + }); });
diff --git a/chrome/test/data/webui/settings/device_page_tests.js b/chrome/test/data/webui/settings/device_page_tests.js index 94f802f..b51ff37 100644 --- a/chrome/test/data/webui/settings/device_page_tests.js +++ b/chrome/test/data/webui/settings/device_page_tests.js
@@ -394,17 +394,12 @@ /** @return {!Promise<!HTMLElement>} */ function showAndGetDeviceSubpage(subpage, expectedRoute) { - return new Promise(function(resolve, reject) { - const row = assert(devicePage.$$('#main #' + subpage + 'Row')); - devicePage.$$('#pages').addEventListener( - 'neon-animation-finish', resolve); - row.click(); - }) - .then(function() { - assertEquals(expectedRoute, settings.getCurrentRoute()); - const page = devicePage.$$('settings-' + subpage); - return assert(page); - }); + const row = assert(devicePage.$$(`#main #${subpage}Row`)); + row.click(); + assertEquals(expectedRoute, settings.getCurrentRoute()); + const page = devicePage.$$('settings-' + subpage); + assert(page); + return Promise.resolve(page); } /** @@ -490,22 +485,14 @@ assertEquals(0, pointersPage.$$('#mouse h2').offsetHeight); assertEquals(0, pointersPage.$$('#touchpad h2').offsetHeight); - // Wait for the transition back to the main page. - return new Promise(function(resolve, reject) { - devicePage.$$('#pages').addEventListener( - 'neon-animation-finish', resolve); + cr.webUIListenerCallback('has-mouse-changed', false); + assertEquals(settings.routes.DEVICE, settings.getCurrentRoute()); + assertEquals(0, devicePage.$$('#main #pointersRow').offsetHeight); - cr.webUIListenerCallback('has-mouse-changed', false); - }) - .then(function() { - assertEquals(settings.routes.DEVICE, settings.getCurrentRoute()); - assertEquals(0, devicePage.$$('#main #pointersRow').offsetHeight); + cr.webUIListenerCallback('has-touchpad-changed', true); + assertLT(0, devicePage.$$('#main #pointersRow').offsetHeight); - cr.webUIListenerCallback('has-touchpad-changed', true); - assertLT(0, devicePage.$$('#main #pointersRow').offsetHeight); - return showAndGetDeviceSubpage( - 'pointers', settings.routes.POINTERS); - }) + return showAndGetDeviceSubpage('pointers', settings.routes.POINTERS) .then(function(page) { assertEquals(0, pointersPage.$$('#mouse').offsetHeight); assertLT(0, pointersPage.$$('#touchpad').offsetHeight);
diff --git a/chrome/test/data/webui/settings/focus_row_behavior_test.js b/chrome/test/data/webui/settings/focus_row_behavior_test.js deleted file mode 100644 index a49288c..0000000 --- a/chrome/test/data/webui/settings/focus_row_behavior_test.js +++ /dev/null
@@ -1,110 +0,0 @@ -// Copyright 2017 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. - -suite('focus-row-behavior', function() { - /** @type {FocusableIronListItemElement} */ let testElement; - - suiteSetup(function() { - document.body.innerHTML = ` - <dom-module id="button-three"> - <template> - <button> - fake button three - </button> - </template> - </dom-module> - - <dom-module id="focus-row-element"> - <template> - <div id="container" focus-row-container> - <span>fake text</span> - <button id="control" focus-row-control focus-type='fake-btn'> - fake button - </button> - <button id="controlTwo" focus-row-control focus-type='fake-btn-two'> - fake button two - </button> - <button-three focus-row-control focus-type='fake-btn-three'> - </button-three> - </div> - </template> - </dom-module> - `; - - Polymer({ - is: 'button-three', - - /** @return {!Element} */ - getFocusableElement: function() { - return this.$$('button'); - }, - }); - - Polymer({ - is: 'focus-row-element', - behaviors: [FocusRowBehavior], - }); - }); - - setup(function(done) { - PolymerTest.clearBody(); - - testElement = document.createElement('focus-row-element'); - document.body.appendChild(testElement); - - // Block until FocusRowBehavior.attached finishes running async setup. - Polymer.RenderStatus.afterNextRender(this, function() { - done(); - }); - }); - - test('item passes focus to first focusable child', function() { - let focused = false; - testElement.$.control.addEventListener('focus', function() { - focused = true; - }); - testElement.fire('focus'); - assertTrue(focused); - }); - - test('will focus a similar item that was last focused', function() { - const lastButton = document.createElement('button'); - lastButton.setAttribute('focus-type', 'fake-btn-two'); - testElement.lastFocused = lastButton; - - let focused = false; - testElement.$.controlTwo.addEventListener('focus', function() { - focused = true; - }); - testElement.fire('focus'); - assertTrue(focused); - }); - - test('mouse clicks on the row does not focus the controls', function() { - let focused = false; - testElement.$.control.addEventListener('focus', function() { - focused = true; - }); - MockInteractions.down(testElement); - MockInteractions.up(testElement); - testElement.click(); - // iron-list is responsible for firing 'focus' after taps, but is not used - // in the test, so its necessary to manually fire 'focus' after tap. - testElement.fire('focus'); - assertFalse(focused); - }); - - test('when focus-override is defined, returned element gains focus', () => { - const lastButton = document.createElement('button'); - lastButton.setAttribute('focus-type', 'fake-btn-three'); - testElement.lastFocused = lastButton; - - const wait = test_util.eventToPromise('focus', testElement); - testElement.fire('focus'); - return wait.then(() => { - const button = getDeepActiveElement(); - assertEquals('fake button three', button.textContent.trim()); - }); - }); -});
diff --git a/chrome/test/data/webui/settings/multidevice_page_tests.js b/chrome/test/data/webui/settings/multidevice_page_tests.js index 89d6735..1dd431c 100644 --- a/chrome/test/data/webui/settings/multidevice_page_tests.js +++ b/chrome/test/data/webui/settings/multidevice_page_tests.js
@@ -82,19 +82,15 @@ }); setup(function() { - settings.navigateTo(settings.routes.MULTIDEVICE); + PolymerTest.clearBody(); browserProxy = new multidevice.TestMultideviceBrowserProxy(); settings.MultiDeviceBrowserProxyImpl.instance_ = browserProxy; - const whenInitialized = browserProxy.whenCalled('getPageContentData'); - PolymerTest.clearBody(); multidevicePage = document.createElement('settings-multidevice-page'); assertTrue(!!multidevicePage); document.body.appendChild(multidevicePage); - return whenInitialized.then(() => { - Polymer.dom.flush(); - }); + return browserProxy.whenCalled('getPageContentData'); }); teardown(function() {
diff --git a/chrome/test/data/webui/settings/people_page_sync_page_test.js b/chrome/test/data/webui/settings/people_page_sync_page_test.js index 54d0e02..a4412818 100644 --- a/chrome/test/data/webui/settings/people_page_sync_page_test.js +++ b/chrome/test/data/webui/settings/people_page_sync_page_test.js
@@ -71,37 +71,6 @@ syncAllDataTypesControl.click(); } - // Tests the initial layout of the sync section and the personalize section, - // depending on the sync state and the unified consent state. - function testInitialLayout( - signedIn, hasError, setupInProgress, syncSectionExpanded, - syncSectionDisabled, personalizeSectionExpanded) { - syncPage.unifiedConsentEnabled = true; - syncPage.syncStatus = { - signedIn: signedIn, - disabled: false, - hasError: hasError, - setupInProgress: setupInProgress, - statusAction: hasError ? settings.StatusAction.REAUTHENTICATE : - settings.StatusAction.NO_ACTION, - }; - Polymer.dom.flush(); - - const syncSectionToggle = syncPage.$$('#sync-section-toggle'); - const syncSectionExpandIcon = - syncSectionToggle.querySelector('cr-expand-button'); - const personalizeSectionToggle = - syncPage.$$('#personalize-section-toggle'); - const personalizeSectionExpandIcon = - personalizeSectionToggle.querySelector('cr-expand-button'); - - assertTrue(syncSectionExpandIcon.expanded == syncSectionExpanded); - assertTrue(syncSectionExpandIcon.disabled == syncSectionDisabled); - assertTrue( - personalizeSectionExpandIcon.expanded == personalizeSectionExpanded); - assertFalse(personalizeSectionExpandIcon.disabled); - } - setup(function() { browserProxy = new TestSyncBrowserProxy(); settings.SyncBrowserProxyImpl.instance_ = browserProxy; @@ -171,32 +140,21 @@ }); test('SyncSectionLayout_NoUnifiedConsent_SignedIn', function() { - const ironCollapse = syncPage.$$('#sync-section'); + const syncSection = syncPage.$$('#sync-section'); const otherItems = syncPage.$$('#other-sync-items'); - const syncSectionToggle = syncPage.$$('#sync-section-toggle'); - // When unified-consent is disabled and signed in, sync-section should be - // visible and open by default. Accordion toggle row should not be present - // and bottom items should not have classes used for indentation. syncPage.syncStatus = {signedIn: true, disabled: false}; syncPage.unifiedConsentEnabled = false; Polymer.dom.flush(); - assertTrue(ironCollapse.opened); - assertFalse(ironCollapse.hidden); - assertTrue(syncSectionToggle.hidden); + assertFalse(syncSection.hidden); assertFalse(otherItems.classList.contains('list-frame')); assertFalse(!!otherItems.querySelector('list-item')); }); test('SyncSectionLayout_UnifiedConsentEnabled_SignedIn', function() { - const ironCollapse = syncPage.$$('#sync-section'); + const syncSection = syncPage.$$('#sync-section'); const otherItems = syncPage.$$('#other-sync-items'); - const syncSectionToggle = syncPage.$$('#sync-section-toggle'); - const expandIcon = syncSectionToggle.querySelector('cr-expand-button'); - // When unified-consent is enabled and signed in, sync-section should be - // visible and open by default. Accordion toggle row should be present, - // and bottom items should have classes used for indentation. syncPage.syncStatus = { signedIn: true, disabled: false, @@ -205,39 +163,11 @@ }; syncPage.unifiedConsentEnabled = true; Polymer.dom.flush(); - assertTrue(ironCollapse.opened); - assertFalse(ironCollapse.hidden); - assertFalse(syncSectionToggle.hidden); - assertTrue(syncSectionToggle.hasAttribute('actionable')); - assertTrue(expandIcon.expanded); - assertFalse(expandIcon.disabled); + assertFalse(syncSection.hidden); assertTrue(otherItems.classList.contains('list-frame')); assertEquals( otherItems.querySelectorAll(':scope > .list-item').length, 3); - // Tapping on the toggle row should toggle ironCollapse. - syncSectionToggle.click(); - Polymer.dom.flush(); - assertFalse(ironCollapse.opened); - assertFalse(expandIcon.expanded); - - // Random changes to syncStatus should not expand the section. - // Regression test for https://crbug.com/869938 - syncPage.syncStatus = { - signedIn: true, - disabled: false, - hasError: false, - statusAction: settings.StatusAction.NO_ACTION, - statusText: 'UninterestingChange', // Dummy change to trigger observer. - }; - assertFalse(ironCollapse.opened); - assertFalse(expandIcon.expanded); - - syncSectionToggle.click(); - Polymer.dom.flush(); - assertTrue(ironCollapse.opened); - assertTrue(expandIcon.expanded); - // Test sync paused state. syncPage.syncStatus = { signedIn: true, @@ -245,7 +175,7 @@ hasError: true, statusAction: settings.StatusAction.REAUTHENTICATE }; - assertTrue(ironCollapse.hidden); + assertTrue(syncSection.hidden); // Test passphrase error state. syncPage.syncStatus = { @@ -254,54 +184,12 @@ hasError: true, statusAction: settings.StatusAction.ENTER_PASSPHRASE }; - assertFalse(ironCollapse.hidden); - }); - - test('SyncSectionLayout_UnifiedConsentEnabled_SignoutCollapse', function() { - const ironCollapse = syncPage.$$('#sync-section'); - const syncSectionToggle = syncPage.$$('#sync-section-toggle'); - const expandIcon = syncSectionToggle.querySelector('cr-expand-button'); - syncPage.syncStatus = { - signedIn: true, - disabled: false, - hasError: false, - statusAction: settings.StatusAction.NO_ACTION, - }; - syncPage.unifiedConsentEnabled = true; - Polymer.dom.flush(); - - // Sync section is initially open when signed in. - assertTrue(ironCollapse.opened); - assertTrue(expandIcon.expanded); - - // Signout collapses the section. - syncPage.syncStatus = { - signedIn: false, - disabled: false, - hasError: false, - statusAction: settings.StatusAction.NO_ACTION, - }; - assertFalse(ironCollapse.opened); - assertFalse(expandIcon.expanded); - - // Signin expands the section. - syncPage.syncStatus = { - signedIn: true, - disabled: false, - hasError: false, - statusAction: settings.StatusAction.NO_ACTION, - }; - assertTrue(ironCollapse.opened); - assertTrue(expandIcon.expanded); + assertFalse(syncSection.hidden); }); test('SyncSectionLayout_UnifiedConsentEnabled_SignedOut', function() { - const ironCollapse = syncPage.$$('#sync-section'); - const syncSectionToggle = syncPage.$$('#sync-section-toggle'); - const expandIcon = syncSectionToggle.querySelector('cr-expand-button'); + const syncSection = syncPage.$$('#sync-section'); - // When unified-consent is enabled and signed out, sync-section should be - // hidden, and the accordion toggle row should be visible not actionable. syncPage.syncStatus = { signedIn: false, disabled: false, @@ -310,19 +198,12 @@ }; syncPage.unifiedConsentEnabled = true; Polymer.dom.flush(); - assertTrue(ironCollapse.hidden); - assertFalse(syncSectionToggle.hidden); - assertFalse(syncSectionToggle.hasAttribute('actionable')); - assertFalse(expandIcon.expanded); - assertTrue(expandIcon.disabled); + assertTrue(syncSection.hidden); }); test('SyncSectionLayout_UnifiedConsentEnabled_SyncDisabled', function() { - const ironCollapse = syncPage.$$('#sync-section'); - const syncSectionToggle = syncPage.$$('#sync-section-toggle'); + const syncSection = syncPage.$$('#sync-section'); - // When unified-consent is enabled and sync is disabled, the sync-section - // should be hidden. syncPage.syncStatus = { signedIn: false, disabled: true, @@ -331,38 +212,7 @@ }; syncPage.unifiedConsentEnabled = true; Polymer.dom.flush(); - assertTrue(ironCollapse.hidden); - assertTrue(syncSectionToggle.hidden); - }); - - test('InitialLayout_UnifiedConsent_SignedIn', function() { - testInitialLayout( - /*signedIn=*/true, - /*hasError=*/false, - /*setupInProgress=*/false, - /*syncSectionExpanded=*/true, - /*syncSectionDisabled=*/false, - /*personalizeSectionExpanded=*/true); - }); - - test('InitialLayout_UnifiedConsent_SignedOut', function() { - testInitialLayout( - /*signedIn=*/false, - /*hasError=*/false, - /*setupInProgress=*/false, - /*syncSectionExpanded=*/false, - /*syncSectionDisabled=*/true, - /*personalizeSectionExpanded=*/true); - }); - - test('InitialLayout_UnifiedConsent_SyncPaused', function() { - testInitialLayout( - /*signedIn=*/true, - /*hasError=*/true, - /*setupInProgress=*/false, - /*syncSectionExpanded=*/false, - /*syncSectionDisabled=*/true, - /*personalizeSectionExpanded=*/true); + assertTrue(syncSection.hidden); }); test('LoadingAndTimeout', function() {
diff --git a/chrome/test/data/webui/settings/settings_main_test.js b/chrome/test/data/webui/settings/settings_main_test.js index 578a50e..0f0095c 100644 --- a/chrome/test/data/webui/settings/settings_main_test.js +++ b/chrome/test/data/webui/settings/settings_main_test.js
@@ -229,6 +229,11 @@ // "advanced" page, when the search has been initiated from a subpage // whose parent is the "advanced" page. test('exiting search mode, advanced expanded', function() { + // Trigger basic page to be rendered once. + settings.navigateTo(settings.routes.APPEARANCE); + Polymer.dom.flush(); + + // Navigate to an "advanced" subpage. settings.navigateTo(settings.routes.SITE_SETTINGS); Polymer.dom.flush(); return assertAdvancedVisibilityAfterSearch('block'); @@ -261,8 +266,11 @@ const basicPage = settingsMain.$$('settings-basic-page'); let advancedPage = null; - return basicPage.$$('#advancedPageTemplate') - .get() + + return test_util.eventToPromise('showing-section', settingsMain) + .then(() => { + return basicPage.$$('#advancedPageTemplate').get(); + }) .then(function(advanced) { advancedPage = advanced; return assertPageVisibility('block', 'block'); @@ -277,7 +285,6 @@ getToggleContainer().querySelector('#advancedToggle'); assertTrue(!!advancedToggle); advancedToggle.click(); - return whenHidden; }) .then(function() {
diff --git a/chrome/test/data/webui/settings/settings_slider_tests.js b/chrome/test/data/webui/settings/settings_slider_tests.js index 4eb7adc..04c72f5 100644 --- a/chrome/test/data/webui/settings/settings_slider_tests.js +++ b/chrome/test/data/webui/settings/settings_slider_tests.js
@@ -24,6 +24,7 @@ }; document.body.appendChild(slider); crSlider = slider.$$('cr-slider'); + return PolymerTest.flushTasks(); }); function pressArrowRight() { @@ -58,6 +59,28 @@ MockInteractions.pressAndReleaseKeyOn(crSlider, 35, [], 'End'); } + function pointerEvent(eventType, ratio) { + const rect = crSlider.$.barContainer.getBoundingClientRect(); + crSlider.dispatchEvent(new PointerEvent(eventType, { + buttons: 1, + pointerId: 1, + clientX: rect.left + (ratio * rect.width), + })); + } + + function pointerDown(ratio) { + pointerEvent('pointerdown', ratio); + } + + function pointerMove(ratio) { + pointerEvent('pointermove', ratio); + } + + function pointerUp() { + // Ignores clientX for pointerup event. + pointerEvent('pointerup', 0); + } + test('enforce value', function() { // Test that the indicator is not present until after the pref is // enforced. @@ -177,4 +200,35 @@ expectEquals(4, crSlider.value); expectEquals(.4, slider.pref.value); }); + + test('update value instantly both off and on', () => { + slider.ticks = ticks; + slider.set('pref.value', 2); + slider.updateValueInstantly = false; + assertEquals(0, crSlider.value); + pointerDown(3 / crSlider.max); + assertEquals(3, crSlider.value); + assertEquals(2, slider.pref.value); + pointerUp(); + assertEquals(3, crSlider.value); + assertEquals(16, slider.pref.value); + + // Once |updateValueInstantly| is turned on, |value| should start updating + // again during drag. + pointerDown(0); + assertEquals(0, crSlider.value); + assertEquals(16, slider.pref.value); + slider.updateValueInstantly = true; + assertEquals(2, slider.pref.value); + pointerMove(1 / crSlider.max); + assertEquals(1, crSlider.value); + assertEquals(4, slider.pref.value); + slider.updateValueInstantly = false; + pointerMove(2 / crSlider.max); + assertEquals(2, crSlider.value); + assertEquals(4, slider.pref.value); + pointerUp(); + assertEquals(2, crSlider.value); + assertEquals(8, slider.pref.value); + }); });
diff --git a/chrome/test/data/webui/welcome/email_chooser_test.js b/chrome/test/data/webui/welcome/email_chooser_test.js index 08f1ca8..5ca35e9 100644 --- a/chrome/test/data/webui/welcome/email_chooser_test.js +++ b/chrome/test/data/webui/welcome/email_chooser_test.js
@@ -22,6 +22,9 @@ /** @type {nux.NuxEmailProxy} */ let testEmailBrowserProxy; + /** @type {nux.ModuleMetricsProxy} */ + let testEmailMetricsProxy; + /** @type {nux.BookmarkProxy} */ let testBookmarkBrowserProxy; @@ -31,16 +34,22 @@ setup(function() { testEmailBrowserProxy = new TestNuxEmailProxy(); nux.NuxEmailProxyImpl.instance_ = testEmailBrowserProxy; + testEmailMetricsProxy = new TestMetricsProxy(); + nux.EmailMetricsProxyImpl.instance_ = testEmailMetricsProxy; testBookmarkBrowserProxy = new TestBookmarkProxy(); nux.BookmarkProxyImpl.instance_ = testBookmarkBrowserProxy; + // Reset w/ new proxy for test. + nux.BookmarkBarManager.instance_ = new nux.BookmarkBarManager(); testEmailBrowserProxy.setEmailList(emails); PolymerTest.clearBody(); testElement = document.createElement('email-chooser'); document.body.appendChild(testElement); + // Simulate nux-email's onRouteEnter call. + testElement.initializeSection(); return Promise.all([ - testEmailBrowserProxy.whenCalled('recordPageInitialized'), + testEmailMetricsProxy.whenCalled('recordPageShown'), testEmailBrowserProxy.whenCalled('getEmailList'), ]); }); @@ -58,13 +67,8 @@ assertFalse(testElement.$$('.action-button').disabled); options[0].click(); - return Promise - .all([ - testBookmarkBrowserProxy.whenCalled('removeBookmark'), - testEmailBrowserProxy.whenCalled('recordClickedOption'), - ]) - .then(responses => { - let removedId = responses[0]; + return testBookmarkBrowserProxy.whenCalled('removeBookmark') + .then(removedId => { assertEquals(removedId, 1); assertFalse(!!testElement.$$('.option[active]')); assertTrue(testElement.$$('.action-button').disabled); @@ -101,7 +105,7 @@ test('test email chooser skip button', function() { let options = testElement.shadowRoot.querySelectorAll('.option'); - testElement.bookmarkBarWasShown_ = true; + testElement.wasBookmarkBarShownOnInit_ = true; // First option should be selected and action button should be enabled. testElement.$.noThanksButton.click(); @@ -109,7 +113,7 @@ .all([ testBookmarkBrowserProxy.whenCalled('removeBookmark'), testBookmarkBrowserProxy.whenCalled('toggleBookmarkBar'), - testEmailBrowserProxy.whenCalled('recordNoThanks'), + testEmailMetricsProxy.whenCalled('recordDidNothingAndChoseSkip'), ]) .then(responses => { let removeBookmarkResponse = responses[0]; @@ -122,14 +126,15 @@ test('test email chooser next button', function() { let options = testElement.shadowRoot.querySelectorAll('.option'); - testElement.bookmarkBarWasShown_ = true; + testElement.wasBookmarkBarShownOnInit_ = true; + // First option should be selected and action button should be enabled. testElement.$$('.action-button').click(); return Promise .all([ testEmailBrowserProxy.whenCalled('recordProviderSelected'), - testEmailBrowserProxy.whenCalled('recordGetStarted'), + testEmailMetricsProxy.whenCalled('recordDidNothingAndChoseNext'), ]) .then(responses => { let recordProviderSelectedResponse = responses[0];
diff --git a/chrome/test/data/webui/welcome/module_metrics_test.js b/chrome/test/data/webui/welcome/module_metrics_test.js new file mode 100644 index 0000000..d012d7a2 --- /dev/null +++ b/chrome/test/data/webui/welcome/module_metrics_test.js
@@ -0,0 +1,89 @@ +// 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. + +cr.define('onboarding_welcome_module_metrics', function() { + suite('ModuleMetricsTest', function() { + /** @type {nux.ModuleMetricsProxy} */ + let testMetricsProxy; + + /** @type {nux.ModuleMetricsManager} */ + let testMetricsManager; + + setup(function() { + testMetricsProxy = new TestMetricsProxy(); + testMetricsManager = new nux.ModuleMetricsManager(testMetricsProxy); + + testMetricsManager.recordPageInitialized(); + + return testMetricsProxy.whenCalled('recordPageShown'); + }); + + teardown(function() { + nux.EmailMetricsProxyImpl.instance_ = null; + }); + + test('do nothing, click skip', function() { + testMetricsManager.recordNoThanks(); + return testMetricsProxy.whenCalled('recordDidNothingAndChoseSkip'); + }); + + test('do nothing, click next', function() { + testMetricsManager.recordGetStarted(); + return testMetricsProxy.whenCalled('recordDidNothingAndChoseNext'); + }); + + test('do nothing, navigate away', function() { + testMetricsManager.recordNavigatedAway(); + return testMetricsProxy.whenCalled('recordDidNothingAndNavigatedAway'); + }); + + test('choose option, click skip', function() { + testMetricsManager.recordClickedOption(); + testMetricsManager.recordNoThanks(); + return testMetricsProxy.whenCalled('recordChoseAnOptionAndChoseSkip'); + }); + + test('choose option, click next', function() { + testMetricsManager.recordClickedOption(); + testMetricsManager.recordGetStarted(); + return testMetricsProxy.whenCalled('recordChoseAnOptionAndChoseNext'); + }); + + test('choose option, navigate away', function() { + testMetricsManager.recordClickedOption(); + testMetricsManager.recordNavigatedAway(); + return testMetricsProxy.whenCalled('recordChoseAnOptionAndNavigatedAway'); + }); + + test('click disabled next, click skip', function() { + testMetricsManager.recordClickedDisabledButton(); + testMetricsManager.recordNoThanks(); + return testMetricsProxy.whenCalled( + 'recordClickedDisabledNextButtonAndChoseSkip'); + }); + + test('click disabled next, click next', function() { + testMetricsManager.recordClickedDisabledButton(); + // 'Next' should become enabled only after clicking another option. + testMetricsManager.recordClickedOption(); + testMetricsManager.recordGetStarted(); + return testMetricsProxy.whenCalled( + 'recordClickedDisabledNextButtonAndChoseNext'); + }); + + test('click disabled next, navigate away', function() { + testMetricsManager.recordClickedDisabledButton(); + testMetricsManager.recordNavigatedAway(); + return testMetricsProxy.whenCalled( + 'recordClickedDisabledNextButtonAndNavigatedAway'); + }); + + test('choose option, click disabled next, click next', function() { + testMetricsManager.recordClickedOption(); + testMetricsManager.recordClickedDisabledButton(); + testMetricsManager.recordGetStarted(); + return testMetricsProxy.whenCalled('recordChoseAnOptionAndChoseNext'); + }); + }); +});
diff --git a/chrome/test/data/webui/welcome/navigation_behavior_test.js b/chrome/test/data/webui/welcome/navigation_behavior_test.js new file mode 100644 index 0000000..2542bf5 --- /dev/null +++ b/chrome/test/data/webui/welcome/navigation_behavior_test.js
@@ -0,0 +1,166 @@ +// 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. + +cr.define('onboarding_welcome_navigation_behavior_test', function() { + suite('NavigationBehaviorTest', function() { + let elements = []; + let callOrders = []; + + suiteSetup(function() { + Polymer({ + is: 'test-element', + + behaviors: [welcome.NavigationBehavior], + + ready: function() { + this.reset(); + }, + + onRouteEnter: function() { + this.enterCalled = true; + callOrders.push('enter'); + }, + + onRouteChange: function() { + this.changeCalled = true; + callOrders.push('change'); + }, + + onRouteExit: function() { + this.exitCalled = true; + callOrders.push('exit'); + }, + + reset: function() { + this.enterCalled = false; + this.changeCalled = false; + this.exitCalled = false; + } + }); + }); + + setup(function() { + PolymerTest.clearBody(); + // Creates 3 elements with IDs step-(0~2). + for (let i = 0; i < 3; i++) { + elements.push(document.createElement('test-element')); + elements[i].id = `step-${i}`; + } + }); + + teardown(function() { + callOrders = []; + elements = []; + }); + + function appendAll() { + elements.forEach(elem => document.body.appendChild(elem)); + } + + function resetAll() { + elements.forEach(elem => elem.reset()); + callOrders = []; + } + + // exit should be called first, enter last, and all change calls in between. + function assertCallOrders() { + assertEquals(callOrders[0], 'exit'); + assertEquals(callOrders[callOrders.length - 1], 'enter'); + callOrders.slice(1, callOrders.length - 1).forEach(called => { + assertEquals(called, 'change'); + }); + } + + test('correct hooks fire when elements are attached', function() { + // Setup the "current route" state before things are appended. + welcome.navigateTo( + /* doesn't matter which route */ welcome.Routes.NEW_USER, 1); + appendAll(); + + assertFalse(elements[0].enterCalled); + assertTrue(elements[0].changeCalled); + assertFalse(elements[0].exitCalled); + + assertTrue(elements[1].enterCalled); + assertTrue(elements[1].changeCalled); + assertFalse(elements[1].exitCalled); + + assertFalse(elements[2].enterCalled); + assertTrue(elements[2].changeCalled); + assertFalse(elements[2].exitCalled); + }); + + test('hooks fire in expected order when elements are attached', function() { + // Pretend we're on step-1 + welcome.navigateTo( + /* doesn't matter which route */ welcome.Routes.NEW_USER, 1); + appendAll(); + resetAll(); + + // move on from step-1 to step 2. + welcome.navigateToNextStep(); + + assertFalse(elements[0].enterCalled); + assertTrue(elements[0].changeCalled); + assertFalse(elements[0].exitCalled); + + assertFalse(elements[1].enterCalled); + assertTrue(elements[1].changeCalled); + assertTrue(elements[1].exitCalled); + + assertTrue(elements[2].enterCalled); + assertTrue(elements[2].changeCalled); + assertFalse(elements[2].exitCalled); + assertCallOrders(); + }); + + test('popstate works as expected', async function() { + // Pretend we're on step-1 + welcome.navigateTo( + /* doesn't matter which route */ welcome.Routes.NEW_USER, 1); + appendAll(); + // move on from step-1 to step 2. + welcome.navigateToNextStep(); + resetAll(); + + // back from step-2 to step 1. + window.history.back(); + + await test_util.eventToPromise('popstate', window); + + assertFalse(elements[0].enterCalled); + assertTrue(elements[0].changeCalled); + assertFalse(elements[0].exitCalled); + + assertTrue(elements[1].enterCalled); + assertTrue(elements[1].changeCalled); + assertFalse(elements[1].exitCalled); + + assertFalse(elements[2].enterCalled); + assertTrue(elements[2].changeCalled); + assertTrue(elements[2].exitCalled); + + assertCallOrders(); + + resetAll(); + // move on from step-1 to step 2 again. + window.history.forward(); + + await test_util.eventToPromise('popstate', window); + + assertFalse(elements[0].enterCalled); + assertTrue(elements[0].changeCalled); + assertFalse(elements[0].exitCalled); + + assertFalse(elements[1].enterCalled); + assertTrue(elements[1].changeCalled); + assertTrue(elements[1].exitCalled); + + assertTrue(elements[2].enterCalled); + assertTrue(elements[2].changeCalled); + assertFalse(elements[2].exitCalled); + assertCallOrders(); + }); + }); +});
diff --git a/chrome/test/data/webui/welcome/onboarding_welcome_browsertest.js b/chrome/test/data/webui/welcome/onboarding_welcome_browsertest.js index d0248e2d..13348d3 100644 --- a/chrome/test/data/webui/welcome/onboarding_welcome_browsertest.js +++ b/chrome/test/data/webui/welcome/onboarding_welcome_browsertest.js
@@ -44,6 +44,7 @@ return super.extraLibraries.concat([ 'email_chooser_test.js', 'test_nux_email_proxy.js', + 'test_metrics_proxy.js', 'test_bookmark_proxy.js', ]); } @@ -94,3 +95,43 @@ TEST_F('OnboardingWelcomeSigninViewTest', 'All', function() { mocha.run(); }); + +OnboardingWelcomeNavigationBehaviorTest = + class extends OnboardingWelcomeBrowserTest { + /** @override */ + get browsePreload() { + return 'chrome://welcome/navigation_behavior.html'; + } + + /** @override */ + get extraLibraries() { + return super.extraLibraries.concat([ + '../settings/test_util.js', + 'navigation_behavior_test.js', + ]); + } +}; + +TEST_F('OnboardingWelcomeNavigationBehaviorTest', 'All', function() { + mocha.run(); +}); + +OnboardingWelcomeModuleMetricsTest = + class extends OnboardingWelcomeBrowserTest { + /** @override */ + get browsePreload() { + return 'chrome://welcome/shared/module_metrics_proxy.html'; + } + + /** @override */ + get extraLibraries() { + return super.extraLibraries.concat([ + 'module_metrics_test.js', + 'test_metrics_proxy.js', + ]); + } +}; + +TEST_F('OnboardingWelcomeModuleMetricsTest', 'All', function() { + mocha.run(); +});
diff --git a/chrome/test/data/webui/welcome/signin_view_test.js b/chrome/test/data/webui/welcome/signin_view_test.js index 020790a..f141c89 100644 --- a/chrome/test/data/webui/welcome/signin_view_test.js +++ b/chrome/test/data/webui/welcome/signin_view_test.js
@@ -68,7 +68,7 @@ noThanksButton.click(); return Promise.all([ testEmailBrowserProxy.whenCalled('getSavedProvider'), - testWelcomeBrowserProxy.whenCalled('goToNewTabPage'), + testWelcomeBrowserProxy.whenCalled('handleUserDecline'), ]); }); @@ -81,7 +81,7 @@ noThanksButton.click(); return testEmailBrowserProxy.whenCalled('getSavedProvider') .then(() => { - return testWelcomeBrowserProxy.whenCalled('goToURL'); + return testWelcomeBrowserProxy.whenCalled('handleUserDecline'); }) .then(url => { assertEquals(url, 'chrome://welcome/email-interstitial?provider=4');
diff --git a/chrome/test/data/webui/welcome/test_metrics_proxy.js b/chrome/test/data/webui/welcome/test_metrics_proxy.js new file mode 100644 index 0000000..ef5d4fc --- /dev/null +++ b/chrome/test/data/webui/welcome/test_metrics_proxy.js
@@ -0,0 +1,77 @@ +// 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. + +/** @implements {nux.ModuleMetricsProxy} */ +class TestMetricsProxy extends TestBrowserProxy { + constructor() { + super([ + 'recordChoseAnOptionAndChoseNext', + 'recordChoseAnOptionAndChoseSkip', + 'recordChoseAnOptionAndNavigatedAway', + 'recordClickedDisabledNextButtonAndChoseNext', + 'recordClickedDisabledNextButtonAndChoseSkip', + 'recordClickedDisabledNextButtonAndNavigatedAway', + 'recordDidNothingAndChoseNext', + 'recordDidNothingAndChoseSkip', + 'recordDidNothingAndNavigatedAway', + 'recordNavigatedAwayThroughBrowserHistory', + 'recordPageShown', + ]); + } + + /** @override */ + recordChoseAnOptionAndChoseNext() { + this.methodCalled('recordChoseAnOptionAndChoseNext'); + } + + /** @override */ + recordChoseAnOptionAndChoseSkip() { + this.methodCalled('recordChoseAnOptionAndChoseSkip'); + } + + /** @override */ + recordChoseAnOptionAndNavigatedAway() { + this.methodCalled('recordChoseAnOptionAndNavigatedAway'); + } + + /** @override */ + recordClickedDisabledNextButtonAndChoseNext() { + this.methodCalled('recordClickedDisabledNextButtonAndChoseNext'); + } + + /** @override */ + recordClickedDisabledNextButtonAndChoseSkip() { + this.methodCalled('recordClickedDisabledNextButtonAndChoseSkip'); + } + + /** @override */ + recordClickedDisabledNextButtonAndNavigatedAway() { + this.methodCalled('recordClickedDisabledNextButtonAndNavigatedAway'); + } + + /** @override */ + recordDidNothingAndChoseNext() { + this.methodCalled('recordDidNothingAndChoseNext'); + } + + /** @override */ + recordDidNothingAndChoseSkip() { + this.methodCalled('recordDidNothingAndChoseSkip'); + } + + /** @override */ + recordDidNothingAndNavigatedAway() { + this.methodCalled('recordDidNothingAndNavigatedAway'); + } + + /** @override */ + recordNavigatedAwayThroughBrowserHistory() { + this.methodCalled('recordNavigatedAwayThroughBrowserHistory'); + } + + /** @override */ + recordPageShown() { + this.methodCalled('recordPageShown'); + } +}
diff --git a/chrome/test/data/webui/welcome/test_nux_email_proxy.js b/chrome/test/data/webui/welcome/test_nux_email_proxy.js index d7a9f3f..816eda6 100644 --- a/chrome/test/data/webui/welcome/test_nux_email_proxy.js +++ b/chrome/test/data/webui/welcome/test_nux_email_proxy.js
@@ -2,6 +2,81 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +/** @implements {nux.ModuleMetricsProxy} */ +class TestEmailMetricsProxy extends TestBrowserProxy { + constructor() { + super([ + 'recordChoseAnOptionAndChoseNext', + 'recordChoseAnOptionAndChoseSkip', + 'recordChoseAnOptionAndNavigatedAway', + 'recordClickedDisabledNextButtonAndChoseNext', + 'recordClickedDisabledNextButtonAndChoseSkip', + 'recordClickedDisabledNextButtonAndNavigatedAway', + 'recordDidNothingAndChoseNext', + 'recordDidNothingAndChoseSkip', + 'recordDidNothingAndNavigatedAway', + 'recordNavigatedAwayThroughBrowserHistory', + 'recordPageShown', + ]); + } + + /** @override */ + recordChoseAnOptionAndChoseNext() { + this.methodCalled('recordChoseAnOptionAndChoseNext'); + } + + /** @override */ + recordChoseAnOptionAndChoseSkip() { + this.methodCalled('recordChoseAnOptionAndChoseSkip'); + } + + /** @override */ + recordChoseAnOptionAndNavigatedAway() { + this.methodCalled('recordChoseAnOptionAndNavigatedAway'); + } + + /** @override */ + recordClickedDisabledNextButtonAndChoseNext() { + this.methodCalled('recordClickedDisabledNextButtonAndChoseNext'); + } + + /** @override */ + recordClickedDisabledNextButtonAndChoseSkip() { + this.methodCalled('recordClickedDisabledNextButtonAndChoseSkip'); + } + + /** @override */ + recordClickedDisabledNextButtonAndNavigatedAway() { + this.methodCalled('recordClickedDisabledNextButtonAndNavigatedAway'); + } + + /** @override */ + recordDidNothingAndChoseNext() { + this.methodCalled('recordDidNothingAndChoseNext'); + } + + /** @override */ + recordDidNothingAndChoseSkip() { + this.methodCalled('recordDidNothingAndChoseSkip'); + } + + /** @override */ + recordDidNothingAndNavigatedAway() { + this.methodCalled('recordDidNothingAndNavigatedAway'); + } + + /** @override */ + recordNavigatedAwayThroughBrowserHistory() { + this.methodCalled('recordNavigatedAwayThroughBrowserHistory'); + } + + /** @override */ + recordPageShown() { + this.methodCalled('recordPageShown'); + } +} + /** @implements {nux.NuxEmailProxy} */ class TestNuxEmailProxy extends TestBrowserProxy { constructor() { @@ -9,13 +84,7 @@ 'cacheBookmarkIcon', 'getEmailList', 'getSavedProvider', - 'recordPageInitialized', - 'recordClickedOption', - 'recordClickedDisabledButton', 'recordProviderSelected', - 'recordNoThanks', - 'recordGetStarted', - 'recordFinalize', ]); /** @private {!Array<!nux.BookmarkListItem>} */ @@ -31,11 +100,6 @@ } /** @override */ - recordPageInitialized() { - this.methodCalled('recordPageInitialized'); - } - - /** @override */ getEmailList() { this.methodCalled('getEmailList'); return Promise.resolve(this.emailList_); @@ -45,35 +109,17 @@ cacheBookmarkIcon() { this.methodCalled('cacheBookmarkIcon'); } + /** @override */ getSavedProvider() { this.methodCalled('getSavedProvider'); return this.stubSavedProvider_; } - /** @override */ - recordClickedOption() { - this.methodCalled('recordClickedOption'); - } - /** @override */ - recordClickedDisabledButton() { - this.methodCalled('recordClickedDisabledButton'); - } + /** @override */ recordProviderSelected() { this.methodCalled('recordProviderSelected', arguments); } - /** @override */ - recordNoThanks() { - this.methodCalled('recordNoThanks'); - } - /** @override */ - recordGetStarted() { - this.methodCalled('recordGetStarted'); - } - /** @override */ - recordFinalize() { - this.methodCalled('recordFinalize'); - } /** @param {!Array<!nux.BookmarkListItem>} emailList */ setEmailList(emailList) {
diff --git a/chrome/test/data/webui/welcome/test_welcome_browser_proxy.js b/chrome/test/data/webui/welcome/test_welcome_browser_proxy.js index b2ea68d..e151927 100644 --- a/chrome/test/data/webui/welcome/test_welcome_browser_proxy.js +++ b/chrome/test/data/webui/welcome/test_welcome_browser_proxy.js
@@ -7,6 +7,7 @@ constructor() { super([ 'handleActivateSignIn', + 'handleUserDecline', 'goToNewTabPage', 'goToURL', ]); @@ -18,6 +19,11 @@ } /** @override */ + handleUserDecline(url) { + this.methodCalled('handleUserDecline', url); + } + + /** @override */ goToNewTabPage() { this.methodCalled('goToNewTabPage'); }
diff --git a/chrome/test/mini_installer/config/chrome_beta_installed.prop b/chrome/test/mini_installer/config/chrome_beta_installed.prop index 41573c7..9b866cfb 100644 --- a/chrome/test/mini_installer/config/chrome_beta_installed.prop +++ b/chrome/test/mini_installer/config/chrome_beta_installed.prop
@@ -3,7 +3,6 @@ "Files": { "$LOCAL_APPDATA\\$CHROME_DIR_BETA\\Application\\chrome.exe": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR_BETA\\Application\\chrome.VisualElementsManifest.xml": {"exists": true}, - "$LOCAL_APPDATA\\$CHROME_DIR_BETA\\Application\\chrome_proxy.exe": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR_BETA\\Application\\$MINI_INSTALLER_FILE_VERSION\\chrome.dll": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR_BETA\\Application\\$MINI_INSTALLER_FILE_VERSION\\chrome_elf.dll":
diff --git a/chrome/test/mini_installer/config/chrome_canary_installed.prop b/chrome/test/mini_installer/config/chrome_canary_installed.prop index 6e51e5e..41aa5385 100644 --- a/chrome/test/mini_installer/config/chrome_canary_installed.prop +++ b/chrome/test/mini_installer/config/chrome_canary_installed.prop
@@ -3,7 +3,6 @@ "Files": { "$LOCAL_APPDATA\\$CHROME_DIR_SXS\\Application\\chrome.exe": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR_SXS\\Application\\chrome.VisualElementsManifest.xml": {"exists": true}, - "$LOCAL_APPDATA\\$CHROME_DIR_SXS\\Application\\chrome_proxy.exe": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR_SXS\\Application\\$MINI_INSTALLER_FILE_VERSION\\chrome.dll": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR_SXS\\Application\\$MINI_INSTALLER_FILE_VERSION\\chrome_elf.dll":
diff --git a/chrome/test/mini_installer/config/chrome_dev_installed.prop b/chrome/test/mini_installer/config/chrome_dev_installed.prop index badfae3..89461a3 100644 --- a/chrome/test/mini_installer/config/chrome_dev_installed.prop +++ b/chrome/test/mini_installer/config/chrome_dev_installed.prop
@@ -3,7 +3,6 @@ "Files": { "$LOCAL_APPDATA\\$CHROME_DIR_DEV\\Application\\chrome.exe": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR_DEV\\Application\\chrome.VisualElementsManifest.xml": {"exists": true}, - "$LOCAL_APPDATA\\$CHROME_DIR_DEV\\Application\\chrome_proxy.exe": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR_DEV\\Application\\$MINI_INSTALLER_FILE_VERSION\\chrome.dll": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR_DEV\\Application\\$MINI_INSTALLER_FILE_VERSION\\chrome_elf.dll":
diff --git a/chrome/test/mini_installer/config/chrome_multi_system_installed.prop b/chrome/test/mini_installer/config/chrome_multi_system_installed.prop index 093a92f7..ddcfccc 100644 --- a/chrome/test/mini_installer/config/chrome_multi_system_installed.prop +++ b/chrome/test/mini_installer/config/chrome_multi_system_installed.prop
@@ -2,7 +2,6 @@ "Files": { "$PROGRAM_FILES\\$CHROME_DIR\\Application\\chrome.exe": {"exists": true}, "$PROGRAM_FILES\\$CHROME_DIR\\Application\\chrome.VisualElementsManifest.xml": {"exists": true}, - "$PROGRAM_FILES\\$CHROME_DIR\\Application\\chrome_proxy.exe": {"exists": true}, "$PROGRAM_FILES\\$CHROME_DIR\\Application\\$PREVIOUS_VERSION_MINI_INSTALLER_FILE_VERSION\\chrome.dll": {"exists": true}, "$PROGRAM_FILES\\$CHROME_DIR\\Application\\$PREVIOUS_VERSION_MINI_INSTALLER_FILE_VERSION\\chrome_elf.dll":
diff --git a/chrome/test/mini_installer/config/chrome_multi_user_installed.prop b/chrome/test/mini_installer/config/chrome_multi_user_installed.prop index dbf1c18..da2de26 100644 --- a/chrome/test/mini_installer/config/chrome_multi_user_installed.prop +++ b/chrome/test/mini_installer/config/chrome_multi_user_installed.prop
@@ -2,7 +2,6 @@ "Files": { "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\chrome.exe": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\chrome.VisualElementsManifest.xml": {"exists": true}, - "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\chrome_proxy.exe": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$PREVIOUS_VERSION_MINI_INSTALLER_FILE_VERSION\\chrome.dll": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$PREVIOUS_VERSION_MINI_INSTALLER_FILE_VERSION\\chrome_elf.dll":
diff --git a/chrome/test/mini_installer/config/chrome_system_installed.prop b/chrome/test/mini_installer/config/chrome_system_installed.prop index 6260f079..a1ac5f64 100644 --- a/chrome/test/mini_installer/config/chrome_system_installed.prop +++ b/chrome/test/mini_installer/config/chrome_system_installed.prop
@@ -2,7 +2,6 @@ "Files": { "$PROGRAM_FILES\\$CHROME_DIR\\Application\\chrome.exe": {"exists": true}, "$PROGRAM_FILES\\$CHROME_DIR\\Application\\chrome.VisualElementsManifest.xml": {"exists": true}, - "$PROGRAM_FILES\\$CHROME_DIR\\Application\\chrome_proxy.exe": {"exists": true}, "$PROGRAM_FILES\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\chrome.dll": {"exists": true}, "$PROGRAM_FILES\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\chrome_elf.dll":
diff --git a/chrome/test/mini_installer/config/chrome_user_installed.prop b/chrome/test/mini_installer/config/chrome_user_installed.prop index 0cf0534..e3c25a6 100644 --- a/chrome/test/mini_installer/config/chrome_user_installed.prop +++ b/chrome/test/mini_installer/config/chrome_user_installed.prop
@@ -2,7 +2,6 @@ "Files": { "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\chrome.exe": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\chrome.VisualElementsManifest.xml": {"exists": true}, - "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\chrome_proxy.exe": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\chrome.dll": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$MINI_INSTALLER_FILE_VERSION\\chrome_elf.dll":
diff --git a/chrome/test/mini_installer/config/previous_chrome_canary_installed.prop b/chrome/test/mini_installer/config/previous_chrome_canary_installed.prop index 6833c3c..46ddd2b 100644 --- a/chrome/test/mini_installer/config/previous_chrome_canary_installed.prop +++ b/chrome/test/mini_installer/config/previous_chrome_canary_installed.prop
@@ -3,7 +3,6 @@ "Files": { "$LOCAL_APPDATA\\$CHROME_DIR_SXS\\Application\\chrome.exe": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR_SXS\\Application\\chrome.VisualElementsManifest.xml": {"exists": true}, - "$LOCAL_APPDATA\\$CHROME_DIR_SXS\\Application\\chrome_proxy.exe": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR_SXS\\Application\\$PREVIOUS_VERSION_MINI_INSTALLER_FILE_VERSION\\chrome.dll": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR_SXS\\Application\\$PREVIOUS_VERSION_MINI_INSTALLER_FILE_VERSION\\chrome_elf.dll": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR_SXS\\Application\\$PREVIOUS_VERSION_MINI_INSTALLER_FILE_VERSION\\Installer\\chrome.7z": {"exists": true},
diff --git a/chrome/test/mini_installer/config/previous_chrome_system_installed.prop b/chrome/test/mini_installer/config/previous_chrome_system_installed.prop index affe252..0cfce8a3 100644 --- a/chrome/test/mini_installer/config/previous_chrome_system_installed.prop +++ b/chrome/test/mini_installer/config/previous_chrome_system_installed.prop
@@ -2,7 +2,6 @@ "Files": { "$PROGRAM_FILES\\$CHROME_DIR\\Application\\chrome.exe": {"exists": true}, "$PROGRAM_FILES\\$CHROME_DIR\\Application\\chrome.VisualElementsManifest.xml": {"exists": true}, - "$PROGRAM_FILES\\$CHROME_DIR\\Application\\chrome_proxy.exe": {"exists": true}, "$PROGRAM_FILES\\$CHROME_DIR\\Application\\$PREVIOUS_VERSION_MINI_INSTALLER_FILE_VERSION\\chrome.dll": {"exists": true}, "$PROGRAM_FILES\\$CHROME_DIR\\Application\\$PREVIOUS_VERSION_MINI_INSTALLER_FILE_VERSION\\chrome_elf.dll":
diff --git a/chrome/test/mini_installer/config/previous_chrome_user_installed.prop b/chrome/test/mini_installer/config/previous_chrome_user_installed.prop index 3ae41cb..6dc9f7a 100644 --- a/chrome/test/mini_installer/config/previous_chrome_user_installed.prop +++ b/chrome/test/mini_installer/config/previous_chrome_user_installed.prop
@@ -2,7 +2,6 @@ "Files": { "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\chrome.exe": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\chrome.VisualElementsManifest.xml": {"exists": true}, - "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\chrome_proxy.exe": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$PREVIOUS_VERSION_MINI_INSTALLER_FILE_VERSION\\chrome.dll": {"exists": true}, "$LOCAL_APPDATA\\$CHROME_DIR\\Application\\$PREVIOUS_VERSION_MINI_INSTALLER_FILE_VERSION\\chrome_elf.dll":
diff --git a/chrome/tools/build/win/FILES.cfg b/chrome/tools/build/win/FILES.cfg index f725a77..7e3718d 100644 --- a/chrome/tools/build/win/FILES.cfg +++ b/chrome/tools/build/win/FILES.cfg
@@ -845,15 +845,4 @@ 'buildtype': ['dev', 'official'], 'archive': 'chrome-win32-syms.zip', }, - # Bookmark apps shortcut target: - { - 'filename': 'chrome_proxy.exe', - 'buildtype': ['dev', 'official'], - 'filegroup': ['default', 'symsrc'], - }, - { - 'filename': 'chrome_proxy.exe.pdb', - 'buildtype': ['dev', 'official'], - 'archive': 'chrome-win32-syms.zip', - }, ]
diff --git a/chrome/utility/safe_browsing/mac/BUILD.gn b/chrome/utility/safe_browsing/mac/BUILD.gn index adaf939..34773a29 100644 --- a/chrome/utility/safe_browsing/mac/BUILD.gn +++ b/chrome/utility/safe_browsing/mac/BUILD.gn
@@ -16,7 +16,7 @@ ":dmg_common", "//base", "//chrome/common/safe_browsing:archive_analyzer_results", - "//chrome/common/safe_browsing:safe_browsing", + "//chrome/common/safe_browsing:binary_feature_extractor", "//components/safe_browsing:csd_proto", ] }
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn index b363ed6..3e4518e 100644 --- a/chromecast/browser/BUILD.gn +++ b/chromecast/browser/BUILD.gn
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/buildflag_header.gni") import("//build/config/ui.gni") import("//chromecast/chromecast.gni") import("//media/media_options.gni") @@ -13,6 +14,11 @@ import("//build/config/android/rules.gni") } +buildflag_header("browser_buildflags") { + header = "browser_buildflags.h" + flags = [ "ENABLE_CAST_AUDIO_MANAGER_MIXER=$enable_cast_audio_manager_mixer" ] +} + cast_source_set("browser") { sources = [ "application_media_capabilities.cc", @@ -114,6 +120,7 @@ ] deps = [ + ":browser_buildflags", "//base", "//base:i18n", "//cc",
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc index aa4724d..b9e03e5 100644 --- a/chromecast/browser/cast_content_browser_client.cc +++ b/chromecast/browser/cast_content_browser_client.cc
@@ -27,6 +27,7 @@ #include "chromecast/base/cast_paths.h" #include "chromecast/base/chromecast_switches.h" #include "chromecast/browser/application_session_id_manager.h" +#include "chromecast/browser/browser_buildflags.h" #include "chromecast/browser/cast_browser_context.h" #include "chromecast/browser/cast_browser_main_parts.h" #include "chromecast/browser/cast_browser_process.h" @@ -269,22 +270,13 @@ std::unique_ptr<::media::AudioManager> CastContentBrowserClient::CreateAudioManager( ::media::AudioLogFactory* audio_log_factory) { - // TODO(alokp): Consider switching off the mixer on audio platforms - // because we already have a mixer in the audio pipeline downstream of - // CastAudioManager. -#if !defined(OS_ANDROID) - bool use_mixer = true; -#else - bool use_mixer = false; -#endif - #if defined(OS_ANDROID) // Disable CMA backend on builds older than N. if (base::android::BuildInfo::GetInstance()->sdk_int() < base::android::SDK_VERSION_NOUGAT) { return nullptr; } -#endif +#endif // defined(OS_ANDROID) // Create the audio thread and initialize the CastSessionIdMap. We need to // initialize the CastSessionIdMap as soon as possible, so that the task @@ -302,7 +294,7 @@ {content::BrowserThread::UI}), GetMediaTaskRunner(), content::ServiceManagerConnection::GetForProcess()->GetConnector(), - use_mixer); + BUILDFLAG(ENABLE_CAST_AUDIO_MANAGER_MIXER)); #else return std::make_unique<media::CastAudioManager>( std::move(audio_thread), audio_log_factory, @@ -313,7 +305,7 @@ {content::BrowserThread::UI}), GetMediaTaskRunner(), content::ServiceManagerConnection::GetForProcess()->GetConnector(), - use_mixer); + BUILDFLAG(ENABLE_CAST_AUDIO_MANAGER_MIXER)); #endif // defined(USE_ALSA) }
diff --git a/chromecast/chromecast.gni b/chromecast/chromecast.gni index 02a14ff..d23449b 100644 --- a/chromecast/chromecast.gni +++ b/chromecast/chromecast.gni
@@ -104,6 +104,11 @@ # Whether to build cast for Android Things N version build_for_android_things_n = false + + # Set to true to enable mixing in CastAudioManager. Only needed on devices + # that do not have a mixer in the CMA backend. + enable_cast_audio_manager_mixer = + chromecast_branding == "google" && !is_cast_audio_only && !is_android } declare_args() {
diff --git a/chromecast/renderer/cast_content_renderer_client.cc b/chromecast/renderer/cast_content_renderer_client.cc index 299f7cd..5429e8e 100644 --- a/chromecast/renderer/cast_content_renderer_client.cc +++ b/chromecast/renderer/cast_content_renderer_client.cc
@@ -206,16 +206,16 @@ false /* force_software_crypto */); } -bool CastContentRendererClient::IsSupportedAudioConfig( - const ::media::AudioConfig& config) { +bool CastContentRendererClient::IsSupportedAudioType( + const ::media::AudioType& type) { #if defined(OS_ANDROID) // No ATV device we know of has (E)AC3 decoder, so it relies on the audio sink // device. - if (config.codec == ::media::kCodecEAC3) + if (type.codec == ::media::kCodecEAC3) return kBitstreamAudioCodecEac3 & supported_bitstream_audio_codecs_; - if (config.codec == ::media::kCodecAC3) + if (type.codec == ::media::kCodecAC3) return kBitstreamAudioCodecAc3 & supported_bitstream_audio_codecs_; - if (config.codec == ::media::kCodecMpegHAudio) + if (type.codec == ::media::kCodecMpegHAudio) return kBitstreamAudioCodecMpegHAudio & supported_bitstream_audio_codecs_; // TODO(sanfin): Implement this for Android. @@ -223,11 +223,11 @@ #else // If the HDMI sink supports bitstreaming the codec, then the vendor backend // does not need to support it. - if (IsSupportedBitstreamAudioCodec(config.codec)) { + if (IsSupportedBitstreamAudioCodec(type.codec)) { return true; } - media::AudioCodec codec = media::ToCastAudioCodec(config.codec); + media::AudioCodec codec = media::ToCastAudioCodec(type.codec); // Cast platform implements software decoding of Opus and FLAC, so only PCM // support is necessary in order to support Opus and FLAC. if (codec == media::kCodecOpus || codec == media::kCodecFLAC) @@ -240,17 +240,17 @@ #endif } -bool CastContentRendererClient::IsSupportedVideoConfig( - const ::media::VideoConfig& config) { +bool CastContentRendererClient::IsSupportedVideoType( + const ::media::VideoType& type) { // TODO(servolk): make use of eotf. #if defined(OS_ANDROID) return supported_profiles_->IsSupportedVideoConfig( - media::ToCastVideoCodec(config.codec, config.profile), - media::ToCastVideoProfile(config.profile), config.level); + media::ToCastVideoCodec(type.codec, type.profile), + media::ToCastVideoProfile(type.profile), type.level); #else return media::MediaCapabilitiesShlib::IsSupportedVideoConfig( - media::ToCastVideoCodec(config.codec, config.profile), - media::ToCastVideoProfile(config.profile), config.level); + media::ToCastVideoCodec(type.codec, type.profile), + media::ToCastVideoProfile(type.profile), type.level); #endif }
diff --git a/chromecast/renderer/cast_content_renderer_client.h b/chromecast/renderer/cast_content_renderer_client.h index efc9117c..40f0e3c4 100644 --- a/chromecast/renderer/cast_content_renderer_client.h +++ b/chromecast/renderer/cast_content_renderer_client.h
@@ -59,8 +59,8 @@ void AddSupportedKeySystems( std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems_properties) override; - bool IsSupportedAudioConfig(const ::media::AudioConfig& config) override; - bool IsSupportedVideoConfig(const ::media::VideoConfig& config) override; + bool IsSupportedAudioType(const ::media::AudioType& type) override; + bool IsSupportedVideoType(const ::media::VideoType& type) override; bool IsSupportedBitstreamAudioCodec(::media::AudioCodec codec) override; blink::WebPrescientNetworking* GetPrescientNetworking() override; bool DeferMediaLoad(content::RenderFrame* render_frame,
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn index 84493c2..8cda85e7 100644 --- a/chromeos/BUILD.gn +++ b/chromeos/BUILD.gn
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/buildflag_header.gni") import("//build/config/chromeos/rules.gni") import("//build/config/ui.gni") import("//testing/libfuzzer/fuzzer_test.gni") @@ -15,6 +16,11 @@ defines = [ "CHROMEOS_IMPLEMENTATION" ] } +buildflag_header("chromeos_buildflags") { + header = "chromeos_buildflags.h" + flags = [ "IS_CROS_CHROME_SDK=$is_cros_chrome_sdk" ] +} + component("chromeos") { configs += [ ":chromeos_implementation", @@ -315,6 +321,7 @@ ":attestation_proto", ":authpolicy_proto", ":biod_proto", + ":chromeos_buildflags", ":cryptohome_proto", ":oobe_config_proto", ":power_manager_proto", @@ -386,7 +393,7 @@ # linux-chromeos). See the following for reference: # https://chromium.googlesource.com/chromium/src/+/master/docs/chromeos_build_instructions.md # https://chromium.googlesource.com/chromiumos/docs/+/master/simple_chrome_workflow.md -if (is_chromeos_chrome) { +if (is_cros_chrome_sdk) { generate_vm_runner_script("cros_vm_launcher") { generated_script = "$root_build_dir/bin/launch_cros_vm"
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 9f40ecc5..c23b363c 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -11349.0.0 \ No newline at end of file +11361.0.0 \ No newline at end of file
diff --git a/chromeos/components/BUILD.gn b/chromeos/components/BUILD.gn index e019b6a..4680b66 100644 --- a/chromeos/components/BUILD.gn +++ b/chromeos/components/BUILD.gn
@@ -16,6 +16,7 @@ deps = [ "//base", "//base/test:test_support", + "//chromeos:chromeos_buildflags", "//chromeos/components/drivefs:unit_tests", "//chromeos/components/multidevice:unit_tests", "//chromeos/components/nearby:unit_tests",
diff --git a/chromeos/components/multidevice/BUILD.gn b/chromeos/components/multidevice/BUILD.gn index 35b75dc..5d72eb0 100644 --- a/chromeos/components/multidevice/BUILD.gn +++ b/chromeos/components/multidevice/BUILD.gn
@@ -6,6 +6,8 @@ static_library("multidevice") { sources = [ + "beacon_seed.cc", + "beacon_seed.h", "expiring_remote_device_cache.cc", "expiring_remote_device_cache.h", "remote_device.cc", @@ -14,12 +16,15 @@ "remote_device_cache.h", "remote_device_ref.cc", "remote_device_ref.h", + "software_feature.cc", + "software_feature.h", "software_feature_state.cc", "software_feature_state.h", ] deps = [ "//base", + "//base:i18n", "//chromeos", "//components/cryptauth/proto", "//components/cryptauth/proto:util", @@ -58,7 +63,7 @@ ":multidevice", ":test_support", "//base/test:test_support", - "//components/cryptauth/proto", + "//chromeos/components/multidevice/mojom:unit_tests", "//components/cryptauth/proto", "//testing/gtest", ]
diff --git a/chromeos/components/multidevice/DEPS b/chromeos/components/multidevice/DEPS index 42916a2..5f933001 100644 --- a/chromeos/components/multidevice/DEPS +++ b/chromeos/components/multidevice/DEPS
@@ -1,3 +1,4 @@ include_rules = [ "+components/cryptauth", + "+mojo/public/cpp", ]
diff --git a/chromeos/components/multidevice/beacon_seed.cc b/chromeos/components/multidevice/beacon_seed.cc new file mode 100644 index 0000000..368a3d9 --- /dev/null +++ b/chromeos/components/multidevice/beacon_seed.cc
@@ -0,0 +1,84 @@ +// 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 "chromeos/components/multidevice/beacon_seed.h" + +#include <algorithm> + +#include "base/base64.h" +#include "base/i18n/time_formatting.h" + +namespace chromeos { + +namespace multidevice { + +BeaconSeed::BeaconSeed() = default; + +BeaconSeed::BeaconSeed(const std::string& data, + base::Time start_time, + base::Time end_time) + : data_(data), start_time_(start_time), end_time_(end_time) {} + +BeaconSeed::BeaconSeed(const BeaconSeed& other) = default; + +BeaconSeed::~BeaconSeed() = default; + +bool BeaconSeed::operator==(const BeaconSeed& other) const { + return data_ == other.data_ && start_time_ == other.start_time_ && + end_time_ == other.end_time_; +} + +BeaconSeed FromCryptAuthSeed(cryptauth::BeaconSeed cryptauth_seed) { + return BeaconSeed( + cryptauth_seed.data(), + base::Time::FromJavaTime(cryptauth_seed.start_time_millis()), + base::Time::FromJavaTime(cryptauth_seed.end_time_millis())); +} + +cryptauth::BeaconSeed ToCryptAuthSeed(BeaconSeed multidevice_seed) { + cryptauth::BeaconSeed cryptauth_seed; + cryptauth_seed.set_data(multidevice_seed.data()); + cryptauth_seed.set_start_time_millis( + multidevice_seed.start_time().ToJavaTime()); + cryptauth_seed.set_end_time_millis(multidevice_seed.end_time().ToJavaTime()); + return cryptauth_seed; +} + +std::vector<cryptauth::BeaconSeed> ToCryptAuthSeedList( + const std::vector<BeaconSeed>& multidevice_seed_list) { + std::vector<cryptauth::BeaconSeed> cryptauth_beacon_seeds; + std::transform(multidevice_seed_list.begin(), multidevice_seed_list.end(), + std::back_inserter(cryptauth_beacon_seeds), + [](auto multidevice_beacon_seed) { + return ToCryptAuthSeed(multidevice_beacon_seed); + }); + return cryptauth_beacon_seeds; +} + +std::vector<BeaconSeed> FromCryptAuthSeedList( + const std::vector<cryptauth::BeaconSeed>& cryptauth_seed_list) { + std::vector<BeaconSeed> multidevice_beacon_seeds; + std::transform(cryptauth_seed_list.begin(), cryptauth_seed_list.end(), + std::back_inserter(multidevice_beacon_seeds), + [](auto cryptauth_beacon_seed) { + return FromCryptAuthSeed(cryptauth_beacon_seed); + }); + return multidevice_beacon_seeds; +} + +std::ostream& operator<<(std::ostream& stream, const BeaconSeed& beacon_seed) { + std::string base_64_data; + base::Base64Encode(beacon_seed.data(), &base_64_data); + + stream << "{base_64_data: \"" << base_64_data << "\", start_time: \"" + << base::TimeFormatShortDateAndTime(beacon_seed.start_time()) << "\", " + << "end_time: \"" + << base::TimeFormatShortDateAndTime(beacon_seed.start_time()) << "\"}"; + + return stream; +} + +} // namespace multidevice + +} // namespace chromeos
diff --git a/chromeos/components/multidevice/beacon_seed.h b/chromeos/components/multidevice/beacon_seed.h new file mode 100644 index 0000000..7dfe965 --- /dev/null +++ b/chromeos/components/multidevice/beacon_seed.h
@@ -0,0 +1,58 @@ +// 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 CHROMEOS_COMPONENTS_MULTIDEVICE_BEACON_SEED_H_ +#define CHROMEOS_COMPONENTS_MULTIDEVICE_BEACON_SEED_H_ + +#include <ostream> +#include <string> +#include <vector> + +#include "base/time/time.h" +#include "components/cryptauth/proto/cryptauth_api.pb.h" + +namespace chromeos { + +namespace multidevice { + +// Salt value used to generate ephemeral IDs for bootstrapping connections. +// A BeaconSeed value is valid only between its start and end timestamps. +// +// This class should always be preferred over the cryptauth::BeaconSeed proto +// except when communicating with the CryptAuth server. +class BeaconSeed { + public: + BeaconSeed(); + BeaconSeed(const std::string& data, + base::Time start_time, + base::Time end_time); + BeaconSeed(const BeaconSeed& other); + ~BeaconSeed(); + + const std::string& data() const { return data_; } + base::Time start_time() const { return start_time_; } + base::Time end_time() const { return end_time_; } + + bool operator==(const BeaconSeed& other) const; + + private: + std::string data_; + base::Time start_time_; + base::Time end_time_; +}; + +BeaconSeed FromCryptAuthSeed(cryptauth::BeaconSeed cryptauth_seed); +cryptauth::BeaconSeed ToCryptAuthSeed(BeaconSeed multidevice_seed); +std::vector<cryptauth::BeaconSeed> ToCryptAuthSeedList( + const std::vector<BeaconSeed>& cryptauth_seed_list); +std::vector<BeaconSeed> FromCryptAuthSeedList( + const std::vector<cryptauth::BeaconSeed>& cryptauth_seed_list); + +std::ostream& operator<<(std::ostream& stream, const BeaconSeed& beacon_seed); + +} // namespace multidevice + +} // namespace chromeos + +#endif // CHROMEOS_COMPONENTS_MULTIDEVICE_BEACON_SEED_H_
diff --git a/chromeos/components/multidevice/mojom/BUILD.gn b/chromeos/components/multidevice/mojom/BUILD.gn new file mode 100644 index 0000000..af858ec --- /dev/null +++ b/chromeos/components/multidevice/mojom/BUILD.gn
@@ -0,0 +1,32 @@ +# 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. + +import("//mojo/public/tools/bindings/mojom.gni") + +mojom("mojom") { + sources = [ + "multidevice_types.mojom", + ] + + public_deps = [ + "//mojo/public/mojom/base", + ] +} + +source_set("unit_tests") { + testonly = true + + sources = [ + "multidevice_mojom_traits_unittest.cc", + ] + + deps = [ + ":mojom", + "//base", + "//base/test:test_support", + "//chromeos/components/multidevice", + "//mojo/public/cpp/test_support:test_utils", + "//testing/gtest", + ] +}
diff --git a/chromeos/components/multidevice/mojom/OWNERS b/chromeos/components/multidevice/mojom/OWNERS new file mode 100644 index 0000000..ae29a36aa --- /dev/null +++ b/chromeos/components/multidevice/mojom/OWNERS
@@ -0,0 +1,6 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS +per-file *_mojom_traits*.*=set noparent +per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS +per-file *.typemap=set noparent +per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/chromeos/components/multidevice/mojom/multidevice.typemap b/chromeos/components/multidevice/mojom/multidevice.typemap new file mode 100644 index 0000000..e22b2d1 --- /dev/null +++ b/chromeos/components/multidevice/mojom/multidevice.typemap
@@ -0,0 +1,30 @@ +# 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. + +mojom = "//chromeos/components/multidevice/mojom/multidevice_types.mojom" + +public_headers = [ + "//chromeos/components/multidevice/beacon_seed.h", + "//chromeos/components/multidevice/remote_device.h", + "//chromeos/components/multidevice/software_feature.h", +] + +traits_headers = + [ "//chromeos/components/multidevice/mojom/multidevice_mojom_traits.h" ] + +sources = [ + "//chromeos/components/multidevice/mojom/multidevice_mojom_traits.cc", + "//chromeos/components/multidevice/mojom/multidevice_mojom_traits.h", +] + +public_deps = [ + "//chromeos/components/multidevice", + "//components/cryptauth/proto", +] + +type_mappings = [ + "chromeos.multidevice.mojom.BeaconSeed=chromeos::multidevice::BeaconSeed", + "chromeos.multidevice.mojom.RemoteDevice=chromeos::multidevice::RemoteDevice", + "chromeos.multidevice.mojom.SoftwareFeature=chromeos::multidevice::SoftwareFeature", +]
diff --git a/chromeos/components/multidevice/mojom/multidevice_mojom_traits.cc b/chromeos/components/multidevice/mojom/multidevice_mojom_traits.cc new file mode 100644 index 0000000..dcfc8da --- /dev/null +++ b/chromeos/components/multidevice/mojom/multidevice_mojom_traits.cc
@@ -0,0 +1,225 @@ +// 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 "chromeos/components/multidevice/mojom/multidevice_mojom_traits.h" + +#include "base/logging.h" +#include "chromeos/components/multidevice/remote_device_ref.h" +#include "mojo/public/cpp/base/time_mojom_traits.h" + +namespace mojo { + +const std::string& +StructTraits<chromeos::multidevice::mojom::BeaconSeedDataView, + chromeos::multidevice::BeaconSeed>:: + data(const chromeos::multidevice::BeaconSeed& beacon_seed) { + return beacon_seed.data(); +} + +base::Time StructTraits<chromeos::multidevice::mojom::BeaconSeedDataView, + chromeos::multidevice::BeaconSeed>:: + start_time(const chromeos::multidevice::BeaconSeed& beacon_seed) { + return beacon_seed.start_time(); +} + +base::Time StructTraits<chromeos::multidevice::mojom::BeaconSeedDataView, + chromeos::multidevice::BeaconSeed>:: + end_time(const chromeos::multidevice::BeaconSeed& beacon_seed) { + return beacon_seed.end_time(); +} + +bool StructTraits<chromeos::multidevice::mojom::BeaconSeedDataView, + chromeos::multidevice::BeaconSeed>:: + Read(chromeos::multidevice::mojom::BeaconSeedDataView in, + chromeos::multidevice::BeaconSeed* out) { + std::string beacon_seed_data; + base::Time start_time; + base::Time end_time; + + if (!in.ReadData(&beacon_seed_data) || !in.ReadStartTime(&start_time) || + !in.ReadEndTime(&end_time)) { + return false; + } + + *out = + chromeos::multidevice::BeaconSeed(beacon_seed_data, start_time, end_time); + + return true; +} + +std::string StructTraits<chromeos::multidevice::mojom::RemoteDeviceDataView, + chromeos::multidevice::RemoteDevice>:: + device_id(const chromeos::multidevice::RemoteDevice& remote_device) { + return remote_device.GetDeviceId(); +} + +const std::string& +StructTraits<chromeos::multidevice::mojom::RemoteDeviceDataView, + chromeos::multidevice::RemoteDevice>:: + user_id(const chromeos::multidevice::RemoteDevice& remote_device) { + return remote_device.user_id; +} + +const std::string& +StructTraits<chromeos::multidevice::mojom::RemoteDeviceDataView, + chromeos::multidevice::RemoteDevice>:: + device_name(const chromeos::multidevice::RemoteDevice& remote_device) { + return remote_device.name; +} + +const std::string& +StructTraits<chromeos::multidevice::mojom::RemoteDeviceDataView, + chromeos::multidevice::RemoteDevice>:: + persistent_symmetric_key( + const chromeos::multidevice::RemoteDevice& remote_device) { + return remote_device.persistent_symmetric_key; +} + +base::Time StructTraits<chromeos::multidevice::mojom::RemoteDeviceDataView, + chromeos::multidevice::RemoteDevice>:: + last_update_time(const chromeos::multidevice::RemoteDevice& remote_device) { + return base::Time::FromJavaTime(remote_device.last_update_time_millis); +} + +const std::map<chromeos::multidevice::SoftwareFeature, + chromeos::multidevice::SoftwareFeatureState>& +StructTraits<chromeos::multidevice::mojom::RemoteDeviceDataView, + chromeos::multidevice::RemoteDevice>:: + software_features( + const chromeos::multidevice::RemoteDevice& remote_device) { + return remote_device.software_features; +} + +const std::vector<chromeos::multidevice::BeaconSeed>& +StructTraits<chromeos::multidevice::mojom::RemoteDeviceDataView, + chromeos::multidevice::RemoteDevice>:: + beacon_seeds(const chromeos::multidevice::RemoteDevice& remote_device) { + return remote_device.beacon_seeds; +} + +bool StructTraits<chromeos::multidevice::mojom::RemoteDeviceDataView, + chromeos::multidevice::RemoteDevice>:: + Read(chromeos::multidevice::mojom::RemoteDeviceDataView in, + chromeos::multidevice::RemoteDevice* out) { + std::string device_id; + base::Time last_update_time; + + if (!in.ReadUserId(&out->user_id) || !in.ReadDeviceName(&out->name) || + !in.ReadDeviceId(&device_id) || + !in.ReadPersistentSymmetricKey(&out->persistent_symmetric_key) || + !in.ReadLastUpdateTime(&last_update_time) || + !in.ReadSoftwareFeatures(&out->software_features) || + !in.ReadBeaconSeeds(&out->beacon_seeds)) { + return false; + } + + out->public_key = + chromeos::multidevice::RemoteDeviceRef::DerivePublicKey(device_id); + out->last_update_time_millis = last_update_time.ToJavaTime(); + + return true; +} + +chromeos::multidevice::mojom::SoftwareFeature +EnumTraits<chromeos::multidevice::mojom::SoftwareFeature, + chromeos::multidevice::SoftwareFeature>:: + ToMojom(chromeos::multidevice::SoftwareFeature input) { + switch (input) { + case chromeos::multidevice::SoftwareFeature::kBetterTogetherHost: + return chromeos::multidevice::mojom::SoftwareFeature:: + BETTER_TOGETHER_HOST; + case chromeos::multidevice::SoftwareFeature::kBetterTogetherClient: + return chromeos::multidevice::mojom::SoftwareFeature:: + BETTER_TOGETHER_CLIENT; + case chromeos::multidevice::SoftwareFeature::kSmartLockHost: + return chromeos::multidevice::mojom::SoftwareFeature::EASY_UNLOCK_HOST; + case chromeos::multidevice::SoftwareFeature::kSmartLockClient: + return chromeos::multidevice::mojom::SoftwareFeature::EASY_UNLOCK_CLIENT; + case chromeos::multidevice::SoftwareFeature::kInstantTetheringHost: + return chromeos::multidevice::mojom::SoftwareFeature::MAGIC_TETHER_HOST; + case chromeos::multidevice::SoftwareFeature::kInstantTetheringClient: + return chromeos::multidevice::mojom::SoftwareFeature::MAGIC_TETHER_CLIENT; + case chromeos::multidevice::SoftwareFeature::kMessagesForWebHost: + return chromeos::multidevice::mojom::SoftwareFeature::SMS_CONNECT_HOST; + case chromeos::multidevice::SoftwareFeature::kMessagesForWebClient: + return chromeos::multidevice::mojom::SoftwareFeature::SMS_CONNECT_CLIENT; + } + + NOTREACHED(); + return chromeos::multidevice::mojom::SoftwareFeature::BETTER_TOGETHER_HOST; +} + +bool EnumTraits<chromeos::multidevice::mojom::SoftwareFeature, + chromeos::multidevice::SoftwareFeature>:: + FromMojom(chromeos::multidevice::mojom::SoftwareFeature input, + chromeos::multidevice::SoftwareFeature* out) { + switch (input) { + case chromeos::multidevice::mojom::SoftwareFeature::BETTER_TOGETHER_HOST: + *out = chromeos::multidevice::SoftwareFeature::kBetterTogetherHost; + return true; + case chromeos::multidevice::mojom::SoftwareFeature::BETTER_TOGETHER_CLIENT: + *out = chromeos::multidevice::SoftwareFeature::kBetterTogetherClient; + return true; + case chromeos::multidevice::mojom::SoftwareFeature::EASY_UNLOCK_HOST: + *out = chromeos::multidevice::SoftwareFeature::kSmartLockHost; + return true; + case chromeos::multidevice::mojom::SoftwareFeature::EASY_UNLOCK_CLIENT: + *out = chromeos::multidevice::SoftwareFeature::kSmartLockClient; + return true; + case chromeos::multidevice::mojom::SoftwareFeature::MAGIC_TETHER_HOST: + *out = chromeos::multidevice::SoftwareFeature::kInstantTetheringHost; + return true; + case chromeos::multidevice::mojom::SoftwareFeature::MAGIC_TETHER_CLIENT: + *out = chromeos::multidevice::SoftwareFeature::kInstantTetheringClient; + return true; + case chromeos::multidevice::mojom::SoftwareFeature::SMS_CONNECT_HOST: + *out = chromeos::multidevice::SoftwareFeature::kMessagesForWebHost; + return true; + case chromeos::multidevice::mojom::SoftwareFeature::SMS_CONNECT_CLIENT: + *out = chromeos::multidevice::SoftwareFeature::kMessagesForWebClient; + return true; + } + + NOTREACHED(); + return false; +} + +chromeos::multidevice::mojom::SoftwareFeatureState +EnumTraits<chromeos::multidevice::mojom::SoftwareFeatureState, + chromeos::multidevice::SoftwareFeatureState>:: + ToMojom(chromeos::multidevice::SoftwareFeatureState input) { + switch (input) { + case chromeos::multidevice::SoftwareFeatureState::kNotSupported: + return chromeos::multidevice::mojom::SoftwareFeatureState::kNotSupported; + case chromeos::multidevice::SoftwareFeatureState::kSupported: + return chromeos::multidevice::mojom::SoftwareFeatureState::kSupported; + case chromeos::multidevice::SoftwareFeatureState::kEnabled: + return chromeos::multidevice::mojom::SoftwareFeatureState::kEnabled; + } + + NOTREACHED(); + return chromeos::multidevice::mojom::SoftwareFeatureState::kNotSupported; +} + +bool EnumTraits<chromeos::multidevice::mojom::SoftwareFeatureState, + chromeos::multidevice::SoftwareFeatureState>:: + FromMojom(chromeos::multidevice::mojom::SoftwareFeatureState input, + chromeos::multidevice::SoftwareFeatureState* out) { + switch (input) { + case chromeos::multidevice::mojom::SoftwareFeatureState::kNotSupported: + *out = chromeos::multidevice::SoftwareFeatureState::kNotSupported; + return true; + case chromeos::multidevice::mojom::SoftwareFeatureState::kSupported: + *out = chromeos::multidevice::SoftwareFeatureState::kSupported; + return true; + case chromeos::multidevice::mojom::SoftwareFeatureState::kEnabled: + *out = chromeos::multidevice::SoftwareFeatureState::kEnabled; + return true; + } + + NOTREACHED(); + return false; +} + +} // namespace mojo
diff --git a/chromeos/components/multidevice/mojom/multidevice_mojom_traits.h b/chromeos/components/multidevice/mojom/multidevice_mojom_traits.h new file mode 100644 index 0000000..b89f93a --- /dev/null +++ b/chromeos/components/multidevice/mojom/multidevice_mojom_traits.h
@@ -0,0 +1,84 @@ +// 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 CHROMEOS_COMPONENTS_MULTIDEVICE_MOJOM_MULTIDEVICE_MOJOM_TRAITS_H_ +#define CHROMEOS_COMPONENTS_MULTIDEVICE_MOJOM_MULTIDEVICE_MOJOM_TRAITS_H_ + +#include <string> +#include <vector> + +#include "base/time/time.h" +#include "chromeos/components/multidevice/beacon_seed.h" +#include "chromeos/components/multidevice/mojom/multidevice_types.mojom.h" +#include "chromeos/components/multidevice/remote_device.h" +#include "chromeos/components/multidevice/software_feature.h" +#include "chromeos/components/multidevice/software_feature_state.h" +#include "mojo/public/cpp/bindings/enum_traits.h" +#include "mojo/public/cpp/bindings/struct_traits.h" + +namespace mojo { + +template <> +class StructTraits<chromeos::multidevice::mojom::BeaconSeedDataView, + chromeos::multidevice::BeaconSeed> { + public: + static const std::string& data( + const chromeos::multidevice::BeaconSeed& beacon_seed); + static base::Time start_time( + const chromeos::multidevice::BeaconSeed& beacon_seed); + static base::Time end_time( + const chromeos::multidevice::BeaconSeed& beacon_seed); + + static bool Read(chromeos::multidevice::mojom::BeaconSeedDataView in, + chromeos::multidevice::BeaconSeed* out); +}; + +template <> +class StructTraits<chromeos::multidevice::mojom::RemoteDeviceDataView, + chromeos::multidevice::RemoteDevice> { + public: + static std::string device_id( + const chromeos::multidevice::RemoteDevice& remote_device); + static const std::string& user_id( + const chromeos::multidevice::RemoteDevice& remote_device); + static const std::string& device_name( + const chromeos::multidevice::RemoteDevice& remote_device); + static const std::string& persistent_symmetric_key( + const chromeos::multidevice::RemoteDevice& remote_device); + static base::Time last_update_time( + const chromeos::multidevice::RemoteDevice& remote_device); + static const std::map<chromeos::multidevice::SoftwareFeature, + chromeos::multidevice::SoftwareFeatureState>& + software_features(const chromeos::multidevice::RemoteDevice& remote_device); + static const std::vector<chromeos::multidevice::BeaconSeed>& beacon_seeds( + const chromeos::multidevice::RemoteDevice& remote_device); + + static bool Read(chromeos::multidevice::mojom::RemoteDeviceDataView in, + chromeos::multidevice::RemoteDevice* out); +}; + +template <> +class EnumTraits<chromeos::multidevice::mojom::SoftwareFeature, + chromeos::multidevice::SoftwareFeature> { + public: + static chromeos::multidevice::mojom::SoftwareFeature ToMojom( + chromeos::multidevice::SoftwareFeature input); + static bool FromMojom(chromeos::multidevice::mojom::SoftwareFeature input, + chromeos::multidevice::SoftwareFeature* out); +}; + +template <> +class EnumTraits<chromeos::multidevice::mojom::SoftwareFeatureState, + chromeos::multidevice::SoftwareFeatureState> { + public: + static chromeos::multidevice::mojom::SoftwareFeatureState ToMojom( + chromeos::multidevice::SoftwareFeatureState input); + static bool FromMojom( + chromeos::multidevice::mojom::SoftwareFeatureState input, + chromeos::multidevice::SoftwareFeatureState* out); +}; + +} // namespace mojo + +#endif // CHROMEOS_COMPONENTS_MULTIDEVICE_MOJOM_MULTIDEVICE_MOJOM_TRAITS_H_
diff --git a/chromeos/components/multidevice/mojom/multidevice_mojom_traits_unittest.cc b/chromeos/components/multidevice/mojom/multidevice_mojom_traits_unittest.cc new file mode 100644 index 0000000..12a22f1 --- /dev/null +++ b/chromeos/components/multidevice/mojom/multidevice_mojom_traits_unittest.cc
@@ -0,0 +1,106 @@ +// 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 "chromeos/components/multidevice/mojom/multidevice_mojom_traits.h" + +#include "base/time/time.h" +#include "chromeos/components/multidevice/beacon_seed.h" +#include "chromeos/components/multidevice/mojom/multidevice_types.mojom.h" +#include "chromeos/components/multidevice/remote_device.h" +#include "mojo/public/cpp/base/time_mojom_traits.h" +#include "mojo/public/cpp/test_support/test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +const char kTestBeaconSeedData[] = "data"; +const int64_t kTestBeaconSeedStartTimeMillis = 1L; +const int64_t kTestBeaconSeedEndTimeMillis = 2L; + +chromeos::multidevice::BeaconSeed CreateTestBeaconSeed() { + return chromeos::multidevice::BeaconSeed( + kTestBeaconSeedData, + base::Time::FromJavaTime(kTestBeaconSeedStartTimeMillis), + base::Time::FromJavaTime(kTestBeaconSeedEndTimeMillis)); +} + +} // namespace + +TEST(MultiDeviceMojomStructTraitsTest, BeaconSeed) { + chromeos::multidevice::BeaconSeed input = CreateTestBeaconSeed(); + + chromeos::multidevice::BeaconSeed output; + EXPECT_TRUE(mojo::test::SerializeAndDeserialize< + chromeos::multidevice::mojom::BeaconSeed>(&input, &output)); + + EXPECT_EQ(kTestBeaconSeedData, output.data()); + EXPECT_EQ(kTestBeaconSeedStartTimeMillis, output.start_time().ToJavaTime()); + EXPECT_EQ(kTestBeaconSeedEndTimeMillis, output.end_time().ToJavaTime()); +} + +TEST(MultiDeviceMojomStructTraitsTest, RemoteDevice) { + std::map<chromeos::multidevice::SoftwareFeature, + chromeos::multidevice::SoftwareFeatureState> + software_features = + std::map<chromeos::multidevice::SoftwareFeature, + chromeos::multidevice::SoftwareFeatureState>(); + software_features + [chromeos::multidevice::SoftwareFeature::kBetterTogetherClient] = + chromeos::multidevice::SoftwareFeatureState::kSupported; + software_features + [chromeos::multidevice::SoftwareFeature::kBetterTogetherHost] = + chromeos::multidevice::SoftwareFeatureState::kEnabled; + + chromeos::multidevice::RemoteDevice input; + input.user_id = "userId"; + input.name = "name"; + input.public_key = "publicKey"; + input.persistent_symmetric_key = "persistentSymmetricKey"; + input.last_update_time_millis = 3L; + input.software_features = software_features; + input.beacon_seeds = {CreateTestBeaconSeed()}; + + chromeos::multidevice::RemoteDevice output; + EXPECT_TRUE(mojo::test::SerializeAndDeserialize< + chromeos::multidevice::mojom::RemoteDevice>(&input, &output)); + + EXPECT_EQ("userId", output.user_id); + EXPECT_EQ("name", output.name); + EXPECT_EQ("publicKey", output.public_key); + EXPECT_EQ("persistentSymmetricKey", output.persistent_symmetric_key); + EXPECT_EQ(3L, output.last_update_time_millis); + EXPECT_EQ(software_features, output.software_features); + ASSERT_EQ(1u, output.beacon_seeds.size()); + EXPECT_EQ(kTestBeaconSeedData, output.beacon_seeds[0].data()); + EXPECT_EQ(kTestBeaconSeedStartTimeMillis, + output.beacon_seeds[0].start_time().ToJavaTime()); + EXPECT_EQ(kTestBeaconSeedEndTimeMillis, + output.beacon_seeds[0].end_time().ToJavaTime()); +} + +TEST(DeviceSyncMojomEnumTraitsTest, SoftwareFeature) { + static constexpr chromeos::multidevice::SoftwareFeature + kTestSoftwareFeatures[] = { + chromeos::multidevice::SoftwareFeature::kBetterTogetherHost, + chromeos::multidevice::SoftwareFeature::kBetterTogetherClient, + chromeos::multidevice::SoftwareFeature::kSmartLockHost, + chromeos::multidevice::SoftwareFeature::kSmartLockClient, + chromeos::multidevice::SoftwareFeature::kInstantTetheringHost, + chromeos::multidevice::SoftwareFeature::kInstantTetheringClient, + chromeos::multidevice::SoftwareFeature::kMessagesForWebHost, + chromeos::multidevice::SoftwareFeature::kMessagesForWebClient}; + + for (auto feature_in : kTestSoftwareFeatures) { + chromeos::multidevice::SoftwareFeature feature_out; + + chromeos::multidevice::mojom::SoftwareFeature serialized_feature = + mojo::EnumTraits< + chromeos::multidevice::mojom::SoftwareFeature, + chromeos::multidevice::SoftwareFeature>::ToMojom(feature_in); + ASSERT_TRUE((mojo::EnumTraits<chromeos::multidevice::mojom::SoftwareFeature, + chromeos::multidevice::SoftwareFeature>:: + FromMojom(serialized_feature, &feature_out))); + EXPECT_EQ(feature_in, feature_out); + } +}
diff --git a/chromeos/components/multidevice/mojom/multidevice_types.mojom b/chromeos/components/multidevice/mojom/multidevice_types.mojom new file mode 100644 index 0000000..9132550f --- /dev/null +++ b/chromeos/components/multidevice/mojom/multidevice_types.mojom
@@ -0,0 +1,85 @@ +// 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. + +module chromeos.multidevice.mojom; + +import "mojo/public/mojom/base/time.mojom"; + +// Enumeration of software features which can be enabled/disabled for a given +// device. Each feature has a host and client portion; here, "host" refers to +// the associated phone which provides the feature (at most one host per +// account), and "client" refers to the Chromebook which consumes the feature +// (multiple clients allowed per account). +enum SoftwareFeature { + // The Better Together (MultiDevice) setup flow feature allows users to go + // through a unified setup flow which enrolls the device for all multi-device + // features. + BETTER_TOGETHER_HOST = 1, + BETTER_TOGETHER_CLIENT = 2, + + // EasyUnlock gives users the ability to unlock their Chromebooks with their + // phone instead of by typing a password. + EASY_UNLOCK_HOST = 3, + EASY_UNLOCK_CLIENT = 4, + + // Magic Tether (Instant Tethering) gives users the ability to use their + // phone's Internet connectivity on their Chromebooks via an automated flow + // which does not require any phone-side interaction. + MAGIC_TETHER_HOST = 5, + MAGIC_TETHER_CLIENT = 6, + + // SMS Connect gives users the ability to read and reply to their text + // messages from their Chromebooks. + SMS_CONNECT_HOST = 7, + SMS_CONNECT_CLIENT = 8 +}; + +// Enumeration of what value a SoftwareFeature can be. +enum SoftwareFeatureState { + kNotSupported, + kSupported, + kEnabled +}; + +// Used to generate rotating BLE advertisement data, which is necessary to +// establish a BLE communication channel between two devices. To +// create the BLE channel, both devices must possess the other's BeaconSeeds. +struct BeaconSeed { + string data; + mojo_base.mojom.Time start_time; + mojo_base.mojom.Time end_time; +}; + +// Metadata describing a remote device with which the current device can +// communicate. +struct RemoteDevice { + // Unique identifier of the device. This field is guaranteed to be + // human-readable (i.e., it does not contain non-ASCII characters). + string device_id; + + // Identifier for the user to whom this device is registered. + string user_id; + + // Human-readable device name; by default, this is the name of the device + // model, but this value is editable. + string device_name; + + // Encryption key used for communication with this device. + string persistent_symmetric_key; + + // The time at which this device's metadata was last updated on the CryptAuth + // back-end. + mojo_base.mojom.Time last_update_time; + + // The features which this device either does not support, supports, or has + // enabled. + map<SoftwareFeature, SoftwareFeatureState> software_features; + + // Seeds belonging to the device. Each seed has start and end timestamps which + // indicate how long the seed is valid, and each device has enough associated + // seeds to keep the device connectable for over 30 days. If no new device + // metadata synced for over 30 days, it is possible that a connection will not + // be able to be established over BLE. + array<BeaconSeed> beacon_seeds; +};
diff --git a/chromeos/components/multidevice/mojom/typemaps.gni b/chromeos/components/multidevice/mojom/typemaps.gni new file mode 100644 index 0000000..27fc7e2 --- /dev/null +++ b/chromeos/components/multidevice/mojom/typemaps.gni
@@ -0,0 +1,5 @@ +# 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. + +typemaps = [ "//chromeos/components/multidevice/mojom/multidevice.typemap" ]
diff --git a/chromeos/components/multidevice/remote_device.cc b/chromeos/components/multidevice/remote_device.cc index ffbf5b3a3..f7d1a24 100644 --- a/chromeos/components/multidevice/remote_device.cc +++ b/chromeos/components/multidevice/remote_device.cc
@@ -11,30 +11,6 @@ namespace multidevice { -namespace { - -// Returns true if both vectors of BeaconSeeds are equal. -bool AreBeaconSeedsEqual( - const std::vector<cryptauth::BeaconSeed> beacon_seeds1, - const std::vector<cryptauth::BeaconSeed> beacon_seeds2) { - if (beacon_seeds1.size() != beacon_seeds2.size()) - return false; - - for (size_t i = 0; i < beacon_seeds1.size(); ++i) { - const cryptauth::BeaconSeed& seed1 = beacon_seeds1[i]; - const cryptauth::BeaconSeed& seed2 = beacon_seeds2[i]; - if (seed1.start_time_millis() != seed2.start_time_millis() || - seed1.end_time_millis() != seed2.end_time_millis() || - seed1.data() != seed2.data()) { - return false; - } - } - - return true; -} - -} // namespace - // static std::string RemoteDevice::GenerateDeviceId(const std::string& public_key) { std::string device_id; @@ -50,9 +26,8 @@ const std::string& public_key, const std::string& persistent_symmetric_key, int64_t last_update_time_millis, - const std::map<cryptauth::SoftwareFeature, SoftwareFeatureState>& - software_features, - const std::vector<cryptauth::BeaconSeed>& beacon_seeds) + const std::map<SoftwareFeature, SoftwareFeatureState>& software_features, + const std::vector<BeaconSeed>& beacon_seeds) : user_id(user_id), name(name), public_key(public_key), @@ -75,7 +50,7 @@ persistent_symmetric_key == other.persistent_symmetric_key && last_update_time_millis == other.last_update_time_millis && software_features == other.software_features && - AreBeaconSeedsEqual(beacon_seeds, other.beacon_seeds); + beacon_seeds == other.beacon_seeds; } bool RemoteDevice::operator<(const RemoteDevice& other) const {
diff --git a/chromeos/components/multidevice/remote_device.h b/chromeos/components/multidevice/remote_device.h index 83225f0..5f626be 100644 --- a/chromeos/components/multidevice/remote_device.h +++ b/chromeos/components/multidevice/remote_device.h
@@ -9,15 +9,15 @@ #include <string> #include <vector> +#include "chromeos/components/multidevice/beacon_seed.h" +#include "chromeos/components/multidevice/software_feature.h" #include "chromeos/components/multidevice/software_feature_state.h" -#include "components/cryptauth/proto/cryptauth_api.pb.h" namespace chromeos { namespace multidevice { struct RemoteDevice { - public: // Generates the device ID for a device given its public key. static std::string GenerateDeviceId(const std::string& public_key); @@ -26,18 +26,18 @@ std::string public_key; std::string persistent_symmetric_key; int64_t last_update_time_millis; - std::map<cryptauth::SoftwareFeature, SoftwareFeatureState> software_features; - std::vector<cryptauth::BeaconSeed> beacon_seeds; + std::map<SoftwareFeature, SoftwareFeatureState> software_features; + std::vector<BeaconSeed> beacon_seeds; RemoteDevice(); - RemoteDevice(const std::string& user_id, - const std::string& name, - const std::string& public_key, - const std::string& persistent_symmetric_key, - int64_t last_update_time_millis, - const std::map<cryptauth::SoftwareFeature, SoftwareFeatureState>& - software_features, - const std::vector<cryptauth::BeaconSeed>& beacon_seeds); + RemoteDevice( + const std::string& user_id, + const std::string& name, + const std::string& public_key, + const std::string& persistent_symmetric_key, + int64_t last_update_time_millis, + const std::map<SoftwareFeature, SoftwareFeatureState>& software_features, + const std::vector<BeaconSeed>& beacon_seeds); RemoteDevice(const RemoteDevice& other); ~RemoteDevice();
diff --git a/chromeos/components/multidevice/remote_device_ref.cc b/chromeos/components/multidevice/remote_device_ref.cc index 7ad450e2..d7b2559 100644 --- a/chromeos/components/multidevice/remote_device_ref.cc +++ b/chromeos/components/multidevice/remote_device_ref.cc
@@ -43,7 +43,7 @@ RemoteDeviceRef::~RemoteDeviceRef() = default; SoftwareFeatureState RemoteDeviceRef::GetSoftwareFeatureState( - const cryptauth::SoftwareFeature& software_feature) const { + const SoftwareFeature& software_feature) const { if (!base::ContainsKey(remote_device_->software_features, software_feature)) return SoftwareFeatureState::kNotSupported;
diff --git a/chromeos/components/multidevice/remote_device_ref.h b/chromeos/components/multidevice/remote_device_ref.h index 5a7e1c86..bb6f2f84 100644 --- a/chromeos/components/multidevice/remote_device_ref.h +++ b/chromeos/components/multidevice/remote_device_ref.h
@@ -12,7 +12,6 @@ #include "base/gtest_prod_util.h" #include "chromeos/components/multidevice/remote_device.h" #include "chromeos/components/multidevice/software_feature_state.h" -#include "components/cryptauth/proto/cryptauth_api.pb.h" namespace chromeos { class EasyUnlockServiceRegular; @@ -67,13 +66,13 @@ int64_t last_update_time_millis() const { return remote_device_->last_update_time_millis; } - const std::vector<cryptauth::BeaconSeed>& beacon_seeds() const { + const std::vector<BeaconSeed>& beacon_seeds() const { return remote_device_->beacon_seeds; } std::string GetDeviceId() const; SoftwareFeatureState GetSoftwareFeatureState( - const cryptauth::SoftwareFeature& software_feature) const; + const SoftwareFeature& software_feature) const; // Returns a shortened device ID for the purpose of concise logging (device // IDs are often so long that logs are difficult to read). Note that this
diff --git a/chromeos/components/multidevice/remote_device_ref_unittest.cc b/chromeos/components/multidevice/remote_device_ref_unittest.cc index d273280d..15510be 100644 --- a/chromeos/components/multidevice/remote_device_ref_unittest.cc +++ b/chromeos/components/multidevice/remote_device_ref_unittest.cc
@@ -20,17 +20,14 @@ // testing::Test: void SetUp() override { - std::map<cryptauth::SoftwareFeature, SoftwareFeatureState> + std::map<SoftwareFeature, SoftwareFeatureState> software_feature_to_state_map; - software_feature_to_state_map - [cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT] = - SoftwareFeatureState::kSupported; - software_feature_to_state_map - [cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = - SoftwareFeatureState::kEnabled; + software_feature_to_state_map[SoftwareFeature::kBetterTogetherClient] = + SoftwareFeatureState::kSupported; + software_feature_to_state_map[SoftwareFeature::kBetterTogetherHost] = + SoftwareFeatureState::kEnabled; - std::vector<cryptauth::BeaconSeed> beacon_seeds( - {cryptauth::BeaconSeed(), cryptauth::BeaconSeed()}); + std::vector<BeaconSeed> beacon_seeds({BeaconSeed(), BeaconSeed()}); remote_device_ = std::make_shared<RemoteDevice>( "user_id", "name", "public_key", "persistent_symmetric_key", @@ -58,13 +55,13 @@ EXPECT_EQ(SoftwareFeatureState::kNotSupported, remote_device_ref.GetSoftwareFeatureState( - cryptauth::SoftwareFeature::MAGIC_TETHER_CLIENT)); + SoftwareFeature::kInstantTetheringClient)); EXPECT_EQ(SoftwareFeatureState::kSupported, remote_device_ref.GetSoftwareFeatureState( - cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT)); + SoftwareFeature::kBetterTogetherClient)); EXPECT_EQ(SoftwareFeatureState::kEnabled, remote_device_ref.GetSoftwareFeatureState( - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST)); + SoftwareFeature::kBetterTogetherHost)); EXPECT_EQ(remote_device_->GetDeviceId(), remote_device_ref.GetDeviceId()); EXPECT_EQ(
diff --git a/chromeos/components/multidevice/remote_device_test_util.cc b/chromeos/components/multidevice/remote_device_test_util.cc index de590eb..d9ada24 100644 --- a/chromeos/components/multidevice/remote_device_test_util.cc +++ b/chromeos/components/multidevice/remote_device_test_util.cc
@@ -46,15 +46,14 @@ RemoteDeviceRefBuilder& RemoteDeviceRefBuilder::SetSupportsMobileHotspot( bool supports_mobile_hotspot) { - remote_device_ - ->software_features[cryptauth::SoftwareFeature::MAGIC_TETHER_HOST] = + remote_device_->software_features[SoftwareFeature::kInstantTetheringHost] = supports_mobile_hotspot ? SoftwareFeatureState::kSupported : SoftwareFeatureState::kNotSupported; return *this; } RemoteDeviceRefBuilder& RemoteDeviceRefBuilder::SetSoftwareFeatureState( - const cryptauth::SoftwareFeature feature, + const SoftwareFeature feature, const SoftwareFeatureState new_state) { remote_device_->software_features[feature] = new_state; return *this; @@ -67,7 +66,7 @@ } RemoteDeviceRefBuilder& RemoteDeviceRefBuilder::SetBeaconSeeds( - const std::vector<cryptauth::BeaconSeed>& beacon_seeds) { + const std::vector<BeaconSeed>& beacon_seeds) { remote_device_->beacon_seeds = beacon_seeds; return *this; } @@ -77,10 +76,10 @@ } RemoteDevice CreateRemoteDeviceForTest() { - std::map<cryptauth::SoftwareFeature, SoftwareFeatureState> software_features; - software_features[cryptauth::SoftwareFeature::EASY_UNLOCK_HOST] = + std::map<SoftwareFeature, SoftwareFeatureState> software_features; + software_features[SoftwareFeature::kSmartLockHost] = SoftwareFeatureState::kEnabled; - software_features[cryptauth::SoftwareFeature::MAGIC_TETHER_HOST] = + software_features[SoftwareFeature::kInstantTetheringHost] = SoftwareFeatureState::kSupported; return RemoteDevice(kTestRemoteDeviceUserId, kTestRemoteDeviceName,
diff --git a/chromeos/components/multidevice/remote_device_test_util.h b/chromeos/components/multidevice/remote_device_test_util.h index 596bc48..a294ae49 100644 --- a/chromeos/components/multidevice/remote_device_test_util.h +++ b/chromeos/components/multidevice/remote_device_test_util.h
@@ -29,12 +29,12 @@ RemoteDeviceRefBuilder& SetSupportsMobileHotspot( bool supports_mobile_hotspot); RemoteDeviceRefBuilder& SetSoftwareFeatureState( - const cryptauth::SoftwareFeature feature, + const SoftwareFeature feature, const SoftwareFeatureState new_state); RemoteDeviceRefBuilder& SetLastUpdateTimeMillis( int64_t last_update_time_millis); RemoteDeviceRefBuilder& SetBeaconSeeds( - const std::vector<cryptauth::BeaconSeed>& beacon_seeds); + const std::vector<BeaconSeed>& beacon_seeds); RemoteDeviceRef Build(); private:
diff --git a/chromeos/components/multidevice/software_feature.cc b/chromeos/components/multidevice/software_feature.cc new file mode 100644 index 0000000..65edcd9 --- /dev/null +++ b/chromeos/components/multidevice/software_feature.cc
@@ -0,0 +1,98 @@ +// 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 "chromeos/components/multidevice/software_feature.h" + +#include "base/logging.h" + +namespace chromeos { + +namespace multidevice { + +SoftwareFeature FromCryptAuthFeature( + cryptauth::SoftwareFeature cryptauth_feature) { + switch (cryptauth_feature) { + case cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST: + return SoftwareFeature::kBetterTogetherHost; + case cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT: + return SoftwareFeature::kBetterTogetherClient; + case cryptauth::SoftwareFeature::EASY_UNLOCK_HOST: + return SoftwareFeature::kSmartLockHost; + case cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT: + return SoftwareFeature::kSmartLockClient; + case cryptauth::SoftwareFeature::MAGIC_TETHER_HOST: + return SoftwareFeature::kInstantTetheringHost; + case cryptauth::SoftwareFeature::MAGIC_TETHER_CLIENT: + return SoftwareFeature::kInstantTetheringClient; + case cryptauth::SoftwareFeature::SMS_CONNECT_HOST: + return SoftwareFeature::kMessagesForWebHost; + case cryptauth::SoftwareFeature::SMS_CONNECT_CLIENT: + return SoftwareFeature::kMessagesForWebClient; + case cryptauth::SoftwareFeature::UNKNOWN_FEATURE: + NOTREACHED(); + } + + NOTREACHED(); + return SoftwareFeature::kBetterTogetherHost; +} + +cryptauth::SoftwareFeature ToCryptAuthFeature( + SoftwareFeature multidevice_feature) { + // Note: No default case needed since SoftwareFeature is an enum class. + switch (multidevice_feature) { + case SoftwareFeature::kBetterTogetherHost: + return cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST; + case SoftwareFeature::kBetterTogetherClient: + return cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT; + case SoftwareFeature::kSmartLockHost: + return cryptauth::SoftwareFeature::EASY_UNLOCK_HOST; + case SoftwareFeature::kSmartLockClient: + return cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT; + case SoftwareFeature::kInstantTetheringHost: + return cryptauth::SoftwareFeature::MAGIC_TETHER_HOST; + case SoftwareFeature::kInstantTetheringClient: + return cryptauth::SoftwareFeature::MAGIC_TETHER_CLIENT; + case SoftwareFeature::kMessagesForWebHost: + return cryptauth::SoftwareFeature::SMS_CONNECT_HOST; + case SoftwareFeature::kMessagesForWebClient: + return cryptauth::SoftwareFeature::SMS_CONNECT_CLIENT; + } + + NOTREACHED(); + return cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST; +} + +std::ostream& operator<<(std::ostream& stream, const SoftwareFeature& feature) { + switch (feature) { + case SoftwareFeature::kBetterTogetherHost: + stream << "[Better Together host]"; + break; + case SoftwareFeature::kBetterTogetherClient: + stream << "[Better Together client]"; + break; + case SoftwareFeature::kSmartLockHost: + stream << "[Smart Lock host]"; + break; + case SoftwareFeature::kSmartLockClient: + stream << "[Smart Lock client]"; + break; + case SoftwareFeature::kInstantTetheringHost: + stream << "[Instant Tethering host]"; + break; + case SoftwareFeature::kInstantTetheringClient: + stream << "[Instant Tethering client]"; + break; + case SoftwareFeature::kMessagesForWebHost: + stream << "[Messages for Web host]"; + break; + case SoftwareFeature::kMessagesForWebClient: + stream << "[Messages for Web client]"; + break; + } + return stream; +} + +} // namespace multidevice + +} // namespace chromeos
diff --git a/chromeos/components/multidevice/software_feature.h b/chromeos/components/multidevice/software_feature.h new file mode 100644 index 0000000..469435f --- /dev/null +++ b/chromeos/components/multidevice/software_feature.h
@@ -0,0 +1,59 @@ +// 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 CHROMEOS_COMPONENTS_MULTIDEVICE_SOFTWARE_FEATURE_H_ +#define CHROMEOS_COMPONENTS_MULTIDEVICE_SOFTWARE_FEATURE_H_ + +#include <ostream> + +#include "components/cryptauth/proto/cryptauth_api.pb.h" + +namespace chromeos { + +namespace multidevice { + +// Multi-device features. In this context, "host" refers to the device +// (typically an Android phone) which provides functionality, and "client" +// refers to the device (typically a Chromebook) which receives functionality. +// +// Note that numerical enum values must not be changed as these values are +// serialized to numbers and stored persistently. +// +// This enum should always be preferred over the cryptauth::SoftwareFeature +// proto except when communicating with the CryptAuth server. +enum class SoftwareFeature { + // Note: Enum value 0 is intentionally skipped here for legacy reasons. + + // Support for multi-device features in general. + kBetterTogetherHost = 1, + kBetterTogetherClient = 2, + + // Smart Lock, which gives the user the ability to unlock and/or sign into a + // Chromebook using an Android phone. + kSmartLockHost = 3, + kSmartLockClient = 4, + + // Instant Tethering, which gives the user the ability to use an Android + // phone's Internet connection on a Chromebook. + kInstantTetheringHost = 5, + kInstantTetheringClient = 6, + + // Messages for Web, which gives the user the ability to sync messages (e.g., + // SMS) between an Android phone and a Chromebook. + kMessagesForWebHost = 7, + kMessagesForWebClient = 8 +}; + +SoftwareFeature FromCryptAuthFeature( + cryptauth::SoftwareFeature cryptauth_feature); +cryptauth::SoftwareFeature ToCryptAuthFeature( + SoftwareFeature multidevice_feature); + +std::ostream& operator<<(std::ostream& stream, const SoftwareFeature& feature); + +} // namespace multidevice + +} // namespace chromeos + +#endif // CHROMEOS_COMPONENTS_MULTIDEVICE_SOFTWARE_FEATURE_H_
diff --git a/chromeos/components/multidevice/software_feature_state.h b/chromeos/components/multidevice/software_feature_state.h index c0bd5966..c4127379 100644 --- a/chromeos/components/multidevice/software_feature_state.h +++ b/chromeos/components/multidevice/software_feature_state.h
@@ -11,9 +11,18 @@ namespace multidevice { +// State of a multi-device feature (see SoftwareFeature). +// +// Note that numerical enum values must not be changed as these values are +// serialized to numbers and stored persistently. enum class SoftwareFeatureState { + // Not supported by the device (e.g., hardware does not support feature). kNotSupported = 0, + + // Supported by device, but device has not enabled the feature. kSupported = 1, + + // Supported by device, and device has enabled the feature. kEnabled = 2 };
diff --git a/chromeos/components/proximity_auth/unlock_manager_impl.cc b/chromeos/components/proximity_auth/unlock_manager_impl.cc index 133a691..37c1a659 100644 --- a/chromeos/components/proximity_auth/unlock_manager_impl.cc +++ b/chromeos/components/proximity_auth/unlock_manager_impl.cc
@@ -135,6 +135,9 @@ if (GetMessenger()) GetMessenger()->RemoveObserver(this); + if (proximity_monitor_) + proximity_monitor_->RemoveObserver(this); + ScreenlockBridge::Get()->RemoveObserver(this); DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this); @@ -164,6 +167,8 @@ AttemptToStartRemoteDeviceLifecycle(); SetWakingUpState(true /* is_waking_up */); } else { + if (proximity_monitor_) + proximity_monitor_->RemoveObserver(this); proximity_monitor_.reset(); } @@ -177,7 +182,10 @@ if (state == RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED) { DCHECK(life_cycle_->GetChannel()); DCHECK(GetMessenger()); - proximity_monitor_ = CreateProximityMonitor(life_cycle_, pref_manager_); + if (!proximity_monitor_) { + proximity_monitor_ = CreateProximityMonitor(life_cycle_, pref_manager_); + proximity_monitor_->AddObserver(this); + } GetMessenger()->AddObserver(this); } @@ -465,7 +473,7 @@ // If the RSSI is too low, then the remote device is nowhere near the local // device. This message should take priority over messages about screen lock // states. - if (!proximity_monitor_->IsUnlockAllowed()) { + if (proximity_monitor_ && !proximity_monitor_->IsUnlockAllowed()) { if (remote_screenlock_state_ && *remote_screenlock_state_ == RemoteScreenlockState::UNLOCKED) { return ScreenlockState::RSSI_TOO_LOW; @@ -516,7 +524,6 @@ if (is_locked_ && life_cycle_ && life_cycle_->GetState() == RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED) { - proximity_monitor_->AddObserver(this); proximity_monitor_->Start(); } else { proximity_monitor_->Stop(); @@ -579,7 +586,7 @@ reject_auth_attempt_weak_ptr_factory_.InvalidateWeakPtrs(); bool should_accept = !error; - if (should_accept) + if (should_accept && proximity_monitor_) proximity_monitor_->RecordProximityMetricsOnAuthSuccess(); is_attempting_auth_ = false;
diff --git a/chromeos/components/proximity_auth/webui/proximity_auth_webui_handler.cc b/chromeos/components/proximity_auth/webui/proximity_auth_webui_handler.cc index 5b6cc15..772e10c 100644 --- a/chromeos/components/proximity_auth/webui/proximity_auth_webui_handler.cc +++ b/chromeos/components/proximity_auth/webui/proximity_auth_webui_handler.cc
@@ -32,15 +32,15 @@ namespace { -constexpr const cryptauth::SoftwareFeature kAllSoftareFeatures[] = { - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, - cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST, - cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, - cryptauth::SoftwareFeature::MAGIC_TETHER_HOST, - cryptauth::SoftwareFeature::MAGIC_TETHER_CLIENT, - cryptauth::SoftwareFeature::SMS_CONNECT_HOST, - cryptauth::SoftwareFeature::SMS_CONNECT_CLIENT}; +constexpr const chromeos::multidevice::SoftwareFeature kAllSoftareFeatures[] = { + chromeos::multidevice::SoftwareFeature::kBetterTogetherHost, + chromeos::multidevice::SoftwareFeature::kBetterTogetherClient, + chromeos::multidevice::SoftwareFeature::kSmartLockHost, + chromeos::multidevice::SoftwareFeature::kSmartLockClient, + chromeos::multidevice::SoftwareFeature::kInstantTetheringHost, + chromeos::multidevice::SoftwareFeature::kInstantTetheringClient, + chromeos::multidevice::SoftwareFeature::kMessagesForWebHost, + chromeos::multidevice::SoftwareFeature::kMessagesForWebClient}; // Keys in the JSON representation of a log message. const char kLogMessageTextKey[] = "text"; @@ -261,7 +261,7 @@ } device_sync_client_->SetSoftwareFeatureState( - public_key, cryptauth::SoftwareFeature::EASY_UNLOCK_HOST, + public_key, chromeos::multidevice::SoftwareFeature::kSmartLockHost, true /* enabled */, true /* is_exclusive */, base::BindOnce(&ProximityAuthWebUIHandler::OnSetSoftwareFeatureState, weak_ptr_factory_.GetWeakPtr(), public_key)); @@ -270,7 +270,7 @@ void ProximityAuthWebUIHandler::FindEligibleUnlockDevices( const base::ListValue* args) { device_sync_client_->FindEligibleDevices( - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST, + chromeos::multidevice::SoftwareFeature::kSmartLockHost, base::BindOnce(&ProximityAuthWebUIHandler::OnFindEligibleDevices, weak_ptr_factory_.GetWeakPtr())); } @@ -378,12 +378,12 @@ dictionary->SetBoolean( kExternalDeviceUnlockKey, remote_device.GetSoftwareFeatureState( - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST) == + chromeos::multidevice::SoftwareFeature::kSmartLockHost) == chromeos::multidevice::SoftwareFeatureState::kEnabled); dictionary->SetBoolean( kExternalDeviceMobileHotspot, remote_device.GetSoftwareFeatureState( - cryptauth::SoftwareFeature::MAGIC_TETHER_HOST) == + chromeos::multidevice::SoftwareFeature::kInstantTetheringHost) == chromeos::multidevice::SoftwareFeatureState::kSupported); dictionary->SetString(kExternalDeviceConnectionStatus, kExternalDeviceDisconnected);
diff --git a/chromeos/components/proximity_auth/webui/resources/proximity_auth.html b/chromeos/components/proximity_auth/webui/resources/proximity_auth.html index 000cd878..5eafab0 100644 --- a/chromeos/components/proximity_auth/webui/resources/proximity_auth.html +++ b/chromeos/components/proximity_auth/webui/resources/proximity_auth.html
@@ -13,6 +13,8 @@ <script src="proximity_auth.js"></script> <script src="chrome://resources/js/mojo_bindings.js"></script> <script src="chrome://resources/js/time.mojom.js"></script> + <script src="chrome://resources/js/chromeos/multidevice_types.mojom.js"> + </script> <script src="chrome://resources/js/chromeos/device_sync.mojom.js"></script> <script src="chrome://resources/js/chromeos/multidevice_setup.mojom.js"> </script>
diff --git a/chromeos/components/run_all_unittests.cc b/chromeos/components/run_all_unittests.cc index f3fa16ea..305f137 100644 --- a/chromeos/components/run_all_unittests.cc +++ b/chromeos/components/run_all_unittests.cc
@@ -5,8 +5,14 @@ #include "base/bind.h" #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" +#include "chromeos/chromeos_buildflags.h" #include "mojo/core/embedder/embedder.h" +#if BUILDFLAG(IS_CROS_CHROME_SDK) +#error This test target only builds with linux-chromeos, not cros chrome-sdk.\ + See comment in build/config/chromeos/rules.gni. +#endif + int main(int argc, char** argv) { // Some unit tests make Mojo calls. mojo::core::Init();
diff --git a/chromeos/components/tether/connect_tethering_operation.cc b/chromeos/components/tether/connect_tethering_operation.cc index a3c6d448..a72684f71d 100644 --- a/chromeos/components/tether/connect_tethering_operation.cc +++ b/chromeos/components/tether/connect_tethering_operation.cc
@@ -246,7 +246,7 @@ break; } - return HostResponseErrorCode::NO_RESPONSE; + return HostResponseErrorCode::UNRECOGNIZED_RESPONSE_ERROR; } void ConnectTetheringOperation::SetClockForTest(base::Clock* clock_for_test) {
diff --git a/chromeos/components/tether/connect_tethering_operation.h b/chromeos/components/tether/connect_tethering_operation.h index 5b71a7a..043defb 100644 --- a/chromeos/components/tether/connect_tethering_operation.h +++ b/chromeos/components/tether/connect_tethering_operation.h
@@ -39,7 +39,9 @@ class ConnectTetheringOperation : public MessageTransferOperation { public: // Includes all error codes of ConnectTetheringResponse_ResponseCode, but - // includes extra values, |NO_RESPONSE| and |INVALID_HOTSPOT_CREDENTIALS|. + // includes extra values: |COULD_NOT_CONNECT_TO_PHONE|, + // |INVALID_HOTSPOT_CREDENTIALS|, |SUCCESSFUL_REQUEST_BUT_NO_RESPONSE|, and + // |UNRECOGNIZED_RESPONSE_ERROR|. enum HostResponseErrorCode { PROVISIONING_FAILED = 0, TETHERING_TIMEOUT = 1, @@ -49,7 +51,8 @@ ENABLING_HOTSPOT_TIMEOUT = 5, UNKNOWN_ERROR = 6, NO_RESPONSE = 7, - INVALID_HOTSPOT_CREDENTIALS = 8 + INVALID_HOTSPOT_CREDENTIALS = 8, + UNRECOGNIZED_RESPONSE_ERROR = 9 }; class Factory {
diff --git a/chromeos/components/tether/host_connection_metrics_logger.cc b/chromeos/components/tether/host_connection_metrics_logger.cc index b847db3b..e7fe1d98 100644 --- a/chromeos/components/tether/host_connection_metrics_logger.cc +++ b/chromeos/components/tether/host_connection_metrics_logger.cc
@@ -99,6 +99,16 @@ RecordConnectionResultFailure( ConnectionToHostResult_FailureEventType::INVALID_HOTSPOT_CREDENTIALS); break; + case ConnectionToHostResult:: + CONNECTION_RESULT_FAILURE_SUCCESSFUL_REQUEST_BUT_NO_RESPONSE: + RecordConnectionResultFailure(ConnectionToHostResult_FailureEventType:: + SUCCESSFUL_REQUEST_BUT_NO_RESPONSE); + break; + case ConnectionToHostResult:: + CONNECTION_RESULT_FAILURE_UNRECOGNIZED_RESPONSE_ERROR: + RecordConnectionResultFailure( + ConnectionToHostResult_FailureEventType::UNRECOGNIZED_RESPONSE_ERROR); + break; default: NOTREACHED(); };
diff --git a/chromeos/components/tether/host_connection_metrics_logger.h b/chromeos/components/tether/host_connection_metrics_logger.h index 44af3e58..fc9a612 100644 --- a/chromeos/components/tether/host_connection_metrics_logger.h +++ b/chromeos/components/tether/host_connection_metrics_logger.h
@@ -39,7 +39,9 @@ CONNECTION_RESULT_FAILURE_ENABLING_HOTSPOT_FAILED, CONNECTION_RESULT_FAILURE_ENABLING_HOTSPOT_TIMEOUT, CONNECTION_RESULT_FAILURE_NO_RESPONSE, - CONNECTION_RESULT_FAILURE_INVALID_HOTSPOT_CREDENTIALS + CONNECTION_RESULT_FAILURE_INVALID_HOTSPOT_CREDENTIALS, + CONNECTION_RESULT_FAILURE_SUCCESSFUL_REQUEST_BUT_NO_RESPONSE, + CONNECTION_RESULT_FAILURE_UNRECOGNIZED_RESPONSE_ERROR, }; // Record the result of an attempted host connection. @@ -147,6 +149,8 @@ ENABLING_HOTSPOT_TIMEOUT = 6, NO_RESPONSE = 7, INVALID_HOTSPOT_CREDENTIALS = 8, + SUCCESSFUL_REQUEST_BUT_NO_RESPONSE = 9, + UNRECOGNIZED_RESPONSE_ERROR = 10, FAILURE_MAX };
diff --git a/chromeos/components/tether/tether_connector_impl.cc b/chromeos/components/tether/tether_connector_impl.cc index ff200f8..dbc27968 100644 --- a/chromeos/components/tether/tether_connector_impl.cc +++ b/chromeos/components/tether/tether_connector_impl.cc
@@ -150,6 +150,8 @@ void TetherConnectorImpl::OnConnectTetheringRequestSent( multidevice::RemoteDeviceRef remote_device) { + did_send_successful_request_ = true; + // If setup is required for the phone, display a notification so that the // user knows to follow instructions on the phone. Note that the notification // is displayed only after a request has been sent successfully. If the @@ -432,8 +434,19 @@ CONNECTION_RESULT_FAILURE_INVALID_HOTSPOT_CREDENTIALS; } + if (error_code == + ConnectTetheringOperation::HostResponseErrorCode::NO_RESPONSE) { + if (did_send_successful_request_) { + return HostConnectionMetricsLogger::ConnectionToHostResult:: + CONNECTION_RESULT_FAILURE_SUCCESSFUL_REQUEST_BUT_NO_RESPONSE; + } else { + return HostConnectionMetricsLogger::ConnectionToHostResult:: + CONNECTION_RESULT_FAILURE_NO_RESPONSE; + } + } + return HostConnectionMetricsLogger::ConnectionToHostResult:: - CONNECTION_RESULT_FAILURE_NO_RESPONSE; + CONNECTION_RESULT_FAILURE_UNRECOGNIZED_RESPONSE_ERROR; } } // namespace tether
diff --git a/chromeos/components/tether/tether_connector_impl.h b/chromeos/components/tether/tether_connector_impl.h index 2bb7449..81246209 100644 --- a/chromeos/components/tether/tether_connector_impl.h +++ b/chromeos/components/tether/tether_connector_impl.h
@@ -114,6 +114,7 @@ DisconnectTetheringRequestSender* disconnect_tethering_request_sender_; WifiHotspotDisconnector* wifi_hotspot_disconnector_; + bool did_send_successful_request_ = false; std::string device_id_pending_connection_; base::Closure success_callback_; network_handler::StringResultCallback error_callback_;
diff --git a/chromeos/components/tether/tether_host_fetcher_impl.cc b/chromeos/components/tether/tether_host_fetcher_impl.cc index ae3454e..85eabc8 100644 --- a/chromeos/components/tether/tether_host_fetcher_impl.cc +++ b/chromeos/components/tether/tether_host_fetcher_impl.cc
@@ -129,7 +129,7 @@ device_sync_client_->GetSyncedDevices()) { multidevice::SoftwareFeatureState magic_tether_host_state = remote_device_ref.GetSoftwareFeatureState( - cryptauth::SoftwareFeature::MAGIC_TETHER_HOST); + chromeos::multidevice::SoftwareFeature::kInstantTetheringHost); if (magic_tether_host_state == multidevice::SoftwareFeatureState::kSupported || magic_tether_host_state == @@ -153,7 +153,7 @@ device_sync_client_->GetSyncedDevices()) { multidevice::SoftwareFeatureState better_together_host_state = remote_device_ref.GetSoftwareFeatureState( - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + chromeos::multidevice::SoftwareFeature::kBetterTogetherHost); // If there's any valid Better Together host, don't support legacy mode. if (better_together_host_state == multidevice::SoftwareFeatureState::kSupported || @@ -164,7 +164,7 @@ multidevice::SoftwareFeatureState magic_tether_host_state = remote_device_ref.GetSoftwareFeatureState( - cryptauth::SoftwareFeature::MAGIC_TETHER_HOST); + chromeos::multidevice::SoftwareFeature::kInstantTetheringHost); if (magic_tether_host_state == multidevice::SoftwareFeatureState::kSupported || magic_tether_host_state ==
diff --git a/chromeos/components/tether/tether_host_fetcher_impl_unittest.cc b/chromeos/components/tether/tether_host_fetcher_impl_unittest.cc index cbbbfcc..3f24266 100644 --- a/chromeos/components/tether/tether_host_fetcher_impl_unittest.cc +++ b/chromeos/components/tether/tether_host_fetcher_impl_unittest.cc
@@ -13,6 +13,8 @@ #include "chromeos/components/multidevice/remote_device.h" #include "chromeos/components/multidevice/remote_device_ref.h" #include "chromeos/components/multidevice/remote_device_test_util.h" +#include "chromeos/components/multidevice/software_feature.h" +#include "chromeos/components/multidevice/software_feature_state.h" #include "chromeos/services/device_sync/public/cpp/fake_device_sync_client.h" #include "chromeos/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h" #include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h" @@ -110,15 +112,17 @@ multidevice::RemoteDeviceList list = multidevice::CreateRemoteDeviceListForTest(kNumTestDevices); for (auto& device : list) { - device.software_features[cryptauth::SoftwareFeature::MAGIC_TETHER_HOST] = + device.software_features + [chromeos::multidevice::SoftwareFeature::kInstantTetheringHost] = multidevice::SoftwareFeatureState::kSupported; } // Mark the first device enabled instead of supported. - list[0].software_features[cryptauth::SoftwareFeature::MAGIC_TETHER_HOST] = + list[0].software_features + [chromeos::multidevice::SoftwareFeature::kInstantTetheringHost] = multidevice::SoftwareFeatureState::kEnabled; - list[0] - .software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = + list[0].software_features + [chromeos::multidevice::SoftwareFeature::kBetterTogetherHost] = multidevice::SoftwareFeatureState::kEnabled; return list; @@ -195,8 +199,8 @@ void TestSingleTetherHost(bool use_legacy_mode = false) { InitializeTest(); if (use_legacy_mode) { - test_remote_device_list_[0] - .software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = + test_remote_device_list_[0].software_features + [chromeos::multidevice::SoftwareFeature::kBetterTogetherHost] = multidevice::SoftwareFeatureState::kNotSupported; test_remote_device_ref_list_ = CreateTestRemoteDeviceRefList(test_remote_device_list_); @@ -218,8 +222,8 @@ // Now, set another device as the only device, but remove its mobile data // support. It should not be returned. multidevice::RemoteDevice remote_device = multidevice::RemoteDevice(); - remote_device - .software_features[cryptauth::SoftwareFeature::MAGIC_TETHER_HOST] = + remote_device.software_features + [chromeos::multidevice::SoftwareFeature::kInstantTetheringHost] = multidevice::SoftwareFeatureState::kNotSupported; SetSyncedDevices(multidevice::RemoteDeviceList{remote_device}); @@ -239,15 +243,15 @@ // Create a list of test devices, only some of which are valid tether hosts. // Ensure that only that subset is fetched. - test_remote_device_list_[3] - .software_features[cryptauth::SoftwareFeature::MAGIC_TETHER_HOST] = + test_remote_device_list_[3].software_features + [chromeos::multidevice::SoftwareFeature::kInstantTetheringHost] = multidevice::SoftwareFeatureState::kNotSupported; - test_remote_device_list_[4] - .software_features[cryptauth::SoftwareFeature::MAGIC_TETHER_HOST] = + test_remote_device_list_[4].software_features + [chromeos::multidevice::SoftwareFeature::kInstantTetheringHost] = multidevice::SoftwareFeatureState::kNotSupported; if (use_legacy_mode) { - test_remote_device_list_[0] - .software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = + test_remote_device_list_[0].software_features + [chromeos::multidevice::SoftwareFeature::kBetterTogetherHost] = multidevice::SoftwareFeatureState::kNotSupported; }
diff --git a/chromeos/resources/BUILD.gn b/chromeos/resources/BUILD.gn index 3ae0262..11e05772 100644 --- a/chromeos/resources/BUILD.gn +++ b/chromeos/resources/BUILD.gn
@@ -2,8 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//tools/grit/grit_rule.gni") import("//chromeos/assistant/assistant.gni") +import("//tools/grit/grit_rule.gni") assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos") @@ -28,6 +28,7 @@ ] deps = [ + "//chromeos/components/multidevice/mojom:mojom_js", "//chromeos/services/device_sync/public/mojom:mojom_js", "//chromeos/services/multidevice_setup/public/mojom:mojom_js", ]
diff --git a/chromeos/resources/multidevice_resources.grdp b/chromeos/resources/multidevice_resources.grdp index ba37df6..b09d5c6 100644 --- a/chromeos/resources/multidevice_resources.grdp +++ b/chromeos/resources/multidevice_resources.grdp
@@ -1,5 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <grit-part> + <include name="IDR_MULTIDEVICE_MULTIDEVICE_TYPES_MOJOM_JS" + file="${mojom_root}/chromeos/components/multidevice/mojom/multidevice_types.mojom.js" + use_base_dir="false" + type="BINDATA" + compress="gzip" /> <include name="IDR_MULTIDEVICE_DEVICE_SYNC_MOJOM_JS" file="${mojom_root}/chromeos/services/device_sync/public/mojom/device_sync.mojom.js" use_base_dir="false"
diff --git a/chromeos/run_all_unittests.cc b/chromeos/run_all_unittests.cc index 7fa086e..ca2ef13 100644 --- a/chromeos/run_all_unittests.cc +++ b/chromeos/run_all_unittests.cc
@@ -5,8 +5,14 @@ #include "base/bind.h" #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" +#include "chromeos/chromeos_buildflags.h" #include "mojo/core/embedder/embedder.h" +#if BUILDFLAG(IS_CROS_CHROME_SDK) +#error This test target only builds with linux-chromeos, not cros chrome-sdk.\ + See comment in build/config/chromeos/rules.gni. +#endif + int main(int argc, char** argv) { // Some unit tests make Mojo calls. mojo::core::Init();
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc index bea52e2..cedb49b 100644 --- a/chromeos/services/assistant/assistant_manager_service_impl.cc +++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -21,6 +21,7 @@ #include "build/util/webkit_version.h" #include "chromeos/assistant/internal/internal_constants.h" #include "chromeos/assistant/internal/internal_util.h" +#include "chromeos/assistant/internal/proto/google3/assistant/api/client_input/warmer_welcome_input.pb.h" #include "chromeos/assistant/internal/proto/google3/assistant/api/client_op/device_args.pb.h" #include "chromeos/dbus/util/version_loader.h" #include "chromeos/services/assistant/public/features.h" @@ -128,7 +129,10 @@ device::mojom::BatteryMonitorPtr battery_monitor, Service* service, network::NetworkConnectionTracker* network_connection_tracker) - : action_module_(std::make_unique<action::CrosActionModule>(this)), + : action_module_(std::make_unique<action::CrosActionModule>( + this, + base::FeatureList::IsEnabled( + assistant::features::kAssistantAppSupport))), main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()), chromium_api_delegate_(service->io_task_runner()), assistant_settings_manager_( @@ -342,6 +346,25 @@ cancel_conversation); } +void AssistantManagerServiceImpl::StartWarmerWelcomeInteraction( + int num_warmer_welcome_triggered, + bool allow_tts) { + DCHECK(assistant_manager_internal_ != nullptr); + + const std::string interaction = + CreateWarmerWelcomeInteraction(num_warmer_welcome_triggered); + + assistant_client::VoicelessOptions options; + options.is_user_initiated = true; + options.modality = + allow_tts ? assistant_client::VoicelessOptions::Modality::VOICE_MODALITY + : assistant_client::VoicelessOptions::Modality::TYPING_MODALITY; + + assistant_manager_internal_->SendVoicelessInteraction( + interaction, /*description=*/"warmer_welcome_trigger", options, + [](auto) {}); +} + void AssistantManagerServiceImpl::StartCachedScreenContextInteraction() { if (!IsScreenContextAllowed(service_->assistant_state())) return; @@ -870,7 +893,9 @@ std::move(post_init_callback).Run(); UpdateDeviceSettings(); - SyncSpeakerIdEnrollmentStatus(); + + if (base::FeatureList::IsEnabled(assistant::features::kAssistantVoiceMatch)) + SyncSpeakerIdEnrollmentStatus(); } void AssistantManagerServiceImpl::SyncSpeakerIdEnrollmentStatus() {
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.h b/chromeos/services/assistant/assistant_manager_service_impl.h index e42cb73f..0344972 100644 --- a/chromeos/services/assistant/assistant_manager_service_impl.h +++ b/chromeos/services/assistant/assistant_manager_service_impl.h
@@ -118,6 +118,8 @@ void StartMetalayerInteraction(const gfx::Rect& region) override; void StartTextInteraction(const std::string& query, bool allow_tts) override; void StartVoiceInteraction() override; + void StartWarmerWelcomeInteraction(int num_warmer_welcome_triggered, + bool allow_tts) override; void StopActiveInteraction(bool cancel_conversation) override; void AddAssistantInteractionSubscriber( mojom::AssistantInteractionSubscriberPtr subscriber) override;
diff --git a/chromeos/services/assistant/fake_assistant_manager_service_impl.cc b/chromeos/services/assistant/fake_assistant_manager_service_impl.cc index 323b7b9..54677c78 100644 --- a/chromeos/services/assistant/fake_assistant_manager_service_impl.cc +++ b/chromeos/services/assistant/fake_assistant_manager_service_impl.cc
@@ -67,6 +67,10 @@ void FakeAssistantManagerServiceImpl::StartVoiceInteraction() {} +void FakeAssistantManagerServiceImpl::StartWarmerWelcomeInteraction( + int num_warmer_welcome_triggered, + bool allow_tts) {} + void FakeAssistantManagerServiceImpl::StopActiveInteraction( bool cancel_conversation) {}
diff --git a/chromeos/services/assistant/fake_assistant_manager_service_impl.h b/chromeos/services/assistant/fake_assistant_manager_service_impl.h index b27b8ed..6e4a105 100644 --- a/chromeos/services/assistant/fake_assistant_manager_service_impl.h +++ b/chromeos/services/assistant/fake_assistant_manager_service_impl.h
@@ -50,6 +50,8 @@ void StartMetalayerInteraction(const gfx::Rect& region) override; void StartTextInteraction(const std::string& query, bool allow_tts) override; void StartVoiceInteraction() override; + void StartWarmerWelcomeInteraction(int num_warmer_welcome_triggered, + bool allow_tts) override; void StopActiveInteraction(bool cancel_conversation) override; void AddAssistantInteractionSubscriber( mojom::AssistantInteractionSubscriberPtr subscriber) override;
diff --git a/chromeos/services/assistant/public/features.cc b/chromeos/services/assistant/public/features.cc index 8e0d4504..bfde058 100644 --- a/chromeos/services/assistant/public/features.cc +++ b/chromeos/services/assistant/public/features.cc
@@ -13,6 +13,12 @@ const base::Feature kAssistantVoiceMatch{"AssistantVoiceMatch", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kAssistantWarmerWelcomeFeature{ + "AssistantWarmerWelcome", base::FEATURE_DISABLED_BY_DEFAULT}; + +const base::Feature kAssistantAppSupport{"AssistantAppSupport", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kEnableDspHotword{"EnableDspHotword", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -27,6 +33,10 @@ return base::FeatureList::IsEnabled(kEnableStereoAudioInput); } +bool IsWarmerWelcomeEnabled() { + return base::FeatureList::IsEnabled(kAssistantWarmerWelcomeFeature); +} + } // namespace features } // namespace assistant } // namespace chromeos
diff --git a/chromeos/services/assistant/public/features.h b/chromeos/services/assistant/public/features.h index 9b3ee079..6a40b1626 100644 --- a/chromeos/services/assistant/public/features.h +++ b/chromeos/services/assistant/public/features.h
@@ -14,6 +14,12 @@ // Enables Assistant voice match enrollment. extern const base::Feature kAssistantVoiceMatch; +// Enable Assistant warmer welcome. +extern const base::Feature kAssistantWarmerWelcomeFeature; + +// Enables Assistant app support. +extern const base::Feature kAssistantAppSupport; + // Enables DSP for hotword detection. extern const base::Feature kEnableDspHotword; @@ -24,6 +30,8 @@ bool IsStereoAudioInputEnabled(); +bool IsWarmerWelcomeEnabled(); + } // namespace features } // namespace assistant } // namespace chromeos
diff --git a/chromeos/services/assistant/public/mojom/assistant.mojom b/chromeos/services/assistant/public/mojom/assistant.mojom index a7df141..a283635b 100644 --- a/chromeos/services/assistant/public/mojom/assistant.mojom +++ b/chromeos/services/assistant/public/mojom/assistant.mojom
@@ -32,6 +32,13 @@ // Starts a new Assistant voice interaction. StartVoiceInteraction(); + // Starts a warmer welcome interaction for Assistant launch. + // |num_warmer_welcome_triggered| is the count of warmer welcomes + // already triggered. If |allow_tts| is true, the result may contain TTS. + // Otherwise TTS will not be present in the generated server response. + StartWarmerWelcomeInteraction(int32 num_warmer_welcome_triggered, + bool allow_tts); + // Stops the active Assistant interaction and cancel the conversation if // |cancel_conversation|. If there is no active interaction, this method // is a no-op.
diff --git a/chromeos/services/assistant/test_support/mock_assistant.h b/chromeos/services/assistant/test_support/mock_assistant.h index f27b4aee..85f1c62 100644 --- a/chromeos/services/assistant/test_support/mock_assistant.h +++ b/chromeos/services/assistant/test_support/mock_assistant.h
@@ -29,6 +29,8 @@ MOCK_METHOD0(StartVoiceInteraction, void()); + MOCK_METHOD2(StartWarmerWelcomeInteraction, void(int, bool)); + MOCK_METHOD1(StopActiveInteraction, void(bool)); MOCK_METHOD1(
diff --git a/chromeos/services/device_sync/BUILD.gn b/chromeos/services/device_sync/BUILD.gn index 873238b..db14f694 100644 --- a/chromeos/services/device_sync/BUILD.gn +++ b/chromeos/services/device_sync/BUILD.gn
@@ -86,7 +86,6 @@ "//chromeos/components/multidevice:test_support", "//chromeos/services/device_sync/public/cpp:unit_tests", "//chromeos/services/device_sync/public/mojom", - "//chromeos/services/device_sync/public/mojom:unit_tests", "//components/cryptauth", "//components/cryptauth:test_support", "//components/gcm_driver:test_support",
diff --git a/chromeos/services/device_sync/device_sync_impl.cc b/chromeos/services/device_sync/device_sync_impl.cc index b727b006..07d098f 100644 --- a/chromeos/services/device_sync/device_sync_impl.cc +++ b/chromeos/services/device_sync/device_sync_impl.cc
@@ -127,17 +127,15 @@ } DeviceSyncSetSoftwareFeature GetDeviceSyncSoftwareFeature( - cryptauth::SoftwareFeature software_feature) { + multidevice::SoftwareFeature software_feature) { switch (software_feature) { - case cryptauth::SoftwareFeature::UNKNOWN_FEATURE: - return DeviceSyncSetSoftwareFeature::kUnknown; - case cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST: + case multidevice::SoftwareFeature::kBetterTogetherHost: return DeviceSyncSetSoftwareFeature::kBetterTogetherSuite; - case cryptauth::SoftwareFeature::EASY_UNLOCK_HOST: + case multidevice::SoftwareFeature::kSmartLockHost: return DeviceSyncSetSoftwareFeature::kSmartLock; - case cryptauth::SoftwareFeature::MAGIC_TETHER_HOST: + case multidevice::SoftwareFeature::kInstantTetheringHost: return DeviceSyncSetSoftwareFeature::kInstantTethering; - case cryptauth::SoftwareFeature::SMS_CONNECT_HOST: + case multidevice::SoftwareFeature::kMessagesForWebHost: return DeviceSyncSetSoftwareFeature::kMessages; default: NOTREACHED(); @@ -146,7 +144,7 @@ } void RecordSetSoftwareFailedFeature(bool enabled, - cryptauth::SoftwareFeature feature) { + multidevice::SoftwareFeature feature) { if (enabled) { UMA_HISTOGRAM_ENUMERATION( "MultiDevice.DeviceSyncService.SetSoftwareFeatureState.Enable." @@ -238,7 +236,7 @@ DeviceSyncImpl::PendingSetSoftwareFeatureRequest:: PendingSetSoftwareFeatureRequest( const std::string& device_public_key, - cryptauth::SoftwareFeature software_feature, + multidevice::SoftwareFeature software_feature, bool enabled, cryptauth::RemoteDeviceProvider* remote_device_provider, SetSoftwareFeatureStateCallback callback) @@ -379,7 +377,7 @@ void DeviceSyncImpl::SetSoftwareFeatureState( const std::string& device_public_key, - cryptauth::SoftwareFeature software_feature, + multidevice::SoftwareFeature software_feature, bool enabled, bool is_exclusive, SetSoftwareFeatureStateCallback callback) { @@ -413,7 +411,7 @@ } void DeviceSyncImpl::FindEligibleDevices( - cryptauth::SoftwareFeature software_feature, + multidevice::SoftwareFeature software_feature, FindEligibleDevicesCallback callback) { if (status_ != Status::READY) { PA_LOG(WARNING) << "DeviceSyncImpl::FindEligibleDevices() invoked before "
diff --git a/chromeos/services/device_sync/device_sync_impl.h b/chromeos/services/device_sync/device_sync_impl.h index 8dd6f8e..1b1fa4d 100644 --- a/chromeos/services/device_sync/device_sync_impl.h +++ b/chromeos/services/device_sync/device_sync_impl.h
@@ -96,11 +96,11 @@ void GetSyncedDevices(GetSyncedDevicesCallback callback) override; void SetSoftwareFeatureState( const std::string& device_public_key, - cryptauth::SoftwareFeature software_feature, + multidevice::SoftwareFeature software_feature, bool enabled, bool is_exclusive, SetSoftwareFeatureStateCallback callback) override; - void FindEligibleDevices(cryptauth::SoftwareFeature software_feature, + void FindEligibleDevices(multidevice::SoftwareFeature software_feature, FindEligibleDevicesCallback callback) override; void GetDebugInfo(GetDebugInfoCallback callback) override; @@ -138,7 +138,7 @@ public: PendingSetSoftwareFeatureRequest( const std::string& device_public_key, - cryptauth::SoftwareFeature software_feature, + multidevice::SoftwareFeature software_feature, bool enabled, cryptauth::RemoteDeviceProvider* remote_device_provider, SetSoftwareFeatureStateCallback callback); @@ -150,7 +150,7 @@ void InvokeCallback(mojom::NetworkRequestResult result); - cryptauth::SoftwareFeature software_feature() const { + multidevice::SoftwareFeature software_feature() const { return software_feature_; } @@ -158,7 +158,7 @@ private: std::string device_public_key_; - cryptauth::SoftwareFeature software_feature_; + multidevice::SoftwareFeature software_feature_; bool enabled_; cryptauth::RemoteDeviceProvider* remote_device_provider_; SetSoftwareFeatureStateCallback callback_;
diff --git a/chromeos/services/device_sync/device_sync_service_unittest.cc b/chromeos/services/device_sync/device_sync_service_unittest.cc index 2c35e96..c2d1c1f 100644 --- a/chromeos/services/device_sync/device_sync_service_unittest.cc +++ b/chromeos/services/device_sync/device_sync_service_unittest.cc
@@ -690,7 +690,7 @@ // kErrorNotInitialized error code. CallSetSoftwareFeatureState( test_devices()[0].public_key, - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, true /* enabled */, + multidevice::SoftwareFeature::kBetterTogetherHost, true /* enabled */, true /* is_exclusive */); auto last_set_response = GetLastSetSoftwareFeatureStateResponseAndReset(); EXPECT_EQ(mojom::NetworkRequestResult::kServiceNotYetInitialized, @@ -698,7 +698,7 @@ // Likewise, FindEligibleDevices() should also return a struct with the same // error code. - CallFindEligibleDevices(cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + CallFindEligibleDevices(multidevice::SoftwareFeature::kBetterTogetherHost); auto last_find_response = GetLastFindEligibleDevicesResponseAndReset(); EXPECT_EQ(mojom::NetworkRequestResult::kServiceNotYetInitialized, last_find_response->first); @@ -768,10 +768,11 @@ return last_synced_devices_result_; } - void CallSetSoftwareFeatureState(const std::string& public_key, - cryptauth::SoftwareFeature software_feature, - bool enabled, - bool is_exclusive) { + void CallSetSoftwareFeatureState( + const std::string& public_key, + multidevice::SoftwareFeature software_feature, + bool enabled, + bool is_exclusive) { base::RunLoop run_loop; cryptauth::FakeSoftwareFeatureManager* manager = fake_software_feature_manager(); @@ -802,7 +803,7 @@ fake_software_feature_manager_factory_->instance()->set_delegate(nullptr); } - void CallFindEligibleDevices(cryptauth::SoftwareFeature software_feature) { + void CallFindEligibleDevices(multidevice::SoftwareFeature software_feature) { base::RunLoop run_loop; cryptauth::FakeSoftwareFeatureManager* manager = fake_software_feature_manager(); @@ -1123,20 +1124,20 @@ fake_software_feature_manager()->set_software_feature_state_calls(); EXPECT_EQ(0u, set_software_calls.size()); - // Set the BETTER_TOGETHER_HOST field to "supported". + // Set the kBetterTogetherHost field to "supported". multidevice::RemoteDevice device_for_test = test_devices()[0]; device_for_test - .software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = + .software_features[multidevice::SoftwareFeature::kBetterTogetherHost] = multidevice::SoftwareFeatureState::kSupported; EXPECT_TRUE(CallForceSyncNow()); SimulateSync(true /* success */, {device_for_test}); - // Enable BETTER_TOGETHER_HOST for the device. + // Enable kBetterTogetherHost for the device. CallSetSoftwareFeatureState(device_for_test.public_key, - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, + multidevice::SoftwareFeature::kBetterTogetherHost, true /* enabled */, true /* is_exclusive */); EXPECT_EQ(1u, set_software_calls.size()); - EXPECT_EQ(cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, + EXPECT_EQ(multidevice::SoftwareFeature::kBetterTogetherHost, set_software_calls[0]->software_feature); EXPECT_TRUE(set_software_calls[0]->enabled); EXPECT_TRUE(set_software_calls[0]->is_exclusive); @@ -1153,7 +1154,7 @@ // Simulate a sync which includes the device with the correct "enabled" state. device_for_test - .software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = + .software_features[multidevice::SoftwareFeature::kBetterTogetherHost] = multidevice::SoftwareFeatureState::kEnabled; base::RunLoop().RunUntilIdle(); SimulateSync(true /* success */, {device_for_test}); @@ -1181,20 +1182,20 @@ fake_software_feature_manager()->set_software_feature_state_calls(); EXPECT_EQ(0u, set_software_calls.size()); - // Set the BETTER_TOGETHER_HOST field to "supported". + // Set the kBetterTogetherHost field to "supported". multidevice::RemoteDevice device_for_test = test_devices()[0]; device_for_test - .software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = + .software_features[multidevice::SoftwareFeature::kBetterTogetherHost] = multidevice::SoftwareFeatureState::kSupported; EXPECT_TRUE(CallForceSyncNow()); SimulateSync(true /* success */, {device_for_test}); - // Enable BETTER_TOGETHER_HOST for the device. + // Enable kBetterTogetherHost for the device. CallSetSoftwareFeatureState(device_for_test.public_key, - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, + multidevice::SoftwareFeature::kBetterTogetherHost, true /* enabled */, true /* is_exclusive */); EXPECT_EQ(1u, set_software_calls.size()); - EXPECT_EQ(cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, + EXPECT_EQ(multidevice::SoftwareFeature::kBetterTogetherHost, set_software_calls[0]->software_feature); EXPECT_TRUE(set_software_calls[0]->enabled); EXPECT_TRUE(set_software_calls[0]->is_exclusive); @@ -1230,20 +1231,20 @@ fake_software_feature_manager()->set_software_feature_state_calls(); EXPECT_EQ(0u, set_software_calls.size()); - // Set the BETTER_TOGETHER_HOST field to "supported". + // Set the kBetterTogetherHost field to "supported". multidevice::RemoteDevice device_for_test = test_devices()[0]; device_for_test - .software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = + .software_features[multidevice::SoftwareFeature::kBetterTogetherHost] = multidevice::SoftwareFeatureState::kSupported; EXPECT_TRUE(CallForceSyncNow()); SimulateSync(true /* success */, {device_for_test}); - // Enable BETTER_TOGETHER_HOST for the device. + // Enable kBetterTogetherHost for the device. CallSetSoftwareFeatureState(device_for_test.public_key, - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, + multidevice::SoftwareFeature::kBetterTogetherHost, true /* enabled */, true /* is_exclusive */); ASSERT_EQ(1u, set_software_calls.size()); - EXPECT_EQ(cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, + EXPECT_EQ(multidevice::SoftwareFeature::kBetterTogetherHost, set_software_calls[0]->software_feature); EXPECT_TRUE(set_software_calls[0]->enabled); EXPECT_TRUE(set_software_calls[0]->is_exclusive); @@ -1276,10 +1277,10 @@ fake_software_feature_manager()->find_eligible_multidevice_host_calls(); EXPECT_EQ(0u, find_eligible_calls.size()); - // Find devices which are BETTER_TOGETHER_HOSTs. - CallFindEligibleDevices(cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + // Find devices which are kBetterTogetherHost. + CallFindEligibleDevices(multidevice::SoftwareFeature::kBetterTogetherHost); EXPECT_EQ(1u, find_eligible_calls.size()); - EXPECT_EQ(cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, + EXPECT_EQ(multidevice::SoftwareFeature::kBetterTogetherHost, find_eligible_calls[0]->software_feature); // The callback has not yet been invoked. @@ -1311,9 +1312,9 @@ "MultiDevice.DeviceSyncService.FindEligibleDevices.Result", true, 1); // Find devices which are BETTER_TOGETHER_HOSTs again. - CallFindEligibleDevices(cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + CallFindEligibleDevices(multidevice::SoftwareFeature::kBetterTogetherHost); EXPECT_EQ(2u, find_eligible_calls.size()); - EXPECT_EQ(cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, + EXPECT_EQ(multidevice::SoftwareFeature::kBetterTogetherHost, find_eligible_calls[1]->software_feature); // The callback has not yet been invoked.
diff --git a/chromeos/services/device_sync/fake_device_sync.cc b/chromeos/services/device_sync/fake_device_sync.cc index 428608d..ba87c117 100644 --- a/chromeos/services/device_sync/fake_device_sync.cc +++ b/chromeos/services/device_sync/fake_device_sync.cc
@@ -73,7 +73,7 @@ void FakeDeviceSync::SetSoftwareFeatureState( const std::string& device_public_key, - cryptauth::SoftwareFeature software_feature, + multidevice::SoftwareFeature software_feature, bool enabled, bool is_exclusive, SetSoftwareFeatureStateCallback callback) { @@ -81,7 +81,7 @@ } void FakeDeviceSync::FindEligibleDevices( - cryptauth::SoftwareFeature software_feature, + multidevice::SoftwareFeature software_feature, FindEligibleDevicesCallback callback) { find_eligible_devices_callback_queue_.push(std::move(callback)); }
diff --git a/chromeos/services/device_sync/fake_device_sync.h b/chromeos/services/device_sync/fake_device_sync.h index 2dc3030..d990ed6e 100644 --- a/chromeos/services/device_sync/fake_device_sync.h +++ b/chromeos/services/device_sync/fake_device_sync.h
@@ -54,11 +54,11 @@ void GetSyncedDevices(GetSyncedDevicesCallback callback) override; void SetSoftwareFeatureState( const std::string& device_public_key, - cryptauth::SoftwareFeature software_feature, + multidevice::SoftwareFeature software_feature, bool enabled, bool is_exclusive, SetSoftwareFeatureStateCallback callback) override; - void FindEligibleDevices(cryptauth::SoftwareFeature software_feature, + void FindEligibleDevices(multidevice::SoftwareFeature software_feature, FindEligibleDevicesCallback callback) override; void GetDebugInfo(GetDebugInfoCallback callback) override;
diff --git a/chromeos/services/device_sync/public/cpp/device_sync_client.h b/chromeos/services/device_sync/public/cpp/device_sync_client.h index 02b5ffaa..9f0294d 100644 --- a/chromeos/services/device_sync/public/cpp/device_sync_client.h +++ b/chromeos/services/device_sync/public/cpp/device_sync_client.h
@@ -13,6 +13,7 @@ #include "base/observer_list.h" #include "base/optional.h" #include "chromeos/components/multidevice/remote_device_ref.h" +#include "chromeos/components/multidevice/software_feature.h" #include "chromeos/services/device_sync/public/mojom/device_sync.mojom.h" namespace chromeos { @@ -67,12 +68,13 @@ // ignored. virtual void SetSoftwareFeatureState( const std::string public_key, - cryptauth::SoftwareFeature software_feature, + multidevice::SoftwareFeature software_feature, bool enabled, bool is_exclusive, mojom::DeviceSync::SetSoftwareFeatureStateCallback callback) = 0; - virtual void FindEligibleDevices(cryptauth::SoftwareFeature software_feature, - FindEligibleDevicesCallback callback) = 0; + virtual void FindEligibleDevices( + multidevice::SoftwareFeature software_feature, + FindEligibleDevicesCallback callback) = 0; virtual void GetDebugInfo( mojom::DeviceSync::GetDebugInfoCallback callback) = 0;
diff --git a/chromeos/services/device_sync/public/cpp/device_sync_client_impl.cc b/chromeos/services/device_sync/public/cpp/device_sync_client_impl.cc index b90940bb..2504e46 100644 --- a/chromeos/services/device_sync/public/cpp/device_sync_client_impl.cc +++ b/chromeos/services/device_sync/public/cpp/device_sync_client_impl.cc
@@ -111,7 +111,7 @@ void DeviceSyncClientImpl::SetSoftwareFeatureState( const std::string public_key, - cryptauth::SoftwareFeature software_feature, + multidevice::SoftwareFeature software_feature, bool enabled, bool is_exclusive, mojom::DeviceSync::SetSoftwareFeatureStateCallback callback) { @@ -120,7 +120,7 @@ } void DeviceSyncClientImpl::FindEligibleDevices( - cryptauth::SoftwareFeature software_feature, + multidevice::SoftwareFeature software_feature, FindEligibleDevicesCallback callback) { device_sync_ptr_->FindEligibleDevices( software_feature,
diff --git a/chromeos/services/device_sync/public/cpp/device_sync_client_impl.h b/chromeos/services/device_sync/public/cpp/device_sync_client_impl.h index 341957aa..70415595 100644 --- a/chromeos/services/device_sync/public/cpp/device_sync_client_impl.h +++ b/chromeos/services/device_sync/public/cpp/device_sync_client_impl.h
@@ -15,6 +15,7 @@ #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "chromeos/components/multidevice/remote_device_ref.h" +#include "chromeos/components/multidevice/software_feature.h" #include "chromeos/services/device_sync/public/cpp/device_sync_client.h" #include "chromeos/services/device_sync/public/mojom/device_sync.mojom.h" #include "mojo/public/cpp/bindings/binding.h" @@ -63,11 +64,11 @@ override; void SetSoftwareFeatureState( const std::string public_key, - cryptauth::SoftwareFeature software_feature, + multidevice::SoftwareFeature software_feature, bool enabled, bool is_exclusive, mojom::DeviceSync::SetSoftwareFeatureStateCallback callback) override; - void FindEligibleDevices(cryptauth::SoftwareFeature software_feature, + void FindEligibleDevices(multidevice::SoftwareFeature software_feature, FindEligibleDevicesCallback callback) override; void GetDebugInfo(mojom::DeviceSync::GetDebugInfoCallback callback) override;
diff --git a/chromeos/services/device_sync/public/cpp/device_sync_client_impl_unittest.cc b/chromeos/services/device_sync/public/cpp/device_sync_client_impl_unittest.cc index edcb30d3..63d0326 100644 --- a/chromeos/services/device_sync/public/cpp/device_sync_client_impl_unittest.cc +++ b/chromeos/services/device_sync/public/cpp/device_sync_client_impl_unittest.cc
@@ -327,7 +327,7 @@ client_->SetSoftwareFeatureState( test_remote_device_ref_list_[0].public_key(), - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, true /* enabled */, + multidevice::SoftwareFeature::kBetterTogetherHost, true /* enabled */, true /* enabled */, base::BindOnce( &DeviceSyncClientImplTest::OnSetSoftwareFeatureStateCompleted, @@ -349,7 +349,7 @@ base::RunLoop run_loop; client_->FindEligibleDevices( - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, + multidevice::SoftwareFeature::kBetterTogetherHost, base::BindOnce( &DeviceSyncClientImplTest::OnFindEligibleDevicesCompleted, base::Unretained(this), run_loop.QuitClosure()));
diff --git a/chromeos/services/device_sync/public/cpp/fake_device_sync_client.cc b/chromeos/services/device_sync/public/cpp/fake_device_sync_client.cc index 5f8ee81..f756216 100644 --- a/chromeos/services/device_sync/public/cpp/fake_device_sync_client.cc +++ b/chromeos/services/device_sync/public/cpp/fake_device_sync_client.cc
@@ -36,7 +36,7 @@ void FakeDeviceSyncClient::SetSoftwareFeatureState( const std::string public_key, - cryptauth::SoftwareFeature software_feature, + multidevice::SoftwareFeature software_feature, bool enabled, bool is_exclusive, mojom::DeviceSync::SetSoftwareFeatureStateCallback callback) { @@ -44,7 +44,7 @@ } void FakeDeviceSyncClient::FindEligibleDevices( - cryptauth::SoftwareFeature software_feature, + multidevice::SoftwareFeature software_feature, FindEligibleDevicesCallback callback) { find_eligible_devices_callback_queue_.push(std::move(callback)); }
diff --git a/chromeos/services/device_sync/public/cpp/fake_device_sync_client.h b/chromeos/services/device_sync/public/cpp/fake_device_sync_client.h index 1a83e1f..7ed7cd5 100644 --- a/chromeos/services/device_sync/public/cpp/fake_device_sync_client.h +++ b/chromeos/services/device_sync/public/cpp/fake_device_sync_client.h
@@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/optional.h" #include "chromeos/components/multidevice/remote_device_ref.h" +#include "chromeos/components/multidevice/software_feature.h" #include "chromeos/services/device_sync/public/cpp/device_sync_client.h" #include "chromeos/services/device_sync/public/mojom/device_sync.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h" @@ -66,11 +67,11 @@ override; void SetSoftwareFeatureState( const std::string public_key, - cryptauth::SoftwareFeature software_feature, + multidevice::SoftwareFeature software_feature, bool enabled, bool is_exclusive, mojom::DeviceSync::SetSoftwareFeatureStateCallback callback) override; - void FindEligibleDevices(cryptauth::SoftwareFeature software_feature, + void FindEligibleDevices(multidevice::SoftwareFeature software_feature, FindEligibleDevicesCallback callback) override; void GetDebugInfo(mojom::DeviceSync::GetDebugInfoCallback callback) override;
diff --git a/chromeos/services/device_sync/public/mojom/BUILD.gn b/chromeos/services/device_sync/public/mojom/BUILD.gn index f239ae3..9a23615 100644 --- a/chromeos/services/device_sync/public/mojom/BUILD.gn +++ b/chromeos/services/device_sync/public/mojom/BUILD.gn
@@ -11,23 +11,7 @@ ] public_deps = [ + "//chromeos/components/multidevice/mojom", "//mojo/public/mojom/base", ] } - -source_set("unit_tests") { - testonly = true - - sources = [ - "device_sync_mojom_traits_unittest.cc", - ] - - deps = [ - ":mojom", - "//base", - "//base/test:test_support", - "//components/cryptauth", - "//mojo/public/cpp/test_support:test_utils", - "//testing/gtest", - ] -}
diff --git a/chromeos/services/device_sync/public/mojom/OWNERS b/chromeos/services/device_sync/public/mojom/OWNERS index ae29a36aa..08850f4 100644 --- a/chromeos/services/device_sync/public/mojom/OWNERS +++ b/chromeos/services/device_sync/public/mojom/OWNERS
@@ -1,6 +1,2 @@ per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS -per-file *_mojom_traits*.*=set noparent -per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS -per-file *.typemap=set noparent -per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/chromeos/services/device_sync/public/mojom/device_sync.mojom b/chromeos/services/device_sync/public/mojom/device_sync.mojom index f2d68a1f..390aeca9 100644 --- a/chromeos/services/device_sync/public/mojom/device_sync.mojom +++ b/chromeos/services/device_sync/public/mojom/device_sync.mojom
@@ -4,46 +4,9 @@ module chromeos.device_sync.mojom; +import "chromeos/components/multidevice/mojom/multidevice_types.mojom"; import "mojo/public/mojom/base/time.mojom"; -// Enumeration of software features which can be enabled/disabled for a given -// device. Each feature has a host and client portion; here, "host" refers to -// the associated phone which provides the feature (at most one host per -// account), and "client" refers to the Chromebook which consumes the feature -// (multiple clients allowed per account). -enum SoftwareFeature { - UNKNOWN_FEATURE, - - // The Better Together (MultiDevice) setup flow feature allows users to go - // through a unified setup flow which enrolls the device for all multi-device - // features. - BETTER_TOGETHER_HOST, - BETTER_TOGETHER_CLIENT, - - // EasyUnlock gives users the ability to unlock their Chromebooks with their - // phone instead of by typing a password. - EASY_UNLOCK_HOST, - EASY_UNLOCK_CLIENT, - - // Magic Tether (Instant Tethering) gives users the ability to use their - // phone's Internet connectivity on their Chromebooks via an automated flow - // which does not require any phone-side interaction. - MAGIC_TETHER_HOST, - MAGIC_TETHER_CLIENT, - - // SMS Connect gives users the ability to read and reply to their text - // messages from their Chromebooks. - SMS_CONNECT_HOST, - SMS_CONNECT_CLIENT -}; - -// Enumeration of what value a SoftwareFeature can be. -enum SoftwareFeatureState { - kNotSupported, - kSupported, - kEnabled -}; - enum NetworkRequestResult { // Successful network request. kSuccess, @@ -79,52 +42,9 @@ kUnknown }; -// Used to generate rotating BLE advertisement data, which is necessary to -// establish a BLE communication channel between two devices. To -// create the BLE channel, both devices must possess the other's BeaconSeeds. -struct BeaconSeed { - string data; - mojo_base.mojom.Time start_time; - mojo_base.mojom.Time end_time; -}; - -// Metadata describing a remote device with which the current device can -// communicate. -struct RemoteDevice { - // Unique identifier of the device. Unlike |public_key|, this field is - // guaranteed to be human-readable (i.e., it does not contain non-ASCII - // characters). - string device_id; - - // Identifier for the user to whom this device is registered. - string user_id; - - // Human-readable device name; by default, this is the name of the device - // model, but this value is editable. - string device_name; - - // Encryption key used for communication with this device. - string persistent_symmetric_key; - - // The time at which this device's metadata was last updated on the CryptAuth - // back-end. - mojo_base.mojom.Time last_update_time; - - // The features which this device either does not support, supports, or has - // enabled. - map<SoftwareFeature, SoftwareFeatureState> software_features; - - // Seeds belonging to the device. Each seed has start and end timestamps which - // indicate how long the seed is valid, and each device has enough associated - // seeds to keep the device connectable for over 30 days. If no new device - // metadata synced for over 30 days, it is possible that a connection will not - // be able to be established over BLE. - array<BeaconSeed> beacon_seeds; -}; - struct FindEligibleDevicesResponse { - array<RemoteDevice> eligible_devices; - array<RemoteDevice> ineligible_devices; + array<chromeos.multidevice.mojom.RemoteDevice> eligible_devices; + array<chromeos.multidevice.mojom.RemoteDevice> ineligible_devices; }; struct DebugInfo { @@ -179,11 +99,13 @@ // Returns all synced devices associated with the primary account. If this // device has not yet registered with the back-end, no list is provided. - GetSyncedDevices() => (array<RemoteDevice>? devices); + GetSyncedDevices() => + (array<chromeos.multidevice.mojom.RemoteDevice>? devices); // Returns the RemoteDevice object associated with this device. If this device // has not yet registered with the back-end, no device is provided. - GetLocalDeviceMetadata() => (RemoteDevice? local_device); + GetLocalDeviceMetadata() => + (chromeos.multidevice.mojom.RemoteDevice? local_device); // Enables or disables the given software feature for the device with the // given public key. If |enabled| and |is_exclusive| are both true, this @@ -201,7 +123,7 @@ // all of the user's devices. SetSoftwareFeatureState( string device_public_key, - SoftwareFeature software_feature, + chromeos.multidevice.mojom.SoftwareFeature software_feature, bool enabled, bool is_exclusive) => (NetworkRequestResult result_code); @@ -213,8 +135,10 @@ // On success, this function returns a null error_code with a valid response // to the callback; on error, it returns a valid error_code string indicating // the reason for failure along with a null response. - FindEligibleDevices(SoftwareFeature software_feature) => - (NetworkRequestResult result_code, FindEligibleDevicesResponse? response); + FindEligibleDevices( + chromeos.multidevice.mojom.SoftwareFeature software_feature) => + (NetworkRequestResult result_code, + FindEligibleDevicesResponse? response); // Functions below are implemented for chrome://proximity-auth page, which is // intended for debugging purposes only.
diff --git a/chromeos/services/device_sync/public/mojom/device_sync.typemap b/chromeos/services/device_sync/public/mojom/device_sync.typemap deleted file mode 100644 index 202c937..0000000 --- a/chromeos/services/device_sync/public/mojom/device_sync.typemap +++ /dev/null
@@ -1,31 +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. - -mojom = "//chromeos/services/device_sync/public/mojom/device_sync.mojom" - -public_headers = [ - "//chromeos/components/multidevice/remote_device.h", - "//components/cryptauth/proto/cryptauth_api.pb.h", -] - -traits_headers = [ - "//chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.h", -] - -sources = [ - "//chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.cc", - "//chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.h", -] - -public_deps = [ - "//chromeos/components/multidevice", - "//components/cryptauth", - "//components/cryptauth/proto", -] - -type_mappings = [ - "chromeos.device_sync.mojom.BeaconSeed=cryptauth::BeaconSeed", - "chromeos.device_sync.mojom.RemoteDevice=chromeos::multidevice::RemoteDevice", - "chromeos.device_sync.mojom.SoftwareFeature=cryptauth::SoftwareFeature", -]
diff --git a/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.cc b/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.cc deleted file mode 100644 index d2d3bc1..0000000 --- a/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.cc +++ /dev/null
@@ -1,230 +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 "chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.h" - -#include "base/logging.h" -#include "chromeos/components/multidevice/remote_device_ref.h" -#include "mojo/public/cpp/base/time_mojom_traits.h" - -namespace mojo { - -const std::string& StructTraits< - chromeos::device_sync::mojom::BeaconSeedDataView, - cryptauth::BeaconSeed>::data(const cryptauth::BeaconSeed& beacon_seed) { - return beacon_seed.data(); -} - -base::Time -StructTraits<chromeos::device_sync::mojom::BeaconSeedDataView, - cryptauth::BeaconSeed>::start_time(const cryptauth::BeaconSeed& - beacon_seed) { - return base::Time::FromJavaTime(beacon_seed.start_time_millis()); -} - -base::Time StructTraits< - chromeos::device_sync::mojom::BeaconSeedDataView, - cryptauth::BeaconSeed>::end_time(const cryptauth::BeaconSeed& beacon_seed) { - return base::Time::FromJavaTime(beacon_seed.end_time_millis()); -} - -bool StructTraits<chromeos::device_sync::mojom::BeaconSeedDataView, - cryptauth::BeaconSeed>:: - Read(chromeos::device_sync::mojom::BeaconSeedDataView in, - cryptauth::BeaconSeed* out) { - std::string beacon_seed_data; - base::Time start_time; - base::Time end_time; - - if (!in.ReadData(&beacon_seed_data) || !in.ReadStartTime(&start_time) || - !in.ReadEndTime(&end_time)) { - return false; - } - - out->set_data(beacon_seed_data); - out->set_start_time_millis(start_time.ToJavaTime()); - out->set_end_time_millis(end_time.ToJavaTime()); - - return true; -} - -std::string StructTraits<chromeos::device_sync::mojom::RemoteDeviceDataView, - chromeos::multidevice::RemoteDevice>:: - device_id(const chromeos::multidevice::RemoteDevice& remote_device) { - return remote_device.GetDeviceId(); -} - -const std::string& -StructTraits<chromeos::device_sync::mojom::RemoteDeviceDataView, - chromeos::multidevice::RemoteDevice>:: - user_id(const chromeos::multidevice::RemoteDevice& remote_device) { - return remote_device.user_id; -} - -const std::string& -StructTraits<chromeos::device_sync::mojom::RemoteDeviceDataView, - chromeos::multidevice::RemoteDevice>:: - device_name(const chromeos::multidevice::RemoteDevice& remote_device) { - return remote_device.name; -} - -const std::string& -StructTraits<chromeos::device_sync::mojom::RemoteDeviceDataView, - chromeos::multidevice::RemoteDevice>:: - persistent_symmetric_key( - const chromeos::multidevice::RemoteDevice& remote_device) { - return remote_device.persistent_symmetric_key; -} - -base::Time StructTraits<chromeos::device_sync::mojom::RemoteDeviceDataView, - chromeos::multidevice::RemoteDevice>:: - last_update_time(const chromeos::multidevice::RemoteDevice& remote_device) { - return base::Time::FromJavaTime(remote_device.last_update_time_millis); -} - -const std::map<cryptauth::SoftwareFeature, - chromeos::multidevice::SoftwareFeatureState>& -StructTraits<chromeos::device_sync::mojom::RemoteDeviceDataView, - chromeos::multidevice::RemoteDevice>:: - software_features( - const chromeos::multidevice::RemoteDevice& remote_device) { - return remote_device.software_features; -} - -const std::vector<cryptauth::BeaconSeed>& -StructTraits<chromeos::device_sync::mojom::RemoteDeviceDataView, - chromeos::multidevice::RemoteDevice>:: - beacon_seeds(const chromeos::multidevice::RemoteDevice& remote_device) { - return remote_device.beacon_seeds; -} - -bool StructTraits<chromeos::device_sync::mojom::RemoteDeviceDataView, - chromeos::multidevice::RemoteDevice>:: - Read(chromeos::device_sync::mojom::RemoteDeviceDataView in, - chromeos::multidevice::RemoteDevice* out) { - std::string device_id; - base::Time last_update_time; - - if (!in.ReadUserId(&out->user_id) || !in.ReadDeviceName(&out->name) || - !in.ReadDeviceId(&device_id) || - !in.ReadPersistentSymmetricKey(&out->persistent_symmetric_key) || - !in.ReadLastUpdateTime(&last_update_time) || - !in.ReadSoftwareFeatures(&out->software_features) || - !in.ReadBeaconSeeds(&out->beacon_seeds)) { - return false; - } - - out->public_key = - chromeos::multidevice::RemoteDeviceRef::DerivePublicKey(device_id); - out->last_update_time_millis = last_update_time.ToJavaTime(); - - return true; -} - -chromeos::device_sync::mojom::SoftwareFeature EnumTraits< - chromeos::device_sync::mojom::SoftwareFeature, - cryptauth::SoftwareFeature>::ToMojom(cryptauth::SoftwareFeature input) { - switch (input) { - case cryptauth::SoftwareFeature::UNKNOWN_FEATURE: - return chromeos::device_sync::mojom::SoftwareFeature::UNKNOWN_FEATURE; - case cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST: - return chromeos::device_sync::mojom::SoftwareFeature:: - BETTER_TOGETHER_HOST; - case cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT: - return chromeos::device_sync::mojom::SoftwareFeature:: - BETTER_TOGETHER_CLIENT; - case cryptauth::SoftwareFeature::EASY_UNLOCK_HOST: - return chromeos::device_sync::mojom::SoftwareFeature::EASY_UNLOCK_HOST; - case cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT: - return chromeos::device_sync::mojom::SoftwareFeature::EASY_UNLOCK_CLIENT; - case cryptauth::SoftwareFeature::MAGIC_TETHER_HOST: - return chromeos::device_sync::mojom::SoftwareFeature::MAGIC_TETHER_HOST; - case cryptauth::SoftwareFeature::MAGIC_TETHER_CLIENT: - return chromeos::device_sync::mojom::SoftwareFeature::MAGIC_TETHER_CLIENT; - case cryptauth::SoftwareFeature::SMS_CONNECT_HOST: - return chromeos::device_sync::mojom::SoftwareFeature::SMS_CONNECT_HOST; - case cryptauth::SoftwareFeature::SMS_CONNECT_CLIENT: - return chromeos::device_sync::mojom::SoftwareFeature::SMS_CONNECT_CLIENT; - } - - NOTREACHED(); - return chromeos::device_sync::mojom::SoftwareFeature::UNKNOWN_FEATURE; -} - -bool EnumTraits<chromeos::device_sync::mojom::SoftwareFeature, - cryptauth::SoftwareFeature>:: - FromMojom(chromeos::device_sync::mojom::SoftwareFeature input, - cryptauth::SoftwareFeature* out) { - switch (input) { - case chromeos::device_sync::mojom::SoftwareFeature::UNKNOWN_FEATURE: - *out = cryptauth::SoftwareFeature::UNKNOWN_FEATURE; - return true; - case chromeos::device_sync::mojom::SoftwareFeature::BETTER_TOGETHER_HOST: - *out = cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST; - return true; - case chromeos::device_sync::mojom::SoftwareFeature::BETTER_TOGETHER_CLIENT: - *out = cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT; - return true; - case chromeos::device_sync::mojom::SoftwareFeature::EASY_UNLOCK_HOST: - *out = cryptauth::SoftwareFeature::EASY_UNLOCK_HOST; - return true; - case chromeos::device_sync::mojom::SoftwareFeature::EASY_UNLOCK_CLIENT: - *out = cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT; - return true; - case chromeos::device_sync::mojom::SoftwareFeature::MAGIC_TETHER_HOST: - *out = cryptauth::SoftwareFeature::MAGIC_TETHER_HOST; - return true; - case chromeos::device_sync::mojom::SoftwareFeature::MAGIC_TETHER_CLIENT: - *out = cryptauth::SoftwareFeature::MAGIC_TETHER_CLIENT; - return true; - case chromeos::device_sync::mojom::SoftwareFeature::SMS_CONNECT_HOST: - *out = cryptauth::SoftwareFeature::SMS_CONNECT_HOST; - return true; - case chromeos::device_sync::mojom::SoftwareFeature::SMS_CONNECT_CLIENT: - *out = cryptauth::SoftwareFeature::SMS_CONNECT_CLIENT; - return true; - } - - NOTREACHED(); - return false; -} - -chromeos::device_sync::mojom::SoftwareFeatureState -EnumTraits<chromeos::device_sync::mojom::SoftwareFeatureState, - chromeos::multidevice::SoftwareFeatureState>:: - ToMojom(chromeos::multidevice::SoftwareFeatureState input) { - switch (input) { - case chromeos::multidevice::SoftwareFeatureState::kNotSupported: - return chromeos::device_sync::mojom::SoftwareFeatureState::kNotSupported; - case chromeos::multidevice::SoftwareFeatureState::kSupported: - return chromeos::device_sync::mojom::SoftwareFeatureState::kSupported; - case chromeos::multidevice::SoftwareFeatureState::kEnabled: - return chromeos::device_sync::mojom::SoftwareFeatureState::kEnabled; - } - - NOTREACHED(); - return chromeos::device_sync::mojom::SoftwareFeatureState::kNotSupported; -} - -bool EnumTraits<chromeos::device_sync::mojom::SoftwareFeatureState, - chromeos::multidevice::SoftwareFeatureState>:: - FromMojom(chromeos::device_sync::mojom::SoftwareFeatureState input, - chromeos::multidevice::SoftwareFeatureState* out) { - switch (input) { - case chromeos::device_sync::mojom::SoftwareFeatureState::kNotSupported: - *out = chromeos::multidevice::SoftwareFeatureState::kNotSupported; - return true; - case chromeos::device_sync::mojom::SoftwareFeatureState::kSupported: - *out = chromeos::multidevice::SoftwareFeatureState::kSupported; - return true; - case chromeos::device_sync::mojom::SoftwareFeatureState::kEnabled: - *out = chromeos::multidevice::SoftwareFeatureState::kEnabled; - return true; - } - - NOTREACHED(); - return false; -} - -} // namespace mojo
diff --git a/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.h b/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.h deleted file mode 100644 index 08f4679e..0000000 --- a/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.h +++ /dev/null
@@ -1,79 +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 CHROMEOS_SERVICES_DEVICE_SYNC_PUBLIC_MOJOM_DEVICE_SYNC_MOJOM_TRAITS_H_ -#define CHROMEOS_SERVICES_DEVICE_SYNC_PUBLIC_MOJOM_DEVICE_SYNC_MOJOM_TRAITS_H_ - -#include <string> -#include <vector> - -#include "base/time/time.h" -#include "chromeos/components/multidevice/remote_device.h" -#include "chromeos/services/device_sync/public/mojom/device_sync.mojom.h" -#include "components/cryptauth/proto/cryptauth_api.pb.h" -#include "mojo/public/cpp/bindings/enum_traits.h" -#include "mojo/public/cpp/bindings/struct_traits.h" - -namespace mojo { - -template <> -class StructTraits<chromeos::device_sync::mojom::BeaconSeedDataView, - cryptauth::BeaconSeed> { - public: - static const std::string& data(const cryptauth::BeaconSeed& beacon_seed); - static base::Time start_time(const cryptauth::BeaconSeed& beacon_seed); - static base::Time end_time(const cryptauth::BeaconSeed& beacon_seed); - - static bool Read(chromeos::device_sync::mojom::BeaconSeedDataView in, - cryptauth::BeaconSeed* out); -}; - -template <> -class StructTraits<chromeos::device_sync::mojom::RemoteDeviceDataView, - chromeos::multidevice::RemoteDevice> { - public: - static std::string device_id( - const chromeos::multidevice::RemoteDevice& remote_device); - static const std::string& user_id( - const chromeos::multidevice::RemoteDevice& remote_device); - static const std::string& device_name( - const chromeos::multidevice::RemoteDevice& remote_device); - static const std::string& persistent_symmetric_key( - const chromeos::multidevice::RemoteDevice& remote_device); - static base::Time last_update_time( - const chromeos::multidevice::RemoteDevice& remote_device); - static const std::map<cryptauth::SoftwareFeature, - chromeos::multidevice::SoftwareFeatureState>& - software_features(const chromeos::multidevice::RemoteDevice& remote_device); - static const std::vector<cryptauth::BeaconSeed>& beacon_seeds( - const chromeos::multidevice::RemoteDevice& remote_device); - - static bool Read(chromeos::device_sync::mojom::RemoteDeviceDataView in, - chromeos::multidevice::RemoteDevice* out); -}; - -template <> -class EnumTraits<chromeos::device_sync::mojom::SoftwareFeature, - cryptauth::SoftwareFeature> { - public: - static chromeos::device_sync::mojom::SoftwareFeature ToMojom( - cryptauth::SoftwareFeature input); - static bool FromMojom(chromeos::device_sync::mojom::SoftwareFeature input, - cryptauth::SoftwareFeature* out); -}; - -template <> -class EnumTraits<chromeos::device_sync::mojom::SoftwareFeatureState, - chromeos::multidevice::SoftwareFeatureState> { - public: - static chromeos::device_sync::mojom::SoftwareFeatureState ToMojom( - chromeos::multidevice::SoftwareFeatureState input); - static bool FromMojom( - chromeos::device_sync::mojom::SoftwareFeatureState input, - chromeos::multidevice::SoftwareFeatureState* out); -}; - -} // namespace mojo - -#endif // CHROMEOS_SERVICES_DEVICE_SYNC_PUBLIC_MOJOM_DEVICE_SYNC_MOJOM_TRAITS_H_
diff --git a/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits_unittest.cc b/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits_unittest.cc deleted file mode 100644 index 8f2e173..0000000 --- a/chromeos/services/device_sync/public/mojom/device_sync_mojom_traits_unittest.cc +++ /dev/null
@@ -1,107 +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 "chromeos/services/device_sync/public/mojom/device_sync_mojom_traits.h" - -#include "base/time/time.h" -#include "chromeos/components/multidevice/remote_device.h" -#include "chromeos/services/device_sync/public/mojom/device_sync.mojom.h" -#include "components/cryptauth/proto/cryptauth_api.pb.h" -#include "mojo/public/cpp/base/time_mojom_traits.h" -#include "mojo/public/cpp/test_support/test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -const char kTestBeaconSeedData[] = "data"; -const int64_t kTestBeaconSeedStartTimeMillis = 1L; -const int64_t kTestBeaconSeedEndTimeMillis = 2L; - -cryptauth::BeaconSeed CreateTestBeaconSeed() { - cryptauth::BeaconSeed beacon_seed; - - beacon_seed.set_data(kTestBeaconSeedData); - beacon_seed.set_start_time_millis(kTestBeaconSeedStartTimeMillis); - beacon_seed.set_end_time_millis(kTestBeaconSeedEndTimeMillis); - - return beacon_seed; -} - -} // namespace - -TEST(DeviceSyncMojomStructTraitsTest, BeaconSeed) { - cryptauth::BeaconSeed input = CreateTestBeaconSeed(); - - cryptauth::BeaconSeed output; - EXPECT_TRUE(mojo::test::SerializeAndDeserialize< - chromeos::device_sync::mojom::BeaconSeed>(&input, &output)); - - EXPECT_EQ(kTestBeaconSeedData, output.data()); - EXPECT_EQ(kTestBeaconSeedStartTimeMillis, output.start_time_millis()); - EXPECT_EQ(kTestBeaconSeedEndTimeMillis, output.end_time_millis()); -} - -TEST(DeviceSyncMojomStructTraitsTest, RemoteDevice) { - std::map<cryptauth::SoftwareFeature, - chromeos::multidevice::SoftwareFeatureState> - software_features = - std::map<cryptauth::SoftwareFeature, - chromeos::multidevice::SoftwareFeatureState>(); - software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT] = - chromeos::multidevice::SoftwareFeatureState::kSupported; - software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = - chromeos::multidevice::SoftwareFeatureState::kEnabled; - - chromeos::multidevice::RemoteDevice input; - input.user_id = "userId"; - input.name = "name"; - input.public_key = "publicKey"; - input.persistent_symmetric_key = "persistentSymmetricKey"; - input.last_update_time_millis = 3L; - input.software_features = software_features; - input.beacon_seeds = {CreateTestBeaconSeed()}; - - chromeos::multidevice::RemoteDevice output; - EXPECT_TRUE(mojo::test::SerializeAndDeserialize< - chromeos::device_sync::mojom::RemoteDevice>(&input, &output)); - - EXPECT_EQ("userId", output.user_id); - EXPECT_EQ("name", output.name); - EXPECT_EQ("publicKey", output.public_key); - EXPECT_EQ("persistentSymmetricKey", output.persistent_symmetric_key); - EXPECT_EQ(3L, output.last_update_time_millis); - EXPECT_EQ(software_features, output.software_features); - ASSERT_EQ(1u, output.beacon_seeds.size()); - EXPECT_EQ(kTestBeaconSeedData, output.beacon_seeds[0].data()); - EXPECT_EQ(kTestBeaconSeedStartTimeMillis, - output.beacon_seeds[0].start_time_millis()); - EXPECT_EQ(kTestBeaconSeedEndTimeMillis, - output.beacon_seeds[0].end_time_millis()); -} - -TEST(DeviceSyncMojomEnumTraitsTest, SoftwareFeature) { - static constexpr cryptauth::SoftwareFeature kTestSoftwareFeatures[] = { - cryptauth::SoftwareFeature::UNKNOWN_FEATURE, - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, - cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST, - cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, - cryptauth::SoftwareFeature::MAGIC_TETHER_HOST, - cryptauth::SoftwareFeature::MAGIC_TETHER_CLIENT, - cryptauth::SoftwareFeature::SMS_CONNECT_HOST, - cryptauth::SoftwareFeature::SMS_CONNECT_CLIENT}; - - for (auto feature_in : kTestSoftwareFeatures) { - cryptauth::SoftwareFeature feature_out; - - chromeos::device_sync::mojom::SoftwareFeature serialized_feature = - mojo::EnumTraits<chromeos::device_sync::mojom::SoftwareFeature, - cryptauth::SoftwareFeature>::ToMojom(feature_in); - ASSERT_TRUE((mojo::EnumTraits< - chromeos::device_sync::mojom::SoftwareFeature, - cryptauth::SoftwareFeature>::FromMojom(serialized_feature, - &feature_out))); - EXPECT_EQ(feature_in, feature_out); - } -}
diff --git a/chromeos/services/device_sync/public/mojom/typemaps.gni b/chromeos/services/device_sync/public/mojom/typemaps.gni deleted file mode 100644 index 0a71cbc..0000000 --- a/chromeos/services/device_sync/public/mojom/typemaps.gni +++ /dev/null
@@ -1,6 +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. - -typemaps = - [ "//chromeos/services/device_sync/public/mojom/device_sync.typemap" ]
diff --git a/chromeos/services/ime/public/cpp/rulebased/def/fa.cc b/chromeos/services/ime/public/cpp/rulebased/def/fa.cc index 464fbbd9..6a20a02 100644 --- a/chromeos/services/ime/public/cpp/rulebased/def/fa.cc +++ b/chromeos/services/ime/public/cpp/rulebased/def/fa.cc
@@ -258,8 +258,7 @@ u8"\u061f", // Slash u8"\u200c", // Space }; -const char** kKeyMap[8] = {kNormal, kShift, kAltGr, - kShift, kCapslock, kShiftCapslock, - kCapslock, kShiftCapslock}; +const char** kKeyMap[8] = {kNormal, kShift, kAltGr, kAltGr, + kCapslock, kShiftCapslock, kAltGr, kShiftCapslock}; } // namespace fa
diff --git a/chromeos/services/ime/public/cpp/rulebased/def/lo.cc b/chromeos/services/ime/public/cpp/rulebased/def/lo.cc index c1f5a47e..e9e6ec54 100644 --- a/chromeos/services/ime/public/cpp/rulebased/def/lo.cc +++ b/chromeos/services/ime/public/cpp/rulebased/def/lo.cc
@@ -309,7 +309,7 @@ u8"\u0020", // Space }; const char** kKeyMap[8] = {kNormal, kShift, kAltGr, - kShift, kCapslock, kShiftCapslock, - kAltgrCapslock, kShiftCapslock}; + kAltGr, kCapslock, kShiftCapslock, + kAltgrCapslock, kAltgrCapslock}; } // namespace lo
diff --git a/chromeos/services/ime/public/cpp/rulebased/def/ta_inscript.cc b/chromeos/services/ime/public/cpp/rulebased/def/ta_inscript.cc index 329406f9..27a13d4 100644 --- a/chromeos/services/ime/public/cpp/rulebased/def/ta_inscript.cc +++ b/chromeos/services/ime/public/cpp/rulebased/def/ta_inscript.cc
@@ -258,8 +258,7 @@ u8"?", // Slash u8"\u0020", // Space }; -const char** kKeyMap[8] = {kNormal, kShift, kAltGr, - kShift, kCapslock, kShiftCapslock, - kCapslock, kShiftCapslock}; +const char** kKeyMap[8] = {kNormal, kShift, kAltGr, kAltGr, + kCapslock, kShiftCapslock, kAltGr, kShiftCapslock}; } // namespace ta_inscript
diff --git a/chromeos/services/ime/public/cpp/rulebased/def/ta_phone.cc b/chromeos/services/ime/public/cpp/rulebased/def/ta_phone.cc index 60eea45..f69910b 100644 --- a/chromeos/services/ime/public/cpp/rulebased/def/ta_phone.cc +++ b/chromeos/services/ime/public/cpp/rulebased/def/ta_phone.cc
@@ -310,9 +310,8 @@ u8"?", // Slash u8"\u0020", // Space }; -const char** kKeyMap[8] = {kNormal, kShift, kAltGr, - kShiftAltGr, kCapslock, kShiftCapslock, - kCapslock, kShiftCapslock}; +const char** kKeyMap[8] = {kNormal, kShift, kAltGr, kShiftAltGr, + kCapslock, kShiftCapslock, kAltGr, kShiftAltGr}; const char* kTransforms[] = {u8"\u0bcd\u0bb1\u0bcd\u0bb1\u0bcd\u001d?i", u8"\u0bcd\u0bb0\u0bbf", u8"\u0bcd\u0bb1\u0bcd\u001d?\\^i",
diff --git a/chromeos/services/ime/public/cpp/rulebased/def/th.cc b/chromeos/services/ime/public/cpp/rulebased/def/th.cc index bfe8f36..92aa21b5 100644 --- a/chromeos/services/ime/public/cpp/rulebased/def/th.cc +++ b/chromeos/services/ime/public/cpp/rulebased/def/th.cc
@@ -309,7 +309,7 @@ u8"\u0020", // Space }; const char** kKeyMap[8] = {kNormal, kShift, kAltGr, - kShift, kCapslock, kShiftCapslock, - kAltgrCapslock, kShiftCapslock}; + kAltGr, kCapslock, kShiftCapslock, + kAltgrCapslock, kAltgrCapslock}; } // namespace th
diff --git a/chromeos/services/multidevice_setup/device_reenroller.cc b/chromeos/services/multidevice_setup/device_reenroller.cc index 7b12b37..b7cf3209 100644 --- a/chromeos/services/multidevice_setup/device_reenroller.cc +++ b/chromeos/services/multidevice_setup/device_reenroller.cc
@@ -149,7 +149,11 @@ i <= cryptauth::SoftwareFeature_MAX; ++i) { cryptauth::SoftwareFeature feature = static_cast<cryptauth::SoftwareFeature>(i); - if (local_device_metadata.GetSoftwareFeatureState(feature) != + if (feature == cryptauth::UNKNOWN_FEATURE) + continue; + + if (local_device_metadata.GetSoftwareFeatureState( + chromeos::multidevice::FromCryptAuthFeature(feature)) != multidevice::SoftwareFeatureState::kNotSupported) { sorted_and_deduped_set.insert(feature); }
diff --git a/chromeos/services/multidevice_setup/device_reenroller_unittest.cc b/chromeos/services/multidevice_setup/device_reenroller_unittest.cc index 98a903a..cc17c9e 100644 --- a/chromeos/services/multidevice_setup/device_reenroller_unittest.cc +++ b/chromeos/services/multidevice_setup/device_reenroller_unittest.cc
@@ -7,6 +7,8 @@ #include "base/macros.h" #include "base/timer/mock_timer.h" #include "chromeos/components/multidevice/remote_device_test_util.h" +#include "chromeos/components/multidevice/software_feature.h" +#include "chromeos/components/multidevice/software_feature_state.h" #include "chromeos/services/device_sync/public/cpp/fake_device_sync_client.h" #include "components/cryptauth/fake_gcm_device_info_provider.h" #include "testing/gtest/include/gtest/gtest.h" @@ -33,7 +35,7 @@ } void SetLocalDeviceMetadataSoftwareFeaturesMap( - const std::map<cryptauth::SoftwareFeature, + const std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>& map) { multidevice::GetMutableRemoteDevice(test_local_device_)->software_features = map; @@ -98,10 +100,10 @@ // Set the current local device metadata to contain a sample of supported // software features. SetLocalDeviceMetadataSoftwareFeaturesMap( - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState>{ - {cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>{ + {multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, + {multidevice::SoftwareFeature::kSmartLockClient, multidevice::SoftwareFeatureState::kSupported}}); // Set the current GcmDeviceInfo supported software features to contain the // same set. @@ -125,10 +127,10 @@ // Set the current local device metadata to contain a sample of supported // software features. SetLocalDeviceMetadataSoftwareFeaturesMap( - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState>{ - {cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>{ + {multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, + {multidevice::SoftwareFeature::kSmartLockClient, multidevice::SoftwareFeatureState::kSupported}}); // Remove one supported software feature in the GcmDeviceInfo. SetFakeGcmDeviceInfoProviderWithSupportedSoftwareFeatures( @@ -146,8 +148,8 @@ fake_device_sync_client()->NotifyEnrollmentFinished(); EXPECT_EQ(1, fake_device_sync_client()->GetForceSyncNowCallbackQueueSize()); SetLocalDeviceMetadataSoftwareFeaturesMap( - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState>{ - {cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>{ + {multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported}}); fake_device_sync_client()->InvokePendingForceSyncNowCallback( true /* success */); @@ -161,10 +163,10 @@ // Set the current local device metadata to contain a sample of supported // software features. SetLocalDeviceMetadataSoftwareFeaturesMap( - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState>{ - {cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>{ + {multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, + {multidevice::SoftwareFeature::kSmartLockClient, multidevice::SoftwareFeatureState::kSupported}}); // Add one more supported software feature in the GcmDeviceInfo. SetFakeGcmDeviceInfoProviderWithSupportedSoftwareFeatures( @@ -184,12 +186,12 @@ fake_device_sync_client()->NotifyEnrollmentFinished(); EXPECT_EQ(1, fake_device_sync_client()->GetForceSyncNowCallbackQueueSize()); SetLocalDeviceMetadataSoftwareFeaturesMap( - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState>{ - {cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>{ + {multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, + {multidevice::SoftwareFeature::kSmartLockClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::MAGIC_TETHER_CLIENT, + {multidevice::SoftwareFeature::kInstantTetheringClient, multidevice::SoftwareFeatureState::kSupported}}); fake_device_sync_client()->InvokePendingForceSyncNowCallback( true /* success */); @@ -203,10 +205,10 @@ // Set the current local device metadata to contain a sample of supported // software features. SetLocalDeviceMetadataSoftwareFeaturesMap( - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState>{ - {cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>{ + {multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, + {multidevice::SoftwareFeature::kSmartLockClient, multidevice::SoftwareFeatureState::kSupported}}); // Add one more supported software feature in the GcmDeviceInfo to trigger a // re-enrollment attempt. @@ -236,10 +238,10 @@ // Set the current local device metadata to contain a sample of supported // software features. SetLocalDeviceMetadataSoftwareFeaturesMap( - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState>{ - {cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>{ + {multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, + {multidevice::SoftwareFeature::kSmartLockClient, multidevice::SoftwareFeatureState::kSupported}}); // Add one more supported software feature in the GcmDeviceInfo to trigger a // re-enrollment attempt. @@ -274,10 +276,10 @@ // Set the current local device metadata to contain a sample of supported // software features. SetLocalDeviceMetadataSoftwareFeaturesMap( - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState>{ - {cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>{ + {multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, + {multidevice::SoftwareFeature::kSmartLockClient, multidevice::SoftwareFeatureState::kSupported}}); // Add one more supported software feature in the GcmDeviceInfo to trigger a // re-enrollment attempt. @@ -298,10 +300,10 @@ EXPECT_EQ(1, fake_device_sync_client()->GetForceSyncNowCallbackQueueSize()); // Assume local device metadata was not updated correctly. SetLocalDeviceMetadataSoftwareFeaturesMap( - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState>{ - {cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>{ + {multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, + {multidevice::SoftwareFeature::kSmartLockClient, multidevice::SoftwareFeatureState::kSupported}}); fake_device_sync_client()->InvokePendingForceSyncNowCallback( true /* success */); @@ -319,12 +321,12 @@ // Set the current local device metadata to contain a sample of supported // software features. SetLocalDeviceMetadataSoftwareFeaturesMap( - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState>{ - {cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>{ + {multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, + {multidevice::SoftwareFeature::kSmartLockClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::MAGIC_TETHER_CLIENT, + {multidevice::SoftwareFeature::kInstantTetheringClient, multidevice::SoftwareFeatureState::kSupported}}); // Add one more supported software feature in the GcmDeviceInfo. SetFakeGcmDeviceInfoProviderWithSupportedSoftwareFeatures( @@ -346,14 +348,14 @@ fake_device_sync_client()->NotifyEnrollmentFinished(); EXPECT_EQ(1, fake_device_sync_client()->GetForceSyncNowCallbackQueueSize()); SetLocalDeviceMetadataSoftwareFeaturesMap( - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState>{ - {cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>{ + {multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, + {multidevice::SoftwareFeature::kSmartLockClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::MAGIC_TETHER_CLIENT, + {multidevice::SoftwareFeature::kInstantTetheringClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::SMS_CONNECT_CLIENT, + {multidevice::SoftwareFeature::kMessagesForWebClient, multidevice::SoftwareFeatureState::kSupported}}); fake_device_sync_client()->InvokePendingForceSyncNowCallback( true /* success */); @@ -368,12 +370,12 @@ // Set the current local device metadata to contain a sample of supported // software features. SetLocalDeviceMetadataSoftwareFeaturesMap( - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState>{ - {cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>{ + {multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, + {multidevice::SoftwareFeature::kSmartLockClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::MAGIC_TETHER_CLIENT, + {multidevice::SoftwareFeature::kInstantTetheringClient, multidevice::SoftwareFeatureState::kSupported}}); // Add one more supported software feature in the GcmDeviceInfo. SetFakeGcmDeviceInfoProviderWithSupportedSoftwareFeatures( @@ -398,10 +400,10 @@ // Set the current local device metadata to contain a sample of supported // software features. SetLocalDeviceMetadataSoftwareFeaturesMap( - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState>{ - {cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>{ + {multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, + {multidevice::SoftwareFeature::kSmartLockClient, multidevice::SoftwareFeatureState::kSupported}}); // Set the current GcmDeviceInfo supported software features to contain the // same set. @@ -427,10 +429,10 @@ // Set the current local device metadata to contain a sample of supported // software features. SetLocalDeviceMetadataSoftwareFeaturesMap( - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState>{ - {cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>{ + {multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, + {multidevice::SoftwareFeature::kSmartLockClient, multidevice::SoftwareFeatureState::kSupported}}); // Set the current GcmDeviceInfo supported software features to contain the // same set. @@ -456,10 +458,10 @@ // Set the current local device metadata to contain a sample of supported // software features. SetLocalDeviceMetadataSoftwareFeaturesMap( - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState>{ - {cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>{ + {multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported}, - {cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, + {multidevice::SoftwareFeature::kSmartLockClient, multidevice::SoftwareFeatureState::kSupported}}); // Set the current GcmDeviceInfo supported software features to contain the // same set. @@ -474,8 +476,8 @@ // Remove a feature from the metadata. SetLocalDeviceMetadataSoftwareFeaturesMap( - std::map<cryptauth::SoftwareFeature, multidevice::SoftwareFeatureState>{ - {cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, + std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>{ + {multidevice::SoftwareFeature::kSmartLockClient, multidevice::SoftwareFeatureState::kSupported}}); fake_device_sync_client()->NotifyNewDevicesSynced();
diff --git a/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl.cc b/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl.cc index 6c986e6..79e0bfc 100644 --- a/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl.cc +++ b/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl.cc
@@ -6,8 +6,8 @@ #include "base/memory/ptr_util.h" #include "base/no_destructor.h" +#include "chromeos/components/multidevice/software_feature.h" #include "chromeos/components/multidevice/software_feature_state.h" -#include "components/cryptauth/proto/cryptauth_api.pb.h" namespace chromeos { @@ -67,7 +67,7 @@ for (const auto& remote_device : device_sync_client_->GetSyncedDevices()) { multidevice::SoftwareFeatureState host_state = remote_device.GetSoftwareFeatureState( - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + multidevice::SoftwareFeature::kBetterTogetherHost); if (host_state == multidevice::SoftwareFeatureState::kSupported || host_state == multidevice::SoftwareFeatureState::kEnabled) { eligible_devices_from_last_sync_.push_back(remote_device);
diff --git a/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl_unittest.cc b/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl_unittest.cc index bf6058d..ded1528 100644 --- a/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl_unittest.cc +++ b/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl_unittest.cc
@@ -10,9 +10,9 @@ #include "base/macros.h" #include "base/stl_util.h" #include "chromeos/components/multidevice/remote_device_test_util.h" +#include "chromeos/components/multidevice/software_feature.h" #include "chromeos/components/multidevice/software_feature_state.h" #include "chromeos/services/device_sync/public/cpp/fake_device_sync_client.h" -#include "components/cryptauth/proto/cryptauth_api.pb.h" #include "testing/gtest/include/gtest/gtest.h" namespace chromeos { @@ -67,10 +67,10 @@ TEST_F(MultiDeviceSetupEligibleHostDevicesProviderImplTest, NoEligibleDevices) { GetMutableRemoteDevice(test_devices()[0]) - ->software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = + ->software_features[multidevice::SoftwareFeature::kBetterTogetherHost] = multidevice::SoftwareFeatureState::kNotSupported; GetMutableRemoteDevice(test_devices()[1]) - ->software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = + ->software_features[multidevice::SoftwareFeature::kBetterTogetherHost] = multidevice::SoftwareFeatureState::kNotSupported; multidevice::RemoteDeviceRefList devices{test_devices()[0], @@ -85,23 +85,23 @@ SupportedAndEnabled) { // Devices 0, 1, and 2 are supported. GetMutableRemoteDevice(test_devices()[0]) - ->software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = + ->software_features[multidevice::SoftwareFeature::kBetterTogetherHost] = multidevice::SoftwareFeatureState::kSupported; GetMutableRemoteDevice(test_devices()[1]) - ->software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = + ->software_features[multidevice::SoftwareFeature::kBetterTogetherHost] = multidevice::SoftwareFeatureState::kSupported; GetMutableRemoteDevice(test_devices()[2]) - ->software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = + ->software_features[multidevice::SoftwareFeature::kBetterTogetherHost] = multidevice::SoftwareFeatureState::kSupported; // Device 3 is enabled. GetMutableRemoteDevice(test_devices()[3]) - ->software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = + ->software_features[multidevice::SoftwareFeature::kBetterTogetherHost] = multidevice::SoftwareFeatureState::kEnabled; // Device 4 is not supported. GetMutableRemoteDevice(test_devices()[4]) - ->software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = + ->software_features[multidevice::SoftwareFeature::kBetterTogetherHost] = multidevice::SoftwareFeatureState::kNotSupported; multidevice::RemoteDeviceRefList devices{test_devices()[0], test_devices()[1],
diff --git a/chromeos/services/multidevice_setup/feature_state_manager_impl.cc b/chromeos/services/multidevice_setup/feature_state_manager_impl.cc index 30a4e103..1a1fcf9d 100644 --- a/chromeos/services/multidevice_setup/feature_state_manager_impl.cc +++ b/chromeos/services/multidevice_setup/feature_state_manager_impl.cc
@@ -12,6 +12,7 @@ #include "base/optional.h" #include "base/stl_util.h" #include "chromeos/components/multidevice/remote_device_ref.h" +#include "chromeos/components/multidevice/software_feature.h" #include "chromeos/components/proximity_auth/logging/logging.h" #include "chromeos/services/multidevice_setup/public/cpp/prefs.h" #include "components/prefs/pref_service.h" @@ -317,16 +318,16 @@ } bool FeatureStateManagerImpl::IsSupportedByChromebook(mojom::Feature feature) { - static const std::pair<mojom::Feature, cryptauth::SoftwareFeature> + static const std::pair<mojom::Feature, multidevice::SoftwareFeature> kFeatureAndClientSoftwareFeaturePairs[] = { {mojom::Feature::kBetterTogetherSuite, - cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT}, + multidevice::SoftwareFeature::kBetterTogetherClient}, {mojom::Feature::kInstantTethering, - cryptauth::SoftwareFeature::MAGIC_TETHER_CLIENT}, + multidevice::SoftwareFeature::kInstantTetheringClient}, {mojom::Feature::kMessages, - cryptauth::SoftwareFeature::SMS_CONNECT_CLIENT}, + multidevice::SoftwareFeature::kMessagesForWebClient}, {mojom::Feature::kSmartLock, - cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT}}; + multidevice::SoftwareFeature::kSmartLockClient}}; for (const auto& pair : kFeatureAndClientSoftwareFeaturePairs) { if (pair.first != feature) @@ -348,26 +349,26 @@ return true; // Special case for Smart Lock: if the host device does not have a lock screen - // set, its SoftwareFeatureState for EASY_UNLOCK_HOST is supported but not + // set, its SoftwareFeatureState for kSmartLockHost is supported but not // enabled. return host_device.GetSoftwareFeatureState( - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST) != + multidevice::SoftwareFeature::kSmartLockHost) != multidevice::SoftwareFeatureState::kSupported; } bool FeatureStateManagerImpl::HasBeenActivatedByPhone( mojom::Feature feature, const multidevice::RemoteDeviceRef& host_device) { - static const std::pair<mojom::Feature, cryptauth::SoftwareFeature> + static const std::pair<mojom::Feature, multidevice::SoftwareFeature> kFeatureAndHostSoftwareFeaturePairs[] = { {mojom::Feature::kBetterTogetherSuite, - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST}, + multidevice::SoftwareFeature::kBetterTogetherHost}, {mojom::Feature::kInstantTethering, - cryptauth::SoftwareFeature::MAGIC_TETHER_HOST}, + multidevice::SoftwareFeature::kInstantTetheringHost}, {mojom::Feature::kMessages, - cryptauth::SoftwareFeature::SMS_CONNECT_HOST}, + multidevice::SoftwareFeature::kMessagesForWebHost}, {mojom::Feature::kSmartLock, - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST}}; + multidevice::SoftwareFeature::kSmartLockHost}}; for (const auto& pair : kFeatureAndHostSoftwareFeaturePairs) { if (pair.first != feature)
diff --git a/chromeos/services/multidevice_setup/feature_state_manager_impl_unittest.cc b/chromeos/services/multidevice_setup/feature_state_manager_impl_unittest.cc index ed34118f..b553a2bb 100644 --- a/chromeos/services/multidevice_setup/feature_state_manager_impl_unittest.cc +++ b/chromeos/services/multidevice_setup/feature_state_manager_impl_unittest.cc
@@ -31,13 +31,15 @@ multidevice::RemoteDevice* raw_device = multidevice::GetMutableRemoteDevice(host_device); raw_device - ->software_features[cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = + ->software_features[multidevice::SoftwareFeature::kBetterTogetherHost] = multidevice::SoftwareFeatureState::kSupported; - raw_device->software_features[cryptauth::SoftwareFeature::EASY_UNLOCK_HOST] = + raw_device->software_features[multidevice::SoftwareFeature::kSmartLockHost] = multidevice::SoftwareFeatureState::kSupported; - raw_device->software_features[cryptauth::SoftwareFeature::MAGIC_TETHER_HOST] = + raw_device + ->software_features[multidevice::SoftwareFeature::kInstantTetheringHost] = multidevice::SoftwareFeatureState::kSupported; - raw_device->software_features[cryptauth::SoftwareFeature::SMS_CONNECT_HOST] = + raw_device + ->software_features[multidevice::SoftwareFeature::kMessagesForWebHost] = multidevice::SoftwareFeatureState::kSupported; return host_device; @@ -136,7 +138,7 @@ fake_observer_->feature_state_updates().size(); SetSoftwareFeatureState(false /* use_local_device */, - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, + multidevice::SoftwareFeature::kBetterTogetherHost, multidevice::SoftwareFeatureState::kEnabled); fake_host_status_provider_->SetHostWithStatus( mojom::HostStatus::kHostVerified, test_host_device_); @@ -149,7 +151,7 @@ void MakeBetterTogetherSuiteDisabledByUser() { SetSoftwareFeatureState(true /* use_local_device */, - cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported); test_pref_service_->SetBoolean(kBetterTogetherSuiteEnabledPrefName, false); EXPECT_EQ( @@ -169,7 +171,7 @@ void SetSoftwareFeatureState( bool use_local_device, - cryptauth::SoftwareFeature software_feature, + multidevice::SoftwareFeature software_feature, multidevice::SoftwareFeatureState software_feature_state) { multidevice::RemoteDeviceRef& device = use_local_device ? test_local_device_ : test_host_device_; @@ -215,7 +217,7 @@ manager()->GetFeatureStates()[mojom::Feature::kBetterTogetherSuite]); SetSoftwareFeatureState(true /* use_local_device */, - cryptauth::SoftwareFeature::BETTER_TOGETHER_CLIENT, + multidevice::SoftwareFeature::kBetterTogetherClient, multidevice::SoftwareFeatureState::kSupported); EXPECT_EQ( mojom::FeatureState::kEnabledByUser, @@ -254,7 +256,7 @@ manager()->GetFeatureStates()[mojom::Feature::kInstantTethering]); SetSoftwareFeatureState(true /* use_local_device */, - cryptauth::SoftwareFeature::MAGIC_TETHER_CLIENT, + multidevice::SoftwareFeature::kInstantTetheringClient, multidevice::SoftwareFeatureState::kSupported); EXPECT_EQ(mojom::FeatureState::kNotSupportedByPhone, manager()->GetFeatureStates()[mojom::Feature::kInstantTethering]); @@ -263,7 +265,7 @@ mojom::FeatureState::kNotSupportedByPhone); SetSoftwareFeatureState(false /* use_local_device */, - cryptauth::SoftwareFeature::MAGIC_TETHER_HOST, + multidevice::SoftwareFeature::kInstantTetheringHost, multidevice::SoftwareFeatureState::kEnabled); EXPECT_EQ(mojom::FeatureState::kEnabledByUser, manager()->GetFeatureStates()[mojom::Feature::kInstantTethering]); @@ -301,7 +303,7 @@ manager()->GetFeatureStates()[mojom::Feature::kMessages]); SetSoftwareFeatureState(true /* use_local_device */, - cryptauth::SoftwareFeature::SMS_CONNECT_CLIENT, + multidevice::SoftwareFeature::kMessagesForWebClient, multidevice::SoftwareFeatureState::kSupported); EXPECT_EQ(mojom::FeatureState::kNotSupportedByPhone, manager()->GetFeatureStates()[mojom::Feature::kMessages]); @@ -309,7 +311,7 @@ mojom::FeatureState::kNotSupportedByPhone); SetSoftwareFeatureState(false /* use_local_device */, - cryptauth::SoftwareFeature::SMS_CONNECT_HOST, + multidevice::SoftwareFeature::kMessagesForWebHost, multidevice::SoftwareFeatureState::kEnabled); EXPECT_EQ(mojom::FeatureState::kEnabledByUser, manager()->GetFeatureStates()[mojom::Feature::kMessages]); @@ -360,7 +362,7 @@ manager()->GetFeatureStates()[mojom::Feature::kSmartLock]); SetSoftwareFeatureState(true /* use_local_device */, - cryptauth::SoftwareFeature::EASY_UNLOCK_CLIENT, + multidevice::SoftwareFeature::kSmartLockClient, multidevice::SoftwareFeatureState::kSupported); EXPECT_EQ(mojom::FeatureState::kUnavailableInsufficientSecurity, manager()->GetFeatureStates()[mojom::Feature::kSmartLock]); @@ -369,7 +371,7 @@ mojom::FeatureState::kUnavailableInsufficientSecurity); SetSoftwareFeatureState(false /* use_local_device */, - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST, + multidevice::SoftwareFeature::kSmartLockHost, multidevice::SoftwareFeatureState::kEnabled); EXPECT_EQ(mojom::FeatureState::kEnabledByUser, manager()->GetFeatureStates()[mojom::Feature::kSmartLock]);
diff --git a/chromeos/services/multidevice_setup/grandfathered_easy_unlock_host_disabler.cc b/chromeos/services/multidevice_setup/grandfathered_easy_unlock_host_disabler.cc index 7b814e7..dfde1df 100644 --- a/chromeos/services/multidevice_setup/grandfathered_easy_unlock_host_disabler.cc +++ b/chromeos/services/multidevice_setup/grandfathered_easy_unlock_host_disabler.cc
@@ -18,7 +18,7 @@ namespace { // Name of the pref that stores the ID of the device which still potentially -// needs to have EASY_UNLOCK_HOST disabled on it. +// needs to have kSmartLockHost disabled on it. const char kEasyUnlockHostIdToDisablePrefName[] = "multidevice_setup.easy_unlock_host_id_to_disable"; @@ -29,7 +29,7 @@ bool IsEasyUnlockHost(const multidevice::RemoteDeviceRef& device) { return device.GetSoftwareFeatureState( - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST) == + multidevice::SoftwareFeature::kSmartLockHost) == multidevice::SoftwareFeatureState::kEnabled; } @@ -91,13 +91,13 @@ host_backend_delegate_->GetMultiDeviceHostFromBackend()) { host_backend_delegate_->AddObserver(this); - // There might be a device stored in the pref waiting for EASY_UNLOCK_HOST to + // There might be a device stored in the pref waiting for kSmartLockHost to // be disabled. DisableEasyUnlockHostIfNecessary(); } void GrandfatheredEasyUnlockHostDisabler::OnHostChangedOnBackend() { - // EASY_UNLOCK_HOST possibly needs to be disabled on the previous + // kSmartLockHost possibly needs to be disabled on the previous // BetterTogether host. SetPotentialEasyUnlockHostToDisable(current_better_together_host_); @@ -117,11 +117,11 @@ if (!host_to_disable) return; - PA_LOG(VERBOSE) << "Attempting to disable EASY_UNLOCK_HOST on device " + PA_LOG(VERBOSE) << "Attempting to disable kSmartLockHost on device " << host_to_disable->GetTruncatedDeviceIdForLogs(); device_sync_client_->SetSoftwareFeatureState( host_to_disable->public_key(), - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST, false /* enabled */, + multidevice::SoftwareFeature::kSmartLockHost, false /* enabled */, false /* is_exclusive */, base::BindOnce( &GrandfatheredEasyUnlockHostDisabler::OnSetSoftwareFeatureStateResult, @@ -135,10 +135,10 @@ result_code == device_sync::mojom::NetworkRequestResult::kSuccess; if (success) { - PA_LOG(VERBOSE) << "Successfully disabled EASY_UNLOCK_HOST on device " + PA_LOG(VERBOSE) << "Successfully disabled kSmartLockHost on device " << device.GetTruncatedDeviceIdForLogs(); } else { - PA_LOG(WARNING) << "Failed to disable EASY_UNLOCK_HOST on device " + PA_LOG(WARNING) << "Failed to disable kSmartLockHost on device " << device.GetTruncatedDeviceIdForLogs() << ", Error code: " << result_code; } @@ -183,7 +183,7 @@ return remote_device.GetDeviceId() == device_id; }); - // The device does not need to have EASY_UNLOCK_HOST disabled if any of the + // The device does not need to have kSmartLockHost disabled if any of the // following are true: // - the device is not in the list of synced devices anymore, // - the device is not the current EasyUnlock host, or
diff --git a/chromeos/services/multidevice_setup/grandfathered_easy_unlock_host_disabler_unittest.cc b/chromeos/services/multidevice_setup/grandfathered_easy_unlock_host_disabler_unittest.cc index 5643630..5690c2af 100644 --- a/chromeos/services/multidevice_setup/grandfathered_easy_unlock_host_disabler_unittest.cc +++ b/chromeos/services/multidevice_setup/grandfathered_easy_unlock_host_disabler_unittest.cc
@@ -52,9 +52,9 @@ } void SetHost(const base::Optional<multidevice::RemoteDeviceRef>& host_device, - cryptauth::SoftwareFeature host_type) { - if (host_type != cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST && - host_type != cryptauth::SoftwareFeature::EASY_UNLOCK_HOST) + multidevice::SoftwareFeature host_type) { + if (host_type != multidevice::SoftwareFeature::kBetterTogetherHost && + host_type != multidevice::SoftwareFeature::kSmartLockHost) return; for (const auto& remote_device : test_devices_) { @@ -67,7 +67,7 @@ : multidevice::SoftwareFeatureState::kSupported; } - if (host_type == cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST) + if (host_type == multidevice::SoftwareFeature::kBetterTogetherHost) fake_host_backend_delegate_->NotifyHostChangedOnBackend(host_device); } @@ -79,9 +79,9 @@ initial_device_id_pref_value); SetHost(initial_better_together_host, - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + multidevice::SoftwareFeature::kBetterTogetherHost); SetHost(initial_easy_unlock_host, - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST); + multidevice::SoftwareFeature::kSmartLockHost); auto mock_timer = std::make_unique<base::MockOneShotTimer>(); mock_timer_ = mock_timer.get(); @@ -141,7 +141,7 @@ test_devices()[0] /* initial_better_together_host */, test_devices()[0] /* initial_easy_unlock_host */); - SetHost(base::nullopt, cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + SetHost(base::nullopt, multidevice::SoftwareFeature::kBetterTogetherHost); EXPECT_EQ(test_devices()[0].GetDeviceId(), GetEasyUnlockHostIdToDisablePrefValue()); @@ -175,7 +175,7 @@ base::nullopt /* initial_better_together_host */, test_devices()[0] /* initial_easy_unlock_host */); - SetHost(test_devices()[1], cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + SetHost(test_devices()[1], multidevice::SoftwareFeature::kBetterTogetherHost); EXPECT_EQ(kNoDevice, GetEasyUnlockHostIdToDisablePrefValue()); EXPECT_EQ( @@ -202,7 +202,7 @@ test_devices()[0] /* initial_better_together_host */, test_devices()[0] /* initial_easy_unlock_host */); - SetHost(test_devices()[1], cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + SetHost(test_devices()[1], multidevice::SoftwareFeature::kBetterTogetherHost); EXPECT_EQ(test_devices()[0].GetDeviceId(), GetEasyUnlockHostIdToDisablePrefValue()); @@ -247,7 +247,7 @@ // Remove device[0] from list fake_device_sync_client()->set_synced_devices({test_devices()[1]}); - SetHost(base::nullopt, cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + SetHost(base::nullopt, multidevice::SoftwareFeature::kBetterTogetherHost); EXPECT_EQ(kNoDevice, GetEasyUnlockHostIdToDisablePrefValue()); EXPECT_EQ( @@ -268,7 +268,7 @@ test_devices()[0] /* initial_better_together_host */, test_devices()[0] /* initial_easy_unlock_host */); - SetHost(base::nullopt, cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + SetHost(base::nullopt, multidevice::SoftwareFeature::kBetterTogetherHost); EXPECT_EQ( 1, @@ -340,7 +340,7 @@ test_devices()[0] /* initial_better_together_host */, test_devices()[0] /* initial_easy_unlock_host */); - SetHost(base::nullopt, cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + SetHost(base::nullopt, multidevice::SoftwareFeature::kBetterTogetherHost); EXPECT_EQ( 1, @@ -350,7 +350,7 @@ EXPECT_TRUE(mock_timer()->IsRunning()); - SetHost(test_devices()[0], cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + SetHost(test_devices()[0], multidevice::SoftwareFeature::kBetterTogetherHost); EXPECT_EQ( 0, @@ -371,12 +371,12 @@ test_devices()[0] /* initial_better_together_host */, test_devices()[0] /* initial_easy_unlock_host */); - SetHost(base::nullopt, cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + SetHost(base::nullopt, multidevice::SoftwareFeature::kBetterTogetherHost); - SetHost(test_devices()[1], cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); - SetHost(test_devices()[1], cryptauth::SoftwareFeature::EASY_UNLOCK_HOST); + SetHost(test_devices()[1], multidevice::SoftwareFeature::kBetterTogetherHost); + SetHost(test_devices()[1], multidevice::SoftwareFeature::kSmartLockHost); - SetHost(base::nullopt, cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + SetHost(base::nullopt, multidevice::SoftwareFeature::kBetterTogetherHost); EXPECT_EQ( 2,
diff --git a/chromeos/services/multidevice_setup/host_backend_delegate_impl.cc b/chromeos/services/multidevice_setup/host_backend_delegate_impl.cc index 26a7cba..af6591f7 100644 --- a/chromeos/services/multidevice_setup/host_backend_delegate_impl.cc +++ b/chromeos/services/multidevice_setup/host_backend_delegate_impl.cc
@@ -11,6 +11,8 @@ #include "base/memory/ptr_util.h" #include "base/no_destructor.h" #include "base/stl_util.h" +#include "chromeos/components/multidevice/software_feature.h" +#include "chromeos/components/multidevice/software_feature_state.h" #include "chromeos/components/proximity_auth/logging/logging.h" #include "chromeos/services/multidevice_setup/eligible_host_devices_provider.h" #include "components/prefs/pref_registry_simple.h" @@ -241,7 +243,7 @@ device_sync_client_->SetSoftwareFeatureState( device_to_set.public_key(), - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, + multidevice::SoftwareFeature::kBetterTogetherHost, should_enable /* enabled */, should_enable /* is_exclusive */, base::BindOnce(&HostBackendDelegateImpl::OnSetSoftwareFeatureStateResult, weak_ptr_factory_.GetWeakPtr(), device_to_set, @@ -285,7 +287,7 @@ [](const auto& remote_device) { multidevice::SoftwareFeatureState host_state = remote_device.GetSoftwareFeatureState( - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST); + multidevice::SoftwareFeature::kBetterTogetherHost); return host_state == multidevice::SoftwareFeatureState::kEnabled; });
diff --git a/chromeos/services/multidevice_setup/host_backend_delegate_impl_unittest.cc b/chromeos/services/multidevice_setup/host_backend_delegate_impl_unittest.cc index 76fe9c7..e15c0d5 100644 --- a/chromeos/services/multidevice_setup/host_backend_delegate_impl_unittest.cc +++ b/chromeos/services/multidevice_setup/host_backend_delegate_impl_unittest.cc
@@ -12,6 +12,8 @@ #include "base/timer/mock_timer.h" #include "base/unguessable_token.h" #include "chromeos/components/multidevice/remote_device_test_util.h" +#include "chromeos/components/multidevice/software_feature.h" +#include "chromeos/components/multidevice/software_feature_state.h" #include "chromeos/services/device_sync/public/cpp/fake_device_sync_client.h" #include "chromeos/services/multidevice_setup/fake_eligible_host_devices_provider.h" #include "chromeos/services/multidevice_setup/fake_host_backend_delegate.h" @@ -183,7 +185,7 @@ GetMutableRemoteDevice(remote_device) ->software_features - [cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST] = + [multidevice::SoftwareFeature::kBetterTogetherHost] = should_be_host ? multidevice::SoftwareFeatureState::kEnabled : multidevice::SoftwareFeatureState::kSupported; }
diff --git a/chromeos/services/multidevice_setup/host_verifier_impl.cc b/chromeos/services/multidevice_setup/host_verifier_impl.cc index eff7655..8e5e43c 100644 --- a/chromeos/services/multidevice_setup/host_verifier_impl.cc +++ b/chromeos/services/multidevice_setup/host_verifier_impl.cc
@@ -7,6 +7,7 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/no_destructor.h" +#include "chromeos/components/multidevice/software_feature.h" #include "chromeos/components/proximity_auth/logging/logging.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" @@ -18,10 +19,10 @@ namespace { // Software features which, when enabled, represent a verified host. -constexpr const cryptauth::SoftwareFeature kPotentialHostFeatures[] = { - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST, - cryptauth::SoftwareFeature::MAGIC_TETHER_HOST, - cryptauth::SoftwareFeature::SMS_CONNECT_HOST}; +constexpr const multidevice::SoftwareFeature kPotentialHostFeatures[] = { + multidevice::SoftwareFeature::kSmartLockHost, + multidevice::SoftwareFeature::kInstantTetheringHost, + multidevice::SoftwareFeature::kMessagesForWebHost}; // Name of the preference containing the time (in milliseconds since Unix // epoch) at which a verification attempt should be retried. If the preference @@ -242,7 +243,7 @@ PA_LOG(VERBOSE) << "HostVerifierImpl::AttemptHostVerification(): Attempting " << "host verification now."; device_sync_client_->FindEligibleDevices( - cryptauth::SoftwareFeature::BETTER_TOGETHER_HOST, base::DoNothing()); + multidevice::SoftwareFeature::kBetterTogetherHost, base::DoNothing()); } } // namespace multidevice_setup
diff --git a/chromeos/services/multidevice_setup/host_verifier_impl_unittest.cc b/chromeos/services/multidevice_setup/host_verifier_impl_unittest.cc index b3f97f48..865aac526 100644 --- a/chromeos/services/multidevice_setup/host_verifier_impl_unittest.cc +++ b/chromeos/services/multidevice_setup/host_verifier_impl_unittest.cc
@@ -10,6 +10,8 @@ #include "base/test/simple_test_clock.h" #include "base/timer/mock_timer.h" #include "chromeos/components/multidevice/remote_device_test_util.h" +#include "chromeos/components/multidevice/software_feature.h" +#include "chromeos/components/multidevice/software_feature_state.h" #include "chromeos/services/device_sync/public/cpp/fake_device_sync_client.h" #include "chromeos/services/multidevice_setup/fake_host_backend_delegate.h" #include "chromeos/services/multidevice_setup/fake_host_verifier.h" @@ -24,10 +26,10 @@ const int64_t kTestTimeMs = 1500000000000; -constexpr const cryptauth::SoftwareFeature kPotentialHostSoftwareFeatures[] = { - cryptauth::SoftwareFeature::EASY_UNLOCK_HOST, - cryptauth::SoftwareFeature::MAGIC_TETHER_HOST, - cryptauth::SoftwareFeature::SMS_CONNECT_HOST}; +constexpr const multidevice::SoftwareFeature kPotentialHostSoftwareFeatures[] = + {multidevice::SoftwareFeature::kSmartLockHost, + multidevice::SoftwareFeature::kInstantTetheringHost, + multidevice::SoftwareFeature::kMessagesForWebHost}; const char kRetryTimestampPrefName[] = "multidevice_setup.current_retry_timestamp_ms";
diff --git a/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom b/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom index c07b1396..2295836 100644 --- a/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom +++ b/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom
@@ -4,7 +4,7 @@ module chromeos.multidevice_setup.mojom; -import "chromeos/services/device_sync/public/mojom/device_sync.mojom"; +import "chromeos/components/multidevice/mojom/multidevice_types.mojom"; // Enumeration of event types which can be dispatched. Only used for debugging // purposes. @@ -122,7 +122,7 @@ // HostStatus::kNoEligibleHosts or // HostStatus::kEligibleHostExistsButNoHostSet, |host_device| is null. OnHostStatusChanged(HostStatus host_status, - chromeos.device_sync.mojom.RemoteDevice? host_device); + chromeos.multidevice.mojom.RemoteDevice? host_device); }; interface FeatureStateObserver { @@ -151,7 +151,7 @@ // Provides a list of all eligible host devices (i.e., those which can be // passed to SetHostDevice()). GetEligibleHostDevices() => - (array<chromeos.device_sync.mojom.RemoteDevice> eligible_host_devices); + (array<chromeos.multidevice.mojom.RemoteDevice> eligible_host_devices); // Sets the host associated with the provided device ID as the host device // for this account. The provided auth token must be valid in order to prove @@ -172,7 +172,7 @@ // HostStatus::kNoEligibleHosts or // HostStatus::kEligibleHostExistsButNoHostSet, |host_device| is null. GetHostStatus() => (HostStatus host_status, - chromeos.device_sync.mojom.RemoteDevice? host_device); + chromeos.multidevice.mojom.RemoteDevice? host_device); // Attempts to enable or disable |feature|. This function succeeds only if // |feature|'s current state is FeatureState::kEnabledByUser or
diff --git a/chromeos/services/secure_channel/ble_service_data_helper_impl.cc b/chromeos/services/secure_channel/ble_service_data_helper_impl.cc index 1cf12a9..82a55f83 100644 --- a/chromeos/services/secure_channel/ble_service_data_helper_impl.cc +++ b/chromeos/services/secure_channel/ble_service_data_helper_impl.cc
@@ -8,6 +8,7 @@ #include "base/memory/ptr_util.h" #include "base/no_destructor.h" #include "chromeos/chromeos_switches.h" +#include "chromeos/components/multidevice/beacon_seed.h" #include "chromeos/components/multidevice/remote_device_cache.h" #include "chromeos/components/multidevice/remote_device_ref.h" #include "chromeos/components/proximity_auth/logging/logging.h" @@ -144,7 +145,9 @@ // First try, identifying |service_data| as a foreground advertisement. if (service_data.size() >= kMinNumBytesInForegroundServiceData) { std::vector<cryptauth::BeaconSeed> beacon_seeds = - remote_device_cache_->GetRemoteDevice(local_device_id)->beacon_seeds(); + multidevice::ToCryptAuthSeedList( + remote_device_cache_->GetRemoteDevice(local_device_id) + ->beacon_seeds()); identified_device_id = foreground_eid_generator_->IdentifyRemoteDeviceByAdvertisement(
diff --git a/chromeos/services/secure_channel/ble_service_data_helper_impl_unittest.cc b/chromeos/services/secure_channel/ble_service_data_helper_impl_unittest.cc index 37019c0..b9c0ac38 100644 --- a/chromeos/services/secure_channel/ble_service_data_helper_impl_unittest.cc +++ b/chromeos/services/secure_channel/ble_service_data_helper_impl_unittest.cc
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" +#include "base/time/time.h" #include "chromeos/components/multidevice/remote_device_cache.h" #include "chromeos/components/multidevice/remote_device_test_util.h" #include "chromeos/services/secure_channel/device_id_pair.h" @@ -57,20 +58,22 @@ current, std::move(adjacent)); } -std::vector<cryptauth::BeaconSeed> CreateFakeBeaconSeeds(int id) { +std::vector<multidevice::BeaconSeed> CreateFakeBeaconSeeds(int id) { std::string id_str = std::to_string(id); - cryptauth::BeaconSeed seed1; - seed1.set_data(fake_beacon_seed1_data + id_str); - seed1.set_start_time_millis(fake_beacon_seed1_start_ms * id); - seed1.set_start_time_millis(fake_beacon_seed1_end_ms * id); + multidevice::BeaconSeed seed1( + fake_beacon_seed1_data + id_str /* data */, + base::Time::FromJavaTime(fake_beacon_seed1_start_ms * + id) /* start_time */, + base::Time::FromJavaTime(fake_beacon_seed1_end_ms * id) /* end_time */); - cryptauth::BeaconSeed seed2; - seed2.set_data(fake_beacon_seed2_data + id_str); - seed2.set_start_time_millis(fake_beacon_seed2_start_ms * id); - seed2.set_start_time_millis(fake_beacon_seed2_end_ms * id); + multidevice::BeaconSeed seed2( + fake_beacon_seed2_data + id_str /* data */, + base::Time::FromJavaTime(fake_beacon_seed2_start_ms * + id) /* start_time */, + base::Time::FromJavaTime(fake_beacon_seed2_end_ms * id) /* end_time */); - std::vector<cryptauth::BeaconSeed> seeds = {seed1, seed2}; + std::vector<multidevice::BeaconSeed> seeds = {seed1, seed2}; return seeds; }
diff --git a/chromeos/services/secure_channel/public/mojom/BUILD.gn b/chromeos/services/secure_channel/public/mojom/BUILD.gn index 52ddeeb..ff92c485a 100644 --- a/chromeos/services/secure_channel/public/mojom/BUILD.gn +++ b/chromeos/services/secure_channel/public/mojom/BUILD.gn
@@ -11,7 +11,7 @@ ] public_deps = [ - "//chromeos/services/device_sync/public/mojom", + "//chromeos/components/multidevice/mojom", "//mojo/public/mojom/base", ] }
diff --git a/chromeos/services/secure_channel/public/mojom/secure_channel.mojom b/chromeos/services/secure_channel/public/mojom/secure_channel.mojom index f58a8c4..06a053b 100644 --- a/chromeos/services/secure_channel/public/mojom/secure_channel.mojom +++ b/chromeos/services/secure_channel/public/mojom/secure_channel.mojom
@@ -4,7 +4,7 @@ module chromeos.secure_channel.mojom; -import "chromeos/services/device_sync/public/mojom/device_sync.mojom"; +import "chromeos/components/multidevice/mojom/multidevice_types.mojom"; enum ConnectionAttemptFailureReason { // The local device could not authenticate with the remote device. This likely @@ -169,8 +169,8 @@ // cancel a connection attempt (i.e., to stop listening for incoming // connections), disconnect |delegate|. ListenForConnectionFromDevice( - chromeos.device_sync.mojom.RemoteDevice device_to_connect, - chromeos.device_sync.mojom.RemoteDevice local_device, + chromeos.multidevice.mojom.RemoteDevice device_to_connect, + chromeos.multidevice.mojom.RemoteDevice local_device, string feature, ConnectionPriority connection_priority, ConnectionDelegate delegate); @@ -183,8 +183,8 @@ // if a connection was attempted and failed several retry attempts. To cancel // the connection attempt, disconnect |delegate|. InitiateConnectionToDevice( - chromeos.device_sync.mojom.RemoteDevice device_to_connect, - chromeos.device_sync.mojom.RemoteDevice local_device, + chromeos.multidevice.mojom.RemoteDevice device_to_connect, + chromeos.multidevice.mojom.RemoteDevice local_device, string feature, ConnectionPriority connection_priority, ConnectionDelegate delegate);
diff --git a/chromeos/test/data/oobe_configuration/TestEnrollUsingToken.json b/chromeos/test/data/oobe_configuration/TestEnrollUsingToken.json new file mode 100644 index 0000000..0138f9c --- /dev/null +++ b/chromeos/test/data/oobe_configuration/TestEnrollUsingToken.json
@@ -0,0 +1,9 @@ +{ + "welcomeNext": true, + "networkSelectGuid": "eth1_guid", + "eulaAutoAccept": true, + "eulaSendStatistics": true, + "updateSkipNonCritical": true, + "wizardAutoEnroll": true, + "enrollmentToken": "00000000-1111-2222-3333-444444444444" +} \ No newline at end of file
diff --git a/components/BUILD.gn b/components/BUILD.gn index 64b23c57..a6863b9a 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -536,8 +536,8 @@ deps += [ "//components/autofill_assistant/browser", "//components/autofill_assistant/browser:proto", - "//content/public/test/android:layouttest_java_support", - "//content/test:layouttest_support", + "//content/public/test/android:web_test_java_support", + "//content/test:web_test_support", "//testing/android/native_test:native_test_support", ] use_default_launcher = false
diff --git a/components/arc/arc_session_impl.cc b/components/arc/arc_session_impl.cc index 3faf412..67ebded 100644 --- a/components/arc/arc_session_impl.cc +++ b/components/arc/arc_session_impl.cc
@@ -222,32 +222,36 @@ return socket_fd; } - // Change permissions on the socket. - struct group arc_bridge_group; - struct group* arc_bridge_group_res = nullptr; - int ret = 0; - char buf[10000]; - do { - ret = getgrnam_r(kArcBridgeSocketGroup, &arc_bridge_group, buf, sizeof(buf), - &arc_bridge_group_res); - } while (ret == EINTR); - if (ret != 0) { - LOG(ERROR) << "getgrnam_r: " << strerror_r(ret, buf, sizeof(buf)); - return base::ScopedFD(); - } + // Change permissions on the socket. Note that since arcvm doesn't directly + // share the socket with ARC, it can use 0600 and the default group. arcvm + // build doesn't have |kArcBridgeSocketGroup| in the first place. + if (!IsArcVmEnabled()) { + struct group arc_bridge_group; + struct group* arc_bridge_group_res = nullptr; + int ret = 0; + char buf[10000]; + do { + ret = getgrnam_r(kArcBridgeSocketGroup, &arc_bridge_group, buf, + sizeof(buf), &arc_bridge_group_res); + } while (ret == EINTR); + if (ret != 0) { + LOG(ERROR) << "getgrnam_r: " << strerror_r(ret, buf, sizeof(buf)); + return base::ScopedFD(); + } - if (!arc_bridge_group_res) { - LOG(ERROR) << "Group '" << kArcBridgeSocketGroup << "' not found"; - return base::ScopedFD(); - } + if (!arc_bridge_group_res) { + LOG(ERROR) << "Group '" << kArcBridgeSocketGroup << "' not found"; + return base::ScopedFD(); + } - if (chown(kArcBridgeSocketPath, -1, arc_bridge_group.gr_gid) < 0) { - PLOG(ERROR) << "chown failed"; - return base::ScopedFD(); + if (chown(kArcBridgeSocketPath, -1, arc_bridge_group.gr_gid) < 0) { + PLOG(ERROR) << "chown failed"; + return base::ScopedFD(); + } } if (!base::SetPosixFilePermissions(base::FilePath(kArcBridgeSocketPath), - 0660)) { + IsArcVmEnabled() ? 0600 : 0660)) { PLOG(ERROR) << "Could not set permissions: " << kArcBridgeSocketPath; return base::ScopedFD(); }
diff --git a/components/arc/arc_vm_client_adapter.cc b/components/arc/arc_vm_client_adapter.cc index a15e1a4..9c18b1988 100644 --- a/components/arc/arc_vm_client_adapter.cc +++ b/components/arc/arc_vm_client_adapter.cc
@@ -8,20 +8,27 @@ #include <utility> #include "base/bind.h" +#include "base/guid.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/task/post_task.h" +#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/session_manager_client.h" +#include "chromeos/dbus/upstart_client.h" namespace arc { namespace { -// TODO(yusukes): Move ArcContainerStopReason to arc:: and remove the #include. +// TODO(yusukes): Move ArcContainerStopReason to arc:: and stop including +// chromeos/dbus/session_manager_client.h. constexpr login_manager::ArcContainerStopReason kDummyReason = login_manager::ArcContainerStopReason::SESSION_MANAGER_SHUTDOWN; -constexpr char kDummyInstanceId[] = "dummyinstanceid"; + +// The conversion of upstart job names to dbus object paths is undocumented. See +// arc_data_remover.cc for more information. +constexpr char kArcVmUpstartJob[] = "arcvm"; } // namespace @@ -44,34 +51,62 @@ void UpgradeArc(const UpgradeArcContainerRequest& request, base::OnceClosure success_callback, UpgradeErrorCallback error_callback) override { - // TODO(yusukes): Start arcvm. - base::PostTask( - FROM_HERE, - base::BindOnce(&ArcVmClientAdapter::OnArcInstanceUpgradeFailed, - weak_factory_.GetWeakPtr(), std::move(error_callback))); + // TODO(yusukes): Consider doing the same as crostini rather than taking to + // Upstart. + VLOG(1) << "Starting arcvm"; + auto* upstart_client = + chromeos::DBusThreadManager::Get()->GetUpstartClient(); + DCHECK(upstart_client); + upstart_client->StartJob( + kArcVmUpstartJob, + {}, // TODO(yusukes): Pass the content of the |request| to the job. + base::BindOnce(&ArcVmClientAdapter::OnArcInstanceUpgraded, + weak_factory_.GetWeakPtr(), std::move(success_callback), + std::move(error_callback))); } void StopArcInstance() override { - // TODO(yusukes): Stop arcvm. - base::PostTask(FROM_HERE, - base::BindOnce(&ArcVmClientAdapter::OnArcInstanceStopped, - weak_factory_.GetWeakPtr())); + // TODO(yusukes): Consider doing the same as crostini rather than taking to + // Upstart. + VLOG(1) << "Stopping arcvm"; + auto* upstart_client = + chromeos::DBusThreadManager::Get()->GetUpstartClient(); + DCHECK(upstart_client); + upstart_client->StopJob( + kArcVmUpstartJob, + base::BindOnce(&ArcVmClientAdapter::OnArcInstanceStopped, + weak_factory_.GetWeakPtr())); } private: void OnArcMiniInstanceStarted(StartMiniArcCallback callback) { - std::move(callback).Run(kDummyInstanceId); + current_instance_id_ = base::GenerateGUID(); + std::move(callback).Run(current_instance_id_); } - void OnArcInstanceUpgradeFailed(UpgradeErrorCallback callback) { - std::move(callback).Run(/*low_free_disk_space=*/false); + void OnArcInstanceUpgraded(base::OnceClosure success_callback, + UpgradeErrorCallback error_callback, + bool result) { + VLOG(1) << "OnArcInstanceUpgraded result=" << result; + if (result) + std::move(success_callback).Run(); + else + std::move(error_callback).Run(/*low_free_disk_space=*/false); } - void OnArcInstanceStopped() { + void OnArcInstanceStopped(bool result) { + VLOG(1) << "OnArcInstanceStopped result=" << result; + if (!result) + LOG(WARNING) << "Failed to stop arcvm. Instance not running?"; for (auto& observer : observer_list_) - observer.ArcInstanceStopped(kDummyReason, kDummyInstanceId); + observer.ArcInstanceStopped(kDummyReason, current_instance_id_); + if (result) + current_instance_id_.clear(); } + // A unique ID associated with the current Upstart job. + std::string current_instance_id_; + // For callbacks. base::WeakPtrFactory<ArcVmClientAdapter> weak_factory_;
diff --git a/components/arc/clipboard/arc_clipboard_bridge.cc b/components/arc/clipboard/arc_clipboard_bridge.cc index 721b3aaf..6e6faab 100644 --- a/components/arc/clipboard/arc_clipboard_bridge.cc +++ b/components/arc/clipboard/arc_clipboard_bridge.cc
@@ -20,12 +20,6 @@ namespace arc { namespace { -// Payload in an Android Binder Parcel should be less than 800 Kb. Save 512 -// bytes for headers, descriptions and mime types. -constexpr size_t kMaxBinderParcelSizeInBytes = 800 * 1024 - 512; -constexpr char kMimeTypeTextError[] = "text/error"; -constexpr char kErrorSizeTooBigForBinder[] = "size too big for binder"; - // Singleton factory for ArcClipboardBridge. class ArcClipboardBridgeFactory : public internal::ArcBrowserContextKeyedServiceFactoryBase< @@ -127,43 +121,6 @@ writer->WriteText(base::UTF8ToUTF16(repr->value->get_text())); } -bool DoesClipFitIntoInstance(const mojom::ClipDataPtr& clip_data) { - // Checks whether the ClipData will fit at Instance's Binder.Parcel. - // (See: android.os.Binder.java # checkParcel() for details). - // - // It calculates an upper-bound limit by multiplying UTF8 strings' size by 2. - // - // A precise check could be done at Instance, but it will require: - // 1: Sending the Clip via Mojo to Instance (memory * 2 + time O(memory)) - // 2: Converting the char* (UTF8) to Java UTF16 Strings (memory * 2 again + - // time O(memory)) - // 3: Creating a temp Parcel with the clip data (memory * 2 again + - // time O(memory)) - // - // An estimate (non-precise) check could be done at Instance as well, but will - // require at least steps 1 and 2. - // - // A simple screenshot + copy to clipboard at Host could take about 4Mb, since - // it is encoded in an HTML <IMG> tag. - // - // The purpose of this hack, is to avoid sending and converting this 4Mb - // several times. - - // TODO(ricardoq): Instead of doing UTF8.size() * 2, get the real size from - // the unconverted UTF16 string. - - size_t size_at_instance_in_bytes = 0; - for (const auto& repr : clip_data->representations) { - if (repr->value->is_text()) - size_at_instance_in_bytes += - repr->value->get_text().size() * sizeof(base::string16::value_type); - else - size_at_instance_in_bytes += repr->value->get_blob().size(); - } - - return size_at_instance_in_bytes < kMaxBinderParcelSizeInBytes; -} - } // namespace // static @@ -234,21 +191,4 @@ std::move(callback).Run(std::move(clip_data)); } -void ArcClipboardBridge::GetClipContentDeprecated( - GetClipContentCallback callback) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); - mojom::ClipDataPtr clip_data = GetClipData(clipboard); - - // Old version of ClipboardInstance can't handle a ClipData larger than 800K. - if (!DoesClipFitIntoInstance(clip_data)) { - clip_data->representations.clear(); - clip_data->representations.push_back(mojom::ClipRepresentation::New( - kMimeTypeTextError, - mojom::ClipValue::NewText(kErrorSizeTooBigForBinder))); - } - std::move(callback).Run(std::move(clip_data)); -} - } // namespace arc
diff --git a/components/arc/clipboard/arc_clipboard_bridge.h b/components/arc/clipboard/arc_clipboard_bridge.h index c8136040..0e26b27 100644 --- a/components/arc/clipboard/arc_clipboard_bridge.h +++ b/components/arc/clipboard/arc_clipboard_bridge.h
@@ -40,7 +40,6 @@ // mojom::ClipboardHost overrides. void SetClipContent(mojom::ClipDataPtr clip_data) override; void GetClipContent(GetClipContentCallback callback) override; - void GetClipContentDeprecated(GetClipContentCallback callback) override; private: ArcBridgeService* const arc_bridge_service_; // Owned by ArcServiceManager.
diff --git a/components/arc/common/clipboard.mojom b/components/arc/common/clipboard.mojom index 566c7deb..11ea946 100644 --- a/components/arc/common/clipboard.mojom +++ b/components/arc/common/clipboard.mojom
@@ -43,10 +43,6 @@ // initiates a 'copy' action. [MinVersion=1] SetClipContent@2(ClipData data); - // DEPRECATED: Please use GetClipContent@4 instead. Clean up after Aug 1 2018. - // This version of ClipboardInstance can't handle a ClipData larger than 800K. - [MinVersion=1] GetClipContentDeprecated@3() => (ClipData data); - // Tells the host to return its clipboard content, usually when the user // initiates a 'paste' action or when the instance needs to re-sync its // clipboard content with the host.
diff --git a/components/assist_ranker/BUILD.gn b/components/assist_ranker/BUILD.gn index f41a45f..c77850f 100644 --- a/components/assist_ranker/BUILD.gn +++ b/components/assist_ranker/BUILD.gn
@@ -17,6 +17,8 @@ "fake_ranker_model_loader.h", "generic_logistic_regression_inference.cc", "generic_logistic_regression_inference.h", + "nn_classifier.cc", + "nn_classifier.h", "predictor_config.cc", "predictor_config.h", "predictor_config_definitions.cc", @@ -54,6 +56,9 @@ "binary_classifier_predictor_unittest.cc", "example_preprocessing_unittest.cc", "generic_logistic_regression_inference_unittest.cc", + "nn_classifier_test_util.cc", + "nn_classifier_test_util.h", + "nn_classifier_unittest.cc", "ranker_example_util_unittest.cc", "ranker_model_loader_impl_unittest.cc", "ranker_model_unittest.cc",
diff --git a/components/assist_ranker/nn_classifier.cc b/components/assist_ranker/nn_classifier.cc new file mode 100644 index 0000000..cd58a0f --- /dev/null +++ b/components/assist_ranker/nn_classifier.cc
@@ -0,0 +1,95 @@ +// Copyright (c) 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 "components/assist_ranker/nn_classifier.h" + +#include "base/logging.h" +#include "components/assist_ranker/proto/nn_classifier.pb.h" + +namespace assist_ranker { +namespace nn_classifier { +namespace { + +using google::protobuf::RepeatedPtrField; +using std::vector; + +vector<float> FeedForward(const NNLayer& layer, const vector<float>& input) { + const RepeatedPtrField<FloatVector>& weights = layer.weights(); + const FloatVector& biases = layer.biases(); + + // Number of nodes in the layer. + const int num_nodes = biases.values().size(); + // Number of values in the input. + const int num_input = input.size(); + DCHECK_EQ(weights.size(), num_input); + + // Initialize with the bias. + vector<float> output(biases.values().begin(), biases.values().end()); + + // For each value in the input. + for (int j = 0; j < num_input; ++j) { + const FloatVector& v = weights[j]; + DCHECK_EQ(v.values().size(), num_nodes); + + // For each node in the layer. + for (int i = 0; i < num_nodes; ++i) { + output[i] += v.values(i) * input[j]; + } + } + return output; +} + +// Apply ReLU activation function to a vector, which sets all values to +// max(0, value). +void Relu(vector<float>* const v) { + // We are modifying the vector so the iterator must be a reference. + for (float& i : *v) + if (i < 0.0f) + i = 0.0f; +} + +bool ValidateLayer(const NNLayer& layer) { + // Number of nodes in the layer (must be non-zero). + const int num_nodes = layer.biases().values().size(); + if (num_nodes == 0) + return false; + + // Number of values in the input (must be non-zero). + const int num_input = layer.weights().size(); + if (num_input == 0) + return false; + + for (int j = 0; j < num_input; ++j) { + // The size of each weight vector must be the number of nodes in the + // layer. + if (layer.weights(j).values().size() != num_nodes) + return false; + } + + return true; +} + +} // namespace + +bool Validate(const NNClassifierModel& model) { + // Check the size of the output from the hidden layer is equal to the size + // of the input in the logits layer. + if (model.hidden_layer().biases().values().size() != + model.logits_layer().weights().size()) { + return false; + } + + return ValidateLayer(model.hidden_layer()) && + ValidateLayer(model.logits_layer()); +} + +vector<float> Inference(const NNClassifierModel& model, + const vector<float>& input) { + vector<float> v = FeedForward(model.hidden_layer(), input); + Relu(&v); + // Feed forward the logits layer. + return FeedForward(model.logits_layer(), v); +} + +} // namespace nn_classifier +} // namespace assist_ranker
diff --git a/components/assist_ranker/nn_classifier.h b/components/assist_ranker/nn_classifier.h new file mode 100644 index 0000000..d5d7efec --- /dev/null +++ b/components/assist_ranker/nn_classifier.h
@@ -0,0 +1,31 @@ +// Copyright (c) 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 COMPONENTS_ASSIST_RANKER_NN_CLASSIFIER_H_ +#define COMPONENTS_ASSIST_RANKER_NN_CLASSIFIER_H_ + +#include <vector> + +#include "components/assist_ranker/proto/nn_classifier.pb.h" + +namespace assist_ranker { +namespace nn_classifier { + +// Implements inference for a neural network model trained using +// tf.contrib.learn.DNNClassifier. The network has a single hidden layer +// with tf.nn.relu as the activation function. The output logits layer has no +// activation function. +// +// Returns a vector of scores for each class in the range -INF to +INF. +std::vector<float> Inference(const NNClassifierModel& model, + const std::vector<float>& input); + +// Validates that the dimensions of the biases and weights in an +// NNClassifierModel are valid. Returns true if the model is valid, false +// otherwise. +bool Validate(const NNClassifierModel& model); + +} // namespace nn_classifier +} // namespace assist_ranker + +#endif // COMPONENTS_ASSIST_RANKER_NN_CLASSIFIER_H_
diff --git a/components/assist_ranker/nn_classifier_test_util.cc b/components/assist_ranker/nn_classifier_test_util.cc new file mode 100644 index 0000000..27f227e --- /dev/null +++ b/components/assist_ranker/nn_classifier_test_util.cc
@@ -0,0 +1,55 @@ +// Copyright (c) 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 "components/assist_ranker/nn_classifier_test_util.h" + +#include "components/assist_ranker/nn_classifier.h" + +namespace assist_ranker { +namespace nn_classifier { +namespace { + +using ::google::protobuf::RepeatedFieldBackInserter; +using ::std::copy; +using ::std::vector; + +void CreateLayer(const vector<float>& biases, + const vector<vector<float>>& weights, + NNLayer* layer) { + copy(biases.begin(), biases.end(), + RepeatedFieldBackInserter(layer->mutable_biases()->mutable_values())); + + for (const auto& w : weights) { + auto* p = layer->add_weights(); + copy(w.begin(), w.end(), RepeatedFieldBackInserter(p->mutable_values())); + } +} + +} // namespace + +NNClassifierModel CreateModel(const vector<float>& hidden_biases, + const vector<vector<float>>& hidden_weights, + const vector<float>& logits_biases, + const vector<vector<float>>& logits_weights) { + NNClassifierModel model; + CreateLayer(hidden_biases, hidden_weights, model.mutable_hidden_layer()); + CreateLayer(logits_biases, logits_weights, model.mutable_logits_layer()); + return model; +} + +bool CheckInference(const NNClassifierModel& model, + const vector<float>& input, + const vector<float>& expected_scores) { + const vector<float> scores = Inference(model, input); + if (scores.size() != expected_scores.size()) + return false; + for (size_t i = 0; i < scores.size(); ++i) { + if (abs(scores[i] - expected_scores[i]) > 1e-05) + return false; + } + + return true; +} + +} // namespace nn_classifier +} // namespace assist_ranker
diff --git a/components/assist_ranker/nn_classifier_test_util.h b/components/assist_ranker/nn_classifier_test_util.h new file mode 100644 index 0000000..730d273 --- /dev/null +++ b/components/assist_ranker/nn_classifier_test_util.h
@@ -0,0 +1,31 @@ +// Copyright (c) 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 COMPONENTS_ASSIST_RANKER_NN_CLASSIFIER_TEST_UTIL_H_ +#define COMPONENTS_ASSIST_RANKER_NN_CLASSIFIER_TEST_UTIL_H_ + +#include <vector> + +#include "components/assist_ranker/proto/nn_classifier.pb.h" + +namespace assist_ranker { +namespace nn_classifier { + +// Creates a NNClassifierModel proto using a specified set of biases and +// weights. +NNClassifierModel CreateModel( + const std::vector<float>& hidden_biases, + const std::vector<std::vector<float>>& hidden_weights, + const std::vector<float>& logits_biases, + const std::vector<std::vector<float>>& logits_weights); + +// Performs inference on the input vector using the specified model, and +// checks that the expected scores are output. +bool CheckInference(const NNClassifierModel& model, + const std::vector<float>& input, + const std::vector<float>& expected_scores); + +} // namespace nn_classifier +} // namespace assist_ranker + +#endif // COMPONENTS_ASSIST_RANKER_NN_CLASSIFIER_TEST_UTIL_H_
diff --git a/components/assist_ranker/nn_classifier_unittest.cc b/components/assist_ranker/nn_classifier_unittest.cc new file mode 100644 index 0000000..fb51d1e --- /dev/null +++ b/components/assist_ranker/nn_classifier_unittest.cc
@@ -0,0 +1,66 @@ +// Copyright (c) 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 "components/assist_ranker/nn_classifier.h" +#include "base/logging.h" +#include "components/assist_ranker/nn_classifier_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace assist_ranker { +namespace nn_classifier { +namespace { + +using ::google::protobuf::RepeatedFieldBackInserter; +using ::std::copy; +using ::std::vector; + +TEST(NNClassifierTest, XorTest) { + // Creates a NN with a single hidden layer of 5 units that solves XOR. + // Creates a DNNClassifier model containing the trained biases and weights. + const NNClassifierModel model = CreateModel( + // Hidden biases. + {{-0.45737201, 0.2009858, 1.02393341, -1.72199488, -0.54427308}}, + // Hidden weights. + {{2.21626472, -0.08185583, -0.7542417, 1.97279537, 0.62363654}, + {-1.71283901, 2.0275352, -1.14731216, 1.56915629, 0.49627137}}, + // Logits biases. + {-1.27781141}, + // Logits weights. + {{2.8636384}, {1.84202337}, {-1.76555872}, {-2.96390629}, {-1.00649774}}); + + ASSERT_TRUE(Validate(model)); + EXPECT_TRUE(CheckInference(model, {0, 0}, {-2.7154054})); + EXPECT_TRUE(CheckInference(model, {0, 1}, {2.8271765})); + EXPECT_TRUE(CheckInference(model, {1, 0}, {2.6790769})); + EXPECT_TRUE(CheckInference(model, {1, 1}, {-3.1652793})); +} + +TEST(NNClassifierTest, ValidateNNClassifierModel) { + // Empty model. + NNClassifierModel model; + EXPECT_FALSE(Validate(model)); + + // Valid model. + model = CreateModel({0, 0, 0}, {{0, 0, 0}, {0, 0, 0}}, {0}, {{0}, {0}, {0}}); + EXPECT_TRUE(Validate(model)); + + // Too few hidden layer biases. + model = CreateModel({0, 0}, {{0, 0, 0}, {0, 0, 0}}, {0}, {{0}, {0}, {0}}); + EXPECT_FALSE(Validate(model)); + + // Too few hidden layer weights. + model = CreateModel({0, 0, 0}, {{0, 0, 0}, {0, 0}}, {0}, {{0}, {0}, {0}}); + EXPECT_FALSE(Validate(model)); + + // Too few logits weights. + model = CreateModel({0, 0, 0}, {{0, 0, 0}, {0, 0, 0}}, {0}, {{0}, {0}}); + EXPECT_FALSE(Validate(model)); + + // Logits biases empty. + model = CreateModel({0, 0, 0}, {{0, 0, 0}, {0, 0, 0}}, {}, {{0}, {0}, {0}}); + EXPECT_FALSE(Validate(model)); +} + +} // namespace +} // namespace nn_classifier +} // namespace assist_ranker
diff --git a/components/assist_ranker/proto/BUILD.gn b/components/assist_ranker/proto/BUILD.gn index 7955a34..cb5b022 100644 --- a/components/assist_ranker/proto/BUILD.gn +++ b/components/assist_ranker/proto/BUILD.gn
@@ -8,6 +8,7 @@ sources = [ "example_preprocessor.proto", "generic_logistic_regression_model.proto", + "nn_classifier.proto", "ranker_example.proto", "ranker_model.proto", "translate_ranker_model.proto",
diff --git a/components/assist_ranker/proto/nn_classifier.proto b/components/assist_ranker/proto/nn_classifier.proto new file mode 100644 index 0000000..9c7421d9 --- /dev/null +++ b/components/assist_ranker/proto/nn_classifier.proto
@@ -0,0 +1,33 @@ +// Copyright (c) 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. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +package assist_ranker; + +// A vector of floating-point values. +message FloatVector { + repeated float values = 1; +} + +// The weights and biases for a single neural-network layer. +message NNLayer { + // The weights for the layer. + repeated FloatVector weights = 1; + + // The bias vectors for the layer. + optional FloatVector biases = 2; +} + +// Defines the model weights and biases for a neural network with a single +// hidden layer. +message NNClassifierModel { + // The single hidden layer. + optional NNLayer hidden_layer = 1; + + // The output logits layer. + optional NNLayer logits_layer = 2; +}
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc index 1e38342..bf3c410 100644 --- a/components/autofill/content/renderer/password_autofill_agent.cc +++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -15,7 +15,6 @@ #include "base/bind.h" #include "base/containers/flat_set.h" #include "base/i18n/case_conversion.h" -#include "base/memory/linked_ptr.h" #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" #include "base/strings/string_number_conversions.h"
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 3e8e313..5d4a8b08 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -176,6 +176,7 @@ "suggestion.h", "suggestion_selection.cc", "suggestion_selection.h", + "sync_utils.h", "ui/card_unmask_prompt_controller.h", "ui/card_unmask_prompt_controller_impl.cc", "ui/card_unmask_prompt_controller_impl.h",
diff --git a/components/autofill/core/browser/autofill_client.cc b/components/autofill/core/browser/autofill_client.cc index 5a53ca8..c77c9b4e 100644 --- a/components/autofill/core/browser/autofill_client.cc +++ b/components/autofill/core/browser/autofill_client.cc
@@ -12,4 +12,8 @@ return version_info::Channel::UNKNOWN; } +std::string AutofillClient::GetPageLanguage() const { + return std::string(); +} + } // namespace autofill
diff --git a/components/autofill/core/browser/autofill_client.h b/components/autofill/core/browser/autofill_client.h index 5ea216c..96d577b 100644 --- a/components/autofill/core/browser/autofill_client.h +++ b/components/autofill/core/browser/autofill_client.h
@@ -95,6 +95,17 @@ NETWORK_ERROR, }; + enum SaveCardOfferUserDecision { + // The user accepted credit card save. + ACCEPTED, + + // The user explicitly declined credit card save. + DECLINED, + + // The user ignored the credit card save prompt. + IGNORED, + }; + enum UnmaskCardReason { // The card is being unmasked for PaymentRequest. UNMASK_FOR_PAYMENT_REQUEST, @@ -110,11 +121,22 @@ base::string16 expiration_date_month; base::string16 expiration_date_year; }; + + // Callback to run after local credit card save is offered. Sends whether the + // prompt was accepted, declined, or ignored in |user_decision|. + typedef base::OnceCallback<void(SaveCardOfferUserDecision user_decision)> + LocalSaveCardPromptCallback; + + // Callback to run after upload credit card save is offered. Sends whether the + // prompt was accepted, declined, or ignored in |user_decision|, and + // additional |user_provided_card_details| if applicable. typedef base::OnceCallback<void( + SaveCardOfferUserDecision user_decision, const UserProvidedCardDetails& user_provided_card_details)> - UserAcceptedUploadCallback; + UploadSaveCardPromptCallback; typedef base::Callback<void(const CreditCard&)> CreditCardScanCallback; + // Callback to run if user presses the Save button in the migration dialog. // Will pass a vector of GUIDs of cards that the user selected to upload to // LocalCardMigrationManager. @@ -174,6 +196,9 @@ // context if possible, SECURITY_LEVEL_COUNT otherwise. virtual security_state::SecurityLevel GetSecurityLevelForUmaHistograms() = 0; + // Returns the current best guess as to the page's display language. + virtual std::string GetPageLanguage() const; + // Causes the Autofill settings UI to be shown. If |show_credit_card_settings| // is true, will show the credit card specific subpage. virtual void ShowAutofillSettings(bool show_credit_card_settings) = 0; @@ -213,13 +238,15 @@ virtual void ConfirmSaveAutofillProfile(const AutofillProfile& profile, base::OnceClosure callback) = 0; - // Runs |callback| if the |card| should be imported as personal data. On - // desktop, shows the offer-to-save bubble if |show_prompt| is true; otherwise - // only shows the omnibox icon. On mobile, shows the offer-to-save infobar if - // |show_prompt| is true; otherwise does not offer to save at all. - virtual void ConfirmSaveCreditCardLocally(const CreditCard& card, - bool show_prompt, - base::OnceClosure callback) = 0; + // Runs |callback| once the user makes a decision with respect to the + // offer-to-save prompt. On desktop, shows the offer-to-save bubble if + // |show_prompt| is true; otherwise only shows the omnibox icon. On mobile, + // shows the offer-to-save infobar if |show_prompt| is true; otherwise does + // not offer to save at all. + virtual void ConfirmSaveCreditCardLocally( + const CreditCard& card, + bool show_prompt, + LocalSaveCardPromptCallback callback) = 0; #if defined(OS_ANDROID) // Run |callback| if the card should be uploaded to payments with updated @@ -228,21 +255,21 @@ base::OnceCallback<void(const base::string16&)> callback) = 0; #endif // defined(OS_ANDROID) - // Runs |callback| if the |card| should be uploaded to Payments. Displays the - // contents of |legal_message| to the user. Displays a cardholder name - // textfield in the bubble if |should_request_name_from_user| is true. - // Displays a pair of expiration date dropdowns in the bubble if - // |should_request_expiration_date_from_user| is true. On desktop, - // shows the offer-to-save bubble if |show_prompt| is true; otherwise only - // shows the omnibox icon. On mobile, shows the offer-to-save infobar if - // |show_prompt| is true; otherwise does not offer to save at all. + // Runs |callback| once the user makes a decision with respect to the + // offer-to-save prompt. Displays the contents of |legal_message| to the user. + // Displays a cardholder name textfield in the bubble if + // |should_request_name_from_user| is true. Displays a pair of expiration date + // dropdowns in the bubble if |should_request_expiration_date_from_user| is + // true. On desktop, shows the offer-to-save bubble if |show_prompt| is true; + // otherwise only shows the omnibox icon. On mobile, shows the offer-to-save + // infobar if |show_prompt| is true; otherwise does not offer to save at all. virtual void ConfirmSaveCreditCardToCloud( const CreditCard& card, std::unique_ptr<base::DictionaryValue> legal_message, bool should_request_name_from_user, bool should_request_expiration_date_from_user, bool show_prompt, - UserAcceptedUploadCallback callback) = 0; + UploadSaveCardPromptCallback callback) = 0; // Will show an infobar to get user consent for Credit Card assistive filling. // Will run |callback| on success.
diff --git a/components/autofill/core/browser/autofill_download_manager.cc b/components/autofill/core/browser/autofill_download_manager.cc index 0d85d9a..3a97c36 100644 --- a/components/autofill/core/browser/autofill_download_manager.cc +++ b/components/autofill/core/browser/autofill_download_manager.cc
@@ -527,8 +527,9 @@ AutofillUploadContents upload; if (!form.EncodeUploadRequest(available_field_types, form_was_autofilled, login_form_signature, observed_submission, - &upload)) + &upload)) { return false; + } // Get the POST payload that contains upload data. std::string payload;
diff --git a/components/autofill/core/browser/autofill_download_manager_unittest.cc b/components/autofill/core/browser/autofill_download_manager_unittest.cc index 7ac6b9f5..bdff3be3e 100644 --- a/components/autofill/core/browser/autofill_download_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -1509,6 +1509,7 @@ AutofillDownloadManager download_manager(driver_.get(), this); FormStructure form_structure(form); + form_structure.set_page_language("fr-ca"); for (int i = 0; i < 8; ++i) { SCOPED_TRACE(base::StringPrintf("submission source = %d", i)); @@ -1539,6 +1540,7 @@ ASSERT_EQ(1u, payloads_.size()); AutofillUploadContents upload; ASSERT_TRUE(upload.ParseFromString(payloads_.front())); + EXPECT_EQ(upload.language(), form_structure.page_language()); ASSERT_TRUE(upload.has_randomized_form_metadata()); EXPECT_TRUE(upload.randomized_form_metadata().has_id()); EXPECT_TRUE(upload.randomized_form_metadata().has_name());
diff --git a/components/autofill/core/browser/autofill_experiments.cc b/components/autofill/core/browser/autofill_experiments.cc index 3482820..76816b8 100644 --- a/components/autofill/core/browser/autofill_experiments.cc +++ b/components/autofill/core/browser/autofill_experiments.cc
@@ -86,6 +86,12 @@ // Wallet feature must be on. DCHECK(base::FeatureList::IsEnabled( features::kAutofillEnableAccountWalletStorage)); + if (!base::FeatureList::IsEnabled( + features::kAutofillEnableAccountWalletStorageUpload)) { + // We're not enabling uploads in the account wallet mode, so suppress + // the upload prompt. + return false; + } } // Also don't offer upload for users that have a secondary sync passphrase.
diff --git a/components/autofill/core/browser/autofill_experiments_unittest.cc b/components/autofill/core/browser/autofill_experiments_unittest.cc index 242f2c15..a23650fb 100644 --- a/components/autofill/core/browser/autofill_experiments_unittest.cc +++ b/components/autofill/core/browser/autofill_experiments_unittest.cc
@@ -102,6 +102,20 @@ } TEST_F(AutofillExperimentsTest, + DenyUpload_TransportSyncDoesNotHaveUploadEnabled) { + scoped_feature_list_.InitWithFeatures( + /*enable_features=*/{features::kAutofillUpstream, + features::kAutofillEnableAccountWalletStorage}, + /*disable_features=*/{ + features::kAutofillEnableAccountWalletStorageUpload}); + // When we have no primary account, Sync will start in Transport-only mode + // (if allowed). + sync_service_.SetIsAuthenticatedAccountPrimary(false); + + EXPECT_FALSE(IsCreditCardUploadEnabled()); +} + +TEST_F(AutofillExperimentsTest, AllowUpload_TransportSyncDoesNotHaveAutofillProfileActiveDataType) { scoped_feature_list_.InitWithFeatures( /*enable_features=*/{features::kAutofillUpstream,
diff --git a/components/autofill/core/browser/autofill_external_delegate.cc b/components/autofill/core/browser/autofill_external_delegate.cc index 33184ca3..d7d6788 100644 --- a/components/autofill/core/browser/autofill_external_delegate.cc +++ b/components/autofill/core/browser/autofill_external_delegate.cc
@@ -43,14 +43,7 @@ AutofillExternalDelegate::AutofillExternalDelegate(AutofillManager* manager, AutofillDriver* driver) - : manager_(manager), - driver_(driver), - query_id_(0), - has_autofill_suggestions_(false), - should_show_scan_credit_card_(false), - popup_type_(PopupType::kUnspecified), - should_show_cc_signin_promo_(false), - weak_ptr_factory_(this) { + : manager_(manager), driver_(driver) { DCHECK(manager); } @@ -72,6 +65,8 @@ popup_type_ = manager_->GetPopupType(query_form_, query_field_); should_show_cc_signin_promo_ = manager_->ShouldShowCreditCardSigninPromo(query_form_, query_field_); + should_show_cards_from_account_option_ = + manager_->ShouldShowCardsFromAccountOption(query_form_, query_field_); } void AutofillExternalDelegate::OnSuggestionsReturned( @@ -116,6 +111,13 @@ } } + if (should_show_cards_from_account_option_) { + suggestions.emplace_back( + l10n_util::GetStringUTF16(IDS_AUTOFILL_SHOW_ACCOUNT_CARDS)); + suggestions.back().frontend_id = POPUP_ITEM_ID_SHOW_ACCOUNT_CARDS; + suggestions.back().icon = base::ASCIIToUTF16("google"); + } + if (has_autofill_suggestions_) ApplyAutofillOptions(&suggestions, is_all_server_suggestions); @@ -241,6 +243,8 @@ &AutofillExternalDelegate::OnCreditCardScanned, GetWeakPtr())); } else if (identifier == POPUP_ITEM_ID_CREDIT_CARD_SIGNIN_PROMO) { manager_->client()->ExecuteCommand(identifier); + } else if (identifier == POPUP_ITEM_ID_SHOW_ACCOUNT_CARDS) { + // TODO(crbug.com/905052): Handle this event. } else { if (identifier > 0) // Denotes an Autofill suggestion. AutofillMetrics::LogAutofillSuggestionAcceptedIndex(position);
diff --git a/components/autofill/core/browser/autofill_external_delegate.h b/components/autofill/core/browser/autofill_external_delegate.h index 6441e5bb..a1e71e13 100644 --- a/components/autofill/core/browser/autofill_external_delegate.h +++ b/components/autofill/core/browser/autofill_external_delegate.h
@@ -143,7 +143,7 @@ // The ID of the last request sent for form field Autofill. Used to ignore // out of date responses. - int query_id_; + int query_id_ = 0; // The current form and field selected by Autofill. FormData query_form_; @@ -153,13 +153,15 @@ gfx::RectF element_bounds_; // Does the popup include any Autofill profile or credit card suggestions? - bool has_autofill_suggestions_; + bool has_autofill_suggestions_ = false; - bool should_show_scan_credit_card_; - PopupType popup_type_; + bool should_show_scan_credit_card_ = false; + PopupType popup_type_ = PopupType::kUnspecified; // Whether the credit card signin promo should be shown to the user. - bool should_show_cc_signin_promo_; + bool should_show_cc_signin_promo_ = false; + + bool should_show_cards_from_account_option_ = false; // The current data list values. std::vector<base::string16> data_list_values_; @@ -168,7 +170,7 @@ // If not null then it will be called in destructor. base::OnceClosure deletion_callback_; - base::WeakPtrFactory<AutofillExternalDelegate> weak_ptr_factory_; + base::WeakPtrFactory<AutofillExternalDelegate> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(AutofillExternalDelegate); };
diff --git a/components/autofill/core/browser/autofill_external_delegate_unittest.cc b/components/autofill/core/browser/autofill_external_delegate_unittest.cc index 568e1f2b..c2ad2c8 100644 --- a/components/autofill/core/browser/autofill_external_delegate_unittest.cc +++ b/components/autofill/core/browser/autofill_external_delegate_unittest.cc
@@ -94,9 +94,8 @@ class MockAutofillManager : public AutofillManager { public: MockAutofillManager(AutofillDriver* driver, MockAutofillClient* client) - // Force to use the constructor designated for unit test, but we don't - // really need personal_data in this test so we pass a NULL pointer. - : AutofillManager(driver, client, nullptr) {} + // Force to use the constructor designated for unit test. + : AutofillManager(driver, client, client->GetPersonalDataManager()) {} ~MockAutofillManager() override {} PopupType GetPopupType(const FormData& form, @@ -110,6 +109,15 @@ MOCK_METHOD2(ShouldShowCreditCardSigninPromo, bool(const FormData& form, const FormFieldData& field)); + bool ShouldShowCardsFromAccountOption(const FormData& form, + const FormFieldData& field) { + return should_show_cards_from_account_option_; + } + + void ShowCardsFromAccountOption() { + should_show_cards_from_account_option_ = true; + } + MOCK_METHOD5(FillOrPreviewForm, void(AutofillDriver::RendererFormDataAction action, int query_id, @@ -125,6 +133,7 @@ const base::string16& cvc)); private: + bool should_show_cards_from_account_option_ = false; DISALLOW_COPY_AND_ASSIGN(MockAutofillManager); }; @@ -175,6 +184,17 @@ std::unique_ptr<AutofillExternalDelegate> external_delegate_; }; +// Variant for use in cases when we expect the AutofillManager would normally +// set the |should_show_cards_from_account_option_| bit. +class AutofillExternalDelegateCardsFromAccountTest + : public AutofillExternalDelegateUnitTest { + protected: + void SetUp() override { + AutofillExternalDelegateUnitTest::SetUp(); + autofill_manager_->ShowCardsFromAccountOption(); + } +}; + // Test that our external delegate called the virtual methods at the right time. TEST_F(AutofillExternalDelegateUnitTest, TestExternalDelegateVirtualCalls) { IssueOnQuery(kQueryId); @@ -829,6 +849,47 @@ kQueryId, autofill_item, /*autoselect_first_suggestion=*/false); } +// Tests that the prompt to show account cards shows up when the corresponding +// bit is set, including any suggestions that are passed along and the "Manage" +// row in the footer. +TEST_F(AutofillExternalDelegateCardsFromAccountTest, + ShouldShowCardsFromAccountOptionWithCards) { + IssueOnQuery(kQueryId); + + auto element_values = testing::ElementsAre( + base::string16(), + l10n_util::GetStringUTF16(IDS_AUTOFILL_SHOW_ACCOUNT_CARDS), + l10n_util::GetStringUTF16(IDS_AUTOFILL_MANAGE)); + EXPECT_CALL(autofill_client_, + ShowAutofillPopup(_, _, SuggestionVectorValuesAre(element_values), + false, _)); + + std::vector<Suggestion> autofill_item; + autofill_item.push_back(Suggestion()); + autofill_item[0].frontend_id = kAutofillProfileId; + + external_delegate_->OnSuggestionsReturned( + kQueryId, autofill_item, /*autoselect_first_suggestion=*/false); +} + +// Tests that the prompt to show account cards shows up when the corresponding +// bit is set, even if no suggestions are passed along. The "Manage" row should +// *not* show up in this case. +TEST_F(AutofillExternalDelegateCardsFromAccountTest, + ShouldShowCardsFromAccountOptionWithoutCards) { + IssueOnQuery(kQueryId); + + auto element_values = testing::ElementsAre( + l10n_util::GetStringUTF16(IDS_AUTOFILL_SHOW_ACCOUNT_CARDS)); + EXPECT_CALL(autofill_client_, + ShowAutofillPopup(_, _, SuggestionVectorValuesAre(element_values), + false, _)); + + external_delegate_->OnSuggestionsReturned( + kQueryId, std::vector<Suggestion>(), + /*autoselect_first_suggestion=*/false); +} + #if !defined(OS_ANDROID) // Test that the delegate includes a separator between the content rows and the // footer, if and only if the kAutofillExpandedPopupViews feature is disabled.
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index 80b86875..13e153c4 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc
@@ -301,11 +301,27 @@ return false; } +bool AutofillManager::ShouldShowCardsFromAccountOption( + const FormData& form, + const FormFieldData& field) { + // Check whether we are dealing with a credit card field. + AutofillField* autofill_field = GetAutofillField(form, field); + if (!autofill_field || autofill_field->Type().group() != CREDIT_CARD) + return false; + + if (IsFormNonSecure(form)) + return false; + + return personal_data_->ShouldShowCardsFromAccountOption(); +} + bool AutofillManager::ShouldParseForms(const std::vector<FormData>& forms, const base::TimeTicks timestamp) { bool enabled = IsAutofillEnabled(); + sync_state_ = personal_data_ ? personal_data_->GetSyncSigninState() + : AutofillSyncSigninState::kNumSyncStates; if (!has_logged_autofill_enabled_) { - AutofillMetrics::LogIsAutofillEnabledAtPageLoad(enabled); + AutofillMetrics::LogIsAutofillEnabledAtPageLoad(enabled, sync_state_); has_logged_autofill_enabled_ = true; } @@ -341,10 +357,12 @@ } autocomplete_history_manager_->OnWillSubmitForm(form_for_autocomplete); - if (IsProfileAutofillEnabled()) - address_form_event_logger_->OnWillSubmitForm(); - if (IsCreditCardAutofillEnabled()) - credit_card_form_event_logger_->OnWillSubmitForm(); + if (IsProfileAutofillEnabled()) { + address_form_event_logger_->OnWillSubmitForm(sync_state_); + } + if (IsCreditCardAutofillEnabled()) { + credit_card_form_event_logger_->OnWillSubmitForm(sync_state_); + } submitted_form->set_submission_source(source); MaybeStartVoteUploadProcess(std::move(submitted_form), timestamp, @@ -365,12 +383,14 @@ AutofillMetrics::CardNumberStatus card_number_status = GetCardNumberStatus(credit_card); - if (IsProfileAutofillEnabled()) - address_form_event_logger_->OnFormSubmitted(/*force_logging=*/false, - card_number_status); - if (IsCreditCardAutofillEnabled()) - credit_card_form_event_logger_->OnFormSubmitted(enable_ablation_logging_, - card_number_status); + if (IsProfileAutofillEnabled()) { + address_form_event_logger_->OnFormSubmitted( + /*force_logging=*/false, card_number_status, sync_state_); + } + if (IsCreditCardAutofillEnabled()) { + credit_card_form_event_logger_->OnFormSubmitted( + enable_ablation_logging_, card_number_status, sync_state_); + } if (!submitted_form->IsAutofillable()) return; @@ -417,6 +437,9 @@ for (const CreditCard* card : credit_cards) copied_credit_cards.push_back(*card); + // Annotate the form with the source language of the page. + form_structure->set_page_language(client_->GetPageLanguage()); + // Attach the Randomized Encoder. form_structure->set_randomized_encoder( RandomizedEncoder::Create(client_->GetPrefs())); @@ -633,11 +656,11 @@ masked_card_, AutofillClient::UNMASK_FOR_AUTOFILL, weak_ptr_factory_.GetWeakPtr(), weak_ptr_factory_.GetWeakPtr()); credit_card_form_event_logger_->OnDidSelectMaskedServerCardSuggestion( - form_structure->form_parsed_timestamp()); + form_structure->form_parsed_timestamp(), sync_state_); return; } credit_card_form_event_logger_->OnDidFillSuggestion( - credit_card, *form_structure, *autofill_field); + credit_card, *form_structure, *autofill_field, sync_state_); } FillOrPreviewDataModelForm( @@ -656,8 +679,8 @@ if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field)) return; if (action == AutofillDriver::FORM_DATA_ACTION_FILL) { - address_form_event_logger_->OnDidFillSuggestion(profile, *form_structure, - *autofill_field); + address_form_event_logger_->OnDidFillSuggestion( + profile, *form_structure, *autofill_field, sync_state_); // Set up the information needed for an eventual refill of this form. if (base::FeatureList::IsEnabled(features::kAutofillDynamicForms) && @@ -821,11 +844,11 @@ if (autofill_field->Type().group() == CREDIT_CARD) { credit_card_form_event_logger_->OnDidShowSuggestions( *form_structure, *autofill_field, - form_structure->form_parsed_timestamp()); + form_structure->form_parsed_timestamp(), sync_state_); } else { address_form_event_logger_->OnDidShowSuggestions( *form_structure, *autofill_field, - form_structure->form_parsed_timestamp()); + form_structure->form_parsed_timestamp(), sync_state_); } } @@ -1034,7 +1057,7 @@ &autofill_field)) return; credit_card_form_event_logger_->OnDidFillSuggestion( - masked_card_, *form_structure, *autofill_field); + masked_card_, *form_structure, *autofill_field, sync_state_); FillCreditCardForm(unmasking_query_id_, unmasking_form_, unmasking_field_, card, cvc); masked_card_ = CreditCard(); @@ -1460,7 +1483,7 @@ const FormStructure& form, const FormFieldData& field, const AutofillField& autofill_field) const { - address_form_event_logger_->OnDidPollSuggestions(field); + address_form_event_logger_->OnDidPollSuggestions(field, sync_state_); std::vector<ServerFieldType> field_types(form.field_count()); for (size_t i = 0; i < form.field_count(); ++i) { @@ -1489,7 +1512,7 @@ const FormFieldData& field, const AutofillType& type, bool* is_all_server_suggestions) const { - credit_card_form_event_logger_->OnDidPollSuggestions(field); + credit_card_form_event_logger_->OnDidPollSuggestions(field, sync_state_); // The field value is sanitized before attempting to match it to the user's // data. @@ -1526,6 +1549,9 @@ const base::TimeTicks timestamp) { DCHECK(!form_structures.empty()); + // Record the current sync state to be used for metrics on this page. + sync_state_ = personal_data_->GetSyncSigninState(); + // Setup the url for metrics that we will collect for this form. form_interactions_ukm_logger_->OnFormsParsed(client_->GetUkmSourceId()); @@ -1540,6 +1566,12 @@ std::set<FormType> current_form_types = form_structure->GetFormTypes(); form_types.insert(current_form_types.begin(), current_form_types.end()); + // Annotate the form with the source language of the page. + // TODO(898510): Move this earlier in the form parsing flow. Ideally the + // form structure should be annotated with the page language before the + // heuristics are run. + form_structure->set_page_language(client_->GetPageLanguage()); + // Configure the query encoding for this form and add it to the appropriate // collection of forms: queryable vs non-queryable. form_structure->set_is_rich_query_enabled(is_rich_query_enabled_); @@ -1910,7 +1942,7 @@ if (itr == filling_contexts_map_.end()) return false; - address_form_event_logger_->OnDidSeeFillableDynamicForm(); + address_form_event_logger_->OnDidSeeFillableDynamicForm(sync_state_); FillingContext* filling_context = itr->second.get(); base::TimeTicks now = base::TimeTicks::Now(); @@ -1918,7 +1950,7 @@ if (filling_context->attempted_refill && delta.InMilliseconds() < kLimitBeforeRefillMs) { - address_form_event_logger_->OnSubsequentRefillAttempt(); + address_form_event_logger_->OnSubsequentRefillAttempt(sync_state_); } return !filling_context->attempted_refill && @@ -1932,7 +1964,7 @@ DCHECK(form_structure); - address_form_event_logger_->OnDidRefill(); + address_form_event_logger_->OnDidRefill(sync_state_); auto itr = filling_contexts_map_.find(form_structure->GetIdentifierForRefill()); @@ -1992,10 +2024,10 @@ context->is_filling_credit_card = true; driver()->DidInteractWithCreditCardForm(); credit_card_form_event_logger_->OnDidInteractWithAutofillableForm( - context->form_structure->form_signature()); + context->form_structure->form_signature(), sync_state_); } else { address_form_event_logger_->OnDidInteractWithAutofillableForm( - context->form_structure->form_signature()); + context->form_structure->form_signature(), sync_state_); } }
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h index 0c2cf7fb..f58900aa 100644 --- a/components/autofill/core/browser/autofill_manager.h +++ b/components/autofill/core/browser/autofill_manager.h
@@ -32,6 +32,7 @@ #include "components/autofill/core/browser/payments/full_card_request.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/browser/popup_types.h" +#include "components/autofill/core/browser/sync_utils.h" #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/signatures_util.h" @@ -93,6 +94,9 @@ virtual bool ShouldShowCreditCardSigninPromo(const FormData& form, const FormFieldData& field); + virtual bool ShouldShowCardsFromAccountOption(const FormData& form, + const FormFieldData& field); + // Called from our external delegate so they cannot be private. virtual void FillOrPreviewForm(AutofillDriver::RendererFormDataAction action, int query_id, @@ -589,6 +593,10 @@ // Tracks whether or not rich query encoding is enabled for this client. const bool is_rich_query_enabled_ = false; + // Used to record metrics. This shoulb be set at the beginning of the + // interaction and re-used throughout the context of this manager. + AutofillSyncSigninState sync_state_ = AutofillSyncSigninState::kNumSyncStates; + base::WeakPtrFactory<AutofillManager> weak_ptr_factory_; friend class AutofillManagerTest;
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc index 698fb848..11b3f85 100644 --- a/components/autofill/core/browser/autofill_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -3972,8 +3972,8 @@ // submissions are still received by AutocompleteHistoryManager. TEST_F(AutofillManagerTest, FormSubmittedAutocompleteEnabled) { TestAutofillClient client; - autofill_manager_.reset( - new TestAutofillManager(autofill_driver_.get(), &client, nullptr)); + autofill_manager_.reset(new TestAutofillManager(autofill_driver_.get(), + &client, &personal_data_)); autofill_manager_->SetAutofillEnabled(false); // Set up our form data. @@ -3989,8 +3989,8 @@ // queried. TEST_F(AutofillManagerTest, AutocompleteSuggestions_SomeWhenAutofillDisabled) { TestAutofillClient client; - autofill_manager_.reset( - new TestAutofillManager(autofill_driver_.get(), &client, nullptr)); + autofill_manager_.reset(new TestAutofillManager(autofill_driver_.get(), + &client, &personal_data_)); autofill_manager_->SetAutofillEnabled(false); autofill_manager_->SetExternalDelegate(external_delegate_.get()); @@ -4013,8 +4013,8 @@ TEST_F(AutofillManagerTest, AutocompleteSuggestions_AutofillDisabledAndFieldShouldNotAutocomplete) { TestAutofillClient client; - autofill_manager_.reset( - new TestAutofillManager(autofill_driver_.get(), &client, nullptr)); + autofill_manager_.reset(new TestAutofillManager(autofill_driver_.get(), + &client, &personal_data_)); autofill_manager_->SetAutofillEnabled(false); autofill_manager_->SetExternalDelegate(external_delegate_.get()); @@ -4085,8 +4085,8 @@ TEST_F(AutofillManagerTest, AutocompleteSuggestions_CreditCardNameFieldShouldAutocomplete) { TestAutofillClient client; - autofill_manager_.reset( - new TestAutofillManager(autofill_driver_.get(), &client, nullptr)); + autofill_manager_.reset(new TestAutofillManager(autofill_driver_.get(), + &client, &personal_data_)); autofill_manager_->SetAutofillEnabled(false); autofill_manager_->SetExternalDelegate(external_delegate_.get()); @@ -4111,8 +4111,8 @@ TEST_F(AutofillManagerTest, AutocompleteSuggestions_CreditCardNumberShouldNotAutocomplete) { TestAutofillClient client; - autofill_manager_.reset( - new TestAutofillManager(autofill_driver_.get(), &client, nullptr)); + autofill_manager_.reset(new TestAutofillManager(autofill_driver_.get(), + &client, &personal_data_)); autofill_manager_->SetAutofillEnabled(false); autofill_manager_->SetExternalDelegate(external_delegate_.get()); @@ -4157,8 +4157,8 @@ TEST_F(AutofillManagerTest, AutocompleteOffRespectedForAutocomplete) { TestAutofillClient client; - autofill_manager_.reset( - new TestAutofillManager(autofill_driver_.get(), &client, nullptr)); + autofill_manager_.reset(new TestAutofillManager(autofill_driver_.get(), + &client, &personal_data_)); autofill_manager_->SetAutofillEnabled(false); autofill_manager_->SetExternalDelegate(external_delegate_.get());
diff --git a/components/autofill/core/browser/autofill_metrics.cc b/components/autofill/core/browser/autofill_metrics.cc index ab0b14ac..15bc81d 100644 --- a/components/autofill/core/browser/autofill_metrics.cc +++ b/components/autofill/core/browser/autofill_metrics.cc
@@ -284,6 +284,21 @@ } } +const char* GetSyncStateSuffix(AutofillSyncSigninState sync_state) { + switch (sync_state) { + case AutofillSyncSigninState::kSignedOut: + return ".SignedOut"; + case AutofillSyncSigninState::kSignedIn: + return ".SignedIn"; + case AutofillSyncSigninState::kSignedInAndWalletSyncTransportEnabled: + return ".SignedInAndWalletSyncTransportEnabled"; + case AutofillSyncSigninState::kSignedInAndSyncFeature: + return ".SignedInAndSyncFeature"; + case AutofillSyncSigninState::kNumSyncStates: + return ".Unknown"; + } +} + // Given a set of |possible_types| for a field, select the best type to use as // the "actual" field type when calculating metrics. If the |predicted_type| is // among the |possible_types] then use that as the best type (i.e., the @@ -747,7 +762,8 @@ bool is_requesting_cardholder_name, bool is_requesting_expiration_date, int previous_save_credit_card_prompt_user_decision, - security_state::SecurityLevel security_level) { + security_state::SecurityLevel security_level, + AutofillSyncSigninState sync_state) { DCHECK_LT(metric, NUM_SAVE_CARD_PROMPT_METRICS); std::string destination = is_uploading ? ".Upload" : ".Local"; std::string show = is_reshow ? ".Reshows" : ".FirstShow"; @@ -755,6 +771,9 @@ "Autofill.SaveCreditCardPrompt" + destination + show; base::UmaHistogramEnumeration(metric_with_destination_and_show, metric, NUM_SAVE_CARD_PROMPT_METRICS); + base::UmaHistogramEnumeration( + metric_with_destination_and_show + GetSyncStateSuffix(sync_state), metric, + NUM_SAVE_CARD_PROMPT_METRICS); if (is_requesting_cardholder_name) { base::UmaHistogramEnumeration( metric_with_destination_and_show + ".RequestingCardholderName", metric, @@ -1236,8 +1255,12 @@ } // static -void AutofillMetrics::LogIsAutofillEnabledAtPageLoad(bool enabled) { - UMA_HISTOGRAM_BOOLEAN("Autofill.IsEnabled.PageLoad", enabled); +void AutofillMetrics::LogIsAutofillEnabledAtPageLoad( + bool enabled, + AutofillSyncSigninState sync_state) { + std::string name("Autofill.IsEnabled.PageLoad"); + UMA_HISTOGRAM_BOOLEAN(name, enabled); + base::UmaHistogramBoolean(name + GetSyncStateSuffix(sync_state), enabled); } // static @@ -1671,7 +1694,9 @@ form_interactions_ukm_logger_(form_interactions_ukm_logger) {} void AutofillMetrics::FormEventLogger::OnDidInteractWithAutofillableForm( - FormSignature form_signature) { + FormSignature form_signature, + AutofillSyncSigninState sync_state) { + sync_state_ = sync_state; if (!has_logged_interacted_) { has_logged_interacted_ = true; form_interactions_ukm_logger_->LogInteractedWithForm( @@ -1682,7 +1707,9 @@ } void AutofillMetrics::FormEventLogger::OnDidPollSuggestions( - const FormFieldData& field) { + const FormFieldData& field, + AutofillSyncSigninState sync_state) { + sync_state_ = sync_state; // Record only one poll user action for consecutive polls of the same field. // This is to avoid recording too many poll actions (for example when a user // types in a field, triggering multiple queries) to make the analysis more @@ -1703,7 +1730,9 @@ void AutofillMetrics::FormEventLogger::OnDidShowSuggestions( const FormStructure& form, const AutofillField& field, - const base::TimeTicks& form_parsed_timestamp) { + const base::TimeTicks& form_parsed_timestamp, + AutofillSyncSigninState sync_state) { + sync_state_ = sync_state; form_interactions_ukm_logger_->LogSuggestionsShown( form, field, form_parsed_timestamp); @@ -1727,7 +1756,9 @@ } void AutofillMetrics::FormEventLogger::OnDidSelectMaskedServerCardSuggestion( - const base::TimeTicks& form_parsed_timestamp) { + const base::TimeTicks& form_parsed_timestamp, + AutofillSyncSigninState sync_state) { + sync_state_ = sync_state; DCHECK(is_for_credit_card_); form_interactions_ukm_logger_->LogSelectedMaskedServerCard( form_parsed_timestamp); @@ -1743,7 +1774,9 @@ void AutofillMetrics::FormEventLogger::OnDidFillSuggestion( const CreditCard& credit_card, const FormStructure& form, - const AutofillField& field) { + const AutofillField& field, + AutofillSyncSigninState sync_state) { + sync_state_ = sync_state; DCHECK(is_for_credit_card_); form_interactions_ukm_logger_->LogDidFillSuggestion( static_cast<int>(credit_card.record_type()), @@ -1788,7 +1821,9 @@ void AutofillMetrics::FormEventLogger::OnDidFillSuggestion( const AutofillProfile& profile, const FormStructure& form, - const AutofillField& field) { + const AutofillField& field, + AutofillSyncSigninState sync_state) { + sync_state_ = sync_state; DCHECK(!is_for_credit_card_); form_interactions_ukm_logger_->LogDidFillSuggestion( static_cast<int>(profile.record_type()), @@ -1812,7 +1847,9 @@ base::UserMetricsAction("Autofill_FilledProfileSuggestion")); } -void AutofillMetrics::FormEventLogger::OnWillSubmitForm() { +void AutofillMetrics::FormEventLogger::OnWillSubmitForm( + AutofillSyncSigninState sync_state) { + sync_state_ = sync_state; // Not logging this kind of form if we haven't logged a user interaction. if (!has_logged_interacted_) return; @@ -1842,7 +1879,9 @@ void AutofillMetrics::FormEventLogger::OnFormSubmitted( bool force_logging, - CardNumberStatus card_number_status) { + CardNumberStatus card_number_status, + AutofillSyncSigninState sync_state) { + sync_state_ = sync_state; // Not logging this kind of form if we haven't logged a user interaction. if (!has_logged_interacted_) return; @@ -1875,15 +1914,21 @@ has_logged_bank_name_available_ = true; } -void AutofillMetrics::FormEventLogger::OnDidSeeFillableDynamicForm() { +void AutofillMetrics::FormEventLogger::OnDidSeeFillableDynamicForm( + AutofillSyncSigninState sync_state) { + sync_state_ = sync_state; Log(AutofillMetrics::FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM); } -void AutofillMetrics::FormEventLogger::OnDidRefill() { +void AutofillMetrics::FormEventLogger::OnDidRefill( + AutofillSyncSigninState sync_state) { + sync_state_ = sync_state; Log(AutofillMetrics::FORM_EVENT_DID_DYNAMIC_REFILL); } -void AutofillMetrics::FormEventLogger::OnSubsequentRefillAttempt() { +void AutofillMetrics::FormEventLogger::OnSubsequentRefillAttempt( + AutofillSyncSigninState sync_state) { + sync_state_ = sync_state; Log(AutofillMetrics::FORM_EVENT_DYNAMIC_CHANGE_AFTER_REFILL); } @@ -1920,6 +1965,8 @@ else name += ".WithBothServerAndLocalData"; base::UmaHistogramEnumeration(name, event, NUM_FORM_EVENTS); + base::UmaHistogramEnumeration(name + GetSyncStateSuffix(sync_state_), event, + NUM_FORM_EVENTS); } void AutofillMetrics::FormEventLogger::Log(
diff --git a/components/autofill/core/browser/autofill_metrics.h b/components/autofill/core/browser/autofill_metrics.h index b9a9c2a..465724c7 100644 --- a/components/autofill/core/browser/autofill_metrics.h +++ b/components/autofill/core/browser/autofill_metrics.h
@@ -18,6 +18,7 @@ #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/form_types.h" +#include "components/autofill/core/browser/sync_utils.h" #include "components/autofill/core/common/form_field_data.h" #include "components/autofill/core/common/signatures_util.h" #include "components/security_state/core/security_state.h" @@ -953,7 +954,8 @@ bool is_requesting_cardholder_name, bool is_requesting_expiration_date_from_user, int previous_save_credit_card_prompt_user_decision, - security_state::SecurityLevel security_level); + security_state::SecurityLevel security_level, + AutofillSyncSigninState sync_state); static void LogSaveCardPromptMetricBySecurityLevel( SaveCardPromptMetric metric, bool is_uploading, @@ -1071,7 +1073,9 @@ const base::TimeDelta& duration); // This should be called each time a page containing forms is loaded. - static void LogIsAutofillEnabledAtPageLoad(bool enabled); + static void LogIsAutofillEnabledAtPageLoad( + bool enabled, + AutofillSyncSigninState sync_state); // This should be called each time a new chrome profile is launched. static void LogIsAutofillEnabledAtStartup(bool enabled); @@ -1262,39 +1266,46 @@ is_context_secure_ = is_context_secure; } - void OnDidInteractWithAutofillableForm(FormSignature form_signature); + void OnDidInteractWithAutofillableForm(FormSignature form_signature, + AutofillSyncSigninState sync_state); - void OnDidPollSuggestions(const FormFieldData& field); + void OnDidPollSuggestions(const FormFieldData& field, + AutofillSyncSigninState sync_state); void OnDidShowSuggestions(const FormStructure& form, const AutofillField& field, - const base::TimeTicks& form_parsed_timestamp); + const base::TimeTicks& form_parsed_timestamp, + AutofillSyncSigninState sync_state); void OnDidSelectMaskedServerCardSuggestion( - const base::TimeTicks& form_parsed_timestamp); + const base::TimeTicks& form_parsed_timestamp, + AutofillSyncSigninState sync_state); // In case of masked cards, caller must make sure this gets called before // the card is upgraded to a full card. void OnDidFillSuggestion(const CreditCard& credit_card, const FormStructure& form, - const AutofillField& field); + const AutofillField& field, + AutofillSyncSigninState sync_state); void OnDidFillSuggestion(const AutofillProfile& profile, const FormStructure& form, - const AutofillField& field); + const AutofillField& field, + AutofillSyncSigninState sync_state); - void OnWillSubmitForm(); + void OnWillSubmitForm(AutofillSyncSigninState sync_state); void OnFormSubmitted(bool force_logging, - const CardNumberStatus card_number_status); + const CardNumberStatus card_number_status, + AutofillSyncSigninState sync_state); void SetBankNameAvailable(); - void OnDidSeeFillableDynamicForm(); + void OnDidSeeFillableDynamicForm(AutofillSyncSigninState sync_state); - void OnDidRefill(); + void OnDidRefill(AutofillSyncSigninState sync_state); - void OnSubsequentRefillAttempt(); + void OnSubsequentRefillAttempt(AutofillSyncSigninState sync_state); private: void Log(FormEvent event) const; @@ -1320,6 +1331,9 @@ FormInteractionsUkmLogger* form_interactions_ukm_logger_; // Weak reference. + + AutofillSyncSigninState sync_state_ = + AutofillSyncSigninState::kNumSyncStates; }; private:
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc index 5beec9b..e14e25e5 100644 --- a/components/autofill/core/browser/autofill_metrics_unittest.cc +++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -25,6 +25,7 @@ #include "components/autofill/core/browser/payments/test_payments_client.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/browser/popup_item_ids.h" +#include "components/autofill/core/browser/sync_utils.h" #include "components/autofill/core/browser/test_autofill_client.h" #include "components/autofill/core/browser/test_autofill_driver.h" #include "components/autofill/core/browser/test_autofill_manager.h" @@ -52,6 +53,7 @@ using autofill::features::kAutofillEnforceMinRequiredFieldsForHeuristics; using autofill::features::kAutofillEnforceMinRequiredFieldsForQuery; using autofill::features::kAutofillEnforceMinRequiredFieldsForUpload; +using SyncSigninState = autofill::AutofillSyncSigninState; using base::ASCIIToUTF16; using base::Bucket; using base::TimeTicks; @@ -8089,7 +8091,7 @@ /*is_requesting_cardholder_name=*/false, /*is_requesting_expiration_date=*/false, /*previous_save_credit_card_prompt_user_decision=*/1, - security_state::SecurityLevel::EV_SECURE); + security_state::SecurityLevel::EV_SECURE, SyncSigninState::kSignedOut); histogram_tester.ExpectBucketCount( "Autofill.SaveCreditCardPrompt.Upload.EV_SECURE", AutofillMetrics::SAVE_CARD_PROMPT_END_NAVIGATION_SHOWING, 1); @@ -8102,7 +8104,7 @@ /*is_reshow=*/true, /*is_requesting_cardholder_name=*/false, /*is_requesting_expiration_date=*/false, /*previous_save_credit_card_prompt_user_decision=*/0, - security_state::SecurityLevel::SECURE); + security_state::SecurityLevel::SECURE, SyncSigninState::kSignedOut); histogram_tester.ExpectBucketCount( "Autofill.SaveCreditCardPrompt.Local.SECURE", AutofillMetrics::SAVE_CARD_PROMPT_SHOWN, 1); @@ -8141,4 +8143,83 @@ /*expected_count=*/1); } +// Verify that we correctly log FormEvent metrics with the appropriate sync +// state. +TEST_F(AutofillMetricsTest, FormEventMetrics_BySyncState) { + { + base::HistogramTester histogram_tester; + AutofillMetrics::FormEventLogger logger( + /*is_for_credit_card=*/true, /*is_in_main_frame=*/false, + /*form_interactions_ukm_logger=*/nullptr); + logger.OnDidSeeFillableDynamicForm(AutofillSyncSigninState::kSignedOut); + histogram_tester.ExpectBucketCount( + "Autofill.FormEvents.CreditCard.WithNoData.SignedOut", + AutofillMetrics::FORM_EVENT_DID_SEE_FILLABLE_DYNAMIC_FORM, 1); + } + { + base::HistogramTester histogram_tester; + AutofillMetrics::FormEventLogger logger( + /*is_for_credit_card=*/false, /*is_in_main_frame=*/true, + /*form_interactions_ukm_logger=*/nullptr); + logger.OnDidRefill(AutofillSyncSigninState::kSignedIn); + histogram_tester.ExpectBucketCount( + "Autofill.FormEvents.Address.WithNoData.SignedIn", + AutofillMetrics::FORM_EVENT_DID_DYNAMIC_REFILL, 1); + } +} + +// Verify that we correctly log the IsEnabled metrics with the appropriate sync +// state. +TEST_F(AutofillMetricsTest, LogIsAutofillEnabledAtPageLoad_BySyncState) { + { + base::HistogramTester histogram_tester; + AutofillMetrics::LogIsAutofillEnabledAtPageLoad(/*enabled=*/true, + SyncSigninState::kSignedIn); + histogram_tester.ExpectBucketCount("Autofill.IsEnabled.PageLoad.SignedIn", + true, 1); + // Make sure the metric without the sync state is still recorded. + histogram_tester.ExpectBucketCount("Autofill.IsEnabled.PageLoad", true, 1); + } + { + base::HistogramTester histogram_tester; + AutofillMetrics::LogIsAutofillEnabledAtPageLoad( + /*enabled=*/false, SyncSigninState::kSignedOut); + histogram_tester.ExpectBucketCount("Autofill.IsEnabled.PageLoad.SignedOut", + false, 1); + // Make sure the metric without the sync state is still recorded. + histogram_tester.ExpectBucketCount("Autofill.IsEnabled.PageLoad", false, 1); + } +} + +// Verify that we correctly log FormEvent metrics with the appropriate sync +// state. +TEST_F(AutofillMetricsTest, LogSaveCardPromptMetric_BySyncState) { + { + base::HistogramTester histogram_tester; + AutofillMetrics::LogSaveCardPromptMetric( + AutofillMetrics::SAVE_CARD_PROMPT_END_NAVIGATION_SHOWING, + /*is_uploading=*/true, /*is_reshow=*/false, + /*is_requesting_cardholder_name=*/false, + /*is_requesting_expiration_date_from_user=*/false, + /*previous_save_credit_card_prompt_user_decision=*/1, + security_state::SecurityLevel::EV_SECURE, SyncSigninState::kSignedIn); + histogram_tester.ExpectBucketCount( + "Autofill.SaveCreditCardPrompt.Upload.FirstShow.SignedIn", + AutofillMetrics::SAVE_CARD_PROMPT_END_NAVIGATION_SHOWING, 1); + } + { + base::HistogramTester histogram_tester; + AutofillMetrics::LogSaveCardPromptMetric( + AutofillMetrics::SAVE_CARD_PROMPT_SHOWN, /*is_uploading=*/false, + /*is_reshow=*/true, /*is_requesting_cardholder_name=*/false, + /*is_requesting_expiration_date_from_user=*/false, + /*previous_save_credit_card_prompt_user_decision=*/0, + security_state::SecurityLevel::SECURE, + SyncSigninState::kSignedInAndSyncFeature); + histogram_tester.ExpectBucketCount( + "Autofill.SaveCreditCardPrompt.Local.Reshows.SignedInAndSyncFeature", + AutofillMetrics::SAVE_CARD_PROMPT_SHOWN, 1); + } +} + } // namespace autofill
diff --git a/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc b/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc index 6ce986b..1a9d6f2 100644 --- a/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc +++ b/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc
@@ -11,7 +11,6 @@ #include "base/values.h" #include "components/autofill/core/browser/autofill_experiments.h" #include "components/autofill/core/browser/credit_card.h" -#include "components/autofill/core/browser/legacy_strike_database.h" #include "components/autofill/core/browser/legal_message_line.h" #include "components/autofill/core/common/autofill_constants.h" #include "components/autofill/core/common/autofill_features.h" @@ -32,30 +31,26 @@ bool should_request_name_from_user, const CreditCard& card, std::unique_ptr<base::DictionaryValue> legal_message, - LegacyStrikeDatabase* strike_database, - AutofillClient::UserAcceptedUploadCallback upload_save_card_callback, - base::OnceClosure local_save_card_callback, + AutofillClient::UploadSaveCardPromptCallback + upload_save_card_prompt_callback, + AutofillClient::LocalSaveCardPromptCallback local_save_card_prompt_callback, PrefService* pref_service) : ConfirmInfoBarDelegate(), upload_(upload), should_request_name_from_user_(should_request_name_from_user), - upload_save_card_callback_(std::move(upload_save_card_callback)), - local_save_card_callback_(std::move(local_save_card_callback)), + upload_save_card_prompt_callback_( + std::move(upload_save_card_prompt_callback)), + local_save_card_prompt_callback_( + std::move(local_save_card_prompt_callback)), pref_service_(pref_service), - legacy_strike_database_(strike_database), had_user_interaction_(false), issuer_icon_id_(CreditCard::IconResourceId(card.network())), card_label_(card.NetworkAndLastFourDigits()), card_sub_label_(card.AbbreviatedExpirationDateForDisplay( !features::IsAutofillSaveCardDialogUnlabeledExpirationDateEnabled())), card_last_four_digits_(card.LastFourDigits()) { - if (upload) { - DCHECK(!upload_save_card_callback_.is_null()); - DCHECK(local_save_card_callback_.is_null()); - } else { - DCHECK(upload_save_card_callback_.is_null()); - DCHECK(!local_save_card_callback_.is_null()); - } + DCHECK_EQ(upload, !upload_save_card_prompt_callback_.is_null()); + DCHECK_EQ(upload, local_save_card_prompt_callback_.is_null()); if (legal_message) { if (!LegalMessageLine::Parse(*legal_message, &legal_messages_, @@ -77,16 +72,8 @@ AutofillSaveCardInfoBarDelegateMobile:: ~AutofillSaveCardInfoBarDelegateMobile() { if (!had_user_interaction_) { + RunSaveCardPromptCallbackWithUserDecision(AutofillClient::IGNORED); LogUserAction(AutofillMetrics::INFOBAR_IGNORED); - if (base::FeatureList::IsEnabled( - features::kAutofillSaveCreditCardUsesStrikeSystem)) { - // If the infobar was ignored, count that as a strike against offering - // save in the future. - legacy_strike_database_->AddStrike( - legacy_strike_database_->GetKeyForCreditCardSave( - base::UTF16ToUTF8(card_last_four_digits_)), - base::DoNothing()); - } } } @@ -150,16 +137,8 @@ } void AutofillSaveCardInfoBarDelegateMobile::InfoBarDismissed() { + RunSaveCardPromptCallbackWithUserDecision(AutofillClient::DECLINED); LogUserAction(AutofillMetrics::INFOBAR_DENIED); - if (base::FeatureList::IsEnabled( - features::kAutofillSaveCreditCardUsesStrikeSystem)) { - // If the infobar was explicitly denied, count that as a strike against - // offering save in the future. - legacy_strike_database_->AddStrike( - legacy_strike_database_->GetKeyForCreditCardSave( - base::UTF16ToUTF8(card_last_four_digits_)), - base::DoNothing()); - } } int AutofillSaveCardInfoBarDelegateMobile::GetButtons() const { @@ -179,15 +158,20 @@ } bool AutofillSaveCardInfoBarDelegateMobile::Accept() { - if (upload_) - std::move(upload_save_card_callback_).Run({}); - else - std::move(local_save_card_callback_).Run(); - + RunSaveCardPromptCallbackWithUserDecision(AutofillClient::ACCEPTED); LogUserAction(AutofillMetrics::INFOBAR_ACCEPTED); return true; } +void AutofillSaveCardInfoBarDelegateMobile:: + RunSaveCardPromptCallbackWithUserDecision( + AutofillClient::SaveCardOfferUserDecision user_decision) { + if (upload_) + std::move(upload_save_card_prompt_callback_).Run(user_decision, {}); + else + std::move(local_save_card_prompt_callback_).Run(user_decision); +} + void AutofillSaveCardInfoBarDelegateMobile::LogUserAction( AutofillMetrics::InfoBarMetric user_action) { DCHECK(!had_user_interaction_);
diff --git a/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h b/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h index 9b2af4c7..381ea336 100644 --- a/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h +++ b/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.h
@@ -24,7 +24,6 @@ namespace autofill { class CreditCard; -class LegacyStrikeDatabase; // An InfoBarDelegate that enables the user to allow or deny storing credit // card information gathered from a form submission. Only used on mobile. @@ -35,9 +34,10 @@ bool should_request_name_from_user, const CreditCard& card, std::unique_ptr<base::DictionaryValue> legal_message, - LegacyStrikeDatabase* legacy_strike_database, - AutofillClient::UserAcceptedUploadCallback upload_save_card_callback, - base::OnceClosure local_save_card_callback, + AutofillClient::UploadSaveCardPromptCallback + upload_save_card_prompt_callback, + AutofillClient::LocalSaveCardPromptCallback + local_save_card_prompt_callback, PrefService* pref_service); ~AutofillSaveCardInfoBarDelegateMobile() override; @@ -73,6 +73,11 @@ bool Accept() override; private: + // Runs the appropriate local or upload save callback with the given + // |user_decision|. + void RunSaveCardPromptCallbackWithUserDecision( + AutofillClient::SaveCardOfferUserDecision user_decision); + void LogUserAction(AutofillMetrics::InfoBarMetric user_action); // Whether the action is an upload or a local save. @@ -81,20 +86,18 @@ // Whether the user should enter/confirm cardholder name. bool should_request_name_from_user_; - // The callback to save the credit card to Google Payments if |upload_| is - // true and the user accepts the infobar. - AutofillClient::UserAcceptedUploadCallback upload_save_card_callback_; + // The callback to run once the user makes a decision with respect to the + // credit card upload offer-to-save prompt (if |upload_| is true). + AutofillClient::UploadSaveCardPromptCallback + upload_save_card_prompt_callback_; - // The callback to save the credit card locally to the device if |upload_| is - // false and the user accepts the infobar. - base::OnceClosure local_save_card_callback_; + // The callback to run once the user makes a decision with respect to the + // local credit card offer-to-save prompt (if |upload_| is false). + AutofillClient::LocalSaveCardPromptCallback local_save_card_prompt_callback_; // Weak reference to read & write |kAutofillAcceptSaveCreditCardPromptState|, PrefService* pref_service_; - // Weak reference to the Autofill LegacyStrikeDatabase. - LegacyStrikeDatabase* legacy_strike_database_; - // Did the user ever explicitly accept or dismiss this infobar? bool had_user_interaction_;
diff --git a/components/autofill/core/browser/credit_card_save_manager.cc b/components/autofill/core/browser/credit_card_save_manager.cc index 8ce0a2a6..3edf31cc 100644 --- a/components/autofill/core/browser/credit_card_save_manager.cc +++ b/components/autofill/core/browser/credit_card_save_manager.cc
@@ -415,7 +415,7 @@ observer_for_testing_->OnOfferLocalSave(); client_->ConfirmSaveCreditCardLocally( local_card_save_candidate_, show_save_prompt_.value(), - base::BindOnce(&CreditCardSaveManager::OnUserDidAcceptLocalSave, + base::BindOnce(&CreditCardSaveManager::OnUserDidDecideOnLocalSave, weak_ptr_factory_.GetWeakPtr())); // Log metrics. @@ -446,7 +446,7 @@ upload_request_.card, std::move(legal_message_), should_request_name_from_user_, should_request_expiration_date_from_user_, show_save_prompt_.value(), - base::BindOnce(&CreditCardSaveManager::OnUserDidAcceptUpload, + base::BindOnce(&CreditCardSaveManager::OnUserDidDecideOnUploadSave, weak_ptr_factory_.GetWeakPtr())); client_->LoadRiskData( base::BindOnce(&CreditCardSaveManager::OnDidGetUploadRiskData, @@ -475,30 +475,42 @@ } } -void CreditCardSaveManager::OnUserDidAcceptLocalSave() { - if (local_card_save_candidate_.HasFirstAndLastName()) - AutofillMetrics::LogSaveCardWithFirstAndLastNameComplete(/*is_local=*/true); +void CreditCardSaveManager::OnUserDidDecideOnLocalSave( + AutofillClient::SaveCardOfferUserDecision user_decision) { + switch (user_decision) { + case AutofillClient::ACCEPTED: + if (local_card_save_candidate_.HasFirstAndLastName()) + AutofillMetrics::LogSaveCardWithFirstAndLastNameComplete( + /*is_local=*/true); - if (base::FeatureList::IsEnabled( - features::kAutofillSaveCreditCardUsesStrikeSystem)) { - LegacyStrikeDatabase* strike_database = client_->GetLegacyStrikeDatabase(); - // Log how many strikes the card had when it was saved. - strike_database->GetStrikes( - strike_database->GetKeyForCreditCardSave( - base::UTF16ToUTF8(local_card_save_candidate_.LastFourDigits())), - base::BindRepeating( - &CreditCardSaveManager::LogStrikesPresentWhenCardSaved, - weak_ptr_factory_.GetWeakPtr(), - /*is_local=*/true)); - // Clear all strikes for this card, in case it is later removed. - strike_database->ClearAllStrikesForKey( - strike_database->GetKeyForCreditCardSave( - base::UTF16ToUTF8(local_card_save_candidate_.LastFourDigits())), - base::DoNothing()); + if (base::FeatureList::IsEnabled( + features::kAutofillSaveCreditCardUsesStrikeSystem)) { + LegacyStrikeDatabase* strike_database = + client_->GetLegacyStrikeDatabase(); + // Log how many strikes the card had when it was saved. + strike_database->GetStrikes( + strike_database->GetKeyForCreditCardSave( + base::UTF16ToUTF8(local_card_save_candidate_.LastFourDigits())), + base::BindRepeating( + &CreditCardSaveManager::LogStrikesPresentWhenCardSaved, + weak_ptr_factory_.GetWeakPtr(), + /*is_local=*/true)); + // Clear all strikes for this card, in case it is later removed. + strike_database->ClearAllStrikesForKey( + strike_database->GetKeyForCreditCardSave( + base::UTF16ToUTF8(local_card_save_candidate_.LastFourDigits())), + base::DoNothing()); + } + + personal_data_manager_->OnAcceptedLocalCreditCardSave( + local_card_save_candidate_); + break; + + case AutofillClient::DECLINED: + case AutofillClient::IGNORED: + OnUserDidIgnoreOrDeclineSave(local_card_save_candidate_.LastFourDigits()); + break; } - - personal_data_manager_->OnAcceptedLocalCreditCardSave( - local_card_save_candidate_); } void CreditCardSaveManager::LogStrikesPresentWhenCardSaved( @@ -739,21 +751,30 @@ return detected_values; } -void CreditCardSaveManager::OnUserDidAcceptUpload( +void CreditCardSaveManager::OnUserDidDecideOnUploadSave( + AutofillClient::SaveCardOfferUserDecision user_decision, const AutofillClient::UserProvidedCardDetails& user_provided_card_details) { + switch (user_decision) { + case AutofillClient::ACCEPTED: // On Android, requesting cardholder name is a two step flow. #if defined(OS_ANDROID) - if (should_request_name_from_user_) { - client_->ConfirmAccountNameFixFlow( - base::BindOnce( + if (should_request_name_from_user_) { + client_->ConfirmAccountNameFixFlow(base::BindOnce( &CreditCardSaveManager::OnUserDidAcceptAccountNameFixFlow, weak_ptr_factory_.GetWeakPtr())); - } else { - OnUserDidAcceptUploadHelper(user_provided_card_details); - } + } else { + OnUserDidAcceptUploadHelper(user_provided_card_details); + } #else - OnUserDidAcceptUploadHelper(user_provided_card_details); + OnUserDidAcceptUploadHelper(user_provided_card_details); #endif + break; + + case AutofillClient::DECLINED: + case AutofillClient::IGNORED: + OnUserDidIgnoreOrDeclineSave(upload_request_.card.LastFourDigits()); + break; + } } #if defined(OS_ANDROID) @@ -826,9 +847,26 @@ weak_ptr_factory_.GetWeakPtr())); } +void CreditCardSaveManager::OnUserDidIgnoreOrDeclineSave( + const base::string16& card_last_four_digits) { + if (base::FeatureList::IsEnabled( + features::kAutofillSaveCreditCardUsesStrikeSystem) && + show_save_prompt_.value()) { + // If the user rejected or ignored save and the offer-to-save bubble or + // infobar was actually shown (NOT just the icon if on desktop), count + // that as a strike against offering upload in the future. + LegacyStrikeDatabase* strike_database = client_->GetLegacyStrikeDatabase(); + strike_database->AddStrike( + strike_database->GetKeyForCreditCardSave( + base::UTF16ToUTF8(card_last_four_digits)), + base::BindRepeating(&CreditCardSaveManager::OnStrikeChangeComplete, + weak_ptr_factory_.GetWeakPtr())); + } +} + void CreditCardSaveManager::OnStrikeChangeComplete(const int num_strikes) { if (observer_for_testing_) - observer_for_testing_->OnCCSMStrikeChangeComplete(); + observer_for_testing_->OnStrikeChangeComplete(); } AutofillMetrics::CardUploadDecisionMetric
diff --git a/components/autofill/core/browser/credit_card_save_manager.h b/components/autofill/core/browser/credit_card_save_manager.h index e851ae8b..e7eb1a7 100644 --- a/components/autofill/core/browser/credit_card_save_manager.h +++ b/components/autofill/core/browser/credit_card_save_manager.h
@@ -81,7 +81,7 @@ virtual void OnReceivedGetUploadDetailsResponse() = 0; virtual void OnSentUploadCardRequest() = 0; virtual void OnReceivedUploadCardResponse() = 0; - virtual void OnCCSMStrikeChangeComplete() = 0; + virtual void OnStrikeChangeComplete() = 0; }; // The parameters should outlive the CreditCardSaveManager. @@ -169,18 +169,27 @@ // Autofill StrikeSystem has made its decision. void OfferCardUploadSave(); - // Clears strikes for the to-be-saved card and has |personal_data_manager_| - // save the card. - void OnUserDidAcceptLocalSave(); + // Called once the user makes a decision with respect to the local credit card + // offer-to-save prompt. If accepted, clears strikes for the to-be-saved card + // and has |personal_data_manager_| save the card. + void OnUserDidDecideOnLocalSave( + AutofillClient::SaveCardOfferUserDecision user_decision); - // Sets |user_did_accept_upload_prompt_| and calls SendUploadCardRequest if - // the risk data is available. Sets the cardholder name on the upload request - // if |user_provided_card_details.cardholder_name| is set. Sets the expiration - // date on the upload request if - // |user_provided_card_details.expiration_date_month| and - // |user_provided_card_details.expiration_date_year| are both set. - void OnUserDidAcceptUpload(const AutofillClient::UserProvidedCardDetails& - user_provided_card_details); + // Called once the user makes a decision with respect to the credit card + // upload offer-to-save prompt. + // If accepted: + // Sets |user_did_accept_upload_prompt_| and calls SendUploadCardRequest if + // the risk data is available. Sets the cardholder name on the upload + // request if |user_provided_card_details.cardholder_name| is set. Sets the + // expiration date on the upload request if + // |user_provided_card_details.expiration_date_month| and + // |user_provided_card_details.expiration_date_year| are both set. + // If rejected or ignored: + // Logs a strike against the current card to deter future offers to save. + void OnUserDidDecideOnUploadSave( + AutofillClient::SaveCardOfferUserDecision user_decision, + const AutofillClient::UserProvidedCardDetails& + user_provided_card_details); #if defined(OS_ANDROID) // Sets |user_did_accept_upload_prompt_| and calls SendUploadCardRequest if @@ -204,6 +213,12 @@ // Finalizes the upload request and calls PaymentsClient::UploadCard(). void SendUploadCardRequest(); + // Called when the user ignored or declined the credit card save prompt. Logs + // a strike for the given card in order to help deter future offers to save, + // provided that save was actually offered to the user. + void OnUserDidIgnoreOrDeclineSave( + const base::string16& card_last_four_digits); + // Used for browsertests. Gives the |observer_for_testing_| a notification // a strike change has been made. void OnStrikeChangeComplete(const int num_strikes);
diff --git a/components/autofill/core/browser/credit_card_save_manager_unittest.cc b/components/autofill/core/browser/credit_card_save_manager_unittest.cc index 160e215..70cd010 100644 --- a/components/autofill/core/browser/credit_card_save_manager_unittest.cc +++ b/components/autofill/core/browser/credit_card_save_manager_unittest.cc
@@ -154,8 +154,8 @@ void UserHasAcceptedUpload( AutofillClient::UserProvidedCardDetails user_provided_card_details) { - credit_card_save_manager_->OnUserDidAcceptUpload( - user_provided_card_details); + credit_card_save_manager_->OnUserDidDecideOnUploadSave( + AutofillClient::ACCEPTED, user_provided_card_details); } // Populates |form| with data corresponding to a simple credit card form.
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index 6b0d96377..1a4bf862 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -551,6 +551,9 @@ upload->set_autofill_used(form_was_autofilled); upload->set_data_present(EncodeFieldTypes(available_field_types)); upload->set_passwords_revealed(passwords_were_revealed_); + if (!page_language_.empty() && randomized_encoder_ != nullptr) { + upload->set_language(page_language_); + } auto triggering_event = (submission_event_ != SubmissionIndicatorEvent::NONE) ? submission_event_
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h index 182458d..218c73ed 100644 --- a/components/autofill/core/browser/form_structure.h +++ b/components/autofill/core/browser/form_structure.h
@@ -325,6 +325,12 @@ void set_is_rich_query_enabled(bool v) { is_rich_query_enabled_ = v; } + const std::string& page_language() const { return page_language_; } + + void set_page_language(std::string language) { + page_language_ = std::move(language); + } + private: friend class AutofillMergeTest; friend class FormStructureTest; @@ -469,6 +475,10 @@ static base::string16 FindLongestCommonPrefix( const std::vector<base::string16>& strings); + // The language detected for this form's page, prior to any translations + // performed by Chrome. + std::string page_language_; + // The id attribute of the form. base::string16 id_attribute_;
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc index 3f61dab..6d018910 100644 --- a/components/autofill/core/browser/personal_data_manager.cc +++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -47,6 +47,7 @@ #include "components/autofill/core/common/autofill_util.h" #include "components/history/core/browser/history_service.h" #include "components/prefs/pref_service.h" +#include "components/sync/driver/sync_auth_util.h" #include "components/sync/driver/sync_service.h" #include "components/sync/driver/sync_service_utils.h" #include "components/version_info/version_info.h" @@ -681,6 +682,8 @@ : identity_manager_->GetPrimaryAccountInfo(); } +// TODO(crbug.com/903914): Clean up this function so that it's more clear what +// it's checking. It should not check the database helper. bool PersonalDataManager::IsSyncFeatureEnabled() const { if (!sync_service_) return false; @@ -694,6 +697,32 @@ ::autofill::prefs::ClearSyncTransportOptIns(pref_service_); } +// TODO(crbug.com/903896): Generalize this to all the possible states relavant +// to Autofill. +AutofillSyncSigninState PersonalDataManager::GetSyncSigninState() const { + // Check if the user is signed out. + if (!sync_service_ || !identity_manager_ || + syncer::DetermineAccountToUse(identity_manager_, + /*allow_secondary_accounts=*/true) + .account_info.IsEmpty()) { + return AutofillSyncSigninState::kSignedOut; + } + + // Check if the user has turned on sync. + if (sync_service_->IsSyncFeatureEnabled()) { + return AutofillSyncSigninState::kSignedInAndSyncFeature; + } + + // Check if the feature is enabled and if Wallet data types are supported. + if (base::FeatureList::IsEnabled( + features::kAutofillEnableAccountWalletStorage) && + sync_service_->GetActiveDataTypes().Has(syncer::AUTOFILL_WALLET_DATA)) { + return AutofillSyncSigninState::kSignedInAndWalletSyncTransportEnabled; + } + + return AutofillSyncSigninState::kSignedIn; +} + void PersonalDataManager::AddObserver(PersonalDataManagerObserver* observer) { observers_.AddObserver(observer); } @@ -1416,11 +1445,29 @@ if (is_syncing_for_test_) return true; + if (!sync_service_) + return false; + + // Check if the user is in sync transport mode for wallet data. + if (!sync_service_->IsSyncFeatureEnabled() && + base::FeatureList::IsEnabled( + features::kAutofillEnableAccountWalletStorage)) { + // For SyncTransport, only show server cards if the user has opted in to + // seeing them in the dropdown, or if the feature to always show server + // cards is enabled. + if (!base::FeatureList::IsEnabled( + features::kAutofillAlwaysShowServerCardsInSyncTransport) && + !prefs::IsUserOptedInWalletSyncTransport( + pref_service_, + sync_service_->GetAuthenticatedAccountInfo().account_id)) { + return false; + } + } + // Server cards should be suggested if the sync service is active. // We check for persistent auth errors, because we don't want to offer server // cards when the user is in the "sync paused" state. - return sync_service_ && - sync_service_->GetActiveDataTypes().Has( + return sync_service_->GetActiveDataTypes().Has( syncer::AUTOFILL_WALLET_DATA) && !sync_service_->GetAuthError().IsPersistentError(); } @@ -2053,7 +2100,7 @@ features::kAutofillEnableAccountWalletStorage)); // The option should only be shown if the user has not already accepted it. - return !::autofill::prefs::IsUserOptedInWalletSyncTransport( + return !prefs::IsUserOptedInWalletSyncTransport( pref_service_, sync_service_->GetAuthenticatedAccountInfo().account_id); }
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h index 42d23f3c..9a3832a 100644 --- a/components/autofill/core/browser/personal_data_manager.h +++ b/components/autofill/core/browser/personal_data_manager.h
@@ -26,6 +26,7 @@ #include "components/autofill/core/browser/payments/payments_customer_data.h" #include "components/autofill/core/browser/proto/server.pb.h" #include "components/autofill/core/browser/suggestion.h" +#include "components/autofill/core/browser/sync_utils.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h" #include "components/history/core/browser/history_service_observer.h" @@ -137,6 +138,9 @@ const GoogleServiceAuthError& error) override {} void OnGaiaCookieDeletedByUserAction() override; + // Returns the current sync status. + AutofillSyncSigninState GetSyncSigninState() const; + // Adds a listener to be notified of PersonalDataManager events. virtual void AddObserver(PersonalDataManagerObserver* observer);
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc index 51726925..b079c4b 100644 --- a/components/autofill/core/browser/personal_data_manager_unittest.cc +++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -39,6 +39,7 @@ #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/personal_data_manager_observer.h" #include "components/autofill/core/browser/suggestion_selection.h" +#include "components/autofill/core/browser/sync_utils.h" #include "components/autofill/core/browser/test_autofill_clock.h" #include "components/autofill/core/browser/test_autofill_profile_validator.h" #include "components/autofill/core/browser/webdata/autofill_table.h" @@ -421,6 +422,15 @@ prefs::kAutofillLastVersionValidated); } + AccountInfo SetActiveSecondaryAccount() { + AccountInfo account_info; + account_info.email = "signed_in_account@email.com"; + account_info.account_id = "account_id"; + sync_service_.SetAuthenticatedAccountInfo(account_info); + sync_service_.SetIsAuthenticatedAccountPrimary(false); + return account_info; + } + // The temporary directory should be deleted at the end to ensure that // files are not used anymore and deletion succeeds. base::ScopedTempDir temp_dir_; @@ -6249,12 +6259,18 @@ } #endif // !defined(OS_ANDROID) +// Sync Transport mode is only for Win, Mac, and Linux. #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) TEST_F(PersonalDataManagerTest, ServerCardsShowInTransportMode) { // Set up PersonalDataManager in transport mode. ResetPersonalDataManager(USER_MODE_NORMAL, /*use_sync_transport_mode=*/true); SetUpThreeCardTypes(); + AccountInfo active_info = SetActiveSecondaryAccount(); + + // Opt-in to seeing server card in sync transport mode. + ::autofill::prefs::SetUserOptedInWalletSyncTransport( + prefs_.get(), active_info.account_id, true); // Check that the server cards are available for suggestion. EXPECT_EQ(3U, personal_data_->GetCreditCards().size()); @@ -6275,6 +6291,65 @@ EXPECT_EQ(1U, personal_data_->GetLocalCreditCards().size()); EXPECT_EQ(2U, personal_data_->GetServerCreditCards().size()); } + +// Make sure that the opt in is necessary to show server cards if the +// appropriate feature is disabled. +TEST_F(PersonalDataManagerTest, ServerCardsShowInTransportMode_NeedOptIn) { + // Disable the feature that always shows server cards in sync transport. + base::test::ScopedFeatureList scoped_features; + scoped_features.InitAndDisableFeature( + features::kAutofillAlwaysShowServerCardsInSyncTransport); + + // Set up PersonalDataManager in transport mode. + ResetPersonalDataManager(USER_MODE_NORMAL, + /*use_sync_transport_mode=*/true); + SetUpThreeCardTypes(); + AccountInfo active_info = SetActiveSecondaryAccount(); + + // The server cards should not be available at first. The user needs to + // accept the opt-in offer. + EXPECT_EQ(3U, personal_data_->GetCreditCards().size()); + EXPECT_EQ( + 1U, personal_data_->GetCreditCardsToSuggest(/*include_server_cards=*/true) + .size()); + EXPECT_EQ(1U, personal_data_->GetLocalCreditCards().size()); + EXPECT_EQ(2U, personal_data_->GetServerCreditCards().size()); + + // Opt-in to seeing server card in sync transport mode. + ::autofill::prefs::SetUserOptedInWalletSyncTransport( + prefs_.get(), active_info.account_id, true); + + // Check that the server cards are available for suggestion. + EXPECT_EQ(3U, personal_data_->GetCreditCards().size()); + EXPECT_EQ( + 3U, personal_data_->GetCreditCardsToSuggest(/*include_server_cards=*/true) + .size()); + EXPECT_EQ(1U, personal_data_->GetLocalCreditCards().size()); + EXPECT_EQ(2U, personal_data_->GetServerCreditCards().size()); +} + +// Make sure that the opt in is not necessary to show server cards if the +// appropriate feature is enabled. +TEST_F(PersonalDataManagerTest, ServerCardsShowInTransportMode_NoOptInNeeded) { + // Enable the feature that always shows server cards in sync transport. + base::test::ScopedFeatureList scoped_features; + scoped_features.InitAndEnableFeature( + features::kAutofillAlwaysShowServerCardsInSyncTransport); + + // Set up PersonalDataManager in transport mode. + ResetPersonalDataManager(USER_MODE_NORMAL, + /*use_sync_transport_mode=*/true); + SetUpThreeCardTypes(); + AccountInfo active_info = SetActiveSecondaryAccount(); + + // Check that the server cards are available for suggestion. + EXPECT_EQ(3U, personal_data_->GetCreditCards().size()); + EXPECT_EQ( + 3U, personal_data_->GetCreditCardsToSuggest(/*include_server_cards=*/true) + .size()); + EXPECT_EQ(1U, personal_data_->GetLocalCreditCards().size()); + EXPECT_EQ(2U, personal_data_->GetServerCreditCards().size()); +} #endif // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) // Tests that all the non settings origins of autofill profiles are cleared but @@ -7148,4 +7223,89 @@ EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption()); } +TEST_F(PersonalDataManagerTest, GetSyncSigninState) { + // Make a non-primary account available with both a refresh token and cookie + // for the first few tests. + identity_test_env_.SetPrimaryAccount("test@gmail.com"); + sync_service_.SetIsAuthenticatedAccountPrimary(false); + sync_service_.SetActiveDataTypes( + syncer::ModelTypeSet(syncer::AUTOFILL_WALLET_DATA)); + + // Check that the sync state is |SignedInAndWalletSyncTransportEnabled| if the + // account info is not empty, the kAutofillEnableAccountWalletStorage feature + // is enabled and the Wallet data type is active for the sync service. + { + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillEnableAccountWalletStorage}, + /*disabled_features=*/{}); + + EXPECT_EQ(AutofillSyncSigninState::kSignedInAndWalletSyncTransportEnabled, + personal_data_->GetSyncSigninState()); + } + + // Check that the sync state is |SignedIn| if the + // kAutofillEnableAccountWalletStorage feature is disabled. + { + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{}, + /*disabled_features=*/{features::kAutofillEnableAccountWalletStorage}); + + EXPECT_EQ(AutofillSyncSigninState::kSignedIn, + personal_data_->GetSyncSigninState()); + } + + // Check that the sync state is |SignedIn| if the sync service does not have + // wallet data active. + { + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillEnableAccountWalletStorage}, + /*disabled_features=*/{}); + sync_service_.SetActiveDataTypes(syncer::ModelTypeSet()); + + EXPECT_EQ(AutofillSyncSigninState::kSignedIn, + personal_data_->GetSyncSigninState()); + } + +// ClearPrimaryAccount is not supported on CrOS. +#if !defined(OS_CHROMEOS) + // Check that the sync state is |SignedOut| when the account info is empty. + { + identity_test_env_.ClearPrimaryAccount(); + EXPECT_EQ(AutofillSyncSigninState::kSignedOut, + personal_data_->GetSyncSigninState()); + } +#endif + + // Simulate that the user has enabled the sync feature. + AccountInfo primary_account_info; + primary_account_info.email = "active_sync_account@email.com"; + sync_service_.SetAuthenticatedAccountInfo(primary_account_info); + sync_service_.SetIsAuthenticatedAccountPrimary(true); +// MakePrimaryAccountAvailable is not supported on CrOS. +#if !defined(OS_CHROMEOS) + identity_test_env_.MakePrimaryAccountAvailable(primary_account_info.email); +#endif + + // Check that the sync state is |SignedInAndSyncFeature| if the sync feature + // is enabled. + EXPECT_EQ(AutofillSyncSigninState::kSignedInAndSyncFeature, + personal_data_->GetSyncSigninState()); + + // Check that the sync state is |SignedInAndSyncFeature| if the the sync + // feature is enabled even if the kAutofillEnableAccountWalletStorage and + // kAutofillGetPaymentsIdentityFromSync features are enabled. + { + base::test::ScopedFeatureList scoped_features; + scoped_features.InitWithFeatures( + /*enabled_features=*/{features::kAutofillEnableAccountWalletStorage, + features::kAutofillGetPaymentsIdentityFromSync}, + /*disabled_features=*/{}); + EXPECT_EQ(AutofillSyncSigninState::kSignedInAndSyncFeature, + personal_data_->GetSyncSigninState()); + } +} + } // namespace autofill
diff --git a/components/autofill/core/browser/sync_utils.h b/components/autofill/core/browser/sync_utils.h new file mode 100644 index 0000000..124104c --- /dev/null +++ b/components/autofill/core/browser/sync_utils.h
@@ -0,0 +1,25 @@ +// 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 COMPONENTS_AUTOFILL_CORE_BROWSER_SYNC_UTILS_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_SYNC_UTILS_H_ + +namespace autofill { + +enum AutofillSyncSigninState { + // The user is not signed in to Chromium. + kSignedOut, + // The user is signed in to Chromium. + kSignedIn, + // The user is signed in to Chromium and sync transport is active for Wallet + // data. + kSignedInAndWalletSyncTransportEnabled, + // The user is signed in, has enabled the sync feature and has not disabled + // Wallet sync. + kSignedInAndSyncFeature, + kNumSyncStates, +}; + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_SYNC_UTILS_H_
diff --git a/components/autofill/core/browser/test_autofill_client.cc b/components/autofill/core/browser/test_autofill_client.cc index 37a9d26..d586d1de 100644 --- a/components/autofill/core/browser/test_autofill_client.cc +++ b/components/autofill/core/browser/test_autofill_client.cc
@@ -18,7 +18,7 @@ } PersonalDataManager* TestAutofillClient::GetPersonalDataManager() { - return nullptr; + return &test_personal_data_manager_; } scoped_refptr<AutofillWebDataService> TestAutofillClient::GetDatabase() { @@ -115,10 +115,10 @@ void TestAutofillClient::ConfirmSaveCreditCardLocally( const CreditCard& card, bool show_prompt, - base::OnceClosure callback) { + LocalSaveCardPromptCallback callback) { confirm_save_credit_card_locally_called_ = true; offer_to_save_credit_card_bubble_was_shown_ = show_prompt; - std::move(callback).Run(); + std::move(callback).Run(AutofillClient::ACCEPTED); } #if defined(OS_ANDROID) @@ -135,9 +135,9 @@ bool should_request_name_from_user, bool should_request_expiration_date_from_user, bool show_prompt, - UserAcceptedUploadCallback callback) { + UploadSaveCardPromptCallback callback) { offer_to_save_credit_card_bubble_was_shown_ = show_prompt; - std::move(callback).Run({}); + std::move(callback).Run(AutofillClient::ACCEPTED, {}); } void TestAutofillClient::ConfirmCreditCardFillAssist(
diff --git a/components/autofill/core/browser/test_autofill_client.h b/components/autofill/core/browser/test_autofill_client.h index 489c2a8..9ac9381b 100644 --- a/components/autofill/core/browser/test_autofill_client.h +++ b/components/autofill/core/browser/test_autofill_client.h
@@ -19,6 +19,7 @@ #include "components/autofill/core/browser/test_address_normalizer.h" #include "components/autofill/core/browser/test_form_data_importer.h" #include "components/autofill/core/browser/test_legacy_strike_database.h" +#include "components/autofill/core/browser/test_personal_data_manager.h" #include "components/prefs/pref_service.h" #include "components/ukm/test_ukm_recorder.h" #include "services/identity/public/cpp/identity_test_environment.h" @@ -61,9 +62,10 @@ MigrationDeleteCardCallback delete_local_card_callback) override; void ConfirmSaveAutofillProfile(const AutofillProfile& profile, base::OnceClosure callback) override; - void ConfirmSaveCreditCardLocally(const CreditCard& card, - bool show_prompt, - base::OnceClosure callback) override; + void ConfirmSaveCreditCardLocally( + const CreditCard& card, + bool show_prompt, + LocalSaveCardPromptCallback callback) override; #if defined(OS_ANDROID) void ConfirmAccountNameFixFlow( base::OnceCallback<void(const base::string16&)> callback) override; @@ -74,7 +76,7 @@ bool should_request_name_from_user, bool should_request_expiration_date_from_user, bool show_prompt, - UserAcceptedUploadCallback callback) override; + UploadSaveCardPromptCallback callback) override; void ConfirmCreditCardFillAssist(const CreditCard& card, base::OnceClosure callback) override; bool HasCreditCardScanFeature() override; @@ -165,6 +167,7 @@ identity::IdentityTestEnvironment identity_test_env_; syncer::SyncService* test_sync_service_ = nullptr; TestAddressNormalizer test_address_normalizer_; + TestPersonalDataManager test_personal_data_manager_; // NULL by default. std::unique_ptr<PrefService> prefs_;
diff --git a/components/autofill/core/browser/ui/local_card_migration_dialog_controller.h b/components/autofill/core/browser/ui/local_card_migration_dialog_controller.h index 0f7e279..03e7b7bca 100644 --- a/components/autofill/core/browser/ui/local_card_migration_dialog_controller.h +++ b/components/autofill/core/browser/ui/local_card_migration_dialog_controller.h
@@ -32,6 +32,7 @@ virtual void OnSaveButtonClicked( const std::vector<std::string>& selected_cards_guids) = 0; virtual void OnCancelButtonClicked() = 0; + virtual void OnDoneButtonClicked() = 0; virtual void OnViewCardsButtonClicked() = 0; virtual void OnLegalMessageLinkClicked(const GURL& url) = 0; virtual void DeleteCard(const std::string& deleted_card_guid) = 0;
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index 9ddabdf..7a1b368 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -36,6 +36,11 @@ const base::Feature kAutofillAlwaysFillAddresses{ "AlwaysFillAddresses", base::FEATURE_ENABLED_BY_DEFAULT}; +// Controls whether the server cards are always shown when the user is in sync +// transport mode, or if an explicit opt-in is required. +const base::Feature kAutofillAlwaysShowServerCardsInSyncTransport{ + "AlwaysShowServerCardsInSyncTransport", base::FEATURE_DISABLED_BY_DEFAULT}; + // Controls the use of GET (instead of POST) to fetch cacheable autofill query // responses. const base::Feature kAutofillCacheQueryResponses{ @@ -69,11 +74,17 @@ const base::Feature kAutofillDynamicForms{"AutofillDynamicForms", base::FEATURE_ENABLED_BY_DEFAULT}; -// Controls whether the server credit cards are saved only in the ephemeral -// account-based storage, instead of the persistent local storage. +// Controls whether we download server credit cards to the ephemeral +// account-based storage when sync the transport is enabled. const base::Feature kAutofillEnableAccountWalletStorage{ "AutofillEnableAccountWalletStorage", base::FEATURE_DISABLED_BY_DEFAULT}; +// Controls whether we show also upload prompts when we are using the +// account-based storage for server cards. +const base::Feature kAutofillEnableAccountWalletStorageUpload{ + "AutofillEnableAccountWalletStorageUpload", + base::FEATURE_ENABLED_BY_DEFAULT}; + // Controls whether we use COMPANY as part of Autofill const base::Feature kAutofillEnableCompanyName{ "AutofillEnableCompanyName", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index 35df5c1..4cf32f6 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -24,6 +24,7 @@ extern const base::Feature kAutofillAllowNonHttpActivation; extern const base::Feature kAutofillAddressNormalizer; extern const base::Feature kAutofillAlwaysFillAddresses; +extern const base::Feature kAutofillAlwaysShowServerCardsInSyncTransport; extern const base::Feature kAutofillCacheQueryResponses; extern const base::Feature kAutofillCreateDataForTest; extern const base::Feature kAutofillCreditCardAblationExperiment; @@ -34,6 +35,7 @@ extern const base::Feature kAutofillDownstreamUseGooglePayBrandingOniOS; extern const base::Feature kAutofillDynamicForms; extern const base::Feature kAutofillEnableAccountWalletStorage; +extern const base::Feature kAutofillEnableAccountWalletStorageUpload; extern const base::Feature kAutofillEnableCompanyName; extern const base::Feature kAutofillEnableIFrameSupportOniOS; extern const base::Feature kAutofillEnforceMinRequiredFieldsForHeuristics;
diff --git a/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.h b/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.h index cb879636..4089ada 100644 --- a/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.h +++ b/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.h
@@ -24,7 +24,7 @@ - (void)receivedUploadCardResponse; -- (void)ccsmStrikeChangeComplete; +- (void)strikeChangeComplete; @end @@ -46,7 +46,7 @@ void OnReceivedGetUploadDetailsResponse() override; void OnSentUploadCardRequest() override; void OnReceivedUploadCardResponse() override; - void OnCCSMStrikeChangeComplete() override; + void OnStrikeChangeComplete() override; private: __weak id<CreditCardSaveManagerTestObserver> observer_ = nil;
diff --git a/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.mm b/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.mm index f615e04..bbb0c41f 100644 --- a/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.mm +++ b/components/autofill/ios/browser/credit_card_save_manager_test_observer_bridge.mm
@@ -43,8 +43,8 @@ [observer_ receivedUploadCardResponse]; } -void CreditCardSaveManagerTestObserverBridge::OnCCSMStrikeChangeComplete() { - [observer_ ccsmStrikeChangeComplete]; +void CreditCardSaveManagerTestObserverBridge::OnStrikeChangeComplete() { + [observer_ strikeChangeComplete]; } } // namespace autofill
diff --git a/components/autofill_assistant/browser/BUILD.gn b/components/autofill_assistant/browser/BUILD.gn index 4fa14e4..368401f 100644 --- a/components/autofill_assistant/browser/BUILD.gn +++ b/components/autofill_assistant/browser/BUILD.gn
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/android/rules.gni") import("//build/config/jumbo.gni") import("//third_party/protobuf/proto_library.gni") @@ -11,6 +12,13 @@ ] } +proto_java_library("proto_java") { + proto_path = "//components/autofill_assistant/browser/" + sources = [ + "$proto_path/service.proto", + ] +} + jumbo_static_library("browser") { sources = [ "access_token_fetcher.h",
diff --git a/components/autofill_assistant/browser/actions/action.cc b/components/autofill_assistant/browser/actions/action.cc index 1e5796d..99000214 100644 --- a/components/autofill_assistant/browser/actions/action.cc +++ b/components/autofill_assistant/browser/actions/action.cc
@@ -41,12 +41,4 @@ return vector; } -Selector Action::ExtractSelector(const ElementReferenceProto& element) { - Selector a_selector; - for (const auto& selector : element.selectors()) { - a_selector.selectors.emplace_back(selector); - } - return a_selector; -} - } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/actions/action.h b/components/autofill_assistant/browser/actions/action.h index 2d272d1..17b1f19 100644 --- a/components/autofill_assistant/browser/actions/action.h +++ b/components/autofill_assistant/browser/actions/action.h
@@ -43,9 +43,6 @@ static std::vector<std::string> ExtractVector( const google::protobuf::RepeatedPtrField<std::string>& repeated_strings); - // Returns a Selector from an ElementReferenceProto. - static Selector ExtractSelector(const ElementReferenceProto& element); - void UpdateProcessedAction(ProcessedActionStatusProto status); const ActionProto proto_;
diff --git a/components/autofill_assistant/browser/actions/action_delegate.h b/components/autofill_assistant/browser/actions/action_delegate.h index bed36ea0..737e954 100644 --- a/components/autofill_assistant/browser/actions/action_delegate.h +++ b/components/autofill_assistant/browser/actions/action_delegate.h
@@ -156,10 +156,10 @@ const std::string& value, base::OnceCallback<void(bool)> callback) = 0; - // Sets the keyboard focus to |selector| and inputs the specified text. + // Sets the keyboard focus to |selector| and inputs the specified text parts. // Returns the result through |callback|. virtual void SendKeyboardInput(const Selector& selector, - const std::string& text, + const std::vector<std::string>& text_parts, base::OnceCallback<void(bool)> callback) = 0; // Return the outerHTML of an element given by |selector|.
diff --git a/components/autofill_assistant/browser/actions/autofill_action.cc b/components/autofill_assistant/browser/actions/autofill_action.cc index f2af426..bf2708e 100644 --- a/components/autofill_assistant/browser/actions/autofill_action.cc +++ b/components/autofill_assistant/browser/actions/autofill_action.cc
@@ -99,7 +99,7 @@ is_autofill_card_ = false; prompt_ = proto.use_address().prompt(); name_ = proto.use_address().name(); - selector_ = ExtractSelector(proto.use_address().form_field_element()); + selector_ = Selector(proto.use_address().form_field_element()); fill_form_message_ = proto.use_address().strings().fill_form(); check_form_message_ = proto.use_address().strings().check_form(); required_fields_value_status_.resize( @@ -110,7 +110,7 @@ is_autofill_card_ = true; prompt_ = proto.use_card().prompt(); name_ = ""; - selector_ = ExtractSelector(proto.use_card().form_field_element()); + selector_ = Selector(proto.use_card().form_field_element()); fill_form_message_ = proto.use_card().strings().fill_form(); check_form_message_ = proto.use_card().strings().check_form(); show_overlay_ = proto.use_card().show_overlay(); @@ -292,7 +292,7 @@ auto& required_address_field = proto_.use_address().required_fields(i); DCHECK_GT(required_address_field.element().selectors_size(), 0); batch_element_checker_->AddFieldValueCheck( - ExtractSelector(required_address_field.element()), + Selector(required_address_field.element()), base::BindOnce(&AutofillAction::OnGetRequiredFieldValue, weak_ptr_factory_.GetWeakPtr(), i)); } @@ -397,7 +397,7 @@ DCHECK_GT( required_fields.Get(required_fields_index).element().selectors_size(), 0); delegate->SetFieldValue( - ExtractSelector(required_fields.Get(required_fields_index).element()), + Selector(required_fields.Get(required_fields_index).element()), fallback_value, required_fields.Get(required_fields_index).simulate_key_presses(), base::BindOnce(&AutofillAction::OnSetFallbackFieldValue,
diff --git a/components/autofill_assistant/browser/actions/click_action.cc b/components/autofill_assistant/browser/actions/click_action.cc index ed72786..3f0bcef 100644 --- a/components/autofill_assistant/browser/actions/click_action.cc +++ b/components/autofill_assistant/browser/actions/click_action.cc
@@ -23,7 +23,7 @@ ProcessActionCallback callback) { DCHECK_GT(proto_.click().element_to_click().selectors_size(), 0); delegate->ShortWaitForElementExist( - ExtractSelector(proto_.click().element_to_click()), + Selector(proto_.click().element_to_click()), base::BindOnce(&ClickAction::OnWaitForElement, weak_ptr_factory_.GetWeakPtr(), base::Unretained(delegate), std::move(callback))); @@ -39,7 +39,7 @@ } delegate->ClickOrTapElement( - ExtractSelector(proto_.click().element_to_click()), + Selector(proto_.click().element_to_click()), base::BindOnce(&::autofill_assistant::ClickAction::OnClick, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); }
diff --git a/components/autofill_assistant/browser/actions/focus_element_action.cc b/components/autofill_assistant/browser/actions/focus_element_action.cc index 33ac4743..acb35ea 100644 --- a/components/autofill_assistant/browser/actions/focus_element_action.cc +++ b/components/autofill_assistant/browser/actions/focus_element_action.cc
@@ -29,7 +29,7 @@ delegate->ShowStatusMessage(focus_element.title()); } delegate->ShortWaitForElementExist( - ExtractSelector(focus_element.element()), + Selector(focus_element.element()), base::BindOnce(&FocusElementAction::OnWaitForElement, weak_ptr_factory_.GetWeakPtr(), base::Unretained(delegate), std::move(callback))); @@ -45,7 +45,7 @@ } delegate->FocusElement( - ExtractSelector(proto_.focus_element().element()), + Selector(proto_.focus_element().element()), base::BindOnce(&FocusElementAction::OnFocusElement, weak_ptr_factory_.GetWeakPtr(), base::Unretained(delegate), std::move(callback))); @@ -56,7 +56,7 @@ bool status) { std::vector<Selector> touchable_elements; for (const auto& ref : proto().focus_element().touchable_element_area()) { - touchable_elements.emplace_back(ExtractSelector(ref)); + touchable_elements.emplace_back(Selector(ref)); } if (!touchable_elements.empty()) delegate->SetTouchableElements(touchable_elements);
diff --git a/components/autofill_assistant/browser/actions/highlight_element_action.cc b/components/autofill_assistant/browser/actions/highlight_element_action.cc index f3dbac6b..eb8f887 100644 --- a/components/autofill_assistant/browser/actions/highlight_element_action.cc +++ b/components/autofill_assistant/browser/actions/highlight_element_action.cc
@@ -24,7 +24,7 @@ ProcessActionCallback callback) { DCHECK_GT(proto_.highlight_element().element().selectors_size(), 0); delegate->ShortWaitForElementExist( - ExtractSelector(proto_.highlight_element().element()), + Selector(proto_.highlight_element().element()), base::BindOnce(&HighlightElementAction::OnWaitForElement, weak_ptr_factory_.GetWeakPtr(), base::Unretained(delegate), std::move(callback))); @@ -40,7 +40,7 @@ } delegate->HighlightElement( - ExtractSelector(proto_.highlight_element().element()), + Selector(proto_.highlight_element().element()), base::BindOnce(&HighlightElementAction::OnHighlightElement, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); }
diff --git a/components/autofill_assistant/browser/actions/mock_action_delegate.h b/components/autofill_assistant/browser/actions/mock_action_delegate.h index 1190adf..a3e74e08 100644 --- a/components/autofill_assistant/browser/actions/mock_action_delegate.h +++ b/components/autofill_assistant/browser/actions/mock_action_delegate.h
@@ -142,7 +142,7 @@ MOCK_METHOD3(SendKeyboardInput, void(const Selector& selector, - const std::string& text, + const std::vector<std::string>& text_parts, base::OnceCallback<void(bool)> callback)); MOCK_METHOD2( GetOuterHtml,
diff --git a/components/autofill_assistant/browser/actions/prompt_action.cc b/components/autofill_assistant/browser/actions/prompt_action.cc index 91a563e..a1e87dc 100644 --- a/components/autofill_assistant/browser/actions/prompt_action.cc +++ b/components/autofill_assistant/browser/actions/prompt_action.cc
@@ -49,7 +49,7 @@ std::string payload; choice_proto.SerializeToString(&payload); batch_element_checker_->AddElementCheck( - kExistenceCheck, ExtractSelector(choice_proto.element_exists()), + kExistenceCheck, Selector(choice_proto.element_exists()), base::BindOnce(&PromptAction::OnElementExist, weak_ptr_factory_.GetWeakPtr(), payload)); }
diff --git a/components/autofill_assistant/browser/actions/select_option_action.cc b/components/autofill_assistant/browser/actions/select_option_action.cc index 48063e2..2c50550d 100644 --- a/components/autofill_assistant/browser/actions/select_option_action.cc +++ b/components/autofill_assistant/browser/actions/select_option_action.cc
@@ -28,7 +28,7 @@ DCHECK_GT(select_option.element().selectors_size(), 0); delegate->ShortWaitForElementExist( - ExtractSelector(select_option.element()), + Selector(select_option.element()), base::BindOnce(&SelectOptionAction::OnWaitForElement, weak_ptr_factory_.GetWeakPtr(), base::Unretained(delegate), std::move(callback))); @@ -44,7 +44,7 @@ } delegate->SelectOption( - ExtractSelector(proto_.select_option().element()), + Selector(proto_.select_option().element()), proto_.select_option().selected_option(), base::BindOnce(&::autofill_assistant::SelectOptionAction::OnSelectOption, weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
diff --git a/components/autofill_assistant/browser/actions/set_attribute_action.cc b/components/autofill_assistant/browser/actions/set_attribute_action.cc index 83ddaadc..47a5681f 100644 --- a/components/autofill_assistant/browser/actions/set_attribute_action.cc +++ b/components/autofill_assistant/browser/actions/set_attribute_action.cc
@@ -23,7 +23,7 @@ void SetAttributeAction::InternalProcessAction(ActionDelegate* delegate, ProcessActionCallback callback) { delegate->ShortWaitForElementExist( - ExtractSelector(proto_.set_attribute().element()), + Selector(proto_.set_attribute().element()), base::BindOnce(&SetAttributeAction::OnWaitForElement, weak_ptr_factory_.GetWeakPtr(), base::Unretained(delegate), std::move(callback))); @@ -39,7 +39,7 @@ } delegate->SetAttribute( - ExtractSelector(proto_.set_attribute().element()), + Selector(proto_.set_attribute().element()), ExtractVector(proto_.set_attribute().attribute()), proto_.set_attribute().value(), base::BindOnce(&SetAttributeAction::OnSetAttribute,
diff --git a/components/autofill_assistant/browser/actions/set_form_field_value_action.cc b/components/autofill_assistant/browser/actions/set_form_field_value_action.cc index 9f3e961c..e149273 100644 --- a/components/autofill_assistant/browser/actions/set_form_field_value_action.cc +++ b/components/autofill_assistant/browser/actions/set_form_field_value_action.cc
@@ -26,7 +26,7 @@ ActionDelegate* delegate, ProcessActionCallback callback) { delegate->ShortWaitForElementExist( - ExtractSelector(proto_.set_form_value().element()), + Selector(proto_.set_form_value().element()), base::BindOnce(&SetFormFieldValueAction::OnWaitForElement, weak_ptr_factory_.GetWeakPtr(), base::Unretained(delegate), std::move(callback))); @@ -61,7 +61,7 @@ } const auto& key_field = proto_.set_form_value().value(next); - const auto& selector = ExtractSelector(proto_.set_form_value().element()); + const auto& selector = Selector(proto_.set_form_value().element()); switch (key_field.keypress_case()) { case SetFormFieldValueProto_KeyPress::kText: delegate->SetFieldValue( @@ -78,7 +78,7 @@ // You should use the `keyboard_input' field instead. if (key_field.keycode() < 128) { // US-ASCII delegate->SendKeyboardInput( - selector, std::string(1, char(key_field.keycode())), + selector, {std::string(1, char(key_field.keycode()))}, base::BindOnce(&SetFormFieldValueAction::OnSetFieldValue, weak_ptr_factory_.GetWeakPtr(), delegate, std::move(callback), /* next = */ next + 1)); @@ -93,7 +93,7 @@ break; case SetFormFieldValueProto_KeyPress::kKeyboardInput: delegate->SendKeyboardInput( - selector, key_field.keyboard_input(), + selector, {key_field.keyboard_input()}, base::BindOnce(&SetFormFieldValueAction::OnSetFieldValue, weak_ptr_factory_.GetWeakPtr(), delegate, std::move(callback), /* next = */ next + 1));
diff --git a/components/autofill_assistant/browser/actions/upload_dom_action.cc b/components/autofill_assistant/browser/actions/upload_dom_action.cc index e23b85e..961443f 100644 --- a/components/autofill_assistant/browser/actions/upload_dom_action.cc +++ b/components/autofill_assistant/browser/actions/upload_dom_action.cc
@@ -23,7 +23,7 @@ ProcessActionCallback callback) { DCHECK_GT(proto_.upload_dom().tree_root().selectors_size(), 0); delegate->ShortWaitForElementExist( - ExtractSelector(proto_.upload_dom().tree_root()), + Selector(proto_.upload_dom().tree_root()), base::BindOnce(&UploadDomAction::OnWaitForElement, weak_ptr_factory_.GetWeakPtr(), base::Unretained(delegate), std::move(callback))); @@ -39,7 +39,7 @@ } delegate->GetOuterHtml( - ExtractSelector(proto_.upload_dom().tree_root()), + Selector(proto_.upload_dom().tree_root()), base::BindOnce(&UploadDomAction::OnGetOuterHtml, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); }
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc index 6c04f2a..0b670025 100644 --- a/components/autofill_assistant/browser/controller.cc +++ b/components/autofill_assistant/browser/controller.cc
@@ -401,13 +401,13 @@ ExecuteScript(script_path); } -void Controller::ScrollBy(float distanceXRatio, float distanceYRatio) { - GetWebController()->ScrollBy(distanceXRatio, distanceYRatio); +void Controller::UpdateTouchableArea() { touchable_element_area_.UpdatePositions(); } -void Controller::UpdateTouchableArea() { - touchable_element_area_.UpdatePositions(); +void Controller::OnUserInteractionInsideTouchableArea() { + script_tracker_->CheckScripts(kPeriodicScriptCheckInterval); + StartPeriodicScriptChecks(); } std::string Controller::GetDebugContext() { @@ -476,21 +476,6 @@ GetUiController()->Shutdown(); } -void Controller::DidGetUserInteraction(const blink::WebInputEvent::Type type) { - switch (type) { - case blink::WebInputEvent::kTouchStart: - case blink::WebInputEvent::kGestureTapDown: - if (!script_tracker_->running()) { - script_tracker_->CheckScripts(kPeriodicScriptCheckInterval); - StartPeriodicScriptChecks(); - } - break; - - default: - break; - } -} - void Controller::DidFinishLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url) { // validated_url might not be the page URL. Ignore it and always check the
diff --git a/components/autofill_assistant/browser/controller.h b/components/autofill_assistant/browser/controller.h index 9f7a982..923c421 100644 --- a/components/autofill_assistant/browser/controller.h +++ b/components/autofill_assistant/browser/controller.h
@@ -103,8 +103,8 @@ void Start(const GURL& initialUrl) override; void OnClickOverlay() override; void OnDestroy() override; - void ScrollBy(float distanceXRatio, float distanceYRatio) override; void UpdateTouchableArea() override; + void OnUserInteractionInsideTouchableArea() override; void OnScriptSelected(const std::string& script_path) override; std::string GetDebugContext() override; bool Terminate() override; @@ -116,7 +116,6 @@ // Overrides content::WebContentsObserver: void DidAttachInterstitialPage() override; - void DidGetUserInteraction(const blink::WebInputEvent::Type type) override; void DidFinishLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url) override; void DidStartNavigation(
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc index ab9abd2c..e17bb39 100644 --- a/components/autofill_assistant/browser/script_executor.cc +++ b/components/autofill_assistant/browser/script_executor.cc
@@ -235,9 +235,9 @@ void ScriptExecutor::SendKeyboardInput( const Selector& selector, - const std::string& text, + const std::vector<std::string>& text_parts, base::OnceCallback<void(bool)> callback) { - delegate_->GetWebController()->SendKeyboardInput(selector, text, + delegate_->GetWebController()->SendKeyboardInput(selector, text_parts, std::move(callback)); }
diff --git a/components/autofill_assistant/browser/script_executor.h b/components/autofill_assistant/browser/script_executor.h index ed79fc2..882a7fb 100644 --- a/components/autofill_assistant/browser/script_executor.h +++ b/components/autofill_assistant/browser/script_executor.h
@@ -135,7 +135,7 @@ const std::string& value, base::OnceCallback<void(bool)> callback) override; void SendKeyboardInput(const Selector& selector, - const std::string& text, + const std::vector<std::string>& text_parts, base::OnceCallback<void(bool)> callback) override; void GetOuterHtml( const Selector& selector,
diff --git a/components/autofill_assistant/browser/script_precondition.cc b/components/autofill_assistant/browser/script_precondition.cc index f768136c..b56c04a 100644 --- a/components/autofill_assistant/browser/script_precondition.cc +++ b/components/autofill_assistant/browser/script_precondition.cc
@@ -30,11 +30,7 @@ continue; } - Selector a_selector; - for (const auto& selector : element.selectors()) { - a_selector.selectors.emplace_back(selector); - } - elements_exist.emplace_back(std::move(a_selector)); + elements_exist.emplace_back(Selector(element)); } std::set<std::string> domain_match; @@ -104,16 +100,13 @@ batch_checks->AddElementCheck(kExistenceCheck, selector, std::move(callback)); } - for (const auto& value_match : form_value_match_) { + for (size_t i = 0; i < form_value_match_.size(); i++) { + const auto& value_match = form_value_match_[i]; DCHECK(!value_match.element().selectors().empty()); - Selector a_selector; - for (const auto& selector : value_match.element().selectors()) { - a_selector.selectors.emplace_back(selector); - } - batch_checks->AddFieldValueCheck( - a_selector, base::BindOnce(&ScriptPrecondition::OnGetFieldValue, - weak_ptr_factory_.GetWeakPtr())); + Selector(value_match.element()), + base::BindOnce(&ScriptPrecondition::OnGetFieldValue, + weak_ptr_factory_.GetWeakPtr(), i)); } } @@ -208,8 +201,21 @@ ReportCheckResult(exists); } -void ScriptPrecondition::OnGetFieldValue(bool exists, +void ScriptPrecondition::OnGetFieldValue(int index, + bool exists, const std::string& value) { + if (!exists) { + ReportCheckResult(false); + return; + } + + // TODO(crbug.com/806868): Differentiate between empty value and failure. + const auto& value_match = form_value_match_[index]; + if (value_match.has_value()) { + ReportCheckResult(value == value_match.value()); + return; + } + ReportCheckResult(!value.empty()); }
diff --git a/components/autofill_assistant/browser/script_precondition.h b/components/autofill_assistant/browser/script_precondition.h index dd768c7..d1c6027 100644 --- a/components/autofill_assistant/browser/script_precondition.h +++ b/components/autofill_assistant/browser/script_precondition.h
@@ -65,7 +65,7 @@ const std::map<std::string, ScriptStatusProto>& executed_scripts) const; void OnCheckElementExists(bool exists); - void OnGetFieldValue(bool exists, const std::string& value); + void OnGetFieldValue(int index, bool exists, const std::string& value); void ReportCheckResult(bool success); std::vector<Selector> elements_exist_;
diff --git a/components/autofill_assistant/browser/script_precondition_unittest.cc b/components/autofill_assistant/browser/script_precondition_unittest.cc index 6d62b103..03ca796 100644 --- a/components/autofill_assistant/browser/script_precondition_unittest.cc +++ b/components/autofill_assistant/browser/script_precondition_unittest.cc
@@ -322,6 +322,13 @@ match->mutable_element()->add_selectors("exists"); EXPECT_TRUE(Check(proto)); + match->set_value("bar"); + EXPECT_FALSE(Check(proto)); + + match->set_value("foo"); + EXPECT_TRUE(Check(proto)); + + match->clear_value(); match->mutable_element()->set_selectors(0, "does_not_exist"); EXPECT_FALSE(Check(proto)); }
diff --git a/components/autofill_assistant/browser/selector.cc b/components/autofill_assistant/browser/selector.cc index a31b5e9..2f4b06b 100644 --- a/components/autofill_assistant/browser/selector.cc +++ b/components/autofill_assistant/browser/selector.cc
@@ -6,8 +6,19 @@ namespace autofill_assistant { -Selector::Selector() = default; -Selector::Selector(std::vector<std::string> s) : selectors(s) {} +Selector::Selector() : pseudo_type(PseudoType::UNDEFINED) {} + +Selector::Selector(const ElementReferenceProto& element) { + for (const auto& selector : element.selectors()) { + selectors.emplace_back(selector); + } + pseudo_type = element.pseudo_type(); +} + +Selector::Selector(std::vector<std::string> s) + : selectors(s), pseudo_type(PseudoType::UNDEFINED) {} +Selector::Selector(std::vector<std::string> s, PseudoType p) + : selectors(s), pseudo_type(p) {} Selector::~Selector() = default; Selector::Selector(Selector&& other) = default; @@ -16,11 +27,14 @@ Selector& Selector::operator=(Selector&& other) = default; bool Selector::operator<(const Selector& other) const { - return this->selectors < other.selectors; + return this->selectors < other.selectors || + (this->selectors == other.selectors && + this->pseudo_type < other.pseudo_type); } bool Selector::operator==(const Selector& other) const { - return this->selectors == other.selectors; + return this->selectors == other.selectors && + this->pseudo_type == other.pseudo_type; } bool Selector::empty() const {
diff --git a/components/autofill_assistant/browser/selector.h b/components/autofill_assistant/browser/selector.h index 6adf2d3b..35612ff0 100644 --- a/components/autofill_assistant/browser/selector.h +++ b/components/autofill_assistant/browser/selector.h
@@ -9,6 +9,7 @@ #include <vector> #include "base/macros.h" +#include "components/autofill_assistant/browser/service.pb.h" namespace autofill_assistant { @@ -19,8 +20,15 @@ // document. std::vector<std::string> selectors; + // An optional pseudo type. This pseudo type is associated to the final + // element matched by |selectors|, which means that we currently don't handle + // matching an element inside a pseudo element. + PseudoType pseudo_type; + Selector(); + explicit Selector(const ElementReferenceProto& element); explicit Selector(std::vector<std::string> s); + Selector(std::vector<std::string> s, PseudoType p); ~Selector(); Selector(Selector&& other);
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto index 2d1656b..b92b4b3 100644 --- a/components/autofill_assistant/browser/service.proto +++ b/components/autofill_assistant/browser/service.proto
@@ -5,6 +5,8 @@ syntax = "proto2"; option optimize_for = LITE_RUNTIME; +option java_package = "org.chromium.chrome.browser.autofill_assistant.proto"; +option java_multiple_files = true; package autofill_assistant; @@ -156,6 +158,11 @@ // Required. The selector associated to the form element whose value should be // checked. optional ElementReferenceProto element = 1; + + // Optional value. If specified, the element value must match the given value, + // even if it's empty. If not specified, we just check that the element value + // is non empty. + optional string value = 2; } enum PolicyType { @@ -298,6 +305,27 @@ PAYMENT_REQUEST_ERROR = 4; } +// The pseudo type values come from +// https://chromedevtools.github.io/devtools-protocol/tot/DOM#type-PseudoType. +enum PseudoType { + UNDEFINED = 0; + FIRST_LINE = 1; + FIRST_LETTER = 2; + BEFORE = 3; + AFTER = 4; + BACKDROP = 5; + SELECTION = 6; + FIRST_LINE_INHERITED = 7; + SCROLLBAR = 8; + SCROLLBAR_THUMB = 9; + SCROLLBAR_BUTTON = 10; + SCROLLBAR_TRACK = 11; + SCROLLBAR_TRACK_PIECE = 12; + SCROLLBAR_CORNER = 13; + RESIZER = 14; + INPUT_LIST_BUTTON = 15; +} + // A reference to an unique element on the page, possibly nested in frames. message ElementReferenceProto { // A sequence of CSS selectors. Any non-final CSS selector is expected to @@ -306,6 +334,11 @@ // APIs are free to reject element references that do not refer to unique // elements (i.e. resolve to more than one element on the page). repeated string selectors = 2; + + // An optional pseudo type. This pseudo type is associated to the final + // element matched by |selector|, which means that we currently don't handle + // matching an element inside a pseudo element. + optional PseudoType pseudo_type = 3; } // Contain all arguments to perform a click.
diff --git a/components/autofill_assistant/browser/ui_delegate.h b/components/autofill_assistant/browser/ui_delegate.h index 69d91dde..dd34d7c 100644 --- a/components/autofill_assistant/browser/ui_delegate.h +++ b/components/autofill_assistant/browser/ui_delegate.h
@@ -23,17 +23,15 @@ // detached from the associated activity. virtual void OnDestroy() = 0; - // Scrolls the browser view. - // - // Distance is expressed as a float between -1.0 and 1.0, relative to the - // width or height of the visible viewport. - virtual void ScrollBy(float distanceXRatio, float distanceYRatio) = 0; - // Asks for updated coordinates for the touchable area. This is called to // speed up update of the touchable areas when there are good reasons to think // that the current coordinates are out of date, such as while scrolling. virtual void UpdateTouchableArea() = 0; + // Called when user interaction within the allowed touchable area was + // detected. This should cause rerun of preconditions check. + virtual void OnUserInteractionInsideTouchableArea() = 0; + // Called when a script was selected for execution. virtual void OnScriptSelected(const std::string& script_path) = 0;
diff --git a/components/autofill_assistant/browser/web_controller.cc b/components/autofill_assistant/browser/web_controller.cc index 80612a67..a740439 100644 --- a/components/autofill_assistant/browser/web_controller.cc +++ b/components/autofill_assistant/browser/web_controller.cc
@@ -11,8 +11,10 @@ #include "base/bind_helpers.h" #include "base/callback.h" +#include "base/i18n/char_iterator.h" #include "base/logging.h" #include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" #include "build/build_config.h" #include "components/autofill/content/browser/content_autofill_driver.h" @@ -69,10 +71,6 @@ node.scrollIntoViewIfNeeded(); })"; -const char* const kScrollByScript = - R"(window.scrollBy(%f * window.visualViewport.width, - %f * window.visualViewport.height))"; - // Javascript to select a value from a select box. Also fires a "change" event // to trigger any listeners. Changing the index directly does not trigger this. const char* const kSelectOptionScript = @@ -152,6 +150,60 @@ return found[0]; return undefined; })"; + +bool ConvertPseudoType(const PseudoType pseudo_type, + dom::PseudoType* pseudo_type_output) { + switch (pseudo_type) { + case PseudoType::UNDEFINED: + break; + case PseudoType::FIRST_LINE: + *pseudo_type_output = dom::PseudoType::FIRST_LINE; + return true; + case PseudoType::FIRST_LETTER: + *pseudo_type_output = dom::PseudoType::FIRST_LETTER; + return true; + case PseudoType::BEFORE: + *pseudo_type_output = dom::PseudoType::BEFORE; + return true; + case PseudoType::AFTER: + *pseudo_type_output = dom::PseudoType::AFTER; + return true; + case PseudoType::BACKDROP: + *pseudo_type_output = dom::PseudoType::BACKDROP; + return true; + case PseudoType::SELECTION: + *pseudo_type_output = dom::PseudoType::SELECTION; + return true; + case PseudoType::FIRST_LINE_INHERITED: + *pseudo_type_output = dom::PseudoType::FIRST_LINE_INHERITED; + return true; + case PseudoType::SCROLLBAR: + *pseudo_type_output = dom::PseudoType::SCROLLBAR; + return true; + case PseudoType::SCROLLBAR_THUMB: + *pseudo_type_output = dom::PseudoType::SCROLLBAR_THUMB; + return true; + case PseudoType::SCROLLBAR_BUTTON: + *pseudo_type_output = dom::PseudoType::SCROLLBAR_BUTTON; + return true; + case PseudoType::SCROLLBAR_TRACK: + *pseudo_type_output = dom::PseudoType::SCROLLBAR_TRACK; + return true; + case PseudoType::SCROLLBAR_TRACK_PIECE: + *pseudo_type_output = dom::PseudoType::SCROLLBAR_TRACK_PIECE; + return true; + case PseudoType::SCROLLBAR_CORNER: + *pseudo_type_output = dom::PseudoType::SCROLLBAR_CORNER; + return true; + case PseudoType::RESIZER: + *pseudo_type_output = dom::PseudoType::RESIZER; + return true; + case PseudoType::INPUT_LIST_BUTTON: + *pseudo_type_output = dom::PseudoType::INPUT_LIST_BUTTON; + return true; + } + return false; +} } // namespace WebController::ElementPositionGetter::ElementPositionGetter() @@ -625,10 +677,32 @@ return; } - // Return object id of the element. if (selector.selectors.size() == index + 1) { - element_result->object_id = result->GetResult()->GetObjectId(); - std::move(callback).Run(std::move(element_result)); + // The pseudo type is associated to the final element matched by + // |selector|, which means that we currently don't handle matching an + // element inside a pseudo element. + if (selector.pseudo_type == PseudoType::UNDEFINED) { + // Return object id of the element. + element_result->object_id = result->GetResult()->GetObjectId(); + std::move(callback).Run(std::move(element_result)); + return; + } + + // We are looking for a pseudo element associated with this element. + dom::PseudoType pseudo_type; + if (!ConvertPseudoType(selector.pseudo_type, &pseudo_type)) { + // Return empty result. + std::move(callback).Run(std::move(element_result)); + return; + } + + devtools_client_->GetDOM()->DescribeNode( + dom::DescribeNodeParams::Builder() + .SetObjectId(result->GetResult()->GetObjectId()) + .Build(), + base::BindOnce(&WebController::OnDescribeNodeForPseudoElement, + weak_ptr_factory_.GetWeakPtr(), pseudo_type, + std::move(element_result), std::move(callback))); return; } @@ -642,6 +716,49 @@ std::move(element_result), std::move(callback))); } +void WebController::OnDescribeNodeForPseudoElement( + dom::PseudoType pseudo_type, + std::unique_ptr<FindElementResult> element_result, + FindElementCallback callback, + std::unique_ptr<dom::DescribeNodeResult> result) { + if (!result || !result->GetNode()) { + DLOG(ERROR) << "Failed to describe the node for pseudo element."; + std::move(callback).Run(std::move(element_result)); + return; + } + + auto* node = result->GetNode(); + if (node->HasPseudoElements()) { + for (const auto& pseudo_element : *(node->GetPseudoElements())) { + if (pseudo_element->HasPseudoType() && + pseudo_element->GetPseudoType() == pseudo_type) { + devtools_client_->GetDOM()->ResolveNode( + dom::ResolveNodeParams::Builder() + .SetBackendNodeId(pseudo_element->GetBackendNodeId()) + .Build(), + base::BindOnce(&WebController::OnResolveNodeForPseudoElement, + weak_ptr_factory_.GetWeakPtr(), + std::move(element_result), std::move(callback))); + return; + } + } + } + + // Failed to find the pseudo element: run the callback with empty result. + std::move(callback).Run(std::move(element_result)); +} + +void WebController::OnResolveNodeForPseudoElement( + std::unique_ptr<FindElementResult> element_result, + FindElementCallback callback, + std::unique_ptr<dom::ResolveNodeResult> result) { + if (result && result->GetObject() && result->GetObject()->HasObjectId()) { + element_result->object_id = result->GetObject()->GetObjectId(); + } + + std::move(callback).Run(std::move(element_result)); +} + void WebController::OnDescribeNode( const std::string& object_id, size_t index, @@ -1036,17 +1153,31 @@ bool simulate_key_presses, base::OnceCallback<void(bool)> callback) { if (simulate_key_presses) { + std::vector<std::string> utf8_chars; + base::i18n::UTF8CharIterator iter(&value); + while (!iter.end()) { + wchar_t wide_char = iter.get(); + std::string utf8_char; + if (!base::WideToUTF8(&wide_char, 1, &utf8_char)) { + DLOG(ERROR) << "Failed to convert character to UTF-8: " << wide_char; + OnResult(false, std::move(callback)); + return; + } + + utf8_chars.push_back(utf8_char); + iter.Advance(); + } + // We first clear the field value, and then simulate the key presses. // TODO(crbug.com/806868): Disable keyboard during this action and then // reset to previous state. InternalSetFieldValue( selector, "", - base::BindOnce(&WebController::OnClearFieldForDispatchKeyEvent, - weak_ptr_factory_.GetWeakPtr(), selector, value, + base::BindOnce(&WebController::OnClearFieldForSendKeyboardInput, + weak_ptr_factory_.GetWeakPtr(), selector, utf8_chars, std::move(callback))); return; } - InternalSetFieldValue(selector, value, std::move(callback)); } @@ -1061,112 +1192,59 @@ std::move(callback))); } -void WebController::OnClearFieldForDispatchKeyEvent( +void WebController::OnClearFieldForSendKeyboardInput( const Selector& selector, - const std::string& value, + const std::vector<std::string>& utf8_chars, base::OnceCallback<void(bool)> callback, bool clear_status) { if (!clear_status) { OnResult(false, std::move(callback)); return; } - - // TODO(crbug.com/806868): Substitute mouse click with touch tap. - // - // Note that 'KeyDown' will not be handled by the element immediately after - // touch tap. Add ~1 second delay before 'DispatchKeyDownEvent' in - // 'OnClickOrTapElementForDispatchKeyEvent' solved the problem, needs more - // investigation for this timing issue. One possible reason is that events - // from different devices are not guarranteed to be handled in order (needs a - // way to make sure previous events have been handled). - ClickElement(selector, - base::BindOnce(&WebController::OnClickElementForDispatchKeyEvent, - weak_ptr_factory_.GetWeakPtr(), value, - std::move(callback))); -} - -void WebController::OnClickElementForDispatchKeyEvent( - const std::string& value, - base::OnceCallback<void(bool)> callback, - bool click_status) { - if (!click_status) { - OnResult(/* result= */ false, std::move(callback)); - return; - } - DispatchKeyDownEvent(value, 0, std::move(callback)); + SendKeyboardInput(selector, utf8_chars, std::move(callback)); } void WebController::OnClickElementForSendKeyboardInput( - const std::string& text, + const std::vector<std::string>& utf8_chars, base::OnceCallback<void(bool)> callback, bool click_status) { if (!click_status) { OnResult(false, std::move(callback)); return; } - DispatchKeyboardTextDownEvent(text, std::move(callback)); + DispatchKeyboardTextDownEvent(utf8_chars, 0, std::move(callback)); } -void WebController::DispatchKeyDownEvent( - const std::string& value, +void WebController::DispatchKeyboardTextDownEvent( + const std::vector<std::string>& utf8_chars, size_t index, base::OnceCallback<void(bool)> callback) { - if (index >= value.size()) { + if (index >= utf8_chars.size()) { OnResult(true, std::move(callback)); return; } devtools_client_->GetInput()->DispatchKeyEvent( - input::DispatchKeyEventParams::Builder() - .SetType(input::DispatchKeyEventType::KEY_DOWN) - .SetText(std::string(1, value[index])) - .Build(), - base::BindOnce(&WebController::DispatchKeyUpEvent, - weak_ptr_factory_.GetWeakPtr(), value, index, - std::move(callback))); -} - -void WebController::DispatchKeyUpEvent( - const std::string& value, - size_t index, - base::OnceCallback<void(bool)> callback) { - DCHECK_LT(index, value.size()); - devtools_client_->GetInput()->DispatchKeyEvent( - input::DispatchKeyEventParams::Builder() - .SetType(input::DispatchKeyEventType::KEY_UP) - .SetText(std::string(1, value[index])) - .Build(), - base::BindOnce(&WebController::OnDispatchKeyUpEvent, - weak_ptr_factory_.GetWeakPtr(), value, index, - std::move(callback))); -} - -void WebController::OnDispatchKeyUpEvent( - const std::string& value, - size_t index, - base::OnceCallback<void(bool)> callback) { - DispatchKeyDownEvent(value, index + 1, std::move(callback)); -} - -void WebController::DispatchKeyboardTextDownEvent( - const std::string& text, - base::OnceCallback<void(bool)> callback) { - devtools_client_->GetInput()->DispatchKeyEvent( CreateKeyEventParamsFromText( - autofill_assistant::input::DispatchKeyEventType::KEY_DOWN, text), + autofill_assistant::input::DispatchKeyEventType::KEY_DOWN, + utf8_chars[index]), base::BindOnce(&WebController::DispatchKeyboardTextUpEvent, - weak_ptr_factory_.GetWeakPtr(), text, + weak_ptr_factory_.GetWeakPtr(), utf8_chars, index, std::move(callback))); } void WebController::DispatchKeyboardTextUpEvent( - const std::string& text, + const std::vector<std::string>& utf8_chars, + size_t index, base::OnceCallback<void(bool)> callback) { + DCHECK_LT(index, utf8_chars.size()); devtools_client_->GetInput()->DispatchKeyEvent( CreateKeyEventParamsFromText( - autofill_assistant::input::DispatchKeyEventType::KEY_UP, text), - base::BindOnce(&WebController::OnDispatchKeyboardTextUpEvent, - weak_ptr_factory_.GetWeakPtr(), std::move(callback))); + autofill_assistant::input::DispatchKeyEventType::KEY_UP, + utf8_chars[index]), + base::BindOnce(&WebController::DispatchKeyboardTextDownEvent, + weak_ptr_factory_.GetWeakPtr(), utf8_chars, index + 1, + std::move(callback))); } auto WebController::CreateKeyEventParamsFromText( @@ -1177,11 +1255,6 @@ return params; } -void WebController::OnDispatchKeyboardTextUpEvent( - base::OnceCallback<void(bool)> callback) { - OnResult(/* result= */ true, std::move(callback)); -} - void WebController::OnPressKeyboard( int key_code, base::OnceCallback<void(bool)> callback, @@ -1274,26 +1347,27 @@ OnResult(result && !result->HasExceptionDetails(), std::move(callback)); } -void WebController::SendKeyboardInput(const Selector& selector, - const std::string& text, - base::OnceCallback<void(bool)> callback) { +void WebController::SendKeyboardInput( + const Selector& selector, + const std::vector<std::string>& utf8_chars, + base::OnceCallback<void(bool)> callback) { DCHECK(!selector.empty()); FindElement(selector, /* strict_mode= */ true, base::BindOnce(&WebController::OnFindElementForSendKeyboardInput, - weak_ptr_factory_.GetWeakPtr(), selector, text, - std::move(callback))); + weak_ptr_factory_.GetWeakPtr(), selector, + utf8_chars, std::move(callback))); } void WebController::OnFindElementForSendKeyboardInput( const Selector& selector, - const std::string& text, + const std::vector<std::string>& utf8_chars, base::OnceCallback<void(bool)> callback, std::unique_ptr<FindElementResult> element_result) { - ClickElement(selector, - base::BindOnce( - &WebController::OnClickElementForSendKeyboardInput, - weak_ptr_factory_.GetWeakPtr(), text, std::move(callback))); + ClickElement(selector, base::BindOnce( + &WebController::OnClickElementForSendKeyboardInput, + weak_ptr_factory_.GetWeakPtr(), utf8_chars, + std::move(callback))); } void WebController::GetOuterHtml( @@ -1320,12 +1394,6 @@ weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } -void WebController::ScrollBy(float distanceXRatio, float distanceYRatio) { - devtools_client_->GetRuntime()->Evaluate( - base::StringPrintf(kScrollByScript, distanceXRatio, distanceYRatio), - base::DoNothing()); -} - void WebController::OnFindElementForPosition( base::OnceCallback<void(bool, const RectF&)> callback, std::unique_ptr<FindElementResult> result) {
diff --git a/components/autofill_assistant/browser/web_controller.h b/components/autofill_assistant/browser/web_controller.h index f5d2a32..e4e26ad 100644 --- a/components/autofill_assistant/browser/web_controller.h +++ b/components/autofill_assistant/browser/web_controller.h
@@ -112,10 +112,11 @@ const std::string& value, base::OnceCallback<void(bool)> callback); - // Sets the keyboard focus to |selector| and inputs the specified text. + // Sets the keyboard focus to |selector| and inputs the specified UTF-8 + // characters in the specified order. // Returns the result through |callback|. virtual void SendKeyboardInput(const Selector& selector, - const std::string& text, + const std::vector<std::string>& utf8_chars, base::OnceCallback<void(bool)> callback); // Return the outerHTML of |selector|. @@ -137,12 +138,6 @@ const Selector& selector, base::OnceCallback<void(bool, const RectF&)> callback); - // Scroll the view by the given distance. - // - // Distances are floats between -1.0 and 1.0, with 1 corresponding to the size - // of the visible viewport. - virtual void ScrollBy(float distanceXRatio, float distanceYRatio); - // Functions to set, get and expire the Autofill Assistant cookie used to // detect when Autofill Assistant has been used on a domain before. virtual void SetCookie(const std::string& domain, @@ -324,6 +319,15 @@ std::unique_ptr<FindElementResult> element_result, FindElementCallback callback, std::unique_ptr<runtime::CallFunctionOnResult> result); + void OnDescribeNodeForPseudoElement( + dom::PseudoType pseudo_type, + std::unique_ptr<FindElementResult> element_result, + FindElementCallback callback, + std::unique_ptr<dom::DescribeNodeResult> result); + void OnResolveNodeForPseudoElement( + std::unique_ptr<FindElementResult> element_result, + FindElementCallback callback, + std::unique_ptr<dom::ResolveNodeResult> result); void OnDescribeNode(const std::string& object_id, size_t index, const Selector& selector, @@ -381,31 +385,20 @@ void InternalSetFieldValue(const Selector& selector, const std::string& value, base::OnceCallback<void(bool)> callback); - void OnClearFieldForDispatchKeyEvent(const Selector& selector, - const std::string& value, - base::OnceCallback<void(bool)> callback, - bool clear_status); - void OnClickElementForDispatchKeyEvent( - const std::string& value, + void OnClearFieldForSendKeyboardInput( + const Selector& selector, + const std::vector<std::string>& utf8_chars, base::OnceCallback<void(bool)> callback, - bool click_status); + bool clear_status); void OnClickElementForSendKeyboardInput( - const std::string& text, + const std::vector<std::string>& utf8_chars, base::OnceCallback<void(bool)> callback, bool click_status); - void DispatchKeyDownEvent(const std::string& value, - size_t index, - base::OnceCallback<void(bool)> callback); - void DispatchKeyUpEvent(const std::string& value, - size_t index, - base::OnceCallback<void(bool)> callback); - void OnDispatchKeyUpEvent(const std::string& value, - size_t index, - base::OnceCallback<void(bool)> callback); - void OnDispatchKeyboardTextUpEvent(base::OnceCallback<void(bool)> callback); - void DispatchKeyboardTextDownEvent(const std::string& text, + void DispatchKeyboardTextDownEvent(const std::vector<std::string>& utf8_chars, + size_t index, base::OnceCallback<void(bool)> callback); - void DispatchKeyboardTextUpEvent(const std::string& text, + void DispatchKeyboardTextUpEvent(const std::vector<std::string>& utf8_chars, + size_t index, base::OnceCallback<void(bool)> callback); void OnFindElementForSetAttribute( const std::vector<std::string>& attribute, @@ -416,7 +409,7 @@ std::unique_ptr<runtime::CallFunctionOnResult> result); void OnFindElementForSendKeyboardInput( const Selector& selector, - const std::string& text, + const std::vector<std::string>& utf8_chars, base::OnceCallback<void(bool)> callback, std::unique_ptr<FindElementResult> element_result); void OnPressKeyboard(int key_code,
diff --git a/components/autofill_assistant/browser/web_controller_browsertest.cc b/components/autofill_assistant/browser/web_controller_browsertest.cc index b6118dd4..f01d7a4 100644 --- a/components/autofill_assistant/browser/web_controller_browsertest.cc +++ b/components/autofill_assistant/browser/web_controller_browsertest.cc
@@ -292,11 +292,12 @@ std::move(done_callback).Run(); } - bool SendKeyboardInput(const Selector& selector, const std::string& text) { + bool SendKeyboardInput(const Selector& selector, + const std::vector<std::string>& text_parts) { base::RunLoop run_loop; bool result; web_controller_->SendKeyboardInput( - selector, text, + selector, text_parts, base::BindOnce(&WebControllerBrowserTest::OnSendKeyboardInput, base::Unretained(this), run_loop.QuitClosure(), &result)); @@ -522,6 +523,17 @@ WaitForElementRemove(selector); } +IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ClickPseudoElement) { + const std::string javascript = R"( + document.querySelector("#terms-and-conditions").checked; + )"; + EXPECT_FALSE(content::EvalJs(shell(), javascript).ExtractBool()); + Selector selector({R"(label[for="terms-and-conditions"])"}, + PseudoType::BEFORE); + ClickElement(selector); + EXPECT_TRUE(content::EvalJs(shell(), javascript).ExtractBool()); +} + IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, FindElement) { Selector selector; selector.selectors.emplace_back("#button"); @@ -658,10 +670,10 @@ a_selector.selectors.clear(); a_selector.selectors.emplace_back("#uppercase_input"); selectors.emplace_back(a_selector); - EXPECT_TRUE( - SetFieldValue(a_selector, "baz", /* simulate_key_presses= */ true)); + EXPECT_TRUE(SetFieldValue(a_selector, /* Zürich */ "Z\xc3\xbcrich", + /* simulate_key_presses= */ true)); expected_values.clear(); - expected_values.emplace_back("BAZ"); + expected_values.emplace_back(/* ZÜRICH */ "Z\xc3\x9cRICH"); GetFieldsValue(selectors, expected_values); selectors.clear(); @@ -677,17 +689,15 @@ } IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, SendKeyboardInput) { - std::vector<std::string> input = { - "Z", /* letter u with diaeresis */ "\xc3\xbc", "r", "i", "c", "h", "\r"}; + std::vector<std::string> text_parts = { + "Z", /* ü */ "\xc3\xbc", "r", "i", "c", "h", "\r"}; std::vector<std::string> expected_values = {"Z\xc3\xbcrich"}; std::vector<Selector> selectors; Selector a_selector; a_selector.selectors.emplace_back("#input6"); selectors.emplace_back(a_selector); - for (const auto& text : input) { - EXPECT_TRUE(SendKeyboardInput(a_selector, text)); - } + EXPECT_TRUE(SendKeyboardInput(a_selector, text_parts)); GetFieldsValue(selectors, expected_values); }
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp index 6858a46..5d2c32d 100644 --- a/components/autofill_strings.grdp +++ b/components/autofill_strings.grdp
@@ -256,25 +256,31 @@ <message name="IDS_AUTOFILL_SAVE_CARD_CARDHOLDER_NAME_FIX_FLOW_HEADER" desc="Header for the cardholder name fix flow."> Confirm name </message> + <message name="IDS_AUTOFILL_SAVE_CARD_PROMPT_UPLOAD_EXPLANATION_TOOLTIP" desc="The tooltip hover text that explains why credit card upload to Google Payments is being offered."> + Chrome is offering to save your cards to your Google Account because you are signed in. You can change this behavior in settings. + </message> <!-- Autofill Local card migration bubble or dialog --> <if expr="not is_ios and not is_android"> <message name="IDS_AUTOFILL_GOOGLE_PAY_LOGO_ACCESSIBLE_NAME" desc="The accessible name for the Google Pay logo in the local card migration bubble or dialog."> Google Pay logo </message> + <message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_ANIMATION_LABEL" desc="The text displayed in the migration pending animation in the omnibox. The animation will be triggered after the user consented to the migration offer."> + Cards saving... + </message> <message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_BUBBLE_TITLE" desc="The title text for a bubble that offers users to start the process of migrating local cards to cloud."> - Save cards to your Google Account? + Use your cards on all your devices? </message> <message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_BUBBLE_BUTTON_LABEL" desc="The text in the OK button of a bubble that offers users to start the process of migration local cards to cloud."> Continue </message> <message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_BUBBLE_BODY_TEXT" desc="The body text for a bubble that offers users to start the process of migrating local cards to cloud."> - In the next step, you can choose which cards to save + Right now, you have cards that can only be used on this device. Click Continue to review cards. </message> <message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_TITLE_OFFER" desc="The title text for a dialog that offers to migrate local cards into the cloud."> - Use your cards in more places + Save cards in your Google Account </message> - <message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_TITLE_DONE" desc="The title text for a dialog shown after the user accepts another dialog that offers to migrate local cards into the cloud and all cards are successfully migrated, or migration of all cards failed and the user deleted all invalid cards."> + <message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_TITLE_DONE" desc="The title text for a dialog shown after the user accepts another dialog that offers to migrate local cards into the cloud and all cards are successfully migrated."> You're all set! </message> <message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_TITLE_FIX" desc="The title text for a dialog shown after the user accepts another dialog that offers to migrate local cards into the cloud but there are errors with the cards that they need to address."> @@ -282,18 +288,18 @@ </message> <message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_OFFER" desc="The body text for a dialog that offers to migrate local cards into the cloud. [ICU Syntax]"> {NUM_CARDS, plural, - =1 {This card and its billing address will be saved to your Google Account so you can check out faster wherever you're signed in} - other {These cards and their billing addresses will be saved to your Google Account so you can check out faster wherever you're signed in}} + =1 {You'll be able to use it when you're signed in. This card and its billing address will be saved in your Google Account.} + other {You'll be able to use them when you're signed in. These cards and their billing addresses will be saved in your Google Account.}} </message> - <message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_DONE" desc="The body text for a dialog shown after the user accepts another dialog that offers to migrate local cards into the cloud and some cards have been successfully migrated. [ICU Syntax]"> + <message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_DONE" desc="The body text for a dialog shown after the user accepts another dialog that offers to migrate local cards into the cloud and all cards are successfully migrated. [ICU Syntax]"> {NUM_CARDS, plural, - =1 {This card has been added to your Google Account. You can now use it from any signed-in device.} - other {These cards have been added to your Google Account. You can now use them from any signed-in device.}} + =1 {This card has been saved in your Google Account} + other {These cards have been saved in your Google Account}} </message> <message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_ERROR" desc="The body text shown on a dialog when the user attempts to migrate their cards to Google Payments, but all migrations fail. [ICU Syntax]"> {NUM_CARDS, plural, - =1 {This card can't be added right now} - other {These cards can't be added right now}} + =1 {This card can't be saved right now} + other {These cards can't be saved right now}} </message> <message name="IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_FIX" desc="The body text shown on a dialog after the user accepts another dialog that offers to migrate local cards into the cloud but there are errors with the cards that they need to address."> Check the info below and delete any invalid cards
diff --git a/components/autofill_strings_grdp/IDS_AUTOFILL_LOCAL_CARD_MIGRATION_ANIMATION_LABEL.png.sha1 b/components/autofill_strings_grdp/IDS_AUTOFILL_LOCAL_CARD_MIGRATION_ANIMATION_LABEL.png.sha1 new file mode 100644 index 0000000..5781e980 --- /dev/null +++ b/components/autofill_strings_grdp/IDS_AUTOFILL_LOCAL_CARD_MIGRATION_ANIMATION_LABEL.png.sha1
@@ -0,0 +1 @@ +586efa2ecee56f146aad85cce92bd41dc433b1e3 \ No newline at end of file
diff --git a/components/autofill_strings_grdp/IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_DONE.png.sha1 b/components/autofill_strings_grdp/IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_DONE.png.sha1 new file mode 100644 index 0000000..33df952 --- /dev/null +++ b/components/autofill_strings_grdp/IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_DONE.png.sha1
@@ -0,0 +1 @@ +ec67b1d63d9d483ef8a3b5ddd07f8419c4377f8e \ No newline at end of file
diff --git a/components/autofill_strings_grdp/IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_ERROR.png.sha1 b/components/autofill_strings_grdp/IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_ERROR.png.sha1 index b5ffe69..145507b0 100644 --- a/components/autofill_strings_grdp/IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_ERROR.png.sha1 +++ b/components/autofill_strings_grdp/IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_ERROR.png.sha1
@@ -1 +1 @@ -f38f9fd1383bd9d1864b5fbc1b5202c126b0b316 \ No newline at end of file +f525599d836186501897f0d1bd53da797ebf289e \ No newline at end of file
diff --git a/components/autofill_strings_grdp/IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_OFFER.png.sha1 b/components/autofill_strings_grdp/IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_OFFER.png.sha1 new file mode 100644 index 0000000..7f96622b --- /dev/null +++ b/components/autofill_strings_grdp/IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_MESSAGE_OFFER.png.sha1
@@ -0,0 +1 @@ +d25c74bcff96c1e5c42f47503322f12e4313f14d \ No newline at end of file
diff --git a/components/autofill_strings_grdp/IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_TITLE_OFFER.png.sha1 b/components/autofill_strings_grdp/IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_TITLE_OFFER.png.sha1 new file mode 100644 index 0000000..7f96622b --- /dev/null +++ b/components/autofill_strings_grdp/IDS_AUTOFILL_LOCAL_CARD_MIGRATION_DIALOG_TITLE_OFFER.png.sha1
@@ -0,0 +1 @@ +d25c74bcff96c1e5c42f47503322f12e4313f14d \ No newline at end of file
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc index 7e46b89..ce18a96 100644 --- a/components/browser_sync/profile_sync_service.cc +++ b/components/browser_sync/profile_sync_service.cc
@@ -1383,13 +1383,6 @@ ReconfigureDatatypeManager(/*bypass_setup_in_progress_check=*/false); } -syncer::ModelTypeSet ProfileSyncService::GetActiveDataTypes() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!data_type_manager_) - return syncer::ModelTypeSet(); - return data_type_manager_->GetActiveDataTypes(); -} - syncer::SyncClient* ProfileSyncService::GetSyncClientForTest() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return sync_client_.get(); @@ -1411,6 +1404,29 @@ return observers_.HasObserver(observer); } +syncer::ModelTypeSet ProfileSyncService::GetRegisteredDataTypes() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + syncer::ModelTypeSet registered_types; + // The |data_type_controllers_| are determined by command-line flags; + // that's effectively what controls the values returned here. + for (const std::pair<const syncer::ModelType, + std::unique_ptr<DataTypeController>>& + type_and_controller : data_type_controllers_) { + registered_types.Put(type_and_controller.first); + } + return registered_types; +} + +syncer::ModelTypeSet ProfileSyncService::GetForcedDataTypes() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + syncer::ModelTypeSet forced_types; + for (const syncer::SyncTypePreferenceProvider* provider : + preference_providers_) { + forced_types.PutAll(provider->GetForcedDataTypes()); + } + return Intersection(forced_types, GetRegisteredDataTypes()); +} + syncer::ModelTypeSet ProfileSyncService::GetPreferredDataTypes() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); syncer::ModelTypeSet preferred_types = @@ -1424,27 +1440,11 @@ return Union(preferred_types, GetForcedDataTypes()); } -syncer::ModelTypeSet ProfileSyncService::GetForcedDataTypes() const { +syncer::ModelTypeSet ProfileSyncService::GetActiveDataTypes() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - syncer::ModelTypeSet forced_types; - for (const syncer::SyncTypePreferenceProvider* provider : - preference_providers_) { - forced_types.PutAll(provider->GetForcedDataTypes()); - } - return Intersection(forced_types, GetRegisteredDataTypes()); -} - -syncer::ModelTypeSet ProfileSyncService::GetRegisteredDataTypes() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - syncer::ModelTypeSet registered_types; - // The |data_type_controllers_| are determined by command-line flags; - // that's effectively what controls the values returned here. - for (const std::pair<const syncer::ModelType, - std::unique_ptr<DataTypeController>>& - type_and_controller : data_type_controllers_) { - registered_types.Put(type_and_controller.first); - } - return registered_types; + if (!data_type_manager_) + return syncer::ModelTypeSet(); + return data_type_manager_->GetActiveDataTypes(); } bool ProfileSyncService::IsUsingSecondaryPassphrase() const { @@ -1977,11 +1977,6 @@ } // static -void ProfileSyncService::SyncEvent(SyncEventCodes code) { - UMA_HISTOGRAM_ENUMERATION("Sync.EventCodes", code, MAX_SYNC_EVENT_CODE); -} - -// static bool ProfileSyncService::IsSyncAllowedByFlag() { return !base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableSync);
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h index d70bd0c..85b64d0 100644 --- a/components/browser_sync/profile_sync_service.h +++ b/components/browser_sync/profile_sync_service.h
@@ -156,29 +156,6 @@ public: using SigninScopedDeviceIdCallback = base::RepeatingCallback<std::string()>; - // NOTE: Used in a UMA histogram, do not reorder etc. - enum SyncEventCodes { - // Events starting the sync service. - // START_FROM_NTP = 1, - // START_FROM_WRENCH = 2, - // START_FROM_OPTIONS = 3, - // START_FROM_BOOKMARK_MANAGER = 4, - // START_FROM_PROFILE_MENU = 5, - // START_FROM_URL = 6, - - // Events regarding cancellation of the signon process of sync. - // CANCEL_FROM_SIGNON_WITHOUT_AUTH = 10, - // CANCEL_DURING_SIGNON = 11, - CANCEL_DURING_CONFIGURE = 12, // Cancelled before choosing data types and - // clicking OK. - - // Events resulting in the stoppage of sync service. - STOP_FROM_OPTIONS = 20, // Sync was stopped from Wrench->Options. - // STOP_FROM_ADVANCED_DIALOG = 21, - - MAX_SYNC_EVENT_CODE = 22 - }; - // If AUTO_START, sync will set IsFirstSetupComplete() automatically and sync // will begin syncing without the user needing to confirm sync settings. enum StartBehavior { @@ -240,11 +217,13 @@ void StopAndClear() override; void RequestStop(SyncStopDataFate data_fate); virtual void RequestStart(); // Virtual for testing. - syncer::ModelTypeSet GetActiveDataTypes() const override; void AddObserver(syncer::SyncServiceObserver* observer) override; void RemoveObserver(syncer::SyncServiceObserver* observer) override; bool HasObserver(const syncer::SyncServiceObserver* observer) const override; + syncer::ModelTypeSet GetRegisteredDataTypes() const override; + syncer::ModelTypeSet GetForcedDataTypes() const override; syncer::ModelTypeSet GetPreferredDataTypes() const override; + syncer::ModelTypeSet GetActiveDataTypes() const override; // Virtual for testing. virtual void OnUserChoseDatatypes(bool sync_everything, syncer::ModelTypeSet chosen_types); @@ -366,9 +345,6 @@ return crypto_.passphrase_required_reason(); } - // Record stats on various events. - static void SyncEvent(SyncEventCodes code); - // Returns whether sync is allowed to run based on command-line switches. // Profile::IsSyncAllowed() is probably a better signal than this function. // This function can be called from any thread, and the implementation doesn't @@ -396,17 +372,6 @@ // SyncPrefObserver implementation. void OnSyncManagedPrefChange(bool is_sync_managed) override; - // Returns the set of types which are enforced programmatically and can not - // be disabled by the user. - syncer::ModelTypeSet GetForcedDataTypes() const; - - // Gets the set of all data types that could be allowed (the set that - // should be advertised to the user). These will typically only change - // via a command-line option. See class comment for more on what it means - // for a datatype to be Registered. - // Virtual for testing. - virtual syncer::ModelTypeSet GetRegisteredDataTypes() const; - // See the SyncServiceCrypto header. // Virtual for testing. virtual syncer::PassphraseType GetPassphraseType() const;
diff --git a/components/browsing_data/core/counters/browsing_data_counter.h b/components/browsing_data/core/counters/browsing_data_counter.h index 3c606bb7..f3f34a3 100644 --- a/components/browsing_data/core/counters/browsing_data_counter.h +++ b/components/browsing_data/core/counters/browsing_data_counter.h
@@ -169,7 +169,6 @@ Callback callback_; // The boolean preference indicating whether this data type is to be deleted. - // If false, we will not count it. BooleanPrefMember pref_; // The integer preference describing the time period for which this data type
diff --git a/components/crash/content/app/crashpad.cc b/components/crash/content/app/crashpad.cc index 4f8b276..a84dbb8 100644 --- a/components/crash/content/app/crashpad.cc +++ b/components/crash/content/app/crashpad.cc
@@ -264,9 +264,11 @@ return false; } +#if !defined(OS_ANDROID) void DumpWithoutCrashing() { CRASHPAD_SIMULATE_CRASH(); } +#endif #if defined(OS_LINUX) || defined(OS_ANDROID) void CrashWithoutDumping(const std::string& message) {
diff --git a/components/crash/content/app/crashpad_linux.cc b/components/crash/content/app/crashpad_linux.cc index 2ef6544..189dcb2d 100644 --- a/components/crash/content/app/crashpad_linux.cc +++ b/components/crash/content/app/crashpad_linux.cc
@@ -29,6 +29,7 @@ #include "third_party/crashpad/crashpad/client/annotation.h" #include "third_party/crashpad/crashpad/client/client_argv_handling.h" #include "third_party/crashpad/crashpad/client/crashpad_client.h" +#include "third_party/crashpad/crashpad/client/simulate_crash_linux.h" #include "third_party/crashpad/crashpad/snapshot/sanitized/sanitization_information.h" #include "third_party/crashpad/crashpad/util/linux/exception_handler_client.h" #include "third_party/crashpad/crashpad/util/linux/exception_information.h" @@ -98,6 +99,22 @@ return Signals::InstallCrashHandlers(HandleCrash, 0, nullptr); } + void HandleCrashNonFatal(int signo, siginfo_t* siginfo, void* context) { + base::ScopedFD connection; + if (ConnectToHandler(signo, &connection) == 0) { + ExceptionInformation exception_information; + SetExceptionInformation(siginfo, static_cast<ucontext_t*>(context), + &exception_information); + + ClientInformation info; + SetClientInformation(&exception_information, &sanitization_, &info); + + ExceptionHandlerClient handler_client(connection.get()); + handler_client.SetCanSetPtracer(false); + handler_client.RequestCrashDump(info); + } + } + private: SandboxedHandler() = default; ~SandboxedHandler() = delete; @@ -148,22 +165,7 @@ static void HandleCrash(int signo, siginfo_t* siginfo, void* context) { SandboxedHandler* state = Get(); - - base::ScopedFD connection; - if (state->ConnectToHandler(signo, &connection) == 0) { - ExceptionInformation exception_information; - SetExceptionInformation(siginfo, static_cast<ucontext_t*>(context), - &exception_information); - - ClientInformation info; - SetClientInformation(&exception_information, &state->sanitization_, - &info); - - ExceptionHandlerClient handler_client(connection.get()); - handler_client.SetCanSetPtracer(false); - handler_client.RequestCrashDump(info); - } - + state->HandleCrashNonFatal(signo, siginfo, context); Signals::RestoreHandlerAndReraiseSignalOnReturn(siginfo, nullptr); } @@ -501,8 +503,32 @@ return true; } +bool g_is_browser = false; + } // namespace +#if defined(OS_ANDROID) +// TODO(jperaza): This might be simplified to have both the browser and child +// processes use CRASHPAD_SIMULATE_CRASH() if CrashpadClient allows injecting +// the Chromium specific SandboxedHandler. +void DumpWithoutCrashing() { + if (g_is_browser) { + CRASHPAD_SIMULATE_CRASH(); + } else { + siginfo_t siginfo; + siginfo.si_signo = crashpad::Signals::kSimulatedSigno; + siginfo.si_errno = 0; + siginfo.si_code = 0; + + ucontext_t context; + crashpad::CaptureContext(&context); + + crashpad::SandboxedHandler::Get()->HandleCrashNonFatal(siginfo.si_signo, + &siginfo, &context); + } +} +#endif + bool DumpWithoutCrashingForClient(CrashReporterClient* client) { base::ScopedFD connection; if (!ConnectToHandler(client, &connection)) { @@ -551,6 +577,8 @@ DCHECK(!embedded_handler); DCHECK(exe_path.empty()); + g_is_browser = browser_process; + bool dump_at_crash = true; #if defined(OS_ANDROID) base::android::SetJavaExceptionCallback(SetJavaExceptionInfo);
diff --git a/components/crash/content/browser/crash_handler_host_linux.cc b/components/crash/content/browser/crash_handler_host_linux.cc index baa7c58..ef97599 100644 --- a/components/crash/content/browser/crash_handler_host_linux.cc +++ b/components/crash/content/browser/crash_handler_host_linux.cc
@@ -54,6 +54,7 @@ #if !defined(OS_CHROMEOS) #include "components/crash/content/app/crashpad.h" #include "third_party/crashpad/crashpad/client/crashpad_client.h" // nogncheck +#include "third_party/crashpad/crashpad/util/posix/signals.h" // nogncheck #endif using content::BrowserThread; @@ -618,7 +619,9 @@ return false; } - NotifyCrashSignalObservers(child_pid, signo); + if (signo != crashpad::Signals::kSimulatedSigno) { + NotifyCrashSignalObservers(child_pid, signo); + } #if defined(OS_ANDROID) if (!request_dump) {
diff --git a/components/cryptauth/BUILD.gn b/components/cryptauth/BUILD.gn index 4205be0..49de1e1 100644 --- a/components/cryptauth/BUILD.gn +++ b/components/cryptauth/BUILD.gn
@@ -53,8 +53,6 @@ "foreground_eid_generator.cc", "foreground_eid_generator.h", "gcm_device_info_provider.h", - "local_device_data_provider.cc", - "local_device_data_provider.h", "network_request_error.cc", "network_request_error.h", "pref_names.cc", @@ -151,8 +149,6 @@ "mock_cryptauth_client.h", "mock_foreground_eid_generator.cc", "mock_foreground_eid_generator.h", - "mock_local_device_data_provider.cc", - "mock_local_device_data_provider.h", "mock_sync_scheduler.cc", "mock_sync_scheduler.h", ] @@ -186,7 +182,6 @@ "device_to_device_secure_context_unittest.cc", "fake_secure_message_delegate_unittest.cc", "foreground_eid_generator_unittest.cc", - "local_device_data_provider_unittest.cc", "raw_eid_generator_impl_unittest.cc", "remote_device_loader_unittest.cc", "remote_device_provider_impl_unittest.cc",
diff --git a/components/cryptauth/background_eid_generator.cc b/components/cryptauth/background_eid_generator.cc index a20d87b3..747842a 100644 --- a/components/cryptauth/background_eid_generator.cc +++ b/components/cryptauth/background_eid_generator.cc
@@ -10,6 +10,7 @@ #include "base/strings/string_util.h" #include "base/time/default_clock.h" #include "base/time/time.h" +#include "chromeos/components/multidevice/beacon_seed.h" #include "chromeos/components/multidevice/remote_device_ref.h" #include "chromeos/components/proximity_auth/logging/logging.h" #include "components/cryptauth/proto/cryptauth_api.pb.h" @@ -106,7 +107,8 @@ remote_devices.begin(), remote_devices.end(), [this, &service_data_without_flags](const auto& remote_device) { std::vector<DataWithTimestamp> eids = - GenerateNearestEids(remote_device.beacon_seeds()); + GenerateNearestEids(chromeos::multidevice::ToCryptAuthSeedList( + remote_device.beacon_seeds())); const auto eid_it = std::find_if( eids.begin(), eids.end(), [&service_data_without_flags](auto eid) { return eid.data == service_data_without_flags;
diff --git a/components/cryptauth/background_eid_generator_unittest.cc b/components/cryptauth/background_eid_generator_unittest.cc index 194aadc..b14f2078 100644 --- a/components/cryptauth/background_eid_generator_unittest.cc +++ b/components/cryptauth/background_eid_generator_unittest.cc
@@ -11,6 +11,7 @@ #include "base/strings/string_util.h" #include "base/test/simple_test_clock.h" #include "base/time/time.h" +#include "chromeos/components/multidevice/beacon_seed.h" #include "chromeos/components/multidevice/remote_device_ref.h" #include "chromeos/components/multidevice/remote_device_test_util.h" #include "components/cryptauth/proto/cryptauth_api.pb.h" @@ -99,7 +100,8 @@ chromeos::multidevice::RemoteDeviceRef device_1 = chromeos::multidevice::RemoteDeviceRefBuilder() .SetPublicKey("publicKey1") - .SetBeaconSeeds(beacon_seeds_) + .SetBeaconSeeds( + chromeos::multidevice::FromCryptAuthSeedList(beacon_seeds_)) .Build(); chromeos::multidevice::RemoteDeviceRef device_2 = chromeos::multidevice::RemoteDeviceRefBuilder()
diff --git a/components/cryptauth/ble/ble_advertisement_generator.cc b/components/cryptauth/ble/ble_advertisement_generator.cc index bde4402..d14d948 100644 --- a/components/cryptauth/ble/ble_advertisement_generator.cc +++ b/components/cryptauth/ble/ble_advertisement_generator.cc
@@ -56,8 +56,9 @@ } std::unique_ptr<DataWithTimestamp> service_data = - eid_generator_->GenerateAdvertisement(local_device_public_key, - remote_device.beacon_seeds()); + eid_generator_->GenerateAdvertisement( + local_device_public_key, chromeos::multidevice::ToCryptAuthSeedList( + remote_device.beacon_seeds())); if (!service_data) { PA_LOG(WARNING) << "Error generating advertisement for device with ID " << remote_device.GetTruncatedDeviceIdForLogs() << ". "
diff --git a/components/cryptauth/ble/ble_advertisement_generator_unittest.cc b/components/cryptauth/ble/ble_advertisement_generator_unittest.cc index 67de5182..b3d41cd 100644 --- a/components/cryptauth/ble/ble_advertisement_generator_unittest.cc +++ b/components/cryptauth/ble/ble_advertisement_generator_unittest.cc
@@ -48,7 +48,8 @@ CryptAuthBleAdvertisementGeneratorTest() : test_remote_device_( chromeos::multidevice::RemoteDeviceRefBuilder() - .SetBeaconSeeds(CreateBeaconSeedsForDevice("remote device id")) + .SetBeaconSeeds(chromeos::multidevice::FromCryptAuthSeedList( + CreateBeaconSeedsForDevice("remote device id"))) .Build()), fake_advertisement_("advertisement1", 1000L, 2000L) {}
diff --git a/components/cryptauth/fake_software_feature_manager.cc b/components/cryptauth/fake_software_feature_manager.cc index 2fe10a7b..8ef3ffe88 100644 --- a/components/cryptauth/fake_software_feature_manager.cc +++ b/components/cryptauth/fake_software_feature_manager.cc
@@ -9,7 +9,7 @@ FakeSoftwareFeatureManager::SetSoftwareFeatureStateArgs:: SetSoftwareFeatureStateArgs( const std::string& public_key, - SoftwareFeature software_feature, + chromeos::multidevice::SoftwareFeature software_feature, bool enabled, const base::Closure& success_callback, const base::Callback<void(NetworkRequestError)>& error_callback, @@ -25,7 +25,7 @@ ~SetSoftwareFeatureStateArgs() = default; FakeSoftwareFeatureManager::FindEligibleDevicesArgs::FindEligibleDevicesArgs( - SoftwareFeature software_feature, + chromeos::multidevice::SoftwareFeature software_feature, const base::Callback<void(const std::vector<ExternalDeviceInfo>&, const std::vector<IneligibleDevice>&)>& success_callback, @@ -43,7 +43,7 @@ void FakeSoftwareFeatureManager::SetSoftwareFeatureState( const std::string& public_key, - SoftwareFeature software_feature, + chromeos::multidevice::SoftwareFeature software_feature, bool enabled, const base::Closure& success_callback, const base::Callback<void(NetworkRequestError)>& error_callback, @@ -58,7 +58,7 @@ } void FakeSoftwareFeatureManager::FindEligibleDevices( - SoftwareFeature software_feature, + chromeos::multidevice::SoftwareFeature software_feature, const base::Callback<void(const std::vector<ExternalDeviceInfo>&, const std::vector<IneligibleDevice>&)>& success_callback,
diff --git a/components/cryptauth/fake_software_feature_manager.h b/components/cryptauth/fake_software_feature_manager.h index 3fa9da2..2a1e5b2 100644 --- a/components/cryptauth/fake_software_feature_manager.h +++ b/components/cryptauth/fake_software_feature_manager.h
@@ -9,8 +9,8 @@ #include <vector> #include "base/callback.h" +#include "chromeos/components/multidevice/software_feature.h" #include "components/cryptauth/network_request_error.h" -#include "components/cryptauth/proto/cryptauth_api.pb.h" #include "components/cryptauth/software_feature_manager.h" namespace cryptauth { @@ -28,7 +28,7 @@ struct SetSoftwareFeatureStateArgs { SetSoftwareFeatureStateArgs( const std::string& public_key, - SoftwareFeature software_feature, + chromeos::multidevice::SoftwareFeature software_feature, bool enabled, const base::Closure& success_callback, const base::Callback<void(NetworkRequestError)>& error_callback, @@ -36,7 +36,7 @@ ~SetSoftwareFeatureStateArgs(); std::string public_key; - SoftwareFeature software_feature; + chromeos::multidevice::SoftwareFeature software_feature; bool enabled; base::Closure success_callback; base::Callback<void(NetworkRequestError)> error_callback; @@ -48,14 +48,14 @@ struct FindEligibleDevicesArgs { FindEligibleDevicesArgs( - SoftwareFeature software_feature, + chromeos::multidevice::SoftwareFeature software_feature, const base::Callback<void(const std::vector<ExternalDeviceInfo>&, const std::vector<IneligibleDevice>&)>& success_callback, const base::Callback<void(NetworkRequestError)>& error_callback); ~FindEligibleDevicesArgs(); - SoftwareFeature software_feature; + chromeos::multidevice::SoftwareFeature software_feature; base::Callback<void(const std::vector<ExternalDeviceInfo>&, const std::vector<IneligibleDevice>&)> success_callback; @@ -83,13 +83,13 @@ // SoftwareFeatureManager: void SetSoftwareFeatureState( const std::string& public_key, - SoftwareFeature software_feature, + chromeos::multidevice::SoftwareFeature software_feature, bool enabled, const base::Closure& success_callback, const base::Callback<void(NetworkRequestError)>& error_callback, bool is_exclusive = false) override; void FindEligibleDevices( - SoftwareFeature software_feature, + chromeos::multidevice::SoftwareFeature software_feature, const base::Callback<void(const std::vector<ExternalDeviceInfo>&, const std::vector<IneligibleDevice>&)>& success_callback,
diff --git a/components/cryptauth/local_device_data_provider.cc b/components/cryptauth/local_device_data_provider.cc deleted file mode 100644 index f98cad81..0000000 --- a/components/cryptauth/local_device_data_provider.cc +++ /dev/null
@@ -1,54 +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 "components/cryptauth/local_device_data_provider.h" - -#include "components/cryptauth/cryptauth_device_manager.h" -#include "components/cryptauth/cryptauth_enrollment_manager.h" -#include "components/cryptauth/cryptauth_service.h" -#include "components/cryptauth/proto/cryptauth_api.pb.h" - -namespace cryptauth { - -LocalDeviceDataProvider::LocalDeviceDataProvider( - CryptAuthService* cryptauth_service) - : cryptauth_service_(cryptauth_service) {} - -LocalDeviceDataProvider::~LocalDeviceDataProvider() {} - -bool LocalDeviceDataProvider::GetLocalDeviceData( - std::string* public_key_out, - std::vector<BeaconSeed>* beacon_seeds_out) const { - DCHECK(public_key_out || beacon_seeds_out); - - std::string public_key = - cryptauth_service_->GetCryptAuthEnrollmentManager()->GetUserPublicKey(); - if (public_key.empty()) { - return false; - } - - std::vector<ExternalDeviceInfo> synced_devices = - cryptauth_service_->GetCryptAuthDeviceManager()->GetSyncedDevices(); - for (const auto& device : synced_devices) { - if (device.has_public_key() && device.public_key() == public_key && - device.beacon_seeds_size() > 0) { - if (public_key_out) { - public_key_out->assign(public_key); - } - - if (beacon_seeds_out) { - beacon_seeds_out->clear(); - for (int i = 0; i < device.beacon_seeds_size(); i++) { - beacon_seeds_out->push_back(device.beacon_seeds(i)); - } - } - - return true; - } - } - - return false; -} - -} // namespace cryptauth
diff --git a/components/cryptauth/local_device_data_provider.h b/components/cryptauth/local_device_data_provider.h deleted file mode 100644 index b93da97c..0000000 --- a/components/cryptauth/local_device_data_provider.h +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2016 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 COMPONENTS_CRYPTAUTH_LOCAL_DEVICE_DATA_PROVIDER_H_ -#define COMPONENTS_CRYPTAUTH_LOCAL_DEVICE_DATA_PROVIDER_H_ - -#include <memory> -#include <string> -#include <vector> - -#include "base/macros.h" - -namespace cryptauth { - -class BeaconSeed; -class CryptAuthService; - -// Fetches CryptAuth data about the local device (i.e., the device on which this -// code is running) for the current user (i.e., the one which is logged-in). -class LocalDeviceDataProvider { - public: - explicit LocalDeviceDataProvider(CryptAuthService* cryptauth_service); - virtual ~LocalDeviceDataProvider(); - - // Fetches the public key and/or the beacon seeds for the local device. - // Returns whether the operation succeeded. If |nullptr| is passed as a - // parameter, the associated data will not be fetched. - virtual bool GetLocalDeviceData( - std::string* public_key_out, - std::vector<BeaconSeed>* beacon_seeds_out) const; - - private: - friend class LocalDeviceDataProviderTest; - - CryptAuthService* cryptauth_service_; - - DISALLOW_COPY_AND_ASSIGN(LocalDeviceDataProvider); -}; - -} // namespace cryptauth - -#endif // COMPONENTS_CRYPTAUTH_LOCAL_DEVICE_DATA_PROVIDER_H_
diff --git a/components/cryptauth/local_device_data_provider_unittest.cc b/components/cryptauth/local_device_data_provider_unittest.cc deleted file mode 100644 index 0ba6e524..0000000 --- a/components/cryptauth/local_device_data_provider_unittest.cc +++ /dev/null
@@ -1,197 +0,0 @@ -// Copyright 2016 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 "components/cryptauth/local_device_data_provider.h" - -#include <memory> -#include <string> -#include <vector> - -#include "base/logging.h" -#include "base/memory/ptr_util.h" -#include "components/cryptauth/cryptauth_enroller.h" -#include "components/cryptauth/fake_cryptauth_device_manager.h" -#include "components/cryptauth/fake_cryptauth_enrollment_manager.h" -#include "components/cryptauth/fake_cryptauth_gcm_manager.h" -#include "components/cryptauth/fake_cryptauth_service.h" -#include "components/cryptauth/proto/cryptauth_api.pb.h" -#include "components/cryptauth/secure_message_delegate.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using testing::NiceMock; -using testing::Return; - -namespace cryptauth { - -namespace { - -const char kDefaultPublicKey[] = "publicKey"; - -const char kBeaconSeed1Data[] = "beaconSeed1Data"; -const int64_t kBeaconSeed1StartMs = 1000L; -const int64_t kBeaconSeed1EndMs = 2000L; - -const char kBeaconSeed2Data[] = "beaconSeed2Data"; -const int64_t kBeaconSeed2StartMs = 2000L; -const int64_t kBeaconSeed2EndMs = 3000L; - -BeaconSeed CreateBeaconSeed(const std::string& data, - int64_t start_ms, - int64_t end_ms) { - BeaconSeed seed; - seed.set_data(data); - seed.set_start_time_millis(start_ms); - seed.set_end_time_millis(end_ms); - return seed; -} - -} // namespace - -class CryptAuthLocalDeviceDataProviderTest : public testing::Test { - protected: - CryptAuthLocalDeviceDataProviderTest() { - fake_beacon_seeds_.push_back(CreateBeaconSeed( - kBeaconSeed1Data, kBeaconSeed1StartMs, kBeaconSeed1EndMs)); - fake_beacon_seeds_.push_back(CreateBeaconSeed( - kBeaconSeed2Data, kBeaconSeed2StartMs, kBeaconSeed2EndMs)); - - // Has no public key and no BeaconSeeds. - ExternalDeviceInfo synced_device1; - fake_synced_devices_.push_back(synced_device1); - - // Has no public key and some BeaconSeeds. - ExternalDeviceInfo synced_device2; - synced_device2.add_beacon_seeds()->CopyFrom(CreateBeaconSeed( - kBeaconSeed1Data, kBeaconSeed1StartMs, kBeaconSeed1EndMs)); - synced_device2.add_beacon_seeds()->CopyFrom(CreateBeaconSeed( - kBeaconSeed2Data, kBeaconSeed2StartMs, kBeaconSeed2EndMs)); - fake_synced_devices_.push_back(synced_device2); - - // Has another different public key and no BeaconSeeds. - ExternalDeviceInfo synced_device3; - synced_device3.set_public_key("anotherPublicKey"); - fake_synced_devices_.push_back(synced_device3); - - // Has different public key and BeaconSeeds. - ExternalDeviceInfo synced_device4; - synced_device4.set_public_key("otherPublicKey"); - synced_device4.add_beacon_seeds()->CopyFrom(CreateBeaconSeed( - kBeaconSeed1Data, kBeaconSeed1StartMs, kBeaconSeed1EndMs)); - synced_device4.add_beacon_seeds()->CopyFrom(CreateBeaconSeed( - kBeaconSeed2Data, kBeaconSeed2StartMs, kBeaconSeed2EndMs)); - fake_synced_devices_.push_back(synced_device4); - - // Has public key but no BeaconSeeds. - ExternalDeviceInfo synced_device5; - synced_device5.set_public_key(kDefaultPublicKey); - fake_synced_devices_.push_back(synced_device5); - - // Has public key and BeaconSeeds. - ExternalDeviceInfo synced_device6; - synced_device6.set_public_key(kDefaultPublicKey); - synced_device6.add_beacon_seeds()->CopyFrom(CreateBeaconSeed( - kBeaconSeed1Data, kBeaconSeed1StartMs, kBeaconSeed1EndMs)); - synced_device6.add_beacon_seeds()->CopyFrom(CreateBeaconSeed( - kBeaconSeed2Data, kBeaconSeed2StartMs, kBeaconSeed2EndMs)); - fake_synced_devices_.push_back(synced_device6); - } - - void SetUp() override { - fake_device_manager_ = std::make_unique<FakeCryptAuthDeviceManager>(); - fake_enrollment_manager_ = - std::make_unique<FakeCryptAuthEnrollmentManager>(); - - fake_cryptauth_service_ = std::make_unique<FakeCryptAuthService>(); - fake_cryptauth_service_->set_cryptauth_device_manager( - fake_device_manager_.get()); - fake_cryptauth_service_->set_cryptauth_enrollment_manager( - fake_enrollment_manager_.get()); - - provider_ = base::WrapUnique( - new LocalDeviceDataProvider(fake_cryptauth_service_.get())); - } - - std::vector<BeaconSeed> fake_beacon_seeds_; - std::vector<ExternalDeviceInfo> fake_synced_devices_; - - std::unique_ptr<FakeCryptAuthDeviceManager> fake_device_manager_; - std::unique_ptr<FakeCryptAuthEnrollmentManager> fake_enrollment_manager_; - std::unique_ptr<FakeCryptAuthService> fake_cryptauth_service_; - - std::unique_ptr<LocalDeviceDataProvider> provider_; - - private: - DISALLOW_COPY_AND_ASSIGN(CryptAuthLocalDeviceDataProviderTest); -}; - -TEST_F(CryptAuthLocalDeviceDataProviderTest, - TestGetLocalDeviceData_NoPublicKey) { - fake_enrollment_manager_->set_user_public_key(std::string()); - fake_device_manager_->set_synced_devices(fake_synced_devices_); - - std::string public_key; - std::vector<BeaconSeed> beacon_seeds; - - EXPECT_FALSE(provider_->GetLocalDeviceData(&public_key, &beacon_seeds)); -} - -TEST_F(CryptAuthLocalDeviceDataProviderTest, - TestGetLocalDeviceData_NoSyncedDevices) { - fake_enrollment_manager_->set_user_public_key(kDefaultPublicKey); - - std::string public_key; - std::vector<BeaconSeed> beacon_seeds; - - EXPECT_FALSE(provider_->GetLocalDeviceData(&public_key, &beacon_seeds)); -} - -TEST_F(CryptAuthLocalDeviceDataProviderTest, - TestGetLocalDeviceData_NoSyncedDeviceMatchingPublicKey) { - fake_enrollment_manager_->set_user_public_key(kDefaultPublicKey); - fake_device_manager_->set_synced_devices(std::vector<ExternalDeviceInfo>{ - fake_synced_devices_[0], fake_synced_devices_[1], fake_synced_devices_[2], - fake_synced_devices_[3]}); - - std::string public_key; - std::vector<BeaconSeed> beacon_seeds; - - EXPECT_FALSE(provider_->GetLocalDeviceData(&public_key, &beacon_seeds)); -} - -TEST_F(CryptAuthLocalDeviceDataProviderTest, - TestGetLocalDeviceData_SyncedDeviceIncludesPublicKeyButNoBeaconSeeds) { - fake_enrollment_manager_->set_user_public_key(kDefaultPublicKey); - fake_device_manager_->synced_devices().push_back(fake_synced_devices_[4]); - - std::string public_key; - std::vector<BeaconSeed> beacon_seeds; - - EXPECT_FALSE(provider_->GetLocalDeviceData(&public_key, &beacon_seeds)); -} - -TEST_F(CryptAuthLocalDeviceDataProviderTest, TestGetLocalDeviceData_Success) { - fake_enrollment_manager_->set_user_public_key(kDefaultPublicKey); - fake_device_manager_->set_synced_devices(fake_synced_devices_); - - std::string public_key; - std::vector<BeaconSeed> beacon_seeds; - - EXPECT_TRUE(provider_->GetLocalDeviceData(&public_key, &beacon_seeds)); - - EXPECT_EQ(kDefaultPublicKey, public_key); - - ASSERT_EQ(fake_beacon_seeds_.size(), beacon_seeds.size()); - for (size_t i = 0; i < fake_beacon_seeds_.size(); i++) { - // Note: google::protobuf::util::MessageDifferencer can only be used to diff - // Message, but BeaconSeed derives from the incompatible MessageLite class. - BeaconSeed expected = fake_beacon_seeds_[i]; - BeaconSeed actual = beacon_seeds[i]; - EXPECT_EQ(expected.data(), actual.data()); - EXPECT_EQ(expected.start_time_millis(), actual.start_time_millis()); - EXPECT_EQ(expected.end_time_millis(), actual.end_time_millis()); - } -} - -} // namespace cryptauth
diff --git a/components/cryptauth/mock_local_device_data_provider.cc b/components/cryptauth/mock_local_device_data_provider.cc deleted file mode 100644 index be56d0b..0000000 --- a/components/cryptauth/mock_local_device_data_provider.cc +++ /dev/null
@@ -1,54 +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 "components/cryptauth/mock_local_device_data_provider.h" - -#include "components/cryptauth/cryptauth_device_manager.h" -#include "components/cryptauth/cryptauth_enrollment_manager.h" -#include "components/cryptauth/proto/cryptauth_api.pb.h" - -namespace cryptauth { - -MockLocalDeviceDataProvider::MockLocalDeviceDataProvider() - : LocalDeviceDataProvider(nullptr /* cryptauth_service */) {} - -MockLocalDeviceDataProvider::~MockLocalDeviceDataProvider() {} - -void MockLocalDeviceDataProvider::SetPublicKey( - std::unique_ptr<std::string> public_key) { - if (public_key) { - public_key_ = std::move(public_key); - } else { - public_key_.reset(); - } -} - -void MockLocalDeviceDataProvider::SetBeaconSeeds( - std::unique_ptr<std::vector<BeaconSeed>> beacon_seeds) { - if (beacon_seeds) { - beacon_seeds_ = std::move(beacon_seeds); - } else { - beacon_seeds_.reset(); - } -} - -bool MockLocalDeviceDataProvider::GetLocalDeviceData( - std::string* public_key_out, - std::vector<BeaconSeed>* beacon_seeds_out) const { - bool success = false; - - if (public_key_ && public_key_out) { - *public_key_out = *public_key_; - success = true; - } - - if (beacon_seeds_ && beacon_seeds_out) { - *beacon_seeds_out = *beacon_seeds_; - success = true; - } - - return success; -} - -} // namespace cryptauth
diff --git a/components/cryptauth/mock_local_device_data_provider.h b/components/cryptauth/mock_local_device_data_provider.h deleted file mode 100644 index 5a4fd8b..0000000 --- a/components/cryptauth/mock_local_device_data_provider.h +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2016 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 COMPONENTS_CRYPTAUTH_MOCK_LOCAL_DEVICE_DATA_PROVIDER_H_ -#define COMPONENTS_CRYPTAUTH_MOCK_LOCAL_DEVICE_DATA_PROVIDER_H_ - -#include <memory> -#include <string> -#include <vector> - -#include "base/macros.h" -#include "components/cryptauth/local_device_data_provider.h" - -namespace cryptauth { - -class BeaconSeed; - -// Test double for LocalDeviceDataProvider. -class MockLocalDeviceDataProvider : public LocalDeviceDataProvider { - public: - MockLocalDeviceDataProvider(); - ~MockLocalDeviceDataProvider() override; - - void SetPublicKey(std::unique_ptr<std::string> public_key); - void SetBeaconSeeds(std::unique_ptr<std::vector<BeaconSeed>> beacon_seeds); - - // LocalDeviceDataProvider: - bool GetLocalDeviceData( - std::string* public_key_out, - std::vector<BeaconSeed>* beacon_seeds_out) const override; - - private: - std::unique_ptr<std::string> public_key_; - std::unique_ptr<std::vector<BeaconSeed>> beacon_seeds_; - - DISALLOW_COPY_AND_ASSIGN(MockLocalDeviceDataProvider); -}; - -} // namespace cryptauth - -#endif // COMPONENTS_CRYPTAUTH_MOCK_LOCAL_DEVICE_DATA_PROVIDER_H_
diff --git a/components/cryptauth/remote_device_loader.cc b/components/cryptauth/remote_device_loader.cc index 71e9c3d..d1d35326 100644 --- a/components/cryptauth/remote_device_loader.cc +++ b/components/cryptauth/remote_device_loader.cc
@@ -12,6 +12,7 @@ #include "base/memory/ptr_util.h" #include "chromeos/components/multidevice/remote_device.h" #include "chromeos/components/multidevice/remote_device_ref.h" +#include "chromeos/components/multidevice/software_feature.h" #include "chromeos/components/proximity_auth/logging/logging.h" #include "components/cryptauth/proto/enum_util.h" #include "components/cryptauth/secure_message_delegate.h" @@ -20,23 +21,31 @@ namespace { -std::map<cryptauth::SoftwareFeature, +std::map<chromeos::multidevice::SoftwareFeature, chromeos::multidevice::SoftwareFeatureState> GetSoftwareFeatureToStateMap(const cryptauth::ExternalDeviceInfo& device) { - std::map<cryptauth::SoftwareFeature, + std::map<chromeos::multidevice::SoftwareFeature, chromeos::multidevice::SoftwareFeatureState> software_feature_to_state_map; for (int i = 0; i < device.supported_software_features_size(); ++i) { - software_feature_to_state_map[SoftwareFeatureStringToEnum( - device.supported_software_features(i))] = - chromeos::multidevice::SoftwareFeatureState::kSupported; + cryptauth::SoftwareFeature feature = + SoftwareFeatureStringToEnum(device.supported_software_features(i)); + if (feature == UNKNOWN_FEATURE) + continue; + + software_feature_to_state_map[chromeos::multidevice::FromCryptAuthFeature( + feature)] = chromeos::multidevice::SoftwareFeatureState::kSupported; } for (int i = 0; i < device.enabled_software_features_size(); ++i) { - software_feature_to_state_map[SoftwareFeatureStringToEnum( - device.enabled_software_features(i))] = - chromeos::multidevice::SoftwareFeatureState::kEnabled; + cryptauth::SoftwareFeature feature = + SoftwareFeatureStringToEnum(device.enabled_software_features(i)); + if (feature == UNKNOWN_FEATURE) + continue; + + software_feature_to_state_map[chromeos::multidevice::FromCryptAuthFeature( + feature)] = chromeos::multidevice::SoftwareFeatureState::kEnabled; } return software_feature_to_state_map; @@ -128,14 +137,16 @@ DCHECK(iterator != remaining_devices_.end()); remaining_devices_.erase(iterator); - std::vector<BeaconSeed> beacon_seeds; - for (const BeaconSeed& beacon_seed : device.beacon_seeds()) - beacon_seeds.push_back(beacon_seed); + std::vector<chromeos::multidevice::BeaconSeed> multidevice_beacon_seeds; + for (const BeaconSeed& cryptauth_beacon_seed : device.beacon_seeds()) { + multidevice_beacon_seeds.push_back( + chromeos::multidevice::FromCryptAuthSeed(cryptauth_beacon_seed)); + } chromeos::multidevice::RemoteDevice remote_device( user_id_, device.friendly_device_name(), device.public_key(), psk, device.last_update_time_millis(), GetSoftwareFeatureToStateMap(device), - beacon_seeds); + multidevice_beacon_seeds); remote_devices_.push_back(remote_device);
diff --git a/components/cryptauth/remote_device_loader_unittest.cc b/components/cryptauth/remote_device_loader_unittest.cc index 1eb45035..ce8db53 100644 --- a/components/cryptauth/remote_device_loader_unittest.cc +++ b/components/cryptauth/remote_device_loader_unittest.cc
@@ -112,7 +112,8 @@ EXPECT_EQ(device_infos[0].public_key(), remote_devices_[0].public_key); ASSERT_EQ(1u, remote_devices_[0].beacon_seeds.size()); - const BeaconSeed& beacon_seed = remote_devices_[0].beacon_seeds[0]; + const BeaconSeed& beacon_seed = chromeos::multidevice::ToCryptAuthSeed( + remote_devices_[0].beacon_seeds[0]); EXPECT_EQ(kBeaconSeedData, beacon_seed.data()); EXPECT_EQ(kBeaconSeedStartTimeMs, beacon_seed.start_time_millis()); EXPECT_EQ(kBeaconSeedEndTimeMs, beacon_seed.end_time_millis()); @@ -170,12 +171,17 @@ EXPECT_EQ(1u, remote_devices_.size()); - EXPECT_EQ(chromeos::multidevice::SoftwareFeatureState::kSupported, - remote_devices_[0].software_features[BETTER_TOGETHER_CLIENT]); + EXPECT_EQ( + chromeos::multidevice::SoftwareFeatureState::kSupported, + remote_devices_[0].software_features + [chromeos::multidevice::SoftwareFeature::kBetterTogetherClient]); EXPECT_EQ(chromeos::multidevice::SoftwareFeatureState::kEnabled, - remote_devices_[0].software_features[BETTER_TOGETHER_HOST]); - EXPECT_EQ(chromeos::multidevice::SoftwareFeatureState::kNotSupported, - remote_devices_[0].software_features[MAGIC_TETHER_HOST]); + remote_devices_[0].software_features + [chromeos::multidevice::SoftwareFeature::kBetterTogetherHost]); + EXPECT_EQ( + chromeos::multidevice::SoftwareFeatureState::kNotSupported, + remote_devices_[0].software_features + [chromeos::multidevice::SoftwareFeature::kInstantTetheringHost]); } } // namespace cryptauth
diff --git a/components/cryptauth/software_feature_manager.h b/components/cryptauth/software_feature_manager.h index e87f5db..28301b2 100644 --- a/components/cryptauth/software_feature_manager.h +++ b/components/cryptauth/software_feature_manager.h
@@ -6,8 +6,8 @@ #define COMPONENTS_CRYPTAUTH_SOFTWARE_FEATURE_MANAGER_H_ #include "base/callback.h" +#include "chromeos/components/multidevice/software_feature.h" #include "components/cryptauth/network_request_error.h" -#include "components/cryptauth/proto/cryptauth_api.pb.h" namespace cryptauth { @@ -27,7 +27,7 @@ // ignored. virtual void SetSoftwareFeatureState( const std::string& public_key, - SoftwareFeature software_feature, + chromeos::multidevice::SoftwareFeature software_feature, bool enabled, const base::Closure& success_callback, const base::Callback<void(NetworkRequestError)>& error_callback, @@ -36,7 +36,7 @@ // Finds eligible devices associated with the logged-in account which support // |software_feature|. virtual void FindEligibleDevices( - SoftwareFeature software_feature, + chromeos::multidevice::SoftwareFeature software_feature, const base::Callback<void(const std::vector<ExternalDeviceInfo>&, const std::vector<IneligibleDevice>&)>& success_callback,
diff --git a/components/cryptauth/software_feature_manager_impl.cc b/components/cryptauth/software_feature_manager_impl.cc index de3bb7d..34bc506 100644 --- a/components/cryptauth/software_feature_manager_impl.cc +++ b/components/cryptauth/software_feature_manager_impl.cc
@@ -72,7 +72,7 @@ void SoftwareFeatureManagerImpl::SetSoftwareFeatureState( const std::string& public_key, - SoftwareFeature software_feature, + chromeos::multidevice::SoftwareFeature software_feature, bool enabled, const base::Closure& success_callback, const base::Callback<void(NetworkRequestError)>& error_callback, @@ -80,15 +80,16 @@ // Note: For legacy reasons, this proto message mentions "ToggleEasyUnlock" // instead of "SetSoftwareFeature" in its name. auto request = std::make_unique<ToggleEasyUnlockRequest>(); - request->set_feature( - cryptauth::SoftwareFeatureEnumToString(software_feature)); + request->set_feature(cryptauth::SoftwareFeatureEnumToString( + chromeos::multidevice::ToCryptAuthFeature(software_feature))); request->set_enable(enabled); request->set_is_exclusive(enabled && is_exclusive); // Special case for EasyUnlock: if EasyUnlock is being disabled, set the // apply_to_all property to true, and do not set the public_key field. bool turn_off_easy_unlock_special_case = - !enabled && software_feature == SoftwareFeature::EASY_UNLOCK_HOST; + !enabled && software_feature == + chromeos::multidevice::SoftwareFeature::kSmartLockHost; request->set_apply_to_all(turn_off_easy_unlock_special_case); if (!turn_off_easy_unlock_special_case) request->set_public_key(public_key); @@ -99,7 +100,7 @@ } void SoftwareFeatureManagerImpl::FindEligibleDevices( - SoftwareFeature software_feature, + chromeos::multidevice::SoftwareFeature software_feature, const base::Callback<void(const std::vector<ExternalDeviceInfo>&, const std::vector<IneligibleDevice>&)>& success_callback, @@ -107,14 +108,14 @@ // Note: For legacy reasons, this proto message mentions "UnlockDevices" // instead of "MultiDeviceHosts" in its name. auto request = std::make_unique<FindEligibleUnlockDevicesRequest>(); - request->set_feature( - cryptauth::SoftwareFeatureEnumToString(software_feature)); + request->set_feature(cryptauth::SoftwareFeatureEnumToString( + chromeos::multidevice::ToCryptAuthFeature(software_feature))); // For historical reasons, the Bluetooth address is abused to mark a which // feature should receive a GCM callback. Read more at // https://crbug.com/883915. - request->set_callback_bluetooth_address( - SoftwareFeatureEnumToStringAllCaps(software_feature)); + request->set_callback_bluetooth_address(SoftwareFeatureEnumToStringAllCaps( + chromeos::multidevice::ToCryptAuthFeature(software_feature))); pending_requests_.emplace(std::make_unique<Request>( std::move(request), success_callback, error_callback));
diff --git a/components/cryptauth/software_feature_manager_impl.h b/components/cryptauth/software_feature_manager_impl.h index e233303..a490d99 100644 --- a/components/cryptauth/software_feature_manager_impl.h +++ b/components/cryptauth/software_feature_manager_impl.h
@@ -41,13 +41,13 @@ // SoftwareFeatureManager: void SetSoftwareFeatureState( const std::string& public_key, - SoftwareFeature software_feature, + chromeos::multidevice::SoftwareFeature software_feature, bool enabled, const base::Closure& success_callback, const base::Callback<void(NetworkRequestError)>& error_callback, bool is_exclusive = false) override; void FindEligibleDevices( - SoftwareFeature software_feature, + chromeos::multidevice::SoftwareFeature software_feature, const base::Callback<void(const std::vector<ExternalDeviceInfo>&, const std::vector<IneligibleDevice>&)>& success_callback,
diff --git a/components/cryptauth/software_feature_manager_impl_unittest.cc b/components/cryptauth/software_feature_manager_impl_unittest.cc index 15b2b9a..66fb9ff 100644 --- a/components/cryptauth/software_feature_manager_impl_unittest.cc +++ b/components/cryptauth/software_feature_manager_impl_unittest.cc
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "chromeos/components/multidevice/remote_device_ref.h" #include "chromeos/components/multidevice/remote_device_test_util.h" +#include "chromeos/components/multidevice/software_feature.h" #include "components/cryptauth/mock_cryptauth_client.h" #include "components/cryptauth/proto/enum_util.h" #include "testing/gmock/include/gmock/gmock.h" @@ -153,7 +154,7 @@ result_ineligible_devices_.clear(); } - void SetSoftwareFeatureState(SoftwareFeature feature, + void SetSoftwareFeatureState(chromeos::multidevice::SoftwareFeature feature, const ExternalDeviceInfo& device_info, bool enabled, bool is_exclusive = false) { @@ -167,7 +168,7 @@ is_exclusive); } - void FindEligibleDevices(SoftwareFeature feature) { + void FindEligibleDevices(chromeos::multidevice::SoftwareFeature feature) { software_feature_manager_->FindEligibleDevices( feature, base::Bind( @@ -261,14 +262,16 @@ }; TEST_F(CryptAuthSoftwareFeatureManagerImplTest, TestOrderUponMultipleRequests) { - SetSoftwareFeatureState(SoftwareFeature::BETTER_TOGETHER_HOST, - test_eligible_external_devices_infos_[0], - true /* enable */); - FindEligibleDevices(SoftwareFeature::BETTER_TOGETHER_HOST); - SetSoftwareFeatureState(SoftwareFeature::BETTER_TOGETHER_CLIENT, - test_eligible_external_devices_infos_[1], - false /* enable */); - FindEligibleDevices(SoftwareFeature::BETTER_TOGETHER_CLIENT); + SetSoftwareFeatureState( + chromeos::multidevice::SoftwareFeature::kBetterTogetherHost, + test_eligible_external_devices_infos_[0], true /* enable */); + FindEligibleDevices( + chromeos::multidevice::SoftwareFeature::kBetterTogetherHost); + SetSoftwareFeatureState( + chromeos::multidevice::SoftwareFeature::kBetterTogetherClient, + test_eligible_external_devices_infos_[1], false /* enable */); + FindEligibleDevices( + chromeos::multidevice::SoftwareFeature::kBetterTogetherClient); EXPECT_EQ(SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_HOST), last_toggle_request_.feature()); @@ -305,15 +308,15 @@ TEST_F(CryptAuthSoftwareFeatureManagerImplTest, TestMultipleSetUnlocksRequests) { - SetSoftwareFeatureState(SoftwareFeature::BETTER_TOGETHER_HOST, - test_eligible_external_devices_infos_[0], - true /* enable */); - SetSoftwareFeatureState(SoftwareFeature::BETTER_TOGETHER_CLIENT, - test_eligible_external_devices_infos_[1], - false /* enable */); - SetSoftwareFeatureState(SoftwareFeature::BETTER_TOGETHER_HOST, - test_eligible_external_devices_infos_[2], - true /* enable */); + SetSoftwareFeatureState( + chromeos::multidevice::SoftwareFeature::kBetterTogetherHost, + test_eligible_external_devices_infos_[0], true /* enable */); + SetSoftwareFeatureState( + chromeos::multidevice::SoftwareFeature::kBetterTogetherClient, + test_eligible_external_devices_infos_[1], false /* enable */); + SetSoftwareFeatureState( + chromeos::multidevice::SoftwareFeature::kBetterTogetherHost, + test_eligible_external_devices_infos_[2], true /* enable */); EXPECT_EQ(SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_HOST), last_toggle_request_.feature()); @@ -340,9 +343,12 @@ TEST_F(CryptAuthSoftwareFeatureManagerImplTest, TestMultipleFindEligibleForUnlockDevicesRequests) { - FindEligibleDevices(SoftwareFeature::BETTER_TOGETHER_HOST); - FindEligibleDevices(SoftwareFeature::BETTER_TOGETHER_CLIENT); - FindEligibleDevices(SoftwareFeature::BETTER_TOGETHER_HOST); + FindEligibleDevices( + chromeos::multidevice::SoftwareFeature::kBetterTogetherHost); + FindEligibleDevices( + chromeos::multidevice::SoftwareFeature::kBetterTogetherClient); + FindEligibleDevices( + chromeos::multidevice::SoftwareFeature::kBetterTogetherHost); EXPECT_EQ(SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_HOST), last_find_request_.feature()); @@ -370,10 +376,11 @@ } TEST_F(CryptAuthSoftwareFeatureManagerImplTest, TestOrderViaMultipleErrors) { - SetSoftwareFeatureState(SoftwareFeature::BETTER_TOGETHER_HOST, - test_eligible_external_devices_infos_[0], - true /* enable */); - FindEligibleDevices(SoftwareFeature::BETTER_TOGETHER_HOST); + SetSoftwareFeatureState( + chromeos::multidevice::SoftwareFeature::kBetterTogetherHost, + test_eligible_external_devices_infos_[0], true /* enable */); + FindEligibleDevices( + chromeos::multidevice::SoftwareFeature::kBetterTogetherHost); EXPECT_EQ(SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_HOST), last_toggle_request_.feature()); @@ -389,9 +396,10 @@ } TEST_F(CryptAuthSoftwareFeatureManagerImplTest, TestIsExclusive) { - SetSoftwareFeatureState(SoftwareFeature::BETTER_TOGETHER_HOST, - test_eligible_external_devices_infos_[0], - true /* enable */, true /* is_exclusive */); + SetSoftwareFeatureState( + chromeos::multidevice::SoftwareFeature::kBetterTogetherHost, + test_eligible_external_devices_infos_[0], true /* enable */, + true /* is_exclusive */); EXPECT_EQ(SoftwareFeatureEnumToString(SoftwareFeature::BETTER_TOGETHER_HOST), last_toggle_request_.feature()); @@ -402,9 +410,9 @@ } TEST_F(CryptAuthSoftwareFeatureManagerImplTest, TestEasyUnlockSpecialCase) { - SetSoftwareFeatureState(SoftwareFeature::EASY_UNLOCK_HOST, - test_eligible_external_devices_infos_[0], - false /* enable */); + SetSoftwareFeatureState( + chromeos::multidevice::SoftwareFeature::kSmartLockHost, + test_eligible_external_devices_infos_[0], false /* enable */); EXPECT_EQ(SoftwareFeatureEnumToString(SoftwareFeature::EASY_UNLOCK_HOST), last_toggle_request_.feature());
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.cc index d5a6fa6..6c5d235 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_util.cc
@@ -189,7 +189,8 @@ return false; proxy_config.proxy_rules().Apply(url, data_reduction_proxy_info); data_reduction_proxy_info->DeprioritizeBadProxies(proxy_retry_info); - return !data_reduction_proxy_info->proxy_server().is_direct(); + return !data_reduction_proxy_info->is_empty() && + !data_reduction_proxy_info->proxy_server().is_direct(); } int64_t CalculateOCLFromOFCL(const net::URLRequest& request) {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_util_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_util_unittest.cc index 9f4c680b..ecdeafdc 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_util_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_util_unittest.cc
@@ -10,6 +10,8 @@ #include "base/time/time.h" #include "components/data_reduction_proxy/proto/client_config.pb.h" +#include "net/proxy_resolution/proxy_config.h" +#include "net/proxy_resolution/proxy_info.h" #include "testing/gtest/include/gtest/gtest.h" namespace data_reduction_proxy { @@ -93,4 +95,20 @@ } } +TEST(DataReductionProxyUtilTest, AllProxiesBad) { + net::ProxyConfig config; + config.proxy_rules().ParseFromString("http=foo"); + + net::ProxyInfo result; + result.UseDirect(); + net::ProxyRetryInfoMap retry_map; + net::ProxyRetryInfo& info = retry_map["foo:80"]; + info.try_while_bad = false; + info.bad_until = base::TimeTicks::Now() + base::TimeDelta::FromDays(2); + EXPECT_FALSE(util::ApplyProxyConfigToProxyInfo( + config, retry_map, GURL("http://foo.com"), &result)); + + EXPECT_TRUE(result.is_empty()); +} + } // namespace data_reduction_proxy
diff --git a/components/download/BUILD.gn b/components/download/BUILD.gn index 737c02e..d022618 100644 --- a/components/download/BUILD.gn +++ b/components/download/BUILD.gn
@@ -12,6 +12,7 @@ "//components/download/database:unit_tests", "//components/download/internal/background_service:unit_tests", "//components/download/internal/common:unit_tests", + "//components/download/public/background_service:unit_tests", "//components/download/quarantine:unit_tests", ] }
diff --git a/components/download/components_unittests.filter b/components/download/components_unittests.filter index 6e37329..131c382f 100644 --- a/components/download/components_unittests.filter +++ b/components/download/components_unittests.filter
@@ -15,4 +15,5 @@ NavigationMonitorImplTest.* NetworkListenerTest.* ProtoConversionsTest.* -ServiceConfigImplTest.* \ No newline at end of file +ServiceConfigImplTest.* +TaskManagerTest.*
diff --git a/components/download/content/internal/download_driver_impl.cc b/components/download/content/internal/download_driver_impl.cc index 89323e37..10c8a8b7 100644 --- a/components/download/content/internal/download_driver_impl.cc +++ b/components/download/content/internal/download_driver_impl.cc
@@ -209,7 +209,7 @@ return; DownloadItem* item = download_manager_->GetDownloadByGuid(guid); if (item) - item->Resume(); + item->Resume(true); } base::Optional<DriverEntry> DownloadDriverImpl::Find(const std::string& guid) {
diff --git a/components/download/database/download_db_conversions.cc b/components/download/database/download_db_conversions.cc index 4cffb21..4691f09 100644 --- a/components/download/database/download_db_conversions.cc +++ b/components/download/database/download_db_conversions.cc
@@ -194,6 +194,7 @@ proto.set_paused(in_progress_info.paused); proto.set_metered(in_progress_info.metered); proto.set_bytes_wasted(in_progress_info.bytes_wasted); + proto.set_auto_resume_count(in_progress_info.auto_resume_count); return proto; } @@ -247,6 +248,7 @@ info.paused = proto.paused(); info.metered = proto.metered(); info.bytes_wasted = proto.bytes_wasted(); + info.auto_resume_count = proto.auto_resume_count(); return info; }
diff --git a/components/download/database/download_db_conversions_unittest.cc b/components/download/database/download_db_conversions_unittest.cc index b82cd5e..0dfbd56 100644 --- a/components/download/database/download_db_conversions_unittest.cc +++ b/components/download/database/download_db_conversions_unittest.cc
@@ -40,6 +40,7 @@ info.received_slices.emplace_back(0, 500, false); info.received_slices.emplace_back(5000, 500, false); info.bytes_wasted = 1234; + info.auto_resume_count = 3; info.fetch_error_body = true; info.request_headers.emplace_back( std::make_pair<std::string, std::string>("123", "456"));
diff --git a/components/download/database/in_progress/in_progress_info.cc b/components/download/database/in_progress/in_progress_info.cc index 15f6dd4..7cb0c20 100644 --- a/components/download/database/in_progress/in_progress_info.cc +++ b/components/download/database/in_progress/in_progress_info.cc
@@ -29,7 +29,8 @@ transient == other.transient && state == other.state && danger_type == other.danger_type && interrupt_reason == other.interrupt_reason && paused == other.paused && - metered == other.metered && bytes_wasted == other.bytes_wasted; + metered == other.metered && bytes_wasted == other.bytes_wasted && + auto_resume_count == other.auto_resume_count; } } // namespace download
diff --git a/components/download/database/in_progress/in_progress_info.h b/components/download/database/in_progress/in_progress_info.h index 4f62954..3f7b5fac 100644 --- a/components/download/database/in_progress/in_progress_info.h +++ b/components/download/database/in_progress/in_progress_info.h
@@ -114,6 +114,10 @@ // Count for how many (extra) bytes were used (including resumption). int64_t bytes_wasted = 0; + // The number of times the download has been auto-resumed since last user + // triggered resumption. + int32_t auto_resume_count = 0; + // Whether the download is initiated on a metered network bool metered = false; };
diff --git a/components/download/database/proto/download_entry.proto b/components/download/database/proto/download_entry.proto index 026c2aa..cbed5951 100644 --- a/components/download/database/proto/download_entry.proto +++ b/components/download/database/proto/download_entry.proto
@@ -72,6 +72,7 @@ optional bool paused = 24; optional bool metered = 25; optional int64 bytes_wasted = 26; + optional int32 auto_resume_count = 27; } // Stores various metadata related to a download.
diff --git a/components/download/internal/common/download_item_impl.cc b/components/download/internal/common/download_item_impl.cc index efbaf03..b5fd270b 100644 --- a/components/download/internal/common/download_item_impl.cc +++ b/components/download/internal/common/download_item_impl.cc
@@ -293,11 +293,13 @@ const std::string& last_modified, int64_t received_bytes, int64_t total_bytes, + int32_t auto_resume_count, const std::string& hash, DownloadItem::DownloadState state, DownloadDangerType danger_type, DownloadInterruptReason interrupt_reason, bool paused, + bool allow_metered, bool opened, base::Time last_access_time, bool transient, @@ -324,6 +326,7 @@ danger_type_(danger_type), delegate_(delegate), paused_(paused), + allow_metered_(allow_metered), opened_(opened), last_access_time_(last_access_time), transient_(transient), @@ -333,6 +336,7 @@ state == COMPLETE, hash, end_time), + auto_resume_count_(auto_resume_count), last_modified_time_(last_modified), etag_(etag), received_slices_(received_slices), @@ -386,6 +390,7 @@ weak_ptr_factory_(this) { delegate_->Attach(); Init(true /* actively downloading */, TYPE_ACTIVE_DOWNLOAD); + allow_metered_ |= delegate_->IsActiveNetworkMetered(); TRACE_EVENT_INSTANT0("download", "DownloadStarted", TRACE_EVENT_SCOPE_THREAD); } @@ -526,6 +531,7 @@ case RESUMING_INTERNAL: // No active request. paused_ = true; + UpdateObservers(); return; case IN_PROGRESS_INTERNAL: @@ -541,7 +547,7 @@ } } -void DownloadItemImpl::Resume() { +void DownloadItemImpl::Resume(bool user_resume) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DVLOG(20) << __func__ << "() download = " << DebugString(true); switch (state_) { @@ -560,12 +566,17 @@ paused_ = false; if (job_) job_->Resume(true); + + UpdateResumptionInfo(true); UpdateObservers(); return; case INTERRUPTED_INTERNAL: + UpdateResumptionInfo(paused_ || user_resume); paused_ = false; - auto_resume_count_ = 0; // User input resets the counter. + if (auto_resume_count_ >= kMaxAutoResumeAttempts) + return; + ResumeInterruptedDownload(ResumptionRequestSource::USER); UpdateObservers(); return; @@ -576,6 +587,13 @@ } } +void DownloadItemImpl::UpdateResumptionInfo(bool user_resume) { + if (user_resume) + allow_metered_ |= delegate_->IsActiveNetworkMetered(); + + auto_resume_count_ = user_resume ? 0 : auto_resume_count_++; +} + void DownloadItemImpl::Cancel(bool user_cancel) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DVLOG(20) << __func__ << "() download = " << DebugString(true); @@ -651,6 +669,10 @@ return paused_; } +bool DownloadItemImpl::AllowMetered() const { + return allow_metered_; +} + bool DownloadItemImpl::IsTemporary() const { return is_temporary_; } @@ -693,6 +715,10 @@ return bytes_wasted_; } +int32_t DownloadItemImpl::GetAutoResumeCount() const { + return auto_resume_count_; +} + const GURL& DownloadItemImpl::GetURL() const { return request_info_.url_chain.empty() ? GURL::EmptyGURL() : request_info_.url_chain.back();
diff --git a/components/download/internal/common/download_item_impl_delegate.cc b/components/download/internal/common/download_item_impl_delegate.cc index bc3f9c3..973248a 100644 --- a/components/download/internal/common/download_item_impl_delegate.cc +++ b/components/download/internal/common/download_item_impl_delegate.cc
@@ -93,6 +93,10 @@ return false; } +bool DownloadItemImplDelegate::IsActiveNetworkMetered() const { + return false; +} + void DownloadItemImplDelegate::ReportBytesWasted(DownloadItemImpl* download) {} } // namespace download
diff --git a/components/download/internal/common/download_item_impl_unittest.cc b/components/download/internal/common/download_item_impl_unittest.cc index d1689fa0..06e966d 100644 --- a/components/download/internal/common/download_item_impl_unittest.cc +++ b/components/download/internal/common/download_item_impl_unittest.cc
@@ -591,7 +591,7 @@ ASSERT_TRUE(item->IsPaused()); - item->Resume(); + item->Resume(false); ASSERT_TRUE(observer.CheckAndResetDownloadUpdated()); task_environment_.RunUntilIdle();
diff --git a/components/download/internal/common/download_utils.cc b/components/download/internal/common/download_utils.cc index 750ecf85..d8b629f8 100644 --- a/components/download/internal/common/download_utils.cc +++ b/components/download/internal/common/download_utils.cc
@@ -379,7 +379,9 @@ in_progress_info.danger_type = item.GetDangerType(); in_progress_info.interrupt_reason = item.GetLastReason(); in_progress_info.paused = item.IsPaused(); + in_progress_info.metered = item.AllowMetered(); in_progress_info.bytes_wasted = item.GetBytesWasted(); + in_progress_info.auto_resume_count = item.GetAutoResumeCount(); download_info.in_progress_info = in_progress_info; @@ -424,8 +426,15 @@ return ResumeMode::INVALID; switch (reason) { - case DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR: case DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT: +#if defined(OS_ANDROID) + // If resume mode is USER_CONTINUE, android can still resume + // the download automatically if we didn't reach the auto resumption + // limit and the interruption was due to network related reasons. + user_action_required = true; + break; +#endif + case DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR: case DOWNLOAD_INTERRUPT_REASON_SERVER_CONTENT_LENGTH_MISMATCH: break;
diff --git a/components/download/internal/common/in_progress_download_manager.cc b/components/download/internal/common/in_progress_download_manager.cc index a017751..276d856 100644 --- a/components/download/internal/common/in_progress_download_manager.cc +++ b/components/download/internal/common/in_progress_download_manager.cc
@@ -53,11 +53,11 @@ in_progress_info->original_mime_type, in_progress_info->start_time, in_progress_info->end_time, in_progress_info->etag, in_progress_info->last_modified, in_progress_info->received_bytes, - in_progress_info->total_bytes, in_progress_info->hash, - in_progress_info->state, in_progress_info->danger_type, - in_progress_info->interrupt_reason, in_progress_info->paused, false, - base::Time(), in_progress_info->transient, - in_progress_info->received_slices); + in_progress_info->total_bytes, in_progress_info->auto_resume_count, + in_progress_info->hash, in_progress_info->state, + in_progress_info->danger_type, in_progress_info->interrupt_reason, + in_progress_info->paused, in_progress_info->metered, false, base::Time(), + in_progress_info->transient, in_progress_info->received_slices); } void OnUrlDownloadHandlerCreated(
diff --git a/components/download/public/background_service/BUILD.gn b/components/download/public/background_service/BUILD.gn index 7a878a0a..4a91c71 100644 --- a/components/download/public/background_service/BUILD.gn +++ b/components/download/public/background_service/BUILD.gn
@@ -22,6 +22,8 @@ "logger.h", "navigation_monitor.h", "service_config.h", + "task_manager.cc", + "task_manager.h", "task_scheduler.h", ] @@ -60,3 +62,18 @@ ] } } + +source_set("unit_tests") { + testonly = true + + sources = [ + "task_manager_unittest.cc", + ] + + deps = [ + "//base/test:test_support", + "//components/download/public/background_service:public", + "//testing/gmock", + "//testing/gtest", + ] +}
diff --git a/components/download/public/background_service/task_manager.cc b/components/download/public/background_service/task_manager.cc new file mode 100644 index 0000000..085b77f --- /dev/null +++ b/components/download/public/background_service/task_manager.cc
@@ -0,0 +1,114 @@ +// 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 "components/download/public/background_service/task_manager.h" + +namespace download { +namespace { + +bool HasDuplicateParams( + const std::map<DownloadTaskType, TaskManager::TaskParams>& map, + DownloadTaskType task_type, + const TaskManager::TaskParams& params) { + auto it = map.find(task_type); + return it != map.end() && it->second == params; +} + +} // namespace + +TaskManager::TaskParams::TaskParams() + : require_unmetered_network(false), + require_charging(false), + optimal_battery_percentage(0), + window_start_time_seconds(0), + window_end_time_seconds(0) {} + +bool TaskManager::TaskParams::operator==( + const TaskManager::TaskParams& other) const { + return require_unmetered_network == other.require_unmetered_network && + require_charging == other.require_charging && + optimal_battery_percentage == other.optimal_battery_percentage && + window_start_time_seconds == other.window_start_time_seconds && + window_end_time_seconds == other.window_end_time_seconds; +} + +TaskManager::TaskManager(std::unique_ptr<TaskScheduler> task_scheduler) + : task_scheduler_(std::move(task_scheduler)) {} + +TaskManager::~TaskManager() = default; + +void TaskManager::ScheduleTask(DownloadTaskType task_type, + const TaskParams& params) { + if (HasDuplicateParams(current_task_params_, task_type, params) || + HasDuplicateParams(pending_task_params_, task_type, params)) { + return; + } + + pending_task_params_[task_type] = params; + if (IsRunningTask(task_type)) + return; + + task_scheduler_->ScheduleTask( + task_type, params.require_unmetered_network, params.require_charging, + params.optimal_battery_percentage, params.window_start_time_seconds, + params.window_end_time_seconds); +} + +void TaskManager::UnscheduleTask(DownloadTaskType task_type) { + pending_task_params_.erase(task_type); + if (IsRunningTask(task_type)) + return; + + task_scheduler_->CancelTask(task_type); +} + +void TaskManager::OnStartScheduledTask(DownloadTaskType task_type, + TaskFinishedCallback callback) { + DCHECK(pending_task_params_.find(task_type) != pending_task_params_.end()); + current_task_params_[task_type] = pending_task_params_[task_type]; + pending_task_params_.erase(task_type); + + DCHECK(!IsRunningTask(task_type)); + task_finished_callbacks_[task_type] = std::move(callback); +} + +void TaskManager::OnStopScheduledTask(DownloadTaskType task_type) { + DCHECK(IsRunningTask(task_type)); + current_task_params_.erase(task_type); + task_finished_callbacks_.erase(task_type); + + if (pending_task_params_.find(task_type) != pending_task_params_.end()) { + auto params = pending_task_params_[task_type]; + pending_task_params_.erase(task_type); + ScheduleTask(task_type, params); + } +} + +bool TaskManager::IsRunningTask(DownloadTaskType task_type) const { + return task_finished_callbacks_.find(task_type) != + task_finished_callbacks_.end(); +} + +void TaskManager::NotifyTaskFinished(DownloadTaskType task_type, + bool needs_reschedule) { + if (!IsRunningTask(task_type)) + return; + + current_task_params_.erase(task_type); + + bool has_pending_params = + pending_task_params_.find(task_type) != pending_task_params_.end(); + + std::move(task_finished_callbacks_[task_type]) + .Run(needs_reschedule && !has_pending_params); + task_finished_callbacks_.erase(task_type); + + if (has_pending_params) { + auto params = pending_task_params_[task_type]; + pending_task_params_.erase(task_type); + ScheduleTask(task_type, params); + } +} + +} // namespace download
diff --git a/components/download/public/background_service/task_manager.h b/components/download/public/background_service/task_manager.h new file mode 100644 index 0000000..c0bf734 --- /dev/null +++ b/components/download/public/background_service/task_manager.h
@@ -0,0 +1,92 @@ +// 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 COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_TASK_MANAGER_H_ +#define COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_TASK_MANAGER_H_ + +#include <stdint.h> +#include <map> + +#include "base/callback.h" +#include "components/download/public/background_service/task_scheduler.h" + +namespace download { + +using TaskFinishedCallback = base::OnceCallback<void(bool)>; + +// A class to manage the calls made to the TaskScheduler, that abstracts away +// the details of the TaskScheduler from the calling code. The tasks can run +// independently of each other as long as they have different |task_type|. +// Scheduling another task of same |task_type| before the task is started will +// overwrite the params of the scheduled task. +class TaskManager { + public: + // Params used when scheduling a task through TaskScheduler::ScheduleTask(). + struct TaskParams { + TaskParams(); + ~TaskParams() = default; + bool operator==(const TaskParams& other) const; + + bool require_unmetered_network; + bool require_charging; + int optimal_battery_percentage; + int64_t window_start_time_seconds; + int64_t window_end_time_seconds; + }; + + explicit TaskManager(std::unique_ptr<TaskScheduler> task_scheduler); + ~TaskManager(); + + // Called to schedule a new task. Overwrites the params if a task of the same + // type is already scheduled. If the task is currently running, it will cache + // the params and schedule the task after the completion/stopping of the + // current task. + void ScheduleTask(DownloadTaskType task_type, const TaskParams& params); + + // Called to unschedule a scheduled task of the given type if it is not yet + // started. Doesn't cancel the currently running task. + void UnscheduleTask(DownloadTaskType task_type); + + // Called when the system starts a scheduled task. The callback will be cached + // by the class and run after receiving a call to NotifyTaskFinished(). + void OnStartScheduledTask(DownloadTaskType task_type, + TaskFinishedCallback callback); + + // Called when the system decides to stop an already running task. + void OnStopScheduledTask(DownloadTaskType task_type); + + // Should be called once the task is complete. The callback passed through + // OnStartScheduledTask() will be run in order to notify that the task is done + // and the system should reschedule the task with the original params if + // |needs_reschedule| is true. If there are pending params for a new task, a + // new task will be scheduled immediately and reschedule logic will not be + // run. + void NotifyTaskFinished(DownloadTaskType task_type, bool needs_reschedule); + + private: + // Whether a task of the given type is already running. + bool IsRunningTask(DownloadTaskType task_type) const; + + std::unique_ptr<TaskScheduler> task_scheduler_; + + // Contains the params for the currently running task, which gets cleared + // after the task is completed or stopped. + std::map<DownloadTaskType, TaskParams> current_task_params_; + + // Contains params for the task to be scheduled. If a task is currently + // running, the new task will be scheduled after the current task is finished + // or immediately if there is no task running right now. The params will move + // to current_task_params_ when the task is started. + std::map<DownloadTaskType, TaskParams> pending_task_params_; + + // Contains the callbacks passed through the OnStartScheduledTask(). These + // will be cleared when the task is completed or stopped by the system. + std::map<DownloadTaskType, TaskFinishedCallback> task_finished_callbacks_; + + DISALLOW_COPY_AND_ASSIGN(TaskManager); +}; + +} // namespace download + +#endif // COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_TASK_MANAGER_H_
diff --git a/components/download/public/background_service/task_manager_unittest.cc b/components/download/public/background_service/task_manager_unittest.cc new file mode 100644 index 0000000..d2d34e8 --- /dev/null +++ b/components/download/public/background_service/task_manager_unittest.cc
@@ -0,0 +1,247 @@ +// 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 "components/download/public/background_service/task_manager.h" + +#include <stdint.h> +#include <memory> +#include <utility> + +#include "base/test/test_mock_time_task_runner.h" +#include "base/test/test_simple_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace download { +namespace { + +class MockTaskScheduler : public TaskScheduler { + public: + MockTaskScheduler() = default; + ~MockTaskScheduler() override = default; + + // TaskScheduler implementation. + MOCK_METHOD6(ScheduleTask, + void(DownloadTaskType, bool, bool, int, int64_t, int64_t)); + MOCK_METHOD1(CancelTask, void(DownloadTaskType)); +}; + +class MockTaskWaiter { + public: + MockTaskWaiter() = default; + ~MockTaskWaiter() = default; + + MOCK_METHOD1(TaskFinished, void(bool)); +}; + +class TaskManagerTest : public testing::Test { + public: + TaskManagerTest() + : task_runner_(new base::TestMockTimeTaskRunner), handle_(task_runner_) { + auto scheduler = std::make_unique<MockTaskScheduler>(); + task_scheduler_ = scheduler.get(); + task_manager_ = std::make_unique<TaskManager>(std::move(scheduler)); + } + + ~TaskManagerTest() override = default; + + protected: + TaskManager::TaskParams CreateTaskParams() { + TaskManager::TaskParams params; + params.require_unmetered_network = false; + params.require_charging = false; + params.optimal_battery_percentage = 15; + params.window_start_time_seconds = 0; + params.window_end_time_seconds = 10; + return params; + } + + void ExpectCallToScheduleTask(DownloadTaskType task_type, + const TaskManager::TaskParams& params, + int call_count) { + EXPECT_CALL( + *task_scheduler_, + ScheduleTask(task_type, params.require_unmetered_network, + params.require_charging, params.optimal_battery_percentage, + params.window_start_time_seconds, + params.window_end_time_seconds)) + .Times(call_count); + } + + scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; + base::ThreadTaskRunnerHandle handle_; + + MockTaskScheduler* task_scheduler_; + std::unique_ptr<TaskManager> task_manager_; + + private: + DISALLOW_COPY_AND_ASSIGN(TaskManagerTest); +}; + +} // namespace + +TEST_F(TaskManagerTest, ScheduleTask) { + auto params = CreateTaskParams(); + + // Schedule a task. + ExpectCallToScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params, 1); + task_manager_->ScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params); + + // Schedule another task with same params. This should be a no-op. + ExpectCallToScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params, 0); + task_manager_->ScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params); + + // Schedule another task with different params. This task should override the + // already scheduled task. + params.optimal_battery_percentage = 20; + ExpectCallToScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params, 1); + task_manager_->ScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params); + + task_runner_->RunUntilIdle(); +} + +TEST_F(TaskManagerTest, UnscheduleTask) { + auto params = CreateTaskParams(); + task_manager_->ScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params); + + EXPECT_CALL(*task_scheduler_, CancelTask(DownloadTaskType::DOWNLOAD_TASK)) + .Times(1); + task_manager_->UnscheduleTask(DownloadTaskType::DOWNLOAD_TASK); + + task_manager_->ScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params); + EXPECT_CALL(*task_scheduler_, CancelTask(DownloadTaskType::DOWNLOAD_TASK)) + .Times(1); + task_manager_->UnscheduleTask(DownloadTaskType::DOWNLOAD_TASK); + + // Cancel is called even if we are not aware of scheduling a task. + EXPECT_CALL(*task_scheduler_, CancelTask(DownloadTaskType::DOWNLOAD_TASK)) + .Times(1); + task_manager_->UnscheduleTask(DownloadTaskType::DOWNLOAD_TASK); + + task_runner_->RunUntilIdle(); +} + +TEST_F(TaskManagerTest, NotifyTaskFinished) { + auto params = CreateTaskParams(); + + task_manager_->ScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params); + + MockTaskWaiter waiter; + auto callback = + base::BindOnce(&MockTaskWaiter::TaskFinished, base::Unretained(&waiter)); + task_manager_->OnStartScheduledTask(DownloadTaskType::DOWNLOAD_TASK, + std::move(callback)); + + EXPECT_CALL(waiter, TaskFinished(false)).Times(1); + task_manager_->NotifyTaskFinished(DownloadTaskType::DOWNLOAD_TASK, false); + task_runner_->RunUntilIdle(); +} + +TEST_F(TaskManagerTest, DifferentTasksCanBeRunIndependently) { + auto params = CreateTaskParams(); + + ExpectCallToScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params, 1); + task_manager_->ScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params); + + ExpectCallToScheduleTask(DownloadTaskType::CLEANUP_TASK, params, 1); + task_manager_->ScheduleTask(DownloadTaskType::CLEANUP_TASK, params); + + MockTaskWaiter waiter; + auto callback1 = + base::BindOnce(&MockTaskWaiter::TaskFinished, base::Unretained(&waiter)); + auto callback2 = + base::BindOnce(&MockTaskWaiter::TaskFinished, base::Unretained(&waiter)); + + EXPECT_CALL(waiter, TaskFinished(false)).Times(1); + task_manager_->OnStartScheduledTask(DownloadTaskType::DOWNLOAD_TASK, + std::move(callback1)); + task_manager_->NotifyTaskFinished(DownloadTaskType::DOWNLOAD_TASK, false); + + EXPECT_CALL(waiter, TaskFinished(true)).Times(1); + task_manager_->OnStartScheduledTask(DownloadTaskType::CLEANUP_TASK, + std::move(callback2)); + task_manager_->NotifyTaskFinished(DownloadTaskType::CLEANUP_TASK, true); + + task_runner_->RunUntilIdle(); +} + +TEST_F(TaskManagerTest, ScheduleTaskWithDifferentParamsWhileRunningTask) { + auto params = CreateTaskParams(); + task_manager_->ScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params); + + MockTaskWaiter waiter; + auto callback = + base::BindOnce(&MockTaskWaiter::TaskFinished, base::Unretained(&waiter)); + + task_manager_->OnStartScheduledTask(DownloadTaskType::DOWNLOAD_TASK, + std::move(callback)); + + params.optimal_battery_percentage = 20; + task_manager_->ScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params); + + ExpectCallToScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params, 1); + EXPECT_CALL(waiter, TaskFinished(false)).Times(1); + task_manager_->NotifyTaskFinished(DownloadTaskType::DOWNLOAD_TASK, false); + task_runner_->RunUntilIdle(); +} + +TEST_F(TaskManagerTest, ScheduleTaskWithSameParamsWhileRunningTask) { + auto params = CreateTaskParams(); + task_manager_->ScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params); + + MockTaskWaiter waiter; + auto callback = + base::BindOnce(&MockTaskWaiter::TaskFinished, base::Unretained(&waiter)); + + task_manager_->OnStartScheduledTask(DownloadTaskType::DOWNLOAD_TASK, + std::move(callback)); + task_manager_->ScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params); + + ExpectCallToScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params, 0); + EXPECT_CALL(waiter, TaskFinished(false)).Times(1); + task_manager_->NotifyTaskFinished(DownloadTaskType::DOWNLOAD_TASK, false); + task_runner_->RunUntilIdle(); +} + +TEST_F(TaskManagerTest, StopTaskWillClearTheCallback) { + auto params = CreateTaskParams(); + task_manager_->ScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params); + + MockTaskWaiter waiter; + auto callback = + base::BindOnce(&MockTaskWaiter::TaskFinished, base::Unretained(&waiter)); + + EXPECT_CALL(waiter, TaskFinished(false)).Times(0); + task_manager_->OnStartScheduledTask(DownloadTaskType::DOWNLOAD_TASK, + std::move(callback)); + task_manager_->OnStopScheduledTask(DownloadTaskType::DOWNLOAD_TASK); + + task_manager_->NotifyTaskFinished(DownloadTaskType::DOWNLOAD_TASK, false); + + task_runner_->RunUntilIdle(); +} + +TEST_F(TaskManagerTest, StopTaskWillSchedulePendingParams) { + auto params = CreateTaskParams(); + task_manager_->ScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params); + + MockTaskWaiter waiter; + auto callback = + base::BindOnce(&MockTaskWaiter::TaskFinished, base::Unretained(&waiter)); + + task_manager_->OnStartScheduledTask(DownloadTaskType::DOWNLOAD_TASK, + std::move(callback)); + + ExpectCallToScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params, 0); + params.optimal_battery_percentage = 20; + task_manager_->ScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params); + + ExpectCallToScheduleTask(DownloadTaskType::DOWNLOAD_TASK, params, 1); + task_manager_->OnStopScheduledTask(DownloadTaskType::DOWNLOAD_TASK); + + task_runner_->RunUntilIdle(); +} + +} // namespace download
diff --git a/components/download/public/common/download_item.h b/components/download/public/common/download_item.h index 538d7d2..3b5d743 100644 --- a/components/download/public/common/download_item.h +++ b/components/download/public/common/download_item.h
@@ -161,7 +161,7 @@ // Resume a download that has been paused or interrupted. Will have no effect // if the download is neither. Only does something if CanResume() returns // true. - virtual void Resume() = 0; + virtual void Resume(bool user_resume) = 0; // Cancel the download operation. // @@ -211,6 +211,9 @@ // transition out of this paused state. virtual bool IsPaused() const = 0; + // Whether the download should be allowed to proceed in a metered network. + virtual bool AllowMetered() const = 0; + // DEPRECATED. True if this is a temporary download and should not be // persisted. virtual bool IsTemporary() const = 0; @@ -228,6 +231,10 @@ // Returns the calculated number of bytes wasted (if any). virtual int64_t GetBytesWasted() const = 0; + // Returns the number of times the download has been auto-resumed since last + // user triggered resumption. + virtual int32_t GetAutoResumeCount() const = 0; + // Origin State accessors ------------------------------------------------- // Final URL. The primary resource being downloaded is from this URL. This is
diff --git a/components/download/public/common/download_item_impl.h b/components/download/public/common/download_item_impl.h index c1df0945..4ede432f 100644 --- a/components/download/public/common/download_item_impl.h +++ b/components/download/public/common/download_item_impl.h
@@ -177,11 +177,13 @@ const std::string& last_modified, int64_t received_bytes, int64_t total_bytes, + int32_t auto_resume_count, const std::string& hash, DownloadItem::DownloadState state, DownloadDangerType danger_type, DownloadInterruptReason interrupt_reason, bool paused, + bool allow_metered, bool opened, base::Time last_access_time, bool transient, @@ -213,7 +215,7 @@ void StealDangerousDownload(bool need_removal, const AcquireFileCallback& callback) override; void Pause() override; - void Resume() override; + void Resume(bool user_resume) override; void Cancel(bool user_cancel) override; void Remove() override; void OpenDownload() override; @@ -223,10 +225,12 @@ DownloadState GetState() const override; DownloadInterruptReason GetLastReason() const override; bool IsPaused() const override; + bool AllowMetered() const override; bool IsTemporary() const override; bool CanResume() const override; bool IsDone() const override; int64_t GetBytesWasted() const override; + int32_t GetAutoResumeCount() const override; const GURL& GetURL() const override; const std::vector<GURL>& GetUrlChain() const override; const GURL& GetOriginalUrl() const override; @@ -581,6 +585,8 @@ void UpdateProgress(int64_t bytes_so_far, int64_t bytes_per_sec); + void UpdateResumptionInfo(bool user_resume); + // Set |hash_| and |hash_state_| based on |hash_state|. void SetHashState(std::unique_ptr<crypto::SecureHash> hash_state); @@ -712,6 +718,9 @@ // was truly paused. bool paused_ = false; + // True if the download can proceed in a metered network. + bool allow_metered_ = false; + // Did the user open the item either directly or indirectly (such as by // setting always open files of this type)? The shelf also sets this field // when the user closes the shelf before the item has been opened but should @@ -748,7 +757,8 @@ int64_t bytes_per_sec_ = 0; // The number of times this download has been resumed automatically. Will be - // reset to 0 if a resumption is performed in response to a Resume() call. + // reset to 0 if a resumption is performed in response to a Resume() call with + // user gesture. int auto_resume_count_ = 0; // In the event of an interruption, the DownloadDestinationObserver interface
diff --git a/components/download/public/common/download_item_impl_delegate.h b/components/download/public/common/download_item_impl_delegate.h index 6a6f3dc..a6eb5429 100644 --- a/components/download/public/common/download_item_impl_delegate.h +++ b/components/download/public/common/download_item_impl_delegate.h
@@ -107,6 +107,9 @@ // Whether the download is off the record. virtual bool IsOffTheRecord() const; + // Check if the current network is a metered network. + virtual bool IsActiveNetworkMetered() const; + // Report extra bytes wasted during resumption. virtual void ReportBytesWasted(DownloadItemImpl* download);
diff --git a/components/download/public/common/mock_download_item.h b/components/download/public/common/mock_download_item.h index f534bd7..5bc0b0a 100644 --- a/components/download/public/common/mock_download_item.h +++ b/components/download/public/common/mock_download_item.h
@@ -42,7 +42,7 @@ MOCK_METHOD0(ValidateDangerousDownload, void()); MOCK_METHOD2(StealDangerousDownload, void(bool, const AcquireFileCallback&)); MOCK_METHOD0(Pause, void()); - MOCK_METHOD0(Resume, void()); + MOCK_METHOD1(Resume, void(bool)); MOCK_METHOD1(Cancel, void(bool)); MOCK_METHOD0(Remove, void()); MOCK_METHOD0(OpenDownload, void()); @@ -52,10 +52,12 @@ MOCK_CONST_METHOD0(GetState, DownloadState()); MOCK_CONST_METHOD0(GetLastReason, DownloadInterruptReason()); MOCK_CONST_METHOD0(IsPaused, bool()); + MOCK_CONST_METHOD0(AllowMetered, bool()); MOCK_CONST_METHOD0(IsTemporary, bool()); MOCK_CONST_METHOD0(CanResume, bool()); MOCK_CONST_METHOD0(IsDone, bool()); MOCK_CONST_METHOD0(GetBytesWasted, int64_t()); + MOCK_CONST_METHOD0(GetAutoResumeCount, int32_t()); MOCK_CONST_METHOD0(GetURL, const GURL&()); MOCK_CONST_METHOD0(GetUrlChain, const std::vector<GURL>&()); MOCK_CONST_METHOD0(GetOriginalUrl, const GURL&());
diff --git a/components/download/public/common/mock_download_item_impl.cc b/components/download/public/common/mock_download_item_impl.cc index ac8524b..5282def 100644 --- a/components/download/public/common/mock_download_item_impl.cc +++ b/components/download/public/common/mock_download_item_impl.cc
@@ -25,12 +25,14 @@ std::string(), 0, 0, + 0, std::string(), DownloadItem::COMPLETE, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, DOWNLOAD_INTERRUPT_REASON_NONE, false, false, + false, base::Time(), true, DownloadItem::ReceivedSlices()) {}
diff --git a/components/download/quarantine/test_support_mac.mm b/components/download/quarantine/test_support_mac.mm index 5fce74b..a1ebbd6d 100644 --- a/components/download/quarantine/test_support_mac.mm +++ b/components/download/quarantine/test_support_mac.mm
@@ -11,7 +11,7 @@ #include "base/files/file_util.h" #include "base/mac/scoped_nsobject.h" #include "base/strings/sys_string_conversions.h" -#include "base/threading/thread_restrictions.h" +#include "base/threading/scoped_blocking_call.h" #include "components/download/quarantine/common_mac.h" #include "url/gurl.h" @@ -20,7 +20,7 @@ bool IsFileQuarantined(const base::FilePath& file, const GURL& expected_source_url, const GURL& referrer_url) { - base::AssertBlockingAllowedDeprecated(); + base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK); if (!base::PathExists(file)) return false;
diff --git a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java b/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java index 1f3c914..02281ba 100644 --- a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java +++ b/components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java
@@ -21,6 +21,7 @@ import android.widget.FrameLayout; import org.chromium.base.TraceEvent; +import org.chromium.base.compat.ApiHelperForO; import org.chromium.content_public.browser.ImeAdapter; import org.chromium.content_public.browser.RenderCoordinates; import org.chromium.content_public.browser.SmartClipProvider; @@ -84,6 +85,10 @@ setFocusable(true); setFocusableInTouchMode(true); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + ApiHelperForO.setDefaultFocusHighlightEnabled(this, false); + } } protected WebContentsAccessibility getWebContentsAccessibility() {
diff --git a/components/history/core/browser/history_service.cc b/components/history/core/browser/history_service.cc index 513a89f..aafc4e6 100644 --- a/components/history/core/browser/history_service.cc +++ b/components/history/core/browser/history_service.cc
@@ -914,14 +914,11 @@ // // TODO(ajwong): Cleanup HistoryBackend lifetime issues. // See http://crbug.com/99767. - history_backend_->AddRef(); base::Closure closing_task = base::Bind(&HistoryBackend::Closing, history_backend_); ScheduleTask(PRIORITY_NORMAL, closing_task); closing_task.Reset(); - HistoryBackend* raw_ptr = history_backend_.get(); - history_backend_ = nullptr; - backend_task_runner_->ReleaseSoon(FROM_HERE, raw_ptr); + backend_task_runner_->ReleaseSoon(FROM_HERE, std::move(history_backend_)); } // Clear |backend_task_runner_| to make sure it's not used after Cleanup().
diff --git a/components/invalidation/impl/BUILD.gn b/components/invalidation/impl/BUILD.gn index 1a14a5f..068ea6d6 100644 --- a/components/invalidation/impl/BUILD.gn +++ b/components/invalidation/impl/BUILD.gn
@@ -291,10 +291,16 @@ "$proto_path/serialized_invalidation.proto", ] } + android_resources("javatests__resources") { + testonly = true + resource_dirs = [] + android_manifest = "android/javatests/AndroidManifest.xml" + } android_library("javatests") { testonly = true deps = [ ":java", + ":javatests__resources", "//base:base_java", "//base:base_java_test_support", "//components/signin/core/browser/android:java",
diff --git a/components/invalidation/impl/android/javatests/AndroidManifest.xml b/components/invalidation/impl/android/javatests/AndroidManifest.xml new file mode 100644 index 0000000..25cac89ed --- /dev/null +++ b/components/invalidation/impl/android/javatests/AndroidManifest.xml
@@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. --> +<!-- package name must be unique --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + package="org.chromium.components.invalidation"> + <application> + <service android:name="org.chromium.components.invalidation.TestableInvalidationClientService" + android:exported="false" /> + </application> +</manifest>
diff --git a/components/neterror/resources/neterror.css b/components/neterror/resources/neterror.css index 77959f3..7142a6c 100644 --- a/components/neterror/resources/neterror.css +++ b/components/neterror/resources/neterror.css
@@ -569,7 +569,7 @@ } #offline-content-summary { - border: 1px solid rgb(223, 225, 229); + border: 1px solid var(--google-gray-300); border-radius: 12px; padding: 12px; text-align: center; @@ -598,7 +598,7 @@ } .offline-content-summary-description { - border-top: 1px solid rgb(223, 225, 229); + border-top: 1px solid var(--google-gray-300); padding-top: 12px; }
diff --git a/components/ntp_tiles/icon_cacher_impl_unittest.cc b/components/ntp_tiles/icon_cacher_impl_unittest.cc index eb65e60d..3bcc854ae 100644 --- a/components/ntp_tiles/icon_cacher_impl_unittest.cc +++ b/components/ntp_tiles/icon_cacher_impl_unittest.cc
@@ -187,7 +187,7 @@ .WillByDefault(ReturnArg<0>()); ui::ResourceBundle::InitSharedInstanceWithLocale( "en-US", &mock_resource_delegate_, - ui::ResourceBundle::LOAD_COMMON_RESOURCES); + ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES); } void TearDown() override {
diff --git a/components/offline_pages/core/background/BUILD.gn b/components/offline_pages/core/background/BUILD.gn index 817f94e..069a714 100644 --- a/components/offline_pages/core/background/BUILD.gn +++ b/components/offline_pages/core/background/BUILD.gn
@@ -33,6 +33,8 @@ "mark_attempt_started_task.cc", "mark_attempt_started_task.h", "offliner.h", + "offliner_client.cc", + "offliner_client.h", "offliner_policy.h", "offliner_policy_utils.cc", "offliner_policy_utils.h", @@ -114,6 +116,7 @@ "mark_attempt_aborted_task_unittest.cc", "mark_attempt_completed_task_unittest.cc", "mark_attempt_started_task_unittest.cc", + "offliner_client_unittest.cc", "pick_request_task_unittest.cc", "reconcile_task_unittest.cc", "remove_requests_task_unittest.cc", @@ -135,6 +138,7 @@ "//services/network:test_support", "//services/network/public/cpp", "//sql:sql", + "//testing/gmock", "//testing/gtest", "//url", ]
diff --git a/components/offline_pages/core/background/offliner_client.cc b/components/offline_pages/core/background/offliner_client.cc new file mode 100644 index 0000000..8f71b975 --- /dev/null +++ b/components/offline_pages/core/background/offliner_client.cc
@@ -0,0 +1,85 @@ +// 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 "components/offline_pages/core/background/offliner_client.h" + +#include <utility> + +#include "components/offline_pages/core/background/save_page_request.h" + +namespace offline_pages { + +OfflinerClient::OfflinerClient( + std::unique_ptr<Offliner> offliner, + const Offliner::ProgressCallback& progress_callback) + : offliner_(std::move(offliner)), progress_callback_(progress_callback) {} + +OfflinerClient::~OfflinerClient() = default; + +bool OfflinerClient::LoadAndSave(const SavePageRequest& request, + base::TimeDelta timeout, + CompleteCallback complete_callback) { + if (Active()) + return false; + if (!offliner_->LoadAndSave(request, + base::BindOnce(&OfflinerClient::OfflinerComplete, + base::Unretained(this)), + progress_callback_)) { + return false; + } + stopping_ = false; + active_request_ = std::make_unique<SavePageRequest>(request); + complete_callback_ = std::move(complete_callback); + watchdog_timer_.Start(FROM_HERE, timeout, this, + &OfflinerClient::HandleWatchdogTimeout); + return true; +} + +void OfflinerClient::Stop(Offliner::RequestStatus status) { + if (!active_request_ || stopping_) + return; + if (offliner_->Cancel(base::BindOnce(&OfflinerClient::CancelComplete, + base::Unretained(this), status))) { + stopping_ = true; + } else { + Finish(status); + } +} + +void OfflinerClient::HandleWatchdogTimeout() { + if (!active_request_ || stopping_) + return; + // Check if the offliner can finish up now. + if (offliner_->HandleTimeout(active_request_->request_id())) + return; + if (offliner_->Cancel(base::BindOnce( + &OfflinerClient::CancelComplete, base::Unretained(this), + Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT))) { + stopping_ = true; + } else { + Finish(Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT); + } +} + +void OfflinerClient::CancelComplete(Offliner::RequestStatus cancel_reason, + const SavePageRequest& request) { + watchdog_timer_.Stop(); + if (active_request_) + Finish(cancel_reason); +} + +void OfflinerClient::OfflinerComplete(const SavePageRequest& request, + Offliner::RequestStatus status) { + if (active_request_) + Finish(status); + watchdog_timer_.Stop(); +} + +void OfflinerClient::Finish(Offliner::RequestStatus status) { + stopping_ = false; + std::unique_ptr<SavePageRequest> request = std::move(active_request_); + std::move(complete_callback_).Run(*request, status); +} + +} // namespace offline_pages
diff --git a/components/offline_pages/core/background/offliner_client.h b/components/offline_pages/core/background/offliner_client.h new file mode 100644 index 0000000..cebd436 --- /dev/null +++ b/components/offline_pages/core/background/offliner_client.h
@@ -0,0 +1,66 @@ +// 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 COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_OFFLINER_CLIENT_H_ +#define COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_OFFLINER_CLIENT_H_ + +#include <memory> + +#include "base/callback.h" +#include "base/timer/timer.h" +#include "components/offline_pages/core/background/offliner.h" + +namespace offline_pages { +class SavePageRequest; + +// Provides an interface to the Offliner and implements a timeout. +class OfflinerClient { + public: + typedef base::OnceCallback<void(const SavePageRequest&, + Offliner::RequestStatus)> + CompleteCallback; + + OfflinerClient(std::unique_ptr<Offliner> offliner, + const Offliner::ProgressCallback& progress_callback); + ~OfflinerClient(); + + bool Ready() const { return !active_request_; } + bool Active() const { return active_request_ != nullptr; } + + // Returns the active request, or null if not active. + const SavePageRequest* ActiveRequest() const { return active_request_.get(); } + + // Begins offlining the request. Calls complete_callback when successfully + // complete, or when the request is cancelled due to Stop(), or running out of + // time. If |LoadAndSave| returns false, the operation failed to start, and + // |complete_callback| will not be called. + bool LoadAndSave(const SavePageRequest& request, + base::TimeDelta timeout, + CompleteCallback complete_callback); + void Stop(Offliner::RequestStatus status); + + public: + void HandleWatchdogTimeout(); + + void CancelComplete(Offliner::RequestStatus cancel_reason, + const SavePageRequest& request); + void OfflinerComplete(const SavePageRequest& request, + Offliner::RequestStatus status); + + void Finish(Offliner::RequestStatus status); + + std::unique_ptr<SavePageRequest> active_request_; + // Whether awaiting the result of |Offliner::Cancel|. + bool stopping_ = false; + + CompleteCallback complete_callback_; + std::unique_ptr<Offliner> offliner_; + const Offliner::ProgressCallback progress_callback_; + // Timer to watch for pre-render attempts running too long. + base::OneShotTimer watchdog_timer_; +}; + +} // namespace offline_pages + +#endif // COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_OFFLINER_CLIENT_H_
diff --git a/components/offline_pages/core/background/offliner_client_unittest.cc b/components/offline_pages/core/background/offliner_client_unittest.cc new file mode 100644 index 0000000..2936521 --- /dev/null +++ b/components/offline_pages/core/background/offliner_client_unittest.cc
@@ -0,0 +1,117 @@ +// 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 "components/offline_pages/core/background/offliner_client.h" + +#include "base/test/mock_callback.h" +#include "base/test/test_mock_time_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "components/offline_pages/core/background/offliner_stub.h" +#include "components/offline_pages/core/background/save_page_request.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace offline_pages { +namespace { +using ::testing::_; + +using MockCompleteCallback = + base::MockCallback<base::RepeatingCallback<void(const SavePageRequest&, + Offliner::RequestStatus)>>; + +using MockProgressCallback = base::MockCallback< + base::RepeatingCallback<void(const SavePageRequest&, int64_t)>>; + +const base::TimeDelta kOneMinute = base::TimeDelta::FromMinutes(1); + +SavePageRequest TestRequest() { + return SavePageRequest(123, GURL("http://test.com"), + ClientId("test-namespace", "test-id"), base::Time(), + /*user_requested=*/true); +} + +class OfflinerClientTest : public testing::Test { + protected: + scoped_refptr<base::TestMockTimeTaskRunner> task_runner_{ + new base::TestMockTimeTaskRunner}; + base::ThreadTaskRunnerHandle task_runner_handle_{task_runner_}; + + MockProgressCallback progress_callback_; + OfflinerStub* offliner_ = new OfflinerStub; + OfflinerClient client_{std::unique_ptr<OfflinerStub>(offliner_), + progress_callback_.Get()}; +}; + +TEST_F(OfflinerClientTest, NoRequests) { + EXPECT_TRUE(client_.Ready()); + EXPECT_FALSE(client_.Active()); + EXPECT_EQ(nullptr, client_.ActiveRequest()); +} + +// Call Stop() when the offliner is not active. It should do nothing. +TEST_F(OfflinerClientTest, StopWithNoRequest) { + client_.Stop(Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED); + + EXPECT_FALSE(client_.Active()); +} + +TEST_F(OfflinerClientTest, LoadAndSave) { + offliner_->enable_callback(true); + + // Load a page. Completion callback and progress callback should be called. + MockCompleteCallback complete_callback; + EXPECT_CALL(complete_callback, Run(_, Offliner::RequestStatus::SAVED)); + EXPECT_CALL(progress_callback_, Run(_, _)); + ASSERT_TRUE( + client_.LoadAndSave(TestRequest(), kOneMinute, complete_callback.Get())); + EXPECT_TRUE(client_.Active()); + + task_runner_->RunUntilIdle(); + EXPECT_FALSE(client_.Active()); +} + +TEST_F(OfflinerClientTest, LoadAndSaveTimeout) { + MockCompleteCallback complete_callback; + EXPECT_CALL(complete_callback, + Run(_, Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT)); + ASSERT_TRUE( + client_.LoadAndSave(TestRequest(), kOneMinute, complete_callback.Get())); + EXPECT_TRUE(client_.Active()); + + task_runner_->FastForwardBy(kOneMinute); + EXPECT_FALSE(client_.Active()); +} + +TEST_F(OfflinerClientTest, StopInFlight) { + MockCompleteCallback complete_callback; + // Simulate loading in progress. + ASSERT_TRUE( + client_.LoadAndSave(TestRequest(), kOneMinute, complete_callback.Get())); + task_runner_->FastForwardBy(kOneMinute / 2); + + // Call Stop(), and verify the corrrect status is returned. + EXPECT_CALL(complete_callback, + Run(_, Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED)); + client_.Stop(Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED); + EXPECT_TRUE(client_.Active()); // Cancellation isn't yet complete. + task_runner_->RunUntilIdle(); + EXPECT_FALSE(client_.Active()); +} + +TEST_F(OfflinerClientTest, LoadAndSaveFailsWhileAlreadyActive) { + MockCompleteCallback complete_callback1; + ASSERT_TRUE( + client_.LoadAndSave(TestRequest(), kOneMinute, complete_callback1.Get())); + EXPECT_CALL(complete_callback1, Run(_, _)).Times(1); + + MockCompleteCallback complete_callback2; + EXPECT_CALL(complete_callback2, Run(_, _)).Times(0); + EXPECT_FALSE( + client_.LoadAndSave(TestRequest(), kOneMinute, complete_callback2.Get())); + + task_runner_->FastForwardUntilNoTasksRemain(); +} + +} // namespace +} // namespace offline_pages
diff --git a/components/offline_pages/core/background/offliner_stub.cc b/components/offline_pages/core/background/offliner_stub.cc index 4e0b905..e747096 100644 --- a/components/offline_pages/core/background/offliner_stub.cc +++ b/components/offline_pages/core/background/offliner_stub.cc
@@ -4,6 +4,8 @@ #include "components/offline_pages/core/background/offliner_stub.h" +#include <utility> + #include "base/bind.h" #include "base/threading/thread_task_runner_handle.h" #include "components/offline_pages/core/background/save_page_request.h" @@ -21,6 +23,7 @@ bool OfflinerStub::LoadAndSave(const SavePageRequest& request, CompletionCallback completion_callback, const ProgressCallback& progress_callback) { + load_and_save_called_ = true; if (disable_loading_) return false; @@ -45,8 +48,9 @@ if (!pending_request_) return false; - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), *pending_request_)); + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, base::BindOnce(std::move(callback), *pending_request_), + cancel_delay_); pending_request_.reset(); return true; }
diff --git a/components/offline_pages/core/background/offliner_stub.h b/components/offline_pages/core/background/offliner_stub.h index 6472058..845270b 100644 --- a/components/offline_pages/core/background/offliner_stub.h +++ b/components/offline_pages/core/background/offliner_stub.h
@@ -39,6 +39,14 @@ void enable_snapshot_on_last_retry() { snapshot_on_last_retry_ = true; } + void set_cancel_delay(base::TimeDelta cancel_delay) { + cancel_delay_ = cancel_delay; + } + + bool has_pending_request() const { return pending_request_ != nullptr; } + + bool load_and_save_called() const { return load_and_save_called_; } + private: CompletionCallback completion_callback_; std::unique_ptr<SavePageRequest> pending_request_; @@ -46,6 +54,8 @@ bool enable_callback_; bool cancel_called_; bool snapshot_on_last_retry_; + bool load_and_save_called_ = false; + base::TimeDelta cancel_delay_; }; } // namespace offline_pages
diff --git a/components/offline_pages/core/background/request_coordinator.cc b/components/offline_pages/core/background/request_coordinator.cc index 086ae2d2..9f52630 100644 --- a/components/offline_pages/core/background/request_coordinator.cc +++ b/components/offline_pages/core/background/request_coordinator.cc
@@ -18,6 +18,7 @@ #include "base/time/clock.h" #include "base/time/time.h" #include "components/offline_pages/core/background/offliner.h" +#include "components/offline_pages/core/background/offliner_client.h" #include "components/offline_pages/core/background/offliner_policy.h" #include "components/offline_pages/core/background/save_page_request.h" #include "components/offline_pages/core/client_policy_controller.h" @@ -187,6 +188,70 @@ } } +// Returns true if |status| originates from the RequestCoordinator, as opposed +// to an |Offliner| result. +constexpr bool IsCanceledOrInternalFailure(Offliner::RequestStatus status) { + switch (status) { + case Offliner::RequestStatus::FOREGROUND_CANCELED: + case Offliner::RequestStatus::LOADING_CANCELED: + case Offliner::RequestStatus::QUEUE_UPDATE_FAILED: + case Offliner::RequestStatus::LOADING_NOT_ACCEPTED: + case Offliner::RequestStatus::LOADING_DEFERRED: + case Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED: + case Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED: + return true; + default: + return false; + } +} + +// Returns the |BackgroundSavePageResult| appropriate for a single attempt +// status. Returns |base::nullopt| for indeterminate status values that can be +// retried. +base::Optional<RequestNotifier::BackgroundSavePageResult> SingleAttemptResult( + Offliner::RequestStatus status) { + switch (status) { + // Success status values. + case Offliner::RequestStatus::SAVED: + case Offliner::RequestStatus::SAVED_ON_LAST_RETRY: + return RequestNotifier::BackgroundSavePageResult::SUCCESS; + + // Cancellation status values. + case Offliner::RequestStatus::FOREGROUND_CANCELED: + case Offliner::RequestStatus::LOADING_CANCELED: + case Offliner::RequestStatus::QUEUE_UPDATE_FAILED: + case Offliner::RequestStatus::LOADING_NOT_ACCEPTED: + case Offliner::RequestStatus::LOADING_DEFERRED: + case Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED: + case Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED: + return base::nullopt; + + // Other failure status values. + case Offliner::RequestStatus::LOADING_FAILED_NO_RETRY: + case Offliner::RequestStatus::LOADING_FAILED_DOWNLOAD: + return RequestNotifier::BackgroundSavePageResult::LOADING_FAILURE; + case Offliner::RequestStatus::DOWNLOAD_THROTTLED: + return RequestNotifier::BackgroundSavePageResult::DOWNLOAD_THROTTLED; + case Offliner::RequestStatus::SAVE_FAILED: + case Offliner::RequestStatus::LOADING_FAILED: + case Offliner::RequestStatus::LOADING_FAILED_NET_ERROR: + case Offliner::RequestStatus::LOADING_FAILED_HTTP_ERROR: + case Offliner::RequestStatus::LOADING_FAILED_NO_NEXT: + case Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT: + return base::nullopt; + + // Only used by |Offliner| internally. + case Offliner::RequestStatus::UNKNOWN: + case Offliner::RequestStatus::LOADED: + // Deprecated. + case Offliner::RequestStatus::DEPRECATED_LOADING_NOT_STARTED: + // Only recorded by |RequestCoordinator| directly. + case Offliner::RequestStatus::BROWSER_KILLED: + DCHECK(false) << "Received invalid status: " << static_cast<int>(status); + return base::nullopt; + } +} + } // namespace RequestCoordinator::SavePageLaterParams::SavePageLaterParams() @@ -210,7 +275,6 @@ state_(RequestCoordinatorState::IDLE), processing_state_(ProcessingWindowState::STOPPED), use_test_device_conditions_(false), - offliner_(std::move(offliner)), policy_(std::move(policy)), queue_(std::move(queue)), scheduler_(std::move(scheduler)), @@ -218,7 +282,6 @@ network_quality_tracker_(network_quality_tracker), ukm_reporter_(std::move(ukm_reporter)), network_quality_at_request_start_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN), - active_request_id_(0), last_offlining_status_(Offliner::RequestStatus::UNKNOWN), scheduler_callback_(base::DoNothing()), internal_start_processing_callback_(base::DoNothing()), @@ -227,6 +290,10 @@ weak_ptr_factory_(this) { DCHECK(policy_ != nullptr); DCHECK(network_quality_tracker_); + offliner_client_ = std::make_unique<OfflinerClient>( + std::move(offliner), + base::BindRepeating(&RequestCoordinator::OfflinerProgressCallback, + weak_ptr_factory_.GetWeakPtr())); std::unique_ptr<CleanupTaskFactory> cleanup_factory( new CleanupTaskFactory(policy_.get(), this, &event_logger_)); queue_->SetCleanupFactory(std::move(cleanup_factory)); @@ -316,24 +383,15 @@ std::move(callback).Run(std::move(requests)); } -void RequestCoordinator::StopOfflining(CancelCallback final_callback, - Offliner::RequestStatus stop_status) { - // Wrapping the |final_callback| since it might be moved twice if offliner - // returns false when Cancel(). - // TODO(https://crbug.com/874313): refactor so we can use |final_callback| as - // an OnceCallback. - auto callback = base::AdaptCallbackForRepeating(std::move(final_callback)); - if (offliner_ && state_ == RequestCoordinatorState::OFFLINING) { - DCHECK_NE(active_request_id_, 0); - if (offliner_->Cancel(base::BindOnce( - &RequestCoordinator::HandleCancelUpdateStatusCallback, - weak_ptr_factory_.GetWeakPtr(), callback, stop_status))) { - return; - } +void RequestCoordinator::StopProcessing(Offliner::RequestStatus stop_status) { + if (offliner_client_ && offliner_client_->Active() && + state_ == RequestCoordinatorState::OFFLINING) { + offliner_client_->Stop(stop_status); + return; } - - UpdateStatusForCancel(stop_status); - callback.Run(active_request_id_); + last_offlining_status_ = stop_status; + state_ = RequestCoordinatorState::IDLE; + ScheduleOrTryNextRequest(stop_status); } void RequestCoordinator::GetRequestsForSchedulingCallback( @@ -356,18 +414,13 @@ scheduler_->Schedule(GetTriggerConditions(user_requested)); } -bool RequestCoordinator::CancelActiveRequestIfItMatches( - const std::vector<int64_t>& request_ids) { +bool RequestCoordinator::CancelActiveRequestIfItMatches(int64_t request_id) { // If we have a request in progress and need to cancel it, call the // offliner to cancel. - if (active_request_id_ != 0) { - if (base::ContainsValue(request_ids, active_request_id_)) { - StopOfflining( - base::BindOnce(&RequestCoordinator::ResetActiveRequestCallback, - weak_ptr_factory_.GetWeakPtr()), - Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED); - return true; - } + if (offliner_client_->Active() && + offliner_client_->ActiveRequest()->request_id() == request_id) { + StopProcessing(Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED); + return true; } return false; @@ -425,7 +478,6 @@ void RequestCoordinator::RemoveRequests(const std::vector<int64_t>& request_ids, RemoveRequestsCallback callback) { - bool canceled = CancelActiveRequestIfItMatches(request_ids); queue_->RemoveRequests( request_ids, base::BindOnce(&RequestCoordinator::HandleRemovedRequestsAndCallback, @@ -437,15 +489,10 @@ "OfflinePages.Background.EffectiveConnectionType.RemoveRequests", network_quality_tracker_->GetEffectiveConnectionType(), net::EFFECTIVE_CONNECTION_TYPE_LAST); - - if (canceled) - TryNextRequest(!kStartOfProcessing); } void RequestCoordinator::PauseRequests( const std::vector<int64_t>& request_ids) { - bool canceled = CancelActiveRequestIfItMatches(request_ids); - // Remove the paused requests from prioritized list. for (int64_t id : request_ids) { auto it = std::find(prioritized_requests_.begin(), @@ -464,9 +511,6 @@ "OfflinePages.Background.EffectiveConnectionType.PauseRequests", network_quality_tracker_->GetEffectiveConnectionType(), net::EFFECTIVE_CONNECTION_TYPE_LAST); - - if (canceled) - TryNextRequest(!kStartOfProcessing); } void RequestCoordinator::ResumeRequests( @@ -515,6 +559,9 @@ void RequestCoordinator::UpdateMultipleRequestsCallback( UpdateRequestsResult result) { for (auto& request : result.updated_items) { + if (request.request_state() == SavePageRequest::RequestState::PAUSED) { + CancelActiveRequestIfItMatches(request.request_id()); + } pending_state_updater_.SetPendingState(request); NotifyChanged(request); } @@ -545,8 +592,10 @@ UpdateRequestsResult result) { // TODO(dougarnett): Define status code for user/api cancel and use here // to determine whether to record cancel time UMA. - for (const auto& request : result.updated_items) + for (const auto& request : result.updated_items) { RecordCancelTimeUMA(request); + CancelActiveRequestIfItMatches(request.request_id()); + } std::move(callback).Run(result.item_statuses); HandleRemovedRequests(status, std::move(result)); } @@ -558,44 +607,6 @@ NotifyCompleted(request, status); } -void RequestCoordinator::HandleCancelUpdateStatusCallback( - CancelCallback final_callback, - Offliner::RequestStatus stop_status, - const SavePageRequest& canceled_request) { - if (stop_status == Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT || - stop_status == Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED) { - // Consider watchdog timeout a completed attempt. - UpdateRequestForCompletedAttempt(canceled_request, stop_status); - } else { - // Otherwise consider this stop an aborted attempt. - UpdateRequestForAbortedAttempt(canceled_request); - } - - RecordOfflinerResult(canceled_request, stop_status); - UpdateStatusForCancel(stop_status); - std::move(final_callback).Run(canceled_request.request_id()); -} - -void RequestCoordinator::UpdateStatusForCancel( - Offliner::RequestStatus stop_status) { - // Stopping offliner means it will not call callback so set last status. - last_offlining_status_ = stop_status; - active_request_id_ = 0; - state_ = RequestCoordinatorState::IDLE; -} - -void RequestCoordinator::ResetActiveRequestCallback(int64_t offline_id) { - active_request_id_ = 0; -} - -void RequestCoordinator::StartSchedulerCallback(int64_t offline_id) { - scheduler_callback_.Run(true); -} - -void RequestCoordinator::TryNextRequestCallback(int64_t offline_id) { - TryNextRequest(!kStartOfProcessing); -} - void RequestCoordinator::MarkDeferredAttemptCallback( UpdateRequestsResult result) { // This is called after the attempt has been marked as deferred in the @@ -611,21 +622,8 @@ weak_ptr_factory_.GetWeakPtr())); } -void RequestCoordinator::StopProcessing(Offliner::RequestStatus stop_status) { - processing_state_ = ProcessingWindowState::STOPPED; - StopOfflining(base::BindOnce(&RequestCoordinator::StartSchedulerCallback, - weak_ptr_factory_.GetWeakPtr()), - stop_status); -} - -void RequestCoordinator::HandleWatchdogTimeout() { - Offliner::RequestStatus watchdog_status = - Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT; - if (offliner_->HandleTimeout(active_request_id_)) - return; - StopOfflining(base::BindOnce(&RequestCoordinator::TryNextRequestCallback, - weak_ptr_factory_.GetWeakPtr()), - watchdog_status); +void RequestCoordinator::CancelProcessing() { + StopProcessing(Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED); } // Returns true if the caller should expect a callback, false otherwise. For @@ -937,6 +935,12 @@ void RequestCoordinator::StartOffliner(int64_t request_id, const std::string& client_namespace, UpdateRequestsResult update_result) { + // If the state changed from OFFLINING, another call to RequestCoordinator has + // resulted in a state change. In this case, it's safe to abort here. + if (state_ != RequestCoordinatorState::OFFLINING) + return; + DCHECK_NE(ProcessingWindowState::STOPPED, processing_state_); + if (update_result.store_state != StoreState::LOADED || update_result.item_statuses.size() != 1 || update_result.item_statuses.at(0).first != request_id || @@ -952,33 +956,24 @@ return; } - active_request_id_ = request_id; network_quality_at_request_start_ = network_quality_tracker_->GetEffectiveConnectionType(); + base::TimeDelta timeout; + if (processing_state_ == ProcessingWindowState::SCHEDULED_WINDOW) { + timeout = base::TimeDelta::FromSeconds( + policy_->GetSinglePageTimeLimitWhenBackgroundScheduledInSeconds()); + } else { + timeout = base::TimeDelta::FromSeconds( + policy_->GetSinglePageTimeLimitForImmediateLoadInSeconds()); + } // Start the load and save process in the offliner (Async). - if (offliner_->LoadAndSave( - update_result.updated_items.at(0), + if (offliner_client_->LoadAndSave( + update_result.updated_items.at(0), timeout, base::BindOnce(&RequestCoordinator::OfflinerDoneCallback, - weak_ptr_factory_.GetWeakPtr()), - base::BindRepeating(&RequestCoordinator::OfflinerProgressCallback, - weak_ptr_factory_.GetWeakPtr()))) { - base::TimeDelta timeout; - if (processing_state_ == ProcessingWindowState::SCHEDULED_WINDOW) { - timeout = base::TimeDelta::FromSeconds( - policy_->GetSinglePageTimeLimitWhenBackgroundScheduledInSeconds()); - } else { - DCHECK(processing_state_ == ProcessingWindowState::IMMEDIATE_WINDOW); - timeout = base::TimeDelta::FromSeconds( - policy_->GetSinglePageTimeLimitForImmediateLoadInSeconds()); - } - + weak_ptr_factory_.GetWeakPtr()))) { // Inform observer of active request. NotifyChanged(update_result.updated_items.at(0)); - - // Start a watchdog timer to catch offliners running too long - watchdog_timer_.Start(FROM_HERE, timeout, this, - &RequestCoordinator::HandleWatchdogTimeout); } else { state_ = RequestCoordinatorState::IDLE; DVLOG(0) << "Unable to start LoadAndSave"; @@ -995,66 +990,38 @@ DVLOG(2) << "offliner finished, saved: " << (status == Offliner::RequestStatus::SAVED) << ", status: " << static_cast<int>(status) << ", " << __func__; - DCHECK_NE(status, Offliner::RequestStatus::UNKNOWN); - DCHECK_NE(status, Offliner::RequestStatus::LOADED); RecordOfflinerResult(request, status); last_offlining_status_ = status; - watchdog_timer_.Stop(); state_ = RequestCoordinatorState::IDLE; - active_request_id_ = 0; + UpdateRequestForAttempt(request, status); - UpdateRequestForCompletedAttempt(request, status); - if (ShouldTryNextRequest(status)) - TryNextRequest(!kStartOfProcessing); - else - scheduler_callback_.Run(true); + ScheduleOrTryNextRequest(status); } -void RequestCoordinator::OfflinerProgressCallback( - const SavePageRequest& request, - int64_t received_bytes) { - DVLOG(2) << "offliner progress, received bytes: " << received_bytes; - DCHECK_GE(received_bytes, 0); - NotifyNetworkProgress(request, received_bytes); -} - -void RequestCoordinator::UpdateRequestForCompletedAttempt( +void RequestCoordinator::UpdateRequestForAttempt( const SavePageRequest& request, Offliner::RequestStatus status) { + base::Optional<RequestNotifier::BackgroundSavePageResult> attempt_result = + SingleAttemptResult(status); + // If the request failed, report the connection type as of the start of the // request. - if (status != Offliner::RequestStatus::SAVED && - status != Offliner::RequestStatus::SAVED_ON_LAST_RETRY) { + if (!attempt_result || + attempt_result.value() != + RequestNotifier::BackgroundSavePageResult::SUCCESS) { RecordNetworkQualityAtRequestStartForFailedRequest( request.client_id(), network_quality_at_request_start_); } - - if (status == Offliner::RequestStatus::FOREGROUND_CANCELED || - status == Offliner::RequestStatus::LOADING_CANCELED) { - // Update the request for the canceled attempt. - // TODO(dougarnett): See if we can conclusively identify other attempt - // aborted cases to treat this way (eg, for Render Process Killed). + if (IsCanceledOrInternalFailure(status)) { UpdateRequestForAbortedAttempt(request); - } else if (status == Offliner::RequestStatus::SAVED || - status == Offliner::RequestStatus::SAVED_ON_LAST_RETRY) { - // Remove the request from the queue if it succeeded - RemoveAttemptedRequest(request, - RequestNotifier::BackgroundSavePageResult::SUCCESS); - } else if (status == Offliner::RequestStatus::LOADING_FAILED_NO_RETRY || - status == Offliner::RequestStatus::LOADING_FAILED_DOWNLOAD) { - RemoveAttemptedRequest( - request, RequestNotifier::BackgroundSavePageResult::LOADING_FAILURE); - } else if (status == Offliner::RequestStatus::DOWNLOAD_THROTTLED) { - RemoveAttemptedRequest( - request, RequestNotifier::BackgroundSavePageResult::DOWNLOAD_THROTTLED); + } else if (attempt_result) { + RemoveAttemptedRequest(request, attempt_result.value()); } else if (request.completed_attempt_count() + 1 >= policy_->GetMaxCompletedTries()) { // Remove from the request queue if we exceeded max retries. The +1 - // represents the request that just completed. Since we call - // MarkAttemptCompleted within the if branches, the completed_attempt_count - // has not yet been updated when we are checking the if condition. - const RequestNotifier::BackgroundSavePageResult result( - RequestNotifier::BackgroundSavePageResult::RETRY_COUNT_EXCEEDED); + // represents the request that just completed. + const RequestNotifier::BackgroundSavePageResult result = + RequestNotifier::BackgroundSavePageResult::RETRY_COUNT_EXCEEDED; event_logger_.RecordDroppedSavePageRequest(request.client_id().name_space, result, request.request_id()); RemoveAttemptedRequest(request, result); @@ -1069,8 +1036,26 @@ } } +void RequestCoordinator::ScheduleOrTryNextRequest( + Offliner::RequestStatus previous_status) { + if (ShouldTryNextRequest(previous_status)) { + TryNextRequest(!kStartOfProcessing); + } else { + processing_state_ = ProcessingWindowState::STOPPED; + scheduler_callback_.Run(true); + } +} + +void RequestCoordinator::OfflinerProgressCallback( + const SavePageRequest& request, + int64_t received_bytes) { + DVLOG(2) << "offliner progress, received bytes: " << received_bytes; + DCHECK_GE(received_bytes, 0); + NotifyNetworkProgress(request, received_bytes); +} + bool RequestCoordinator::ShouldTryNextRequest( - Offliner::RequestStatus previous_request_status) { + Offliner::RequestStatus previous_request_status) const { switch (previous_request_status) { case Offliner::RequestStatus::SAVED: case Offliner::RequestStatus::SAVE_FAILED: @@ -1085,13 +1070,21 @@ case Offliner::RequestStatus::FOREGROUND_CANCELED: case Offliner::RequestStatus::LOADING_CANCELED: case Offliner::RequestStatus::LOADING_FAILED_NO_NEXT: + case Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED: + case Offliner::RequestStatus::QUEUE_UPDATE_FAILED: + case Offliner::RequestStatus::LOADING_NOT_ACCEPTED: + case Offliner::RequestStatus::LOADING_DEFERRED: // No further processing in this service window. return false; case Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT: case Offliner::RequestStatus::SAVED_ON_LAST_RETRY: // If we timed out, check to see that there is time budget. return processing_state_ == ProcessingWindowState::IMMEDIATE_WINDOW; - default: + case Offliner::RequestStatus::UNKNOWN: + case Offliner::RequestStatus::LOADED: + case Offliner::RequestStatus::DEPRECATED_LOADING_NOT_STARTED: + case Offliner::RequestStatus::BROWSER_KILLED: + // Should not be possible to receive these values. // Make explicit choice about new status codes that actually reach here. // Their default is no further processing in this service window. NOTREACHED();
diff --git a/components/offline_pages/core/background/request_coordinator.h b/components/offline_pages/core/background/request_coordinator.h index 4ca42f1..5538fc6 100644 --- a/components/offline_pages/core/background/request_coordinator.h +++ b/components/offline_pages/core/background/request_coordinator.h
@@ -36,6 +36,7 @@ namespace offline_pages { struct ClientId; +class OfflinerClient; class OfflinerPolicy; class Offliner; class SavePageRequest; @@ -118,9 +119,6 @@ std::vector<std::unique_ptr<SavePageRequest>>)> GetRequestsCallback; - // Callback for stopping the background offlining. - typedef base::OnceCallback<void(int64_t request_id)> CancelCallback; - // Callback for SavePageLater calls. typedef base::OnceCallback<void(AddRequestResult)> SavePageLaterCallback; @@ -162,6 +160,9 @@ const DeviceConditions& device_conditions, const base::RepeatingCallback<void(bool)>& callback); + // Cancel previously scheduled processing of requests. + void CancelProcessing(); + // Attempts to starts processing of one or more queued save page later // requests (if device conditions are suitable) in immediate mode // (opposed to scheduled background mode). This method is suitable to call @@ -175,12 +176,6 @@ bool StartImmediateProcessing( const base::RepeatingCallback<void(bool)>& callback); - // Stops the current request processing if active. This is a way for - // caller to abort processing; otherwise, processing will complete on - // its own. In either case, the callback will be called when processing - // is stopped or complete. - void StopProcessing(Offliner::RequestStatus stop_status); - // Used to denote that the foreground thread is ready for the offliner // to start work on a previously entered, but unavailable request. void EnableForOffliner(int64_t request_id, const ClientId& client_id); @@ -207,8 +202,6 @@ internal_start_processing_callback_ = callback; } - void StartImmediatelyForTest() { StartImmediatelyIfConnected(); } - // Observers implementing the RequestCoordinator::Observer interface can // register here to get notifications of changes to request state. This // pointer is not owned, and it is the callers responsibility to remove the @@ -236,17 +229,12 @@ ClientPolicyController* GetPolicyController(); - // Returns the status of the most recent offlining. - Offliner::RequestStatus last_offlining_status() { - return last_offlining_status_; - } - // Return the state of the request coordinator. RequestCoordinatorState state() { return state_; } // Tracks whether the last offlining attempt got canceled. This is reset by // the next call to start processing. - bool is_canceled() { + bool is_canceled() const { return processing_state_ == ProcessingWindowState::STOPPED; } @@ -281,6 +269,11 @@ IMMEDIATE_WINDOW, }; + // Stops the current request processing if active. Whether or not a request is + // active, ScheduleOrTryNextRequest() will be called to resume processing + // eventually. + void StopProcessing(Offliner::RequestStatus stop_status); + // Receives the results of a get from the request queue, and turns that into // SavePageRequest objects for the caller of GetQueuedRequests. void GetQueuedRequestsCallback( @@ -312,16 +305,6 @@ void HandleRemovedRequests(RequestNotifier::BackgroundSavePageResult status, UpdateRequestsResult result); - // Handle updating of request status after cancel is called. Will call - // HandleCancelRecordResultCallback for UMA handling - void HandleCancelUpdateStatusCallback( - CancelCallback next_callback, - Offliner::RequestStatus stop_status, - const SavePageRequest& canceled_request); - void UpdateStatusForCancel(Offliner::RequestStatus stop_status); - void ResetActiveRequestCallback(int64_t offline_id); - void StartSchedulerCallback(int64_t offline_id); - void TryNextRequestCallback(int64_t offline_id); void MarkDeferredAttemptCallback(UpdateRequestsResult result); bool StartProcessingInternal( @@ -370,12 +353,6 @@ size_t total_requests, size_t available_requests); - void HandleWatchdogTimeout(); - - // Cancels an in progress offlining, and updates state appropriately. - void StopOfflining(CancelCallback callback, - Offliner::RequestStatus stop_status); - // Marks attempt on the request and sends it to offliner in continuation. void SendRequestToOffliner(const SavePageRequest& request); @@ -395,25 +372,30 @@ void OfflinerProgressCallback(const SavePageRequest& request, int64_t received_bytes); - // Records a completed attempt for the request and update it in the queue - // (possibly removing it). - void UpdateRequestForCompletedAttempt(const SavePageRequest& request, - Offliner::RequestStatus status); + // Records a completed or aborted attempt for the request and update it in + // the queue (possibly removing it). + void UpdateRequestForAttempt(const SavePageRequest& request, + Offliner::RequestStatus status); // Returns whether we should try another request based on the outcome // of the previous one. - bool ShouldTryNextRequest(Offliner::RequestStatus previous_request_status); + bool ShouldTryNextRequest( + Offliner::RequestStatus previous_request_status) const; // Try to find and start offlining an available request. // |is_start_of_processing| identifies if this is the beginning of a // processing window (vs. continuing within a current processing window). void TryNextRequest(bool is_start_of_processing); + // Either schedules to resume processing, or resumes processing immediately. + // |previous_status| is the reason processing the previous request stopped. + void ScheduleOrTryNextRequest(Offliner::RequestStatus previous_status); + // Cross the JNI Bridge and get the current device conditions from Android. void UpdateCurrentConditionsFromAndroid(); - // If there is an active request in the list, cancel that request. - bool CancelActiveRequestIfItMatches(const std::vector<int64_t>& request_ids); + // If the active request is identified by |request_id|, cancel it. + bool CancelActiveRequestIfItMatches(int64_t request_id); // Records an aborted attempt for the request and update it in the queue // (possibly removing it). @@ -450,6 +432,8 @@ // Cached value of whether low end device. Overwritable for testing. bool is_low_end_device_; + // Access to |Offliner|, always non-null. + std::unique_ptr<OfflinerClient> offliner_client_; // Current state of the request coordinator. RequestCoordinatorState state_; // Identifies the type of current processing window or if processing stopped. @@ -459,8 +443,6 @@ bool use_test_device_conditions_; // For use by tests, a fake network connection type net::NetworkChangeNotifier::ConnectionType test_connection_type_; - // Owned pointer to the current offliner. - std::unique_ptr<Offliner> offliner_; base::Time operation_start_time_; // The observers. base::ObserverList<Observer>::Unchecked observers_; @@ -482,7 +464,7 @@ net::EffectiveConnectionType network_quality_at_request_start_; // Holds an ID of the currently active request. int64_t active_request_id_; - // Status of the most recent offlining. + // Status of the most recent offlining, retained for testing only. Offliner::RequestStatus last_offlining_status_; // A set of request_ids that we are holding off until the download manager is // done with them. @@ -499,8 +481,6 @@ base::RepeatingCallback<void(bool)> internal_start_processing_callback_; // Logger to record events. RequestCoordinatorEventLogger event_logger_; - // Timer to watch for pre-render attempts running too long. - base::OneShotTimer watchdog_timer_; // Used for potential immediate processing when we get network connection. std::unique_ptr<ConnectionNotifier> connection_notifier_; // Used to track prioritized requests.
diff --git a/components/offline_pages/core/background/request_coordinator_unittest.cc b/components/offline_pages/core/background/request_coordinator_unittest.cc index 28ea3e22..de6d985 100644 --- a/components/offline_pages/core/background/request_coordinator_unittest.cc +++ b/components/offline_pages/core/background/request_coordinator_unittest.cc
@@ -162,6 +162,7 @@ RequestCoordinator* coordinator() const { return coordinator_taco_->request_coordinator(); } + OfflinerStub* offliner() const { return offliner_; } SchedulerStub* scheduler_stub() const { return reinterpret_cast<SchedulerStub*>(coordinator()->scheduler()); } @@ -225,6 +226,8 @@ offliner_->enable_snapshot_on_last_retry(); } + bool OfflinerCalled() const { return offliner_->load_and_save_called(); } + void SetEffectiveConnectionTypeForTest(net::EffectiveConnectionType type) { network_quality_tracker_->ReportEffectiveConnectionTypeForTesting(type); } @@ -331,6 +334,11 @@ return coordinator()->last_offlining_status_; } + // Calls the private method |StopProcessing| on |coordinator()|. + void StopProcessing(Offliner::RequestStatus stop_status) { + coordinator()->StopProcessing(stop_status); + } + bool OfflinerWasCanceled() const { return offliner_->cancel_called(); } void ResetOfflinerWasCanceled() { offliner_->reset_cancel_called(); } @@ -367,6 +375,10 @@ bool add_request_callback_called() { return add_request_callback_called_; } + scoped_refptr<base::TestMockTimeTaskRunner> task_runner() const { + return task_runner_; + } + protected: ActiveTabInfoStub* active_tab_info_ = nullptr; @@ -1078,9 +1090,9 @@ processing_callback())); EXPECT_TRUE(state() == RequestCoordinatorState::PICKING); - // Now, quick, before it can do much (we haven't called PumpLoop), cancel it. - coordinator()->StopProcessing( - Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED); + // Now, quick, before it can do much (we haven't called PumpLoop), cancel it + // with a status that precludes trying again. + StopProcessing(Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED); // Let the async callbacks in the request coordinator run. PumpLoop(); @@ -1090,7 +1102,7 @@ // OfflinerDoneCallback will not end up getting called with status SAVED, // since we cancelled the event before it called offliner_->LoadAndSave(). - EXPECT_EQ(Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED, + EXPECT_EQ(Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED, last_offlining_status()); // Since offliner was not started, it will not have seen cancel call. @@ -1128,8 +1140,7 @@ EXPECT_FALSE(state() == RequestCoordinatorState::PICKING); // Now we cancel it while the background loader is busy. - coordinator()->StopProcessing( - Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED); + StopProcessing(Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED); // Let the async callbacks in the cancel run. PumpLoop(); @@ -1143,13 +1154,61 @@ // OfflinerDoneCallback will not end up getting called with status SAVED, // since we cancelled the event before the LoadAndSave completed. - EXPECT_EQ(Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED, + EXPECT_EQ(Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED, last_offlining_status()); // Since offliner was started, it will have seen cancel call. EXPECT_TRUE(OfflinerWasCanceled()); } +// Test handling of StartScheduledProcessing before a previous attempt has been +// fully stopped. +TEST_F(RequestCoordinatorTest, StartAttemptBeforeFullyStopped) { + // Add a request to the queue, wait for callbacks to finish. + AddRequest1(); + PumpLoop(); + + // Ensure the start processing request stops before the completion callback. + EnableOfflinerCallback(false); + + ASSERT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(), + processing_callback())); + // Let all the async parts of the start processing pipeline run to completion. + PumpLoop(); + + // Observer called for starting processing. + ASSERT_TRUE(observer().changed_called()); + ASSERT_EQ(SavePageRequest::RequestState::OFFLINING, observer().state()); + observer().Clear(); + + // Now we cancel it while the background loader is busy, and attempt to start + // another request. Because the previous request hasn't completely stopped, + // the second request will not start. + StopProcessing(Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED); + + AddRequest2(); + EXPECT_FALSE(coordinator()->StartScheduledProcessing(device_conditions(), + processing_callback())); + PumpLoop(); + EXPECT_FALSE(offliner()->has_pending_request()); +} + +// Verify the request coordinator can stop while in the picking state. +TEST_F(RequestCoordinatorTest, StopProcessingWhilePicking) { + // Add a request and start processing. + AddRequest1(); + ASSERT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(), + processing_callback())); + ASSERT_EQ(RequestCoordinatorState::PICKING, state()); + + StopProcessing(Offliner::RequestStatus::BACKGROUND_SCHEDULER_CANCELED); + + // Let all the async parts of the start processing pipeline run to completion. + // The offliner should have never been called. + PumpLoop(); + EXPECT_FALSE(OfflinerCalled()); +} + // This tests that canceling a request will result in TryNextRequest() getting // called. TEST_F(RequestCoordinatorTest, RemoveInflightRequest) { @@ -1181,6 +1240,44 @@ EXPECT_TRUE(OfflinerWasCanceled()); } +TEST_F(RequestCoordinatorTest, RemoveInflightRequestAndAddAnother) { + // Add a request to the queue, wait for callbacks to finish. + AddRequest1(); + PumpLoop(); + // Test a different ordering of tasks, by delaying the offliner cancellation. + offliner()->set_cancel_delay(base::TimeDelta::FromSeconds(1)); + // Ensure the start processing request stops before the completion callback. + EnableOfflinerCallback(false); + + EXPECT_TRUE(coordinator()->StartScheduledProcessing(device_conditions(), + processing_callback())); + + // Let all the async parts of the start processing pipeline run to completion. + PumpLoop(); + // Since the offliner is disabled, this callback should not be called. + EXPECT_FALSE(processing_callback_called()); + + // Add a new request, and remove current request while it is processing. + RequestCoordinator::SavePageLaterParams request2; + request2.url = kUrl2; + request2.client_id = kClientId2; + request2.user_requested = true; + coordinator()->SavePageLater(request2, base::DoNothing()); + + std::vector<int64_t> request_ids{kRequestId1}; + coordinator()->RemoveRequests( + request_ids, base::BindOnce(&RequestCoordinatorTest::RemoveRequestsDone, + base::Unretained(this))); + + AdvanceClockBy(base::TimeDelta::FromSeconds(2)); + + // Since offliner was started, it will have seen cancel call. + EXPECT_TRUE(OfflinerWasCanceled()); + // The second request should be offlining now. + EXPECT_TRUE(offliner()->has_pending_request()); + EXPECT_TRUE(state() == RequestCoordinatorState::OFFLINING); +} + TEST_F(RequestCoordinatorTest, MarkRequestCompleted) { int64_t request_id = SavePageLaterWithAvailability( RequestCoordinator::RequestAvailability::DISABLED_FOR_OFFLINER);
diff --git a/components/offline_pages/core/model/clear_storage_task_unittest.cc b/components/offline_pages/core/model/clear_storage_task_unittest.cc index 93f7736..bfecdd3 100644 --- a/components/offline_pages/core/model/clear_storage_task_unittest.cc +++ b/components/offline_pages/core/model/clear_storage_task_unittest.cc
@@ -12,10 +12,12 @@ #include "base/files/file_util.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/simple_test_clock.h" +#include "base/time/clock.h" #include "base/time/time.h" #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/model/model_task_test_base.h" #include "components/offline_pages/core/model/offline_page_test_utils.h" +#include "components/offline_pages/core/test_scoped_offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { @@ -87,7 +89,7 @@ } ArchiveManager* archive_manager() { return archive_manager_.get(); } - base::SimpleTestClock* clock() { return &clock_; } + TestScopedOfflineClock* clock() { return &clock_; } size_t last_cleared_page_count() { return last_cleared_page_count_; } int total_cleared_times() { return total_cleared_times_; } ClearStorageResult last_clear_storage_result() { @@ -97,7 +99,7 @@ private: std::unique_ptr<TestArchiveManager> archive_manager_; - base::SimpleTestClock clock_; + TestScopedOfflineClock clock_; size_t last_cleared_page_count_; int total_cleared_times_; @@ -156,16 +158,17 @@ generator()->SetArchiveDirectory(PrivateDir()); } + generator()->SetLastAccessTime(clock_.Now()); for (int i = 0; i < setting.fresh_page_count; ++i) { - generator()->SetLastAccessTime(clock_.Now()); AddPage(); } + + generator()->SetLastAccessTime(clock_.Now() - + policy_controller() + ->GetPolicy(setting.name_space) + .lifetime_policy.expiration_period); for (int i = 0; i < setting.expired_page_count; ++i) { // Make the pages expired. - generator()->SetLastAccessTime(clock_.Now() - - policy_controller() - ->GetPolicy(setting.name_space) - .lifetime_policy.expiration_period); AddPage(); } }
diff --git a/components/offline_pages/core/model/delete_page_task.cc b/components/offline_pages/core/model/delete_page_task.cc index 4825332..08bfd6f7 100644 --- a/components/offline_pages/core/model/delete_page_task.cc +++ b/components/offline_pages/core/model/delete_page_task.cc
@@ -8,10 +8,12 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/metrics/histogram_functions.h" +#include "base/time/clock.h" #include "base/time/time.h" #include "build/build_config.h" #include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/model/offline_page_model_utils.h" +#include "components/offline_pages/core/offline_clock.h" #include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/offline_page_metadata_store.h" #include "components/offline_pages/core/offline_page_model.h" @@ -82,7 +84,7 @@ void ReportDeletePageHistograms( const std::vector<DeletedPageInfoWrapper>& info_wrappers) { const int max_minutes = base::TimeDelta::FromDays(365).InMinutes(); - base::Time delete_time = base::Time::Now(); + base::Time delete_time = OfflineClock()->Now(); for (const auto& info_wrapper : info_wrappers) { base::UmaHistogramCustomCounts( model_utils::AddHistogramSuffix(info_wrapper.client_id.name_space,
diff --git a/components/offline_pages/core/model/delete_page_task_unittest.cc b/components/offline_pages/core/model/delete_page_task_unittest.cc index bb9ad90..88a4784 100644 --- a/components/offline_pages/core/model/delete_page_task_unittest.cc +++ b/components/offline_pages/core/model/delete_page_task_unittest.cc
@@ -13,9 +13,12 @@ #include "base/optional.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" +#include "base/time/clock.h" +#include "base/time/time.h" #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/model/model_task_test_base.h" #include "components/offline_pages/core/model/offline_page_model_utils.h" +#include "components/offline_pages/core/offline_clock.h" #include "components/offline_pages/core/offline_page_types.h" #include "components/offline_pages/core/offline_store_types.h" #include "testing/gtest/include/gtest/gtest.h" @@ -421,7 +424,7 @@ generator()->SetNamespace(kTestNamespace); generator()->SetUrl(kTestUrl1); // Guarantees that page1 will be deleted by making it older. - base::Time now = base::Time::Now(); + base::Time now = OfflineClock()->Now(); generator()->SetLastAccessTime(now - base::TimeDelta::FromMinutes(5)); OfflinePageItem page1 = generator()->CreateItemWithTempFile(); generator()->SetLastAccessTime(now);
diff --git a/components/offline_pages/core/model/get_pages_task_unittest.cc b/components/offline_pages/core/model/get_pages_task_unittest.cc index 831c7791..d55772e5 100644 --- a/components/offline_pages/core/model/get_pages_task_unittest.cc +++ b/components/offline_pages/core/model/get_pages_task_unittest.cc
@@ -5,9 +5,9 @@ #include "components/offline_pages/core/model/get_pages_task.h" #include <stdint.h> - #include <utility> +#include "base/time/time.h" #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/model/model_task_test_base.h" #include "components/offline_pages/core/offline_page_types.h"
diff --git a/components/offline_pages/core/model/mark_page_accessed_task_unittest.cc b/components/offline_pages/core/model/mark_page_accessed_task_unittest.cc index 5b73e60..b19bb58 100644 --- a/components/offline_pages/core/model/mark_page_accessed_task_unittest.cc +++ b/components/offline_pages/core/model/mark_page_accessed_task_unittest.cc
@@ -7,9 +7,11 @@ #include <memory> #include "base/test/metrics/histogram_tester.h" +#include "base/time/clock.h" #include "base/time/time.h" #include "components/offline_pages/core/model/model_task_test_base.h" #include "components/offline_pages/core/model/offline_page_model_utils.h" +#include "components/offline_pages/core/offline_clock.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { @@ -36,7 +38,7 @@ kTestFileSize); store_test_util()->InsertItem(page); - base::Time current_time = base::Time::Now(); + base::Time current_time = OfflineClock()->Now(); auto task = std::make_unique<MarkPageAccessedTask>(store(), kTestOfflineId, current_time); RunTask(std::move(task)); @@ -62,7 +64,7 @@ kTestFileSize); store_test_util()->InsertItem(page); - base::Time current_time = base::Time::Now(); + base::Time current_time = OfflineClock()->Now(); auto task = std::make_unique<MarkPageAccessedTask>(store(), kTestOfflineId, current_time); RunTask(std::move(task)); @@ -83,7 +85,7 @@ "OfflinePages.PageAccessInterval"), (current_time - page.last_access_time).InMinutes(), 1); - base::Time second_time = base::Time::Now(); + base::Time second_time = OfflineClock()->Now(); task = std::make_unique<MarkPageAccessedTask>(store(), kTestOfflineId, second_time); RunTask(std::move(task));
diff --git a/components/offline_pages/core/model/offline_page_model_taskified.cc b/components/offline_pages/core/model/offline_page_model_taskified.cc index a966e392..c53ed883 100644 --- a/components/offline_pages/core/model/offline_page_model_taskified.cc +++ b/components/offline_pages/core/model/offline_page_model_taskified.cc
@@ -15,8 +15,6 @@ #include "base/strings/string16.h" #include "base/task/post_task.h" #include "base/threading/thread_task_runner_handle.h" -#include "base/time/clock.h" -#include "base/time/default_clock.h" #include "base/time/time.h" #include "components/offline_pages/core/archive_manager.h" #include "components/offline_pages/core/client_namespace_constants.h" @@ -32,6 +30,7 @@ #include "components/offline_pages/core/model/startup_maintenance_task.h" #include "components/offline_pages/core/model/store_thumbnail_task.h" #include "components/offline_pages/core/model/update_file_path_task.h" +#include "components/offline_pages/core/offline_clock.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/offline_page_metadata_store.h" #include "components/offline_pages/core/offline_page_model.h" @@ -184,13 +183,11 @@ std::unique_ptr<OfflinePageMetadataStore> store, std::unique_ptr<ArchiveManager> archive_manager, std::unique_ptr<SystemDownloadManager> download_manager, - const scoped_refptr<base::SequencedTaskRunner>& task_runner, - base::Clock* clock) + const scoped_refptr<base::SequencedTaskRunner>& task_runner) : store_(std::move(store)), archive_manager_(std::move(archive_manager)), download_manager_(std::move(download_manager)), policy_controller_(new ClientPolicyController()), - clock_(clock), task_queue_(this), skip_clearing_original_url_for_testing_(false), skip_maintenance_tasks_for_testing_(false), @@ -255,7 +252,7 @@ create_archive_params, web_contents, base::BindOnce(&OfflinePageModelTaskified::OnCreateArchiveDone, weak_ptr_factory_.GetWeakPtr(), save_page_params, - offline_id, GetCurrentTime(), std::move(archiver), + offline_id, OfflineTimeNow(), std::move(archiver), std::move(callback))); } @@ -271,7 +268,7 @@ void OfflinePageModelTaskified::MarkPageAccessed(int64_t offline_id) { auto task = std::make_unique<MarkPageAccessedTask>(store_.get(), offline_id, - GetCurrentTime()); + OfflineTimeNow()); task_queue_.AddTask(std::move(task)); } @@ -535,7 +532,7 @@ download_manager_.get(), base::BindOnce(&OfflinePageModelTaskified::PublishArchiveDone, weak_ptr_factory_.GetWeakPtr(), std::move(archiver), - std::move(callback), GetCurrentTime())); + std::move(callback), OfflineTimeNow())); return; } @@ -545,7 +542,7 @@ AddPage(offline_page, base::BindOnce(&OfflinePageModelTaskified::OnAddPageForSavePageDone, weak_ptr_factory_.GetWeakPtr(), std::move(callback), - offline_page, GetCurrentTime())); + offline_page, OfflineTimeNow())); // Note: If the archiver instance ownership was not transferred, it will be // deleted here. } @@ -565,7 +562,7 @@ return; } - const base::Time add_page_start_time = GetCurrentTime(); + const base::Time add_page_start_time = OfflineTimeNow(); base::UmaHistogramTimes(model_utils::AddHistogramSuffix( offline_page.client_id.name_space, "OfflinePages.SavePage.PublishArchiveTime"), @@ -630,7 +627,7 @@ InformSavePageDone(std::move(callback), save_page_result, page_attempted.client_id, offline_id); if (save_page_result == SavePageResult::SUCCESS) { - base::Time successful_finish_time = GetCurrentTime(); + base::Time successful_finish_time = OfflineTimeNow(); base::UmaHistogramTimes( model_utils::AddHistogramSuffix(page_attempted.client_id.name_space, "OfflinePages.SavePage.AddPageTime"), @@ -711,7 +708,7 @@ if (skip_maintenance_tasks_for_testing_) return; // If not enough time has passed, don't queue maintenance tasks. - base::Time now = GetCurrentTime(); + base::Time now = OfflineClock()->Now(); if (now - last_maintenance_tasks_schedule_time_ < kClearStorageInterval) return; @@ -736,7 +733,7 @@ store_.get(), archive_manager_.get(), policy_controller_.get())); task_queue_.AddTask(std::make_unique<CleanupThumbnailsTask>( - store_.get(), GetCurrentTime(), base::DoNothing())); + store_.get(), OfflineClock()->Now(), base::DoNothing())); } task_queue_.AddTask(std::make_unique<ClearStorageTask>( @@ -820,9 +817,4 @@ archive_manager_->EnsureArchivesDirCreated(base::DoNothing()); } -base::Time OfflinePageModelTaskified::GetCurrentTime() { - CHECK(clock_); - return clock_->Now(); -} - } // namespace offline_pages
diff --git a/components/offline_pages/core/model/offline_page_model_taskified.h b/components/offline_pages/core/model/offline_page_model_taskified.h index 1cfa4d30..201917e 100644 --- a/components/offline_pages/core/model/offline_page_model_taskified.h +++ b/components/offline_pages/core/model/offline_page_model_taskified.h
@@ -71,8 +71,7 @@ std::unique_ptr<OfflinePageMetadataStore> store, std::unique_ptr<ArchiveManager> archive_manager, std::unique_ptr<SystemDownloadManager> download_manager, - const scoped_refptr<base::SequencedTaskRunner>& task_runner, - base::Clock* clock); + const scoped_refptr<base::SequencedTaskRunner>& task_runner); ~OfflinePageModelTaskified() override; // TaskQueue::Delegate implementation. @@ -141,7 +140,6 @@ // Methods for testing only: OfflinePageMetadataStore* GetStoreForTesting() { return store_.get(); } - void SetClockForTesting(base::Clock* clock) { clock_ = clock; } void SetSkipClearingOriginalUrlForTesting() { skip_clearing_original_url_for_testing_ = true; } @@ -226,7 +224,6 @@ // Other utility methods. void RemovePagesMatchingUrlAndNamespace(const OfflinePageItem& page); void CreateArchivesDirectoryIfNeeded(); - base::Time GetCurrentTime(); // Persistent store for offline page metadata. std::unique_ptr<OfflinePageMetadataStore> store_; @@ -243,9 +240,6 @@ // The observers. base::ObserverList<Observer>::Unchecked observers_; - // Clock for testing only. - base::Clock* clock_ = nullptr; - // Logger to facilitate recording of events. OfflinePageModelEventLogger offline_event_logger_;
diff --git a/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc b/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc index 708f73d..3f5faa14 100644 --- a/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc +++ b/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc
@@ -17,6 +17,7 @@ #include "base/test/mock_callback.h" #include "base/test/scoped_feature_list.h" #include "base/test/test_mock_time_task_runner.h" +#include "base/time/clock.h" #include "build/build_config.h" #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/model/clear_storage_task.h" @@ -33,6 +34,7 @@ #include "components/offline_pages/core/offline_page_types.h" #include "components/offline_pages/core/offline_store_utils.h" #include "components/offline_pages/core/stub_system_download_manager.h" +#include "components/offline_pages/core/test_scoped_offline_clock.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -136,11 +138,13 @@ // Getters for private fields. base::TestMockTimeTaskRunner* task_runner() { return task_runner_.get(); } + base::Clock* clock() { return task_runner_->GetMockClock(); } OfflinePageModelTaskified* model() { return model_.get(); } OfflinePageMetadataStore* store() { return store_test_util_.store(); } OfflinePageMetadataStoreTestUtil* store_test_util() { return &store_test_util_; } + StubSystemDownloadManager* download_manager_stub() { return download_manager_stub_; } @@ -182,6 +186,8 @@ base::ScopedTempDir private_archive_dir_; base::ScopedTempDir public_archive_dir_; + TestScopedOfflineClockOverride clock_; + base::FilePath last_path_created_by_archiver_; bool observer_add_page_called_; OfflinePageItem last_added_page_; @@ -193,7 +199,8 @@ : task_runner_(new base::TestMockTimeTaskRunner(base::Time::Now(), base::TimeTicks::Now())), task_runner_handle_(task_runner_), - store_test_util_(task_runner_) {} + store_test_util_(task_runner_), + clock_(task_runner_->GetMockClock()) {} OfflinePageModelTaskifiedTest::~OfflinePageModelTaskifiedTest() {} @@ -244,8 +251,7 @@ download_manager_stub_); model_ = std::make_unique<OfflinePageModelTaskified>( store_test_util()->ReleaseStore(), std::move(archive_manager), - std::move(download_manager), base::ThreadTaskRunnerHandle::Get(), - task_runner_->GetMockClock()); + std::move(download_manager), base::ThreadTaskRunnerHandle::Get()); model_->AddObserver(this); histogram_tester_ = std::make_unique<base::HistogramTester>(); ResetResults(); @@ -1491,8 +1497,8 @@ base::MockCallback<MultipleOfflinePageItemCallback> callback; model()->GetAllPages(callback.Get()); PumpLoop(); - EXPECT_EQ(task_runner()->Now(), last_maintenance_tasks_schedule_time()); - base::Time last_scheduling_time = task_runner()->Now(); + EXPECT_EQ(clock()->Now(), last_maintenance_tasks_schedule_time()); + base::Time last_scheduling_time = clock()->Now(); // Confirm no runs so far. histogram_tester()->ExpectTotalCount( "OfflinePages.ClearTemporaryPages.Result", 0); @@ -1514,7 +1520,7 @@ // Note: The previous elapsed delay is discounted from the clock advance here. task_runner()->FastForwardBy( OfflinePageModelTaskified::kClearStorageInterval / 2 - run_delay); - ASSERT_GT(task_runner()->Now(), last_scheduling_time); + ASSERT_GT(clock()->Now(), last_scheduling_time); model()->GetAllPages(callback.Get()); // And advance the delay too. task_runner()->FastForwardBy(run_delay); @@ -1535,7 +1541,7 @@ SavePageWithExpectedResult(kTestUrl, kTestClientId1, kTestUrl2, kEmptyRequestOrigin, std::move(archiver), SavePageResult::SUCCESS); - last_scheduling_time = task_runner()->Now(); + last_scheduling_time = clock()->Now(); // Advance the delay again. task_runner()->FastForwardBy(run_delay); PumpLoop(); @@ -1696,7 +1702,7 @@ // Store a thumbnail. OfflinePageThumbnail thumb; thumb.offline_id = 1; - thumb.expiration = base::Time::Now(); + thumb.expiration = clock()->Now(); thumb.thumbnail = "abc123"; model()->StoreThumbnail(thumb); EXPECT_CALL(*this, ThumbnailAdded(_, thumb));
diff --git a/components/offline_pages/core/offline_clock.cc b/components/offline_pages/core/offline_clock.cc index bb441844..60fc4b0 100644 --- a/components/offline_pages/core/offline_clock.cc +++ b/components/offline_pages/core/offline_clock.cc
@@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/time/default_clock.h" +#include "base/time/time.h" namespace offline_pages { @@ -26,4 +27,8 @@ custom_clock_ = clock; } +base::Time OfflineTimeNow() { + return OfflineClock()->Now(); +} + } // namespace offline_pages
diff --git a/components/offline_pages/core/offline_clock.h b/components/offline_pages/core/offline_clock.h index 5a15d6e..5cf384c 100644 --- a/components/offline_pages/core/offline_clock.h +++ b/components/offline_pages/core/offline_clock.h
@@ -7,6 +7,7 @@ namespace base { class Clock; +class Time; } namespace offline_pages { @@ -19,6 +20,10 @@ // use |TestScopedOfflineClock| instead if possible. void SetOfflineClockForTesting(base::Clock* clock); +// Returns the current time given by |OfflineClock|. This used as a shortcut +// for calls to |OfflineClock()->Now()| +base::Time OfflineTimeNow(); + } // namespace offline_pages #endif // COMPONENTS_OFFLINE_PAGES_CORE_OFFLINE_CLOCK_H_
diff --git a/components/offline_pages/core/offline_event_logger.cc b/components/offline_pages/core/offline_event_logger.cc index 55865ea..35afd20 100644 --- a/components/offline_pages/core/offline_event_logger.cc +++ b/components/offline_pages/core/offline_event_logger.cc
@@ -2,10 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/strings/stringprintf.h" -#include "base/time/time.h" #include "components/offline_pages/core/offline_event_logger.h" +#include "base/strings/stringprintf.h" +#include "base/time/clock.h" +#include "base/time/time.h" +#include "components/offline_pages/core/offline_clock.h" + namespace offline_pages { OfflineEventLogger::OfflineEventLogger() @@ -36,7 +39,7 @@ return; base::Time::Exploded current_time; - base::Time::Now().LocalExplode(¤t_time); + OfflineClock()->Now().LocalExplode(¤t_time); std::string date_string = base::StringPrintf( "%d %02d %02d %02d:%02d:%02d", current_time.year, current_time.month,
diff --git a/components/offline_pages/core/offline_page_metadata_store.cc b/components/offline_pages/core/offline_page_metadata_store.cc index 1e130ea7..890ff988 100644 --- a/components/offline_pages/core/offline_page_metadata_store.cc +++ b/components/offline_pages/core/offline_page_metadata_store.cc
@@ -13,7 +13,9 @@ #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" #include "base/strings/utf_string_conversions.h" +#include "base/time/clock.h" #include "components/offline_pages/core/client_namespace_constants.h" +#include "components/offline_pages/core/offline_clock.h" #include "components/offline_pages/core/offline_page_item.h" #include "components/offline_pages/core/offline_store_types.h" #include "components/offline_pages/core/offline_store_utils.h" @@ -411,7 +413,7 @@ if (!last_closing_time_.is_null()) { ReportStoreEvent(OfflinePagesStoreEvent::kReopened); UMA_HISTOGRAM_CUSTOM_TIMES("OfflinePages.SQLStorage.TimeFromCloseToOpen", - base::Time::Now() - last_closing_time_, + OfflineClock()->Now() - last_closing_time_, base::TimeDelta::FromMilliseconds(10), base::TimeDelta::FromMinutes(10), 50 /* buckets */); @@ -466,7 +468,7 @@ } TRACE_EVENT_ASYNC_STEP_PAST0("offline_pages", "Metadata Store", this, "Open"); - last_closing_time_ = base::Time::Now(); + last_closing_time_ = OfflineClock()->Now(); ReportStoreEvent(OfflinePagesStoreEvent::kClosed); state_ = StoreState::NOT_LOADED;
diff --git a/components/offline_pages/core/offline_page_metadata_store_unittest.cc b/components/offline_pages/core/offline_page_metadata_store_unittest.cc index 689a761..f455255 100644 --- a/components/offline_pages/core/offline_page_metadata_store_unittest.cc +++ b/components/offline_pages/core/offline_page_metadata_store_unittest.cc
@@ -17,8 +17,10 @@ #include "base/test/bind_test_util.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/clock.h" #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/model/offline_page_item_generator.h" +#include "components/offline_pages/core/offline_clock.h" #include "components/offline_pages/core/offline_page_item.h" #include "components/offline_pages/core/offline_page_metadata_store.h" #include "components/offline_pages/core/offline_page_model.h" @@ -134,7 +136,7 @@ statement.BindString(7, kTestClientId2.id); statement.BindCString(8, kTestURL); statement.BindString(9, base::FilePath(kFilePath).MaybeAsASCII()); - statement.BindInt64(10, store_utils::ToDatabaseTime(base::Time::Now())); + statement.BindInt64(10, store_utils::ToDatabaseTime(OfflineClock()->Now())); ASSERT_TRUE(statement.Run()); ASSERT_TRUE(connection.DoesTableExist(OFFLINE_PAGES_TABLE_V1)); ASSERT_FALSE(connection.DoesColumnExist(OFFLINE_PAGES_TABLE_V1, "title")); @@ -180,7 +182,7 @@ statement.BindString(7, kTestClientId2.id); statement.BindCString(8, kTestURL); statement.BindString(9, base::FilePath(kFilePath).MaybeAsASCII()); - statement.BindInt64(10, store_utils::ToDatabaseTime(base::Time::Now())); + statement.BindInt64(10, store_utils::ToDatabaseTime(OfflineClock()->Now())); statement.BindString16(11, base::UTF8ToUTF16("Test title")); ASSERT_TRUE(statement.Run()); ASSERT_TRUE(connection.DoesTableExist(OFFLINE_PAGES_TABLE_V1)); @@ -227,7 +229,7 @@ statement.BindString(6, kTestClientId2.id); statement.BindCString(7, kTestURL); statement.BindString(8, base::FilePath(kFilePath).MaybeAsASCII()); - statement.BindInt64(9, store_utils::ToDatabaseTime(base::Time::Now())); + statement.BindInt64(9, store_utils::ToDatabaseTime(OfflineClock()->Now())); statement.BindString16(10, base::UTF8ToUTF16("Test title")); ASSERT_TRUE(statement.Run()); ASSERT_TRUE(connection.DoesTableExist(OFFLINE_PAGES_TABLE_V1)); @@ -272,7 +274,7 @@ statement.BindString(6, kTestClientId2.id); statement.BindCString(7, kTestURL); statement.BindString(8, base::FilePath(kFilePath).MaybeAsASCII()); - statement.BindInt64(9, store_utils::ToDatabaseTime(base::Time::Now())); + statement.BindInt64(9, store_utils::ToDatabaseTime(OfflineClock()->Now())); statement.BindString16(10, base::UTF8ToUTF16("Test title")); statement.BindCString(11, kOriginalTestURL); ASSERT_TRUE(statement.Run()); @@ -894,7 +896,7 @@ base::FilePath(FILE_PATH_LITERAL("//other.page.com.mhtml")); OfflinePageItem offline_page_2(GURL("https://other.page.com"), 5678LL, kTestClientId2, file_path_2, 12345, - base::Time::Now(), kTestRequestOrigin); + OfflineClock()->Now(), kTestRequestOrigin); offline_page_2.original_url = GURL("https://example.com/bar"); offline_page_2.system_download_id = kTestSystemDownloadId; offline_page_2.digest = kTestDigest;
diff --git a/components/offline_pages/core/prefetch/prefetch_downloader_impl.cc b/components/offline_pages/core/prefetch/prefetch_downloader_impl.cc index ded2ef7..d700035 100644 --- a/components/offline_pages/core/prefetch/prefetch_downloader_impl.cc +++ b/components/offline_pages/core/prefetch/prefetch_downloader_impl.cc
@@ -8,11 +8,12 @@ #include "base/callback_helpers.h" #include "base/logging.h" #include "base/strings/string_util.h" -#include "base/time/default_clock.h" +#include "base/time/clock.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "components/download/public/background_service/download_params.h" #include "components/download/public/background_service/download_service.h" +#include "components/offline_pages/core/offline_clock.h" #include "components/offline_pages/core/offline_event_logger.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/prefetch/prefetch_dispatcher.h" @@ -38,8 +39,7 @@ PrefetchDownloaderImpl::PrefetchDownloaderImpl( download::DownloadService* download_service, version_info::Channel channel) - : clock_(base::DefaultClock::GetInstance()), - download_service_(download_service), + : download_service_(download_service), channel_(channel), weak_ptr_factory_(this) { DCHECK(download_service); @@ -117,7 +117,7 @@ params.scheduling_params.battery_requirements = download::SchedulingParams::BatteryRequirements::BATTERY_SENSITIVE; params.scheduling_params.cancel_time = - clock_->Now() + kPrefetchDownloadLifetime; + OfflineClock()->Now() + kPrefetchDownloadLifetime; params.request_params.url = PrefetchDownloadURL(download_location, channel_); std::string experiment_header = PrefetchExperimentHeader(); @@ -216,10 +216,6 @@ NotifyDispatcher(prefetch_service_, result); } -void PrefetchDownloaderImpl::SetClockForTesting(base::Clock* clock) { - clock_ = clock; -} - void PrefetchDownloaderImpl::OnStartDownload( const std::string& download_id, download::DownloadParams::StartResult result) {
diff --git a/components/offline_pages/core/prefetch/prefetch_downloader_impl.h b/components/offline_pages/core/prefetch/prefetch_downloader_impl.h index 3a7f0b0..e8258ef 100644 --- a/components/offline_pages/core/prefetch/prefetch_downloader_impl.h +++ b/components/offline_pages/core/prefetch/prefetch_downloader_impl.h
@@ -51,8 +51,6 @@ int64_t file_size) override; void OnDownloadFailed(const std::string& download_id) override; - void SetClockForTesting(base::Clock* clock); - private: enum class DownloadServiceStatus { // The download service is booting up. @@ -73,8 +71,6 @@ const std::map<std::string, std::pair<base::FilePath, int64_t>>& success_downloads); - base::Clock* clock_; - // Unowned. It is valid until |this| instance is disposed. download::DownloadService* download_service_;
diff --git a/components/offline_pages/core/prefetch/prefetch_downloader_impl_unittest.cc b/components/offline_pages/core/prefetch/prefetch_downloader_impl_unittest.cc index f77debc..a422ec31 100644 --- a/components/offline_pages/core/prefetch/prefetch_downloader_impl_unittest.cc +++ b/components/offline_pages/core/prefetch/prefetch_downloader_impl_unittest.cc
@@ -8,7 +8,7 @@ #include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" -#include "base/test/simple_test_clock.h" +#include "base/time/clock.h" #include "base/time/time.h" #include "components/download/public/background_service/test/test_download_service.h" #include "components/offline_pages/core/client_namespace_constants.h" @@ -18,6 +18,7 @@ #include "components/offline_pages/core/prefetch/prefetch_service_test_taco.h" #include "components/offline_pages/core/prefetch/test_download_client.h" #include "components/offline_pages/core/prefetch/test_prefetch_dispatcher.h" +#include "components/offline_pages/core/test_scoped_offline_clock.h" #include "net/base/url_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -45,7 +46,6 @@ auto downloader = std::make_unique<PrefetchDownloaderImpl>( &download_service_, kTestChannel); - downloader->SetClockForTesting(&clock_); download_service_.SetFailedDownload(kFailedDownloadId, false); download_service_.SetIsReady(true); download_client_ = std::make_unique<TestDownloadClient>(downloader.get()); @@ -82,7 +82,7 @@ return prefetch_dispatcher()->download_results; } - base::SimpleTestClock* clock() { return &clock_; } + TestScopedOfflineClock* clock() { return &clock_; } PrefetchDownloader* prefetch_downloader() const { return prefetch_service_taco_->prefetch_service()->GetPrefetchDownloader(); @@ -97,7 +97,7 @@ download::test::TestDownloadService download_service_; std::unique_ptr<TestDownloadClient> download_client_; std::unique_ptr<PrefetchServiceTestTaco> prefetch_service_taco_; - base::SimpleTestClock clock_; + TestScopedOfflineClock clock_; }; TEST_F(PrefetchDownloaderImplTest, DownloadParams) {
diff --git a/components/offline_pages/core/prefetch/prefetch_item.h b/components/offline_pages/core/prefetch/prefetch_item.h index 0a7c340d..d0af6340 100644 --- a/components/offline_pages/core/prefetch/prefetch_item.h +++ b/components/offline_pages/core/prefetch/prefetch_item.h
@@ -105,10 +105,10 @@ // item. It holds a negative value otherwise. int64_t archive_body_length = -1; - // The last time the URL was attempted to be added to the store. Normally this - // is just the time the item was added. If the same URL is added multiple - // times, this is the timestamp of the last time. creation_time - // is used as a proxy for priority. + // The last time the URL was suggested to be prefetched. Normally this is the + // time the item was initially added but if the same URL is suggested multiple + // times, it will be updated with the timestamp of the last time. + // |creation_time| is used as a proxy for priority. base::Time creation_time; // Time used for the expiration of the item depending on the applicable policy
diff --git a/components/offline_pages/core/prefetch/tasks/add_unique_urls_task_unittest.cc b/components/offline_pages/core/prefetch/tasks/add_unique_urls_task_unittest.cc index 86cbf7b..6df8ed8 100644 --- a/components/offline_pages/core/prefetch/tasks/add_unique_urls_task_unittest.cc +++ b/components/offline_pages/core/prefetch/tasks/add_unique_urls_task_unittest.cc
@@ -29,13 +29,19 @@ const char kClientId1[] = "ID-1"; const char kClientId2[] = "ID-2"; const char kClientId3[] = "ID-3"; -const GURL kTestURL1("https://www.google.com/"); -const GURL kTestURL2("http://www.example.com/"); -const GURL kTestURL3("https://news.google.com/"); const char kTestThumbnailURL[] = "http://thumbnail.com/"; -const base::string16 kTestTitle1 = base::ASCIIToUTF16("Title 1"); -const base::string16 kTestTitle2 = base::ASCIIToUTF16("Title 2"); -const base::string16 kTestTitle3 = base::ASCIIToUTF16("Title 3"); +PrefetchURL PrefetchURL1() { + return {kClientId1, GURL("https://www.url1.com/"), + base::ASCIIToUTF16("Title 1")}; +} +PrefetchURL PrefetchURL2() { + return {kClientId2, GURL("http://www.url2.com/"), + base::ASCIIToUTF16("Title 2")}; +} +PrefetchURL PrefetchURL3() { + return {kClientId3, GURL("http://www.url3.com/"), + base::ASCIIToUTF16("Title 3")}; +} } // namespace class AddUniqueUrlsTaskTest : public PrefetchTaskTestBase { @@ -70,37 +76,34 @@ TEST_F(AddUniqueUrlsTaskTest, AddTaskInEmptyStore) { std::vector<PrefetchURL> urls; - PrefetchURL url1{kClientId1, kTestURL1, kTestTitle1}; + PrefetchURL url1 = PrefetchURL1(); url1.thumbnail_url = GURL(kTestThumbnailURL); urls.push_back(url1); - urls.emplace_back(kClientId2, kTestURL2, kTestTitle2); + urls.push_back(PrefetchURL2()); RunTask(std::make_unique<AddUniqueUrlsTask>(dispatcher(), store(), kTestNamespace, urls)); std::map<std::string, PrefetchItem> items = GetAllItems(); ASSERT_EQ(2U, items.size()); + // Check that all fields of PrefetchURL are correct for item 1. ASSERT_GT(items.count(kClientId1), 0U); - EXPECT_EQ(kTestURL1, items[kClientId1].url); + EXPECT_EQ(PrefetchURL1().url, items[kClientId1].url); EXPECT_EQ(kTestNamespace, items[kClientId1].client_id.name_space); - EXPECT_EQ(kTestTitle1, items[kClientId1].title); - ASSERT_GT(items.count(kClientId2), 0U); + EXPECT_EQ(PrefetchURL1().title, items[kClientId1].title); EXPECT_EQ(kTestThumbnailURL, items[kClientId1].thumbnail_url); - ASSERT_GT(items.count(kClientId2), 0ul); - EXPECT_EQ(kTestURL2, items[kClientId2].url); - EXPECT_EQ(kTestNamespace, items[kClientId2].client_id.name_space); - EXPECT_EQ(kTestTitle2, items[kClientId2].title); - EXPECT_GT(items[kClientId1].creation_time, items[kClientId2].creation_time); + // Check that the second item exists. + ASSERT_GT(items.count(kClientId2), 0UL); EXPECT_EQ(1, dispatcher()->task_schedule_count); } TEST_F(AddUniqueUrlsTaskTest, SingleDuplicateUrlNotAdded) { // Add the same URL twice in a single round. Only one entry should be added. - std::vector<PrefetchURL> urls = { - {kClientId1, kTestURL1, kTestTitle1}, - {kClientId2, kTestURL1, kTestTitle2}, - }; + PrefetchURL item1 = PrefetchURL1(); + PrefetchURL item2 = PrefetchURL2(); + item2.url = item1.url; + const std::vector<PrefetchURL> urls = {item1, item2}; RunTask(std::make_unique<AddUniqueUrlsTask>(dispatcher(), store(), kTestNamespace, urls)); EXPECT_EQ(1, dispatcher()->task_schedule_count); @@ -125,10 +128,9 @@ clock.SetNow(start_time); // Populate the store with pre-existing items. - std::vector<PrefetchURL> urls = {{kClientId1, kTestURL1, kTestTitle1}, - {kClientId2, kTestURL2, kTestTitle2}}; - RunTask(std::make_unique<AddUniqueUrlsTask>(dispatcher(), store(), - kTestNamespace, urls)); + RunTask(std::make_unique<AddUniqueUrlsTask>( + dispatcher(), store(), kTestNamespace, + std::vector<PrefetchURL>{PrefetchURL1(), PrefetchURL2()})); EXPECT_EQ(1, dispatcher()->task_schedule_count); // Advance time by 1 hour to verify that timestamp of ID-1 is updated on the @@ -138,13 +140,14 @@ // Turn ID-1 and ID-2 items into zombies. // Note: ZombifyPrefetchItem returns the number of affected items. - EXPECT_EQ(1, store_util()->ZombifyPrefetchItems(kTestNamespace, kTestURL1)); - EXPECT_EQ(1, store_util()->ZombifyPrefetchItems(kTestNamespace, kTestURL2)); + EXPECT_EQ(1, store_util()->ZombifyPrefetchItems(kTestNamespace, + PrefetchURL1().url)); + EXPECT_EQ(1, store_util()->ZombifyPrefetchItems(kTestNamespace, + PrefetchURL2().url)); - urls = {{kClientId1, kTestURL1, kTestTitle1}, - {kClientId3, kTestURL3, kTestTitle3}}; - RunTask(std::make_unique<AddUniqueUrlsTask>(dispatcher(), store(), - kTestNamespace, urls)); + RunTask(std::make_unique<AddUniqueUrlsTask>( + dispatcher(), store(), kTestNamespace, + std::vector<PrefetchURL>{PrefetchURL1(), PrefetchURL3()})); EXPECT_EQ(2, dispatcher()->task_schedule_count); std::map<std::string, PrefetchItem> items = GetAllItems(); @@ -152,9 +155,9 @@ ASSERT_GT(items.count(kClientId1), 0U); // Re-suggested ID-1 should have its timestamp updated. - EXPECT_EQ(kTestURL1, items[kClientId1].url); + EXPECT_EQ(PrefetchURL1().url, items[kClientId1].url); EXPECT_EQ(kTestNamespace, items[kClientId1].client_id.name_space); - EXPECT_EQ(kTestTitle1, items[kClientId1].title); + EXPECT_EQ(PrefetchURL1().title, items[kClientId1].title); EXPECT_EQ(PrefetchItemState::ZOMBIE, items[kClientId1].state); // Note: as timestamps are inserted with microsecond variations, we're // comparing them using a safe range of 1 second. @@ -167,9 +170,9 @@ // Previously existing ID-2 should not have been modified. ASSERT_GT(items.count(kClientId2), 0U); - EXPECT_EQ(kTestURL2, items[kClientId2].url); + EXPECT_EQ(PrefetchURL2().url, items[kClientId2].url); EXPECT_EQ(kTestNamespace, items[kClientId2].client_id.name_space); - EXPECT_EQ(kTestTitle2, items[kClientId2].title); + EXPECT_EQ(PrefetchURL2().title, items[kClientId2].title); EXPECT_EQ(PrefetchItemState::ZOMBIE, items[kClientId2].state); EXPECT_LE(start_time, items[kClientId2].creation_time); EXPECT_GE(start_time + base::TimeDelta::FromSeconds(1), @@ -180,9 +183,9 @@ // Newly suggested ID-3 should be added. ASSERT_GT(items.count(kClientId3), 0U); - EXPECT_EQ(kTestURL3, items[kClientId3].url); + EXPECT_EQ(PrefetchURL3().url, items[kClientId3].url); EXPECT_EQ(kTestNamespace, items[kClientId3].client_id.name_space); - EXPECT_EQ(kTestTitle3, items[kClientId3].title); + EXPECT_EQ(PrefetchURL3().title, items[kClientId3].title); EXPECT_EQ(PrefetchItemState::NEW_REQUEST, items[kClientId3].state); EXPECT_LE(later_time, items[kClientId3].creation_time); EXPECT_GE(later_time + base::TimeDelta::FromSeconds(1),
diff --git a/components/offline_pages/core/test_scoped_offline_clock.cc b/components/offline_pages/core/test_scoped_offline_clock.cc index dc9ea68..1374c3d9 100644 --- a/components/offline_pages/core/test_scoped_offline_clock.cc +++ b/components/offline_pages/core/test_scoped_offline_clock.cc
@@ -8,11 +8,17 @@ namespace offline_pages { -TestScopedOfflineClock::TestScopedOfflineClock() { - SetOfflineClockForTesting(this); +TestScopedOfflineClockOverride::TestScopedOfflineClockOverride( + base::Clock* clock) { + SetOfflineClockForTesting(clock); } -TestScopedOfflineClock::~TestScopedOfflineClock() { + +TestScopedOfflineClockOverride::~TestScopedOfflineClockOverride() { SetOfflineClockForTesting(nullptr); } +TestScopedOfflineClock::TestScopedOfflineClock() : override_(this) {} + +TestScopedOfflineClock::~TestScopedOfflineClock() {} + } // namespace offline_pages
diff --git a/components/offline_pages/core/test_scoped_offline_clock.h b/components/offline_pages/core/test_scoped_offline_clock.h index be25a21a..00a5775 100644 --- a/components/offline_pages/core/test_scoped_offline_clock.h +++ b/components/offline_pages/core/test_scoped_offline_clock.h
@@ -10,6 +10,17 @@ namespace offline_pages { +// Overrides |OfflineClock()| with |clock| upon construction. Returns +// |OfflineClock()| to its original state upon destruction. +class TestScopedOfflineClockOverride { + public: + explicit TestScopedOfflineClockOverride(base::Clock* clock); + ~TestScopedOfflineClockOverride(); + + private: + DISALLOW_COPY_AND_ASSIGN(TestScopedOfflineClockOverride); +}; + // Overrides |OfflineClock()| with |this| upon construction. Returns // |OfflineClock()| to its original state upon destruction. class TestScopedOfflineClock : public base::SimpleTestClock { @@ -18,6 +29,8 @@ ~TestScopedOfflineClock() override; private: + TestScopedOfflineClockOverride override_; + DISALLOW_COPY_AND_ASSIGN(TestScopedOfflineClock); };
diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omnibox/browser/autocomplete_result.cc index a12d7ab1b..ecc5e1e 100644 --- a/components/omnibox/browser/autocomplete_result.cc +++ b/components/omnibox/browser/autocomplete_result.cc
@@ -31,6 +31,8 @@ #include "third_party/metrics_proto/omnibox_input_type.pb.h" #include "ui/base/l10n/l10n_util.h" +typedef AutocompleteMatchType ACMatchType; + struct MatchGURLHash { // The |bool| is whether the match is a calculator suggestion. We want them // compare differently against other matches with the same URL. @@ -122,7 +124,7 @@ i.description); matches_.push_back(i); if (!AutocompleteMatch::IsSearchType(i.type) && - i.type != AutocompleteMatchType::DOCUMENT_SUGGESTION) { + i.type != ACMatchType::DOCUMENT_SUGGESTION) { const OmniboxFieldTrial::EmphasizeTitlesCondition condition( OmniboxFieldTrial::GetEmphasizeTitlesConditionForInput(input)); bool emphasize = false; @@ -415,6 +417,42 @@ : GURL(); } +// static +bool AutocompleteResult::IsBetterMatch( + AutocompleteMatch& first, + AutocompleteMatch& second, + metrics::OmniboxEventProto::PageClassification page_classification) { + // This object implements greater than. + CompareWithDemoteByType<AutocompleteMatch> compare_demote_by_type( + page_classification); + + if (first.type == ACMatchType::SEARCH_SUGGEST_ENTITY && + second.type != ACMatchType::SEARCH_SUGGEST_ENTITY) { + // If |first| is an entity suggestion and |second| isn't, |first| is + // considered better. If its type-adjusted relevance is lower, boost it to + // the value of |second|. + if (compare_demote_by_type(second, first)) { + first.RecordAdditionalInfo(kScoreBoostedFrom, second.relevance); + first.relevance = second.relevance; + } + return true; + } else if (first.type != ACMatchType::SEARCH_SUGGEST_ENTITY && + second.type == ACMatchType::SEARCH_SUGGEST_ENTITY) { + // Likewise, if |second| is an entity suggestion and |first| isn't, first + // is not considered better, even if it has a higher type-adjusted + // relevance. If it does have a higher relevance, boost |second|. + if (compare_demote_by_type(first, second)) { + second.RecordAdditionalInfo(kScoreBoostedFrom, first.relevance); + second.relevance = first.relevance; + } + return false; + } + + // In the case that both values are entity suggestions or both aren't, |first| + // is simply considered better if it's type-adjusted relevance is higher. + return compare_demote_by_type(first, second); +} + void AutocompleteResult::SortAndDedupMatches( metrics::OmniboxEventProto::PageClassification page_classification, ACMatches* matches) { @@ -426,31 +464,28 @@ std::pair<GURL, bool> p = GetMatchComparisonFields(*i); url_to_matches[p].push_back(i); } - CompareWithDemoteByType<AutocompleteMatch> compare_demote_by_type( - page_classification); // Find best default, and non-default, match in each group. for (auto& group : url_to_matches) { - const auto& p = group.first; - const GURL& gurl = p.first; + const auto& key = group.first; + const GURL& gurl = key.first; // The list of matches whose URL are equivalent. - auto& duplicate_matches = group.second; + std::list<ACMatches::iterator>& duplicate_matches = group.second; if (gurl.is_empty() || duplicate_matches.size() == 1) continue; auto best_match = duplicate_matches.end(); auto best_default = duplicate_matches.end(); - for (auto i = duplicate_matches.begin(); i != duplicate_matches.end(); - ++i) { - if ((*i)->allowed_to_be_default_match) { + for (auto match = duplicate_matches.begin(); + match != duplicate_matches.end(); ++match) { + if ((*match)->allowed_to_be_default_match) { if (best_default == duplicate_matches.end() || - // This object implements greater than. - compare_demote_by_type(**i, **best_default)) { - best_default = i; + IsBetterMatch(**match, **best_default, page_classification)) { + best_default = match; } } if (best_match == duplicate_matches.end() || - compare_demote_by_type(**i, **best_match)) { - best_match = i; + IsBetterMatch(**match, **best_match, page_classification)) { + best_match = match; } } if (best_match != best_default && best_default != duplicate_matches.end()) { @@ -490,7 +525,7 @@ base::string16 common_prefix; for (const auto& match : matches_) { - if (match.type == AutocompleteMatchType::SEARCH_SUGGEST_TAIL) { + if (match.type == ACMatchType::SEARCH_SUGGEST_TAIL) { int common_length; base::StringToInt( match.GetAdditionalInfo(kACMatchPropertyContentsStartIndex), @@ -530,7 +565,7 @@ void AutocompleteResult::MaybeCullTailSuggestions(ACMatches* matches) { std::function<bool(const AutocompleteMatch&)> is_tail = [](const AutocompleteMatch& match) { - return match.type == AutocompleteMatchType::SEARCH_SUGGEST_TAIL; + return match.type == ACMatchType::SEARCH_SUGGEST_TAIL; }; auto non_tail_default = std::find_if( matches->begin(), matches->end(), [&](const AutocompleteMatch& match) { @@ -630,5 +665,5 @@ std::pair<GURL, bool> AutocompleteResult::GetMatchComparisonFields( const AutocompleteMatch& match) { return std::make_pair(match.stripped_destination_url, - match.type == AutocompleteMatchType::CALCULATOR); + match.type == ACMatchType::CALCULATOR); }
diff --git a/components/omnibox/browser/autocomplete_result.h b/components/omnibox/browser/autocomplete_result.h index afd1841..2fc01098 100644 --- a/components/omnibox/browser/autocomplete_result.h +++ b/components/omnibox/browser/autocomplete_result.h
@@ -148,6 +148,16 @@ typedef ACMatches::iterator::difference_type matches_difference_type; #endif + // Returns true if |first| is preferred over |second| based on the type and + // relevance (as adjusted by the context of the match type and page type). If + // one candidate is preferred over another despite having lower type-adjusted + // relevance, copies the relevance from the higher relevance match into the + // lower. + static bool IsBetterMatch( + AutocompleteMatch& first, + AutocompleteMatch& second, + metrics::OmniboxEventProto::PageClassification page_classification); + // Returns true if |matches| contains a match with the same destination as // |match|. static bool HasMatchByDestination(const AutocompleteMatch& match,
diff --git a/components/omnibox/browser/base_search_provider.cc b/components/omnibox/browser/base_search_provider.cc index 43a3db4..7f4dab29 100644 --- a/components/omnibox/browser/base_search_provider.cc +++ b/components/omnibox/browser/base_search_provider.cc
@@ -293,8 +293,6 @@ (base::CollapseWhitespace(input_lower, false) == base::i18n::ToLower(suggestion.match_contents())); - if (suggestion.from_keyword_provider()) - match.fill_into_edit.append(match.keyword + base::char16(' ')); // We only allow inlinable navsuggestions that were received before the // last keystroke because we don't want asynchronous inline autocompletions. if (!input.prevent_inline_autocomplete() && @@ -312,13 +310,12 @@ DCHECK(search_url.SupportsReplacement(search_terms_data)); base::string16 query(suggestion.suggestion()); base::string16 original_query(input.text()); - base::string16 fill_into_edit(suggestion.suggestion()); if (suggestion.type() == AutocompleteMatchType::CALCULATOR) { // Use query text, rather than the calculator answer suggestion, to search. query = original_query; original_query.clear(); } - match.fill_into_edit.append(fill_into_edit); + match.fill_into_edit = GetFillIntoEdit(suggestion, template_url); match.search_terms_args.reset(new TemplateURLRef::SearchTermsArgs(query)); match.search_terms_args->original_query = original_query; match.search_terms_args->accepted_suggestion = accepted_suggestion; @@ -340,6 +337,20 @@ } // static +base::string16 BaseSearchProvider::GetFillIntoEdit( + const SearchSuggestionParser::SuggestResult& suggest_result, + const TemplateURL* template_url) { + base::string16 fill_into_edit; + + if (suggest_result.from_keyword_provider()) + fill_into_edit.append(template_url->keyword() + base::char16(' ')); + + fill_into_edit.append(suggest_result.suggestion()); + + return fill_into_edit; +} + +// static bool BaseSearchProvider::CanSendURL( const GURL& current_page_url, const GURL& suggest_url,
diff --git a/components/omnibox/browser/base_search_provider.h b/components/omnibox/browser/base_search_provider.h index a89835c..41f06b1c 100644 --- a/components/omnibox/browser/base_search_provider.h +++ b/components/omnibox/browser/base_search_provider.h
@@ -132,6 +132,14 @@ int accepted_suggestion, bool append_extra_query_params_from_command_line); + // Returns the appropriate value for the fill_into_edit field of an + // AutcompleteMatch. The result consists of the suggestion text from + // |suggest_result|, optionally prepended by the keyword from |template_url| + // if |suggest_result| is from the keyword provider. + static base::string16 GetFillIntoEdit( + const SearchSuggestionParser::SuggestResult& suggest_result, + const TemplateURL* template_url); + // Returns whether we can send the URL of the current page in any suggest // requests. Doing this requires that all the following hold: // * The suggest request is sent over HTTPS. This avoids leaking the current
diff --git a/components/omnibox/browser/search_provider.cc b/components/omnibox/browser/search_provider.cc index aba3390..42299c5 100644 --- a/components/omnibox/browser/search_provider.cc +++ b/components/omnibox/browser/search_provider.cc
@@ -208,10 +208,8 @@ ++sug_it; } } - for (auto nav_it = results->navigation_results.begin(); - nav_it != results->navigation_results.end(); ++nav_it) { - nav_it->set_received_after_last_keystroke(false); - } + for (auto& navigation_result : results->navigation_results) + navigation_result.set_received_after_last_keystroke(false); } } @@ -461,14 +459,10 @@ void SearchProvider::UpdateMatchContentsClass( const base::string16& input_text, SearchSuggestionParser::Results* results) { - for (auto sug_it = results->suggest_results.begin(); - sug_it != results->suggest_results.end(); ++sug_it) { - sug_it->ClassifyMatchContents(false, input_text); - } - for (auto nav_it = results->navigation_results.begin(); - nav_it != results->navigation_results.end(); ++nav_it) { - nav_it->CalculateAndClassifyMatchContents(false, input_text); - } + for (auto& suggest_result : results->suggest_results) + suggest_result.ClassifyMatchContents(false, input_text); + for (auto& navigation_result : results->navigation_results) + navigation_result.CalculateAndClassifyMatchContents(false, input_text); } void SearchProvider::SortResults(bool is_keyword, @@ -593,16 +587,15 @@ } void SearchProvider::RecordTopSuggestion() { - top_query_suggestion_match_contents_ = base::string16(); + top_query_suggestion_fill_into_edit_ = base::string16(); top_navigation_suggestion_ = GURL(); auto first_match = AutocompleteResult::FindTopMatch(matches_); - if ((first_match != matches_.end()) && - !first_match->inline_autocompletion.empty()) { + if (first_match != matches_.end()) { // Identify if this match came from a query suggestion or a navsuggestion. // In either case, extracts the identifying feature of the suggestion // (query string or navigation url). if (AutocompleteMatch::IsSearchType(first_match->type)) - top_query_suggestion_match_contents_ = first_match->contents; + top_query_suggestion_fill_into_edit_ = first_match->fill_into_edit; else top_navigation_suggestion_ = first_match->destination_url; } @@ -826,18 +819,18 @@ // clobbering top results, which may be used for inline autocompletion. // Other results don't need similar changes, because they shouldn't be // displayed asynchronously anyway. - if (!top_query_suggestion_match_contents_.empty()) { - for (auto sug_it = results->suggest_results.begin(); - sug_it != results->suggest_results.end(); ++sug_it) { - if (sug_it->match_contents() == top_query_suggestion_match_contents_) - sug_it->set_received_after_last_keystroke(false); + if (!top_query_suggestion_fill_into_edit_.empty()) { + for (auto& suggest_result : results->suggest_results) { + if (GetFillIntoEdit(suggest_result, providers_.GetKeywordProviderURL()) == + top_query_suggestion_fill_into_edit_) { + suggest_result.set_received_after_last_keystroke(false); + } } } if (top_navigation_suggestion_.is_valid()) { - for (auto nav_it = results->navigation_results.begin(); - nav_it != results->navigation_results.end(); ++nav_it) { - if (nav_it->url() == top_navigation_suggestion_) - nav_it->set_received_after_last_keystroke(false); + for (auto& navigation_result : results->navigation_results) { + if (navigation_result.url() == top_navigation_suggestion_) + navigation_result.set_received_after_last_keystroke(false); } } }
diff --git a/components/omnibox/browser/search_provider.h b/components/omnibox/browser/search_provider.h index f638cc4..3540c063 100644 --- a/components/omnibox/browser/search_provider.h +++ b/components/omnibox/browser/search_provider.h
@@ -413,7 +413,7 @@ SearchSuggestionParser::Results keyword_results_; // The top query suggestion, left blank if none. - base::string16 top_query_suggestion_match_contents_; + base::string16 top_query_suggestion_fill_into_edit_; // The top navigation suggestion, left blank/invalid if none. GURL top_navigation_suggestion_;
diff --git a/components/omnibox/browser/shortcuts_backend.cc b/components/omnibox/browser/shortcuts_backend.cc index 393a965f..115f6daf 100644 --- a/components/omnibox/browser/shortcuts_backend.cc +++ b/components/omnibox/browser/shortcuts_backend.cc
@@ -146,13 +146,7 @@ } ShortcutsBackend::~ShortcutsBackend() { - if (db_) { - auto* db = db_.get(); - db->AddRef(); - db_ = nullptr; - if (!db_runner_->ReleaseSoon(FROM_HERE, db)) - db->Release(); - } + db_runner_->ReleaseSoon(FROM_HERE, std::move(db_)); } // static
diff --git a/components/password_manager/content/browser/content_password_manager_driver.cc b/components/password_manager/content/browser/content_password_manager_driver.cc index 53f6c1a8..27c7177 100644 --- a/components/password_manager/content/browser/content_password_manager_driver.cc +++ b/components/password_manager/content/browser/content_password_manager_driver.cc
@@ -12,6 +12,7 @@ #include "components/autofill/core/common/password_form.h" #include "components/password_manager/content/browser/bad_message.h" #include "components/password_manager/content/browser/content_password_manager_driver_factory.h" +#include "components/password_manager/content/browser/form_submission_tracker_util.h" #include "components/password_manager/core/browser/log_manager.h" #include "components/password_manager/core/browser/password_manager.h" #include "components/password_manager/core/browser/password_manager_client.h" @@ -23,6 +24,7 @@ #include "content/public/browser/web_contents.h" #include "net/cert/cert_status_flags.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#include "ui/base/page_transition_types.h" namespace password_manager { @@ -171,7 +173,9 @@ // Clear page specific data after main frame navigation. if (navigation_handle->IsInMainFrame() && !navigation_handle->IsSameDocument()) { - GetPasswordManager()->DidNavigateMainFrame(); + NotifyDidNavigateMainFrame(navigation_handle->IsRendererInitiated(), + navigation_handle->GetPageTransition(), + GetPasswordManager()); GetPasswordAutofillManager()->DidNavigateMainFrame(); } }
diff --git a/components/password_manager/content/browser/form_submission_tracker_util.cc b/components/password_manager/content/browser/form_submission_tracker_util.cc index 58be99e4..4ef86c4c 100644 --- a/components/password_manager/content/browser/form_submission_tracker_util.cc +++ b/components/password_manager/content/browser/form_submission_tracker_util.cc
@@ -4,28 +4,24 @@ #include "components/password_manager/content/browser/form_submission_tracker_util.h" +#include "base/logging.h" #include "components/password_manager/core/browser/form_submission_observer.h" -#include "content/public/browser/navigation_handle.h" namespace password_manager { -void NotifyOnStartNavigation(content::NavigationHandle* navigation_handle, - PasswordManagerDriver* driver, - FormSubmissionObserver* observer) { - DCHECK(navigation_handle); +void NotifyDidNavigateMainFrame(bool is_renderer_initiated, + ui::PageTransition transition, + FormSubmissionObserver* observer) { DCHECK(observer); // Password manager isn't interested in - // - subframe navigations, // - user initiated navigations (e.g. click on the bookmark), // - hyperlink navigations. - if (!navigation_handle->IsInMainFrame() || - !navigation_handle->IsRendererInitiated() || - ui::PageTransitionCoreTypeIs(navigation_handle->GetPageTransition(), - ui::PAGE_TRANSITION_LINK)) - return; + bool form_may_be_submitted = + is_renderer_initiated && + !ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_LINK); - observer->OnStartNavigation(driver); + observer->DidNavigateMainFrame(form_may_be_submitted); } } // namespace password_manager
diff --git a/components/password_manager/content/browser/form_submission_tracker_util.h b/components/password_manager/content/browser/form_submission_tracker_util.h index 2a8ff2e1..8103c06 100644 --- a/components/password_manager/content/browser/form_submission_tracker_util.h +++ b/components/password_manager/content/browser/form_submission_tracker_util.h
@@ -5,23 +5,17 @@ #ifndef COMPONENTS_PASSWORD_MANAGER_CONTENT_BROWSER_FORM_SUBMISSION_TRACKER_UTIL_H_ #define COMPONENTS_PASSWORD_MANAGER_CONTENT_BROWSER_FORM_SUBMISSION_TRACKER_UTIL_H_ -#include "base/macros.h" - -namespace content { -class NavigationHandle; -} // namespace content +#include "ui/base/page_transition_types.h" namespace password_manager { class FormSubmissionObserver; -class PasswordManagerDriver; -// Calls |observer_| if the navigation is interesting for the password -// manager. |driver| is just passed to the observer. None content -// initiated, none top level, hyperlinks navigations are ignored. -void NotifyOnStartNavigation(content::NavigationHandle* navigation_handle, - PasswordManagerDriver* driver, - FormSubmissionObserver* observer); +// Calls |observer| with information whether the navigation might be due to a +// form submision. +void NotifyDidNavigateMainFrame(bool is_renderer_initiated, + ui::PageTransition transition, + FormSubmissionObserver* observer); } // namespace password_manager
diff --git a/components/password_manager/content/browser/form_submission_tracker_util_unittest.cc b/components/password_manager/content/browser/form_submission_tracker_util_unittest.cc index 362ccd4b..10ecc9b 100644 --- a/components/password_manager/content/browser/form_submission_tracker_util_unittest.cc +++ b/components/password_manager/content/browser/form_submission_tracker_util_unittest.cc
@@ -13,11 +13,9 @@ namespace password_manager { namespace { -constexpr char kExampleURL[] = "https://example.com"; - class FormSubmissionObserverMock : public FormSubmissionObserver { public: - MOCK_METHOD1(OnStartNavigation, void(PasswordManagerDriver*)); + MOCK_METHOD1(DidNavigateMainFrame, void(bool form_may_be_submitted)); }; class FormSubmissionTrackerUtilTest @@ -34,13 +32,22 @@ DISALLOW_COPY_AND_ASSIGN(FormSubmissionTrackerUtilTest); }; -TEST_F(FormSubmissionTrackerUtilTest, DidStartNavigation) { - std::unique_ptr<content::NavigationHandle> navigation_handle = - content::NavigationHandle::CreateNavigationHandleForTesting( - GURL(kExampleURL), main_rfh(), false, net::OK, false, false, - ui::PAGE_TRANSITION_FORM_SUBMIT); - EXPECT_CALL(observer(), OnStartNavigation(nullptr)); - NotifyOnStartNavigation(navigation_handle.get(), nullptr, &observer()); +TEST_F(FormSubmissionTrackerUtilTest, NotRendererInitiated) { + EXPECT_CALL(observer(), DidNavigateMainFrame(false)); + NotifyDidNavigateMainFrame(false /* is_renderer_initiated */, + ui::PAGE_TRANSITION_FORM_SUBMIT, &observer()); +} + +TEST_F(FormSubmissionTrackerUtilTest, LinkTransition) { + EXPECT_CALL(observer(), DidNavigateMainFrame(false)); + NotifyDidNavigateMainFrame(true /* is_renderer_initiated */, + ui::PAGE_TRANSITION_LINK, &observer()); +} + +TEST_F(FormSubmissionTrackerUtilTest, RendererInitiatedFormSubmit) { + EXPECT_CALL(observer(), DidNavigateMainFrame(true)); + NotifyDidNavigateMainFrame(true /* is_renderer_initiated */, + ui::PAGE_TRANSITION_FORM_SUBMIT, &observer()); } } // namespace
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn index 1c8e10c..ef92ebe 100644 --- a/components/password_manager/core/browser/BUILD.gn +++ b/components/password_manager/core/browser/BUILD.gn
@@ -272,6 +272,14 @@ configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] } +if (is_android) { + java_cpp_enum("password_manager_java_enums_srcjar") { + sources = [ + "manage_passwords_referrer.h", + ] + } +} + fuzzable_proto_library("proto") { sources = [ "android_affiliation/affiliation_api.proto",
diff --git a/components/password_manager/core/browser/export/password_csv_writer_unittest.cc b/components/password_manager/core/browser/export/password_csv_writer_unittest.cc index 6a0f2d8..777ea8c 100644 --- a/components/password_manager/core/browser/export/password_csv_writer_unittest.cc +++ b/components/password_manager/core/browser/export/password_csv_writer_unittest.cc
@@ -22,14 +22,12 @@ TEST(PasswordCSVWriterTest, SerializePasswords_ZeroPasswords) { std::vector<std::unique_ptr<PasswordForm>> passwords; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_TRUE(ReadCSV(PasswordCSVWriter::SerializePasswords(passwords), - &column_names, &records)); + CSVTable table; + ASSERT_TRUE(table.ReadCSV(PasswordCSVWriter::SerializePasswords(passwords))); - EXPECT_THAT(column_names, AllOf(Contains("url"), Contains("username"), - Contains("password"))); - EXPECT_EQ(0u, records.size()); + EXPECT_THAT(table.column_names(), AllOf(Contains("url"), Contains("username"), + Contains("password"))); + EXPECT_EQ(0u, table.records().size()); } TEST(PasswordCSVWriterTest, SerializePasswords_SinglePassword) { @@ -40,17 +38,18 @@ form.password_value = base::UTF8ToUTF16("Secret"); passwords.push_back(std::make_unique<PasswordForm>(form)); - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_TRUE(ReadCSV(PasswordCSVWriter::SerializePasswords(passwords), - &column_names, &records)); + CSVTable table; + ASSERT_TRUE(table.ReadCSV(PasswordCSVWriter::SerializePasswords(passwords))); - EXPECT_THAT(column_names, AllOf(Contains("url"), Contains("username"), - Contains("password"))); - EXPECT_EQ(1u, records.size()); - EXPECT_EQ(records[0]["url"], "http://example.com/"); - EXPECT_EQ(records[0]["username"], "Someone"); - EXPECT_EQ(records[0]["password"], "Secret"); + EXPECT_THAT(table.column_names(), AllOf(Contains("url"), Contains("username"), + Contains("password"))); + EXPECT_EQ(1u, table.records().size()); + EXPECT_THAT(table.records()[0], + Contains(std::make_pair("url", "http://example.com/"))); + EXPECT_THAT(table.records()[0], + Contains(std::make_pair("username", "Someone"))); + EXPECT_THAT(table.records()[0], + Contains(std::make_pair("password", "Secret"))); } TEST(PasswordCSVWriterTest, SerializePasswords_TwoPasswords) { @@ -65,20 +64,23 @@ form.password_value = base::UTF8ToUTF16("None"); passwords.push_back(std::make_unique<PasswordForm>(form)); - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_TRUE(ReadCSV(PasswordCSVWriter::SerializePasswords(passwords), - &column_names, &records)); + CSVTable table; + ASSERT_TRUE(table.ReadCSV(PasswordCSVWriter::SerializePasswords(passwords))); - EXPECT_THAT(column_names, AllOf(Contains("url"), Contains("username"), - Contains("password"))); - EXPECT_EQ(2u, records.size()); - EXPECT_EQ(records[0]["url"], "http://example.com/"); - EXPECT_EQ(records[0]["username"], "Someone"); - EXPECT_EQ(records[0]["password"], "Secret"); - EXPECT_EQ(records[1]["url"], "http://other.org/"); - EXPECT_EQ(records[1]["username"], "Anyone"); - EXPECT_EQ(records[1]["password"], "None"); + EXPECT_THAT(table.column_names(), AllOf(Contains("url"), Contains("username"), + Contains("password"))); + EXPECT_EQ(2u, table.records().size()); + EXPECT_THAT(table.records()[0], + Contains(std::make_pair("url", "http://example.com/"))); + EXPECT_THAT(table.records()[0], + Contains(std::make_pair("username", "Someone"))); + EXPECT_THAT(table.records()[0], + Contains(std::make_pair("password", "Secret"))); + EXPECT_THAT(table.records()[1], + Contains(std::make_pair("url", "http://other.org/"))); + EXPECT_THAT(table.records()[1], + Contains(std::make_pair("username", "Anyone"))); + EXPECT_THAT(table.records()[1], Contains(std::make_pair("password", "None"))); } } // namespace password_manager
diff --git a/components/password_manager/core/browser/form_parsing/form_parser.cc b/components/password_manager/core/browser/form_parsing/form_parser.cc index 0de8408..00113b5 100644 --- a/components/password_manager/core/browser/form_parsing/form_parser.cc +++ b/components/password_manager/core/browser/form_parsing/form_parser.cc
@@ -156,6 +156,15 @@ FieldPropertiesFlags::AUTOFILLED)); } +bool DoesStringContainOnlyDigits(const base::string16& s) { + return std::all_of(s.begin(), s.end(), &base::IsAsciiDigit<base::char16>); +} + +// Heuristics to determine that a string is very unlikely to be a username. +bool IsProbablyNotUsername(const base::string16& s) { + return s.empty() || (s.size() < 3 && DoesStringContainOnlyDigits(s)); +} + // A helper struct that is used to capture significant fields to be used for // the construction of a PasswordForm. struct SignificantFields { @@ -541,8 +550,9 @@ Interactability best_interactability) { DCHECK(first_relevant_password != processed_fields.end()); - // For saving filter out empty fields. - const bool consider_only_non_empty = mode == FormDataParser::Mode::kSaving; + // For saving filter out empty fields and fields with values which are not + // username. + const bool is_saving = mode == FormDataParser::Mode::kSaving; // Search through the text input fields preceding |first_relevant_password| // and find the closest one focusable and the closest one in general. @@ -556,7 +566,7 @@ continue; if (!MatchesInteractability(*it, best_interactability)) continue; - if (consider_only_non_empty && it->field->value.empty()) + if (is_saving && IsProbablyNotUsername(it->field->value)) continue; if (IsFieldCVC(*it)) continue;
diff --git a/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc b/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc index 8c806a1..5178fac6 100644 --- a/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc +++ b/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
@@ -700,6 +700,20 @@ }); } +TEST(FormParserTest, TextFieldValueIsNotUsername) { + CheckTestData({{ + "Text field value is unlikely username so it should be ignored on saving", + { + {.role_filling = ElementRole::USERNAME, + .form_control_type = "text", + .value = "12"}, + {.role = ElementRole::CURRENT_PASSWORD, + .form_control_type = "password", + .value = "strong_pw"}, + }, + }}); +} + TEST(FormParserTest, TestAutocomplete) { CheckTestData({ {
diff --git a/components/password_manager/core/browser/form_submission_observer.h b/components/password_manager/core/browser/form_submission_observer.h index e886e01..9a6c253 100644 --- a/components/password_manager/core/browser/form_submission_observer.h +++ b/components/password_manager/core/browser/form_submission_observer.h
@@ -7,14 +7,15 @@ namespace password_manager { -class PasswordManagerDriver; - // Observer interface for the password manager about the relevant events from // the embedder. + class FormSubmissionObserver { public: - // Notifies the listener that a form may be submitted due to a navigation. - virtual void OnStartNavigation(PasswordManagerDriver* driver) = 0; + // Notifies the listener that the main frame navigation happened. Not called + // for same document navigation. |form_may_be_submitted| true if the reason of + // this navigation might be a form submission. + virtual void DidNavigateMainFrame(bool form_may_be_submitted) = 0; protected: virtual ~FormSubmissionObserver() = default;
diff --git a/components/password_manager/core/browser/import/csv_reader.cc b/components/password_manager/core/browser/import/csv_reader.cc index 957c314..706c91f6 100644 --- a/components/password_manager/core/browser/import/csv_reader.cc +++ b/components/password_manager/core/browser/import/csv_reader.cc
@@ -6,6 +6,9 @@ #include <stddef.h> +#include <algorithm> +#include <utility> + #include "base/logging.h" #include "base/macros.h" #include "base/strings/string_util.h" @@ -97,22 +100,21 @@ namespace password_manager { -bool ReadCSV(base::StringPiece csv, - std::vector<std::string>* column_names, - std::vector<std::map<std::string, std::string>>* records) { - DCHECK(column_names); - DCHECK(records); +CSVTable::CSVTable() = default; - column_names->clear(); - records->clear(); +CSVTable::~CSVTable() = default; + +bool CSVTable::ReadCSV(base::StringPiece csv) { + records_.clear(); + column_names_.clear(); // Normalize EOL sequences so that we uniformly use a single LF character. - std::string normalized_csv(csv.as_string()); + std::string normalized_csv(csv); base::ReplaceSubstringsAfterOffset(&normalized_csv, 0, "\r\n", "\n"); // Read header row. CSVParser parser(normalized_csv); - if (!parser.ParseNextCSVRow(column_names)) + if (!parser.ParseNextCSVRow(&column_names_)) return false; // Reader data records rows. @@ -121,10 +123,13 @@ if (!parser.ParseNextCSVRow(&fields)) return false; - records->resize(records->size() + 1); - for (size_t i = 0; i < column_names->size() && i < fields.size(); ++i) { - records->back()[(*column_names)[i]].swap(fields[i]); + std::map<base::StringPiece, std::string> row_map; + const size_t available_columns = + std::min(column_names_.size(), fields.size()); + for (size_t i = 0; i < available_columns; ++i) { + row_map[column_names_[i]] = std::move(fields[i]); } + records_.push_back(std::move(row_map)); } return true;
diff --git a/components/password_manager/core/browser/import/csv_reader.h b/components/password_manager/core/browser/import/csv_reader.h index ad1c487e..d05c537d 100644 --- a/components/password_manager/core/browser/import/csv_reader.h +++ b/components/password_manager/core/browser/import/csv_reader.h
@@ -14,27 +14,42 @@ namespace password_manager { -// Reads tabular data from CSV (Comma Separated Values) format as defined in RFC -// 4180, with the following limitations/relaxations: -// * The input should be UTF-8 encoded. No code points should be escaped. -// * The first line must be a header that contains the column names. -// * Records may be separated by either LF or CRLF sequences. Each CRLF will -// be converted to LF characters inside quotes. -// * Inconsistent number of fields within records is handled gracefully. Extra -// fields are ignored. Missing fields will have no corresponding key-value -// pair in the record. -// * Repeated columns of the same name are not supported (the last value will -// be preserved). -// -// The CSV representation of the data will be read from |csv|. The first line of -// the file should be a header to extract |column_names| from. From each -// subsequent line, the extracted values are put into a map mapping column names -// to the value of the corresponding field, and inserted into |records|. Both -// |column_names| and |records| will be overwritten. Returns false if parsing -// failed due to a syntax error. -bool ReadCSV(base::StringPiece csv, - std::vector<std::string>* column_names, - std::vector<std::map<std::string, std::string>>* records); +// Parsed representation of tabular CSV data. +class CSVTable { + public: + CSVTable(); + ~CSVTable(); + + // Reads tabular data |csv| in a CSV (Comma Separated Values) format and fills + // the column_names_ and records_ accordingly. The CSV format is understood as + // defined in RFC 4180, with the following limitations/relaxations: + // * The input should be UTF-8 encoded. No code points should be escaped. + // * The first line must be a header that contains the column names. + // * Records may be separated by either LF or CRLF sequences. Each CRLF will + // be converted to LF characters inside quotes. + // * Inconsistent number of fields within records is handled gracefully. + // Extra fields are ignored. Missing fields will have no corresponding + // key-value pair in the record. + // * Repeated columns of the same name are not supported (the last value + // will be preserved). + // Returns false if parsing failed due to a syntax error. + bool ReadCSV(base::StringPiece csv); + + const std::vector<std::string>& column_names() const { return column_names_; } + + const std::vector<std::map<base::StringPiece, std::string>>& records() const { + return records_; + } + + private: + // Values from the first row. + std::vector<std::string> column_names_; + // Values from the subsequent rows. Each map represents one row and maps the + // column names to the value stored at that column in that row. + std::vector<std::map<base::StringPiece, std::string>> records_; + + DISALLOW_COPY_AND_ASSIGN(CSVTable); +}; } // namespace password_manager
diff --git a/components/password_manager/core/browser/import/csv_reader_unittest.cc b/components/password_manager/core/browser/import/csv_reader_unittest.cc index 7b326af..c71067f2 100644 --- a/components/password_manager/core/browser/import/csv_reader_unittest.cc +++ b/components/password_manager/core/browser/import/csv_reader_unittest.cc
@@ -10,27 +10,17 @@ namespace password_manager { TEST(CSVReaderTest, EmptyCSV) { - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - EXPECT_TRUE(ReadCSV(std::string(), &column_names, &records)); - EXPECT_THAT(column_names, testing::ElementsAre("")); - EXPECT_EQ(0u, records.size()); -} - -TEST(CSVReaderTest, OutputArgumentsAreOverwritten) { - std::vector<std::string> column_names(3); - std::vector<std::map<std::string, std::string>> records(4); - EXPECT_TRUE(ReadCSV(std::string(), &column_names, &records)); - EXPECT_THAT(column_names, testing::ElementsAre("")); - EXPECT_EQ(0u, records.size()); + CSVTable table; + EXPECT_TRUE(table.ReadCSV(std::string())); + EXPECT_THAT(table.column_names(), testing::ElementsAre("")); + EXPECT_EQ(0u, table.records().size()); } TEST(CSVReaderTest, CSVConsistingOfSingleNewLine) { - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - EXPECT_TRUE(ReadCSV(std::string("\n"), &column_names, &records)); - EXPECT_THAT(column_names, testing::ElementsAre("")); - EXPECT_EQ(0u, records.size()); + CSVTable table; + EXPECT_TRUE(table.ReadCSV(std::string("\n"))); + EXPECT_THAT(table.column_names(), testing::ElementsAre("")); + EXPECT_EQ(0u, table.records().size()); } TEST(CSVReaderTest, SingleColumn) { @@ -39,28 +29,26 @@ "alpha\n" "beta\n"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - EXPECT_TRUE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + EXPECT_TRUE(table.ReadCSV(kTestCSVInput)); - EXPECT_THAT(column_names, testing::ElementsAre("foo")); - ASSERT_EQ(2u, records.size()); - EXPECT_THAT(records[0], testing::ElementsAre( - std::make_pair("foo", "alpha"))); - EXPECT_THAT(records[1], testing::ElementsAre( - std::make_pair("foo", "beta"))); + EXPECT_THAT(table.column_names(), testing::ElementsAre("foo")); + ASSERT_EQ(2u, table.records().size()); + EXPECT_THAT(table.records()[0], + testing::ElementsAre(std::make_pair("foo", "alpha"))); + EXPECT_THAT(table.records()[1], + testing::ElementsAre(std::make_pair("foo", "beta"))); } TEST(CSVReaderTest, HeaderOnly) { const char kTestCSVInput[] = "foo,bar\n"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_TRUE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + ASSERT_TRUE(table.ReadCSV(kTestCSVInput)); - EXPECT_THAT(column_names, testing::ElementsAre("foo", "bar")); - EXPECT_EQ(0u, records.size()); + EXPECT_THAT(table.column_names(), testing::ElementsAre("foo", "bar")); + EXPECT_EQ(0u, table.records().size()); } TEST(CSVReaderTest, HeaderAndSimpleRecords) { @@ -69,20 +57,19 @@ "alpha,beta,gamma\n" "delta,epsilon,zeta\n"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_TRUE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + ASSERT_TRUE(table.ReadCSV(kTestCSVInput)); - EXPECT_THAT(column_names, testing::ElementsAre("foo", "bar", "baz")); - ASSERT_EQ(2u, records.size()); - EXPECT_THAT(records[0], testing::ElementsAre( - std::make_pair("bar", "beta"), - std::make_pair("baz", "gamma"), - std::make_pair("foo", "alpha"))); - EXPECT_THAT(records[1], testing::ElementsAre( - std::make_pair("bar", "epsilon"), - std::make_pair("baz", "zeta"), - std::make_pair("foo", "delta"))); + EXPECT_THAT(table.column_names(), testing::ElementsAre("foo", "bar", "baz")); + ASSERT_EQ(2u, table.records().size()); + EXPECT_THAT(table.records()[0], + testing::ElementsAre(std::make_pair("bar", "beta"), + std::make_pair("baz", "gamma"), + std::make_pair("foo", "alpha"))); + EXPECT_THAT(table.records()[1], + testing::ElementsAre(std::make_pair("bar", "epsilon"), + std::make_pair("baz", "zeta"), + std::make_pair("foo", "delta"))); } TEST(CSVReaderTest, EmptyStringColumnNamesAreSupported) { @@ -90,16 +77,15 @@ "foo,,bar\n" "alpha,beta,gamma\n"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_TRUE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + ASSERT_TRUE(table.ReadCSV(kTestCSVInput)); - EXPECT_THAT(column_names, testing::ElementsAre("foo", "", "bar")); - ASSERT_EQ(1u, records.size()); - EXPECT_THAT(records[0], testing::ElementsAre( - std::make_pair("", "beta"), - std::make_pair("bar", "gamma"), - std::make_pair("foo", "alpha"))); + EXPECT_THAT(table.column_names(), testing::ElementsAre("foo", "", "bar")); + ASSERT_EQ(1u, table.records().size()); + EXPECT_THAT(table.records()[0], + testing::ElementsAre(std::make_pair("", "beta"), + std::make_pair("bar", "gamma"), + std::make_pair("foo", "alpha"))); } TEST(CSVReaderTest, ExtraSpacesArePreserved) { @@ -107,15 +93,14 @@ "left,right\n" " alpha beta , \n"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_TRUE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + ASSERT_TRUE(table.ReadCSV(kTestCSVInput)); - EXPECT_THAT(column_names, testing::ElementsAre("left", "right")); - ASSERT_EQ(1u, records.size()); - EXPECT_THAT(records[0], testing::ElementsAre( - std::make_pair("left", " alpha beta "), - std::make_pair("right", " "))); + EXPECT_THAT(table.column_names(), testing::ElementsAre("left", "right")); + ASSERT_EQ(1u, table.records().size()); + EXPECT_THAT(table.records()[0], + testing::ElementsAre(std::make_pair("left", " alpha beta "), + std::make_pair("right", " "))); } TEST(CSVReaderTest, CharactersOutsideASCIIPrintableArePreservedVerbatim) { @@ -123,18 +108,21 @@ "left,right\n" "\x07\t\x0B\x1F,$\xc2\xa2\xe2\x98\x83\xf0\xa4\xad\xa2\n"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_TRUE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + ASSERT_TRUE(table.ReadCSV(kTestCSVInput)); - EXPECT_THAT(column_names, testing::ElementsAre("left", "right")); - ASSERT_EQ(1u, records.size()); - EXPECT_THAT(records[0], testing::ElementsAre( - // Characters below 0x20: bell, horizontal + vertical tab, unit separator. - std::make_pair("left", "\x07\t\x0B\x1F"), - // Unicode code points having 1..4 byte UTF-8 representation: dollar sign - // (U+0024), cent sign (U+00A2), snowman (U+2603), Han character U+24B62. - std::make_pair("right", "$\xc2\xa2\xe2\x98\x83\xf0\xa4\xad\xa2"))); + EXPECT_THAT(table.column_names(), testing::ElementsAre("left", "right")); + ASSERT_EQ(1u, table.records().size()); + EXPECT_THAT( + table.records()[0], + testing::ElementsAre( + // Characters below 0x20: bell, horizontal + vertical tab, unit + // separator. + std::make_pair("left", "\x07\t\x0B\x1F"), + // Unicode code points having 1..4 byte UTF-8 representation: dollar + // sign (U+0024), cent sign (U+00A2), snowman (U+2603), Han character + // U+24B62. + std::make_pair("right", "$\xc2\xa2\xe2\x98\x83\xf0\xa4\xad\xa2"))); } TEST(CSVReaderTest, EnclosingDoubleQuotesAreTrimmed) { @@ -142,15 +130,14 @@ "\"left\",\"right\"\n" "\"alpha\",\"beta\"\n"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_TRUE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + ASSERT_TRUE(table.ReadCSV(kTestCSVInput)); - EXPECT_THAT(column_names, testing::ElementsAre("left", "right")); - ASSERT_EQ(1u, records.size()); - EXPECT_THAT(records[0], testing::ElementsAre( - std::make_pair("left", "alpha"), - std::make_pair("right", "beta"))); + EXPECT_THAT(table.column_names(), testing::ElementsAre("left", "right")); + ASSERT_EQ(1u, table.records().size()); + EXPECT_THAT(table.records()[0], + testing::ElementsAre(std::make_pair("left", "alpha"), + std::make_pair("right", "beta"))); } TEST(CSVReaderTest, SeparatorsInsideDoubleQuotesAreTreatedVerbatim) { @@ -160,21 +147,20 @@ "\"C\r\nD\",\"D\n\"\n" "\",\",\",,\"\n"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_TRUE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + ASSERT_TRUE(table.ReadCSV(kTestCSVInput)); - EXPECT_THAT(column_names, testing::ElementsAre("left", "right")); - ASSERT_EQ(3u, records.size()); - EXPECT_THAT(records[0], testing::ElementsAre( - std::make_pair("left", "A\rB"), - std::make_pair("right", "B\nC"))); - EXPECT_THAT(records[1], testing::ElementsAre( - std::make_pair("left", "C\nD"), - std::make_pair("right", "D\n"))); - EXPECT_THAT(records[2], testing::ElementsAre( - std::make_pair("left", ","), - std::make_pair("right", ",,"))); + EXPECT_THAT(table.column_names(), testing::ElementsAre("left", "right")); + ASSERT_EQ(3u, table.records().size()); + EXPECT_THAT(table.records()[0], + testing::ElementsAre(std::make_pair("left", "A\rB"), + std::make_pair("right", "B\nC"))); + EXPECT_THAT(table.records()[1], + testing::ElementsAre(std::make_pair("left", "C\nD"), + std::make_pair("right", "D\n"))); + EXPECT_THAT(table.records()[2], + testing::ElementsAre(std::make_pair("left", ","), + std::make_pair("right", ",,"))); } TEST(CSVReaderTest, EscapedDoubleQuotes) { @@ -183,18 +169,17 @@ "\"\",\"\"\"\"\"\"\n" "\"\"\"\",\"A\"\"B\"\"\"\"C\"\n"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_TRUE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + ASSERT_TRUE(table.ReadCSV(kTestCSVInput)); - EXPECT_THAT(column_names, testing::ElementsAre("left", "right")); - ASSERT_EQ(2u, records.size()); - EXPECT_THAT(records[0], testing::ElementsAre( - std::make_pair("left", ""), - std::make_pair("right", "\"\""))); - EXPECT_THAT(records[1], testing::ElementsAre( - std::make_pair("left", "\""), - std::make_pair("right", "A\"B\"\"C"))); + EXPECT_THAT(table.column_names(), testing::ElementsAre("left", "right")); + ASSERT_EQ(2u, table.records().size()); + EXPECT_THAT(table.records()[0], + testing::ElementsAre(std::make_pair("left", ""), + std::make_pair("right", "\"\""))); + EXPECT_THAT(table.records()[1], + testing::ElementsAre(std::make_pair("left", "\""), + std::make_pair("right", "A\"B\"\"C"))); } TEST(CSVReaderTest, InconsistentFieldsCountIsTreatedGracefully) { @@ -203,17 +188,16 @@ "A\n" "B,C,D\n"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_TRUE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + ASSERT_TRUE(table.ReadCSV(kTestCSVInput)); - EXPECT_THAT(column_names, testing::ElementsAre("left", "right")); - ASSERT_EQ(2u, records.size()); - EXPECT_THAT(records[0], testing::ElementsAre( - std::make_pair("left", "A"))); - EXPECT_THAT(records[1], testing::ElementsAre( - std::make_pair("left", "B"), - std::make_pair("right", "C"))); + EXPECT_THAT(table.column_names(), testing::ElementsAre("left", "right")); + ASSERT_EQ(2u, table.records().size()); + EXPECT_THAT(table.records()[0], + testing::ElementsAre(std::make_pair("left", "A"))); + EXPECT_THAT(table.records()[1], + testing::ElementsAre(std::make_pair("left", "B"), + std::make_pair("right", "C"))); } TEST(CSVReaderTest, SupportMissingNewLineAtEOF) { @@ -221,15 +205,14 @@ "left,right\n" "alpha,beta"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_TRUE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + ASSERT_TRUE(table.ReadCSV(kTestCSVInput)); - EXPECT_THAT(column_names, testing::ElementsAre("left", "right")); - ASSERT_EQ(1u, records.size()); - EXPECT_THAT(records[0], testing::ElementsAre( - std::make_pair("left", "alpha"), - std::make_pair("right", "beta"))); + EXPECT_THAT(table.column_names(), testing::ElementsAre("left", "right")); + ASSERT_EQ(1u, table.records().size()); + EXPECT_THAT(table.records()[0], + testing::ElementsAre(std::make_pair("left", "alpha"), + std::make_pair("right", "beta"))); } TEST(CSVReaderTest, EmptyFields) { @@ -238,20 +221,20 @@ "alpha,beta,\n" ",,gamma\n"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_TRUE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + ASSERT_TRUE(table.ReadCSV(kTestCSVInput)); - EXPECT_THAT(column_names, testing::ElementsAre("left", "middle", "right")); - ASSERT_EQ(2u, records.size()); - EXPECT_THAT(records[0], testing::ElementsAre( - std::make_pair("left", "alpha"), - std::make_pair("middle", "beta"), - std::make_pair("right", ""))); - EXPECT_THAT(records[1], testing::ElementsAre( - std::make_pair("left", ""), - std::make_pair("middle", ""), - std::make_pair("right", "gamma"))); + EXPECT_THAT(table.column_names(), + testing::ElementsAre("left", "middle", "right")); + ASSERT_EQ(2u, table.records().size()); + EXPECT_THAT(table.records()[0], + testing::ElementsAre(std::make_pair("left", "alpha"), + std::make_pair("middle", "beta"), + std::make_pair("right", ""))); + EXPECT_THAT(table.records()[1], + testing::ElementsAre(std::make_pair("left", ""), + std::make_pair("middle", ""), + std::make_pair("right", "gamma"))); } TEST(CSVReaderTest, CRLFTreatedAsAndConvertedToLF) { @@ -259,15 +242,14 @@ "left,right\r\n" "\"\r\",\"\r\n\"\r\n"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_TRUE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + ASSERT_TRUE(table.ReadCSV(kTestCSVInput)); - EXPECT_THAT(column_names, testing::ElementsAre("left", "right")); - ASSERT_EQ(1u, records.size()); - EXPECT_THAT(records[0], testing::ElementsAre( - std::make_pair("left", "\r"), - std::make_pair("right", "\n"))); + EXPECT_THAT(table.column_names(), testing::ElementsAre("left", "right")); + ASSERT_EQ(1u, table.records().size()); + EXPECT_THAT(table.records()[0], + testing::ElementsAre(std::make_pair("left", "\r"), + std::make_pair("right", "\n"))); } TEST(CSVReaderTest, LastValueForRepeatedColumnNamesIsPreserved) { @@ -275,15 +257,14 @@ "foo,bar,bar\n" "alpha,beta,gamma\n"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_TRUE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + ASSERT_TRUE(table.ReadCSV(kTestCSVInput)); - EXPECT_THAT(column_names, testing::ElementsAre("foo", "bar", "bar")); - ASSERT_EQ(1u, records.size()); - EXPECT_THAT(records[0], testing::ElementsAre( - std::make_pair("bar", "gamma"), - std::make_pair("foo", "alpha"))); + EXPECT_THAT(table.column_names(), testing::ElementsAre("foo", "bar", "bar")); + ASSERT_EQ(1u, table.records().size()); + EXPECT_THAT(table.records()[0], + testing::ElementsAre(std::make_pair("bar", "gamma"), + std::make_pair("foo", "alpha"))); } TEST(CSVReaderTest, FailureWhenEOFInsideQuotes) { @@ -291,9 +272,8 @@ "left,right\n" "\"alpha\",\"unmatched\n"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_FALSE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + ASSERT_FALSE(table.ReadCSV(kTestCSVInput)); } TEST(CSVReaderTest, FailureWhenSemiQuotedContentInHeader) { @@ -301,9 +281,8 @@ "\"a\"b\"c\",right\n" "alpha,beta\n"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_FALSE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + ASSERT_FALSE(table.ReadCSV(kTestCSVInput)); } TEST(CSVReaderTest, FailureWhenSemiQuotedContentOnSubsequentLine) { @@ -311,9 +290,8 @@ "alpha,beta\n" "left,\"a\"b\"c\"\n"; - std::vector<std::string> column_names; - std::vector<std::map<std::string, std::string>> records; - ASSERT_FALSE(ReadCSV(kTestCSVInput, &column_names, &records)); + CSVTable table; + ASSERT_FALSE(table.ReadCSV(kTestCSVInput)); } } // namespace password_manager
diff --git a/components/password_manager/core/browser/import/password_csv_reader.cc b/components/password_manager/core/browser/import/password_csv_reader.cc index 2c0ca50..37e4226 100644 --- a/components/password_manager/core/browser/import/password_csv_reader.cc +++ b/components/password_manager/core/browser/import/password_csv_reader.cc
@@ -61,14 +61,13 @@ PasswordImporter::Result PasswordCSVReader::DeserializePasswords( const std::string& input, std::vector<PasswordForm>* passwords) { - std::vector<std::string> header; - std::vector<std::map<std::string, std::string>> records; - if (!ReadCSV(input, &header, &records)) + CSVTable table; + if (!table.ReadCSV(input)) return PasswordImporter::SYNTAX_ERROR; // Put the names into a set with case insensitive comparison. std::set<std::string, CaseInsensitiveComparison> lowercase_column_names; - for (const auto& name : header) { + for (const auto& name : table.column_names()) { lowercase_column_names.insert(name); } url_field_name_ = GetIntersectingName(lowercase_column_names, url_names); @@ -82,9 +81,9 @@ } passwords->clear(); - passwords->reserve(records.size()); + passwords->reserve(table.records().size()); - for (const auto& record : records) { + for (const auto& record : table.records()) { PasswordForm form; if (RecordToPasswordForm(record, &form)) passwords->push_back(form); @@ -93,7 +92,7 @@ } bool PasswordCSVReader::RecordToPasswordForm( - const std::map<std::string, std::string>& record, + const std::map<base::StringPiece, std::string>& record, PasswordForm* form) { GURL origin; auto origin_in_record = record.find(url_field_name_);
diff --git a/components/password_manager/core/browser/import/password_csv_reader.h b/components/password_manager/core/browser/import/password_csv_reader.h index 919f8ed..5937a97 100644 --- a/components/password_manager/core/browser/import/password_csv_reader.h +++ b/components/password_manager/core/browser/import/password_csv_reader.h
@@ -40,8 +40,9 @@ private: // Converts a parsed CSV line |record| to a |form| if possible, and returns // false otherwise. - bool RecordToPasswordForm(const std::map<std::string, std::string>& record, - autofill::PasswordForm* form); + bool RecordToPasswordForm( + const std::map<base::StringPiece, std::string>& record, + autofill::PasswordForm* form); // Deduced values of the column names for the mandatory columns. std::string url_field_name_;
diff --git a/components/password_manager/core/browser/manage_passwords_referrer.h b/components/password_manager/core/browser/manage_passwords_referrer.h index 7ab3edf..ce50c46 100644 --- a/components/password_manager/core/browser/manage_passwords_referrer.h +++ b/components/password_manager/core/browser/manage_passwords_referrer.h
@@ -9,13 +9,17 @@ // Enumerates referrers that can trigger a navigation to the manage passwords // page. +// A Java counterpart will be generated for this enum. +// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.password_manager enum class ManagePasswordsReferrer { // Corresponds to Chrome's settings page. kChromeSettings = 0, // Corresponds to the manage passwords bubble when clicking the key icon. + // Only used on desktop. kManagePasswordsBubble = 1, // Corresponds to the context menu following a right click into a password // field. + // Only used on desktop. kPasswordContextMenu = 2, // Corresponds to the password dropdown shown when clicking into a password // field. @@ -24,8 +28,13 @@ // was generated. kPasswordGenerationConfirmation = 4, // Corresponds to the profile chooser next to the omnibar ("Autofill Home"). + // Only used on desktop. kProfileChooser = 5, - kMaxValue = kProfileChooser, + // Corresponds to the passwords accessory sheet on Android, triggered by + // tapping on the key icon above in the keyboard accessory bar. + // Only used on Android + kPasswordsAccessorySheet = 6, + kMaxValue = kPasswordsAccessorySheet, }; } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index 69ff44c4..5c58556d 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -531,6 +531,23 @@ } } +void PasswordManager::DidNavigateMainFrame(bool form_may_be_submitted) { + entry_to_check_ = NavigationEntryToCheck::LAST_COMMITTED; + pending_login_managers_.clear(); + + if (form_may_be_submitted) { + for (std::unique_ptr<NewPasswordFormManager>& manager : form_managers_) { + if (manager->is_submitted()) { + owned_submitted_form_manager_ = std::move(manager); + break; + } + } + } + + form_managers_.clear(); + predictions_.clear(); +} + void PasswordManager::UpdateFormManagers() { std::vector<PasswordFormManagerInterface*> form_managers; for (const auto& form_manager : form_managers_) @@ -602,21 +619,6 @@ observers_.RemoveObserver(observer); } -void PasswordManager::DidNavigateMainFrame() { - entry_to_check_ = NavigationEntryToCheck::LAST_COMMITTED; - pending_login_managers_.clear(); - - for (std::unique_ptr<NewPasswordFormManager>& manager : form_managers_) { - if (manager->is_submitted()) { - owned_submitted_form_manager_ = std::move(manager); - break; - } - } - - form_managers_.clear(); - predictions_.clear(); -} - void PasswordManager::OnPasswordFormSubmitted( password_manager::PasswordManagerDriver* driver, const PasswordForm& password_form) { @@ -929,11 +931,6 @@ } } -void PasswordManager::OnStartNavigation(PasswordManagerDriver* driver) { - // TODO(crbug/842643): use this signal instead of DidStartProvisionalLoad in - // the renderer. -} - void PasswordManager::ProvisionallySaveManager( const PasswordForm& form, PasswordFormManager* matched_manager,
diff --git a/components/password_manager/core/browser/password_manager.h b/components/password_manager/core/browser/password_manager.h index 9aee964..d43ba98 100644 --- a/components/password_manager/core/browser/password_manager.h +++ b/components/password_manager/core/browser/password_manager.h
@@ -104,9 +104,8 @@ void ProvisionallySavePassword(const autofill::PasswordForm& form, const PasswordManagerDriver* driver); - // Should be called when the user navigates the main frame. Not called for - // in-page navigation. - void DidNavigateMainFrame(); + // FormSubmissionObserver: + void DidNavigateMainFrame(bool form_may_be_submitted) override; // Handles password forms being parsed. void OnPasswordFormsParsed(PasswordManagerDriver* driver, @@ -193,9 +192,6 @@ PasswordManagerTest, ShouldBlockPasswordForSameOriginButDifferentSchemeTest); - // FormSubmissionObserver: - void OnStartNavigation(PasswordManagerDriver* driver) override; - // Clones |matched_manager| and keeps it as |provisional_save_manager_|. // |form| is saved provisionally to |provisional_save_manager_|. void ProvisionallySaveManager(const autofill::PasswordForm& form,
diff --git a/components/password_manager/core/browser/password_manager_client.cc b/components/password_manager/core/browser/password_manager_client.cc index 0c2c96c..52b2cef 100644 --- a/components/password_manager/core/browser/password_manager_client.cc +++ b/components/password_manager/core/browser/password_manager_client.cc
@@ -80,6 +80,10 @@ void PasswordManagerClient::AnnotateNavigationEntry(bool has_password_field) {} +std::string PasswordManagerClient::GetPageLanguage() const { + return std::string(); +} + PasswordRequirementsService* PasswordManagerClient::GetPasswordRequirementsService() { // Not impemented but that is a valid state as per interface definition.
diff --git a/components/password_manager/core/browser/password_manager_client.h b/components/password_manager/core/browser/password_manager_client.h index f10f96d..b675ece37 100644 --- a/components/password_manager/core/browser/password_manager_client.h +++ b/components/password_manager/core/browser/password_manager_client.h
@@ -216,6 +216,9 @@ // Record that we saw a password field on this page. virtual void AnnotateNavigationEntry(bool has_password_field); + // Returns the current best guess as to the page's display language. + virtual std::string GetPageLanguage() const; + #if defined(SAFE_BROWSING_DB_LOCAL) // Return the PasswordProtectionService associated with this instance. virtual safe_browsing::PasswordProtectionService*
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc index 1ec0476..affd8da 100644 --- a/components/password_manager/core/browser/password_manager_unittest.cc +++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -517,7 +517,7 @@ // Now the password manager waits for the navigation to complete. observed.clear(); - manager()->DidNavigateMainFrame(); + manager()->DidNavigateMainFrame(true); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -677,7 +677,7 @@ EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0); EXPECT_CALL(*store_, UpdateLogin(_)); observed.clear(); - manager()->DidNavigateMainFrame(); + manager()->DidNavigateMainFrame(true); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); EXPECT_EQ(1, @@ -709,7 +709,7 @@ OnPasswordFormSubmitted(form); EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0); observed.clear(); - manager()->DidNavigateMainFrame(); + manager()->DidNavigateMainFrame(true); manager()->OnPasswordFormsRendered(&driver_, observed, true); } @@ -844,7 +844,7 @@ manager()->OnPasswordFormsRendered(&driver_, observed, true); // Now navigate to a second page. - manager()->DidNavigateMainFrame(); + manager()->DidNavigateMainFrame(true); // This page contains a form with the same markup, but on a different // URL. @@ -1324,7 +1324,7 @@ // Now the password manager waits for the navigation to complete. observed.clear(); - manager()->DidNavigateMainFrame(); + manager()->DidNavigateMainFrame(true); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -1659,7 +1659,7 @@ // Now the password manager waits for the navigation to complete. observed.clear(); - manager()->DidNavigateMainFrame(); + manager()->DidNavigateMainFrame(true); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -1987,7 +1987,7 @@ EXPECT_CALL(*store_, UpdateLoginWithPrimaryKey(_, presaved_form)); OnPasswordFormSubmitted(form); observed.clear(); - manager()->DidNavigateMainFrame(); + manager()->DidNavigateMainFrame(true); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -2111,7 +2111,7 @@ EXPECT_CALL(*store_, UpdateLoginWithPrimaryKey(_, _)).Times(0); observed_forms.clear(); - manager()->DidNavigateMainFrame(); + manager()->DidNavigateMainFrame(true); manager()->OnPasswordFormsParsed(&driver_, observed_forms); manager()->OnPasswordFormsRendered(&driver_, observed_forms, true); EXPECT_THAT(saved_form, FormMatches(android_form)); @@ -2145,7 +2145,7 @@ .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); observed_forms.clear(); - manager()->DidNavigateMainFrame(); + manager()->DidNavigateMainFrame(true); manager()->OnPasswordFormsParsed(&driver_, observed_forms); manager()->OnPasswordFormsRendered(&driver_, observed_forms, true); @@ -2990,33 +2990,44 @@ // 3. The password disappeared after navigation. // 4. A save prompt is shown. TEST_F(PasswordManagerTest, SavingAfterUserTypingAndNavigation) { - base::test::ScopedFeatureList scoped_feature_list; - TurnOnNewParsingForSaving(&scoped_feature_list); - EXPECT_CALL(client_, IsSavingAndFillingEnabledForCurrentPage()) - .WillRepeatedly(Return(true)); + for (bool form_may_be_submitted : {false, true}) { + SCOPED_TRACE(testing::Message() + << "form_may_be_submitted = " << form_may_be_submitted); + base::test::ScopedFeatureList scoped_feature_list; + TurnOnNewParsingForSaving(&scoped_feature_list); + EXPECT_CALL(client_, IsSavingAndFillingEnabledForCurrentPage()) + .WillRepeatedly(Return(true)); - PasswordForm form(MakeSimpleForm()); - EXPECT_CALL(*store_, GetLogins(_, _)) - .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms())); - manager()->OnPasswordFormsParsed(&driver_, {form}); + PasswordForm form(MakeSimpleForm()); + EXPECT_CALL(*store_, GetLogins(_, _)) + .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms())); + manager()->OnPasswordFormsParsed(&driver_, {form}); - // The user is typing as a result the saving manual fallback is shown. - std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; - EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false)) - .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); - manager()->ShowManualFallbackForSaving(&driver_, form); - ASSERT_TRUE(form_manager_to_save); - EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), FormMatches(form)); + // The user is typing as a result the saving manual fallback is shown. + std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; + EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false)) + .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); + manager()->ShowManualFallbackForSaving(&driver_, form); + ASSERT_TRUE(form_manager_to_save); + EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), + FormMatches(form)); - // Check that a save prompt is shown when there is no password form after - // the navigation (which suggests that the submission was successful). - EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)) - .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); + // Check that a save prompt is shown when there is no password form after + // the navigation (which suggests that the submission was successful). + if (form_may_be_submitted) { + EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)) + .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); + } else { + EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0); + } - manager()->DidNavigateMainFrame(); - manager()->OnPasswordFormsRendered(&driver_, {}, true); + manager()->DidNavigateMainFrame(form_may_be_submitted); + manager()->OnPasswordFormsRendered(&driver_, {}, true); - EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), FormMatches(form)); + EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), + FormMatches(form)); + testing::Mock::VerifyAndClearExpectations(&client_); + } } // Check that when a form is submitted and a NewPasswordFormManager not present,
diff --git a/components/password_manager/core/browser/votes_uploader.cc b/components/password_manager/core/browser/votes_uploader.cc index 450fc7d..b52b9cd 100644 --- a/components/password_manager/core/browser/votes_uploader.cc +++ b/components/password_manager/core/browser/votes_uploader.cc
@@ -307,6 +307,9 @@ logger.LogFormStructure(Logger::STRING_FORM_VOTES, form_structure); } + // Annotate the form with the source language of the page. + form_structure.set_page_language(client_->GetPageLanguage()); + // Attach the Randomized Encoder. form_structure.set_randomized_encoder( RandomizedEncoder::Create(client_->GetPrefs())); @@ -361,6 +364,9 @@ logger.LogFormStructure(Logger::STRING_FORM_VOTES, form_structure); } + // Annotate the form with the source language of the page. + form_structure.set_page_language(client_->GetPageLanguage()); + // Attach the Randomized Encoder. form_structure.set_randomized_encoder( RandomizedEncoder::Create(client_->GetPrefs()));
diff --git a/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc b/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc index 75dd444..e262962 100644 --- a/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc +++ b/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc
@@ -26,27 +26,26 @@ ~FakeRendererPpapiHost() override {} ppapi::host::PpapiHost* GetPpapiHost() override { return nullptr; } - bool IsValidInstance(PP_Instance instance) const override { return true; } + bool IsValidInstance(PP_Instance instance) override { return true; } content::PepperPluginInstance* GetPluginInstance( - PP_Instance instance) const override { + PP_Instance instance) override { return nullptr; } content::RenderFrame* GetRenderFrameForInstance( - PP_Instance instance) const override { + PP_Instance instance) override { return render_frame_; } - content::RenderView* GetRenderViewForInstance( - PP_Instance instance) const override { + content::RenderView* GetRenderViewForInstance(PP_Instance instance) override { return nullptr; } blink::WebPluginContainer* GetContainerForInstance( - PP_Instance instance) const override { + PP_Instance instance) override { return nullptr; } - bool HasUserGesture(PP_Instance instance) const override { return false; } - int GetRoutingIDForWidget(PP_Instance instance) const override { return 0; } + bool HasUserGesture(PP_Instance instance) override { return false; } + int GetRoutingIDForWidget(PP_Instance instance) override { return 0; } gfx::Point PluginPointToRenderFrame(PP_Instance instance, - const gfx::Point& pt) const override { + const gfx::Point& pt) override { return gfx::Point(); } IPC::PlatformFileForTransit ShareHandleWithRemote( @@ -66,15 +65,14 @@ const base::ReadOnlySharedMemoryRegion& region) override { return base::ReadOnlySharedMemoryRegion(); } - bool IsRunningInProcess() const override { return false; } - std::string GetPluginName() const override { return std::string(); } + bool IsRunningInProcess() override { return false; } + std::string GetPluginName() override { return std::string(); } void SetToExternalPluginHost() override {} void CreateBrowserResourceHosts( PP_Instance instance, const std::vector<IPC::Message>& nested_msgs, - base::OnceCallback<void(const std::vector<int>&)> callback) - const override {} - GURL GetDocumentURL(PP_Instance instance) const override { return GURL(); } + base::OnceCallback<void(const std::vector<int>&)> callback) override {} + GURL GetDocumentURL(PP_Instance instance) override { return GURL(); } private: content::RenderFrame* render_frame_;
diff --git a/components/policy/resources/PRESUBMIT.py b/components/policy/resources/PRESUBMIT.py index a67ef23..ed94212 100644 --- a/components/policy/resources/PRESUBMIT.py +++ b/components/policy/resources/PRESUBMIT.py
@@ -113,18 +113,28 @@ results = [] results.extend(_CheckPolicyTemplatesSyntax(input_api, output_api)) - os_path = input_api.os_path - local_path = input_api.PresubmitLocalPath() - template_path = os_path.join(local_path, 'policy_templates.json') - affected_files = input_api.AffectedFiles() - if any(f.AbsoluteLocalPath() == template_path for f in affected_files): + root = input_api.change.RepositoryRoot() + template_path = template_path = input_api.os_path.join( + root, 'components', 'policy', 'resources', 'policy_templates.json') + # policies in chrome/test/data/policy/policy_test_cases.json. + test_cases_path = input_api.os_path.join( + root, 'chrome', 'test', 'data', 'policy', 'policy_test_cases.json') + affected_files = input_api.change.AffectedFiles() + + template_changed = any(f.AbsoluteLocalPath() == template_path \ + for f in affected_files) + tests_changed = any(f.AbsoluteLocalPath() == test_cases_path \ + for f in affected_files) + + if template_changed or tests_changed: try: policies = _GetPolicyTemplates(template_path) except: results.append(output_api.PresubmitError('Invalid Python/JSON syntax.')) return results results.extend(_CheckPolicyTestCases(input_api, output_api, policies)) - results.extend(_CheckPolicyHistograms(input_api, output_api, policies)) + if template_changed: + results.extend(_CheckPolicyHistograms(input_api, output_api, policies)) return results
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 4f86d3b..953d7c5 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -7061,6 +7061,7 @@ 'type': 'main', 'schema': { 'type': 'boolean' }, 'supported_on': ['chrome_os:37-'], + 'supported_chrome_os_management': ['google_cloud'], 'device_only': True, 'features': { 'dynamic_refresh': True, @@ -13976,6 +13977,84 @@ The policy should be specified as a string that expresses the URL and hash in the JSON format.''', }, + { + 'name': 'ParentAccessCodeConfig', + 'type': 'dict', + 'schema': { + 'type': 'object', + 'properties': { + 'current_config': { + 'id': 'Config', + 'type': 'object', + 'description': 'Configuration used to generate and verify Parent Access Code.', + 'properties': { + 'shared_secret': { + 'type': 'string', + 'description': 'Secret shared between child and parent devices.' + }, + 'access_code_ttl': { + 'type': 'integer', + 'minimum': 30, + 'maximum': 3600, + 'description': 'Time that access code is valid for (in seconds).' + }, + 'clock_drift_tolerance': { + 'type': 'integer', + 'minimum': 0, + 'maximum': 1800, + 'description': 'The allowed difference between the clock on child and parent devices (in seconds).' + } + } + }, + 'future_config': { + '$ref': 'Config', + }, + 'old_configs': { + 'type': 'array', + 'items': { '$ref': 'Config'}, + } + }, + }, + 'sensitiveValue': True, + 'supported_on': ['chrome_os:73-'], + 'features': { + 'dynamic_refresh': True, + 'per_profile': True + }, + 'example_value': { + 'current_config': { + 'shared_secret': 'oOA9nX02LdhYdOzwMsGof+QA3wUKP4YMNlk9S/W3o+w=', + 'access_code_ttl': 600, + 'clock_drift_tolerance': 300 + }, + 'future_config': { + 'shared_secret': 'KMsoIjnpvcWmiU1GHchp2blR96mNyJwS', + 'access_code_ttl': 600, + 'clock_drift_tolerance': 300 + }, + 'old_configs': [{ + 'shared_secret': 'sTr6jqMTJGCbLhWI5plFTQb/VsqxwX2Q', + 'access_code_ttl': 600, + 'clock_drift_tolerance': 300 + }], + }, + 'id': 507, + 'caption': '''Parent Access Code Configuration''', + 'tags': [], + 'desc': '''This policy specifies configuration that is used to generate and verify Parent Access Code. + + |current_config| is always used for generating access code and should be used for validating access code only when it cannot be validated with |future_config|. + |future_config| is the primary config used for validating access code. + |old_configs| should be used for validating access code only when it cannot be validated with |future_config| nor |current_config|. + + The expected way of using this policy is to gradually rotate access code configuration. New configuration is always put into |future_config| and at the same + time the existing value is moved into |current_config|. |current_config|'s previous values are moved into |old_configs| and removed after rotation cycle is finished. + + This policy applies only to child user. + When this policy is set Parent Access Code can be verified on child user's device. + When this policy is unset it is not possible to verify Parent Access Code on child user's device.''' + }, + ], 'messages': { @@ -14114,8 +14193,20 @@ 'desc': '''A label for the legacy single-line textbox for a policy also has a more user-friendly multi-line textbox. See http://crbug/829328''', 'text': '''<ph name="POLICY_NAME">$6<ex>Wallpaper Image</ex></ph> (The single-line field is deprecated and will be removed in the future. Please start using the multi-line textbox below.)''', }, + 'doc_policy_restriction': { + 'desc': '''Caption text of the field 'restrictions' in the summary chart of a policy in the generated documentation''', + 'text': '''Restrictions:''' + }, + 'doc_range_minimum': { + 'desc': '''Caption text of the field 'minimum' in the summary chart of a policy in the generated documentation. Present only if policy has a minimum range restriction.''', + 'text': '''Minimum:''' + }, + 'doc_range_maximum': { + 'desc': '''Caption text of the field 'maximum' in the summary chart of a policy in the generated documentation. Present only if policy has a maximum range restriction.''', + 'text': '''Maximum:''' + }, }, 'placeholders': [], 'deleted_policy_ids': [412], - 'highest_id_currently_used': 506, + 'highest_id_currently_used': 507, }
diff --git a/components/policy/tools/template_writers/writers/adm_writer.py b/components/policy/tools/template_writers/writers/adm_writer.py index cf0f03c..6bffe31f 100755 --- a/components/policy/tools/template_writers/writers/adm_writer.py +++ b/components/policy/tools/template_writers/writers/adm_writer.py
@@ -122,7 +122,15 @@ builder.AddLine('VALUENAME "%s"' % policy['name']) if policy['type'] == 'int': # The default max for NUMERIC values is 9999 which is too small for us. - builder.AddLine('MIN 0 MAX 2000000000') + max = '2000000000' + min = '0' + if self.PolicyHasRestrictions(policy): + schema = policy['schema'] + if 'minimum' in schema: + min = schema['minimum'] + if 'maximum' in schema: + max = schema['maximum'] + builder.AddLine('MIN ' + str(min) + ' MAX ' + max) if policy['type'] in ('string', 'dict', 'external'): # The default max for EDITTEXT values is 1023, which is too small for # big JSON blobs and other string policies. @@ -140,6 +148,12 @@ builder.AddLine('END ITEMLIST', -1) builder.AddLine('END PART', -1) + def PolicyHasRestrictions(self, policy): + if 'schema' in policy: + return any(keyword in policy['schema'] \ + for keyword in ['minimum', 'maximum']) + return False + def _WritePolicy(self, policy, key_name, builder): policy_name = self._Escape(policy['name'] + '_Policy') self._AddGuiString(policy_name, policy['caption'])
diff --git a/components/policy/tools/template_writers/writers/admx_writer.py b/components/policy/tools/template_writers/writers/admx_writer.py index 6416f5e..0d59bf7 100755 --- a/components/policy/tools/template_writers/writers/admx_writer.py +++ b/components/policy/tools/template_writers/writers/admx_writer.py
@@ -269,14 +269,24 @@ } self.AddElement(parent, 'multiText', attributes) - def _AddIntPolicy(self, parent, name): + def _AddIntPolicy(self, parent, policy): '''Generates ADMX elements for an Int-Policy and adds them to the passed parent node. ''' + #default max value for an integer + max = '2000000000' + min = '0' + if self.PolicyHasRestrictions(policy): + schema = policy['schema'] + if 'minimum' in schema: + min = schema['minimum'] + if 'maximum' in schema: + max = schema['maximum'] attributes = { - 'id': name, - 'valueName': name, - 'maxValue': '2000000000', + 'id': policy['name'], + 'valueName': policy['name'], + 'maxValue': str(max), + 'minValue': str(min), } self.AddElement(parent, 'decimal', attributes) @@ -323,6 +333,12 @@ disabled_value_elem = self.AddElement(parent, 'disabledValue') self.AddElement(disabled_value_elem, 'decimal', {'value': '0'}) + def PolicyHasRestrictions(self, policy): + if 'schema' in policy: + return any(keyword in policy['schema'] \ + for keyword in ['minimum', 'maximum']) + return False + def _GetElements(self, policy_group_elem): '''Returns the ADMX "elements" child from an ADMX "policy" element. If the "policy" element has no "elements" child yet, a new child is created. @@ -382,7 +398,7 @@ self._AddMultiStringPolicy(parent, policy_name) elif element_type == AdmxElementType.INT: parent = self._GetElements(policy_elem) - self._AddIntPolicy(parent, policy_name) + self._AddIntPolicy(parent, policy) elif element_type == AdmxElementType.ENUM: parent = self._GetElements(policy_elem) self._AddEnumPolicy(parent, policy)
diff --git a/components/policy/tools/template_writers/writers/admx_writer_unittest.py b/components/policy/tools/template_writers/writers/admx_writer_unittest.py index 163ed6e3..9e5cf94 100755 --- a/components/policy/tools/template_writers/writers/admx_writer_unittest.py +++ b/components/policy/tools/template_writers/writers/admx_writer_unittest.py
@@ -373,7 +373,7 @@ ' <parentCategory ref="PolicyGroup"/>\n' ' <supportedOn ref="SUPPORTED_TESTOS"/>\n' ' <elements>\n' - ' <decimal id="SampleIntPolicy" maxValue="2000000000" ' + ' <decimal id="SampleIntPolicy" maxValue="2000000000" minValue="0" ' 'valueName="SampleIntPolicy"/>\n' ' </elements>\n' '</policy>')
diff --git a/components/policy/tools/template_writers/writers/doc_writer.py b/components/policy/tools/template_writers/writers/doc_writer.py index 79001542..fea2dd40 100755 --- a/components/policy/tools/template_writers/writers/doc_writer.py +++ b/components/policy/tools/template_writers/writers/doc_writer.py
@@ -499,6 +499,22 @@ # Add the list element: self.AddElement(ul, 'li', {}, ' '.join(text)) + def _AddRangeRestrictionsList(self, parent, schema): + '''Creates a HTML list containing range restrictions for an integer type + policy. + + Args: + parent: The DOM node for which the list will be added. + schema: The schema of the policy. + ''' + ul = self._AddStyledElement(parent, 'ul', ['ul']) + if 'minimum' in schema: + text_min = self._GetLocalizedMessage('range_minimum') + self.AddElement(ul, 'li', {}, text_min + str(schema['minimum'])) + if 'maximum' in schema: + text_max = self._GetLocalizedMessage('range_maximum') + self.AddElement(ul, 'li', {}, text_max + str(schema['maximum'])) + def _AddPolicyDetails(self, parent, policy): '''Adds the list of attributes of a policy to the HTML DOM node parent. It will have the form: @@ -562,6 +578,10 @@ self._AddFeatures(dd, policy) dd = self._AddPolicyAttribute(dl, 'description') self._AddDescription(dd, policy) + if 'schema' in policy: + if self.SchemaHasRangeRestriction(policy['schema']): + dd = self._AddPolicyAttribute(dl, 'policy_restriction') + self._AddRangeRestrictionsList(dd, policy['schema']) if 'arc_support' in policy: dd = self._AddPolicyAttribute(dl, 'arc_support') self._AddParagraphs(dd, policy['arc_support']) @@ -650,6 +670,13 @@ self.AddElement(parent2, 'a', {'href': '#top'}, self._GetLocalizedMessage('back_to_top')) + def SchemaHasRangeRestriction(self, schema): + if 'maximum' in schema: + return True + if 'minimum' in schema: + return schema['minimum'] != 0 + return False + # # Implementation of abstract methods of TemplateWriter: #
diff --git a/components/previews/content/previews_decider_impl.cc b/components/previews/content/previews_decider_impl.cc index a0b1f2b..160c935 100644 --- a/components/previews/content/previews_decider_impl.cc +++ b/components/previews/content/previews_decider_impl.cc
@@ -31,6 +31,7 @@ void LogPreviewsEligibilityReason(PreviewsEligibilityReason status, PreviewsType type) { + DCHECK_LT(status, PreviewsEligibilityReason::LAST); UMA_HISTOGRAM_ENUMERATION("Previews.EligibilityReason", status, PreviewsEligibilityReason::LAST); int32_t max_limit = static_cast<int32_t>(PreviewsEligibilityReason::LAST); @@ -294,16 +295,21 @@ // perform its own ECT check and for previews with hints because the hints may // specify variable ECT thresholds for slow page hints. if (!is_drp_server_preview && !ShouldCheckOptimizationHints(type)) { + if (effective_connection_type_ == net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN) { + return PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE; + } + passed_reasons->push_back( + PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE); + // Network quality estimator may sometimes return effective connection type // as offline when the Android APIs incorrectly return device connectivity // as null. See https://crbug.com/838969. So, we do not trigger previews // when |observed_effective_connection_type| is // net::EFFECTIVE_CONNECTION_TYPE_OFFLINE. - if (effective_connection_type_ <= net::EFFECTIVE_CONNECTION_TYPE_OFFLINE) { - return PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE; + if (effective_connection_type_ == net::EFFECTIVE_CONNECTION_TYPE_OFFLINE) { + return PreviewsEligibilityReason::DEVICE_OFFLINE; } - passed_reasons->push_back( - PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE); + passed_reasons->push_back(PreviewsEligibilityReason::DEVICE_OFFLINE); if (effective_connection_type_ > previews::params::GetECTThresholdForPreview(type)) { @@ -464,21 +470,30 @@ // connection type as offline when the Android APIs incorrectly return device // connectivity as null. See https://crbug.com/838969. So, we do not trigger // previews when |ect| is net::EFFECTIVE_CONNECTION_TYPE_OFFLINE. - if (previews_data->navigation_ect() <= - net::EFFECTIVE_CONNECTION_TYPE_OFFLINE) { + if (previews_data->navigation_ect() == + net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN) { return PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE; } passed_reasons->push_back( PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE); + + if (previews_data->navigation_ect() == + net::EFFECTIVE_CONNECTION_TYPE_OFFLINE) { + return PreviewsEligibilityReason::DEVICE_OFFLINE; + } + passed_reasons->push_back(PreviewsEligibilityReason::DEVICE_OFFLINE); + if (previews_data->navigation_ect() > ect_threshold) { return PreviewsEligibilityReason::NETWORK_NOT_SLOW; } passed_reasons->push_back(PreviewsEligibilityReason::NETWORK_NOT_SLOW); + if (previews_data->navigation_ect() > params::GetSessionMaxECTThreshold()) { return PreviewsEligibilityReason::NETWORK_NOT_SLOW_FOR_SESSION; } passed_reasons->push_back( PreviewsEligibilityReason::NETWORK_NOT_SLOW_FOR_SESSION); + LogTriggeredPreviewEffectiveConnectionType(previews_data->navigation_ect(), type);
diff --git a/components/previews/content/previews_decider_impl_unittest.cc b/components/previews/content/previews_decider_impl_unittest.cc index 35dc33d..f0ee500 100644 --- a/components/previews/content/previews_decider_impl_unittest.cc +++ b/components/previews/content/previews_decider_impl_unittest.cc
@@ -556,6 +556,23 @@ static_cast<int>(PreviewsEligibilityReason::NETWORK_NOT_SLOW), 1); } +TEST_F(PreviewsDeciderImplTest, TestDisallowOfflineWhenNetworkOffline) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(features::kPreviews); + InitializeUIService(); + + PreviewsUserData user_data(kDefaultPageId); + + ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_OFFLINE); + base::HistogramTester histogram_tester; + EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart( + &user_data, GURL("https://www.google.com"), false, + PreviewsType::OFFLINE)); + histogram_tester.ExpectUniqueSample( + "Previews.EligibilityReason.Offline", + static_cast<int>(PreviewsEligibilityReason::DEVICE_OFFLINE), 1); +} + TEST_F(PreviewsDeciderImplTest, TestDisallowOfflineOnReload) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeature(features::kPreviews); @@ -1163,9 +1180,7 @@ histogram_tester.ExpectUniqueSample( "Previews.EligibilityReason.ResourceLoadingHints", - static_cast<int>( - PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE), - 1); + static_cast<int>(PreviewsEligibilityReason::DEVICE_OFFLINE), 1); // Expect no triggered ECT logged. histogram_tester.ExpectTotalCount( @@ -1489,6 +1504,7 @@ PreviewsEligibilityReason::USER_BLACKLISTED, PreviewsEligibilityReason::HOST_BLACKLISTED, PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE, + PreviewsEligibilityReason::DEVICE_OFFLINE, }; PreviewsUserData user_data(kDefaultPageId); previews_decider_impl()->ShouldAllowPreviewAtNavigationStart( @@ -1531,6 +1547,7 @@ PreviewsEligibilityReason::USER_BLACKLISTED, PreviewsEligibilityReason::HOST_BLACKLISTED, PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE, + PreviewsEligibilityReason::DEVICE_OFFLINE, PreviewsEligibilityReason::NETWORK_NOT_SLOW, }; @@ -1604,6 +1621,7 @@ PreviewsEligibilityReason::USER_BLACKLISTED, PreviewsEligibilityReason::HOST_BLACKLISTED, PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE, + PreviewsEligibilityReason::DEVICE_OFFLINE, PreviewsEligibilityReason::NETWORK_NOT_SLOW, PreviewsEligibilityReason::RELOAD_DISALLOWED, };
diff --git a/components/previews/core/previews_black_list.h b/components/previews/core/previews_black_list.h index ef6740a..3f705be 100644 --- a/components/previews/core/previews_black_list.h +++ b/components/previews/core/previews_black_list.h
@@ -29,6 +29,7 @@ namespace previews { +// Must remain synchronized with PreviewsEligibilityReason in enums.xml. enum class PreviewsEligibilityReason { // The preview navigation was allowed. ALLOWED = 0, @@ -66,6 +67,8 @@ // The network is faster than the max slow page triggering threshold for the // session. NETWORK_NOT_SLOW_FOR_SESSION = 14, + // Device is offline. + DEVICE_OFFLINE = 15, LAST, };
diff --git a/components/previews/core/previews_logger.cc b/components/previews/core/previews_logger.cc index 5708b70..332cce4 100644 --- a/components/previews/core/previews_logger.cc +++ b/components/previews/core/previews_logger.cc
@@ -83,6 +83,9 @@ return want_inverse_description ? "Network is slow enough for the session" : "Network not slow enough for the session"; + case PreviewsEligibilityReason::DEVICE_OFFLINE: + return want_inverse_description ? "Device is online" + : "Device is offline"; } NOTREACHED(); return "";
diff --git a/components/printing/common/printer_capabilities.cc b/components/printing/common/printer_capabilities.cc index d8fc0d4..775b485 100644 --- a/components/printing/common/printer_capabilities.cc +++ b/components/printing/common/printer_capabilities.cc
@@ -39,6 +39,7 @@ std::unique_ptr<base::DictionaryValue> GetPrinterCapabilitiesOnBlockingPoolThread( const std::string& device_name, + const PrinterSemanticCapsAndDefaults::Papers& additional_papers, scoped_refptr<PrintBackend> print_backend) { base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK); DCHECK(!device_name.empty()); @@ -63,6 +64,8 @@ return empty_capabilities; } + info.papers.insert(info.papers.end(), additional_papers.begin(), + additional_papers.end()); return cloud_print::PrinterSemanticCapsAndDefaultsToCdd(info); } @@ -112,6 +115,7 @@ std::unique_ptr<base::DictionaryValue> GetSettingsOnBlockingPool( const std::string& device_name, const PrinterBasicInfo& basic_info, + const PrinterSemanticCapsAndDefaults::Papers& additional_papers, scoped_refptr<PrintBackend> print_backend) { base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK); @@ -132,8 +136,8 @@ auto printer_info_capabilities = std::make_unique<base::DictionaryValue>(); printer_info_capabilities->SetDictionary(kPrinter, std::move(printer_info)); printer_info_capabilities->Set( - kSettingCapabilities, - GetPrinterCapabilitiesOnBlockingPoolThread(device_name, print_backend)); + kSettingCapabilities, GetPrinterCapabilitiesOnBlockingPoolThread( + device_name, additional_papers, print_backend)); return printer_info_capabilities; }
diff --git a/components/printing/common/printer_capabilities.h b/components/printing/common/printer_capabilities.h index 91019fd..9a1d245 100644 --- a/components/printing/common/printer_capabilities.h +++ b/components/printing/common/printer_capabilities.h
@@ -10,6 +10,7 @@ #include <utility> #include "base/memory/scoped_refptr.h" +#include "printing/backend/print_backend.h" namespace base { class DictionaryValue; @@ -17,7 +18,6 @@ namespace printing { -class PrintBackend; struct PrinterBasicInfo; extern const char kPrinter[]; @@ -32,9 +32,12 @@ // for passage to the WebUI. The settings are obtained using |print_backend| if // it is provided. If |print_backend| is null, uses a new PrintBackend instance // with default settings. +// Data from |basic_info| and |additional_papers| are incorporated into the +// returned dictionary. std::unique_ptr<base::DictionaryValue> GetSettingsOnBlockingPool( const std::string& device_name, const PrinterBasicInfo& basic_info, + const PrinterSemanticCapsAndDefaults::Papers& additional_papers, scoped_refptr<PrintBackend> print_backend); } // namespace printing
diff --git a/components/printing/common/printer_capabilities_unittest.cc b/components/printing/common/printer_capabilities_unittest.cc index cc852f4..a98902d38 100644 --- a/components/printing/common/printer_capabilities_unittest.cc +++ b/components/printing/common/printer_capabilities_unittest.cc
@@ -16,6 +16,8 @@ namespace printing { +using base::Value; + namespace { const char kDpi[] = "dpi"; @@ -47,9 +49,11 @@ TEST_F(PrinterCapabilitiesTest, NonNullForMissingPrinter) { std::string printer_name = "missing_printer"; PrinterBasicInfo basic_info; + PrinterSemanticCapsAndDefaults::Papers no_additional_papers; std::unique_ptr<base::DictionaryValue> settings_dictionary = - GetSettingsOnBlockingPool(printer_name, basic_info, nullptr); + GetSettingsOnBlockingPool(printer_name, basic_info, no_additional_papers, + nullptr); ASSERT_TRUE(settings_dictionary); } @@ -57,6 +61,7 @@ TEST_F(PrinterCapabilitiesTest, ProvidedCapabilitiesUsed) { std::string printer_name = "test_printer"; PrinterBasicInfo basic_info; + PrinterSemanticCapsAndDefaults::Papers no_additional_papers; // Set a capability and add a valid printer. auto caps = std::make_unique<PrinterSemanticCapsAndDefaults>(); @@ -64,7 +69,8 @@ print_backend()->AddValidPrinter(printer_name, std::move(caps)); std::unique_ptr<base::DictionaryValue> settings_dictionary = - GetSettingsOnBlockingPool(printer_name, basic_info, print_backend()); + GetSettingsOnBlockingPool(printer_name, basic_info, no_additional_papers, + print_backend()); // Verify settings were created. ASSERT_TRUE(settings_dictionary); @@ -85,12 +91,14 @@ TEST_F(PrinterCapabilitiesTest, NullCapabilitiesExcluded) { std::string printer_name = "test_printer"; PrinterBasicInfo basic_info; + PrinterSemanticCapsAndDefaults::Papers no_additional_papers; // Return false when attempting to retrieve capabilities. print_backend()->AddValidPrinter(printer_name, nullptr); std::unique_ptr<base::DictionaryValue> settings_dictionary = - GetSettingsOnBlockingPool(printer_name, basic_info, print_backend()); + GetSettingsOnBlockingPool(printer_name, basic_info, no_additional_papers, + print_backend()); // Verify settings were created. ASSERT_TRUE(settings_dictionary); @@ -102,4 +110,77 @@ EXPECT_TRUE(caps_dict->empty()); } +TEST_F(PrinterCapabilitiesTest, AdditionalPapers) { + std::string printer_name = "test_printer"; + PrinterBasicInfo basic_info; + + // Set a capability and add a valid printer. + auto caps = std::make_unique<PrinterSemanticCapsAndDefaults>(); + caps->dpis = {{600, 600}}; + print_backend()->AddValidPrinter(printer_name, std::move(caps)); + + // Add some more paper sizes. + PrinterSemanticCapsAndDefaults::Papers additional_papers; + additional_papers.push_back({"foo", "vendor", {200, 300}}); + additional_papers.push_back({"bar", "vendor", {600, 600}}); + + std::unique_ptr<base::DictionaryValue> settings_dictionary = + GetSettingsOnBlockingPool(printer_name, basic_info, additional_papers, + print_backend()); + + // Verify settings were created. + ASSERT_TRUE(settings_dictionary); + + // Verify there is a CDD with a printer entry. + const Value* cdd = settings_dictionary->FindKeyOfType( + kSettingCapabilities, Value::Type::DICTIONARY); + ASSERT_TRUE(cdd); + const Value* printer = cdd->FindKeyOfType(kPrinter, Value::Type::DICTIONARY); + ASSERT_TRUE(printer); + + // Verify there are 2 paper sizes. + const Value* media_size = + printer->FindKeyOfType("media_size", Value::Type::DICTIONARY); + ASSERT_TRUE(media_size); + const Value* media_option = + media_size->FindKeyOfType("option", Value::Type::LIST); + ASSERT_TRUE(media_option); + const auto& list = media_option->GetList(); + ASSERT_EQ(2U, list.size()); + ASSERT_TRUE(list[0].is_dict()); + ASSERT_TRUE(list[1].is_dict()); + + // Verify the 2 paper sizes are the ones in |additional_papers|. + const Value* name; + const Value* vendor; + const Value* width; + const Value* height; + + name = list[0].FindKeyOfType("custom_display_name", Value::Type::STRING); + ASSERT_TRUE(name); + EXPECT_EQ("foo", name->GetString()); + vendor = list[0].FindKeyOfType("vendor_id", Value::Type::STRING); + ASSERT_TRUE(vendor); + EXPECT_EQ("vendor", vendor->GetString()); + width = list[0].FindKeyOfType("width_microns", Value::Type::INTEGER); + ASSERT_TRUE(width); + EXPECT_EQ(200, width->GetInt()); + height = list[0].FindKeyOfType("height_microns", Value::Type::INTEGER); + ASSERT_TRUE(height); + EXPECT_EQ(300, height->GetInt()); + + name = list[1].FindKeyOfType("custom_display_name", Value::Type::STRING); + ASSERT_TRUE(name); + EXPECT_EQ("bar", name->GetString()); + vendor = list[1].FindKeyOfType("vendor_id", Value::Type::STRING); + ASSERT_TRUE(vendor); + EXPECT_EQ("vendor", vendor->GetString()); + width = list[1].FindKeyOfType("width_microns", Value::Type::INTEGER); + ASSERT_TRUE(width); + EXPECT_EQ(600, width->GetInt()); + height = list[1].FindKeyOfType("height_microns", Value::Type::INTEGER); + ASSERT_TRUE(height); + EXPECT_EQ(600, height->GetInt()); +} + } // namespace printing
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc index 5634f69..770bc47 100644 --- a/components/printing/renderer/print_render_frame_helper.cc +++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -995,7 +995,7 @@ std::unique_ptr<blink::WebURLLoaderFactory> PrepareFrameAndViewForPrint::CreateURLLoaderFactory() { - return frame_.GetFrame()->Client()->CreateURLLoaderFactory(); + return blink::Platform::Current()->CreateDefaultURLLoaderFactory(); } void PrepareFrameAndViewForPrint::CallOnReady() {
diff --git a/components/reading_list/core/reading_list_store_unittest.cc b/components/reading_list/core/reading_list_store_unittest.cc index 4e295cd..1aa7227 100644 --- a/components/reading_list/core/reading_list_store_unittest.cc +++ b/components/reading_list/core/reading_list_store_unittest.cc
@@ -9,8 +9,8 @@ #include <utility> #include "base/bind.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" #include "base/test/simple_test_clock.h" #include "components/reading_list/core/reading_list_model_impl.h" #include "components/sync/model/mock_model_type_change_processor.h" @@ -142,8 +142,8 @@ return model_->SyncMergeEntry(std::move(entry)); } - // In memory model type store needs a MessageLoop. - base::MessageLoop message_loop_; + // In memory model type store needs to be able to post tasks. + base::test::ScopedTaskEnvironment task_environment_; testing::NiceMock<syncer::MockModelTypeChangeProcessor> processor_; std::unique_ptr<syncer::ModelTypeStore> store_;
diff --git a/components/rlz/rlz_tracker.cc b/components/rlz/rlz_tracker.cc index 2b35d730..204a6c6 100644 --- a/components/rlz/rlz_tracker.cc +++ b/components/rlz/rlz_tracker.cc
@@ -302,8 +302,13 @@ if (delegate_->IsBrandOrganic(brand_) && delegate_->IsBrandOrganic(reactivation_brand_)) { SYSLOG(INFO) << "RLZ is disabled"; - } else { - rlz_lib::UpdateExistingAccessPointRlz(brand_); + } else if (delegate_->ShouldUpdateExistingAccessPointRlz()) { + background_task_runner_->PostTask( + FROM_HERE, base::BindOnce( + [](const std::string& brand) { + rlz_lib::UpdateExistingAccessPointRlz(brand); + }, + brand_)); } #endif
diff --git a/components/rlz/rlz_tracker_delegate.h b/components/rlz/rlz_tracker_delegate.h index d2c2df9f..c158dcb1 100644 --- a/components/rlz/rlz_tracker_delegate.h +++ b/components/rlz/rlz_tracker_delegate.h
@@ -69,6 +69,10 @@ // once. virtual void SetHomepageSearchCallback(const base::Closure& callback) = 0; + // Returns true if the existing access point RLZ strings in the data file + // should be updated. + virtual bool ShouldUpdateExistingAccessPointRlz() = 0; + private: DISALLOW_COPY_AND_ASSIGN(RLZTrackerDelegate); };
diff --git a/components/rlz/rlz_tracker_unittest.cc b/components/rlz/rlz_tracker_unittest.cc index e33f7dc9..81273ae 100644 --- a/components/rlz/rlz_tracker_unittest.cc +++ b/components/rlz/rlz_tracker_unittest.cc
@@ -110,6 +110,9 @@ on_homepage_search_callback_ = callback; } + // A speculative fix for https://crbug.com/907379. + bool ShouldUpdateExistingAccessPointRlz() override { return false; } + private: scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
diff --git a/components/safe_browsing/browser/threat_details_cache.h b/components/safe_browsing/browser/threat_details_cache.h index d823417..70181aa 100644 --- a/components/safe_browsing/browser/threat_details_cache.h +++ b/components/safe_browsing/browser/threat_details_cache.h
@@ -13,7 +13,6 @@ #include "base/callback.h" #include "base/containers/hash_tables.h" -#include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" #include "net/base/completion_callback.h"
diff --git a/components/safe_browsing/db/v4_store.cc b/components/safe_browsing/db/v4_store.cc index e1cba619..9adf309 100644 --- a/components/safe_browsing/db/v4_store.cc +++ b/components/safe_browsing/db/v4_store.cc
@@ -855,7 +855,8 @@ void V4Store::CollectStoreInfo( DatabaseManagerInfo::DatabaseInfo::StoreInfo* store_info, const std::string& base_metric) { - store_info->set_file_name(base_metric + GetUmaSuffixForStore(store_path_)); + store_info->set_file_name(GetUmaSuffixForStore(store_path_) + .substr(1)); // Strip the '.' off the front store_info->set_file_size_bytes(file_size_); store_info->set_update_status(static_cast<int>(last_apply_update_result_)); store_info->set_checks_attempted(checks_attempted_);
diff --git a/components/safe_browsing/db/v4_update_protocol_manager.cc b/components/safe_browsing/db/v4_update_protocol_manager.cc index f410258..094430b 100644 --- a/components/safe_browsing/db/v4_update_protocol_manager.cc +++ b/components/safe_browsing/db/v4_update_protocol_manager.cc
@@ -443,8 +443,14 @@ if (last_response_code_) update_info->set_network_status_code(last_response_code_); - if (last_response_time_.ToJavaTime()) + if (last_response_time_.ToJavaTime()) { update_info->set_last_update_time_millis(last_response_time_.ToJavaTime()); + + // We should only find the next update if the last_response is valid. + base::Time next_update = last_response_time_ + next_update_interval_; + if (next_update.ToJavaTime()) + update_info->set_next_update_time_millis(next_update.ToJavaTime()); + } } } // namespace safe_browsing
diff --git a/components/safe_browsing/proto/webui.proto b/components/safe_browsing/proto/webui.proto index c495460..446de08 100644 --- a/components/safe_browsing/proto/webui.proto +++ b/components/safe_browsing/proto/webui.proto
@@ -20,6 +20,10 @@ // The time, since epoch, when the last update request was sent to // SafeBrowsing. optional uint64 last_update_time_millis = 2; + + // The time, since epoch, when the next update request will be sent to + // SafeBrowsing. + optional uint64 next_update_time_millis = 3; } optional UpdateInfo update_info = 1;
diff --git a/components/safe_browsing/web_ui/safe_browsing_ui.cc b/components/safe_browsing/web_ui/safe_browsing_ui.cc index 684efde6..0848288 100644 --- a/components/safe_browsing/web_ui/safe_browsing_ui.cc +++ b/components/safe_browsing/web_ui/safe_browsing_ui.cc
@@ -197,36 +197,48 @@ void AddStoreInfo(const DatabaseManagerInfo::DatabaseInfo::StoreInfo store_info, base::ListValue* database_info_list) { - if (store_info.has_file_size_bytes() && store_info.has_file_name()) { + if (store_info.has_file_name()) { database_info_list->GetList().push_back( base::Value(store_info.file_name())); - database_info_list->GetList().push_back( - base::Value(static_cast<double>(store_info.file_size_bytes()))); + } else { + database_info_list->GetList().push_back(base::Value("Unknown store")); } + + std::string store_info_string = "<blockquote>"; + if (store_info.has_file_size_bytes()) { + store_info_string += + "Size (in bytes): " + std::to_string(store_info.file_size_bytes()) + + "<br>"; + } + if (store_info.has_update_status()) { - database_info_list->GetList().push_back(base::Value("Store update status")); - database_info_list->GetList().push_back( - base::Value(store_info.update_status())); + store_info_string += + "Update status: " + std::to_string(store_info.update_status()) + "<br>"; } + if (store_info.has_last_apply_update_time_millis()) { - database_info_list->GetList().push_back(base::Value("Last update time")); - database_info_list->GetList().push_back( - UserReadableTimeFromMillisSinceEpoch( - store_info.last_apply_update_time_millis())); + store_info_string += "Last update time: " + + UserReadableTimeFromMillisSinceEpoch( + store_info.last_apply_update_time_millis()) + .GetString() + + "<br>"; } + if (store_info.has_checks_attempted()) { - database_info_list->GetList().push_back( - base::Value("Number of database checks")); - database_info_list->GetList().push_back( - base::Value(static_cast<int>(store_info.checks_attempted()))); + store_info_string += "Number of database checks: " + + std::to_string(store_info.checks_attempted()) + "<br>"; } + + store_info_string += "</blockquote>"; + + database_info_list->GetList().push_back(base::Value(store_info_string)); } void AddDatabaseInfo(const DatabaseManagerInfo::DatabaseInfo database_info, base::ListValue* database_info_list) { if (database_info.has_database_size_bytes()) { database_info_list->GetList().push_back( - base::Value("Database size in bytes")); + base::Value("Database size (in bytes)")); database_info_list->GetList().push_back( base::Value(static_cast<double>(database_info.database_size_bytes()))); } @@ -252,6 +264,12 @@ UserReadableTimeFromMillisSinceEpoch( update_info.last_update_time_millis())); } + if (update_info.has_next_update_time_millis()) { + database_info_list->GetList().push_back(base::Value("Next update time")); + database_info_list->GetList().push_back( + UserReadableTimeFromMillisSinceEpoch( + update_info.next_update_time_millis())); + } } void ParseFullHashInfo(
diff --git a/components/search_provider_logos/BUILD.gn b/components/search_provider_logos/BUILD.gn index 18619792..44688b7f 100644 --- a/components/search_provider_logos/BUILD.gn +++ b/components/search_provider_logos/BUILD.gn
@@ -18,7 +18,6 @@ "logo_service.h", "logo_service_impl.cc", "logo_service_impl.h", - "logo_tracker.cc", "logo_tracker.h", "switches.cc", "switches.h",
diff --git a/components/search_provider_logos/fixed_logo_api.h b/components/search_provider_logos/fixed_logo_api.h index 7801357..4d625d0 100644 --- a/components/search_provider_logos/fixed_logo_api.h +++ b/components/search_provider_logos/fixed_logo_api.h
@@ -16,11 +16,12 @@ struct EncodedLogo; -// Implements AppendFingerprintToLogoURL, defined in logo_tracker.h, +// Implements AppendQueryparamsToLogoURL, defined in logo_common.h, // for static logos. GURL UseFixedLogoUrl(const GURL& logo_url, const std::string& fingerprint); -// Implements ParseLogoResponse, defined in logo_tracker.h, for static logos. +// Implements ParseLogoResponse, defined in logo_common.h, +// for static logos. std::unique_ptr<EncodedLogo> ParseFixedLogoResponse( std::unique_ptr<std::string> response, base::Time response_time,
diff --git a/components/search_provider_logos/google_logo_api.cc b/components/search_provider_logos/google_logo_api.cc index ab753b9..bc18006 100644 --- a/components/search_provider_logos/google_logo_api.cc +++ b/components/search_provider_logos/google_logo_api.cc
@@ -200,6 +200,29 @@ return nullptr; } + const bool is_eligible_for_share_button = + (logo->metadata.type == LogoType::ANIMATED || + logo->metadata.type == LogoType::SIMPLE); + + if (is_eligible_for_share_button) { + const base::DictionaryValue* share_button = nullptr; + std::string short_link_str; + // The short link in the doodle proto is an incomplete URL with the format + // //g.co/*. Complete the URL if possible. + if (ddljson->GetDictionary("share_button", &share_button) && + ddljson->GetString("short_link", &short_link_str) && + short_link_str.find("//g.co") == 0) { + share_button->GetInteger("offset_x", &logo->metadata.share_button_x); + share_button->GetInteger("offset_y", &logo->metadata.share_button_y); + share_button->GetDouble("opacity", &logo->metadata.share_button_opacity); + share_button->GetString("icon_image", &logo->metadata.share_button_icon); + share_button->GetString("background_color", + &logo->metadata.share_button_bg); + short_link_str.insert(0, "https:"); + logo->metadata.short_link = GURL(short_link_str); + } + } + logo->metadata.full_page_url = ParseUrl(*ddljson, "fullpage_interactive_url", base_url);
diff --git a/components/search_provider_logos/logo_cache.cc b/components/search_provider_logos/logo_cache.cc index f4f6ece..a06f4019 100644 --- a/components/search_provider_logos/logo_cache.cc +++ b/components/search_provider_logos/logo_cache.cc
@@ -34,6 +34,13 @@ const char kAnimatedUrlKey[] = "animated_url"; const char kLogUrlKey[] = "log_url"; const char kCtaLogUrlKey[] = "cta_log_url"; +const char kShortLinkKey[] = "short_link"; + +const char kShareButtonX[] = "share_button_x"; +const char kShareButtonY[] = "share_button_y"; +const char kShareButtonOpacity[] = "share_button_opacity"; +const char kShareButtonIcon[] = "share_button_icon"; +const char kShareButtonBg[] = "share_button_bg"; const char kSimpleType[] = "SIMPLE"; const char kAnimatedType[] = "ANIMATED"; @@ -170,6 +177,7 @@ std::string animated_url; std::string log_url; std::string cta_log_url; + std::string short_link; if (!dict->GetString(kSourceUrlKey, &source_url) || !dict->GetString(kFingerprintKey, &metadata->fingerprint) || !dict->GetString(kTypeKey, &type) || @@ -179,10 +187,16 @@ !dict->GetString(kAnimatedUrlKey, &animated_url) || !dict->GetString(kLogUrlKey, &log_url) || !dict->GetString(kCtaLogUrlKey, &cta_log_url) || + !dict->GetString(kShortLinkKey, &short_link) || !dict->GetString(kMimeTypeKey, &metadata->mime_type) || !dict->GetBoolean(kCanShowAfterExpirationKey, &metadata->can_show_after_expiration) || !dict->GetInteger(kNumBytesKey, logo_num_bytes) || + !dict->GetInteger(kShareButtonX, &metadata->share_button_x) || + !dict->GetInteger(kShareButtonY, &metadata->share_button_y) || + !dict->GetDouble(kShareButtonOpacity, &metadata->share_button_opacity) || + !dict->GetString(kShareButtonIcon, &metadata->share_button_icon) || + !dict->GetString(kShareButtonBg, &metadata->share_button_bg) || !GetTimeValue(*dict, kExpirationTimeKey, &metadata->expiration_time)) { return nullptr; } @@ -193,6 +207,7 @@ metadata->animated_url = GURL(animated_url); metadata->log_url = GURL(log_url); metadata->cta_log_url = GURL(cta_log_url); + metadata->short_link = GURL(short_link); return metadata; } @@ -211,10 +226,16 @@ dict.SetString(kAnimatedUrlKey, metadata.animated_url.spec()); dict.SetString(kLogUrlKey, metadata.log_url.spec()); dict.SetString(kCtaLogUrlKey, metadata.cta_log_url.spec()); + dict.SetString(kShortLinkKey, metadata.short_link.spec()); dict.SetString(kMimeTypeKey, metadata.mime_type); dict.SetBoolean(kCanShowAfterExpirationKey, metadata.can_show_after_expiration); dict.SetInteger(kNumBytesKey, num_bytes); + dict.SetInteger(kShareButtonX, metadata.share_button_x); + dict.SetInteger(kShareButtonY, metadata.share_button_y); + dict.SetDouble(kShareButtonOpacity, metadata.share_button_opacity); + dict.SetString(kShareButtonIcon, metadata.share_button_icon); + dict.SetString(kShareButtonBg, metadata.share_button_bg); SetTimeValue(dict, kExpirationTimeKey, metadata.expiration_time); base::JSONWriter::Write(dict, str); }
diff --git a/components/search_provider_logos/logo_common.h b/components/search_provider_logos/logo_common.h index dd3f4c5..a26e38c9 100644 --- a/components/search_provider_logos/logo_common.h +++ b/components/search_provider_logos/logo_common.h
@@ -73,6 +73,9 @@ // there is one, or the only image otherwise). May be empty. GURL log_url; + // The URL used for sharing doodles. + GURL short_link; + // SIMPLE, ANIMATED: ignored // INTERACTIVE: appropriate dimensions for the iframe. int iframe_width_px = 0; @@ -91,6 +94,23 @@ // When the logo expires. After this time, the logo will not be used and will // be deleted. base::Time expiration_time; + + // Used by the Optional Doodle Share Button --------------------------------- + + // Share button x position + int share_button_x = -1; + + // Share button y position + int share_button_y = -1; + + // Share button opacity + double share_button_opacity = 0; + + // Share button icon image, uses Data URI format. + std::string share_button_icon; + + // Share button background color, uses hex format. + std::string share_button_bg; }; enum class LogoCallbackReason {
diff --git a/components/search_provider_logos/logo_service_impl.cc b/components/search_provider_logos/logo_service_impl.cc index 692bf78..b7dc7df2 100644 --- a/components/search_provider_logos/logo_service_impl.cc +++ b/components/search_provider_logos/logo_service_impl.cc
@@ -4,11 +4,17 @@ #include "components/search_provider_logos/logo_service_impl.h" +#include <algorithm> +#include <utility> + #include "base/command_line.h" #include "base/feature_list.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/metrics/field_trial_params.h" +#include "base/metrics/histogram_macros.h" +#include "base/task/post_task.h" +#include "base/task_runner_util.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/default_clock.h" #include "build/build_config.h" @@ -22,13 +28,60 @@ #include "components/search_provider_logos/logo_tracker.h" #include "components/search_provider_logos/switches.h" #include "components/signin/core/browser/gaia_cookie_manager_service.h" +#include "net/http/http_status_code.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/cpp/shared_url_loader_factory.h" - -using search_provider_logos::LogoTracker; +#include "services/network/public/cpp/simple_url_loader.h" +#include "ui/gfx/image/image.h" namespace search_provider_logos { namespace { +const int64_t kMaxDownloadBytes = 1024 * 1024; +const int kDecodeLogoTimeoutSeconds = 30; + +// Implements a callback for image_fetcher::ImageDecoder. If Run() is called on +// a callback returned by GetCallback() within 30 seconds, forwards the decoded +// image to the wrapped callback. If not, sends an empty image to the wrapped +// callback instead. Either way, deletes the object and prevents further calls. +// +// TODO(sfiera): find a more idiomatic way of setting a deadline on the +// callback. This is implemented as a self-deleting object in part because it +// needed to when it used to be a delegate and in part because I couldn't figure +// out a better way, now that it isn't. +class ImageDecodedHandlerWithTimeout { + public: + static base::RepeatingCallback<void(const gfx::Image&)> Wrap( + const base::RepeatingCallback<void(const SkBitmap&)>& + image_decoded_callback) { + auto* handler = new ImageDecodedHandlerWithTimeout(image_decoded_callback); + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&ImageDecodedHandlerWithTimeout::OnImageDecoded, + handler->weak_ptr_factory_.GetWeakPtr(), gfx::Image()), + base::TimeDelta::FromSeconds(kDecodeLogoTimeoutSeconds)); + return base::BindRepeating(&ImageDecodedHandlerWithTimeout::OnImageDecoded, + handler->weak_ptr_factory_.GetWeakPtr()); + } + + private: + explicit ImageDecodedHandlerWithTimeout( + const base::RepeatingCallback<void(const SkBitmap&)>& + image_decoded_callback) + : image_decoded_callback_(image_decoded_callback), + weak_ptr_factory_(this) {} + + void OnImageDecoded(const gfx::Image& decoded_image) { + image_decoded_callback_.Run(decoded_image.AsBitmap()); + delete this; + } + + base::RepeatingCallback<void(const SkBitmap&)> image_decoded_callback_; + base::WeakPtrFactory<ImageDecodedHandlerWithTimeout> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(ImageDecodedHandlerWithTimeout); +}; + void ObserverOnLogoAvailable(LogoObserver* observer, bool from_cache, LogoCallbackReason type, @@ -72,6 +125,57 @@ } } +// Returns whether the metadata for the cached logo indicates that the logo is +// OK to show, i.e. it's not expired or it's allowed to be shown temporarily +// after expiration. +bool IsLogoOkToShow(const LogoMetadata& metadata, base::Time now) { + base::TimeDelta offset = + base::TimeDelta::FromMilliseconds(kMaxTimeToLiveMS * 3 / 2); + base::Time distant_past = now - offset; + // Sanity check so logos aren't accidentally cached forever. + if (metadata.expiration_time < distant_past) { + return false; + } + return metadata.can_show_after_expiration || metadata.expiration_time >= now; +} + +// Reads the logo from the cache and returns it. Returns NULL if the cache is +// empty, corrupt, expired, or doesn't apply to the current logo URL. +std::unique_ptr<EncodedLogo> GetLogoFromCacheOnFileThread(LogoCache* logo_cache, + const GURL& logo_url, + base::Time now) { + const LogoMetadata* metadata = logo_cache->GetCachedLogoMetadata(); + if (!metadata) + return nullptr; + + if (metadata->source_url != logo_url || !IsLogoOkToShow(*metadata, now)) { + logo_cache->SetCachedLogo(nullptr); + return nullptr; + } + + return logo_cache->GetCachedLogo(); +} + +void NotifyAndClear(std::vector<EncodedLogoCallback>* encoded_callbacks, + std::vector<LogoCallback>* decoded_callbacks, + LogoCallbackReason type, + const EncodedLogo* encoded_logo, + const Logo* decoded_logo) { + auto opt_encoded_logo = + encoded_logo ? base::Optional<EncodedLogo>(*encoded_logo) : base::nullopt; + for (EncodedLogoCallback& callback : *encoded_callbacks) { + std::move(callback).Run(type, opt_encoded_logo); + } + encoded_callbacks->clear(); + + auto opt_decoded_logo = + decoded_logo ? base::Optional<Logo>(*decoded_logo) : base::nullopt; + for (LogoCallback& callback : *decoded_callbacks) { + std::move(callback).Run(type, opt_decoded_logo); + } + decoded_callbacks->clear(); +} + } // namespace class LogoServiceImpl::SigninObserver @@ -120,7 +224,15 @@ signin_observer_(std::make_unique<SigninObserver>( cookie_service, base::BindRepeating(&LogoServiceImpl::SigninStatusChanged, - base::Unretained(this)))) {} + base::Unretained(this)))), + is_idle_(true), + is_cached_logo_valid_(false), + cache_task_runner_(base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})), + logo_cache_(new LogoCache(cache_directory_), + base::OnTaskRunnerDeleter(cache_task_runner_)), + weak_ptr_factory_(this) {} LogoServiceImpl::~LogoServiceImpl() = default; @@ -128,6 +240,7 @@ // The GaiaCookieManagerService may be destroyed at any point after Shutdown, // so make sure we drop any references to it. signin_observer_.reset(); + ReturnToIdle(kDownloadOutcomeNotTracked); } void LogoServiceImpl::GetLogo(search_provider_logos::LogoObserver* observer) { @@ -191,59 +304,402 @@ return; } - InitializeLogoTrackerIfNecessary(); + if (!clock_) { + clock_ = base::DefaultClock::GetInstance(); + } const bool use_fixed_logo = !doodle_url.is_valid(); if (use_fixed_logo) { - logo_tracker_->SetServerAPI( - logo_url, base::Bind(&search_provider_logos::ParseFixedLogoResponse), - base::Bind(&search_provider_logos::UseFixedLogoUrl)); + SetServerAPI( + logo_url, + base::BindRepeating(&search_provider_logos::ParseFixedLogoResponse), + base::BindRepeating(&search_provider_logos::UseFixedLogoUrl)); } else { // We encode the type of doodle (regular or gray) in the URL so that the // logo cache gets cleared when that value changes. GURL prefilled_url = AppendPreliminaryParamsToDoodleURL( want_gray_logo_getter_.Run(), doodle_url); - logo_tracker_->SetServerAPI( + SetServerAPI( prefilled_url, base::Bind(&search_provider_logos::ParseDoodleLogoResponse, base_url), base::Bind(&search_provider_logos::AppendFingerprintParamToDoodleURL)); } - logo_tracker_->GetLogo(std::move(callbacks)); + DCHECK(!logo_url_.is_empty()); + DCHECK(callbacks.on_cached_decoded_logo_available || + callbacks.on_cached_encoded_logo_available || + callbacks.on_fresh_decoded_logo_available || + callbacks.on_fresh_encoded_logo_available); + + if (callbacks.on_cached_encoded_logo_available) { + on_cached_encoded_logo_.push_back( + std::move(callbacks.on_cached_encoded_logo_available)); + } + if (callbacks.on_cached_decoded_logo_available) { + on_cached_decoded_logo_.push_back( + std::move(callbacks.on_cached_decoded_logo_available)); + } + if (callbacks.on_fresh_encoded_logo_available) { + on_fresh_encoded_logo_.push_back( + std::move(callbacks.on_fresh_encoded_logo_available)); + } + if (callbacks.on_fresh_decoded_logo_available) { + on_fresh_decoded_logo_.push_back( + std::move(callbacks.on_fresh_decoded_logo_available)); + } + + if (is_idle_) { + is_idle_ = false; + + base::PostTaskAndReplyWithResult( + cache_task_runner_.get(), FROM_HERE, + base::BindRepeating(&GetLogoFromCacheOnFileThread, + base::Unretained(logo_cache_.get()), logo_url_, + clock_->Now()), + base::BindRepeating(&LogoServiceImpl::OnCachedLogoRead, + weak_ptr_factory_.GetWeakPtr())); + } else if (is_cached_logo_valid_) { + NotifyAndClear(&on_cached_encoded_logo_, &on_cached_decoded_logo_, + LogoCallbackReason::DETERMINED, cached_encoded_logo_.get(), + cached_logo_.get()); + } } void LogoServiceImpl::SetLogoCacheForTests(std::unique_ptr<LogoCache> cache) { - logo_cache_for_test_ = std::move(cache); + // |logo_cache_| has a custom deleter, which makes the two unique_ptrs + // be different types. so one can't be moved on top of the other. + logo_cache_.reset(std::move(cache).release()); } void LogoServiceImpl::SetClockForTests(base::Clock* clock) { - clock_for_test_ = clock; + clock_ = clock; } -void LogoServiceImpl::InitializeLogoTrackerIfNecessary() { - if (logo_tracker_) { +void LogoServiceImpl::SetServerAPI( + const GURL& logo_url, + const ParseLogoResponse& parse_logo_response_func, + const AppendQueryparamsToLogoURL& append_queryparams_func) { + if (logo_url == logo_url_) + return; + + ReturnToIdle(kDownloadOutcomeNotTracked); + + logo_url_ = logo_url; + parse_logo_response_func_ = parse_logo_response_func; + append_queryparams_func_ = append_queryparams_func; +} + +void LogoServiceImpl::ClearCachedLogo() { + // First cancel any fetch that might be ongoing. + ReturnToIdle(kDownloadOutcomeNotTracked); + // Then clear any cached logo. + SetCachedLogo(nullptr); +} + +void LogoServiceImpl::ReturnToIdle(int outcome) { + if (outcome != kDownloadOutcomeNotTracked) { + UMA_HISTOGRAM_ENUMERATION("NewTabPage.LogoDownloadOutcome", + static_cast<LogoDownloadOutcome>(outcome), + DOWNLOAD_OUTCOME_COUNT); + } + + // Cancel the current asynchronous operation, if any. + loader_.reset(); + weak_ptr_factory_.InvalidateWeakPtrs(); + + // Reset state. + is_idle_ = true; + cached_logo_.reset(); + cached_encoded_logo_.reset(); + is_cached_logo_valid_ = false; + + // Clear callbacks. + NotifyAndClear(&on_cached_encoded_logo_, &on_cached_decoded_logo_, + LogoCallbackReason::CANCELED, nullptr, nullptr); + NotifyAndClear(&on_fresh_encoded_logo_, &on_fresh_decoded_logo_, + LogoCallbackReason::CANCELED, nullptr, nullptr); +} + +void LogoServiceImpl::OnCachedLogoRead( + std::unique_ptr<EncodedLogo> cached_logo) { + DCHECK(!is_idle_); + + if (cached_logo) { + // Store the value of logo->encoded_image for use below. This ensures that + // logo->encoded_image is evaulated before base::Passed(&logo), which sets + // logo to NULL. + scoped_refptr<base::RefCountedString> encoded_image = + cached_logo->encoded_image; + image_decoder_->DecodeImage( + encoded_image->data(), gfx::Size(), // No particular size desired. + ImageDecodedHandlerWithTimeout::Wrap(base::BindRepeating( + &LogoServiceImpl::OnCachedLogoAvailable, + weak_ptr_factory_.GetWeakPtr(), base::Passed(&cached_logo)))); + } else { + OnCachedLogoAvailable({}, SkBitmap()); + } +} + +void LogoServiceImpl::SetCachedLogo(std::unique_ptr<EncodedLogo> logo) { + cache_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&LogoCache::SetCachedLogo, + base::Unretained(logo_cache_.get()), + base::Owned(logo.release()))); +} + +void LogoServiceImpl::SetCachedMetadata(const LogoMetadata& metadata) { + cache_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&LogoCache::UpdateCachedLogoMetadata, + base::Unretained(logo_cache_.get()), metadata)); +} + +void LogoServiceImpl::OnCachedLogoAvailable( + std::unique_ptr<EncodedLogo> encoded_logo, + const SkBitmap& image) { + DCHECK(!is_idle_); + + if (!image.isNull()) { + cached_logo_.reset(new Logo()); + cached_logo_->metadata = encoded_logo->metadata; + cached_logo_->image = image; + cached_encoded_logo_ = std::move(encoded_logo); + } + is_cached_logo_valid_ = true; + NotifyAndClear(&on_cached_encoded_logo_, &on_cached_decoded_logo_, + LogoCallbackReason::DETERMINED, cached_encoded_logo_.get(), + cached_logo_.get()); + FetchLogo(); +} + +void LogoServiceImpl::FetchLogo() { + DCHECK(!loader_); + DCHECK(!is_idle_); + + std::string fingerprint; + if (cached_logo_ && !cached_logo_->metadata.fingerprint.empty() && + cached_logo_->metadata.expiration_time >= clock_->Now()) { + fingerprint = cached_logo_->metadata.fingerprint; + } + GURL url = append_queryparams_func_.Run(logo_url_, fingerprint); + net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("logo_service", R"( + semantics { + sender: "Logo Service" + description: + "Provides the logo image (aka Doodle) if Google is your configured " + "search provider." + trigger: "Displaying the new tab page on iOS or Android." + data: + "Logo ID, and the user's Google cookies to show for example " + "birthday doodles at appropriate times." + destination: OTHER + } + policy { + cookies_allowed: YES + cookies_store: "user" + setting: + "Choosing a non-Google search engine in Chromium settings under " + "'Search Engine' will disable this feature." + policy_exception_justification: + "Not implemented, considered not useful as it does not upload any" + "data and just downloads a logo image." + })"); + auto request = std::make_unique<network::ResourceRequest>(); + request->url = url; + // TODO(https://crbug.com/808498) re-add data use measurement once + // SimpleURLLoader supports it: + // data_use_measurement::DataUseUserData::SEARCH_PROVIDER_LOGOS + loader_ = + network::SimpleURLLoader::Create(std::move(request), traffic_annotation); + loader_->DownloadToString( + url_loader_factory_.get(), + base::BindOnce(&LogoServiceImpl::OnURLLoadComplete, + base::Unretained(this), loader_.get()), + kMaxDownloadBytes); + logo_download_start_time_ = base::TimeTicks::Now(); +} + +void LogoServiceImpl::OnFreshLogoParsed(bool* parsing_failed, + bool from_http_cache, + std::unique_ptr<EncodedLogo> logo) { + DCHECK(!is_idle_); + + if (logo) + logo->metadata.source_url = logo_url_; + + if (!logo || !logo->encoded_image) { + OnFreshLogoAvailable(std::move(logo), /*download_failed=*/false, + *parsing_failed, from_http_cache, SkBitmap()); + } else { + // Store the value of logo->encoded_image for use below. This ensures that + // logo->encoded_image is evaulated before base::Passed(&logo), which sets + // logo to NULL. + scoped_refptr<base::RefCountedString> encoded_image = logo->encoded_image; + image_decoder_->DecodeImage( + encoded_image->data(), gfx::Size(), // No particular size desired. + ImageDecodedHandlerWithTimeout::Wrap(base::BindRepeating( + &LogoServiceImpl::OnFreshLogoAvailable, + weak_ptr_factory_.GetWeakPtr(), base::Passed(&logo), + /*download_failed=*/false, *parsing_failed, from_http_cache))); + } +} + +void LogoServiceImpl::OnFreshLogoAvailable( + std::unique_ptr<EncodedLogo> encoded_logo, + bool download_failed, + bool parsing_failed, + bool from_http_cache, + const SkBitmap& image) { + DCHECK(!is_idle_); + + LogoDownloadOutcome download_outcome = DOWNLOAD_OUTCOME_COUNT; + std::unique_ptr<Logo> logo; + + if (download_failed) { + download_outcome = DOWNLOAD_OUTCOME_DOWNLOAD_FAILED; + } else if (encoded_logo && !encoded_logo->encoded_image && cached_logo_ && + !encoded_logo->metadata.fingerprint.empty() && + encoded_logo->metadata.fingerprint == + cached_logo_->metadata.fingerprint) { + // The cached logo was revalidated, i.e. its fingerprint was verified. + // mime_type isn't sent when revalidating, so copy it from the cached logo. + encoded_logo->metadata.mime_type = cached_logo_->metadata.mime_type; + SetCachedMetadata(encoded_logo->metadata); + download_outcome = DOWNLOAD_OUTCOME_LOGO_REVALIDATED; + } else if (encoded_logo && image.isNull()) { + // Image decoding failed. Do nothing. + download_outcome = DOWNLOAD_OUTCOME_DECODING_FAILED; + } else { + // Check if the server returned a valid, non-empty response. + if (encoded_logo) { + UMA_HISTOGRAM_BOOLEAN("NewTabPage.LogoImageDownloaded", from_http_cache); + + DCHECK(!image.isNull()); + logo.reset(new Logo()); + logo->metadata = encoded_logo->metadata; + logo->image = image; + } + + if (logo) { + download_outcome = DOWNLOAD_OUTCOME_NEW_LOGO_SUCCESS; + } else { + if (parsing_failed) + download_outcome = DOWNLOAD_OUTCOME_PARSING_FAILED; + else + download_outcome = DOWNLOAD_OUTCOME_NO_LOGO_TODAY; + } + } + + LogoCallbackReason callback_type = LogoCallbackReason::FAILED; + switch (download_outcome) { + case DOWNLOAD_OUTCOME_NEW_LOGO_SUCCESS: + DCHECK(encoded_logo); + DCHECK(logo); + callback_type = LogoCallbackReason::DETERMINED; + break; + + case DOWNLOAD_OUTCOME_PARSING_FAILED: + case DOWNLOAD_OUTCOME_NO_LOGO_TODAY: + // Clear the cached logo if it was non-null. Otherwise, report this as a + // revalidation of "no logo". + DCHECK(!encoded_logo); + DCHECK(!logo); + if (cached_logo_) { + callback_type = LogoCallbackReason::DETERMINED; + } else { + callback_type = LogoCallbackReason::REVALIDATED; + } + break; + + case DOWNLOAD_OUTCOME_DOWNLOAD_FAILED: + // In the download failed, don't notify the callback at all, since the + // callback should continue to use the cached logo. + DCHECK(!encoded_logo); + DCHECK(!logo); + callback_type = LogoCallbackReason::FAILED; + break; + + case DOWNLOAD_OUTCOME_DECODING_FAILED: + DCHECK(encoded_logo); + DCHECK(!logo); + encoded_logo.reset(); + callback_type = LogoCallbackReason::FAILED; + break; + + case DOWNLOAD_OUTCOME_LOGO_REVALIDATED: + // In the server reported that the cached logo is still current, don't + // notify the callback at all, since the callback should continue to use + // the cached logo. + DCHECK(encoded_logo); + DCHECK(!logo); + callback_type = LogoCallbackReason::REVALIDATED; + break; + + case DOWNLOAD_OUTCOME_COUNT: + NOTREACHED(); + return; + } + + NotifyAndClear(&on_fresh_encoded_logo_, &on_fresh_decoded_logo_, + callback_type, encoded_logo.get(), logo.get()); + + switch (callback_type) { + case LogoCallbackReason::DETERMINED: + SetCachedLogo(std::move(encoded_logo)); + break; + + default: + break; + } + + ReturnToIdle(download_outcome); +} + +void LogoServiceImpl::OnURLLoadComplete(const network::SimpleURLLoader* source, + std::unique_ptr<std::string> body) { + DCHECK(!is_idle_); + std::unique_ptr<network::SimpleURLLoader> cleanup_loader(loader_.release()); + + if (source->NetError() != net::OK) { + OnFreshLogoAvailable({}, /*download_failed=*/true, false, false, + SkBitmap()); return; } - std::unique_ptr<LogoCache> logo_cache = std::move(logo_cache_for_test_); - if (!logo_cache) { - logo_cache = std::make_unique<LogoCache>(cache_directory_); + if (!source->ResponseInfo() || !source->ResponseInfo()->headers || + source->ResponseInfo()->headers->response_code() != net::HTTP_OK) { + OnFreshLogoAvailable({}, /*download_failed=*/true, false, false, + SkBitmap()); + return; } - base::Clock* clock = clock_for_test_; - if (!clock) { - clock = base::DefaultClock::GetInstance(); - } + UMA_HISTOGRAM_TIMES("NewTabPage.LogoDownloadTime", + base::TimeTicks::Now() - logo_download_start_time_); - logo_tracker_ = std::make_unique<LogoTracker>(url_loader_factory_, - std::move(image_decoder_), - std::move(logo_cache), clock); + std::unique_ptr<std::string> response = + body ? std::move(body) : std::make_unique<std::string>(); + base::Time response_time = clock_->Now(); + + bool from_http_cache = !source->ResponseInfo()->network_accessed; + + bool* parsing_failed = new bool(false); + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, + {base::MayBlock(), base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, + base::BindOnce(parse_logo_response_func_, std::move(response), + response_time, parsing_failed), + base::BindOnce(&LogoServiceImpl::OnFreshLogoParsed, + weak_ptr_factory_.GetWeakPtr(), + base::Owned(parsing_failed), from_http_cache)); } void LogoServiceImpl::SigninStatusChanged() { // Clear any cached logo, since it may be personalized (e.g. birthday Doodle). - InitializeLogoTrackerIfNecessary(); - logo_tracker_->ClearCachedLogo(); + if (!clock_) { + clock_ = base::DefaultClock::GetInstance(); + } + ClearCachedLogo(); } } // namespace search_provider_logos
diff --git a/components/search_provider_logos/logo_service_impl.h b/components/search_provider_logos/logo_service_impl.h index 16bf118..276d72f23 100644 --- a/components/search_provider_logos/logo_service_impl.h +++ b/components/search_provider_logos/logo_service_impl.h
@@ -5,10 +5,18 @@ #ifndef COMPONENTS_SEARCH_PROVIDER_LOGOS_ANDROID_LOGO_SERVICE_IMPL_H_ #define COMPONENTS_SEARCH_PROVIDER_LOGOS_ANDROID_LOGO_SERVICE_IMPL_H_ +#include <memory> +#include <string> +#include <vector> + #include "base/callback.h" #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/sequenced_task_runner.h" +#include "base/time/clock.h" +#include "base/time/time.h" #include "components/search_provider_logos/logo_common.h" #include "components/search_provider_logos/logo_service.h" @@ -24,13 +32,13 @@ } // namespace image_fetcher namespace network { +class SimpleURLLoader; class SharedURLLoaderFactory; } // namespace network namespace search_provider_logos { class LogoCache; -class LogoTracker; class LogoObserver; class LogoServiceImpl : public LogoService { @@ -48,9 +56,28 @@ // KeyedService implementation. void Shutdown() override; - // LogoService implementation. - void GetLogo(LogoCallbacks callbacks) override; + // Defines the server API for downloading and parsing the logo. This must be + // called at least once before calling GetLogo(). + // + // |logo_url| is the URL from which the logo will be downloaded. If |logo_url| + // is different than the current logo URL, any pending callbacks will be run + // with LogoCallbackReason::CANCELED. + // + // |parse_logo_response_func| is a callback that will be used to parse the + // server's response into a EncodedLogo object. |append_queryparams_func| is a + // callback that will return the URL from which to download the logo. + void SetServerAPI(const GURL& logo_url, + const ParseLogoResponse& parse_logo_response_func, + const AppendQueryparamsToLogoURL& append_queryparams_func); + + // Retrieves the current search provider's logo from the local cache and/or + // over the network, and registers the callbacks to be called when the cached + // and/or fresh logos are available. + // + // At least one callback must be non-null. All non-null callbacks will be + // invoked exactly once. void GetLogo(LogoObserver* observer) override; + void GetLogo(LogoCallbacks callbacks) override; // Overrides the cache used to store logos. void SetLogoCacheForTests(std::unique_ptr<LogoCache> cache); @@ -59,12 +86,70 @@ void SetClockForTests(base::Clock* clock); private: + // These values must stay in sync with the NewTabPageLogoDownloadOutcome enum + // in histograms.xml. And any addtion should be treated as append-only! + // Animated doodle is not covered by this enum. + enum LogoDownloadOutcome { + DOWNLOAD_OUTCOME_NEW_LOGO_SUCCESS, + DOWNLOAD_OUTCOME_NO_LOGO_TODAY, + DOWNLOAD_OUTCOME_DOWNLOAD_FAILED, + DOWNLOAD_OUTCOME_PARSING_FAILED, + DOWNLOAD_OUTCOME_DECODING_FAILED, + DOWNLOAD_OUTCOME_LOGO_REVALIDATED, + DOWNLOAD_OUTCOME_COUNT, + }; + + const int kDownloadOutcomeNotTracked = -1; + class SigninObserver; - void InitializeLogoTrackerIfNecessary(); - void SigninStatusChanged(); + // Clear any cached logo we might have. Useful on sign-out to get rid of + // (potentially) personalized data. + void ClearCachedLogo(); + + // Cancels the current asynchronous operation, if any, and resets all member + // variables that change as the logo is fetched. This method also records UMA + // histograms for for the given LogoDownloadOutcome. + void ReturnToIdle(int outcome); + + // Called when the cached logo has been read from the cache. |cached_logo| + // will be NULL if there wasn't a valid, up-to-date logo in the cache. + void OnCachedLogoRead(std::unique_ptr<EncodedLogo> cached_logo); + + // Called when the cached logo has been decoded into an SkBitmap. |image| will + // be NULL if decoding failed. + void OnCachedLogoAvailable(std::unique_ptr<EncodedLogo> encoded_logo, + const SkBitmap& image); + + // Stores |logo| in the cache. + void SetCachedLogo(std::unique_ptr<EncodedLogo> logo); + + // Updates the metadata for the logo already stored in the cache. + void SetCachedMetadata(const LogoMetadata& metadata); + + // Starts fetching the current logo over the network. + void FetchLogo(); + + // Called when the logo has been downloaded and parsed. |logo| will be NULL + // if the server's response was invalid. + void OnFreshLogoParsed(bool* parsing_failed, + bool from_http_cache, + std::unique_ptr<EncodedLogo> logo); + + // Called when the fresh logo has been decoded into an SkBitmap. |image| will + // be NULL if decoding failed. + void OnFreshLogoAvailable(std::unique_ptr<EncodedLogo> logo, + bool download_failed, + bool parsing_failed, + bool from_http_cache, + const SkBitmap& image); + + // Invoked by |loader|. + void OnURLLoadComplete(const network::SimpleURLLoader* source, + std::unique_ptr<std::string> body); + // Constructor arguments. const base::FilePath cache_directory_; TemplateURLService* const template_url_service_; @@ -74,19 +159,58 @@ // optimized for gray backgrounds or not. base::RepeatingCallback<bool()> want_gray_logo_getter_; - // logo_tracker_ takes ownership if/when it is initialized. std::unique_ptr<image_fetcher::ImageDecoder> image_decoder_; std::unique_ptr<SigninObserver> signin_observer_; - // For testing. - base::Clock* clock_for_test_ = nullptr; + // The URL from which the logo is fetched. + GURL logo_url_; - // For testing. logo_tracker_ takes ownership if/when it is initialized. - std::unique_ptr<LogoCache> logo_cache_for_test_; + // The function used to parse the logo response from the server. + ParseLogoResponse parse_logo_response_func_; - // Lazily initialized on first call to GetLogo(). - std::unique_ptr<search_provider_logos::LogoTracker> logo_tracker_; + // The function used to include the cached logo's fingerprint and call to + // action request in the logo URL. + AppendQueryparamsToLogoURL append_queryparams_func_; + + // False if an asynchronous task is currently running. + bool is_idle_; + + // The logo that's been read from the cache, or NULL if the cache is empty. + // Meaningful only if is_cached_logo_valid_ is true; NULL otherwise. + std::unique_ptr<Logo> cached_logo_; + std::unique_ptr<EncodedLogo> cached_encoded_logo_; + + // Whether the value of |cached_logo_| reflects the actual cached logo. + // This will be false if the logo hasn't been read from the cache yet. + // |cached_logo_| may be NULL even if |is_cached_logo_valid_| is true, if no + // logo is cached. + bool is_cached_logo_valid_; + + // The timestamp for the last time a logo was stated to be downloaded. + base::TimeTicks logo_download_start_time_; + + // The SimpleURLLoader currently fetching the logo. NULL when not loading. + std::unique_ptr<network::SimpleURLLoader> loader_; + + // Lists of callbacks to be invoked when logos are available. All should be + // empty when the state is IDLE. + std::vector<LogoCallback> on_cached_decoded_logo_; + std::vector<EncodedLogoCallback> on_cached_encoded_logo_; + std::vector<LogoCallback> on_fresh_decoded_logo_; + std::vector<EncodedLogoCallback> on_fresh_encoded_logo_; + + // The SequencedTaskRunner on which the cache lives. + scoped_refptr<base::SequencedTaskRunner> cache_task_runner_; + + // The cache used to persist the logo on disk. Used only on a background + // SequencedTaskRunner. + std::unique_ptr<LogoCache, base::OnTaskRunnerDeleter> logo_cache_; + + // Clock used to determine current time. Can be overridden in tests. + base::Clock* clock_ = nullptr; + + base::WeakPtrFactory<LogoServiceImpl> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(LogoServiceImpl); };
diff --git a/components/search_provider_logos/logo_service_impl_unittest.cc b/components/search_provider_logos/logo_service_impl_unittest.cc index 252a1124..6a2d5861 100644 --- a/components/search_provider_logos/logo_service_impl_unittest.cc +++ b/components/search_provider_logos/logo_service_impl_unittest.cc
@@ -64,8 +64,8 @@ using ::testing::Not; using ::testing::NotNull; using ::testing::Pointee; -using ::testing::StrictMock; using ::testing::Return; +using ::testing::StrictMock; using sync_preferences::TestingPrefServiceSyncable; @@ -285,7 +285,9 @@ : task_environment_(task_environment), signin_client_(&pref_service_), token_service_(&pref_service_), - cookie_service_(&token_service_, &signin_client_) { + cookie_service_(&token_service_, + &signin_client_, + &test_url_loader_factory_) { // GaiaCookieManagerService calls static methods of AccountTrackerService // which access prefs. AccountTrackerService::RegisterPrefs(pref_service_.registry()); @@ -312,6 +314,7 @@ TestingPrefServiceSyncable pref_service_; TestSigninClient signin_client_; FakeProfileOAuth2TokenService token_service_; + network::TestURLLoaderFactory test_url_loader_factory_; FakeGaiaCookieManagerService cookie_service_; };
diff --git a/components/search_provider_logos/logo_tracker.cc b/components/search_provider_logos/logo_tracker.cc deleted file mode 100644 index bb2f5bf..0000000 --- a/components/search_provider_logos/logo_tracker.cc +++ /dev/null
@@ -1,506 +0,0 @@ -// Copyright 2014 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 "components/search_provider_logos/logo_tracker.h" - -#include <algorithm> -#include <utility> - -#include "base/bind_helpers.h" -#include "base/metrics/histogram_macros.h" -#include "base/task/post_task.h" -#include "base/task_runner_util.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/clock.h" -#include "components/data_use_measurement/core/data_use_user_data.h" -#include "components/image_fetcher/core/image_decoder.h" -#include "net/http/http_response_headers.h" -#include "net/http/http_status_code.h" -#include "net/traffic_annotation/network_traffic_annotation.h" -#include "services/network/public/cpp/resource_request.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" -#include "services/network/public/cpp/simple_url_loader.h" -#include "ui/gfx/geometry/size.h" -#include "ui/gfx/image/image.h" - -namespace search_provider_logos { - -namespace { - -const int64_t kMaxDownloadBytes = 1024 * 1024; -const int kDecodeLogoTimeoutSeconds = 30; - -// Implements a callback for image_fetcher::ImageDecoder. If Run() is called on -// a callback returned by GetCallback() within 30 seconds, forwards the decoded -// image to the wrapped callback. If not, sends an empty image to the wrapped -// callback instead. Either way, deletes the object and prevents further calls. -// -// TODO(sfiera): find a more idiomatic way of setting a deadline on the -// callback. This is implemented as a self-deleting object in part because it -// needed to when it used to be a delegate and in part because I couldn't figure -// out a better way, now that it isn't. -class ImageDecodedHandlerWithTimeout { - public: - static base::Callback<void(const gfx::Image&)> Wrap( - const base::Callback<void(const SkBitmap&)>& image_decoded_callback) { - auto* handler = new ImageDecodedHandlerWithTimeout(image_decoded_callback); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::BindOnce(&ImageDecodedHandlerWithTimeout::OnImageDecoded, - handler->weak_ptr_factory_.GetWeakPtr(), gfx::Image()), - base::TimeDelta::FromSeconds(kDecodeLogoTimeoutSeconds)); - return base::Bind(&ImageDecodedHandlerWithTimeout::OnImageDecoded, - handler->weak_ptr_factory_.GetWeakPtr()); - } - - private: - explicit ImageDecodedHandlerWithTimeout( - const base::Callback<void(const SkBitmap&)>& image_decoded_callback) - : image_decoded_callback_(image_decoded_callback), - weak_ptr_factory_(this) {} - - void OnImageDecoded(const gfx::Image& decoded_image) { - image_decoded_callback_.Run(decoded_image.AsBitmap()); - delete this; - } - - base::Callback<void(const SkBitmap&)> image_decoded_callback_; - base::WeakPtrFactory<ImageDecodedHandlerWithTimeout> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(ImageDecodedHandlerWithTimeout); -}; - -// Returns whether the metadata for the cached logo indicates that the logo is -// OK to show, i.e. it's not expired or it's allowed to be shown temporarily -// after expiration. -bool IsLogoOkToShow(const LogoMetadata& metadata, base::Time now) { - base::TimeDelta offset = - base::TimeDelta::FromMilliseconds(kMaxTimeToLiveMS * 3 / 2); - base::Time distant_past = now - offset; - // Sanity check so logos aren't accidentally cached forever. - if (metadata.expiration_time < distant_past) { - return false; - } - return metadata.can_show_after_expiration || metadata.expiration_time >= now; -} - -// Reads the logo from the cache and returns it. Returns NULL if the cache is -// empty, corrupt, expired, or doesn't apply to the current logo URL. -std::unique_ptr<EncodedLogo> GetLogoFromCacheOnFileThread(LogoCache* logo_cache, - const GURL& logo_url, - base::Time now) { - const LogoMetadata* metadata = logo_cache->GetCachedLogoMetadata(); - if (!metadata) - return nullptr; - - if (metadata->source_url != logo_url || !IsLogoOkToShow(*metadata, now)) { - logo_cache->SetCachedLogo(nullptr); - return nullptr; - } - - return logo_cache->GetCachedLogo(); -} - -void NotifyAndClear(std::vector<EncodedLogoCallback>* encoded_callbacks, - std::vector<LogoCallback>* decoded_callbacks, - LogoCallbackReason type, - const EncodedLogo* encoded_logo, - const Logo* decoded_logo) { - auto opt_encoded_logo = - encoded_logo ? base::Optional<EncodedLogo>(*encoded_logo) : base::nullopt; - for (EncodedLogoCallback& callback : *encoded_callbacks) { - std::move(callback).Run(type, opt_encoded_logo); - } - encoded_callbacks->clear(); - - auto opt_decoded_logo = - decoded_logo ? base::Optional<Logo>(*decoded_logo) : base::nullopt; - for (LogoCallback& callback : *decoded_callbacks) { - std::move(callback).Run(type, opt_decoded_logo); - } - decoded_callbacks->clear(); -} - -} // namespace - -LogoTracker::LogoTracker( - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - std::unique_ptr<image_fetcher::ImageDecoder> image_decoder, - std::unique_ptr<LogoCache> logo_cache, - base::Clock* clock) - : is_idle_(true), - is_cached_logo_valid_(false), - image_decoder_(std::move(image_decoder)), - cache_task_runner_(base::CreateSequencedTaskRunnerWithTraits( - {base::MayBlock(), base::TaskPriority::USER_VISIBLE, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})), - logo_cache_(logo_cache.release(), - base::OnTaskRunnerDeleter(cache_task_runner_)), - clock_(clock), - url_loader_factory_(std::move(url_loader_factory)), - weak_ptr_factory_(this) {} - -LogoTracker::~LogoTracker() { - ReturnToIdle(kDownloadOutcomeNotTracked); -} - -void LogoTracker::SetServerAPI( - const GURL& logo_url, - const ParseLogoResponse& parse_logo_response_func, - const AppendQueryparamsToLogoURL& append_queryparams_func) { - if (logo_url == logo_url_) - return; - - ReturnToIdle(kDownloadOutcomeNotTracked); - - logo_url_ = logo_url; - parse_logo_response_func_ = parse_logo_response_func; - append_queryparams_func_ = append_queryparams_func; -} - -void LogoTracker::GetLogo(LogoCallbacks callbacks) { - DCHECK(!logo_url_.is_empty()); - DCHECK(callbacks.on_cached_decoded_logo_available || - callbacks.on_cached_encoded_logo_available || - callbacks.on_fresh_decoded_logo_available || - callbacks.on_fresh_encoded_logo_available); - - if (callbacks.on_cached_encoded_logo_available) { - on_cached_encoded_logo_.push_back( - std::move(callbacks.on_cached_encoded_logo_available)); - } - if (callbacks.on_cached_decoded_logo_available) { - on_cached_decoded_logo_.push_back( - std::move(callbacks.on_cached_decoded_logo_available)); - } - if (callbacks.on_fresh_encoded_logo_available) { - on_fresh_encoded_logo_.push_back( - std::move(callbacks.on_fresh_encoded_logo_available)); - } - if (callbacks.on_fresh_decoded_logo_available) { - on_fresh_decoded_logo_.push_back( - std::move(callbacks.on_fresh_decoded_logo_available)); - } - - if (is_idle_) { - is_idle_ = false; - base::PostTaskAndReplyWithResult( - cache_task_runner_.get(), FROM_HERE, - base::Bind(&GetLogoFromCacheOnFileThread, - base::Unretained(logo_cache_.get()), logo_url_, - clock_->Now()), - base::Bind(&LogoTracker::OnCachedLogoRead, - weak_ptr_factory_.GetWeakPtr())); - } else if (is_cached_logo_valid_) { - NotifyAndClear(&on_cached_encoded_logo_, &on_cached_decoded_logo_, - LogoCallbackReason::DETERMINED, cached_encoded_logo_.get(), - cached_logo_.get()); - } -} - -void LogoTracker::ClearCachedLogo() { - // First cancel any fetch that might be ongoing. - ReturnToIdle(kDownloadOutcomeNotTracked); - // Then clear any cached logo. - SetCachedLogo(nullptr); -} - -void LogoTracker::ReturnToIdle(int outcome) { - if (outcome != kDownloadOutcomeNotTracked) { - UMA_HISTOGRAM_ENUMERATION("NewTabPage.LogoDownloadOutcome", - static_cast<LogoDownloadOutcome>(outcome), - DOWNLOAD_OUTCOME_COUNT); - } - // Cancel the current asynchronous operation, if any. - loader_.reset(); - weak_ptr_factory_.InvalidateWeakPtrs(); - - // Reset state. - is_idle_ = true; - cached_logo_.reset(); - cached_encoded_logo_.reset(); - is_cached_logo_valid_ = false; - - // Clear callbacks. - NotifyAndClear(&on_cached_encoded_logo_, &on_cached_decoded_logo_, - LogoCallbackReason::CANCELED, nullptr, nullptr); - NotifyAndClear(&on_fresh_encoded_logo_, &on_fresh_decoded_logo_, - LogoCallbackReason::CANCELED, nullptr, nullptr); -} - -void LogoTracker::OnCachedLogoRead(std::unique_ptr<EncodedLogo> cached_logo) { - DCHECK(!is_idle_); - - if (cached_logo) { - // Store the value of logo->encoded_image for use below. This ensures that - // logo->encoded_image is evaulated before base::Passed(&logo), which sets - // logo to NULL. - scoped_refptr<base::RefCountedString> encoded_image = - cached_logo->encoded_image; - image_decoder_->DecodeImage( - encoded_image->data(), gfx::Size(), // No particular size desired. - ImageDecodedHandlerWithTimeout::Wrap(base::Bind( - &LogoTracker::OnCachedLogoAvailable, weak_ptr_factory_.GetWeakPtr(), - base::Passed(&cached_logo)))); - } else { - OnCachedLogoAvailable({}, SkBitmap()); - } -} - -void LogoTracker::OnCachedLogoAvailable( - std::unique_ptr<EncodedLogo> encoded_logo, - const SkBitmap& image) { - DCHECK(!is_idle_); - - if (!image.isNull()) { - cached_logo_.reset(new Logo()); - cached_logo_->metadata = encoded_logo->metadata; - cached_logo_->image = image; - cached_encoded_logo_ = std::move(encoded_logo); - } - is_cached_logo_valid_ = true; - NotifyAndClear(&on_cached_encoded_logo_, &on_cached_decoded_logo_, - LogoCallbackReason::DETERMINED, cached_encoded_logo_.get(), - cached_logo_.get()); - FetchLogo(); -} - -void LogoTracker::SetCachedLogo(std::unique_ptr<EncodedLogo> logo) { - cache_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&LogoCache::SetCachedLogo, - base::Unretained(logo_cache_.get()), - base::Owned(logo.release()))); -} - -void LogoTracker::SetCachedMetadata(const LogoMetadata& metadata) { - cache_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&LogoCache::UpdateCachedLogoMetadata, - base::Unretained(logo_cache_.get()), metadata)); -} - -void LogoTracker::FetchLogo() { - DCHECK(!loader_); - DCHECK(!is_idle_); - - std::string fingerprint; - if (cached_logo_ && !cached_logo_->metadata.fingerprint.empty() && - cached_logo_->metadata.expiration_time >= clock_->Now()) { - fingerprint = cached_logo_->metadata.fingerprint; - } - GURL url = append_queryparams_func_.Run(logo_url_, fingerprint); - - net::NetworkTrafficAnnotationTag traffic_annotation = - net::DefineNetworkTrafficAnnotation("logo_tracker", R"( - semantics { - sender: "Logo Tracker" - description: - "Provides the logo image (aka Doodle) if Google is your configured " - "search provider." - trigger: "Displaying the new tab page on iOS or Android." - data: - "Logo ID, and the user's Google cookies to show for example " - "birthday doodles at appropriate times." - destination: OTHER - } - policy { - cookies_allowed: YES - cookies_store: "user" - setting: - "Choosing a non-Google search engine in Chromium settings under " - "'Search Engine' will disable this feature." - policy_exception_justification: - "Not implemented, considered not useful as it does not upload any" - "data and just downloads a logo image." - })"); - auto request = std::make_unique<network::ResourceRequest>(); - request->url = url; - // TODO(https://crbug.com/808498) re-add data use measurement once - // SimpleURLLoader supports it: - // data_use_measurement::DataUseUserData::SEARCH_PROVIDER_LOGOS - loader_ = - network::SimpleURLLoader::Create(std::move(request), traffic_annotation); - loader_->DownloadToString( - url_loader_factory_.get(), - base::BindOnce(&LogoTracker::OnURLLoadComplete, base::Unretained(this), - loader_.get()), - kMaxDownloadBytes); - logo_download_start_time_ = base::TimeTicks::Now(); -} - -void LogoTracker::OnFreshLogoParsed(bool* parsing_failed, - bool from_http_cache, - std::unique_ptr<EncodedLogo> logo) { - DCHECK(!is_idle_); - - if (logo) - logo->metadata.source_url = logo_url_; - - if (!logo || !logo->encoded_image) { - OnFreshLogoAvailable(std::move(logo), /*download_failed=*/false, - *parsing_failed, from_http_cache, SkBitmap()); - } else { - // Store the value of logo->encoded_image for use below. This ensures that - // logo->encoded_image is evaulated before base::Passed(&logo), which sets - // logo to NULL. - scoped_refptr<base::RefCountedString> encoded_image = logo->encoded_image; - image_decoder_->DecodeImage( - encoded_image->data(), gfx::Size(), // No particular size desired. - ImageDecodedHandlerWithTimeout::Wrap(base::Bind( - &LogoTracker::OnFreshLogoAvailable, weak_ptr_factory_.GetWeakPtr(), - base::Passed(&logo), /*download_failed=*/false, *parsing_failed, - from_http_cache))); - } -} - -void LogoTracker::OnFreshLogoAvailable( - std::unique_ptr<EncodedLogo> encoded_logo, - bool download_failed, - bool parsing_failed, - bool from_http_cache, - const SkBitmap& image) { - DCHECK(!is_idle_); - - LogoDownloadOutcome download_outcome = DOWNLOAD_OUTCOME_COUNT; - std::unique_ptr<Logo> logo; - - if (download_failed) { - download_outcome = DOWNLOAD_OUTCOME_DOWNLOAD_FAILED; - } else if (encoded_logo && !encoded_logo->encoded_image && cached_logo_ && - !encoded_logo->metadata.fingerprint.empty() && - encoded_logo->metadata.fingerprint == - cached_logo_->metadata.fingerprint) { - // The cached logo was revalidated, i.e. its fingerprint was verified. - // mime_type isn't sent when revalidating, so copy it from the cached logo. - encoded_logo->metadata.mime_type = cached_logo_->metadata.mime_type; - SetCachedMetadata(encoded_logo->metadata); - download_outcome = DOWNLOAD_OUTCOME_LOGO_REVALIDATED; - } else if (encoded_logo && image.isNull()) { - // Image decoding failed. Do nothing. - download_outcome = DOWNLOAD_OUTCOME_DECODING_FAILED; - } else { - // Check if the server returned a valid, non-empty response. - if (encoded_logo) { - UMA_HISTOGRAM_BOOLEAN("NewTabPage.LogoImageDownloaded", from_http_cache); - - DCHECK(!image.isNull()); - logo.reset(new Logo()); - logo->metadata = encoded_logo->metadata; - logo->image = image; - } - - if (logo) { - download_outcome = DOWNLOAD_OUTCOME_NEW_LOGO_SUCCESS; - } else { - if (parsing_failed) - download_outcome = DOWNLOAD_OUTCOME_PARSING_FAILED; - else - download_outcome = DOWNLOAD_OUTCOME_NO_LOGO_TODAY; - } - } - - LogoCallbackReason callback_type = LogoCallbackReason::FAILED; - switch (download_outcome) { - case DOWNLOAD_OUTCOME_NEW_LOGO_SUCCESS: - DCHECK(encoded_logo); - DCHECK(logo); - callback_type = LogoCallbackReason::DETERMINED; - break; - - case DOWNLOAD_OUTCOME_PARSING_FAILED: - case DOWNLOAD_OUTCOME_NO_LOGO_TODAY: - // Clear the cached logo if it was non-null. Otherwise, report this as a - // revalidation of "no logo". - DCHECK(!encoded_logo); - DCHECK(!logo); - if (cached_logo_) { - callback_type = LogoCallbackReason::DETERMINED; - } else { - callback_type = LogoCallbackReason::REVALIDATED; - } - break; - - case DOWNLOAD_OUTCOME_DOWNLOAD_FAILED: - // In the download failed, don't notify the callback at all, since the - // callback should continue to use the cached logo. - DCHECK(!encoded_logo); - DCHECK(!logo); - callback_type = LogoCallbackReason::FAILED; - break; - - case DOWNLOAD_OUTCOME_DECODING_FAILED: - DCHECK(encoded_logo); - DCHECK(!logo); - encoded_logo.reset(); - callback_type = LogoCallbackReason::FAILED; - break; - - case DOWNLOAD_OUTCOME_LOGO_REVALIDATED: - // In the server reported that the cached logo is still current, don't - // notify the callback at all, since the callback should continue to use - // the cached logo. - DCHECK(encoded_logo); - DCHECK(!logo); - callback_type = LogoCallbackReason::REVALIDATED; - break; - - case DOWNLOAD_OUTCOME_COUNT: - NOTREACHED(); - return; - } - - NotifyAndClear(&on_fresh_encoded_logo_, &on_fresh_decoded_logo_, - callback_type, encoded_logo.get(), logo.get()); - - switch (callback_type) { - case LogoCallbackReason::DETERMINED: - SetCachedLogo(std::move(encoded_logo)); - break; - - default: - break; - } - - ReturnToIdle(download_outcome); -} - -void LogoTracker::OnURLLoadComplete(const network::SimpleURLLoader* source, - std::unique_ptr<std::string> body) { - DCHECK(!is_idle_); - std::unique_ptr<network::SimpleURLLoader> cleanup_loader(loader_.release()); - - if (source->NetError() != net::OK) { - OnFreshLogoAvailable({}, /*download_failed=*/true, false, false, - SkBitmap()); - return; - } - - if (!source->ResponseInfo() || !source->ResponseInfo()->headers || - source->ResponseInfo()->headers->response_code() != net::HTTP_OK) { - OnFreshLogoAvailable({}, /*download_failed=*/true, false, false, - SkBitmap()); - return; - } - - UMA_HISTOGRAM_TIMES("NewTabPage.LogoDownloadTime", - base::TimeTicks::Now() - logo_download_start_time_); - - std::unique_ptr<std::string> response = - body ? std::move(body) : std::make_unique<std::string>(); - base::Time response_time = clock_->Now(); - - bool from_http_cache = !source->ResponseInfo()->network_accessed; - - bool* parsing_failed = new bool(false); - base::PostTaskWithTraitsAndReplyWithResult( - FROM_HERE, - {base::MayBlock(), base::TaskPriority::USER_VISIBLE, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, - base::BindOnce(parse_logo_response_func_, std::move(response), - response_time, parsing_failed), - base::BindOnce(&LogoTracker::OnFreshLogoParsed, - weak_ptr_factory_.GetWeakPtr(), - base::Owned(parsing_failed), from_http_cache)); -} - -} // namespace search_provider_logos
diff --git a/components/search_provider_logos/logo_tracker.h b/components/search_provider_logos/logo_tracker.h index 762aa8db..af057c8 100644 --- a/components/search_provider_logos/logo_tracker.h +++ b/components/search_provider_logos/logo_tracker.h
@@ -5,32 +5,7 @@ #ifndef COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_TRACKER_H_ #define COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_TRACKER_H_ -#include <stdint.h> - -#include <memory> -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/files/file_path.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/optional.h" -#include "base/sequenced_task_runner.h" -#include "base/time/clock.h" -#include "base/time/time.h" -#include "components/search_provider_logos/logo_cache.h" #include "components/search_provider_logos/logo_common.h" -#include "url/gurl.h" - -namespace image_fetcher { -class ImageDecoder; -} - -namespace network { -class SimpleURLLoader; -class SharedURLLoaderFactory; -} namespace search_provider_logos { @@ -55,173 +30,6 @@ virtual void OnObserverRemoved() = 0; }; -// This class provides the logo for a search provider. Logos are downloaded from -// the search provider's logo URL and cached on disk. -// -// Call SetServerAPI() at least once to specify how to get the logo from the -// server. Then call GetLogo() to trigger retrieval of the logo and receive -// updates once the cached and/or fresh logos are available. -class LogoTracker { - public: - // Constructs a LogoTracker with the given LogoDelegate. Takes ownership of - // |delegate|, which will be deleted at the same time as the LogoTracker. - // - // |cached_logo_directory| is the directory in which the cached logo and its - // metadata should be saved. - // - // |background_task_runner| is the TaskRunner that should be used to for - // CPU-intensive background operations. - // - // |url_loader_factory| is the SharedURLLoaderFactory used to download - // the logo. - explicit LogoTracker( - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - std::unique_ptr<image_fetcher::ImageDecoder> image_decoder, - std::unique_ptr<LogoCache> logo_cache, - base::Clock* clock); - - ~LogoTracker(); - - // Defines the server API for downloading and parsing the logo. This must be - // called at least once before calling GetLogo(). - // - // |logo_url| is the URL from which the logo will be downloaded. If |logo_url| - // is different than the current logo URL, any pending callbacks will be run - // with LogoCallbackReason::CANCELED. - // - // |parse_logo_response_func| is a callback that will be used to parse the - // server's response into a EncodedLogo object. |append_queryparams_func| is a - // callback that will return the URL from which to download the logo. - void SetServerAPI(const GURL& logo_url, - const ParseLogoResponse& parse_logo_response_func, - const AppendQueryparamsToLogoURL& append_queryparams_func); - - // Retrieves the current search provider's logo from the local cache and/or - // over the network, and registers the callbacks to be called when the cached - // and/or fresh logos are available. - // - // At least one callback must be non-null. All non-null callbacks will be - // invoked exactly once. - void GetLogo(LogoCallbacks callbacks); - - // Clear any cached logo we might have. Useful on sign-out to get rid of - // (potentially) personalized data. - void ClearCachedLogo(); - - private: - // These values must stay in sync with the NewTabPageLogoDownloadOutcome enum - // in histograms.xml. And any addtion should be treated as append-only! - // Animated doodle is not covered by this enum. - enum LogoDownloadOutcome { - DOWNLOAD_OUTCOME_NEW_LOGO_SUCCESS, - DOWNLOAD_OUTCOME_NO_LOGO_TODAY, - DOWNLOAD_OUTCOME_DOWNLOAD_FAILED, - DOWNLOAD_OUTCOME_PARSING_FAILED, - DOWNLOAD_OUTCOME_DECODING_FAILED, - DOWNLOAD_OUTCOME_LOGO_REVALIDATED, - DOWNLOAD_OUTCOME_COUNT, - }; - - const int kDownloadOutcomeNotTracked = -1; - - // Cancels the current asynchronous operation, if any, and resets all member - // variables that change as the logo is fetched. This method also records UMA - // histograms for for the given LogoDownloadOutcome. - void ReturnToIdle(int outcome); - - // Called when the cached logo has been read from the cache. |cached_logo| - // will be NULL if there wasn't a valid, up-to-date logo in the cache. - void OnCachedLogoRead(std::unique_ptr<EncodedLogo> cached_logo); - - // Called when the cached logo has been decoded into an SkBitmap. |image| will - // be NULL if decoding failed. - void OnCachedLogoAvailable(std::unique_ptr<EncodedLogo> encoded_logo, - const SkBitmap& image); - - // Stores |logo| in the cache. - void SetCachedLogo(std::unique_ptr<EncodedLogo> logo); - - // Updates the metadata for the logo already stored in the cache. - void SetCachedMetadata(const LogoMetadata& metadata); - - // Starts fetching the current logo over the network. - void FetchLogo(); - - // Called when the logo has been downloaded and parsed. |logo| will be NULL - // if the server's response was invalid. - void OnFreshLogoParsed(bool* parsing_failed, - bool from_http_cache, - std::unique_ptr<EncodedLogo> logo); - - // Called when the fresh logo has been decoded into an SkBitmap. |image| will - // be NULL if decoding failed. - void OnFreshLogoAvailable(std::unique_ptr<EncodedLogo> logo, - bool download_failed, - bool parsing_failed, - bool from_http_cache, - const SkBitmap& image); - - // Invoked by |loader|. - void OnURLLoadComplete(const network::SimpleURLLoader* source, - std::unique_ptr<std::string> body); - - // The URL from which the logo is fetched. - GURL logo_url_; - - // The function used to parse the logo response from the server. - ParseLogoResponse parse_logo_response_func_; - - // The function used to include the cached logo's fingerprint and call to - // action request in the logo URL. - AppendQueryparamsToLogoURL append_queryparams_func_; - - // False if an asynchronous task is currently running. - bool is_idle_; - - // The logo that's been read from the cache, or NULL if the cache is empty. - // Meaningful only if is_cached_logo_valid_ is true; NULL otherwise. - std::unique_ptr<Logo> cached_logo_; - std::unique_ptr<EncodedLogo> cached_encoded_logo_; - - // Whether the value of |cached_logo_| reflects the actual cached logo. - // This will be false if the logo hasn't been read from the cache yet. - // |cached_logo_| may be NULL even if |is_cached_logo_valid_| is true, if no - // logo is cached. - bool is_cached_logo_valid_; - - // The timestamp for the last time a logo is stated to be downloaded. - base::TimeTicks logo_download_start_time_; - - // The SimpleURLLoader currently fetching the logo. NULL when not loading. - std::unique_ptr<network::SimpleURLLoader> loader_; - - // Lists of callbacks to be invoked when logos are available. All should be - // empty when the state is IDLE. - std::vector<LogoCallback> on_cached_decoded_logo_; - std::vector<EncodedLogoCallback> on_cached_encoded_logo_; - std::vector<LogoCallback> on_fresh_decoded_logo_; - std::vector<EncodedLogoCallback> on_fresh_encoded_logo_; - - const std::unique_ptr<image_fetcher::ImageDecoder> image_decoder_; - - // The SequencedTaskRunner on which the cache lives. - scoped_refptr<base::SequencedTaskRunner> cache_task_runner_; - - // The cache used to persist the logo on disk. Used only on a background - // SequencedTaskRunner. - std::unique_ptr<LogoCache, base::OnTaskRunnerDeleter> logo_cache_; - - // Clock used to determine current time. Can be overridden in tests. - base::Clock* clock_; - - // Used for network requests. - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; - - base::WeakPtrFactory<LogoTracker> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(LogoTracker); -}; - } // namespace search_provider_logos #endif // COMPONENTS_SEARCH_PROVIDER_LOGOS_LOGO_TRACKER_H_
diff --git a/components/signin/core/browser/about_signin_internals.cc b/components/signin/core/browser/about_signin_internals.cc index 2139af7..2f5a530 100644 --- a/components/signin/core/browser/about_signin_internals.cc +++ b/components/signin/core/browser/about_signin_internals.cc
@@ -25,7 +25,6 @@ #include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/signin/core/browser/signin_client.h" #include "components/signin/core/browser/signin_internals_util.h" -#include "components/signin/core/browser/signin_manager.h" #include "components/signin/core/browser/signin_switches.h" #include "google_apis/gaia/oauth2_token_service_delegate.h" #include "net/base/backoff_entry.h" @@ -173,8 +172,6 @@ return "None"; case signin::AccountConsistencyMethod::kMirror: return "Mirror"; - case signin::AccountConsistencyMethod::kDiceFixAuthErrors: - return "DICE fixing auth errors"; case signin::AccountConsistencyMethod::kDiceMigration: return "DICE migration"; case signin::AccountConsistencyMethod::kDice: @@ -190,14 +187,12 @@ ProfileOAuth2TokenService* token_service, AccountTrackerService* account_tracker, identity::IdentityManager* identity_manager, - SigninManagerBase* signin_manager, SigninErrorController* signin_error_controller, GaiaCookieManagerService* cookie_manager_service, signin::AccountConsistencyMethod account_consistency) : token_service_(token_service), account_tracker_(account_tracker), identity_manager_(identity_manager), - signin_manager_(signin_manager), client_(nullptr), signin_error_controller_(signin_error_controller), cookie_manager_service_(cookie_manager_service), @@ -313,7 +308,6 @@ signin_error_controller_->AddObserver(this); identity_manager_->AddObserver(this); identity_manager_->AddDiagnosticsObserver(this); - signin_manager_->AddSigninDiagnosticsObserver(this); token_service_->AddObserver(this); token_service_->AddDiagnosticsObserver(this); cookie_manager_service_->AddObserver(this); @@ -323,7 +317,6 @@ signin_error_controller_->RemoveObserver(this); identity_manager_->RemoveObserver(this); identity_manager_->RemoveDiagnosticsObserver(this); - signin_manager_->RemoveSigninDiagnosticsObserver(this); token_service_->RemoveObserver(this); token_service_->RemoveDiagnosticsObserver(this); cookie_manager_service_->RemoveObserver(this);
diff --git a/components/signin/core/browser/about_signin_internals.h b/components/signin/core/browser/about_signin_internals.h index 23aa4fd..0b43ff90 100644 --- a/components/signin/core/browser/about_signin_internals.h +++ b/components/signin/core/browser/about_signin_internals.h
@@ -18,7 +18,6 @@ #include "components/signin/core/browser/signin_client.h" #include "components/signin/core/browser/signin_error_controller.h" #include "components/signin/core/browser/signin_internals_util.h" -#include "components/signin/core/browser/signin_manager.h" #include "google_apis/gaia/oauth2_token_service.h" #include "services/identity/public/cpp/identity_manager.h" @@ -39,7 +38,6 @@ // to propagate to about:signin-internals via SigninInternalsUI. class AboutSigninInternals : public KeyedService, - public signin_internals_util::SigninDiagnosticsObserver, public OAuth2TokenService::Observer, public OAuth2TokenService::DiagnosticsObserver, public GaiaCookieManagerService::Observer, @@ -60,7 +58,6 @@ AboutSigninInternals(ProfileOAuth2TokenService* token_service, AccountTrackerService* account_tracker, identity::IdentityManager* identity_manager, - SigninManagerBase* signin_manager, SigninErrorController* signin_error_controller, GaiaCookieManagerService* cookie_manager_service, signin::AccountConsistencyMethod account_consistency); @@ -196,16 +193,15 @@ signin::AccountConsistencyMethod account_consistency); }; - // SigninManager::SigninDiagnosticsObserver implementation. - void NotifySigninValueChanged( - const signin_internals_util::TimedSigninStatusField& field, - const std::string& value) override; - // IdentityMager::DiagnosticsObserver implementations. void OnAccessTokenRequested(const std::string& account_id, const std::string& consumer_id, const identity::ScopeSet& scopes) override; + void NotifySigninValueChanged( + const signin_internals_util::TimedSigninStatusField& field, + const std::string& value) override; + // OAuth2TokenService::DiagnosticsObserver implementations. void OnFetchAccessTokenComplete(const std::string& account_id, const std::string& consumer_id, @@ -246,9 +242,6 @@ // Weak pointer to the identity manager. identity::IdentityManager* identity_manager_; - // Weak pointer to the signin manager. - SigninManagerBase* signin_manager_; - // Weak pointer to the client. SigninClient* client_;
diff --git a/components/signin/core/browser/account_consistency_method.h b/components/signin/core/browser/account_consistency_method.h index f1d1b38..bee4dc3 100644 --- a/components/signin/core/browser/account_consistency_method.h +++ b/components/signin/core/browser/account_consistency_method.h
@@ -21,9 +21,6 @@ // Account management UI in the avatar bubble. kMirror, - // No account consistency, but Dice fixes authentication errors. - kDiceFixAuthErrors, - // Account management UI on Gaia webpages is enabled once the accounts become // consistent. kDiceMigration,
diff --git a/components/signin/core/browser/account_investigator_unittest.cc b/components/signin/core/browser/account_investigator_unittest.cc index b72205b0..10ad5406 100644 --- a/components/signin/core/browser/account_investigator_unittest.cc +++ b/components/signin/core/browser/account_investigator_unittest.cc
@@ -8,9 +8,9 @@ #include <string> #include <vector> -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_task_environment.h" #include "base/timer/timer.h" #include "components/prefs/pref_registry_simple.h" #include "components/signin/core/browser/account_tracker_service.h" @@ -44,7 +44,9 @@ &token_service_, &account_tracker_service_, nullptr), - gaia_cookie_manager_service_(&token_service_, &signin_client_), + gaia_cookie_manager_service_(&token_service_, + &signin_client_, + &test_url_loader_factory_), identity_test_env_(&account_tracker_service_, &token_service_, &signin_manager_, @@ -85,8 +87,7 @@ const AccountInfo& info, const std::vector<ListedAccount>& signed_in_accounts, const std::vector<ListedAccount>& signed_out_accounts) { - return AccountInvestigator::DiscernRelation(info, - signed_in_accounts, + return AccountInvestigator::DiscernRelation(info, signed_in_accounts, signed_out_accounts); } void SharedReport(const std::vector<gaia::ListedAccount>& signed_in_accounts, @@ -110,8 +111,7 @@ const AccountRelation expected) { HistogramTester histogram_tester; investigator_.SignedInAccountRelationReport(signed_in_accounts, - signed_out_accounts, - type); + signed_out_accounts, type); ExpectRelationReport(type, histogram_tester, expected); } @@ -162,12 +162,13 @@ private: // Timer needs a message loop. - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment task_environment_; sync_preferences::TestingPrefServiceSyncable prefs_; AccountTrackerService account_tracker_service_; TestSigninClient signin_client_; FakeProfileOAuth2TokenService token_service_; FakeSigninManager signin_manager_; + network::TestURLLoaderFactory test_url_loader_factory_; FakeGaiaCookieManagerService gaia_cookie_manager_service_; identity::IdentityTestEnvironment identity_test_env_; AccountInvestigator investigator_; @@ -330,7 +331,7 @@ // Simulate a sign out of the content area. const HistogramTester histogram_tester2; investigator()->OnGaiaAccountsInCookieUpdated( - no_accounts, just_one, GoogleServiceAuthError::AuthErrorNone()); + no_accounts, just_one, GoogleServiceAuthError::AuthErrorNone()); const AccountRelation expected_relation = AccountRelation::NO_SIGNED_IN_SINGLE_SIGNED_OUT_MATCH; ExpectSharedReportHistograms(ReportingType::ON_CHANGE, histogram_tester2,
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc index b4128da..018cad1 100644 --- a/components/signin/core/browser/account_reconcilor_unittest.cc +++ b/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -10,12 +10,12 @@ #include <utility> #include "base/macros.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/scoped_observer.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" +#include "base/test/scoped_task_environment.h" #include "base/time/time.h" #include "base/timer/mock_timer.h" #include "build/build_config.h" @@ -40,6 +40,8 @@ #include "google_apis/gaia/google_service_auth_error.h" #include "net/url_request/test_url_fetcher_factory.h" #include "services/identity/public/cpp/identity_test_environment.h" +#include "services/identity/public/cpp/identity_test_utils.h" +#include "services/identity/public/cpp/primary_account_mutator.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -167,7 +169,6 @@ return std::make_unique<signin::MirrorAccountReconcilorDelegate>( identity_manager); case signin::AccountConsistencyMethod::kDisabled: - case signin::AccountConsistencyMethod::kDiceFixAuthErrors: return std::make_unique<signin::AccountReconcilorDelegate>(); case signin::AccountConsistencyMethod::kDiceMigration: case signin::AccountConsistencyMethod::kDice: @@ -249,7 +250,9 @@ AccountReconcilorTest(); ~AccountReconcilorTest() override; - FakeSigninManagerForTesting* signin_manager() { return &signin_manager_; } + identity::IdentityTestEnvironment* identity_test_env() { + return &identity_test_env_; + } FakeProfileOAuth2TokenService* token_service() { return &token_service_; } DiceTestSigninClient* test_signin_client() { return &test_signin_client_; } AccountTrackerService* account_tracker() { return &account_tracker_; } @@ -262,8 +265,7 @@ MockAccountReconcilor* GetMockReconcilor( std::unique_ptr<signin::AccountReconcilorDelegate> delegate); - std::string ConnectProfileToAccount(const std::string& gaia_id, - const std::string& username); + AccountInfo ConnectProfileToAccount(const std::string& email); std::string PickAccountIdForAccount(const std::string& gaia_id, const std::string& username); @@ -290,7 +292,7 @@ void DeleteReconcilor() { mock_reconcilor_.reset(); } private: - base::MessageLoop loop; + base::test::ScopedTaskEnvironment task_environment_; signin::AccountConsistencyMethod account_consistency_; sync_preferences::TestingPrefServiceSyncable pref_service_; DiceTestSigninClient test_signin_client_; @@ -405,16 +407,11 @@ token_service_.Shutdown(); } -std::string AccountReconcilorTest::ConnectProfileToAccount( - const std::string& gaia_id, - const std::string& username) { - const std::string account_id = SeedAccountInfo(gaia_id, username); -#if !defined(OS_CHROMEOS) - signin_manager()->set_password("password"); -#endif - signin_manager()->SetAuthenticatedAccountInfo(gaia_id, username); - token_service()->UpdateCredentials(account_id, "refresh_token"); - return account_id; +AccountInfo AccountReconcilorTest::ConnectProfileToAccount( + const std::string& email) { + AccountInfo account_info = + identity_test_env()->MakePrimaryAccountAvailable(email); + return account_info; } std::string AccountReconcilorTest::PickAccountIdForAccount( @@ -522,9 +519,12 @@ }; AccountReconcilorTestTable() { - accounts_['A'] = {"a@gmail.com", "A"}; - accounts_['B'] = {"b@gmail.com", "B"}; - accounts_['C'] = {"c@gmail.com", "C"}; + accounts_['A'] = {"a@gmail.com", + identity::GetTestGaiaIdForEmail("a@gmail.com")}; + accounts_['B'] = {"b@gmail.com", + identity::GetTestGaiaIdForEmail("b@gmail.com")}; + accounts_['C'] = {"c@gmail.com", + identity::GetTestGaiaIdForEmail("c@gmail.com")}; } // Build Tokens from string. @@ -569,21 +569,26 @@ // Checks that the tokens in the TokenService match the tokens. void VerifyCurrentTokens(const std::vector<Token>& tokens) { - EXPECT_EQ(token_service()->GetAccounts().size(), tokens.size()); + auto* identity_manager = identity_test_env()->identity_manager(); + EXPECT_EQ(identity_manager->GetAccountsWithRefreshTokens().size(), + tokens.size()); + bool authenticated_account_found = false; for (const Token& token : tokens) { std::string account_id = PickAccountIdForAccount(token.gaia_id, token.email); - EXPECT_TRUE(token_service()->RefreshTokenIsAvailable(account_id)); - EXPECT_EQ(token.has_error, - token_service()->RefreshTokenHasError(account_id)); + EXPECT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id)); + EXPECT_EQ( + token.has_error, + identity_manager->HasAccountWithRefreshTokenInPersistentErrorState( + account_id)); if (token.is_authenticated) { - EXPECT_EQ(account_id, signin_manager()->GetAuthenticatedAccountId()); + EXPECT_EQ(account_id, identity_manager->GetPrimaryAccountId()); authenticated_account_found = true; } } if (!authenticated_account_found) - EXPECT_EQ("", signin_manager()->GetAuthenticatedAccountId()); + EXPECT_EQ("", identity_manager->GetPrimaryAccountId()); } // Checks that reconcile is idempotent. @@ -623,7 +628,19 @@ std::vector<FakeGaiaCookieManagerService::CookieParams> cookie_params; for (const auto& cookie : cookies) { std::string gaia_id = cookie.gaia_id; - cookie_params.push_back({accounts_[gaia_id[0]].email, gaia_id, + + // Figure the account token of this specific account id, + // ie 'A', 'B', or 'C'. + char account_key = '\0'; + for (const auto& account : accounts_) { + if (account.second.gaia_id == gaia_id) { + account_key = account.first; + break; + } + } + ASSERT_NE(account_key, '\0'); + + cookie_params.push_back({accounts_[account_key].email, gaia_id, cookie.is_valid, false /* signed_out */, true /* verified */}); } @@ -631,6 +648,10 @@ cookie_manager_service()->set_list_accounts_stale_for_testing(true); } + std::string GaiaIdForAccountKey(char account_key) { + return accounts_[account_key].gaia_id; + } + std::map<char, Account> accounts_; }; @@ -645,14 +666,12 @@ ASSERT_TRUE(reconcilor); ASSERT_FALSE(reconcilor->IsRegisteredWithTokenService()); - account_tracker()->SeedAccountInfo("12345", "user@gmail.com"); - signin_manager()->SignIn("12345", "user@gmail.com", "password"); + identity_test_env()->MakePrimaryAccountAvailable("user@gmail.com"); ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService()); EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()); - signin_manager()->SignOut(signin_metrics::SIGNOUT_TEST, - signin_metrics::SignoutDelete::IGNORE_METRIC); + identity_test_env()->ClearPrimaryAccount(); ASSERT_FALSE(reconcilor->IsRegisteredWithTokenService()); } @@ -662,21 +681,25 @@ // causes the try_bots to time out. TEST_P(AccountReconcilorMirrorEndpointParamTest, Reauth) { const std::string email = "user@gmail.com"; - const std::string account_id = ConnectProfileToAccount("12345", email); + AccountInfo account_info = ConnectProfileToAccount(email); AccountReconcilor* reconcilor = GetMockReconcilor(); ASSERT_TRUE(reconcilor); ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService()); // Simulate reauth. The state of the reconcilor should not change. - signin_manager()->OnExternalSigninCompleted(email); + auto* account_mutator = + identity_test_env()->identity_manager()->GetPrimaryAccountMutator(); + DCHECK(account_mutator); + account_mutator->SetPrimaryAccount(account_info.account_id); + ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService()); } #endif // !defined(OS_CHROMEOS) TEST_P(AccountReconcilorMirrorEndpointParamTest, ProfileAlreadyConnected) { - ConnectProfileToAccount("12345", "user@gmail.com"); + ConnectProfileToAccount("user@gmail.com"); AccountReconcilor* reconcilor = GetMockReconcilor(); ASSERT_TRUE(reconcilor); @@ -901,15 +924,18 @@ std::vector<Token> tokens_before_reconcile = ParseTokenString(GetParam().tokens); for (const Token& token : tokens_before_reconcile) { - std::string account_id = SeedAccountInfo(token.gaia_id, token.email); - if (token.is_authenticated) - ConnectProfileToAccount(token.gaia_id, token.email); - else - token_service()->UpdateCredentials(account_id, "refresh_token"); + std::string account_id; + if (token.is_authenticated) { + account_id = ConnectProfileToAccount(token.email).account_id; + } else { + account_id = SeedAccountInfo(token.gaia_id, token.email); + identity_test_env()->SetRefreshTokenForAccount(account_id); + } if (token.has_error) { - token_service()->UpdateAuthErrorForTesting( - account_id, GoogleServiceAuthError( - GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); + identity::UpdatePersistentErrorOfRefreshTokenForAccount( + identity_test_env()->identity_manager(), account_id, + GoogleServiceAuthError( + GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); } } VerifyCurrentTokens(tokens_before_reconcile); @@ -934,12 +960,14 @@ continue; } std::string cookie(1, GetParam().gaia_api_calls[i]); - EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(cookie)).Times(1); + std::string account_id_for_cookie = GaiaIdForAccountKey(cookie[0]); + EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id_for_cookie)) + .Times(1); // MergeSession fixes an existing cookie or appends it at the end. auto it = std::find(cookies.begin(), cookies.end(), - Cookie{cookie, false /* is_valid */}); + Cookie{account_id_for_cookie, false /* is_valid */}); if (it == cookies.end()) - cookies.push_back({cookie, true}); + cookies.push_back({account_id_for_cookie, true}); else it->is_valid = true; } @@ -1015,17 +1043,18 @@ ParseTokenString(GetParam().tokens); Token primary_account; for (const Token& token : tokens_before_reconcile) { - std::string account_id = SeedAccountInfo(token.gaia_id, token.email); + std::string account_id; if (token.is_authenticated) { - primary_account = token; - ConnectProfileToAccount(token.gaia_id, token.email); + account_id = ConnectProfileToAccount(token.email).account_id; } else { - token_service()->UpdateCredentials(account_id, "refresh_token"); + account_id = SeedAccountInfo(token.gaia_id, token.email); + identity_test_env()->SetRefreshTokenForAccount(account_id); } if (token.has_error) { - token_service()->UpdateAuthErrorForTesting( - account_id, GoogleServiceAuthError( - GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); + identity::UpdatePersistentErrorOfRefreshTokenForAccount( + identity_test_env()->identity_manager(), account_id, + GoogleServiceAuthError( + GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); } } VerifyCurrentTokens(tokens_before_reconcile); @@ -1116,8 +1145,7 @@ ASSERT_TRUE(reconcilor); ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService()); - account_tracker()->SeedAccountInfo("12345", "user@gmail.com"); - signin_manager()->SignIn("12345", "user@gmail.com", "password"); + identity_test_env()->MakePrimaryAccountAvailable("user@gmail.com"); ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService()); // Reconcilor should not logout all accounts from the cookies when @@ -1126,16 +1154,15 @@ EXPECT_CALL(*GetMockReconcilor(), PerformSetCookiesAction(::testing::_)) .Times(0); - signin_manager()->SignOut(signin_metrics::SIGNOUT_TEST, - signin_metrics::SignoutDelete::IGNORE_METRIC); + identity_test_env()->ClearPrimaryAccount(); ASSERT_TRUE(reconcilor->IsRegisteredWithTokenService()); } // Tests that reconcile starts even when Sync is not enabled. TEST_P(AccountReconcilorDiceEndpointParamTest, DiceReconcileWithoutSignin) { // Add a token in Chrome but do not sign in. - const std::string account_id = SeedAccountInfo("12345", "user@gmail.com"); - token_service()->UpdateCredentials(account_id, "refresh_token"); + const std::string account_id = + identity_test_env()->MakeAccountAvailable("user@gmail.com").account_id; cookie_manager_service()->SetListAccountsResponseNoAccounts(); if (!IsMultiloginEnabled()) { @@ -1186,19 +1213,24 @@ TEST_P(AccountReconcilorDiceEndpointParamTest, DiceReconcileReuseGaiaFirstAccount) { // Add accounts 1 and 2 to the token service. - const std::string account_id_1 = SeedAccountInfo("12345", "user@gmail.com"); - const std::string account_id_2 = SeedAccountInfo("67890", "other@gmail.com"); - token_service()->UpdateCredentials(account_id_1, "refresh_token"); - token_service()->UpdateCredentials(account_id_2, "refresh_token"); + const AccountInfo account_info_1 = + identity_test_env()->MakeAccountAvailable("user@gmail.com"); + const std::string account_id_1 = account_info_1.account_id; + const AccountInfo account_info_2 = + identity_test_env()->MakeAccountAvailable("other@gmail.com"); + const std::string account_id_2 = account_info_2.account_id; - ASSERT_EQ(2u, token_service()->GetAccounts().size()); - ASSERT_EQ(account_id_1, token_service()->GetAccounts()[0]); - ASSERT_EQ(account_id_2, token_service()->GetAccounts()[1]); + auto* identity_manager = identity_test_env()->identity_manager(); + std::vector<AccountInfo> accounts = + identity_manager->GetAccountsWithRefreshTokens(); + ASSERT_EQ(2u, accounts.size()); + ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_1)); + ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_2)); // Add accounts 2 and 3 to the Gaia cookie. const std::string account_id_3 = SeedAccountInfo("9999", "foo@gmail.com"); cookie_manager_service()->SetListAccountsResponseTwoAccounts( - "other@gmail.com", "67890", "foo@gmail.com", "9999"); + account_info_2.email, account_info_2.gaia, "foo@gmail.com", "9999"); if (!IsMultiloginEnabled()) { testing::InSequence mock_sequence; @@ -1207,7 +1239,7 @@ EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id_2)); EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id_1)); } else { - std::vector<std::string> accounts_to_send = {account_id_1, account_id_2}; + std::vector<std::string> accounts_to_send = {account_id_2, account_id_1}; // Send accounts to Gaia in any order, it will determine the order itself in // PRESERVE order. const signin::MultiloginParameters params( @@ -1237,16 +1269,22 @@ // lost. TEST_P(AccountReconcilorDiceEndpointParamTest, DiceLastKnownFirstAccount) { // Add accounts to the token service and the Gaia cookie in a different order. - const std::string account_id_1 = SeedAccountInfo("12345", "user@gmail.com"); - const std::string account_id_2 = SeedAccountInfo("67890", "other@gmail.com"); + AccountInfo account_info_1 = + identity_test_env()->MakeAccountAvailable("user@gmail.com"); + const std::string account_id_1 = account_info_1.account_id; + AccountInfo account_info_2 = + identity_test_env()->MakeAccountAvailable("other@gmail.com"); + const std::string account_id_2 = account_info_2.account_id; cookie_manager_service()->SetListAccountsResponseTwoAccounts( - "other@gmail.com", "67890", "user@gmail.com", "12345"); - token_service()->UpdateCredentials(account_id_1, "refresh_token"); - token_service()->UpdateCredentials(account_id_2, "refresh_token"); + account_info_2.email, account_info_2.gaia, account_info_1.email, + account_info_1.gaia); - ASSERT_EQ(2u, token_service()->GetAccounts().size()); - ASSERT_EQ(account_id_1, token_service()->GetAccounts()[0]); - ASSERT_EQ(account_id_2, token_service()->GetAccounts()[1]); + auto* identity_manager = identity_test_env()->identity_manager(); + std::vector<AccountInfo> accounts = + identity_manager->GetAccountsWithRefreshTokens(); + ASSERT_EQ(2u, accounts.size()); + ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_1)); + ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_2)); // Do one reconcile. It should do nothing but to populating the last known // account. @@ -1337,8 +1375,7 @@ // Add a token to Chrome. const std::string chrome_account_id = - SeedAccountInfo("67890", "other@gmail.com"); - token_service()->UpdateCredentials(chrome_account_id, "refresh_token"); + identity_test_env()->MakeAccountAvailable("other@gmail.com").account_id; if (!IsMultiloginEnabled()) { // Check that the Chrome account is merged and the unverified account is not @@ -1379,10 +1416,10 @@ pref_service()->SetBoolean(prefs::kTokenServiceDiceCompatible, true); // Chrome account is consistent with the cookie. - const std::string account_id = SeedAccountInfo("12345", "user@gmail.com"); - token_service()->UpdateCredentials(account_id, "refresh_token"); - cookie_manager_service()->SetListAccountsResponseOneAccount("user@gmail.com", - "12345"); + AccountInfo account_info = + identity_test_env()->MakeAccountAvailable("user@gmail.com"); + cookie_manager_service()->SetListAccountsResponseOneAccount( + account_info.email, account_info.gaia); AccountReconcilor* reconcilor = GetMockReconcilor(); // Dice is not enabled by default. EXPECT_FALSE(reconcilor->delegate_->IsAccountConsistencyEnforced()); @@ -1409,10 +1446,10 @@ SetAccountConsistency(signin::AccountConsistencyMethod::kDiceMigration); // Chrome account is consistent with the cookie. - const std::string account_id = SeedAccountInfo("12345", "user@gmail.com"); - token_service()->UpdateCredentials(account_id, "refresh_token"); - cookie_manager_service()->SetListAccountsResponseOneAccount("user@gmail.com", - "12345"); + AccountInfo account_info = + identity_test_env()->MakeAccountAvailable("user@gmail.com"); + cookie_manager_service()->SetListAccountsResponseOneAccount( + account_info.email, account_info.gaia); AccountReconcilor* reconcilor = GetMockReconcilor(); // Dice is not enabled by default. EXPECT_FALSE(reconcilor->delegate_->IsAccountConsistencyEnforced()); @@ -1440,7 +1477,7 @@ // Add a token in Chrome. const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); + ConnectProfileToAccount("user@gmail.com").account_id; cookie_manager_service()->SetListAccountsResponseNoAccounts(); AccountReconcilor* reconcilor = GetMockReconcilor(); @@ -1480,12 +1517,14 @@ // Add a tokens in Chrome, signin to Sync, but no Gaia cookies. const std::string account_id_1 = - ConnectProfileToAccount("12345", "user@gmail.com"); - const std::string account_id_2 = SeedAccountInfo("67890", "other@gmail.com"); - token_service()->UpdateCredentials(account_id_2, "refresh_token"); + ConnectProfileToAccount("user@gmail.com").account_id; + const std::string account_id_2 = + identity_test_env()->MakeAccountAvailable("other@gmail.com").account_id; cookie_manager_service()->SetListAccountsResponseNoAccounts(); - ASSERT_TRUE(token_service()->RefreshTokenIsAvailable(account_id_1)); - ASSERT_TRUE(token_service()->RefreshTokenIsAvailable(account_id_2)); + + auto* identity_manager = identity_test_env()->identity_manager(); + ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_1)); + ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_2)); // Reconcile should revoke the secondary account. AccountReconcilor* reconcilor = GetMockReconcilor(); @@ -1512,8 +1551,8 @@ ASSERT_FALSE(reconcilor->is_reconcile_started_); ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState()); - EXPECT_TRUE(token_service()->RefreshTokenIsAvailable(account_id_1)); - EXPECT_FALSE(token_service()->RefreshTokenIsAvailable(account_id_2)); + EXPECT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_1)); + EXPECT_FALSE(identity_manager->HasAccountWithRefreshToken(account_id_2)); // Profile was not migrated. EXPECT_FALSE(test_signin_client()->is_ready_for_dice_migration()); @@ -1527,13 +1566,15 @@ pref_service()->SetBoolean(prefs::kTokenServiceDiceCompatible, true); // Add a tokens in Chrome but no Gaia cookies. - const std::string account_id_1 = SeedAccountInfo("12345", "user@gmail.com"); - const std::string account_id_2 = SeedAccountInfo("67890", "other@gmail.com"); - token_service()->UpdateCredentials(account_id_1, "refresh_token"); - token_service()->UpdateCredentials(account_id_2, "refresh_token"); + const std::string account_id_1 = + identity_test_env()->MakeAccountAvailable("user@gmail.com").account_id; + const std::string account_id_2 = + identity_test_env()->MakeAccountAvailable("other@gmail.com").account_id; cookie_manager_service()->SetListAccountsResponseNoAccounts(); - ASSERT_TRUE(token_service()->RefreshTokenIsAvailable(account_id_1)); - ASSERT_TRUE(token_service()->RefreshTokenIsAvailable(account_id_2)); + + auto* identity_manager = identity_test_env()->identity_manager(); + ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_1)); + ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(account_id_2)); // Reconcile should revoke the secondary account. AccountReconcilor* reconcilor = GetMockReconcilor(); @@ -1543,8 +1584,8 @@ ASSERT_FALSE(reconcilor->is_reconcile_started_); ASSERT_EQ(signin_metrics::ACCOUNT_RECONCILOR_OK, reconcilor->GetState()); - EXPECT_FALSE(token_service()->RefreshTokenIsAvailable(account_id_1)); - EXPECT_FALSE(token_service()->RefreshTokenIsAvailable(account_id_2)); + EXPECT_FALSE(identity_manager->HasAccountWithRefreshToken(account_id_1)); + EXPECT_FALSE(identity_manager->HasAccountWithRefreshToken(account_id_2)); // Profile is now ready for migration on next startup. base::RunLoop().RunUntilIdle(); @@ -1559,17 +1600,22 @@ SetAccountConsistency(signin::AccountConsistencyMethod::kDice); const std::string primary_account_id = - account_tracker()->SeedAccountInfo("12345", "user@gmail.com"); - token_service()->UpdateCredentials(primary_account_id, "refresh_token"); - signin_manager()->SignIn("12345", "user@gmail.com", "password"); + identity_test_env() + ->MakePrimaryAccountAvailable("user@gmail.com") + .account_id; const std::string secondary_account_id = - SeedAccountInfo("67890", "other@gmail.com"); - token_service()->UpdateCredentials(secondary_account_id, "refresh_token"); + identity_test_env()->MakeAccountAvailable("other@gmail.com").account_id; - ASSERT_TRUE(token_service()->RefreshTokenIsAvailable(primary_account_id)); - ASSERT_FALSE(token_service()->RefreshTokenHasError(primary_account_id)); - ASSERT_TRUE(token_service()->RefreshTokenIsAvailable(secondary_account_id)); - ASSERT_FALSE(token_service()->RefreshTokenHasError(secondary_account_id)); + auto* identity_manager = identity_test_env()->identity_manager(); + ASSERT_TRUE(identity_manager->HasAccountWithRefreshToken(primary_account_id)); + ASSERT_FALSE( + identity_manager->HasAccountWithRefreshTokenInPersistentErrorState( + primary_account_id)); + ASSERT_TRUE( + identity_manager->HasAccountWithRefreshToken(secondary_account_id)); + ASSERT_FALSE( + identity_manager->HasAccountWithRefreshTokenInPersistentErrorState( + secondary_account_id)); AccountReconcilor* reconcilor = GetMockReconcilor(); @@ -1578,30 +1624,38 @@ std::unique_ptr<AccountReconcilor::ScopedSyncedDataDeletion> deletion = reconcilor->GetScopedSyncDataDeletion(); reconcilor->OnGaiaCookieDeletedByUserAction(); - EXPECT_TRUE(token_service()->RefreshTokenIsAvailable(primary_account_id)); - EXPECT_FALSE(token_service()->RefreshTokenHasError(primary_account_id)); + EXPECT_TRUE( + identity_manager->HasAccountWithRefreshToken(primary_account_id)); EXPECT_FALSE( - token_service()->RefreshTokenIsAvailable(secondary_account_id)); + identity_manager->HasAccountWithRefreshTokenInPersistentErrorState( + primary_account_id)); + EXPECT_FALSE( + identity_manager->HasAccountWithRefreshToken(secondary_account_id)); } - token_service()->UpdateCredentials(secondary_account_id, "refresh_token"); + identity_test_env()->SetRefreshTokenForAccount(secondary_account_id); reconcilor->OnGaiaCookieDeletedByUserAction(); // Without scoped deletion, the primary token is also invalidated. - EXPECT_TRUE(token_service()->RefreshTokenIsAvailable(primary_account_id)); - EXPECT_TRUE(token_service()->RefreshTokenHasError(primary_account_id)); + EXPECT_TRUE(identity_manager->HasAccountWithRefreshToken(primary_account_id)); + EXPECT_TRUE( + identity_manager->HasAccountWithRefreshTokenInPersistentErrorState( + primary_account_id)); EXPECT_EQ(GoogleServiceAuthError::InvalidGaiaCredentialsReason:: CREDENTIALS_REJECTED_BY_CLIENT, - token_service() - ->GetAuthError(primary_account_id) + identity_manager + ->GetErrorStateOfRefreshTokenForAccount(primary_account_id) .GetInvalidGaiaCredentialsReason()); - EXPECT_FALSE(token_service()->RefreshTokenIsAvailable(secondary_account_id)); + EXPECT_FALSE( + identity_manager->HasAccountWithRefreshToken(secondary_account_id)); // If the primary account has an error, always revoke it. - token_service()->UpdateCredentials(primary_account_id, "refresh_token"); - ASSERT_FALSE(token_service()->RefreshTokenHasError(primary_account_id)); - token_service()->UpdateAuthErrorForTesting( - primary_account_id, + identity_test_env()->SetRefreshTokenForAccount(primary_account_id); + EXPECT_FALSE( + identity_manager->HasAccountWithRefreshTokenInPersistentErrorState( + primary_account_id)); + identity::UpdatePersistentErrorOfRefreshTokenForAccount( + identity_test_env()->identity_manager(), primary_account_id, GoogleServiceAuthError::FromInvalidGaiaCredentialsReason( GoogleServiceAuthError::InvalidGaiaCredentialsReason:: CREDENTIALS_REJECTED_BY_SERVER)); @@ -1611,8 +1665,8 @@ reconcilor->OnGaiaCookieDeletedByUserAction(); EXPECT_EQ(GoogleServiceAuthError::InvalidGaiaCredentialsReason:: CREDENTIALS_REJECTED_BY_CLIENT, - token_service() - ->GetAuthError(primary_account_id) + identity_manager + ->GetErrorStateOfRefreshTokenForAccount(primary_account_id) .GetInvalidGaiaCredentialsReason()); } } @@ -1687,15 +1741,18 @@ std::vector<Token> tokens_before_reconcile = ParseTokenString(GetParam().tokens); for (const Token& token : tokens_before_reconcile) { - std::string account_id = SeedAccountInfo(token.gaia_id, token.email); - if (token.is_authenticated) - ConnectProfileToAccount(token.gaia_id, token.email); - else - token_service()->UpdateCredentials(account_id, "refresh_token"); + std::string account_id; + if (token.is_authenticated) { + account_id = ConnectProfileToAccount(token.email).account_id; + } else { + account_id = SeedAccountInfo(token.gaia_id, token.email); + identity_test_env()->SetRefreshTokenForAccount(account_id); + } if (token.has_error) { - token_service()->UpdateAuthErrorForTesting( - account_id, GoogleServiceAuthError( - GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); + identity::UpdatePersistentErrorOfRefreshTokenForAccount( + identity_test_env()->identity_manager(), account_id, + GoogleServiceAuthError( + GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); } } VerifyCurrentTokens(tokens_before_reconcile); @@ -1715,8 +1772,8 @@ if (GetParam().gaia_api_calls[i] == 'M') { std::vector<std::string> accounts_to_send; for (int i = 0; GetParam().cookies_after_reconcile[i] != '\0'; ++i) { - std::string account_to_send = - std::string(1, GetParam().cookies_after_reconcile[i]); + char cookie = GetParam().cookies_after_reconcile[i]; + std::string account_to_send = GaiaIdForAccountKey(cookie); accounts_to_send.push_back(PickAccountIdForAccount( account_to_send, accounts_[GetParam().cookies_after_reconcile[i]].email)); @@ -1769,7 +1826,7 @@ // automatically started when tokens are loaded. TEST_P(AccountReconcilorMirrorEndpointParamTest, TokensNotLoaded) { const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); + ConnectProfileToAccount("user@gmail.com").account_id; cookie_manager_service()->SetListAccountsResponseNoAccounts(); token_service()->set_all_credentials_loaded_for_testing(false); @@ -1807,11 +1864,11 @@ } TEST_P(AccountReconcilorMirrorEndpointParamTest, GetAccountsFromCookieSuccess) { - const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + const std::string account_id = account_info.account_id; cookie_manager_service()->SetListAccountsResponseOneAccountWithParams( - {"user@gmail.com", "12345", false /* valid */, false /* signed_out */, - true /* verified */}); + {account_info.email, account_info.gaia, false /* valid */, + false /* signed_out */, true /* verified */}); if (!IsMultiloginEnabled()) { EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id)); @@ -1842,8 +1899,7 @@ } TEST_P(AccountReconcilorMirrorEndpointParamTest, GetAccountsFromCookieFailure) { - ; - ConnectProfileToAccount("12345", "user@gmail.com"); + ConnectProfileToAccount("user@gmail.com"); cookie_manager_service()->SetListAccountsResponseWebLoginRequired(); AccountReconcilor* reconcilor = GetMockReconcilor(); @@ -1866,14 +1922,13 @@ } TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileNoop) { - const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); AccountReconcilor* reconcilor = GetMockReconcilor(); ASSERT_TRUE(reconcilor); - cookie_manager_service()->SetListAccountsResponseOneAccount("user@gmail.com", - "12345"); + cookie_manager_service()->SetListAccountsResponseOneAccount( + account_info.email, account_info.gaia); reconcilor->StartReconcile(); ASSERT_TRUE(reconcilor->is_reconcile_started_); @@ -1893,8 +1948,8 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileCookiesDisabled) { const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); - token_service()->UpdateCredentials(account_id, "refresh_token"); + ConnectProfileToAccount("user@gmail.com").account_id; + identity_test_env()->SetRefreshTokenForAccount(account_id); test_signin_client()->set_are_signin_cookies_allowed(false); AccountReconcilor* reconcilor = GetMockReconcilor(); @@ -1913,8 +1968,8 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileContentSettings) { const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); - token_service()->UpdateCredentials(account_id, "refresh_token"); + ConnectProfileToAccount("user@gmail.com").account_id; + identity_test_env()->SetRefreshTokenForAccount(account_id); AccountReconcilor* reconcilor = GetMockReconcilor(); ASSERT_TRUE(reconcilor); @@ -1933,8 +1988,8 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileContentSettingsGaiaUrl) { const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); - token_service()->UpdateCredentials(account_id, "refresh_token"); + ConnectProfileToAccount("user@gmail.com").account_id; + identity_test_env()->SetRefreshTokenForAccount(account_id); AccountReconcilor* reconcilor = GetMockReconcilor(); ASSERT_TRUE(reconcilor); @@ -1948,8 +2003,8 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileContentSettingsNonGaiaUrl) { const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); - token_service()->UpdateCredentials(account_id, "refresh_token"); + ConnectProfileToAccount("user@gmail.com").account_id; + identity_test_env()->SetRefreshTokenForAccount(account_id); AccountReconcilor* reconcilor = GetMockReconcilor(); ASSERT_TRUE(reconcilor); @@ -1963,8 +2018,8 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileContentSettingsInvalidPattern) { const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); - token_service()->UpdateCredentials(account_id, "refresh_token"); + ConnectProfileToAccount("user@gmail.com").account_id; + identity_test_env()->SetRefreshTokenForAccount(account_id); AccountReconcilor* reconcilor = GetMockReconcilor(); ASSERT_TRUE(reconcilor); @@ -1991,10 +2046,9 @@ return; } - const std::string account_id = - ConnectProfileToAccount("12345", "Dot.S@gmail.com"); - cookie_manager_service()->SetListAccountsResponseOneAccount("dot.s@gmail.com", - "12345"); + AccountInfo account_info = ConnectProfileToAccount("Dot.S@gmail.com"); + cookie_manager_service()->SetListAccountsResponseOneAccount( + account_info.email, account_info.gaia); AccountReconcilor* reconcilor = GetMockReconcilor(); ASSERT_TRUE(reconcilor); @@ -2010,12 +2064,12 @@ } TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileNoopMultiple) { - const std::string account_id = - ConnectProfileToAccount("67890", "user@gmail.com"); - const std::string account_id2 = SeedAccountInfo("12345", "other@gmail.com"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + AccountInfo account_info_2 = + identity_test_env()->MakeAccountAvailable("other@gmail.com"); cookie_manager_service()->SetListAccountsResponseTwoAccounts( - "user@gmail.com", "67890", "other@gmail.com", "12345"); - token_service()->UpdateCredentials(account_id2, "refresh_token"); + account_info.email, account_info.gaia, account_info_2.email, + account_info_2.gaia); AccountReconcilor* reconcilor = GetMockReconcilor(); ASSERT_TRUE(reconcilor); @@ -2034,14 +2088,14 @@ } TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileAddToCookie) { - const std::string account_id = - ConnectProfileToAccount("67890", "user@gmail.com"); - token_service()->UpdateCredentials(account_id, "refresh_token"); - cookie_manager_service()->SetListAccountsResponseOneAccount("user@gmail.com", - "67890"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + const std::string account_id = account_info.account_id; + identity_test_env()->SetRefreshTokenForAccount(account_id); + cookie_manager_service()->SetListAccountsResponseOneAccount( + account_info.email, account_info.gaia); - const std::string account_id2 = SeedAccountInfo("12345", "other@gmail.com"); - token_service()->UpdateCredentials(account_id2, "refresh_token"); + const std::string account_id2 = + identity_test_env()->MakeAccountAvailable("other@gmail.com").account_id; if (!IsMultiloginEnabled()) { EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2)); @@ -2108,16 +2162,16 @@ #endif // Add one account to Chrome and instantiate the reconcilor. - const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); - token_service()->UpdateCredentials(account_id, "refresh_token"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + const std::string account_id = account_info.account_id; + identity_test_env()->SetRefreshTokenForAccount(account_id); TestGaiaCookieObserver observer; cookie_manager_service()->AddObserver(&observer); AccountReconcilor* reconcilor = GetMockReconcilor(); base::RunLoop().RunUntilIdle(); ASSERT_FALSE(reconcilor->is_reconcile_started_); - cookie_manager_service()->SetListAccountsResponseOneAccount("user@gmail.com", - "12345"); + cookie_manager_service()->SetListAccountsResponseOneAccount( + account_info.email, account_info.gaia); if (account_consistency == signin::AccountConsistencyMethod::kDice) { EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()) .Times(1); @@ -2125,10 +2179,11 @@ // Set an authentication error. ASSERT_FALSE(observer.cookies_updated_); - token_service()->UpdateAuthErrorForTesting( - account_id, GoogleServiceAuthError::FromInvalidGaiaCredentialsReason( - GoogleServiceAuthError::InvalidGaiaCredentialsReason:: - CREDENTIALS_REJECTED_BY_SERVER)); + identity::UpdatePersistentErrorOfRefreshTokenForAccount( + identity_test_env()->identity_manager(), account_id, + GoogleServiceAuthError::FromInvalidGaiaCredentialsReason( + GoogleServiceAuthError::InvalidGaiaCredentialsReason:: + CREDENTIALS_REJECTED_BY_SERVER)); base::RunLoop().RunUntilIdle(); // Check that a call to ListAccount was triggered. @@ -2144,14 +2199,14 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, SignoutAfterErrorDoesNotRecordUma) { - const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); - token_service()->UpdateCredentials(account_id, "refresh_token"); - cookie_manager_service()->SetListAccountsResponseOneAccount("user@gmail.com", - "12345"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + const std::string account_id = account_info.account_id; + identity_test_env()->SetRefreshTokenForAccount(account_id); + cookie_manager_service()->SetListAccountsResponseOneAccount( + account_info.email, account_info.gaia); - const std::string account_id2 = SeedAccountInfo("67890", "other@gmail.com"); - token_service()->UpdateCredentials(account_id2, "refresh_token"); + const std::string account_id2 = + identity_test_env()->MakeAccountAvailable("other@gmail.com").account_id; if (!IsMultiloginEnabled()) { EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2)); @@ -2178,8 +2233,7 @@ ASSERT_FALSE(reconcilor->is_reconcile_started_); EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()); - signin_manager()->SignOut(signin_metrics::SIGNOUT_TEST, - signin_metrics::SignoutDelete::IGNORE_METRIC); + identity_test_env()->ClearPrimaryAccount(); base::HistogramTester::CountsMap expected_counts; expected_counts["Signin.Reconciler.Duration.Failure"] = 1; @@ -2194,11 +2248,11 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileRemoveFromCookie) { - const std::string account_id = - ConnectProfileToAccount("67890", "user@gmail.com"); - token_service()->UpdateCredentials(account_id, "refresh_token"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + const std::string account_id = account_info.account_id; + identity_test_env()->SetRefreshTokenForAccount(account_id); cookie_manager_service()->SetListAccountsResponseTwoAccounts( - "user@gmail.com", "67890", "other@gmail.com", "12345"); + account_info.email, account_info.gaia, "other@gmail.com", "12345"); if (!IsMultiloginEnabled()) { EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()); @@ -2239,14 +2293,13 @@ // Check that reconcile is aborted if there is token error on primary account. TEST_P(AccountReconcilorMirrorEndpointParamTest, TokenErrorOnPrimary) { - const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); - token_service()->UpdateAuthErrorForTesting( - account_id, + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + identity::UpdatePersistentErrorOfRefreshTokenForAccount( + identity_test_env()->identity_manager(), account_info.account_id, GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); cookie_manager_service()->SetListAccountsResponseTwoAccounts( - "user@gmail.com", "12345", "other@gmail.com", "67890"); + account_info.email, account_info.gaia, "other@gmail.com", "67890"); AccountReconcilor* reconcilor = GetMockReconcilor(); reconcilor->StartReconcile(); @@ -2257,14 +2310,15 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileAddToCookieTwice) { - const std::string account_id = - ConnectProfileToAccount("67890", "user@gmail.com"); - const std::string account_id2 = SeedAccountInfo("12345", "other@gmail.com"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + const std::string account_id = account_info.account_id; + AccountInfo account_info2 = + identity_test_env()->MakeAccountAvailable("other@gmail.com"); + const std::string account_id2 = account_info2.account_id; const std::string account_id3 = SeedAccountInfo("34567", "third@gmail.com"); - cookie_manager_service()->SetListAccountsResponseOneAccount("user@gmail.com", - "67890"); - token_service()->UpdateCredentials(account_id2, "refresh_token"); + cookie_manager_service()->SetListAccountsResponseOneAccount( + account_info.email, account_info.gaia); if (!IsMultiloginEnabled()) { EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2)); @@ -2303,11 +2357,12 @@ // Do another pass after I've added a third account to the token service cookie_manager_service()->SetListAccountsResponseTwoAccounts( - "user@gmail.com", "67890", "other@gmail.com", "12345"); + account_info.email, account_info.gaia, account_info2.email, + account_info2.gaia); cookie_manager_service()->set_list_accounts_stale_for_testing(true); // This will cause the reconcilor to fire. - token_service()->UpdateCredentials(account_id3, "refresh_token"); + identity_test_env()->SetRefreshTokenForAccount(account_id3); if (IsMultiloginEnabled()) { std::vector<std::string> accounts_to_send = {account_id, account_id2, account_id3}; @@ -2347,13 +2402,15 @@ } TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileBadPrimary) { - const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); - const std::string account_id2 = SeedAccountInfo("67890", "other@gmail.com"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + const std::string account_id = account_info.account_id; - token_service()->UpdateCredentials(account_id2, "refresh_token"); + AccountInfo account_info2 = + identity_test_env()->MakeAccountAvailable("other@gmail.com"); + const std::string account_id2 = account_info2.account_id; cookie_manager_service()->SetListAccountsResponseTwoAccounts( - "other@gmail.com", "67890", "user@gmail.com", "12345"); + account_info2.email, account_info2.gaia, account_info.email, + account_info.gaia); if (!IsMultiloginEnabled()) { EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()); @@ -2396,10 +2453,9 @@ } TEST_P(AccountReconcilorMirrorEndpointParamTest, StartReconcileOnlyOnce) { - const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); - cookie_manager_service()->SetListAccountsResponseOneAccount("user@gmail.com", - "12345"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + cookie_manager_service()->SetListAccountsResponseOneAccount( + account_info.email, account_info.gaia); AccountReconcilor* reconcilor = GetMockReconcilor(); ASSERT_TRUE(reconcilor); @@ -2413,10 +2469,10 @@ } TEST_P(AccountReconcilorMirrorEndpointParamTest, Lock) { - const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); - cookie_manager_service()->SetListAccountsResponseOneAccount("user@gmail.com", - "12345"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + cookie_manager_service()->SetListAccountsResponseOneAccount( + account_info.email, account_info.gaia); + AccountReconcilor* reconcilor = GetMockReconcilor(); ASSERT_TRUE(reconcilor); ASSERT_FALSE(reconcilor->is_reconcile_started_); @@ -2487,15 +2543,16 @@ TEST_P(AccountReconcilorMethodParamTest, StartReconcileWithSessionInfoExpiredDefault) { SetAccountConsistency(GetParam()); - const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); - const std::string account_id2 = SeedAccountInfo("67890", "other@gmail.com"); - token_service()->UpdateCredentials(account_id2, "refresh_token"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + const std::string account_id = account_info.account_id; + AccountInfo account_info2 = + identity_test_env()->MakeAccountAvailable("other@gmail.com"); + const std::string account_id2 = account_info2.account_id; cookie_manager_service()->SetListAccountsResponseWithParams( - {{"user@gmail.com", "12345", false /* valid */, false /* signed_out */, - true /* verified */}, - {"other@gmail.com", "67890", true /* valid */, false /* signed_out */, - true /* verified */}}); + {{account_info.email, account_info.gaia, false /* valid */, + false /* signed_out */, true /* verified */}, + {account_info2.email, account_info2.gaia, true /* valid */, + false /* signed_out */, true /* verified */}}); EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id)); @@ -2514,11 +2571,11 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, AddAccountToCookieCompletedWithBogusAccount) { - const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + const std::string account_id = account_info.account_id; cookie_manager_service()->SetListAccountsResponseOneAccountWithParams( - {"user@gmail.com", "12345", false /* valid */, false /* signed_out */, - true /* verified */}); + {account_info.email, account_info.gaia, false /* valid */, + false /* signed_out */, true /* verified */}); if (!IsMultiloginEnabled()) { EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id)); @@ -2553,10 +2610,11 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, NoLoopWithBadPrimary) { // Connect profile to a primary account and then add a secondary account. - const std::string account_id1 = - ConnectProfileToAccount("12345", "user@gmail.com"); - const std::string account_id2 = SeedAccountInfo("67890", "other@gmail.com"); - token_service()->UpdateCredentials(account_id2, "refresh_token"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + const std::string account_id1 = account_info.account_id; + AccountInfo account_info2 = + identity_test_env()->MakeAccountAvailable("other@gmail.com"); + const std::string account_id2 = account_info2.account_id; if (!IsMultiloginEnabled()) { EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()); @@ -2571,8 +2629,8 @@ } // The primary account is in auth error, so it is not in the cookie. cookie_manager_service()->SetListAccountsResponseOneAccountWithParams( - {"other@gmail.com", "67890", false /* valid */, false /* signed_out */, - true /* verified */}); + {account_info2.email, account_info2.gaia, false /* valid */, + false /* signed_out */, true /* verified */}); AccountReconcilor* reconcilor = GetMockReconcilor(); ASSERT_TRUE(reconcilor); @@ -2600,7 +2658,8 @@ // Now that we've tried once, the token service knows that the primary // account has an auth error. - token_service()->UpdateAuthErrorForTesting(account_id1, error); + identity::UpdatePersistentErrorOfRefreshTokenForAccount( + identity_test_env()->identity_manager(), account_id1, error); // A second attempt to reconcile should be a noop. reconcilor->StartReconcile(); @@ -2612,13 +2671,13 @@ TEST_P(AccountReconcilorMirrorEndpointParamTest, WontMergeAccountsWithError) { // Connect profile to a primary account and then add a secondary account. const std::string account_id1 = - ConnectProfileToAccount("12345", "user@gmail.com"); - const std::string account_id2 = SeedAccountInfo("67890", "other@gmail.com"); - token_service()->UpdateCredentials(account_id2, "refresh_token"); + ConnectProfileToAccount("user@gmail.com").account_id; + const std::string account_id2 = + identity_test_env()->MakeAccountAvailable("other@gmail.com").account_id; // Mark the secondary account in auth error state. - token_service()->UpdateAuthErrorForTesting( - account_id2, + identity::UpdatePersistentErrorOfRefreshTokenForAccount( + identity_test_env()->identity_manager(), account_id2, GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); // The cookie starts empty. @@ -2660,8 +2719,7 @@ // Test that delegate timeout is called when the delegate offers a valid // timeout. TEST_F(AccountReconcilorTest, DelegateTimeoutIsCalled) { - const std::string account_id = - ConnectProfileToAccount("12345", "user@gmail.com"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); auto spy_delegate0 = std::make_unique<SpyReconcilorDelegate>(); SpyReconcilorDelegate* spy_delegate = spy_delegate0.get(); AccountReconcilor* reconcilor = GetMockReconcilor(std::move(spy_delegate0)); @@ -2684,9 +2742,9 @@ // Test that delegate timeout is not called when the delegate does not offer a // valid timeout. TEST_P(AccountReconcilorMirrorEndpointParamTest, DelegateTimeoutIsNotCalled) { - ConnectProfileToAccount("12345", "user@gmail.com"); - cookie_manager_service()->SetListAccountsResponseOneAccount("user@gmail.com", - "12345"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + cookie_manager_service()->SetListAccountsResponseOneAccount( + account_info.email, account_info.gaia); AccountReconcilor* reconcilor = GetMockReconcilor(); ASSERT_TRUE(reconcilor); auto timer0 = std::make_unique<base::MockOneShotTimer>(); @@ -2703,9 +2761,9 @@ ::testing::ValuesIn({false, true})); TEST_F(AccountReconcilorTest, DelegateTimeoutIsNotCalledIfTimeoutIsNotReached) { - ConnectProfileToAccount("12345", "user@gmail.com"); - cookie_manager_service()->SetListAccountsResponseOneAccount("user@gmail.com", - "12345"); + AccountInfo account_info = ConnectProfileToAccount("user@gmail.com"); + cookie_manager_service()->SetListAccountsResponseOneAccount( + account_info.email, account_info.gaia); auto spy_delegate0 = std::make_unique<SpyReconcilorDelegate>(); SpyReconcilorDelegate* spy_delegate = spy_delegate0.get(); AccountReconcilor* reconcilor = GetMockReconcilor(std::move(spy_delegate0));
diff --git a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountHolder.java b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountHolder.java index e5e8001..42df492 100644 --- a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountHolder.java +++ b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountHolder.java
@@ -18,13 +18,12 @@ */ public class AccountHolder { private final Account mAccount; - private final String mPassword; private final Map<String, String> mAuthTokens; private final Map<String, Boolean> mHasBeenAccepted; private final boolean mAlwaysAccept; private final Set<String> mFeatures; - private AccountHolder(Account account, String password, Map<String, String> authTokens, + private AccountHolder(Account account, Map<String, String> authTokens, Map<String, Boolean> hasBeenAccepted, boolean alwaysAccept, Set<String> features) { assert account != null; assert authTokens != null; @@ -32,7 +31,6 @@ assert features != null; mAccount = account; - mPassword = password; mAuthTokens = authTokens; mHasBeenAccepted = hasBeenAccepted; mAlwaysAccept = alwaysAccept; @@ -43,10 +41,6 @@ return mAccount; } - public String getPassword() { - return mPassword; - } - public boolean hasAuthTokenRegistered(String authTokenType) { return mAuthTokens.containsKey(authTokenType); } @@ -102,10 +96,6 @@ return new Builder(account); } - public AccountHolder withPassword(String password) { - return copy().password(password).build(); - } - public AccountHolder withAuthTokens(Map<String, String> authTokens) { return copy().authTokens(authTokens).build(); } @@ -124,7 +114,6 @@ private Builder copy() { return builder(mAccount) - .password(mPassword) .authTokens(mAuthTokens) .hasBeenAcceptedMap(mHasBeenAccepted) .alwaysAccept(mAlwaysAccept); @@ -135,7 +124,6 @@ */ public static class Builder { private Account mAccount; - private String mPassword; private Map<String, String> mAuthTokens = new HashMap<>(); private Map<String, Boolean> mHasBeenAccepted = new HashMap<>(); private boolean mAlwaysAccept; @@ -150,11 +138,6 @@ return this; } - public Builder password(String password) { - mPassword = password; - return this; - } - public Builder authToken(String authTokenType, String authToken) { mAuthTokens.put(authTokenType, authToken); return this; @@ -198,7 +181,7 @@ public AccountHolder build() { return new AccountHolder( - mAccount, mPassword, mAuthTokens, mHasBeenAccepted, mAlwaysAccept, mFeatures); + mAccount, mAuthTokens, mHasBeenAccepted, mAlwaysAccept, mFeatures); } } }
diff --git a/components/signin/core/browser/dice_account_reconcilor_delegate.cc b/components/signin/core/browser/dice_account_reconcilor_delegate.cc index 53aacc6b..5b053f49 100644 --- a/components/signin/core/browser/dice_account_reconcilor_delegate.cc +++ b/components/signin/core/browser/dice_account_reconcilor_delegate.cc
@@ -20,11 +20,12 @@ AccountConsistencyMethod account_consistency) : signin_client_(signin_client), account_consistency_(account_consistency) { DCHECK(signin_client_); + DCHECK(DiceMethodGreaterOrEqual(account_consistency_, + AccountConsistencyMethod::kDiceMigration)); } bool DiceAccountReconcilorDelegate::IsReconcileEnabled() const { - return DiceMethodGreaterOrEqual(account_consistency_, - AccountConsistencyMethod::kDiceMigration); + return true; } bool DiceAccountReconcilorDelegate::IsAccountConsistencyEnforced() const { @@ -171,12 +172,9 @@ // Migration happens on startup if the last reconcile was a no-op and the // refresh tokens are Dice-compatible. - if (DiceMethodGreaterOrEqual(account_consistency_, - AccountConsistencyMethod::kDiceMigration)) { - signin_client_->SetReadyForDiceMigration( - reconcile_is_noop && signin_client_->GetPrefs()->GetBoolean( - prefs::kTokenServiceDiceCompatible)); - } + signin_client_->SetReadyForDiceMigration( + reconcile_is_noop && signin_client_->GetPrefs()->GetBoolean( + prefs::kTokenServiceDiceCompatible)); } } // namespace signin
diff --git a/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc b/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc index f3b36df..4c46755 100644 --- a/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc +++ b/components/signin/core/browser/dice_account_reconcilor_delegate_unittest.cc
@@ -66,15 +66,6 @@ DiceTestSigninClient client(&pref_service); { - // Dice migration not enabled. - testing::InSequence mock_sequence; - EXPECT_CALL(client, SetReadyForDiceMigration(testing::_)).Times(0); - DiceAccountReconcilorDelegate delegate( - &client, AccountConsistencyMethod::kDiceFixAuthErrors); - delegate.OnReconcileFinished("account", true /* is_reconcile_noop */); - } - - { // Dice migration enabled, but token service is not ready. testing::InSequence mock_sequence; EXPECT_CALL(client, SetReadyForDiceMigration(false)).Times(1);
diff --git a/components/signin/core/browser/dice_header_helper.cc b/components/signin/core/browser/dice_header_helper.cc index fb51916..4a7c91f 100644 --- a/components/signin/core/browser/dice_header_helper.cc +++ b/components/signin/core/browser/dice_header_helper.cc
@@ -20,7 +20,6 @@ // Request parameters. const char kRequestSigninAll[] = "all_accounts"; -const char kRequestSigninSyncAccount[] = "sync_account"; const char kRequestSignoutNoConfirmation[] = "no_confirmation"; const char kRequestSignoutShowConfirmation[] = "show_confirmation"; @@ -194,24 +193,12 @@ return false; } - // With kDiceFixAuthError, only set the request header if the user is signed - // in and has an authentication error. - if (!signed_in_with_auth_error_ && - (account_consistency_ == AccountConsistencyMethod::kDiceFixAuthErrors)) { - return false; - } - return gaia::IsGaiaSignonRealm(url.GetOrigin()); } std::string DiceHeaderHelper::BuildRequestHeader( const std::string& sync_account_id, const std::string& device_id) { - // When fixing auth errors, only add the header when Sync is actually in error - // state. - DCHECK( - signed_in_with_auth_error_ || - (account_consistency_ != AccountConsistencyMethod::kDiceFixAuthErrors)); DCHECK(!(sync_account_id.empty() && signed_in_with_auth_error_)); std::vector<std::string> parts; @@ -224,10 +211,7 @@ parts.push_back("sync_account_id=" + sync_account_id); // Restrict Signin to Sync account only when fixing auth errors. - std::string signin_mode = - (account_consistency_ == AccountConsistencyMethod::kDiceFixAuthErrors) - ? kRequestSigninSyncAccount - : kRequestSigninAll; + std::string signin_mode = kRequestSigninAll; parts.push_back("signin_mode=" + signin_mode); // Show the signout confirmation only when Dice is fully enabled.
diff --git a/components/signin/core/browser/fake_gaia_cookie_manager_service.cc b/components/signin/core/browser/fake_gaia_cookie_manager_service.cc index 619a489..d01ed5f 100644 --- a/components/signin/core/browser/fake_gaia_cookie_manager_service.cc +++ b/components/signin/core/browser/fake_gaia_cookie_manager_service.cc
@@ -16,14 +16,25 @@ FakeGaiaCookieManagerService::FakeGaiaCookieManagerService( OAuth2TokenService* token_service, SigninClient* client, + network::TestURLLoaderFactory* test_url_loader_factory) + : GaiaCookieManagerService(token_service, client), + test_url_loader_factory_(test_url_loader_factory), + shared_loader_factory_( + base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( + test_url_loader_factory_)) {} + +FakeGaiaCookieManagerService::FakeGaiaCookieManagerService( + OAuth2TokenService* token_service, + SigninClient* client, bool use_fake_url_loader) : GaiaCookieManagerService(token_service, client) { if (use_fake_url_loader) { - test_url_loader_factory_ = + owned_test_url_loader_factory_ = std::make_unique<network::TestURLLoaderFactory>(); + test_url_loader_factory_ = owned_test_url_loader_factory_.get(); shared_loader_factory_ = base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( - test_url_loader_factory_.get()); + test_url_loader_factory_); } }
diff --git a/components/signin/core/browser/fake_gaia_cookie_manager_service.h b/components/signin/core/browser/fake_gaia_cookie_manager_service.h index 66a67cd..a36c514 100644 --- a/components/signin/core/browser/fake_gaia_cookie_manager_service.h +++ b/components/signin/core/browser/fake_gaia_cookie_manager_service.h
@@ -10,11 +10,11 @@ #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "components/signin/core/browser/gaia_cookie_manager_service.h" +#include "services/network/test/test_url_loader_factory.h" namespace network { -class TestURLLoaderFactory; class WeakWrapperSharedURLLoaderFactory; -} +} // namespace network class FakeGaiaCookieManagerService : public GaiaCookieManagerService { public: @@ -27,9 +27,18 @@ bool verified; }; + FakeGaiaCookieManagerService( + OAuth2TokenService* token_service, + SigninClient* client, + network::TestURLLoaderFactory* test_url_loader_factory); + + // DEPRECATED, use other constructors instead. + // TODO(https://crbug.com/907782): Delete this after all references are + // removed. FakeGaiaCookieManagerService(OAuth2TokenService* token_service, SigninClient* client, bool use_fake_url_fetcher = true); + ~FakeGaiaCookieManagerService() override; void SetListAccountsResponseHttpNotFound(); @@ -50,8 +59,18 @@ private: scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; + // Temporary workaround until all tests are updated to own the + // TestURLLoaderFactory themselves. + // TODO(https://crbug.com/907782): Remove this. + std::unique_ptr<network::TestURLLoaderFactory> owned_test_url_loader_factory_; + // Provide a fake response for calls to /ListAccounts. - std::unique_ptr<network::TestURLLoaderFactory> test_url_loader_factory_; + // Owned by the client if passed in via the constructor that takes in this + // pointer; owned by the ivar above if |true| is passed in via the constructor + // that takes in a boolean; null otherwise. + // TODO(https://crbug.com/907782): Update this comment as necessary when the + // constructor that takes in a boolean is eliminated. + network::TestURLLoaderFactory* test_url_loader_factory_ = nullptr; scoped_refptr<network::WeakWrapperSharedURLLoaderFactory> shared_loader_factory_;
diff --git a/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc b/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc index 170eb8d..ef8d8e1 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc +++ b/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc
@@ -12,11 +12,11 @@ #include "base/location.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_task_environment.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "components/prefs/pref_registry_simple.h" @@ -231,7 +231,7 @@ } private: - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment task_environment_; FakeOAuth2TokenService token_service_; GoogleServiceAuthError no_error_; GoogleServiceAuthError error_;
diff --git a/components/signin/core/browser/mirror_account_reconcilor_delegate.h b/components/signin/core/browser/mirror_account_reconcilor_delegate.h index da80446..05f9f72 100644 --- a/components/signin/core/browser/mirror_account_reconcilor_delegate.h +++ b/components/signin/core/browser/mirror_account_reconcilor_delegate.h
@@ -5,6 +5,9 @@ #ifndef COMPONENTS_SIGNIN_CORE_BROWSER_MIRROR_ACCOUNT_RECONCILOR_DELEGATE_H_ #define COMPONENTS_SIGNIN_CORE_BROWSER_MIRROR_ACCOUNT_RECONCILOR_DELEGATE_H_ +#include <string> +#include <vector> + #include "base/macros.h" #include "components/signin/core/browser/account_reconcilor_delegate.h" #include "services/identity/public/cpp/identity_manager.h" @@ -16,12 +19,18 @@ : public AccountReconcilorDelegate, public identity::IdentityManager::Observer { public: - MirrorAccountReconcilorDelegate(identity::IdentityManager* identity_manager); + explicit MirrorAccountReconcilorDelegate( + identity::IdentityManager* identity_manager); ~MirrorAccountReconcilorDelegate() override; + protected: + // AccountReconcilorDelegate: + // TODO(sinhak): Make this private after deleting + // |ChromeOSAccountReconcilorDelegate|. + bool IsReconcileEnabled() const override; + private: // AccountReconcilorDelegate: - bool IsReconcileEnabled() const override; bool IsAccountConsistencyEnforced() const override; gaia::GaiaSource GetGaiaApiSource() const override; bool ShouldAbortReconcileIfPrimaryHasError() const override;
diff --git a/components/signin/core/browser/profile_oauth2_token_service.h b/components/signin/core/browser/profile_oauth2_token_service.h index 0186693..f0a75e5e 100644 --- a/components/signin/core/browser/profile_oauth2_token_service.h +++ b/components/signin/core/browser/profile_oauth2_token_service.h
@@ -8,7 +8,6 @@ #include <string> #include "base/macros.h" -#include "base/memory/linked_ptr.h" #include "components/keyed_service/core/keyed_service.h" #include "components/signin/core/browser/signin_metrics.h" #include "google_apis/gaia/oauth2_token_service.h"
diff --git a/components/signin/core/browser/signin_header_helper_unittest.cc b/components/signin/core/browser/signin_header_helper_unittest.cc index 5414b2f..1697fd9 100644 --- a/components/signin/core/browser/signin_header_helper_unittest.cc +++ b/components/signin/core/browser/signin_header_helper_unittest.cc
@@ -8,8 +8,8 @@ #include <string> #include "base/command_line.h" -#include "base/message_loop/message_loop.h" #include "base/strings/stringprintf.h" +#include "base/test/scoped_task_environment.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/prefs/pref_member.h" #include "components/signin/core/browser/account_consistency_method.h" @@ -112,7 +112,7 @@ } #endif - base::MessageLoop loop_; + base::test::ScopedTaskEnvironment task_environment_; bool sync_enabled_ = false; bool sync_has_auth_error_ = false; @@ -327,37 +327,6 @@ kDiceProtocolVersion, client_id.c_str())); } -// Tests that a Dice request is returned only when there is an authentication -// error if the method is kDiceFixAuthErrors. -TEST_F(SigninHeaderHelperTest, TestDiceFixAuthError) { - account_consistency_ = AccountConsistencyMethod::kDiceFixAuthErrors; - // No Dice request unless all conditions are met. - CheckDiceHeaderRequest(GURL("https://accounts.google.com"), "0123456789", - "mode=0,enable_account_consistency=false", ""); - sync_has_auth_error_ = false; - sync_enabled_ = true; - CheckDiceHeaderRequest(GURL("https://accounts.google.com"), "0123456789", - "mode=0,enable_account_consistency=false", ""); - sync_has_auth_error_ = true; - sync_enabled_ = false; - CheckDiceHeaderRequest(GURL("https://accounts.google.com"), "0123456789", - "mode=0,enable_account_consistency=false", ""); - sync_has_auth_error_ = true; - sync_enabled_ = true; - CheckDiceHeaderRequest(GURL("https://accounts.google.com"), "", "", ""); - - // Dice request when there is an account id, Sync is enabled and in error - // state. - std::string client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id(); - CheckDiceHeaderRequest( - GURL("https://accounts.google.com"), "0123456789", - "mode=0,enable_account_consistency=false", - base::StringPrintf("version=%s,client_id=%s,device_id=DeviceID," - "sync_account_id=0123456789,signin_mode=sync_account," - "signout_mode=no_confirmation", - kDiceProtocolVersion, client_id.c_str())); -} - // Tests that the Mirror request is returned with the GAIA Id on Drive origin, // even if account consistency is disabled. TEST_F(SigninHeaderHelperTest, TestMirrorRequestDrive) {
diff --git a/components/signin/core/browser/signin_manager_unittest.cc b/components/signin/core/browser/signin_manager_unittest.cc index 75bd3d8..fe573bb 100644 --- a/components/signin/core/browser/signin_manager_unittest.cc +++ b/components/signin/core/browser/signin_manager_unittest.cc
@@ -11,8 +11,8 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/compiler_specific.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" #include "build/build_config.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" @@ -78,7 +78,8 @@ : test_signin_client_(&user_prefs_), token_service_(&user_prefs_), cookie_manager_service_(&token_service_, - &test_signin_client_), + &test_signin_client_, + &test_url_loader_factory_), account_consistency_(signin::AccountConsistencyMethod::kDisabled) { AccountFetcherService::RegisterPrefs(user_prefs_.registry()); AccountTrackerService::RegisterPrefs(user_prefs_.registry()); @@ -156,12 +157,13 @@ manager_->CompletePendingSignin(); } - base::MessageLoop loop_; + base::test::ScopedTaskEnvironment task_environment_; sync_preferences::TestingPrefServiceSyncable user_prefs_; TestingPrefServiceSimple local_state_; TestSigninClient test_signin_client_; FakeProfileOAuth2TokenService token_service_; AccountTrackerService account_tracker_; + network::TestURLLoaderFactory test_url_loader_factory_; FakeGaiaCookieManagerService cookie_manager_service_; FakeAccountFetcherService account_fetcher_; std::unique_ptr<SigninManager> manager_;
diff --git a/components/signin/core/browser/signin_tracker_unittest.cc b/components/signin/core/browser/signin_tracker_unittest.cc index 78cc5424..87a6d5c8 100644 --- a/components/signin/core/browser/signin_tracker_unittest.cc +++ b/components/signin/core/browser/signin_tracker_unittest.cc
@@ -5,7 +5,7 @@ #include "components/signin/core/browser/signin_tracker.h" #include "base/compiler_specific.h" -#include "base/message_loop/message_loop.h" +#include "base/test/scoped_task_environment.h" #include "build/build_config.h" #include "components/signin/core/browser/account_consistency_method.h" #include "components/signin/core/browser/account_tracker_service.h" @@ -53,7 +53,8 @@ : signin_client_(&pref_service_), fake_oauth2_token_service_(&pref_service_), fake_gaia_cookie_manager_service_(&fake_oauth2_token_service_, - &signin_client_), + &signin_client_, + &test_url_loader_factory_), #if defined(OS_CHROMEOS) fake_signin_manager_(&signin_client_, &account_tracker_) { #else @@ -76,12 +77,13 @@ ~SigninTrackerTest() override { tracker_.reset(); } - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment task_environment_; std::unique_ptr<SigninTracker> tracker_; sync_preferences::TestingPrefServiceSyncable pref_service_; AccountTrackerService account_tracker_; TestSigninClient signin_client_; FakeProfileOAuth2TokenService fake_oauth2_token_service_; + network::TestURLLoaderFactory test_url_loader_factory_; FakeGaiaCookieManagerService fake_gaia_cookie_manager_service_; FakeSigninManagerForTesting fake_signin_manager_; MockObserver observer_;
diff --git a/components/ssl_errors/error_classification_unittest.cc b/components/ssl_errors/error_classification_unittest.cc index be7b8ad..ea281ed 100644 --- a/components/ssl_errors/error_classification_unittest.cc +++ b/components/ssl_errors/error_classification_unittest.cc
@@ -7,13 +7,11 @@ #include <memory> #include "base/files/file_path.h" -#include "base/message_loop/message_loop.h" #include "base/strings/string_split.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_task_environment.h" #include "base/test/simple_test_clock.h" #include "base/test/simple_test_tick_clock.h" -#include "base/threading/thread_task_runner_handle.h" #include "base/time/default_clock.h" #include "base/time/default_tick_clock.h" #include "components/network_time/network_time_test_utils.h" @@ -254,7 +252,6 @@ histograms.ExpectTotalCount(kNetworkTimeHistogram, 0); TestingPrefServiceSimple pref_service; network_time::NetworkTimeTracker::RegisterPrefs(pref_service.registry()); - base::MessageLoop loop; network_time::NetworkTimeTracker network_time_tracker( std::make_unique<base::DefaultClock>(), std::make_unique<base::DefaultTickClock>(), &pref_service,
diff --git a/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc b/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc index 2d30fd2..db8389e 100644 --- a/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc +++ b/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc
@@ -10,8 +10,8 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" #include "base/test/test_simple_task_runner.h" #include "base/threading/sequenced_task_runner_handle.h" #include "components/subresource_filter/content/browser/async_document_subresource_filter_test_utils.h" @@ -75,9 +75,9 @@ testing::TestRulesetPair test_ruleset_pair_; // Note: ADSF assumes a task runner is associated with the current thread. - // Instantiate a MessageLoop on the current thread and use RunLoop to handle - // the replies ADSF tasks generate. - base::MessageLoop message_loop_; + // Instantiate a MessageLoop on the current thread and use base::RunLoop to + // handle the replies ADSF tasks generate. + base::test::ScopedTaskEnvironment task_environment_; scoped_refptr<base::TestSimpleTaskRunner> blocking_task_runner_ = new base::TestSimpleTaskRunner;
diff --git a/components/sync/driver/fake_sync_service.cc b/components/sync/driver/fake_sync_service.cc index cabcb00..99b135a 100644 --- a/components/sync/driver/fake_sync_service.cc +++ b/components/sync/driver/fake_sync_service.cc
@@ -65,6 +65,14 @@ void FakeSyncService::OnDataTypeRequestsSyncStartup(ModelType type) {} +ModelTypeSet FakeSyncService::GetRegisteredDataTypes() const { + return ModelTypeSet(); +} + +ModelTypeSet FakeSyncService::GetForcedDataTypes() const { + return ModelTypeSet(); +} + ModelTypeSet FakeSyncService::GetPreferredDataTypes() const { return ModelTypeSet(); }
diff --git a/components/sync/driver/fake_sync_service.h b/components/sync/driver/fake_sync_service.h index 417c022..b822ed05 100644 --- a/components/sync/driver/fake_sync_service.h +++ b/components/sync/driver/fake_sync_service.h
@@ -38,6 +38,8 @@ bool HasObserver(const SyncServiceObserver* observer) const override; void OnDataTypeRequestsSyncStartup(ModelType type) override; void StopAndClear() override; + ModelTypeSet GetRegisteredDataTypes() const override; + ModelTypeSet GetForcedDataTypes() const override; ModelTypeSet GetPreferredDataTypes() const override; std::unique_ptr<SyncSetupInProgressHandle> GetSetupInProgressHandle() override;
diff --git a/components/sync/driver/sync_service.h b/components/sync/driver/sync_service.h index 3832558..3893c727 100644 --- a/components/sync/driver/sync_service.h +++ b/components/sync/driver/sync_service.h
@@ -230,8 +230,17 @@ // DATA TYPE STATE ////////////////////////////////////////////////////////////////////////////// + // Returns the set of data types that are supported in principle. These will + // typically only change via a command-line option. + virtual syncer::ModelTypeSet GetRegisteredDataTypes() const = 0; + + // Returns the set of types which are enforced programmatically and can not + // be disabled by the user. + virtual syncer::ModelTypeSet GetForcedDataTypes() const = 0; + // Returns the set of types which are preferred for enabling. This is a - // superset of the active types (see GetActiveDataTypes()). + // superset of the active types (see GetActiveDataTypes()). This also includes + // any forced types. virtual ModelTypeSet GetPreferredDataTypes() const = 0; // Get the set of current active data types (those chosen or configured by
diff --git a/components/sync/driver/sync_service_utils.cc b/components/sync/driver/sync_service_utils.cc index 78b76dec..71947b5 100644 --- a/components/sync/driver/sync_service_utils.cc +++ b/components/sync/driver/sync_service_utils.cc
@@ -4,6 +4,7 @@ #include "components/sync/driver/sync_service_utils.h" +#include "base/metrics/histogram_macros.h" #include "components/sync/base/sync_prefs.h" #include "components/sync/driver/sync_service.h" #include "components/sync/engine/cycle/sync_cycle_snapshot.h" @@ -75,4 +76,8 @@ return UploadState::NOT_ACTIVE; } +void RecordSyncEvent(SyncEventCodes code) { + UMA_HISTOGRAM_ENUMERATION("Sync.EventCodes", code, MAX_SYNC_EVENT_CODE); +} + } // namespace syncer
diff --git a/components/sync/driver/sync_service_utils.h b/components/sync/driver/sync_service_utils.h index 65f29ec..dcd3772 100644 --- a/components/sync/driver/sync_service_utils.h +++ b/components/sync/driver/sync_service_utils.h
@@ -43,6 +43,31 @@ UploadState GetUploadToGoogleState(const SyncService* sync_service, ModelType type); +// NOTE: Used in a UMA histogram, do not reorder etc. +enum SyncEventCodes { + // Events starting the sync service. + // START_FROM_NTP = 1, + // START_FROM_WRENCH = 2, + // START_FROM_OPTIONS = 3, + // START_FROM_BOOKMARK_MANAGER = 4, + // START_FROM_PROFILE_MENU = 5, + // START_FROM_URL = 6, + + // Events regarding cancellation of the signon process of sync. + // CANCEL_FROM_SIGNON_WITHOUT_AUTH = 10, + // CANCEL_DURING_SIGNON = 11, + CANCEL_DURING_CONFIGURE = 12, // Cancelled before choosing data types and + // clicking OK. + + // Events resulting in the stoppage of sync service. + STOP_FROM_OPTIONS = 20, // Sync was stopped from Wrench->Options. + // STOP_FROM_ADVANCED_DIALOG = 21, + + MAX_SYNC_EVENT_CODE = 22 +}; + +void RecordSyncEvent(SyncEventCodes code); + } // namespace syncer #endif // COMPONENTS_SYNC_DRIVER_SYNC_SERVICE_UTILS_H_
diff --git a/components/sync/driver/test_sync_service.cc b/components/sync/driver/test_sync_service.cc index 5f42672c..47a1685 100644 --- a/components/sync/driver/test_sync_service.cc +++ b/components/sync/driver/test_sync_service.cc
@@ -154,6 +154,14 @@ return setup_in_progress_; } +ModelTypeSet TestSyncService::GetRegisteredDataTypes() const { + return ModelTypeSet::All(); +} + +ModelTypeSet TestSyncService::GetForcedDataTypes() const { + return ModelTypeSet(); +} + ModelTypeSet TestSyncService::GetPreferredDataTypes() const { return preferred_data_types_; }
diff --git a/components/sync/driver/test_sync_service.h b/components/sync/driver/test_sync_service.h index 0c406f3..7335e62 100644 --- a/components/sync/driver/test_sync_service.h +++ b/components/sync/driver/test_sync_service.h
@@ -60,6 +60,8 @@ override; bool IsSetupInProgress() const override; + ModelTypeSet GetRegisteredDataTypes() const override; + ModelTypeSet GetForcedDataTypes() const override; ModelTypeSet GetPreferredDataTypes() const override; ModelTypeSet GetActiveDataTypes() const override;
diff --git a/components/sync_bookmarks/bookmark_data_type_controller_unittest.cc b/components/sync_bookmarks/bookmark_data_type_controller_unittest.cc index c68a7a5..424738f2 100644 --- a/components/sync_bookmarks/bookmark_data_type_controller_unittest.cc +++ b/components/sync_bookmarks/bookmark_data_type_controller_unittest.cc
@@ -10,8 +10,8 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/callback.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" #include "base/threading/sequenced_task_runner_handle.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/test/bookmark_test_helpers.h" @@ -143,7 +143,7 @@ history_service_->NotifyHistoryServiceLoaded(); } - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment task_environment_; testing::NiceMock<syncer::SyncApiComponentFactoryMock> components_factory_; std::unique_ptr<BookmarkModel> bookmark_model_; std::unique_ptr<HistoryMock> history_service_;
diff --git a/components/test/data/autofill_assistant/autofill_assistant_target_website.html b/components/test/data/autofill_assistant/autofill_assistant_target_website.html index 8bcfd9f..65df22a 100644 --- a/components/test/data/autofill_assistant/autofill_assistant_target_website.html +++ b/components/test/data/autofill_assistant/autofill_assistant_target_website.html
@@ -49,6 +49,37 @@ #touch_area_three { position: absolute; } + + #terms-and-conditions { + position: absolute; + z-index: -1; + left: -9999px; + } + + label[for="terms-and-conditions"] { + padding-left: 48px; + position: relative; + display: inline-block; + min-height: 48px; + font-weight: normal; + } + + label[for="terms-and-conditions"]:before { + content: ""; + width: 32px; + height: 32px; + line-height: 32px; + border: 1px solid #acacac; + position: absolute; + z-index: 0; + top: 0; + left: 0; + text-align: center; + } + + #terms-and-conditions:checked + label[for="terms-and-conditions"]:before { + content: "\2714"; + } </style> </head> @@ -124,6 +155,11 @@ <iframe id="iframe" name="test_iframe" width="100%" height="500" src= "autofill_assistant_target_website_iframe_one.html"></iframe> + <input type="checkbox" id="terms-and-conditions" /> + <label for="terms-and-conditions" > + <a href="#">I have read and understood <br />the terms and conditions</a> + </label> + <script> let upperCaseInput = document.querySelector("#uppercase_input"); document.addEventListener('keyup', () => {
diff --git a/components/tracing/common/tracing_sampler_profiler.cc b/components/tracing/common/tracing_sampler_profiler.cc index 0090b155..f8c79fee 100644 --- a/components/tracing/common/tracing_sampler_profiler.cc +++ b/components/tracing/common/tracing_sampler_profiler.cc
@@ -142,35 +142,32 @@ slot.get()->Set(base::WrapUnique( new TracingSamplerProfiler(base::PlatformThread::CurrentId()))); } - TracingSamplerProfiler* profiler = slot.get()->Get().get(); - profiler->OnMessageLoopStarted(); } TracingSamplerProfiler::TracingSamplerProfiler( base::PlatformThreadId sampled_thread_id) - : sampled_thread_id_(sampled_thread_id), weak_ptr_factory_(this) { + : sampled_thread_id_(sampled_thread_id) { + DCHECK_NE(sampled_thread_id_, base::kInvalidThreadId); + // Make sure tracing system notices profiler category. TRACE_EVENT_WARMUP_CATEGORY(TRACE_DISABLED_BY_DEFAULT("cpu_profiler")); - DCHECK_NE(sampled_thread_id_, base::kInvalidThreadId); - - // In case tracing is currently running, start the sample profiler. The trace - // category can be enabled only if tracing is enabled. + // If tracing was enabled before initializing this class, we missed the + // OnTraceLogEnabled() event. Synthesize it so we can late-join the party. + // If the observer is added after the calling |OnTraceLogEnabled|, there is + // a race condition where tracing can be turned on between. By using this + // ordering, the |OnTraceLogEnabled| will be called twice if tracing is turned + // on between. + base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this); OnTraceLogEnabled(); } TracingSamplerProfiler::~TracingSamplerProfiler() { - base::trace_event::TraceLog::GetInstance()->RemoveAsyncEnabledStateObserver( - this); -} - -void TracingSamplerProfiler::OnMessageLoopStarted() { - base::trace_event::TraceLog::GetInstance()->AddAsyncEnabledStateObserver( - weak_ptr_factory_.GetWeakPtr()); - OnTraceLogEnabled(); + base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this); } void TracingSamplerProfiler::OnTraceLogEnabled() { + base::AutoLock lock(lock_); // Ensure there was not an instance of the profiler already running. if (profiler_.get()) return; @@ -205,6 +202,7 @@ } void TracingSamplerProfiler::OnTraceLogDisabled() { + base::AutoLock lock(lock_); if (!profiler_.get()) return; // Stop and release the stack sampling profiler.
diff --git a/components/tracing/common/tracing_sampler_profiler.h b/components/tracing/common/tracing_sampler_profiler.h index 8462d2ae0..16c0f016 100644 --- a/components/tracing/common/tracing_sampler_profiler.h +++ b/components/tracing/common/tracing_sampler_profiler.h
@@ -20,9 +20,15 @@ // This class is a bridge between the base stack sampling profiler and chrome // tracing. It's listening to TraceLog enabled/disabled events and it's starting -// a stack profiler on the current thread if needed. +// a stack profiler on the current thread if needed. The sampling profiler is +// lazily instantiated when tracing is activated and released when tracing is +// disabled. +// +// The TracingSamplerProfiler must be created and destroyed on the sampled +// thread. The tracelog observers can be called on any thread which force the +// field |profiler_| to be thread-safe. class TRACING_EXPORT TracingSamplerProfiler - : public base::trace_event::TraceLog::AsyncEnabledStateObserver { + : public base::trace_event::TraceLog::EnabledStateObserver { public: // Creates sampling profiler on main thread. Since the message loop might not // be setup when creating this profiler, the client must call @@ -36,11 +42,8 @@ ~TracingSamplerProfiler() override; - // Notify the profiler that the message loop for current thread is started. - // Only required for main thread. - void OnMessageLoopStarted(); - // trace_event::TraceLog::EnabledStateObserver implementation: + // These methods are thread-safe. void OnTraceLogEnabled() override; void OnTraceLogDisabled() override; @@ -48,9 +51,9 @@ explicit TracingSamplerProfiler(base::PlatformThreadId sampled_thread_id); const base::PlatformThreadId sampled_thread_id_; - std::unique_ptr<base::StackSamplingProfiler> profiler_; - base::WeakPtrFactory<TracingSamplerProfiler> weak_ptr_factory_; + base::Lock lock_; + std::unique_ptr<base::StackSamplingProfiler> profiler_; // under |lock_| DISALLOW_COPY_AND_ASSIGN(TracingSamplerProfiler); };
diff --git a/components/tracing/common/tracing_sampler_profiler_unittest.cc b/components/tracing/common/tracing_sampler_profiler_unittest.cc index 585a6f1..b3f9d63 100644 --- a/components/tracing/common/tracing_sampler_profiler_unittest.cc +++ b/components/tracing/common/tracing_sampler_profiler_unittest.cc
@@ -144,7 +144,6 @@ TEST_F(TracingSampleProfilerTest, OnSampleCompleted) { auto profiler = TracingSamplerProfiler::CreateOnMainThread(); - profiler->OnMessageLoopStarted(); BeginTrace(); base::RunLoop().RunUntilIdle(); WaitForEvents(); @@ -156,7 +155,6 @@ TEST_F(TracingSampleProfilerTest, JoinRunningTracing) { BeginTrace(); auto profiler = TracingSamplerProfiler::CreateOnMainThread(); - profiler->OnMessageLoopStarted(); base::RunLoop().RunUntilIdle(); WaitForEvents(); EndTracing();
diff --git a/components/translate/core/browser/translate_prefs.cc b/components/translate/core/browser/translate_prefs.cc index ab27062..1c6ffb36 100644 --- a/components/translate/core/browser/translate_prefs.cc +++ b/components/translate/core/browser/translate_prefs.cc
@@ -73,38 +73,6 @@ namespace { -// Expands language codes to make these more suitable for Accept-Language. -// Example: ['en-US', 'ja', 'en-CA'] => ['en-US', 'en', 'ja', 'en-CA']. -// 'en' won't appear twice as this function eliminates duplicates. -// The StringPieces in |expanded_languages| are references to the strings in -// |languages|. -void ExpandLanguageCodes(const std::vector<std::string>& languages, - std::vector<base::StringPiece>* expanded_languages) { - DCHECK(expanded_languages); - DCHECK(expanded_languages->empty()); - - // used to eliminate duplicates. - std::set<base::StringPiece> seen; - - for (const auto& language : languages) { - if (seen.find(language) == seen.end()) { - expanded_languages->push_back(language); - seen.insert(language); - } - - std::vector<base::StringPiece> tokens = base::SplitStringPiece( - language, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - if (tokens.size() == 0) - continue; - - base::StringPiece main_part = tokens[0]; - if (seen.find(main_part) == seen.end()) { - expanded_languages->push_back(main_part); - seen.insert(main_part); - } - } -} - // Extract a timestamp from a base::Value. // Will return base::Time() if no valid timestamp exists. base::Time GetTimeStamp(const base::Value& value) { @@ -115,9 +83,6 @@ } // namespace -const base::Feature kImprovedLanguageSettings{"ImprovedLanguageSettings", - base::FEATURE_ENABLED_BY_DEFAULT}; - const base::Feature kRegionalLocalesAsDisplayUI{ "RegionalLocalesAsDisplayUI", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -261,7 +226,6 @@ // We should block the language if the list does not already contain another // language with the same base language. const bool should_block = - !base::FeatureList::IsEnabled(kImprovedLanguageSettings) || !language::ContainsSameBaseLanguage(languages, chrome_language); if (force_blocked || should_block) { @@ -297,12 +261,10 @@ languages.erase(it); UpdateLanguageList(languages); - if (base::FeatureList::IsEnabled(kImprovedLanguageSettings)) { - // We should unblock the language if this was the last one from the same - // language family. - if (!language::ContainsSameBaseLanguage(languages, chrome_language)) { - UnblockLanguage(input_language); - } + // We should unblock the language if this was the last one from the same + // language family. + if (!language::ContainsSameBaseLanguage(languages, chrome_language)) { + UnblockLanguage(input_language); } } } @@ -474,11 +436,11 @@ base::UTF16ToUTF8(adjusted_native_display_name); std::string supports_translate_code = pair.first; - if (base::FeatureList::IsEnabled(translate::kImprovedLanguageSettings)) { - // Extract the base language: if the base language can be translated, then - // even the regional one should be marked as such. - translate::ToTranslateLanguageSynonym(&supports_translate_code); - } + + // Extract the base language: if the base language can be translated, then + // even the regional one should be marked as such. + translate::ToTranslateLanguageSynonym(&supports_translate_code); + language.supports_translate = translate_language_set.count(supports_translate_code) > 0; @@ -787,14 +749,6 @@ prefs_->SetString(preferred_languages_pref_, languages_str); #endif - // Save the same language list as accept languages preference as well, but we - // need to expand the language list, to make it more acceptable. For instance, - // some web sites don't understand 'en-US' but 'en'. See crosbug.com/9884. - if (!base::FeatureList::IsEnabled(kImprovedLanguageSettings)) { - std::vector<base::StringPiece> accept_languages; - ExpandLanguageCodes(languages, &accept_languages); - languages_str = base::JoinString(accept_languages, ","); - } prefs_->SetString(accept_languages_pref_, languages_str); }
diff --git a/components/translate/core/browser/translate_prefs.h b/components/translate/core/browser/translate_prefs.h index 71ac48f6..69dd4cb 100644 --- a/components/translate/core/browser/translate_prefs.h +++ b/components/translate/core/browser/translate_prefs.h
@@ -31,10 +31,6 @@ namespace translate { -// Enables or disables the new improved language settings. -// These settings support the new UI. -extern const base::Feature kImprovedLanguageSettings; - // Enables or disables the regional locales as valid selection for the display // UI. extern const base::Feature kRegionalLocalesAsDisplayUI;
diff --git a/components/translate/core/browser/translate_prefs_unittest.cc b/components/translate/core/browser/translate_prefs_unittest.cc index 54167eb..6de2c35 100644 --- a/components/translate/core/browser/translate_prefs_unittest.cc +++ b/components/translate/core/browser/translate_prefs_unittest.cc
@@ -271,43 +271,8 @@ now_ - base::TimeDelta::FromMinutes(2)); } -// The logic of UpdateLanguageList() changes based on the value of feature -// kImprovedLanguageSettings, which is a boolean. -// We write two separate test cases for true and false. TEST_F(TranslatePrefsTest, UpdateLanguageList) { - ScopedFeatureList disable_feature; - disable_feature.InitAndDisableFeature(translate::kImprovedLanguageSettings); - - // Empty update. - std::vector<std::string> languages; - translate_prefs_->UpdateLanguageList(languages); - ExpectLanguagePrefs(""); - - // One language. - languages = {"en"}; - translate_prefs_->UpdateLanguageList(languages); - ExpectLanguagePrefs("en"); - - // More than one language. - languages = {"en", "ja", "it"}; - translate_prefs_->UpdateLanguageList(languages); - ExpectLanguagePrefs("en,ja,it"); - - // Locale-specific codes. - // The list is exanded by adding the base languagese. - languages = {"en-US", "ja", "en-CA", "fr-CA"}; - translate_prefs_->UpdateLanguageList(languages); - ExpectLanguagePrefs("en-US,en,ja,en-CA,fr-CA,fr", "en-US,ja,en-CA,fr-CA"); - - // List already expanded. - languages = {"en-US", "en", "fr", "fr-CA"}; - translate_prefs_->UpdateLanguageList(languages); - ExpectLanguagePrefs("en-US,en,fr,fr-CA"); -} - -TEST_F(TranslatePrefsTest, UpdateLanguageListFeatureEnabled) { ScopedFeatureList enable_feature; - enable_feature.InitAndEnableFeature(translate::kImprovedLanguageSettings); // Empty update. std::vector<std::string> languages; @@ -387,86 +352,8 @@ EXPECT_THAT(display_names, ElementsAreArray(sorted)); } -// Check a sample of languages returned by GetLanguageInfoList(). -TEST_F(TranslatePrefsTest, GetLanguageInfoListSampleLanguages) { - ScopedFeatureList disable_feature; - disable_feature.InitAndDisableFeature(translate::kImprovedLanguageSettings); - - std::vector<TranslateLanguageInfo> language_list; - TranslateLanguageInfo language; - - //----------------------------------- - // Test with US locale. - TranslatePrefs::GetLanguageInfoList("en-US", true /* translate_enabled */, - &language_list); - - language = GetLanguageByCode("en", language_list); - EXPECT_EQ("en", language.code); - EXPECT_EQ("English", language.display_name); - EXPECT_EQ("English", language.native_display_name); - EXPECT_TRUE(language.supports_translate); - - language = GetLanguageByCode("en-US", language_list); - EXPECT_EQ("en-US", language.code); - EXPECT_EQ("English (United States)", language.display_name); - EXPECT_EQ("English (United States)", language.native_display_name); - EXPECT_FALSE(language.supports_translate); - - language = GetLanguageByCode("it", language_list); - EXPECT_EQ("it", language.code); - EXPECT_EQ("Italian", language.display_name); - EXPECT_EQ("italiano", language.native_display_name); - EXPECT_TRUE(language.supports_translate); - - language = GetLanguageByCode("it-IT", language_list); - EXPECT_EQ("it-IT", language.code); - EXPECT_EQ("Italian (Italy)", language.display_name); - EXPECT_EQ("italiano (Italia)", language.native_display_name); - EXPECT_FALSE(language.supports_translate); - - language = GetLanguageByCode("ru", language_list); - EXPECT_EQ("ru", language.code); - EXPECT_EQ("Russian", language.display_name); - EXPECT_EQ("русский", language.native_display_name); - EXPECT_TRUE(language.supports_translate); - - //----------------------------------- - // Test with Italian locale. - language_list.clear(); - TranslatePrefs::GetLanguageInfoList("it", true /* translate_enabled */, - &language_list); - - language = GetLanguageByCode("en-US", language_list); - EXPECT_EQ("en-US", language.code); - EXPECT_EQ("inglese (Stati Uniti)", language.display_name); - EXPECT_EQ("English (United States)", language.native_display_name); - EXPECT_FALSE(language.supports_translate); - - language = GetLanguageByCode("it", language_list); - EXPECT_EQ("it", language.code); - EXPECT_EQ("italiano", language.display_name); - EXPECT_EQ("italiano", language.native_display_name); - EXPECT_TRUE(language.supports_translate); - - language = GetLanguageByCode("it-IT", language_list); - EXPECT_EQ("it-IT", language.code); - EXPECT_EQ("italiano (Italia)", language.display_name); - EXPECT_EQ("italiano (Italia)", language.native_display_name); - EXPECT_FALSE(language.supports_translate); - - language = GetLanguageByCode("fr-FR", language_list); - EXPECT_EQ("fr-FR", language.code); - EXPECT_EQ("francese (Francia)", language.display_name); - EXPECT_EQ("français (France)", language.native_display_name); - EXPECT_FALSE(language.supports_translate); -} - -// With feature enabled, GetLanguageInfoList() should set different values for -// supports_translate. -// TODO(claudiomagni): Clean up this method once the feature is launched. -TEST_F(TranslatePrefsTest, GetLanguageInfoListFeatureEnabled) { +TEST_F(TranslatePrefsTest, GetLanguageInfoList) { ScopedFeatureList enable_feature; - enable_feature.InitAndEnableFeature(translate::kImprovedLanguageSettings); std::vector<TranslateLanguageInfo> language_list; TranslateLanguageInfo language; @@ -565,63 +452,8 @@ ExpectBlockedLanguageListContent({"zh-TW"}); } -TEST_F(TranslatePrefsTest, AddToLanguageList) { - ScopedFeatureList disable_feature; - disable_feature.InitAndDisableFeature(translate::kImprovedLanguageSettings); - std::vector<std::string> languages; - - // One language. - translate_prefs_->UpdateLanguageList(languages); - translate_prefs_->ClearBlockedLanguages(); - translate_prefs_->AddToLanguageList("it-IT", /*force_blocked=*/true); - ExpectLanguagePrefs("it-IT,it", "it-IT"); - ExpectBlockedLanguageListContent({"it"}); - - // Multiple languages. - translate_prefs_->UpdateLanguageList(languages); - translate_prefs_->ClearBlockedLanguages(); - translate_prefs_->AddToLanguageList("it-IT", /*force_blocked=*/true); - translate_prefs_->AddToLanguageList("fr-FR", /*force_blocked=*/true); - translate_prefs_->AddToLanguageList("fr-CA", /*force_blocked=*/true); - ExpectLanguagePrefs("it-IT,it,fr-FR,fr,fr-CA", "it-IT,fr-FR,fr-CA"); - ExpectBlockedLanguageListContent({"it", "fr"}); - - // Language already in list. - languages = {"en-US", "es-AR"}; - translate_prefs_->UpdateLanguageList(languages); - translate_prefs_->ClearBlockedLanguages(); - translate_prefs_->AddToLanguageList("es-AR", /*force_blocked=*/true); - ExpectLanguagePrefs("en-US,en,es-AR,es", "en-US,es-AR"); - ExpectBlockedLanguageListContent({"es"}); - - // Language from same family already in list. - languages = {"en-US", "es-AR"}; - translate_prefs_->UpdateLanguageList(languages); - translate_prefs_->ClearBlockedLanguages(); - translate_prefs_->AddToLanguageList("es-ES", /*force_blocked=*/true); - ExpectLanguagePrefs("en-US,en,es-AR,es,es-ES", "en-US,es-AR,es-ES"); - ExpectBlockedLanguageListContent({"es"}); - - // Force blocked false, language not already in list. - languages = {"en-US"}; - translate_prefs_->UpdateLanguageList(languages); - translate_prefs_->ClearBlockedLanguages(); - translate_prefs_->AddToLanguageList("it-IT", /*force_blocked=*/false); - ExpectLanguagePrefs("en-US,en,it-IT,it", "en-US,it-IT"); - ExpectBlockedLanguageListContent({"it"}); - - // Force blocked false, language from same family already in list. - languages = {"en-US", "es-AR"}; - translate_prefs_->UpdateLanguageList(languages); - translate_prefs_->ClearBlockedLanguages(); - translate_prefs_->AddToLanguageList("es-ES", /*force_blocked=*/false); - ExpectLanguagePrefs("en-US,en,es-AR,es,es-ES", "en-US,es-AR,es-ES"); - ExpectBlockedLanguageListContent({"es"}); -} - TEST_F(TranslatePrefsTest, AddToLanguageListFeatureEnabled) { ScopedFeatureList enable_feature; - enable_feature.InitAndEnableFeature(translate::kImprovedLanguageSettings); std::vector<std::string> languages; // Force blocked false, language not already in list. @@ -641,94 +473,8 @@ ExpectBlockedLanguageListContent({}); } -TEST_F(TranslatePrefsTest, RemoveFromLanguageList) { - ScopedFeatureList disable_feature; - disable_feature.InitAndDisableFeature(translate::kImprovedLanguageSettings); - std::vector<std::string> languages; - - // Remove from empty list. - translate_prefs_->UpdateLanguageList(languages); - translate_prefs_->ClearBlockedLanguages(); - translate_prefs_->RemoveFromLanguageList("it-IT"); - ExpectLanguagePrefs(""); - ExpectBlockedLanguageListContent({}); - - // Languages are never unblocked. - languages = {"en-US", "es-AR", "es-ES"}; - translate_prefs_->UpdateLanguageList(languages); - translate_prefs_->ClearBlockedLanguages(); - translate_prefs_->BlockLanguage("en-US"); - translate_prefs_->BlockLanguage("es-AR"); - translate_prefs_->RemoveFromLanguageList("es-ES"); - ExpectLanguagePrefs("en-US,en,es-AR,es", "en-US,es-AR"); - ExpectBlockedLanguageListContent({"en", "es"}); - -// With the feature disabled, some behaviors for ChromeOS are different from -// other platforms and should be tested separately. -#if defined(OS_CHROMEOS) - - // One language. - languages = {"it-IT"}; - translate_prefs_->UpdateLanguageList(languages); - translate_prefs_->ClearBlockedLanguages(); - translate_prefs_->RemoveFromLanguageList("it-IT"); - ExpectLanguagePrefs(""); - ExpectBlockedLanguageListContent({}); - - // Multiple languages. - languages = {"en-US", "es-AR", "fr-CA"}; - translate_prefs_->UpdateLanguageList(languages); - translate_prefs_->ClearBlockedLanguages(); - translate_prefs_->RemoveFromLanguageList("es-AR"); - translate_prefs_->RemoveFromLanguageList("fr-CA"); - ExpectLanguagePrefs("en-US,en", "en-US"); - ExpectBlockedLanguageListContent({}); - - // Languages are never unblocked, even if it's the last of a family. - languages = {"en-US", "es-AR"}; - translate_prefs_->UpdateLanguageList(languages); - translate_prefs_->ClearBlockedLanguages(); - translate_prefs_->BlockLanguage("en-US"); - translate_prefs_->BlockLanguage("es-AR"); - translate_prefs_->RemoveFromLanguageList("es-AR"); - ExpectLanguagePrefs("en-US,en", "en-US"); - ExpectBlockedLanguageListContent({"en", "es"}); - -#else - - // One language. - languages = {"it-IT"}; - translate_prefs_->UpdateLanguageList(languages); - translate_prefs_->ClearBlockedLanguages(); - translate_prefs_->RemoveFromLanguageList("it-IT"); - ExpectLanguagePrefs("it"); - ExpectBlockedLanguageListContent({}); - - // Multiple languages. - languages = {"en-US", "es-AR", "fr-CA"}; - translate_prefs_->UpdateLanguageList(languages); - translate_prefs_->ClearBlockedLanguages(); - translate_prefs_->RemoveFromLanguageList("es-AR"); - translate_prefs_->RemoveFromLanguageList("fr-CA"); - ExpectLanguagePrefs("en-US,en,es,fr"); - ExpectBlockedLanguageListContent({}); - - // Languages are never unblocked, even if it's the last of a family. - languages = {"en-US", "es-AR"}; - translate_prefs_->UpdateLanguageList(languages); - translate_prefs_->ClearBlockedLanguages(); - translate_prefs_->BlockLanguage("en-US"); - translate_prefs_->BlockLanguage("es-AR"); - translate_prefs_->RemoveFromLanguageList("es-AR"); - ExpectLanguagePrefs("en-US,en,es"); - ExpectBlockedLanguageListContent({"en", "es"}); - -#endif -} - TEST_F(TranslatePrefsTest, RemoveFromLanguageListFeatureEnabled) { ScopedFeatureList enable_feature; - enable_feature.InitAndEnableFeature(translate::kImprovedLanguageSettings); std::vector<std::string> languages; // Unblock last language of a family.
diff --git a/components/ui_devtools/views/overlay_agent_aura.cc b/components/ui_devtools/views/overlay_agent_aura.cc index deba833a..4fd9c64 100644 --- a/components/ui_devtools/views/overlay_agent_aura.cc +++ b/components/ui_devtools/views/overlay_agent_aura.cc
@@ -11,11 +11,13 @@ #include "components/ui_devtools/views/window_element.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/effects/SkDashPathEffect.h" -#include "ui/aura/client/screen_position_client.h" #include "ui/aura/env.h" #include "ui/compositor/paint_recorder.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" #include "ui/events/event.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/render_text.h" #include "ui/views/background.h" #include "ui/views/border.h" @@ -530,20 +532,26 @@ } gfx::NativeWindow root = window_and_bounds.first->GetRootWindow(); +#if defined(OS_CHROMEOS) + // Get the screen's display-root window; otherwise, if the window belongs to + // a window service client, |root| will only be a client-root window. + aura::Window* window = display::Screen::GetScreen()->GetWindowAtScreenPoint( + root->GetBoundsInScreen().origin()); + if (window) // May be null in unit tests. + root = window->GetRootWindow(); +#endif // OS_CHROMEOS + layer_for_highlighting_->SetBounds(root->bounds()); layer_for_highlighting_->SchedulePaint(root->bounds()); + layer_for_highlighting_screen_offset_ = + root->GetBoundsInScreen().OffsetFromOrigin(); if (root->layer() != layer_for_highlighting_->parent()) root->layer()->Add(layer_for_highlighting_.get()); else root->layer()->StackAtTop(layer_for_highlighting_.get()); - aura::client::ScreenPositionClient* screen_position_client = - aura::client::GetScreenPositionClient(root); hovered_rect_ = window_and_bounds.second; - gfx::Point origin = hovered_rect_.origin(); - screen_position_client->ConvertPointFromScreen(root, &origin); - hovered_rect_.set_origin(origin); return true; } @@ -624,7 +632,9 @@ const gfx::Rect& screen_bounds(layer_for_highlighting_->bounds()); ui::PaintRecorder recorder(context, screen_bounds.size()); gfx::Canvas* canvas = recorder.canvas(); + // Convert the hovered rect from screen coordinates to layer coordinates. gfx::RectF hovered_rect_f(hovered_rect_); + hovered_rect_f.Offset(-layer_for_highlighting_screen_offset_); cc::PaintFlags flags; flags.setStrokeWidth(1.0f); @@ -648,15 +658,17 @@ // Display size of the rectangle after mouse click. if (show_size_on_canvas_) { - DrawSizeOfRectangle(hovered_rect_, RectSide::BOTTOM_SIDE, canvas, - render_text_.get()); + DrawSizeOfRectangle(gfx::ToNearestRect(hovered_rect_f), + RectSide::BOTTOM_SIDE, canvas, render_text_.get()); } return; } flags.setPathEffect(nullptr); flags.setColor(SK_ColorBLUE); + // Convert the pinned rect from screen coordinates to layer coordinates. gfx::RectF pinned_rect_f(pinned_rect_); + pinned_rect_f.Offset(-layer_for_highlighting_screen_offset_); // Draw |pinned_rect_f| bounds in blue. canvas->DrawRect(pinned_rect_f, flags); @@ -670,9 +682,9 @@ flags.setColor(SK_ColorRED); // Make sure |pinned_rect_f| stays on the right or below of |hovered_rect_f|. - if (pinned_rect_.x() < hovered_rect_.x() || - (pinned_rect_.x() == hovered_rect_.x() && - pinned_rect_.y() < hovered_rect_.y())) { + if (pinned_rect_f.x() < hovered_rect_f.x() || + (pinned_rect_f.x() == hovered_rect_f.x() && + pinned_rect_f.y() < hovered_rect_f.y())) { std::swap(pinned_rect_f, hovered_rect_f); }
diff --git a/components/ui_devtools/views/overlay_agent_aura.h b/components/ui_devtools/views/overlay_agent_aura.h index 23124f9..d21c20ec 100644 --- a/components/ui_devtools/views/overlay_agent_aura.h +++ b/components/ui_devtools/views/overlay_agent_aura.h
@@ -108,9 +108,14 @@ HighlightRectsConfiguration highlight_rect_config_; bool is_swap_ = false; + // The layer used to paint highlights, and its offset from the screen origin. std::unique_ptr<ui::Layer> layer_for_highlighting_; + gfx::Vector2d layer_for_highlighting_screen_offset_; + + // Hovered and pinned element bounds in screen coordinates; empty if none. gfx::Rect hovered_rect_; gfx::Rect pinned_rect_; + int pinned_id_ = 0; DISALLOW_COPY_AND_ASSIGN(OverlayAgentAura);
diff --git a/components/ukm/observers/sync_disable_observer.cc b/components/ukm/observers/sync_disable_observer.cc index 0309c13..58ef844 100644 --- a/components/ukm/observers/sync_disable_observer.cc +++ b/components/ukm/observers/sync_disable_observer.cc
@@ -243,17 +243,14 @@ must_purge = previous_state.AllowsUkm() && !state.AllowsUkm(); } else { // Use the previous logic to investigate crbug.com/891777. - must_purge = - // Trigger a purge if history sync was disabled. - (previous_state.history_enabled && !state.history_enabled) || - // Trigger a purge if engine has become disabled. - (previous_state.initialized && !state.initialized) || - // Trigger a purge if the user added a passphrase. Since we can't - // detect the use of a passphrase while the engine is not initialized, - // we may miss the transition if the user adds a passphrase in this - // state. - (previous_state.initialized && state.initialized && - !previous_state.passphrase_protected && state.passphrase_protected); + bool previous_state_allowed_ukm = previous_state.history_enabled && + previous_state.initialized && + !previous_state.passphrase_protected; + bool current_state_allows_ukm = state.history_enabled && + state.initialized && + !state.passphrase_protected; + // Trigger a purge if UKM used to be allowed, but isn't anymore. + must_purge = previous_state_allowed_ukm && !current_state_allows_ukm; } UMA_HISTOGRAM_BOOLEAN("UKM.SyncDisable.Purge", must_purge);
diff --git a/components/unified_consent/unified_consent_service_unittest.cc b/components/unified_consent/unified_consent_service_unittest.cc index efa4227..13d51fd2 100644 --- a/components/unified_consent/unified_consent_service_unittest.cc +++ b/components/unified_consent/unified_consent_service_unittest.cc
@@ -6,9 +6,10 @@ #include <map> #include <memory> +#include "base/run_loop.h" -#include "base/message_loop/message_loop.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_task_environment.h" #include "build/build_config.h" #include "components/autofill/core/common/autofill_prefs.h" #include "components/sync/base/sync_prefs.h" @@ -183,7 +184,7 @@ } protected: - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment task_environment_; sync_preferences::TestingPrefServiceSyncable pref_service_; identity::IdentityTestEnvironment identity_test_environment_; TestSyncService sync_service_;
diff --git a/components/variations/service/variations_service.cc b/components/variations/service/variations_service.cc index 74fa1a7..75fc26a 100644 --- a/components/variations/service/variations_service.cc +++ b/components/variations/service/variations_service.cc
@@ -426,6 +426,14 @@ // Chrome OS may switch language on the fly. DCHECK_EQ(locale, field_trial_creator_.application_locale()); #else + +#if defined(OS_ANDROID) + // TODO(asvitkine): Speculative early return to silence CHECK failures on + // Android, see crbug.com/912320. + if (locale.empty()) + return; +#endif + // Uses a CHECK rather than a DCHECK to ensure that issues are caught since // problems in this area may only appear in the wild due to official builds // and end user machines. @@ -553,8 +561,11 @@ std::move(resource_request), traffic_annotation); // Ensure our callback is called even with "304 Not Modified" responses. pending_seed_request_->SetAllowHttpErrorResults(true); + // Set the redirect callback so we can cancel on redirects. // base::Unretained is safe here since this class owns // |pending_seed_request_|'s lifetime. + pending_seed_request_->SetOnRedirectCallback(base::BindRepeating( + &VariationsService::OnSimpleLoaderRedirect, base::Unretained(this))); pending_seed_request_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( client_->GetURLLoaderFactory().get(), base::BindOnce(&VariationsService::OnSimpleLoaderComplete, @@ -668,24 +679,51 @@ void VariationsService::OnSimpleLoaderComplete( std::unique_ptr<std::string> response_body) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + OnSimpleLoaderCompleteOrRedirect(std::move(response_body), false); +} +void VariationsService::OnSimpleLoaderRedirect( + const net::RedirectInfo& redirect_info, + const network::ResourceResponseHead& response_head, + std::vector<std::string>* to_be_removed_headers) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + OnSimpleLoaderCompleteOrRedirect(nullptr, true); +} + +void VariationsService::OnSimpleLoaderCompleteOrRedirect( + std::unique_ptr<std::string> response_body, + bool was_redirect) { const bool is_first_request = !initial_request_completed_; initial_request_completed_ = true; - int net_error = pending_seed_request_->NetError(); - int response_code = -1; + bool is_success = false; + int net_error = net::ERR_ABORTED; scoped_refptr<net::HttpResponseHeaders> headers; - if (pending_seed_request_->ResponseInfo() && - pending_seed_request_->ResponseInfo()->headers) { - headers = pending_seed_request_->ResponseInfo()->headers; - response_code = headers->response_code(); - } - bool is_success = headers && (net_error == net::OK); + + int response_code = -1; // We use the final URL HTTPS/HTTP value to pass to StoreSeed, since // signature validation should be forced on for any HTTP fetch, including - // redirects from HTTPS to HTTP. - bool final_url_was_https = - pending_seed_request_->GetFinalURL().SchemeIs(url::kHttpsScheme); + // redirects from HTTPS to HTTP. We default to false since we can't get this + // value (nor will it be used) in the redirect case. + bool final_url_was_https = false; + + // Variations seed fetches should not follow redirects, so if this request was + // redirected, keep the default values for |net_error| and |is_success| (treat + // it as a net::ERR_ABORTED), and the fetch will be cancelled when + // pending_seed_request is reset. + if (!was_redirect) { + final_url_was_https = + pending_seed_request_->GetFinalURL().SchemeIs(url::kHttpsScheme); + const network::ResourceResponseHead* response_info = + pending_seed_request_->ResponseInfo(); + if (response_info && response_info->headers) { + headers = response_info->headers; + response_code = headers->response_code(); + } + net_error = pending_seed_request_->NetError(); + is_success = headers && (net_error == net::OK); + } + pending_seed_request_.reset(); if (last_request_was_http_retry_) { base::UmaHistogramSparse("Variations.SeedFetchResponseOrErrorCode",
diff --git a/components/variations/service/variations_service.h b/components/variations/service/variations_service.h index b299f12..217a7c5 100644 --- a/components/variations/service/variations_service.h +++ b/components/variations/service/variations_service.h
@@ -27,6 +27,8 @@ #include "components/variations/variations_seed_store.h" #include "components/version_info/version_info.h" #include "components/web_resource/resource_request_allowed_notifier.h" +#include "net/url_request/redirect_info.h" +#include "services/network/public/cpp/resource_response.h" #include "url/gurl.h" class PrefService; @@ -311,6 +313,17 @@ // Called by SimpleURLLoader when |pending_seed_request_| load completes. void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body); + // Called by SimpleURLLoader when |pending_seed_request_| load is redirected. + void OnSimpleLoaderRedirect( + const net::RedirectInfo& redirect_info, + const network::ResourceResponseHead& response_head, + std::vector<std::string>* to_be_removed_headers); + + // Handles post-fetch events. + void OnSimpleLoaderCompleteOrRedirect( + std::unique_ptr<std::string> response_body, + bool was_redirect); + // Retry the fetch over HTTP, called by OnSimpleLoaderComplete when a request // fails. Returns true is the fetch was successfully started, this does not // imply the actual fetch was successful.
diff --git a/components/variations/service/variations_service_unittest.cc b/components/variations/service/variations_service_unittest.cc index 03c0707..626f900c 100644 --- a/components/variations/service/variations_service_unittest.cc +++ b/components/variations/service/variations_service_unittest.cc
@@ -45,6 +45,7 @@ #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/test/test_network_connection_tracker.h" #include "services/network/test/test_url_loader_factory.h" +#include "services/network/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace variations { @@ -965,6 +966,34 @@ EXPECT_FALSE(service.fetch_attempted()); } +TEST_F(VariationsServiceTest, SeedNotStoredWhenRedirected) { + VariationsService::EnableFetchForTesting(); + + TestVariationsService service( + std::make_unique<web_resource::TestRequestAllowedNotifier>( + &prefs_, network_tracker_), + &prefs_, GetMetricsStateManager(), true); + + EXPECT_FALSE(service.seed_stored()); + + net::RedirectInfo redirect_info; + redirect_info.status_code = 301; + redirect_info.new_url = service.interception_url(); + network::TestURLLoaderFactory::Redirects redirects{ + {redirect_info, network::ResourceResponseHead()}}; + + network::ResourceResponseHead head = + network::CreateResourceResponseHead(net::HTTP_OK); + + service.test_url_loader_factory()->AddResponse( + service.interception_url(), head, SerializeSeed(CreateTestSeed()), + network::URLLoaderCompletionStatus(), redirects); + + service.set_intercepts_fetch(false); + service.DoActualFetch(); + EXPECT_FALSE(service.seed_stored()); +} + // TODO(isherman): Add an integration test for saving and loading a safe seed, // once the loading functionality is implemented on the seed store.
diff --git a/components/version_info/android/BUILD.gn b/components/version_info/android/BUILD.gn index 3d5ee847..fd542402 100644 --- a/components/version_info/android/BUILD.gn +++ b/components/version_info/android/BUILD.gn
@@ -3,23 +3,23 @@ # found in the LICENSE file. import("//build/config/android/rules.gni") -import("//build/config/zip.gni") import("//build/util/process_version.gni") import("//chrome/android/channel.gni") +_version_constants_java_file = "$target_gen_dir/java/org/chromium/components/version_info/VersionConstants.java" + # Depend on this on the Java side to get org.components.version_info.Channel and # org.components.version_info.VersionConstants. android_library("version_constants_java") { java_files = [ "java/src/org/chromium/components/version_info/VersionConstantsBridge.java", + _version_constants_java_file, ] deps = [ + ":generate_version_constants", "//base:base_java", ] - srcjar_deps = [ - ":channel_enum_srcjar", - ":version_constants_srcjar", - ] + srcjar_deps = [ ":channel_enum_srcjar" ] } # Depend on this on the native side to get version_info::GetChannel. It requires @@ -41,21 +41,9 @@ ] } -version_constants_java_file = "$target_gen_dir/java/org/chromium/components/version_info/VersionConstants.java" -zip("version_constants_srcjar") { - inputs = [ - version_constants_java_file, - ] - output = "$target_gen_dir/$target_name.srcjar" - base_dir = "$target_gen_dir/java" - deps = [ - ":generate_version_constants_java", - ] -} - -process_version("generate_version_constants_java") { +process_version("generate_version_constants") { template_file = "java/VersionConstants.java.version" - output = version_constants_java_file + output = _version_constants_java_file sources = [ "//chrome/VERSION", ]
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn index fd0ee4f9..e368572d 100644 --- a/components/viz/common/BUILD.gn +++ b/components/viz/common/BUILD.gn
@@ -3,8 +3,8 @@ # found in the LICENSE file. import("//components/viz/viz.gni") -import("//testing/test.gni") import("//gpu/vulkan/features.gni") +import("//testing/test.gni") source_set("resource_format") { sources = [ @@ -45,6 +45,13 @@ defines = [ "VIZ_VULKAN_CONTEXT_PROVIDER_IMPLEMENTATION" ] + # TODO(cblume): http://crbug.com/911313 + # Abstract out the platform specific defines. Right now we need the android + # platform specific define here to be able to include android specific + # functions. + if (is_android) { + defines += [ "VK_USE_PLATFORM_ANDROID_KHR" ] + } sources = [ "gpu/vulkan_context_provider.h", "gpu/vulkan_in_process_context_provider.cc",
diff --git a/components/viz/service/display/direct_renderer.cc b/components/viz/service/display/direct_renderer.cc index 0b491d5..13d5605 100644 --- a/components/viz/service/display/direct_renderer.cc +++ b/components/viz/service/display/direct_renderer.cc
@@ -526,17 +526,8 @@ for (int i = 0; i < settings_->slow_down_compositing_scale_factor; ++i) DrawRenderPass(render_pass); - bool first_request = true; - for (auto& copy_request : render_pass->copy_requests) { - // CopyDrawnRenderPass() can change the binding of the framebuffer target as - // a part of its usual scaling and readback operations. Therefore, make sure - // to restore the correct framebuffer between readbacks. (Even if it did - // not, a Mac-specific bug requires this workaround: http://crbug.com/99393) - if (!first_request) - UseRenderPass(render_pass); + for (auto& copy_request : render_pass->copy_requests) CopyDrawnRenderPass(std::move(copy_request)); - first_request = false; - } } void DirectRenderer::DrawRenderPass(const RenderPass* render_pass) {
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc index b247dae..8f228a4 100644 --- a/components/viz/service/display/gl_renderer.cc +++ b/components/viz/service/display/gl_renderer.cc
@@ -665,10 +665,6 @@ if (!backdrop_filters) return false; DCHECK(!backdrop_filters->IsEmpty()); - - // TODO(hendrikw): Look into allowing background filters to see pixels from - // other render targets. See crbug.com/314867. - return true; } @@ -812,19 +808,36 @@ sk_sp<SkImage> GLRenderer::ApplyBackgroundFilters( const RenderPassDrawQuad* quad, - const cc::FilterOperations& backdrop_filters, + const cc::FilterOperations* backdrop_filters, + const cc::FilterOperations* regular_filters, uint32_t background_texture, const gfx::Rect& rect, const gfx::Rect& unclipped_rect, const float backdrop_filter_quality) { - DCHECK(ShouldApplyBackgroundFilters(quad, &backdrop_filters)); + DCHECK(ShouldApplyBackgroundFilters(quad, backdrop_filters)); auto use_gr_context = ScopedUseGrContext::Create(this); gfx::Vector2d clipping_offset = (rect.top_right() - unclipped_rect.top_right()) + (rect.bottom_left() - unclipped_rect.bottom_left()); + + // Update the backdrop filter to include "regular" filters and opacity. + cc::FilterOperations backdrop_filters_plus_effects = *backdrop_filters; + bool need_prepaint = false; + if (regular_filters) { + need_prepaint = true; + for (const auto& filter_op : regular_filters->operations()) + backdrop_filters_plus_effects.Append(filter_op); + } + if (quad->shared_quad_state->opacity < 1.0) { + need_prepaint = true; + backdrop_filters_plus_effects.Append( + cc::FilterOperation::CreateOpacityFilter( + quad->shared_quad_state->opacity)); + } + auto paint_filter = cc::RenderSurfaceFilters::BuildImageFilter( - backdrop_filters, gfx::SizeF(rect.size()), + backdrop_filters_plus_effects, gfx::SizeF(rect.size()), gfx::Vector2dF(clipping_offset)); // TODO(senorblanco): background filters should be moved to the @@ -871,6 +884,16 @@ paint.setImageFilter(filter->makeWithLocalMatrix(local_matrix)); surface->getCanvas()->translate(-quality_adjusted_rect.x(), -quality_adjusted_rect.y()); + if (need_prepaint) { + // If we have filters or opacity applied, in addition to the backdrop- + // filter, then first paint the backdrop (unfiltered) at full opacity. The + // backdrop-filtered content will not be blended with the backdrop later, it + // will be rastered over the top. + surface->getCanvas()->drawImageRect( + src_image, SkRect::MakeWH(rect.width(), rect.height()), + RectToSkRect(quality_adjusted_rect), nullptr); + } + // Then paint with the backdrop-filter, plus other filters and opacity. surface->getCanvas()->drawImageRect( src_image, SkRect::MakeWH(rect.width(), rect.height()), RectToSkRect(quality_adjusted_rect), &paint); @@ -1053,8 +1076,8 @@ // Apply the background filters to R, so that it is applied in the // pixels' coordinate space. params->background_image = ApplyBackgroundFilters( - quad, *params->backdrop_filters, params->background_texture, - params->background_rect, unclipped_rect, + quad, params->backdrop_filters, params->filters, + params->background_texture, params->background_rect, unclipped_rect, params->backdrop_filter_quality); if (params->background_image) { params->background_image_id = @@ -2540,6 +2563,15 @@ // The copier modified texture/framebuffer bindings, shader programs, and // other GL state; and so this must be restored before continuing. RestoreGLState(); + + // CopyDrawnRenderPass() can change the binding of the framebuffer target as + // a part of its usual scaling and readback operations. It will break next + // CopyDrawnRenderPass() call for the root render pass. Therefore, make sure + // to restore the correct framebuffer between readbacks. (Even if it did + // not, a Mac-specific bug requires this workaround: http://crbug.com/99393) + const auto* render_pass = current_frame()->current_render_pass; + if (render_pass == current_frame()->root_render_pass) + BindFramebufferToOutputSurface(); } void GLRenderer::ToGLMatrix(float* gl_matrix, const gfx::Transform& transform) {
diff --git a/components/viz/service/display/gl_renderer.h b/components/viz/service/display/gl_renderer.h index 9ef28e9..a63fe91 100644 --- a/components/viz/service/display/gl_renderer.h +++ b/components/viz/service/display/gl_renderer.h
@@ -206,9 +206,18 @@ static bool ShouldApplyBackgroundFilters( const RenderPassDrawQuad* quad, const cc::FilterOperations* backdrop_filters); + // Applies the backdrop filters to the backdrop that has been painted to this + // point, and returns it as an SkImage. Any opacity and/or "regular" + // (non-backdrop) filters will also be applied directly to the backdrop- + // filtered image at this point, so that the final result is as if the + // filtered backdrop image was painted as the starting point for this new + // stacking context, which would then be painted into its parent with opacity + // and filters applied. This is an approximation, but it should be close + // enough. sk_sp<SkImage> ApplyBackgroundFilters( const RenderPassDrawQuad* quad, - const cc::FilterOperations& backdrop_filters, + const cc::FilterOperations* backdrop_filters, + const cc::FilterOperations* regular_filters, uint32_t background_texture, const gfx::Rect& rect, const gfx::Rect& unclipped_rect,
diff --git a/components/viz/service/display/gl_renderer_unittest.cc b/components/viz/service/display/gl_renderer_unittest.cc index 521882e..37a1bb5 100644 --- a/components/viz/service/display/gl_renderer_unittest.cc +++ b/components/viz/service/display/gl_renderer_unittest.cc
@@ -4154,6 +4154,10 @@ /*secure_output_only=*/false, ui::ProtectedVideoType::kClear); EXPECT_CALL(overlay_scheduler, + Schedule(0, gfx::OVERLAY_TRANSFORM_NONE, kSurfaceOverlayTextureId, + gfx::Rect(viewport_size), _, _, kGpuFenceId)) + .Times(1); + EXPECT_CALL(overlay_scheduler, Schedule(1, gfx::OVERLAY_TRANSFORM_NONE, _, gfx::Rect(viewport_size), _, _, kGpuFenceId)) .Times(1);
diff --git a/components/viz/service/display/overlay_processor.cc b/components/viz/service/display/overlay_processor.cc index 54069e5..e5be9d9 100644 --- a/components/viz/service/display/overlay_processor.cc +++ b/components/viz/service/display/overlay_processor.cc
@@ -9,7 +9,6 @@ #include "base/metrics/histogram_macros.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" -#include "components/viz/common/quads/solid_color_draw_quad.h" #include "components/viz/service/display/dc_layer_overlay.h" #include "components/viz/service/display/display_resource_provider.h" #include "components/viz/service/display/output_surface.h" @@ -252,61 +251,4 @@ damage_rect->Union(output_surface_overlay_damage_rect); } -namespace { - -bool DiscardableQuad(const DrawQuad* q) { - float opacity = q->shared_quad_state->opacity; - if (opacity < std::numeric_limits<float>::epsilon()) - return true; - - if (q->material == DrawQuad::SOLID_COLOR) { - if (SolidColorDrawQuad::MaterialCast(q)->color == SK_ColorBLACK || - SolidColorDrawQuad::MaterialCast(q)->color == SK_ColorTRANSPARENT) - return true; - - const SkColor color = SolidColorDrawQuad::MaterialCast(q)->color; - const float alpha = (SkColorGetA(color) * (1.0f / 255.0f)) * opacity; - return q->ShouldDrawWithBlending() && - alpha < std::numeric_limits<float>::epsilon(); - } - - return false; -} - -} // namespace - -// static -void OverlayProcessor::EliminateOrCropPrimary( - const QuadList& quad_list, - const QuadList::Iterator& candidate_iterator, - OverlayCandidate* primary, - OverlayCandidateList* candidate_list) { - gfx::RectF content_rect; - - for (auto it = quad_list.begin(); it != quad_list.end(); ++it) { - if (it == candidate_iterator) - continue; - if (!DiscardableQuad(*it)) { - auto& transform = it->shared_quad_state->quad_to_target_transform; - gfx::RectF display_rect = gfx::RectF(it->rect); - transform.TransformRect(&display_rect); - content_rect.Union(display_rect); - } - } - - if (!content_rect.IsEmpty()) { - // Sometimes the content quads extend past primary->display_rect, so first - // clip the content_rect to that. - content_rect.Intersect(primary->display_rect); - DCHECK_NE(0, primary->display_rect.width()); - DCHECK_NE(0, primary->display_rect.height()); - primary->uv_rect = gfx::ScaleRect( - content_rect, 1. / primary->resource_size_in_pixels.width(), - 1. / primary->resource_size_in_pixels.height()); - primary->display_rect = content_rect; - - candidate_list->push_back(*primary); - } -} - } // namespace viz
diff --git a/components/viz/service/display/overlay_processor.h b/components/viz/service/display/overlay_processor.h index b78d721..a21a634 100644 --- a/components/viz/service/display/overlay_processor.h +++ b/components/viz/service/display/overlay_processor.h
@@ -79,15 +79,6 @@ gfx::Rect* damage_rect, std::vector<gfx::Rect>* content_bounds); - // Determine if we can eliminate (all remaining quads are black or - // transparent) or crop (non-black content is a small sub-rectangle) the - // primary framebuffer. - static void EliminateOrCropPrimary( - const QuadList& quad_list, - const QuadList::Iterator& candidate_iterator, - OverlayCandidate* primary, - OverlayCandidateList* candidate_list); - void SetDCHasHwOverlaySupportForTesting() { dc_processor_.SetHasHwOverlaySupport(); }
diff --git a/components/viz/service/display/overlay_strategy_single_on_top.cc b/components/viz/service/display/overlay_strategy_single_on_top.cc index 100332f6..ccfc620 100644 --- a/components/viz/service/display/overlay_strategy_single_on_top.cc +++ b/components/viz/service/display/overlay_strategy_single_on_top.cc
@@ -44,25 +44,29 @@ if (best_quad_it == quad_list->end()) return false; - OverlayCandidateList new_candidate_list; - if (candidate_list->size() == 1) { - OverlayCandidate primary(candidate_list->back()); - OverlayProcessor::EliminateOrCropPrimary(*quad_list, best_quad_it, &primary, - &new_candidate_list); - } else { - new_candidate_list = *candidate_list; - } + if (TryOverlay(quad_list, candidate_list, best_candidate, best_quad_it)) + return true; + return false; +} + +bool OverlayStrategySingleOnTop::TryOverlay( + QuadList* quad_list, + OverlayCandidateList* candidate_list, + const OverlayCandidate& candidate, + QuadList::Iterator candidate_iterator) { // Add the overlay. - new_candidate_list.push_back(best_candidate); + OverlayCandidateList new_candidate_list = *candidate_list; + new_candidate_list.push_back(candidate); new_candidate_list.back().plane_z_order = 1; // Check for support. capability_checker_->CheckOverlaySupport(&new_candidate_list); + const OverlayCandidate& overlay_candidate = new_candidate_list.back(); // If the candidate can be handled by an overlay, create a pass for it. - if (new_candidate_list.back().overlay_handled) { - quad_list->EraseAndInvalidateAllPointers(best_quad_it); + if (overlay_candidate.overlay_handled) { + quad_list->EraseAndInvalidateAllPointers(candidate_iterator); candidate_list->swap(new_candidate_list); return true; }
diff --git a/components/viz/service/display/overlay_strategy_underlay.cc b/components/viz/service/display/overlay_strategy_underlay.cc index b0bf8355..2dd89a5 100644 --- a/components/viz/service/display/overlay_strategy_underlay.cc +++ b/components/viz/service/display/overlay_strategy_underlay.cc
@@ -57,19 +57,11 @@ continue; } - OverlayCandidateList new_candidate_list; - if (candidate_list->size() == 1) { - OverlayCandidate primary(candidate_list->back()); - primary.is_opaque = false; - OverlayProcessor::EliminateOrCropPrimary(quad_list, it, &primary, - &new_candidate_list); - } else { - new_candidate_list = *candidate_list; - } - // Add the overlay. + OverlayCandidateList new_candidate_list = *candidate_list; new_candidate_list.push_back(candidate); new_candidate_list.back().plane_z_order = -1; + new_candidate_list.front().is_opaque = false; // Check for support. capability_checker_->CheckOverlaySupport(&new_candidate_list);
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc index afa8b38d..1ed1f92c 100644 --- a/components/viz/service/display/overlay_unittest.cc +++ b/components/viz/service/display/overlay_unittest.cc
@@ -584,18 +584,6 @@ std::vector<gfx::Rect> content_bounds_; }; -OverlayCandidateList BackbufferOverlayList(const RenderPass* root_render_pass) { - OverlayCandidateList list; - OverlayCandidate output_surface_plane; - output_surface_plane.display_rect = gfx::RectF(root_render_pass->output_rect); - output_surface_plane.resource_size_in_pixels = - root_render_pass->output_rect.size(); - output_surface_plane.use_output_surface_for_resource = true; - output_surface_plane.overlay_handled = true; - list.push_back(output_surface_plane); - return list; -} - using FullscreenOverlayTest = OverlayTest<FullscreenOverlayValidator>; using SingleOverlayOnTopTest = OverlayTest<SingleOnTopOverlayValidator>; using UnderlayTest = OverlayTest<UnderlayOverlayValidator>; @@ -1557,25 +1545,6 @@ EXPECT_EQ(0U, candidate_list.size()); } -TEST_F(SingleOverlayOnTopTest, AllowVideoNormalTransform) { - std::unique_ptr<RenderPass> pass = CreateRenderPass(); - CreateFullscreenCandidateVideoQuad( - resource_provider_.get(), child_resource_provider_.get(), - child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), - kNormalTransform); - - OverlayCandidateList candidate_list; - OverlayProcessor::FilterOperationsMap render_pass_filters; - OverlayProcessor::FilterOperationsMap render_pass_background_filters; - RenderPassList pass_list; - pass_list.push_back(std::move(pass)); - overlay_processor_->ProcessForOverlays( - resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), - render_pass_filters, render_pass_background_filters, &candidate_list, - nullptr, nullptr, &damage_rect_, &content_bounds_); - EXPECT_EQ(1U, candidate_list.size()); -} - TEST_F(SingleOverlayOnTopTest, RejectVideoSwapTransform) { std::unique_ptr<RenderPass> pass = CreateRenderPass(); CreateFullscreenCandidateVideoQuad( @@ -1595,33 +1564,6 @@ EXPECT_EQ(0U, candidate_list.size()); } -TEST_F(SingleOverlayOnTopTest, - AllowVideoNormalTransformWithOutputSurfaceOverlay) { - std::unique_ptr<RenderPass> pass = CreateRenderPass(); - CreateFullscreenCandidateQuad( - resource_provider_.get(), child_resource_provider_.get(), - child_provider_.get(), pass->shared_quad_state_list.back(), pass.get()); - - gfx::Rect video_rect = gfx::ScaleToEnclosingRect(pass->output_rect, .5); - CreateCandidateVideoQuadAt( - resource_provider_.get(), child_resource_provider_.get(), - child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(), - video_rect, kNormalTransform); - - OverlayCandidateList candidate_list(BackbufferOverlayList(pass.get())); - OverlayProcessor::FilterOperationsMap render_pass_filters; - OverlayProcessor::FilterOperationsMap render_pass_background_filters; - RenderPassList pass_list; - pass_list.push_back(std::move(pass)); - overlay_processor_->ProcessForOverlays( - resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), - render_pass_filters, render_pass_background_filters, &candidate_list, - nullptr, nullptr, &damage_rect_, &content_bounds_); - ASSERT_EQ(2U, candidate_list.size()); - EXPECT_EQ(candidate_list[0].uv_rect, gfx::RectF(.5, .5)); - EXPECT_EQ(candidate_list[1].uv_rect, gfx::RectF(.1, .2, .9, .8)); -} - TEST_F(UnderlayTest, AllowVideoXMirrorTransform) { std::unique_ptr<RenderPass> pass = CreateRenderPass(); CreateFullscreenCandidateVideoQuad( @@ -1987,7 +1929,6 @@ OverlayCandidateList candidate_list; OverlayCandidate candidate; - candidate.display_rect = gfx::RectF(pass->output_rect); candidate.use_output_surface_for_resource = true; candidate.is_opaque = true; candidate_list.push_back(candidate); @@ -2286,7 +2227,6 @@ OverlayCandidateList candidate_list; OverlayCandidate candidate; - candidate.display_rect = gfx::RectF(pass->output_rect); candidate.use_output_surface_for_resource = true; candidate.is_opaque = true; candidate_list.push_back(candidate); @@ -2326,6 +2266,16 @@ EXPECT_TRUE(content_bounds_.empty()); } +OverlayCandidateList BackbufferOverlayList(const RenderPass* root_render_pass) { + OverlayCandidateList list; + OverlayCandidate output_surface_plane; + output_surface_plane.display_rect = gfx::RectF(root_render_pass->output_rect); + output_surface_plane.use_output_surface_for_resource = true; + output_surface_plane.overlay_handled = true; + list.push_back(output_surface_plane); + return list; +} + TEST_F(CALayerOverlayTest, AllowNonAxisAlignedTransform) { std::unique_ptr<RenderPass> pass = CreateRenderPass(); CreateFullscreenCandidateQuad( @@ -2857,7 +2807,7 @@ OutputSurface* output_surface, DisplayResourceProvider* resource_provider) : GLRenderer(settings, output_surface, resource_provider, nullptr), - expected_overlay_count_(0) {} + expect_overlays_(false) {} MOCK_METHOD2(DoDrawQuad, void(const DrawQuad* quad, const gfx::QuadF* draw_region)); @@ -2871,17 +2821,21 @@ void FinishDrawingFrame() override { GLRenderer::FinishDrawingFrame(); - ASSERT_EQ(expected_overlay_count_, current_frame()->overlay_list.size()); - if (expected_overlay_count_ > 0) - EXPECT_GE(current_frame()->overlay_list.back().resource_id, 0U); + if (!expect_overlays_) { + EXPECT_EQ(0U, current_frame()->overlay_list.size()); + return; + } + + ASSERT_EQ(2U, current_frame()->overlay_list.size()); + EXPECT_GE(current_frame()->overlay_list.back().resource_id, 0U); } - void set_expected_overlay_count(unsigned int overlay_count) { - expected_overlay_count_ = overlay_count; + void set_expect_overlays(bool expect_overlays) { + expect_overlays_ = expect_overlays; } private: - unsigned int expected_overlay_count_; + bool expect_overlays_; }; class MockOverlayScheduler { @@ -2966,7 +2920,7 @@ TEST_F(GLRendererWithOverlaysTest, OverlayQuadNotDrawn) { bool use_validator = true; Init(use_validator); - renderer_->set_expected_overlay_count(1); + renderer_->set_expect_overlays(true); output_surface_->GetOverlayCandidateValidator()->AddExpectedRect( gfx::RectF(kOverlayBottomRightRect)); @@ -2987,6 +2941,10 @@ // Candidate pass was taken out and extra skipped pass added, // so only draw 2 quads. EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(2); + EXPECT_CALL(scheduler_, + Schedule(0, gfx::OVERLAY_TRANSFORM_NONE, _, + gfx::Rect(kDisplaySize), gfx::RectF(0, 0, 1, 1), _, _)) + .Times(1); EXPECT_CALL( scheduler_, Schedule(1, gfx::OVERLAY_TRANSFORM_NONE, _, kOverlayBottomRightRect, @@ -3004,7 +2962,7 @@ TEST_F(GLRendererWithOverlaysTest, OccludedQuadInUnderlay) { bool use_validator = true; Init(use_validator); - renderer_->set_expected_overlay_count(1); + renderer_->set_expect_overlays(true); std::unique_ptr<RenderPass> pass = CreateRenderPass(); @@ -3024,6 +2982,10 @@ // Expect to be replaced with transparent hole quad and placed in underlay. EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(3); EXPECT_CALL(scheduler_, + Schedule(0, gfx::OVERLAY_TRANSFORM_NONE, _, + gfx::Rect(kDisplaySize), gfx::RectF(0, 0, 1, 1), _, _)) + .Times(1); + EXPECT_CALL(scheduler_, Schedule(-1, gfx::OVERLAY_TRANSFORM_NONE, _, kOverlayRect, BoundingRect(kUVTopLeft, kUVBottomRight), _, _)) .Times(1); @@ -3039,7 +3001,7 @@ TEST_F(GLRendererWithOverlaysTest, NoValidatorNoOverlay) { bool use_validator = false; Init(use_validator); - renderer_->set_expected_overlay_count(0); + renderer_->set_expect_overlays(false); std::unique_ptr<RenderPass> pass = CreateRenderPass(); @@ -3066,14 +3028,13 @@ Mock::VerifyAndClearExpectations(&scheduler_); } -// GLRenderer skips drawing occluded quads when partial swap is enabled and -// turns off primary plane. +// GLRenderer skips drawing occluded quads when partial swap is enabled. TEST_F(GLRendererWithOverlaysTest, OccludedQuadNotDrawnWhenPartialSwapEnabled) { provider_->TestContextGL()->set_have_post_sub_buffer(true); settings_.partial_swap_enabled = true; bool use_validator = true; Init(use_validator); - renderer_->set_expected_overlay_count(1); + renderer_->set_expect_overlays(true); std::unique_ptr<RenderPass> pass = CreateRenderPass(); @@ -3090,8 +3051,7 @@ output_surface_->set_is_displayed_as_overlay_plane(true); EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(0); - // Only the candidate quad gets scheduled - EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(1); + EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(2); DrawFrame(&pass_list, kDisplaySize); EXPECT_EQ(0U, output_surface_->bind_framebuffer_count()); SwapBuffers(); @@ -3099,13 +3059,12 @@ Mock::VerifyAndClearExpectations(&scheduler_); } -// GLRenderer skips drawing occluded quads when empty swap is enabled and -// turns off primary plane. +// GLRenderer skips drawing occluded quads when empty swap is enabled. TEST_F(GLRendererWithOverlaysTest, OccludedQuadNotDrawnWhenEmptySwapAllowed) { provider_->TestContextGL()->set_have_commit_overlay_planes(true); bool use_validator = true; Init(use_validator); - renderer_->set_expected_overlay_count(1); + renderer_->set_expect_overlays(true); std::unique_ptr<RenderPass> pass = CreateRenderPass(); @@ -3123,8 +3082,7 @@ output_surface_->set_is_displayed_as_overlay_plane(true); EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(0); - // Only the candidate quad gets scheduled - EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(1); + EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(2); DrawFrame(&pass_list, kDisplaySize); EXPECT_EQ(0U, output_surface_->bind_framebuffer_count()); SwapBuffers(); @@ -3135,7 +3093,7 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedWithDelay) { bool use_validator = true; Init(use_validator); - renderer_->set_expected_overlay_count(2); + renderer_->set_expect_overlays(true); ResourceId resource1 = CreateResourceInLayerTree( child_resource_provider_.get(), gfx::Size(32, 32), true); @@ -3243,7 +3201,7 @@ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(0); DirectRenderer::DrawingFrame frame_no_overlays; frame_no_overlays.render_passes_in_draw_order = &pass_list; - renderer_->set_expected_overlay_count(0); + renderer_->set_expect_overlays(false); renderer_->SetCurrentFrame(frame_no_overlays); renderer_->BeginDrawingFrame(); renderer_->FinishDrawingFrame(); @@ -3262,7 +3220,7 @@ EXPECT_FALSE(resource_provider_->InUse(mapped_resource3)); // Use the same buffer twice. - renderer_->set_expected_overlay_count(2); + renderer_->set_expect_overlays(true); EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(2); renderer_->SetCurrentFrame(frame1); renderer_->BeginDrawingFrame(); @@ -3300,7 +3258,7 @@ EXPECT_FALSE(resource_provider_->InUse(mapped_resource3)); EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(0); - renderer_->set_expected_overlay_count(0); + renderer_->set_expect_overlays(false); renderer_->SetCurrentFrame(frame_no_overlays); renderer_->BeginDrawingFrame(); renderer_->FinishDrawingFrame(); @@ -3324,7 +3282,7 @@ bool use_validator = true; settings_.release_overlay_resources_after_gpu_query = true; Init(use_validator); - renderer_->set_expected_overlay_count(2); + renderer_->set_expect_overlays(true); ResourceId resource1 = CreateResourceInLayerTree( child_resource_provider_.get(), gfx::Size(32, 32), true);
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index 7e62d1b7..cb86d37 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -1088,8 +1088,20 @@ } // Draw render pass with backdrop effects. + // Update the backdrop filter to include "regular" filters and opacity. + cc::FilterOperations backdrop_filters_plus_effects = *backdrop_filters; + if (params.filters) { + for (const auto& filter_op : params.filters->operations()) + backdrop_filters_plus_effects.Append(filter_op); + } + if (quad->shared_quad_state->opacity < 1.0) { + backdrop_filters_plus_effects.Append( + cc::FilterOperation::CreateOpacityFilter( + quad->shared_quad_state->opacity)); + } + auto background_paint_filter = cc::RenderSurfaceFilters::BuildImageFilter( - *backdrop_filters, + backdrop_filters_plus_effects, gfx::SizeF(content_image->width(), content_image->height())); auto background_image_filter = background_paint_filter ? background_paint_filter->cached_sk_filter_ @@ -1120,6 +1132,7 @@ SkAutoCanvasRestore auto_canvas_restore_for_save_layer(current_canvas_, false /* do_save */); current_canvas_->saveLayer(rec); + // TODO(masonfreed): need to draw the backdrop once first here current_canvas_->drawImageRect(content_image, content_rect, dest_visible_rect, paint); } @@ -1164,13 +1177,10 @@ switch (draw_mode_) { case DrawMode::DDL: { // Root framebuffer uses id 0 in SkiaOutputSurface. - RenderPassId render_pass_id = 0; - // If we are in child render pass and we don't have overdraw, copy the - // current render pass. - if (current_frame()->root_render_pass != - current_frame()->current_render_pass && - !settings_->show_overdraw_feedback) - render_pass_id = current_frame()->current_render_pass->id; + auto render_pass_id = 0; + const auto* render_pass = current_frame()->current_render_pass; + if (render_pass != current_frame()->root_render_pass) + render_pass_id = render_pass->id; skia_output_surface_->CopyOutput(render_pass_id, window_copy_rect, std::move(request)); break; @@ -1258,10 +1268,6 @@ if (!backdrop_filters) return false; DCHECK(!backdrop_filters->IsEmpty()); - - // TODO(hendrikw): Look into allowing background filters to see pixels from - // other render targets. See crbug.com/314867. - return true; }
diff --git a/components/viz/service/display/software_renderer.cc b/components/viz/service/display/software_renderer.cc index 1b2c335..fb60e103 100644 --- a/components/viz/service/display/software_renderer.cc +++ b/components/viz/service/display/software_renderer.cc
@@ -643,10 +643,6 @@ if (!backdrop_filters) return false; DCHECK(!backdrop_filters->IsEmpty()); - - // TODO(hendrikw): Look into allowing background filters to see pixels from - // other render targets. See crbug.com/314867. - return true; } @@ -729,6 +725,8 @@ SkShader::TileMode content_tile_mode) const { const cc::FilterOperations* backdrop_filters = BackgroundFiltersForPass(quad->render_pass_id); + const cc::FilterOperations* regular_filters = + FiltersForPass(quad->render_pass_id); if (!ShouldApplyBackgroundFilters(quad, backdrop_filters)) return nullptr; @@ -760,9 +758,22 @@ gfx::Vector2dF clipping_offset = (unclipped_rect.top_right() - backdrop_rect.top_right()) + (backdrop_rect.bottom_left() - unclipped_rect.bottom_left()); + + // Update the backdrop filter to include "regular" filters and opacity. + cc::FilterOperations backdrop_filters_plus_effects = *backdrop_filters; + if (regular_filters) { + for (const auto& filter_op : regular_filters->operations()) + backdrop_filters_plus_effects.Append(filter_op); + } + if (quad->shared_quad_state->opacity < 1.0) { + backdrop_filters_plus_effects.Append( + cc::FilterOperation::CreateOpacityFilter( + quad->shared_quad_state->opacity)); + } + sk_sp<SkImageFilter> filter = cc::RenderSurfaceFilters::BuildImageFilter( - *backdrop_filters, + backdrop_filters_plus_effects, gfx::SizeF(backdrop_bitmap.width(), backdrop_bitmap.height()), clipping_offset) ->cached_sk_filter_;
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h index 64b4e99..4501800 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -140,7 +140,7 @@ bool MakeCurrent(); GrContext* gr_context() { return context_state_->gr_context; } - gl::GLContext* gl_context() { return context_state_->context.get(); } + gl::GLContext* gl_context() { return context_state_->context(); } const gpu::CommandBufferId command_buffer_id_; GpuServiceImpl* const gpu_service_;
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc index eec96038..9ce7beb2 100644 --- a/components/viz/service/gl/gpu_service_impl.cc +++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -298,7 +298,7 @@ // TODO(penghuang): https://crbug.com/899740 Support GLSurface which is not // compatible. DCHECK_EQ(surface->GetCompatibilityKey(), - context_state->surface->GetCompatibilityKey()); + context_state->surface()->GetCompatibilityKey()); DCHECK(!context_state->use_virtualized_gl_contexts); return context_state; }
diff --git a/components/viz/test/data/backdrop_filter_rotated_sw.png b/components/viz/test/data/backdrop_filter_rotated_sw.png index 5b9395f..338e697 100644 --- a/components/viz/test/data/backdrop_filter_rotated_sw.png +++ b/components/viz/test/data/backdrop_filter_rotated_sw.png Binary files differ
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 4ca679d..d85fec4b4 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -569,6 +569,7 @@ "cache_storage/cache_storage_context_impl.h", "cache_storage/cache_storage_dispatcher_host.cc", "cache_storage/cache_storage_dispatcher_host.h", + "cache_storage/cache_storage_handle.h", "cache_storage/cache_storage_histogram_utils.cc", "cache_storage/cache_storage_histogram_utils.h", "cache_storage/cache_storage_index.cc", @@ -1765,6 +1766,8 @@ "utility_process_host.h", "wake_lock/wake_lock_context_host.cc", "wake_lock/wake_lock_context_host.h", + "wake_lock/wake_lock_service_impl.cc", + "wake_lock/wake_lock_service_impl.h", "web_contents/aura/gesture_nav_simple.cc", "web_contents/aura/gesture_nav_simple.h", "web_contents/aura/overscroll_navigation_overlay.cc",
diff --git a/content/browser/DEPS b/content/browser/DEPS index 174a7868..94298c7 100644 --- a/content/browser/DEPS +++ b/content/browser/DEPS
@@ -152,10 +152,16 @@ "+third_party/blink/public/platform/reporting.mojom.h", "+third_party/blink/public/platform/web_feature.mojom.h", "+third_party/blink/public/web/commit_result.mojom.h", - "+third_party/blink/public/web/devtools_agent.mojom.h", "+third_party/blink/public/web/devtools_frontend.mojom.h", # DO NOT ADD ANY CHROME OR COMPONENTS INCLUDES HERE!!! # See https://sites.google.com/a/chromium.org/dev/developers/content-module # for more information. ] + +specific_include_rules = { + # To share values of UMA enums between product code and tests. + "cross_site_document_blocking_browsertest.cc": [ + "+services/network/url_loader.h", + ], +}
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc index 02c285b..ed19e6c 100644 --- a/content/browser/accessibility/browser_accessibility_android.cc +++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -1064,7 +1064,7 @@ case ax::mojom::Role::kListItem: case ax::mojom::Role::kListBoxOption: case ax::mojom::Role::kTreeItem: - index = GetIntAttribute(ax::mojom::IntAttribute::kPosInSet) - 1; + index = node()->GetPosInSet() - 1; break; default: break; @@ -1085,7 +1085,7 @@ case ax::mojom::Role::kList: case ax::mojom::Role::kListBox: case ax::mojom::Role::kDescriptionList: - count = PlatformChildCount(); + count = node()->GetSetSize(); break; default: break; @@ -1385,7 +1385,7 @@ GetRole() == ax::mojom::Role::kListBox || GetRole() == ax::mojom::Role::kDescriptionList || GetRole() == ax::mojom::Role::kTree) { - return PlatformChildCount(); + return node()->GetSetSize(); } return 0; @@ -1402,7 +1402,7 @@ if (GetRole() == ax::mojom::Role::kListItem || GetRole() == ax::mojom::Role::kListBoxOption || GetRole() == ax::mojom::Role::kTreeItem) { - return GetIndexInParent(); + return node()->GetPosInSet() - 1; } return node()->GetTableCellRowIndex();
diff --git a/content/browser/appcache/mock_appcache_storage.h b/content/browser/appcache/mock_appcache_storage.h index 0a4fcb75..80cc4bad 100644 --- a/content/browser/appcache/mock_appcache_storage.h +++ b/content/browser/appcache/mock_appcache_storage.h
@@ -49,7 +49,7 @@ // For use in unit tests. // Note: This class is also being used to bootstrap our development efforts. -// We can get layout tests up and running, and back fill with real storage +// We can get web tests up and running, and back fill with real storage // somewhat in parallel. class MockAppCacheStorage : public AppCacheStorage { public:
diff --git a/content/browser/background_fetch/background_fetch_context.cc b/content/browser/background_fetch/background_fetch_context.cc index 9c1de39..3882c17 100644 --- a/content/browser/background_fetch/background_fetch_context.cc +++ b/content/browser/background_fetch/background_fetch_context.cc
@@ -40,7 +40,7 @@ service_worker_context_(service_worker_context), registration_notifier_( std::make_unique<BackgroundFetchRegistrationNotifier>()), - delegate_proxy_(browser_context_->GetBackgroundFetchDelegate()), + delegate_proxy_(browser_context_), weak_factory_(this) { // Although this lives only on the IO thread, it is constructed on UI thread. DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/content/browser/background_fetch/background_fetch_data_manager.cc b/content/browser/background_fetch/background_fetch_data_manager.cc index 321d7c6..a276f287 100644 --- a/content/browser/background_fetch/background_fetch_data_manager.cc +++ b/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -80,6 +80,37 @@ AddDatabaseTask(std::make_unique<background_fetch::CleanupTask>(this)); } +CacheStorageHandle BackgroundFetchDataManager::GetOrOpenCacheStorage( + const url::Origin& origin, + const std::string& unique_id) { + auto it = cache_storage_handle_map_.find(unique_id); + if (it != cache_storage_handle_map_.end()) { + if (it->second.value()) { + DCHECK_EQ(origin, it->second.value()->Origin()); + } else { + // The backing CacheStorage has been forcibly closed due to an external + // event. Re-open the CacheStorage and update the handle. + it->second = cache_manager()->OpenCacheStorage( + origin, CacheStorageOwner::kBackgroundFetch); + } + return it->second.Clone(); + } + + // This origin and unique_id has never been opened before. Open + // the CacheStorage, remember the association in the map, and return the + // handle. + CacheStorageHandle handle = cache_manager()->OpenCacheStorage( + origin, CacheStorageOwner::kBackgroundFetch); + cache_storage_handle_map_.emplace(unique_id, handle.Clone()); + return handle; +} + +void BackgroundFetchDataManager::ReleaseCacheStorage( + const std::string& unique_id) { + bool erased = cache_storage_handle_map_.erase(unique_id); + DCHECK(erased); +} + BackgroundFetchDataManager::~BackgroundFetchDataManager() { DCHECK_CURRENTLY_ON(BrowserThread::IO); }
diff --git a/content/browser/background_fetch/background_fetch_data_manager.h b/content/browser/background_fetch/background_fetch_data_manager.h index 346060c..9b88d49 100644 --- a/content/browser/background_fetch/background_fetch_data_manager.h +++ b/content/browser/background_fetch/background_fetch_data_manager.h
@@ -204,6 +204,18 @@ void Cleanup(); + // Get a CacheStorageHandle for the given |origin| and |unique_id|. This will + // either come from an existing CacheStorageHandle or will cause the + // CacheStorage to be opened. + CacheStorageHandle GetOrOpenCacheStorage(const url::Origin& origin, + const std::string& unique_id); + + // Release the CacheStorageHandle for the given |unique_id|, if + // it's open. DoomCache should be called prior to releasing the handle. + // There must be an entry in |cache_storage_handle_map_| for the given + // |unique_id|. + void ReleaseCacheStorage(const std::string& unique_id); + // Whether Shutdown was called on BackgroundFetchContext. bool shutting_down_ = false; @@ -213,8 +225,8 @@ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; - // The BackgroundFetch stores its own reference to CacheStorageManager - // in case StoragePartitionImpl is destoyed, which releases the reference. + // BackgroundFetch stores its own reference to CacheStorageManager + // in case StoragePartitionImpl is destroyed, which releases the reference. scoped_refptr<CacheStorageManager> cache_manager_; // The blob storage request with which response information will be stored. @@ -232,6 +244,13 @@ // the browser is shutdown first. std::set<std::string> ref_counted_unique_ids_; + // A map of open CacheStorageHandle objects keyed by the registration + // |unique_id|. These handles are created opportunistically in + // GetOrOpenCacheStorage(). They are cleared after the Cache has been + // deleted and ReleaseCacheStorage() is called. + // TODO(crbug.com/711354): Possibly update key when CORS support is added. + std::map<std::string, CacheStorageHandle> cache_storage_handle_map_; + base::WeakPtrFactory<BackgroundFetchDataManager> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(BackgroundFetchDataManager);
diff --git a/content/browser/background_fetch/background_fetch_data_manager_unittest.cc b/content/browser/background_fetch/background_fetch_data_manager_unittest.cc index c5fc0d5e..8a2c2a2 100644 --- a/content/browser/background_fetch/background_fetch_data_manager_unittest.cc +++ b/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
@@ -430,8 +430,11 @@ bool result = false; base::RunLoop run_loop; - background_fetch_data_manager_->cache_manager()->HasCache( - origin(), CacheStorageOwner::kBackgroundFetch, cache_name, + CacheStorageHandle cache_storage = + background_fetch_data_manager_->cache_manager()->OpenCacheStorage( + origin(), CacheStorageOwner::kBackgroundFetch); + cache_storage.value()->HasCache( + cache_name, base::BindOnce(&BackgroundFetchDataManagerTest::DidFindCache, base::Unretained(this), run_loop.QuitClosure(), &result)); @@ -445,9 +448,11 @@ bool result = false; base::RunLoop run_loop; - background_fetch_data_manager_->cache_manager()->MatchCache( - origin(), CacheStorageOwner::kBackgroundFetch, kExampleUniqueId, - BackgroundFetchSettledFetch::CloneRequest(request), + CacheStorageHandle cache_storage = + background_fetch_data_manager_->cache_manager()->OpenCacheStorage( + origin(), CacheStorageOwner::kBackgroundFetch); + cache_storage.value()->MatchCache( + kExampleUniqueId, BackgroundFetchSettledFetch::CloneRequest(request), nullptr /* match_params */, base::BindOnce(&BackgroundFetchDataManagerTest::DidMatchCache, base::Unretained(this), run_loop.QuitClosure(), @@ -461,8 +466,10 @@ CacheStorageCacheHandle handle; { base::RunLoop run_loop; - background_fetch_data_manager_->cache_manager()->OpenCache( - origin(), CacheStorageOwner::kBackgroundFetch, + CacheStorageHandle cache_storage = + background_fetch_data_manager_->cache_manager()->OpenCacheStorage( + origin(), CacheStorageOwner::kBackgroundFetch); + cache_storage.value()->OpenCache( kExampleUniqueId /* cache_name */, base::BindOnce(&BackgroundFetchDataManagerTest::DidOpenCache, base::Unretained(this), run_loop.QuitClosure(),
diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy.cc b/content/browser/background_fetch/background_fetch_delegate_proxy.cc index 9170b11..b0289a9 100644 --- a/content/browser/background_fetch/background_fetch_delegate_proxy.cc +++ b/content/browser/background_fetch/background_fetch_delegate_proxy.cc
@@ -12,6 +12,7 @@ #include "content/browser/background_fetch/background_fetch_job_controller.h" #include "content/public/browser/background_fetch_description.h" #include "content/public/browser/background_fetch_response.h" +#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/download_manager.h" #include "ui/gfx/geometry/size.h" @@ -26,14 +27,12 @@ : public BackgroundFetchDelegate::Client { public: Core(const base::WeakPtr<BackgroundFetchDelegateProxy>& io_parent, - BackgroundFetchDelegate* delegate) - : io_parent_(io_parent), delegate_(delegate), weak_ptr_factory_(this) { + BrowserContext* browser_context) + : io_parent_(io_parent), + browser_context_(browser_context), + weak_ptr_factory_(this) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - - // Some BrowserContext implementations return nullptr for their delegate - // implementation and the feature should be disabled in that case. - if (delegate_) - delegate_->SetDelegateClient(GetWeakPtrOnUI()); + DCHECK(browser_context_); } ~Core() override { DCHECK_CURRENTLY_ON(BrowserThread::UI); } @@ -55,8 +54,10 @@ const url::Origin& origin, const ResourceRequestInfo::WebContentsGetter& wc_getter, BackgroundFetchDelegate::GetPermissionForOriginCallback callback) { - if (delegate_) { - delegate_->GetPermissionForOrigin( + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + if (auto* delegate = browser_context_->GetBackgroundFetchDelegate()) { + delegate->GetPermissionForOrigin( origin, wc_getter, base::BindOnce(&Core::ForwardGetPermissionForOriginCallbackToIO, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); @@ -77,8 +78,8 @@ BackgroundFetchDelegate::GetIconDisplaySizeCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (delegate_) { - delegate_->GetIconDisplaySize( + if (auto* delegate = browser_context_->GetBackgroundFetchDelegate()) { + delegate->GetIconDisplaySize( base::BindOnce(&Core::ForwardGetIconDisplaySizeCallbackToIO, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } else { @@ -92,15 +93,10 @@ std::unique_ptr<BackgroundFetchDescription> fetch_description) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - // If there are multiple clients created we might have registered the wrong - // one with the delegate by overwriting it. This check makes sure that we - // register the correct client until multiple clients are supported. - // TODO(crbug.com/907075): Support multiple clients. - if (delegate_ && delegate_->client().get() != this) - delegate_->SetDelegateClient(GetWeakPtrOnUI()); - - if (delegate_) - delegate_->CreateDownloadJob(std::move(fetch_description)); + auto* delegate = browser_context_->GetBackgroundFetchDelegate(); + if (delegate) + delegate->CreateDownloadJob(GetWeakPtrOnUI(), + std::move(fetch_description)); } void StartRequest(const std::string& job_unique_id, @@ -112,7 +108,8 @@ // TODO(crbug/757760): This can be nullptr, if the delegate has shut down, // in which case we need to make sure this is retried when the browser // restarts. - if (!delegate_) + auto* delegate = browser_context_->GetBackgroundFetchDelegate(); + if (!delegate) return; const blink::mojom::FetchAPIRequestPtr& fetch_request = @@ -165,24 +162,24 @@ // TODO(crbug.com/774054): Update |has_request_body| after the cache storage // supports request bodies. - delegate_->DownloadUrl(job_unique_id, request->download_guid(), - fetch_request->method, fetch_request->url, - traffic_annotation, headers, - /* has_request_body= */ false); + delegate->DownloadUrl(job_unique_id, request->download_guid(), + fetch_request->method, fetch_request->url, + traffic_annotation, headers, + /* has_request_body= */ false); } void Abort(const std::string& job_unique_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (delegate_) - delegate_->Abort(job_unique_id); + if (auto* delegate = browser_context_->GetBackgroundFetchDelegate()) + delegate->Abort(job_unique_id); } void MarkJobComplete(const std::string& job_unique_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (delegate_) - delegate_->MarkJobComplete(job_unique_id); + if (auto* delegate = browser_context_->GetBackgroundFetchDelegate()) + delegate->MarkJobComplete(job_unique_id); } void UpdateUI(const std::string& job_unique_id, @@ -190,8 +187,8 @@ const base::Optional<SkBitmap>& icon) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (delegate_) - delegate_->UpdateUI(job_unique_id, title, icon); + if (auto* delegate = browser_context_->GetBackgroundFetchDelegate()) + delegate->UpdateUI(job_unique_id, title, icon); } // BackgroundFetchDelegate::Client implementation: @@ -210,7 +207,6 @@ const std::string& guid, std::unique_ptr<content::BackgroundFetchResponse> response) override; void OnUIActivated(const std::string& unique_id) override; - void OnDelegateShutdown() override; void GetUploadData( const std::string& job_unique_id, const std::string& download_guid, @@ -220,9 +216,7 @@ // Weak reference to the IO thread outer class that owns us. base::WeakPtr<BackgroundFetchDelegateProxy> io_parent_; - // Delegate is owned elsewhere and is valid from construction until - // OnDelegateShutDown (if not initially nullptr). - BackgroundFetchDelegate* delegate_; + BrowserContext* browser_context_; base::WeakPtrFactory<Core> weak_ptr_factory_; @@ -283,10 +277,6 @@ job_unique_id)); } -void BackgroundFetchDelegateProxy::Core::OnDelegateShutdown() { - delegate_ = nullptr; -} - void BackgroundFetchDelegateProxy::Core::GetUploadData( const std::string& job_unique_id, const std::string& download_guid, @@ -330,14 +320,14 @@ BackgroundFetchDelegateProxy::JobDetails::~JobDetails() = default; BackgroundFetchDelegateProxy::BackgroundFetchDelegateProxy( - BackgroundFetchDelegate* delegate) + BrowserContext* browser_context) : weak_ptr_factory_(this) { DCHECK_CURRENTLY_ON(BrowserThread::UI); // Normally it would be unsafe to obtain a weak pointer on the UI thread from // a factory that lives on the IO thread, but it's ok in the constructor as // |this| can't be destroyed before the constructor finishes. - ui_core_.reset(new Core(weak_ptr_factory_.GetWeakPtr(), delegate)); + ui_core_.reset(new Core(weak_ptr_factory_.GetWeakPtr(), browser_context)); // Since this constructor runs on the UI thread, a WeakPtr can be safely // obtained from the Core.
diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy.h b/content/browser/background_fetch/background_fetch_delegate_proxy.h index 2cdd7fe..fb6f7ab0 100644 --- a/content/browser/background_fetch/background_fetch_delegate_proxy.h +++ b/content/browser/background_fetch/background_fetch_delegate_proxy.h
@@ -24,6 +24,8 @@ namespace content { +class BrowserContext; + // Proxy class for passing messages between BackgroundFetchJobControllers on the // IO thread and BackgroundFetchDelegate on the UI thread. class CONTENT_EXPORT BackgroundFetchDelegateProxy { @@ -61,7 +63,7 @@ virtual ~Controller() {} }; - explicit BackgroundFetchDelegateProxy(BackgroundFetchDelegate* delegate); + explicit BackgroundFetchDelegateProxy(BrowserContext* browser_context); ~BackgroundFetchDelegateProxy();
diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc b/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc index ddfe7db..4d90a9c 100644 --- a/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc +++ b/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
@@ -29,7 +29,7 @@ class FakeBackgroundFetchDelegate : public BackgroundFetchDelegate { public: - FakeBackgroundFetchDelegate() {} + FakeBackgroundFetchDelegate() = default; // BackgroundFetchDelegate implementation: void GetIconDisplaySize( @@ -43,7 +43,11 @@ std::move(callback).Run(BackgroundFetchPermission::ALLOWED); } void CreateDownloadJob( - std::unique_ptr<BackgroundFetchDescription> fetch_description) override {} + base::WeakPtr<Client> client, + std::unique_ptr<BackgroundFetchDescription> fetch_description) override { + job_id_to_client_.emplace(fetch_description->job_unique_id, + std::move(client)); + } void DownloadUrl(const std::string& job_unique_id, const std::string& guid, const std::string& method, @@ -51,7 +55,7 @@ const net::NetworkTrafficAnnotationTag& traffic_annotation, const net::HttpRequestHeaders& headers, bool has_request_body) override { - if (!client()) + if (!job_id_to_client_[job_unique_id]) return; download_guid_to_job_id_map_[guid] = job_unique_id; @@ -61,7 +65,8 @@ std::vector<GURL>({url}), base::MakeRefCounted<net::HttpResponseHeaders>("200 OK")); - client()->OnDownloadStarted(job_unique_id, guid, std::move(response)); + job_id_to_client_[job_unique_id]->OnDownloadStarted(job_unique_id, guid, + std::move(response)); if (complete_downloads_) { base::PostTaskWithTraits( FROM_HERE, {BrowserThread::IO}, @@ -91,7 +96,7 @@ private: void CompleteDownload(const std::string& job_unique_id, const std::string& guid) { - if (!client()) + if (!job_id_to_client_[job_unique_id]) return; if (aborted_jobs_.count(download_guid_to_job_id_map_[guid])) @@ -101,7 +106,7 @@ std::vector<GURL>({download_guid_to_url_map_[guid]}), base::MakeRefCounted<net::HttpResponseHeaders>("200 OK")); - client()->OnDownloadComplete( + job_id_to_client_[job_unique_id]->OnDownloadComplete( job_unique_id, guid, std::make_unique<BackgroundFetchResult>( std::move(response), base::Time::Now(), base::FilePath(), @@ -112,9 +117,25 @@ std::set<std::string> aborted_jobs_; std::map<std::string, std::string> download_guid_to_job_id_map_; std::map<std::string, GURL> download_guid_to_url_map_; + std::map<std::string, base::WeakPtr<Client>> job_id_to_client_; bool complete_downloads_ = true; }; +class FakeTestBrowserContext : public TestBrowserContext { + public: + FakeTestBrowserContext() = default; + ~FakeTestBrowserContext() override = default; + + FakeBackgroundFetchDelegate* GetBackgroundFetchDelegate() override { + if (!delegate_) + delegate_ = std::make_unique<FakeBackgroundFetchDelegate>(); + return delegate_.get(); + } + + private: + std::unique_ptr<FakeBackgroundFetchDelegate> delegate_; +}; + class FakeController : public BackgroundFetchDelegateProxy::Controller { public: FakeController() : weak_ptr_factory_(this) {} @@ -147,7 +168,9 @@ class BackgroundFetchDelegateProxyTest : public BackgroundFetchTestBase { public: - BackgroundFetchDelegateProxyTest() : delegate_proxy_(&delegate_) {} + BackgroundFetchDelegateProxyTest() : delegate_proxy_(&browser_context_) { + delegate_ = browser_context_.GetBackgroundFetchDelegate(); + } void DidGetIconDisplaySize(base::Closure quit_closure, gfx::Size* out_display_size, const gfx::Size& display_size) { @@ -157,7 +180,8 @@ } protected: - FakeBackgroundFetchDelegate delegate_; + FakeTestBrowserContext browser_context_; + FakeBackgroundFetchDelegate* delegate_; BackgroundFetchDelegateProxy delegate_proxy_; }; @@ -172,10 +196,6 @@ } // namespace -TEST_F(BackgroundFetchDelegateProxyTest, SetDelegate) { - EXPECT_TRUE(delegate_.client().get()); -} - TEST_F(BackgroundFetchDelegateProxyTest, StartRequest) { FakeController controller; auto fetch_request = blink::mojom::FetchAPIRequest::New(); @@ -210,7 +230,7 @@ EXPECT_FALSE(controller.request_started_); EXPECT_FALSE(controller.request_completed_); - delegate_.set_complete_downloads(false); + delegate_->set_complete_downloads(false); auto fetch_description = std::make_unique<BackgroundFetchDescription>( kExampleUniqueId, "Job 1", url::Origin(), SkBitmap(), 0 /* completed_parts */, 1 /* total_parts */, @@ -305,7 +325,47 @@ delegate_proxy_.UpdateUI(kExampleUniqueId, "Job 1 Complete!", base::nullopt); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(delegate_.ui_update_count_, 1); + EXPECT_EQ(delegate_->ui_update_count_, 1); +} + +TEST_F(BackgroundFetchDelegateProxyTest, MultipleClients) { + FakeController controller1, controller2; + EXPECT_FALSE(controller1.request_started_); + EXPECT_FALSE(controller1.request_completed_); + EXPECT_FALSE(controller2.request_started_); + EXPECT_FALSE(controller2.request_completed_); + + BackgroundFetchDelegateProxy delegate_proxy1(&browser_context_); + BackgroundFetchDelegateProxy delegate_proxy2(&browser_context_); + + auto fetch_description1 = std::make_unique<BackgroundFetchDescription>( + kExampleUniqueId, "Job 1", url::Origin(), SkBitmap(), + 0 /* completed_parts */, 1 /* total_parts */, + 0 /* completed_parts_size */, 0 /* total_parts_size */, + std::vector<std::string>(), /* start_paused = */ false); + auto fetch_description2 = std::make_unique<BackgroundFetchDescription>( + kExampleUniqueId2, "Job 2", url::Origin(), SkBitmap(), + 0 /* completed_parts */, 1 /* total_parts */, + 0 /* completed_parts_size */, 0 /* total_parts_size */, + std::vector<std::string>(), /* start_paused = */ false); + + delegate_proxy1.CreateDownloadJob(controller1.weak_ptr_factory_.GetWeakPtr(), + std::move(fetch_description1), + {} /* active_fetch_requests */); + delegate_proxy2.CreateDownloadJob(controller2.weak_ptr_factory_.GetWeakPtr(), + std::move(fetch_description2), + {} /* active_fetch_requests */); + + auto request = CreateRequestInfo(0 /* request_index */, + blink::mojom::FetchAPIRequest::New()); + delegate_proxy1.StartRequest(kExampleUniqueId, url::Origin(), request); + delegate_proxy2.StartRequest(kExampleUniqueId2, url::Origin(), request); + base::RunLoop().RunUntilIdle(); + + EXPECT_TRUE(controller1.request_started_); + EXPECT_TRUE(controller1.request_completed_); + EXPECT_TRUE(controller2.request_started_); + EXPECT_TRUE(controller2.request_completed_); } } // namespace content
diff --git a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc index d744945..15aa568 100644 --- a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc +++ b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
@@ -144,9 +144,8 @@ std::unique_ptr<BackgroundFetchJobController> CreateJobController( const BackgroundFetchRegistrationId& registration_id, int total_downloads) { - delegate_ = browser_context()->GetBackgroundFetchDelegate(); - DCHECK(delegate_); - delegate_proxy_ = std::make_unique<BackgroundFetchDelegateProxy>(delegate_); + delegate_proxy_ = + std::make_unique<BackgroundFetchDelegateProxy>(browser_context()); auto controller = std::make_unique<BackgroundFetchJobController>( nullptr /* data_manager */, delegate_proxy_.get(), registration_id,
diff --git a/content/browser/background_fetch/background_fetch_scheduler_unittest.cc b/content/browser/background_fetch/background_fetch_scheduler_unittest.cc index b120ec0..5e54e8a 100644 --- a/content/browser/background_fetch/background_fetch_scheduler_unittest.cc +++ b/content/browser/background_fetch/background_fetch_scheduler_unittest.cc
@@ -73,8 +73,8 @@ embedded_worker_test_helper()->context_wrapper()); data_manager_->InitializeOnIOThread(); - delegate_proxy_ = std::make_unique<BackgroundFetchDelegateProxy>( - browser_context()->GetBackgroundFetchDelegate()); + delegate_proxy_ = + std::make_unique<BackgroundFetchDelegateProxy>(browser_context()); scheduler_ = std::make_unique<BackgroundFetchScheduler>( data_manager_.get(), nullptr, delegate_proxy_.get(),
diff --git a/content/browser/background_fetch/mock_background_fetch_delegate.cc b/content/browser/background_fetch/mock_background_fetch_delegate.cc index e4fb322..28ee785d 100644 --- a/content/browser/background_fetch/mock_background_fetch_delegate.cc +++ b/content/browser/background_fetch/mock_background_fetch_delegate.cc
@@ -77,7 +77,10 @@ GetIconDisplaySizeCallback callback) {} void MockBackgroundFetchDelegate::CreateDownloadJob( - std::unique_ptr<BackgroundFetchDescription> fetch_description) {} + base::WeakPtr<Client> client, + std::unique_ptr<BackgroundFetchDescription> fetch_description) { + job_id_to_client_map_[fetch_description->job_unique_id] = std::move(client); +} void MockBackgroundFetchDelegate::DownloadUrl( const std::string& job_unique_id, @@ -109,7 +112,7 @@ PostAbortCheckingTask( job_unique_id, base::BindOnce(&BackgroundFetchDelegate::Client::OnDownloadStarted, - client(), job_unique_id, guid, + job_id_to_client_map_[job_unique_id], job_unique_id, guid, std::make_unique<BackgroundFetchResponse>( std::vector<GURL>({url}), test_response->headers))); @@ -118,15 +121,15 @@ PostAbortCheckingTask( job_unique_id, base::BindOnce(&BackgroundFetchDelegate::Client::OnDownloadUpdated, - client(), job_unique_id, guid, - test_response->data.size() / 2)); + job_id_to_client_map_[job_unique_id], job_unique_id, + guid, test_response->data.size() / 2)); // Report progress at 100% complete. PostAbortCheckingTask( job_unique_id, base::BindOnce(&BackgroundFetchDelegate::Client::OnDownloadUpdated, - client(), job_unique_id, guid, - test_response->data.size())); + job_id_to_client_map_[job_unique_id], job_unique_id, + guid, test_response->data.size())); } if (test_response->succeeded) { @@ -146,8 +149,8 @@ PostAbortCheckingTask( job_unique_id, base::BindOnce( - &BackgroundFetchDelegate::Client::OnDownloadComplete, client(), - job_unique_id, guid, + &BackgroundFetchDelegate::Client::OnDownloadComplete, + job_id_to_client_map_[job_unique_id], job_unique_id, guid, std::make_unique<BackgroundFetchResult>( std::make_unique<BackgroundFetchResponse>( std::vector<GURL>({url}), test_response->headers), @@ -162,7 +165,8 @@ PostAbortCheckingTask( job_unique_id, base::BindOnce(&BackgroundFetchDelegate::Client::OnDownloadComplete, - client(), job_unique_id, guid, std::move(result))); + job_id_to_client_map_[job_unique_id], job_unique_id, + guid, std::move(result))); } seen_guids_.insert(guid);
diff --git a/content/browser/background_fetch/mock_background_fetch_delegate.h b/content/browser/background_fetch/mock_background_fetch_delegate.h index 9f67cf5..18f22aa0 100644 --- a/content/browser/background_fetch/mock_background_fetch_delegate.h +++ b/content/browser/background_fetch/mock_background_fetch_delegate.h
@@ -75,6 +75,7 @@ void GetIconDisplaySize( BackgroundFetchDelegate::GetIconDisplaySizeCallback callback) override; void CreateDownloadJob( + base::WeakPtr<Client> client, std::unique_ptr<BackgroundFetchDescription> fetch_description) override; void DownloadUrl(const std::string& job_unique_id, const std::string& guid, @@ -125,6 +126,9 @@ // Map from download GUIDs to unique job ids. std::map<std::string, std::string> download_guid_to_job_id_map_; + // Map from job GUIDs to Clients. + std::map<std::string, base::WeakPtr<Client>> job_id_to_client_map_; + DISALLOW_COPY_AND_ASSIGN(MockBackgroundFetchDelegate); };
diff --git a/content/browser/background_fetch/storage/create_metadata_task.cc b/content/browser/background_fetch/storage/create_metadata_task.cc index 24a2925..6028d2cf 100644 --- a/content/browser/background_fetch/storage/create_metadata_task.cc +++ b/content/browser/background_fetch/storage/create_metadata_task.cc
@@ -357,11 +357,11 @@ } // Create cache entries. - cache_manager()->OpenCache(registration_id_.origin(), - CacheStorageOwner::kBackgroundFetch, - registration_id_.unique_id() /* cache_name */, - base::BindOnce(&CreateMetadataTask::DidOpenCache, - weak_factory_.GetWeakPtr())); + CacheStorageHandle cache_storage = GetOrOpenCacheStorage(registration_id_); + cache_storage.value()->OpenCache( + registration_id_.unique_id() /* cache_name */, + base::BindOnce(&CreateMetadataTask::DidOpenCache, + weak_factory_.GetWeakPtr())); } void CreateMetadataTask::DidOpenCache(CacheStorageCacheHandle handle,
diff --git a/content/browser/background_fetch/storage/database_task.cc b/content/browser/background_fetch/storage/database_task.cc index 0029afb1..3199e0b2 100644 --- a/content/browser/background_fetch/storage/database_task.cc +++ b/content/browser/background_fetch/storage/database_task.cc
@@ -156,6 +156,22 @@ return data_manager()->quota_manager_proxy(); } +CacheStorageHandle DatabaseTask::GetOrOpenCacheStorage( + const BackgroundFetchRegistrationId& registration_id) { + return GetOrOpenCacheStorage(registration_id.origin(), + registration_id.unique_id()); +} + +CacheStorageHandle DatabaseTask::GetOrOpenCacheStorage( + const url::Origin& origin, + const std::string& unique_id) { + return data_manager()->GetOrOpenCacheStorage(origin, unique_id); +} + +void DatabaseTask::ReleaseCacheStorage(const std::string& unique_id) { + data_manager()->ReleaseCacheStorage(unique_id); +} + } // namespace background_fetch } // namespace content
diff --git a/content/browser/background_fetch/storage/database_task.h b/content/browser/background_fetch/storage/database_task.h index 471d9ca..add6e5c 100644 --- a/content/browser/background_fetch/storage/database_task.h +++ b/content/browser/background_fetch/storage/database_task.h
@@ -122,6 +122,15 @@ int64_t size, IsQuotaAvailableCallback callback); + CacheStorageHandle GetOrOpenCacheStorage( + const BackgroundFetchRegistrationId& registration_id); + CacheStorageHandle GetOrOpenCacheStorage(const url::Origin& origin, + const std::string& unique_id); + + // Release the CacheStorageHandle for the given |unique_id|, if + // it's open. DoomCache should be called prior to releasing the handle. + void ReleaseCacheStorage(const std::string& unique_id); + private: // Each task must override this function and perform the following steps: // 1) Report storage error (UMA) if applicable.
diff --git a/content/browser/background_fetch/storage/delete_registration_task.cc b/content/browser/background_fetch/storage/delete_registration_task.cc index ade9a78..88724ba 100644 --- a/content/browser/background_fetch/storage/delete_registration_task.cc +++ b/content/browser/background_fetch/storage/delete_registration_task.cc
@@ -71,8 +71,9 @@ DidGetRegistration(barrier_closure, {}, blink::ServiceWorkerStatusCode::kOk); #endif // DCHECK_IS_ON() - cache_manager()->DeleteCache( - origin_, CacheStorageOwner::kBackgroundFetch, unique_id_ /* cache_name */, + CacheStorageHandle cache_storage = GetOrOpenCacheStorage(origin_, unique_id_); + cache_storage.value()->DoomCache( + unique_id_ /* cache_name */, base::BindOnce(&DeleteRegistrationTask::DidDeleteCache, weak_factory_.GetWeakPtr(), barrier_closure)); } @@ -134,6 +135,8 @@ if (error != blink::mojom::CacheStorageError::kSuccess && error != blink::mojom::CacheStorageError::kErrorNotFound) { SetStorageError(BackgroundFetchStorageError::kCacheStorageError); + } else { + ReleaseCacheStorage(unique_id_); } std::move(done_closure).Run(); }
diff --git a/content/browser/background_fetch/storage/mark_request_complete_task.cc b/content/browser/background_fetch/storage/mark_request_complete_task.cc index c6b99fb4..ec15df12 100644 --- a/content/browser/background_fetch/storage/mark_request_complete_task.cc +++ b/content/browser/background_fetch/storage/mark_request_complete_task.cc
@@ -122,8 +122,8 @@ return; } - cache_manager()->OpenCache( - registration_id_.origin(), CacheStorageOwner::kBackgroundFetch, + CacheStorageHandle cache_storage = GetOrOpenCacheStorage(registration_id_); + cache_storage.value()->OpenCache( registration_id_.unique_id() /* cache_name */, base::BindOnce(&MarkRequestCompleteTask::DidOpenCache, weak_factory_.GetWeakPtr(), std::move(response),
diff --git a/content/browser/background_fetch/storage/match_requests_task.cc b/content/browser/background_fetch/storage/match_requests_task.cc index 487e7b2..c72f98b 100644 --- a/content/browser/background_fetch/storage/match_requests_task.cc +++ b/content/browser/background_fetch/storage/match_requests_task.cc
@@ -31,11 +31,11 @@ MatchRequestsTask::~MatchRequestsTask() = default; void MatchRequestsTask::Start() { - cache_manager()->OpenCache(registration_id_.origin(), - CacheStorageOwner::kBackgroundFetch, - registration_id_.unique_id() /* cache_name */, - base::BindOnce(&MatchRequestsTask::DidOpenCache, - weak_factory_.GetWeakPtr())); + CacheStorageHandle cache_storage = GetOrOpenCacheStorage(registration_id_); + cache_storage.value()->OpenCache( + registration_id_.unique_id() /* cache_name */, + base::BindOnce(&MatchRequestsTask::DidOpenCache, + weak_factory_.GetWeakPtr())); } void MatchRequestsTask::DidOpenCache(CacheStorageCacheHandle handle,
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc index 28185f7..98761a3 100644 --- a/content/browser/background_sync/background_sync_manager.cc +++ b/content/browser/background_sync/background_sync_manager.cc
@@ -10,6 +10,7 @@ #include "base/bind.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/task/post_task.h" #include "base/threading/thread_task_runner_handle.h" @@ -1008,19 +1009,27 @@ service_worker_id, active_registrations_[service_worker_id].origin, base::BindOnce( &BackgroundSyncManager::FireReadyEventsDidFindRegistration, - weak_ptr_factory_.GetWeakPtr(), sw_id_and_tag.second, - events_fired_barrier_closure, events_completed_barrier_closure)); + weak_ptr_factory_.GetWeakPtr(), service_worker_id, + sw_id_and_tag.second, events_fired_barrier_closure, + events_completed_barrier_closure)); } } void BackgroundSyncManager::FireReadyEventsDidFindRegistration( + int64_t service_worker_id, const std::string& tag, base::OnceClosure event_fired_callback, base::OnceClosure event_completed_callback, blink::ServiceWorkerStatusCode service_worker_status, scoped_refptr<ServiceWorkerRegistration> service_worker_registration) { DCHECK_CURRENTLY_ON(BrowserThread::IO); + + BackgroundSyncRegistration* registration = + LookupActiveRegistration(service_worker_id, tag); + if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) { + if (registration) + registration->set_sync_state(blink::mojom::BackgroundSyncState::PENDING); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, std::move(event_fired_callback)); base::ThreadTaskRunnerHandle::Get()->PostTask( @@ -1028,10 +1037,25 @@ return; } - BackgroundSyncRegistration* registration = - LookupActiveRegistration(service_worker_registration->id(), tag); + DCHECK_EQ(service_worker_id, service_worker_registration->id()); DCHECK(registration); + const bool option_conditions_met = + AreOptionConditionsMet(*registration->options()); + UMA_HISTOGRAM_BOOLEAN("BackgroundSync.OptionConditionsChanged", + !option_conditions_met); + + // The connectivity was lost before dispatching the sync event, so there is + // no point in going through with it. + if (!option_conditions_met) { + registration->set_sync_state(blink::mojom::BackgroundSyncState::PENDING); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, std::move(event_fired_callback)); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, std::move(event_completed_callback)); + return; + } + num_firing_registrations_ += 1; const bool last_chance =
diff --git a/content/browser/background_sync/background_sync_manager.h b/content/browser/background_sync/background_sync_manager.h index 268ae78..72c990e 100644 --- a/content/browser/background_sync/background_sync_manager.h +++ b/content/browser/background_sync/background_sync_manager.h
@@ -251,6 +251,7 @@ void FireReadyEvents(); void FireReadyEventsImpl(base::OnceClosure callback); void FireReadyEventsDidFindRegistration( + int64_t service_worker_id, const std::string& tag, base::OnceClosure event_fired_callback, base::OnceClosure event_completed_callback,
diff --git a/content/browser/background_sync/background_sync_manager_unittest.cc b/content/browser/background_sync/background_sync_manager_unittest.cc index 1d0c807..824b2d148f 100644 --- a/content/browser/background_sync/background_sync_manager_unittest.cc +++ b/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -17,6 +17,7 @@ #include "base/metrics/field_trial.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/mock_entropy_provider.h" #include "base/test/simple_test_clock.h" #include "base/threading/thread_task_runner_handle.h" @@ -948,6 +949,37 @@ EXPECT_FALSE(GetRegistration(sync_options_2_)); } +TEST_F(BackgroundSyncManagerTest, DispatchCancelledOnNetworkFailure) { + InitSyncEventTest(); + base::HistogramTester histogram_tester; + + SetNetwork(network::mojom::ConnectionType::CONNECTION_NONE); + EXPECT_TRUE(Register(sync_options_1_)); + EXPECT_EQ(0, sync_events_called_); + EXPECT_TRUE(GetRegistration(sync_options_1_)); + + BackgroundSyncNetworkObserver* network_observer = + test_background_sync_manager_->GetNetworkObserverForTesting(); + ASSERT_TRUE(network_observer); + + // Set the network, then immediately remove it. + network_observer->NotifyManagerIfConnectionChangedForTesting( + network::mojom::ConnectionType::CONNECTION_WIFI); + network_observer->NotifyManagerIfConnectionChangedForTesting( + network::mojom::ConnectionType::CONNECTION_NONE); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(0, sync_events_called_); + ASSERT_TRUE(GetRegistration(sync_options_1_)); + + // The event fires after the network is restored. + SetNetwork(network::mojom::ConnectionType::CONNECTION_WIFI); + EXPECT_EQ(1, sync_events_called_); + EXPECT_FALSE(GetRegistration(sync_options_1_)); + histogram_tester.ExpectBucketCount("BackgroundSync.OptionConditionsChanged", + false, 1); +} + TEST_F(BackgroundSyncManagerTest, FiresOnManagerRestart) { InitSyncEventTest();
diff --git a/content/browser/background_sync/background_sync_network_observer.cc b/content/browser/background_sync/background_sync_network_observer.cc index 15de5cc8..662b3138 100644 --- a/content/browser/background_sync/background_sync_network_observer.cc +++ b/content/browser/background_sync/background_sync_network_observer.cc
@@ -71,7 +71,6 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); return connection_type_ != network::mojom::ConnectionType::CONNECTION_NONE; - return false; } void BackgroundSyncNetworkObserver::OnConnectionChanged(
diff --git a/content/browser/bluetooth/bluetooth_blocklist.cc b/content/browser/bluetooth/bluetooth_blocklist.cc index 97aea3e..db5a6968 100644 --- a/content/browser/bluetooth/bluetooth_blocklist.cc +++ b/content/browser/bluetooth/bluetooth_blocklist.cc
@@ -141,11 +141,11 @@ void BluetoothBlocklist::PopulateWithDefaultValues() { blocklisted_uuids_.clear(); - // Testing from Layout Tests Note: + // Testing from Web Tests Note: // // Random UUIDs for object & exclude permutations that do not exist in the // standard blocklist are included to facilitate integration testing from - // Layout Tests. Unit tests can dynamically modify the blocklist, but don't + // Web Tests. Unit tests can dynamically modify the blocklist, but don't // offer the full integration test to the Web Bluetooth Javascript bindings. // // This is done for simplicity as opposed to exposing a testing API that can @@ -170,13 +170,13 @@ Add(BluetoothUUID("2a02"), Value::EXCLUDE_WRITES); Add(BluetoothUUID("2a03"), Value::EXCLUDE); Add(BluetoothUUID("2a25"), Value::EXCLUDE); - // Characteristics for Layout Tests: + // Characteristics for Web Tests: Add(BluetoothUUID("bad1c9a2-9a5b-4015-8b60-1579bbbf2135"), Value::EXCLUDE_READS); // Descriptors: Add(BluetoothUUID("2902"), Value::EXCLUDE_WRITES); Add(BluetoothUUID("2903"), Value::EXCLUDE_WRITES); - // Descriptors for Layout Tests: + // Descriptors for Web Tests: Add(BluetoothUUID("bad2ddcf-60db-45cd-bef9-fd72b153cf7c"), Value::EXCLUDE); Add(BluetoothUUID("bad3ec61-3cc3-4954-9702-7977df514114"), Value::EXCLUDE_READS);
diff --git a/content/browser/browser_context.cc b/content/browser/browser_context.cc index 9075365..d489e15 100644 --- a/content/browser/browser_context.cc +++ b/content/browser/browser_context.cc
@@ -566,8 +566,7 @@ void BrowserContext::NotifyWillBeDestroyed(BrowserContext* browser_context) { // Make sure NotifyWillBeDestroyed is idempotent. This helps facilitate the // pattern where NotifyWillBeDestroyed is called from *both* - // ShellBrowserContext and its derived classes (e.g. - // LayoutTestBrowserContext). + // ShellBrowserContext and its derived classes (e.g. WebTestBrowserContext). if (browser_context->was_notify_will_be_destroyed_called_) return; browser_context->was_notify_will_be_destroyed_called_ = true;
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index bce899c..154b8398 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -1318,6 +1318,14 @@ midi_service_.reset(new midi::MidiService); } + { + TRACE_EVENT0("startup", "BrowserThreadsStarted::Subsystem:GamepadService"); + device::GamepadService::GetInstance()->StartUp( + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->Clone()); + } + #if defined(OS_WIN) if (base::FeatureList::IsEnabled(features::kHighDynamicRange)) HDRProxy::Initialize();
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc index e706efb..fa03ea1 100644 --- a/content/browser/browser_plugin/browser_plugin_guest.cc +++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -1108,10 +1108,10 @@ // We could add functionality to set a specific capture sequence number on the // |view|, but knowing that it's changed is sufficient for us simply request // that our RenderWidgetHostView synchronizes its surfaces. Note that this - // should only happen during layout tests, since that is the only call that + // should only happen during web tests, since that is the only call that // should trigger the capture sequence number to change. if (capture_sequence_number_changed) - view->EnsureSurfaceSynchronizedForLayoutTest(); + view->EnsureSurfaceSynchronizedForWebTest(); RenderWidgetHostImpl* render_widget_host = RenderWidgetHostImpl::From(view->GetRenderWidgetHost());
diff --git a/content/browser/browser_thread_unittest.cc b/content/browser/browser_thread_unittest.cc index 377f0cbf8..b7d4168f7 100644 --- a/content/browser/browser_thread_unittest.cc +++ b/content/browser/browser_thread_unittest.cc
@@ -34,6 +34,8 @@ std::move(on_release_).Run(); } + void AddRef() {} + void StopUIThread() { ui_thread_->Stop(); } protected: @@ -152,7 +154,8 @@ TEST_F(BrowserThreadTest, Release) { base::RunLoop run_loop; ExpectRelease(run_loop.QuitWhenIdleClosure()); - BrowserThread::ReleaseSoon(BrowserThread::UI, FROM_HERE, this); + BrowserThread::ReleaseSoon(BrowserThread::UI, FROM_HERE, + base::WrapRefCounted(this)); run_loop.Run(); } @@ -212,7 +215,7 @@ base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::UI}); base::RunLoop run_loop; ExpectRelease(run_loop.QuitWhenIdleClosure()); - task_runner->ReleaseSoon(FROM_HERE, this); + task_runner->ReleaseSoon(FROM_HERE, base::WrapRefCounted(this)); run_loop.Run(); }
diff --git a/content/browser/browsing_data/clear_site_data_handler_browsertest.cc b/content/browser/browsing_data/clear_site_data_handler_browsertest.cc index fbaa291..7eda569 100644 --- a/content/browser/browsing_data/clear_site_data_handler_browsertest.cc +++ b/content/browser/browsing_data/clear_site_data_handler_browsertest.cc
@@ -1009,7 +1009,14 @@ // Expect the update to fail and the service worker to be removed. EXPECT_FALSE(RunScriptAndGetBool("updateServiceWorker()")); delegate()->VerifyAndClearExpectations(); - EXPECT_FALSE(RunScriptAndGetBool("hasServiceWorker()")); + // The service worker should be gone but a few tests are flaky and fail + // because it hasn't been removed. To find out if this is just a + // timing issue, add some delay if the first call returns true. + // TODO(crbug.com/912313): Check if this worked and find out why. + if (RunScriptAndGetBool("hasServiceWorker()")) { + LOG(ERROR) << "There was a service worker, checking again in a second"; + EXPECT_FALSE(RunScriptAndGetBool("setTimeout(hasServiceWorker, 1000)")); + } } } // namespace content
diff --git a/content/browser/browsing_data/clear_site_data_utils.cc b/content/browser/browsing_data/clear_site_data_utils.cc index 431925a..0626214 100644 --- a/content/browser/browsing_data/clear_site_data_utils.cc +++ b/content/browser/browsing_data/clear_site_data_utils.cc
@@ -44,7 +44,13 @@ scoped_observer_.Add(remover_); } - ~SiteDataClearer() override {} + ~SiteDataClearer() override { + // This SiteDataClearer class is self-owned, and the only way for it to be + // destroyed should be the "delete this" part in + // OnBrowsingDataRemoverDone() function, and it invokes the |callback_|. So + // when this destructor is called, the |callback_| should be null. + DCHECK(!callback_); + } void RunAndDestroySelfWhenDone() { DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/content/browser/cache_storage/cache_storage.cc b/content/browser/cache_storage/cache_storage.cc index 4802bef6..1c638d8f4 100644 --- a/content/browser/cache_storage/cache_storage.cc +++ b/content/browser/cache_storage/cache_storage.cc
@@ -604,6 +604,25 @@ CacheStorage::~CacheStorage() { } +CacheStorageHandle CacheStorage::CreateHandle() { + return CacheStorageHandle(weak_factory_.GetWeakPtr()); +} + +void CacheStorage::AddHandleRef() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + handle_ref_count_ += 1; +} + +void CacheStorage::DropHandleRef() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(handle_ref_count_ > 0); + handle_ref_count_ -= 1; + if (!handle_ref_count_ && cache_storage_manager_) { + ReleaseUnreferencedCaches(); + cache_storage_manager_->CacheStorageUnreferenced(this, origin_, owner_); + } +} + void CacheStorage::OpenCache(const std::string& cache_name, CacheAndErrorCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -615,6 +634,10 @@ CacheStorageQuotaClient::GetIDFromOwner(owner_), origin_, StorageType::kTemporary); + // TODO: Hold a handle to this CacheStorage instance while executing + // operations to better support use by internal code that may + // start a single operation without explicitly maintaining a + // handle. scheduler_->ScheduleOperation( CacheStorageSchedulerOp::kOpen, base::BindOnce(&CacheStorage::OpenCacheImpl, weak_factory_.GetWeakPtr(), @@ -1225,7 +1248,7 @@ void CacheStorage::CacheUnreferenced(CacheStorageCache* cache) { DCHECK(cache); - cache->AssertUnreferenced(); + DCHECK(cache->IsUnreferenced()); auto doomed_caches_it = doomed_caches_.find(cache); if (doomed_caches_it != doomed_caches_.end()) { // The last reference to a doomed cache is gone, perform clean up. @@ -1233,10 +1256,28 @@ return; } + // Opportunistically keep warmed caches open when the CacheStorage is + // still actively referenced. Repeatedly opening and closing simple + // disk_cache backends can be quite slow. This is easy to trigger when + // a site uses caches.match() frequently because the a Cache object is + // never exposed to script to explicitly hold the backend open. + if (handle_ref_count_) + return; + + // The CacheStorage is not actively being referenced. Close the cache + // immediately. auto cache_map_it = cache_map_.find(cache->cache_name()); DCHECK(cache_map_it != cache_map_.end()); cache_map_it->second.reset(); } +void CacheStorage::ReleaseUnreferencedCaches() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + for (auto& entry : cache_map_) { + if (entry.second && entry.second->IsUnreferenced()) + entry.second.reset(); + } +} + } // namespace content
diff --git a/content/browser/cache_storage/cache_storage.h b/content/browser/cache_storage/cache_storage.h index 1fcd148..f8450029 100644 --- a/content/browser/cache_storage/cache_storage.h +++ b/content/browser/cache_storage/cache_storage.h
@@ -16,10 +16,12 @@ #include "base/files/file_path.h" #include "base/gtest_prod_util.h" #include "base/macros.h" +#include "base/memory/memory_pressure_listener.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "content/browser/cache_storage/cache_storage_cache.h" #include "content/browser/cache_storage/cache_storage_cache_observer.h" +#include "content/browser/cache_storage/cache_storage_handle.h" #include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom.h" #include "url/origin.h" @@ -78,6 +80,23 @@ // callbacks. virtual ~CacheStorage(); + // Creates a new handle to this CacheStorage instance. Each handle represents + // a signal that the CacheStorage is in active use and should avoid cleaning + // up resources, if possible. However, there are some cases, such as a + // user-initiated storage wipe, that will forcibly delete the CacheStorage + // instance. Therefore the handle should be treated as a weak pointer that + // needs to be tested for existence before use. + CacheStorageHandle CreateHandle(); + + // These methods are called by the CacheStorageHandle to track the number + // of outstanding references. + void AddHandleRef(); + void DropHandleRef(); + void AssertUnreferenced() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!handle_ref_count_); + } + // Get the cache for the given key. If the cache is not found it is // created. The CacheStorgeCacheHandle in the callback prolongs the lifetime // of the cache. Once all handles to a cache are deleted the cache is deleted. @@ -139,6 +158,13 @@ // CacheStorageCacheObserver: void CacheSizeUpdated(const CacheStorageCache* cache) override; + // The immutable origin of the CacheStorage. + const url::Origin& Origin() const { return origin_; } + + // Destroy any CacheStorageCache instances that are not currently referenced + // by a CacheStorageCacheHandle. + void ReleaseUnreferencedCaches(); + private: friend class CacheStorageCache; friend class cache_storage_manager_unittest::CacheStorageManagerTest; @@ -278,7 +304,7 @@ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; // The origin that this CacheStorage is associated with. - url::Origin origin_; + const url::Origin origin_; // The owner that this CacheStorage is associated with. CacheStorageOwner owner_; @@ -288,7 +314,9 @@ CacheStorageManager* cache_storage_manager_; base::CancelableOnceClosure index_write_task_; + size_t handle_ref_count_ = 0; + SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory<CacheStorage> weak_factory_; DISALLOW_COPY_AND_ASSIGN(CacheStorage);
diff --git a/content/browser/cache_storage/cache_storage_cache.cc b/content/browser/cache_storage/cache_storage_cache.cc index a47864e..96e9623 100644 --- a/content/browser/cache_storage/cache_storage_cache.cc +++ b/content/browser/cache_storage/cache_storage_cache.cc
@@ -514,20 +514,29 @@ void CacheStorageCache::AddHandleRef() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); handle_ref_count_ += 1; + // Reference the parent CacheStorage while the Cache is referenced. Some + // code may only directly reference the Cache and we don't want to let the + // CacheStorage cleanup if it becomes unreferenced in these cases. + if (handle_ref_count_ == 1 && cache_storage_) + cache_storage_handle_ = cache_storage_->CreateHandle(); } void CacheStorageCache::DropHandleRef() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(handle_ref_count_ > 0); handle_ref_count_ -= 1; + // Dropping the last reference may result in the parent CacheStorage + // deleting itself or this Cache object. Be careful not to touch the + // `this` pointer in this method after the following code. if (handle_ref_count_ == 0 && cache_storage_) { + CacheStorageHandle handle = std::move(cache_storage_handle_); cache_storage_->CacheUnreferenced(this); } } -void CacheStorageCache::AssertUnreferenced() const { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(!handle_ref_count_); +bool CacheStorageCache::IsUnreferenced() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return !handle_ref_count_; } void CacheStorageCache::Match(blink::mojom::FetchAPIRequestPtr request,
diff --git a/content/browser/cache_storage/cache_storage_cache.h b/content/browser/cache_storage/cache_storage_cache.h index 572ddc79..1790d40 100644 --- a/content/browser/cache_storage/cache_storage_cache.h +++ b/content/browser/cache_storage/cache_storage_cache.h
@@ -18,6 +18,7 @@ #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "content/browser/cache_storage/cache_storage_cache_handle.h" +#include "content/browser/cache_storage/cache_storage_handle.h" #include "content/common/service_worker/service_worker_types.h" #include "net/base/io_buffer.h" #include "net/disk_cache/disk_cache.h" @@ -238,7 +239,7 @@ virtual CacheStorageCacheHandle CreateHandle(); void AddHandleRef(); void DropHandleRef(); - void AssertUnreferenced() const; + bool IsUnreferenced() const; private: // QueryCache types: @@ -484,9 +485,14 @@ const std::string cache_name_; base::FilePath path_; - // Raw pointer is safe because CacheStorage owns this object. + // Raw pointer is safe because the CacheStorage instance owns this + // CacheStorageCache object. CacheStorage* cache_storage_; + // A handle that is used to keep the owning CacheStorage instance referenced + // as long this cache object is also referenced. + CacheStorageHandle cache_storage_handle_; + scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_; base::WeakPtr<storage::BlobStorageContext> blob_storage_context_; BackendState backend_state_ = BACKEND_UNINITIALIZED;
diff --git a/content/browser/cache_storage/cache_storage_dispatcher_host.cc b/content/browser/cache_storage/cache_storage_dispatcher_host.cc index 6f24fdf..0766d52 100644 --- a/content/browser/cache_storage/cache_storage_dispatcher_host.cc +++ b/content/browser/cache_storage/cache_storage_dispatcher_host.cc
@@ -20,6 +20,7 @@ #include "content/browser/cache_storage/cache_storage_cache.h" #include "content/browser/cache_storage/cache_storage_cache_handle.h" #include "content/browser/cache_storage/cache_storage_context_impl.h" +#include "content/browser/cache_storage/cache_storage_histogram_utils.h" #include "content/browser/cache_storage/cache_storage_manager.h" #include "content/common/background_fetch/background_fetch_types.h" #include "content/common/service_worker/service_worker_utils.h" @@ -41,15 +42,11 @@ using blink::mojom::CacheStorageError; using blink::mojom::CacheStorageVerboseError; -const int32_t kCachePreservationSeconds = 5; - // TODO(lucmult): Check this before binding. bool OriginCanAccessCacheStorage(const url::Origin& origin) { return !origin.opaque() && IsOriginSecure(origin.GetURL()); } -void StopPreservingCache(CacheStorageCacheHandle cache_handle) {} - } // namespace // Implements the mojom interface CacheStorageCache. It's owned by @@ -58,11 +55,8 @@ class CacheStorageDispatcherHost::CacheImpl : public blink::mojom::CacheStorageCache { public: - CacheImpl(CacheStorageCacheHandle cache_handle, - CacheStorageDispatcherHost* dispatcher_host) - : cache_handle_(std::move(cache_handle)), - owner_(dispatcher_host), - weak_factory_(this) {} + explicit CacheImpl(CacheStorageCacheHandle cache_handle) + : cache_handle_(std::move(cache_handle)), weak_factory_(this) {} ~CacheImpl() override = default; @@ -187,13 +181,168 @@ } CacheStorageCacheHandle cache_handle_; + base::WeakPtrFactory<CacheImpl> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(CacheImpl); +}; + +// Implements the mojom interface CacheStorage. It's owned by the +// CacheStorageDispatcherHost. The CacheStorageImpl is destroyed when the +// client drops its mojo ptr which in turn removes from StrongBindingSet in +// CacheStorageDispatcherHost. +class CacheStorageDispatcherHost::CacheStorageImpl final + : public blink::mojom::CacheStorage { + public: + CacheStorageImpl(CacheStorageDispatcherHost* owner, const url::Origin& origin) + : owner_(owner), origin_(origin), weak_factory_(this) { + // The CacheStorageHandle is empty to start and lazy initialized on first + // use via GetOrCreateCacheStorage(). In the future we could eagerly create + // the backend when the mojo connection is created. + } + + ~CacheStorageImpl() override = default; + + // Mojo CacheStorage Interface implementation: + void Keys(blink::mojom::CacheStorage::KeysCallback callback) override { + content::CacheStorage* cache_storage = GetOrCreateCacheStorage(); + if (!cache_storage) { + std::move(callback).Run(std::vector<base::string16>()); + return; + } + cache_storage->EnumerateCaches(base::BindOnce( + [](blink::mojom::CacheStorage::KeysCallback callback, + const CacheStorageIndex& cache_index) { + std::vector<base::string16> string16s; + for (const auto& metadata : cache_index.ordered_cache_metadata()) { + string16s.push_back(base::UTF8ToUTF16(metadata.name)); + } + std::move(callback).Run(string16s); + }, + std::move(callback))); + } + + void Delete(const base::string16& cache_name, + blink::mojom::CacheStorage::DeleteCallback callback) override { + content::CacheStorage* cache_storage = GetOrCreateCacheStorage(); + if (!cache_storage) { + std::move(callback).Run( + MakeErrorStorage(ErrorStorageType::kStorageHandleNull)); + return; + } + cache_storage->DoomCache(base::UTF16ToUTF8(cache_name), + std::move(callback)); + } + + void Has(const base::string16& cache_name, + blink::mojom::CacheStorage::HasCallback callback) override { + content::CacheStorage* cache_storage = GetOrCreateCacheStorage(); + if (!cache_storage) { + std::move(callback).Run( + MakeErrorStorage(ErrorStorageType::kStorageHandleNull)); + return; + } + cache_storage->HasCache( + base::UTF16ToUTF8(cache_name), + base::BindOnce( + [](blink::mojom::CacheStorage::HasCallback callback, bool has_cache, + CacheStorageError error) { + if (!has_cache) + error = CacheStorageError::kErrorNotFound; + std::move(callback).Run(error); + }, + std::move(callback))); + } + + void Match(blink::mojom::FetchAPIRequestPtr request, + blink::mojom::QueryParamsPtr match_params, + blink::mojom::CacheStorage::MatchCallback callback) override { + content::CacheStorage* cache_storage = GetOrCreateCacheStorage(); + if (!cache_storage) { + std::move(callback).Run(blink::mojom::MatchResult::NewStatus( + CacheStorageError::kErrorNotFound)); + return; + } + + auto on_match = BindOnce( + [](blink::mojom::CacheStorage::MatchCallback callback, + CacheStorageError error, + blink::mojom::FetchAPIResponsePtr response) { + if (error != CacheStorageError::kSuccess) { + std::move(callback).Run( + blink::mojom::MatchResult::NewStatus(error)); + return; + } + + std::move(callback).Run( + blink::mojom::MatchResult::NewResponse(std::move(response))); + }, + std::move(callback)); + + if (!match_params->cache_name) { + cache_storage->MatchAllCaches(std::move(request), std::move(match_params), + std::move(on_match)); + return; + } + std::string cache_name = base::UTF16ToUTF8(*match_params->cache_name); + cache_storage->MatchCache(std::move(cache_name), std::move(request), + std::move(match_params), std::move(on_match)); + } + + void Open(const base::string16& cache_name, + blink::mojom::CacheStorage::OpenCallback callback) override { + content::CacheStorage* cache_storage = GetOrCreateCacheStorage(); + if (!cache_storage) { + std::move(callback).Run(blink::mojom::OpenResult::NewStatus( + MakeErrorStorage(ErrorStorageType::kStorageHandleNull))); + return; + } + cache_storage->OpenCache( + base::UTF16ToUTF8(cache_name), + base::BindOnce( + [](base::WeakPtr<CacheStorageImpl> self, + blink::mojom::CacheStorage::OpenCallback callback, + CacheStorageCacheHandle cache_handle, CacheStorageError error) { + if (!self) + return; + + if (error != CacheStorageError::kSuccess) { + std::move(callback).Run( + blink::mojom::OpenResult::NewStatus(error)); + return; + } + + blink::mojom::CacheStorageCacheAssociatedPtrInfo ptr_info; + auto request = mojo::MakeRequest(&ptr_info); + auto cache_impl = + std::make_unique<CacheImpl>(std::move(cache_handle)); + self->owner_->AddCacheBinding(std::move(cache_impl), + std::move(request)); + + std::move(callback).Run( + blink::mojom::OpenResult::NewCache(std::move(ptr_info))); + }, + weak_factory_.GetWeakPtr(), std::move(callback))); + } + + private: + // Helper method that returns the current CacheStorageHandle value. If the + // handle is closed, then it attempts to open a new CacheStorageHandle + // automatically. This automatic open is necessary to re-attach to the + // backend after the browser storage has been wiped. + content::CacheStorage* GetOrCreateCacheStorage() { + DCHECK(owner_); + if (!cache_storage_handle_.value()) + cache_storage_handle_ = owner_->OpenCacheStorage(origin_); + return cache_storage_handle_.value(); + } // Owns this. CacheStorageDispatcherHost* const owner_; - base::WeakPtrFactory<CacheImpl> weak_factory_; + const url::Origin origin_; + CacheStorageHandle cache_storage_handle_; - DISALLOW_COPY_AND_ASSIGN(CacheImpl); + base::WeakPtrFactory<CacheStorageImpl> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(CacheStorageImpl); }; CacheStorageDispatcherHost::CacheStorageDispatcherHost() = default; @@ -214,170 +363,29 @@ context_ = context; } -void CacheStorageDispatcherHost::Has( - const base::string16& cache_name, - blink::mojom::CacheStorage::HasCallback callback) { - TRACE_EVENT0("CacheStorage", "CacheStorageDispatcherHost::OnCacheStorageHas"); - url::Origin origin = bindings_.dispatch_context(); - if (!OriginCanAccessCacheStorage(origin)) { - bindings_.ReportBadMessage("CSDH_INVALID_ORIGIN"); - return; - } - if (!ValidState()) - return; - context_->cache_manager()->HasCache( - origin, CacheStorageOwner::kCacheAPI, base::UTF16ToUTF8(cache_name), - base::BindOnce(&CacheStorageDispatcherHost::OnHasCallback, this, - std::move(callback))); -} - -void CacheStorageDispatcherHost::Open( - const base::string16& cache_name, - blink::mojom::CacheStorage::OpenCallback callback) { - TRACE_EVENT0("CacheStorage", - "CacheStorageDispatcherHost::OnCacheStorageOpen"); - url::Origin origin = bindings_.dispatch_context(); - if (!OriginCanAccessCacheStorage(origin)) { - bindings_.ReportBadMessage("CSDH_INVALID_ORIGIN"); - return; - } - if (!ValidState()) - return; - context_->cache_manager()->OpenCache( - origin, CacheStorageOwner::kCacheAPI, base::UTF16ToUTF8(cache_name), - base::BindOnce(&CacheStorageDispatcherHost::OnOpenCallback, this, origin, - std::move(callback))); -} - -void CacheStorageDispatcherHost::Delete( - const base::string16& cache_name, - blink::mojom::CacheStorage::DeleteCallback callback) { - TRACE_EVENT0("CacheStorage", - "CacheStorageDispatcherHost::OnCacheStorageDelete"); - url::Origin origin = bindings_.dispatch_context(); - if (!OriginCanAccessCacheStorage(origin)) { - bindings_.ReportBadMessage("CSDH_INVALID_ORIGIN"); - return; - } - if (!ValidState()) - return; - context_->cache_manager()->DeleteCache(origin, CacheStorageOwner::kCacheAPI, - base::UTF16ToUTF8(cache_name), - - std::move(callback)); -} - -void CacheStorageDispatcherHost::Keys( - blink::mojom::CacheStorage::KeysCallback callback) { - TRACE_EVENT0("CacheStorage", - "CacheStorageDispatcherHost::OnCacheStorageKeys"); - url::Origin origin = bindings_.dispatch_context(); - - if (!OriginCanAccessCacheStorage(origin)) { - bindings_.ReportBadMessage("CSDH_INVALID_ORIGIN"); - return; - } - if (!ValidState()) - return; - context_->cache_manager()->EnumerateCaches( - origin, CacheStorageOwner::kCacheAPI, - base::BindOnce(&CacheStorageDispatcherHost::OnKeysCallback, this, - std::move(callback))); -} - -void CacheStorageDispatcherHost::Match( - blink::mojom::FetchAPIRequestPtr request, - blink::mojom::QueryParamsPtr match_params, - blink::mojom::CacheStorage::MatchCallback callback) { - TRACE_EVENT0("CacheStorage", - "CacheStorageDispatcherHost::OnCacheStorageMatch"); - url::Origin origin = bindings_.dispatch_context(); - if (!OriginCanAccessCacheStorage(origin)) { - bindings_.ReportBadMessage("CSDH_INVALID_ORIGIN"); - return; - } - if (!ValidState()) - return; - - if (!match_params->cache_name) { - context_->cache_manager()->MatchAllCaches( - origin, CacheStorageOwner::kCacheAPI, std::move(request), - std::move(match_params), - base::BindOnce(&CacheStorageDispatcherHost::OnMatchCallback, this, - std::move(callback))); - return; - } - std::string cache_name = base::UTF16ToUTF8(*match_params->cache_name); - context_->cache_manager()->MatchCache( - origin, CacheStorageOwner::kCacheAPI, std::move(cache_name), - std::move(request), std::move(match_params), - base::BindOnce(&CacheStorageDispatcherHost::OnMatchCallback, this, - std::move(callback))); -} - -void CacheStorageDispatcherHost::OnHasCallback( - blink::mojom::CacheStorage::HasCallback callback, - bool has_cache, - CacheStorageError error) { - if (!has_cache) - error = CacheStorageError::kErrorNotFound; - std::move(callback).Run(error); -} - -void CacheStorageDispatcherHost::OnOpenCallback( - url::Origin origin, - blink::mojom::CacheStorage::OpenCallback callback, - CacheStorageCacheHandle cache_handle, - CacheStorageError error) { - if (error != CacheStorageError::kSuccess) { - std::move(callback).Run(blink::mojom::OpenResult::NewStatus(error)); - return; - } - - // Hang on to the cache for a few seconds. This way if the user quickly closes - // and reopens it the cache backend won't have to be reinitialized. - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::BindOnce(&StopPreservingCache, cache_handle.Clone()), - base::TimeDelta::FromSeconds(kCachePreservationSeconds)); - - blink::mojom::CacheStorageCacheAssociatedPtrInfo ptr_info; - auto request = mojo::MakeRequest(&ptr_info); - auto cache_impl = std::make_unique<CacheImpl>(std::move(cache_handle), this); - cache_bindings_.AddBinding(std::move(cache_impl), std::move(request)); - - std::move(callback).Run( - blink::mojom::OpenResult::NewCache(std::move(ptr_info))); -} - -void CacheStorageDispatcherHost::OnKeysCallback( - blink::mojom::CacheStorage::KeysCallback callback, - const CacheStorageIndex& cache_index) { - std::vector<base::string16> string16s; - for (const auto& metadata : cache_index.ordered_cache_metadata()) { - string16s.push_back(base::UTF8ToUTF16(metadata.name)); - } - - std::move(callback).Run(string16s); -} - -void CacheStorageDispatcherHost::OnMatchCallback( - blink::mojom::CacheStorage::MatchCallback callback, - CacheStorageError error, - blink::mojom::FetchAPIResponsePtr response) { - if (error != CacheStorageError::kSuccess) { - std::move(callback).Run(blink::mojom::MatchResult::NewStatus(error)); - return; - } - - std::move(callback).Run( - blink::mojom::MatchResult::NewResponse(std::move(response))); -} - void CacheStorageDispatcherHost::AddBinding( blink::mojom::CacheStorageRequest request, const url::Origin& origin) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - bindings_.AddBinding(this, std::move(request), origin); + auto impl = std::make_unique<CacheStorageImpl>(this, origin); + bindings_.AddBinding(std::move(impl), std::move(request)); +} + +void CacheStorageDispatcherHost::AddCacheBinding( + std::unique_ptr<CacheImpl> cache_impl, + blink::mojom::CacheStorageCacheAssociatedRequest request) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + cache_bindings_.AddBinding(std::move(cache_impl), std::move(request)); +} + +CacheStorageHandle CacheStorageDispatcherHost::OpenCacheStorage( + const url::Origin& origin) { + if (!context_ || !context_->cache_manager() || + !OriginCanAccessCacheStorage(origin)) + return CacheStorageHandle(); + + return context_->cache_manager()->OpenCacheStorage( + origin, CacheStorageOwner::kCacheAPI); } bool CacheStorageDispatcherHost::ValidState() {
diff --git a/content/browser/cache_storage/cache_storage_dispatcher_host.h b/content/browser/cache_storage/cache_storage_dispatcher_host.h index 2cd443f1a..1f07b73 100644 --- a/content/browser/cache_storage/cache_storage_dispatcher_host.h +++ b/content/browser/cache_storage/cache_storage_dispatcher_host.h
@@ -17,7 +17,6 @@ #include "content/browser/cache_storage/cache_storage.h" #include "content/browser/cache_storage/cache_storage_index.h" #include "content/public/browser/browser_thread.h" -#include "mojo/public/cpp/bindings/associated_binding_set.h" #include "mojo/public/cpp/bindings/strong_associated_binding_set.h" #include "mojo/public/cpp/bindings/strong_binding_set.h" #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h" @@ -35,8 +34,7 @@ // messages are processed on the IO thread. class CONTENT_EXPORT CacheStorageDispatcherHost : public base::RefCountedThreadSafe<CacheStorageDispatcherHost, - BrowserThread::DeleteOnIOThread>, - public blink::mojom::CacheStorage { + BrowserThread::DeleteOnIOThread> { public: CacheStorageDispatcherHost(); @@ -57,39 +55,21 @@ friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>; friend class base::DeleteHelper<CacheStorageDispatcherHost>; + class CacheStorageImpl; class CacheImpl; + friend class CacheImpl; - ~CacheStorageDispatcherHost() override; + void AddCacheBinding( + std::unique_ptr<CacheImpl> cache_impl, + blink::mojom::CacheStorageCacheAssociatedRequest request); + + CacheStorageHandle OpenCacheStorage(const url::Origin& origin); + + ~CacheStorageDispatcherHost(); // Called by Init() on IO thread. void CreateCacheListener(CacheStorageContextImpl* context); - // Mojo CacheStorage Interface implementation: - void Keys(blink::mojom::CacheStorage::KeysCallback callback) override; - void Delete(const base::string16& cache_name, - blink::mojom::CacheStorage::DeleteCallback callback) override; - void Has(const base::string16& cache_name, - blink::mojom::CacheStorage::HasCallback callback) override; - void Match(blink::mojom::FetchAPIRequestPtr request, - blink::mojom::QueryParamsPtr match_params, - blink::mojom::CacheStorage::MatchCallback callback) override; - void Open(const base::string16& cache_name, - blink::mojom::CacheStorage::OpenCallback callback) override; - - // Callbacks used by Mojo implementation: - void OnKeysCallback(KeysCallback callback, - const CacheStorageIndex& cache_index); - void OnHasCallback(blink::mojom::CacheStorage::HasCallback callback, - bool has_cache, - blink::mojom::CacheStorageError error); - void OnMatchCallback(blink::mojom::CacheStorage::MatchCallback callback, - blink::mojom::CacheStorageError error, - blink::mojom::FetchAPIResponsePtr response); - void OnOpenCallback(url::Origin origin, - blink::mojom::CacheStorage::OpenCallback callback, - CacheStorageCacheHandle cache_handle, - blink::mojom::CacheStorageError error); - // Validate the current state of required members, returns false if they // aren't valid and also close |bindings_|, so it's safe to not run // mojo callbacks. @@ -97,7 +77,7 @@ scoped_refptr<CacheStorageContextImpl> context_; - mojo::BindingSet<blink::mojom::CacheStorage, url::Origin> bindings_; + mojo::StrongBindingSet<blink::mojom::CacheStorage> bindings_; mojo::StrongAssociatedBindingSet<blink::mojom::CacheStorageCache> cache_bindings_;
diff --git a/content/browser/cache_storage/cache_storage_handle.h b/content/browser/cache_storage/cache_storage_handle.h new file mode 100644 index 0000000..7096d00a --- /dev/null +++ b/content/browser/cache_storage/cache_storage_handle.h
@@ -0,0 +1,17 @@ +// 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_BROWSER_CACHE_STORAGE_CACHE_STORAGE_HANDLE_H_ +#define CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_HANDLE_H_ + +#include "content/browser/cache_storage/cache_storage_ref.h" + +namespace content { + +class CacheStorage; +using CacheStorageHandle = CacheStorageRef<CacheStorage>; + +} // namespace content + +#endif // CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_HANDLE_H_
diff --git a/content/browser/cache_storage/cache_storage_histogram_utils.h b/content/browser/cache_storage/cache_storage_histogram_utils.h index 00c07f65..a7c7520 100644 --- a/content/browser/cache_storage/cache_storage_histogram_utils.h +++ b/content/browser/cache_storage/cache_storage_histogram_utils.h
@@ -36,7 +36,8 @@ kKeysImplBackendClosed = 21, kCreateBackendDidCreateFailed = 22, kStorageGetAllMatchedEntriesBackendClosed = 23, - kMaxValue = kStorageGetAllMatchedEntriesBackendClosed, + kStorageHandleNull = 24, + kMaxValue = kStorageHandleNull, }; blink::mojom::CacheStorageError MakeErrorStorage(ErrorStorageType type);
diff --git a/content/browser/cache_storage/cache_storage_manager.cc b/content/browser/cache_storage/cache_storage_manager.cc index cd2cde6b..b1fa277 100644 --- a/content/browser/cache_storage/cache_storage_manager.cc +++ b/content/browser/cache_storage/cache_storage_manager.cc
@@ -180,89 +180,30 @@ CacheStorageManager::~CacheStorageManager() = default; -void CacheStorageManager::OpenCache( +CacheStorageHandle CacheStorageManager::OpenCacheStorage( const url::Origin& origin, - CacheStorageOwner owner, - const std::string& cache_name, - CacheStorage::CacheAndErrorCallback callback) { + CacheStorageOwner owner) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - CacheStorage* cache_storage = FindOrCreateCacheStorage(origin, owner); + // Wait to create the MemoryPressureListener until the first CacheStorage + // object is needed. This ensures we create the listener on the correct + // thread. + if (!memory_pressure_listener_) { + memory_pressure_listener_ = + std::make_unique<base::MemoryPressureListener>(base::BindRepeating( + &CacheStorageManager::OnMemoryPressure, base::Unretained(this))); + } - cache_storage->OpenCache(cache_name, std::move(callback)); -} - -void CacheStorageManager::HasCache( - const url::Origin& origin, - CacheStorageOwner owner, - const std::string& cache_name, - CacheStorage::BoolAndErrorCallback callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - CacheStorage* cache_storage = FindOrCreateCacheStorage(origin, owner); - cache_storage->HasCache(cache_name, std::move(callback)); -} - -void CacheStorageManager::DeleteCache(const url::Origin& origin, - CacheStorageOwner owner, - const std::string& cache_name, - CacheStorage::ErrorCallback callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - CacheStorage* cache_storage = FindOrCreateCacheStorage(origin, owner); - cache_storage->DoomCache(cache_name, std::move(callback)); -} - -void CacheStorageManager::EnumerateCaches( - const url::Origin& origin, - CacheStorageOwner owner, - CacheStorage::IndexCallback callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - CacheStorage* cache_storage = FindOrCreateCacheStorage(origin, owner); - - cache_storage->EnumerateCaches(std::move(callback)); -} - -void CacheStorageManager::MatchCache( - const url::Origin& origin, - CacheStorageOwner owner, - const std::string& cache_name, - blink::mojom::FetchAPIRequestPtr request, - blink::mojom::QueryParamsPtr match_params, - CacheStorageCache::ResponseCallback callback) { - CacheStorage* cache_storage = FindOrCreateCacheStorage(origin, owner); - - cache_storage->MatchCache(cache_name, std::move(request), - std::move(match_params), std::move(callback)); -} - -void CacheStorageManager::MatchAllCaches( - const url::Origin& origin, - CacheStorageOwner owner, - blink::mojom::FetchAPIRequestPtr request, - blink::mojom::QueryParamsPtr match_params, - CacheStorageCache::ResponseCallback callback) { - CacheStorage* cache_storage = FindOrCreateCacheStorage(origin, owner); - - cache_storage->MatchAllCaches(std::move(request), std::move(match_params), - std::move(callback)); -} - -void CacheStorageManager::WriteToCache( - const url::Origin& origin, - CacheStorageOwner owner, - const std::string& cache_name, - blink::mojom::FetchAPIRequestPtr request, - blink::mojom::FetchAPIResponsePtr response, - CacheStorage::ErrorCallback callback) { - // Cache API should write through the dispatcher. - DCHECK_NE(owner, CacheStorageOwner::kCacheAPI); - - CacheStorage* cache_storage = FindOrCreateCacheStorage(origin, owner); - - cache_storage->WriteToCache(cache_name, std::move(request), - std::move(response), std::move(callback)); + CacheStorageMap::const_iterator it = cache_storage_map_.find({origin, owner}); + if (it == cache_storage_map_.end()) { + CacheStorage* cache_storage = new CacheStorage( + ConstructOriginPath(root_path_, origin, owner), IsMemoryBacked(), + cache_task_runner_.get(), quota_manager_proxy_, blob_context_, this, + origin, owner); + cache_storage_map_[{origin, owner}] = base::WrapUnique(cache_storage); + return cache_storage->CreateHandle(); + } + return it->second.get()->CreateHandle(); } void CacheStorageManager::SetBlobParametersForCache( @@ -295,6 +236,20 @@ observer.OnCacheContentChanged(origin, name); } +void CacheStorageManager::CacheStorageUnreferenced(CacheStorage* cache_storage, + const url::Origin& origin, + CacheStorageOwner owner) { + DCHECK(cache_storage); + cache_storage->AssertUnreferenced(); + auto it = cache_storage_map_.find({origin, owner}); + DCHECK(it != cache_storage_map_.end()); + DCHECK(it->second.get() == cache_storage); + + // Currently we don't do anything when a CacheStorage instance becomes + // unreferenced. In the future we will deallocate some or all of the + // CacheStorage's state. +} + void CacheStorageManager::GetAllOriginsUsage( CacheStorageOwner owner, CacheStorageContext::GetUsageInfoCallback callback) { @@ -350,9 +305,9 @@ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, barrier_closure); continue; } - CacheStorage* cache_storage = FindOrCreateCacheStorage( + CacheStorageHandle cache_storage = OpenCacheStorage( url::Origin::Create(usage.origin), CacheStorageOwner::kCacheAPI); - cache_storage->Size( + cache_storage.value()->Size( base::BindOnce(&OneOriginSizeReported, barrier_closure, &usage)); } } @@ -363,9 +318,9 @@ storage::QuotaClient::GetUsageCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - CacheStorage* cache_storage = FindOrCreateCacheStorage(origin, owner); + CacheStorageHandle cache_storage = OpenCacheStorage(origin, owner); - cache_storage->Size(std::move(callback)); + cache_storage.value()->Size(std::move(callback)); } void CacheStorageManager::GetOrigins( @@ -423,7 +378,7 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); // Create the CacheStorage for the origin if it hasn't been loaded yet. - FindOrCreateCacheStorage(origin, owner); + CacheStorageHandle handle = OpenCacheStorage(origin, owner); auto it = cache_storage_map_.find({origin, owner}); DCHECK(it != cache_storage_map_.end()); @@ -491,22 +446,6 @@ } } -CacheStorage* CacheStorageManager::FindOrCreateCacheStorage( - const url::Origin& origin, - CacheStorageOwner owner) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - CacheStorageMap::const_iterator it = cache_storage_map_.find({origin, owner}); - if (it == cache_storage_map_.end()) { - CacheStorage* cache_storage = new CacheStorage( - ConstructOriginPath(root_path_, origin, owner), IsMemoryBacked(), - cache_task_runner_.get(), quota_manager_proxy_, blob_context_, this, - origin, owner); - cache_storage_map_[{origin, owner}] = base::WrapUnique(cache_storage); - return cache_storage; - } - return it->second.get(); -} - // static base::FilePath CacheStorageManager::ConstructOriginPath( const base::FilePath& root_path, @@ -522,4 +461,14 @@ return root_path.AppendASCII(origin_hash_hex); } +void CacheStorageManager::OnMemoryPressure( + base::MemoryPressureListener::MemoryPressureLevel level) { + if (level != base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) + return; + + for (auto& entry : cache_storage_map_) { + entry.second->ReleaseUnreferencedCaches(); + } +} + } // namespace content
diff --git a/content/browser/cache_storage/cache_storage_manager.h b/content/browser/cache_storage/cache_storage_manager.h index 01891a2..9a5832c4 100644 --- a/content/browser/cache_storage/cache_storage_manager.h +++ b/content/browser/cache_storage/cache_storage_manager.h
@@ -12,6 +12,7 @@ #include "base/files/file_path.h" #include "base/macros.h" +#include "base/memory/memory_pressure_listener.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_refptr.h" #include "content/browser/cache_storage/cache_storage.h" @@ -73,44 +74,10 @@ const url::Origin& origin, CacheStorageOwner owner); - // Methods to support the CacheStorage spec. These methods call the - // corresponding CacheStorage method on the appropriate thread. - void OpenCache(const url::Origin& origin, - CacheStorageOwner owner, - const std::string& cache_name, - CacheStorage::CacheAndErrorCallback callback); - void HasCache(const url::Origin& origin, - CacheStorageOwner owner, - const std::string& cache_name, - CacheStorage::BoolAndErrorCallback callback); - void DeleteCache(const url::Origin& origin, - CacheStorageOwner owner, - const std::string& cache_name, - CacheStorage::ErrorCallback callback); - void EnumerateCaches(const url::Origin& origin, - CacheStorageOwner owner, - CacheStorage::IndexCallback callback); - void MatchCache(const url::Origin& origin, - CacheStorageOwner owner, - const std::string& cache_name, - blink::mojom::FetchAPIRequestPtr request, - blink::mojom::QueryParamsPtr match_params, - CacheStorageCache::ResponseCallback callback); - void MatchAllCaches(const url::Origin& origin, - CacheStorageOwner owner, - blink::mojom::FetchAPIRequestPtr request, - blink::mojom::QueryParamsPtr match_params, - CacheStorageCache::ResponseCallback callback); - - // Method to support writing to a cache directly from CacheStorageManager. - // This should be used by non-CacheAPI owners. The Cache API writes are - // handled via the dispatcher. - void WriteToCache(const url::Origin& origin, - CacheStorageOwner owner, - const std::string& cache_name, - blink::mojom::FetchAPIRequestPtr request, - blink::mojom::FetchAPIResponsePtr response, - CacheStorage::ErrorCallback callback); + // Open the CacheStorage for the given origin and owner. A reference counting + // handle is returned which can be stored and used similar to a weak pointer. + CacheStorageHandle OpenCacheStorage(const url::Origin& origin, + CacheStorageOwner owner); // This must be called before creating any of the public *Cache functions // above. @@ -130,6 +97,12 @@ base::FilePath root_path() const { return root_path_; } + // This method is called when the last CacheStorageHandle for a particular + // instance is destroyed and its reference count drops to zero. + void CacheStorageUnreferenced(CacheStorage* cache_storage, + const url::Origin& origin, + CacheStorageOwner owner); + private: friend class base::DeleteHelper<CacheStorageManager>; friend class base::RefCountedThreadSafe<CacheStorageManager>; @@ -149,10 +122,6 @@ virtual ~CacheStorageManager(); - // The returned CacheStorage* is owned by this manager. - CacheStorage* FindOrCreateCacheStorage(const url::Origin& origin, - CacheStorageOwner owner); - // QuotaClient and Browsing Data Deletion support void GetAllOriginsUsage(CacheStorageOwner owner, CacheStorageContext::GetUsageInfoCallback callback); @@ -188,6 +157,10 @@ bool IsMemoryBacked() const { return root_path_.empty(); } + // MemoryPressureListener callback + void OnMemoryPressure( + base::MemoryPressureListener::MemoryPressureLevel level); + base::FilePath root_path_; scoped_refptr<base::SequencedTaskRunner> cache_task_runner_; @@ -201,6 +174,8 @@ base::WeakPtr<storage::BlobStorageContext> blob_context_; + std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; + base::WeakPtrFactory<CacheStorageManager> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(CacheStorageManager); };
diff --git a/content/browser/cache_storage/cache_storage_manager_unittest.cc b/content/browser/cache_storage/cache_storage_manager_unittest.cc index f439f8f..c1e316b 100644 --- a/content/browser/cache_storage/cache_storage_manager_unittest.cc +++ b/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -283,9 +283,11 @@ callback_bool_ = false; base::RunLoop loop; bool write_was_scheduled = - CacheStorageForOrigin(origin)->InitiateScheduledIndexWriteForTest( - base::BindOnce(&CacheStorageManagerTest::BoolCallback, - base::Unretained(this), &loop)); + CacheStorageForOrigin(origin) + .value() + ->InitiateScheduledIndexWriteForTest( + base::BindOnce(&CacheStorageManagerTest::BoolCallback, + base::Unretained(this), &loop)); loop.Run(); DCHECK(callback_bool_); return write_was_scheduled; @@ -328,8 +330,10 @@ CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) { base::HistogramTester histogram_tester; base::RunLoop loop; - cache_manager_->OpenCache( - origin, owner, cache_name, + CacheStorageHandle cache_storage = + cache_manager_->OpenCacheStorage(origin, owner); + cache_storage.value()->OpenCache( + cache_name, base::BindOnce(&CacheStorageManagerTest::CacheAndErrorCallback, base::Unretained(this), base::Unretained(&loop))); loop.Run(); @@ -349,8 +353,10 @@ CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) { base::HistogramTester histogram_tester; base::RunLoop loop; - cache_manager_->HasCache( - origin, owner, cache_name, + CacheStorageHandle cache_storage = + cache_manager_->OpenCacheStorage(origin, owner); + cache_storage.value()->HasCache( + cache_name, base::BindOnce(&CacheStorageManagerTest::BoolAndErrorCallback, base::Unretained(this), base::Unretained(&loop))); loop.Run(); @@ -363,8 +369,10 @@ CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) { base::HistogramTester histogram_tester; base::RunLoop loop; - cache_manager_->DeleteCache( - origin, owner, cache_name, + CacheStorageHandle cache_storage = + cache_manager_->OpenCacheStorage(origin, owner); + cache_storage.value()->DoomCache( + cache_name, base::BindOnce(&CacheStorageManagerTest::ErrorCallback, base::Unretained(this), base::Unretained(&loop))); loop.Run(); @@ -376,8 +384,9 @@ CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) { base::HistogramTester histogram_tester; base::RunLoop loop; - cache_manager_->EnumerateCaches( - origin, owner, + CacheStorageHandle cache_storage = + cache_manager_->OpenCacheStorage(origin, owner); + cache_storage.value()->EnumerateCaches( base::BindOnce(&CacheStorageManagerTest::CacheMetadataCallback, base::Unretained(this), base::Unretained(&loop))); loop.Run(); @@ -404,8 +413,10 @@ CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) { base::HistogramTester histogram_tester; base::RunLoop loop; - cache_manager_->MatchCache( - origin, owner, cache_name, std::move(request), std::move(match_params), + CacheStorageHandle cache_storage = + cache_manager_->OpenCacheStorage(origin, owner); + cache_storage.value()->MatchCache( + cache_name, std::move(request), std::move(match_params), base::BindOnce(&CacheStorageManagerTest::CacheMatchCallback, base::Unretained(this), base::Unretained(&loop))); loop.Run(); @@ -430,8 +441,10 @@ CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) { base::HistogramTester histogram_tester; base::RunLoop loop; - cache_manager_->MatchAllCaches( - origin, owner, std::move(request), std::move(match_params), + CacheStorageHandle cache_storage = + cache_manager_->OpenCacheStorage(origin, owner); + cache_storage.value()->MatchAllCaches( + std::move(request), std::move(match_params), base::BindOnce(&CacheStorageManagerTest::CacheMatchCallback, base::Unretained(this), base::Unretained(&loop))); loop.Run(); @@ -448,9 +461,10 @@ request->url = GURL(request_url); base::RunLoop loop; - cache_manager_->WriteToCache( - origin, owner, cache_name, std::move(request), - blink::mojom::FetchAPIResponse::New(), + CacheStorageHandle cache_storage = + cache_manager_->OpenCacheStorage(origin, owner); + cache_storage.value()->WriteToCache( + cache_name, std::move(request), blink::mojom::FetchAPIResponse::New(), base::BindOnce(&CacheStorageManagerTest::ErrorCallback, base::Unretained(this), base::Unretained(&loop))); loop.Run(); @@ -562,9 +576,9 @@ return callback_error_ == CacheStorageError::kSuccess; } - CacheStorage* CacheStorageForOrigin(const url::Origin& origin) { - return cache_manager_->FindOrCreateCacheStorage( - origin, CacheStorageOwner::kCacheAPI); + CacheStorageHandle CacheStorageForOrigin(const url::Origin& origin) { + return cache_manager_->OpenCacheStorage(origin, + CacheStorageOwner::kCacheAPI); } int64_t GetOriginUsage( @@ -599,8 +613,8 @@ int64_t GetSizeThenCloseAllCaches(const url::Origin& origin) { base::RunLoop loop; - CacheStorage* cache_storage = CacheStorageForOrigin(origin); - cache_storage->GetSizeThenCloseAllCaches( + CacheStorageHandle cache_storage = CacheStorageForOrigin(origin); + cache_storage.value()->GetSizeThenCloseAllCaches( base::BindOnce(&CacheStorageManagerTest::UsageCallback, base::Unretained(this), &loop)); loop.Run(); @@ -609,9 +623,10 @@ int64_t Size(const url::Origin& origin) { base::RunLoop loop; - CacheStorage* cache_storage = CacheStorageForOrigin(origin); - cache_storage->Size(base::BindOnce(&CacheStorageManagerTest::UsageCallback, - base::Unretained(this), &loop)); + CacheStorageHandle cache_storage = CacheStorageForOrigin(origin); + cache_storage.value()->Size( + base::BindOnce(&CacheStorageManagerTest::UsageCallback, + base::Unretained(this), &loop)); loop.Run(); return callback_usage_; } @@ -1023,19 +1038,90 @@ EXPECT_STREQ("foo", GetFirstIndexName().c_str()); } -// With a persistent cache if the client drops its reference to a -// CacheStorageCache it should be deleted. +// Dropping a reference to a cache should not immediately destroy it. These +// warm cache objects are kept alive to optimize the next open. TEST_F(CacheStorageManagerTest, DropReference) { + CacheStorageHandle cache_storage = CacheStorageForOrigin(origin1_); + EXPECT_TRUE(Open(origin1_, "foo")); base::WeakPtr<CacheStorageCache> cache = callback_cache_handle_.value()->AsWeakPtr(); // Run a cache operation to ensure that the cache has finished initializing so - // that when the handle is dropped it can close immediately. + // that when the handle is dropped it could possibly close immediately. EXPECT_FALSE(CacheMatch(callback_cache_handle_.value(), GURL("http://example.com/foo"))); callback_cache_handle_ = CacheStorageCacheHandle(); - EXPECT_FALSE(cache); + EXPECT_TRUE(cache) << "unreferenced cache destroyed while owning " + "CacheStorage is still referenced"; + + cache_storage = CacheStorageHandle(); + EXPECT_FALSE(cache) << "unreferenced cache not destroyed after last " + "CacheStorage reference removed"; +} + +// Deleting a cache should remove any warmed caches that been kept alive +// without a reference. +TEST_F(CacheStorageManagerTest, DropReferenceAndDelete) { + // Hold a reference to the CacheStorage to permit the warmed + // CacheStorageCache to be kept alive. + CacheStorageHandle cache_storage = CacheStorageForOrigin(origin1_); + + EXPECT_TRUE(Open(origin1_, "foo")); + base::WeakPtr<CacheStorageCache> cache = + callback_cache_handle_.value()->AsWeakPtr(); + // Run a cache operation to ensure that the cache has finished initializing so + // that when the handle is dropped it could possibly close immediately. + EXPECT_FALSE(CacheMatch(callback_cache_handle_.value(), + GURL("http://example.com/foo"))); + + callback_cache_handle_ = CacheStorageCacheHandle(); + EXPECT_TRUE(cache) << "unreferenced cache destroyed while owning " + "CacheStorage is still referenced"; + + // Delete() should trigger its destruction, however. + EXPECT_TRUE(Delete(origin1_, "foo")); + base::RunLoop().RunUntilIdle(); + + EXPECT_FALSE(cache) + << "deleted cache not destroyed after last reference removed"; +} + +// Critical memory pressure should remove any warmed caches that been kept +// alive without a reference. +TEST_F(CacheStorageManagerTest, DropReferenceAndMemoryPressure) { + // Hold a reference to the CacheStorage to permit the warmed + // CacheStorageCache to be kept alive. + CacheStorageHandle cache_storage = CacheStorageForOrigin(origin1_); + + EXPECT_TRUE(Open(origin1_, "foo")); + base::WeakPtr<CacheStorageCache> cache = + callback_cache_handle_.value()->AsWeakPtr(); + // Run a cache operation to ensure that the cache has finished initializing so + // that when the handle is dropped it could possibly close immediately. + EXPECT_FALSE(CacheMatch(callback_cache_handle_.value(), + GURL("http://example.com/foo"))); + + callback_cache_handle_ = CacheStorageCacheHandle(); + EXPECT_TRUE(cache) << "unreferenced cache destroyed while owning " + "CacheStorage is still referenced"; + + // Moderate memory pressure should not destroy unreferenced cache objects + // since reading data back in from disk can be expensive. + base::MemoryPressureListener::NotifyMemoryPressure( + base::MemoryPressureListener::MemoryPressureLevel:: + MEMORY_PRESSURE_LEVEL_MODERATE); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(cache); + + // Critical memory pressure should destroy unreferenced cache objects. + base::MemoryPressureListener::NotifyMemoryPressure( + base::MemoryPressureListener::MemoryPressureLevel:: + MEMORY_PRESSURE_LEVEL_CRITICAL); + base::RunLoop().RunUntilIdle(); + + EXPECT_FALSE(cache) + << "unreferenced cache not destroyed on critical memory pressure"; } // A cache continues to work so long as there is a handle to it. Only after the @@ -1119,8 +1205,8 @@ auto size_before_close = Size(origin1_); EXPECT_GT(size_before_close, 0); - CacheStorage* cache_storage = CacheStorageForOrigin(origin1_); - auto cache_handle = cache_storage->GetLoadedCache(kCacheName); + CacheStorageHandle cache_storage = CacheStorageForOrigin(origin1_); + auto cache_handle = cache_storage.value()->GetLoadedCache(kCacheName); CacheStorageCache* cache = cache_handle.value(); base::FilePath index_path = cache->path().AppendASCII("index"); cache_handle = CacheStorageCacheHandle(); @@ -1310,19 +1396,19 @@ TEST_P(CacheStorageManagerTestP, OpenRunsSerially) { EXPECT_FALSE(Delete(origin1_, "tmp")); // Init storage. - CacheStorage* cache_storage = CacheStorageForOrigin(origin1_); - cache_storage->StartAsyncOperationForTesting(); + CacheStorageHandle cache_storage = CacheStorageForOrigin(origin1_); + cache_storage.value()->StartAsyncOperationForTesting(); base::RunLoop open_loop; - cache_manager_->OpenCache( - origin1_, CacheStorageOwner::kCacheAPI, "foo", + cache_storage.value()->OpenCache( + "foo", base::BindOnce(&CacheStorageManagerTest::CacheAndErrorCallback, base::Unretained(this), base::Unretained(&open_loop))); base::RunLoop().RunUntilIdle(); EXPECT_FALSE(callback_cache_handle_.value()); - cache_storage->CompleteAsyncOperationForTesting(); + cache_storage.value()->CompleteAsyncOperationForTesting(); open_loop.Run(); EXPECT_TRUE(callback_cache_handle_.value()); }
diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc index d77ca70c..0b547de 100644 --- a/content/browser/child_process_security_policy_impl.cc +++ b/content/browser/child_process_security_policy_impl.cc
@@ -95,6 +95,27 @@ return true; } +// Helper function that checks to make sure calls on +// CanAccessDataForOrigin() are only made on valid threads. +// TODO(acolwell): Expand the usage of this check to other +// ChildProcessSecurityPolicyImpl methods. +bool IsRunningOnExpectedThread() { + if (BrowserThread::CurrentlyOn(BrowserThread::IO) || + BrowserThread::CurrentlyOn(BrowserThread::UI)) { + return true; + } + + std::string thread_name(base::PlatformThread::GetName()); + + // TODO(acolwell): Remove once all tests are updated to properly + // identify that they are running on the UI or IO threads. + if (thread_name.empty()) + return true; + + LOG(ERROR) << "Running on unexpected thread '" << thread_name << "'"; + return false; +} + } // namespace // The SecurityState class is used to maintain per-child process security state @@ -860,7 +881,7 @@ // // TODO(alexmos): This should eventually also check the origin lock, but // currently this is not done due to certain corner cases involving HTML - // imports and layout tests that simulate requests from isolated worlds. See + // imports and web tests that simulate requests from isolated worlds. See // https://crbug.com/515309. if (CanCommitURL(child_id, url, false /* check_origin_lock */)) return true; @@ -1119,6 +1140,8 @@ bool ChildProcessSecurityPolicyImpl::CanAccessDataForOrigin(int child_id, const GURL& url) { + DCHECK(IsRunningOnExpectedThread()); + // It's important to call DetermineProcessLockURL before // acquiring |lock_|, since DetermineProcessLockURL consults // IsIsolatedOrigin, which needs to grab the same lock.
diff --git a/content/browser/child_process_security_policy_unittest.cc b/content/browser/child_process_security_policy_unittest.cc index 8884e1b..b002138 100644 --- a/content/browser/child_process_security_policy_unittest.cc +++ b/content/browser/child_process_security_policy_unittest.cc
@@ -12,6 +12,7 @@ #include "content/browser/site_instance_impl.h" #include "content/public/common/bindings_policy.h" #include "content/public/common/url_constants.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "content/test/test_content_browser_client.h" #include "storage/browser/fileapi/file_permission_policy.h" #include "storage/browser/fileapi/file_system_url.h" @@ -113,6 +114,7 @@ } private: + TestBrowserThreadBundle thread_bundle_; ChildProcessSecurityPolicyTestBrowserClient test_browser_client_; ContentBrowserClient* old_browser_client_; };
diff --git a/content/browser/cross_site_transfer_browsertest.cc b/content/browser/cross_site_transfer_browsertest.cc index ba27a50..1f2bffc49 100644 --- a/content/browser/cross_site_transfer_browsertest.cc +++ b/content/browser/cross_site_transfer_browsertest.cc
@@ -350,9 +350,9 @@ // This is a regression test for https://crbug.com/726067. // // This test is somewhat similar to -// http/tests/navigation/form-targets-cross-site-frame-post.html layout test +// http/tests/navigation/form-targets-cross-site-frame-post.html web test // except that it 1) tests with files, 2) simulates a malicious scenario and 3) -// verifies file access (all of these 3 things are not possible with layout +// verifies file access (all of these 3 things are not possible with web // tests). // // This test is very similar to CrossSiteTransferTest.PostWithFileData above,
diff --git a/content/browser/devtools/devtools_renderer_channel.h b/content/browser/devtools/devtools_renderer_channel.h index 84ded2f..b0f1f7c 100644 --- a/content/browser/devtools/devtools_renderer_channel.h +++ b/content/browser/devtools/devtools_renderer_channel.h
@@ -12,7 +12,7 @@ #include "content/common/content_export.h" #include "mojo/public/cpp/bindings/associated_binding.h" #include "mojo/public/cpp/bindings/binding.h" -#include "third_party/blink/public/web/devtools_agent.mojom.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" namespace gfx { class Point;
diff --git a/content/browser/devtools/devtools_session.h b/content/browser/devtools/devtools_session.h index cacdd49..d17677d 100644 --- a/content/browser/devtools/devtools_session.h +++ b/content/browser/devtools/devtools_session.h
@@ -14,7 +14,7 @@ #include "content/browser/devtools/protocol/forward.h" #include "content/public/browser/devtools_external_agent_proxy.h" #include "mojo/public/cpp/bindings/associated_binding.h" -#include "third_party/blink/public/web/devtools_agent.mojom.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" namespace content {
diff --git a/content/browser/devtools/devtools_url_loader_interceptor.cc b/content/browser/devtools/devtools_url_loader_interceptor.cc index fa34582..572cfaa 100644 --- a/content/browser/devtools/devtools_url_loader_interceptor.cc +++ b/content/browser/devtools/devtools_url_loader_interceptor.cc
@@ -1071,10 +1071,10 @@ response_metadata_->redirect_info = std::make_unique<net::RedirectInfo>( net::RedirectInfo::ComputeRedirectInfo( request.method, request.url, request.site_for_cookies, - first_party_url_policy, request.referrer_policy, - request.referrer.spec(), &headers, headers.response_code(), - redirect_url, false /* insecure_scheme_was_upgraded */, - true /* copy_fragment */)); + request.top_frame_origin, first_party_url_policy, + request.referrer_policy, request.referrer.spec(), &headers, + headers.response_code(), redirect_url, + false /* insecure_scheme_was_upgraded */, true /* copy_fragment */)); client_->OnReceiveRedirect(*response_metadata_->redirect_info, response_metadata_->head);
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index 991a10dd..15c1505 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -55,7 +55,7 @@ #include "mojo/public/cpp/bindings/associated_binding.h" #include "services/network/public/cpp/features.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" -#include "third_party/blink/public/web/devtools_agent.mojom.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" #if defined(OS_ANDROID) #include "content/browser/renderer_host/compositor_impl_android.h"
diff --git a/content/browser/devtools/service_worker_devtools_agent_host.h b/content/browser/devtools/service_worker_devtools_agent_host.h index f6b8842..df37d5a 100644 --- a/content/browser/devtools/service_worker_devtools_agent_host.h +++ b/content/browser/devtools/service_worker_devtools_agent_host.h
@@ -14,7 +14,7 @@ #include "base/unguessable_token.h" #include "content/browser/devtools/devtools_agent_host_impl.h" #include "content/browser/devtools/service_worker_devtools_manager.h" -#include "third_party/blink/public/web/devtools_agent.mojom.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" namespace content {
diff --git a/content/browser/devtools/service_worker_devtools_manager.h b/content/browser/devtools/service_worker_devtools_manager.h index 6745d91..43a2a2f 100644 --- a/content/browser/devtools/service_worker_devtools_manager.h +++ b/content/browser/devtools/service_worker_devtools_manager.h
@@ -16,7 +16,7 @@ #include "base/observer_list.h" #include "base/unguessable_token.h" #include "content/common/content_export.h" -#include "third_party/blink/public/web/devtools_agent.mojom.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" #include "url/gurl.h" namespace network {
diff --git a/content/browser/devtools/shared_worker_devtools_agent_host.cc b/content/browser/devtools/shared_worker_devtools_agent_host.cc index a74e129..38bc859 100644 --- a/content/browser/devtools/shared_worker_devtools_agent_host.cc +++ b/content/browser/devtools/shared_worker_devtools_agent_host.cc
@@ -17,7 +17,7 @@ #include "content/browser/worker_host/shared_worker_service_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" -#include "third_party/blink/public/web/devtools_agent.mojom.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" namespace content {
diff --git a/content/browser/devtools/worker_devtools_agent_host.h b/content/browser/devtools/worker_devtools_agent_host.h index 817d0989..1750966 100644 --- a/content/browser/devtools/worker_devtools_agent_host.h +++ b/content/browser/devtools/worker_devtools_agent_host.h
@@ -8,7 +8,7 @@ #include "base/macros.h" #include "base/unguessable_token.h" #include "content/browser/devtools/devtools_agent_host_impl.h" -#include "third_party/blink/public/web/devtools_agent.mojom.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" #include "url/gurl.h" namespace content {
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc index 4fcfe05..70fc8ad 100644 --- a/content/browser/download/download_browsertest.cc +++ b/content/browser/download/download_browsertest.cc
@@ -1049,7 +1049,7 @@ intermediate_file_path, url_chain, received_slices, parameters); // Resume the parallel download with sparse file and received slices data. - download->Resume(); + download->Resume(false); WaitForCompletion(download); // TODO(qinmin): count the failed partial responses in DownloadJob when // support_partial_response is false. EmbeddedTestServer doesn't know @@ -1522,7 +1522,7 @@ parameters.ClearInjectedErrors(); TestDownloadHttpResponse::StartServing(parameters, server_url); - download->Resume(); + download->Resume(false); WaitForCompletion(download); ASSERT_EQ(parameters.size, download->GetReceivedBytes()); @@ -1615,7 +1615,7 @@ parameters.ClearInjectedErrors(); TestDownloadHttpResponse::StartServing(parameters, download_url); - download->Resume(); + download->Resume(false); WaitForCompletion(download); ASSERT_NO_FATAL_FAILURE(ReadAndVerifyFileContents( @@ -1652,7 +1652,7 @@ "Location: %s\r\n\r\n", second_url.spec().c_str()), first_url); - download->Resume(); + download->Resume(false); WaitForInterrupt(download); EXPECT_EQ(download::DOWNLOAD_INTERRUPT_REASON_SERVER_UNREACHABLE, download->GetLastReason()); @@ -1661,7 +1661,7 @@ // use the partial data it had prior to the first interruption. parameters.ClearInjectedErrors(); TestDownloadHttpResponse::StartServing(parameters, first_url); - download->Resume(); + download->Resume(false); WaitForCompletion(download); ASSERT_EQ(parameters.size, download->GetReceivedBytes()); @@ -1775,7 +1775,7 @@ "Content-Range: bytes 1000000-2000000/3000000\r\n" "\r\n", server_url); - download->Resume(); + download->Resume(false); WaitForInterrupt(download); EXPECT_EQ(download::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT, download->GetLastReason()); @@ -1787,7 +1787,7 @@ "Content-Range: ooga-booga-booga-booga\r\n" "\r\n", server_url); - download->Resume(); + download->Resume(false); WaitForInterrupt(download); EXPECT_EQ(download::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT, download->GetLastReason()); @@ -1798,7 +1798,7 @@ "Some-Headers: ooga-booga-booga-booga\r\n" "\r\n", server_url); - download->Resume(); + download->Resume(false); WaitForInterrupt(download); EXPECT_EQ(download::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT, download->GetLastReason()); @@ -1807,7 +1807,7 @@ // use the partial data it had prior to the first interruption. parameters.ClearInjectedErrors(); TestDownloadHttpResponse::StartServing(parameters, server_url); - download->Resume(); + download->Resume(false); WaitForCompletion(download); ASSERT_EQ(parameters.size, download->GetReceivedBytes()); @@ -1864,7 +1864,7 @@ parameters.pattern_generator_seed = kNewPatternGeneratorSeed; TestDownloadHttpResponse::StartServing(parameters, server_url); - download->Resume(); + download->Resume(false); WaitForCompletion(download); ASSERT_EQ(interruption_offset, download->GetBytesWasted()); @@ -1928,7 +1928,7 @@ parameters.ClearInjectedErrors(); TestDownloadHttpResponse::StartServing(parameters, server_url); - download->Resume(); + download->Resume(false); WaitForCompletion(download); ASSERT_EQ(parameters.size, download->GetReceivedBytes()); @@ -1976,7 +1976,7 @@ parameters.ClearInjectedErrors(); TestDownloadHttpResponse::StartServing(parameters, server_url); - download->Resume(); + download->Resume(false); WaitForCompletion(download); ASSERT_EQ(interruption_offset, download->GetBytesWasted()); @@ -2023,7 +2023,7 @@ injector->ClearError(); // Resume and watch completion. - download->Resume(); + download->Resume(false); WaitForCompletion(download); EXPECT_EQ(download->GetState(), download::DownloadItem::COMPLETE); } @@ -2066,7 +2066,7 @@ // Clear the old errors list. injector->ClearError(); - download->Resume(); + download->Resume(false); WaitForCompletion(download); EXPECT_EQ(download->GetState(), download::DownloadItem::COMPLETE); } @@ -2106,7 +2106,7 @@ // Clear the old errors list. injector->ClearError(); - download->Resume(); + download->Resume(false); WaitForCompletion(download); EXPECT_EQ(download->GetState(), download::DownloadItem::COMPLETE); } @@ -2146,27 +2146,27 @@ parameters.injected_errors.pop(); TestDownloadHttpResponse::StartServing(parameters, server_url2); - download->Resume(); + download->Resume(false); WaitForInterrupt(download); parameters.injected_errors.pop(); TestDownloadHttpResponse::StartServing(parameters, server_url2); - download->Resume(); + download->Resume(false); WaitForInterrupt(download); parameters.injected_errors.pop(); TestDownloadHttpResponse::StartServing(parameters, server_url2); - download->Resume(); + download->Resume(false); WaitForInterrupt(download); parameters.injected_errors.pop(); TestDownloadHttpResponse::StartServing(parameters, server_url2); - download->Resume(); + download->Resume(false); WaitForInterrupt(download); parameters.injected_errors.pop(); TestDownloadHttpResponse::StartServing(parameters, server_url2); - download->Resume(); + download->Resume(false); WaitForCompletion(download); EXPECT_EQ(expected_hash, download->GetHash()); @@ -2273,7 +2273,7 @@ parameters.pause_offset = -1; TestDownloadHttpResponse::StartServing(parameters, server_url); - download->Resume(); + download->Resume(false); request_pause_handler.WaitForCallback(); // At this point, the download resumption request has been sent out, but the @@ -2326,7 +2326,7 @@ parameters.ClearInjectedErrors(); TestDownloadHttpResponse::StartServing(parameters, server_url); - download->Resume(); + download->Resume(false); request_pause_handler.WaitForCallback(); // At this point, the download item has initiated a network request for the @@ -2386,7 +2386,7 @@ parameters.ClearInjectedErrors(); TestDownloadHttpResponse::StartServing(parameters, server_url); - download->Resume(); + download->Resume(false); WaitForInProgress(download); download->Remove(); @@ -2431,7 +2431,7 @@ parameters.ClearInjectedErrors(); TestDownloadHttpResponse::StartServing(parameters, server_url); - download->Resume(); + download->Resume(false); WaitForInProgress(download); download->Cancel(true); @@ -2470,7 +2470,7 @@ base::Time(), false, std::vector<download::DownloadItem::ReceivedSlice>()); - download->Resume(); + download->Resume(false); WaitForCompletion(download); EXPECT_FALSE(PathExists(intermediate_file_path)); @@ -2536,7 +2536,7 @@ base::Time(), false, std::vector<download::DownloadItem::ReceivedSlice>()); - download->Resume(); + download->Resume(false); WaitForCompletion(download); EXPECT_FALSE(PathExists(intermediate_file_path)); @@ -2589,7 +2589,7 @@ base::Time(), false, std::vector<download::DownloadItem::ReceivedSlice>()); - download->Resume(); + download->Resume(false); WaitForCompletion(download); EXPECT_EQ(kIntermediateSize, download->GetBytesWasted()); @@ -2649,7 +2649,7 @@ base::Time(), false, std::vector<download::DownloadItem::ReceivedSlice>()); - download->Resume(); + download->Resume(false); WaitForCompletion(download); EXPECT_FALSE(PathExists(intermediate_file_path)); @@ -2715,7 +2715,7 @@ base::Time(), false, std::vector<download::DownloadItem::ReceivedSlice>()); - download->Resume(); + download->Resume(false); WaitForCompletion(download); EXPECT_FALSE(PathExists(intermediate_file_path)); @@ -2790,7 +2790,7 @@ base::Time(), false, std::vector<download::DownloadItem::ReceivedSlice>()); - download->Resume(); + download->Resume(false); WaitForCompletion(download); EXPECT_FALSE(PathExists(intermediate_file_path)); @@ -2863,7 +2863,7 @@ base::Time(), false, std::vector<download::DownloadItem::ReceivedSlice>()); - download->Resume(); + download->Resume(false); WaitForCompletion(download); // The amount "extra" that was added to the file. @@ -2908,7 +2908,7 @@ parameters.ClearInjectedErrors(); TestDownloadHttpResponse::StartServing(parameters, server_url); - download->Resume(); + download->Resume(false); WaitForCompletion(download); ASSERT_EQ(parameters.size, download->GetReceivedBytes()); @@ -3762,7 +3762,7 @@ // The fetch error body should be cached in download item. The download should // start from beginning. - download->Resume(); + download->Resume(false); WaitForCompletion(download); // The file should be empty.
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc index 44cf7659..644ddcb9 100644 --- a/content/browser/download/download_manager_impl.cc +++ b/content/browser/download/download_manager_impl.cc
@@ -236,8 +236,9 @@ delegate, guid, download_id, current_path, target_path, url_chain, referrer_url, site_url, tab_url, tab_refererr_url, mime_type, original_mime_type, start_time, end_time, etag, last_modified, - received_bytes, total_bytes, hash, state, danger_type, interrupt_reason, - false /* paused */, opened, last_access_time, transient, + received_bytes, total_bytes, 0 /* auto_resume_count */, hash, state, + danger_type, interrupt_reason, false /* paused */, + false /* allow_metered */, opened, last_access_time, transient, received_slices); } @@ -773,6 +774,11 @@ return browser_context_->IsOffTheRecord(); } +bool DownloadManagerImpl::IsActiveNetworkMetered() const { + // TODO(shaktisahu): Call ChromeDownloadManagerDelegate to get this. + return false; +} + void DownloadManagerImpl::ReportBytesWasted( download::DownloadItemImpl* download) { in_progress_manager_->ReportBytesWasted(download);
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h index b94e85cf..d596137 100644 --- a/content/browser/download/download_manager_impl.h +++ b/content/browser/download/download_manager_impl.h
@@ -257,6 +257,7 @@ base::Optional<download::DownloadEntry> GetInProgressEntry( download::DownloadItemImpl* download) override; bool IsOffTheRecord() const override; + bool IsActiveNetworkMetered() const override; void ReportBytesWasted(download::DownloadItemImpl* download) override; // Drops a download before it is created.
diff --git a/content/browser/download/download_manager_impl_unittest.cc b/content/browser/download/download_manager_impl_unittest.cc index dc69c07..c5cfc6c 100644 --- a/content/browser/download/download_manager_impl_unittest.cc +++ b/content/browser/download/download_manager_impl_unittest.cc
@@ -748,10 +748,10 @@ url_chain, GURL("http://example.com/a"), GURL("http://example.com/a"), GURL("http://example.com/a"), GURL("http://example.com/a"), "application/octet-stream", "application/octet-stream", base::Time::Now(), - base::Time::Now(), std::string(), std::string(), 10, 10, std::string(), + base::Time::Now(), std::string(), std::string(), 10, 10, 0, std::string(), download::DownloadItem::INTERRUPTED, download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, - download::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, false, false, + download::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, false, false, false, base::Time::Now(), true, std::vector<download::DownloadItem::ReceivedSlice>()); in_progress_manager->AddDownloadItem(std::move(in_progress_item));
diff --git a/content/browser/fileapi/browser_file_system_helper.cc b/content/browser/fileapi/browser_file_system_helper.cc index f3d73489..031f5b2 100644 --- a/content/browser/fileapi/browser_file_system_helper.cc +++ b/content/browser/fileapi/browser_file_system_helper.cc
@@ -69,6 +69,48 @@ additional_allowed_schemes); } +bool CheckCanReadFileSystemFileOnUIThread(int process_id, + const storage::FileSystemURL& url) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + ChildProcessSecurityPolicyImpl* policy = + ChildProcessSecurityPolicyImpl::GetInstance(); + return policy->CanReadFileSystemFile(process_id, url); +} + +void GrantReadAccessOnUIThread(int process_id, + const base::FilePath& platform_path) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + ChildProcessSecurityPolicyImpl* policy = + ChildProcessSecurityPolicyImpl::GetInstance(); + if (!policy->CanReadFile(process_id, platform_path)) { + policy->GrantReadFile(process_id, platform_path); + } +} + +// Helper function that used by SyncGetPlatformPath() to get the platform +// path, grant read access, and send return the path via a callback. +void GetPlatformPathOnFileThread( + scoped_refptr<storage::FileSystemContext> context, + int process_id, + const storage::FileSystemURL& url, + SyncGetPlatformPathCB callback, + bool can_read_filesystem_file) { + DCHECK(context->default_file_task_runner()->RunsTasksInCurrentSequence()); + + if (!can_read_filesystem_file) { + std::move(callback).Run(base::FilePath()); + return; + } + + base::FilePath platform_path; + context->operation_runner()->SyncGetPlatformPath(url, &platform_path); + + base::PostTaskWithTraitsAndReply( + FROM_HERE, {BrowserThread::UI}, + base::BindOnce(&GrantReadAccessOnUIThread, process_id, platform_path), + base::BindOnce(std::move(callback), platform_path)); +} + } // namespace scoped_refptr<storage::FileSystemContext> CreateFileSystemContext( @@ -120,30 +162,27 @@ void SyncGetPlatformPath(storage::FileSystemContext* context, int process_id, const GURL& path, - base::FilePath* platform_path) { + SyncGetPlatformPathCB callback) { DCHECK(context->default_file_task_runner()-> RunsTasksInCurrentSequence()); - DCHECK(platform_path); - *platform_path = base::FilePath(); storage::FileSystemURL url(context->CrackURL(path)); - if (!FileSystemURLIsValid(context, url)) + if (!FileSystemURLIsValid(context, url)) { + // Note: Posting a task here so this function always returns + // before the callback is called no matter which path is taken. + base::PostTask(FROM_HERE, + base::BindOnce(std::move(callback), base::FilePath())); return; + } // Make sure if this file is ok to be read (in the current architecture // which means roughly same as the renderer is allowed to get the platform // path to the file). - ChildProcessSecurityPolicyImpl* policy = - ChildProcessSecurityPolicyImpl::GetInstance(); - if (!policy->CanReadFileSystemFile(process_id, url)) - return; - - context->operation_runner()->SyncGetPlatformPath(url, platform_path); - - // The path is to be attached to URLLoader so we grant read permission - // for the file. (We need to check first because a parent directory may - // already have the permissions and we don't need to grant it to the file.) - if (!policy->CanReadFile(process_id, *platform_path)) - policy->GrantReadFile(process_id, *platform_path); + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, {BrowserThread::UI}, + base::BindOnce(&CheckCanReadFileSystemFileOnUIThread, process_id, url), + base::BindOnce(&GetPlatformPathOnFileThread, + scoped_refptr<storage::FileSystemContext>(context), + process_id, url, std::move(callback))); } void PrepareDropDataForChildProcess(
diff --git a/content/browser/fileapi/browser_file_system_helper.h b/content/browser/fileapi/browser_file_system_helper.h index b9679f9..64e8658 100644 --- a/content/browser/fileapi/browser_file_system_helper.h +++ b/content/browser/fileapi/browser_file_system_helper.h
@@ -34,10 +34,11 @@ // Get the platform path from a file system URL. This needs to be called // on the FILE thread. +using SyncGetPlatformPathCB = base::OnceCallback<void(const base::FilePath&)>; CONTENT_EXPORT void SyncGetPlatformPath(storage::FileSystemContext* context, int process_id, const GURL& path, - base::FilePath* platform_path); + SyncGetPlatformPathCB callback); // Make it possible for a |drop_data|'s resources to be read by |child_id|'s // process -- by granting permissions, rewriting |drop_data|, or both.
diff --git a/content/browser/fileapi/file_system_manager_impl.cc b/content/browser/fileapi/file_system_manager_impl.cc index d9b2eb6..36a0af6 100644 --- a/content/browser/fileapi/file_system_manager_impl.cc +++ b/content/browser/fileapi/file_system_manager_impl.cc
@@ -828,12 +828,21 @@ storage::FileSystemContext* context, base::WeakPtr<FileSystemManagerImpl> file_system_manager, GetPlatformPathCallback callback) { - base::FilePath platform_path; - SyncGetPlatformPath(context, process_id, path, &platform_path); - base::PostTaskWithTraits( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&FileSystemManagerImpl::DidGetPlatformPath, - file_system_manager, std::move(callback), platform_path)); + DCHECK(context->default_file_task_runner()->RunsTasksInCurrentSequence()); + + SyncGetPlatformPath( + context, process_id, path, + base::BindOnce( + [](base::WeakPtr<FileSystemManagerImpl> file_system_manager, + GetPlatformPathCallback callback, + const base::FilePath& platform_path) { + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::IO}, + base::BindOnce(&FileSystemManagerImpl::DidGetPlatformPath, + std::move(file_system_manager), + std::move(callback), platform_path)); + }, + std::move(file_system_manager), std::move(callback))); } base::Optional<base::File::Error> FileSystemManagerImpl::ValidateFileSystemURL(
diff --git a/content/browser/fileapi/file_system_url_loader_factory.cc b/content/browser/fileapi/file_system_url_loader_factory.cc index 1d74910..bfc9a1a 100644 --- a/content/browser/fileapi/file_system_url_loader_factory.cc +++ b/content/browser/fileapi/file_system_url_loader_factory.cc
@@ -485,9 +485,10 @@ static_cast<int64_t>(kDefaultFileSystemUrlPipeSize), remaining_bytes_); if (!bytes_to_read) { if (consumer_handle_.is_valid()) { - // This was an empty file; make sure to call OnReceiveResponse - // regardless. + // This was an empty file; make sure to call OnReceiveResponse and + // OnStartLoadingResponseBody regardless. client_->OnReceiveResponse(head_); + client_->OnStartLoadingResponseBody(std::move(consumer_handle_)); } OnFileWritten(MOJO_RESULT_OK); return;
diff --git a/content/browser/frame_host/frame_tree_node.cc b/content/browser/frame_host/frame_tree_node.cc index 3c1f5ed..413bfeb 100644 --- a/content/browser/frame_host/frame_tree_node.cc +++ b/content/browser/frame_host/frame_tree_node.cc
@@ -9,6 +9,7 @@ #include <queue> #include <utility> +#include "base/feature_list.h" #include "base/lazy_instance.h" #include "base/macros.h" #include "base/metrics/histogram_macros.h" @@ -22,6 +23,7 @@ #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/common/frame_messages.h" #include "content/public/browser/browser_thread.h" +#include "content/public/common/content_features.h" #include "content/public/common/navigation_policy.h" #include "third_party/blink/public/common/frame/sandbox_flags.h" #include "third_party/blink/public/common/frame/user_activation_update_type.h" @@ -550,6 +552,24 @@ for (FrameTreeNode* node = this; node; node = node->parent()) node->user_activation_state_.Activate(); replication_state_.has_received_user_gesture = true; + + // TODO(mustaq): The following block relaxes UAv2 a bit to make it slightly + // closer to the old (v1) model, to address a Hangout regression. We will + // remove this after implementing a mechanism to delegate activation to + // subframes (https://crbug.com/728334) + if (base::FeatureList::IsEnabled(features::kUserActivationV2) && + base::FeatureList::IsEnabled( + features::kUserActivationSameOriginVisibility)) { + const url::Origin& current_origin = + this->current_frame_host()->GetLastCommittedOrigin(); + for (FrameTreeNode* node : frame_tree()->Nodes()) { + if (node->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith( + current_origin)) { + node->user_activation_state_.Activate(); + } + } + } + return true; }
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index 5e3e6d6..5129a1e1 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -1489,12 +1489,21 @@ frame_tree_node_, begin_params_.get(), &report_raw_headers); devtools_instrumentation::OnNavigationRequestWillBeSent(*this); + // If this is a top-frame navigation, then use the origin of the url (and + // update it as redirects happen). If this is a sub-frame navigation, get the + // URL from the top frame. + GURL top_frame_url = + frame_tree_node_->IsMainFrame() + ? common_params_.url + : frame_tree_node_->frame_tree()->root()->current_url(); + url::Origin top_frame_origin = url::Origin::Create(top_frame_url); + loader_ = NavigationURLLoader::Create( browser_context->GetResourceContext(), partition, std::make_unique<NavigationRequestInfo>( common_params_, begin_params_.Clone(), site_for_cookies, - frame_tree_node_->IsMainFrame(), parent_is_main_frame, - IsSecureFrame(frame_tree_node_->parent()), + top_frame_origin, frame_tree_node_->IsMainFrame(), + parent_is_main_frame, IsSecureFrame(frame_tree_node_->parent()), frame_tree_node_->frame_tree_node_id(), is_for_guests_only, report_raw_headers, navigating_frame_host->GetVisibilityState() ==
diff --git a/content/browser/frame_host/navigation_request_info.cc b/content/browser/frame_host/navigation_request_info.cc index f02f9a18..b0ab6cd 100644 --- a/content/browser/frame_host/navigation_request_info.cc +++ b/content/browser/frame_host/navigation_request_info.cc
@@ -11,6 +11,7 @@ const CommonNavigationParams& common_params, mojom::BeginNavigationParamsPtr begin_params, const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin, bool is_main_frame, bool parent_is_main_frame, bool are_ancestors_secure, @@ -26,6 +27,7 @@ : common_params(common_params), begin_params(std::move(begin_params)), site_for_cookies(site_for_cookies), + top_frame_origin(top_frame_origin), is_main_frame(is_main_frame), parent_is_main_frame(parent_is_main_frame), are_ancestors_secure(are_ancestors_secure), @@ -42,6 +44,7 @@ : common_params(other.common_params), begin_params(other.begin_params.Clone()), site_for_cookies(other.site_for_cookies), + top_frame_origin(other.top_frame_origin), is_main_frame(other.is_main_frame), parent_is_main_frame(other.parent_is_main_frame), are_ancestors_secure(other.are_ancestors_secure),
diff --git a/content/browser/frame_host/navigation_request_info.h b/content/browser/frame_host/navigation_request_info.h index 8b6a81c9..e0d5915 100644 --- a/content/browser/frame_host/navigation_request_info.h +++ b/content/browser/frame_host/navigation_request_info.h
@@ -26,6 +26,7 @@ NavigationRequestInfo(const CommonNavigationParams& common_params, mojom::BeginNavigationParamsPtr begin_params, const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin, bool is_main_frame, bool parent_is_main_frame, bool are_ancestors_secure, @@ -48,6 +49,12 @@ // checked by the third-party cookie blocking policy. const GURL site_for_cookies; + // The origin of the navigation if top frame, else the origin of the top + // frame. + // TODO(crbug.com/910716) Make this required. I believe we just need to add + // support for signed exchange redirects. + const base::Optional<url::Origin> top_frame_origin; + const bool is_main_frame; const bool parent_is_main_frame;
diff --git a/content/browser/frame_host/navigator_impl_unittest.cc b/content/browser/frame_host/navigator_impl_unittest.cc index abda7b16..e69a9ff3 100644 --- a/content/browser/frame_host/navigator_impl_unittest.cc +++ b/content/browser/frame_host/navigator_impl_unittest.cc
@@ -312,6 +312,8 @@ EXPECT_EQ(kUrl2, subframe_loader->request_info()->common_params.url); // First party for cookies url should be that of the main frame. EXPECT_EQ(kUrl1, subframe_loader->request_info()->site_for_cookies); + EXPECT_EQ(url::Origin::Create(kUrl1), + subframe_loader->request_info()->top_frame_origin); EXPECT_FALSE(subframe_loader->request_info()->is_main_frame); EXPECT_TRUE(subframe_loader->request_info()->parent_is_main_frame); EXPECT_TRUE(subframe_request->browser_initiated());
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index aa700f2..9faf366 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -92,6 +92,7 @@ #include "content/browser/scoped_active_url.h" #include "content/browser/speech/speech_recognition_dispatcher_host.h" #include "content/browser/storage_partition_impl.h" +#include "content/browser/wake_lock/wake_lock_service_impl.h" #include "content/browser/webauth/authenticator_impl.h" #include "content/browser/webauth/scoped_virtual_authenticator_environment.h" #include "content/browser/websockets/websocket_manager.h" @@ -427,22 +428,22 @@ base::debug::SetCrashKeyString(site_url_key, site_url.spec()); } -url::Origin GetOriginForURLLoaderFactory(GURL target_url, - SiteInstanceImpl* site_instance) { - // Calculate the origin that will be used as a fallback for URLs such as - // about:blank and/or data:. If full site isolation is enabled, then - // |site_instance|-based origin will be correct. Otherwise, falling back to a - // unique/opaque origin should be safe. - // - // TODO(lukasza, nasko): https://crbug.com/888079: Do not fall back to - // |site_instance| - instead the browser process should already know at - // ready-to-commit time the origin to be committed. - url::Origin fallback_origin = - SiteIsolationPolicy::UseDedicatedProcessesForAllSites() - ? url::Origin::Create(site_instance->GetSiteURL()) - : url::Origin(); +base::Optional<url::Origin> GetOriginForURLLoaderFactory( + GURL target_url, + SiteInstanceImpl* site_instance) { + // TODO(lukasza, nasko): https://crbug.com/888079: Use exact origin, instead + // of falling back to site URL for about:blank and about:srcdoc. + if (target_url.SchemeIs(url::kAboutScheme)) { + if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) + return url::Origin::Create(site_instance->GetSiteURL()); + return base::nullopt; + } - return url::Origin::Resolve(target_url, fallback_origin); + // In cases not covered above, URLLoaderFactory should be associated with the + // origin of |target_url|. This works fine for all URLs, including data: URLs + // (which should use an opaque origin for their subresource requests) and + // blob: URLs (which embed their origin inside the |target_url|). + return url::Origin::Create(target_url); } service_manager::Connector* MaybeGetConnectorForProcess() { @@ -453,6 +454,12 @@ return connection->GetConnector(); } +std::unique_ptr<URLLoaderFactoryBundleInfo> CloneFactoryBundle( + scoped_refptr<URLLoaderFactoryBundle> bundle) { + return base::WrapUnique( + static_cast<URLLoaderFactoryBundleInfo*>(bundle->Clone().release())); +} + } // namespace class RenderFrameHostImpl::DroppedInterfaceRequestLogger @@ -3984,6 +3991,9 @@ registry_->AddInterface(base::BindRepeating(&AudioContextManagerImpl::Create, base::Unretained(this))); + + registry_->AddInterface(base::BindRepeating(&WakeLockServiceImpl::Create, + base::Unretained(this))); } void RenderFrameHostImpl::ResetWaitingState() { @@ -4536,7 +4546,8 @@ GetContentClient()->browser()->WillCreateURLLoaderFactory( browser_context, this, GetProcess()->GetID(), false /* is_navigation */, - GetOriginForURLLoaderFactory(common_params.url, GetSiteInstance()), + GetOriginForURLLoaderFactory(common_params.url, GetSiteInstance()) + .value_or(url::Origin()), &factory_request, nullptr /* header_client */, nullptr /* bypass_redirect_checks */); // Keep DevTools proxy last, i.e. closest to the network. @@ -4586,8 +4597,11 @@ std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle_for_prefetch; network::mojom::URLLoaderFactoryPtr prefetch_loader_factory; if (subresource_loader_factories) { - SaveSubresourceFactories(std::move(subresource_loader_factories)); - factory_bundle_for_prefetch = CloneSubresourceFactories(); + // Clone the factory bundle for prefetch. + auto bundle = base::MakeRefCounted<URLLoaderFactoryBundle>( + std::move(subresource_loader_factories)); + subresource_loader_factories = CloneFactoryBundle(bundle); + factory_bundle_for_prefetch = CloneFactoryBundle(bundle); } else if (base::FeatureList::IsEnabled( blink::features::kServiceWorkerServicification) && (!is_same_document || is_first_navigation)) { @@ -4630,7 +4644,8 @@ navigation_request_->GetCommitNavigationClient()) { navigation_request_->GetCommitNavigationClient()->CommitNavigation( head, common_params, request_params, - std::move(url_loader_client_endpoints), CloneSubresourceFactories(), + std::move(url_loader_client_endpoints), + std::move(subresource_loader_factories), std::move(subresource_overrides), std::move(controller), std::move(prefetch_loader_factory), devtools_navigation_token, base::BindOnce(&RenderFrameHostImpl::OnCrossDocumentCommitProcessed, @@ -4638,7 +4653,8 @@ } else { GetNavigationControl()->CommitNavigation( head, common_params, request_params, - std::move(url_loader_client_endpoints), CloneSubresourceFactories(), + std::move(url_loader_client_endpoints), + std::move(subresource_loader_factories), std::move(subresource_overrides), std::move(controller), std::move(prefetch_loader_factory), devtools_navigation_token, request ? base::BindOnce( @@ -4704,7 +4720,6 @@ URLLoaderFactoryBundleInfo::SchemeMap(), URLLoaderFactoryBundleInfo::OriginMap(), bypass_redirect_checks); } - SaveSubresourceFactories(std::move(subresource_loader_factories)); auto find_request = navigation_requests_.find(navigation_id); NavigationRequest* request = find_request != navigation_requests_.end() @@ -4714,13 +4729,13 @@ request->GetCommitNavigationClient()) { request->GetCommitNavigationClient()->CommitFailedNavigation( common_params, request_params, has_stale_copy_in_cache, error_code, - error_page_content, CloneSubresourceFactories(), + error_page_content, std::move(subresource_loader_factories), base::BindOnce(&RenderFrameHostImpl::OnCrossDocumentCommitProcessed, base::Unretained(this), navigation_id)); } else { GetNavigationControl()->CommitFailedNavigation( common_params, request_params, has_stale_copy_in_cache, error_code, - error_page_content, CloneSubresourceFactories(), + error_page_content, std::move(subresource_loader_factories), base::BindOnce(&RenderFrameHostImpl::OnCrossDocumentCommitProcessed, base::Unretained(this), navigation_id)); } @@ -5219,9 +5234,8 @@ CreateInitiatorSpecificURLLoaderFactories( initiators_requiring_separate_url_loader_factory_), bypass_redirect_checks); - SaveSubresourceFactories(std::move(subresource_loader_factories)); GetNavigationControl()->UpdateSubresourceLoaderFactories( - CloneSubresourceFactories()); + std::move(subresource_loader_factories)); } std::set<int> RenderFrameHostImpl::GetNavigationEntryIdsPendingCommit() { @@ -5234,7 +5248,7 @@ } bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve( - const url::Origin& origin, + const base::Optional<url::Origin>& origin, network::mojom::URLLoaderFactoryRequest default_factory_request) { bool bypass_redirect_checks = CreateNetworkServiceDefaultFactoryInternal( origin, std::move(default_factory_request)); @@ -5261,7 +5275,7 @@ } bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryInternal( - const url::Origin& origin, + const base::Optional<url::Origin>& origin, network::mojom::URLLoaderFactoryRequest default_factory_request) { auto* context = GetSiteInstance()->GetBrowserContext(); bool bypass_redirect_checks = false; @@ -5269,8 +5283,9 @@ network::mojom::TrustedURLLoaderHeaderClientPtrInfo header_client; if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { GetContentClient()->browser()->WillCreateURLLoaderFactory( - context, this, GetProcess()->GetID(), false /* is_navigation */, origin, - &default_factory_request, &header_client, &bypass_redirect_checks); + context, this, GetProcess()->GetID(), false /* is_navigation */, + origin.value_or(url::Origin()), &default_factory_request, + &header_client, &bypass_redirect_checks); } // Keep DevTools proxy last, i.e. closest to the network. @@ -6052,27 +6067,6 @@ navigation_requests_.erase(navigation_id); } -void RenderFrameHostImpl::SaveSubresourceFactories( - std::unique_ptr<URLLoaderFactoryBundleInfo> bundle_info) { - // CHECK for https://crbug.com/849929. - CHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService) || - bundle_info); - subresource_loader_factories_bundle_ = nullptr; - if (bundle_info) { - subresource_loader_factories_bundle_ = - base::MakeRefCounted<URLLoaderFactoryBundle>(std::move(bundle_info)); - } -} - -std::unique_ptr<URLLoaderFactoryBundleInfo> -RenderFrameHostImpl::CloneSubresourceFactories() { - if (subresource_loader_factories_bundle_) { - return base::WrapUnique(static_cast<URLLoaderFactoryBundleInfo*>( - subresource_loader_factories_bundle_->Clone().release())); - } - return nullptr; -} - std::unique_ptr<base::trace_event::TracedValue> RenderFrameHostImpl::CommitAsTracedValue( FrameHostMsg_DidCommitProvisionalLoad_Params* validated_params) const {
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 12d88e6..98bd156 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -67,6 +67,7 @@ #include "third_party/blink/public/common/frame/frame_owner_element_type.h" #include "third_party/blink/public/common/frame/user_activation_update_type.h" #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" #include "third_party/blink/public/mojom/frame/find_in_page.mojom.h" #include "third_party/blink/public/mojom/frame/navigation_initiator.mojom.h" #include "third_party/blink/public/mojom/presentation/presentation.mojom.h" @@ -78,7 +79,6 @@ #include "third_party/blink/public/platform/web_scroll_types.h" #include "third_party/blink/public/platform/web_sudden_termination_disabler_type.h" #include "third_party/blink/public/web/commit_result.mojom.h" -#include "third_party/blink/public/web/devtools_agent.mojom.h" #include "third_party/blink/public/web/web_text_direction.h" #include "third_party/blink/public/web/web_tree_scope_type.h" #include "ui/accessibility/ax_mode.h" @@ -1086,14 +1086,14 @@ // case of navigation) or has last committed (when handling network process // crashes). bool CreateNetworkServiceDefaultFactoryAndObserve( - const url::Origin& origin, + const base::Optional<url::Origin>& origin, network::mojom::URLLoaderFactoryRequest default_factory_request); // |origin| is the origin that the RenderFrame is either committing (in the // case of navigation) or has last committed (when handling network process // crashes). bool CreateNetworkServiceDefaultFactoryInternal( - const url::Origin& origin, + const base::Optional<url::Origin>& origin, network::mojom::URLLoaderFactoryRequest default_factory_request); // Returns true if the ExecuteJavaScript() API can be used on this host. @@ -1309,12 +1309,6 @@ void OnCrossDocumentCommitProcessed(int64_t navigation_id, blink::mojom::CommitResult result); - // Saves and clones URLLoaderFactoryBundleInfo for subresource loading. - // Must be called every time subresource_factories_bundle is updated. - void SaveSubresourceFactories( - std::unique_ptr<URLLoaderFactoryBundleInfo> bundle_info); - std::unique_ptr<URLLoaderFactoryBundleInfo> CloneSubresourceFactories(); - // Creates a TracedValue object containing the details of a committed // navigation, so it can be logged with the tracing system. std::unique_ptr<base::trace_event::TracedValue> CommitAsTracedValue( @@ -1639,10 +1633,6 @@ ContentBrowserClient::NonNetworkURLLoaderFactoryMap non_network_url_loader_factories_; - // A bundle of subresource loader factories used by this frame. - // A clone of this bundle is sent to the renderer process. - scoped_refptr<URLLoaderFactoryBundle> subresource_loader_factories_bundle_; - // Bitfield for renderer-side state that blocks fast shutdown of the frame. blink::WebSuddenTerminationDisablerType sudden_termination_disabler_types_enabled_ = 0;
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc index af8281d..b21bcb2 100644 --- a/content/browser/frame_host/render_frame_host_manager.cc +++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -2186,11 +2186,16 @@ // so that's probably good. // Note the RenderWidgetHostView can be missing if the process for the old // RenderFrameHost crashed. - // TODO(creis): As long as show/hide are on RVH, we don't want to hide on - // subframe navigations or we will interfere with the top-level frame. - // TODO(danakj): For subframes the old_render_frame_host will get swapped out - // and eventually deleted on SwapOutACK. So why would we want to Hide() it - // here anyways? + // TODO(crbug.com/419087): This is only done for the main frame, as for sub + // frames the RenderWidget and its view will be destroyed when the frame is + // detached, but for the main frame it is not. This call to Hide() can go away + // when the main frame's RenderWidget is destroyed on frame detach. Note that + // calling this on a subframe that is not a local root would be incorrect as + // it would hide an ancestor local root's RenderWidget when that frame is not + // necessarily navigating. Removing this Hide() has previously been attempted + // without success in r426913 (https://crbug.com/658688) and r438516 (broke + // assumptions about RenderWidgetHosts not changing RenderWidgetHostViews over + // time). if (is_main_frame && old_render_frame_host->GetView()) { // Note that this hides the RenderWidget but does not hide the Page. If it // did hide the Page then making a new RenderFrameHost on another call to
diff --git a/content/browser/frame_host/render_frame_message_filter.cc b/content/browser/frame_host/render_frame_message_filter.cc index 324ed2f..541ce8c 100644 --- a/content/browser/frame_host/render_frame_message_filter.cc +++ b/content/browser/frame_host/render_frame_message_filter.cc
@@ -295,6 +295,10 @@ return &cookie_manager_; } +void RenderFrameMessageFilter::ClearResourceContext() { + resource_context_ = nullptr; +} + void RenderFrameMessageFilter::InitializeCookieManager( network::mojom::CookieManagerRequest cookie_manager_request) { RenderProcessHost* render_process_host = @@ -458,6 +462,9 @@ const GURL& url, const GURL& site_for_cookies, bool* cookies_enabled) { + if (!resource_context_) + return; + // TODO(ananta): If this render frame is associated with an automation // channel, aka ChromeFrame then we need to retrieve cookie settings from the // external host. @@ -472,6 +479,11 @@ const GURL& site_for_cookies, GetCookiesCallback callback, const net::CookieList& cookie_list) { + if (!resource_context_) { + std::move(callback).Run(std::string()); + return; + } + // Check the policy for get cookies, and pass cookie_list to the // TabSpecificContentSetting for logging purpose. if (GetContentClient()->browser()->AllowGetCookie( @@ -538,6 +550,11 @@ const GURL& site_for_cookies, const std::string& cookie_line, SetCookieCallback callback) { + if (!resource_context_) { + std::move(callback).Run(); + return; + } + ChildProcessSecurityPolicyImpl* policy = ChildProcessSecurityPolicyImpl::GetInstance(); if (!policy->CanAccessDataForOrigin(render_process_id_, url)) { @@ -598,6 +615,11 @@ const GURL& url, const GURL& site_for_cookies, GetCookiesCallback callback) { + if (!resource_context_) { + std::move(callback).Run(std::string()); + return; + } + ChildProcessSecurityPolicyImpl* policy = ChildProcessSecurityPolicyImpl::GetInstance(); if (!policy->CanAccessDataForOrigin(render_process_id_, url)) { @@ -663,6 +685,9 @@ bool* found, WebPluginInfo* info, std::string* actual_mime_type) { + if (!resource_context_) + return; + bool allow_wildcard = true; *found = plugin_service_->GetPluginInfo( render_process_id_, render_frame_id, resource_context_, url,
diff --git a/content/browser/frame_host/render_frame_message_filter.h b/content/browser/frame_host/render_frame_message_filter.h index 91a7d32..8280d10 100644 --- a/content/browser/frame_host/render_frame_message_filter.h +++ b/content/browser/frame_host/render_frame_message_filter.h
@@ -74,6 +74,9 @@ network::mojom::CookieManagerPtr* GetCookieManager(); + // Clears |resource_context_| to prevent accessing it after deletion. + void ClearResourceContext(); + protected: friend class TestSaveImageFromDataURL;
diff --git a/content/browser/frame_host/render_frame_message_filter_browsertest.cc b/content/browser/frame_host/render_frame_message_filter_browsertest.cc index 01e6a62..3222349 100644 --- a/content/browser/frame_host/render_frame_message_filter_browsertest.cc +++ b/content/browser/frame_host/render_frame_message_filter_browsertest.cc
@@ -310,4 +310,97 @@ ASSERT_FALSE(web_rfh->IsRenderFrameLive()); } +class WaitingCookieStore : public net::CookieMonster { + public: + WaitingCookieStore() : CookieMonster(nullptr, nullptr, nullptr) {} + + void GetCookieListWithOptionsAsync(const GURL& url, + const net::CookieOptions& options, + GetCookieListCallback callback) override { + callback_ = std::move(callback); + } + + void Finish() { std::move(callback_).Run({}); } + + private: + GetCookieListCallback callback_; +}; + +class CookieStoreContentBrowserClient : public ContentBrowserClient { + public: + ~CookieStoreContentBrowserClient() override { + BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, + std::move(cookie_store_)); + } + + net::CookieStore* OverrideCookieStoreForURL( + const GURL& url, + ResourceContext* context) override { + if (!cookie_store_) + cookie_store_ = std::make_unique<WaitingCookieStore>(); + return cookie_store_.get(); + } + + bool AllowGetCookie(const GURL& url, + const GURL& first_party, + const net::CookieList& cookie_list, + ResourceContext* context, + int render_process_id, + int render_frame_id) override { + num_allow_get_cookie_calls_++; + return false; + } + + void FinishGetCookieList() { + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::IO}, + base::BindOnce(&WaitingCookieStore::Finish, + base::Unretained(cookie_store_.get()))); + } + + int num_allow_get_cookie_calls() const { return num_allow_get_cookie_calls_; } + + private: + int num_allow_get_cookie_calls_ = 0; + std::unique_ptr<WaitingCookieStore> cookie_store_; +}; + +IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest, + CookieCallbackAfterProfileDestroyed) { + CookieStoreContentBrowserClient browser_client; + content::ContentBrowserClient* old_browser_client = + content::SetBrowserClientForTesting(&browser_client); + + ASSERT_TRUE(embedded_test_server()->Start()); + NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")); + + base::RunLoop run_loop; + WebContentsImpl* web_contents = + static_cast<WebContentsImpl*>(shell()->web_contents()); + FrameTreeNode* root = web_contents->GetFrameTree()->root(); + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::IO}, + base::BindOnce( + [](RenderFrameHost* frame, base::RunLoop* run_loop) { + GetFilterForProcess(frame->GetProcess()) + ->GetCookies( + frame->GetRoutingID(), GURL("http://127.0.0.1/"), + GURL("http://127.0.0.1/"), + base::BindOnce([](base::RunLoop* run_loop, + const std::string&) { run_loop->Quit(); }, + run_loop)); + }, + root->current_frame_host(), &run_loop)); + + shell()->Close(); + base::RunLoop().RunUntilIdle(); + + int num_calls = browser_client.num_allow_get_cookie_calls(); + browser_client.FinishGetCookieList(); + run_loop.Run(); + EXPECT_EQ(num_calls, browser_client.num_allow_get_cookie_calls()); + + content::SetBrowserClientForTesting(old_browser_client); +} + } // namespace content
diff --git a/content/browser/gpu/gpu_data_manager_impl.cc b/content/browser/gpu/gpu_data_manager_impl.cc index 976bfcd0..b569538 100644 --- a/content/browser/gpu/gpu_data_manager_impl.cc +++ b/content/browser/gpu/gpu_data_manager_impl.cc
@@ -85,6 +85,12 @@ return private_->HardwareAccelerationEnabled(); } +void GpuDataManagerImpl::AppendGpuCommandLine( + base::CommandLine* command_line) const { + base::AutoLock auto_lock(lock_); + private_->AppendGpuCommandLine(command_line); +} + void GpuDataManagerImpl::RequestGpuSupportedRuntimeVersion() const { base::AutoLock auto_lock(lock_); private_->RequestGpuSupportedRuntimeVersion(); @@ -141,12 +147,6 @@ return private_->GetGpuFeatureInfoForHardwareGpu(); } -void GpuDataManagerImpl::AppendGpuCommandLine( - base::CommandLine* command_line) const { - base::AutoLock auto_lock(lock_); - private_->AppendGpuCommandLine(command_line); -} - void GpuDataManagerImpl::UpdateGpuPreferences( gpu::GpuPreferences* gpu_preferences) const { base::AutoLock auto_lock(lock_);
diff --git a/content/browser/gpu/gpu_data_manager_impl.h b/content/browser/gpu/gpu_data_manager_impl.h index 2a18cf5..9be8e89 100644 --- a/content/browser/gpu/gpu_data_manager_impl.h +++ b/content/browser/gpu/gpu_data_manager_impl.h
@@ -31,10 +31,6 @@ class GURL; -namespace base { -class CommandLine; -} - namespace gpu { struct GpuPreferences; struct VideoMemoryUsageStats; @@ -67,6 +63,7 @@ void RemoveObserver(GpuDataManagerObserver* observer) override; void DisableHardwareAcceleration() override; bool HardwareAccelerationEnabled() const override; + void AppendGpuCommandLine(base::CommandLine* command_line) const override; void RequestGpuSupportedRuntimeVersion() const; bool GpuProcessStartAllowed() const; @@ -93,9 +90,6 @@ gpu::GPUInfo GetGPUInfoForHardwareGpu() const; gpu::GpuFeatureInfo GetGpuFeatureInfoForHardwareGpu() const; - // Insert switches into gpu process command line: kUseGL, etc. - void AppendGpuCommandLine(base::CommandLine* command_line) const; - // Update GpuPreferences based on blacklisting decisions. void UpdateGpuPreferences(gpu::GpuPreferences* gpu_preferences) const;
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc index f14fd05c..0654cb3 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -1766,11 +1766,7 @@ // Make sure the last reference to a ChainedBlobWriter is released (and // deleted) on the IDB sequence since it owns a transaction which has // sequence affinity. - IndexedDBBackingStore::Transaction::ChainedBlobWriter* raw_tmp = - chained_blob_writer_.get(); - raw_tmp->AddRef(); - chained_blob_writer_ = nullptr; - task_runner_->ReleaseSoon(FROM_HERE, raw_tmp); + task_runner_->ReleaseSoon(FROM_HERE, std::move(chained_blob_writer_)); } friend class base::RefCountedThreadSafe<LocalWriteClosure>;
diff --git a/content/browser/indexed_db/indexed_db_context_impl.cc b/content/browser/indexed_db/indexed_db_context_impl.cc index 400f9cea..5198305e 100644 --- a/content/browser/indexed_db/indexed_db_context_impl.cc +++ b/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -429,12 +429,6 @@ return paths; } -// TODO(jsbell): Update callers to use url::Origin overload and remove. -base::FilePath IndexedDBContextImpl::GetFilePathForTesting( - const GURL& origin_url) const { - return GetFilePathForTesting(Origin::Create(origin_url)); -} - base::FilePath IndexedDBContextImpl::GetFilePathForTesting( const Origin& origin) const { return GetLevelDBPath(origin);
diff --git a/content/browser/indexed_db/indexed_db_context_impl.h b/content/browser/indexed_db/indexed_db_context_impl.h index ddc5813..ea5fa2b 100644 --- a/content/browser/indexed_db/indexed_db_context_impl.h +++ b/content/browser/indexed_db/indexed_db_context_impl.h
@@ -22,7 +22,6 @@ #include "content/public/browser/indexed_db_context.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/quota/special_storage_policy.h" -#include "url/gurl.h" #include "url/origin.h" namespace base { @@ -90,12 +89,10 @@ void DeleteForOrigin(const url::Origin& origin) override; void CopyOriginData(const url::Origin& origin, IndexedDBContext* dest_context) override; - base::FilePath GetFilePathForTesting(const GURL& origin_url) const override; + base::FilePath GetFilePathForTesting( + const url::Origin& origin) const override; void ResetCachesForTesting() override; - // TODO(jsbell): Replace IndexedDBContext members with these. - base::FilePath GetFilePathForTesting(const url::Origin& origin) const; - // Methods called by IndexedDBDispatcherHost for quota support. void ConnectionOpened(const url::Origin& origin, IndexedDBConnection* db); void ConnectionClosed(const url::Origin& origin, IndexedDBConnection* db);
diff --git a/content/browser/keyboard_lock_browsertest.cc b/content/browser/keyboard_lock_browsertest.cc index 4894106e..2d8f0d6 100644 --- a/content/browser/keyboard_lock_browsertest.cc +++ b/content/browser/keyboard_lock_browsertest.cc
@@ -677,7 +677,7 @@ // KeyboardLockServiceImpl returns success from the RequestKeyboardLock() // call when the Chrome side of the feature is disabled. This prevents - // problems running the WebKit layout tests. + // problems running the Blink web tests. bool result = false; ASSERT_TRUE(ExecuteScriptAndExtractBool(web_contents()->GetMainFrame(), kKeyboardLockMethodCallWithAllKeys,
diff --git a/content/browser/loader/cross_site_document_blocking_browsertest.cc b/content/browser/loader/cross_site_document_blocking_browsertest.cc index 84213048..acd6dbc 100644 --- a/content/browser/loader/cross_site_document_blocking_browsertest.cc +++ b/content/browser/loader/cross_site_document_blocking_browsertest.cc
@@ -41,6 +41,7 @@ #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/network_switches.h" #include "services/network/test/test_url_loader_client.h" +#include "services/network/url_loader.h" #include "testing/gmock/include/gmock/gmock.h" #include "third_party/blink/public/common/service_worker/service_worker_utils.h" @@ -49,6 +50,8 @@ using testing::Not; using testing::HasSubstr; using Action = network::CrossOriginReadBlocking::Action; +using RequestInitiatorOriginLockCompatibility = + network::URLLoader::RequestInitiatorOriginLockCompatibility; namespace { @@ -87,16 +90,31 @@ // Ensure the correct histograms are incremented for blocking events. // Assumes the resource type is XHR. -void InspectHistograms(const base::HistogramTester& histograms, - const CorbExpectations& expectations, - const std::string& resource_name, - ResourceType resource_type) { +void InspectHistograms( + const base::HistogramTester& histograms, + const CorbExpectations& expectations, + const std::string& resource_name, + ResourceType resource_type, + bool special_request_initiator_origin_lock_check_for_appcache = false) { // //services/network doesn't have access to content::ResourceType and // therefore cannot log some CORB UMAs. bool is_restricted_uma_expected = false; if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { is_restricted_uma_expected = true; FetchHistogramsFromChildProcesses(); + + // TODO(lukasza): https://crbug.com/910287: Remove the special case below + // after ensuring that |request_initiator| coming through AppCache is + // trustworthy (today kBrowserProcess will be reported in + // NetworkService.URLLoader.RequestInitiatorOriginLockCompatibility when + // AppCache is relaying renderer requests through a browser process). + auto expected_lock_compatibility = + special_request_initiator_origin_lock_check_for_appcache + ? RequestInitiatorOriginLockCompatibility::kBrowserProcess + : RequestInitiatorOriginLockCompatibility::kCompatibleLock; + histograms.ExpectUniqueSample( + "NetworkService.URLLoader.RequestInitiatorOriginLockCompatibility", + expected_lock_compatibility, 1); } std::string bucket; @@ -374,6 +392,9 @@ RequestInterceptor interceptor(resource_url); EXPECT_TRUE(NavigateToURL(shell(), GURL("http://foo.com/title1.html"))); + // Make sure that base::HistogramTester below starts with a clean slate. + FetchHistogramsFromChildProcesses(); + // Issue the request that will be intercepted. base::HistogramTester histograms; const char kScriptTemplate[] = R"( @@ -504,11 +525,18 @@ "cors.txt"}; for (const char* resource : allowed_resources) { SCOPED_TRACE(base::StringPrintf("... while testing page: %s", resource)); + + // Make sure that base::HistogramTester below starts with a clean slate. + FetchHistogramsFromChildProcesses(); + + // Fetch. base::HistogramTester histograms; bool was_blocked; ASSERT_TRUE(ExecuteScriptAndExtractBool( shell(), base::StringPrintf("sendRequest('%s');", resource), &was_blocked)); + + // Verify results of the fetch. EXPECT_FALSE(was_blocked); InspectHistograms(histograms, kShouldBeAllowedWithoutSniffing, resource, RESOURCE_TYPE_XHR); @@ -663,10 +691,11 @@ content::JsReplace(kScriptTemplate, "logo.png"))); } - FetchHistogramsFromChildProcesses(); - // Verify that CORB also works in presence of AppCache. { + // Make sure that base::HistogramTester below starts with a clean slate. + FetchHistogramsFromChildProcesses(); + // Fetch... base::HistogramTester histograms; const char kScriptTemplate[] = R"( @@ -677,8 +706,10 @@ interceptor.WaitForRequestCompletion(); // Verify... + bool special_request_initiator_origin_lock_check_for_appcache = true; InspectHistograms(histograms, kShouldBeBlockedWithoutSniffing, - "nosniff.json", RESOURCE_TYPE_IMAGE); + "nosniff.json", RESOURCE_TYPE_IMAGE, + special_request_initiator_origin_lock_check_for_appcache); interceptor.Verify(kShouldBeBlockedWithoutSniffing); } } @@ -695,10 +726,15 @@ "a.com", "/cross_site_iframe_factory.html?a(b)")); EXPECT_TRUE(NavigateToURL(shell(), main_url)); + // Make sure that base::HistogramTester below starts with a clean slate. + FetchHistogramsFromChildProcesses(); + // Inject a cross-origin <link rel="prefetch" ...> into the main frame. // TODO(lukasza): https://crbug.com/827633#c5: We might need to switch to // listening to the onload event below (after/if CORB starts to consistently // avoid injecting net errors). + FetchHistogramsFromChildProcesses(); + base::HistogramTester histograms; const char* prefetch_injection_script_template = R"( var link = document.createElement("link"); link.rel = "prefetch"; @@ -719,8 +755,6 @@ // Respond to the prefetch request in a way that: // 1) will enable caching // 2) won't finish until after CORB has blocked the response. - FetchHistogramsFromChildProcesses(); - base::HistogramTester histograms; std::string response_bytes = "HTTP/1.1 200 OK\r\n" "Cache-Control: public, max-age=10\r\n" @@ -909,6 +943,9 @@ SetUpServiceWorker(); + // Make sure that base::HistogramTester below starts with a clean slate. + FetchHistogramsFromChildProcesses(); + base::HistogramTester histograms; std::string response; std::string script = R"( @@ -959,6 +996,9 @@ std::string script = base::StringPrintf(script_template, cross_origin_url.spec().c_str()); + // Make sure that base::HistogramTester below starts with a clean slate. + FetchHistogramsFromChildProcesses(); + // The service worker will forward the request to the network, but a response // will be intercepted by the service worker and replaced with a new, // artificial error.
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc index 2905e741..da0f0227 100644 --- a/content/browser/loader/navigation_url_loader_impl.cc +++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -85,7 +85,6 @@ #include "services/network/public/cpp/wrapper_shared_url_loader_factory.h" #include "services/network/public/mojom/request_context_frame_type.mojom.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" -#include "services/service_manager/public/cpp/connector.h" #include "third_party/blink/public/common/mime_util/mime_util.h" #include "third_party/blink/public/common/service_worker/service_worker_utils.h" @@ -209,6 +208,7 @@ new_request->method = request_info->common_params.method; new_request->url = request_info->common_params.url; new_request->site_for_cookies = request_info->site_for_cookies; + new_request->top_frame_origin = request_info->top_frame_origin; net::RequestPriority net_priority = net::HIGHEST; if (!request_info->is_main_frame && @@ -299,6 +299,7 @@ return std::make_unique<NavigationRequestInfo>( std::move(new_common_params), std::move(new_begin_params), updated_resource_request.site_for_cookies, + updated_resource_request.top_frame_origin, previous_request_info.is_main_frame, previous_request_info.parent_is_main_frame, previous_request_info.are_ancestors_secure, @@ -586,7 +587,6 @@ base::TimeTicks::Now())); } - // TODO(arthursonzogni): See if this could eventually be unified with Start(). void StartWithoutNetworkService( net::URLRequestContextGetter* url_request_context_getter, storage::FileSystemContext* upload_file_system_context, @@ -620,56 +620,10 @@ base::Unretained(service_worker_navigation_handle_core), base::Unretained(appcache_handle_core)); - // Requests to Blob scheme won't get redirected to/from other schemes - // or be intercepted, so we just let it go here. - if (request_info_->common_params.url.SchemeIsBlob() && - request_info_->blob_url_loader_factory) { - url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( - network::SharedURLLoaderFactory::Create( - std::move(request_info_->blob_url_loader_factory)), - CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id? */, - network::mojom::kURLLoadOptionNone, resource_request_.get(), this, - kNavigationUrlLoaderTrafficAnnotation, - base::ThreadTaskRunnerHandle::Get()); - return; - } - - if (blink::ServiceWorkerUtils::IsServicificationEnabled() && - service_worker_navigation_handle_core) { - std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor = - CreateServiceWorkerInterceptor(*request_info_, - service_worker_navigation_handle_core); - // The interceptor for service worker may not be created for some reasons - // (e.g. the origin is not secure). - if (service_worker_interceptor) - interceptors_.push_back(std::move(service_worker_interceptor)); - } - - if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) { - DCHECK(!network_loader_factory_); - interceptors_.push_back(CreateSignedExchangeRequestHandler( - *request_info_, - base::MakeRefCounted< - SignedExchangeURLLoaderFactoryForNonNetworkService>( - resource_context_, url_request_context_getter), - std::move(signed_exchange_prefetch_metric_recorder))); - } - - // If an interceptor is not created, we no longer have to go through the - // rest of the network service code. - if (interceptors_.empty()) { - url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( - base::MakeRefCounted<SingleRequestURLLoaderFactory>( - default_request_handler_factory_.Run( - false /* was_request_intercepted */)), - CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */, - network::mojom::kURLLoadOptionNone, resource_request_.get(), - this /* client */, kNavigationUrlLoaderTrafficAnnotation, - base::ThreadTaskRunnerHandle::Get()); - return; - } - - Restart(); + StartInternal(request_info_.get(), service_worker_navigation_handle_core, + nullptr /* appcache_handle_core */, + std::move(signed_exchange_prefetch_metric_recorder), + {} /* factory_for_webui */, url_request_context_getter); } void Start( @@ -682,8 +636,7 @@ std::unique_ptr<NavigationRequestInfo> request_info, std::unique_ptr<NavigationUIData> navigation_ui_data, network::mojom::URLLoaderFactoryPtrInfo factory_for_webui, - int frame_tree_node_id, - std::unique_ptr<service_manager::Connector> connector) { + int frame_tree_node_id) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService)); DCHECK(!started_); @@ -708,9 +661,34 @@ resource_context_, &blob_handles_); } + StartInternal(request_info.get(), service_worker_navigation_handle_core, + appcache_handle_core, + std::move(signed_exchange_prefetch_metric_recorder), + std::move(factory_for_webui), + nullptr /* url_request_context_getter */); + } + + // Common setup routines, called by both StartWithoutNetworkService() and + // Start(). Most parameters (except for |request_info| and + // |url_request_context_getter|) are for setting up feature-specific + // loaders and interceptors, and they can be null depending on the flags. + // |url_request_context_getter| is non-null only for non-NetworkService + // code paths. + // TODO(kinuko): Merge this back to Start() once NetworkService is fully + // shipped. + void StartInternal( + NavigationRequestInfo* request_info, + ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core, + AppCacheNavigationHandleCore* appcache_handle_core, + scoped_refptr<SignedExchangePrefetchMetricRecorder> + signed_exchange_prefetch_metric_recorder, + network::mojom::URLLoaderFactoryPtrInfo factory_for_webui, + net::URLRequestContextGetter* url_request_context_getter) { + // NetworkService cases only. // Requests to WebUI scheme won't get redirected to/from other schemes // or be intercepted, so we just let it go here. if (factory_for_webui.is_valid()) { + DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService)); url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>( std::move(factory_for_webui)), @@ -735,15 +713,24 @@ return; } - if (service_worker_navigation_handle_core) { + // Set-up an interceptor for service workers if S13nSW is enabled and + // non-null |service_worker_navigation_handle_core| is given. + if (service_worker_navigation_handle_core && + blink::ServiceWorkerUtils::IsServicificationEnabled()) { std::unique_ptr<NavigationLoaderInterceptor> service_worker_interceptor = CreateServiceWorkerInterceptor(*request_info, service_worker_navigation_handle_core); + // The interceptor for service worker may not be created for some reasons + // (e.g. the origin is not secure). if (service_worker_interceptor) interceptors_.push_back(std::move(service_worker_interceptor)); } + // NetworkService cases only. + // Set-up an interceptor for AppCache if non-null |appcache_handle_core| + // is given. if (appcache_handle_core) { + DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService)); std::unique_ptr<NavigationLoaderInterceptor> appcache_interceptor = AppCacheRequestHandler::InitializeForMainResourceNetworkService( *resource_request_, appcache_handle_core->host()->GetWeakPtr()); @@ -751,12 +738,23 @@ interceptors_.push_back(std::move(appcache_interceptor)); } + // Set-up an interceptor for SignedExchange handling if it is enabled. if (signed_exchange_utils::IsSignedExchangeHandlingEnabled()) { + auto network_loader_factory = network_loader_factory_; + if (!network_loader_factory) { + DCHECK( + !base::FeatureList::IsEnabled(network::features::kNetworkService)); + DCHECK(url_request_context_getter); + network_loader_factory = base::MakeRefCounted< + SignedExchangeURLLoaderFactoryForNonNetworkService>( + resource_context_, url_request_context_getter); + } interceptors_.push_back(CreateSignedExchangeRequestHandler( - *request_info, network_loader_factory_, + *request_info, std::move(network_loader_factory), std::move(signed_exchange_prefetch_metric_recorder))); } + // See if embedders want to add interceptors. std::vector<std::unique_ptr<URLLoaderRequestInterceptor>> browser_interceptors = GetContentClient() ->browser() @@ -771,6 +769,23 @@ } } + // Non-NetworkService cases only. + // If an interceptor is not created, we no longer have to go through the + // rest of the network service code. + if (!base::FeatureList::IsEnabled(network::features::kNetworkService) && + interceptors_.empty()) { + DCHECK(default_request_handler_factory_); + url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( + base::MakeRefCounted<SingleRequestURLLoaderFactory>( + default_request_handler_factory_.Run( + false /* was_request_intercepted */)), + CreateURLLoaderThrottles(), -1 /* routing_id */, 0 /* request_id */, + network::mojom::kURLLoadOptionNone, resource_request_.get(), + this /* client */, kNavigationUrlLoaderTrafficAnnotation, + base::ThreadTaskRunnerHandle::Get()); + return; + } + Restart(); } @@ -1028,7 +1043,6 @@ const base::Optional<net::HttpRequestHeaders>& modified_request_headers) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!redirect_info_.new_url.is_empty()); - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { auto* common_params = const_cast<CommonNavigationParams*>(&request_info_->common_params); @@ -1065,6 +1079,7 @@ resource_request_->url = redirect_info_.new_url; resource_request_->method = redirect_info_.new_method; resource_request_->site_for_cookies = redirect_info_.new_site_for_cookies; + resource_request_->top_frame_origin = redirect_info_.new_top_frame_origin; resource_request_->referrer = GURL(redirect_info_.new_referrer); resource_request_->referrer_policy = redirect_info_.new_referrer_policy; url_chain_.push_back(redirect_info_.new_url); @@ -1743,15 +1758,14 @@ weak_factory_.GetWeakPtr()); base::PostTaskWithTraits( FROM_HERE, {BrowserThread::IO}, - base::BindOnce( - &URLLoaderRequestController::Start, - base::Unretained(request_controller_.get()), - std::move(network_factory_info), - service_worker_navigation_handle_core, appcache_handle_core, - std::move(signed_exchange_prefetch_metric_recorder), - std::move(request_info), std::move(navigation_ui_data), - std::move(factory_for_webui), frame_tree_node_id, - ServiceManagerConnection::GetForProcess()->GetConnector()->Clone())); + base::BindOnce(&URLLoaderRequestController::Start, + base::Unretained(request_controller_.get()), + std::move(network_factory_info), + service_worker_navigation_handle_core, + appcache_handle_core, + std::move(signed_exchange_prefetch_metric_recorder), + std::move(request_info), std::move(navigation_ui_data), + std::move(factory_for_webui), frame_tree_node_id)); } NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {
diff --git a/content/browser/loader/navigation_url_loader_impl_unittest.cc b/content/browser/loader/navigation_url_loader_impl_unittest.cc index 6e039919..3dd219a 100644 --- a/content/browser/loader/navigation_url_loader_impl_unittest.cc +++ b/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -181,7 +181,8 @@ std::unique_ptr<NavigationRequestInfo> request_info( new NavigationRequestInfo( - common_params, std::move(begin_params), url, is_main_frame, + common_params, std::move(begin_params), url, + url::Origin::Create(url), is_main_frame, false /* parent_is_main_frame */, false /* are_ancestors_secure */, -1 /* frame_tree_node_id */, false /* is_for_guests_only */, false /* report_raw_headers */, false /* is_prerenering */, @@ -306,6 +307,38 @@ NavigateAndReturnRequestPriority(url, false /* is_main_frame */)); } +TEST_F(NavigationURLLoaderImplTest, TopFrameOriginOfMainFrameNavigation) { + ASSERT_TRUE(http_test_server_.Start()); + + const GURL url = http_test_server_.GetURL("/foo"); + + TestNavigationURLLoaderDelegate delegate; + std::unique_ptr<NavigationURLLoader> loader = CreateTestLoader( + url, + base::StringPrintf("%s: %s", net::HttpRequestHeaders::kOrigin, + url.GetOrigin().spec().c_str()), + "GET", &delegate, NavigationDownloadPolicy::kAllow, + true /*is_main_frame*/, false /*upgrade_if_insecure*/); + delegate.WaitForRequestStarted(); + + ASSERT_TRUE(most_recent_resource_request_); + EXPECT_EQ(url::Origin::Create(url), + *most_recent_resource_request_->top_frame_origin); +} + +TEST_F(NavigationURLLoaderImplTest, + TopFrameOriginOfRedirectedMainFrameNavigation) { + ASSERT_TRUE(http_test_server_.Start()); + + const GURL url = http_test_server_.GetURL("/redirect301-to-echo"); + const GURL final_url = http_test_server_.GetURL("/echo"); + + HTTPRedirectOriginHeaderTest(url, "GET", "GET", url.GetOrigin().spec()); + + EXPECT_EQ(url::Origin::Create(final_url), + *most_recent_resource_request_->top_frame_origin); +} + TEST_F(NavigationURLLoaderImplTest, Redirect301Tests) { ASSERT_TRUE(http_test_server_.Start());
diff --git a/content/browser/loader/navigation_url_loader_unittest.cc b/content/browser/loader/navigation_url_loader_unittest.cc index f3cbb99..a90bfba 100644 --- a/content/browser/loader/navigation_url_loader_unittest.cc +++ b/content/browser/loader/navigation_url_loader_unittest.cc
@@ -94,8 +94,8 @@ std::unique_ptr<NavigationRequestInfo> request_info( new NavigationRequestInfo(common_params, std::move(begin_params), url, - true, false, false, -1, false, false, false, - false, nullptr, + url::Origin::Create(url), true, false, false, + -1, false, false, false, false, nullptr, base::UnguessableToken::Create(), base::UnguessableToken::Create())); return NavigationURLLoader::Create(
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index 83b81f3..2831e90 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -850,6 +850,7 @@ new_request->set_method(request_data.method); new_request->set_site_for_cookies(request_data.site_for_cookies); + new_request->set_top_frame_origin(request_data.top_frame_origin); new_request->set_attach_same_site_cookies( request_data.attach_same_site_cookies); new_request->set_upgrade_if_insecure(request_data.upgrade_if_insecure); @@ -1474,6 +1475,7 @@ new_request->set_method(info.common_params.method); new_request->set_site_for_cookies(info.site_for_cookies); + new_request->set_top_frame_origin(info.top_frame_origin); new_request->set_initiator(info.begin_params->initiator_origin); new_request->set_upgrade_if_insecure(info.upgrade_if_insecure); if (info.is_main_frame) {
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc index 73b5961..43919fe 100644 --- a/content/browser/loader/resource_dispatcher_host_unittest.cc +++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -843,8 +843,8 @@ common_params.url = url; std::unique_ptr<NavigationRequestInfo> request_info( new NavigationRequestInfo(common_params, std::move(begin_params), url, - true, false, false, -1, false, false, false, - false, nullptr, + url::Origin::Create(url), true, false, false, + -1, false, false, false, false, nullptr, base::UnguessableToken::Create(), base::UnguessableToken::Create())); std::unique_ptr<NavigationURLLoader> test_loader =
diff --git a/content/browser/media/android/media_resource_getter_impl.cc b/content/browser/media/android/media_resource_getter_impl.cc index 88841bbd..0198f2b 100644 --- a/content/browser/media/android/media_resource_getter_impl.cc +++ b/content/browser/media/android/media_resource_getter_impl.cc
@@ -84,20 +84,13 @@ std::move(callback)); } -} // namespace - -static void RequestPlaformPathFromFileSystemURL( - const GURL& url, - int render_process_id, +void OnSyncGetPlatformPathDone( scoped_refptr<storage::FileSystemContext> file_system_context, - media::MediaResourceGetter::GetPlatformPathCB callback) { + media::MediaResourceGetter::GetPlatformPathCB callback, + const base::FilePath& platform_path) { DCHECK(file_system_context->default_file_task_runner() ->RunsTasksInCurrentSequence()); - base::FilePath platform_path; - SyncGetPlatformPath(file_system_context.get(), - render_process_id, - url, - &platform_path); + base::FilePath data_storage_path; base::PathService::Get(base::DIR_ANDROID_APP_DATA, &data_storage_path); if (data_storage_path.IsParent(platform_path)) @@ -106,6 +99,20 @@ ReturnResultOnUIThread(std::move(callback), std::string()); } +void RequestPlatformPathFromFileSystemURL( + const GURL& url, + int render_process_id, + scoped_refptr<storage::FileSystemContext> file_system_context, + media::MediaResourceGetter::GetPlatformPathCB callback) { + DCHECK(file_system_context->default_file_task_runner() + ->RunsTasksInCurrentSequence()); + SyncGetPlatformPath(file_system_context.get(), render_process_id, url, + base::BindOnce(&OnSyncGetPlatformPathDone, + file_system_context, std::move(callback))); +} + +} // namespace + // The task object that retrieves media resources on the IO thread. // TODO(qinmin): refactor this class to make the code reusable by others as // there are lots of duplicated functionalities elsewhere. @@ -247,7 +254,7 @@ scoped_refptr<storage::FileSystemContext> context(file_system_context_); context->default_file_task_runner()->PostTask( - FROM_HERE, base::BindOnce(&RequestPlaformPathFromFileSystemURL, url, + FROM_HERE, base::BindOnce(&RequestPlatformPathFromFileSystemURL, url, render_process_id_, context, std::move(cb))); }
diff --git a/content/browser/media/capture/desktop_capture_device.cc b/content/browser/media/capture/desktop_capture_device.cc index 7e9d1927..64dd8cb 100644 --- a/content/browser/media/capture/desktop_capture_device.cc +++ b/content/browser/media/capture/desktop_capture_device.cc
@@ -364,8 +364,6 @@ // last frame. if (!black_frame_ || !black_frame_->size().equals(output_size)) { black_frame_.reset(new webrtc::BasicDesktopFrame(output_size)); - memset(black_frame_->data(), 0, - black_frame_->stride() * black_frame_->size().height()); } output_data = black_frame_->data(); } else { @@ -396,7 +394,6 @@ // letterboxed areas. if (!output_frame_) { output_frame_.reset(new webrtc::BasicDesktopFrame(output_size)); - memset(output_frame_->data(), 0, output_bytes); } DCHECK(output_frame_->size().equals(output_size)); @@ -418,7 +415,6 @@ // crbug.com/437740). if (!output_frame_) { output_frame_.reset(new webrtc::BasicDesktopFrame(output_size)); - memset(output_frame_->data(), 0, output_bytes); } output_frame_->CopyPixelsFrom(
diff --git a/content/browser/media/media_suspend_browsertest.cc b/content/browser/media/media_suspend_browsertest.cc index 1cd1a66f..80b2a857 100644 --- a/content/browser/media/media_suspend_browsertest.cc +++ b/content/browser/media/media_suspend_browsertest.cc
@@ -22,7 +22,7 @@ // This browser test ensures the force suspend IPC messages are working properly // and that players suspended in this way can be resumed. Note: This does not -// test suspend in various ready states; those tests are handled by layout tests +// test suspend in various ready states; those tests are handled by web tests // for ease of writing and ready state manipulation. class MediaSuspendTest : public MediaBrowserTest { public:
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc index ba1db40..e194b1d 100644 --- a/content/browser/navigation_browsertest.cc +++ b/content/browser/navigation_browsertest.cc
@@ -43,6 +43,7 @@ #include "content/public/test/test_navigation_observer.h" #include "content/public/test/test_navigation_throttle.h" #include "content/public/test/test_navigation_throttle_inserter.h" +#include "content/public/test/url_loader_interceptor.h" #include "content/shell/browser/shell.h" #include "content/shell/browser/shell_content_browser_client.h" #include "content/shell/browser/shell_download_manager_delegate.h" @@ -191,6 +192,40 @@ NavigationBaseBrowserTest::SetUpOnMainThread(); ASSERT_TRUE(embedded_test_server()->Start()); } + + // Navigate to |url| and for each ResourceRequest record its + // top_frame_origin. Stop listening after |final_resource| has been + // detected. The output is recorded in |top_frame_origins|. + void NavigateAndRecordTopFrameOrigins( + const GURL& url, + const GURL& final_resource, + bool from_renderer, + std::map<GURL, url::Origin>* top_frame_origins) { + if (from_renderer) + EXPECT_TRUE(NavigateToURL(shell(), GURL("about:blank"))); + + base::RunLoop run_loop; + base::OnceClosure quit_closure = run_loop.QuitClosure(); + + // Intercept network requests and record them. + URLLoaderInterceptor interceptor(base::BindLambdaForTesting( + [&](URLLoaderInterceptor::RequestParams* params) -> bool { + (*top_frame_origins)[params->url_request.url] = + *params->url_request.top_frame_origin; + + if (params->url_request.url == final_resource) + std::move(quit_closure).Run(); + return false; + })); + + if (from_renderer) + EXPECT_TRUE(NavigateToURLFromRenderer(shell(), url)); + else + EXPECT_TRUE(NavigateToURL(shell(), url)); + + // Wait until the last resource we care about has been requested. + run_loop.Run(); + } }; // Ensure that browser initiated basic navigations work. @@ -715,6 +750,48 @@ EXPECT_EQ("\"done\"", done); } +IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, BrowserNavigationTopFrameOrigin) { + std::map<GURL, url::Origin> top_frame_origins; + GURL url(embedded_test_server()->GetURL("/title1.html")); + + NavigateAndRecordTopFrameOrigins(url, url /*final_resource*/, + false /*from_renderer*/, &top_frame_origins); + EXPECT_EQ(url::Origin::Create(url), top_frame_origins[url]); +} + +IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, RenderNavigationTopFrameOrigin) { + std::map<GURL, url::Origin> top_frame_origins; + GURL url(embedded_test_server()->GetURL("/title2.html")); + + NavigateAndRecordTopFrameOrigins(url, url /*final_resource*/, + true /*from_renderer*/, &top_frame_origins); + EXPECT_EQ(url::Origin::Create(url), top_frame_origins[url]); +} + +IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SubframeTopFrameOrigin) { + std::map<GURL, url::Origin> top_frame_origins; + GURL url(embedded_test_server()->GetURL("/page_with_iframe.html")); + GURL iframe_document = embedded_test_server()->GetURL("/title1.html"); + + NavigateAndRecordTopFrameOrigins(url, iframe_document /*final_resource*/, + false /*from_renderer*/, &top_frame_origins); + EXPECT_EQ(url::Origin::Create(url), top_frame_origins[url]); + EXPECT_EQ(url::Origin::Create(url), top_frame_origins[iframe_document]); +} + +IN_PROC_BROWSER_TEST_F(NavigationBrowserTest, SubresourceTopFrameOrigin) { + std::map<GURL, url::Origin> top_frame_origins; + GURL url(embedded_test_server()->GetURL("/page_with_iframe_and_image.html")); + GURL blank_image = embedded_test_server()->GetURL("/blank.jpg"); + + NavigateAndRecordTopFrameOrigins(url, blank_image /*final_resource*/, + false /*from_renderer*/, &top_frame_origins); + EXPECT_EQ(url::Origin::Create(url), top_frame_origins[url]); + EXPECT_EQ(url::Origin::Create(url), + top_frame_origins[embedded_test_server()->GetURL("/image.jpg")]); + EXPECT_EQ(url::Origin::Create(url), top_frame_origins[blank_image]); +} + // Navigation are started in the browser process. After the headers are // received, the URLLoaderClient is transferred from the browser process to the // renderer process. This test ensures that when the the URLLoader is deleted
diff --git a/content/browser/presentation/presentation_service_impl.cc b/content/browser/presentation/presentation_service_impl.cc index 21c99f7..b05b18e 100644 --- a/content/browser/presentation/presentation_service_impl.cc +++ b/content/browser/presentation/presentation_service_impl.cc
@@ -137,7 +137,7 @@ void PresentationServiceImpl::SetReceiver( blink::mojom::PresentationReceiverPtr receiver) { - // Presentation receiver virtual layout tests (which have the flag set) has no + // Presentation receiver virtual web tests (which have the flag set) has no // ReceiverPresentationServiceDelegate implementation. // TODO(imcheng): Refactor content_browser_client to return a no-op // PresentationService instead.
diff --git a/content/browser/renderer_host/code_cache_host_impl.cc b/content/browser/renderer_host/code_cache_host_impl.cc index ee6b9d6..5418b68 100644 --- a/content/browser/renderer_host/code_cache_host_impl.cc +++ b/content/browser/renderer_host/code_cache_host_impl.cc
@@ -207,8 +207,10 @@ if (!data.empty()) memcpy(buf->data(), &data.front(), data.size()); - cache_storage_context_->cache_manager()->OpenCache( - cache_storage_origin, CacheStorageOwner::kCacheAPI, + CacheStorageHandle cache_storage = + cache_storage_context_->cache_manager()->OpenCacheStorage( + cache_storage_origin, CacheStorageOwner::kCacheAPI); + cache_storage.value()->OpenCache( cache_storage_cache_name, base::BindOnce(&CodeCacheHostImpl::OnCacheStorageOpenCallback, weak_ptr_factory_.GetWeakPtr(), url,
diff --git a/content/browser/renderer_host/input/fling_controller.cc b/content/browser/renderer_host/input/fling_controller.cc index 4304ecee..f1db4c2 100644 --- a/content/browser/renderer_host/input/fling_controller.cc +++ b/content/browser/renderer_host/input/fling_controller.cc
@@ -178,7 +178,7 @@ } void FlingController::ScheduleFlingProgress() { - scheduler_client_->ScheduleFlingProgress(); + scheduler_client_->ScheduleFlingProgress(weak_ptr_factory_.GetWeakPtr()); } void FlingController::ProcessGestureFlingCancel( @@ -398,7 +398,7 @@ } if (had_active_fling) { - scheduler_client_->DidStopFlingingOnBrowser(); + scheduler_client_->DidStopFlingingOnBrowser(weak_ptr_factory_.GetWeakPtr()); TRACE_EVENT_ASYNC_END0("input", kFlingTraceName, this); } } @@ -430,15 +430,6 @@ return true; } -void FlingController::RegisterFlingSchedulerObserver() { - scheduler_client_->RegisterFlingSchedulerObserver( - weak_ptr_factory_.GetWeakPtr()); -} - -void FlingController::UnregisterFlingSchedulerObserver() { - scheduler_client_->UnregisterFlingSchedulerObserver(); -} - bool FlingController::FlingCancellationIsDeferred() const { return fling_booster_ && fling_booster_->fling_cancellation_is_deferred(); }
diff --git a/content/browser/renderer_host/input/fling_controller.h b/content/browser/renderer_host/input/fling_controller.h index ad01fa63..ac44240 100644 --- a/content/browser/renderer_host/input/fling_controller.h +++ b/content/browser/renderer_host/input/fling_controller.h
@@ -39,14 +39,11 @@ public: virtual ~FlingControllerSchedulerClient() {} - virtual void ScheduleFlingProgress() = 0; - - virtual void RegisterFlingSchedulerObserver( + virtual void ScheduleFlingProgress( base::WeakPtr<FlingController> fling_controller) = 0; - virtual void UnregisterFlingSchedulerObserver() = 0; - - virtual void DidStopFlingingOnBrowser() = 0; + virtual void DidStopFlingingOnBrowser( + base::WeakPtr<FlingController> fling_controller) = 0; virtual bool NeedsBeginFrameForFlingProgress() = 0; }; @@ -100,19 +97,6 @@ gfx::Vector2dF CurrentFlingVelocity() const; - // Registering the FlingScheduler after processing a GFS causes a frame of - // jank at the beginning of the fling (see https://crbug.com/882907). This is - // because the first OnAnimationStep call after observer's registration might - // be missing and/or incorrectly have the timestamp of the last begin frame - // before the observer's registration rather than the first begin frame after - // the registration (https://crbug.com/848796). To avoid this issue we - // register the observer on GSB instead of GFS so that the potential - // missing/incorrect OnAnimationStep call passes by the time that the GFS is - // processed. We unregister the observer on GSE instead of when the fling - // stops since not all GSBs are followed by GFS events. - void RegisterFlingSchedulerObserver(); - void UnregisterFlingSchedulerObserver(); - // Returns the |TouchpadTapSuppressionController| instance. TouchpadTapSuppressionController* GetTouchpadTapSuppressionController();
diff --git a/content/browser/renderer_host/input/fling_controller_unittest.cc b/content/browser/renderer_host/input/fling_controller_unittest.cc index 05e279bc..3d16d841 100644 --- a/content/browser/renderer_host/input/fling_controller_unittest.cc +++ b/content/browser/renderer_host/input/fling_controller_unittest.cc
@@ -69,16 +69,15 @@ } // FlingControllerSchedulerClient - void ScheduleFlingProgress() override { + void ScheduleFlingProgress( + base::WeakPtr<FlingController> fling_controller) override { DCHECK(!scheduled_next_fling_progress_); scheduled_next_fling_progress_ = true; } - void DidStopFlingingOnBrowser() override { + void DidStopFlingingOnBrowser( + base::WeakPtr<FlingController> fling_controller) override { notified_client_after_fling_stop_ = true; } - void RegisterFlingSchedulerObserver( - base::WeakPtr<FlingController> fling_controller) override {} - void UnregisterFlingSchedulerObserver() override {} bool NeedsBeginFrameForFlingProgress() override { return needs_begin_frame_for_fling_progress_; }
diff --git a/content/browser/renderer_host/input/fling_scheduler.cc b/content/browser/renderer_host/input/fling_scheduler.cc index d21bebf2..cf220cb 100644 --- a/content/browser/renderer_host/input/fling_scheduler.cc +++ b/content/browser/renderer_host/input/fling_scheduler.cc
@@ -24,41 +24,32 @@ observed_compositor_->RemoveAnimationObserver(this); } -void FlingScheduler::ScheduleFlingProgress() { - // Don't do anything if a ui::Compositor is already being observed. - if (observed_compositor_) - return; - - host_->SetNeedsBeginFrameForFlingProgress(); -} - -void FlingScheduler::RegisterFlingSchedulerObserver( +void FlingScheduler::ScheduleFlingProgress( base::WeakPtr<FlingController> fling_controller) { DCHECK(fling_controller); fling_controller_ = fling_controller; - // Convert the following if-statement back to DCHECK(!observed_compositor_) - // once https://crbug.com/897216 is fixed. + // Don't do anything if a ui::Compositor is already being observed. if (observed_compositor_) return; ui::Compositor* compositor = GetCompositor(); // If a ui::Compositor can't be obtained, ask the host for BeginFrames. - if (!compositor) + if (!compositor) { + host_->SetNeedsBeginFrameForFlingProgress(); return; - + } compositor->AddAnimationObserver(this); observed_compositor_ = compositor; } -void FlingScheduler::UnregisterFlingSchedulerObserver() { +void FlingScheduler::DidStopFlingingOnBrowser( + base::WeakPtr<FlingController> fling_controller) { + DCHECK(fling_controller); if (observed_compositor_) { observed_compositor_->RemoveAnimationObserver(this); observed_compositor_ = nullptr; } fling_controller_ = nullptr; -} - -void FlingScheduler::DidStopFlingingOnBrowser() { host_->DidStopFlinging(); }
diff --git a/content/browser/renderer_host/input/fling_scheduler.h b/content/browser/renderer_host/input/fling_scheduler.h index 658c589..7e263503 100644 --- a/content/browser/renderer_host/input/fling_scheduler.h +++ b/content/browser/renderer_host/input/fling_scheduler.h
@@ -24,11 +24,10 @@ ~FlingScheduler() override; // FlingControllerSchedulerClient - void ScheduleFlingProgress() override; - void RegisterFlingSchedulerObserver( + void ScheduleFlingProgress( base::WeakPtr<FlingController> fling_controller) override; - void UnregisterFlingSchedulerObserver() override; - void DidStopFlingingOnBrowser() override; + void DidStopFlingingOnBrowser( + base::WeakPtr<FlingController> fling_controller) override; bool NeedsBeginFrameForFlingProgress() override; // FlingSchedulerBase
diff --git a/content/browser/renderer_host/input/fling_scheduler_android.cc b/content/browser/renderer_host/input/fling_scheduler_android.cc index 7a110e25..28cb2db 100644 --- a/content/browser/renderer_host/input/fling_scheduler_android.cc +++ b/content/browser/renderer_host/input/fling_scheduler_android.cc
@@ -20,40 +20,33 @@ observed_window_->RemoveObserver(this); } -void FlingSchedulerAndroid::ScheduleFlingProgress() { +void FlingSchedulerAndroid::ScheduleFlingProgress( + base::WeakPtr<FlingController> fling_controller) { + DCHECK(fling_controller); + fling_controller_ = fling_controller; if (!observed_window_) { + ui::WindowAndroid* window = GetRootWindow(); // If the root window does not have a Compositor (happens on Android // WebView), we'll never receive an OnAnimate call. In this case fall back // to BeginFrames coming from the host. - host_->SetNeedsBeginFrameForFlingProgress(); - return; + if (!window || !window->GetCompositor()) { + host_->SetNeedsBeginFrameForFlingProgress(); + return; + } + window->AddObserver(this); + observed_window_ = window; } observed_window_->SetNeedsAnimate(); } -void FlingSchedulerAndroid::RegisterFlingSchedulerObserver( +void FlingSchedulerAndroid::DidStopFlingingOnBrowser( base::WeakPtr<FlingController> fling_controller) { DCHECK(fling_controller); - fling_controller_ = fling_controller; - - DCHECK(!observed_window_); - ui::WindowAndroid* window = GetRootWindow(); - if (!window || !window->GetCompositor()) - return; - - window->AddObserver(this); - observed_window_ = window; -} - -void FlingSchedulerAndroid::UnregisterFlingSchedulerObserver() { if (observed_window_) { observed_window_->RemoveObserver(this); observed_window_ = nullptr; } fling_controller_ = nullptr; -} - -void FlingSchedulerAndroid::DidStopFlingingOnBrowser() { host_->DidStopFlinging(); }
diff --git a/content/browser/renderer_host/input/fling_scheduler_android.h b/content/browser/renderer_host/input/fling_scheduler_android.h index f1b61e7..3b54e4e 100644 --- a/content/browser/renderer_host/input/fling_scheduler_android.h +++ b/content/browser/renderer_host/input/fling_scheduler_android.h
@@ -21,11 +21,10 @@ ~FlingSchedulerAndroid() override; // FlingControllerSchedulerClient - void ScheduleFlingProgress() override; - void RegisterFlingSchedulerObserver( + void ScheduleFlingProgress( base::WeakPtr<FlingController> fling_controller) override; - void UnregisterFlingSchedulerObserver() override; - void DidStopFlingingOnBrowser() override; + void DidStopFlingingOnBrowser( + base::WeakPtr<FlingController> fling_controller) override; bool NeedsBeginFrameForFlingProgress() override; // FlingSchedulerBase
diff --git a/content/browser/renderer_host/input/fling_scheduler_unittest.cc b/content/browser/renderer_host/input/fling_scheduler_unittest.cc index 3a29457..392cc8d 100644 --- a/content/browser/renderer_host/input/fling_scheduler_unittest.cc +++ b/content/browser/renderer_host/input/fling_scheduler_unittest.cc
@@ -18,13 +18,15 @@ public: FakeFlingScheduler(RenderWidgetHostImpl* host) : FlingScheduler(host) {} - void ScheduleFlingProgress() override { - FlingScheduler::ScheduleFlingProgress(); + void ScheduleFlingProgress( + base::WeakPtr<FlingController> fling_controller) override { + FlingScheduler::ScheduleFlingProgress(fling_controller); fling_in_progress_ = true; } - void DidStopFlingingOnBrowser() override { - FlingScheduler::DidStopFlingingOnBrowser(); + void DidStopFlingingOnBrowser( + base::WeakPtr<FlingController> fling_controller) override { + FlingScheduler::DidStopFlingingOnBrowser(fling_controller); fling_in_progress_ = false; } @@ -54,7 +56,6 @@ fling_scheduler_ = std::make_unique<FakeFlingScheduler>(widget_host_); fling_controller_ = std::make_unique<FlingController>( this, fling_scheduler_.get(), FlingController::Config()); - fling_controller_->RegisterFlingSchedulerObserver(); } void TearDown() override { @@ -103,12 +104,7 @@ void SendGeneratedWheelEvent( const MouseWheelEventWithLatencyInfo& wheel_event) override {} void SendGeneratedGestureScrollEvents( - const GestureEventWithLatencyInfo& gesture_event) override { - if (gesture_event.event.GetType() == - blink::WebInputEvent::kGestureScrollEnd) { - fling_controller_->UnregisterFlingSchedulerObserver(); - } - } + const GestureEventWithLatencyInfo& gesture_event) override {} std::unique_ptr<FlingController> fling_controller_; std::unique_ptr<FakeFlingScheduler> fling_scheduler_;
diff --git a/content/browser/renderer_host/input/gesture_event_queue.cc b/content/browser/renderer_host/input/gesture_event_queue.cc index e2fecd20..049f62fd 100644 --- a/content/browser/renderer_host/input/gesture_event_queue.cc +++ b/content/browser/renderer_host/input/gesture_event_queue.cc
@@ -153,12 +153,6 @@ DCHECK_NE(gesture_event.event.GetType(), WebInputEvent::kGestureFlingStart); DCHECK_NE(gesture_event.event.GetType(), WebInputEvent::kGestureFlingCancel); sent_events_awaiting_ack_.push_back(gesture_event); - if (gesture_event.event.GetType() == WebInputEvent::kGestureScrollBegin) { - fling_controller_.RegisterFlingSchedulerObserver(); - } else if (gesture_event.event.GetType() == - WebInputEvent::kGestureScrollEnd) { - fling_controller_.UnregisterFlingSchedulerObserver(); - } client_->SendGestureEventImmediately(gesture_event); }
diff --git a/content/browser/renderer_host/input/gesture_event_queue_unittest.cc b/content/browser/renderer_host/input/gesture_event_queue_unittest.cc index fb2da96..d8afcf8 100644 --- a/content/browser/renderer_host/input/gesture_event_queue_unittest.cc +++ b/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
@@ -96,15 +96,10 @@ const GestureEventWithLatencyInfo& gesture_event) override {} // FlingControllerSchedulerClient - void ScheduleFlingProgress() override {} - void DidStopFlingingOnBrowser() override {} - void RegisterFlingSchedulerObserver( - base::WeakPtr<FlingController> fling_controller) override { - fling_scheduler_observer_registered_ = true; - } - void UnregisterFlingSchedulerObserver() override { - fling_scheduler_observer_registered_ = false; - } + void ScheduleFlingProgress( + base::WeakPtr<FlingController> fling_controller) override {} + void DidStopFlingingOnBrowser( + base::WeakPtr<FlingController> fling_controller) override {} bool NeedsBeginFrameForFlingProgress() override { return false; } protected: @@ -186,10 +181,6 @@ SyntheticWebGestureEventBuilder::Build(type, sourceDevice))); } - bool fling_scheduler_observer_registered() const { - return fling_scheduler_observer_registered_; - } - unsigned GestureEventQueueSize() { return queue()->sent_events_awaiting_ack_.size(); } @@ -233,7 +224,6 @@ WebGestureEvent last_acked_event_; std::unique_ptr<InputEventAckState> sync_ack_result_; std::unique_ptr<WebGestureEvent> sync_followup_event_; - bool fling_scheduler_observer_registered_ = false; base::test::ScopedFeatureList feature_list_; }; @@ -493,17 +483,4 @@ EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); } -// Checks that the fling scheduler observer is regsitered/unregistered on -// GSB/GSE respectively. -TEST_F(GestureEventQueueWithCompositorEventQueueTest, - FlingSchedulerOpbserverRegisteredOnGSB) { - EXPECT_FALSE(fling_scheduler_observer_registered()); - SimulateGestureEvent(WebInputEvent::kGestureScrollBegin, - blink::kWebGestureDeviceTouchscreen); - EXPECT_TRUE(fling_scheduler_observer_registered()); - SimulateGestureEvent(WebInputEvent::kGestureScrollEnd, - blink::kWebGestureDeviceTouchscreen); - EXPECT_FALSE(fling_scheduler_observer_registered()); -} - } // namespace content
diff --git a/content/browser/renderer_host/input/mock_input_router_client.h b/content/browser/renderer_host/input/mock_input_router_client.h index 68c75c35..a9e5694 100644 --- a/content/browser/renderer_host/input/mock_input_router_client.h +++ b/content/browser/renderer_host/input/mock_input_router_client.h
@@ -67,11 +67,10 @@ } // FlingControllerSchedulerClient - void ScheduleFlingProgress() override {} - void DidStopFlingingOnBrowser() override {} - void RegisterFlingSchedulerObserver( + void ScheduleFlingProgress( base::WeakPtr<FlingController> fling_controller) override {} - void UnregisterFlingSchedulerObserver() override {} + void DidStopFlingingOnBrowser( + base::WeakPtr<FlingController> fling_controller) override {} bool NeedsBeginFrameForFlingProgress() override; private:
diff --git a/content/browser/renderer_host/input/touch_action_browsertest.cc b/content/browser/renderer_host/input/touch_action_browsertest.cc index 3bbc1d1..daf2a80 100644 --- a/content/browser/renderer_host/input/touch_action_browsertest.cc +++ b/content/browser/renderer_host/input/touch_action_browsertest.cc
@@ -431,9 +431,14 @@ scroll_left = GetScrollLeft(); } - // Expect it scrolled at least half of the expected distance. - EXPECT_LE(expected_scroll_position_after_scroll.y() / 2, scroll_top); - EXPECT_LE(expected_scroll_position_after_scroll.x() / 2, scroll_left); + // It seems that even if the compositor frame has scrolled half of the + // expected scroll offset, the Blink side scroll offset may not yet be + // updated, so here we expect it to at least have scrolled. + // TODO(crbug.com/902446): this can be resolved by fixing this bug. + if (expected_scroll_position_after_scroll.y() > 0) + EXPECT_GT(scroll_top, 0); + if (expected_scroll_position_after_scroll.x() > 0) + EXPECT_GT(scroll_left, 0); } const bool compositor_touch_action_enabled_;
diff --git a/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc b/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc index fc65765..33e7daf 100644 --- a/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc +++ b/content/browser/renderer_host/media/audio_output_authorization_handler_unittest.cc
@@ -18,9 +18,9 @@ #include "content/public/test/test_renderer_host.h" #include "media/audio/audio_device_description.h" #include "media/audio/audio_system_impl.h" -#include "media/audio/audio_thread_impl.h" #include "media/audio/fake_audio_log_factory.h" #include "media/audio/fake_audio_manager.h" +#include "media/audio/test_audio_thread.h" #include "media/base/media_switches.h" #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_test_util.h" @@ -103,7 +103,7 @@ RenderViewHostTestHarness::SetUp(); audio_manager_ = std::make_unique<media::FakeAudioManager>( - std::make_unique<media::AudioThreadImpl>(), &log_factory_); + std::make_unique<media::TestAudioThread>(true), &log_factory_); audio_system_ = std::make_unique<media::AudioSystemImpl>(audio_manager_.get()); media_stream_manager_ = std::make_unique<MediaStreamManager>(
diff --git a/content/browser/renderer_host/pepper/pepper_truetype_font_host.cc b/content/browser/renderer_host/pepper/pepper_truetype_font_host.cc index 6f4b48e..4e4b030 100644 --- a/content/browser/renderer_host/pepper/pepper_truetype_font_host.cc +++ b/content/browser/renderer_host/pepper/pepper_truetype_font_host.cc
@@ -45,14 +45,9 @@ } PepperTrueTypeFontHost::~PepperTrueTypeFontHost() { - if (font_.get()) { - // Release the font on the task runner in case the implementation requires - // long blocking operations. - font_->AddRef(); - PepperTrueTypeFont* raw_font = font_.get(); - font_ = nullptr; - task_runner_->ReleaseSoon(FROM_HERE, raw_font); - } + // Release the font on the task runner in case the implementation requires + // long blocking operations. + task_runner_->ReleaseSoon(FROM_HERE, std::move(font_)); } int32_t PepperTrueTypeFontHost::OnResourceMessageReceived(
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index b828a697..9839916 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -44,6 +44,7 @@ #include "base/metrics/user_metrics.h" #include "base/no_destructor.h" #include "base/numerics/ranges.h" +#include "base/numerics/safe_conversions.h" #include "base/process/process_handle.h" #include "base/rand_util.h" #include "base/single_thread_task_runner.h" @@ -1684,6 +1685,13 @@ << "RenderProcessHostImpl is destroyed by something other than itself"; #endif + if (render_frame_message_filter_) { + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::IO}, + base::BindOnce(&RenderFrameMessageFilter::ClearResourceContext, + render_frame_message_filter_)); + } + // Make sure to clean up the in-process renderer before the channel, otherwise // it may still run and have its IPCs fail, causing asserts. in_process_renderer_.reset(); @@ -1765,17 +1773,6 @@ std::move(service_request)); } -#if !defined(OS_MACOSX) - if (!BrowserMainLoop::GetInstance()->AudioServiceOutOfProcess()) { - DCHECK(BrowserMainLoop::GetInstance()->audio_manager()); - // Intentionally delay the hang monitor creation after the first renderer - // is created. On Mac audio thread is the UI thread, a hang monitor is not - // necessary or recommended. - media::AudioManager::StartHangMonitorIfNeeded( - base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO})); - } -#endif // !defined(OS_MACOSX) - #if defined(OS_ANDROID) // Initialize the java audio manager so that media session tests will pass. // See internal b/29872494. @@ -2256,20 +2253,15 @@ associated_registry->AddInterface(base::Bind( &RenderProcessHostImpl::CreateRendererHost, base::Unretained(this))); + // TODO(lukasza): https://crbug.com/891872: Stop vending out non-origin-bound + // URLLoaderFactories to the renderer process. if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { - // Using an opaque origin here should be safe - the URLLoaderFactory created - // for such origin shouldn't have any special privileges. - // - // TODO(lukasza): https://crbug.com/871827: Use the actual origin that will - // be used as |request_initiator|. The origin should come from the browser - // process. - const url::Origin kSafeOrigin = url::Origin(); - + const base::Optional<url::Origin> kNoOrigin = base::nullopt; AddUIThreadInterface( registry.get(), - base::Bind(&RenderProcessHostImpl::CreateURLLoaderFactory, - base::Unretained(this), kSafeOrigin, - nullptr /* header_client */)); + base::BindRepeating(&RenderProcessHostImpl::CreateURLLoaderFactory, + base::Unretained(this), kNoOrigin, + nullptr /* header_client */)); } registry->AddInterface( @@ -2530,7 +2522,7 @@ } void RenderProcessHostImpl::CreateURLLoaderFactory( - const url::Origin& origin, + const base::Optional<url::Origin>& origin, network::mojom::TrustedURLLoaderHeaderClientPtrInfo header_client, network::mojom::URLLoaderFactoryRequest request) { if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { @@ -2543,9 +2535,12 @@ network::mojom::NetworkContext* network_context = storage_partition_impl_->GetNetworkContext(); - network::mojom::URLLoaderFactoryPtrInfo embedder_provided_factory = - GetContentClient()->browser()->CreateURLLoaderFactoryForNetworkRequests( - this, network_context, &header_client, origin); + network::mojom::URLLoaderFactoryPtrInfo embedder_provided_factory; + if (origin.has_value()) { + embedder_provided_factory = + GetContentClient()->browser()->CreateURLLoaderFactoryForNetworkRequests( + this, network_context, &header_client, origin.value()); + } if (embedder_provided_factory) { mojo::FuseInterface(std::move(request), std::move(embedder_provided_factory)); @@ -2553,6 +2548,7 @@ network::mojom::URLLoaderFactoryParamsPtr params = network::mojom::URLLoaderFactoryParams::New(); params->process_id = GetID(); + params->request_initiator_site_lock = origin; params->disable_web_security = base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableWebSecurity); @@ -3626,13 +3622,14 @@ return stop_rtp_dump_callback_; } -void RenderProcessHostImpl::SetWebRtcEventLogOutput(int lid, bool enabled) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (enabled) { - Send(new PeerConnectionTracker_StartEventLogOutput(lid)); - } else { - Send(new PeerConnectionTracker_StopEventLog(lid)); - } +void RenderProcessHostImpl::EnableWebRtcEventLogOutput(int lid, + int output_period_ms) { + Send(new PeerConnectionTracker_StartEventLogOutput( + lid, base::saturated_cast<unsigned int>(output_period_ms))); +} + +void RenderProcessHostImpl::DisableWebRtcEventLogOutput(int lid) { + Send(new PeerConnectionTracker_StopEventLog(lid)); } IPC::ChannelProxy* RenderProcessHostImpl::GetChannel() {
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index 8b291548..f84fa02 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -199,7 +199,8 @@ bool incoming, bool outgoing, const WebRtcRtpPacketCallback& packet_callback) override; - void SetWebRtcEventLogOutput(int lid, bool enabled) override; + void EnableWebRtcEventLogOutput(int lid, int output_period_ms) override; + void DisableWebRtcEventLogOutput(int lid) override; void BindInterface(const std::string& interface_name, mojo::ScopedMessagePipeHandle interface_pipe) override; const service_manager::Identity& GetChildIdentity() const override; @@ -219,7 +220,7 @@ resource_coordinator::ProcessResourceCoordinator* GetProcessResourceCoordinator() override; void CreateURLLoaderFactory( - const url::Origin& origin, + const base::Optional<url::Origin>& origin, network::mojom::TrustedURLLoaderHeaderClientPtrInfo header_client, network::mojom::URLLoaderFactoryRequest request) override;
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index a62cb0c..1a9083d9 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -474,9 +474,6 @@ switches::autoplay::kUserGestureRequiredPolicy) { prefs.autoplay_policy = AutoplayPolicy::kUserGestureRequired; } else if (autoplay_policy == - switches::autoplay::kUserGestureRequiredForCrossOriginPolicy) { - prefs.autoplay_policy = AutoplayPolicy::kUserGestureRequiredForCrossOrigin; - } else if (autoplay_policy == switches::autoplay::kDocumentUserActivationRequiredPolicy) { prefs.autoplay_policy = AutoplayPolicy::kDocumentUserActivationRequired; } else {
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 130e988..69f3b6a 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -525,7 +525,7 @@ void DidReceiveRendererFrame(); - // Don't check whether we expected a resize ack during layout tests. + // Don't check whether we expected a resize ack during web tests. static void DisableResizeAckCheckForTesting(); InputRouter* input_router() { return input_router_.get(); }
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index 205856fb..575ff95 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -908,7 +908,7 @@ std::move(callback), start_time)); } -void RenderWidgetHostViewAndroid::EnsureSurfaceSynchronizedForLayoutTest() { +void RenderWidgetHostViewAndroid::EnsureSurfaceSynchronizedForWebTest() { ++latest_capture_sequence_number_; SynchronizeVisualProperties(cc::DeadlinePolicy::UseInfiniteDeadline(), base::nullopt);
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h index a1ccad9..a70fe2f9 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.h +++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -117,7 +117,7 @@ const gfx::Rect& src_rect, const gfx::Size& output_size, base::OnceCallback<void(const SkBitmap&)> callback) override; - void EnsureSurfaceSynchronizedForLayoutTest() override; + void EnsureSurfaceSynchronizedForWebTest() override; uint32_t GetCaptureSequenceNumber() const override; bool DoBrowserControlsShrinkRendererSize() const override; float GetTopControlsHeight() const override;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 45fa0246..caa00ceb 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -397,7 +397,7 @@ RenderViewHost* rvh = RenderViewHost::From(host()); if (rvh) { // TODO(mostynb): actually use prefs. Landing this as a separate CL - // first to rebaseline some unreliable layout tests. + // first to rebaseline some unreliable web tests. ignore_result(rvh->GetWebkitPreferences()); } } @@ -655,7 +655,7 @@ return delegated_frame_host_->CanCopyFromCompositingSurface(); } -void RenderWidgetHostViewAura::EnsureSurfaceSynchronizedForLayoutTest() { +void RenderWidgetHostViewAura::EnsureSurfaceSynchronizedForWebTest() { ++latest_capture_sequence_number_; SynchronizeVisualProperties(cc::DeadlinePolicy::UseInfiniteDeadline(), base::nullopt);
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index df797fe..e719fb1 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -144,7 +144,7 @@ const gfx::Rect& src_rect, const gfx::Size& output_size, base::OnceCallback<void(const SkBitmap&)> callback) override; - void EnsureSurfaceSynchronizedForLayoutTest() override; + void EnsureSurfaceSynchronizedForWebTest() override; void TransformPointToRootSurface(gfx::PointF* point) override; gfx::Rect GetBoundsInRootWindow() override; void WheelEventAck(const blink::WebMouseWheelEvent& event, @@ -681,7 +681,7 @@ // Latest capture sequence number which is incremented when the caller // requests surfaces be synchronized via - // EnsureSurfaceSynchronizedForLayoutTest(). + // EnsureSurfaceSynchronizedForWebTest(). uint32_t latest_capture_sequence_number_ = 0u; // The pointer type of the most recent gesture/mouse/touch event.
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc index 7d101bd0..2d5f670 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -234,7 +234,7 @@ return GetLocalSurfaceIdAllocation().IsValid(); } -void RenderWidgetHostViewChildFrame::EnsureSurfaceSynchronizedForLayoutTest() { +void RenderWidgetHostViewChildFrame::EnsureSurfaceSynchronizedForWebTest() { // The capture sequence number which would normally be updated here is // actually retrieved from the frame connector. }
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.h b/content/browser/renderer_host/render_widget_host_view_child_frame.h index d73fc816..46b12ab 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame.h +++ b/content/browser/renderer_host/render_widget_host_view_child_frame.h
@@ -93,7 +93,7 @@ const gfx::Rect& src_rect, const gfx::Size& output_size, base::OnceCallback<void(const SkBitmap&)> callback) override; - void EnsureSurfaceSynchronizedForLayoutTest() override; + void EnsureSurfaceSynchronizedForWebTest() override; uint32_t GetCaptureSequenceNumber() const override; void Show() override; void Hide() override;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 6e0f4971..cadea70 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -139,7 +139,7 @@ const gfx::Rect& src_rect, const gfx::Size& output_size, base::OnceCallback<void(const SkBitmap&)> callback) override; - void EnsureSurfaceSynchronizedForLayoutTest() override; + void EnsureSurfaceSynchronizedForWebTest() override; void FocusedNodeChanged(bool is_editable_node, const gfx::Rect& node_bounds_in_screen) override; void DidCreateNewRendererCompositorFrameSink( @@ -629,7 +629,7 @@ // Latest capture sequence number which is incremented when the caller // requests surfaces be synchronized via - // EnsureSurfaceSynchronizedForLayoutTest(). + // EnsureSurfaceSynchronizedForWebTest(). uint32_t latest_capture_sequence_number_ = 0u; // Remote accessibility objects corresponding to the NSWindow and its root
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index 86e898d4..d3a86ca07 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -217,7 +217,7 @@ if (rvh) { // TODO(mostynb): actually use prefs. Landing this as a separate CL - // first to rebaseline some unreliable layout tests. + // first to rebaseline some unreliable web tests. ignore_result(rvh->GetWebkitPreferences()); needs_begin_frames = !rvh->GetDelegate()->IsNeverVisible(); } @@ -853,7 +853,7 @@ std::move(callback)); } -void RenderWidgetHostViewMac::EnsureSurfaceSynchronizedForLayoutTest() { +void RenderWidgetHostViewMac::EnsureSurfaceSynchronizedForWebTest() { ++latest_capture_sequence_number_; browser_compositor_->ForceNewSurfaceId(); }
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm index 8286606..ed58d5a 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -1305,7 +1305,7 @@ // event gets dispatched. base::RunLoop run_loop; base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, run_loop.QuitClosure(), + FROM_HERE, run_loop.QuitWhenIdleClosure(), base::TimeDelta::FromMilliseconds(100)); run_loop.Run();
diff --git a/content/browser/renderer_host/web_database_host_impl.cc b/content/browser/renderer_host/web_database_host_impl.cc index 65af343..79a390e 100644 --- a/content/browser/renderer_host/web_database_host_impl.cc +++ b/content/browser/renderer_host/web_database_host_impl.cc
@@ -7,6 +7,7 @@ #include <string> #include <utility> +#include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" @@ -36,6 +37,26 @@ const int kNumDeleteRetries = 2; // The delay between each retry to delete the SQLite database. const int kDelayDeleteRetryMs = 100; + +void ValidateOriginOnUIThread( + int process_id, + const url::Origin& origin, + scoped_refptr<base::SequencedTaskRunner> callback_task_runner, + base::OnceClosure success_callback, + mojo::ReportBadMessageCallback error_callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanAccessDataForOrigin( + process_id, origin.GetURL())) { + callback_task_runner->PostTask( + FROM_HERE, + base::BindOnce(std::move(error_callback), "Unauthorized origin.")); + return; + } + + callback_task_runner->PostTask(FROM_HERE, std::move(success_callback)); +} + } // namespace WebDatabaseHostImpl::WebDatabaseHostImpl( @@ -43,7 +64,8 @@ scoped_refptr<storage::DatabaseTracker> db_tracker) : process_id_(process_id), observer_added_(false), - db_tracker_(std::move(db_tracker)) { + db_tracker_(std::move(db_tracker)), + weak_ptr_factory_(this) { DCHECK(db_tracker_); } @@ -74,8 +96,16 @@ int32_t desired_flags, OpenFileCallback callback) { DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); - if (!ValidateOrigin(vfs_file_name)) - return; + ValidateOrigin(vfs_file_name, + base::BindOnce(&WebDatabaseHostImpl::OpenFileValidated, + weak_ptr_factory_.GetWeakPtr(), vfs_file_name, + desired_flags, std::move(callback))); +} + +void WebDatabaseHostImpl::OpenFileValidated(const base::string16& vfs_file_name, + int32_t desired_flags, + OpenFileCallback callback) { + DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); base::File file; const base::File* tracked_file = nullptr; @@ -127,19 +157,28 @@ bool sync_dir, DeleteFileCallback callback) { DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); - if (!ValidateOrigin(vfs_file_name)) - return; - - DatabaseDeleteFile(vfs_file_name, sync_dir, std::move(callback), - kNumDeleteRetries); + ValidateOrigin( + vfs_file_name, + base::BindOnce(&WebDatabaseHostImpl::DatabaseDeleteFile, + weak_ptr_factory_.GetWeakPtr(), vfs_file_name, sync_dir, + std::move(callback), kNumDeleteRetries)); } void WebDatabaseHostImpl::GetFileAttributes( const base::string16& vfs_file_name, GetFileAttributesCallback callback) { DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); - if (!ValidateOrigin(vfs_file_name)) - return; + ValidateOrigin( + vfs_file_name, + base::BindOnce(&WebDatabaseHostImpl::GetFileAttributesValidated, + weak_ptr_factory_.GetWeakPtr(), vfs_file_name, + std::move(callback))); +} + +void WebDatabaseHostImpl::GetFileAttributesValidated( + const base::string16& vfs_file_name, + GetFileAttributesCallback callback) { + DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); int32_t attributes = -1; base::FilePath db_file = @@ -153,8 +192,16 @@ void WebDatabaseHostImpl::GetFileSize(const base::string16& vfs_file_name, GetFileSizeCallback callback) { DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); - if (!ValidateOrigin(vfs_file_name)) - return; + ValidateOrigin(vfs_file_name, + base::BindOnce(&WebDatabaseHostImpl::GetFileSizeValidated, + weak_ptr_factory_.GetWeakPtr(), vfs_file_name, + std::move(callback))); +} + +void WebDatabaseHostImpl::GetFileSizeValidated( + const base::string16& vfs_file_name, + GetFileSizeCallback callback) { + DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); int64_t size = 0LL; base::FilePath db_file = @@ -169,9 +216,17 @@ int64_t expected_size, SetFileSizeCallback callback) { DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); - if (!ValidateOrigin(vfs_file_name)) - return; + ValidateOrigin(vfs_file_name, + base::BindOnce(&WebDatabaseHostImpl::SetFileSizeValidated, + weak_ptr_factory_.GetWeakPtr(), vfs_file_name, + expected_size, std::move(callback))); +} +void WebDatabaseHostImpl::SetFileSizeValidated( + const base::string16& vfs_file_name, + int64_t expected_size, + SetFileSizeCallback callback) { + DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); bool success = false; base::FilePath db_file = DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_.get(), vfs_file_name); @@ -187,9 +242,17 @@ // QuotaManager is only available on the IO thread. DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); - if (!ValidateOrigin(origin)) { - return; - } + ValidateOrigin( + origin, base::BindOnce(&WebDatabaseHostImpl::GetSpaceAvailableValidated, + weak_ptr_factory_.GetWeakPtr(), origin, + std::move(callback))); +} + +void WebDatabaseHostImpl::GetSpaceAvailableValidated( + const url::Origin& origin, + GetSpaceAvailableCallback callback) { + // QuotaManager is only available on the IO thread. + DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); DCHECK(db_tracker_->quota_manager_proxy()); db_tracker_->quota_manager_proxy()->GetUsageAndQuota( @@ -246,8 +309,8 @@ db_tracker_->task_runner()->PostDelayedTask( FROM_HERE, base::BindOnce(&WebDatabaseHostImpl::DatabaseDeleteFile, - base::Unretained(this), vfs_file_name, sync_dir, - std::move(callback), reschedule_count - 1), + weak_ptr_factory_.GetWeakPtr(), vfs_file_name, + sync_dir, std::move(callback), reschedule_count - 1), base::TimeDelta::FromMilliseconds(kDelayDeleteRetryMs)); return; } @@ -267,9 +330,18 @@ db_tracker_->AddObserver(this); } - if (!ValidateOrigin(origin)) { - return; - } + ValidateOrigin(origin, base::BindOnce(&WebDatabaseHostImpl::OpenedValidated, + weak_ptr_factory_.GetWeakPtr(), origin, + database_name, database_description, + estimated_size)); +} + +void WebDatabaseHostImpl::OpenedValidated( + const url::Origin& origin, + const base::string16& database_name, + const base::string16& database_description, + int64_t estimated_size) { + DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); UMA_HISTOGRAM_BOOLEAN("websql.OpenDatabase", IsOriginSecure(origin.GetURL())); @@ -288,10 +360,15 @@ const base::string16& database_name) { DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); - if (!ValidateOrigin(origin)) { - return; - } + ValidateOrigin(origin, base::BindOnce(&WebDatabaseHostImpl::ModifiedValidated, + weak_ptr_factory_.GetWeakPtr(), origin, + database_name)); +} +void WebDatabaseHostImpl::ModifiedValidated( + const url::Origin& origin, + const base::string16& database_name) { + DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); std::string origin_identifier(storage::GetIdentifierFromOrigin(origin)); if (!database_connections_.IsDatabaseOpened(origin_identifier, database_name)) { @@ -306,9 +383,14 @@ const base::string16& database_name) { DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); - if (!ValidateOrigin(origin)) { - return; - } + ValidateOrigin(origin, base::BindOnce(&WebDatabaseHostImpl::ClosedValidated, + weak_ptr_factory_.GetWeakPtr(), origin, + database_name)); +} + +void WebDatabaseHostImpl::ClosedValidated(const url::Origin& origin, + const base::string16& database_name) { + DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); std::string origin_identifier(storage::GetIdentifierFromOrigin(origin)); if (!database_connections_.IsDatabaseOpened(origin_identifier, @@ -325,12 +407,11 @@ const base::string16& database_name, int32_t error) { DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence()); - if (!ValidateOrigin(origin)) { - return; - } - - db_tracker_->HandleSqliteError(storage::GetIdentifierFromOrigin(origin), - database_name, error); + ValidateOrigin( + origin, + base::BindOnce(&storage::DatabaseTracker::HandleSqliteError, db_tracker_, + storage::GetIdentifierFromOrigin(origin), database_name, + error)); } void WebDatabaseHostImpl::OnDatabaseSizeChanged( @@ -375,37 +456,36 @@ return *database_provider_; } -bool WebDatabaseHostImpl::ValidateOrigin(const url::Origin& origin) { +void WebDatabaseHostImpl::ValidateOrigin(const url::Origin& origin, + base::OnceClosure callback) { if (origin.opaque()) { mojo::ReportBadMessage("Invalid origin."); - return false; + return; } - if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanAccessDataForOrigin( - process_id_, origin.GetURL())) { - mojo::ReportBadMessage("Unauthorized origin."); - return false; - } - return true; + base::PostTaskWithTraits( + FROM_HERE, {BrowserThread::UI}, + base::BindOnce(&ValidateOriginOnUIThread, process_id_, origin, + base::RetainedRef(db_tracker_->task_runner()), + std::move(callback), mojo::GetBadMessageCallback())); } -bool WebDatabaseHostImpl::ValidateOrigin(const base::string16& vfs_file_name) { +void WebDatabaseHostImpl::ValidateOrigin(const base::string16& vfs_file_name, + base::OnceClosure callback) { std::string origin_identifier; - if (vfs_file_name.empty()) - return true; + if (vfs_file_name.empty()) { + std::move(callback).Run(); + return; + } if (!DatabaseUtil::CrackVfsFileName(vfs_file_name, &origin_identifier, nullptr, nullptr)) { - return true; + std::move(callback).Run(); + return; } - if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanAccessDataForOrigin( - process_id_, - storage::GetOriginURLFromIdentifier(origin_identifier))) { - mojo::ReportBadMessage("Unauthorized origin."); - return false; - } - return true; + ValidateOrigin(storage::GetOriginFromIdentifier(origin_identifier), + std::move(callback)); } } // namespace content
diff --git a/content/browser/renderer_host/web_database_host_impl.h b/content/browser/renderer_host/web_database_host_impl.h index c57d2fc..2affca7 100644 --- a/content/browser/renderer_host/web_database_host_impl.h +++ b/content/browser/renderer_host/web_database_host_impl.h
@@ -7,6 +7,7 @@ #include <string> +#include "base/callback_forward.h" #include "base/strings/string16.h" #include "build/build_config.h" #include "mojo/public/cpp/bindings/binding.h" @@ -90,17 +91,50 @@ // exist. blink::mojom::WebDatabase& GetWebDatabase(); - // Check that an IPC call has permission to access the passed origin. Must - // be called from within the context of a mojo call. Invalid calls will - // report a bad message, which will terminate the calling process. If this - // returns false, the caller should return immediately without invoking - // callbacks. - bool ValidateOrigin(const url::Origin& origin); + // blink::mojom::WebDatabaseHost methods called after ValidateOrigin() + // successfully validates the origin. + void OpenFileValidated(const base::string16& vfs_file_name, + int32_t desired_flags, + OpenFileCallback callback); + + void GetFileAttributesValidated(const base::string16& vfs_file_name, + GetFileAttributesCallback callback); + + void GetFileSizeValidated(const base::string16& vfs_file_name, + GetFileSizeCallback callback); + + void SetFileSizeValidated(const base::string16& vfs_file_name, + int64_t expected_size, + SetFileSizeCallback callback); + + void GetSpaceAvailableValidated(const url::Origin& origin, + GetSpaceAvailableCallback callback); + + void OpenedValidated(const url::Origin& origin, + const base::string16& database_name, + const base::string16& database_description, + int64_t estimated_size); + + void ModifiedValidated(const url::Origin& origin, + const base::string16& database_name); + + void ClosedValidated(const url::Origin& origin, + const base::string16& database_name); + + void HandleSqliteErrorValidated(const url::Origin& origin, + const base::string16& database_name, + int32_t error); + + // Asynchronously calls |callback| but only if |process_id_| has permission to + // access the passed |origin|. Must be called from within the context of a + // mojo call. Invalid calls will report a bad message, which will terminate + // the calling process. + void ValidateOrigin(const url::Origin& origin, base::OnceClosure callback); // As above, but for calls where the origin is embedded in a VFS filename. // Empty filenames signalling a temp file are permitted. - bool ValidateOrigin(const base::string16& vfs_file_name); - + void ValidateOrigin(const base::string16& vfs_file_name, + base::OnceClosure callback); // Our render process host ID, used to bind to the correct render process. const int process_id_; @@ -116,6 +150,10 @@ // The database tracker for the current browser context. const scoped_refptr<storage::DatabaseTracker> db_tracker_; + + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<WebDatabaseHostImpl> weak_ptr_factory_; }; } // namespace content
diff --git a/content/browser/renderer_host/web_database_host_impl_unittest.cc b/content/browser/renderer_host/web_database_host_impl_unittest.cc index c469547..af9cd542 100644 --- a/content/browser/renderer_host/web_database_host_impl_unittest.cc +++ b/content/browser/renderer_host/web_database_host_impl_unittest.cc
@@ -4,6 +4,7 @@ #include "content/browser/renderer_host/web_database_host_impl.h" +#include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "content/browser/child_process_security_policy_impl.h" #include "content/public/test/test_browser_thread_bundle.h" @@ -35,14 +36,24 @@ mojo::core::ProcessErrorCallback()); } - const std::string& last_error() const { return last_error_; } + const std::string& WaitForError() { + if (last_error_.empty()) + run_loop_.Run(); + + return last_error_; + } private: - void ReportBadMessage(const std::string& error) { last_error_ = error; } + void ReportBadMessage(const std::string& error) { + DCHECK(!error.empty()); + last_error_ = error; + run_loop_.Quit(); + } mojo::Message dummy_message_; mojo::internal::MessageDispatchContext context_; std::string last_error_; + base::RunLoop run_loop_; DISALLOW_COPY_AND_ASSIGN(BadMessageObserver); }; @@ -70,14 +81,14 @@ void CheckUnauthorizedOrigin(const Callable& func) { BadMessageObserver bad_message_observer; func(); - EXPECT_EQ("Unauthorized origin.", bad_message_observer.last_error()); + EXPECT_EQ("Unauthorized origin.", bad_message_observer.WaitForError()); } template <typename Callable> void CheckInvalidOrigin(const Callable& func) { BadMessageObserver bad_message_observer; func(); - EXPECT_EQ("Invalid origin.", bad_message_observer.last_error()); + EXPECT_EQ("Invalid origin.", bad_message_observer.WaitForError()); } WebDatabaseHostImpl* host() { return host_.get(); }
diff --git a/content/browser/screen_orientation/screen_orientation_browsertest.cc b/content/browser/screen_orientation/screen_orientation_browsertest.cc index be616484..9bbdb96 100644 --- a/content/browser/screen_orientation/screen_orientation_browsertest.cc +++ b/content/browser/screen_orientation/screen_orientation_browsertest.cc
@@ -241,7 +241,7 @@ // Check that using screen orientation after a frame is detached doesn't crash // the renderer process. -// This could be a LayoutTest if they were not using a mock screen orientation +// This could be a web test if they were not using a mock screen orientation // controller. IN_PROC_BROWSER_TEST_F(ScreenOrientationBrowserTest, CrashTest_UseAfterDetach) { GURL test_url = GetTestUrl("screen_orientation",
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc index d27cbf4..994565847 100644 --- a/content/browser/service_worker/service_worker_browsertest.cc +++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -2791,7 +2791,7 @@ // meant to test an internal quirk of MimeSniffingResourceHandler, which // might not make sense in the NetworkService implementation anyway. If we // want a behavior test for MIME sniffing for navigation preload, it can be - // an end-to-end layout test instead. + // an end-to-end web test instead. // This has to be called so the EmbeddedTestServer IO Thread is created, // otherwise we crash on destruction. @@ -3190,10 +3190,12 @@ } void OpenCacheOnIOThread(int* result, base::OnceClosure continuation) { - cache_storage_context_->cache_manager()->OpenCache( - url::Origin::Create(origin_), CacheStorageOwner::kCacheAPI, cache_name_, - base::BindOnce(&self::OnCacheStorageOpenCallback, this, result, - std::move(continuation))); + CacheStorageHandle cache_storage = + cache_storage_context_->cache_manager()->OpenCacheStorage( + url::Origin::Create(origin_), CacheStorageOwner::kCacheAPI); + cache_storage.value()->OpenCache( + cache_name_, base::BindOnce(&self::OnCacheStorageOpenCallback, this, + result, std::move(continuation))); } void OnCacheStorageOpenCallback(int* result,
diff --git a/content/browser/service_worker/service_worker_navigation_loader.cc b/content/browser/service_worker/service_worker_navigation_loader.cc index 83081f2..83f69a09 100644 --- a/content/browser/service_worker/service_worker_navigation_loader.cc +++ b/content/browser/service_worker/service_worker_navigation_loader.cc
@@ -600,9 +600,9 @@ fetch_event_timing_->respond_with_settled_time); // Time spent reading response body. - UMA_HISTOGRAM_TIMES( + UMA_HISTOGRAM_MEDIUM_TIMES( "ServiceWorker.LoadTiming.MainFrame.MainResource." - "ResponseReceivedToCompleted", + "ResponseReceivedToCompleted2", completion_time_ - response_head_.load_timing.receive_headers_end); } else { // Renderer -> Browser IPC delay (network fallback case).
diff --git a/content/browser/service_worker/service_worker_navigation_loader_unittest.cc b/content/browser/service_worker/service_worker_navigation_loader_unittest.cc index a916ddcc..60fa7c7 100644 --- a/content/browser/service_worker/service_worker_navigation_loader_unittest.cc +++ b/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
@@ -624,7 +624,7 @@ blink::ServiceWorkerStatusCode::kOk, 1); histogram_tester.ExpectTotalCount( "ServiceWorker.LoadTiming.MainFrame.MainResource." - "ResponseReceivedToCompleted", + "ResponseReceivedToCompleted2", 1); } @@ -709,7 +709,7 @@ // Test histogram of reading body. histogram_tester.ExpectTotalCount( "ServiceWorker.LoadTiming.MainFrame.MainResource." - "ResponseReceivedToCompleted", + "ResponseReceivedToCompleted2", 1); } @@ -751,7 +751,7 @@ 0); histogram_tester.ExpectTotalCount( "ServiceWorker.LoadTiming.MainFrame.MainResource." - "ResponseReceivedToCompleted", + "ResponseReceivedToCompleted2", 0); } @@ -798,7 +798,7 @@ // Test histogram of reading body. histogram_tester.ExpectTotalCount( "ServiceWorker.LoadTiming.MainFrame.MainResource." - "ResponseReceivedToCompleted", + "ResponseReceivedToCompleted2", 1); } @@ -848,7 +848,7 @@ 0); histogram_tester.ExpectTotalCount( "ServiceWorker.LoadTiming.MainFrame.MainResource." - "ResponseReceivedToCompleted", + "ResponseReceivedToCompleted2", 0); } @@ -905,7 +905,7 @@ 0); histogram_tester.ExpectTotalCount( "ServiceWorker.LoadTiming.MainFrame.MainResource." - "ResponseReceivedToCompleted", + "ResponseReceivedToCompleted2", 0); }
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index fcb879a..e3e9f53f1 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -85,9 +85,6 @@ namespace { -// Only used when the network service is enabled. -bool g_allow_get_url_request_context = false; - base::LazyInstance<StoragePartitionImpl::CreateNetworkFactoryCallback>::Leaky g_url_loader_factory_callback_for_test = LAZY_INSTANCE_INITIALIZER; @@ -258,20 +255,6 @@ } // namespace -ScopedAllowGetURLRequestContext::ScopedAllowGetURLRequestContext() { - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) - return; - DCHECK(!g_allow_get_url_request_context); - g_allow_get_url_request_context = true; -} - -ScopedAllowGetURLRequestContext::~ScopedAllowGetURLRequestContext() { - if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) - return; - DCHECK(g_allow_get_url_request_context); - g_allow_get_url_request_context = false; -} - // Class to own the NetworkContext wrapping a storage partitions // URLRequestContext, when the ContentBrowserClient doesn't provide a // NetworkContext itself. @@ -768,7 +751,7 @@ #if defined(OS_WIN) || defined(OS_MACOSX) || \ (defined(OS_LINUX) && !defined(OS_CHROMEOS)) if (base::FeatureList::IsEnabled(network::features::kNetworkService)) - DCHECK(g_allow_get_url_request_context); + NOTREACHED(); #endif return url_request_context_.get(); } @@ -778,7 +761,7 @@ #if defined(OS_WIN) || defined(OS_MACOSX) || \ (defined(OS_LINUX) && !defined(OS_CHROMEOS)) if (base::FeatureList::IsEnabled(network::features::kNetworkService)) - DCHECK(g_allow_get_url_request_context); + NOTREACHED(); #endif return media_url_request_context_.get(); }
diff --git a/content/browser/wake_lock/wake_lock_service_impl.cc b/content/browser/wake_lock/wake_lock_service_impl.cc new file mode 100644 index 0000000..9754f887 --- /dev/null +++ b/content/browser/wake_lock/wake_lock_service_impl.cc
@@ -0,0 +1,37 @@ +// 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/browser/wake_lock/wake_lock_service_impl.h" + +#include "content/public/browser/web_contents.h" +#include "services/device/public/mojom/wake_lock_context.mojom.h" + +namespace content { + +// static +void WakeLockServiceImpl::Create(RenderFrameHost* render_frame_host, + blink::mojom::WakeLockServiceRequest request) { + DCHECK(render_frame_host); + new WakeLockServiceImpl(render_frame_host, std::move(request)); +} + +void WakeLockServiceImpl::GetWakeLock(device::mojom::WakeLockType type, + device::mojom::WakeLockReason reason, + const std::string& description, + device::mojom::WakeLockRequest request) { + device::mojom::WakeLockContext* wake_lock_context = + web_contents()->GetWakeLockContext(); + + if (!wake_lock_context) + return; + + wake_lock_context->GetWakeLock(type, reason, description, std::move(request)); +} + +WakeLockServiceImpl::WakeLockServiceImpl( + RenderFrameHost* render_frame_host, + blink::mojom::WakeLockServiceRequest request) + : FrameServiceBase(render_frame_host, std::move(request)) {} + +} // namespace content
diff --git a/content/browser/wake_lock/wake_lock_service_impl.h b/content/browser/wake_lock/wake_lock_service_impl.h new file mode 100644 index 0000000..1aee032 --- /dev/null +++ b/content/browser/wake_lock/wake_lock_service_impl.h
@@ -0,0 +1,32 @@ +// 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_BROWSER_WAKE_LOCK_WAKE_LOCK_SERVICE_IMPL_H_ +#define CONTENT_BROWSER_WAKE_LOCK_WAKE_LOCK_SERVICE_IMPL_H_ + +#include "content/public/browser/frame_service_base.h" +#include "third_party/blink/public/mojom/wake_lock/wake_lock.mojom.h" + +namespace content { + +class WakeLockServiceImpl final + : public FrameServiceBase<blink::mojom::WakeLockService> { + public: + static void Create(RenderFrameHost*, blink::mojom::WakeLockServiceRequest); + + // WakeLockService implementation. + void GetWakeLock(device::mojom::WakeLockType, + device::mojom::WakeLockReason, + const std::string&, + device::mojom::WakeLockRequest) final; + + private: + WakeLockServiceImpl(RenderFrameHost*, blink::mojom::WakeLockServiceRequest); + + DISALLOW_COPY_AND_ASSIGN(WakeLockServiceImpl); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_WAKE_LOCK_WAKE_LOCK_SERVICE_IMPL_H_
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 1b57097..ef41fbd 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2811,6 +2811,8 @@ new_contents_impl->delayed_load_url_params_ = std::move(load_params); } else { new_contents_impl->controller_.LoadURLWithParams(*load_params.get()); + if (!is_guest) + new_contents_impl->Focus(); } } } @@ -4100,28 +4102,9 @@ } bool WebContentsImpl::FocusLocationBarByDefault() { - // When the browser is started with about:blank as the startup URL, focus - // the location bar (which will also select its contents) so people can - // simply begin typing to navigate elsewhere. - // - // We need to be careful not to trigger this for anything other than the - // startup navigation. In particular, if we allow an attacker to open a - // popup to about:blank, then navigate, focusing the Omnibox will cause the - // end of the new URL to be scrolled into view instead of the start, - // allowing the attacker to spoof other URLs. The conditions checked here - // are all aimed at ensuring no such attacker-controlled navigation can - // trigger this. - // - // Note that we check the pending entry instead of the visible one; for the - // startup URL case these are the same, but for the attacker-controlled - // navigation case the visible entry is the committed "about:blank" URL and - // the pending entry is the problematic navigation elsewhere. - NavigationEntryImpl* entry = controller_.GetPendingEntry(); - if (controller_.IsInitialNavigation() && entry && - !entry->is_renderer_initiated() && - entry->GetURL() == url::kAboutBlankURL) { + if (should_focus_location_bar_by_default_) return true; - } + return delegate_ && delegate_->ShouldFocusLocationBarByDefault(this); } @@ -4138,6 +4121,24 @@ if (display_cutout_host_impl_) display_cutout_host_impl_->DidStartNavigation(navigation_handle); + + if (navigation_handle->IsInMainFrame()) { + // When the browser is started with about:blank as the startup URL, focus + // the location bar (which will also select its contents) so people can + // simply begin typing to navigate elsewhere. + // + // We need to be careful not to trigger this for anything other than the + // startup navigation. In particular, if we allow an attacker to open a + // popup to about:blank, then navigate, focusing the Omnibox will cause the + // end of the new URL to be scrolled into view instead of the start, + // allowing the attacker to spoof other URLs. The conditions checked here + // are all aimed at ensuring no such attacker-controlled navigation can + // trigger this. + should_focus_location_bar_by_default_ = + controller_.IsInitialNavigation() && + !navigation_handle->IsRendererInitiated() && + navigation_handle->GetURL() == url::kAboutBlankURL; + } } void WebContentsImpl::DidRedirectNavigation( @@ -4233,6 +4234,13 @@ ukm::SourceIdType::NAVIGATION_ID); } } + + // If we didn't end up on about:blank after setting this in DidStartNavigation + // then don't focus the location bar. + if (should_focus_location_bar_by_default_ && + navigation_handle->GetURL() != url::kAboutBlankURL) { + should_focus_location_bar_by_default_ = false; + } } void WebContentsImpl::DidFailLoadWithError( @@ -5614,6 +5622,10 @@ LoadingStateChanged(frame_tree_node->IsMainFrame() && to_different_document, false, nullptr); + // Reset the focus state from DidStartNavigation to false if a new load starts + // afterward, in case loading logic triggers a FocusLocationBarByDefault call. + should_focus_location_bar_by_default_ = false; + // Notify accessibility that the user is navigating away from the // current document. //
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 010d9c9c..5a30b357 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -1810,6 +1810,11 @@ // Store the frame that is currently fullscreen, nullptr if there is none. RenderFrameHostImpl* current_fullscreen_frame_ = nullptr; + // Whether location bar should be focused by default. This is computed in + // DidStartNavigation/DidFinishNavigation and only set for an initial + // navigation triggered by the browser going to about:blank. + bool should_focus_location_bar_by_default_ = false; + base::WeakPtrFactory<WebContentsImpl> loading_weak_factory_; base::WeakPtrFactory<WebContentsImpl> weak_factory_;
diff --git a/content/browser/webauth/authenticator_impl.cc b/content/browser/webauth/authenticator_impl.cc index 62827143..29a7796 100644 --- a/content/browser/webauth/authenticator_impl.cc +++ b/content/browser/webauth/authenticator_impl.cc
@@ -1111,7 +1111,7 @@ request_delegate_->DidFailWithInterestingReason( AuthenticatorRequestClientDelegate::InterestingFailureReason::kTimeout); - // TODO(crbug.com/814418): Add layout tests to verify timeouts are + // TODO(crbug.com/814418): Add web tests to verify timeouts are // indistinguishable from NOT_ALLOWED_ERROR cases. FailWithNotAllowedErrorAndCleanup(); }
diff --git a/content/browser/webkit_browsertest.cc b/content/browser/webkit_browsertest.cc index 8b2b69a..af8c94f83 100644 --- a/content/browser/webkit_browsertest.cc +++ b/content/browser/webkit_browsertest.cc
@@ -53,7 +53,7 @@ using WebKitBrowserTest = ContentBrowserTest; // This is a browser test because it is hard to reproduce reliably in a -// layout test without races. http://crbug.com/75604 deals with a request +// web test without races. http://crbug.com/75604 deals with a request // for an async script which gets data in the response and immediately // after aborts. This test creates that condition, and it is passed // if chrome does not crash. @@ -77,7 +77,7 @@ // destroying the Document, so it is not a use after free unless // you don't have test_runner loaded. -// TODO(gavinp): remove this browser_test if we can get good LayoutTest +// TODO(gavinp): remove this browser_test if we can get good web test // coverage of the same issue. const char kXsltBadImportPage[] = "/webkit/xslt-bad-import.html"; IN_PROC_BROWSER_TEST_F(WebKitBrowserTest, XsltBadImport) { @@ -97,7 +97,7 @@ // TODO(gavinp,jochen): This browser_test depends on there not being a // prerendering client and prerendering platform provided by the test_shell. -// But both will exist when we use content_shell to run layout tests. We must +// But both will exist when we use content_shell to run web tests. We must // then add a mechanism to start content_shell without these, or else this // test is not very interesting. const char kPrerenderNoCrashPage[] = "/prerender/prerender-no-crash.html";
diff --git a/content/browser/webui/shared_resources_data_source.cc b/content/browser/webui/shared_resources_data_source.cc index 7b0eccd..a4265860 100644 --- a/content/browser/webui/shared_resources_data_source.cc +++ b/content/browser/webui/shared_resources_data_source.cc
@@ -88,6 +88,8 @@ "js/chromeos/multidevice_setup.mojom.js"}, {IDR_MULTIDEVICE_MULTIDEVICE_SETUP_CONSTANTS_MOJOM_JS, "js/chromeos/multidevice_setup_constants.mojom.js"}, + {IDR_MULTIDEVICE_MULTIDEVICE_TYPES_MOJOM_JS, + "js/chromeos/multidevice_types.mojom.js"}, }; } #endif // !defined(OS_CHROMEOS)
diff --git a/content/browser/worker_host/mock_shared_worker.cc b/content/browser/worker_host/mock_shared_worker.cc index e50380f5..371b03b 100644 --- a/content/browser/worker_host/mock_shared_worker.cc +++ b/content/browser/worker_host/mock_shared_worker.cc
@@ -21,7 +21,7 @@ } // namespace -MockSharedWorker::MockSharedWorker(mojom::SharedWorkerRequest request) +MockSharedWorker::MockSharedWorker(blink::mojom::SharedWorkerRequest request) : binding_(this, std::move(request)) {} MockSharedWorker::~MockSharedWorker() = default; @@ -77,8 +77,8 @@ const std::string& expected_name, blink::mojom::ContentSecurityPolicyType expected_content_security_policy_type, - mojom::SharedWorkerHostPtr* host, - mojom::SharedWorkerRequest* request) { + blink::mojom::SharedWorkerHostPtr* host, + blink::mojom::SharedWorkerRequest* request) { std::unique_ptr<CreateParams> create_params = std::move(create_params_); if (!create_params) return false; @@ -111,8 +111,8 @@ blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories, blink::mojom::ControllerServiceWorkerInfoPtr controller_info, - mojom::SharedWorkerHostPtr host, - mojom::SharedWorkerRequest request, + blink::mojom::SharedWorkerHostPtr host, + blink::mojom::SharedWorkerRequest request, service_manager::mojom::InterfaceProviderPtr interface_provider) { DCHECK(!create_params_); create_params_ = std::make_unique<CreateParams>();
diff --git a/content/browser/worker_host/mock_shared_worker.h b/content/browser/worker_host/mock_shared_worker.h index b2f3ad98..301fd33 100644 --- a/content/browser/worker_host/mock_shared_worker.h +++ b/content/browser/worker_host/mock_shared_worker.h
@@ -24,9 +24,9 @@ namespace content { class URLLoaderFactoryBundleInfo; -class MockSharedWorker : public mojom::SharedWorker { +class MockSharedWorker : public blink::mojom::SharedWorker { public: - explicit MockSharedWorker(mojom::SharedWorkerRequest request); + explicit MockSharedWorker(blink::mojom::SharedWorkerRequest request); ~MockSharedWorker() override; bool CheckReceivedConnect(int* connection_request_id, @@ -35,7 +35,7 @@ bool CheckReceivedTerminate(); private: - // mojom::SharedWorker methods: + // blink::mojom::SharedWorker methods: void Connect(int connection_request_id, mojo::ScopedMessagePipeHandle port) override; void Terminate() override; @@ -43,7 +43,7 @@ blink::mojom::DevToolsAgentHostAssociatedPtrInfo host_ptr_info, blink::mojom::DevToolsAgentAssociatedRequest request) override; - mojo::Binding<mojom::SharedWorker> binding_; + mojo::Binding<blink::mojom::SharedWorker> binding_; std::queue<std::pair<int, blink::MessagePortChannel>> connect_received_; bool terminate_received_ = false; @@ -60,8 +60,8 @@ const std::string& expected_name, blink::mojom::ContentSecurityPolicyType expected_content_security_policy_type, - mojom::SharedWorkerHostPtr* host, - mojom::SharedWorkerRequest* request); + blink::mojom::SharedWorkerHostPtr* host, + blink::mojom::SharedWorkerRequest* request); private: // mojom::SharedWorkerFactory methods: @@ -80,8 +80,8 @@ blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories, blink::mojom::ControllerServiceWorkerInfoPtr controller_info, - mojom::SharedWorkerHostPtr host, - mojom::SharedWorkerRequest request, + blink::mojom::SharedWorkerHostPtr host, + blink::mojom::SharedWorkerRequest request, service_manager::mojom::InterfaceProviderPtr interface_provider) override; struct CreateParams { @@ -90,8 +90,8 @@ blink::mojom::SharedWorkerInfoPtr info; bool pause_on_start; blink::mojom::WorkerContentSettingsProxyPtr content_settings; - mojom::SharedWorkerHostPtr host; - mojom::SharedWorkerRequest request; + blink::mojom::SharedWorkerHostPtr host; + blink::mojom::SharedWorkerRequest request; service_manager::mojom::InterfaceProviderPtr interface_provider; };
diff --git a/content/browser/worker_host/shared_worker_connector_impl.cc b/content/browser/worker_host/shared_worker_connector_impl.cc index a1b9c5a..9ec48360 100644 --- a/content/browser/worker_host/shared_worker_connector_impl.cc +++ b/content/browser/worker_host/shared_worker_connector_impl.cc
@@ -19,7 +19,7 @@ void SharedWorkerConnectorImpl::Create( int process_id, int frame_id, - mojom::SharedWorkerConnectorRequest request) { + blink::mojom::SharedWorkerConnectorRequest request) { mojo::MakeStrongBinding( base::WrapUnique(new SharedWorkerConnectorImpl(process_id, frame_id)), std::move(request));
diff --git a/content/browser/worker_host/shared_worker_connector_impl.h b/content/browser/worker_host/shared_worker_connector_impl.h index aa96a6f..6c6d629 100644 --- a/content/browser/worker_host/shared_worker_connector_impl.h +++ b/content/browser/worker_host/shared_worker_connector_impl.h
@@ -6,23 +6,23 @@ #define CONTENT_BROWSER_WORKER_HOST_SHARED_WORKER_CONNECTOR_IMPL_H_ #include "content/common/content_export.h" -#include "content/common/shared_worker/shared_worker_connector.mojom.h" +#include "third_party/blink/public/mojom/worker/shared_worker_connector.mojom.h" namespace content { // Instances of this class live on the UI thread and have their lifetime bound // to a Mojo connection. class CONTENT_EXPORT SharedWorkerConnectorImpl - : public mojom::SharedWorkerConnector { + : public blink::mojom::SharedWorkerConnector { public: static void Create(int process_id, int frame_id, - mojom::SharedWorkerConnectorRequest request); + blink::mojom::SharedWorkerConnectorRequest request); private: SharedWorkerConnectorImpl(int process_id, int frame_id); - // mojom::SharedWorkerConnector methods: + // blink::mojom::SharedWorkerConnector methods: void Connect( blink::mojom::SharedWorkerInfoPtr info, blink::mojom::SharedWorkerClientPtr client,
diff --git a/content/browser/worker_host/shared_worker_host.cc b/content/browser/worker_host/shared_worker_host.cc index dd1a25b..9bba074c 100644 --- a/content/browser/worker_host/shared_worker_host.cc +++ b/content/browser/worker_host/shared_worker_host.cc
@@ -210,7 +210,7 @@ instance_->url(), this, mojo::MakeRequest(&content_settings)); // Set up host interface. - mojom::SharedWorkerHostPtr host; + blink::mojom::SharedWorkerHostPtr host; binding_.Bind(mojo::MakeRequest(&host)); // Set up interface provider interface.
diff --git a/content/browser/worker_host/shared_worker_host.h b/content/browser/worker_host/shared_worker_host.h index 0696000..713891d 100644 --- a/content/browser/worker_host/shared_worker_host.h +++ b/content/browser/worker_host/shared_worker_host.h
@@ -17,16 +17,16 @@ #include "base/time/time.h" #include "base/unguessable_token.h" #include "content/common/service_worker/service_worker_provider.mojom.h" -#include "content/common/shared_worker/shared_worker.mojom.h" #include "content/common/shared_worker/shared_worker_factory.mojom.h" -#include "content/common/shared_worker/shared_worker_host.mojom.h" #include "content/public/browser/global_routing_id.h" #include "mojo/public/cpp/bindings/binding.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/service_manager/public/mojom/interface_provider.mojom.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" +#include "third_party/blink/public/mojom/worker/shared_worker.mojom.h" #include "third_party/blink/public/mojom/worker/shared_worker_client.mojom.h" +#include "third_party/blink/public/mojom/worker/shared_worker_host.mojom.h" #include "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom.h" -#include "third_party/blink/public/web/devtools_agent.mojom.h" class GURL; @@ -48,7 +48,7 @@ // SharedWorkerServiceImpl and destructed when a worker context or worker's // message filter is closed. class CONTENT_EXPORT SharedWorkerHost - : public mojom::SharedWorkerHost, + : public blink::mojom::SharedWorkerHost, public service_manager::mojom::InterfaceProvider { public: SharedWorkerHost(SharedWorkerServiceImpl* service, @@ -150,7 +150,7 @@ using ClientList = std::list<ClientInfo>; - // mojom::SharedWorkerHost methods: + // blink::mojom::SharedWorkerHost methods: void OnConnected(int connection_request_id) override; void OnContextClosed() override; void OnReadyForInspection() override; @@ -174,15 +174,15 @@ void AdvanceTo(Phase phase); - mojo::Binding<mojom::SharedWorkerHost> binding_; + mojo::Binding<blink::mojom::SharedWorkerHost> binding_; // |service_| owns |this|. SharedWorkerServiceImpl* service_; std::unique_ptr<SharedWorkerInstance> instance_; ClientList clients_; - mojom::SharedWorkerRequest worker_request_; - mojom::SharedWorkerPtr worker_; + blink::mojom::SharedWorkerRequest worker_request_; + blink::mojom::SharedWorkerPtr worker_; const int process_id_; int next_connection_request_id_;
diff --git a/content/browser/worker_host/shared_worker_host_unittest.cc b/content/browser/worker_host/shared_worker_host_unittest.cc index 40585cf0..e92e49f 100644 --- a/content/browser/worker_host/shared_worker_host_unittest.cc +++ b/content/browser/worker_host/shared_worker_host_unittest.cc
@@ -169,8 +169,8 @@ base::RunLoop().RunUntilIdle(); // The factory should have gotten the CreateSharedWorker message. - mojom::SharedWorkerHostPtr worker_host; - mojom::SharedWorkerRequest worker_request; + blink::mojom::SharedWorkerHostPtr worker_host; + blink::mojom::SharedWorkerRequest worker_request; EXPECT_TRUE(factory_impl.CheckReceivedCreateSharedWorker( host->instance()->url(), host->instance()->name(), host->instance()->content_security_policy_type(), &worker_host, @@ -266,8 +266,8 @@ base::RunLoop().RunUntilIdle(); { - mojom::SharedWorkerHostPtr worker_host; - mojom::SharedWorkerRequest worker_request; + blink::mojom::SharedWorkerHostPtr worker_host; + blink::mojom::SharedWorkerRequest worker_request; EXPECT_TRUE(factory_impl.CheckReceivedCreateSharedWorker( host->instance()->url(), host->instance()->name(), host->instance()->content_security_policy_type(), &worker_host, @@ -308,8 +308,8 @@ base::RunLoop().RunUntilIdle(); { - mojom::SharedWorkerHostPtr worker_host; - mojom::SharedWorkerRequest worker_request; + blink::mojom::SharedWorkerHostPtr worker_host; + blink::mojom::SharedWorkerRequest worker_request; EXPECT_TRUE(factory_impl.CheckReceivedCreateSharedWorker( host->instance()->url(), host->instance()->name(), host->instance()->content_security_policy_type(), &worker_host,
diff --git a/content/browser/worker_host/shared_worker_service_impl.h b/content/browser/worker_host/shared_worker_service_impl.h index 43e216db..ef843e96 100644 --- a/content/browser/worker_host/shared_worker_service_impl.h +++ b/content/browser/worker_host/shared_worker_service_impl.h
@@ -15,11 +15,11 @@ #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/worker_host/shared_worker_host.h" #include "content/common/service_worker/service_worker_provider.mojom.h" -#include "content/common/shared_worker/shared_worker_connector.mojom.h" #include "content/common/shared_worker/shared_worker_factory.mojom.h" #include "content/public/browser/shared_worker_service.h" #include "services/network/public/cpp/resource_response.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" +#include "third_party/blink/public/mojom/worker/shared_worker_connector.mojom.h" #include "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom.h" namespace blink {
diff --git a/content/browser/worker_host/shared_worker_service_impl_unittest.cc b/content/browser/worker_host/shared_worker_service_impl_unittest.cc index 6c31424..d3aa1ee 100644 --- a/content/browser/worker_host/shared_worker_service_impl_unittest.cc +++ b/content/browser/worker_host/shared_worker_service_impl_unittest.cc
@@ -33,10 +33,10 @@ class SharedWorkerServiceImplTest : public RenderViewHostImplTestHarness { public: - mojom::SharedWorkerConnectorPtr MakeSharedWorkerConnector( + blink::mojom::SharedWorkerConnectorPtr MakeSharedWorkerConnector( RenderProcessHost* process_host, int frame_id) { - mojom::SharedWorkerConnectorPtr connector; + blink::mojom::SharedWorkerConnectorPtr connector; SharedWorkerConnectorImpl::Create(process_host->GetID(), frame_id, mojo::MakeRequest(&connector)); return connector; @@ -102,7 +102,7 @@ namespace { -void ConnectToSharedWorker(mojom::SharedWorkerConnectorPtr connector, +void ConnectToSharedWorker(blink::mojom::SharedWorkerConnectorPtr connector, const GURL& url, const std::string& name, MockSharedWorkerClient* client, @@ -149,8 +149,8 @@ MockSharedWorkerFactory factory(std::move(factory_request)); base::RunLoop().RunUntilIdle(); - mojom::SharedWorkerHostPtr worker_host; - mojom::SharedWorkerRequest worker_request; + blink::mojom::SharedWorkerHostPtr worker_host; + blink::mojom::SharedWorkerRequest worker_request; EXPECT_TRUE(factory.CheckReceivedCreateSharedWorker( kUrl, "name", blink::mojom::ContentSecurityPolicyType::kReport, &worker_host, &worker_request)); @@ -225,8 +225,8 @@ MockSharedWorkerFactory factory(std::move(factory_request)); base::RunLoop().RunUntilIdle(); - mojom::SharedWorkerHostPtr worker_host; - mojom::SharedWorkerRequest worker_request; + blink::mojom::SharedWorkerHostPtr worker_host; + blink::mojom::SharedWorkerRequest worker_request; EXPECT_TRUE(factory.CheckReceivedCreateSharedWorker( kUrl, "name", blink::mojom::ContentSecurityPolicyType::kReport, &worker_host, &worker_request)); @@ -365,8 +365,8 @@ MockSharedWorkerFactory factory(std::move(factory_request)); base::RunLoop().RunUntilIdle(); - mojom::SharedWorkerHostPtr worker_host; - mojom::SharedWorkerRequest worker_request; + blink::mojom::SharedWorkerHostPtr worker_host; + blink::mojom::SharedWorkerRequest worker_request; EXPECT_TRUE(factory.CheckReceivedCreateSharedWorker( kUrl, kName, blink::mojom::ContentSecurityPolicyType::kReport, &worker_host, &worker_request)); @@ -438,8 +438,8 @@ MockSharedWorkerFactory factory0(std::move(factory_request0)); base::RunLoop().RunUntilIdle(); - mojom::SharedWorkerHostPtr worker_host0; - mojom::SharedWorkerRequest worker_request0; + blink::mojom::SharedWorkerHostPtr worker_host0; + blink::mojom::SharedWorkerRequest worker_request0; EXPECT_TRUE(factory0.CheckReceivedCreateSharedWorker( kUrl0, kName, blink::mojom::ContentSecurityPolicyType::kReport, &worker_host0, &worker_request0)); @@ -463,8 +463,8 @@ MockSharedWorkerFactory factory1(std::move(factory_request1)); base::RunLoop().RunUntilIdle(); - mojom::SharedWorkerHostPtr worker_host1; - mojom::SharedWorkerRequest worker_request1; + blink::mojom::SharedWorkerHostPtr worker_host1; + blink::mojom::SharedWorkerRequest worker_request1; EXPECT_TRUE(factory1.CheckReceivedCreateSharedWorker( kUrl1, kName, blink::mojom::ContentSecurityPolicyType::kReport, &worker_host1, &worker_request1)); @@ -523,8 +523,8 @@ MockSharedWorkerFactory factory0(std::move(factory_request0)); base::RunLoop().RunUntilIdle(); - mojom::SharedWorkerHostPtr worker_host0; - mojom::SharedWorkerRequest worker_request0; + blink::mojom::SharedWorkerHostPtr worker_host0; + blink::mojom::SharedWorkerRequest worker_request0; EXPECT_TRUE(factory0.CheckReceivedCreateSharedWorker( kUrl, kName0, blink::mojom::ContentSecurityPolicyType::kReport, &worker_host0, &worker_request0)); @@ -548,8 +548,8 @@ MockSharedWorkerFactory factory1(std::move(factory_request1)); base::RunLoop().RunUntilIdle(); - mojom::SharedWorkerHostPtr worker_host1; - mojom::SharedWorkerRequest worker_request1; + blink::mojom::SharedWorkerHostPtr worker_host1; + blink::mojom::SharedWorkerRequest worker_request1; EXPECT_TRUE(factory1.CheckReceivedCreateSharedWorker( kUrl, kName1, blink::mojom::ContentSecurityPolicyType::kReport, &worker_host1, &worker_request1)); @@ -617,8 +617,8 @@ base::RunLoop().RunUntilIdle(); - mojom::SharedWorkerHostPtr worker_host; - mojom::SharedWorkerRequest worker_request; + blink::mojom::SharedWorkerHostPtr worker_host; + blink::mojom::SharedWorkerRequest worker_request; EXPECT_TRUE(factory.CheckReceivedCreateSharedWorker( kUrl, kName, blink::mojom::ContentSecurityPolicyType::kReport, &worker_host, &worker_request)); @@ -696,15 +696,15 @@ base::RunLoop().RunUntilIdle(); - mojom::SharedWorkerHostPtr worker_host0; - mojom::SharedWorkerRequest worker_request0; + blink::mojom::SharedWorkerHostPtr worker_host0; + blink::mojom::SharedWorkerRequest worker_request0; EXPECT_TRUE(factory0.CheckReceivedCreateSharedWorker( kUrl0, kName, blink::mojom::ContentSecurityPolicyType::kReport, &worker_host0, &worker_request0)); MockSharedWorker worker0(std::move(worker_request0)); - mojom::SharedWorkerHostPtr worker_host1; - mojom::SharedWorkerRequest worker_request1; + blink::mojom::SharedWorkerHostPtr worker_host1; + blink::mojom::SharedWorkerRequest worker_request1; EXPECT_TRUE(factory1.CheckReceivedCreateSharedWorker( kUrl1, kName, blink::mojom::ContentSecurityPolicyType::kReport, &worker_host1, &worker_request1)); @@ -785,15 +785,15 @@ base::RunLoop().RunUntilIdle(); - mojom::SharedWorkerHostPtr worker_host0; - mojom::SharedWorkerRequest worker_request0; + blink::mojom::SharedWorkerHostPtr worker_host0; + blink::mojom::SharedWorkerRequest worker_request0; EXPECT_TRUE(factory0.CheckReceivedCreateSharedWorker( kUrl, kName0, blink::mojom::ContentSecurityPolicyType::kReport, &worker_host0, &worker_request0)); MockSharedWorker worker0(std::move(worker_request0)); - mojom::SharedWorkerHostPtr worker_host1; - mojom::SharedWorkerRequest worker_request1; + blink::mojom::SharedWorkerHostPtr worker_host1; + blink::mojom::SharedWorkerRequest worker_request1; EXPECT_TRUE(factory1.CheckReceivedCreateSharedWorker( kUrl, kName1, blink::mojom::ContentSecurityPolicyType::kReport, &worker_host1, &worker_request1)); @@ -870,8 +870,8 @@ base::RunLoop().RunUntilIdle(); - mojom::SharedWorkerHostPtr worker_host0; - mojom::SharedWorkerRequest worker_request0; + blink::mojom::SharedWorkerHostPtr worker_host0; + blink::mojom::SharedWorkerRequest worker_request0; EXPECT_TRUE(factory0.CheckReceivedCreateSharedWorker( kUrl, kName, blink::mojom::ContentSecurityPolicyType::kReport, &worker_host0, &worker_request0)); @@ -904,8 +904,8 @@ base::RunLoop().RunUntilIdle(); - mojom::SharedWorkerHostPtr worker_host1; - mojom::SharedWorkerRequest worker_request1; + blink::mojom::SharedWorkerHostPtr worker_host1; + blink::mojom::SharedWorkerRequest worker_request1; EXPECT_TRUE(factory1.CheckReceivedCreateSharedWorker( kUrl, kName, blink::mojom::ContentSecurityPolicyType::kReport, &worker_host1, &worker_request1)); @@ -993,8 +993,8 @@ base::RunLoop().RunUntilIdle(); - mojom::SharedWorkerHostPtr worker_host1; - mojom::SharedWorkerRequest worker_request1; + blink::mojom::SharedWorkerHostPtr worker_host1; + blink::mojom::SharedWorkerRequest worker_request1; EXPECT_TRUE(factory1.CheckReceivedCreateSharedWorker( kUrl, kName, blink::mojom::ContentSecurityPolicyType::kReport, &worker_host1, &worker_request1)); @@ -1068,8 +1068,8 @@ base::RunLoop().RunUntilIdle(); // Expect a create shared worker. - mojom::SharedWorkerHostPtr worker_host; - mojom::SharedWorkerRequest worker_request; + blink::mojom::SharedWorkerHostPtr worker_host; + blink::mojom::SharedWorkerRequest worker_request; EXPECT_TRUE(factory.CheckReceivedCreateSharedWorker( kURL, kName, blink::mojom::ContentSecurityPolicyType::kReport, &worker_host, &worker_request));
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index 4f18996..2a8c1ab 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn
@@ -512,10 +512,7 @@ "service_worker/service_worker.mojom", "service_worker/service_worker_container.mojom", "service_worker/service_worker_provider.mojom", - "shared_worker/shared_worker.mojom", - "shared_worker/shared_worker_connector.mojom", "shared_worker/shared_worker_factory.mojom", - "shared_worker/shared_worker_host.mojom", "url_loader_factory_bundle.mojom", "widget.mojom", ]
diff --git a/content/common/frame.mojom b/content/common/frame.mojom index 0ff5c850..53d7ae2 100644 --- a/content/common/frame.mojom +++ b/content/common/frame.mojom
@@ -23,7 +23,7 @@ import "third_party/blink/public/mojom/referrer.mojom"; import "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom"; import "third_party/blink/public/web/commit_result.mojom"; -import "third_party/blink/public/web/devtools_agent.mojom"; +import "third_party/blink/public/mojom/devtools/devtools_agent.mojom"; import "third_party/blink/public/web/window_features.mojom"; import "ui/base/mojo/window_open_disposition.mojom"; import "url/mojom/url.mojom";
diff --git a/content/common/frame_replication_state.h b/content/common/frame_replication_state.h index 79d2954..8d5e317 100644 --- a/content/common/frame_replication_state.h +++ b/content/common/frame_replication_state.h
@@ -68,7 +68,7 @@ // |unique_name| is used in heuristics that try to identify the same frame // across different, unrelated navigations (i.e. to refer to the frame // when going back/forward in session history OR when refering to the frame - // in layout tests results). + // in web tests results). // // |unique_name| needs to be replicated to ensure that unique name for a given // frame is the same across all renderers - without replication a renderer
diff --git a/content/common/media/peer_connection_tracker_messages.h b/content/common/media/peer_connection_tracker_messages.h index f5821e0..73d4979 100644 --- a/content/common/media/peer_connection_tracker_messages.h +++ b/content/common/media/peer_connection_tracker_messages.h
@@ -44,8 +44,9 @@ IPC_MESSAGE_CONTROL2(PeerConnectionTracker_StartEventLogFile, int /* peer_connection_local_id */, IPC::PlatformFileForTransit /* file */) -IPC_MESSAGE_CONTROL1(PeerConnectionTracker_StartEventLogOutput, - int /* peer_connection_local_id */) +IPC_MESSAGE_CONTROL2(PeerConnectionTracker_StartEventLogOutput, + int /* peer_connection_local_id */, + int /* output_period_ms */) IPC_MESSAGE_CONTROL1(PeerConnectionTracker_StopEventLog, int /* peer_connection_local_id */)
diff --git a/content/common/service_worker/embedded_worker.mojom b/content/common/service_worker/embedded_worker.mojom index 3a4052b..30519f8 100644 --- a/content/common/service_worker/embedded_worker.mojom +++ b/content/common/service_worker/embedded_worker.mojom
@@ -21,7 +21,7 @@ import "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom"; import "third_party/blink/public/platform/web_feature.mojom"; import "third_party/blink/public/web/console_message.mojom"; -import "third_party/blink/public/web/devtools_agent.mojom"; +import "third_party/blink/public/mojom/devtools/devtools_agent.mojom"; import "third_party/blink/public/web/worker_content_settings_proxy.mojom"; import "url/mojom/url.mojom";
diff --git a/content/common/service_worker/service_worker_loader_helpers.cc b/content/common/service_worker/service_worker_loader_helpers.cc index 1b26bc94..736dcbe 100644 --- a/content/common/service_worker/service_worker_loader_helpers.cc +++ b/content/common/service_worker/service_worker_loader_helpers.cc
@@ -124,8 +124,8 @@ : net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL; return net::RedirectInfo::ComputeRedirectInfo( original_request.method, original_request.url, - original_request.site_for_cookies, first_party_url_policy, - original_request.referrer_policy, + original_request.site_for_cookies, original_request.top_frame_origin, + first_party_url_policy, original_request.referrer_policy, network::ComputeReferrer(original_request.referrer), response_head.headers.get(), response_head.headers->response_code(), original_request.url.Resolve(new_location), false);
diff --git a/content/common/shared_worker/shared_worker.mojom b/content/common/shared_worker/shared_worker.mojom deleted file mode 100644 index 6a31c53..0000000 --- a/content/common/shared_worker/shared_worker.mojom +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2017 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. - -module content.mojom; - -import "third_party/blink/public/web/devtools_agent.mojom"; - -// Interface used by the host to control the shared worker. -interface SharedWorker { - // Called to establish a new client connection to the shared worker. The - // |connection_id| parameter will be echoed back to the host via the - // OnConnected method. - Connect(int32 connection_id, handle<message_pipe> message_port); - - // Called to terminate the shared worker. This results in the shared worker - // closing its end of the mojo connection. - Terminate(); - - // Binds a DevToolsAgent interface for this shared worker, used for - // remote debugging. See DevToolsAgent for details. - BindDevToolsAgent(associated blink.mojom.DevToolsAgentHost agent_host, - associated blink.mojom.DevToolsAgent& agent); -};
diff --git a/content/common/shared_worker/shared_worker_connector.mojom b/content/common/shared_worker/shared_worker_connector.mojom deleted file mode 100644 index 44492a3..0000000 --- a/content/common/shared_worker/shared_worker_connector.mojom +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2017 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. - -module content.mojom; - -import "third_party/blink/public/mojom/blob/blob_url_store.mojom"; -import "third_party/blink/public/mojom/worker/shared_worker_client.mojom"; -import "third_party/blink/public/mojom/worker/shared_worker_creation_context_type.mojom"; -import "third_party/blink/public/mojom/worker/shared_worker_info.mojom"; - -// This interface is exposed to enable a client to create and connect to a -// shared worker. -interface SharedWorkerConnector { - // Connect to (and create if necessary) a SharedWorker specified by |info|. - // The SharedWorker will be terminated if all clients go away. - // |blob_url_token| should be non-null when the worker is loaded from a blob: - // URL. The token will then be used to look up the blob associated with the - // blob URL. Without this by the time the worker code starts fetching - // the URL the blob URL might no longer be valid. - Connect(blink.mojom.SharedWorkerInfo info, - blink.mojom.SharedWorkerClient client, - blink.mojom.SharedWorkerCreationContextType creation_context_type, - handle<message_pipe> message_port, - blink.mojom.BlobURLToken? blob_url_token); -};
diff --git a/content/common/shared_worker/shared_worker_factory.mojom b/content/common/shared_worker/shared_worker_factory.mojom index 354ceb0..9707445 100644 --- a/content/common/shared_worker/shared_worker_factory.mojom +++ b/content/common/shared_worker/shared_worker_factory.mojom
@@ -5,8 +5,6 @@ module content.mojom; import "content/common/service_worker/service_worker_provider.mojom"; -import "content/common/shared_worker/shared_worker.mojom"; -import "content/common/shared_worker/shared_worker_host.mojom"; import "content/common/url_loader_factory_bundle.mojom"; import "content/public/common/renderer_preference_watcher.mojom"; import "content/public/common/renderer_preferences.mojom"; @@ -14,6 +12,8 @@ import "services/network/public/mojom/url_loader_factory.mojom"; import "services/service_manager/public/mojom/interface_provider.mojom"; import "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom"; +import "third_party/blink/public/mojom/worker/shared_worker.mojom"; +import "third_party/blink/public/mojom/worker/shared_worker_host.mojom"; import "third_party/blink/public/mojom/worker/shared_worker_info.mojom"; import "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom"; import "third_party/blink/public/web/worker_content_settings_proxy.mojom"; @@ -88,7 +88,7 @@ // ServiceWorkerContainer.SetController(). blink.mojom.ControllerServiceWorkerInfo? controller_info, - SharedWorkerHost host, - SharedWorker& shared_worker, + blink.mojom.SharedWorkerHost host, + blink.mojom.SharedWorker& shared_worker, service_manager.mojom.InterfaceProvider interface_provider); };
diff --git a/content/common/shared_worker/shared_worker_host.mojom b/content/common/shared_worker/shared_worker_host.mojom deleted file mode 100644 index 58e6082b..0000000 --- a/content/common/shared_worker/shared_worker_host.mojom +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2017 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. - -module content.mojom; - -import "third_party/blink/public/platform/web_feature.mojom"; - -// Each shared worker has a corresponding host. The host controls the lifetime -// of the shared worker. This interface is used by the shared worker to talk to -// its host. -interface SharedWorkerHost { - // Called in response to SharedWorker's Connect method. The |connection_id| - // parameter is the same value passed to the Connect method. - OnConnected(int32 connection_id); - - // Indicates that the shared worker self-closed. This should trigger the host - // to terminate the shared worker. - OnContextClosed(); - - // Indicates that the shared worker is ready for inspection. - OnReadyForInspection(); - - // Indicates that the script successfully loaded. - OnScriptLoaded(); - - // Indicates that the script failed to load. - OnScriptLoadFailed(); - - // Indicates that the shared worker used a feature. This is intended to be - // logged by the client-side feature logging infrastructure. - OnFeatureUsed(blink.mojom.WebFeature feature); -};
diff --git a/content/common/throttling_url_loader.cc b/content/common/throttling_url_loader.cc index 044a92e..18292c5 100644 --- a/content/common/throttling_url_loader.cc +++ b/content/common/throttling_url_loader.cc
@@ -350,6 +350,8 @@ redirect_info.new_method = start_info_->url_request.method; redirect_info.new_url = throttle_will_start_redirect_url_; redirect_info.new_site_for_cookies = throttle_will_start_redirect_url_; + redirect_info.new_top_frame_origin = + url::Origin::Create(throttle_will_start_redirect_url_); network::ResourceResponseHead response_head; std::string header_string = base::StringPrintf( @@ -557,6 +559,7 @@ request.url = redirect_info.new_url; request.method = redirect_info.new_method; request.site_for_cookies = redirect_info.new_site_for_cookies; + request.top_frame_origin = redirect_info.new_top_frame_origin; request.referrer = GURL(redirect_info.new_referrer); request.referrer_policy = redirect_info.new_referrer_policy;
diff --git a/content/common/unique_name_helper.cc b/content/common/unique_name_helper.cc index 676e4412..28b28172 100644 --- a/content/common/unique_name_helper.cc +++ b/content/common/unique_name_helper.cc
@@ -200,7 +200,7 @@ // The deterministic part of unique name should be included if // 1. The new subframe is not created by script or // 2. The new subframe is created by script, but we are still asked for the - // old, stable part for layout tests (via + // old, stable part for web tests (via // |g_preserve_stable_unique_name_for_testing|). if (!is_created_by_script || g_preserve_stable_unique_name_for_testing) { PendingChildFrameAdapter adapter(frame_);
diff --git a/content/common/unique_name_helper.h b/content/common/unique_name_helper.h index 2f53cc9..5df9f522 100644 --- a/content/common/unique_name_helper.h +++ b/content/common/unique_name_helper.h
@@ -17,7 +17,7 @@ // Frame helper that manages the details of generating a quasi-stable unique // name for the frame. The name is unique within a page, and is used for: // - matching up session history items with recreated frames -// - layout test results +// - web test results // // Description of the current unique name format // --------------------------------------------- @@ -181,7 +181,7 @@ // Enters a mode causing future uses of GenerateNameForNewChildFrame to // preserve the original, stable unique name, so that it can be recovered - // (e.g. for layout tests) by ExtractStableNameForTesting method below. This + // (e.g. for web tests) by ExtractStableNameForTesting method below. This // mode is not enabled by default, because it makes unique names longer, and // thus negatively affects memory usage. static void PreserveStableUniqueNameForTesting();
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc index c2061485..1c96f168 100644 --- a/content/gpu/gpu_main.cc +++ b/content/gpu/gpu_main.cc
@@ -340,7 +340,6 @@ // Setup tracing sampler profiler as early as possible. std::unique_ptr<tracing::TracingSamplerProfiler> tracing_sampler_profiler = tracing::TracingSamplerProfiler::CreateOnMainThread(); - tracing_sampler_profiler->OnMessageLoopStarted(); #if defined(OS_ANDROID) base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 44aaf207..01298f3 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -496,6 +496,7 @@ "javatests/src/org/chromium/content/browser/VideoRotateToFullscreenTest.java", "javatests/src/org/chromium/content/browser/VSyncPausedTest.java", "javatests/src/org/chromium/content/browser/ViewportTest.java", + "javatests/src/org/chromium/content/browser/WakeLockTest.java", "javatests/src/org/chromium/content/browser/WebContentsObserverAndroidTest.java", "javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java", "javatests/src/org/chromium/content/browser/accessibility/captioning/CaptioningChangeDelegateTest.java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java b/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java index c40dfe43..20439053 100644 --- a/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java
@@ -321,7 +321,7 @@ // If full browser startup is not needed, execute all the callbacks now. executeEnqueuedCallbacks(STARTUP_SUCCESS); } - ServicificationStartupUma.getInstance().commit(); + recordStartupUma(); } private void executeEnqueuedCallbacks(int startupResult) { @@ -422,6 +422,14 @@ } /** + * Can be overridden by testing. + */ + @VisibleForTesting + void recordStartupUma() { + ServicificationStartupUma.getInstance().commit(); + } + + /** * Initialization needed for tests. Mainly used by content browsertests. */ @Override
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/BrowserStartupControllerTest.java b/content/public/android/javatests/src/org/chromium/content/browser/BrowserStartupControllerTest.java index ac8989253..b1a48db 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/BrowserStartupControllerTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/BrowserStartupControllerTest.java
@@ -51,6 +51,9 @@ } @Override + void recordStartupUma() {} + + @Override int contentMainStart(boolean startServiceManagerOnly) { if (startServiceManagerOnly) { mServiceManagerLaunchCounter++;
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/WakeLockTest.java b/content/public/android/javatests/src/org/chromium/content/browser/WakeLockTest.java new file mode 100644 index 0000000..90ea822 --- /dev/null +++ b/content/public/android/javatests/src/org/chromium/content/browser/WakeLockTest.java
@@ -0,0 +1,79 @@ +// 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. + +package org.chromium.content.browser; + +import android.support.test.filters.SmallTest; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Feature; +import org.chromium.content_public.browser.test.ContentJUnit4ClassRunner; +import org.chromium.content_public.browser.test.util.Criteria; +import org.chromium.content_public.browser.test.util.CriteriaHelper; +import org.chromium.content_public.browser.test.util.JavaScriptUtils; +import org.chromium.content_shell_apk.ContentShellActivityTestRule; + +import java.util.concurrent.TimeoutException; + +/** + * Integration tests for the Wake Lock API. + */ +@RunWith(ContentJUnit4ClassRunner.class) +@CommandLineFlags.Add({"enable-experimental-web-platform-features"}) +public class WakeLockTest { + @Rule + public ContentShellActivityTestRule mActivityTestRule = new ContentShellActivityTestRule(); + + private static final String TEST_PATH = "content/test/data/android/title1.html"; + + @Before + public void setUp() throws Exception { + try { + mActivityTestRule.launchContentShellWithUrlSync(TEST_PATH); + } catch (Throwable t) { + Assert.fail("Couldn't load test page."); + } + } + + private void getWakeLock(String type) throws InterruptedException, TimeoutException { + StringBuilder sb = new StringBuilder(); + sb.append("navigator.getWakeLock('" + type + "').then(wake => {"); + sb.append(" var request" + type + " = wake.createRequest();"); + sb.append("});"); + JavaScriptUtils.executeJavaScriptAndWaitForResult( + mActivityTestRule.getWebContents(), sb.toString()); + } + + @After + public void tearDown() throws Exception {} + + @Test + @SmallTest + @Feature({"WakeLock"}) + public void testScreenLock() throws Exception { + Assert.assertFalse(mActivityTestRule.getActivity() + .getActiveShell() + .getContentView() + .getKeepScreenOn()); + + getWakeLock("screen"); + + CriteriaHelper.pollInstrumentationThread(new Criteria() { + @Override + public boolean isSatisfied() { + return mActivityTestRule.getActivity() + .getActiveShell() + .getContentView() + .getKeepScreenOn(); + } + }); + } +}
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json index bf404c7..fe2939d7 100644 --- a/content/public/app/mojo/content_browser_manifest.json +++ b/content/public/app/mojo/content_browser_manifest.json
@@ -183,9 +183,11 @@ "blink.mojom.PrefetchURLLoaderService", "blink.mojom.PresentationService", "blink.mojom.QuotaDispatcherHost", + "blink.mojom.SharedWorkerConnector", "blink.mojom.SpeechRecognizer", "blink.mojom.TextSuggestionHost", "blink.mojom.UnhandledTapNotifier", + "blink.mojom.WakeLockService", "blink.mojom.WebBluetoothService", "blink.mojom.WebUsbService", "blink.test.mojom.VirtualAuthenticatorManager", @@ -200,7 +202,6 @@ "content.mojom.MediaStreamDispatcherHost", "content.mojom.RendererAudioInputStreamFactory", "content.mojom.RendererAudioOutputStreamFactory", - "content.mojom.SharedWorkerConnector", "device.mojom.GamepadMonitor", "device.mojom.Geolocation", "device.mojom.NFC",
diff --git a/content/public/app/mojo/content_renderer_manifest.json b/content/public/app/mojo/content_renderer_manifest.json index 69de28a..9830c56a 100644 --- a/content/public/app/mojo/content_renderer_manifest.json +++ b/content/public/app/mojo/content_renderer_manifest.json
@@ -40,8 +40,7 @@ "device": [ "device:power_monitor", "device:screen_orientation", - "device:time_zone_monitor", - "device:wake_lock" + "device:time_zone_monitor" ], "ui": [ "discardable_memory",
diff --git a/content/public/browser/background_fetch_delegate.cc b/content/public/browser/background_fetch_delegate.cc index aeefdc9..c3fce51b 100644 --- a/content/public/browser/background_fetch_delegate.cc +++ b/content/public/browser/background_fetch_delegate.cc
@@ -6,8 +6,8 @@ namespace content { -BackgroundFetchDelegate::BackgroundFetchDelegate() {} +BackgroundFetchDelegate::BackgroundFetchDelegate() = default; -BackgroundFetchDelegate::~BackgroundFetchDelegate() {} +BackgroundFetchDelegate::~BackgroundFetchDelegate() = default; } // namespace content
diff --git a/content/public/browser/background_fetch_delegate.h b/content/public/browser/background_fetch_delegate.h index 5e6ed708..79f5c0b 100644 --- a/content/public/browser/background_fetch_delegate.h +++ b/content/public/browser/background_fetch_delegate.h
@@ -100,10 +100,6 @@ // Called when the UI of a background fetch job is activated. virtual void OnUIActivated(const std::string& job_unique_id) = 0; - // Called by the delegate when it's shutting down to signal that the - // delegate is no longer valid. - virtual void OnDelegateShutdown() = 0; - // Called by the Download Client when it needs the upload data for // the given |download_guid|. virtual void GetUploadData(const std::string& job_unique_id, @@ -130,8 +126,9 @@ // a notification can be updated with the current status. If the download was // already started in a previous browser session, then |current_guids| should // contain the GUIDs of in progress downloads, while completed downloads are - // recorded in |completed_parts|. + // recorded in |completed_parts|. Updates are communicated to |client|. virtual void CreateDownloadJob( + base::WeakPtr<Client> client, std::unique_ptr<BackgroundFetchDescription> fetch_description) = 0; // Creates a new download identified by |download_guid| in the download job @@ -156,14 +153,6 @@ virtual void UpdateUI(const std::string& job_unique_id, const base::Optional<std::string>& title, const base::Optional<SkBitmap>& icon) = 0; - - // Set the client that the delegate should communicate changes to. - void SetDelegateClient(base::WeakPtr<Client> client) { client_ = client; } - - base::WeakPtr<Client> client() { return client_; } - - private: - base::WeakPtr<Client> client_; }; } // namespace content
diff --git a/content/public/browser/browser_thread.h b/content/public/browser/browser_thread.h index 279b5691..c2b7716e 100644 --- a/content/public/browser/browser_thread.h +++ b/content/public/browser/browser_thread.h
@@ -86,10 +86,11 @@ } template <class T> - static bool ReleaseSoon(ID identifier, + static void ReleaseSoon(ID identifier, const base::Location& from_here, - const T* object) { - return GetTaskRunnerForThread(identifier)->ReleaseSoon(from_here, object); + scoped_refptr<T>&& object) { + GetTaskRunnerForThread(identifier) + ->ReleaseSoon(from_here, std::move(object)); } // For use with scheduling non-critical tasks for execution after startup.
diff --git a/content/public/browser/gpu_data_manager.h b/content/public/browser/gpu_data_manager.h index 481bf03..2b1e20f4 100644 --- a/content/public/browser/gpu_data_manager.h +++ b/content/public/browser/gpu_data_manager.h
@@ -12,6 +12,10 @@ #include "base/process/process.h" #include "content/common/content_export.h" +namespace base { +class CommandLine; +} + namespace gpu { struct GPUInfo; struct VideoMemoryUsageStats; @@ -61,6 +65,9 @@ // Whether a GPU is in use (as opposed to a software renderer). virtual bool HardwareAccelerationEnabled() const = 0; + // Insert switches into gpu process command line: kUseGL, etc. + virtual void AppendGpuCommandLine(base::CommandLine* command_line) const = 0; + protected: virtual ~GpuDataManager() {} };
diff --git a/content/public/browser/indexed_db_context.h b/content/public/browser/indexed_db_context.h index 2254732..6e42ec2f 100644 --- a/content/public/browser/indexed_db_context.h +++ b/content/public/browser/indexed_db_context.h
@@ -14,8 +14,6 @@ #include "base/memory/ref_counted.h" #include "content/common/content_export.h" -class GURL; - namespace base { class SequencedTaskRunner; } @@ -48,7 +46,7 @@ // Get the file name of the local storage file for the given origin. virtual base::FilePath GetFilePathForTesting( - const GURL& origin_url) const = 0; + const url::Origin& origin) const = 0; // Forget the origins/sizes read from disk. virtual void ResetCachesForTesting() = 0;
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h index ab71ef2..43be044 100644 --- a/content/public/browser/render_process_host.h +++ b/content/public/browser/render_process_host.h
@@ -14,6 +14,7 @@ #include "base/callback_list.h" #include "base/containers/id_map.h" +#include "base/optional.h" #include "base/process/kill.h" #include "base/process/process.h" #include "base/supports_user_data.h" @@ -318,7 +319,8 @@ // Start/stop event log output from WebRTC on this RPH for the peer connection // identified locally within the RPH using the ID |lid|. - virtual void SetWebRtcEventLogOutput(int lid, bool enabled) = 0; + virtual void EnableWebRtcEventLogOutput(int lid, int output_period_ms) = 0; + virtual void DisableWebRtcEventLogOutput(int lid) = 0; // Binds interfaces exposed to the browser process from the renderer. virtual void BindInterface(const std::string& interface_name, @@ -415,8 +417,10 @@ // // |header_client| will be used in URLLoaderFactoryParams when creating the // factory. + // + // TODO(lukasza, nasko): https://crbug.com/888079: Make |origin| mandatory. virtual void CreateURLLoaderFactory( - const url::Origin& origin, + const base::Optional<url::Origin>& origin, network::mojom::TrustedURLLoaderHeaderClientPtrInfo header_client, network::mojom::URLLoaderFactoryRequest request) = 0;
diff --git a/content/public/browser/render_widget_host_view.h b/content/public/browser/render_widget_host_view.h index 59885019..b2ee7df 100644 --- a/content/public/browser/render_widget_host_view.h +++ b/content/public/browser/render_widget_host_view.h
@@ -217,7 +217,7 @@ // Ensures that all surfaces are synchronized for the next call to // CopyFromSurface. This is used by web tests. - virtual void EnsureSurfaceSynchronizedForLayoutTest() = 0; + virtual void EnsureSurfaceSynchronizedForWebTest() = 0; // Creates a video capturer, which will allow the caller to receive a stream // of media::VideoFrames captured from this view. The capturer is configured
diff --git a/content/public/browser/storage_partition.h b/content/public/browser/storage_partition.h index 7c63432..6fe4d0bd 100644 --- a/content/public/browser/storage_partition.h +++ b/content/public/browser/storage_partition.h
@@ -17,17 +17,12 @@ #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/mojom/cookie_manager.mojom.h" -class ChromeURLRequestContextGetter; class GURL; namespace base { class Time; } -namespace cast { -class CastTransportHostFilter; -} - namespace storage { class FileSystemContext; } @@ -70,18 +65,6 @@ class ZoomLevelDelegate; #endif // !defined(OS_ANDROID) -// See comment below on GetURLRequestContext. -class CONTENT_EXPORT ScopedAllowGetURLRequestContext { - private: - // https://crbug.com/806817 - friend class cast::CastTransportHostFilter; - // Uses URLRequestContextGetter to cast to a derived class. - friend class ::ChromeURLRequestContextGetter; - ScopedAllowGetURLRequestContext(); - ~ScopedAllowGetURLRequestContext(); - DISALLOW_COPY_AND_ASSIGN(ScopedAllowGetURLRequestContext); -}; - // Defines what persistent state a child process can access. // // The StoragePartition defines the view each child process has of the @@ -91,10 +74,8 @@ class CONTENT_EXPORT StoragePartition { public: virtual base::FilePath GetPath() = 0; - // http://crbug.com/837753 these methods shouldn't be called when the network - // service is enabled. There are a few remaining callers which have to - // instantiate a ScopedAllowGetURLRequestContext object while they make this - // call. + // These can't be called when the network service is enabled, since net/ runs + // in a separate process. virtual net::URLRequestContextGetter* GetURLRequestContext() = 0; virtual net::URLRequestContextGetter* GetMediaURLRequestContext() = 0;
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index da51e9f..a98d0f5 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -440,6 +440,13 @@ const base::Feature kTouchpadAsyncPinchEvents{"TouchpadAsyncPinchEvents", base::FEATURE_ENABLED_BY_DEFAULT}; +// Allows user activation propagation to all frames having the same origin as +// the activation notifier frame. This is an intermediate measure before we +// have an iframe attribute to declaratively allow user activation propagation +// to subframes. +const base::Feature kUserActivationSameOriginVisibility{ + "UserActivationSameOriginVisibility", base::FEATURE_ENABLED_BY_DEFAULT}; + // An experimental simple user-activation model where the user gesture state is // tracked through a frame-based state instead of the gesture tokens we use // today.
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 19b5bca0..b6aa2ab 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -105,6 +105,7 @@ CONTENT_EXPORT extern const base::Feature kTimerThrottlingForHiddenFrames; CONTENT_EXPORT extern const base::Feature kTouchpadAsyncPinchEvents; CONTENT_EXPORT extern const base::Feature kTouchpadOverscrollHistoryNavigation; +CONTENT_EXPORT extern const base::Feature kUserActivationSameOriginVisibility; CONTENT_EXPORT extern const base::Feature kUserActivationV2; CONTENT_EXPORT extern const base::Feature kV8ContextSnapshot; CONTENT_EXPORT extern const base::Feature kV8LowMemoryModeForSubframes;
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index f3a3f15f..852baf21 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc
@@ -258,7 +258,7 @@ const char kDisableSharedWorkers[] = "disable-shared-workers"; // Do not use runtime-detected high-end CPU optimizations in Skia. This is -// useful for forcing a baseline code path for e.g. layout tests. +// useful for forcing a baseline code path for e.g. web tests. const char kDisableSkiaRuntimeOpts[] = "disable-skia-runtime-opts"; // Disable smooth scrolling for testing. @@ -411,7 +411,7 @@ const char kEnableStrictPowerfulFeatureRestrictions[] = "enable-strict-powerful-feature-restrictions"; -// Enabled threaded compositing for layout tests. +// Enabled threaded compositing for web tests. const char kEnableThreadedCompositing[] = "enable-threaded-compositing"; // Enable tracing during the execution of browser tests.
diff --git a/content/public/common/web_preferences.h b/content/public/common/web_preferences.h index 3a44d90..7f83da9 100644 --- a/content/public/common/web_preferences.h +++ b/content/public/common/web_preferences.h
@@ -69,7 +69,6 @@ enum class AutoplayPolicy { kNoUserGestureRequired, kUserGestureRequired, - kUserGestureRequiredForCrossOrigin, kDocumentUserActivationRequired, };
diff --git a/content/public/renderer/PRESUBMIT.py b/content/public/renderer/PRESUBMIT.py new file mode 100644 index 0000000..670a23d6 --- /dev/null +++ b/content/public/renderer/PRESUBMIT.py
@@ -0,0 +1,43 @@ +# 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. + +"""Content public presubmit script + +See https://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts +for more details about the presubmit API built into gcl. +""" + +def _CheckConstInterfaces(input_api, output_api): + # Matches 'virtual...const = 0;', 'virtual...const;' or 'virtual...const {}' + pattern = input_api.re.compile(r'virtual[^;]*const\s*(=\s*0)?\s*({}|;)', + input_api.re.MULTILINE) + + files = [] + for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile): + if not f.LocalPath().endswith('.h'): + continue + + contents = input_api.ReadFile(f) + if pattern.search(contents): + files.append(f) + + if len(files): + return [output_api.PresubmitError( + 'Do not add const to content/public ' + 'interfaces. See ' + 'https://www.chromium.org/developers/content-module/content-api', + files) ] + + return [] + +def CheckChangeOnUpload(input_api, output_api): + results = [] + results.extend(_CheckConstInterfaces(input_api, output_api)) + return results + + +def CheckChangeOnCommit(input_api, output_api): + results = [] + results.extend(_CheckConstInterfaces(input_api, output_api)) + return results
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc index 0df995d6..fe30f4b 100644 --- a/content/public/renderer/content_renderer_client.cc +++ b/content/public/renderer/content_renderer_client.cc
@@ -172,16 +172,14 @@ return false; } -bool ContentRendererClient::IsSupportedAudioConfig( - const media::AudioConfig& config) { +bool ContentRendererClient::IsSupportedAudioType(const media::AudioType& type) { // Defer to media's default support. - return ::media::IsSupportedAudioConfig(config); + return ::media::IsDefaultSupportedAudioType(type); } -bool ContentRendererClient::IsSupportedVideoConfig( - const media::VideoConfig& config) { +bool ContentRendererClient::IsSupportedVideoType(const media::VideoType& type) { // Defer to media's default support. - return ::media::IsSupportedVideoConfig(config); + return ::media::IsDefaultSupportedVideoType(type); } bool ContentRendererClient::IsSupportedBitstreamAudioCodec(
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h index 2c17ca8..33d3285 100644 --- a/content/public/renderer/content_renderer_client.h +++ b/content/public/renderer/content_renderer_client.h
@@ -22,7 +22,7 @@ #include "content/public/common/content_client.h" #include "content/public/renderer/url_loader_throttle_provider.h" #include "content/public/renderer/websocket_handshake_throttle_provider.h" -#include "media/base/decode_capabilities.h" +#include "media/base/supported_types.h" #include "services/service_manager/public/mojom/service.mojom.h" #include "third_party/blink/public/platform/web_content_settings_client.h" #include "third_party/blink/public/web/web_navigation_policy.h" @@ -277,10 +277,10 @@ virtual bool IsKeySystemsUpdateNeeded(); // Allows embedder to describe customized audio capabilities. - virtual bool IsSupportedAudioConfig(const media::AudioConfig& config); + virtual bool IsSupportedAudioType(const media::AudioType& type); // Allows embedder to describe customized video capabilities. - virtual bool IsSupportedVideoConfig(const media::VideoConfig& config); + virtual bool IsSupportedVideoType(const media::VideoType& type); // Return true if the bitstream format |codec| is supported by the audio sink. virtual bool IsSupportedBitstreamAudioCodec(media::AudioCodec codec);
diff --git a/content/public/renderer/fixed_received_data.cc b/content/public/renderer/fixed_received_data.cc index a185a31..096a732 100644 --- a/content/public/renderer/fixed_received_data.cc +++ b/content/public/renderer/fixed_received_data.cc
@@ -18,11 +18,11 @@ FixedReceivedData::~FixedReceivedData() { } -const char* FixedReceivedData::payload() const { +const char* FixedReceivedData::payload() { return data_.empty() ? nullptr : &data_[0]; } -int FixedReceivedData::length() const { +int FixedReceivedData::length() { return static_cast<int>(data_.size()); }
diff --git a/content/public/renderer/fixed_received_data.h b/content/public/renderer/fixed_received_data.h index 5660bad3..6ba5ccc 100644 --- a/content/public/renderer/fixed_received_data.h +++ b/content/public/renderer/fixed_received_data.h
@@ -23,8 +23,8 @@ FixedReceivedData(const std::vector<char>& data); ~FixedReceivedData() override; - const char* payload() const override; - int length() const override; + const char* payload() override; + int length() override; private: std::vector<char> data_;
diff --git a/content/public/renderer/media_stream_audio_renderer.h b/content/public/renderer/media_stream_audio_renderer.h index 94732bc..338662790 100644 --- a/content/public/renderer/media_stream_audio_renderer.h +++ b/content/public/renderer/media_stream_audio_renderer.h
@@ -52,11 +52,11 @@ // Time stamp that reflects the current render time. Should not be updated // when paused. - virtual base::TimeDelta GetCurrentRenderTime() const = 0; + virtual base::TimeDelta GetCurrentRenderTime() = 0; // Returns true if the implementation is a local renderer and false // otherwise. - virtual bool IsLocalRenderer() const = 0; + virtual bool IsLocalRenderer() = 0; protected: friend class base::RefCountedThreadSafe<MediaStreamAudioRenderer>;
diff --git a/content/public/renderer/pepper_plugin_instance.h b/content/public/renderer/pepper_plugin_instance.h index 99a7a8a0..1a25bccd 100644 --- a/content/public/renderer/pepper_plugin_instance.h +++ b/content/public/renderer/pepper_plugin_instance.h
@@ -63,7 +63,7 @@ virtual blink::WebPluginContainer* GetContainer() = 0; - virtual v8::Isolate* GetIsolate() const = 0; + virtual v8::Isolate* GetIsolate() = 0; virtual ppapi::VarTracker* GetVarTracker() = 0;
diff --git a/content/public/renderer/plugin_instance_throttler.h b/content/public/renderer/plugin_instance_throttler.h index 85df382..a0f098f 100644 --- a/content/public/renderer/plugin_instance_throttler.h +++ b/content/public/renderer/plugin_instance_throttler.h
@@ -83,8 +83,8 @@ virtual void AddObserver(Observer* observer) = 0; virtual void RemoveObserver(Observer* observer) = 0; - virtual bool IsThrottled() const = 0; - virtual bool IsHiddenForPlaceholder() const = 0; + virtual bool IsThrottled() = 0; + virtual bool IsHiddenForPlaceholder() = 0; // Marks the plugin as essential. Unthrottles the plugin if already throttled. virtual void MarkPluginEssential(PowerSaverUnthrottleMethod method) = 0; @@ -92,10 +92,10 @@ // Called by the placeholder when the plugin should temporarily be hidden. virtual void SetHiddenForPlaceholder(bool hidden) = 0; - virtual blink::WebPlugin* GetWebPlugin() const = 0; + virtual blink::WebPlugin* GetWebPlugin() = 0; // Gets the throttler's best estimate of the plugin's visible dimensions. - virtual const gfx::Size& GetSize() const = 0; + virtual const gfx::Size& GetSize() = 0; // Throttler needs to know when the plugin audio is throttled, as this may // prevent the plugin from generating new frames.
diff --git a/content/public/renderer/render_frame.h b/content/public/renderer/render_frame.h index 18c70e6..479dc59 100644 --- a/content/public/renderer/render_frame.h +++ b/content/public/renderer/render_frame.h
@@ -202,7 +202,7 @@ const url::Origin& main_frame_origin, const url::Origin& content_origin, const gfx::Size& unobscured_size, - RecordPeripheralDecision record_decision) const = 0; + RecordPeripheralDecision record_decision) = 0; // Whitelists a |content_origin| so its content will never be throttled in // this RenderFrame. Whitelist is cleared by top level navigation. @@ -234,7 +234,7 @@ virtual void SetZoomLevel(double zoom_level) = 0; // Returns the page's zoom level from the frame's RenderView. - virtual double GetZoomLevel() const = 0; + virtual double GetZoomLevel() = 0; // Adds |message| to the DevTools console. virtual void AddMessageToConsole(ConsoleMessageLevel level, @@ -246,10 +246,10 @@ // Returns the PreviewsState of this frame, a bitmask of potentially several // Previews optimizations. - virtual PreviewsState GetPreviewsState() const = 0; + virtual PreviewsState GetPreviewsState() = 0; // Whether or not this frame is currently pasting. - virtual bool IsPasting() const = 0; + virtual bool IsPasting() = 0; // Loads specified |html| to this frame. |base_url| is used to resolve // relative urls in the document. @@ -273,7 +273,7 @@ // Bitwise-ORed set of extra bindings that have been enabled. See // BindingsPolicy for details. - virtual int GetEnabledBindings() const = 0; + virtual int GetEnabledBindings() = 0; // Set the accessibility mode to force creation of RenderAccessibility. virtual void SetAccessibilityModeForTest(ui::AXMode new_mode) = 0;
diff --git a/content/public/renderer/render_thread.h b/content/public/renderer/render_thread.h index f54655c4..5ed2164 100644 --- a/content/public/renderer/render_thread.h +++ b/content/public/renderer/render_thread.h
@@ -106,7 +106,7 @@ blink::scheduler::WebRendererProcessType type) = 0; // Returns the user-agent string. - virtual blink::WebString GetUserAgent() const = 0; + virtual blink::WebString GetUserAgent() = 0; }; } // namespace content
diff --git a/content/public/renderer/render_view.h b/content/public/renderer/render_view.h index 3a36ce8..dee1d18c 100644 --- a/content/public/renderer/render_view.h +++ b/content/public/renderer/render_view.h
@@ -62,16 +62,16 @@ virtual RenderFrame* GetMainRenderFrame() = 0; // Get the routing ID of the view. - virtual int GetRoutingID() const = 0; + virtual int GetRoutingID() = 0; // Returns the size of the view. - virtual gfx::Size GetSize() const = 0; + virtual gfx::Size GetSize() = 0; // Returns the device scale factor of the display the render view is in. - virtual float GetDeviceScaleFactor() const = 0; + virtual float GetDeviceScaleFactor() = 0; // Returns the page's zoom level for the render view. - virtual float GetZoomLevel() const = 0; + virtual float GetZoomLevel() = 0; // Gets WebKit related preferences associated with this view. virtual const WebPreferences& GetWebkitPreferences() = 0; @@ -89,7 +89,7 @@ // Whether content state (such as form state, scroll position and page // contents) should be sent to the browser immediately. This is normally // false, but set to true by some tests. - virtual bool GetContentStateImmediately() const = 0; + virtual bool GetContentStateImmediately() = 0; // Inject edit commands to be used for the next keyboard event. // TODO(alexmos): Currently, these are used only by BlinkTestRunner. They @@ -100,7 +100,7 @@ virtual void ClearEditCommands() = 0; // Returns |renderer_preferences_.accept_languages| value. - virtual const std::string& GetAcceptLanguages() const = 0; + virtual const std::string& GetAcceptLanguages() = 0; virtual void UpdateBrowserControlsState(BrowserControlsState constraints, BrowserControlsState current,
diff --git a/content/public/renderer/renderer_ppapi_host.h b/content/public/renderer/renderer_ppapi_host.h index e4fe6a7b..07c37625 100644 --- a/content/public/renderer/renderer_ppapi_host.h +++ b/content/public/renderer/renderer_ppapi_host.h
@@ -63,47 +63,44 @@ // Returns true if the given PP_Instance is valid and belongs to the // plugin associated with this host. - virtual bool IsValidInstance(PP_Instance instance) const = 0; + virtual bool IsValidInstance(PP_Instance instance) = 0; // Returns the PluginInstance for the given PP_Instance, or NULL if the // PP_Instance is invalid (the common case this will be invalid is during // plugin teardown when resource hosts are being force-freed). - virtual PepperPluginInstance* GetPluginInstance( - PP_Instance instance) const = 0; + virtual PepperPluginInstance* GetPluginInstance(PP_Instance instance) = 0; // Returns the RenderFrame for the given plugin instance, or NULL if the // instance is invalid. - virtual RenderFrame* GetRenderFrameForInstance( - PP_Instance instance) const = 0; + virtual RenderFrame* GetRenderFrameForInstance(PP_Instance instance) = 0; // Returns the RenderView for the given plugin instance, or NULL if the // instance is invalid. - virtual RenderView* GetRenderViewForInstance(PP_Instance instance) const = 0; + virtual RenderView* GetRenderViewForInstance(PP_Instance instance) = 0; // Returns the WebPluginContainer for the given plugin instance, or NULL if // the instance is invalid. virtual blink::WebPluginContainer* GetContainerForInstance( - PP_Instance instance) const = 0; + PP_Instance instance) = 0; // Returns true if the given instance is considered to be currently // processing a user gesture or the plugin module has the "override user // gesture" flag set (in which case it can always do things normally // restricted by user gestures). Returns false if the instance is invalid or // if there is no current user gesture. - virtual bool HasUserGesture(PP_Instance instance) const = 0; + virtual bool HasUserGesture(PP_Instance instance) = 0; // Returns the routing ID for the render widget containing the given // instance. This will take into account the current Flash fullscreen state, // so if there is a Flash fullscreen instance active, this will return the // routing ID of the fullscreen widget. Returns 0 on failure. - virtual int GetRoutingIDForWidget(PP_Instance instance) const = 0; + virtual int GetRoutingIDForWidget(PP_Instance instance) = 0; // Converts the given plugin coordinate to the containing RenderFrame. This // will take into account the current Flash fullscreen state so will use // the fullscreen widget if it's displayed. - virtual gfx::Point PluginPointToRenderFrame( - PP_Instance instance, - const gfx::Point& pt) const = 0; + virtual gfx::Point PluginPointToRenderFrame(PP_Instance instance, + const gfx::Point& pt) = 0; // Shares a file handle (HANDLE / file descriptor) with the remote side. It // returns a handle that should be sent in exactly one IPC message. Upon @@ -129,9 +126,9 @@ const base::ReadOnlySharedMemoryRegion& region) = 0; // Returns true if the plugin is running in process. - virtual bool IsRunningInProcess() const = 0; + virtual bool IsRunningInProcess() = 0; - virtual std::string GetPluginName() const = 0; + virtual std::string GetPluginName() = 0; // Used by the embedder to inform this RendererPpapiHost that the associated // plugin module is a host for "external plugins." @@ -158,14 +155,14 @@ virtual void CreateBrowserResourceHosts( PP_Instance instance, const std::vector<IPC::Message>& nested_msgs, - base::OnceCallback<void(const std::vector<int>&)> callback) const = 0; + base::OnceCallback<void(const std::vector<int>&)> callback) = 0; // Gets the URL of the document containing the given PP_Instance. // Returns an empty URL if the instance is invalid. // TODO(yzshen): Some methods such as this one don't need to be pure virtual. // Instead, they could be directly implemented using other methods in this // interface. Consider changing them to static helpers. - virtual GURL GetDocumentURL(PP_Instance instance) const = 0; + virtual GURL GetDocumentURL(PP_Instance instance) = 0; protected: virtual ~RendererPpapiHost() {}
diff --git a/content/public/renderer/request_peer.h b/content/public/renderer/request_peer.h index b6b34e9..5738e41 100644 --- a/content/public/renderer/request_peer.h +++ b/content/public/renderer/request_peer.h
@@ -46,8 +46,8 @@ class CONTENT_EXPORT ReceivedData { public: virtual ~ReceivedData() {} - virtual const char* payload() const = 0; - virtual int length() const = 0; + virtual const char* payload() = 0; + virtual int length() = 0; }; // A ThreadSafeReceivedData can be deleted on ANY thread. @@ -98,7 +98,7 @@ const network::URLLoaderCompletionStatus& status) = 0; // Returns the task runner on which this request peer is running. - virtual scoped_refptr<base::TaskRunner> GetTaskRunner() const = 0; + virtual scoped_refptr<base::TaskRunner> GetTaskRunner() = 0; virtual ~RequestPeer() {} };
diff --git a/content/public/renderer/v8_value_converter.h b/content/public/renderer/v8_value_converter.h index 9bdeb241..85538b83 100644 --- a/content/public/renderer/v8_value_converter.h +++ b/content/public/renderer/v8_value_converter.h
@@ -43,7 +43,7 @@ virtual bool FromV8Object(v8::Local<v8::Object> value, std::unique_ptr<base::Value>* out, v8::Isolate* isolate, - const FromV8ValueCallback& callback) const; + const FromV8ValueCallback& callback); // If false is returned, V8ValueConverter proceeds with the default // behavior. @@ -52,24 +52,24 @@ virtual bool FromV8Array(v8::Local<v8::Array> value, std::unique_ptr<base::Value>* out, v8::Isolate* isolate, - const FromV8ValueCallback& callback) const; + const FromV8ValueCallback& callback); // If false is returned, V8ValueConverter proceeds with the default // behavior. v8::Object is passed as ArrayBuffer and ArrayBufferView // classes are siblings. virtual bool FromV8ArrayBuffer(v8::Local<v8::Object> value, std::unique_ptr<base::Value>* out, - v8::Isolate* isolate) const; + v8::Isolate* isolate); // If false is returned, V8ValueConverter proceeds with the default // behavior. This allows to intercept "non-finite" values and do something // with them. virtual bool FromV8Number(v8::Local<v8::Number> value, - std::unique_ptr<base::Value>* out) const; + std::unique_ptr<base::Value>* out); // If false is returned, V8ValueConverter proceeds with the default // behavior. - virtual bool FromV8Undefined(std::unique_ptr<base::Value>* out) const; + virtual bool FromV8Undefined(std::unique_ptr<base::Value>* out); }; static std::unique_ptr<V8ValueConverter> Create(); @@ -112,9 +112,8 @@ // while setting a value, that property or item is skipped, leaving a hole in // the case of arrays. // TODO(dcheng): This should just take a const reference. - virtual v8::Local<v8::Value> ToV8Value( - const base::Value* value, - v8::Local<v8::Context> context) const = 0; + virtual v8::Local<v8::Value> ToV8Value(const base::Value* value, + v8::Local<v8::Context> context) = 0; // Converts a v8::Value to base::Value. // @@ -127,7 +126,7 @@ // converted to Value(Type::NONE). virtual std::unique_ptr<base::Value> FromV8Value( v8::Local<v8::Value> value, - v8::Local<v8::Context> context) const = 0; + v8::Local<v8::Context> context) = 0; }; } // namespace content
diff --git a/content/public/test/android/BUILD.gn b/content/public/test/android/BUILD.gn index 5ba8e3b..5cc796b 100644 --- a/content/public/test/android/BUILD.gn +++ b/content/public/test/android/BUILD.gn
@@ -8,7 +8,7 @@ ] } -android_library("layouttest_java_support") { +android_library("web_test_java_support") { testonly = true deps = [ "//base:base_java", @@ -19,7 +19,7 @@ android_library("content_java_test_support") { testonly = true deps = [ - ":layouttest_java_support", + ":web_test_java_support", "//base:base_java", "//base:base_java_test_support", "//content/public/android:content_java",
diff --git a/content/public/test/fake_download_item.cc b/content/public/test/fake_download_item.cc index 6a1828b..6565484 100644 --- a/content/public/test/fake_download_item.cc +++ b/content/public/test/fake_download_item.cc
@@ -237,7 +237,7 @@ NOTREACHED(); } -void FakeDownloadItem::Resume() { +void FakeDownloadItem::Resume(bool user_resume) { NOTREACHED(); } @@ -261,6 +261,11 @@ return false; } +bool FakeDownloadItem::AllowMetered() const { + NOTREACHED(); + return false; +} + bool FakeDownloadItem::IsTemporary() const { NOTREACHED(); return false; @@ -276,6 +281,11 @@ return 0; } +int32_t FakeDownloadItem::GetAutoResumeCount() const { + NOTREACHED(); + return 0; +} + const GURL& FakeDownloadItem::GetReferrerUrl() const { NOTREACHED(); return dummy_url;
diff --git a/content/public/test/fake_download_item.h b/content/public/test/fake_download_item.h index b11534e..cf364c8 100644 --- a/content/public/test/fake_download_item.h +++ b/content/public/test/fake_download_item.h
@@ -30,7 +30,7 @@ void UpdateObservers() override; void Remove() override; void Pause() override; - void Resume() override; + void Resume(bool user_resume) override; void Cancel(bool user_cancel) override; void OpenDownload() override; void ShowDownloadInShell() override; @@ -58,9 +58,11 @@ const std::string& GetETag() const override; const std::string& GetLastModifiedTime() const override; bool IsPaused() const override; + bool AllowMetered() const override; bool IsTemporary() const override; bool CanResume() const override; int64_t GetBytesWasted() const override; + int32_t GetAutoResumeCount() const override; const GURL& GetReferrerUrl() const override; const GURL& GetSiteUrl() const override; const GURL& GetTabUrl() const override;
diff --git a/content/public/test/layouttest_support.h b/content/public/test/layouttest_support.h deleted file mode 100644 index 06de084..0000000 --- a/content/public/test/layouttest_support.h +++ /dev/null
@@ -1,162 +0,0 @@ -// Copyright (c) 2012 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_PUBLIC_TEST_LAYOUTTEST_SUPPORT_H_ -#define CONTENT_PUBLIC_TEST_LAYOUTTEST_SUPPORT_H_ - -#include <stddef.h> - -#include <memory> -#include <string> - -#include "base/callback_forward.h" -#include "cc/layers/texture_layer.h" -#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_type.h" - -class GURL; - -namespace blink { -struct Manifest; -class WebInputEvent; -class WebLocalFrame; -struct WebSize; -class WebURL; -class WebURLRequest; -class WebView; -} - -namespace gfx { -class ColorSpace; -} - -namespace test_runner { -class WebFrameTestProxyBase; -class WebViewTestProxyBase; -class WebWidgetTestProxyBase; -} - -namespace content { - -class RenderFrame; -class RenderView; -class StoragePartition; - -// Turn the browser process into layout test mode. -void EnableBrowserLayoutTestMode(); - -// Terminates all workers and notifies when complete. This is used for -// testing when it is important to make sure that all shared worker activity -// has stopped. -void TerminateAllSharedWorkersForTesting(StoragePartition* storage_partition, - base::OnceClosure callback); - -/////////////////////////////////////////////////////////////////////////////// -// The following methods are meant to be used from a renderer. - -// Turn a renderer into layout test mode. -void EnableRendererLayoutTestMode(); - -// "Casts" |render_view| to |WebViewTestProxyBase|. Caller has to ensure that -// prior to construction of |render_view|, EnableWebTestProxyCreation was -// called. -test_runner::WebViewTestProxyBase* GetWebViewTestProxyBase( - RenderView* render_view); - -// "Casts" |render_frame| to |WebFrameTestProxyBase|. Caller has to ensure -// that prior to construction of |render_frame|, EnableTestProxyCreation -// was called. -test_runner::WebFrameTestProxyBase* GetWebFrameTestProxyBase( - RenderFrame* render_frame); - -// Gets WebWidgetTestProxyBase associated with |frame| (either the view's widget -// or the local root's frame widget). Caller has to ensure that prior to -// construction of |render_frame|, EnableTestProxyCreation was called. -test_runner::WebWidgetTestProxyBase* GetWebWidgetTestProxyBase( - blink::WebLocalFrame* frame); - -// Enable injecting of a WebViewTestProxy between WebViews and RenderViews, -// WebWidgetTestProxy between WebWidgets and RenderWidgets and WebFrameTestProxy -// between WebFrames and RenderFrames. -void EnableWebTestProxyCreation(); - -typedef base::OnceCallback<void(const GURL&, const blink::Manifest&)> - FetchManifestCallback; -void FetchManifest(blink::WebView* view, FetchManifestCallback callback); - -// Returns the length of the local session history of a render view. -int GetLocalSessionHistoryLength(RenderView* render_view); - -// Sets the focus of the render view depending on |enable|. This only overrides -// the state of the renderer, and does not sync the focus to the browser -// process. -void SetFocusAndActivate(RenderView* render_view, bool enable); - -// Changes the window rect of the given render view. -void ForceResizeRenderView(RenderView* render_view, - const blink::WebSize& new_size); - -// Set the device scale factor and force the compositor to resize. -void SetDeviceScaleFactor(RenderView* render_view, float factor); - -// Get the window to viewport scale. -float GetWindowToViewportScale(RenderView* render_view); - -// Converts |event| from screen coordinates to coordinates used by the widget -// associated with the |web_widget_test_proxy_base|. Returns nullptr if no -// transformation was necessary (e.g. for a keyboard event OR if widget requires -// no scaling and has coordinates starting at (0,0)). -std::unique_ptr<blink::WebInputEvent> TransformScreenToWidgetCoordinates( - test_runner::WebWidgetTestProxyBase* web_widget_test_proxy_base, - const blink::WebInputEvent& event); - -// Get the color space for a given name string. This is not in the ColorSpace -// class to avoid bloating the shipping build. -gfx::ColorSpace GetTestingColorSpace(const std::string& name); - -// Set the device color space. -void SetDeviceColorSpace(RenderView* render_view, - const gfx::ColorSpace& color_space); - -// Sets the scan duration to reflect the given setting. -enum class BluetoothTestScanDurationSetting { - kImmediateTimeout, // Set the scan duration to 0 seconds. - kNeverTimeout, // Set the scan duration to base::TimeDelta::Max() seconds. -}; -void SetTestBluetoothScanDuration(BluetoothTestScanDurationSetting setting); - -// Enables or disables synchronous resize mode. When enabled, all window-sizing -// machinery is short-circuited inside the renderer. This mode is necessary for -// some tests that were written before browsers had multi-process architecture -// and rely on window resizes to happen synchronously. -// See http://crbug.com/309760 for details. -void UseSynchronousResizeMode(RenderView* render_view, bool enable); - -// Control auto resize mode. -void EnableAutoResizeMode(RenderView* render_view, - const blink::WebSize& min_size, - const blink::WebSize& max_size); -void DisableAutoResizeMode(RenderView* render_view, - const blink::WebSize& new_size); - -// Run all pending idle tasks immediately, and then invoke callback. -void SchedulerRunIdleTasks(base::OnceClosure callback); - -// Causes the RenderWidget corresponding to |render_frame| to update its -// TextInputState. -void ForceTextInputStateUpdateForRenderFrame(RenderFrame* render_frame); - -// PlzNavigate -// Returns true if the navigation identified by the |request| was initiated by -// the browser or renderer. -bool IsNavigationInitiatedByRenderer(const blink::WebURLRequest& request); - -// RewriteURLFunction must be safe to call from any thread in the renderer -// process. -using RewriteURLFunction = blink::WebURL (*)(const std::string&, - bool is_wpt_mode); -void SetWorkerRewriteURLFunction(RewriteURLFunction rewrite_url_function); - -} // namespace content - -#endif // CONTENT_PUBLIC_TEST_LAYOUTTEST_SUPPORT_H_
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc index f045298..0299faa 100644 --- a/content/public/test/mock_render_process_host.cc +++ b/content/public/test/mock_render_process_host.cc
@@ -412,7 +412,7 @@ } void MockRenderProcessHost::CreateURLLoaderFactory( - const url::Origin& origin, + const base::Optional<url::Origin>& origin, network::mojom::TrustedURLLoaderHeaderClientPtrInfo header_client, network::mojom::URLLoaderFactoryRequest request) { url_loader_factory_->Clone(std::move(request)); @@ -475,7 +475,9 @@ return WebRtcStopRtpDumpCallback(); } -void MockRenderProcessHost::SetWebRtcEventLogOutput(int lid, bool enabled) {} +void MockRenderProcessHost::EnableWebRtcEventLogOutput(int lid, + int output_period_ms) {} +void MockRenderProcessHost::DisableWebRtcEventLogOutput(int lid) {} bool MockRenderProcessHost::OnMessageReceived(const IPC::Message& msg) { IPC::Listener* listener = listeners_.Lookup(msg.routing_id());
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h index 61bc06e..052c942 100644 --- a/content/public/test/mock_render_process_host.h +++ b/content/public/test/mock_render_process_host.h
@@ -127,7 +127,8 @@ bool incoming, bool outgoing, const WebRtcRtpPacketCallback& packet_callback) override; - void SetWebRtcEventLogOutput(int lid, bool enabled) override; + void EnableWebRtcEventLogOutput(int lid, int output_period_ms) override; + void DisableWebRtcEventLogOutput(int lid) override; void BindInterface(const std::string& interface_name, mojo::ScopedMessagePipeHandle interface_pipe) override; const service_manager::Identity& GetChildIdentity() const override; @@ -146,7 +147,7 @@ resource_coordinator::ProcessResourceCoordinator* GetProcessResourceCoordinator() override; void CreateURLLoaderFactory( - const url::Origin& origin, + const base::Optional<url::Origin>& origin, network::mojom::TrustedURLLoaderHeaderClientPtrInfo header_client, network::mojom::URLLoaderFactoryRequest request) override;
diff --git a/content/public/test/mock_render_thread.cc b/content/public/test/mock_render_thread.cc index 35505de2f..d4e82c1 100644 --- a/content/public/test/mock_render_thread.cc +++ b/content/public/test/mock_render_thread.cc
@@ -224,7 +224,7 @@ void MockRenderThread::SetRendererProcessType( blink::scheduler::WebRendererProcessType type) {} -blink::WebString MockRenderThread::GetUserAgent() const { +blink::WebString MockRenderThread::GetUserAgent() { return blink::WebString(); }
diff --git a/content/public/test/mock_render_thread.h b/content/public/test/mock_render_thread.h index 8ed4e44..d327be9 100644 --- a/content/public/test/mock_render_thread.h +++ b/content/public/test/mock_render_thread.h
@@ -78,7 +78,7 @@ bool IsOnline() override; void SetRendererProcessType( blink::scheduler::WebRendererProcessType type) override; - blink::WebString GetUserAgent() const override; + blink::WebString GetUserAgent() override; #if defined(OS_WIN) void PreCacheFont(const LOGFONT& log_font) override; void ReleaseCachedFonts() override;
diff --git a/content/public/test/nested_message_pump_android.h b/content/public/test/nested_message_pump_android.h index f1a7905..19594fb 100644 --- a/content/public/test/nested_message_pump_android.h +++ b/content/public/test/nested_message_pump_android.h
@@ -12,7 +12,7 @@ namespace content { -// A nested message pump to be used for content browsertests and layout tests +// A nested message pump to be used for content browsertests and web tests // on Android. It overrides the default UI message pump to allow nested loops. class NestedMessagePumpAndroid : public base::MessagePumpForUI { public:
diff --git a/content/public/test/test_runner_support.h b/content/public/test/test_runner_support.h index 8c4d95f9..9b14c36 100644 --- a/content/public/test/test_runner_support.h +++ b/content/public/test/test_runner_support.h
@@ -13,9 +13,9 @@ namespace content { -// Returns a frame name that can be used in the output of layout tests +// Returns a frame name that can be used in the output of web tests // (the name is derived from the frame's unique name). -std::string GetFrameNameForLayoutTests(blink::WebLocalFrame* frame); +std::string GetFrameNameForWebTests(blink::WebLocalFrame* frame); } // namespace content
diff --git a/content/public/test/web_test_support.h b/content/public/test/web_test_support.h new file mode 100644 index 0000000..1183f55 --- /dev/null +++ b/content/public/test/web_test_support.h
@@ -0,0 +1,162 @@ +// Copyright (c) 2012 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_PUBLIC_TEST_WEB_TEST_SUPPORT_H_ +#define CONTENT_PUBLIC_TEST_WEB_TEST_SUPPORT_H_ + +#include <stddef.h> + +#include <memory> +#include <string> + +#include "base/callback_forward.h" +#include "cc/layers/texture_layer.h" +#include "third_party/blink/public/common/screen_orientation/web_screen_orientation_type.h" + +class GURL; + +namespace blink { +struct Manifest; +class WebInputEvent; +class WebLocalFrame; +struct WebSize; +class WebURL; +class WebURLRequest; +class WebView; +} // namespace blink + +namespace gfx { +class ColorSpace; +} + +namespace test_runner { +class WebFrameTestProxyBase; +class WebViewTestProxyBase; +class WebWidgetTestProxyBase; +} // namespace test_runner + +namespace content { + +class RenderFrame; +class RenderView; +class StoragePartition; + +// Turn the browser process into web test mode. +void EnableBrowserWebTestMode(); + +// Terminates all workers and notifies when complete. This is used for +// testing when it is important to make sure that all shared worker activity +// has stopped. +void TerminateAllSharedWorkersForTesting(StoragePartition* storage_partition, + base::OnceClosure callback); + +/////////////////////////////////////////////////////////////////////////////// +// The following methods are meant to be used from a renderer. + +// Turn a renderer into web test mode. +void EnableRendererWebTestMode(); + +// "Casts" |render_view| to |WebViewTestProxyBase|. Caller has to ensure that +// prior to construction of |render_view|, EnableWebTestProxyCreation was +// called. +test_runner::WebViewTestProxyBase* GetWebViewTestProxyBase( + RenderView* render_view); + +// "Casts" |render_frame| to |WebFrameTestProxyBase|. Caller has to ensure +// that prior to construction of |render_frame|, EnableTestProxyCreation +// was called. +test_runner::WebFrameTestProxyBase* GetWebFrameTestProxyBase( + RenderFrame* render_frame); + +// Gets WebWidgetTestProxyBase associated with |frame| (either the view's widget +// or the local root's frame widget). Caller has to ensure that prior to +// construction of |render_frame|, EnableTestProxyCreation was called. +test_runner::WebWidgetTestProxyBase* GetWebWidgetTestProxyBase( + blink::WebLocalFrame* frame); + +// Enable injecting of a WebViewTestProxy between WebViews and RenderViews, +// WebWidgetTestProxy between WebWidgets and RenderWidgets and WebFrameTestProxy +// between WebFrames and RenderFrames. +void EnableWebTestProxyCreation(); + +typedef base::OnceCallback<void(const GURL&, const blink::Manifest&)> + FetchManifestCallback; +void FetchManifest(blink::WebView* view, FetchManifestCallback callback); + +// Returns the length of the local session history of a render view. +int GetLocalSessionHistoryLength(RenderView* render_view); + +// Sets the focus of the render view depending on |enable|. This only overrides +// the state of the renderer, and does not sync the focus to the browser +// process. +void SetFocusAndActivate(RenderView* render_view, bool enable); + +// Changes the window rect of the given render view. +void ForceResizeRenderView(RenderView* render_view, + const blink::WebSize& new_size); + +// Set the device scale factor and force the compositor to resize. +void SetDeviceScaleFactor(RenderView* render_view, float factor); + +// Get the window to viewport scale. +float GetWindowToViewportScale(RenderView* render_view); + +// Converts |event| from screen coordinates to coordinates used by the widget +// associated with the |web_widget_test_proxy_base|. Returns nullptr if no +// transformation was necessary (e.g. for a keyboard event OR if widget requires +// no scaling and has coordinates starting at (0,0)). +std::unique_ptr<blink::WebInputEvent> TransformScreenToWidgetCoordinates( + test_runner::WebWidgetTestProxyBase* web_widget_test_proxy_base, + const blink::WebInputEvent& event); + +// Get the color space for a given name string. This is not in the ColorSpace +// class to avoid bloating the shipping build. +gfx::ColorSpace GetTestingColorSpace(const std::string& name); + +// Set the device color space. +void SetDeviceColorSpace(RenderView* render_view, + const gfx::ColorSpace& color_space); + +// Sets the scan duration to reflect the given setting. +enum class BluetoothTestScanDurationSetting { + kImmediateTimeout, // Set the scan duration to 0 seconds. + kNeverTimeout, // Set the scan duration to base::TimeDelta::Max() seconds. +}; +void SetTestBluetoothScanDuration(BluetoothTestScanDurationSetting setting); + +// Enables or disables synchronous resize mode. When enabled, all window-sizing +// machinery is short-circuited inside the renderer. This mode is necessary for +// some tests that were written before browsers had multi-process architecture +// and rely on window resizes to happen synchronously. +// See http://crbug.com/309760 for details. +void UseSynchronousResizeMode(RenderView* render_view, bool enable); + +// Control auto resize mode. +void EnableAutoResizeMode(RenderView* render_view, + const blink::WebSize& min_size, + const blink::WebSize& max_size); +void DisableAutoResizeMode(RenderView* render_view, + const blink::WebSize& new_size); + +// Run all pending idle tasks immediately, and then invoke callback. +void SchedulerRunIdleTasks(base::OnceClosure callback); + +// Causes the RenderWidget corresponding to |render_frame| to update its +// TextInputState. +void ForceTextInputStateUpdateForRenderFrame(RenderFrame* render_frame); + +// PlzNavigate +// Returns true if the navigation identified by the |request| was initiated by +// the browser or renderer. +bool IsNavigationInitiatedByRenderer(const blink::WebURLRequest& request); + +// RewriteURLFunction must be safe to call from any thread in the renderer +// process. +using RewriteURLFunction = blink::WebURL (*)(const std::string&, + bool is_wpt_mode); +void SetWorkerRewriteURLFunction(RewriteURLFunction rewrite_url_function); + +} // namespace content + +#endif // CONTENT_PUBLIC_TEST_WEB_TEST_SUPPORT_H_
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 16cba34e..c8d520e 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -173,16 +173,12 @@ "java/gin_java_bridge_value_converter.h", "java/gin_java_function_invocation_helper.cc", "java/gin_java_function_invocation_helper.h", - "layout_test_dependencies.cc", - "layout_test_dependencies.h", "loader/child_url_loader_factory_bundle.cc", "loader/child_url_loader_factory_bundle.h", "loader/code_cache_loader_impl.cc", "loader/code_cache_loader_impl.h", "loader/frame_request_blocker.cc", "loader/frame_request_blocker.h", - "loader/ftp_directory_listing_response_delegate.cc", - "loader/ftp_directory_listing_response_delegate.h", "loader/navigation_response_override_parameters.cc", "loader/navigation_response_override_parameters.h", "loader/request_extra_data.cc", @@ -564,12 +560,8 @@ "service_worker/web_service_worker_provider_impl.h", "shared_worker/embedded_shared_worker_stub.cc", "shared_worker/embedded_shared_worker_stub.h", - "shared_worker/shared_worker_client_impl.cc", - "shared_worker/shared_worker_client_impl.h", "shared_worker/shared_worker_factory_impl.cc", "shared_worker/shared_worker_factory_impl.h", - "shared_worker/shared_worker_repository.cc", - "shared_worker/shared_worker_repository.h", "skia_benchmarking_extension.cc", "skia_benchmarking_extension.h", "stats_collection_controller.cc", @@ -586,6 +578,8 @@ "v8_value_converter_impl.h", "web_database_observer_impl.cc", "web_database_observer_impl.h", + "web_test_dependencies.cc", + "web_test_dependencies.h", "web_ui_extension.cc", "web_ui_extension.h", "web_ui_extension_data.cc",
diff --git a/content/renderer/drop_data_builder.cc b/content/renderer/drop_data_builder.cc index 28ec9b1..1ffa4fa 100644 --- a/content/renderer/drop_data_builder.cc +++ b/content/renderer/drop_data_builder.cc
@@ -27,9 +27,7 @@ result.key_modifiers = drag_data.ModifierKeyState(); result.referrer_policy = network::mojom::ReferrerPolicy::kDefault; - const WebVector<WebDragData::Item>& item_list = drag_data.Items(); - for (size_t i = 0; i < item_list.size(); ++i) { - const WebDragData::Item& item = item_list[i]; + for (const WebDragData::Item& item : drag_data.Items()) { switch (item.storage_type) { case WebDragData::Item::kStorageTypeString: { base::string16 str_type(item.string_type.Utf16());
diff --git a/content/renderer/gpu/gpu_benchmarking_extension.cc b/content/renderer/gpu/gpu_benchmarking_extension.cc index 46026cf..23235a33 100644 --- a/content/renderer/gpu/gpu_benchmarking_extension.cc +++ b/content/renderer/gpu/gpu_benchmarking_extension.cc
@@ -1047,7 +1047,7 @@ // SyntheticPointerActionListParams object. ActionsParser actions_parser(value.get()); if (!actions_parser.ParsePointerActionSequence()) { - // TODO(dtapuska): Throw an error here, some layout tests start + // TODO(dtapuska): Throw an error here, some web tests start // failing when this is done though. // args->ThrowTypeError(actions_parser.error_message()); return false;
diff --git a/content/renderer/gpu/layer_tree_view.cc b/content/renderer/gpu/layer_tree_view.cc index cccbfea..dff7678 100644 --- a/content/renderer/gpu/layer_tree_view.cc +++ b/content/renderer/gpu/layer_tree_view.cc
@@ -202,7 +202,7 @@ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}); } if (!is_threaded) { - // Single-threaded layout tests, and unit tests. + // Single-threaded web tests, and unit tests. layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded(this, std::move(params)); } else { @@ -468,7 +468,7 @@ }, std::move(callback), std::move(main_thread_task_runner))); auto swap_promise = - delegate_->RequestCopyOfOutputForLayoutTest(std::move(request)); + delegate_->RequestCopyOfOutputForWebTest(std::move(request)); // Force a commit to happen. The temporary copy output request will // be installed after layout which will happen as a part of the commit, for @@ -504,7 +504,7 @@ return; if (in_synchronous_compositor_update_) { - // LayoutTests can use a nested message loop to pump frames while inside a + // Web tests can use a nested message loop to pump frames while inside a // frame, but the compositor does not support this. In this case, we only // run blink's lifecycle updates. delegate_->BeginMainFrame(base::TimeTicks::Now()); @@ -592,7 +592,7 @@ // If we're compositing synchronously, the SetNeedsCommit call which will be // issued by |layer_tree_host_| is not going to cause a commit, due to the - // fact that this would make layout tests slow and cause flakiness. However, + // fact that this would make web tests slow and cause flakiness. However, // in this case we actually need a commit to transfer the decode requests to // the impl side. So, force a commit to happen. if (CompositeIsSynchronous()) {
diff --git a/content/renderer/gpu/layer_tree_view_delegate.h b/content/renderer/gpu/layer_tree_view_delegate.h index 06dfd95..4d8a2188 100644 --- a/content/renderer/gpu/layer_tree_view_delegate.h +++ b/content/renderer/gpu/layer_tree_view_delegate.h
@@ -77,9 +77,9 @@ // perform actual painting work. virtual void WillBeginCompositorFrame() = 0; - // For use in layout test mode only, attempts to copy the full content of the + // For use in web test mode only, attempts to copy the full content of the // compositor. - virtual std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForLayoutTest( + virtual std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForWebTest( std::unique_ptr<viz::CopyOutputRequest> request) = 0; protected:
diff --git a/content/renderer/java/gin_java_bridge_value_converter.cc b/content/renderer/java/gin_java_bridge_value_converter.cc index 3d929ed..70d1160 100644 --- a/content/renderer/java/gin_java_bridge_value_converter.cc +++ b/content/renderer/java/gin_java_bridge_value_converter.cc
@@ -45,7 +45,7 @@ v8::Local<v8::Object> value, std::unique_ptr<base::Value>* out, v8::Isolate* isolate, - const FromV8ValueCallback& callback) const { + const FromV8ValueCallback& callback) { GinJavaBridgeObject* unwrapped; if (!gin::ConvertFromV8(isolate, value, &unwrapped)) { return false; @@ -123,7 +123,7 @@ bool GinJavaBridgeValueConverter::FromV8ArrayBuffer( v8::Local<v8::Object> value, std::unique_ptr<base::Value>* out, - v8::Isolate* isolate) const { + v8::Isolate* isolate) { if (!value->IsTypedArray()) { *out = GinJavaBridgeValue::CreateUndefinedValue(); return true; @@ -151,7 +151,7 @@ bool GinJavaBridgeValueConverter::FromV8Number( v8::Local<v8::Number> value, - std::unique_ptr<base::Value>* out) const { + std::unique_ptr<base::Value>* out) { double double_value = value->Value(); if (std::isfinite(double_value)) return false; @@ -160,7 +160,7 @@ } bool GinJavaBridgeValueConverter::FromV8Undefined( - std::unique_ptr<base::Value>* out) const { + std::unique_ptr<base::Value>* out) { *out = GinJavaBridgeValue::CreateUndefinedValue(); return true; }
diff --git a/content/renderer/java/gin_java_bridge_value_converter.h b/content/renderer/java/gin_java_bridge_value_converter.h index d1f0310c..1f42b60 100644 --- a/content/renderer/java/gin_java_bridge_value_converter.h +++ b/content/renderer/java/gin_java_bridge_value_converter.h
@@ -29,13 +29,13 @@ bool FromV8Object(v8::Local<v8::Object> value, std::unique_ptr<base::Value>* out, v8::Isolate* isolate, - const FromV8ValueCallback& callback) const override; + const FromV8ValueCallback& callback) override; bool FromV8ArrayBuffer(v8::Local<v8::Object> value, std::unique_ptr<base::Value>* out, - v8::Isolate* isolate) const override; + v8::Isolate* isolate) override; bool FromV8Number(v8::Local<v8::Number> value, - std::unique_ptr<base::Value>* out) const override; - bool FromV8Undefined(std::unique_ptr<base::Value>* out) const override; + std::unique_ptr<base::Value>* out) override; + bool FromV8Undefined(std::unique_ptr<base::Value>* out) override; private: std::unique_ptr<V8ValueConverter> converter_;
diff --git a/content/renderer/layout_test_dependencies.cc b/content/renderer/layout_test_dependencies.cc deleted file mode 100644 index 200da44..0000000 --- a/content/renderer/layout_test_dependencies.cc +++ /dev/null
@@ -1,9 +0,0 @@ -// Copyright 2016 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/layout_test_dependencies.h" - -namespace content { -LayoutTestDependencies::~LayoutTestDependencies() {} -} // namespace content
diff --git a/content/renderer/layout_test_dependencies.h b/content/renderer/layout_test_dependencies.h deleted file mode 100644 index 4e556d87..0000000 --- a/content/renderer/layout_test_dependencies.h +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2016 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_RENDER_LAYOUT_TEST_DEPENDENCIES_H_ -#define CONTENT_RENDER_LAYOUT_TEST_DEPENDENCIES_H_ - -#include <stdint.h> -#include <memory> - -#include "base/memory/ref_counted.h" -#include "components/viz/common/frame_sinks/copy_output_request.h" -#include "content/common/content_export.h" - -namespace cc { -class CopyOutputRequest; -class LayerTreeFrameSink; -class SwapPromise; -} - -namespace gpu { -class GpuChannelHost; -class GpuMemoryBufferManager; -} - -namespace viz { -class ContextProvider; -class RasterContextProvider; -} - -namespace content { -class CompositorDependencies; - -// This class allows injection of LayoutTest-specific behaviour to the -// RenderThreadImpl. -class CONTENT_EXPORT LayoutTestDependencies { - public: - virtual ~LayoutTestDependencies(); - - // Returns true if the layout tests should use the display compositor pixel - // dumps. - virtual bool UseDisplayCompositorPixelDump() const = 0; - - virtual std::unique_ptr<cc::LayerTreeFrameSink> CreateLayerTreeFrameSink( - int32_t routing_id, - scoped_refptr<gpu::GpuChannelHost> gpu_channel, - scoped_refptr<viz::ContextProvider> compositor_context_provider, - scoped_refptr<viz::RasterContextProvider> worker_context_provider, - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, - CompositorDependencies* deps) = 0; - - // Returns a SwapPromise which should be queued for the next compositor frame. - virtual std::unique_ptr<cc::SwapPromise> RequestCopyOfOutput( - int32_t routing_id, - std::unique_ptr<viz::CopyOutputRequest> request) = 0; -}; - -} // namespace content - -#endif // CONTENT_RENDER_LAYOUT_TEST_DEPENDENCIES_H_
diff --git a/content/renderer/loader/ftp_directory_listing_response_delegate.cc b/content/renderer/loader/ftp_directory_listing_response_delegate.cc deleted file mode 100644 index 05a3b203..0000000 --- a/content/renderer/loader/ftp_directory_listing_response_delegate.cc +++ /dev/null
@@ -1,134 +0,0 @@ -// Copyright 2014 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/loader/ftp_directory_listing_response_delegate.h" - -#include <stddef.h> -#include <stdint.h> - -#include <vector> - -#include "base/i18n/encoding_detection.h" -#include "base/i18n/icu_string_conversions.h" -#include "base/logging.h" -#include "base/strings/string_util.h" -#include "base/strings/sys_string_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "base/time/time.h" -#include "content/renderer/loader/weburlresponse_extradata_impl.h" -#include "net/base/directory_listing.h" -#include "net/base/escape.h" -#include "net/base/net_errors.h" -#include "net/ftp/ftp_directory_listing_parser.h" -#include "net/net_buildflags.h" -#include "third_party/blink/public/platform/web_url.h" -#include "third_party/blink/public/platform/web_url_loader_client.h" - -using blink::WebURLLoader; -using blink::WebURLLoaderClient; -using blink::WebURLResponse; -using net::FtpDirectoryListingEntry; - -namespace { - -base::string16 ConvertPathToUTF16(const std::string& path) { - // Per RFC 2640, FTP servers should use UTF-8 or its proper subset ASCII, - // but many old FTP servers use legacy encodings. Try UTF-8 first. - if (base::IsStringUTF8(path)) - return base::UTF8ToUTF16(path); - - // Try detecting the encoding. The sample is rather small though, so it may - // fail. - std::string encoding; - if (base::DetectEncoding(path, &encoding) && encoding != "US-ASCII") { - base::string16 path_utf16; - if (base::CodepageToUTF16(path, encoding.c_str(), - base::OnStringConversionError::SUBSTITUTE, - &path_utf16)) { - return path_utf16; - } - } - - // Use system native encoding as the last resort. - return base::WideToUTF16(base::SysNativeMBToWide(path)); -} - -} // namespace - -namespace content { - -FtpDirectoryListingResponseDelegate::FtpDirectoryListingResponseDelegate( - WebURLLoaderClient* client, - WebURLLoader* loader, - const WebURLResponse& response) - : client_(client), - loader_(loader) { - if (response.GetExtraData()) { - // |extra_data| can be NULL during tests. - WebURLResponseExtraDataImpl* extra_data = - static_cast<WebURLResponseExtraDataImpl*>(response.GetExtraData()); - extra_data->set_is_ftp_directory_listing(true); - } - Init(response.CurrentRequestUrl()); -} - -void FtpDirectoryListingResponseDelegate::Cancel() { - client_ = nullptr; - loader_ = nullptr; -} - -void FtpDirectoryListingResponseDelegate::OnReceivedData(const char* data, - int data_len) { - buffer_.append(data, data_len); -} - -void FtpDirectoryListingResponseDelegate::OnCompletedRequest() { - std::vector<FtpDirectoryListingEntry> entries; - int rv = net::ERR_NOT_IMPLEMENTED; -#if !BUILDFLAG(DISABLE_FTP_SUPPORT) - rv = net::ParseFtpDirectoryListing(buffer_, base::Time::Now(), &entries); -#endif - if (rv != net::OK) { - SendDataToClient("<script>onListingParsingError();</script>\n"); - return; - } - for (const FtpDirectoryListingEntry& entry : entries) { - // Skip the current and parent directory entries in the listing. - // net::GetParentDirectoryLink() takes care of them. - if (base::EqualsASCII(entry.name, ".") || - base::EqualsASCII(entry.name, "..")) - continue; - - bool is_directory = (entry.type == FtpDirectoryListingEntry::DIRECTORY); - int64_t size = - entry.type == FtpDirectoryListingEntry::FILE ? entry.size : 0; - SendDataToClient(net::GetDirectoryListingEntry( - entry.name, entry.raw_name, is_directory, size, entry.last_modified)); - } -} - -void FtpDirectoryListingResponseDelegate::Init(const GURL& response_url) { - net::UnescapeRule::Type unescape_rules = - net::UnescapeRule::SPACES | - net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS; - std::string unescaped_path = net::UnescapeURLComponent(response_url.path(), - unescape_rules); - SendDataToClient(net::GetDirectoryListingHeader( - ConvertPathToUTF16(unescaped_path))); - - // If this isn't top level directory (i.e. the path isn't "/",) - // add a link to the parent directory. - if (response_url.path().length() > 1) { - SendDataToClient(net::GetParentDirectoryLink()); - } -} - -void FtpDirectoryListingResponseDelegate::SendDataToClient( - const std::string& data) { - if (client_) { - client_->DidReceiveData(data.data(), data.length()); - } -} - -} // namespace content
diff --git a/content/renderer/loader/ftp_directory_listing_response_delegate.h b/content/renderer/loader/ftp_directory_listing_response_delegate.h deleted file mode 100644 index 19212cc9f..0000000 --- a/content/renderer/loader/ftp_directory_listing_response_delegate.h +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2014 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. -// -// A delegate class of WebURLLoaderImpl that handles text/vnd.chromium.ftp-dir -// data. - -#ifndef CONTENT_RENDERER_LOADER_FTP_DIRECTORY_LISTING_RESPONSE_DELEGATE_H_ -#define CONTENT_RENDERER_LOADER_FTP_DIRECTORY_LISTING_RESPONSE_DELEGATE_H_ - -#include <string> - -#include "base/macros.h" -#include "third_party/blink/public/platform/web_url_response.h" - -namespace blink { -class WebURLLoader; -class WebURLLoaderClient; -} - -class GURL; - -namespace content { - -class FtpDirectoryListingResponseDelegate { - public: - FtpDirectoryListingResponseDelegate(blink::WebURLLoaderClient* client, - blink::WebURLLoader* loader, - const blink::WebURLResponse& response); - - // The request has been canceled, so stop making calls to the client. - void Cancel(); - - // Passed through from ResourceHandleInternal - void OnReceivedData(const char* data, int data_len); - void OnCompletedRequest(); - - private: - void Init(const GURL& response_url); - - void SendDataToClient(const std::string& data); - - // Pointers to the client and associated loader so we can make callbacks as - // we parse pieces of data. - blink::WebURLLoaderClient* client_; - blink::WebURLLoader* loader_; - - // Buffer for data received from the network. - std::string buffer_; - - DISALLOW_COPY_AND_ASSIGN(FtpDirectoryListingResponseDelegate); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_LOADER_FTP_DIRECTORY_LISTING_RESPONSE_DELEGATE_H_
diff --git a/content/renderer/loader/resource_dispatcher_unittest.cc b/content/renderer/loader/resource_dispatcher_unittest.cc index c32ad585..66713bf 100644 --- a/content/renderer/loader/resource_dispatcher_unittest.cc +++ b/content/renderer/loader/resource_dispatcher_unittest.cc
@@ -197,7 +197,7 @@ } original_peer_->OnCompletedRequest(status); } - scoped_refptr<base::TaskRunner> GetTaskRunner() const override { + scoped_refptr<base::TaskRunner> GetTaskRunner() override { return blink::scheduler::GetSingleThreadTaskRunnerForTesting(); }
diff --git a/content/renderer/loader/shared_memory_data_consumer_handle.cc b/content/renderer/loader/shared_memory_data_consumer_handle.cc index 5a6c577..ae994d2 100644 --- a/content/renderer/loader/shared_memory_data_consumer_handle.cc +++ b/content/renderer/loader/shared_memory_data_consumer_handle.cc
@@ -34,8 +34,8 @@ } } - const char* payload() const override { return data_->payload(); } - int length() const override { return data_->length(); } + const char* payload() override { return data_->payload(); } + int length() override { return data_->length(); } private: std::unique_ptr<RequestPeer::ReceivedData> data_;
diff --git a/content/renderer/loader/shared_memory_data_consumer_handle_unittest.cc b/content/renderer/loader/shared_memory_data_consumer_handle_unittest.cc index 711942c..1792ae8b7 100644 --- a/content/renderer/loader/shared_memory_data_consumer_handle_unittest.cc +++ b/content/renderer/loader/shared_memory_data_consumer_handle_unittest.cc
@@ -79,10 +79,8 @@ logger_->Add(name_ + " is destructed."); } - const char* payload() const override { - return data_.empty() ? nullptr : &data_[0]; - } - int length() const override { return static_cast<int>(data_.size()); } + const char* payload() override { return data_.empty() ? nullptr : &data_[0]; } + int length() override { return static_cast<int>(data_.size()); } private: const std::string name_;
diff --git a/content/renderer/loader/sync_load_context.cc b/content/renderer/loader/sync_load_context.cc index 62adce5..fcb1472 100644 --- a/content/renderer/loader/sync_load_context.cc +++ b/content/renderer/loader/sync_load_context.cc
@@ -217,7 +217,7 @@ CompleteRequest(true /* remove_pending_request */); } -scoped_refptr<base::TaskRunner> SyncLoadContext::GetTaskRunner() const { +scoped_refptr<base::TaskRunner> SyncLoadContext::GetTaskRunner() { return task_runner_; }
diff --git a/content/renderer/loader/sync_load_context.h b/content/renderer/loader/sync_load_context.h index 4580bfb4..64ef44e1 100644 --- a/content/renderer/loader/sync_load_context.h +++ b/content/renderer/loader/sync_load_context.h
@@ -79,7 +79,7 @@ void OnTransferSizeUpdated(int transfer_size_diff) override; void OnCompletedRequest( const network::URLLoaderCompletionStatus& status) override; - scoped_refptr<base::TaskRunner> GetTaskRunner() const override; + scoped_refptr<base::TaskRunner> GetTaskRunner() override; void OnFinishCreatingBlob(blink::mojom::SerializedBlobPtr blob);
diff --git a/content/renderer/loader/test_request_peer.cc b/content/renderer/loader/test_request_peer.cc index 2318d3dc..751c5ee 100644 --- a/content/renderer/loader/test_request_peer.cc +++ b/content/renderer/loader/test_request_peer.cc
@@ -98,7 +98,7 @@ context_->completion_status = status; } -scoped_refptr<base::TaskRunner> TestRequestPeer::GetTaskRunner() const { +scoped_refptr<base::TaskRunner> TestRequestPeer::GetTaskRunner() { return blink::scheduler::GetSingleThreadTaskRunnerForTesting(); }
diff --git a/content/renderer/loader/test_request_peer.h b/content/renderer/loader/test_request_peer.h index a19eb97..dfc29e4 100644 --- a/content/renderer/loader/test_request_peer.h +++ b/content/renderer/loader/test_request_peer.h
@@ -46,7 +46,7 @@ void OnReceivedCachedMetadata(const char* data, int len) override; void OnCompletedRequest( const network::URLLoaderCompletionStatus& status) override; - scoped_refptr<base::TaskRunner> GetTaskRunner() const override; + scoped_refptr<base::TaskRunner> GetTaskRunner() override; struct Context final { Context();
diff --git a/content/renderer/loader/url_loader_client_impl.cc b/content/renderer/loader/url_loader_client_impl.cc index f9d5578..faeb453 100644 --- a/content/renderer/loader/url_loader_client_impl.cc +++ b/content/renderer/loader/url_loader_client_impl.cc
@@ -234,7 +234,7 @@ void URLLoaderClientImpl::OnReceiveResponse( const network::ResourceResponseHead& response_head) { - has_received_response_ = true; + has_received_response_head_ = true; if (NeedsStoringMessage()) { StoreAndDispatch( std::make_unique<DeferredOnReceiveResponse>(response_head)); @@ -246,7 +246,7 @@ void URLLoaderClientImpl::OnReceiveRedirect( const net::RedirectInfo& redirect_info, const network::ResourceResponseHead& response_head) { - DCHECK(!has_received_response_); + DCHECK(!has_received_response_head_); DCHECK(!body_consumer_); if (base::FeatureList::IsEnabled(network::features::kNetworkService) && !bypass_redirect_checks_ && @@ -300,7 +300,9 @@ void URLLoaderClientImpl::OnStartLoadingResponseBody( mojo::ScopedDataPipeConsumerHandle body) { DCHECK(!body_consumer_); - DCHECK(has_received_response_); + DCHECK(has_received_response_head_); + DCHECK(!has_received_response_body_); + has_received_response_body_ = true; if (pass_response_pipe_to_dispatcher_) { resource_dispatcher_->OnStartLoadingResponseBody(request_id_, @@ -323,6 +325,8 @@ const network::URLLoaderCompletionStatus& status) { has_received_complete_ = true; if (!body_consumer_) { + // Except for errors, there must always be a response's body. + DCHECK(has_received_response_body_ || status.error_code != net::OK); if (NeedsStoringMessage()) { StoreAndDispatch(std::make_unique<DeferredOnComplete>(status)); } else {
diff --git a/content/renderer/loader/url_loader_client_impl.h b/content/renderer/loader/url_loader_client_impl.h index 8ebd277..ba980c8 100644 --- a/content/renderer/loader/url_loader_client_impl.h +++ b/content/renderer/loader/url_loader_client_impl.h
@@ -98,7 +98,8 @@ scoped_refptr<URLResponseBodyConsumer> body_consumer_; std::vector<std::unique_ptr<DeferredMessage>> deferred_messages_; const int request_id_; - bool has_received_response_ = false; + bool has_received_response_head_ = false; + bool has_received_response_body_ = false; bool has_received_complete_ = false; bool is_deferred_ = false; bool pass_response_pipe_to_dispatcher_ = false;
diff --git a/content/renderer/loader/url_loader_client_impl_unittest.cc b/content/renderer/loader/url_loader_client_impl_unittest.cc index 1ee557c..4ecade12 100644 --- a/content/renderer/loader/url_loader_client_impl_unittest.cc +++ b/content/renderer/loader/url_loader_client_impl_unittest.cc
@@ -156,20 +156,6 @@ EXPECT_EQ(8, request_peer_context_.total_encoded_data_length); } -TEST_F(URLLoaderClientImplTest, OnCompleteWithoutResponseBody) { - network::ResourceResponseHead response_head; - network::URLLoaderCompletionStatus status; - - url_loader_client_->OnReceiveResponse(response_head); - url_loader_client_->OnComplete(status); - - EXPECT_FALSE(request_peer_context_.received_response); - EXPECT_FALSE(request_peer_context_.complete); - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(request_peer_context_.received_response); - EXPECT_TRUE(request_peer_context_.complete); -} - TEST_F(URLLoaderClientImplTest, OnCompleteWithResponseBody) { network::ResourceResponseHead response_head; network::URLLoaderCompletionStatus status; @@ -291,6 +277,10 @@ network::URLLoaderCompletionStatus status; url_loader_client_->OnReceiveResponse(response_head); + mojo::DataPipe data_pipe; + data_pipe.producer_handle.reset(); // Empty body. + url_loader_client_->OnStartLoadingResponseBody( + std::move(data_pipe.consumer_handle)); url_loader_client_->OnComplete(status); EXPECT_FALSE(request_peer_context_.received_response); @@ -466,6 +456,10 @@ network::URLLoaderCompletionStatus status; url_loader_client_->OnReceiveResponse(response_head); + mojo::DataPipe data_pipe; + data_pipe.producer_handle.reset(); // Empty body. + url_loader_client_->OnStartLoadingResponseBody( + std::move(data_pipe.consumer_handle)); url_loader_client_->OnTransferSizeUpdated(4); url_loader_client_->OnComplete(status);
diff --git a/content/renderer/loader/url_response_body_consumer.cc b/content/renderer/loader/url_response_body_consumer.cc index f5ac29b..9a99b40 100644 --- a/content/renderer/loader/url_response_body_consumer.cc +++ b/content/renderer/loader/url_response_body_consumer.cc
@@ -25,8 +25,8 @@ ~ReceivedData() override { consumer_->Reclaim(length_); } - const char* payload() const override { return payload_; } - int length() const override { return length_; } + const char* payload() override { return payload_; } + int length() override { return length_; } private: const char* const payload_;
diff --git a/content/renderer/loader/url_response_body_consumer_unittest.cc b/content/renderer/loader/url_response_body_consumer_unittest.cc index 7def49e..95954e1 100644 --- a/content/renderer/loader/url_response_body_consumer_unittest.cc +++ b/content/renderer/loader/url_response_body_consumer_unittest.cc
@@ -72,7 +72,7 @@ context_->error_code = status.error_code; context_->run_loop_quit_closure.Run(); } - scoped_refptr<base::TaskRunner> GetTaskRunner() const override { + scoped_refptr<base::TaskRunner> GetTaskRunner() override { return blink::scheduler::GetSingleThreadTaskRunnerForTesting(); }
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc index 41dc0627..e1070e88 100644 --- a/content/renderer/loader/web_url_loader_impl.cc +++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -31,7 +31,6 @@ #include "content/public/common/referrer.h" #include "content/public/renderer/fixed_received_data.h" #include "content/public/renderer/request_peer.h" -#include "content/renderer/loader/ftp_directory_listing_response_delegate.h" #include "content/renderer/loader/request_extra_data.h" #include "content/renderer/loader/resource_dispatcher.h" #include "content/renderer/loader/shared_memory_data_consumer_handle.h" @@ -447,7 +446,6 @@ ResourceDispatcher* resource_dispatcher_; std::unique_ptr<WebResourceLoadingTaskRunnerHandle> task_runner_handle_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - std::unique_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_; std::unique_ptr<SharedMemoryDataConsumerHandle::Writer> body_stream_writer_; mojom::KeepAliveHandlePtr keep_alive_handle_; enum DeferState {NOT_DEFERRING, SHOULD_DEFER, DEFERRED_DATA}; @@ -478,7 +476,7 @@ void OnReceivedCachedMetadata(const char* data, int len) override; void OnCompletedRequest( const network::URLLoaderCompletionStatus& status) override; - scoped_refptr<base::TaskRunner> GetTaskRunner() const override { + scoped_refptr<base::TaskRunner> GetTaskRunner() override { return context_->task_runner(); } @@ -510,7 +508,7 @@ context_->resource_dispatcher()->Cancel(context_->request_id(), context_->task_runner()); } - scoped_refptr<base::TaskRunner> GetTaskRunner() const override { + scoped_refptr<base::TaskRunner> GetTaskRunner() override { return context_->task_runner(); } @@ -553,11 +551,6 @@ if (body_stream_writer_) body_stream_writer_->Fail(); - // Ensure that we do not notify the delegate anymore as it has - // its own pointer to the client. - if (ftp_listing_delegate_) - ftp_listing_delegate_->Cancel(); - // Do not make any further calls to the client. client_ = nullptr; loader_ = nullptr; @@ -648,6 +641,7 @@ resource_request->method = method; resource_request->url = url_; resource_request->site_for_cookies = request.SiteForCookies(); + resource_request->top_frame_origin = request.TopFrameOrigin(); resource_request->upgrade_if_insecure = request.UpgradeIfInsecure(); resource_request->is_revalidating = request.IsRevalidating(); if (!request.RequestorOrigin().IsNull()) { @@ -825,6 +819,7 @@ url_ = WebURL(redirect_info.new_url); return client_->WillFollowRedirect( url_, redirect_info.new_site_for_cookies, + redirect_info.new_top_frame_origin, WebString::FromUTF8(redirect_info.new_referrer), Referrer::NetReferrerPolicyToBlinkReferrerPolicy( redirect_info.new_referrer_policy), @@ -844,17 +839,6 @@ WebURLResponse response; PopulateURLResponse(url_, info, &response, report_raw_headers_, request_id_); - bool show_raw_listing = false; - if (info.mime_type == "text/vnd.chromium.ftp-dir") { - if (GURL(url_).query_piece() == "raw") { - // Set the MIME type to plain text to prevent any active content. - response.SetMIMEType("text/plain"); - show_raw_listing = true; - } else { - // We're going to produce a parsed listing in HTML. - response.SetMIMEType("text/html"); - } - } if (info.headers.get() && info.mime_type == "multipart/x-mixed-replace") { std::string content_type; info.headers->EnumerateHeader(nullptr, "content-type", &content_type); @@ -897,13 +881,6 @@ // go away. if (!client_) return; - - DCHECK(!ftp_listing_delegate_); - if (info.mime_type == "text/vnd.chromium.ftp-dir" && !show_raw_listing) { - ftp_listing_delegate_ = - std::make_unique<FtpDirectoryListingResponseDelegate>(client_, loader_, - response); - } } void WebURLLoaderImpl::Context::OnStartLoadingResponseBody( @@ -923,20 +900,11 @@ "loading", "WebURLLoaderImpl::Context::OnReceivedData", this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); - if (ftp_listing_delegate_) { - // The FTP listing delegate will make the appropriate calls to - // client_->didReceiveData and client_->didReceiveResponse. - ftp_listing_delegate_->OnReceivedData(payload, data_length); - return; - } - // We dispatch the data even when |useStreamOnResponse()| is set, in order // to make Devtools work. client_->DidReceiveData(payload, data_length); if (use_stream_on_response_) { - // We don't support |ftp_listing_delegate_| for now. - // TODO(yhirano): Support ftp listening. body_stream_writer_->AddData(std::move(data)); } } @@ -960,11 +928,6 @@ int64_t total_transfer_size = status.encoded_data_length; int64_t encoded_body_size = status.encoded_body_length; - if (ftp_listing_delegate_) { - ftp_listing_delegate_->OnCompletedRequest(); - ftp_listing_delegate_.reset(nullptr); - } - if (body_stream_writer_ && status.error_code != net::OK) body_stream_writer_->Fail(); body_stream_writer_.reset(); @@ -1002,12 +965,6 @@ void WebURLLoaderImpl::Context::CancelBodyStreaming() { scoped_refptr<Context> protect(this); - // Notify renderer clients that the request is canceled. - if (ftp_listing_delegate_) { - ftp_listing_delegate_->OnCompletedRequest(); - ftp_listing_delegate_.reset(nullptr); - } - if (body_stream_writer_) { body_stream_writer_->Fail(); body_stream_writer_.reset();
diff --git a/content/renderer/loader/web_url_loader_impl_unittest.cc b/content/renderer/loader/web_url_loader_impl_unittest.cc index 59b60ea3..0af9e414 100644 --- a/content/renderer/loader/web_url_loader_impl_unittest.cc +++ b/content/renderer/loader/web_url_loader_impl_unittest.cc
@@ -55,14 +55,6 @@ const char kTestHTTPSURL[] = "https://foo"; const char kTestData[] = "blah!"; -const char kFtpDirMimeType[] = "text/vnd.chromium.ftp-dir"; -// Simple FTP directory listing. Tests are not concerned with correct parsing, -// but rather correct cleanup when deleted while parsing. Important details of -// this list are that it contains more than one entry that are not "." or "..". -const char kFtpDirListing[] = - "drwxr-xr-x 3 ftp ftp 4096 May 15 18:11 goat\n" - "drwxr-xr-x 3 ftp ftp 4096 May 15 18:11 hat"; - class TestResourceDispatcher : public ResourceDispatcher { public: TestResourceDispatcher() : canceled_(false), defers_loading_(false) {} @@ -193,13 +185,15 @@ ~TestWebURLLoaderClient() override {} // blink::WebURLLoaderClient implementation: - bool WillFollowRedirect(const blink::WebURL& new_url, - const blink::WebURL& new_site_for_cookies, - const blink::WebString& new_referrer, - network::mojom::ReferrerPolicy new_referrer_policy, - const blink::WebString& new_method, - const blink::WebURLResponse& passed_redirect_response, - bool& report_raw_headers) override { + bool WillFollowRedirect( + const blink::WebURL& new_url, + const blink::WebURL& new_site_for_cookies, + const base::Optional<blink::WebSecurityOrigin>& new_top_frame_origin, + const blink::WebString& new_referrer, + network::mojom::ReferrerPolicy new_referrer_policy, + const blink::WebString& new_method, + const blink::WebURLResponse& passed_redirect_response, + bool& report_raw_headers) override { EXPECT_TRUE(loader_); // No test currently simulates mutiple redirects. @@ -391,22 +385,6 @@ EXPECT_EQ(net::ERR_FAILED, client()->error()->reason()); } - void DoReceiveResponseFtp() { - EXPECT_FALSE(client()->did_receive_response()); - network::ResourceResponseInfo response_info; - response_info.mime_type = kFtpDirMimeType; - peer()->OnReceivedResponse(response_info); - EXPECT_TRUE(client()->did_receive_response()); - } - - void DoReceiveDataFtp() { - auto size = strlen(kFtpDirListing); - peer()->OnReceivedData( - std::make_unique<FixedReceivedData>(kFtpDirListing, size)); - // The FTP delegate should modify the data the client sees. - EXPECT_NE(kFtpDirListing, client()->received_data()); - } - TestWebURLLoaderClient* client() { return client_.get(); } TestResourceDispatcher* dispatcher() { return &dispatcher_; } RequestPeer* peer() { return dispatcher()->peer(); } @@ -572,67 +550,6 @@ EXPECT_TRUE(dispatcher()->defers_loading()); } -// FTP integration tests. These are focused more on safe deletion than correct -// parsing of FTP responses. - -TEST_F(WebURLLoaderImplTest, Ftp) { - DoStartAsyncRequest(); - DoReceiveResponseFtp(); - DoReceiveDataFtp(); - DoCompleteRequest(); - EXPECT_FALSE(dispatcher()->canceled()); -} - -TEST_F(WebURLLoaderImplTest, FtpDeleteOnReceiveResponse) { - client()->set_delete_on_receive_response(); - DoStartAsyncRequest(); - DoReceiveResponseFtp(); - - // No data should have been received. - EXPECT_EQ("", client()->received_data()); -} - -TEST_F(WebURLLoaderImplTest, FtpDeleteOnReceiveFirstData) { - client()->set_delete_on_receive_data(); - DoStartAsyncRequest(); - DoReceiveResponseFtp(); - - EXPECT_NE("", client()->received_data()); -} - -TEST_F(WebURLLoaderImplTest, FtpDeleteOnReceiveMoreData) { - DoStartAsyncRequest(); - DoReceiveResponseFtp(); - DoReceiveDataFtp(); - - // Directory listings are only parsed once the request completes, so this will - // cancel in DoReceiveDataFtp, before the request finishes. - client()->set_delete_on_receive_data(); - - network::URLLoaderCompletionStatus status(net::OK); - status.encoded_data_length = arraysize(kTestData); - status.encoded_body_length = arraysize(kTestData); - status.decoded_body_length = arraysize(kTestData); - peer()->OnCompletedRequest(status); - EXPECT_FALSE(client()->did_finish()); -} - -TEST_F(WebURLLoaderImplTest, FtpDeleteOnFinish) { - client()->set_delete_on_finish(); - DoStartAsyncRequest(); - DoReceiveResponseFtp(); - DoReceiveDataFtp(); - DoCompleteRequest(); -} - -TEST_F(WebURLLoaderImplTest, FtpDeleteOnFail) { - client()->set_delete_on_fail(); - DoStartAsyncRequest(); - DoReceiveResponseFtp(); - DoReceiveDataFtp(); - DoFailRequest(); -} - // Checks that the navigation response override parameters provided on // navigation commit are properly applied. TEST_F(WebURLLoaderImplTest, BrowserSideNavigationCommit) {
diff --git a/content/renderer/loader/weburlresponse_extradata_impl.cc b/content/renderer/loader/weburlresponse_extradata_impl.cc index c30ad8e..ef94567 100644 --- a/content/renderer/loader/weburlresponse_extradata_impl.cc +++ b/content/renderer/loader/weburlresponse_extradata_impl.cc
@@ -7,8 +7,7 @@ namespace content { WebURLResponseExtraDataImpl::WebURLResponseExtraDataImpl() - : is_ftp_directory_listing_(false), - effective_connection_type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN) {} + : effective_connection_type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN) {} WebURLResponseExtraDataImpl::~WebURLResponseExtraDataImpl() { }
diff --git a/content/renderer/loader/weburlresponse_extradata_impl.h b/content/renderer/loader/weburlresponse_extradata_impl.h index aa5e687..ae5f3ee4 100644 --- a/content/renderer/loader/weburlresponse_extradata_impl.h +++ b/content/renderer/loader/weburlresponse_extradata_impl.h
@@ -49,11 +49,6 @@ was_alternate_protocol_available_ = was_alternate_protocol_available; } - bool is_ftp_directory_listing() const { return is_ftp_directory_listing_; } - void set_is_ftp_directory_listing(bool is_ftp_directory_listing) { - is_ftp_directory_listing_ = is_ftp_directory_listing; - } - net::EffectiveConnectionType effective_connection_type() const { return effective_connection_type_; } @@ -63,7 +58,6 @@ } private: - bool is_ftp_directory_listing_; bool was_fetched_via_spdy_; bool was_alpn_negotiated_; bool was_alternate_protocol_available_;
diff --git a/content/renderer/media/media_factory.cc b/content/renderer/media/media_factory.cc index 9df20fe..4d16316 100644 --- a/content/renderer/media/media_factory.cc +++ b/content/renderer/media/media_factory.cc
@@ -143,8 +143,8 @@ // See https://crbug.com/838128 content::RenderThreadImpl* render_thread = content::RenderThreadImpl::current(); - if (render_thread && render_thread->layout_test_mode() && - !render_thread->LayoutTestModeUsesDisplayCompositorPixelDump()) { + if (render_thread && render_thread->web_test_mode() && + !render_thread->WebTestModeUsesDisplayCompositorPixelDump()) { return blink::WebMediaPlayer::SurfaceLayerMode::kNever; }
diff --git a/content/renderer/media/render_media_client.cc b/content/renderer/media/render_media_client.cc index 6447901c..10061f18 100644 --- a/content/renderer/media/render_media_client.cc +++ b/content/renderer/media/render_media_client.cc
@@ -34,14 +34,12 @@ return GetContentClient()->renderer()->IsKeySystemsUpdateNeeded(); } -bool RenderMediaClient::IsSupportedAudioConfig( - const media::AudioConfig& config) { - return GetContentClient()->renderer()->IsSupportedAudioConfig(config); +bool RenderMediaClient::IsSupportedAudioType(const media::AudioType& type) { + return GetContentClient()->renderer()->IsSupportedAudioType(type); } -bool RenderMediaClient::IsSupportedVideoConfig( - const media::VideoConfig& config) { - return GetContentClient()->renderer()->IsSupportedVideoConfig(config); +bool RenderMediaClient::IsSupportedVideoType(const media::VideoType& type) { + return GetContentClient()->renderer()->IsSupportedVideoType(type); } bool RenderMediaClient::IsSupportedBitstreamAudioCodec(
diff --git a/content/renderer/media/render_media_client.h b/content/renderer/media/render_media_client.h index 2fd7c65..eeb99cc 100644 --- a/content/renderer/media/render_media_client.h +++ b/content/renderer/media/render_media_client.h
@@ -23,8 +23,8 @@ std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) final; bool IsKeySystemsUpdateNeeded() final; - bool IsSupportedAudioConfig(const media::AudioConfig& config) final; - bool IsSupportedVideoConfig(const media::VideoConfig& config) final; + bool IsSupportedAudioType(const media::AudioType& type) final; + bool IsSupportedVideoType(const media::VideoType& type) final; bool IsSupportedBitstreamAudioCodec(media::AudioCodec codec) final; private:
diff --git a/content/renderer/media/stream/media_stream_constraints_util_audio.cc b/content/renderer/media/stream/media_stream_constraints_util_audio.cc index 99a41b43..01162296 100644 --- a/content/renderer/media/stream/media_stream_constraints_util_audio.cc +++ b/content/renderer/media/stream/media_stream_constraints_util_audio.cc
@@ -11,6 +11,7 @@ #include <vector> #include "base/strings/string_number_conversions.h" +#include "build/build_config.h" #include "content/common/media/media_stream_controls.h" #include "content/public/common/content_features.h" #include "content/renderer/media/stream/media_stream_audio_source.h" @@ -18,6 +19,7 @@ #include "content/renderer/media/stream/media_stream_constraints_util_sets.h" #include "content/renderer/media/stream/media_stream_video_source.h" #include "content/renderer/media/stream/processed_local_audio_source.h" +#include "media/audio/audio_features.h" #include "media/base/audio_parameters.h" #include "media/base/limits.h" #include "third_party/blink/public/platform/web_media_constraints.h" @@ -198,13 +200,6 @@ if (goog_ec_allowed_values_.IsEmpty()) return constraint_set.goog_echo_cancellation.GetName(); - // Make sure that the results from googEchoCancellation and echoCancellation - // constraints do not contradict each other. - auto ec_intersection = - ec_allowed_values_.Intersection(goog_ec_allowed_values_); - if (ec_intersection.IsEmpty()) - return constraint_set.echo_cancellation.GetName(); - ec_type_allowed_values_ = ec_type_allowed_values_.Intersection( media_constraints::StringSetFromConstraint( constraint_set.echo_cancellation_type)); @@ -219,7 +214,9 @@ return constraint_set.echo_cancellation_type.GetName(); } - return nullptr; + // Finally, if this container is empty, fail due to contradiction of the + // resulting allowed values for goog_ec, ec, and/or ec_type. + return IsEmpty() ? constraint_set.echo_cancellation.GetName() : nullptr; } std::tuple<double, EchoCancellationType> SelectSettingsAndScore( @@ -239,8 +236,15 @@ } bool IsEmpty() const { - return ec_allowed_values_.IsEmpty() || goog_ec_allowed_values_.IsEmpty() || - ec_type_allowed_values_.IsEmpty(); + // This container is empty when googEchoCancellation and echoCancellation + // constraints contradict each other. + auto ec_intersection = + ec_allowed_values_.Intersection(goog_ec_allowed_values_); + // This container is also empty if echoCancellation and + // echoCancellationType contraddict each other. + bool ec_type_contraddicts_ec = !ec_allowed_values_.Contains(false) && + ec_type_allowed_values_.IsEmpty(); + return ec_type_contraddicts_ec || ec_intersection.IsEmpty(); } // Audio-processing properties are disabled by default for content capture, @@ -271,6 +275,20 @@ private: static DiscreteSet<std::string> GetEchoCancellationTypesFromParameters( const media::AudioParameters& audio_parameters) { +#if defined(OS_MACOSX) || defined(OS_CHROMEOS) + // If force system echo cancellation feature is enabled: only expose that + // type if available, otherwise expose no type. + if (base::FeatureList::IsEnabled(features::kForceEnableSystemAec)) { + std::vector<std::string> types; + if (audio_parameters.effects() & + (media::AudioParameters::EXPERIMENTAL_ECHO_CANCELLER | + media::AudioParameters::ECHO_CANCELLER)) { + types.push_back(blink::kEchoCancellationTypeSystem); + } + return DiscreteSet<std::string>(types); + } +#endif // defined(OS_MACOSX) || defined(OS_CHROMEOS) + // The browser and AEC3 echo cancellers are always available. std::vector<std::string> types = {blink::kEchoCancellationTypeBrowser, blink::kEchoCancellationTypeAec3}; @@ -682,6 +700,7 @@ : default_device_id_(default_device_id) { for (const auto& capability : capabilities) { devices_.emplace_back(capability, media_stream_source.empty()); + DCHECK(!devices_.back().IsEmpty()); } } @@ -782,6 +801,8 @@ CandidatesContainer candidates(capabilities, media_stream_source, default_device_id); + DCHECK(!candidates.IsEmpty()); + auto* failed_constraint_name = candidates.ApplyConstraintSet(constraints.Basic()); if (failed_constraint_name)
diff --git a/content/renderer/media/stream/track_audio_renderer.cc b/content/renderer/media/stream/track_audio_renderer.cc index b678ec37..c5bb0de 100644 --- a/content/renderer/media/stream/track_audio_renderer.cc +++ b/content/renderer/media/stream/track_audio_renderer.cc
@@ -223,7 +223,7 @@ return sink_ ? sink_->GetOutputDeviceInfo() : media::OutputDeviceInfo(); } -base::TimeDelta TrackAudioRenderer::GetCurrentRenderTime() const { +base::TimeDelta TrackAudioRenderer::GetCurrentRenderTime() { DCHECK(task_runner_->BelongsToCurrentThread()); base::AutoLock auto_lock(thread_lock_); if (source_params_.IsValid()) { @@ -234,7 +234,7 @@ return prior_elapsed_render_time_; } -bool TrackAudioRenderer::IsLocalRenderer() const { +bool TrackAudioRenderer::IsLocalRenderer() { DCHECK(task_runner_->BelongsToCurrentThread()); return MediaStreamAudioTrack::From(audio_track_)->is_local_track(); }
diff --git a/content/renderer/media/stream/track_audio_renderer.h b/content/renderer/media/stream/track_audio_renderer.h index e391dc2..10dbe36 100644 --- a/content/renderer/media/stream/track_audio_renderer.h +++ b/content/renderer/media/stream/track_audio_renderer.h
@@ -74,8 +74,8 @@ void Pause() override; void SetVolume(float volume) override; media::OutputDeviceInfo GetOutputDeviceInfo() override; - base::TimeDelta GetCurrentRenderTime() const override; - bool IsLocalRenderer() const override; + base::TimeDelta GetCurrentRenderTime() override; + bool IsLocalRenderer() override; void SwitchOutputDevice(const std::string& device_id, media::OutputDeviceStatusCB callback) override;
diff --git a/content/renderer/media/stream/webmediaplayer_ms_unittest.cc b/content/renderer/media/stream/webmediaplayer_ms_unittest.cc index 90bc2ab..335a72f 100644 --- a/content/renderer/media/stream/webmediaplayer_ms_unittest.cc +++ b/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
@@ -283,11 +283,9 @@ void SwitchOutputDevice(const std::string& device_id, media::OutputDeviceStatusCB callback) override {} - base::TimeDelta GetCurrentRenderTime() const override { - return base::TimeDelta(); - } + base::TimeDelta GetCurrentRenderTime() override { return base::TimeDelta(); } - bool IsLocalRenderer() const override { return true; } + bool IsLocalRenderer() override { return true; } protected: ~MockMediaStreamAudioRenderer() override {} @@ -1114,6 +1112,10 @@ CheckSizeChanged(gfx::Size(kStandardWidth, kStandardHeight))); message_loop_controller_.RunAndWaitForStatus( media::PipelineStatus::PIPELINE_OK); + // The exact ordering of delayed vs non-delayed tasks is not defined. + // Make sure we run all non-delayed tasks (E.G. CheckForFrameChanges) before + // testing state. + base::RunLoop().RunUntilIdle(); blink::WebSize natural_size = player_->NaturalSize(); // Check that height and width are flipped. EXPECT_EQ(kStandardHeight, natural_size.width); @@ -1132,6 +1134,7 @@ } message_loop_controller_.RunAndWaitForStatus( media::PipelineStatus::PIPELINE_OK); + base::RunLoop().RunUntilIdle(); natural_size = player_->NaturalSize(); EXPECT_EQ(kStandardHeight, natural_size.height); EXPECT_EQ(kStandardWidth, natural_size.width); @@ -1172,6 +1175,9 @@ CheckSizeChanged(gfx::Size(kStandardWidth, kStandardHeight))); message_loop_controller_.RunAndWaitForStatus( media::PipelineStatus::PIPELINE_OK); + // The exact ordering of delayed vs non-delayed tasks is not defined. + // Make sure we run all non-delayed tasks before testing state. + base::RunLoop().RunUntilIdle(); if (!enable_surface_layer_for_video_) { ASSERT_TRUE(layer_ != nullptr); EXPECT_TRUE(layer_->contents_opaque()); @@ -1187,6 +1193,7 @@ } message_loop_controller_.RunAndWaitForStatus( media::PipelineStatus::PIPELINE_OK); + base::RunLoop().RunUntilIdle(); if (!enable_surface_layer_for_video_) { EXPECT_FALSE(layer_->contents_opaque()); } @@ -1201,6 +1208,7 @@ } message_loop_controller_.RunAndWaitForStatus( media::PipelineStatus::PIPELINE_OK); + base::RunLoop().RunUntilIdle(); if (!enable_surface_layer_for_video_) EXPECT_TRUE(layer_->contents_opaque());
diff --git a/content/renderer/media/webrtc/peer_connection_tracker.cc b/content/renderer/media/webrtc/peer_connection_tracker.cc index 86eca3a..cabde67 100644 --- a/content/renderer/media/webrtc/peer_connection_tracker.cc +++ b/content/renderer/media/webrtc/peer_connection_tracker.cc
@@ -12,6 +12,7 @@ #include <utility> #include <vector> +#include "base/numerics/safe_conversions.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" @@ -561,11 +562,12 @@ } } -void PeerConnectionTracker::OnStartEventLogOutput(int peer_connection_id) { +void PeerConnectionTracker::OnStartEventLogOutput(int peer_connection_id, + int output_period_ms) { DCHECK_CALLED_ON_VALID_THREAD(main_thread_); for (auto& it : peer_connection_id_map_) { if (it.second == peer_connection_id) { - it.first->StartEventLog(); + it.first->StartEventLog(output_period_ms); return; } }
diff --git a/content/renderer/media/webrtc/peer_connection_tracker.h b/content/renderer/media/webrtc/peer_connection_tracker.h index e667474..17125e3a 100644 --- a/content/renderer/media/webrtc/peer_connection_tracker.h +++ b/content/renderer/media/webrtc/peer_connection_tracker.h
@@ -230,7 +230,7 @@ IPC::PlatformFileForTransit file); // IPC Message handler for starting event log (output). - void OnStartEventLogOutput(int peer_connection_id); + void OnStartEventLogOutput(int peer_connection_id, int output_period_ms); // IPC Message handler for stopping event log. void OnStopEventLog(int peer_connection_id);
diff --git a/content/renderer/media/webrtc/rtc_peer_connection_handler.cc b/content/renderer/media/webrtc/rtc_peer_connection_handler.cc index 22ce98b0..4248ec7 100644 --- a/content/renderer/media/webrtc/rtc_peer_connection_handler.cc +++ b/content/renderer/media/webrtc/rtc_peer_connection_handler.cc
@@ -1846,16 +1846,15 @@ IPC::PlatformFileForTransitToPlatformFile(file), max_file_size_bytes); } -void RTCPeerConnectionHandler::StartEventLog() { +void RTCPeerConnectionHandler::StartEventLog(int output_period_ms) { DCHECK(task_runner_->RunsTasksInCurrentSequence()); - constexpr int64_t kOutputPeriodMs = 5000; // TODO(eladalon): StartRtcEventLog() return value is not useful; remove it // or find a way to be able to use it. // https://crbug.com/775415 native_peer_connection_->StartRtcEventLog( std::make_unique<RtcEventLogOutputSinkProxy>( peer_connection_observer_.get()), - kOutputPeriodMs); + output_period_ms); } void RTCPeerConnectionHandler::StopEventLog() {
diff --git a/content/renderer/media/webrtc/rtc_peer_connection_handler.h b/content/renderer/media/webrtc/rtc_peer_connection_handler.h index ecc599b..e036b58 100644 --- a/content/renderer/media/webrtc/rtc_peer_connection_handler.h +++ b/content/renderer/media/webrtc/rtc_peer_connection_handler.h
@@ -186,9 +186,11 @@ virtual void CloseClientPeerConnection(); // Start recording an event log. + // TODO(crbug.com/775415): Remove he version with IPC::PlatformFileForTransit, + // since it's no longer used. void StartEventLog(IPC::PlatformFileForTransit file, int64_t max_file_size_bytes); - void StartEventLog(); + void StartEventLog(int output_period_ms); // Stop recording an event log. void StopEventLog();
diff --git a/content/renderer/media/webrtc/rtc_video_encoder.cc b/content/renderer/media/webrtc/rtc_video_encoder.cc index 94ecd41..c127936a 100644 --- a/content/renderer/media/webrtc/rtc_video_encoder.cc +++ b/content/renderer/media/webrtc/rtc_video_encoder.cc
@@ -965,6 +965,8 @@ EncoderInfo info; info.implementation_name = RTCVideoEncoder::Impl::ImplementationName(); info.supports_native_handle = true; + info.is_hardware_accelerated = true; + info.has_internal_source = false; return info; }
diff --git a/content/renderer/media/webrtc/video_codec_factory.cc b/content/renderer/media/webrtc/video_codec_factory.cc index a5f19755..89446fe6 100644 --- a/content/renderer/media/webrtc/video_codec_factory.cc +++ b/content/renderer/media/webrtc/video_codec_factory.cc
@@ -14,10 +14,10 @@ #include "third_party/webrtc/api/video_codecs/video_decoder_software_fallback_wrapper.h" #include "third_party/webrtc/api/video_codecs/video_encoder_software_fallback_wrapper.h" #include "third_party/webrtc/media/base/codec.h" +#include "third_party/webrtc/media/engine/encoder_simulcast_proxy.h" #include "third_party/webrtc/media/engine/internaldecoderfactory.h" #include "third_party/webrtc/media/engine/internalencoderfactory.h" #include "third_party/webrtc/media/engine/simulcast_encoder_adapter.h" -#include "third_party/webrtc/media/engine/vp8_encoder_simulcast_proxy.h" #if defined(OS_ANDROID) #include "media/base/android/media_codec_util.h" @@ -112,7 +112,7 @@ software_encoder = base::EqualsCaseInsensitiveASCII(format.name.c_str(), cricket::kVp8CodecName) - ? std::make_unique<webrtc::VP8EncoderSimulcastProxy>( + ? std::make_unique<webrtc::EncoderSimulcastProxy>( &software_encoder_factory_) : software_encoder_factory_.CreateVideoEncoder(format); }
diff --git a/content/renderer/media/webrtc/webrtc_audio_renderer.cc b/content/renderer/media/webrtc/webrtc_audio_renderer.cc index 916ee43..3c3904f 100644 --- a/content/renderer/media/webrtc/webrtc_audio_renderer.cc +++ b/content/renderer/media/webrtc/webrtc_audio_renderer.cc
@@ -131,12 +131,12 @@ return delegate_->SwitchOutputDevice(device_id, std::move(callback)); } - base::TimeDelta GetCurrentRenderTime() const override { + base::TimeDelta GetCurrentRenderTime() override { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); return delegate_->GetCurrentRenderTime(); } - bool IsLocalRenderer() const override { + bool IsLocalRenderer() override { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); return delegate_->IsLocalRenderer(); } @@ -354,13 +354,13 @@ return sink_ ? sink_->GetOutputDeviceInfo() : media::OutputDeviceInfo(); } -base::TimeDelta WebRtcAudioRenderer::GetCurrentRenderTime() const { +base::TimeDelta WebRtcAudioRenderer::GetCurrentRenderTime() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); base::AutoLock auto_lock(lock_); return current_time_; } -bool WebRtcAudioRenderer::IsLocalRenderer() const { +bool WebRtcAudioRenderer::IsLocalRenderer() { return false; }
diff --git a/content/renderer/media/webrtc/webrtc_audio_renderer.h b/content/renderer/media/webrtc/webrtc_audio_renderer.h index 6c7957f..0a1fe11 100644 --- a/content/renderer/media/webrtc/webrtc_audio_renderer.h +++ b/content/renderer/media/webrtc/webrtc_audio_renderer.h
@@ -122,8 +122,8 @@ void Stop() override; void SetVolume(float volume) override; media::OutputDeviceInfo GetOutputDeviceInfo() override; - base::TimeDelta GetCurrentRenderTime() const override; - bool IsLocalRenderer() const override; + base::TimeDelta GetCurrentRenderTime() override; + bool IsLocalRenderer() override; void SwitchOutputDevice(const std::string& device_id, media::OutputDeviceStatusCB callback) override;
diff --git a/content/renderer/pepper/content_renderer_pepper_host_factory.cc b/content/renderer/pepper/content_renderer_pepper_host_factory.cc index 401e48c6..0bd85ec 100644 --- a/content/renderer/pepper/content_renderer_pepper_host_factory.cc +++ b/content/renderer/pepper/content_renderer_pepper_host_factory.cc
@@ -53,7 +53,7 @@ namespace { -static bool CanUseCameraDeviceAPI(const RendererPpapiHost* host, +static bool CanUseCameraDeviceAPI(RendererPpapiHost* host, PP_Instance instance) { blink::WebPluginContainer* container = host->GetContainerForInstance(instance); @@ -67,7 +67,7 @@ document_url); } -bool CanUseCompositorAPI(const RendererPpapiHost* host, PP_Instance instance) { +bool CanUseCompositorAPI(RendererPpapiHost* host, PP_Instance instance) { blink::WebPluginContainer* container = host->GetContainerForInstance(instance); if (!container)
diff --git a/content/renderer/pepper/fake_pepper_plugin_instance.cc b/content/renderer/pepper/fake_pepper_plugin_instance.cc index 9f66074..9990e80 100644 --- a/content/renderer/pepper/fake_pepper_plugin_instance.cc +++ b/content/renderer/pepper/fake_pepper_plugin_instance.cc
@@ -19,7 +19,9 @@ return nullptr; } -v8::Isolate* FakePepperPluginInstance::GetIsolate() const { return nullptr; } +v8::Isolate* FakePepperPluginInstance::GetIsolate() { + return nullptr; +} ppapi::VarTracker* FakePepperPluginInstance::GetVarTracker() { return nullptr; }
diff --git a/content/renderer/pepper/fake_pepper_plugin_instance.h b/content/renderer/pepper/fake_pepper_plugin_instance.h index 1f19eb7..1e8d20c 100644 --- a/content/renderer/pepper/fake_pepper_plugin_instance.h +++ b/content/renderer/pepper/fake_pepper_plugin_instance.h
@@ -21,7 +21,7 @@ // PepperPluginInstance overrides. content::RenderFrame* GetRenderFrame() override; blink::WebPluginContainer* GetContainer() override; - v8::Isolate* GetIsolate() const override; + v8::Isolate* GetIsolate() override; ppapi::VarTracker* GetVarTracker() override; const GURL& GetPluginURL() override; base::FilePath GetModulePath() override;
diff --git a/content/renderer/pepper/mock_renderer_ppapi_host.cc b/content/renderer/pepper/mock_renderer_ppapi_host.cc index bed1e6d..fcf20c1 100644 --- a/content/renderer/pepper/mock_renderer_ppapi_host.cc +++ b/content/renderer/pepper/mock_renderer_ppapi_host.cc
@@ -28,46 +28,46 @@ return &ppapi_host_; } -bool MockRendererPpapiHost::IsValidInstance(PP_Instance instance) const { +bool MockRendererPpapiHost::IsValidInstance(PP_Instance instance) { return instance == pp_instance_; } PepperPluginInstance* MockRendererPpapiHost::GetPluginInstance( - PP_Instance instance) const { + PP_Instance instance) { return plugin_instance_.get(); } RenderFrame* MockRendererPpapiHost::GetRenderFrameForInstance( - PP_Instance instance) const { + PP_Instance instance) { if (instance == pp_instance_) return render_frame_; return nullptr; } RenderView* MockRendererPpapiHost::GetRenderViewForInstance( - PP_Instance instance) const { + PP_Instance instance) { if (instance == pp_instance_) return render_view_; return nullptr; } blink::WebPluginContainer* MockRendererPpapiHost::GetContainerForInstance( - PP_Instance instance) const { + PP_Instance instance) { NOTIMPLEMENTED(); return nullptr; } -bool MockRendererPpapiHost::HasUserGesture(PP_Instance instance) const { +bool MockRendererPpapiHost::HasUserGesture(PP_Instance instance) { return has_user_gesture_; } -int MockRendererPpapiHost::GetRoutingIDForWidget(PP_Instance instance) const { +int MockRendererPpapiHost::GetRoutingIDForWidget(PP_Instance instance) { return 0; } gfx::Point MockRendererPpapiHost::PluginPointToRenderFrame( PP_Instance instance, - const gfx::Point& pt) const { + const gfx::Point& pt) { return gfx::Point(); } @@ -99,9 +99,11 @@ return base::ReadOnlySharedMemoryRegion(); } -bool MockRendererPpapiHost::IsRunningInProcess() const { return false; } +bool MockRendererPpapiHost::IsRunningInProcess() { + return false; +} -std::string MockRendererPpapiHost::GetPluginName() const { +std::string MockRendererPpapiHost::GetPluginName() { return std::string(); } @@ -112,12 +114,12 @@ void MockRendererPpapiHost::CreateBrowserResourceHosts( PP_Instance instance, const std::vector<IPC::Message>& nested_msgs, - base::OnceCallback<void(const std::vector<int>&)> callback) const { + base::OnceCallback<void(const std::vector<int>&)> callback) { std::move(callback).Run(std::vector<int>(nested_msgs.size(), 0)); return; } -GURL MockRendererPpapiHost::GetDocumentURL(PP_Instance instance) const { +GURL MockRendererPpapiHost::GetDocumentURL(PP_Instance instance) { NOTIMPLEMENTED(); return GURL(); }
diff --git a/content/renderer/pepper/mock_renderer_ppapi_host.h b/content/renderer/pepper/mock_renderer_ppapi_host.h index 7aa7f2c..64281256 100644 --- a/content/renderer/pepper/mock_renderer_ppapi_host.h +++ b/content/renderer/pepper/mock_renderer_ppapi_host.h
@@ -33,16 +33,16 @@ // RendererPpapiHost. ppapi::host::PpapiHost* GetPpapiHost() override; - bool IsValidInstance(PP_Instance instance) const override; - PepperPluginInstance* GetPluginInstance(PP_Instance instance) const override; - RenderFrame* GetRenderFrameForInstance(PP_Instance instance) const override; - RenderView* GetRenderViewForInstance(PP_Instance instance) const override; + bool IsValidInstance(PP_Instance instance) override; + PepperPluginInstance* GetPluginInstance(PP_Instance instance) override; + RenderFrame* GetRenderFrameForInstance(PP_Instance instance) override; + RenderView* GetRenderViewForInstance(PP_Instance instance) override; blink::WebPluginContainer* GetContainerForInstance( - PP_Instance instance) const override; - bool HasUserGesture(PP_Instance instance) const override; - int GetRoutingIDForWidget(PP_Instance instance) const override; + PP_Instance instance) override; + bool HasUserGesture(PP_Instance instance) override; + int GetRoutingIDForWidget(PP_Instance instance) override; gfx::Point PluginPointToRenderFrame(PP_Instance instance, - const gfx::Point& pt) const override; + const gfx::Point& pt) override; IPC::PlatformFileForTransit ShareHandleWithRemote( base::PlatformFile handle, bool should_close_source) override; @@ -52,15 +52,14 @@ const base::UnsafeSharedMemoryRegion& region) override; base::ReadOnlySharedMemoryRegion ShareReadOnlySharedMemoryRegionWithRemote( const base::ReadOnlySharedMemoryRegion& region) override; - bool IsRunningInProcess() const override; - std::string GetPluginName() const override; + bool IsRunningInProcess() override; + std::string GetPluginName() override; void SetToExternalPluginHost() override; void CreateBrowserResourceHosts( PP_Instance instance, const std::vector<IPC::Message>& nested_msgs, - base::OnceCallback<void(const std::vector<int>&)> callback) - const override; - GURL GetDocumentURL(PP_Instance instance) const override; + base::OnceCallback<void(const std::vector<int>&)> callback) override; + GURL GetDocumentURL(PP_Instance instance) override; private: ppapi::proxy::ResourceMessageTestSink sink_;
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc index 3aa93d2a..13a78b9 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.cc +++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -3064,7 +3064,9 @@ return container_; } -v8::Isolate* PepperPluginInstanceImpl::GetIsolate() const { return isolate_; } +v8::Isolate* PepperPluginInstanceImpl::GetIsolate() { + return isolate_; +} ppapi::VarTracker* PepperPluginInstanceImpl::GetVarTracker() { return HostGlobals::Get()->GetVarTracker();
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.h b/content/renderer/pepper/pepper_plugin_instance_impl.h index af9f4f4..25d6804e 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.h +++ b/content/renderer/pepper/pepper_plugin_instance_impl.h
@@ -385,7 +385,7 @@ // PluginInstance implementation RenderFrame* GetRenderFrame() override; blink::WebPluginContainer* GetContainer() override; - v8::Isolate* GetIsolate() const override; + v8::Isolate* GetIsolate() override; ppapi::VarTracker* GetVarTracker() override; const GURL& GetPluginURL() override; base::FilePath GetModulePath() override;
diff --git a/content/renderer/pepper/plugin_instance_throttler_impl.cc b/content/renderer/pepper/plugin_instance_throttler_impl.cc index 867efb30..5550586 100644 --- a/content/renderer/pepper/plugin_instance_throttler_impl.cc +++ b/content/renderer/pepper/plugin_instance_throttler_impl.cc
@@ -85,11 +85,11 @@ observer_list_.RemoveObserver(observer); } -bool PluginInstanceThrottlerImpl::IsThrottled() const { +bool PluginInstanceThrottlerImpl::IsThrottled() { return state_ == THROTTLER_STATE_PLUGIN_THROTTLED; } -bool PluginInstanceThrottlerImpl::IsHiddenForPlaceholder() const { +bool PluginInstanceThrottlerImpl::IsHiddenForPlaceholder() { return is_hidden_for_placeholder_; } @@ -117,12 +117,12 @@ observer.OnHiddenForPlaceholder(hidden); } -PepperWebPluginImpl* PluginInstanceThrottlerImpl::GetWebPlugin() const { +PepperWebPluginImpl* PluginInstanceThrottlerImpl::GetWebPlugin() { DCHECK(web_plugin_); return web_plugin_; } -const gfx::Size& PluginInstanceThrottlerImpl::GetSize() const { +const gfx::Size& PluginInstanceThrottlerImpl::GetSize() { return unobscured_size_; }
diff --git a/content/renderer/pepper/plugin_instance_throttler_impl.h b/content/renderer/pepper/plugin_instance_throttler_impl.h index 3fbcdec..80b4d04 100644 --- a/content/renderer/pepper/plugin_instance_throttler_impl.h +++ b/content/renderer/pepper/plugin_instance_throttler_impl.h
@@ -40,12 +40,12 @@ // PluginInstanceThrottler implementation: void AddObserver(Observer* observer) override; void RemoveObserver(Observer* observer) override; - bool IsThrottled() const override; - bool IsHiddenForPlaceholder() const override; + bool IsThrottled() override; + bool IsHiddenForPlaceholder() override; void MarkPluginEssential(PowerSaverUnthrottleMethod method) override; void SetHiddenForPlaceholder(bool hidden) override; - PepperWebPluginImpl* GetWebPlugin() const override; - const gfx::Size& GetSize() const override; + PepperWebPluginImpl* GetWebPlugin() override; + const gfx::Size& GetSize() override; void NotifyAudioThrottled() override; void SetWebPlugin(PepperWebPluginImpl* web_plugin);
diff --git a/content/renderer/pepper/renderer_ppapi_host_impl.cc b/content/renderer/pepper/renderer_ppapi_host_impl.cc index e88a3a6..465cdf58 100644 --- a/content/renderer/pepper/renderer_ppapi_host_impl.cc +++ b/content/renderer/pepper/renderer_ppapi_host_impl.cc
@@ -139,7 +139,7 @@ } RenderFrame* RendererPpapiHostImpl::GetRenderFrameForInstance( - PP_Instance instance) const { + PP_Instance instance) { PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance); if (!instance_object) return nullptr; @@ -150,7 +150,7 @@ } RenderView* RendererPpapiHostImpl::GetRenderViewForInstance( - PP_Instance instance) const { + PP_Instance instance) { PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance); if (!instance_object) return nullptr; @@ -160,24 +160,24 @@ return instance_object->render_frame()->render_view(); } -bool RendererPpapiHostImpl::IsValidInstance(PP_Instance instance) const { +bool RendererPpapiHostImpl::IsValidInstance(PP_Instance instance) { return !!GetAndValidateInstance(instance); } PepperPluginInstance* RendererPpapiHostImpl::GetPluginInstance( - PP_Instance instance) const { + PP_Instance instance) { return GetAndValidateInstance(instance); } blink::WebPluginContainer* RendererPpapiHostImpl::GetContainerForInstance( - PP_Instance instance) const { + PP_Instance instance) { PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance); if (!instance_object) return nullptr; return instance_object->container(); } -bool RendererPpapiHostImpl::HasUserGesture(PP_Instance instance) const { +bool RendererPpapiHostImpl::HasUserGesture(PP_Instance instance) { PepperPluginInstanceImpl* instance_object = GetAndValidateInstance(instance); if (!instance_object) return false; @@ -188,7 +188,7 @@ return instance_object->IsProcessingUserGesture(); } -int RendererPpapiHostImpl::GetRoutingIDForWidget(PP_Instance instance) const { +int RendererPpapiHostImpl::GetRoutingIDForWidget(PP_Instance instance) { PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance); if (!plugin_instance) return 0; @@ -201,7 +201,7 @@ gfx::Point RendererPpapiHostImpl::PluginPointToRenderFrame( PP_Instance instance, - const gfx::Point& pt) const { + const gfx::Point& pt) { PepperPluginInstanceImpl* plugin_instance = GetAndValidateInstance(instance); if (!plugin_instance || plugin_instance->flash_fullscreen()) { // Flash fullscreen is special in that it renders into its own separate, @@ -257,11 +257,11 @@ return dispatcher_->ShareReadOnlySharedMemoryRegionWithRemote(region); } -bool RendererPpapiHostImpl::IsRunningInProcess() const { +bool RendererPpapiHostImpl::IsRunningInProcess() { return is_running_in_process_; } -std::string RendererPpapiHostImpl::GetPluginName() const { +std::string RendererPpapiHostImpl::GetPluginName() { return module_->name(); } @@ -272,7 +272,7 @@ void RendererPpapiHostImpl::CreateBrowserResourceHosts( PP_Instance instance, const std::vector<IPC::Message>& nested_msgs, - base::OnceCallback<void(const std::vector<int>&)> callback) const { + base::OnceCallback<void(const std::vector<int>&)> callback) { RenderFrame* render_frame = GetRenderFrameForInstance(instance); PepperBrowserConnection* browser_connection = PepperBrowserConnection::Get(render_frame); @@ -286,7 +286,7 @@ } } -GURL RendererPpapiHostImpl::GetDocumentURL(PP_Instance pp_instance) const { +GURL RendererPpapiHostImpl::GetDocumentURL(PP_Instance pp_instance) { PepperPluginInstanceImpl* instance = GetAndValidateInstance(pp_instance); if (!instance) return GURL();
diff --git a/content/renderer/pepper/renderer_ppapi_host_impl.h b/content/renderer/pepper/renderer_ppapi_host_impl.h index 92ff85f6..9562855 100644 --- a/content/renderer/pepper/renderer_ppapi_host_impl.h +++ b/content/renderer/pepper/renderer_ppapi_host_impl.h
@@ -74,16 +74,16 @@ // RendererPpapiHost implementation. ppapi::host::PpapiHost* GetPpapiHost() override; - bool IsValidInstance(PP_Instance instance) const override; - PepperPluginInstance* GetPluginInstance(PP_Instance instance) const override; - RenderFrame* GetRenderFrameForInstance(PP_Instance instance) const override; - RenderView* GetRenderViewForInstance(PP_Instance instance) const override; + bool IsValidInstance(PP_Instance instance) override; + PepperPluginInstance* GetPluginInstance(PP_Instance instance) override; + RenderFrame* GetRenderFrameForInstance(PP_Instance instance) override; + RenderView* GetRenderViewForInstance(PP_Instance instance) override; blink::WebPluginContainer* GetContainerForInstance( - PP_Instance instance) const override; - bool HasUserGesture(PP_Instance instance) const override; - int GetRoutingIDForWidget(PP_Instance instance) const override; + PP_Instance instance) override; + bool HasUserGesture(PP_Instance instance) override; + int GetRoutingIDForWidget(PP_Instance instance) override; gfx::Point PluginPointToRenderFrame(PP_Instance instance, - const gfx::Point& pt) const override; + const gfx::Point& pt) override; IPC::PlatformFileForTransit ShareHandleWithRemote( base::PlatformFile handle, bool should_close_source) override; @@ -93,15 +93,14 @@ const base::UnsafeSharedMemoryRegion& region) override; base::ReadOnlySharedMemoryRegion ShareReadOnlySharedMemoryRegionWithRemote( const base::ReadOnlySharedMemoryRegion& region) override; - bool IsRunningInProcess() const override; - std::string GetPluginName() const override; + bool IsRunningInProcess() override; + std::string GetPluginName() override; void SetToExternalPluginHost() override; void CreateBrowserResourceHosts( PP_Instance instance, const std::vector<IPC::Message>& nested_msgs, - base::OnceCallback<void(const std::vector<int>&)> callback) - const override; - GURL GetDocumentURL(PP_Instance pp_instance) const override; + base::OnceCallback<void(const std::vector<int>&)> callback) override; + GURL GetDocumentURL(PP_Instance pp_instance) override; // Returns whether the plugin is running in a secure context. bool IsSecureContext(PP_Instance pp_instance) const;
diff --git a/content/renderer/pepper/video_encoder_shim.cc b/content/renderer/pepper/video_encoder_shim.cc index 7498cd4..cfafc83 100644 --- a/content/renderer/pepper/video_encoder_shim.cc +++ b/content/renderer/pepper/video_encoder_shim.cc
@@ -271,10 +271,7 @@ PendingEncode frame = frames_.front(); frames_.pop_front(); - frame.frame->AddRef(); - media::VideoFrame* raw_frame = frame.frame.get(); - frame.frame = nullptr; - renderer_task_runner_->ReleaseSoon(FROM_HERE, raw_frame); + renderer_task_runner_->ReleaseSoon(FROM_HERE, std::move(frame.frame)); } buffers_.clear(); }
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index b321a29..e0c8e42 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -145,7 +145,6 @@ #include "content/renderer/service_worker/service_worker_network_provider.h" #include "content/renderer/service_worker/service_worker_provider_context.h" #include "content/renderer/service_worker/web_service_worker_provider_impl.h" -#include "content/renderer/shared_worker/shared_worker_repository.h" #include "content/renderer/skia_benchmarking_extension.h" #include "content/renderer/stats_collection_controller.h" #include "content/renderer/v8_value_converter_impl.h" @@ -1504,7 +1503,7 @@ // space/context. scoped_refptr<RenderWidget> render_widget; if (g_create_render_widget) { - // LayoutTest hooks inject a different type (subclass) for RenderWidget, + // Web test hooks inject a different type (subclass) for RenderWidget, // allowing it to override the behaviour of the WebWidgetClient which // RenderWidget provides. render_widget = g_create_render_widget( @@ -1537,7 +1536,7 @@ // pulling the device scale factor off the WebView itself. render_widget->UpdateWebViewWithDeviceScaleFactor(); - // LayoutTest hooks to set up the injected type for RenderWidget. + // Web test hooks to set up the injected type for RenderWidget. if (g_render_widget_initialized) g_render_widget_initialized(render_widget.get()); @@ -1783,10 +1782,8 @@ #if BUILDFLAG(ENABLE_PLUGINS) new PepperBrowserConnection(this); #endif - shared_worker_repository_ = - std::make_unique<SharedWorkerRepository>(GetInterfaceProvider()); - GetWebFrame()->SetSharedWorkerRepositoryClient( - shared_worker_repository_.get()); + + GetWebFrame()->InitializeSharedWorkerRepositoryClient(GetInterfaceProvider()); RegisterMojoInterfaces(); @@ -3022,7 +3019,7 @@ const url::Origin& main_frame_origin, const url::Origin& content_origin, const gfx::Size& unobscured_size, - RecordPeripheralDecision record_decision) const { + RecordPeripheralDecision record_decision) { return plugin_power_saver_helper_->GetPeripheralContentStatus( main_frame_origin, content_origin, unobscured_size, record_decision); } @@ -3042,9 +3039,7 @@ #endif // BUILDFLAG(ENABLE_PLUGINS) bool RenderFrameImpl::IsFTPDirectoryListing() { - WebURLResponseExtraDataImpl* extra_data = - GetExtraDataFromResponse(frame_->GetDocumentLoader()->GetResponse()); - return extra_data ? extra_data->is_ftp_directory_listing() : false; + return frame_->GetDocumentLoader()->IsListingFtpDirectory(); } void RenderFrameImpl::AttachGuest(int element_instance_id) { @@ -3066,7 +3061,7 @@ render_view_->UpdateZoomLevel(zoom_level); } -double RenderFrameImpl::GetZoomLevel() const { +double RenderFrameImpl::GetZoomLevel() { return render_view_->page_zoom_level(); } @@ -3097,11 +3092,11 @@ previews_state_ = previews_state; } -PreviewsState RenderFrameImpl::GetPreviewsState() const { +PreviewsState RenderFrameImpl::GetPreviewsState() { return previews_state_; } -bool RenderFrameImpl::IsPasting() const { +bool RenderFrameImpl::IsPasting() { return is_pasting_; } @@ -7101,7 +7096,7 @@ return GetWebFrame()->GetTaskRunner(task_type); } -int RenderFrameImpl::GetEnabledBindings() const { +int RenderFrameImpl::GetEnabledBindings() { return enabled_bindings_; }
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index c39fe81..4465da9 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -171,7 +171,6 @@ class RenderViewImpl; class RenderWidget; class RenderWidgetFullscreenPepper; -class SharedWorkerRepository; class UserMediaClientImpl; struct CSPViolationParams; struct CommonNavigationParams; @@ -482,7 +481,7 @@ const url::Origin& main_frame_origin, const url::Origin& content_origin, const gfx::Size& unobscured_size, - RecordPeripheralDecision record_decision) const override; + RecordPeripheralDecision record_decision) override; void WhitelistContentOrigin(const url::Origin& content_origin) override; void PluginDidStartLoading() override; void PluginDidStopLoading() override; @@ -494,12 +493,12 @@ size_t offset, const gfx::Range& range) override; void SetZoomLevel(double zoom_level) override; - double GetZoomLevel() const override; + double GetZoomLevel() override; void AddMessageToConsole(ConsoleMessageLevel level, const std::string& message) override; void SetPreviewsState(PreviewsState previews_state) override; - PreviewsState GetPreviewsState() const override; - bool IsPasting() const override; + PreviewsState GetPreviewsState() override; + bool IsPasting() override; bool IsBrowserSideNavigationPending() override; void LoadHTMLString(const std::string& html, const GURL& base_url, @@ -508,7 +507,7 @@ bool replace_current_item) override; scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner( blink::TaskType task_type) override; - int GetEnabledBindings() const override; + int GetEnabledBindings() override; void SetAccessibilityModeForTest(ui::AXMode new_mode) override; scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; @@ -1476,7 +1475,6 @@ #endif std::unique_ptr<FrameBlameContext> blame_context_; - std::unique_ptr<SharedWorkerRepository> shared_worker_repository_; // Plugins ------------------------------------------------------------------- #if BUILDFLAG(ENABLE_PLUGINS)
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index f706c47..787ee19b 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -1496,7 +1496,7 @@ main_thread_scheduler_->SetRendererProcessType(type); } -blink::WebString RenderThreadImpl::GetUserAgent() const { +blink::WebString RenderThreadImpl::GetUserAgent() { DCHECK(!user_agent_.IsNull()); return user_agent_; } @@ -1896,10 +1896,10 @@ render_frame_metadata_observer_client_request, mojom::RenderFrameMetadataObserverPtr render_frame_metadata_observer_ptr, const char* client_name) { - // Misconfigured bots (eg. crbug.com/780757) could run layout tests on a + // Misconfigured bots (eg. crbug.com/780757) could run web tests on a // machine where gpu compositing doesn't work. Don't crash in that case. - if (layout_test_mode() && is_gpu_compositing_disabled_) { - LOG(FATAL) << "Layout tests require gpu compositing, but it is disabled."; + if (web_test_mode() && is_gpu_compositing_disabled_) { + LOG(FATAL) << "Web tests require gpu compositing, but it is disabled."; return; } @@ -1963,7 +1963,7 @@ mojo::MakeRequest(&compositor_frame_sink_client); if (is_gpu_compositing_disabled_) { - DCHECK(!layout_test_mode()); + DCHECK(!web_test_mode()); frame_sink_provider_->CreateForWidget( widget_routing_id, std::move(compositor_frame_sink_request), std::move(compositor_frame_sink_client)); @@ -2025,16 +2025,16 @@ attributes, ws::command_buffer_metrics::ContextType::RENDER_COMPOSITOR)); - if (layout_test_deps_) { - if (!layout_test_deps_->UseDisplayCompositorPixelDump()) { - std::move(callback).Run(layout_test_deps_->CreateLayerTreeFrameSink( + if (web_test_deps_) { + if (!web_test_deps_->UseDisplayCompositorPixelDump()) { + std::move(callback).Run(web_test_deps_->CreateLayerTreeFrameSink( widget_routing_id, std::move(gpu_channel_host), std::move(context_provider), std::move(worker_context_provider), GetGpuMemoryBufferManager(), this)); return; } else if (!params.compositor_task_runner) { // The frame sink provider expects a compositor task runner, but we might - // not have that if we're running layout tests in single threaded mode. + // not have that if we're running web tests in single threaded mode. // Set it to be our thread's task runner instead. params.compositor_task_runner = GetCompositorMainThreadTaskRunner(); } @@ -2079,13 +2079,12 @@ } std::unique_ptr<cc::SwapPromise> -RenderThreadImpl::RequestCopyOfOutputForLayoutTest( +RenderThreadImpl::RequestCopyOfOutputForWebTest( int32_t widget_routing_id, std::unique_ptr<viz::CopyOutputRequest> request) { - DCHECK(layout_test_deps_ && - !layout_test_deps_->UseDisplayCompositorPixelDump()); - return layout_test_deps_->RequestCopyOfOutput(widget_routing_id, - std::move(request)); + DCHECK(web_test_deps_ && !web_test_deps_->UseDisplayCompositorPixelDump()); + return web_test_deps_->RequestCopyOfOutput(widget_routing_id, + std::move(request)); } std::unique_ptr<blink::WebMediaStreamCenter>
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index a9d0667..8cdd01be 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -40,9 +40,9 @@ #include "content/public/renderer/render_thread.h" #include "content/public/renderer/url_loader_throttle_provider.h" #include "content/renderer/gpu/compositor_dependencies.h" -#include "content/renderer/layout_test_dependencies.h" #include "content/renderer/media/audio/audio_input_ipc_factory.h" #include "content/renderer/media/audio/audio_output_ipc_factory.h" +#include "content/renderer/web_test_dependencies.h" #include "gpu/ipc/client/gpu_channel_host.h" #include "ipc/ipc_sync_channel.h" #include "media/media_buildflags.h" @@ -213,7 +213,7 @@ bool IsOnline() override; void SetRendererProcessType( blink::scheduler::WebRendererProcessType type) override; - blink::WebString GetUserAgent() const override; + blink::WebString GetUserAgent() override; // IPC::Listener implementation via ChildThreadImpl: void OnAssociatedInterfaceRequest( @@ -279,25 +279,24 @@ blink::AssociatedInterfaceRegistry* GetAssociatedInterfaceRegistry(); - std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForLayoutTest( + std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForWebTest( int32_t widget_routing_id, std::unique_ptr<viz::CopyOutputRequest> request); - // True if we are running layout tests. This currently disables forwarding + // True if we are running web tests. This currently disables forwarding // various status messages to the console, skips network error pages, and // short circuits size update and focus events. - bool layout_test_mode() const { return !!layout_test_deps_; } - void set_layout_test_dependencies( - std::unique_ptr<LayoutTestDependencies> deps) { - layout_test_deps_ = std::move(deps); + bool web_test_mode() const { return !!web_test_deps_; } + void set_web_test_dependencies(std::unique_ptr<WebTestDependencies> deps) { + web_test_deps_ = std::move(deps); } - // Returns whether we are running layout tests with display compositor for + // Returns whether we are running web tests with display compositor for // pixel dump enabled. It is meant to disable feature that require display // compositor while it is not enabled by default. - // This should only be called if currently running in layout tests. - bool LayoutTestModeUsesDisplayCompositorPixelDump() const { - DCHECK(layout_test_deps_); - return layout_test_deps_->UseDisplayCompositorPixelDump(); + // This should only be called if currently running in web tests. + bool WebTestModeUsesDisplayCompositorPixelDump() const { + DCHECK(web_test_deps_); + return web_test_deps_->UseDisplayCompositorPixelDump(); } discardable_memory::ClientDiscardableSharedMemoryManager* @@ -639,8 +638,8 @@ blink::WebString user_agent_; - // Used to control layout test specific behavior. - std::unique_ptr<LayoutTestDependencies> layout_test_deps_; + // Used to control web test specific behavior. + std::unique_ptr<WebTestDependencies> web_test_deps_; // Sticky once true, indicates that compositing is done without Gpu, so // resources given to the compositor or to the viz service should be
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index ed1efc6..80c571f 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -464,7 +464,7 @@ RenderFrameImpl::ResolveOpener(params->opener_frame_route_id); // Pass WidgetClient(), not |this|, as the WebWidgetClient. The method may - // be overridden in layout tests to inject a test-only WebWidgetClient. + // be overridden in web tests to inject a test-only WebWidgetClient. webview_ = WebView::Create(this, WidgetClient(), params->hidden, /*compositing_enabled=*/true, opener_frame ? opener_frame->View() : nullptr); @@ -880,10 +880,6 @@ settings->SetAutoplayPolicy( WebSettings::AutoplayPolicy::kUserGestureRequired); break; - case AutoplayPolicy::kUserGestureRequiredForCrossOrigin: - settings->SetAutoplayPolicy( - WebSettings::AutoplayPolicy::kUserGestureRequiredForCrossOrigin); - break; case AutoplayPolicy::kDocumentUserActivationRequired: settings->SetAutoplayPolicy( WebSettings::AutoplayPolicy::kDocumentUserActivationRequired); @@ -1158,7 +1154,7 @@ void RenderViewImpl::RequestScheduleAnimationForWidget() { // Schedule the animation on the WidgetClient() which may not be the - // RenderWidget directly in layout tests. + // RenderWidget directly in web tests. WidgetClient()->ScheduleAnimation(); } @@ -1361,7 +1357,7 @@ // multiple windows being opened, because, well, the app doesn't support // multiple windows. // TODO(dcheng): It's awkward that this is plumbed into Blink but not really - // used much in Blink, except to enable layout testing... perhaps this should + // used much in Blink, except to enable web testing... perhaps this should // be checked directly in the browser side. if (status == mojom::CreateNewWindowStatus::kReuse) return webview(); @@ -1711,7 +1707,7 @@ GetWidget()->ClearEditCommands(); } -const std::string& RenderViewImpl::GetAcceptLanguages() const { +const std::string& RenderViewImpl::GetAcceptLanguages() { return renderer_preferences_.accept_languages; } @@ -1804,19 +1800,19 @@ return main_render_frame_; } -int RenderViewImpl::GetRoutingID() const { +int RenderViewImpl::GetRoutingID() { return routing_id_; } -gfx::Size RenderViewImpl::GetSize() const { +gfx::Size RenderViewImpl::GetSize() { return size(); } -float RenderViewImpl::GetDeviceScaleFactor() const { +float RenderViewImpl::GetDeviceScaleFactor() { return GetWebScreenInfo().device_scale_factor; } -float RenderViewImpl::GetZoomLevel() const { +float RenderViewImpl::GetZoomLevel() { return page_zoom_level_; } @@ -1836,7 +1832,7 @@ return frame_widget_; } -bool RenderViewImpl::GetContentStateImmediately() const { +bool RenderViewImpl::GetContentStateImmediately() { return send_content_state_immediately_; } @@ -2038,7 +2034,7 @@ // we won't have to test for user gesture anymore and we can // move that code back to render_widget.cc if (WebUserGestureIndicator::IsProcessingUserGesture(calling_frame) && - !RenderThreadImpl::current()->layout_test_mode()) { + !RenderThreadImpl::current()->web_test_mode()) { Send(new ViewHostMsg_Focus(GetRoutingID())); // Tattle on the frame that called |window.focus()|.
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index 6d8654a..3f35d7ce 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h
@@ -120,8 +120,7 @@ RenderWidget::ShowCallback show_callback, scoped_refptr<base::SingleThreadTaskRunner> task_runner); - // Used by content_layouttest_support to hook into the creation of - // RenderViewImpls. + // Used by web_test_support to hook into the creation of RenderViewImpls. static void InstallCreateHook(RenderViewImpl* (*create_render_view_impl)( CompositorDependencies* compositor_deps, const mojom::CreateViewParams&)); @@ -199,7 +198,7 @@ unsigned GetLocalSessionHistoryLengthForTesting() const; // Invokes OnSetFocus and marks the widget as active depending on the value - // of |enable|. This is used for layout tests that need to control the focus + // of |enable|. This is used for web tests that need to control the focus // synchronously from the renderer. void SetFocusAndActivateForTesting(bool enable); @@ -266,19 +265,19 @@ bool Send(IPC::Message* message) override; RenderFrameImpl* GetMainRenderFrame() override; - int GetRoutingID() const override; - gfx::Size GetSize() const override; - float GetDeviceScaleFactor() const override; - float GetZoomLevel() const override; + int GetRoutingID() override; + gfx::Size GetSize() override; + float GetDeviceScaleFactor() override; + float GetZoomLevel() override; const WebPreferences& GetWebkitPreferences() override; void SetWebkitPreferences(const WebPreferences& preferences) override; blink::WebView* GetWebView() override; blink::WebFrameWidget* GetWebFrameWidget() override; - bool GetContentStateImmediately() const override; + bool GetContentStateImmediately() override; void SetEditCommandForNextKeyEvent(const std::string& name, const std::string& value) override; void ClearEditCommands() override; - const std::string& GetAcceptLanguages() const override; + const std::string& GetAcceptLanguages() override; void UpdateBrowserControlsState(BrowserControlsState constraints, BrowserControlsState current, bool animate) override;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 6ac66a6..33b3c6a9 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -1127,9 +1127,9 @@ observer.WillBeginCompositorFrame(); } -std::unique_ptr<cc::SwapPromise> RenderWidget::RequestCopyOfOutputForLayoutTest( +std::unique_ptr<cc::SwapPromise> RenderWidget::RequestCopyOfOutputForWebTest( std::unique_ptr<viz::CopyOutputRequest> request) { - return RenderThreadImpl::current()->RequestCopyOfOutputForLayoutTest( + return RenderThreadImpl::current()->RequestCopyOfOutputForWebTest( routing_id_, std::move(request)); } @@ -1283,6 +1283,16 @@ text_input_mode_ = new_mode; can_compose_inline_ = new_can_compose_inline; 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): Introduce a |text_input_state_revision_| var to synchronize + // the RFM with the TextInputStateChanged message. https://crbug.com/912309 + if (layer_tree_view_ && IsSurfaceSynchronizationEnabled()) { + layer_tree_view_->RequestNewLocalSurfaceId(); + } +#endif } } @@ -1861,7 +1871,7 @@ EmulatedToScreenRectIfNeeded(&window_rect); if (resizing_mode_selector_->is_synchronous_mode()) { - // This is a layout-test-only path. At one point, it was planned to be + // This is a web-test-only path. At one point, it was planned to be // removed. See https://crbug.com/309760. SetWindowRectSynchronously(window_rect); return; @@ -2749,8 +2759,8 @@ // The means the renderer compositor has 2 possible modes: // - Threaded compositing with a scheduler. - // - Single threaded compositing without a scheduler (for layout tests only). - // Using the scheduler in layout tests introduces additional composite steps + // - Single threaded compositing without a scheduler (for web tests only). + // Using the scheduler in web tests introduces additional composite steps // that create flakiness. settings.single_thread_proxy_scheduler = false;
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index c5e16c64..e967c5f 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -306,7 +306,7 @@ void RequestScheduleAnimation() override; void UpdateVisualState(bool record_main_frame_metrics) override; void WillBeginCompositorFrame() override; - std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForLayoutTest( + std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForWebTest( std::unique_ptr<viz::CopyOutputRequest> request) override; // RenderWidgetInputHandlerDelegate @@ -732,7 +732,7 @@ const gfx::Size& new_compositor_viewport_pixel_size, const ScreenInfo& new_screen_info); - // Used to force the size of a window when running layout tests. + // Used to force the size of a window when running web tests. void SetWindowRectSynchronously(const gfx::Rect& new_window_rect); void UpdateCaptureSequenceNumber(uint32_t capture_sequence_number);
diff --git a/content/renderer/renderer_main.cc b/content/renderer/renderer_main.cc index db58e3d..2fe53ee7 100644 --- a/content/renderer/renderer_main.cc +++ b/content/renderer/renderer_main.cc
@@ -214,7 +214,6 @@ // Setup tracing sampler profiler as early as possible. auto tracing_sampler_profiler = tracing::TracingSamplerProfiler::CreateOnMainThread(); - tracing_sampler_profiler->OnMessageLoopStarted(); if (need_sandbox) should_run_loop = platform.EnableSandbox();
diff --git a/content/renderer/renderer_webapplicationcachehost_impl.cc b/content/renderer/renderer_webapplicationcachehost_impl.cc index 785f6fe1..de5414b7 100644 --- a/content/renderer/renderer_webapplicationcachehost_impl.cc +++ b/content/renderer/renderer_webapplicationcachehost_impl.cc
@@ -29,7 +29,7 @@ void RendererWebApplicationCacheHostImpl::OnLogMessage( AppCacheLogLevel log_level, const std::string& message) { - if (RenderThreadImpl::current()->layout_test_mode()) + if (RenderThreadImpl::current()->web_test_mode()) return; RenderViewImpl* render_view = GetRenderView();
diff --git a/content/renderer/resizing_mode_selector.cc b/content/renderer/resizing_mode_selector.cc index b02b9703..cc16b16 100644 --- a/content/renderer/resizing_mode_selector.cc +++ b/content/renderer/resizing_mode_selector.cc
@@ -14,7 +14,7 @@ bool ResizingModeSelector::NeverUsesSynchronousResize() const { return !RenderThreadImpl::current() || // can be NULL when in unit tests - !RenderThreadImpl::current()->layout_test_mode(); + !RenderThreadImpl::current()->web_test_mode(); } bool ResizingModeSelector::ShouldAbortOnResize(
diff --git a/content/renderer/resizing_mode_selector.h b/content/renderer/resizing_mode_selector.h index 46a7182..1743fba 100644 --- a/content/renderer/resizing_mode_selector.h +++ b/content/renderer/resizing_mode_selector.h
@@ -17,7 +17,7 @@ // and receiving them from host; and // 2) The synchronous mode, which short-circuits the resizing logic to operate // strictly inside renderer. -// The latter is necessary to support a handful of layout tests that were +// The latter is necessary to support a handful of web tests that were // written with the expectation of a synchronous resize, and we're going to // eventually rewrite or remove all of them. See http://crbug.com/309760 for // details.
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc index d48078e..f0f67ef2 100644 --- a/content/renderer/service_worker/service_worker_context_client.cc +++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -236,26 +236,20 @@ return WebURLRequest::Priority::kVeryLow; } -// If |is_for_fetch_event| is true, some headers may be omitted according -// to the embedder. It's always true now, but it might change with -// more Onion Souping, and future callsites like Background Fetch probably don't -// want to do the header filtering, since it's important for them to have the -// exact request as sent to network. -void ToWebServiceWorkerRequest(const network::ResourceRequest& request, - const std::string request_body_blob_uuid, - uint64_t request_body_blob_size, - blink::mojom::BlobPtrInfo request_body_blob, - const std::string& client_id, - std::vector<blink::mojom::BlobPtrInfo> blob_ptrs, - blink::WebServiceWorkerRequest* web_request, - bool is_for_fetch_event) { +void ToWebServiceWorkerRequestForFetchEvent( + const network::ResourceRequest& request, + const std::string request_body_blob_uuid, + uint64_t request_body_blob_size, + blink::mojom::BlobPtrInfo request_body_blob, + const std::string& client_id, + std::vector<blink::mojom::BlobPtrInfo> blob_ptrs, + blink::WebServiceWorkerRequest* web_request) { DCHECK(web_request); web_request->SetURL(blink::WebURL(request.url)); web_request->SetMethod(blink::WebString::FromUTF8(request.method)); if (!request.headers.IsEmpty()) { for (net::HttpRequestHeaders::Iterator it(request.headers); it.GetNext();) { - if (!is_for_fetch_event || - !GetContentClient() + if (!GetContentClient() ->renderer() ->IsExcludedHeaderForServiceWorkerFetchEvent(it.name())) { web_request->SetHeader(blink::WebString::FromUTF8(it.name()), @@ -1623,11 +1617,11 @@ // Dispatch the event to the service worker execution context. blink::WebServiceWorkerRequest web_request; - ToWebServiceWorkerRequest( + ToWebServiceWorkerRequestForFetchEvent( std::move(params->request), params->request_body_blob_uuid, params->request_body_blob_size, std::move(params->request_body_blob), params->client_id, std::move(params->request_body_blob_ptrs), - &web_request, true /* is_for_fetch_event */); + &web_request); proxy_->DispatchFetchEvent(event_id, web_request, navigation_preload_sent); }
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/content/renderer/shared_worker/embedded_shared_worker_stub.cc index 12ce4600..329dcf7 100644 --- a/content/renderer/shared_worker/embedded_shared_worker_stub.cc +++ b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -221,8 +221,8 @@ blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, std::unique_ptr<URLLoaderFactoryBundleInfo> factory_bundle, blink::mojom::ControllerServiceWorkerInfoPtr controller_info, - mojom::SharedWorkerHostPtr host, - mojom::SharedWorkerRequest request, + blink::mojom::SharedWorkerHostPtr host, + blink::mojom::SharedWorkerRequest request, service_manager::mojom::InterfaceProviderPtr interface_provider) : binding_(this, std::move(request)), host_(std::move(host)),
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.h b/content/renderer/shared_worker/embedded_shared_worker_stub.h index da70fae..fef56b5 100644 --- a/content/renderer/shared_worker/embedded_shared_worker_stub.h +++ b/content/renderer/shared_worker/embedded_shared_worker_stub.h
@@ -11,20 +11,20 @@ #include "base/macros.h" #include "base/unguessable_token.h" #include "content/common/service_worker/service_worker_provider.mojom.h" -#include "content/common/shared_worker/shared_worker.mojom.h" -#include "content/common/shared_worker/shared_worker_host.mojom.h" #include "content/public/common/renderer_preference_watcher.mojom.h" #include "content/public/common/renderer_preferences.h" #include "ipc/ipc_listener.h" #include "mojo/public/cpp/bindings/binding.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/service_manager/public/mojom/interface_provider.mojom.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" +#include "third_party/blink/public/mojom/worker/shared_worker.mojom.h" +#include "third_party/blink/public/mojom/worker/shared_worker_host.mojom.h" #include "third_party/blink/public/mojom/worker/shared_worker_info.mojom.h" #include "third_party/blink/public/mojom/worker/worker_main_script_load_params.mojom.h" #include "third_party/blink/public/platform/web_content_security_policy.h" #include "third_party/blink/public/platform/web_content_settings_client.h" #include "third_party/blink/public/platform/web_string.h" -#include "third_party/blink/public/web/devtools_agent.mojom.h" #include "third_party/blink/public/web/web_shared_worker_client.h" #include "third_party/blink/public/web/worker_content_settings_proxy.mojom.h" #include "url/gurl.h" @@ -56,7 +56,7 @@ // // This class owns blink::WebSharedWorker. class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient, - public mojom::SharedWorker { + public blink::mojom::SharedWorker { public: EmbeddedSharedWorkerStub( blink::mojom::SharedWorkerInfoPtr info, @@ -73,8 +73,8 @@ blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories, blink::mojom::ControllerServiceWorkerInfoPtr controller_info, - mojom::SharedWorkerHostPtr host, - mojom::SharedWorkerRequest request, + blink::mojom::SharedWorkerHostPtr host, + blink::mojom::SharedWorkerRequest request, service_manager::mojom::InterfaceProviderPtr interface_provider); ~EmbeddedSharedWorkerStub() override; @@ -109,8 +109,8 @@ blink::mojom::DevToolsAgentHostAssociatedPtrInfo host, blink::mojom::DevToolsAgentAssociatedRequest request) override; - mojo::Binding<mojom::SharedWorker> binding_; - mojom::SharedWorkerHostPtr host_; + mojo::Binding<blink::mojom::SharedWorker> binding_; + blink::mojom::SharedWorkerHostPtr host_; const std::string name_; bool running_ = false; GURL url_;
diff --git a/content/renderer/shared_worker/shared_worker_client_impl.cc b/content/renderer/shared_worker/shared_worker_client_impl.cc deleted file mode 100644 index a628bdf7..0000000 --- a/content/renderer/shared_worker/shared_worker_client_impl.cc +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2017 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/shared_worker/shared_worker_client_impl.h" - -#include "content/child/child_thread_impl.h" -#include "content/common/view_messages.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "third_party/blink/public/platform/web_feature.mojom.h" - -namespace content { - -SharedWorkerClientImpl::SharedWorkerClientImpl( - std::unique_ptr<blink::WebSharedWorkerConnectListener> listener) - : listener_(std::move(listener)) {} - -SharedWorkerClientImpl::~SharedWorkerClientImpl() = default; - -void SharedWorkerClientImpl::OnCreated( - blink::mojom::SharedWorkerCreationContextType creation_context_type) { - listener_->WorkerCreated(creation_context_type); -} - -void SharedWorkerClientImpl::OnConnected( - const std::vector<blink::mojom::WebFeature>& features_used) { - listener_->Connected(); - for (auto feature : features_used) - listener_->CountFeature(feature); -} - -void SharedWorkerClientImpl::OnScriptLoadFailed() { - listener_->ScriptLoadFailed(); -} - -void SharedWorkerClientImpl::OnFeatureUsed(blink::mojom::WebFeature feature) { - listener_->CountFeature(feature); -} - -} // namespace content
diff --git a/content/renderer/shared_worker/shared_worker_client_impl.h b/content/renderer/shared_worker/shared_worker_client_impl.h deleted file mode 100644 index c973029..0000000 --- a/content/renderer/shared_worker/shared_worker_client_impl.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2017 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_SHARED_WORKER_SHARED_WORKER_CLIENT_IMPL_H_ -#define CONTENT_RENDERER_SHARED_WORKER_SHARED_WORKER_CLIENT_IMPL_H_ - -#include "base/macros.h" -#include "third_party/blink/public/mojom/worker/shared_worker_client.mojom.h" -#include "third_party/blink/public/web/web_shared_worker_connect_listener.h" - -namespace content { - -// An instance of this class has the same lifetime as the shared worker. -class SharedWorkerClientImpl : public blink::mojom::SharedWorkerClient { - public: - explicit SharedWorkerClientImpl( - std::unique_ptr<blink::WebSharedWorkerConnectListener> listener); - ~SharedWorkerClientImpl() override; - - private: - // mojom::SharedWorkerClient methods: - void OnCreated(blink::mojom::SharedWorkerCreationContextType - creation_context_type) override; - void OnConnected( - const std::vector<blink::mojom::WebFeature>& features_used) override; - void OnScriptLoadFailed() override; - void OnFeatureUsed(blink::mojom::WebFeature feature) override; - - std::unique_ptr<blink::WebSharedWorkerConnectListener> listener_; - - DISALLOW_COPY_AND_ASSIGN(SharedWorkerClientImpl); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_SHARED_WORKER_SHARED_WORKER_CLIENT_IMPL_H_
diff --git a/content/renderer/shared_worker/shared_worker_factory_impl.cc b/content/renderer/shared_worker/shared_worker_factory_impl.cc index 6b3344a..5724ad03 100644 --- a/content/renderer/shared_worker/shared_worker_factory_impl.cc +++ b/content/renderer/shared_worker/shared_worker_factory_impl.cc
@@ -35,8 +35,8 @@ blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories, blink::mojom::ControllerServiceWorkerInfoPtr controller_info, - mojom::SharedWorkerHostPtr host, - mojom::SharedWorkerRequest request, + blink::mojom::SharedWorkerHostPtr host, + blink::mojom::SharedWorkerRequest request, service_manager::mojom::InterfaceProviderPtr interface_provider) { // Bound to the lifetime of the underlying blink::WebSharedWorker instance. new EmbeddedSharedWorkerStub(
diff --git a/content/renderer/shared_worker/shared_worker_factory_impl.h b/content/renderer/shared_worker/shared_worker_factory_impl.h index 4778834..6e81fd7 100644 --- a/content/renderer/shared_worker/shared_worker_factory_impl.h +++ b/content/renderer/shared_worker/shared_worker_factory_impl.h
@@ -36,8 +36,8 @@ blink::mojom::WorkerMainScriptLoadParamsPtr main_script_load_params, std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories, blink::mojom::ControllerServiceWorkerInfoPtr controller_info, - mojom::SharedWorkerHostPtr host, - mojom::SharedWorkerRequest request, + blink::mojom::SharedWorkerHostPtr host, + blink::mojom::SharedWorkerRequest request, service_manager::mojom::InterfaceProviderPtr interface_provider) override; DISALLOW_COPY_AND_ASSIGN(SharedWorkerFactoryImpl);
diff --git a/content/renderer/shared_worker/shared_worker_repository.cc b/content/renderer/shared_worker/shared_worker_repository.cc deleted file mode 100644 index ea4da7a..0000000 --- a/content/renderer/shared_worker/shared_worker_repository.cc +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 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/shared_worker/shared_worker_repository.h" - -#include "content/common/view_messages.h" -#include "content/renderer/render_frame_impl.h" -#include "services/service_manager/public/cpp/interface_provider.h" -#include "third_party/blink/public/web/web_shared_worker_connect_listener.h" - -namespace content { - -SharedWorkerRepository::SharedWorkerRepository( - service_manager::InterfaceProvider* interface_provider) - : interface_provider_(interface_provider) {} - -SharedWorkerRepository::~SharedWorkerRepository() = default; - -void SharedWorkerRepository::Connect( - const blink::WebURL& url, - const blink::WebString& name, - DocumentID document_id, - const blink::WebString& content_security_policy, - blink::mojom::ContentSecurityPolicyType content_security_policy_type, - blink::mojom::IPAddressSpace creation_address_space, - blink::mojom::SharedWorkerCreationContextType creation_context_type, - blink::MessagePortChannel channel, - mojo::ScopedMessagePipeHandle blob_url_token, - std::unique_ptr<blink::WebSharedWorkerConnectListener> listener) { - // Lazy bind the connector. - if (!connector_) - interface_provider_->GetInterface(mojo::MakeRequest(&connector_)); - - blink::mojom::SharedWorkerInfoPtr info(blink::mojom::SharedWorkerInfo::New( - url, name.Utf8(), content_security_policy.Utf8(), - content_security_policy_type, creation_address_space)); - - blink::mojom::SharedWorkerClientPtr client; - AddWorker(document_id, - std::make_unique<SharedWorkerClientImpl>(std::move(listener)), - mojo::MakeRequest(&client)); - - connector_->Connect( - std::move(info), std::move(client), creation_context_type, - channel.ReleaseHandle(), - blink::mojom::BlobURLTokenPtr(blink::mojom::BlobURLTokenPtrInfo( - std::move(blob_url_token), blink::mojom::BlobURLToken::Version_))); -} - -void SharedWorkerRepository::DocumentDetached(DocumentID document_id) { - // Delete any associated SharedWorkerClientImpls, which will signal, via the - // dropped mojo connection, disinterest in the associated shared worker. - client_map_.erase(document_id); -} - -void SharedWorkerRepository::AddWorker( - DocumentID document_id, - std::unique_ptr<blink::mojom::SharedWorkerClient> impl, - blink::mojom::SharedWorkerClientRequest request) { - std::pair<ClientMap::iterator, bool> result = - client_map_.emplace(document_id, nullptr); - std::unique_ptr<ClientSet>& clients = result.first->second; - if (!clients) - clients = std::make_unique<ClientSet>(); - clients->AddBinding(std::move(impl), std::move(request)); -} - -} // namespace content
diff --git a/content/renderer/shared_worker/shared_worker_repository.h b/content/renderer/shared_worker/shared_worker_repository.h deleted file mode 100644 index 20ef3eed..0000000 --- a/content/renderer/shared_worker/shared_worker_repository.h +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 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_SHARED_WORKER_SHARED_WORKER_REPOSITORY_H_ -#define CONTENT_RENDERER_SHARED_WORKER_SHARED_WORKER_REPOSITORY_H_ - -#include <list> -#include <map> -#include <memory> - -#include "base/macros.h" -#include "content/common/shared_worker/shared_worker_connector.mojom.h" -#include "content/renderer/shared_worker/shared_worker_client_impl.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "mojo/public/cpp/bindings/strong_binding_set.h" -#include "third_party/blink/public/mojom/csp/content_security_policy.mojom.h" -#include "third_party/blink/public/web/web_shared_worker_repository_client.h" - -namespace blink { -class MessagePortChannel; -} - -namespace service_manager { -class InterfaceProvider; -} - -namespace content { - -class SharedWorkerRepository final - : public blink::WebSharedWorkerRepositoryClient { - public: - explicit SharedWorkerRepository( - service_manager::InterfaceProvider* interface_provider); - ~SharedWorkerRepository(); - - // WebSharedWorkerRepositoryClient overrides. - void Connect( - const blink::WebURL& url, - const blink::WebString& name, - DocumentID document_id, - const blink::WebString& content_security_policy, - blink::mojom::ContentSecurityPolicyType, - blink::mojom::IPAddressSpace, - blink::mojom::SharedWorkerCreationContextType, - blink::MessagePortChannel channel, - mojo::ScopedMessagePipeHandle blob_url_token, - std::unique_ptr<blink::WebSharedWorkerConnectListener> listener) override; - void DocumentDetached(DocumentID document_id) override; - - private: - void AddWorker(DocumentID document_id, - std::unique_ptr<blink::mojom::SharedWorkerClient> impl, - blink::mojom::SharedWorkerClientRequest request); - - service_manager::InterfaceProvider* interface_provider_; - - mojom::SharedWorkerConnectorPtr connector_; - - using ClientSet = mojo::StrongBindingSet<blink::mojom::SharedWorkerClient>; - using ClientMap = std::map<DocumentID, std::unique_ptr<ClientSet>>; - ClientMap client_map_; - - DISALLOW_COPY_AND_ASSIGN(SharedWorkerRepository); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_SHARED_WORKER_SHARED_WORKER_REPOSITORY_H_
diff --git a/content/renderer/v8_value_converter_impl.cc b/content/renderer/v8_value_converter_impl.cc index 833151b..90b588a 100644 --- a/content/renderer/v8_value_converter_impl.cc +++ b/content/renderer/v8_value_converter_impl.cc
@@ -27,7 +27,7 @@ v8::Local<v8::Object> value, std::unique_ptr<base::Value>* out, v8::Isolate* isolate, - const FromV8ValueCallback& callback) const { + const FromV8ValueCallback& callback) { return false; } @@ -35,29 +35,28 @@ v8::Local<v8::Array> value, std::unique_ptr<base::Value>* out, v8::Isolate* isolate, - const FromV8ValueCallback& callback) const { + const FromV8ValueCallback& callback) { return false; } bool V8ValueConverter::Strategy::FromV8ArrayBuffer( v8::Local<v8::Object> value, std::unique_ptr<base::Value>* out, - v8::Isolate* isolate) const { + v8::Isolate* isolate) { return false; } bool V8ValueConverter::Strategy::FromV8Number( v8::Local<v8::Number> value, - std::unique_ptr<base::Value>* out) const { + std::unique_ptr<base::Value>* out) { return false; } bool V8ValueConverter::Strategy::FromV8Undefined( - std::unique_ptr<base::Value>* out) const { + std::unique_ptr<base::Value>* out) { return false; } - namespace { // For the sake of the storage API, make this quite large. @@ -212,7 +211,8 @@ } v8::Local<v8::Value> V8ValueConverterImpl::ToV8Value( - const base::Value* value, v8::Local<v8::Context> context) const { + const base::Value* value, + v8::Local<v8::Context> context) { v8::Context::Scope context_scope(context); v8::EscapableHandleScope handle_scope(context->GetIsolate()); return handle_scope.Escape( @@ -221,7 +221,7 @@ std::unique_ptr<base::Value> V8ValueConverterImpl::FromV8Value( v8::Local<v8::Value> val, - v8::Local<v8::Context> context) const { + v8::Local<v8::Context> context) { v8::Context::Scope context_scope(context); v8::HandleScope handle_scope(context->GetIsolate()); FromV8ValueState state(avoid_identity_hash_for_testing_);
diff --git a/content/renderer/v8_value_converter_impl.h b/content/renderer/v8_value_converter_impl.h index 16d19a5f4..a6ae3c7 100644 --- a/content/renderer/v8_value_converter_impl.h +++ b/content/renderer/v8_value_converter_impl.h
@@ -31,12 +31,11 @@ void SetStripNullFromObjects(bool val) override; void SetConvertNegativeZeroToInt(bool val) override; void SetStrategy(Strategy* strategy) override; - v8::Local<v8::Value> ToV8Value( - const base::Value* value, - v8::Local<v8::Context> context) const override; + v8::Local<v8::Value> ToV8Value(const base::Value* value, + v8::Local<v8::Context> context) override; std::unique_ptr<base::Value> FromV8Value( v8::Local<v8::Value> value, - v8::Local<v8::Context> context) const override; + v8::Local<v8::Context> context) override; private: friend class ScopedAvoidIdentityHashForTesting;
diff --git a/content/renderer/v8_value_converter_impl_unittest.cc b/content/renderer/v8_value_converter_impl_unittest.cc index e83c800..6c1b42b 100644 --- a/content/renderer/v8_value_converter_impl_unittest.cc +++ b/content/renderer/v8_value_converter_impl_unittest.cc
@@ -170,7 +170,7 @@ return child->IsNull(); } - void TestWeirdType(const V8ValueConverterImpl& converter, + void TestWeirdType(V8ValueConverterImpl& converter, v8::Local<v8::Value> val, base::Value::Type expected_type, std::unique_ptr<base::Value> expected_value) { @@ -1042,29 +1042,29 @@ bool FromV8Object(v8::Local<v8::Object> value, std::unique_ptr<base::Value>* out, v8::Isolate* isolate, - const FromV8ValueCallback& callback) const override { + const FromV8ValueCallback& callback) override { *out = NewReferenceValue(); return true; } bool FromV8Array(v8::Local<v8::Array> value, std::unique_ptr<base::Value>* out, v8::Isolate* isolate, - const FromV8ValueCallback& callback) const override { + const FromV8ValueCallback& callback) override { *out = NewReferenceValue(); return true; } bool FromV8ArrayBuffer(v8::Local<v8::Object> value, std::unique_ptr<base::Value>* out, - v8::Isolate* isolate) const override { + v8::Isolate* isolate) override { *out = NewReferenceValue(); return true; } bool FromV8Number(v8::Local<v8::Number> value, - std::unique_ptr<base::Value>* out) const override { + std::unique_ptr<base::Value>* out) override { *out = NewReferenceValue(); return true; } - bool FromV8Undefined(std::unique_ptr<base::Value>* out) const override { + bool FromV8Undefined(std::unique_ptr<base::Value>* out) override { *out = NewReferenceValue(); return true; } @@ -1131,25 +1131,25 @@ bool FromV8Object(v8::Local<v8::Object> value, std::unique_ptr<base::Value>* out, v8::Isolate* isolate, - const FromV8ValueCallback& callback) const override { + const FromV8ValueCallback& callback) override { return false; } bool FromV8Array(v8::Local<v8::Array> value, std::unique_ptr<base::Value>* out, v8::Isolate* isolate, - const FromV8ValueCallback& callback) const override { + const FromV8ValueCallback& callback) override { return false; } bool FromV8ArrayBuffer(v8::Local<v8::Object> value, std::unique_ptr<base::Value>* out, - v8::Isolate* isolate) const override { + v8::Isolate* isolate) override { return false; } bool FromV8Number(v8::Local<v8::Number> value, - std::unique_ptr<base::Value>* out) const override { + std::unique_ptr<base::Value>* out) override { return false; } - bool FromV8Undefined(std::unique_ptr<base::Value>* out) const override { + bool FromV8Undefined(std::unique_ptr<base::Value>* out) override { return false; } };
diff --git a/content/renderer/web_test_dependencies.cc b/content/renderer/web_test_dependencies.cc new file mode 100644 index 0000000..5ff39a7 --- /dev/null +++ b/content/renderer/web_test_dependencies.cc
@@ -0,0 +1,9 @@ +// Copyright 2016 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/web_test_dependencies.h" + +namespace content { +WebTestDependencies::~WebTestDependencies() {} +} // namespace content
diff --git a/content/renderer/web_test_dependencies.h b/content/renderer/web_test_dependencies.h new file mode 100644 index 0000000..3e3e88bb --- /dev/null +++ b/content/renderer/web_test_dependencies.h
@@ -0,0 +1,60 @@ +// Copyright 2016 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_WEB_TEST_DEPENDENCIES_H_ +#define CONTENT_RENDERER_WEB_TEST_DEPENDENCIES_H_ + +#include <stdint.h> +#include <memory> + +#include "base/memory/ref_counted.h" +#include "components/viz/common/frame_sinks/copy_output_request.h" +#include "content/common/content_export.h" + +namespace cc { +class CopyOutputRequest; +class LayerTreeFrameSink; +class SwapPromise; +} // namespace cc + +namespace gpu { +class GpuChannelHost; +class GpuMemoryBufferManager; +} // namespace gpu + +namespace viz { +class ContextProvider; +class RasterContextProvider; +} // namespace viz + +namespace content { +class CompositorDependencies; + +// This class allows injection of WebTest-specific behaviour to the +// RenderThreadImpl. +class CONTENT_EXPORT WebTestDependencies { + public: + virtual ~WebTestDependencies(); + + // Returns true if the web tests should use the display compositor pixel + // dumps. + virtual bool UseDisplayCompositorPixelDump() const = 0; + + virtual std::unique_ptr<cc::LayerTreeFrameSink> CreateLayerTreeFrameSink( + int32_t routing_id, + scoped_refptr<gpu::GpuChannelHost> gpu_channel, + scoped_refptr<viz::ContextProvider> compositor_context_provider, + scoped_refptr<viz::RasterContextProvider> worker_context_provider, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, + CompositorDependencies* deps) = 0; + + // Returns a SwapPromise which should be queued for the next compositor frame. + virtual std::unique_ptr<cc::SwapPromise> RequestCopyOfOutput( + int32_t routing_id, + std::unique_ptr<viz::CopyOutputRequest> request) = 0; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_WEB_TEST_DEPENDENCIES_H_
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn index a547dfe..4836e76c 100644 --- a/content/shell/BUILD.gn +++ b/content/shell/BUILD.gn
@@ -290,9 +290,9 @@ "//content/public/common:service_names", "//content/shell/test_runner:test_runner", "//content/test:content_test_mojo_bindings", - "//content/test:layouttest_support", - "//content/test:mojo_layouttest_bindings", + "//content/test:mojo_web_test_bindings", "//content/test:test_support", + "//content/test:web_test_support", "//device/bluetooth", "//device/bluetooth:fake_bluetooth", "//device/bluetooth:mocks", @@ -348,8 +348,8 @@ deps += [ "//third_party/fuchsia-sdk/sdk:policy" ] } - # Annoyingly, this target and layouttest_support have circular includes. - allow_circular_includes_from = [ "//content/test:layouttest_support" ] + # Annoyingly, this target and web_test_support have circular includes. + allow_circular_includes_from = [ "//content/test:web_test_support" ] if (enable_plugins) { deps += [
diff --git a/content/shell/android/BUILD.gn b/content/shell/android/BUILD.gn index de25005..6be386b4 100644 --- a/content/shell/android/BUILD.gn +++ b/content/shell/android/BUILD.gn
@@ -172,7 +172,7 @@ "//base:base_java_test_support", "//components/crash/android:java", "//content/public/android:content_java", - "//content/public/test/android:layouttest_java_support", + "//content/public/test/android:web_test_java_support", "//media/capture/video/android:capture_java", "//net/android:net_java", "//services/shape_detection:shape_detection_java",
diff --git a/content/shell/app/blink_test_platform_support_android.cc b/content/shell/app/blink_test_platform_support_android.cc index 2b37988..3029ce6 100644 --- a/content/shell/app/blink_test_platform_support_android.cc +++ b/content/shell/app/blink_test_platform_support_android.cc
@@ -34,7 +34,7 @@ } bool BlinkTestPlatformInitialize() { - // Initialize Skia with the font configuration files crafted for layout tests. + // Initialize Skia with the font configuration files crafted for web tests. SkFontMgr_Android_CustomFonts custom; custom.fSystemFontUse = SkFontMgr_Android_CustomFonts::kOnlyCustom; custom.fBasePath = kFontDirectory;
diff --git a/content/shell/app/blink_test_platform_support_fuchsia.cc b/content/shell/app/blink_test_platform_support_fuchsia.cc index 650d504a..3ac315c 100644 --- a/content/shell/app/blink_test_platform_support_fuchsia.cc +++ b/content/shell/app/blink_test_platform_support_fuchsia.cc
@@ -15,7 +15,7 @@ } bool BlinkTestPlatformInitialize() { - // Initialize Skia with the font configuration files crafted for layout tests. + // Initialize Skia with the font configuration files crafted for web tests. SkFontMgr_Android_CustomFonts custom; custom.fSystemFontUse = SkFontMgr_Android_CustomFonts::kOnlyCustom; custom.fBasePath = "/pkg/test_fonts/";
diff --git a/content/shell/app/blink_test_platform_support_mac.mm b/content/shell/app/blink_test_platform_support_mac.mm index 674de25f..3e9fa971 100644 --- a/content/shell/app/blink_test_platform_support_mac.mm +++ b/content/shell/app/blink_test_platform_support_mac.mm
@@ -16,8 +16,8 @@ namespace { -void SetDefaultsToLayoutTestValues(void) { - // So we can match the WebKit layout tests, we want to force a bunch of +void SetDefaultsToWebTestValues(void) { + // So we can match the Blnk web tests, we want to force a bunch of // preferences that control appearance to match. // (We want to do this as early as possible in application startup so // the settings are in before any higher layers could cache values.) @@ -25,7 +25,7 @@ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; // Do not set text-rendering prefs (AppleFontSmoothing, // AppleAntiAliasingThreshold) here: Skia picks the right settings for this - // in layout test mode, see FontSkia.cpp in WebKit and + // in web test mode, see FontSkia.cpp in WebKit and // SkFontHost_mac_coretext.cpp in skia. const NSInteger kBlueTintedAppearance = 1; [defaults setInteger:kBlueTintedAppearance @@ -43,7 +43,7 @@ [defaults setObject:@"Always" forKey:@"AppleShowScrollBars"]; - // Disable AppNap since layout tests do not always meet the requirements to + // Disable AppNap since web tests do not always meet the requirements to // avoid "napping" which will cause test timeouts. http://crbug.com/811525. [defaults setBool:YES forKey:@"NSAppSleepDisabled"]; } @@ -55,8 +55,7 @@ } bool BlinkTestPlatformInitialize() { - - SetDefaultsToLayoutTestValues(); + SetDefaultsToWebTestValues(); // Load font files in the resource folder. static const char* const kFontFileNames[] = {"Ahem.TTF",
diff --git a/content/shell/app/shell_main_delegate.cc b/content/shell/app/shell_main_delegate.cc index e1d00d9..537e1a40 100644 --- a/content/shell/app/shell_main_delegate.cc +++ b/content/shell/app/shell_main_delegate.cc
@@ -23,8 +23,8 @@ #include "content/public/browser/browser_main_runner.h" #include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" -#include "content/public/test/layouttest_support.h" #include "content/public/test/ppapi_test_utils.h" +#include "content/public/test/web_test_support.h" #include "content/shell/app/blink_test_platform_support.h" #include "content/shell/app/shell_crash_reporter_client.h" #include "content/shell/browser/shell_browser_main.h" @@ -201,7 +201,7 @@ } } - EnableBrowserLayoutTestMode(); + EnableBrowserWebTestMode(); #if BUILDFLAG(ENABLE_PLUGINS) if (!ppapi::RegisterBlinkTestPlugin(&command_line)) { @@ -215,7 +215,7 @@ #if !defined(OS_ANDROID) // TODO(crbug/567947) Enable display compositor pixel dumps for Android // once testing becomes possible on post-kitkat OSes, and once we've - // had a chance to debug the layout test failures that occur when this + // had a chance to debug the web test failures that occur when this // flag is present. command_line.AppendSwitch(switches::kEnableDisplayCompositorPixelDump); #endif @@ -254,7 +254,7 @@ // and display compositor pixel dumps. if (command_line.HasSwitch(switches::kEnableDisplayCompositorPixelDump)) { // TODO(crbug.com/894613) Add kRunAllCompositorStagesBeforeDraw back here - // once you figure out why it causes so much layout test flakiness. + // once you figure out why it causes so much web test flakiness. // command_line.AppendSwitch(switches::kRunAllCompositorStagesBeforeDraw); command_line.AppendSwitch(cc::switches::kDisableCheckerImaging); } @@ -282,7 +282,7 @@ "srgb"); } - // We want stable/baseline results when running layout tests. + // We want stable/baseline results when running web tests. command_line.AppendSwitch(switches::kDisableSkiaRuntimeOpts); command_line.AppendSwitch(switches::kDisallowNonExactResourceReuse);
diff --git a/content/shell/browser/content_shell_browser_manifest_overlay.json b/content/shell/browser/content_shell_browser_manifest_overlay.json index 98f8dd0..48bf90c 100644 --- a/content/shell/browser/content_shell_browser_manifest_overlay.json +++ b/content/shell/browser/content_shell_browser_manifest_overlay.json
@@ -4,7 +4,7 @@ "service_manager:connector": { "provides": { "renderer": [ - "content.mojom.MojoLayoutTestHelper", + "content.mojom.MojoWebTestHelper", "content.mojom.FakeBluetoothChooser", "content.mojom.WebTestBluetoothFakeAdapterSetter", "bluetooth.mojom.FakeBluetooth" @@ -21,7 +21,7 @@ "navigation:frame": { "provides": { "renderer": [ - "content.mojom.MojoLayoutTestHelper" + "content.mojom.MojoWebTestHelper" ] } }
diff --git a/content/shell/browser/renderer_host/shell_render_widget_host_view_mac_delegate.mm b/content/shell/browser/renderer_host/shell_render_widget_host_view_mac_delegate.mm index 099a70e..338b4a89 100644 --- a/content/shell/browser/renderer_host/shell_render_widget_host_view_mac_delegate.mm +++ b/content/shell/browser/renderer_host/shell_render_widget_host_view_mac_delegate.mm
@@ -16,7 +16,7 @@ - (id)init { if ((self = [super init])) { - // Throw out all native input events if we are running with layout test + // Throw out all native input events if we are running with web test // enabled. drop_events_ = switches::IsRunWebTestsSwitchPresent(); }
diff --git a/content/shell/browser/shell.cc b/content/shell/browser/shell.cc index 43f5c34..961fbe17 100644 --- a/content/shell/browser/shell.cc +++ b/content/shell/browser/shell.cc
@@ -405,11 +405,11 @@ // Normally, the difference between NEW_POPUP and NEW_WINDOW is that a popup // should have no toolbar, no status bar, no menu bar, no scrollbars and be // not resizable. For simplicity and to enable new testing scenarios in - // content shell and layout tests, popups don't get special treatment below + // content shell and web tests, popups don't get special treatment below // (i.e. they will have a toolbar and other things described here). case WindowOpenDisposition::NEW_POPUP: case WindowOpenDisposition::NEW_WINDOW: - // content_shell doesn't really support tabs, but some layout tests use + // content_shell doesn't really support tabs, but some web tests use // middle click (which translates into kNavigationPolicyNewBackgroundTab), // so we treat the cases below just like a NEW_WINDOW disposition. case WindowOpenDisposition::NEW_BACKGROUND_TAB: @@ -429,7 +429,7 @@ case WindowOpenDisposition::SINGLETON_TAB: // No incognito mode in content_shell: case WindowOpenDisposition::OFF_THE_RECORD: - // TODO(lukasza): Investigate if some layout tests might need support for + // TODO(lukasza): Investigate if some web tests might need support for // SAVE_TO_DISK disposition. This would probably require that // BlinkTestController always sets up and cleans up a temporary directory // as the default downloads destinations for the duration of a test.
diff --git a/content/shell/browser/shell_platform_data_aura.cc b/content/shell/browser/shell_platform_data_aura.cc index df05a9c..6672d886 100644 --- a/content/shell/browser/shell_platform_data_aura.cc +++ b/content/shell/browser/shell_platform_data_aura.cc
@@ -98,7 +98,7 @@ // TODO(https://crbug.com/872339): Implement PlatformScreen for all // platforms and remove this code. if (!screen_) { - // Some layout tests expect to be able to resize the window, so the screen + // Some web tests expect to be able to resize the window, so the screen // must be larger than the window. screen_.reset( aura::TestScreen::Create(gfx::ScaleToCeiledSize(initial_size, 2.0)));
diff --git a/content/shell/browser/web_test/blink_test_controller.cc b/content/shell/browser/web_test/blink_test_controller.cc index 015fbd6..4f1a69e8 100644 --- a/content/shell/browser/web_test/blink_test_controller.cc +++ b/content/shell/browser/web_test/blink_test_controller.cc
@@ -54,7 +54,7 @@ #include "content/public/common/bindings_policy.h" #include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" -#include "content/public/test/layouttest_support.h" +#include "content/public/test/web_test_support.h" #include "content/shell/browser/shell.h" #include "content/shell/browser/shell_browser_context.h" #include "content/shell/browser/shell_content_browser_client.h" @@ -99,7 +99,7 @@ result.append(indent, ' '); } - std::string url = test_runner::NormalizeLayoutTestURL( + std::string url = test_runner::NormalizeWebTestURL( base::UTF16ToUTF8(frame_state.url_string.value_or(base::string16()))); result.append(url); DCHECK(frame_state.target); @@ -427,14 +427,14 @@ main_window_->web_contents()->GetRenderViewHost()->GetMainFrame()) .FlushForTesting(); - // Loading the URL will immediately start the layout test. Manually call + // Loading the URL will immediately start the web test. Manually call // LoadURLWithParams on the WebContents to avoid extraneous calls from - // content::Shell such as SetFocus(), which could race with the layout + // content::Shell such as SetFocus(), which could race with the web // test. NavigationController::LoadURLParams params(test_url_); // Using PAGE_TRANSITION_LINK avoids a BrowsingInstance/process swap - // between layout tests. + // between web tests. params.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK); @@ -489,7 +489,7 @@ } else { NavigationController::LoadURLParams params(test_url_); // Using PAGE_TRANSITION_LINK avoids a BrowsingInstance/process swap - // between layout tests. + // between web tests. params.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK); params.should_clear_history_list = true; @@ -562,7 +562,7 @@ if (should_override_prefs_) { *prefs = prefs_; } else { - ApplyLayoutTestDefaultPreferences(prefs); + ApplyWebTestDefaultPreferences(prefs); if (is_compositing_test_) { base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); if (!command_line.HasSwitch(switches::kDisableGpu)) @@ -598,7 +598,7 @@ for (auto* window : Shell::windows()) { WebContents* web_contents = window->web_contents(); // Only capture the history from windows in the same process_host as the - // main window. During layout tests, we only use two processes when a + // main window. During web tests, we only use two processes when a // devtools window is open. // TODO(https://crbug.com/771003): Dump history for all WebContentses, not // just ones that happen to be in the same process_host as the main test @@ -630,7 +630,7 @@ // force each renderer to produce a frame. if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableThreadedCompositing)) { - rwhv->EnsureSurfaceSynchronizedForLayoutTest(); + rwhv->EnsureSurfaceSynchronizedForWebTest(); EnqueueSurfaceCopyRequest(); } else { CompositeAllFramesThen( @@ -658,7 +658,7 @@ void BlinkTestController::CompositeAllFramesThen( base::OnceCallback<void()> callback) { // Only allow a single call to CompositeAllFramesThen(), without a call to - // ResetAfterLayoutTest() in between. More than once risks overlapping calls, + // ResetAfterWebTest() in between. More than once risks overlapping calls, // due to the asynchronous nature of CompositeNodeQueueThen(), which can lead // to use-after-free, e.g. // https://clusterfuzz.com/v2/testcase-detail/4929420383748096
diff --git a/content/shell/browser/web_test/blink_test_controller.h b/content/shell/browser/web_test/blink_test_controller.h index 7960f15d..07f5f73 100644 --- a/content/shell/browser/web_test/blink_test_controller.h +++ b/content/shell/browser/web_test/blink_test_controller.h
@@ -298,7 +298,7 @@ // Map from frame_tree_node_id into frame-specific dumps. std::map<int, std::string> frame_to_layout_dump_map_; - // Number of LayoutTestControl.DumpFrameLayout responses we are waiting for. + // Number of WebTestControl.DumpFrameLayout responses we are waiting for. int pending_layout_dumps_; // Renderer processes are observed to detect crashes.
diff --git a/content/shell/browser/web_test/devtools_protocol_test_bindings.cc b/content/shell/browser/web_test/devtools_protocol_test_bindings.cc index 19a55ae..be2c7c01 100644 --- a/content/shell/browser/web_test/devtools_protocol_test_bindings.cc +++ b/content/shell/browser/web_test/devtools_protocol_test_bindings.cc
@@ -26,7 +26,7 @@ // This constant should be in sync with // the constant // kMaxMessageChunkSize in chrome/browser/devtools/devtools_ui_bindings.cc. -constexpr size_t kLayoutTestMaxMessageChunkSize = +constexpr size_t kWebTestMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4; } // namespace @@ -113,7 +113,7 @@ void DevToolsProtocolTestBindings::DispatchProtocolMessage( DevToolsAgentHost* agent_host, const std::string& message) { - if (message.length() < kLayoutTestMaxMessageChunkSize) { + if (message.length() < kWebTestMaxMessageChunkSize) { std::string param; base::EscapeJSONString(message, true, ¶m); std::string code = "DevToolsAPI.dispatchMessage(" + param + ");"; @@ -124,9 +124,9 @@ size_t total_size = message.length(); for (size_t pos = 0; pos < message.length(); - pos += kLayoutTestMaxMessageChunkSize) { + pos += kWebTestMaxMessageChunkSize) { std::string param; - base::EscapeJSONString(message.substr(pos, kLayoutTestMaxMessageChunkSize), + base::EscapeJSONString(message.substr(pos, kWebTestMaxMessageChunkSize), true, ¶m); std::string code = "DevToolsAPI.dispatchMessageChunk(" + param + "," + std::to_string(pos ? 0 : total_size) + ");";
diff --git a/content/shell/browser/web_test/fake_bluetooth_chooser.cc b/content/shell/browser/web_test/fake_bluetooth_chooser.cc index 4bd83146..79508bb 100644 --- a/content/shell/browser/web_test/fake_bluetooth_chooser.cc +++ b/content/shell/browser/web_test/fake_bluetooth_chooser.cc
@@ -8,7 +8,7 @@ #include <utility> #include "content/public/browser/bluetooth_chooser.h" -#include "content/public/test/layouttest_support.h" +#include "content/public/test/web_test_support.h" #include "content/shell/common/web_test/fake_bluetooth_chooser.mojom.h" namespace content {
diff --git a/content/shell/browser/web_test/fake_bluetooth_chooser.h b/content/shell/browser/web_test/fake_bluetooth_chooser.h index 997c67e..613f8cb 100644 --- a/content/shell/browser/web_test/fake_bluetooth_chooser.h +++ b/content/shell/browser/web_test/fake_bluetooth_chooser.h
@@ -14,7 +14,7 @@ namespace content { // Implementation of FakeBluetoothChooser in -// src/content/shell/common/layout_test/fake_bluetooth_chooser.mojom +// src/content/shell/common/web_test/fake_bluetooth_chooser.mojom // to provide a method of controlling the Bluetooth chooser during a test. // Serves as a Bluetooth chooser factory for choosers that can be manually // controlled through the Mojo API. Only one instance of this class will exist @@ -31,7 +31,7 @@ // Resets the test scan duration to timeout immediately. ~FakeBluetoothChooser() override; - // LayoutTestContentBrowserClient will create an instance of this class when a + // WebTestContentBrowserClient will create an instance of this class when a // request is bound. It will maintain ownership of the instance temporarily // until the chooser is opened. When the chooser is opened, ownership of this // instance will shift to the caller of
diff --git a/content/shell/browser/web_test/leak_detector.cc b/content/shell/browser/web_test/leak_detector.cc index 286d2fb6..333d878 100644 --- a/content/shell/browser/web_test/leak_detector.cc +++ b/content/shell/browser/web_test/leak_detector.cc
@@ -21,7 +21,7 @@ // TODO(hajimehoshi): Now these are hard-corded. If we add a target to count // objects like RefCounted whose initial state is diffcult to estimate, we stop // using hard-coded values. Instead, we need to load about:blank ahead of the -// layout tests actually and initialize LeakDetector by the got values. +// web tests actually and initialize LeakDetector by the got values. const int kInitialNumberOfLiveAudioNodes = 0; const int kInitialNumberOfLiveDocuments = 1; const int kInitialNumberOfLiveNodes = 4;
diff --git a/content/shell/browser/web_test/mojo_web_test_helper.cc b/content/shell/browser/web_test/mojo_web_test_helper.cc index 833bd297..9e9682c 100644 --- a/content/shell/browser/web_test/mojo_web_test_helper.cc +++ b/content/shell/browser/web_test/mojo_web_test_helper.cc
@@ -13,7 +13,7 @@ MojoWebTestHelper::~MojoWebTestHelper() {} // static -void MojoWebTestHelper::Create(mojom::MojoLayoutTestHelperRequest request) { +void MojoWebTestHelper::Create(mojom::MojoWebTestHelperRequest request) { mojo::MakeStrongBinding(std::make_unique<MojoWebTestHelper>(), std::move(request)); }
diff --git a/content/shell/browser/web_test/mojo_web_test_helper.h b/content/shell/browser/web_test/mojo_web_test_helper.h index eebb2c6..aa2d2456 100644 --- a/content/shell/browser/web_test/mojo_web_test_helper.h +++ b/content/shell/browser/web_test/mojo_web_test_helper.h
@@ -6,18 +6,18 @@ #define CONTENT_SHELL_BROWSER_WEB_TEST_MOJO_WEB_TEST_HELPER_H_ #include "base/macros.h" -#include "content/test/data/mojo_layouttest_test.mojom.h" +#include "content/test/data/mojo_web_test_helper_test.mojom.h" namespace content { -class MojoWebTestHelper : public mojom::MojoLayoutTestHelper { +class MojoWebTestHelper : public mojom::MojoWebTestHelper { public: MojoWebTestHelper(); ~MojoWebTestHelper() override; - static void Create(mojom::MojoLayoutTestHelperRequest request); + static void Create(mojom::MojoWebTestHelperRequest request); - // mojom::MojoLayoutTestHelper: + // mojom::MojoWebTestHelper: void Reverse(const std::string& message, ReverseCallback callback) override; private:
diff --git a/content/shell/browser/web_test/test_info_extractor.cc b/content/shell/browser/web_test/test_info_extractor.cc index 24603b1..de585798 100644 --- a/content/shell/browser/web_test/test_info_extractor.cc +++ b/content/shell/browser/web_test/test_info_extractor.cc
@@ -31,8 +31,8 @@ #if defined(OS_FUCHSIA) // Fuchsia doesn't support stdin stream for packaged apps. This means that when // running content_shell on Fuchsia it's not possible to use stdin to pass list -// of tests. To workaround this issue for layout tests we redirect stdin stream -// to a TCP socket connected to the layout test runner. The runner uses +// of tests. To workaround this issue for web tests we redirect stdin stream +// to a TCP socket connected to the web test runner. The runner uses // --stdin-redirect to specify address and port for stdin redirection. constexpr char kStdinRedirectSwitch[] = "stdin-redirect"; @@ -65,7 +65,7 @@ #endif // defined(OS_FUCHSIA) -std::unique_ptr<TestInfo> GetTestInfoFromLayoutTestName( +std::unique_ptr<TestInfo> GetTestInfoFromWebTestName( const std::string& test_name, bool protocol_mode) { // A test name is formatted like file:///path/to/test'pixelhash @@ -159,7 +159,7 @@ DCHECK(!test_string.empty()); if (test_string == "QUIT") return nullptr; - return GetTestInfoFromLayoutTestName(test_string, protocol_mode); + return GetTestInfoFromWebTestName(test_string, protocol_mode); } } // namespace content
diff --git a/content/shell/browser/web_test/web_test_background_fetch_delegate.cc b/content/shell/browser/web_test/web_test_background_fetch_delegate.cc index 31287ea..33a51fc 100644 --- a/content/shell/browser/web_test/web_test_background_fetch_delegate.cc +++ b/content/shell/browser/web_test/web_test_background_fetch_delegate.cc
@@ -27,7 +27,7 @@ namespace content { // Implementation of a Download Service client that will be servicing -// Background Fetch requests when running layout tests. +// Background Fetch requests when running web tests. class WebTestBackgroundFetchDelegate::WebTestBackgroundFetchDownloadClient : public download::Client { public: @@ -35,10 +35,7 @@ base::WeakPtr<content::BackgroundFetchDelegate::Client> client) : client_(std::move(client)) {} - ~WebTestBackgroundFetchDownloadClient() override { - if (client_) - client_->OnDelegateShutdown(); - } + ~WebTestBackgroundFetchDownloadClient() override = default; // Registers the |guid| as belonging to a Background Fetch job identified by // |job_unique_id|. Downloads may only be registered once. @@ -190,24 +187,16 @@ } void WebTestBackgroundFetchDelegate::CreateDownloadJob( - std::unique_ptr<BackgroundFetchDescription> fetch_description) {} - -void WebTestBackgroundFetchDelegate::DownloadUrl( - const std::string& job_unique_id, - const std::string& download_guid, - const std::string& method, - const GURL& url, - const net::NetworkTrafficAnnotationTag& traffic_annotation, - const net::HttpRequestHeaders& headers, - bool has_request_body) { + base::WeakPtr<Client> client, + std::unique_ptr<BackgroundFetchDescription> fetch_description) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - // Lazily create the |download_service_| because only very few layout tests + // Lazily create the |download_service_| because only very few web tests // actually require Background Fetch. if (!download_service_) { auto clients = std::make_unique<download::DownloadClientMap>(); auto background_fetch_client = - std::make_unique<WebTestBackgroundFetchDownloadClient>(client()); + std::make_unique<WebTestBackgroundFetchDownloadClient>(client); // Store a reference to the client for storing a GUID -> Unique ID mapping. background_fetch_client_ = background_fetch_client.get(); @@ -231,6 +220,17 @@ {BrowserThread::IO}))); } } +} + +void WebTestBackgroundFetchDelegate::DownloadUrl( + const std::string& job_unique_id, + const std::string& download_guid, + const std::string& method, + const GURL& url, + const net::NetworkTrafficAnnotationTag& traffic_annotation, + const net::HttpRequestHeaders& headers, + bool has_request_body) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); background_fetch_client_->RegisterDownload(download_guid, job_unique_id);
diff --git a/content/shell/browser/web_test/web_test_background_fetch_delegate.h b/content/shell/browser/web_test/web_test_background_fetch_delegate.h index d3b8bac..64d7f51d 100644 --- a/content/shell/browser/web_test/web_test_background_fetch_delegate.h +++ b/content/shell/browser/web_test/web_test_background_fetch_delegate.h
@@ -32,6 +32,7 @@ const ResourceRequestInfo::WebContentsGetter& wc_getter, GetPermissionForOriginCallback callback) override; void CreateDownloadJob( + base::WeakPtr<Client> client, std::unique_ptr<BackgroundFetchDescription> fetch_description) override; void DownloadUrl(const std::string& job_unique_id, const std::string& download_guid,
diff --git a/content/shell/browser/web_test/web_test_bluetooth_adapter_provider.cc b/content/shell/browser/web_test/web_test_bluetooth_adapter_provider.cc index a73deedb..8f7d6559 100644 --- a/content/shell/browser/web_test/web_test_bluetooth_adapter_provider.cc +++ b/content/shell/browser/web_test/web_test_bluetooth_adapter_provider.cc
@@ -692,7 +692,7 @@ device::BluetoothRemoteGattCharacteristic::PROPERTY_WRITE); // Crash if WriteRemoteDescriptor called. Not using GoogleMock's Expect - // because this is used in layout tests that may not report a mock + // because this is used in web tests that may not report a mock // expectation. ON_CALL(*client_config, WriteRemoteDescriptor(_, _, _)) .WillByDefault( @@ -708,9 +708,9 @@ device::BluetoothRemoteGattCharacteristic::PROPERTY_WRITE); // Crash if ReadRemoteDescriptor called. Not using GoogleMock's Expect - // because this is used in layout tests that may not report a mock + // because this is used in web tests that may not report a mock // expectation - // error correctly as a layout test failure. + // error correctly as a web test failure. ON_CALL(*no_read_descriptor, ReadRemoteDescriptor(_, _)) .WillByDefault( Invoke([](const BluetoothRemoteGattDescriptor::ValueCallback&, @@ -1390,8 +1390,8 @@ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE)); // Crash if ReadRemoteCharacteristic called. Not using GoogleMock's Expect - // because this is used in layout tests that may not report a mock expectation - // error correctly as a layout test failure. + // because this is used in web tests that may not report a mock expectation + // error correctly as a web test failure. ON_CALL(*blocklist_exclude_reads_characteristic, ReadRemoteCharacteristic(_, _)) .WillByDefault( @@ -1423,8 +1423,8 @@ BluetoothRemoteGattCharacteristic::PROPERTY_READ)); // Crash if ReadRemoteCharacteristic called. Not using GoogleMock's Expect - // because this is used in layout tests that may not report a mock expectation - // error correctly as a layout test failure. + // because this is used in web tests that may not report a mock expectation + // error correctly as a web test failure. ON_CALL(*serial_number_string, ReadRemoteCharacteristic(_, _)) .WillByDefault( Invoke([](const BluetoothRemoteGattCharacteristic::ValueCallback&, @@ -1480,8 +1480,8 @@ .WillByDefault(RunCallback<0>(value)); // Crash if WriteRemoteCharacteristic called. Not using GoogleMock's Expect - // because this is used in layout tests that may not report a mock - // expectation error correctly as a layout test failure. + // because this is used in web tests that may not report a mock + // expectation error correctly as a web test failure. ON_CALL(*peripheral_privacy_flag, WriteRemoteCharacteristic(_, _, _)) .WillByDefault( Invoke([](const std::vector<uint8_t>&, const base::Closure&,
diff --git a/content/shell/browser/web_test/web_test_bluetooth_adapter_provider.h b/content/shell/browser/web_test/web_test_bluetooth_adapter_provider.h index c8a48ce..31aac5a 100644 --- a/content/shell/browser/web_test/web_test_bluetooth_adapter_provider.h +++ b/content/shell/browser/web_test/web_test_bluetooth_adapter_provider.h
@@ -21,7 +21,7 @@ namespace content { // Implements fake adapters with named mock data set for use in tests as a -// result of layout tests calling testRunner.setBluetoothFakeAdapter. +// result of web tests calling testRunner.setBluetoothFakeAdapter. // An adapter named 'FooAdapter' in // https://webbluetoothcg.github.io/web-bluetooth/tests/ is provided by a
diff --git a/content/shell/browser/web_test/web_test_bluetooth_fake_adapter_setter_impl.cc b/content/shell/browser/web_test/web_test_bluetooth_fake_adapter_setter_impl.cc index 371a0a5..0fea80a7 100644 --- a/content/shell/browser/web_test/web_test_bluetooth_fake_adapter_setter_impl.cc +++ b/content/shell/browser/web_test/web_test_bluetooth_fake_adapter_setter_impl.cc
@@ -7,7 +7,7 @@ #include <string> #include <utility> -#include "content/public/test/layouttest_support.h" +#include "content/public/test/web_test_support.h" #include "content/shell/browser/web_test/web_test_bluetooth_adapter_provider.h" #include "device/bluetooth/bluetooth_adapter_factory_wrapper.h" #include "mojo/public/cpp/bindings/strong_binding.h"
diff --git a/content/shell/browser/web_test/web_test_browser_main.cc b/content/shell/browser/web_test/web_test_browser_main.cc index 3c0262e..3374f20 100644 --- a/content/shell/browser/web_test/web_test_browser_main.cc +++ b/content/shell/browser/web_test/web_test_browser_main.cc
@@ -53,7 +53,7 @@ *ran_at_least_once = true; #if defined(OS_ANDROID) // The message loop on Android is provided by the system, and does not - // offer a blocking Run() method. For layout tests, use a nested loop + // offer a blocking Run() method. For web tests, use a nested loop // together with a base::RunLoop so it can block until a QuitClosure. base::RunLoop run_loop; content::Shell::SetMainMessageLoopQuitClosure(run_loop.QuitClosure()); @@ -119,16 +119,15 @@ int WebTestBrowserMain( const content::MainFunctionParams& parameters, const std::unique_ptr<content::BrowserMainRunner>& main_runner) { - base::ScopedTempDir browser_context_path_for_layout_tests; + base::ScopedTempDir browser_context_path_for_web_tests; - CHECK(browser_context_path_for_layout_tests.CreateUniqueTempDir()); - CHECK( - !browser_context_path_for_layout_tests.GetPath().MaybeAsASCII().empty()); + CHECK(browser_context_path_for_web_tests.CreateUniqueTempDir()); + CHECK(!browser_context_path_for_web_tests.GetPath().MaybeAsASCII().empty()); base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kIgnoreCertificateErrors); base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( switches::kContentShellDataPath, - browser_context_path_for_layout_tests.GetPath().MaybeAsASCII()); + browser_context_path_for_web_tests.GetPath().MaybeAsASCII()); // Always disable the unsandbox GPU process for DX12 and Vulkan Info // collection to avoid interference. This GPU process is launched 15
diff --git a/content/shell/browser/web_test/web_test_content_browser_client.cc b/content/shell/browser/web_test/web_test_content_browser_client.cc index 6cf0559..2cf8206 100644 --- a/content/shell/browser/web_test/web_test_content_browser_client.cc +++ b/content/shell/browser/web_test/web_test_content_browser_client.cc
@@ -45,9 +45,9 @@ namespace content { namespace { -WebTestContentBrowserClient* g_layout_test_browser_client; +WebTestContentBrowserClient* g_web_test_browser_client; -void BindWebTestHelper(mojom::MojoLayoutTestHelperRequest request, +void BindWebTestHelper(mojom::MojoWebTestHelperRequest request, RenderFrameHost* render_frame_host) { MojoWebTestHelper::Create(std::move(request)); } @@ -89,17 +89,17 @@ WebTestContentBrowserClient::WebTestContentBrowserClient() : mock_platform_notification_service_( std::make_unique<MockPlatformNotificationService>()) { - DCHECK(!g_layout_test_browser_client); + DCHECK(!g_web_test_browser_client); - g_layout_test_browser_client = this; + g_web_test_browser_client = this; } WebTestContentBrowserClient::~WebTestContentBrowserClient() { - g_layout_test_browser_client = nullptr; + g_web_test_browser_client = nullptr; } WebTestContentBrowserClient* WebTestContentBrowserClient::Get() { - return g_layout_test_browser_client; + return g_web_test_browser_client; } WebTestBrowserContext* WebTestContentBrowserClient::GetWebTestBrowserContext() { @@ -243,7 +243,7 @@ // // Don't isolate WPT origins on // 1) platforms where strict Site Isolation is not the default. - // 2) in layout tests under virtual/not-site-per-process where + // 2) in web tests under virtual/not-site-per-process where // --disable-site-isolation-trials switch is used. if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) { // The list of hostnames below is based on
diff --git a/content/shell/browser/web_test/web_test_message_filter.cc b/content/shell/browser/web_test/web_test_message_filter.cc index 3742f2c..d24eb79 100644 --- a/content/shell/browser/web_test/web_test_message_filter.cc +++ b/content/shell/browser/web_test/web_test_message_filter.cc
@@ -12,7 +12,7 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/permission_type.h" -#include "content/public/test/layouttest_support.h" +#include "content/public/test/web_test_support.h" #include "content/shell/browser/shell_browser_context.h" #include "content/shell/browser/shell_content_browser_client.h" #include "content/shell/browser/shell_network_delegate.h"
diff --git a/content/shell/browser/web_test/web_test_push_messaging_service.cc b/content/shell/browser/web_test/web_test_push_messaging_service.cc index 95f355b2..1c5e704 100644 --- a/content/shell/browser/web_test/web_test_push_messaging_service.cc +++ b/content/shell/browser/web_test/web_test_push_messaging_service.cc
@@ -20,7 +20,7 @@ namespace { -// NIST P-256 public key made available to layout tests. Must be an uncompressed +// NIST P-256 public key made available to web tests. Must be an uncompressed // point in accordance with SEC1 2.3.3. const uint8_t kTestP256Key[] = { 0x04, 0x55, 0x52, 0x6A, 0xA5, 0x6E, 0x8E, 0xAA, 0x47, 0x97, 0x36,
diff --git a/content/shell/common/shell_messages.h b/content/shell/common/shell_messages.h index 16f4d8e..f071c55 100644 --- a/content/shell/common/shell_messages.h +++ b/content/shell/common/shell_messages.h
@@ -33,7 +33,7 @@ // Asks the browser process to perform a layout dump spanning all the // (potentially cross-process) frames. This goes through multiple -// LayoutTestControl.DumpFrameLayout calls and ends with sending of +// WebTestControl.DumpFrameLayout calls and ends with sending of // ShellViewMsg_LayoutDumpCompleted. IPC_MESSAGE_ROUTED0(ShellViewHostMsg_InitiateLayoutDump)
diff --git a/content/shell/common/shell_origin_trial_policy.cc b/content/shell/common/shell_origin_trial_policy.cc index 7654e8a9..b6e31223 100644 --- a/content/shell/common/shell_origin_trial_policy.cc +++ b/content/shell/common/shell_origin_trial_policy.cc
@@ -13,7 +13,7 @@ namespace { // This is the public key which the content shell will use to enable origin -// trial features. Trial tokens for use in layout tests can be created with the +// trial features. Trial tokens for use in web tests can be created with the // tool in /tools/origin_trials/generate_token.py, using the private key // contained in /tools/origin_trials/eftest.key. static const uint8_t kOriginTrialPublicKey[] = {
diff --git a/content/shell/common/shell_switches.cc b/content/shell/common/shell_switches.cc index 56fed89..0c5ebf41 100644 --- a/content/shell/common/shell_switches.cc +++ b/content/shell/common/shell_switches.cc
@@ -17,7 +17,7 @@ const char kCrashDumpsDir[] = "crash-dumps-dir"; // Exposes the window.internals object to JavaScript for interactive development -// and debugging of layout tests that rely on it. +// and debugging of web tests that rely on it. const char kExposeInternalsForTesting[] = "expose-internals-for-testing"; // Registers additional font files on Windows (for fonts outside the usual
diff --git a/content/shell/common/web_test/web_test_content_client.cc b/content/shell/common/web_test/web_test_content_client.cc index 5055ecc..d5dac5374 100644 --- a/content/shell/common/web_test/web_test_content_client.cc +++ b/content/shell/common/web_test/web_test_content_client.cc
@@ -10,7 +10,7 @@ bool WebTestContentClient::CanSendWhileSwappedOut(const IPC::Message* message) { switch (message->type()) { - // Used in layout tests; handled in BlinkTestController. + // Used in web tests; handled in BlinkTestController. case ShellViewHostMsg_PrintMessage::ID: return true;
diff --git a/content/shell/common/web_test/web_test_messages.h b/content/shell/common/web_test/web_test_messages.h index 05baac5..d481cfe 100644 --- a/content/shell/common/web_test/web_test_messages.h +++ b/content/shell/common/web_test/web_test_messages.h
@@ -47,18 +47,16 @@ bool /* should dump navigation history */, bool /* should dump pixels */) -// Notifies the browser that one of renderers has changed layout test runtime +// Notifies the browser that one of renderers has changed web test runtime // flags (i.e. has set dump_as_text). -IPC_MESSAGE_CONTROL1( - WebTestHostMsg_WebTestRuntimeFlagsChanged, - base::DictionaryValue /* changed_layout_test_runtime_flags */) +IPC_MESSAGE_CONTROL1(WebTestHostMsg_WebTestRuntimeFlagsChanged, + base::DictionaryValue /* changed_web_test_runtime_flags */) // Used send flag changes to renderers - either when // 1) broadcasting change happening in one renderer to all other renderers, or // 2) sending accumulated changes to a single new renderer. -IPC_MESSAGE_CONTROL1( - WebTestMsg_ReplicateWebTestRuntimeFlagsChanges, - base::DictionaryValue /* changed_layout_test_runtime_flags */) +IPC_MESSAGE_CONTROL1(WebTestMsg_ReplicateWebTestRuntimeFlagsChanges, + base::DictionaryValue /* changed_web_test_runtime_flags */) // Sent by secondary test window to notify the test has finished. IPC_MESSAGE_CONTROL0(WebTestHostMsg_TestFinishedInSecondaryRenderer)
diff --git a/content/shell/renderer/shell_content_renderer_client.h b/content/shell/renderer/shell_content_renderer_client.h index e3a9864..b4a9408f5 100644 --- a/content/shell/renderer/shell_content_renderer_client.h +++ b/content/shell/renderer/shell_content_renderer_client.h
@@ -40,7 +40,7 @@ std::string* error_html) override; // TODO(mkwst): These toggle based on the kEnablePepperTesting flag. Do we - // need that outside of layout tests? + // need that outside of web tests? bool IsPluginAllowedToUseCompositorAPI(const GURL& url) override; bool IsPluginAllowedToUseDevChannelAPIs() override;
diff --git a/content/shell/renderer/web_test/blink_test_helpers.cc b/content/shell/renderer/web_test/blink_test_helpers.cc index a201f07..40b58ed1d 100644 --- a/content/shell/renderer/web_test/blink_test_helpers.cc +++ b/content/shell/renderer/web_test/blink_test_helpers.cc
@@ -68,9 +68,8 @@ namespace content { -void ExportLayoutTestSpecificPreferences( - const test_runner::TestPreferences& from, - WebPreferences* to) { +void ExportWebTestSpecificPreferences(const test_runner::TestPreferences& from, + WebPreferences* to) { to->allow_universal_access_from_file_urls = from.allow_universal_access_from_file_urls; to->javascript_can_access_clipboard = from.java_script_can_access_clipboard; @@ -97,10 +96,10 @@ to->spatial_navigation_enabled = from.spatial_navigation_enabled; } -// Applies settings that differ between layout tests and regular mode. Some +// Applies settings that differ between web tests and regular mode. Some // of the defaults are controlled via command line flags which are -// automatically set for layout tests. -void ApplyLayoutTestDefaultPreferences(WebPreferences* prefs) { +// automatically set for web tests. +void ApplyWebTestDefaultPreferences(WebPreferences* prefs) { const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); prefs->allow_universal_access_from_file_urls = true; @@ -173,7 +172,7 @@ return result; } -WebURL RewriteLayoutTestsURL(const std::string& utf8_url, bool is_wpt_mode) { +WebURL RewriteWebTestsURL(const std::string& utf8_url, bool is_wpt_mode) { if (is_wpt_mode) { WebURL rewritten_url = RewriteAbsolutePathInCsswgTest(utf8_url); if (!rewritten_url.IsEmpty())
diff --git a/content/shell/renderer/web_test/blink_test_helpers.h b/content/shell/renderer/web_test/blink_test_helpers.h index 63d72f6..081f0308 100644 --- a/content/shell/renderer/web_test/blink_test_helpers.h +++ b/content/shell/renderer/web_test/blink_test_helpers.h
@@ -20,13 +20,12 @@ // The TestRunner library keeps its settings in a TestPreferences object. // The content_shell, however, uses WebPreferences. This method exports the -// settings from the TestRunner library which are relevant for layout tests. -void ExportLayoutTestSpecificPreferences( - const test_runner::TestPreferences& from, - WebPreferences* to); +// settings from the TestRunner library which are relevant for web tests. +void ExportWebTestSpecificPreferences(const test_runner::TestPreferences& from, + WebPreferences* to); -// Applies settings that differ between layout tests and regular mode. -void ApplyLayoutTestDefaultPreferences(WebPreferences* prefs); +// Applies settings that differ between web tests and regular mode. +void ApplyWebTestDefaultPreferences(WebPreferences* prefs); // The build directory of the Blink checkout. base::FilePath GetBuildDirectory(); @@ -34,8 +33,7 @@ // Replaces file:///tmp/web_tests/ with the actual path to the // web_tests directory, or rewrite URLs generated from absolute // path links in web-platform-tests. -blink::WebURL RewriteLayoutTestsURL(const std::string& utf8_url, - bool is_wpt_mode); +blink::WebURL RewriteWebTestsURL(const std::string& utf8_url, bool is_wpt_mode); } // namespace content
diff --git a/content/shell/renderer/web_test/blink_test_runner.cc b/content/shell/renderer/web_test/blink_test_runner.cc index 624862e..444bbe5 100644 --- a/content/shell/renderer/web_test/blink_test_runner.cc +++ b/content/shell/renderer/web_test/blink_test_runner.cc
@@ -40,7 +40,7 @@ #include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_view.h" #include "content/public/renderer/render_view_visitor.h" -#include "content/public/test/layouttest_support.h" +#include "content/public/test/web_test_support.h" #include "content/shell/common/shell_messages.h" #include "content/shell/common/shell_switches.h" #include "content/shell/common/web_test/web_test_messages.h" @@ -248,9 +248,9 @@ return WebURL(GURL(data_url_prefix + contents_base64)); } -WebURL BlinkTestRunner::RewriteLayoutTestsURL(const std::string& utf8_url, - bool is_wpt_mode) { - return content::RewriteLayoutTestsURL(utf8_url, is_wpt_mode); +WebURL BlinkTestRunner::RewriteWebTestsURL(const std::string& utf8_url, + bool is_wpt_mode) { + return content::RewriteWebTestsURL(utf8_url, is_wpt_mode); } test_runner::TestPreferences* BlinkTestRunner::Preferences() { @@ -259,7 +259,7 @@ void BlinkTestRunner::ApplyPreferences() { WebPreferences prefs = render_view()->GetWebkitPreferences(); - ExportLayoutTestSpecificPreferences(prefs_, &prefs); + ExportWebTestSpecificPreferences(prefs_, &prefs); render_view()->SetWebkitPreferences(prefs); Send(new ShellViewHostMsg_OverridePreferences(routing_id(), prefs)); } @@ -390,7 +390,7 @@ } #endif - // Some layout tests use file://// which we resolve as a UNC path. Normalize + // Some web tests use file://// which we resolve as a UNC path. Normalize // them to just file:///. std::string result = resource; static const size_t kFileLen = sizeof("file:///") - 1; @@ -398,9 +398,7 @@ base::CompareCase::SENSITIVE)) { result = result.substr(0, kFileLen) + result.substr(kFileLen + 1); } - return RewriteLayoutTestsURL(result, false /* is_wpt_mode */) - .GetString() - .Utf8(); + return RewriteWebTestsURL(result, false /* is_wpt_mode */).GetString().Utf8(); } void BlinkTestRunner::SetLocale(const std::string& locale) { @@ -410,7 +408,7 @@ void BlinkTestRunner::OnWebTestRuntimeFlagsChanged( const base::DictionaryValue& changed_values) { // Ignore changes that happen before we got the initial, accumulated - // layout flag changes in either OnReplicateTestConfiguration or + // web flag changes in either OnReplicateTestConfiguration or // OnSetTestConfiguration. test_runner::WebTestInterfaces* interfaces = WebTestRenderThreadObserver::GetInstance()->test_interfaces(); @@ -439,7 +437,7 @@ } // Now we know that we're in the main frame, we should generate dump results. - // Clean out the lifecycle if needed before capturing the layout tree + // Clean out the lifecycle if needed before capturing the web tree // dump and pixels from the compositor. auto* web_frame = render_view()->GetWebView()->MainFrame()->ToWebLocalFrame(); web_frame->FrameWidget()->UpdateAllLifecyclePhases( @@ -450,10 +448,10 @@ dump_result_ = mojom::WebTestDump::New(); CaptureLocalAudioDump(); - // TODO(vmpstr): Sometimes the layout isn't stable, which means that if we + // TODO(vmpstr): Sometimes the web isn't stable, which means that if we // just ask the browser to ask us to do a dump, the layout would be different // compared to if we do it now. This probably needs to be rebaselined. But for - // now, just capture a local layout first. + // now, just capture a local web first. CaptureLocalLayoutDump(); // TODO(vmpstr): This code should move to the browser, but since again some // tests seem to be timing dependent, capture a local pixels dump first. Note
diff --git a/content/shell/renderer/web_test/blink_test_runner.h b/content/shell/renderer/web_test/blink_test_runner.h index f4fd6da..3d22fe4 100644 --- a/content/shell/renderer/web_test/blink_test_runner.h +++ b/content/shell/renderer/web_test/blink_test_runner.h
@@ -41,8 +41,8 @@ namespace content { // This is the renderer side of the webkit test runner. -// TODO(lukasza): Rename to LayoutTestRenderViewObserver for consistency with -// LayoutTestRenderFrameObserver. +// TODO(lukasza): Rename to WebTestRenderViewObserver for consistency with +// WebTestRenderFrameObserver. class BlinkTestRunner : public RenderViewObserver, public RenderViewObserverTracker<BlinkTestRunner>, public test_runner::WebTestDelegate { @@ -73,8 +73,8 @@ blink::WebString GetAbsoluteWebStringFromUTF8Path( const std::string& utf8_path) override; blink::WebURL LocalFileToDataURL(const blink::WebURL& file_url) override; - blink::WebURL RewriteLayoutTestsURL(const std::string& utf8_url, - bool is_wpt_mode) override; + blink::WebURL RewriteWebTestsURL(const std::string& utf8_url, + bool is_wpt_mode) override; test_runner::TestPreferences* Preferences() override; void ApplyPreferences() override; void SetPopupBlockingEnabled(bool block_popups) override; @@ -150,14 +150,14 @@ bool IsNavigationInitiatedByRenderer( const blink::WebURLRequest& request) override; - // Resets a RenderView to a known state for layout tests. It is used both when + // Resets a RenderView to a known state for web tests. It is used both when // a RenderView is created and when reusing an existing RenderView for the // next test case. // When reusing an existing RenderView, |for_new_test| should be true, which // also resets additional state, like the main frame's name and opener. void Reset(bool for_new_test); - // Message handlers forwarded by LayoutTestRenderFrameObserver. + // Message handlers forwarded by WebTestRenderFrameObserver. void OnSetTestConfiguration(mojom::ShellTestConfigurationPtr params); void OnReplicateTestConfiguration(mojom::ShellTestConfigurationPtr params); void OnSetupSecondaryRenderer();
diff --git a/content/shell/renderer/web_test/test_media_stream_renderer_factory.h b/content/shell/renderer/web_test/test_media_stream_renderer_factory.h index eb90f20..2a54228 100644 --- a/content/shell/renderer/web_test/test_media_stream_renderer_factory.h +++ b/content/shell/renderer/web_test/test_media_stream_renderer_factory.h
@@ -13,7 +13,7 @@ namespace content { // TestMediaStreamClient is a mock implementation of MediaStreamClient used when -// running layout tests. +// running web tests. class TestMediaStreamRendererFactory : public MediaStreamRendererFactory { public: TestMediaStreamRendererFactory();
diff --git a/content/shell/renderer/web_test/test_media_stream_video_renderer.h b/content/shell/renderer/web_test/test_media_stream_video_renderer.h index 6d67232..bc20cb3 100644 --- a/content/shell/renderer/web_test/test_media_stream_video_renderer.h +++ b/content/shell/renderer/web_test/test_media_stream_video_renderer.h
@@ -18,7 +18,7 @@ // A MediaStreamVideoRenderer that generates raw frames and // passes them to webmediaplayer. -// Since non-black pixel values are required in the layout test, e.g., +// Since non-black pixel values are required in the web test, e.g., // media/video-capture-canvas.html, this class should generate frame with // only non-black pixels. class TestMediaStreamVideoRenderer : public MediaStreamVideoRenderer {
diff --git a/content/shell/renderer/web_test/web_test_content_renderer_client.cc b/content/shell/renderer/web_test/web_test_content_renderer_client.cc index 8e132b8..ab319e4c 100644 --- a/content/shell/renderer/web_test/web_test_content_renderer_client.cc +++ b/content/shell/renderer/web_test/web_test_content_renderer_client.cc
@@ -17,7 +17,7 @@ #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_view.h" -#include "content/public/test/layouttest_support.h" +#include "content/public/test/web_test_support.h" #include "content/shell/common/shell_switches.h" #include "content/shell/common/web_test/web_test_switches.h" #include "content/shell/renderer/shell_render_view_observer.h" @@ -63,7 +63,7 @@ WebTestContentRendererClient::WebTestContentRendererClient() { EnableWebTestProxyCreation(); - SetWorkerRewriteURLFunction(RewriteLayoutTestsURL); + SetWorkerRewriteURLFunction(RewriteWebTestsURL); } WebTestContentRendererClient::~WebTestContentRendererClient() {} @@ -130,7 +130,7 @@ void WebTestContentRendererClient:: SetRuntimeFeaturesDefaultsBeforeBlinkInitialization() { - // We always expose GC to layout tests. + // We always expose GC to web tests. std::string flags("--expose-gc"); v8::V8::SetFlagsFromString(flags.c_str(), static_cast<int>(flags.size())); if (!base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -144,7 +144,7 @@ } bool WebTestContentRendererClient::IsIdleMediaSuspendEnabled() { - // Disable idle media suspend to avoid layout tests getting into accidentally + // Disable idle media suspend to avoid web tests getting into accidentally // bad states if they take too long to run. return false; }
diff --git a/content/shell/renderer/web_test/web_test_render_thread_observer.cc b/content/shell/renderer/web_test/web_test_render_thread_observer.cc index 36003f19..89eddfc 100644 --- a/content/shell/renderer/web_test/web_test_render_thread_observer.cc +++ b/content/shell/renderer/web_test/web_test_render_thread_observer.cc
@@ -6,7 +6,7 @@ #include "content/public/common/content_client.h" #include "content/public/renderer/render_thread.h" -#include "content/public/test/layouttest_support.h" +#include "content/public/test/web_test_support.h" #include "content/shell/common/shell_messages.h" #include "content/shell/common/web_test/web_test_messages.h" #include "content/shell/common/web_test/web_test_switches.h" @@ -29,7 +29,7 @@ CHECK(!g_instance); g_instance = this; RenderThread::Get()->AddObserver(this); - EnableRendererLayoutTestMode(); + EnableRendererWebTestMode(); test_interfaces_.reset(new test_runner::WebTestInterfaces); test_interfaces_->ResetAll();
diff --git a/content/shell/test_runner/BUILD.gn b/content/shell/test_runner/BUILD.gn index 1d2c029..0c56511 100644 --- a/content/shell/test_runner/BUILD.gn +++ b/content/shell/test_runner/BUILD.gn
@@ -35,8 +35,6 @@ "layout_and_paint_async_then.h", "layout_dump.cc", "layout_dump.h", - "layout_test_runtime_flags.cc", - "layout_test_runtime_flags.h", "mock_content_settings_client.cc", "mock_content_settings_client.h", "mock_grammar_check.cc", @@ -82,6 +80,8 @@ "web_test_interfaces.cc", "web_test_interfaces.h", "web_test_runner.h", + "web_test_runtime_flags.cc", + "web_test_runtime_flags.h", "web_view_test_client.cc", "web_view_test_client.h", "web_view_test_proxy.cc",
diff --git a/content/shell/test_runner/accessibility_controller.cc b/content/shell/test_runner/accessibility_controller.cc index d9abf2d..2c2c0fb 100644 --- a/content/shell/test_runner/accessibility_controller.cc +++ b/content/shell/test_runner/accessibility_controller.cc
@@ -221,7 +221,7 @@ if (!frame) return v8::Local<v8::Object>(); - // TODO(lukasza): Finish adding OOPIF support to the layout tests harness. + // TODO(lukasza): Finish adding OOPIF support to the web tests harness. CHECK(frame->IsWebLocalFrame()) << "This function cannot be called if the main frame is not a " "local frame."; @@ -282,7 +282,7 @@ AccessibilityController::GetAccessibilityObjectForMainFrame() { blink::WebFrame* frame = web_view()->MainFrame(); - // TODO(lukasza): Finish adding OOPIF support to the layout tests harness. + // TODO(lukasza): Finish adding OOPIF support to the web tests harness. CHECK(frame && frame->IsWebLocalFrame()) << "This function cannot be called if the main frame is not a " "local frame.";
diff --git a/content/shell/test_runner/event_sender.cc b/content/shell/test_runner/event_sender.cc index 4f187f1..1a6a5cf2 100644 --- a/content/shell/test_runner/event_sender.cc +++ b/content/shell/test_runner/event_sender.cc
@@ -487,7 +487,7 @@ } // How much we should scroll per event - the value here is chosen to match the -// WebKit impl and layout test results. +// WebKit impl and web test results. const float kScrollbarPixelsPerTick = 40.0f; // Get the edit command corresponding to a keyboard event. @@ -1502,7 +1502,7 @@ bool generate_char = false; - // Convert \n -> VK_RETURN. Some layout tests use \n to mean "Enter", when + // Convert \n -> VK_RETURN. Some web tests use \n to mean "Enter", when // Windows uses \r for "Enter". int code = 0; int text = 0;
diff --git a/content/shell/test_runner/layout_dump.cc b/content/shell/test_runner/layout_dump.cc index 4b3b422..6c0277b9 100644 --- a/content/shell/test_runner/layout_dump.cc +++ b/content/shell/test_runner/layout_dump.cc
@@ -30,7 +30,7 @@ // Add header for all but the main frame. Skip empty frames. if (frame->Parent() && !frame->GetDocument().DocumentElement().IsNull()) { result.append("\n--------\nFrame: '"); - result.append(content::GetFrameNameForLayoutTests(frame)); + result.append(content::GetFrameNameForWebTests(frame)); result.append("'\n--------\n"); } @@ -43,7 +43,7 @@ if (offset.width > 0 || offset.height > 0) { if (frame->Parent()) { result = std::string("frame '") + - content::GetFrameNameForLayoutTests(frame) + "' "; + content::GetFrameNameForWebTests(frame) + "' "; } base::StringAppendF(&result, "scrolled to %d,%d\n", offset.width, offset.height); @@ -54,16 +54,13 @@ } // namespace -std::string DumpLayout(WebLocalFrame* frame, - const LayoutTestRuntimeFlags& flags) { +std::string DumpLayout(WebLocalFrame* frame, const WebTestRuntimeFlags& flags) { DCHECK(frame); std::string result; if (flags.dump_as_text()) { result = DumpFrameHeaderIfNeeded(frame); - result += frame->GetDocument() - .ContentAsTextForTesting(flags.should_use_inner_text_dump()) - .Utf8(); + result += frame->GetDocument().ContentAsTextForTesting().Utf8(); result += "\n"; } else if (flags.dump_as_markup()) { DCHECK(!flags.is_printing());
diff --git a/content/shell/test_runner/layout_dump.h b/content/shell/test_runner/layout_dump.h index 09bb976d..06c820a 100644 --- a/content/shell/test_runner/layout_dump.h +++ b/content/shell/test_runner/layout_dump.h
@@ -7,8 +7,8 @@ #include <string> -#include "content/shell/test_runner/layout_test_runtime_flags.h" #include "content/shell/test_runner/test_runner_export.h" +#include "content/shell/test_runner/web_test_runtime_flags.h" namespace blink { class WebLocalFrame; @@ -19,7 +19,7 @@ // Dumps textual representation of |frame| contents. Exact dump mode depends // on |flags| (i.e. dump_as_text VS dump_as_markup and/or is_printing). TEST_RUNNER_EXPORT std::string DumpLayout(blink::WebLocalFrame* frame, - const LayoutTestRuntimeFlags& flags); + const WebTestRuntimeFlags& flags); } // namespace test_runner
diff --git a/content/shell/test_runner/layout_test_runtime_flags.cc b/content/shell/test_runner/layout_test_runtime_flags.cc deleted file mode 100644 index 28dad84d..0000000 --- a/content/shell/test_runner/layout_test_runtime_flags.cc +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2016 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/shell/test_runner/layout_test_runtime_flags.h" - -namespace test_runner { - -LayoutTestRuntimeFlags::LayoutTestRuntimeFlags() { - Reset(); -} - -void LayoutTestRuntimeFlags::Reset() { - set_generate_pixel_results(true); - - set_dump_as_text(false); - set_dump_as_markup(false); - set_dump_as_layout(false); - set_dump_child_frames(false); - - set_is_printing(false); - set_printing_frame(""); - - set_policy_delegate_enabled(false); - set_policy_delegate_is_permissive(false); - set_policy_delegate_should_notify_done(false); - set_wait_until_done(false); - set_wait_until_external_url_load(false); - - set_dump_selection_rect(false); - set_dump_drag_image(false); - - set_accept_languages(""); - - set_dump_web_content_settings_client_callbacks(false); - set_images_allowed(true); - set_scripts_allowed(true); - set_storage_allowed(true); - set_plugins_allowed(true); - set_running_insecure_content_allowed(false); - set_autoplay_allowed(true); - - set_dump_editting_callbacks(false); - set_dump_frame_load_callbacks(false); - set_dump_ping_loader_callbacks(false); - set_dump_user_gesture_in_frame_load_callbacks(false); - set_dump_resource_load_callbacks(false); - set_dump_resource_response_mime_types(false); - set_dump_navigation_policy(false); - - set_dump_title_changes(false); - set_dump_icon_changes(false); - set_dump_console_messages(true); - - set_stay_on_page_after_handling_before_unload(false); - - set_have_top_loading_frame(false); - - set_can_open_windows(false); - - set_dump_create_view(false); - set_dump_spell_check_callbacks(false); - set_dump_javascript_dialogs(true); - - set_has_custom_text_output(false); - set_custom_text_output(""); - - // No need to report the initial state - only the future delta is important. - tracked_dictionary().ResetChangeTracking(); -} - -} // namespace test_runner
diff --git a/content/shell/test_runner/layout_test_runtime_flags.h b/content/shell/test_runner/layout_test_runtime_flags.h deleted file mode 100644 index a5bfae01..0000000 --- a/content/shell/test_runner/layout_test_runtime_flags.h +++ /dev/null
@@ -1,204 +0,0 @@ -// Copyright 2016 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_SHELL_TEST_RUNNER_LAYOUT_TEST_RUNTIME_FLAGS_H_ -#define CONTENT_SHELL_TEST_RUNNER_LAYOUT_TEST_RUNTIME_FLAGS_H_ - -#include <string> - -#include "base/logging.h" -#include "base/macros.h" -#include "base/values.h" -#include "content/shell/test_runner/test_runner_export.h" -#include "content/shell/test_runner/tracked_dictionary.h" - -namespace test_runner { - -// LayoutTestRuntimeFlags stores flags controlled by layout tests at runtime -// (i.e. by calling testRunner.dumpAsText() or testRunner.waitUntilDone()). -// Changes to the flags are tracked (to help replicate them across renderers). -class TEST_RUNNER_EXPORT LayoutTestRuntimeFlags { - public: - // Creates default flags (see also the Reset method). - LayoutTestRuntimeFlags(); - - // Resets all the values to their defaults. - void Reset(); - - TrackedDictionary& tracked_dictionary() { return dict_; } - -#define DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(name) \ - bool name() const { \ - bool result; \ - bool found = dict_.current_values().GetBoolean(#name, &result); \ - DCHECK(found); \ - return result; \ - } \ - void set_##name(bool new_value) { dict_.SetBoolean(#name, new_value); } - -#define DEFINE_STRING_LAYOUT_TEST_RUNTIME_FLAG(name) \ - std::string name() const { \ - std::string result; \ - bool found = dict_.current_values().GetString(#name, &result); \ - DCHECK(found); \ - return result; \ - } \ - void set_##name(const std::string& new_value) { \ - dict_.SetString(#name, new_value); \ - } - - // If true, the test runner will generate pixel results. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(generate_pixel_results) - - // If true, the test runner will produce a plain text dump. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_as_text) - - // If true and dump_as_text is false, the test runner will produce a dump of - // the DOM. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_as_markup) - - // If true and both dump_as_text and dump_as_markup are false, the test runner - // will dump a text representation of the layout. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_as_layout) - - // If true, the test runner will recursively dump all frames as text, markup - // or layout depending on which of dump_as_text, dump_as_markup and - // dump_as_layout is effective. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_child_frames) - - // If true, layout is to target printed pages. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(is_printing) - - // If this is non-empty and is_printing is true, pixel dump will be for the - // named frame printed. - DEFINE_STRING_LAYOUT_TEST_RUNTIME_FLAG(printing_frame) - - // If true, don't dump output until notifyDone is called. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(wait_until_done) - - // If true, ends the test when a URL is loaded externally via - // WebLocalFrameClient::loadURLExternally(). - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(wait_until_external_url_load) - - // Causes navigation actions just printout the intended navigation instead - // of taking you to the page. This is used for cases like mailto, where you - // don't actually want to open the mail program. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(policy_delegate_enabled) - - // Toggles the behavior of the policy delegate. If true, then navigations - // will be allowed. Otherwise, they will be ignored (dropped). - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(policy_delegate_is_permissive) - - // If true, the policy delegate will signal layout test completion. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(policy_delegate_should_notify_done) - - // If true, the test runner will draw the bounds of the current selection rect - // taking possible transforms of the selection rect into account. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_selection_rect) - - // If true, the test runner will dump the drag image as pixel results. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_drag_image) - - // Contents of Accept-Language HTTP header requested by the test. - DEFINE_STRING_LAYOUT_TEST_RUNTIME_FLAG(accept_languages) - - // Flags influencing behavior of MockContentSettingsClient. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(images_allowed) - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(scripts_allowed) - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(storage_allowed) - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(plugins_allowed) - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(running_insecure_content_allowed) - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG( - dump_web_content_settings_client_callbacks) - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(autoplay_allowed) - - // If true, the test runner will write a descriptive line for each editing - // command. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_editting_callbacks) - - // If true, the test runner will output a descriptive line for each frame - // load callback. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_frame_load_callbacks) - - // If true, the test runner will output a descriptive line for each - // PingLoader dispatched. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_ping_loader_callbacks) - - // If true, the test runner will output a line of the user gesture status - // text for some frame load callbacks. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG( - dump_user_gesture_in_frame_load_callbacks) - - // If true, the test runner will output a descriptive line for each resource - // load callback. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_resource_load_callbacks) - - // If true, the test runner will output the MIME type for each resource that - // was loaded. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_resource_response_mime_types) - - // If true, content_shell will dump the default navigation policy passed to - // WebLocalFrameClient::decidePolicyForNavigation. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_navigation_policy) - - // If true, output a message when the page title is changed. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_title_changes) - - // If true, the test runner will print out the icon change notifications. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_icon_changes) - - // If true, the console messages produced by the page will - // be part of test output. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_console_messages) - - // Desired return value of WebLocalFrameClient::runModalBeforeUnloadDialog. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG( - stay_on_page_after_handling_before_unload) - - // Indicates if the test already tracks a top loading frame (in any of the - // renderer processes). This flag is trying to prevent different renderer - // processes from tracking different top loading frames (i.e. main frame in - // one renderer and an OOPIF in another renderer). - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(have_top_loading_frame) - - // If true, new windows can be opened via javascript or by plugins. By - // default, set to false and can be toggled to true using - // setCanOpenWindows(). - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(can_open_windows) - - // If true, output a descriptive line each time WebViewClient::createView - // is invoked. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_create_view) - - // If true, the test runner will output descriptive test for spellcheck - // execution. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_spell_check_callbacks) - - // If true, content_shell will output text for alert(), confirm(), prompt(), - // etc. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(dump_javascript_dialogs) - - // True if the test called testRunner.setCustomTextOutput. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(has_custom_text_output) - - // Contains text passed by the test to testRunner.setCustomTextOutput. - DEFINE_STRING_LAYOUT_TEST_RUNTIME_FLAG(custom_text_output) - - // Controls which implementation to use for text dump, to help progressive - // rebaseline of layout test text dumps. - // TODO(xiaochengh): Remove this flag when rebaseline is complete. - DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG(should_use_inner_text_dump) - -#undef DEFINE_BOOL_LAYOUT_TEST_RUNTIME_FLAG -#undef DEFINE_STRING_LAYOUT_TEST_RUNTIME_FLAG - - private: - TrackedDictionary dict_; - - DISALLOW_COPY_AND_ASSIGN(LayoutTestRuntimeFlags); -}; - -} // namespace test_runner - -#endif // CONTENT_SHELL_TEST_RUNNER_LAYOUT_TEST_RUNTIME_FLAGS_H_
diff --git a/content/shell/test_runner/mock_content_settings_client.cc b/content/shell/test_runner/mock_content_settings_client.cc index 55d92303..1fd0d98 100644 --- a/content/shell/test_runner/mock_content_settings_client.cc +++ b/content/shell/test_runner/mock_content_settings_client.cc
@@ -4,16 +4,16 @@ #include "content/shell/test_runner/mock_content_settings_client.h" -#include "content/shell/test_runner/layout_test_runtime_flags.h" #include "content/shell/test_runner/test_common.h" #include "content/shell/test_runner/web_test_delegate.h" +#include "content/shell/test_runner/web_test_runtime_flags.h" #include "third_party/blink/public/platform/web_url.h" namespace test_runner { MockContentSettingsClient::MockContentSettingsClient( - LayoutTestRuntimeFlags* layout_test_runtime_flags) - : delegate_(nullptr), flags_(layout_test_runtime_flags) {} + WebTestRuntimeFlags* web_test_runtime_flags) + : delegate_(nullptr), flags_(web_test_runtime_flags) {} MockContentSettingsClient::~MockContentSettingsClient() {} @@ -23,7 +23,7 @@ if (flags_->dump_web_content_settings_client_callbacks() && delegate_) { delegate_->PrintMessage( std::string("MockContentSettingsClient: allowImage(") + - NormalizeLayoutTestURL(image_url.GetString().Utf8()) + + NormalizeWebTestURL(image_url.GetString().Utf8()) + "): " + (allowed ? "true" : "false") + "\n"); } return allowed; @@ -40,7 +40,7 @@ if (flags_->dump_web_content_settings_client_callbacks() && delegate_) { delegate_->PrintMessage( std::string("MockContentSettingsClient: allowScriptFromSource(") + - NormalizeLayoutTestURL(script_url.GetString().Utf8()) + + NormalizeWebTestURL(script_url.GetString().Utf8()) + "): " + (allowed ? "true" : "false") + "\n"); } return allowed;
diff --git a/content/shell/test_runner/mock_content_settings_client.h b/content/shell/test_runner/mock_content_settings_client.h index 97909cf..0f8e3e17 100644 --- a/content/shell/test_runner/mock_content_settings_client.h +++ b/content/shell/test_runner/mock_content_settings_client.h
@@ -10,14 +10,14 @@ namespace test_runner { -class LayoutTestRuntimeFlags; class WebTestDelegate; +class WebTestRuntimeFlags; class MockContentSettingsClient : public blink::WebContentSettingsClient { public: // Caller has to guarantee that |layout_test_runtime_flags| lives longer // than the MockContentSettingsClient being constructed here. - MockContentSettingsClient(LayoutTestRuntimeFlags* layout_test_runtime_flags); + MockContentSettingsClient(WebTestRuntimeFlags* layout_test_runtime_flags); ~MockContentSettingsClient() override; @@ -38,7 +38,7 @@ private: WebTestDelegate* delegate_; - LayoutTestRuntimeFlags* flags_; + WebTestRuntimeFlags* flags_; DISALLOW_COPY_AND_ASSIGN(MockContentSettingsClient); };
diff --git a/content/shell/test_runner/mock_spell_check.cc b/content/shell/test_runner/mock_spell_check.cc index 141dc40..cfd7242a 100644 --- a/content/shell/test_runner/mock_spell_check.cc +++ b/content/shell/test_runner/mock_spell_check.cc
@@ -143,9 +143,8 @@ if (initialized_) return false; - // Create a table that consists of misspelled words used in WebKit layout - // tests. - // Since WebKit layout tests don't have so many misspelled words as + // Create a table that consists of misspelled words used in Blink web tests. + // Since Blink web tests don't have so many misspelled words as // well-spelled words, it is easier to compare the given word with misspelled // ones than to compare with well-spelled ones. static const char* misspelled_words[] = {
diff --git a/content/shell/test_runner/pixel_dump.cc b/content/shell/test_runner/pixel_dump.cc index 4a6df44c..6d3fc1b 100644 --- a/content/shell/test_runner/pixel_dump.cc +++ b/content/shell/test_runner/pixel_dump.cc
@@ -17,7 +17,7 @@ #include "cc/paint/paint_flags.h" #include "cc/paint/skia_paint_canvas.h" #include "content/shell/common/web_test/web_test_utils.h" -#include "content/shell/test_runner/layout_test_runtime_flags.h" +#include "content/shell/test_runner/web_test_runtime_flags.h" #include "services/service_manager/public/cpp/connector.h" // FIXME: Including platform_canvas.h here is a layering violation. #include "skia/ext/platform_canvas.h"
diff --git a/content/shell/test_runner/spell_check_client.cc b/content/shell/test_runner/spell_check_client.cc index f7f9791..55dda0df3 100644 --- a/content/shell/test_runner/spell_check_client.cc +++ b/content/shell/test_runner/spell_check_client.cc
@@ -44,7 +44,7 @@ // blink::WebSpellCheckClient bool SpellCheckClient::IsSpellCheckingEnabled() const { - // Ensure that the spellchecker code paths are always tested in layout tests. + // Ensure that the spellchecker code paths are always tested in web tests. return true; }
diff --git a/content/shell/test_runner/test_common.cc b/content/shell/test_runner/test_common.cc index 87991dce..31a2e5f3 100644 --- a/content/shell/test_runner/test_common.cc +++ b/content/shell/test_runner/test_common.cc
@@ -35,7 +35,7 @@ const char* kIllegalString = "illegal value"; -std::string NormalizeLayoutTestURL(const std::string& url) { +std::string NormalizeWebTestURL(const std::string& url) { std::string result = url; size_t pos; if (!url.find(file_url_pattern) &&
diff --git a/content/shell/test_runner/test_common.h b/content/shell/test_runner/test_common.h index 846f3ea..6837dd5 100644 --- a/content/shell/test_runner/test_common.h +++ b/content/shell/test_runner/test_common.h
@@ -27,7 +27,7 @@ return !IsASCIIAlpha(ch); } -TEST_RUNNER_EXPORT std::string NormalizeLayoutTestURL(const std::string& url); +TEST_RUNNER_EXPORT std::string NormalizeWebTestURL(const std::string& url); std::string URLDescription(const GURL& url); const char* WebNavigationPolicyToString(
diff --git a/content/shell/test_runner/test_interfaces.cc b/content/shell/test_runner/test_interfaces.cc index f148823..a5c59079 100644 --- a/content/shell/test_runner/test_interfaces.cc +++ b/content/shell/test_runner/test_interfaces.cc
@@ -25,23 +25,12 @@ namespace test_runner { -namespace { -bool ShouldUseInnerTextDump(const std::string& test_path) { - // We are switching the text dump implementation to spec-conformant - // Element.innerText. To avoid gigantic patch, we control the rebaseline - // progress here in a per-directory manner. - // TODO(xiaochengh): Progressively allow more tests to use innerText. - // Remove this function once rebaseline is complete. - return test_path >= "web_tests/a" && test_path < "web_tests/t"; -} -} // namespace - TestInterfaces::TestInterfaces() : gamepad_controller_(new GamepadController()), test_runner_(new TestRunner(this)), delegate_(nullptr), main_view_(nullptr) { - blink::SetLayoutTestMode(true); + blink::SetWebTestMode(true); // NOTE: please don't put feature specific enable flags here, // instead add them to runtime_enabled_features.json5 @@ -111,7 +100,7 @@ // we don't dump non-human-readable binary data. In non-protocol mode, we // still generate pixel results (though don't dump them) to let the renderer // execute the same code regardless of the protocol mode, e.g. for ease of - // debugging a layout test issue. + // debugging a web test issue. if (!protocol_mode) test_runner_->setShouldDumpAsLayout(true); @@ -134,9 +123,6 @@ spec.find("://web-platform.test") != std::string::npos || spec.find("/harness-tests/wpt/") != std::string::npos) test_runner_->set_is_web_platform_tests_mode(); - - const bool should_use_inner_text = ShouldUseInnerTextDump(spec); - test_runner_->SetShouldUseInnerTextDump(should_use_inner_text); } void TestInterfaces::WindowOpened(WebViewTestProxyBase* proxy) {
diff --git a/content/shell/test_runner/test_preferences.cc b/content/shell/test_runner/test_preferences.cc index 16c63bc3..c7ddc53 100644 --- a/content/shell/test_runner/test_preferences.cc +++ b/content/shell/test_runner/test_preferences.cc
@@ -30,7 +30,7 @@ plugins_enabled = true; caret_browsing_enabled = false; - // Allow those layout tests running as local files, i.e. under + // Allow those web tests running as local files, i.e. under // web_tests/http/tests/local, to access http server. allow_universal_access_from_file_urls = true;
diff --git a/content/shell/test_runner/test_runner.cc b/content/shell/test_runner/test_runner.cc index 3e4feb9..049e93b0 100644 --- a/content/shell/test_runner/test_runner.cc +++ b/content/shell/test_runner/test_runner.cc
@@ -1478,7 +1478,7 @@ // We delay processing queued work to avoid recursion problems. controller_->delegate_->PostTask(base::BindOnce( &TestRunner::WorkQueue::ProcessWork, weak_factory_.GetWeakPtr())); - } else if (!controller_->layout_test_runtime_flags_.wait_until_done()) { + } else if (!controller_->web_test_runtime_flags_.wait_until_done()) { controller_->delegate_->TestFinished(); } } @@ -1512,7 +1512,7 @@ } } - if (!controller_->layout_test_runtime_flags_.wait_until_done() && + if (!controller_->web_test_runtime_flags_.wait_until_done() && !controller_->topLoadingFrame()) controller_->delegate_->TestFinished(); } @@ -1526,7 +1526,7 @@ delegate_(nullptr), main_view_(nullptr), mock_content_settings_client_( - new MockContentSettingsClient(&layout_test_runtime_flags_)), + new MockContentSettingsClient(&web_test_runtime_flags_)), mock_screen_orientation_client_(new MockScreenOrientationClient), spellcheck_(new SpellCheckClient(this)), chooser_count_(0), @@ -1564,7 +1564,7 @@ void TestRunner::Reset() { is_web_platform_tests_mode_ = false; top_loading_frame_ = nullptr; - layout_test_runtime_flags_.Reset(); + web_test_runtime_flags_.Reset(); mock_screen_orientation_client_->ResetData(); drag_image_.reset(); @@ -1618,54 +1618,54 @@ } bool TestRunner::ShouldDumpSelectionRect() const { - return layout_test_runtime_flags_.dump_selection_rect(); + return web_test_runtime_flags_.dump_selection_rect(); } bool TestRunner::shouldDumpEditingCallbacks() const { - return layout_test_runtime_flags_.dump_editting_callbacks(); + return web_test_runtime_flags_.dump_editting_callbacks(); } void TestRunner::setShouldDumpAsText(bool value) { - layout_test_runtime_flags_.set_dump_as_text(value); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_as_text(value); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::setShouldDumpAsMarkup(bool value) { - layout_test_runtime_flags_.set_dump_as_markup(value); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_as_markup(value); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::setShouldDumpAsLayout(bool value) { - layout_test_runtime_flags_.set_dump_as_layout(value); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_as_layout(value); + OnWebTestRuntimeFlagsChanged(); } bool TestRunner::shouldDumpAsCustomText() const { - return layout_test_runtime_flags_.has_custom_text_output(); + return web_test_runtime_flags_.has_custom_text_output(); } std::string TestRunner::customDumpText() const { - return layout_test_runtime_flags_.custom_text_output(); + return web_test_runtime_flags_.custom_text_output(); } void TestRunner::setCustomTextOutput(const std::string& text) { - layout_test_runtime_flags_.set_custom_text_output(text); - layout_test_runtime_flags_.set_has_custom_text_output(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_custom_text_output(text); + web_test_runtime_flags_.set_has_custom_text_output(true); + OnWebTestRuntimeFlagsChanged(); } bool TestRunner::ShouldGeneratePixelResults() { CheckResponseMimeType(); - return layout_test_runtime_flags_.generate_pixel_results(); + return web_test_runtime_flags_.generate_pixel_results(); } bool TestRunner::shouldStayOnPageAfterHandlingBeforeUnload() const { - return layout_test_runtime_flags_.stay_on_page_after_handling_before_unload(); + return web_test_runtime_flags_.stay_on_page_after_handling_before_unload(); } void TestRunner::setShouldGeneratePixelResults(bool value) { - layout_test_runtime_flags_.set_generate_pixel_results(value); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_generate_pixel_results(value); + OnWebTestRuntimeFlagsChanged(); } bool TestRunner::ShouldDumpAsAudio() const { @@ -1678,18 +1678,18 @@ bool TestRunner::IsRecursiveLayoutDumpRequested() { CheckResponseMimeType(); - return layout_test_runtime_flags_.dump_child_frames(); + return web_test_runtime_flags_.dump_child_frames(); } std::string TestRunner::DumpLayout(blink::WebLocalFrame* frame) { CheckResponseMimeType(); - return ::test_runner::DumpLayout(frame, layout_test_runtime_flags_); + return ::test_runner::DumpLayout(frame, web_test_runtime_flags_); } bool TestRunner::DumpPixelsAsync( blink::WebLocalFrame* frame, base::OnceCallback<void(const SkBitmap&)> callback) { - if (layout_test_runtime_flags_.dump_drag_image()) { + if (web_test_runtime_flags_.dump_drag_image()) { if (drag_image_.isNull()) { // This means the test called dumpDragImage but did not initiate a drag. // Return a blank image so that the test fails. @@ -1706,7 +1706,7 @@ // If we need to do a display compositor pixel dump, then delegate that to the // browser by returning true. Note that printing case can be handled here. - if (!layout_test_runtime_flags_.is_printing() && + if (!web_test_runtime_flags_.is_printing() && base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableDisplayCompositorPixelDump)) { frame->View()->MainFrameWidget()->RequestPresentationCallbackForTesting( @@ -1722,15 +1722,15 @@ } // See if we need to draw the selection bounds rect on top of the snapshot. - if (layout_test_runtime_flags_.dump_selection_rect()) { + if (web_test_runtime_flags_.dump_selection_rect()) { callback = CreateSelectionBoundsRectDrawingCallback(frame, std::move(callback)); } // Request appropriate kind of pixel dump. - if (layout_test_runtime_flags_.is_printing()) { + if (web_test_runtime_flags_.is_printing()) { auto* target_frame = frame; - std::string frame_name = layout_test_runtime_flags_.printing_frame(); + std::string frame_name = web_test_runtime_flags_.printing_frame(); if (!frame_name.empty()) { auto* frame_to_print = frame->FindFrameByName(blink::WebString::FromUTF8(frame_name)); @@ -1750,10 +1750,10 @@ void TestRunner::ReplicateWebTestRuntimeFlagsChanges( const base::DictionaryValue& changed_values) { if (test_is_running_) { - layout_test_runtime_flags_.tracked_dictionary().ApplyUntrackedChanges( + web_test_runtime_flags_.tracked_dictionary().ApplyUntrackedChanges( changed_values); - bool allowed = layout_test_runtime_flags_.plugins_allowed(); + bool allowed = web_test_runtime_flags_.plugins_allowed(); for (WebViewTestProxyBase* window : test_interfaces_->GetWindowList()) window->web_view()->GetSettings()->SetPluginsEnabled(allowed); } @@ -1770,17 +1770,17 @@ bool TestRunner::shouldDumpFrameLoadCallbacks() const { return test_is_running_ && - layout_test_runtime_flags_.dump_frame_load_callbacks(); + web_test_runtime_flags_.dump_frame_load_callbacks(); } void TestRunner::setShouldDumpFrameLoadCallbacks(bool value) { - layout_test_runtime_flags_.set_dump_frame_load_callbacks(value); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_frame_load_callbacks(value); + OnWebTestRuntimeFlagsChanged(); } bool TestRunner::shouldDumpPingLoaderCallbacks() const { return test_is_running_ && - layout_test_runtime_flags_.dump_ping_loader_callbacks(); + web_test_runtime_flags_.dump_ping_loader_callbacks(); } void TestRunner::setShouldEnableViewSource(bool value) { @@ -1798,33 +1798,33 @@ bool TestRunner::shouldDumpUserGestureInFrameLoadCallbacks() const { return test_is_running_ && - layout_test_runtime_flags_.dump_user_gesture_in_frame_load_callbacks(); + web_test_runtime_flags_.dump_user_gesture_in_frame_load_callbacks(); } bool TestRunner::shouldDumpTitleChanges() const { - return layout_test_runtime_flags_.dump_title_changes(); + return web_test_runtime_flags_.dump_title_changes(); } bool TestRunner::shouldDumpIconChanges() const { - return layout_test_runtime_flags_.dump_icon_changes(); + return web_test_runtime_flags_.dump_icon_changes(); } bool TestRunner::shouldDumpCreateView() const { - return layout_test_runtime_flags_.dump_create_view(); + return web_test_runtime_flags_.dump_create_view(); } bool TestRunner::canOpenWindows() const { - return layout_test_runtime_flags_.can_open_windows(); + return web_test_runtime_flags_.can_open_windows(); } bool TestRunner::shouldDumpResourceLoadCallbacks() const { return test_is_running_ && - layout_test_runtime_flags_.dump_resource_load_callbacks(); + web_test_runtime_flags_.dump_resource_load_callbacks(); } bool TestRunner::shouldDumpResourceResponseMIMETypes() const { return test_is_running_ && - layout_test_runtime_flags_.dump_resource_response_mime_types(); + web_test_runtime_flags_.dump_resource_response_mime_types(); } blink::WebContentSettingsClient* TestRunner::GetWebContentSettings() const { @@ -1836,7 +1836,7 @@ } bool TestRunner::shouldDumpSpellCheckCallbacks() const { - return layout_test_runtime_flags_.dump_spell_check_callbacks(); + return web_test_runtime_flags_.dump_spell_check_callbacks(); } bool TestRunner::ShouldDumpBackForwardList() const { @@ -1844,11 +1844,11 @@ } bool TestRunner::isPrinting() const { - return layout_test_runtime_flags_.is_printing(); + return web_test_runtime_flags_.is_printing(); } bool TestRunner::shouldWaitUntilExternalURLLoad() const { - return layout_test_runtime_flags_.wait_until_external_url_load(); + return web_test_runtime_flags_.wait_until_external_url_load(); } const std::set<std::string>* TestRunner::httpHeadersToClear() const { @@ -1863,12 +1863,12 @@ if (!IsFramePartOfMainTestWindow(frame)) return false; - if (top_loading_frame_ || layout_test_runtime_flags_.have_top_loading_frame()) + if (top_loading_frame_ || web_test_runtime_flags_.have_top_loading_frame()) return false; top_loading_frame_ = frame; - layout_test_runtime_flags_.set_have_top_loading_frame(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_have_top_loading_frame(true); + OnWebTestRuntimeFlagsChanged(); return true; } @@ -1880,9 +1880,9 @@ return false; top_loading_frame_ = nullptr; - DCHECK(layout_test_runtime_flags_.have_top_loading_frame()); - layout_test_runtime_flags_.set_have_top_loading_frame(false); - OnLayoutTestRuntimeFlagsChanged(); + DCHECK(web_test_runtime_flags_.have_top_loading_frame()); + web_test_runtime_flags_.set_have_top_loading_frame(false); + OnWebTestRuntimeFlagsChanged(); LocationChangeDone(); return true; @@ -1897,22 +1897,22 @@ } void TestRunner::policyDelegateDone() { - DCHECK(layout_test_runtime_flags_.wait_until_done()); + DCHECK(web_test_runtime_flags_.wait_until_done()); delegate_->TestFinished(); - layout_test_runtime_flags_.set_wait_until_done(false); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_wait_until_done(false); + OnWebTestRuntimeFlagsChanged(); } bool TestRunner::policyDelegateEnabled() const { - return layout_test_runtime_flags_.policy_delegate_enabled(); + return web_test_runtime_flags_.policy_delegate_enabled(); } bool TestRunner::policyDelegateIsPermissive() const { - return layout_test_runtime_flags_.policy_delegate_is_permissive(); + return web_test_runtime_flags_.policy_delegate_is_permissive(); } bool TestRunner::policyDelegateShouldNotifyDone() const { - return layout_test_runtime_flags_.policy_delegate_should_notify_done(); + return web_test_runtime_flags_.policy_delegate_should_notify_done(); } void TestRunner::setToolTipText(const blink::WebString& text) { @@ -1920,14 +1920,14 @@ } void TestRunner::setDragImage(const SkBitmap& drag_image) { - if (layout_test_runtime_flags_.dump_drag_image()) { + if (web_test_runtime_flags_.dump_drag_image()) { if (drag_image_.isNull()) drag_image_ = drag_image; } } bool TestRunner::shouldDumpNavigationPolicy() const { - return layout_test_runtime_flags_.dump_navigation_policy(); + return web_test_runtime_flags_.dump_navigation_policy(); } midi::mojom::Result TestRunner::midiAccessorResult() { @@ -1966,8 +1966,8 @@ }; void TestRunner::WaitUntilDone() { - layout_test_runtime_flags_.set_wait_until_done(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_wait_until_done(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::QueueBackNavigation(int how_far_back) { @@ -2076,21 +2076,21 @@ void TestRunner::SetCustomPolicyDelegate(gin::Arguments* args) { bool value; args->GetNext(&value); - layout_test_runtime_flags_.set_policy_delegate_enabled(value); + web_test_runtime_flags_.set_policy_delegate_enabled(value); if (!args->PeekNext().IsEmpty() && args->PeekNext()->IsBoolean()) { args->GetNext(&value); - layout_test_runtime_flags_.set_policy_delegate_is_permissive(value); + web_test_runtime_flags_.set_policy_delegate_is_permissive(value); } - OnLayoutTestRuntimeFlagsChanged(); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::WaitForPolicyDelegate() { - layout_test_runtime_flags_.set_policy_delegate_enabled(true); - layout_test_runtime_flags_.set_policy_delegate_should_notify_done(true); - layout_test_runtime_flags_.set_wait_until_done(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_policy_delegate_enabled(true); + web_test_runtime_flags_.set_policy_delegate_should_notify_done(true); + web_test_runtime_flags_.set_wait_until_done(true); + OnWebTestRuntimeFlagsChanged(); } int TestRunner::WindowCount() { @@ -2262,15 +2262,15 @@ } std::string TestRunner::GetAcceptLanguages() const { - return layout_test_runtime_flags_.accept_languages(); + return web_test_runtime_flags_.accept_languages(); } void TestRunner::SetAcceptLanguages(const std::string& accept_languages) { if (accept_languages == GetAcceptLanguages()) return; - layout_test_runtime_flags_.set_accept_languages(accept_languages); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_accept_languages(accept_languages); + OnWebTestRuntimeFlagsChanged(); for (WebViewTestProxyBase* window : test_interfaces_->GetWindowList()) window->web_view()->AcceptLanguagesChanged(); @@ -2282,48 +2282,48 @@ } void TestRunner::DumpEditingCallbacks() { - layout_test_runtime_flags_.set_dump_editting_callbacks(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_editting_callbacks(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpAsMarkup() { - layout_test_runtime_flags_.set_dump_as_markup(true); - layout_test_runtime_flags_.set_generate_pixel_results(false); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_as_markup(true); + web_test_runtime_flags_.set_generate_pixel_results(false); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpAsText() { - layout_test_runtime_flags_.set_dump_as_text(true); - layout_test_runtime_flags_.set_generate_pixel_results(false); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_as_text(true); + web_test_runtime_flags_.set_generate_pixel_results(false); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpAsTextWithPixelResults() { - layout_test_runtime_flags_.set_dump_as_text(true); - layout_test_runtime_flags_.set_generate_pixel_results(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_as_text(true); + web_test_runtime_flags_.set_generate_pixel_results(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpAsLayout() { - layout_test_runtime_flags_.set_dump_as_layout(true); - layout_test_runtime_flags_.set_generate_pixel_results(false); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_as_layout(true); + web_test_runtime_flags_.set_generate_pixel_results(false); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpAsLayoutWithPixelResults() { - layout_test_runtime_flags_.set_dump_as_layout(true); - layout_test_runtime_flags_.set_generate_pixel_results(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_as_layout(true); + web_test_runtime_flags_.set_generate_pixel_results(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpChildFrames() { - layout_test_runtime_flags_.set_dump_child_frames(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_child_frames(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpIconChanges() { - layout_test_runtime_flags_.set_dump_icon_changes(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_icon_changes(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::SetAudioData(const gin::ArrayBufferView& view) { @@ -2334,84 +2334,82 @@ } void TestRunner::DumpFrameLoadCallbacks() { - layout_test_runtime_flags_.set_dump_frame_load_callbacks(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_frame_load_callbacks(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpPingLoaderCallbacks() { - layout_test_runtime_flags_.set_dump_ping_loader_callbacks(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_ping_loader_callbacks(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpUserGestureInFrameLoadCallbacks() { - layout_test_runtime_flags_.set_dump_user_gesture_in_frame_load_callbacks( - true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_user_gesture_in_frame_load_callbacks(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpTitleChanges() { - layout_test_runtime_flags_.set_dump_title_changes(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_title_changes(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpCreateView() { - layout_test_runtime_flags_.set_dump_create_view(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_create_view(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::SetCanOpenWindows() { - layout_test_runtime_flags_.set_can_open_windows(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_can_open_windows(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpResourceLoadCallbacks() { - layout_test_runtime_flags_.set_dump_resource_load_callbacks(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_resource_load_callbacks(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpResourceResponseMIMETypes() { - layout_test_runtime_flags_.set_dump_resource_response_mime_types(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_resource_response_mime_types(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::SetImagesAllowed(bool allowed) { - layout_test_runtime_flags_.set_images_allowed(allowed); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_images_allowed(allowed); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::SetScriptsAllowed(bool allowed) { - layout_test_runtime_flags_.set_scripts_allowed(allowed); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_scripts_allowed(allowed); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::SetStorageAllowed(bool allowed) { - layout_test_runtime_flags_.set_storage_allowed(allowed); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_storage_allowed(allowed); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::SetPluginsAllowed(bool allowed) { - layout_test_runtime_flags_.set_plugins_allowed(allowed); + web_test_runtime_flags_.set_plugins_allowed(allowed); for (WebViewTestProxyBase* window : test_interfaces_->GetWindowList()) window->web_view()->GetSettings()->SetPluginsEnabled(allowed); - OnLayoutTestRuntimeFlagsChanged(); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::SetAllowRunningOfInsecureContent(bool allowed) { - layout_test_runtime_flags_.set_running_insecure_content_allowed(allowed); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_running_insecure_content_allowed(allowed); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::SetAutoplayAllowed(bool allowed) { - layout_test_runtime_flags_.set_autoplay_allowed(allowed); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_autoplay_allowed(allowed); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpPermissionClientCallbacks() { - layout_test_runtime_flags_.set_dump_web_content_settings_client_callbacks( - true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_web_content_settings_client_callbacks(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::SetDisallowedSubresourcePathSuffixes( @@ -2426,8 +2424,8 @@ } void TestRunner::DumpSpellCheckCallbacks() { - layout_test_runtime_flags_.set_dump_spell_check_callbacks(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_spell_check_callbacks(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpBackForwardList() { @@ -2435,8 +2433,8 @@ } void TestRunner::DumpSelectionRect() { - layout_test_runtime_flags_.set_dump_selection_rect(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_selection_rect(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::SetPrinting() { @@ -2444,25 +2442,19 @@ } void TestRunner::SetPrintingForFrame(const std::string& frame_name) { - layout_test_runtime_flags_.set_printing_frame(frame_name); - layout_test_runtime_flags_.set_is_printing(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_printing_frame(frame_name); + web_test_runtime_flags_.set_is_printing(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::ClearPrinting() { - layout_test_runtime_flags_.set_is_printing(false); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_is_printing(false); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::SetShouldStayOnPageAfterHandlingBeforeUnload(bool value) { - layout_test_runtime_flags_.set_stay_on_page_after_handling_before_unload( - value); - OnLayoutTestRuntimeFlagsChanged(); -} - -void TestRunner::SetShouldUseInnerTextDump(bool value) { - layout_test_runtime_flags_.set_should_use_inner_text_dump(value); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_stay_on_page_after_handling_before_unload(value); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::SetWillSendRequestClearHeader(const std::string& header) { @@ -2476,30 +2468,30 @@ } void TestRunner::WaitUntilExternalURLLoad() { - layout_test_runtime_flags_.set_wait_until_external_url_load(true); - layout_test_runtime_flags_.set_wait_until_done(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_wait_until_external_url_load(true); + web_test_runtime_flags_.set_wait_until_done(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpDragImage() { - layout_test_runtime_flags_.set_dump_drag_image(true); + web_test_runtime_flags_.set_dump_drag_image(true); DumpAsTextWithPixelResults(); - OnLayoutTestRuntimeFlagsChanged(); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::DumpNavigationPolicy() { - layout_test_runtime_flags_.set_dump_navigation_policy(true); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_navigation_policy(true); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::SetDumpConsoleMessages(bool value) { - layout_test_runtime_flags_.set_dump_console_messages(value); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_console_messages(value); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::SetDumpJavaScriptDialogs(bool value) { - layout_test_runtime_flags_.set_dump_javascript_dialogs(value); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_javascript_dialogs(value); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::SetEffectiveConnectionType( @@ -2512,11 +2504,11 @@ } bool TestRunner::ShouldDumpConsoleMessages() const { - return layout_test_runtime_flags_.dump_console_messages(); + return web_test_runtime_flags_.dump_console_messages(); } bool TestRunner::ShouldDumpJavaScriptDialogs() const { - return layout_test_runtime_flags_.dump_javascript_dialogs(); + return web_test_runtime_flags_.dump_javascript_dialogs(); } bool TestRunner::IsChooserShown() { @@ -2590,15 +2582,15 @@ animation_requires_raster_ = do_raster; } -void TestRunner::OnLayoutTestRuntimeFlagsChanged() { - if (layout_test_runtime_flags_.tracked_dictionary().changed_values().empty()) +void TestRunner::OnWebTestRuntimeFlagsChanged() { + if (web_test_runtime_flags_.tracked_dictionary().changed_values().empty()) return; if (!test_is_running_) return; delegate_->OnWebTestRuntimeFlagsChanged( - layout_test_runtime_flags_.tracked_dictionary().changed_values()); - layout_test_runtime_flags_.tracked_dictionary().ResetChangeTracking(); + web_test_runtime_flags_.tracked_dictionary().changed_values()); + web_test_runtime_flags_.tracked_dictionary().ResetChangeTracking(); } void TestRunner::LocationChangeDone() { @@ -2607,7 +2599,7 @@ // No more new work after the first complete load. work_queue_.set_frozen(true); - if (!layout_test_runtime_flags_.wait_until_done()) + if (!web_test_runtime_flags_.wait_until_done()) work_queue_.ProcessWorkSoon(); } @@ -2615,7 +2607,7 @@ // Text output: the test page can request different types of output which we // handle here. - if (layout_test_runtime_flags_.dump_as_text()) + if (web_test_runtime_flags_.dump_as_text()) return; if (!main_view_) @@ -2633,17 +2625,17 @@ if (mimeType != "text/plain") return; - layout_test_runtime_flags_.set_dump_as_text(true); - layout_test_runtime_flags_.set_generate_pixel_results(false); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_dump_as_text(true); + web_test_runtime_flags_.set_generate_pixel_results(false); + OnWebTestRuntimeFlagsChanged(); } void TestRunner::NotifyDone() { - if (layout_test_runtime_flags_.wait_until_done() && !topLoadingFrame() && + if (web_test_runtime_flags_.wait_until_done() && !topLoadingFrame() && work_queue_.is_empty()) delegate_->TestFinished(); - layout_test_runtime_flags_.set_wait_until_done(false); - OnLayoutTestRuntimeFlagsChanged(); + web_test_runtime_flags_.set_wait_until_done(false); + OnWebTestRuntimeFlagsChanged(); } } // namespace test_runner
diff --git a/content/shell/test_runner/test_runner.h b/content/shell/test_runner/test_runner.h index 46b45f7..6429304 100644 --- a/content/shell/test_runner/test_runner.h +++ b/content/shell/test_runner/test_runner.h
@@ -17,9 +17,9 @@ #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "base/strings/string16.h" -#include "content/shell/test_runner/layout_test_runtime_flags.h" #include "content/shell/test_runner/test_runner_export.h" #include "content/shell/test_runner/web_test_runner.h" +#include "content/shell/test_runner/web_test_runtime_flags.h" #include "media/midi/midi_service.mojom.h" #include "third_party/blink/public/platform/web_effective_connection_type.h" #include "third_party/blink/public/platform/web_image.h" @@ -62,7 +62,7 @@ // 2. It manages global test state. Example: // - Tracking topLoadingFrame that can finish the test when it loads. // - WorkQueue holding load requests from the TestInterfaces -// - LayoutTestRuntimeFlags +// - WebTestRuntimeFlags class TestRunner : public WebTestRunner { public: explicit TestRunner(TestInterfaces*); @@ -168,8 +168,6 @@ bool ShouldDumpJavaScriptDialogs() const; - void SetShouldUseInnerTextDump(bool value); - blink::WebEffectiveConnectionType effective_connection_type() const { return effective_connection_type_; } @@ -243,7 +241,7 @@ void SetCloseRemainingWindowsWhenComplete(bool close_remaining_windows); void ResetTestHelperControllers(); - // Allows layout tests to manage origins' allow list. + // Allows web tests to manage origins' allow list. void AddOriginAccessAllowListEntry(const std::string& source_origin, const std::string& destination_protocol, const std::string& destination_host, @@ -459,7 +457,7 @@ // Inspect chooser state bool IsChooserShown(); - // Allows layout tests to exec scripts at WebInspector side. + // Allows web tests to exec scripts at WebInspector side. void EvaluateInWebInspector(int call_id, const std::string& script); // Clears all databases. @@ -501,9 +499,9 @@ // Simulates closing a Web Notification. void SimulateWebNotificationClose(const std::string& title, bool by_user); - // Takes care of notifying the delegate after a change to layout test runtime + // Takes care of notifying the delegate after a change to web test runtime // flags. - void OnLayoutTestRuntimeFlagsChanged(); + void OnWebTestRuntimeFlagsChanged(); /////////////////////////////////////////////////////////////////////////// // Internal helpers @@ -536,7 +534,7 @@ int web_history_item_count_; // Flags controlling what content gets dumped as a layout text result. - LayoutTestRuntimeFlags layout_test_runtime_flags_; + WebTestRuntimeFlags web_test_runtime_flags_; // If true, the test runner will output a base64 encoded WAVE file. bool dump_as_audio_; @@ -595,7 +593,7 @@ // This does not include most "ordinary" animations, such as CSS animations. bool animation_requires_raster_; - // An effective connection type settable by layout tests. + // An effective connection type settable by web tests. blink::WebEffectiveConnectionType effective_connection_type_; // Forces v8 compilation cache to be disabled (used for inspector tests).
diff --git a/content/shell/test_runner/test_runner_for_specific_view.cc b/content/shell/test_runner/test_runner_for_specific_view.cc index b8443b4a..e7f6691c 100644 --- a/content/shell/test_runner/test_runner_for_specific_view.cc +++ b/content/shell/test_runner/test_runner_for_specific_view.cc
@@ -240,7 +240,7 @@ blink::MainThreadIsolate(), callback); CHECK(web_view()->MainFrame()->IsWebLocalFrame()) - << "Layout tests harness doesn't currently support running " + << "Web tests harness doesn't currently support running " << "testRuner.capturePixelsAsyncThen from an OOPIF"; web_view_test_proxy_->test_interfaces()->GetTestRunner()->DumpPixelsAsync( @@ -273,7 +273,7 @@ argv[1] = v8::Number::New(isolate, height); // Skia's internal byte order is platform-dependent. Always convert to RGBA - // in order to provide a consistent ordering to the layout tests. + // in order to provide a consistent ordering to the web tests. const SkImageInfo bufferInfo = snapshot.info().makeColorType(kRGBA_8888_SkColorType); const size_t bufferRowBytes = bufferInfo.minRowBytes(); @@ -678,7 +678,7 @@ blink::WebLocalFrame* TestRunnerForSpecificView::GetLocalMainFrame() { if (!web_view()->MainFrame()->IsWebLocalFrame()) { // Hitting the check below uncovers a new scenario that requires OOPIF - // support in the layout tests harness. + // support in the web tests harness. CHECK(false) << "This function cannot be called if the main frame is not a " "local frame."; }
diff --git a/content/shell/test_runner/test_runner_for_specific_view.h b/content/shell/test_runner/test_runner_for_specific_view.h index a982f083..3b3ddcf 100644 --- a/content/shell/test_runner/test_runner_for_specific_view.h +++ b/content/shell/test_runner/test_runner_for_specific_view.h
@@ -110,7 +110,7 @@ v8::UniquePersistent<v8::Function> callback, const std::vector<std::string>& events); - // Change the bluetooth test data while running a layout test. + // Change the bluetooth test data while running a web test. void SetBluetoothFakeAdapter(const std::string& adapter_name, v8::Local<v8::Function> callback); @@ -134,7 +134,7 @@ // TODO(oshima): Remove this once all platforms migrated. void EnableUseZoomForDSF(v8::Local<v8::Function> callback); - // Change the device color profile while running a layout test. + // Change the device color profile while running a web test. void SetColorProfile(const std::string& name, v8::Local<v8::Function> callback); @@ -218,7 +218,7 @@ std::string SelectionAsMarkup(); void SetViewSourceForFrame(const std::string& name, bool enabled); - // Many parts of the layout test harness assume that the main frame is local. + // Many parts of the web test harness assume that the main frame is local. // Having all of them go through the helper below makes it easier to catch // scenarios that require breaking this assumption. blink::WebLocalFrame* GetLocalMainFrame();
diff --git a/content/shell/test_runner/text_input_controller.cc b/content/shell/test_runner/text_input_controller.cc index a2e19a55..0dabe7d2 100644 --- a/content/shell/test_runner/text_input_controller.cc +++ b/content/shell/test_runner/text_input_controller.cc
@@ -393,7 +393,7 @@ } void TextInputController::ForceTextInputStateUpdate() { - // TODO(lukasza): Finish adding OOPIF support to the layout tests harness. + // TODO(lukasza): Finish adding OOPIF support to the web tests harness. CHECK(view()->MainFrame()->IsWebLocalFrame()) << "WebView does not have a local main frame and" " cannot handle input method controller tasks."; @@ -410,7 +410,7 @@ if (!view()->MainFrame()) return nullptr; - // TODO(lukasza): Finish adding OOPIF support to the layout tests harness. + // TODO(lukasza): Finish adding OOPIF support to the web tests harness. CHECK(view()->MainFrame()->IsWebLocalFrame()) << "WebView does not have a local main frame and" " cannot handle input method controller tasks.";
diff --git a/content/shell/test_runner/text_input_controller.h b/content/shell/test_runner/text_input_controller.h index df9d1f2..a7f03e31 100644 --- a/content/shell/test_runner/text_input_controller.h +++ b/content/shell/test_runner/text_input_controller.h
@@ -22,7 +22,7 @@ class WebViewTestProxyBase; // TextInputController is bound to window.textInputController in Javascript -// when content_shell is running. Layout tests use it to exercise various +// when content_shell is running. Web tests use it to exercise various // corners of text input. class TextInputController { public:
diff --git a/content/shell/test_runner/web_ax_object_proxy.cc b/content/shell/test_runner/web_ax_object_proxy.cc index d35039ef..2b88f31 100644 --- a/content/shell/test_runner/web_ax_object_proxy.cc +++ b/content/shell/test_runner/web_ax_object_proxy.cc
@@ -25,7 +25,7 @@ namespace { // Map role value to string, matching Safari/Mac platform implementation to -// avoid rebaselining layout tests. +// avoid rebaselining web tests. std::string RoleToString(ax::mojom::Role role) { std::string result = "AXRole: AX"; switch (role) {
diff --git a/content/shell/test_runner/web_frame_test_client.cc b/content/shell/test_runner/web_frame_test_client.cc index 442c33a..3a08c02 100644 --- a/content/shell/test_runner/web_frame_test_client.cc +++ b/content/shell/test_runner/web_frame_test_client.cc
@@ -159,7 +159,7 @@ // static void WebFrameTestClient::PrintFrameDescription(WebTestDelegate* delegate, blink::WebLocalFrame* frame) { - std::string name = content::GetFrameNameForLayoutTests(frame); + std::string name = content::GetFrameNameForWebTests(frame); if (frame == frame->View()->MainFrame()) { DCHECK(name.empty()); delegate->PrintMessage("main frame"); @@ -467,7 +467,7 @@ } // Set the new substituted URL. - request.SetURL(delegate_->RewriteLayoutTestsURL( + request.SetURL(delegate_->RewriteWebTestsURL( request.Url().GetString().Utf8(), test_runner()->is_web_platform_tests_mode())); }
diff --git a/content/shell/test_runner/web_frame_test_client.h b/content/shell/test_runner/web_frame_test_client.h index 29d47b5..1f1b876 100644 --- a/content/shell/test_runner/web_frame_test_client.h +++ b/content/shell/test_runner/web_frame_test_client.h
@@ -82,7 +82,7 @@ void HandleWebAccessibilityEvent(const blink::WebAXObject& obj, const char* event_name); - // Borrowed pointers to other parts of Layout Tests state. + // Borrowed pointers to other parts of web tests state. WebTestDelegate* delegate_; WebViewTestProxyBase* web_view_test_proxy_base_; WebFrameTestProxyBase* web_frame_test_proxy_base_;
diff --git a/content/shell/test_runner/web_test_delegate.h b/content/shell/test_runner/web_test_delegate.h index b0b5b93..656027e 100644 --- a/content/shell/test_runner/web_test_delegate.h +++ b/content/shell/test_runner/web_test_delegate.h
@@ -55,7 +55,7 @@ // only). virtual void PrintMessageToStderr(const std::string& message) = 0; - // Add a message to the text dump for the layout test. + // Add a message to the text dump for the web test. virtual void PrintMessage(const std::string& message) = 0; virtual void PostTask(base::OnceClosure task) = 0; @@ -80,10 +80,10 @@ // Replaces file:///tmp/web_tests/ with the actual path to the // web_tests directory, or rewrite URLs generated from absolute // path links in web-platform-tests. - virtual blink::WebURL RewriteLayoutTestsURL(const std::string& utf8_url, - bool is_wpt_mode) = 0; + virtual blink::WebURL RewriteWebTestsURL(const std::string& utf8_url, + bool is_wpt_mode) = 0; - // Manages the settings to used for layout tests. + // Manages the settings to used for web tests. virtual TestPreferences* Preferences() = 0; virtual void ApplyPreferences() = 0; virtual void SetPopupBlockingEnabled(bool block_popups) = 0; @@ -150,10 +150,10 @@ // Returns whether or not the use-zoom-for-dsf flag is enabled. virtual bool IsUseZoomForDSFEnabled() = 0; - // Change the device color space while running a layout test. + // Change the device color space while running a web test. virtual void SetDeviceColorSpace(const std::string& name) = 0; - // Set the bluetooth adapter while running a layout test, uses Mojo to + // Set the bluetooth adapter while running a web test, uses Mojo to // communicate with the browser. virtual void SetBluetoothFakeAdapter(const std::string& adapter_name, base::OnceClosure callback) = 0; @@ -183,7 +183,7 @@ // third-party context is blocked. virtual void SetBlockThirdPartyCookies(bool block) = 0; - // The same as RewriteLayoutTestsURL unless the resource is a path starting + // The same as RewriteWebTestsURL unless the resource is a path starting // with /tmp/, then return a file URL to a temporary file. virtual std::string PathToLocalResource(const std::string& resource) = 0; @@ -220,7 +220,7 @@ base::OnceCallback<void(const GURL&, const blink::Manifest&)> callback) = 0; - // Sends a message to the LayoutTestPermissionManager in order for it to + // Sends a message to the WebTestPermissionManager in order for it to // update its database. virtual void SetPermission(const std::string& permission_name, const std::string& permission_value,
diff --git a/content/shell/test_runner/web_test_runner.h b/content/shell/test_runner/web_test_runner.h index e8bfe4b..bbf2f2c 100644 --- a/content/shell/test_runner/web_test_runner.h +++ b/content/shell/test_runner/web_test_runner.h
@@ -27,11 +27,11 @@ class WebTestRunner { public: - // Returns a mock WebContentSettings that is used for layout tests. An + // Returns a mock WebContentSettings that is used for web tests. An // embedder should use this for all WebViews it creates. virtual blink::WebContentSettingsClient* GetWebContentSettings() const = 0; - // Returns a mock WebTextCheckClient that is used for layout tests. An + // Returns a mock WebTextCheckClient that is used for web tests. An // embedder should use this for all WebLocalFrames it creates. virtual blink::WebTextCheckClient* GetWebTextCheckClient() const = 0;
diff --git a/content/shell/test_runner/web_test_runtime_flags.cc b/content/shell/test_runner/web_test_runtime_flags.cc new file mode 100644 index 0000000..e21cfbd --- /dev/null +++ b/content/shell/test_runner/web_test_runtime_flags.cc
@@ -0,0 +1,72 @@ +// Copyright 2016 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/shell/test_runner/web_test_runtime_flags.h" + +namespace test_runner { + +WebTestRuntimeFlags::WebTestRuntimeFlags() { + Reset(); +} + +void WebTestRuntimeFlags::Reset() { + set_generate_pixel_results(true); + + set_dump_as_text(false); + set_dump_as_markup(false); + set_dump_as_layout(false); + set_dump_child_frames(false); + + set_is_printing(false); + set_printing_frame(""); + + set_policy_delegate_enabled(false); + set_policy_delegate_is_permissive(false); + set_policy_delegate_should_notify_done(false); + set_wait_until_done(false); + set_wait_until_external_url_load(false); + + set_dump_selection_rect(false); + set_dump_drag_image(false); + + set_accept_languages(""); + + set_dump_web_content_settings_client_callbacks(false); + set_images_allowed(true); + set_scripts_allowed(true); + set_storage_allowed(true); + set_plugins_allowed(true); + set_running_insecure_content_allowed(false); + set_autoplay_allowed(true); + + set_dump_editting_callbacks(false); + set_dump_frame_load_callbacks(false); + set_dump_ping_loader_callbacks(false); + set_dump_user_gesture_in_frame_load_callbacks(false); + set_dump_resource_load_callbacks(false); + set_dump_resource_response_mime_types(false); + set_dump_navigation_policy(false); + + set_dump_title_changes(false); + set_dump_icon_changes(false); + set_dump_console_messages(true); + + set_stay_on_page_after_handling_before_unload(false); + + set_have_top_loading_frame(false); + + set_can_open_windows(false); + + set_dump_create_view(false); + set_dump_spell_check_callbacks(false); + set_dump_javascript_dialogs(true); + + set_has_custom_text_output(false); + set_custom_text_output(""); + + // No need to report the initial state - only the future delta is important. + tracked_dictionary().ResetChangeTracking(); +} + +} // namespace test_runner
diff --git a/content/shell/test_runner/web_test_runtime_flags.h b/content/shell/test_runner/web_test_runtime_flags.h new file mode 100644 index 0000000..8175afd --- /dev/null +++ b/content/shell/test_runner/web_test_runtime_flags.h
@@ -0,0 +1,196 @@ +// Copyright 2016 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_SHELL_TEST_RUNNER_WEB_TEST_RUNTIME_FLAGS_H_ +#define CONTENT_SHELL_TEST_RUNNER_WEB_TEST_RUNTIME_FLAGS_H_ + +#include <string> + +#include "base/logging.h" +#include "base/macros.h" +#include "base/values.h" +#include "content/shell/test_runner/test_runner_export.h" +#include "content/shell/test_runner/tracked_dictionary.h" + +namespace test_runner { + +// WebTestRuntimeFlags stores flags controlled by web tests at runtime +// (i.e. by calling testRunner.dumpAsText() or testRunner.waitUntilDone()). +// Changes to the flags are tracked (to help replicate them across renderers). +class TEST_RUNNER_EXPORT WebTestRuntimeFlags { + public: + // Creates default flags (see also the Reset method). + WebTestRuntimeFlags(); + + // Resets all the values to their defaults. + void Reset(); + + TrackedDictionary& tracked_dictionary() { return dict_; } + +#define DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(name) \ + bool name() const { \ + bool result; \ + bool found = dict_.current_values().GetBoolean(#name, &result); \ + DCHECK(found); \ + return result; \ + } \ + void set_##name(bool new_value) { dict_.SetBoolean(#name, new_value); } + +#define DEFINE_STRING_WEB_TEST_RUNTIME_FLAG(name) \ + std::string name() const { \ + std::string result; \ + bool found = dict_.current_values().GetString(#name, &result); \ + DCHECK(found); \ + return result; \ + } \ + void set_##name(const std::string& new_value) { \ + dict_.SetString(#name, new_value); \ + } + + // If true, the test runner will generate pixel results. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(generate_pixel_results) + + // If true, the test runner will produce a plain text dump. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_as_text) + + // If true and dump_as_text is false, the test runner will produce a dump of + // the DOM. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_as_markup) + + // If true and both dump_as_text and dump_as_markup are false, the test runner + // will dump a text representation of the layout. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_as_layout) + + // If true, the test runner will recursively dump all frames as text, markup + // or layout depending on which of dump_as_text, dump_as_markup and + // dump_as_layout is effective. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_child_frames) + + // If true, layout is to target printed pages. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(is_printing) + + // If this is non-empty and is_printing is true, pixel dump will be for the + // named frame printed. + DEFINE_STRING_WEB_TEST_RUNTIME_FLAG(printing_frame) + + // If true, don't dump output until notifyDone is called. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(wait_until_done) + + // If true, ends the test when a URL is loaded externally via + // WebLocalFrameClient::loadURLExternally(). + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(wait_until_external_url_load) + + // Causes navigation actions just printout the intended navigation instead + // of taking you to the page. This is used for cases like mailto, where you + // don't actually want to open the mail program. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(policy_delegate_enabled) + + // Toggles the behavior of the policy delegate. If true, then navigations + // will be allowed. Otherwise, they will be ignored (dropped). + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(policy_delegate_is_permissive) + + // If true, the policy delegate will signal web test completion. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(policy_delegate_should_notify_done) + + // If true, the test runner will draw the bounds of the current selection rect + // taking possible transforms of the selection rect into account. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_selection_rect) + + // If true, the test runner will dump the drag image as pixel results. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_drag_image) + + // Contents of Accept-Language HTTP header requested by the test. + DEFINE_STRING_WEB_TEST_RUNTIME_FLAG(accept_languages) + + // Flags influencing behavior of MockContentSettingsClient. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(images_allowed) + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(scripts_allowed) + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(storage_allowed) + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(plugins_allowed) + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(running_insecure_content_allowed) + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_web_content_settings_client_callbacks) + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(autoplay_allowed) + + // If true, the test runner will write a descriptive line for each editing + // command. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_editting_callbacks) + + // If true, the test runner will output a descriptive line for each frame + // load callback. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_frame_load_callbacks) + + // If true, the test runner will output a descriptive line for each + // PingLoader dispatched. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_ping_loader_callbacks) + + // If true, the test runner will output a line of the user gesture status + // text for some frame load callbacks. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_user_gesture_in_frame_load_callbacks) + + // If true, the test runner will output a descriptive line for each resource + // load callback. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_resource_load_callbacks) + + // If true, the test runner will output the MIME type for each resource that + // was loaded. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_resource_response_mime_types) + + // If true, content_shell will dump the default navigation policy passed to + // WebLocalFrameClient::decidePolicyForNavigation. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_navigation_policy) + + // If true, output a message when the page title is changed. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_title_changes) + + // If true, the test runner will print out the icon change notifications. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_icon_changes) + + // If true, the console messages produced by the page will + // be part of test output. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_console_messages) + + // Desired return value of WebLocalFrameClient::runModalBeforeUnloadDialog. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(stay_on_page_after_handling_before_unload) + + // Indicates if the test already tracks a top loading frame (in any of the + // renderer processes). This flag is trying to prevent different renderer + // processes from tracking different top loading frames (i.e. main frame in + // one renderer and an OOPIF in another renderer). + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(have_top_loading_frame) + + // If true, new windows can be opened via javascript or by plugins. By + // default, set to false and can be toggled to true using + // setCanOpenWindows(). + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(can_open_windows) + + // If true, output a descriptive line each time WebViewClient::createView + // is invoked. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_create_view) + + // If true, the test runner will output descriptive test for spellcheck + // execution. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_spell_check_callbacks) + + // If true, content_shell will output text for alert(), confirm(), prompt(), + // etc. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(dump_javascript_dialogs) + + // True if the test called testRunner.setCustomTextOutput. + DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG(has_custom_text_output) + + // Contains text passed by the test to testRunner.setCustomTextOutput. + DEFINE_STRING_WEB_TEST_RUNTIME_FLAG(custom_text_output) + +#undef DEFINE_BOOL_WEB_TEST_RUNTIME_FLAG +#undef DEFINE_STRING_WEB_TEST_RUNTIME_FLAG + + private: + TrackedDictionary dict_; + + DISALLOW_COPY_AND_ASSIGN(WebTestRuntimeFlags); +}; + +} // namespace test_runner + +#endif // CONTENT_SHELL_TEST_RUNNER_WEB_TEST_RUNTIME_FLAGS_H_
diff --git a/content/shell/test_runner/web_view_test_client.cc b/content/shell/test_runner/web_view_test_client.cc index a458204..8470180b 100644 --- a/content/shell/test_runner/web_view_test_client.cc +++ b/content/shell/test_runner/web_view_test_client.cc
@@ -39,8 +39,8 @@ WebViewTestClient::~WebViewTestClient() {} -// The output from these methods in layout test mode should match that -// expected by the layout tests. See EditingDelegate.m in DumpRenderTree. +// The output from these methods in web test mode should match that +// expected by the web tests. See EditingDelegate.m in DumpRenderTree. blink::WebView* WebViewTestClient::CreateView( blink::WebLocalFrame* frame,
diff --git a/content/shell/test_runner/web_widget_test_proxy.h b/content/shell/test_runner/web_widget_test_proxy.h index 8607288..5ed94f8 100644 --- a/content/shell/test_runner/web_widget_test_proxy.h +++ b/content/shell/test_runner/web_widget_test_proxy.h
@@ -90,7 +90,7 @@ // * when a fooClient has a mock implementation, WebWidgetTestProxy can // override the fooClient() call and have WebWidgetTestProxyBase return the // mock implementation. -// * when a value needs to be overridden by LayoutTests, WebWidgetTestProxy can +// * when a value needs to be overridden by web tests, WebWidgetTestProxy can // override RenderViewImpl's getter and call a getter from // WebWidgetTestProxyBase instead. In addition, WebWidgetTestProxyBase will // have a public setter that could be called from the TestRunner.
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 80d8043..382420d 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -538,8 +538,8 @@ ] deps = [ - ":layouttest_support", ":test_support", + ":web_test_support", "//base", "//base:i18n", "//base/test:test_config", @@ -588,14 +588,14 @@ ] } -mojom("mojo_layouttest_bindings") { +mojom("mojo_web_test_bindings") { testonly = true sources = [ "data/lite_js_test.mojom", - "data/mojo_layouttest_test.mojom", + "data/mojo_web_test_helper_test.mojom", ] - # This mojom interface is exposed publicly to layout tests which use + # This mojom interface is exposed publicly to web tests which use # prepackaged redistributable JS bindings. It is therefore not desirable to # scramble these messages. scramble_message_ids = false @@ -608,7 +608,7 @@ ] } -static_library("layouttest_support") { +static_library("web_test_support") { testonly = true # See comment at the top of //content/BUILD.gn for why this is disabled in @@ -618,10 +618,10 @@ } sources = [ - "../public/test/layouttest_support.h", "../public/test/nested_message_pump_android.cc", "../public/test/nested_message_pump_android.h", - "layouttest_support.cc", + "../public/test/web_test_support.h", + "web_test_support.cc", ] deps = [ @@ -942,8 +942,8 @@ deps = [ ":browsertest_support", ":content_test_mojo_bindings", - ":layouttest_support", ":test_support", + ":web_test_support", ":web_ui_test_mojo_bindings", "//base/test:test_support", "//components/discardable_memory/client",
diff --git a/content/test/DEPS b/content/test/DEPS index 056b8674..5d00d1c 100644 --- a/content/test/DEPS +++ b/content/test/DEPS
@@ -41,7 +41,7 @@ ] specific_include_rules = { - "layouttest_support.cc": [ + "web_test_support.cc": [ "+content/shell/test_runner", "+content/shell/common/shell_switches.h", "+services/ws/public/cpp/gpu",
diff --git a/content/test/data/accessibility/aria/aria-listbox-expected-android.txt b/content/test/data/accessibility/aria/aria-listbox-expected-android.txt index c70c389..4050d5c 100644 --- a/content/test/data/accessibility/aria/aria-listbox-expected-android.txt +++ b/content/test/data/accessibility/aria/aria-listbox-expected-android.txt
@@ -1,7 +1,7 @@ android.webkit.WebView focusable focused scrollable -++android.widget.ListView role_description='list box' clickable collection item_count=5 row_count=5 +++android.widget.ListView role_description='list box' clickable collection item_count=4 row_count=4 ++++android.view.View clickable collection_item focusable name='Item 1' ++++android.view.View clickable collection_item focusable name='Item 2' item_index=1 row_index=1 ++++android.view.View role_description='splitter' -++++android.view.View clickable collection_item focusable name='Second group item 1' row_index=3 -++++android.view.View clickable collection_item focusable name='Second group item 2' item_index=1 row_index=4 \ No newline at end of file +++++android.view.View clickable collection_item focusable name='Second group item 1' item_index=2 row_index=2 +++++android.view.View clickable collection_item focusable name='Second group item 2' item_index=3 row_index=3
diff --git a/content/test/data/accessibility/html/dd-expected-android.txt b/content/test/data/accessibility/html/dd-expected-android.txt index 5003558e..243bc3f6 100644 --- a/content/test/data/accessibility/html/dd-expected-android.txt +++ b/content/test/data/accessibility/html/dd-expected-android.txt
@@ -1,4 +1,4 @@ android.webkit.WebView focusable focused scrollable -++android.widget.ListView collection item_count=2 row_count=2 +++android.widget.ListView collection item_count=1 row_count=1 ++++android.view.View collection_item name='Coffee' ++++android.view.View role_description='definition' name='Black hot drink'
diff --git a/content/test/data/accessibility/html/dl-expected-android.txt b/content/test/data/accessibility/html/dl-expected-android.txt index d98ab88..a370b3e 100644 --- a/content/test/data/accessibility/html/dl-expected-android.txt +++ b/content/test/data/accessibility/html/dl-expected-android.txt
@@ -1,5 +1,5 @@ android.webkit.WebView focusable focused scrollable -++android.widget.ListView collection item_count=2 row_count=2 +++android.widget.ListView collection item_count=1 row_count=1 ++++android.view.View collection_item name='Term' ++++android.view.View role_description='definition' name='Description' ++android.view.View role_description='definition' name='Definition'
diff --git a/content/test/data/accessibility/html/dt-expected-android.txt b/content/test/data/accessibility/html/dt-expected-android.txt index 5003558e..243bc3f6 100644 --- a/content/test/data/accessibility/html/dt-expected-android.txt +++ b/content/test/data/accessibility/html/dt-expected-android.txt
@@ -1,4 +1,4 @@ android.webkit.WebView focusable focused scrollable -++android.widget.ListView collection item_count=2 row_count=2 +++android.widget.ListView collection item_count=1 row_count=1 ++++android.view.View collection_item name='Coffee' ++++android.view.View role_description='definition' name='Black hot drink'
diff --git a/content/test/data/accessibility/html/list-expected-android.txt b/content/test/data/accessibility/html/list-expected-android.txt index b9f6f01..deece12 100644 --- a/content/test/data/accessibility/html/list-expected-android.txt +++ b/content/test/data/accessibility/html/list-expected-android.txt
@@ -9,9 +9,9 @@ ++++android.view.View collection_item item_index=2 row_index=2 ++++++android.view.View name='• ' ++++++android.view.View name='toe' -++android.widget.ListView collection item_count=5 row_count=5 +++android.widget.ListView collection item_count=3 row_count=3 ++++android.view.View collection_item name='tic' ++++android.view.View name=' ' -++++android.view.View collection_item name='tac' item_index=1 row_index=2 +++++android.view.View collection_item name='tac' item_index=1 row_index=1 ++++android.view.View name=' ' -++++android.view.View collection_item name='toe' item_index=2 row_index=4 +++++android.view.View collection_item name='toe' item_index=2 row_index=2
diff --git a/content/test/data/accessibility/html/nestedlist-expected-android.txt b/content/test/data/accessibility/html/nestedlist-expected-android.txt index dffe4e0..a367b1c 100644 --- a/content/test/data/accessibility/html/nestedlist-expected-android.txt +++ b/content/test/data/accessibility/html/nestedlist-expected-android.txt
@@ -1,6 +1,6 @@ android.webkit.WebView focusable focused scrollable ++android.view.View name='This is a multi-leveled list' -++android.widget.ListView collection hierarchical item_count=4 row_count=4 +++android.widget.ListView collection hierarchical item_count=3 row_count=3 ++++android.view.View collection_item ++++++android.view.View name='1. ' ++++++android.view.View name='Sports'
diff --git a/content/test/data/accessibility/html/nestedlist.html b/content/test/data/accessibility/html/nestedlist.html index f2dbd5f..9b6f9c67 100644 --- a/content/test/data/accessibility/html/nestedlist.html +++ b/content/test/data/accessibility/html/nestedlist.html
@@ -14,6 +14,6 @@ </ol> </li> <li> Recipes </li> - <ol> - </ol> + <ol> + </ol> </ol>
diff --git a/content/test/data/blob_storage/common.js b/content/test/data/blob_storage/common.js index e9b3cc6a..839fa0c 100644 --- a/content/test/data/blob_storage/common.js +++ b/content/test/data/blob_storage/common.js
@@ -29,8 +29,8 @@ } // The following functions are based on -// WebKit/LayoutTests/fast/js/resources/js-test-pre.js -// so that the tests will look similar to the existing layout tests. +// blink/web_tests/resources/js-test.js +// so that the tests will look similar to the existing web tests. function stringify(v) { if (v === 0 && 1/v < 0) return "-0";
diff --git a/content/test/data/indexeddb/common.js b/content/test/data/indexeddb/common.js index 6f4d01cc..f0886ef 100644 --- a/content/test/data/indexeddb/common.js +++ b/content/test/data/indexeddb/common.js
@@ -75,7 +75,7 @@ // The following functions are based on // blink/web_tests/resources/js-test.js -// so that the tests will look similar to the existing layout tests. +// so that the tests will look similar to the existing web tests. function stringify(v) { if (v === 0 && 1/v < 0)
diff --git a/content/test/data/media/getusermedia-depth-capture.html b/content/test/data/media/getusermedia-depth-capture.html index e1dabf1..38590ff 100644 --- a/content/test/data/media/getusermedia-depth-capture.html +++ b/content/test/data/media/getusermedia-depth-capture.html
@@ -17,7 +17,7 @@ return document.getElementById(id); }; - // testVideoToImageBitmap and the tests below are layout tests that we + // testVideoToImageBitmap and the tests below are web tests that we // run here because they require --use-fake-device-for-media-capture. function getDepthStreamAndCallCreateImageBitmap() { console.log('Calling getDepthStreamAndCallCreateImageBitmap');
diff --git a/content/test/data/mojo_layouttest_test.mojom b/content/test/data/mojo_layouttest_test.mojom deleted file mode 100644 index 4f6ec84a..0000000 --- a/content/test/data/mojo_layouttest_test.mojom +++ /dev/null
@@ -1,10 +0,0 @@ -// Copyright 2014 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. - -module content.mojom; - -interface MojoLayoutTestHelper { - Reverse(string message) => (string reversed); -}; -
diff --git a/content/test/data/mojo_web_test_helper_test.mojom b/content/test/data/mojo_web_test_helper_test.mojom new file mode 100644 index 0000000..ad5b88a --- /dev/null +++ b/content/test/data/mojo_web_test_helper_test.mojom
@@ -0,0 +1,10 @@ +// Copyright 2014 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. + +module content.mojom; + +interface MojoWebTestHelper { + Reverse(string message) => (string reversed); +}; +
diff --git a/content/test/data/page_with_iframe_and_image.html b/content/test/data/page_with_iframe_and_image.html new file mode 100644 index 0000000..0217f09 --- /dev/null +++ b/content/test/data/page_with_iframe_and_image.html
@@ -0,0 +1,9 @@ +<html> +<head></head> +<body> + <img src="image.jpg"/> + <p>This page has an iframe. Yay for iframes! + <p> + <iframe src="page_with_image.html" id="test_iframe"></iframe> +</body> +</html>
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 20981cc..43b358f 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -313,6 +313,11 @@ self.Fail('conformance/misc/webgl-specific-stencil-settings.html', ['passthrough'], bug=844349) + # TODO(jmadill): Re-enable after fix. http://anglebug.com/3012 + self.Fail('conformance2/extensions/' + + 'webgl_multiview_transform_feedback.html', + ['passthrough'], bug=3012) # ANGLE bug ID + # Passthrough command decoder / OpenGL self.Fail('conformance2/misc/uninitialized-test-2.html', ['passthrough', 'opengl'], bug=602688) @@ -376,6 +381,9 @@ self.Fail('conformance2/renderbuffers/' + 'multisampled-depth-renderbuffer-initialization.html', ['win', 'passthrough', 'opengl', 'intel'], bug=2760) # ANGLE bug + self.Flaky('conformance2/rendering/' + + 'out-of-bounds-index-buffers-after-copying.html', + ['win', 'passthrough', 'opengl', 'intel'], bug=912579) self.Fail('conformance/glsl/constructors/glsl-construct-mat2.html', ['win', 'passthrough', 'opengl', 'intel'], bug=602688) self.Fail('conformance2/textures/misc/texture-npot.html', @@ -629,6 +637,27 @@ self.Fail('conformance2/uniforms/draw-with-uniform-blocks.html', ['mac', ('nvidia', 0xfe9)], bug=795052) + self.Flaky('conformance2/glsl3/compound-assignment-type-combination.html', + ['mac', ('nvidia', 0xfe9)], bug=911772) + self.Flaky('conformance2/query/occlusion-query.html', + ['mac', ('nvidia', 0xfe9)], bug=911772) + self.Flaky('conformance2/state/gl-object-get-calls.html', + ['mac', ('nvidia', 0xfe9)], bug=911772) + self.Flaky('conformance2/textures/canvas_sub_rectangle/' + + 'tex-2d-r8-red-unsigned_byte.html', + ['mac', ('nvidia', 0xfe9)], bug=911772) + self.Flaky('conformance2/textures/canvas_sub_rectangle/' + + 'tex-2d-rgb5_a1-rgba-unsigned_short_5_5_5_1.html', + ['mac', ('nvidia', 0xfe9)], bug=911772) + self.Flaky('conformance2/textures/canvas_sub_rectangle/' + + 'tex-2d-rgb16f-rgb-half_float.html', + ['mac', ('nvidia', 0xfe9)], bug=911772) + self.Flaky('conformance2/textures/canvas_sub_rectangle/' + + 'tex-2d-rgb565-rgb-unsigned_short_5_6_5.html', + ['mac', ('nvidia', 0xfe9)], bug=911772) + self.Flaky('conformance2/textures/canvas/tex-3d-r16f-red-half_float.html', + ['mac', ('nvidia', 0xfe9)], bug=911772) + # When these fail on this configuration, they fail multiple times in a row. self.Fail('deqp/functional/gles3/shaderoperator/*', ['mac', 'nvidia'], bug=756537)
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 06915f11..fdb9102 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -44,6 +44,8 @@ self.Fail('WebglExtension_EXT_color_buffer_float', ['win', 'mac']) + self.Fail('WebglExtension_WEBGL_multi_draw_instanced', + ['passthrough', 'vulkan'], bug=2672) # angle bug ID # Skip these, rather than expect them to fail, to speed up test # execution. The browser is restarted even after expected test # failures. @@ -746,6 +748,8 @@ ['android', ('qualcomm', 'Adreno (TM) 418')], bug=609883) self.Flaky('conformance/glsl/constructors/glsl-construct-ivec4.html', ['android', ('qualcomm', 'Adreno (TM) 418')], bug=912161) + self.Flaky('conformance/glsl/constructors/glsl-construct-mat2.html', + ['android', ('qualcomm', 'Adreno (TM) 418')], bug=912161) self.Flaky('conformance/glsl/constructors/' + 'glsl-construct-vec-mat-corner-cases.html', ['android', ('qualcomm', 'Adreno (TM) 418')], bug=912161) @@ -844,6 +848,10 @@ ['android', 'nvidia'], bug=478572) self.Fail('conformance/glsl/bugs/multiplication-assignment.html', ['android', 'nvidia'], bug=606096) + self.Flaky('conformance/glsl/constructors/glsl-construct-ivec4.html', + ['android', 'nvidia'], bug=912161) + self.Flaky('conformance/glsl/constructors/glsl-construct-mat2.html', + ['android', 'nvidia'], bug=912161) self.Flaky('conformance/extensions/oes-texture-half-float-with-video.html', ['android', 'nvidia'], bug=891456) self.Flaky('conformance/extensions/oes-texture-float-with-video.html',
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py b/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py index ea64598..a5367d4 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py
@@ -168,6 +168,8 @@ 'WEBGL_depth_texture', 'WEBGL_draw_buffers', 'WEBGL_lose_context', + 'WEBGL_multi_draw', + 'WEBGL_multi_draw_instanced', ] else: return [ @@ -185,6 +187,8 @@ 'WEBGL_debug_renderer_info', 'WEBGL_debug_shaders', 'WEBGL_lose_context', + 'WEBGL_multi_draw', + 'WEBGL_multi_draw_instanced', 'WEBGL_multiview', ]
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc deleted file mode 100644 index d180e377..0000000 --- a/content/test/layouttest_support.cc +++ /dev/null
@@ -1,569 +0,0 @@ -// Copyright (c) 2012 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/public/test/layouttest_support.h" - -#include <stddef.h> - -#include <algorithm> -#include <unordered_map> -#include <utility> -#include <vector> - -#include "base/callback.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "build/build_config.h" -#include "cc/base/switches.h" -#include "cc/test/pixel_test_output_surface.h" -#include "components/viz/common/features.h" -#include "components/viz/common/frame_sinks/copy_output_request.h" -#include "components/viz/test/test_layer_tree_frame_sink.h" -#include "content/browser/bluetooth/bluetooth_device_chooser_controller.h" -#include "content/browser/renderer_host/render_process_host_impl.h" -#include "content/browser/renderer_host/render_widget_host_impl.h" -#include "content/browser/worker_host/shared_worker_service_impl.h" -#include "content/common/renderer.mojom.h" -#include "content/common/unique_name_helper.h" -#include "content/public/browser/storage_partition.h" -#include "content/public/common/gpu_stream_constants.h" -#include "content/public/common/page_state.h" -#include "content/public/common/screen_info.h" -#include "content/renderer/gpu/layer_tree_view.h" -#include "content/renderer/input/render_widget_input_handler_delegate.h" -#include "content/renderer/layout_test_dependencies.h" -#include "content/renderer/loader/request_extra_data.h" -#include "content/renderer/loader/web_worker_fetch_context_impl.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 "content/renderer/renderer_blink_platform_impl.h" -#include "content/shell/common/shell_switches.h" -#include "content/shell/common/web_test/web_test_switches.h" -#include "content/shell/renderer/web_test/blink_test_runner.h" -#include "content/shell/renderer/web_test/web_test_render_thread_observer.h" -#include "content/shell/test_runner/test_common.h" -#include "content/shell/test_runner/web_frame_test_proxy.h" -#include "content/shell/test_runner/web_test_interfaces.h" -#include "content/shell/test_runner/web_view_test_proxy.h" -#include "content/shell/test_runner/web_widget_test_proxy.h" -#include "gpu/ipc/service/image_transport_surface.h" -#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h" -#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" -#include "third_party/blink/public/platform/web_float_rect.h" -#include "third_party/blink/public/platform/web_input_event.h" -#include "third_party/blink/public/platform/web_rect.h" -#include "third_party/blink/public/web/web_view.h" -#include "ui/base/ui_base_switches.h" -#include "ui/events/blink/blink_event_util.h" -#include "ui/gfx/geometry/vector2d.h" -#include "ui/gfx/icc_profile.h" -#include "ui/gfx/test/icc_profiles.h" - -#if defined(OS_MACOSX) -#include "content/browser/frame_host/popup_menu_helper_mac.h" -#elif defined(OS_WIN) -#include "content/child/font_warmup_win.h" -#include "third_party/blink/public/web/win/web_font_rendering.h" -#include "third_party/skia/include/core/SkFontMgr.h" -#include "third_party/skia/include/core/SkRefCnt.h" -#include "third_party/skia/include/ports/SkTypeface_win.h" -#include "ui/gfx/win/direct_write.h" -#endif - -using blink::WebRect; -using blink::WebSize; - -namespace content { - -namespace { - -RenderViewImpl* CreateWebViewTestProxy(CompositorDependencies* compositor_deps, - const mojom::CreateViewParams& params) { - test_runner::WebTestInterfaces* interfaces = - WebTestRenderThreadObserver::GetInstance()->test_interfaces(); - - auto* render_view_proxy = - new test_runner::WebViewTestProxy(compositor_deps, params); - - BlinkTestRunner* test_runner = new BlinkTestRunner(render_view_proxy); - // TODO(lukasza): Using the 1st BlinkTestRunner as the main delegate is wrong, - // but it is difficult to change because this behavior has been baked for a - // long time into test assumptions (i.e. which PrintMessage gets delivered to - // the browser depends on this). - static bool first_test_runner = true; - if (first_test_runner) { - first_test_runner = false; - interfaces->SetDelegate(test_runner); - } - - render_view_proxy->Initialize(interfaces, test_runner); - return render_view_proxy; -} - -RenderWidget* CreateWebWidgetTestProxy(int32_t routing_id, - CompositorDependencies* compositor_deps, - WidgetType popup_type, - const ScreenInfo& screen_info, - blink::WebDisplayMode display_mode, - bool swapped_out, - bool hidden, - bool never_visible) { - auto* render_widget_proxy = new test_runner::WebWidgetTestProxy( - routing_id, compositor_deps, popup_type, screen_info, display_mode, - swapped_out, hidden, never_visible); - return render_widget_proxy; -} - -void RenderWidgetInitialized(RenderWidget* render_widget) { - test_runner::WebTestInterfaces* interfaces = - WebTestRenderThreadObserver::GetInstance()->test_interfaces(); - - blink::WebWidget* web_widget = render_widget->GetWebWidget(); - // This callback is run only for RenderWidgets that are for a frame. - CHECK(web_widget->IsWebFrameWidget()); - auto* web_frame_widget = static_cast<blink::WebFrameWidget*>(web_widget); - // RenderWidgets for a frame will have a local root with a RenderView. - blink::WebView* web_view = web_frame_widget->LocalRoot()->View(); - RenderView* render_view = content::RenderView::FromWebView(web_view); - // RenderViews are always RenderViewImpls internally. - auto* render_view_impl = static_cast<RenderViewImpl*>(render_view); - - // We are here because CreateWebWidgetTestProxy() was used to make the - // RenderWidget, and it creates a WebWidgetTestProxy instead, which is-a - // RenderWidget. - auto* render_widget_proxy = - static_cast<test_runner::WebWidgetTestProxy*>(render_widget); - render_widget_proxy->Initialize(interfaces, web_widget, render_view_impl); -} - -RenderFrameImpl* CreateWebFrameTestProxy(RenderFrameImpl::CreateParams params) { - test_runner::WebTestInterfaces* interfaces = - WebTestRenderThreadObserver::GetInstance()->test_interfaces(); - - // RenderFrameImpl always has a RenderViewImpl for it. - RenderViewImpl* render_view_impl = params.render_view; - - auto* render_frame_proxy = - new test_runner::WebFrameTestProxy(std::move(params)); - render_frame_proxy->Initialize(interfaces, render_view_impl); - return render_frame_proxy; -} - -float GetWindowToViewportScale(RenderWidget* render_widget) { - blink::WebFloatRect rect(0, 0, 1.0f, 0.0); - render_widget->ConvertWindowToViewport(&rect); - return rect.width; -} - -#if defined(OS_WIN) -// DirectWrite only has access to %WINDIR%\Fonts by default. For developer -// side-loading, support kRegisterFontFiles to allow access to additional fonts. -void RegisterSideloadedTypefaces(SkFontMgr* fontmgr) { - for (const auto& file : switches::GetSideloadFontFiles()) { - blink::WebFontRendering::AddSideloadedFontForTesting( - fontmgr->makeFromFile(file.c_str())); - } -} -#endif // OS_WIN - -} // namespace - -test_runner::WebViewTestProxyBase* GetWebViewTestProxyBase( - RenderView* render_view) { - auto* render_view_proxy = - static_cast<test_runner::WebViewTestProxy*>(render_view); - return static_cast<test_runner::WebViewTestProxyBase*>(render_view_proxy); -} - -test_runner::WebFrameTestProxyBase* GetWebFrameTestProxyBase( - RenderFrame* render_frame) { - auto* render_frame_proxy = - static_cast<test_runner::WebFrameTestProxy*>(render_frame); - return static_cast<test_runner::WebFrameTestProxyBase*>(render_frame_proxy); -} - -test_runner::WebWidgetTestProxyBase* GetWebWidgetTestProxyBase( - blink::WebLocalFrame* frame) { - DCHECK(frame); - RenderFrame* local_root = RenderFrame::FromWebFrame(frame->LocalRoot()); - DCHECK(local_root); - // TODO(lfg): Simplify once RenderView no longer inherits from RenderWidget. - if (local_root->IsMainFrame()) { - test_runner::WebViewTestProxyBase* web_view_test_proxy_base = - GetWebViewTestProxyBase(local_root->GetRenderView()); - test_runner::WebWidgetTestProxyBase* web_widget_test_proxy_base = - web_view_test_proxy_base->web_widget_test_proxy_base(); - DCHECK(web_widget_test_proxy_base->web_widget()->IsWebView()); - return web_widget_test_proxy_base; - } else { - RenderWidget* render_widget = - static_cast<RenderFrameImpl*>(local_root)->GetRenderWidget(); - DCHECK(render_widget); - auto* render_widget_proxy = - static_cast<test_runner::WebWidgetTestProxy*>(render_widget); - auto* web_widget_test_proxy_base = - static_cast<test_runner::WebWidgetTestProxyBase*>(render_widget_proxy); - DCHECK(web_widget_test_proxy_base->web_widget()->IsWebFrameWidget()); - return web_widget_test_proxy_base; - } -} - -RenderWidget* GetRenderWidget( - test_runner::WebWidgetTestProxyBase* web_widget_test_proxy_base) { - DCHECK(web_widget_test_proxy_base); - - blink::WebWidget* widget = web_widget_test_proxy_base->web_widget(); - // TODO(lfg): Simplify once RenderView no longer inherits from RenderWidget. - if (widget->IsWebView()) { - test_runner::WebViewTestProxyBase* render_view_proxy_base = - web_widget_test_proxy_base->web_view_test_proxy_base(); - auto* render_view_proxy = - static_cast<test_runner::WebViewTestProxy*>(render_view_proxy_base); - RenderViewImpl* render_view_impl = - static_cast<RenderViewImpl*>(render_view_proxy); - return render_view_impl->GetWidget(); - } else if (widget->IsWebFrameWidget()) { - auto* render_widget_proxy = static_cast<test_runner::WebWidgetTestProxy*>( - web_widget_test_proxy_base); - return static_cast<RenderWidget*>(render_widget_proxy); - } else { - NOTREACHED(); - return nullptr; - } -} - -void EnableWebTestProxyCreation() { - RenderViewImpl::InstallCreateHook(CreateWebViewTestProxy); - RenderFrameImpl::InstallCreateHook(CreateWebFrameTestProxy, - CreateWebWidgetTestProxy, - RenderWidgetInitialized); -} - -void FetchManifest(blink::WebView* view, FetchManifestCallback callback) { - RenderFrameImpl::FromWebFrame(view->MainFrame()) - ->GetManifestManager() - .RequestManifest(std::move(callback)); -} - -void SetWorkerRewriteURLFunction(RewriteURLFunction rewrite_url_function) { - WebWorkerFetchContextImpl::InstallRewriteURLFunction(rewrite_url_function); -} - -namespace { - -// Invokes a callback on commit (on the main thread) to obtain the output -// surface that should be used, then asks that output surface to submit the copy -// request at SwapBuffers time. -class CopyRequestSwapPromise : public cc::SwapPromise { - public: - using FindLayerTreeFrameSinkCallback = - base::Callback<viz::TestLayerTreeFrameSink*()>; - CopyRequestSwapPromise( - std::unique_ptr<viz::CopyOutputRequest> request, - FindLayerTreeFrameSinkCallback find_layer_tree_frame_sink_callback) - : copy_request_(std::move(request)), - find_layer_tree_frame_sink_callback_( - std::move(find_layer_tree_frame_sink_callback)) {} - - // cc::SwapPromise implementation. - void OnCommit() override { - layer_tree_frame_sink_from_commit_ = - find_layer_tree_frame_sink_callback_.Run(); - DCHECK(layer_tree_frame_sink_from_commit_); - } - void DidActivate() override {} - void WillSwap(viz::CompositorFrameMetadata*) override { - layer_tree_frame_sink_from_commit_->RequestCopyOfOutput( - std::move(copy_request_)); - } - void DidSwap() override {} - void DidNotSwap(DidNotSwapReason r) override { - // The compositor should always swap in layout test mode. - NOTREACHED() << "did not swap for reason " << r; - } - int64_t TraceId() const override { return 0; } - - private: - std::unique_ptr<viz::CopyOutputRequest> copy_request_; - FindLayerTreeFrameSinkCallback find_layer_tree_frame_sink_callback_; - viz::TestLayerTreeFrameSink* layer_tree_frame_sink_from_commit_ = nullptr; -}; - -} // namespace - -class LayoutTestDependenciesImpl : public LayoutTestDependencies, - public viz::TestLayerTreeFrameSinkClient { - public: - bool UseDisplayCompositorPixelDump() const override { - base::CommandLine* cmd = base::CommandLine::ForCurrentProcess(); - return cmd->HasSwitch(switches::kEnableDisplayCompositorPixelDump); - } - - std::unique_ptr<cc::LayerTreeFrameSink> CreateLayerTreeFrameSink( - int32_t routing_id, - scoped_refptr<gpu::GpuChannelHost> gpu_channel, - scoped_refptr<viz::ContextProvider> compositor_context_provider, - scoped_refptr<viz::RasterContextProvider> worker_context_provider, - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, - CompositorDependencies* deps) override { - // This could override the GpuChannel for a LayerTreeFrameSink that was - // previously being created but in that case the old GpuChannel would be - // lost as would the LayerTreeFrameSink. - gpu_channel_ = gpu_channel; - gpu_memory_buffer_manager_ = gpu_memory_buffer_manager; - - auto* task_runner = deps->GetCompositorImplThreadTaskRunner().get(); - bool synchronous_composite = !task_runner; - if (!task_runner) - task_runner = base::ThreadTaskRunnerHandle::Get().get(); - - viz::RendererSettings renderer_settings; - base::CommandLine* cmd = base::CommandLine::ForCurrentProcess(); - renderer_settings.allow_antialiasing &= - !cmd->HasSwitch(cc::switches::kDisableCompositedAntialiasing); - renderer_settings.highp_threshold_min = 2048; - // Keep texture sizes exactly matching the bounds of the RenderPass to avoid - // floating point badness in texcoords. - renderer_settings.dont_round_texture_sizes_for_pixel_tests = true; - renderer_settings.use_skia_renderer = features::IsUsingSkiaRenderer(); - - constexpr bool disable_display_vsync = false; - constexpr double refresh_rate = 60.0; - auto layer_tree_frame_sink = std::make_unique<viz::TestLayerTreeFrameSink>( - std::move(compositor_context_provider), - std::move(worker_context_provider), gpu_memory_buffer_manager, - renderer_settings, task_runner, synchronous_composite, - disable_display_vsync, refresh_rate); - layer_tree_frame_sink->SetClient(this); - layer_tree_frame_sinks_[routing_id] = layer_tree_frame_sink.get(); - return std::move(layer_tree_frame_sink); - } - - std::unique_ptr<cc::SwapPromise> RequestCopyOfOutput( - int32_t routing_id, - std::unique_ptr<viz::CopyOutputRequest> request) override { - // Note that we can't immediately check layer_tree_frame_sinks_, since it - // may not have been created yet. Instead, we wait until OnCommit to find - // the currently active LayerTreeFrameSink for the given RenderWidget - // routing_id. - return std::make_unique<CopyRequestSwapPromise>( - std::move(request), - base::Bind( - &LayoutTestDependenciesImpl::FindLayerTreeFrameSink, - // |this| will still be valid, because its lifetime is tied to - // RenderThreadImpl, which outlives layout test execution. - base::Unretained(this), routing_id)); - } - - // TestLayerTreeFrameSinkClient implementation. - std::unique_ptr<viz::OutputSurface> CreateDisplayOutputSurface( - scoped_refptr<viz::ContextProvider> compositor_context_provider) - override { - // This is for an offscreen context for the compositor. So the default - // framebuffer doesn't need alpha, depth, stencil, antialiasing. - gpu::ContextCreationAttribs attributes; - attributes.alpha_size = -1; - attributes.depth_size = 0; - attributes.stencil_size = 0; - attributes.samples = 0; - attributes.sample_buffers = 0; - attributes.bind_generates_resource = false; - attributes.lose_context_when_out_of_memory = true; - const bool automatic_flushes = false; - const bool support_locking = false; - const bool support_grcontext = true; - - scoped_refptr<viz::ContextProvider> context_provider; - - gpu::ContextResult context_result = gpu::ContextResult::kTransientFailure; - while (context_result != gpu::ContextResult::kSuccess) { - context_provider = base::MakeRefCounted<ws::ContextProviderCommandBuffer>( - gpu_channel_, gpu_memory_buffer_manager_, kGpuStreamIdDefault, - kGpuStreamPriorityDefault, gpu::kNullSurfaceHandle, - GURL("chrome://gpu/" - "LayoutTestDependenciesImpl::CreateOutputSurface"), - automatic_flushes, support_locking, support_grcontext, - gpu::SharedMemoryLimits(), attributes, - ws::command_buffer_metrics::ContextType::FOR_TESTING); - context_result = context_provider->BindToCurrentThread(); - - // Layout tests can't recover from a fatal or surface failure. - CHECK(!gpu::IsFatalOrSurfaceFailure(context_result)); - } - - bool flipped_output_surface = false; - return std::make_unique<cc::PixelTestOutputSurface>( - std::move(context_provider), flipped_output_surface); - } - void DisplayReceivedLocalSurfaceId( - const viz::LocalSurfaceId& local_surface_id) override {} - void DisplayReceivedCompositorFrame( - const viz::CompositorFrame& frame) override {} - void DisplayWillDrawAndSwap(bool will_draw_and_swap, - viz::RenderPassList* render_passes) override {} - void DisplayDidDrawAndSwap() override {} - - private: - viz::TestLayerTreeFrameSink* FindLayerTreeFrameSink(int32_t routing_id) { - auto it = layer_tree_frame_sinks_.find(routing_id); - return it == layer_tree_frame_sinks_.end() ? nullptr : it->second; - } - - // Entries are not removed, so this map can grow. However, it is only used in - // layout tests, so this memory usage does not occur in production. - // Entries in this map will outlive the output surface, because this object is - // owned by RenderThreadImpl, which outlives layout test execution. - std::unordered_map<int32_t, viz::TestLayerTreeFrameSink*> - layer_tree_frame_sinks_; - scoped_refptr<gpu::GpuChannelHost> gpu_channel_; - gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_ = nullptr; -}; - -void EnableRendererLayoutTestMode() { - RenderThreadImpl::current()->set_layout_test_dependencies( - std::make_unique<LayoutTestDependenciesImpl>()); - - UniqueNameHelper::PreserveStableUniqueNameForTesting(); - -#if defined(OS_WIN) - RegisterSideloadedTypefaces(SkFontMgr_New_DirectWrite().get()); -#endif -} - -void EnableBrowserLayoutTestMode() { -#if defined(OS_MACOSX) - PopupMenuHelper::DontShowPopupMenuForTesting(); -#endif - RenderWidgetHostImpl::DisableResizeAckCheckForTesting(); -} - -void TerminateAllSharedWorkersForTesting(StoragePartition* storage_partition, - base::OnceClosure callback) { - static_cast<SharedWorkerServiceImpl*>( - storage_partition->GetSharedWorkerService()) - ->TerminateAllWorkersForTesting(std::move(callback)); -} - -int GetLocalSessionHistoryLength(RenderView* render_view) { - return static_cast<RenderViewImpl*>(render_view)-> - GetLocalSessionHistoryLengthForTesting(); -} - -void SetFocusAndActivate(RenderView* render_view, bool enable) { - static_cast<RenderViewImpl*>(render_view)-> - SetFocusAndActivateForTesting(enable); -} - -void ForceResizeRenderView(RenderView* render_view, - const WebSize& new_size) { - auto* render_view_impl = static_cast<RenderViewImpl*>(render_view); - gfx::Rect window_rect(render_view_impl->RootWindowRect().x, - render_view_impl->RootWindowRect().y, new_size.width, - new_size.height); - RenderWidget* render_widget = render_view_impl->GetWidget(); - render_widget->SetWindowRectSynchronouslyForTesting(window_rect); -} - -void SetDeviceScaleFactor(RenderView* render_view, float factor) { - RenderWidget* render_widget = - static_cast<RenderViewImpl*>(render_view)->GetWidget(); - render_widget->SetDeviceScaleFactorForTesting(factor); -} - -float GetWindowToViewportScale(RenderView* render_view) { - return GetWindowToViewportScale( - static_cast<RenderViewImpl*>(render_view)->GetWidget()); -} - -std::unique_ptr<blink::WebInputEvent> TransformScreenToWidgetCoordinates( - test_runner::WebWidgetTestProxyBase* web_widget_test_proxy_base, - const blink::WebInputEvent& event) { - DCHECK(web_widget_test_proxy_base); - RenderWidget* render_widget = GetRenderWidget(web_widget_test_proxy_base); - - blink::WebRect view_rect = render_widget->ViewRect(); - float scale = GetWindowToViewportScale(render_widget); - gfx::Vector2d delta(-view_rect.x, -view_rect.y); - return ui::TranslateAndScaleWebInputEvent(event, delta, scale); -} - -gfx::ColorSpace GetTestingColorSpace(const std::string& name) { - if (name == "genericRGB") { - return gfx::ICCProfileForTestingGenericRGB().GetColorSpace(); - } else if (name == "sRGB") { - return gfx::ColorSpace::CreateSRGB(); - } else if (name == "test" || name == "colorSpin") { - return gfx::ICCProfileForTestingColorSpin().GetColorSpace(); - } else if (name == "adobeRGB") { - return gfx::ICCProfileForTestingAdobeRGB().GetColorSpace(); - } else if (name == "reset") { - return display::Display::GetForcedDisplayColorProfile(); - } - return gfx::ColorSpace(); -} - -void SetDeviceColorSpace(RenderView* render_view, - const gfx::ColorSpace& color_space) { - RenderWidget* render_widget = - static_cast<RenderViewImpl*>(render_view)->GetWidget(); - render_widget->SetDeviceColorSpaceForTesting(color_space); -} - -void SetTestBluetoothScanDuration(BluetoothTestScanDurationSetting setting) { - switch (setting) { - case BluetoothTestScanDurationSetting::kImmediateTimeout: - BluetoothDeviceChooserController::SetTestScanDurationForTesting( - BluetoothDeviceChooserController::TestScanDurationSetting:: - IMMEDIATE_TIMEOUT); - break; - case BluetoothTestScanDurationSetting::kNeverTimeout: - BluetoothDeviceChooserController::SetTestScanDurationForTesting( - BluetoothDeviceChooserController::TestScanDurationSetting:: - NEVER_TIMEOUT); - break; - } -} - -void UseSynchronousResizeMode(RenderView* render_view, bool enable) { - RenderWidget* render_widget = - static_cast<RenderViewImpl*>(render_view)->GetWidget(); - render_widget->UseSynchronousResizeModeForTesting(enable); -} - -void EnableAutoResizeMode(RenderView* render_view, - const WebSize& min_size, - const WebSize& max_size) { - RenderWidget* render_widget = - static_cast<RenderViewImpl*>(render_view)->GetWidget(); - render_widget->EnableAutoResizeForTesting(min_size, max_size); -} - -void DisableAutoResizeMode(RenderView* render_view, const WebSize& new_size) { - RenderWidget* render_widget = - static_cast<RenderViewImpl*>(render_view)->GetWidget(); - render_widget->DisableAutoResizeForTesting(new_size); -} - -void SchedulerRunIdleTasks(base::OnceClosure callback) { - blink::scheduler::WebThreadScheduler* scheduler = - content::RenderThreadImpl::current()->GetWebMainThreadScheduler(); - blink::scheduler::RunIdleTasksForTesting(scheduler, std::move(callback)); -} - -void ForceTextInputStateUpdateForRenderFrame(RenderFrame* frame) { - if (auto* render_widget = - static_cast<RenderFrameImpl*>(frame)->GetRenderWidget()) { - render_widget->ShowVirtualKeyboard(); - } -} - -bool IsNavigationInitiatedByRenderer(const blink::WebURLRequest& request) { - RequestExtraData* extra_data = - static_cast<RequestExtraData*>(request.GetExtraData()); - return extra_data && extra_data->navigation_initiated_by_renderer(); -} - -} // namespace content
diff --git a/content/test/stub_layer_tree_view_delegate.cc b/content/test/stub_layer_tree_view_delegate.cc index 2e9a3f5c9..71753b7 100644 --- a/content/test/stub_layer_tree_view_delegate.cc +++ b/content/test/stub_layer_tree_view_delegate.cc
@@ -18,7 +18,7 @@ } std::unique_ptr<cc::SwapPromise> -StubLayerTreeViewDelegate::RequestCopyOfOutputForLayoutTest( +StubLayerTreeViewDelegate::RequestCopyOfOutputForWebTest( std::unique_ptr<viz::CopyOutputRequest> request) { return nullptr; }
diff --git a/content/test/stub_layer_tree_view_delegate.h b/content/test/stub_layer_tree_view_delegate.h index 995bcb1d..76653d3 100644 --- a/content/test/stub_layer_tree_view_delegate.h +++ b/content/test/stub_layer_tree_view_delegate.h
@@ -29,7 +29,7 @@ void RequestScheduleAnimation() override {} void UpdateVisualState(bool record_main_frame_metrics) override {} void WillBeginCompositorFrame() override {} - std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForLayoutTest( + std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForWebTest( std::unique_ptr<viz::CopyOutputRequest> request) override; };
diff --git a/content/test/test_blink_web_unit_test_support.cc b/content/test/test_blink_web_unit_test_support.cc index 703f236e..651a591 100644 --- a/content/test/test_blink_web_unit_test_support.cc +++ b/content/test/test_blink_web_unit_test_support.cc
@@ -177,7 +177,7 @@ service_manager::BinderRegistry empty_registry; blink::Initialize(this, &empty_registry, main_thread_scheduler_.get()); g_test_platform = this; - blink::SetLayoutTestMode(true); + blink::SetWebTestMode(true); blink::WebRuntimeFeatures::EnableDatabase(true); blink::WebRuntimeFeatures::EnableNotifications(true); blink::WebRuntimeFeatures::EnableTouchEventFeatureDetection(true);
diff --git a/content/test/test_render_view_host.h b/content/test/test_render_view_host.h index 177cb784..d66ebb9 100644 --- a/content/test/test_render_view_host.h +++ b/content/test/test_render_view_host.h
@@ -103,7 +103,7 @@ void SetNeedsBeginFrames(bool needs_begin_frames) override {} void SetWantsAnimateOnlyBeginFrames() override {} void TakeFallbackContentFrom(RenderWidgetHostView* view) override; - void EnsureSurfaceSynchronizedForLayoutTest() override {} + void EnsureSurfaceSynchronizedForWebTest() override {} // RenderWidgetHostViewBase: void InitAsPopup(RenderWidgetHostView* parent_host_view,
diff --git a/content/test/test_runner_support.cc b/content/test/test_runner_support.cc index 4ceda09..2aee6b56 100644 --- a/content/test/test_runner_support.cc +++ b/content/test/test_runner_support.cc
@@ -10,7 +10,7 @@ namespace content { -std::string GetFrameNameForLayoutTests(blink::WebLocalFrame* frame) { +std::string GetFrameNameForWebTests(blink::WebLocalFrame* frame) { std::string unique_name = RenderFrameImpl::FromWebFrame(frame)->unique_name(); return UniqueNameHelper::ExtractStableNameForTesting(unique_name); }
diff --git a/content/test/web_test_support.cc b/content/test/web_test_support.cc new file mode 100644 index 0000000..d3f1096 --- /dev/null +++ b/content/test/web_test_support.cc
@@ -0,0 +1,567 @@ +// Copyright (c) 2012 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/public/test/web_test_support.h" + +#include <stddef.h> + +#include <algorithm> +#include <unordered_map> +#include <utility> +#include <vector> + +#include "base/callback.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "build/build_config.h" +#include "cc/base/switches.h" +#include "cc/test/pixel_test_output_surface.h" +#include "components/viz/common/features.h" +#include "components/viz/common/frame_sinks/copy_output_request.h" +#include "components/viz/test/test_layer_tree_frame_sink.h" +#include "content/browser/bluetooth/bluetooth_device_chooser_controller.h" +#include "content/browser/renderer_host/render_process_host_impl.h" +#include "content/browser/renderer_host/render_widget_host_impl.h" +#include "content/browser/worker_host/shared_worker_service_impl.h" +#include "content/common/renderer.mojom.h" +#include "content/common/unique_name_helper.h" +#include "content/public/browser/storage_partition.h" +#include "content/public/common/gpu_stream_constants.h" +#include "content/public/common/page_state.h" +#include "content/public/common/screen_info.h" +#include "content/renderer/gpu/layer_tree_view.h" +#include "content/renderer/input/render_widget_input_handler_delegate.h" +#include "content/renderer/loader/request_extra_data.h" +#include "content/renderer/loader/web_worker_fetch_context_impl.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 "content/renderer/renderer_blink_platform_impl.h" +#include "content/renderer/web_test_dependencies.h" +#include "content/shell/common/shell_switches.h" +#include "content/shell/common/web_test/web_test_switches.h" +#include "content/shell/renderer/web_test/blink_test_runner.h" +#include "content/shell/renderer/web_test/web_test_render_thread_observer.h" +#include "content/shell/test_runner/test_common.h" +#include "content/shell/test_runner/web_frame_test_proxy.h" +#include "content/shell/test_runner/web_test_interfaces.h" +#include "content/shell/test_runner/web_view_test_proxy.h" +#include "content/shell/test_runner/web_widget_test_proxy.h" +#include "gpu/ipc/service/image_transport_surface.h" +#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h" +#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" +#include "third_party/blink/public/platform/web_float_rect.h" +#include "third_party/blink/public/platform/web_input_event.h" +#include "third_party/blink/public/platform/web_rect.h" +#include "third_party/blink/public/web/web_view.h" +#include "ui/base/ui_base_switches.h" +#include "ui/events/blink/blink_event_util.h" +#include "ui/gfx/geometry/vector2d.h" +#include "ui/gfx/icc_profile.h" +#include "ui/gfx/test/icc_profiles.h" + +#if defined(OS_MACOSX) +#include "content/browser/frame_host/popup_menu_helper_mac.h" +#elif defined(OS_WIN) +#include "content/child/font_warmup_win.h" +#include "third_party/blink/public/web/win/web_font_rendering.h" +#include "third_party/skia/include/core/SkFontMgr.h" +#include "third_party/skia/include/core/SkRefCnt.h" +#include "third_party/skia/include/ports/SkTypeface_win.h" +#include "ui/gfx/win/direct_write.h" +#endif + +using blink::WebRect; +using blink::WebSize; + +namespace content { + +namespace { + +RenderViewImpl* CreateWebViewTestProxy(CompositorDependencies* compositor_deps, + const mojom::CreateViewParams& params) { + test_runner::WebTestInterfaces* interfaces = + WebTestRenderThreadObserver::GetInstance()->test_interfaces(); + + auto* render_view_proxy = + new test_runner::WebViewTestProxy(compositor_deps, params); + + BlinkTestRunner* test_runner = new BlinkTestRunner(render_view_proxy); + // TODO(lukasza): Using the 1st BlinkTestRunner as the main delegate is wrong, + // but it is difficult to change because this behavior has been baked for a + // long time into test assumptions (i.e. which PrintMessage gets delivered to + // the browser depends on this). + static bool first_test_runner = true; + if (first_test_runner) { + first_test_runner = false; + interfaces->SetDelegate(test_runner); + } + + render_view_proxy->Initialize(interfaces, test_runner); + return render_view_proxy; +} + +RenderWidget* CreateWebWidgetTestProxy(int32_t routing_id, + CompositorDependencies* compositor_deps, + WidgetType popup_type, + const ScreenInfo& screen_info, + blink::WebDisplayMode display_mode, + bool swapped_out, + bool hidden, + bool never_visible) { + auto* render_widget_proxy = new test_runner::WebWidgetTestProxy( + routing_id, compositor_deps, popup_type, screen_info, display_mode, + swapped_out, hidden, never_visible); + return render_widget_proxy; +} + +void RenderWidgetInitialized(RenderWidget* render_widget) { + test_runner::WebTestInterfaces* interfaces = + WebTestRenderThreadObserver::GetInstance()->test_interfaces(); + + blink::WebWidget* web_widget = render_widget->GetWebWidget(); + // This callback is run only for RenderWidgets that are for a frame. + CHECK(web_widget->IsWebFrameWidget()); + auto* web_frame_widget = static_cast<blink::WebFrameWidget*>(web_widget); + // RenderWidgets for a frame will have a local root with a RenderView. + blink::WebView* web_view = web_frame_widget->LocalRoot()->View(); + RenderView* render_view = content::RenderView::FromWebView(web_view); + // RenderViews are always RenderViewImpls internally. + auto* render_view_impl = static_cast<RenderViewImpl*>(render_view); + + // We are here because CreateWebWidgetTestProxy() was used to make the + // RenderWidget, and it creates a WebWidgetTestProxy instead, which is-a + // RenderWidget. + auto* render_widget_proxy = + static_cast<test_runner::WebWidgetTestProxy*>(render_widget); + render_widget_proxy->Initialize(interfaces, web_widget, render_view_impl); +} + +RenderFrameImpl* CreateWebFrameTestProxy(RenderFrameImpl::CreateParams params) { + test_runner::WebTestInterfaces* interfaces = + WebTestRenderThreadObserver::GetInstance()->test_interfaces(); + + // RenderFrameImpl always has a RenderViewImpl for it. + RenderViewImpl* render_view_impl = params.render_view; + + auto* render_frame_proxy = + new test_runner::WebFrameTestProxy(std::move(params)); + render_frame_proxy->Initialize(interfaces, render_view_impl); + return render_frame_proxy; +} + +float GetWindowToViewportScale(RenderWidget* render_widget) { + blink::WebFloatRect rect(0, 0, 1.0f, 0.0); + render_widget->ConvertWindowToViewport(&rect); + return rect.width; +} + +#if defined(OS_WIN) +// DirectWrite only has access to %WINDIR%\Fonts by default. For developer +// side-loading, support kRegisterFontFiles to allow access to additional fonts. +void RegisterSideloadedTypefaces(SkFontMgr* fontmgr) { + for (const auto& file : switches::GetSideloadFontFiles()) { + blink::WebFontRendering::AddSideloadedFontForTesting( + fontmgr->makeFromFile(file.c_str())); + } +} +#endif // OS_WIN + +} // namespace + +test_runner::WebViewTestProxyBase* GetWebViewTestProxyBase( + RenderView* render_view) { + auto* render_view_proxy = + static_cast<test_runner::WebViewTestProxy*>(render_view); + return static_cast<test_runner::WebViewTestProxyBase*>(render_view_proxy); +} + +test_runner::WebFrameTestProxyBase* GetWebFrameTestProxyBase( + RenderFrame* render_frame) { + auto* render_frame_proxy = + static_cast<test_runner::WebFrameTestProxy*>(render_frame); + return static_cast<test_runner::WebFrameTestProxyBase*>(render_frame_proxy); +} + +test_runner::WebWidgetTestProxyBase* GetWebWidgetTestProxyBase( + blink::WebLocalFrame* frame) { + DCHECK(frame); + RenderFrame* local_root = RenderFrame::FromWebFrame(frame->LocalRoot()); + DCHECK(local_root); + // TODO(lfg): Simplify once RenderView no longer inherits from RenderWidget. + if (local_root->IsMainFrame()) { + test_runner::WebViewTestProxyBase* web_view_test_proxy_base = + GetWebViewTestProxyBase(local_root->GetRenderView()); + test_runner::WebWidgetTestProxyBase* web_widget_test_proxy_base = + web_view_test_proxy_base->web_widget_test_proxy_base(); + DCHECK(web_widget_test_proxy_base->web_widget()->IsWebView()); + return web_widget_test_proxy_base; + } else { + RenderWidget* render_widget = + static_cast<RenderFrameImpl*>(local_root)->GetRenderWidget(); + DCHECK(render_widget); + auto* render_widget_proxy = + static_cast<test_runner::WebWidgetTestProxy*>(render_widget); + auto* web_widget_test_proxy_base = + static_cast<test_runner::WebWidgetTestProxyBase*>(render_widget_proxy); + DCHECK(web_widget_test_proxy_base->web_widget()->IsWebFrameWidget()); + return web_widget_test_proxy_base; + } +} + +RenderWidget* GetRenderWidget( + test_runner::WebWidgetTestProxyBase* web_widget_test_proxy_base) { + DCHECK(web_widget_test_proxy_base); + + blink::WebWidget* widget = web_widget_test_proxy_base->web_widget(); + // TODO(lfg): Simplify once RenderView no longer inherits from RenderWidget. + if (widget->IsWebView()) { + test_runner::WebViewTestProxyBase* render_view_proxy_base = + web_widget_test_proxy_base->web_view_test_proxy_base(); + auto* render_view_proxy = + static_cast<test_runner::WebViewTestProxy*>(render_view_proxy_base); + RenderViewImpl* render_view_impl = + static_cast<RenderViewImpl*>(render_view_proxy); + return render_view_impl->GetWidget(); + } else if (widget->IsWebFrameWidget()) { + auto* render_widget_proxy = static_cast<test_runner::WebWidgetTestProxy*>( + web_widget_test_proxy_base); + return static_cast<RenderWidget*>(render_widget_proxy); + } else { + NOTREACHED(); + return nullptr; + } +} + +void EnableWebTestProxyCreation() { + RenderViewImpl::InstallCreateHook(CreateWebViewTestProxy); + RenderFrameImpl::InstallCreateHook(CreateWebFrameTestProxy, + CreateWebWidgetTestProxy, + RenderWidgetInitialized); +} + +void FetchManifest(blink::WebView* view, FetchManifestCallback callback) { + RenderFrameImpl::FromWebFrame(view->MainFrame()) + ->GetManifestManager() + .RequestManifest(std::move(callback)); +} + +void SetWorkerRewriteURLFunction(RewriteURLFunction rewrite_url_function) { + WebWorkerFetchContextImpl::InstallRewriteURLFunction(rewrite_url_function); +} + +namespace { + +// Invokes a callback on commit (on the main thread) to obtain the output +// surface that should be used, then asks that output surface to submit the copy +// request at SwapBuffers time. +class CopyRequestSwapPromise : public cc::SwapPromise { + public: + using FindLayerTreeFrameSinkCallback = + base::Callback<viz::TestLayerTreeFrameSink*()>; + CopyRequestSwapPromise( + std::unique_ptr<viz::CopyOutputRequest> request, + FindLayerTreeFrameSinkCallback find_layer_tree_frame_sink_callback) + : copy_request_(std::move(request)), + find_layer_tree_frame_sink_callback_( + std::move(find_layer_tree_frame_sink_callback)) {} + + // cc::SwapPromise implementation. + void OnCommit() override { + layer_tree_frame_sink_from_commit_ = + find_layer_tree_frame_sink_callback_.Run(); + DCHECK(layer_tree_frame_sink_from_commit_); + } + void DidActivate() override {} + void WillSwap(viz::CompositorFrameMetadata*) override { + layer_tree_frame_sink_from_commit_->RequestCopyOfOutput( + std::move(copy_request_)); + } + void DidSwap() override {} + void DidNotSwap(DidNotSwapReason r) override { + // The compositor should always swap in web test mode. + NOTREACHED() << "did not swap for reason " << r; + } + int64_t TraceId() const override { return 0; } + + private: + std::unique_ptr<viz::CopyOutputRequest> copy_request_; + FindLayerTreeFrameSinkCallback find_layer_tree_frame_sink_callback_; + viz::TestLayerTreeFrameSink* layer_tree_frame_sink_from_commit_ = nullptr; +}; + +} // namespace + +class WebTestDependenciesImpl : public WebTestDependencies, + public viz::TestLayerTreeFrameSinkClient { + public: + bool UseDisplayCompositorPixelDump() const override { + base::CommandLine* cmd = base::CommandLine::ForCurrentProcess(); + return cmd->HasSwitch(switches::kEnableDisplayCompositorPixelDump); + } + + std::unique_ptr<cc::LayerTreeFrameSink> CreateLayerTreeFrameSink( + int32_t routing_id, + scoped_refptr<gpu::GpuChannelHost> gpu_channel, + scoped_refptr<viz::ContextProvider> compositor_context_provider, + scoped_refptr<viz::RasterContextProvider> worker_context_provider, + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, + CompositorDependencies* deps) override { + // This could override the GpuChannel for a LayerTreeFrameSink that was + // previously being created but in that case the old GpuChannel would be + // lost as would the LayerTreeFrameSink. + gpu_channel_ = gpu_channel; + gpu_memory_buffer_manager_ = gpu_memory_buffer_manager; + + auto* task_runner = deps->GetCompositorImplThreadTaskRunner().get(); + bool synchronous_composite = !task_runner; + if (!task_runner) + task_runner = base::ThreadTaskRunnerHandle::Get().get(); + + viz::RendererSettings renderer_settings; + base::CommandLine* cmd = base::CommandLine::ForCurrentProcess(); + renderer_settings.allow_antialiasing &= + !cmd->HasSwitch(cc::switches::kDisableCompositedAntialiasing); + renderer_settings.highp_threshold_min = 2048; + // Keep texture sizes exactly matching the bounds of the RenderPass to avoid + // floating point badness in texcoords. + renderer_settings.dont_round_texture_sizes_for_pixel_tests = true; + renderer_settings.use_skia_renderer = features::IsUsingSkiaRenderer(); + + constexpr bool disable_display_vsync = false; + constexpr double refresh_rate = 60.0; + auto layer_tree_frame_sink = std::make_unique<viz::TestLayerTreeFrameSink>( + std::move(compositor_context_provider), + std::move(worker_context_provider), gpu_memory_buffer_manager, + renderer_settings, task_runner, synchronous_composite, + disable_display_vsync, refresh_rate); + layer_tree_frame_sink->SetClient(this); + layer_tree_frame_sinks_[routing_id] = layer_tree_frame_sink.get(); + return std::move(layer_tree_frame_sink); + } + + std::unique_ptr<cc::SwapPromise> RequestCopyOfOutput( + int32_t routing_id, + std::unique_ptr<viz::CopyOutputRequest> request) override { + // Note that we can't immediately check layer_tree_frame_sinks_, since it + // may not have been created yet. Instead, we wait until OnCommit to find + // the currently active LayerTreeFrameSink for the given RenderWidget + // routing_id. + return std::make_unique<CopyRequestSwapPromise>( + std::move(request), + base::Bind(&WebTestDependenciesImpl::FindLayerTreeFrameSink, + // |this| will still be valid, because its lifetime is tied + // to RenderThreadImpl, which outlives web test execution. + base::Unretained(this), routing_id)); + } + + // TestLayerTreeFrameSinkClient implementation. + std::unique_ptr<viz::OutputSurface> CreateDisplayOutputSurface( + scoped_refptr<viz::ContextProvider> compositor_context_provider) + override { + // This is for an offscreen context for the compositor. So the default + // framebuffer doesn't need alpha, depth, stencil, antialiasing. + gpu::ContextCreationAttribs attributes; + attributes.alpha_size = -1; + attributes.depth_size = 0; + attributes.stencil_size = 0; + attributes.samples = 0; + attributes.sample_buffers = 0; + attributes.bind_generates_resource = false; + attributes.lose_context_when_out_of_memory = true; + const bool automatic_flushes = false; + const bool support_locking = false; + const bool support_grcontext = true; + + scoped_refptr<viz::ContextProvider> context_provider; + + gpu::ContextResult context_result = gpu::ContextResult::kTransientFailure; + while (context_result != gpu::ContextResult::kSuccess) { + context_provider = base::MakeRefCounted<ws::ContextProviderCommandBuffer>( + gpu_channel_, gpu_memory_buffer_manager_, kGpuStreamIdDefault, + kGpuStreamPriorityDefault, gpu::kNullSurfaceHandle, + GURL("chrome://gpu/" + "WebTestDependenciesImpl::CreateOutputSurface"), + automatic_flushes, support_locking, support_grcontext, + gpu::SharedMemoryLimits(), attributes, + ws::command_buffer_metrics::ContextType::FOR_TESTING); + context_result = context_provider->BindToCurrentThread(); + + // Web tests can't recover from a fatal or surface failure. + CHECK(!gpu::IsFatalOrSurfaceFailure(context_result)); + } + + bool flipped_output_surface = false; + return std::make_unique<cc::PixelTestOutputSurface>( + std::move(context_provider), flipped_output_surface); + } + void DisplayReceivedLocalSurfaceId( + const viz::LocalSurfaceId& local_surface_id) override {} + void DisplayReceivedCompositorFrame( + const viz::CompositorFrame& frame) override {} + void DisplayWillDrawAndSwap(bool will_draw_and_swap, + viz::RenderPassList* render_passes) override {} + void DisplayDidDrawAndSwap() override {} + + private: + viz::TestLayerTreeFrameSink* FindLayerTreeFrameSink(int32_t routing_id) { + auto it = layer_tree_frame_sinks_.find(routing_id); + return it == layer_tree_frame_sinks_.end() ? nullptr : it->second; + } + + // Entries are not removed, so this map can grow. However, it is only used in + // web tests, so this memory usage does not occur in production. + // Entries in this map will outlive the output surface, because this object is + // owned by RenderThreadImpl, which outlives web test execution. + std::unordered_map<int32_t, viz::TestLayerTreeFrameSink*> + layer_tree_frame_sinks_; + scoped_refptr<gpu::GpuChannelHost> gpu_channel_; + gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_ = nullptr; +}; + +void EnableRendererWebTestMode() { + RenderThreadImpl::current()->set_web_test_dependencies( + std::make_unique<WebTestDependenciesImpl>()); + + UniqueNameHelper::PreserveStableUniqueNameForTesting(); + +#if defined(OS_WIN) + RegisterSideloadedTypefaces(SkFontMgr_New_DirectWrite().get()); +#endif +} + +void EnableBrowserWebTestMode() { +#if defined(OS_MACOSX) + PopupMenuHelper::DontShowPopupMenuForTesting(); +#endif + RenderWidgetHostImpl::DisableResizeAckCheckForTesting(); +} + +void TerminateAllSharedWorkersForTesting(StoragePartition* storage_partition, + base::OnceClosure callback) { + static_cast<SharedWorkerServiceImpl*>( + storage_partition->GetSharedWorkerService()) + ->TerminateAllWorkersForTesting(std::move(callback)); +} + +int GetLocalSessionHistoryLength(RenderView* render_view) { + return static_cast<RenderViewImpl*>(render_view) + ->GetLocalSessionHistoryLengthForTesting(); +} + +void SetFocusAndActivate(RenderView* render_view, bool enable) { + static_cast<RenderViewImpl*>(render_view) + ->SetFocusAndActivateForTesting(enable); +} + +void ForceResizeRenderView(RenderView* render_view, const WebSize& new_size) { + auto* render_view_impl = static_cast<RenderViewImpl*>(render_view); + gfx::Rect window_rect(render_view_impl->RootWindowRect().x, + render_view_impl->RootWindowRect().y, new_size.width, + new_size.height); + RenderWidget* render_widget = render_view_impl->GetWidget(); + render_widget->SetWindowRectSynchronouslyForTesting(window_rect); +} + +void SetDeviceScaleFactor(RenderView* render_view, float factor) { + RenderWidget* render_widget = + static_cast<RenderViewImpl*>(render_view)->GetWidget(); + render_widget->SetDeviceScaleFactorForTesting(factor); +} + +float GetWindowToViewportScale(RenderView* render_view) { + return GetWindowToViewportScale( + static_cast<RenderViewImpl*>(render_view)->GetWidget()); +} + +std::unique_ptr<blink::WebInputEvent> TransformScreenToWidgetCoordinates( + test_runner::WebWidgetTestProxyBase* web_widget_test_proxy_base, + const blink::WebInputEvent& event) { + DCHECK(web_widget_test_proxy_base); + RenderWidget* render_widget = GetRenderWidget(web_widget_test_proxy_base); + + blink::WebRect view_rect = render_widget->ViewRect(); + float scale = GetWindowToViewportScale(render_widget); + gfx::Vector2d delta(-view_rect.x, -view_rect.y); + return ui::TranslateAndScaleWebInputEvent(event, delta, scale); +} + +gfx::ColorSpace GetTestingColorSpace(const std::string& name) { + if (name == "genericRGB") { + return gfx::ICCProfileForTestingGenericRGB().GetColorSpace(); + } else if (name == "sRGB") { + return gfx::ColorSpace::CreateSRGB(); + } else if (name == "test" || name == "colorSpin") { + return gfx::ICCProfileForTestingColorSpin().GetColorSpace(); + } else if (name == "adobeRGB") { + return gfx::ICCProfileForTestingAdobeRGB().GetColorSpace(); + } else if (name == "reset") { + return display::Display::GetForcedDisplayColorProfile(); + } + return gfx::ColorSpace(); +} + +void SetDeviceColorSpace(RenderView* render_view, + const gfx::ColorSpace& color_space) { + RenderWidget* render_widget = + static_cast<RenderViewImpl*>(render_view)->GetWidget(); + render_widget->SetDeviceColorSpaceForTesting(color_space); +} + +void SetTestBluetoothScanDuration(BluetoothTestScanDurationSetting setting) { + switch (setting) { + case BluetoothTestScanDurationSetting::kImmediateTimeout: + BluetoothDeviceChooserController::SetTestScanDurationForTesting( + BluetoothDeviceChooserController::TestScanDurationSetting:: + IMMEDIATE_TIMEOUT); + break; + case BluetoothTestScanDurationSetting::kNeverTimeout: + BluetoothDeviceChooserController::SetTestScanDurationForTesting( + BluetoothDeviceChooserController::TestScanDurationSetting:: + NEVER_TIMEOUT); + break; + } +} + +void UseSynchronousResizeMode(RenderView* render_view, bool enable) { + RenderWidget* render_widget = + static_cast<RenderViewImpl*>(render_view)->GetWidget(); + render_widget->UseSynchronousResizeModeForTesting(enable); +} + +void EnableAutoResizeMode(RenderView* render_view, + const WebSize& min_size, + const WebSize& max_size) { + RenderWidget* render_widget = + static_cast<RenderViewImpl*>(render_view)->GetWidget(); + render_widget->EnableAutoResizeForTesting(min_size, max_size); +} + +void DisableAutoResizeMode(RenderView* render_view, const WebSize& new_size) { + RenderWidget* render_widget = + static_cast<RenderViewImpl*>(render_view)->GetWidget(); + render_widget->DisableAutoResizeForTesting(new_size); +} + +void SchedulerRunIdleTasks(base::OnceClosure callback) { + blink::scheduler::WebThreadScheduler* scheduler = + content::RenderThreadImpl::current()->GetWebMainThreadScheduler(); + blink::scheduler::RunIdleTasksForTesting(scheduler, std::move(callback)); +} + +void ForceTextInputStateUpdateForRenderFrame(RenderFrame* frame) { + if (auto* render_widget = + static_cast<RenderFrameImpl*>(frame)->GetRenderWidget()) { + render_widget->ShowVirtualKeyboard(); + } +} + +bool IsNavigationInitiatedByRenderer(const blink::WebURLRequest& request) { + RequestExtraData* extra_data = + static_cast<RequestExtraData*>(request.GetExtraData()); + return extra_data && extra_data->navigation_initiated_by_renderer(); +} + +} // namespace content
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.cc index b18b7d5c..c9f0f4d 100644 --- a/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.cc +++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.cc
@@ -25,6 +25,7 @@ namespace { +using ABI::Windows::Devices::Bluetooth::BluetoothCacheMode_Uncached; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: GattCharacteristicProperties; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: @@ -41,10 +42,10 @@ GattCommunicationStatus_Success; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::GattReadResult; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: - GattWriteOption_WriteWithResponse; -using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: GattWriteOption_WriteWithoutResponse; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + GattWriteOption_WriteWithResponse; +using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: GattWriteResult; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: IGattCharacteristic; @@ -163,9 +164,10 @@ } ComPtr<IAsyncOperation<GattReadResult*>> read_value_op; - HRESULT hr = characteristic_->ReadValueAsync(&read_value_op); + HRESULT hr = characteristic_->ReadValueWithCacheModeAsync( + BluetoothCacheMode_Uncached, &read_value_op); if (FAILED(hr)) { - VLOG(2) << "GattCharacteristic::ReadValueAsync failed: " + VLOG(2) << "GattCharacteristic::ReadValueWithCacheModeAsync failed: " << logging::SystemErrorCodeToString(hr); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE,
diff --git a/device/bluetooth/bluetooth_remote_gatt_descriptor_winrt.cc b/device/bluetooth/bluetooth_remote_gatt_descriptor_winrt.cc index 3c7b806f..e70433a 100644 --- a/device/bluetooth/bluetooth_remote_gatt_descriptor_winrt.cc +++ b/device/bluetooth/bluetooth_remote_gatt_descriptor_winrt.cc
@@ -18,6 +18,7 @@ namespace { +using ABI::Windows::Devices::Bluetooth::BluetoothCacheMode_Uncached; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: GattCommunicationStatus; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: @@ -26,14 +27,14 @@ using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: GattWriteResult; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: - IGattDescriptor2; -using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: IGattDescriptor; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: - IGattReadResult2; + IGattDescriptor2; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: IGattReadResult; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: + IGattReadResult2; +using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: IGattWriteResult; using ABI::Windows::Foundation::IAsyncOperation; using ABI::Windows::Storage::Streams::IBuffer; @@ -106,9 +107,10 @@ } ComPtr<IAsyncOperation<GattReadResult*>> read_value_op; - HRESULT hr = descriptor_->ReadValueAsync(&read_value_op); + HRESULT hr = descriptor_->ReadValueWithCacheModeAsync( + BluetoothCacheMode_Uncached, &read_value_op); if (FAILED(hr)) { - VLOG(2) << "GattDescriptor::ReadValueAsync failed: " + VLOG(2) << "GattDescriptor::ReadValueWithCacheModeAsync failed: " << logging::SystemErrorCodeToString(hr); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE,
diff --git a/device/bluetooth/test/fake_gatt_characteristic_winrt.cc b/device/bluetooth/test/fake_gatt_characteristic_winrt.cc index 75a7faf..1c726b2 100644 --- a/device/bluetooth/test/fake_gatt_characteristic_winrt.cc +++ b/device/bluetooth/test/fake_gatt_characteristic_winrt.cc
@@ -24,8 +24,7 @@ namespace { using ABI::Windows::Devices::Bluetooth::BluetoothCacheMode; -using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: - GattCharacteristic; +using ABI::Windows::Devices::Bluetooth::BluetoothCacheMode_Uncached; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: GattCharacteristic; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: @@ -56,9 +55,9 @@ GattWriteResult; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: IGattReadResult; -using ABI::Windows::Foundation::Collections::IVectorView; using ABI::Windows::Foundation::IAsyncOperation; using ABI::Windows::Foundation::ITypedEventHandler; +using ABI::Windows::Foundation::Collections::IVectorView; using ABI::Windows::Storage::Streams::IBuffer; using Microsoft::WRL::Make; @@ -120,6 +119,15 @@ HRESULT FakeGattCharacteristicWinrt::ReadValueAsync( IAsyncOperation<GattReadResult*>** value) { + return E_NOTIMPL; +} + +HRESULT FakeGattCharacteristicWinrt::ReadValueWithCacheModeAsync( + BluetoothCacheMode cache_mode, + IAsyncOperation<GattReadResult*>** value) { + if (cache_mode != BluetoothCacheMode_Uncached) + return E_NOTIMPL; + auto async_op = Make<base::win::AsyncOperation<GattReadResult*>>(); DCHECK(!read_value_callback_); read_value_callback_ = async_op->callback(); @@ -128,12 +136,6 @@ return S_OK; } -HRESULT FakeGattCharacteristicWinrt::ReadValueWithCacheModeAsync( - BluetoothCacheMode cache_mode, - IAsyncOperation<GattReadResult*>** value) { - return E_NOTIMPL; -} - HRESULT FakeGattCharacteristicWinrt::WriteValueAsync( IBuffer* value, IAsyncOperation<GattCommunicationStatus>** async_op) {
diff --git a/device/bluetooth/test/fake_gatt_descriptor_winrt.cc b/device/bluetooth/test/fake_gatt_descriptor_winrt.cc index b4a06a9..fb8da37 100644 --- a/device/bluetooth/test/fake_gatt_descriptor_winrt.cc +++ b/device/bluetooth/test/fake_gatt_descriptor_winrt.cc
@@ -19,6 +19,7 @@ namespace { using ABI::Windows::Devices::Bluetooth::BluetoothCacheMode; +using ABI::Windows::Devices::Bluetooth::BluetoothCacheMode_Uncached; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: GattCommunicationStatus; using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: @@ -64,6 +65,15 @@ HRESULT FakeGattDescriptorWinrt::ReadValueAsync( IAsyncOperation<GattReadResult*>** value) { + return E_NOTIMPL; +} + +HRESULT FakeGattDescriptorWinrt::ReadValueWithCacheModeAsync( + BluetoothCacheMode cache_mode, + IAsyncOperation<GattReadResult*>** value) { + if (cache_mode != BluetoothCacheMode_Uncached) + return E_NOTIMPL; + auto async_op = Make<base::win::AsyncOperation<GattReadResult*>>(); DCHECK(!read_value_callback_); read_value_callback_ = async_op->callback(); @@ -72,12 +82,6 @@ return S_OK; } -HRESULT FakeGattDescriptorWinrt::ReadValueWithCacheModeAsync( - BluetoothCacheMode cache_mode, - IAsyncOperation<GattReadResult*>** value) { - return E_NOTIMPL; -} - HRESULT FakeGattDescriptorWinrt::WriteValueAsync( IBuffer* value, IAsyncOperation<GattCommunicationStatus>** async_op) {
diff --git a/device/fido/fido_constants.cc b/device/fido/fido_constants.cc index 5a63f4e..91f8e34 100644 --- a/device/fido/fido_constants.cc +++ b/device/fido/fido_constants.cc
@@ -28,21 +28,6 @@ const char kCredentialTypeMapKey[] = "type"; const char kCredentialAlgorithmMapKey[] = "alg"; -const uint32_t kHidBroadcastChannel = 0xffffffff; -const size_t kHidInitPacketHeaderSize = 7; -const size_t kHidContinuationPacketHeaderSize = 5; -const size_t kHidMaxPacketSize = 64; -const uint8_t kHidMaxLockSeconds = 10; -const size_t kHidMaxMessageSize = 7609; - -const size_t kU2fMaxResponseSize = 65536; -const uint8_t kP1TupRequired = 0x01; -const uint8_t kP1TupConsumed = 0x02; -const uint8_t kP1TupRequiredConsumed = kP1TupRequired | kP1TupConsumed; -const uint8_t kP1CheckOnly = 0x07; -const uint8_t kP1IndividualAttestation = 0x80; -const size_t kMaxKeyHandleLength = 255; - const base::TimeDelta kDeviceTimeout = base::TimeDelta::FromSeconds(3); const base::TimeDelta kU2fRetryDelay = base::TimeDelta::FromMilliseconds(200); const base::TimeDelta kHidKeepAliveDelay =
diff --git a/device/fido/fido_constants.h b/device/fido/fido_constants.h index 4ba2a569..a356d1e 100644 --- a/device/fido/fido_constants.h +++ b/device/fido/fido_constants.h
@@ -308,35 +308,34 @@ COMPONENT_EXPORT(DEVICE_FIDO) extern const char kCredentialAlgorithmMapKey[]; // HID transport specific constants. -COMPONENT_EXPORT(DEVICE_FIDO) extern const uint32_t kHidBroadcastChannel; -COMPONENT_EXPORT(DEVICE_FIDO) extern const size_t kHidInitPacketHeaderSize; -COMPONENT_EXPORT(DEVICE_FIDO) -extern const size_t kHidContinuationPacketHeaderSize; -COMPONENT_EXPORT(DEVICE_FIDO) extern const size_t kHidMaxPacketSize; +constexpr uint32_t kHidBroadcastChannel = 0xffffffff; +constexpr size_t kHidInitPacketHeaderSize = 7; +constexpr size_t kHidContinuationPacketHeaderSize = 5; +constexpr size_t kHidMaxPacketSize = 64; -COMPONENT_EXPORT(DEVICE_FIDO) extern const uint8_t kHidMaxLockSeconds; +constexpr uint8_t kHidMaxLockSeconds = 10; // Messages are limited to an initiation packet and 128 continuation packets. -COMPONENT_EXPORT(DEVICE_FIDO) extern const size_t kHidMaxMessageSize; +constexpr size_t kHidMaxMessageSize = 7609; // U2F APDU encoding constants, as specified in // https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html#bib-U2FHeader -COMPONENT_EXPORT(DEVICE_FIDO) extern const size_t kU2fMaxResponseSize; +constexpr size_t kU2fMaxResponseSize = 65536; // P1 instructions. -COMPONENT_EXPORT(DEVICE_FIDO) extern const uint8_t kP1TupRequired; -COMPONENT_EXPORT(DEVICE_FIDO) extern const uint8_t kP1TupConsumed; -COMPONENT_EXPORT(DEVICE_FIDO) extern const uint8_t kP1TupRequiredConsumed; +constexpr uint8_t kP1TupRequired = 0x01; +constexpr uint8_t kP1TupConsumed = 0x02; +constexpr uint8_t kP1TupRequiredConsumed = kP1TupRequired | kP1TupConsumed; // Control byte used for check-only setting. The check-only command is used to // determine if the provided key handle was originally created by this token // and whether it was created for the provided application parameter. -COMPONENT_EXPORT(DEVICE_FIDO) extern const uint8_t kP1CheckOnly; +constexpr uint8_t kP1CheckOnly = 0x07; // Indicates that an individual attestation certificate is acceptable to // return with this registration. -COMPONENT_EXPORT(DEVICE_FIDO) extern const uint8_t kP1IndividualAttestation; -COMPONENT_EXPORT(DEVICE_FIDO) extern const size_t kMaxKeyHandleLength; +constexpr uint8_t kP1IndividualAttestation = 0x80; +constexpr size_t kMaxKeyHandleLength = 255; // Maximum wait time before client error outs on device. COMPONENT_EXPORT(DEVICE_FIDO) extern const base::TimeDelta kDeviceTimeout;
diff --git a/device/fido/hid/fido_hid_discovery.cc b/device/fido/hid/fido_hid_discovery.cc index a114186b5..5c288c9 100644 --- a/device/fido/hid/fido_hid_discovery.cc +++ b/device/fido/hid/fido_hid_discovery.cc
@@ -40,7 +40,9 @@ device::mojom::HidDeviceInfoPtr device_info) { // The init packet header is the larger of the headers so we only compare // against it below. - DCHECK_GE(kHidInitPacketHeaderSize, kHidContinuationPacketHeaderSize); + static_assert( + kHidInitPacketHeaderSize >= kHidContinuationPacketHeaderSize, + "init header is expected to be larger than continuation header"); // Ignore non-U2F devices. if (filter_.Matches(*device_info) &&
diff --git a/device/fido/hid/fido_hid_message.cc b/device/fido/hid/fido_hid_message.cc index ff5cb3c..52aa492 100644 --- a/device/fido/hid/fido_hid_message.cc +++ b/device/fido/hid/fido_hid_message.cc
@@ -139,7 +139,9 @@ size_t max_report_size, base::span<const uint8_t> data) : channel_id_(channel_id) { - DCHECK_GE(kHidInitPacketHeaderSize, kHidContinuationPacketHeaderSize); + static_assert( + kHidInitPacketHeaderSize >= kHidContinuationPacketHeaderSize, + "init header is expected to be larger than continuation header"); DCHECK_GT(max_report_size, kHidInitPacketHeaderSize); const size_t init_packet_data_size =
diff --git a/device/gamepad/BUILD.gn b/device/gamepad/BUILD.gn index 265dbbf..d390612 100644 --- a/device/gamepad/BUILD.gn +++ b/device/gamepad/BUILD.gn
@@ -106,6 +106,10 @@ "//third_party/blink/public:blink_headers", ] + public_deps = [ + "//services/device/public/mojom", + ] + defines = [ "DEVICE_GAMEPAD_IMPLEMENTATION" ] if (is_win) {
diff --git a/device/gamepad/gamepad_id.h b/device/gamepad/gamepad_id.h index e1468ee6..7a5d356 100644 --- a/device/gamepad/gamepad_id.h +++ b/device/gamepad/gamepad_id.h
@@ -521,10 +521,11 @@ kVendorf000Product00f1, kHamaProduct0001, kHamaProduct0005, + kSteelSeriesBtProduct1419, // Add new items here. kMaxValue must be updated to the last item in the // enumeration. - kMaxValue = kHamaProduct0005, + kMaxValue = kSteelSeriesBtProduct1419, }; } // namespace device
diff --git a/device/gamepad/gamepad_id_list.cc b/device/gamepad/gamepad_id_list.cc index 17a52c6..586ba70 100644 --- a/device/gamepad/gamepad_id_list.cc +++ b/device/gamepad/gamepad_id_list.cc
@@ -32,6 +32,7 @@ {0x0079, 0x1844, kXInputTypeNone, GamepadId::kDragonRiseProduct1844}, // Steelseries ApS (Bluetooth) {0x0111, 0x1417, kXInputTypeNone, GamepadId::kSteelSeriesBtProduct1417}, + {0x0111, 0x1419, kXInputTypeNone, GamepadId::kSteelSeriesBtProduct1419}, {0x0111, 0x1420, kXInputTypeNone, GamepadId::kSteelSeriesBtProduct1420}, {0x0113, 0xf900, kXInputTypeNone, GamepadId::kVendor0113Productf900}, // Creative Technology, Ltd @@ -391,7 +392,7 @@ {0x0f30, 0x8888, kXInputTypeXbox, GamepadId::kJessTechnologyProduct8888}, // Etoms Electronics Corp. {0x102c, 0xff0c, kXInputTypeXbox, GamepadId::kEtomsElectronicsProductff0c}, - // SteelSeries ApS + // SteelSeries ApS (USB) {0x1038, 0x1412, kXInputTypeNone, GamepadId::kSteelSeriesProduct1412}, {0x1038, 0x1418, kXInputTypeNone, GamepadId::kSteelSeriesProduct1418}, {0x1038, 0x1420, kXInputTypeNone, GamepadId::kSteelSeriesProduct1420},
diff --git a/device/gamepad/gamepad_service.cc b/device/gamepad/gamepad_service.cc index bb9995a..8282f74dd 100644 --- a/device/gamepad/gamepad_service.cc +++ b/device/gamepad/gamepad_service.cc
@@ -15,6 +15,7 @@ #include "device/gamepad/gamepad_consumer.h" #include "device/gamepad/gamepad_data_fetcher.h" #include "device/gamepad/gamepad_provider.h" +#include "services/service_manager/public/cpp/connector.h" namespace device { @@ -56,6 +57,15 @@ return g_gamepad_service; } +void GamepadService::StartUp( + std::unique_ptr<service_manager::Connector> service_manager_connector) { + service_manager_connector_ = std::move(service_manager_connector); +} + +service_manager::Connector* GamepadService::GetConnector() { + return service_manager_connector_.get(); +} + void GamepadService::ConsumerBecameActive(device::GamepadConsumer* consumer) { DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
diff --git a/device/gamepad/gamepad_service.h b/device/gamepad/gamepad_service.h index 12723ac4b..85feb220 100644 --- a/device/gamepad/gamepad_service.h +++ b/device/gamepad/gamepad_service.h
@@ -26,6 +26,10 @@ class GamepadServiceTestConstructor; } +namespace service_manager { +class Connector; +} + namespace device { class GamepadConsumer; class GamepadDataFetcher; @@ -40,6 +44,11 @@ // Returns the GamepadService singleton. static GamepadService* GetInstance(); + void StartUp( + std::unique_ptr<service_manager::Connector> service_manager_connector); + + service_manager::Connector* GetConnector(); + // Increments the number of users of the provider. The Provider is running // when there's > 0 users, and is paused when the count drops to 0. // consumer is registered to listen for gamepad connections. If this is the @@ -150,6 +159,8 @@ bool gesture_callback_pending_; + std::unique_ptr<service_manager::Connector> service_manager_connector_; + DISALLOW_COPY_AND_ASSIGN(GamepadService); };
diff --git a/device/gamepad/gamepad_standard_mappings_linux.cc b/device/gamepad/gamepad_standard_mappings_linux.cc index abfd8a22..4cb0361 100644 --- a/device/gamepad/gamepad_standard_mappings_linux.cc +++ b/device/gamepad/gamepad_standard_mappings_linux.cc
@@ -495,7 +495,7 @@ mapped->axes_length = AXIS_INDEX_COUNT; } -void MapperSteelSeriesStratusXL(const Gamepad& input, Gamepad* mapped) { +void MapperSteelSeriesStratusXLUsb(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1]; @@ -524,6 +524,39 @@ mapped->axes_length = AXIS_INDEX_COUNT; } +void MapperSteelSeriesStratusXLBt(const Gamepad& input, Gamepad* mapped) { + *mapped = input; + mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0]; + mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1]; + mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3]; + mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4]; + mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6]; + mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7]; + mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[5]); + mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]); + mapped->buttons[BUTTON_INDEX_BACK_SELECT] = NullButton(); + mapped->buttons[BUTTON_INDEX_START] = input.buttons[11]; + mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[13]; + mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[14]; + mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[7]); + mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[7]); + mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[6]); + mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] = + AxisPositiveAsButton(input.axes[6]); + mapped->buttons[BUTTON_INDEX_META] = NullButton(); + // The BACK_SELECT and META button currently aren't mappable since they are + // handled separately as key events, causing browser HOME and BACK actions. If + // this is fixed, they should be added here. + + mapped->axes[AXIS_INDEX_LEFT_STICK_X] = input.axes[0]; + mapped->axes[AXIS_INDEX_LEFT_STICK_Y] = input.axes[1]; + mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[2]; + mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[3]; + + mapped->buttons_length = BUTTON_INDEX_META; + mapped->axes_length = AXIS_INDEX_COUNT; +} + void MapperSwitchProUsb(const Gamepad& input, Gamepad* mapped) { *mapped = input; mapped->axes[AXIS_INDEX_LEFT_STICK_X] = RenormalizeAndClampAxis( @@ -736,7 +769,9 @@ // Zeemote: SteelSeries FREE {GamepadId::kSteelSeriesProduct1412, MapperSteelSeriesZeemote}, // SteelSeries Stratus XL USB - {GamepadId::kSteelSeriesProduct1418, MapperSteelSeriesStratusXL}, + {GamepadId::kSteelSeriesProduct1418, MapperSteelSeriesStratusXLUsb}, + // SteelSeries Stratus XL Bluetooth + {GamepadId::kSteelSeriesBtProduct1419, MapperSteelSeriesStratusXLBt}, // Razer Serval Controller {GamepadId::kRazer1532Product0900, MapperRazerServal}, // ADT-1 Controller
diff --git a/device/gamepad/public/mojom/BUILD.gn b/device/gamepad/public/mojom/BUILD.gn index 1bd367a..3cd7845 100644 --- a/device/gamepad/public/mojom/BUILD.gn +++ b/device/gamepad/public/mojom/BUILD.gn
@@ -11,6 +11,7 @@ deps = [ "//mojo/public/mojom/base", + "//services/service_manager/public/mojom", ] output_prefix = "gamepad_mojom"
diff --git a/device/usb/usb_device_handle.h b/device/usb/usb_device_handle.h index ee92e79..8c50b48f 100644 --- a/device/usb/usb_device_handle.h +++ b/device/usb/usb_device_handle.h
@@ -69,8 +69,6 @@ virtual void ResetDevice(ResultCallback callback) = 0; virtual void ClearHalt(uint8_t endpoint, ResultCallback callback) = 0; - // The transfer functions may be called from any thread. The provided callback - // will be run on the caller's thread. virtual void ControlTransfer(UsbTransferDirection direction, UsbControlTransferType request_type, UsbControlTransferRecipient recipient,
diff --git a/device/usb/usb_device_handle_impl.cc b/device/usb/usb_device_handle_impl.cc index b8c2307a..3a909c7c 100644 --- a/device/usb/usb_device_handle_impl.cc +++ b/device/usb/usb_device_handle_impl.cc
@@ -104,40 +104,6 @@ return UsbTransferStatus::TRANSFER_ERROR; } -static void RunTransferCallback( - scoped_refptr<base::TaskRunner> callback_task_runner, - UsbDeviceHandle::TransferCallback callback, - UsbTransferStatus status, - scoped_refptr<base::RefCountedBytes> buffer, - size_t result) { - if (callback_task_runner->RunsTasksInCurrentSequence()) { - std::move(callback).Run(status, buffer, result); - } else { - callback_task_runner->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), status, buffer, result)); - } -} - -void ReportIsochronousTransferError( - scoped_refptr<base::TaskRunner> callback_task_runner, - UsbDeviceHandle::IsochronousTransferCallback callback, - const std::vector<uint32_t> packet_lengths, - UsbTransferStatus status) { - std::vector<UsbDeviceHandle::IsochronousPacket> packets( - packet_lengths.size()); - for (size_t i = 0; i < packet_lengths.size(); ++i) { - packets[i].length = packet_lengths[i]; - packets[i].transferred_length = 0; - packets[i].status = status; - } - if (callback_task_runner->RunsTasksInCurrentSequence()) { - std::move(callback).Run(nullptr, packets); - } else { - callback_task_runner->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), nullptr, packets)); - } -} - } // namespace class UsbDeviceHandleImpl::InterfaceClaimer @@ -209,7 +175,6 @@ uint16_t length, scoped_refptr<base::RefCountedBytes> buffer, unsigned int timeout, - scoped_refptr<base::TaskRunner> callback_task_runner, TransferCallback* callback); static std::unique_ptr<Transfer> CreateBulkTransfer( scoped_refptr<UsbDeviceHandleImpl> device_handle, @@ -217,7 +182,6 @@ scoped_refptr<base::RefCountedBytes> buffer, int length, unsigned int timeout, - scoped_refptr<base::TaskRunner> callback_task_runner, TransferCallback* callback); static std::unique_ptr<Transfer> CreateInterruptTransfer( scoped_refptr<UsbDeviceHandleImpl> device_handle, @@ -225,7 +189,6 @@ scoped_refptr<base::RefCountedBytes> buffer, int length, unsigned int timeout, - scoped_refptr<base::TaskRunner> callback_task_runner, TransferCallback* callback); static std::unique_ptr<Transfer> CreateIsochronousTransfer( scoped_refptr<UsbDeviceHandleImpl> device_handle, @@ -234,7 +197,6 @@ size_t length, const std::vector<uint32_t>& packet_lengths, unsigned int timeout, - scoped_refptr<base::TaskRunner> callback_task_runner, IsochronousTransferCallback* callback); ~Transfer(); @@ -248,22 +210,16 @@ return claimed_interface_.get(); } - scoped_refptr<base::TaskRunner> callback_task_runner() const { - return callback_task_runner_; - } - private: Transfer(scoped_refptr<UsbDeviceHandleImpl> device_handle, scoped_refptr<InterfaceClaimer> claimed_interface, UsbTransferType transfer_type, scoped_refptr<base::RefCountedBytes> buffer, size_t length, - scoped_refptr<base::TaskRunner> callback_task_runner, TransferCallback callback); Transfer(scoped_refptr<UsbDeviceHandleImpl> device_handle, scoped_refptr<InterfaceClaimer> claimed_interface, scoped_refptr<base::RefCountedBytes> buffer, - scoped_refptr<base::TaskRunner> callback_task_runner, IsochronousTransferCallback callback); static void LIBUSB_CALL PlatformCallback(PlatformUsbTransferHandle handle); @@ -278,7 +234,6 @@ size_t length_; bool cancelled_ = false; scoped_refptr<base::SequencedTaskRunner> task_runner_; - scoped_refptr<base::TaskRunner> callback_task_runner_; TransferCallback callback_; IsochronousTransferCallback iso_callback_; }; @@ -294,12 +249,10 @@ uint16_t length, scoped_refptr<base::RefCountedBytes> buffer, unsigned int timeout, - scoped_refptr<base::TaskRunner> callback_task_runner, TransferCallback* callback) { std::unique_ptr<Transfer> transfer( new Transfer(device_handle, nullptr, UsbTransferType::CONTROL, buffer, - length + LIBUSB_CONTROL_SETUP_SIZE, callback_task_runner, - std::move(*callback))); + length + LIBUSB_CONTROL_SETUP_SIZE, std::move(*callback))); transfer->platform_transfer_ = libusb_alloc_transfer(0); if (!transfer->platform_transfer_) { @@ -326,12 +279,10 @@ scoped_refptr<base::RefCountedBytes> buffer, int length, unsigned int timeout, - scoped_refptr<base::TaskRunner> callback_task_runner, TransferCallback* callback) { std::unique_ptr<Transfer> transfer(new Transfer( device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint), - UsbTransferType::BULK, buffer, length, callback_task_runner, - std::move(*callback))); + UsbTransferType::BULK, buffer, length, std::move(*callback))); transfer->platform_transfer_ = libusb_alloc_transfer(0); if (!transfer->platform_transfer_) { @@ -356,12 +307,10 @@ scoped_refptr<base::RefCountedBytes> buffer, int length, unsigned int timeout, - scoped_refptr<base::TaskRunner> callback_task_runner, TransferCallback* callback) { std::unique_ptr<Transfer> transfer(new Transfer( device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint), - UsbTransferType::INTERRUPT, buffer, length, callback_task_runner, - std::move(*callback))); + UsbTransferType::INTERRUPT, buffer, length, std::move(*callback))); transfer->platform_transfer_ = libusb_alloc_transfer(0); if (!transfer->platform_transfer_) { @@ -387,11 +336,10 @@ size_t length, const std::vector<uint32_t>& packet_lengths, unsigned int timeout, - scoped_refptr<base::TaskRunner> callback_task_runner, IsochronousTransferCallback* callback) { std::unique_ptr<Transfer> transfer(new Transfer( device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint), - buffer, callback_task_runner, std::move(*callback))); + buffer, std::move(*callback))); int num_packets = static_cast<int>(packet_lengths.size()); transfer->platform_transfer_ = libusb_alloc_transfer(num_packets); @@ -418,14 +366,12 @@ UsbTransferType transfer_type, scoped_refptr<base::RefCountedBytes> buffer, size_t length, - scoped_refptr<base::TaskRunner> callback_task_runner, TransferCallback callback) : transfer_type_(transfer_type), device_handle_(device_handle), buffer_(buffer), claimed_interface_(claimed_interface), length_(length), - callback_task_runner_(callback_task_runner), callback_(std::move(callback)) { task_runner_ = base::ThreadTaskRunnerHandle::Get(); } @@ -434,13 +380,11 @@ scoped_refptr<UsbDeviceHandleImpl> device_handle, scoped_refptr<InterfaceClaimer> claimed_interface, scoped_refptr<base::RefCountedBytes> buffer, - scoped_refptr<base::TaskRunner> callback_task_runner, IsochronousTransferCallback callback) : transfer_type_(UsbTransferType::ISOCHRONOUS), device_handle_(device_handle), buffer_(buffer), claimed_interface_(claimed_interface), - callback_task_runner_(callback_task_runner), iso_callback_(std::move(callback)) { task_runner_ = base::ThreadTaskRunnerHandle::Get(); } @@ -576,10 +520,7 @@ // This loop must ensure that what may be the final reference is released on // the right thread. for (auto& map_entry : claimed_interfaces_) { - InterfaceClaimer* interface_claimer = map_entry.second.get(); - interface_claimer->AddRef(); - map_entry.second = nullptr; - blocking_task_runner_->ReleaseSoon(FROM_HERE, interface_claimer); + blocking_task_runner_->ReleaseSoon(FROM_HERE, std::move(map_entry.second)); } device_->HandleClosed(this); @@ -644,9 +585,9 @@ transfer->Cancel(); } } - interface_claimer->AddRef(); interface_claimer->set_release_callback(std::move(callback)); - blocking_task_runner_->ReleaseSoon(FROM_HERE, interface_claimer); + blocking_task_runner_->ReleaseSoon( + FROM_HERE, std::move(claimed_interfaces_[interface_number])); claimed_interfaces_.erase(interface_number); RefreshEndpointMap(); @@ -712,18 +653,44 @@ scoped_refptr<base::RefCountedBytes> buffer, unsigned int timeout, TransferCallback callback) { - if (task_runner_->BelongsToCurrentThread()) { - ControlTransferInternal(direction, request_type, recipient, request, value, - index, buffer, timeout, task_runner_, - std::move(callback)); - } else { + DCHECK(thread_checker_.CalledOnValidThread()); + + if (!device_) { task_runner_->PostTask( - FROM_HERE, base::BindOnce(&UsbDeviceHandleImpl::ControlTransferInternal, - this, direction, request_type, recipient, - request, value, index, buffer, timeout, - base::ThreadTaskRunnerHandle::Get(), - std::move(callback))); + FROM_HERE, base::BindOnce(std::move(callback), + UsbTransferStatus::DISCONNECT, buffer, 0)); + return; } + + if (!base::IsValueInRangeForNumericType<uint16_t>(buffer->size())) { + USB_LOG(USER) << "Transfer too long."; + task_runner_->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR, + buffer, 0)); + return; + } + + const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + buffer->size(); + auto resized_buffer = + base::MakeRefCounted<base::RefCountedBytes>(resized_length); + memcpy(resized_buffer->front() + LIBUSB_CONTROL_SETUP_SIZE, buffer->front(), + buffer->size()); + + std::unique_ptr<Transfer> transfer = Transfer::CreateControlTransfer( + this, CreateRequestType(direction, request_type, recipient), request, + value, index, static_cast<uint16_t>(buffer->size()), resized_buffer, + timeout, &callback); + if (!transfer) { + DCHECK(callback); + task_runner_->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR, + buffer, 0)); + return; + } + + SubmitTransfer(std::move(transfer)); } void UsbDeviceHandleImpl::IsochronousTransferIn( @@ -731,19 +698,24 @@ const std::vector<uint32_t>& packet_lengths, unsigned int timeout, IsochronousTransferCallback callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + + if (!device_) { + ReportIsochronousTransferError(std::move(callback), packet_lengths, + UsbTransferStatus::DISCONNECT); + return; + } + uint8_t endpoint_address = ConvertTransferDirection(UsbTransferDirection::INBOUND) | endpoint_number; - if (task_runner_->BelongsToCurrentThread()) { - IsochronousTransferInInternal(endpoint_address, packet_lengths, timeout, - task_runner_, std::move(callback)); - } else { - task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&UsbDeviceHandleImpl::IsochronousTransferInInternal, - this, endpoint_address, packet_lengths, timeout, - base::ThreadTaskRunnerHandle::Get(), - std::move(callback))); - } + size_t length = + std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u); + auto buffer = base::MakeRefCounted<base::RefCountedBytes>(length); + std::unique_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer( + this, endpoint_address, buffer, length, packet_lengths, timeout, + &callback); + DCHECK(transfer); + SubmitTransfer(std::move(transfer)); } void UsbDeviceHandleImpl::IsochronousTransferOut( @@ -752,20 +724,24 @@ const std::vector<uint32_t>& packet_lengths, unsigned int timeout, IsochronousTransferCallback callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + + if (!device_) { + ReportIsochronousTransferError(std::move(callback), packet_lengths, + UsbTransferStatus::DISCONNECT); + return; + } + uint8_t endpoint_address = ConvertTransferDirection(UsbTransferDirection::OUTBOUND) | endpoint_number; - if (task_runner_->BelongsToCurrentThread()) { - IsochronousTransferOutInternal(endpoint_address, buffer, packet_lengths, - timeout, task_runner_, std::move(callback)); - } else { - task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&UsbDeviceHandleImpl::IsochronousTransferOutInternal, - this, endpoint_address, buffer, packet_lengths, timeout, - base::ThreadTaskRunnerHandle::Get(), - std::move(callback))); - } + size_t length = + std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u); + std::unique_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer( + this, endpoint_address, buffer, length, packet_lengths, timeout, + &callback); + DCHECK(transfer); + SubmitTransfer(std::move(transfer)); } void UsbDeviceHandleImpl::GenericTransfer( @@ -774,18 +750,59 @@ scoped_refptr<base::RefCountedBytes> buffer, unsigned int timeout, TransferCallback callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + + if (!device_) { + task_runner_->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), + UsbTransferStatus::DISCONNECT, buffer, 0)); + return; + } + uint8_t endpoint_address = ConvertTransferDirection(direction) | endpoint_number; - if (task_runner_->BelongsToCurrentThread()) { - GenericTransferInternal(endpoint_address, buffer, timeout, task_runner_, - std::move(callback)); - } else { + const auto endpoint_it = endpoint_map_.find(endpoint_address); + if (endpoint_it == endpoint_map_.end()) { + USB_LOG(DEBUG) << "Failed to submit transfer because endpoint " + << static_cast<int>(endpoint_address) + << " not part of a claimed interface."; task_runner_->PostTask( - FROM_HERE, base::BindOnce(&UsbDeviceHandleImpl::GenericTransferInternal, - this, endpoint_address, buffer, timeout, - base::ThreadTaskRunnerHandle::Get(), - std::move(callback))); + FROM_HERE, + base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR, + buffer, 0)); + return; } + + if (!base::IsValueInRangeForNumericType<int>(buffer->size())) { + USB_LOG(DEBUG) << "Transfer too long."; + task_runner_->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR, + buffer, 0)); + return; + } + + std::unique_ptr<Transfer> transfer; + UsbTransferType transfer_type = endpoint_it->second.endpoint->transfer_type; + if (transfer_type == UsbTransferType::BULK) { + transfer = Transfer::CreateBulkTransfer(this, endpoint_address, buffer, + static_cast<int>(buffer->size()), + timeout, &callback); + } else if (transfer_type == UsbTransferType::INTERRUPT) { + transfer = Transfer::CreateInterruptTransfer( + this, endpoint_address, buffer, static_cast<int>(buffer->size()), + timeout, &callback); + } else { + USB_LOG(DEBUG) << "Endpoint " << static_cast<int>(endpoint_address) + << " is not a bulk or interrupt endpoint."; + task_runner_->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR, + buffer, 0)); + return; + } + DCHECK(transfer); + SubmitTransfer(std::move(transfer)); } const UsbInterfaceDescriptor* UsbDeviceHandleImpl::FindInterfaceByEndpoint( @@ -875,10 +892,8 @@ if (!device_) { if (interface_claimer) { // Ensure that the InterfaceClaimer is released on the blocking thread. - InterfaceClaimer* raw_interface_claimer = interface_claimer.get(); - interface_claimer->AddRef(); - interface_claimer = nullptr; - blocking_task_runner_->ReleaseSoon(FROM_HERE, raw_interface_claimer); + blocking_task_runner_->ReleaseSoon(FROM_HERE, + std::move(interface_claimer)); } std::move(callback).Run(false); @@ -981,152 +996,20 @@ return nullptr; } -void UsbDeviceHandleImpl::ControlTransferInternal( - UsbTransferDirection direction, - UsbControlTransferType request_type, - UsbControlTransferRecipient recipient, - uint8_t request, - uint16_t value, - uint16_t index, - scoped_refptr<base::RefCountedBytes> buffer, - unsigned int timeout, - scoped_refptr<base::TaskRunner> callback_task_runner, - TransferCallback callback) { +void UsbDeviceHandleImpl::ReportIsochronousTransferError( + UsbDeviceHandle::IsochronousTransferCallback callback, + const std::vector<uint32_t> packet_lengths, + UsbTransferStatus status) { DCHECK(thread_checker_.CalledOnValidThread()); - - if (!device_) { - RunTransferCallback(callback_task_runner, std::move(callback), - UsbTransferStatus::DISCONNECT, buffer, 0); - return; + std::vector<UsbDeviceHandle::IsochronousPacket> packets( + packet_lengths.size()); + for (size_t i = 0; i < packet_lengths.size(); ++i) { + packets[i].length = packet_lengths[i]; + packets[i].transferred_length = 0; + packets[i].status = status; } - - if (!base::IsValueInRangeForNumericType<uint16_t>(buffer->size())) { - USB_LOG(USER) << "Transfer too long."; - RunTransferCallback(callback_task_runner, std::move(callback), - UsbTransferStatus::TRANSFER_ERROR, buffer, 0); - return; - } - - const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + buffer->size(); - auto resized_buffer = - base::MakeRefCounted<base::RefCountedBytes>(resized_length); - memcpy(resized_buffer->front() + LIBUSB_CONTROL_SETUP_SIZE, buffer->front(), - buffer->size()); - - std::unique_ptr<Transfer> transfer = Transfer::CreateControlTransfer( - this, CreateRequestType(direction, request_type, recipient), request, - value, index, static_cast<uint16_t>(buffer->size()), resized_buffer, - timeout, callback_task_runner, &callback); - if (!transfer) { - DCHECK(callback); - RunTransferCallback(callback_task_runner, std::move(callback), - UsbTransferStatus::TRANSFER_ERROR, buffer, 0); - return; - } - - SubmitTransfer(std::move(transfer)); -} - -void UsbDeviceHandleImpl::IsochronousTransferInInternal( - uint8_t endpoint_address, - const std::vector<uint32_t>& packet_lengths, - unsigned int timeout, - scoped_refptr<base::TaskRunner> callback_task_runner, - IsochronousTransferCallback callback) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!device_) { - ReportIsochronousTransferError(callback_task_runner, std::move(callback), - packet_lengths, - UsbTransferStatus::DISCONNECT); - return; - } - - size_t length = - std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u); - auto buffer = base::MakeRefCounted<base::RefCountedBytes>(length); - std::unique_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer( - this, endpoint_address, buffer, length, packet_lengths, timeout, - callback_task_runner, &callback); - DCHECK(transfer); - SubmitTransfer(std::move(transfer)); -} - -void UsbDeviceHandleImpl::IsochronousTransferOutInternal( - uint8_t endpoint_address, - scoped_refptr<base::RefCountedBytes> buffer, - const std::vector<uint32_t>& packet_lengths, - unsigned int timeout, - scoped_refptr<base::TaskRunner> callback_task_runner, - IsochronousTransferCallback callback) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!device_) { - ReportIsochronousTransferError(callback_task_runner, std::move(callback), - packet_lengths, - UsbTransferStatus::DISCONNECT); - return; - } - - size_t length = - std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u); - std::unique_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer( - this, endpoint_address, buffer, length, packet_lengths, timeout, - callback_task_runner, &callback); - DCHECK(transfer); - SubmitTransfer(std::move(transfer)); -} - -void UsbDeviceHandleImpl::GenericTransferInternal( - uint8_t endpoint_address, - scoped_refptr<base::RefCountedBytes> buffer, - unsigned int timeout, - scoped_refptr<base::TaskRunner> callback_task_runner, - TransferCallback callback) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!device_) { - RunTransferCallback(callback_task_runner, std::move(callback), - UsbTransferStatus::DISCONNECT, buffer, 0); - return; - } - - const auto endpoint_it = endpoint_map_.find(endpoint_address); - if (endpoint_it == endpoint_map_.end()) { - USB_LOG(DEBUG) << "Failed to submit transfer because endpoint " - << static_cast<int>(endpoint_address) - << " not part of a claimed interface."; - RunTransferCallback(callback_task_runner, std::move(callback), - UsbTransferStatus::TRANSFER_ERROR, buffer, 0); - return; - } - - if (!base::IsValueInRangeForNumericType<int>(buffer->size())) { - USB_LOG(DEBUG) << "Transfer too long."; - RunTransferCallback(callback_task_runner, std::move(callback), - UsbTransferStatus::TRANSFER_ERROR, buffer, 0); - return; - } - - std::unique_ptr<Transfer> transfer; - UsbTransferType transfer_type = endpoint_it->second.endpoint->transfer_type; - if (transfer_type == UsbTransferType::BULK) { - transfer = Transfer::CreateBulkTransfer( - this, endpoint_address, buffer, static_cast<int>(buffer->size()), - timeout, callback_task_runner, &callback); - } else if (transfer_type == UsbTransferType::INTERRUPT) { - transfer = Transfer::CreateInterruptTransfer( - this, endpoint_address, buffer, static_cast<int>(buffer->size()), - timeout, callback_task_runner, &callback); - } else { - USB_LOG(DEBUG) << "Endpoint " << static_cast<int>(endpoint_address) - << " is not a bulk or interrupt endpoint."; - RunTransferCallback(callback_task_runner, std::move(callback), - UsbTransferStatus::TRANSFER_ERROR, buffer, 0); - return; - } - DCHECK(transfer); - SubmitTransfer(std::move(transfer)); + task_runner_->PostTask(FROM_HERE, + base::BindOnce(std::move(callback), nullptr, packets)); } void UsbDeviceHandleImpl::SubmitTransfer(std::unique_ptr<Transfer> transfer) { @@ -1148,11 +1031,7 @@ << "Missing transfer completed"; transfers_.erase(transfer); - if (transfer->callback_task_runner()->RunsTasksInCurrentSequence()) { - std::move(callback).Run(); - } else { - transfer->callback_task_runner()->PostTask(FROM_HERE, std::move(callback)); - } + std::move(callback).Run(); // libusb_free_transfer races with libusb_submit_transfer and only work- // around is to make sure to call them on the same thread.
diff --git a/device/usb/usb_device_handle_impl.h b/device/usb/usb_device_handle_impl.h index 32dbe04..2e0b7d69 100644 --- a/device/usb/usb_device_handle_impl.h +++ b/device/usb/usb_device_handle_impl.h
@@ -25,7 +25,6 @@ class RefCountedBytes; class SequencedTaskRunner; class SingleThreadTaskRunner; -class TaskRunner; } namespace device { @@ -127,39 +126,10 @@ scoped_refptr<InterfaceClaimer> GetClaimedInterfaceForEndpoint( uint8_t endpoint); - void ControlTransferInternal( - UsbTransferDirection direction, - UsbControlTransferType request_type, - UsbControlTransferRecipient recipient, - uint8_t request, - uint16_t value, - uint16_t index, - scoped_refptr<base::RefCountedBytes> buffer, - unsigned int timeout, - scoped_refptr<base::TaskRunner> callback_task_runner, - TransferCallback callback); - - void IsochronousTransferInInternal( - uint8_t endpoint_address, - const std::vector<uint32_t>& packet_lengths, - unsigned int timeout, - scoped_refptr<base::TaskRunner> callback_task_runner, - IsochronousTransferCallback callback); - - void IsochronousTransferOutInternal( - uint8_t endpoint_address, - scoped_refptr<base::RefCountedBytes> buffer, - const std::vector<uint32_t>& packet_lengths, - unsigned int timeout, - scoped_refptr<base::TaskRunner> callback_task_runner, - IsochronousTransferCallback callback); - - void GenericTransferInternal( - uint8_t endpoint_address, - scoped_refptr<base::RefCountedBytes> buffer, - unsigned int timeout, - scoped_refptr<base::TaskRunner> callback_task_runner, - TransferCallback callback); + void ReportIsochronousTransferError( + UsbDeviceHandle::IsochronousTransferCallback callback, + const std::vector<uint32_t> packet_lengths, + UsbTransferStatus status); // Submits a transfer and starts tracking it. Retains the buffer and copies // the completion callback until the transfer finishes, whereupon it invokes
diff --git a/device/usb/usb_device_handle_usbfs.cc b/device/usb/usb_device_handle_usbfs.cc index 1ebe96b..a5143402 100644 --- a/device/usb/usb_device_handle_usbfs.cc +++ b/device/usb/usb_device_handle_usbfs.cc
@@ -162,8 +162,7 @@ struct UsbDeviceHandleUsbfs::Transfer { Transfer() = delete; Transfer(scoped_refptr<base::RefCountedBytes> buffer, - TransferCallback callback, - scoped_refptr<base::SingleThreadTaskRunner> callback_runner); + TransferCallback callback); Transfer(scoped_refptr<base::RefCountedBytes> buffer, IsochronousTransferCallback callback); ~Transfer(); @@ -187,8 +186,6 @@ IsochronousTransferCallback isoc_callback; private: - scoped_refptr<base::SingleThreadTaskRunner> callback_runner; - DISALLOW_COPY_AND_ASSIGN(Transfer); public: @@ -359,11 +356,8 @@ UsbDeviceHandleUsbfs::Transfer::Transfer( scoped_refptr<base::RefCountedBytes> buffer, - TransferCallback callback, - scoped_refptr<base::SingleThreadTaskRunner> callback_runner) - : buffer(buffer), - callback(std::move(callback)), - callback_runner(callback_runner) { + TransferCallback callback) + : buffer(buffer), callback(std::move(callback)) { memset(&urb, 0, sizeof(urb)); urb.usercontext = this; urb.buffer = buffer->front(); @@ -395,14 +389,7 @@ size_t bytes_transferred) { DCHECK_NE(urb.type, USBDEVFS_URB_TYPE_ISO); DCHECK(callback); - if (!callback_runner || callback_runner->BelongsToCurrentThread()) { - std::move(callback).Run(status, buffer, bytes_transferred); - } else { - callback_runner->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), status, buffer, bytes_transferred)); - } - callback.Reset(); + std::move(callback).Run(status, buffer, bytes_transferred); } void UsbDeviceHandleUsbfs::Transfer::RunIsochronousCallback( @@ -598,8 +585,8 @@ return; } - std::unique_ptr<Transfer> transfer( - new (0) Transfer(buffer, std::move(callback), nullptr)); + std::unique_ptr<Transfer> transfer(new (0) + Transfer(buffer, std::move(callback))); transfer->control_transfer_buffer = BuildControlTransferBuffer( direction, request_type, recipient, request, value, index, buffer); transfer->urb.type = USBDEVFS_URB_TYPE_CONTROL; @@ -656,16 +643,47 @@ scoped_refptr<base::RefCountedBytes> buffer, unsigned int timeout, TransferCallback callback) { - if (task_runner_->BelongsToCurrentThread()) { - GenericTransferInternal(direction, endpoint_number, buffer, timeout, - std::move(callback), task_runner_); - } else { + DCHECK(sequence_checker_.CalledOnValidSequence()); + if (!device_) { + task_runner_->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), + UsbTransferStatus::DISCONNECT, nullptr, 0)); + return; + } + + uint8_t endpoint_address = + ConvertEndpointDirection(direction) | endpoint_number; + auto it = endpoints_.find(endpoint_address); + if (it == endpoints_.end()) { + USB_LOG(USER) << "Endpoint address " << static_cast<int>(endpoint_address) + << " is not part of a claimed interface."; task_runner_->PostTask( FROM_HERE, - base::BindOnce(&UsbDeviceHandleUsbfs::GenericTransferInternal, this, - direction, endpoint_number, buffer, timeout, - std::move(callback), - base::ThreadTaskRunnerHandle::Get())); + base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR, + nullptr, 0)); + return; + } + + std::unique_ptr<Transfer> transfer(new (0) + Transfer(buffer, std::move(callback))); + transfer->urb.endpoint = endpoint_address; + transfer->urb.buffer_length = buffer->size(); + transfer->urb.type = ConvertTransferType(it->second.type); + + // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported + // by USBDEVFS_REAPURBNDELAY. This code assumes a recent kernel that can + // accept arbitrarily large transfer requests, hopefully also using a scatter- + // gather list. + int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_SUBMITURB, &transfer->urb)); + if (rc) { + rc = logging::GetLastSystemErrorCode(); + USB_PLOG(DEBUG) << "Failed to submit transfer"; + task_runner_->PostTask( + FROM_HERE, base::BindOnce(std::move(transfer->callback), + ConvertTransferResult(rc), nullptr, 0)); + } else { + SetUpTimeoutCallback(transfer.get(), timeout); + transfers_.push_back(std::move(transfer)); } } @@ -765,57 +783,6 @@ } } -void UsbDeviceHandleUsbfs::GenericTransferInternal( - UsbTransferDirection direction, - uint8_t endpoint_number, - scoped_refptr<base::RefCountedBytes> buffer, - unsigned int timeout, - TransferCallback callback, - scoped_refptr<base::SingleThreadTaskRunner> callback_runner) { - DCHECK(sequence_checker_.CalledOnValidSequence()); - if (!device_) { - callback_runner->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), - UsbTransferStatus::DISCONNECT, nullptr, 0)); - return; - } - - uint8_t endpoint_address = - ConvertEndpointDirection(direction) | endpoint_number; - auto it = endpoints_.find(endpoint_address); - if (it == endpoints_.end()) { - USB_LOG(USER) << "Endpoint address " << static_cast<int>(endpoint_address) - << " is not part of a claimed interface."; - callback_runner->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR, - nullptr, 0)); - return; - } - - std::unique_ptr<Transfer> transfer( - new (0) Transfer(buffer, std::move(callback), callback_runner)); - transfer->urb.endpoint = endpoint_address; - transfer->urb.buffer_length = buffer->size(); - transfer->urb.type = ConvertTransferType(it->second.type); - - // USBDEVFS_SUBMITURB appears to be non-blocking as completion is reported - // by USBDEVFS_REAPURBNDELAY. This code assumes a recent kernel that can - // accept arbitrarily large transfer requests, hopefully also using a scatter- - // gather list. - int rc = HANDLE_EINTR(ioctl(fd_, USBDEVFS_SUBMITURB, &transfer->urb)); - if (rc) { - rc = logging::GetLastSystemErrorCode(); - USB_PLOG(DEBUG) << "Failed to submit transfer"; - callback_runner->PostTask( - FROM_HERE, base::BindOnce(std::move(transfer->callback), - ConvertTransferResult(rc), nullptr, 0)); - } else { - SetUpTimeoutCallback(transfer.get(), timeout); - transfers_.push_back(std::move(transfer)); - } -} - void UsbDeviceHandleUsbfs::ReapedUrbs(const std::vector<usbdevfs_urb*>& urbs) { DCHECK(sequence_checker_.CalledOnValidSequence()); for (auto* urb : urbs) {
diff --git a/device/usb/usb_device_handle_usbfs.h b/device/usb/usb_device_handle_usbfs.h index 02b42d8..0764d98 100644 --- a/device/usb/usb_device_handle_usbfs.h +++ b/device/usb/usb_device_handle_usbfs.h
@@ -66,8 +66,6 @@ const std::vector<uint32_t>& packet_lengths, unsigned int timeout, IsochronousTransferCallback callback) override; - // To support DevTools this function may be called from any thread and on - // completion |callback| will be run on that thread. void GenericTransfer(UsbTransferDirection direction, uint8_t endpoint_number, scoped_refptr<base::RefCountedBytes> buffer, @@ -111,13 +109,6 @@ const std::vector<uint32_t>& packet_lengths, unsigned int timeout, IsochronousTransferCallback callback); - void GenericTransferInternal( - UsbTransferDirection direction, - uint8_t endpoint_number, - scoped_refptr<base::RefCountedBytes> buffer, - unsigned int timeout, - TransferCallback callback, - scoped_refptr<base::SingleThreadTaskRunner> callback_runner); void ReapedUrbs(const std::vector<usbdevfs_urb*>& urbs); void TransferComplete(std::unique_ptr<Transfer> transfer); void RefreshEndpointInfo();
diff --git a/device/usb/usb_device_handle_win.cc b/device/usb/usb_device_handle_win.cc index 265c3f2..4c7cf9f 100644 --- a/device/usb/usb_device_handle_win.cc +++ b/device/usb/usb_device_handle_win.cc
@@ -382,8 +382,7 @@ control_request->MaybeStartWatching( result, last_error, base::BindOnce(&UsbDeviceHandleWin::TransferComplete, - weak_factory_.GetWeakPtr(), nullptr, std::move(callback), - buffer)); + weak_factory_.GetWeakPtr(), std::move(callback), buffer)); } void UsbDeviceHandleWin::IsochronousTransferIn( @@ -415,17 +414,50 @@ scoped_refptr<base::RefCountedBytes> buffer, unsigned int timeout, TransferCallback callback) { - if (task_runner_->BelongsToCurrentThread()) { - GenericTransferInternal(direction, endpoint_number, std::move(buffer), - timeout, std::move(callback), task_runner_); - } else { + DCHECK(thread_checker_.CalledOnValidThread()); + uint8_t endpoint_address = endpoint_number; + if (direction == UsbTransferDirection::INBOUND) + endpoint_address |= 0x80; + + auto endpoint_it = endpoints_.find(endpoint_address); + if (endpoint_it == endpoints_.end()) { task_runner_->PostTask( FROM_HERE, - base::BindOnce(&UsbDeviceHandleWin::GenericTransferInternal, this, - direction, endpoint_number, std::move(buffer), timeout, - std::move(callback), - base::ThreadTaskRunnerHandle::Get())); + base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR, + nullptr, 0)); + return; } + + auto interface_it = + interfaces_.find(endpoint_it->second.interface->interface_number); + DCHECK(interface_it != interfaces_.end()); + Interface* interface = &interface_it->second; + if (!interface->claimed) { + task_runner_->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR, + nullptr, 0)); + return; + } + + DCHECK(interface->handle.IsValid()); + Request* request = MakeRequest(true /* winusb_handle */); + BOOL result; + if (direction == UsbTransferDirection::INBOUND) { + result = WinUsb_ReadPipe(interface->handle.Get(), endpoint_address, + buffer->front(), buffer->size(), nullptr, + request->overlapped()); + } else { + result = WinUsb_WritePipe(interface->handle.Get(), endpoint_address, + buffer->front(), buffer->size(), nullptr, + request->overlapped()); + } + DWORD last_error = GetLastError(); + request->MaybeStartWatching( + result, last_error, + base::BindOnce(&UsbDeviceHandleWin::TransferComplete, + weak_factory_.GetWeakPtr(), std::move(callback), + std::move(buffer))); } const UsbInterfaceDescriptor* UsbDeviceHandleWin::FindInterfaceByEndpoint( @@ -635,7 +667,6 @@ } void UsbDeviceHandleWin::TransferComplete( - scoped_refptr<base::SequencedTaskRunner> callback_task_runner, TransferCallback callback, scoped_refptr<base::RefCountedBytes> buffer, Request* request_ptr, @@ -653,68 +684,7 @@ status = UsbTransferStatus::TRANSFER_ERROR; } - if (!callback_task_runner || - callback_task_runner->RunsTasksInCurrentSequence()) { - std::move(callback).Run(status, std::move(buffer), bytes_transferred); - } else { - callback_task_runner->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), status, - std::move(buffer), bytes_transferred)); - } -} - -void UsbDeviceHandleWin::GenericTransferInternal( - UsbTransferDirection direction, - uint8_t endpoint_number, - scoped_refptr<base::RefCountedBytes> buffer, - unsigned int timeout, - TransferCallback callback, - scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner) { - DCHECK(thread_checker_.CalledOnValidThread()); - uint8_t endpoint_address = endpoint_number; - if (direction == UsbTransferDirection::INBOUND) - endpoint_address |= 0x80; - - auto endpoint_it = endpoints_.find(endpoint_address); - if (endpoint_it == endpoints_.end()) { - callback_task_runner->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR, - nullptr, 0)); - return; - } - - auto interface_it = - interfaces_.find(endpoint_it->second.interface->interface_number); - DCHECK(interface_it != interfaces_.end()); - Interface* interface = &interface_it->second; - if (!interface->claimed) { - callback_task_runner->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR, - nullptr, 0)); - return; - } - - DCHECK(interface->handle.IsValid()); - Request* request = MakeRequest(true /* winusb_handle */); - BOOL result; - if (direction == UsbTransferDirection::INBOUND) { - result = WinUsb_ReadPipe(interface->handle.Get(), endpoint_address, - buffer->front(), buffer->size(), nullptr, - request->overlapped()); - } else { - result = WinUsb_WritePipe(interface->handle.Get(), endpoint_address, - buffer->front(), buffer->size(), nullptr, - request->overlapped()); - } - DWORD last_error = GetLastError(); - request->MaybeStartWatching( - result, last_error, - base::BindOnce(&UsbDeviceHandleWin::TransferComplete, - weak_factory_.GetWeakPtr(), - std::move(callback_task_runner), std::move(callback), - std::move(buffer))); + std::move(callback).Run(status, std::move(buffer), bytes_transferred); } void UsbDeviceHandleWin::ReportIsochronousError(
diff --git a/device/usb/usb_device_handle_win.h b/device/usb/usb_device_handle_win.h index 4547ac5..83aacca 100644 --- a/device/usb/usb_device_handle_win.h +++ b/device/usb/usb_device_handle_win.h
@@ -137,19 +137,11 @@ DWORD win32_result, size_t bytes_transferred); void TransferComplete( - scoped_refptr<base::SequencedTaskRunner> callback_task_runner, TransferCallback callback, scoped_refptr<base::RefCountedBytes> buffer, Request* request_ptr, DWORD win32_result, size_t bytes_transferred); - void GenericTransferInternal( - UsbTransferDirection direction, - uint8_t endpoint_number, - scoped_refptr<base::RefCountedBytes> buffer, - unsigned int timeout, - TransferCallback callback, - scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner); void ReportIsochronousError(const std::vector<uint32_t>& packet_lengths, IsochronousTransferCallback callback, UsbTransferStatus status);
diff --git a/docs/accessibility/tts.md b/docs/accessibility/tts.md index e1d07640..353479b 100644 --- a/docs/accessibility/tts.md +++ b/docs/accessibility/tts.md
@@ -22,7 +22,7 @@ - The extension is passed an [Options object](https://developer.chrome.com/apps/tts#method-speak) in chrome.tts.speak, which is translated into a - [tts_controller Utterance](https://cs.chromium.org/chromium/src/chrome/browser/speech/tts_controller.h?dr=CSs&l=130). + [tts_controller Utterance](https://cs.chromium.org/chromium/src/content/public/browser/tts_controller.h?dr=CSs&l=120). - Web Speech API @@ -37,12 +37,20 @@ ### Processing -- The [TtsController](https://cs.chromium.org/chromium/src/chrome/browser/speech/tts_controller.h) processes utterances and sends them to the correct output engine +- The [TtsControllerImpl](https://cs.chromium.org/chromium/src/content/browser/speech/tts_controller_impl.h) +(in content/) processes utterances and sends them to the correct output engine. + +- The [TtsControllerDelegateImpl](https://cs.chromium.org/chromium/src/chrome/browser/speech/tts_controller_delegate_impl.h) +(in chrome/) provides chrome-specific functionality, including making use of +user prefs in Chrome OS. ### Output - May differ by system, including Mac, Wind, Android, Arc++, and Chrome OS + - Platform APIs are in [content/browser/speech](https://cs.chromium.org/chromium/src/content/browser/speech/), expect for + Chrome OS's, which is in [chrome/browser/speech](https://cs.chromium.org/chromium/src/chrome/browser/speech/). + - In Chrome OS: - [TtsEngineExtensionAPI](https://cs.chromium.org/chromium/src/chrome/browser/speech/extension_api/tts_engine_extension_api.h) @@ -50,3 +58,22 @@ coming soon, third-party speech engines. - [PATTS](patts.md) is the built-in Chrome OS text-to-speech engine. + +### Testing + +- Unit tests + + - TtsControllerUnittest in content/browser/speech + + - TtsControllerDelegateImplUnittest in chrome/browser/speech + + - ArcTtsServiceUnittest for ARC++ voices + +- Browser tests + + - TtsApiTest tests Chrome TTS extension APIs + +- Fuzzer + + - In content_unittests, content/browser/speech/tts_platform_fuzzer.cc + (currently Windows only). \ No newline at end of file
diff --git a/docs/infra/cq_builders.md b/docs/infra/cq_builders.md index 52a1e51..eaa4ea6 100644 --- a/docs/infra/cq_builders.md +++ b/docs/infra/cq_builders.md
@@ -140,16 +140,7 @@ Path regular expressions: * [`//build/.*check_gn_headers.*`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:build/.*check_gn_headers.*) -* [linux_layout_tests_layout_ng](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_layout_tests_layout_ng) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_layout_tests_layout_ng)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_layout_tests_layout_ng)) - - Path regular expressions: - * [`//third_party/blink/renderer/core/(layout|paint)/ng/.+`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/renderer/core/(layout|paint)/ng/) - * [`//third_party/blink/renderer/core/editing/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/editing/) - * [`//third_party/blink/renderer/platform/fonts/shaping/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/fonts/shaping/) - * [`//third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG) - * [`//third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/) - -* [linux_layout_tests_slimming_paint_v2](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_layout_tests_slimming_paint_v2) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_layout_tests_slimming_paint_v2)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_layout_tests_slimming_paint_v2)) +* [linux_layout_tests_composite_after_paint](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_layout_tests_composite_after_paint) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_layout_tests_composite_after_paint)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_layout_tests_composite_after_paint)) Path regular expressions: * [`//third_party/blink/renderer/core/paint/compositing/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/paint/compositing/) @@ -160,6 +151,15 @@ * [`//third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint) * [`//third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/) +* [linux_layout_tests_layout_ng](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_layout_tests_layout_ng) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_layout_tests_layout_ng)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_layout_tests_layout_ng)) + + Path regular expressions: + * [`//third_party/blink/renderer/core/(layout|paint)/ng/.+`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/renderer/core/(layout|paint)/ng/) + * [`//third_party/blink/renderer/core/editing/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/editing/) + * [`//third_party/blink/renderer/platform/fonts/shaping/.+`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/fonts/shaping/) + * [`//third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG`](https://cs.chromium.org/search/?q=package:%5Echromium$+file:third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG) + * [`//third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/.+`](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/) + * [linux_mojo](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux_mojo) ([`cq.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:cq.cfg+linux_mojo)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+linux_mojo)) Path regular expressions:
diff --git a/docs/tab_helpers.md b/docs/tab_helpers.md index b5807c38..97fccfc9f 100644 --- a/docs/tab_helpers.md +++ b/docs/tab_helpers.md
@@ -18,10 +18,10 @@ that allows an object to observe events in the life of a `WebContents`. As an example, if we look at the `TabStripModel`, there are times when it need to watch out for WebContents being deleted. So it creates a -[DeletionObserver](https://code.google.com/p/chromium/codesearch#chromium/src/chrome/browser/ui/tabs/tab_strip_model.cc&q=DeletionObserver). -The `DeletionObserver` overrides `WebContentsDestroyed()`, and when a -`WebContents` gets destroyed, the callback is called and the `DeletionObserver` -processes the message. Note that `DeletionObserver` is not owned by the +[TabStripModel::WebContentsData](https://code.google.com/p/chromium/codesearch#chromium/src/chrome/browser/ui/tabs/tab_strip_model.cc&q=TabStripModel::WebContentsData). +That object overrides `WebContentsDestroyed()`, and when a +`WebContents` gets destroyed, the callback is called and the object +processes the message. Note that `TabStripModel::WebContentsData` object is not owned by the `WebContents`. It is owned indirectly by the `TabStripModel`. ## `SupportsUserData` and `WebContentsUserData`
diff --git a/docs/updating_clang_format_binaries.md b/docs/updating_clang_format_binaries.md index 95ef812..7a4e6ca 100644 --- a/docs/updating_clang_format_binaries.md +++ b/docs/updating_clang_format_binaries.md
@@ -64,16 +64,23 @@ svn co http://llvm.org/svn/llvm-project/cfe/trunk@$CLANG_REV clang cd ../../llvm-build -# Option 1: with cmake +# On Mac, do the following: MACOSX_DEPLOYMENT_TARGET=10.9 cmake -G Ninja -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_ASSERTIONS=NO -DLLVM_ENABLE_THREADS=NO ../llvm/ time caffeinate ninja clang-format strip bin/clang-format -# (On Linux, to build with clang, which produces smaller binaries, add this to -# your cmake invocation. -# On Mac, the system compiler is already clang so it's not needed there.) --DCMAKE_C_COMPILER=$PWD/../chrome/src/third_party/llvm-build/Release+Asserts/bin/clang -DCMAKE_CXX_COMPILER=$PWD/../chrome/src/third_party/llvm-build/Release+Asserts/bin/clang++ +#On Linux, do the following: +cmake -G Ninja -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_ENABLE_ASSERTIONS=NO -DLLVM_ENABLE_THREADS=NO \ + -DCMAKE_C_COMPILER=$PWD/../chrome/src/third_party/llvm-build/Release+Asserts/bin/clang \ + -DCMAKE_CXX_COMPILER=$PWD/../chrome/src/third_party/llvm-build/Release+Asserts/bin/clang++ \ + -DCMAKE_ASM_COMPILER=$PWD/../chrome/src/third_party/llvm-build/Release+Asserts/bin/clang \ + -DLLVM_ENABLE_TERMINFO=OFF -DCMAKE_CXX_STANDARD_LIBRARIES="-static-libgcc -static-libstdc++" ../llvm/ +ninja clang-format +strip bin/clang-format + + ``` Platform specific notes:
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc index b8a391c..f9c61859 100644 --- a/extensions/browser/event_router.cc +++ b/extensions/browser/event_router.cc
@@ -728,6 +728,12 @@ NOTREACHED(); return; } + // TODO(https://crbug.com/870838): Remove after investigating the bug. + if (ExtensionsBrowserClient::Get()->IsShuttingDown()) { + LOG(ERROR) + << "Event dispatched while shutting down extensions browser client."; + return; + } if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context)) return; // TODO(https://crbug.com/870838): Remove after investigating the bug.
diff --git a/extensions/browser/extension_event_histogram_value.h b/extensions/browser/extension_event_histogram_value.h index d3d964d..9ae89704 100644 --- a/extensions/browser/extension_event_histogram_value.h +++ b/extensions/browser/extension_event_histogram_value.h
@@ -446,6 +446,8 @@ ARC_APPS_PRIVATE_ON_INSTALLED = 425, FILE_MANAGER_PRIVATE_ON_CROSTINI_SHARED_PATHS_CHANGED = 426, AUTOMATION_INTERNAL_ON_GET_TEXT_LOCATION_RESULT = 427, + INPUT_METHOD_PRIVATE_ON_SETTINGS_CHANGED = 428, + INPUT_METHOD_PRIVATE_ON_SCREEN_PROJECTION_CHANGED = 429, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/extensions/browser/url_loader_factory_manager.cc b/extensions/browser/url_loader_factory_manager.cc index 49a41677..88ef28a 100644 --- a/extensions/browser/url_loader_factory_manager.cc +++ b/extensions/browser/url_loader_factory_manager.cc
@@ -82,6 +82,7 @@ // TODO(lukasza): https://crbug.com/846346: Use more granular CORB enforcement // based on the specific |extension|'s permissions. params->is_corb_enabled = false; + params->request_initiator_site_lock = url::Origin::Create(extension.url()); // Create the URLLoaderFactory. network::mojom::URLLoaderFactoryPtrInfo factory_info;
diff --git a/extensions/common/api/_permission_features.json b/extensions/common/api/_permission_features.json index b122f31..31430a9 100644 --- a/extensions/common/api/_permission_features.json +++ b/extensions/common/api/_permission_features.json
@@ -360,7 +360,7 @@ "channel": "stable", "extension_types": ["extension", "legacy_packaged_app", "platform_app"] }, - "lockScreen": [{ + "lockScreen": { "channel": "stable", "extension_types": ["platform_app"], "platforms": ["chromeos"], @@ -368,13 +368,7 @@ "6F9C741B8E0E546652134F1138DF0284A7C9B21E", // http://crbug.com/728309 "47448626CB266C60AA2404E4EB426E025DF497DF" // http://crbug.com/728309 ] - }, { - // TODO(tbarzic): Remove this once the apps in the white-list can be used - // to test lock screen note taking. - "channel": "dev", - "extension_types": ["platform_app"], - "platforms": ["chromeos"] - }], + }, "mediaPerceptionPrivate": [{ "channel": "stable", "extension_types": ["platform_app"],
diff --git a/extensions/renderer/activity_log_converter_strategy.cc b/extensions/renderer/activity_log_converter_strategy.cc index d4612a4..40fbbdb1 100644 --- a/extensions/renderer/activity_log_converter_strategy.cc +++ b/extensions/renderer/activity_log_converter_strategy.cc
@@ -71,7 +71,7 @@ v8::Local<v8::Object> value, std::unique_ptr<base::Value>* out, v8::Isolate* isolate, - const FromV8ValueCallback& callback) const { + const FromV8ValueCallback& callback) { return FromV8Internal(value, out, isolate, callback); } @@ -79,7 +79,7 @@ v8::Local<v8::Array> value, std::unique_ptr<base::Value>* out, v8::Isolate* isolate, - const FromV8ValueCallback& callback) const { + const FromV8ValueCallback& callback) { return FromV8Internal(value, out, isolate, callback); }
diff --git a/extensions/renderer/activity_log_converter_strategy.h b/extensions/renderer/activity_log_converter_strategy.h index 7a450856..3cb5d0dd 100644 --- a/extensions/renderer/activity_log_converter_strategy.h +++ b/extensions/renderer/activity_log_converter_strategy.h
@@ -30,11 +30,11 @@ bool FromV8Object(v8::Local<v8::Object> value, std::unique_ptr<base::Value>* out, v8::Isolate* isolate, - const FromV8ValueCallback& callback) const override; + const FromV8ValueCallback& callback) override; bool FromV8Array(v8::Local<v8::Array> value, std::unique_ptr<base::Value>* out, v8::Isolate* isolate, - const FromV8ValueCallback& callback) const override; + const FromV8ValueCallback& callback) override; private: bool FromV8Internal(v8::Local<v8::Object> value,
diff --git a/extensions/renderer/display_source_custom_bindings.cc b/extensions/renderer/display_source_custom_bindings.cc index 88f64ec..9347495 100644 --- a/extensions/renderer/display_source_custom_bindings.cc +++ b/extensions/renderer/display_source_custom_bindings.cc
@@ -54,20 +54,18 @@ v8::Local<v8::Value> GetChildValue(v8::Local<v8::Object> value, const std::string& key_name, - v8::Isolate* isolate) { - v8::Local<v8::Array> property_names(value->GetOwnPropertyNames()); - for (uint32_t i = 0; i < property_names->Length(); ++i) { - v8::Local<v8::Value> key(property_names->Get(i)); - if (key_name == *v8::String::Utf8Value(isolate, key)) { - v8::TryCatch try_catch(isolate); - v8::Local<v8::Value> child_v8 = value->Get(key); - if (try_catch.HasCaught()) { - return v8::Null(isolate); - } - return child_v8; - } + v8::Local<v8::Context> context) { + v8::Isolate* isolate = context->GetIsolate(); + v8::TryCatch try_catch(isolate); + v8::Local<v8::String> key; + v8::Local<v8::Value> child_value; + if (v8::String::NewFromUtf8(isolate, key_name.c_str(), + v8::NewStringType::kNormal) + .ToLocal(&key) && + value->HasOwnProperty(context, key).FromMaybe(false) && + value->Get(context, key).ToLocal(&child_value)) { + return child_value; } - return v8::Null(isolate); } @@ -84,12 +82,13 @@ CHECK(args[0]->IsObject()); v8::Isolate* isolate = context()->isolate(); + v8::Local<v8::Context> v8_context = context()->v8_context(); v8::Local<v8::Object> start_info = args[0].As<v8::Object>(); v8::Local<v8::Value> sink_id_val = - GetChildValue(start_info, "sinkId", isolate); + GetChildValue(start_info, "sinkId", v8_context); CHECK(sink_id_val->IsInt32()); - const int sink_id = sink_id_val->ToInt32(isolate)->Value(); + const int sink_id = sink_id_val.As<v8::Int32>()->Value(); if (GetDisplaySession(sink_id)) { isolate->ThrowException(v8::Exception::Error( v8::String::NewFromUtf8(isolate, kSessionAlreadyStarted, @@ -99,9 +98,9 @@ } v8::Local<v8::Value> video_stream_val = - GetChildValue(start_info, "videoTrack", isolate); + GetChildValue(start_info, "videoTrack", v8_context); v8::Local<v8::Value> audio_stream_val = - GetChildValue(start_info, "audioTrack", isolate); + GetChildValue(start_info, "audioTrack", v8_context); if ((video_stream_val->IsNull() || video_stream_val->IsUndefined()) && (audio_stream_val->IsNull() || audio_stream_val->IsUndefined())) { @@ -141,7 +140,7 @@ std::unique_ptr<DisplaySourceAuthInfo> auth_info; v8::Local<v8::Value> auth_info_v8_val = - GetChildValue(start_info, "authenticationInfo", isolate); + GetChildValue(start_info, "authenticationInfo", v8_context); if (!auth_info_v8_val->IsNull()) { CHECK(auth_info_v8_val->IsObject()); std::unique_ptr<base::Value> auth_info_val = @@ -194,7 +193,7 @@ CHECK(args[0]->IsInt32()); v8::Isolate* isolate = context()->isolate(); - int sink_id = args[0]->ToInt32(args.GetIsolate())->Value(); + int sink_id = args[0].As<v8::Int32>()->Value(); DisplaySourceSession* session = GetDisplaySession(sink_id); if (!session) { isolate->ThrowException(
diff --git a/extensions/renderer/logging_native_handler.cc b/extensions/renderer/logging_native_handler.cc index 72938859..9bd2b61 100644 --- a/extensions/renderer/logging_native_handler.cc +++ b/extensions/renderer/logging_native_handler.cc
@@ -66,8 +66,7 @@ bool* check_value, std::string* error_message) { CHECK_LE(args.Length(), 2); - *check_value = - args[0]->BooleanValue(context()->v8_context()).FromMaybe(false); + *check_value = args[0]->BooleanValue(context()->isolate()); if (args.Length() == 2) { *error_message = "Error: " + std::string(*v8::String::Utf8Value( args.GetIsolate(), args[1]));
diff --git a/extensions/renderer/send_request_natives.cc b/extensions/renderer/send_request_natives.cc index 1e39f93..3e2c4d3 100644 --- a/extensions/renderer/send_request_natives.cc +++ b/extensions/renderer/send_request_natives.cc
@@ -34,12 +34,9 @@ base::ElapsedTimer timer; CHECK_EQ(5, args.Length()); std::string name = *v8::String::Utf8Value(args.GetIsolate(), args[0]); - bool has_callback = - args[2]->BooleanValue(context()->v8_context()).FromMaybe(false); - bool for_io_thread = - args[3]->BooleanValue(context()->v8_context()).FromMaybe(false); - bool preserve_null_in_objects = - args[4]->BooleanValue(context()->v8_context()).FromMaybe(false); + bool has_callback = args[2]->BooleanValue(context()->isolate()); + bool for_io_thread = args[3]->BooleanValue(context()->isolate()); + bool preserve_null_in_objects = args[4]->BooleanValue(context()->isolate()); int request_id = request_sender_->GetNextRequestId(); args.GetReturnValue().Set(static_cast<int32_t>(request_id));
diff --git a/gpu/command_buffer/service/decoder_context.h b/gpu/command_buffer/service/decoder_context.h index abc53a0..523bf03 100644 --- a/gpu/command_buffer/service/decoder_context.h +++ b/gpu/command_buffer/service/decoder_context.h
@@ -213,6 +213,12 @@ // Methods required by GpuTracer // virtual gles2::Outputter* outputter() const = 0; + + // Restores all attributs in the gl context state. + virtual void RestoreAllAttributes() const = 0; + + // Restores texture states for a given service id. + virtual void RestoreTextureState(unsigned service_id) const = 0; }; } // namespace gpu
diff --git a/gpu/command_buffer/service/gl_context_virtual_delegate.h b/gpu/command_buffer/service/gl_context_virtual_delegate.h index 1b2ffc57..0db2f14 100644 --- a/gpu/command_buffer/service/gl_context_virtual_delegate.h +++ b/gpu/command_buffer/service/gl_context_virtual_delegate.h
@@ -32,7 +32,6 @@ // Restore States. virtual void RestoreGlobalState() const = 0; virtual void ClearAllAttributes() const = 0; - virtual void RestoreAllAttributes() const = 0; virtual void RestoreActiveTexture() const = 0; virtual void RestoreAllTextureUnitAndSamplerBindings( const gles2::ContextState* prev_state) const = 0; @@ -42,7 +41,6 @@ virtual void RestoreFramebufferBindings() const = 0; virtual void RestoreRenderbufferBindings() = 0; virtual void RestoreProgramBindings() const = 0; - virtual void RestoreTextureState(unsigned service_id) const = 0; virtual void RestoreTextureUnitBindings(unsigned unit) const = 0; virtual void RestoreVertexAttribArray(unsigned index) = 0; virtual void RestoreAllExternalTextureBindingsIfNeeded() = 0;
diff --git a/gpu/command_buffer/service/gl_state_restorer_impl.cc b/gpu/command_buffer/service/gl_state_restorer_impl.cc index d47a8d4d..0d20724 100644 --- a/gpu/command_buffer/service/gl_state_restorer_impl.cc +++ b/gpu/command_buffer/service/gl_state_restorer_impl.cc
@@ -71,12 +71,14 @@ void GLStateRestorerImpl::PauseQueries() { DCHECK(delegate_.get()); - delegate_->GetQueryManager()->PauseQueries(); + if (auto* query_manager = delegate_->GetQueryManager()) + query_manager->PauseQueries(); } void GLStateRestorerImpl::ResumeQueries() { DCHECK(delegate_.get()); - delegate_->GetQueryManager()->ResumeQueries(); + if (auto* query_manager = delegate_->GetQueryManager()) + query_manager->ResumeQueries(); } const gles2::ContextState* GLStateRestorerImpl::GetContextState() const {
diff --git a/gpu/command_buffer/service/gr_cache_controller.cc b/gpu/command_buffer/service/gr_cache_controller.cc index 4bb1cc19..787ef40 100644 --- a/gpu/command_buffer/service/gr_cache_controller.cc +++ b/gpu/command_buffer/service/gr_cache_controller.cc
@@ -21,7 +21,7 @@ void GrCacheController::ScheduleGrContextCleanup() { DCHECK(task_runner_->BelongsToCurrentThread()); - DCHECK(context_state_->context->IsCurrent(nullptr)); + DCHECK(context_state_->IsCurrent(nullptr)); if (!context_state_->gr_context) return; @@ -35,7 +35,6 @@ // a long while even if it is under budget. Below we set a call back to // purge all possible GrContext resources if the context itself is not being // used. - context_state_->context->DirtyVirtualContextState(); context_state_->need_context_state_reset = true; context_state_->gr_context->performDeferredCleanup( std::chrono::seconds(kOldResourceCleanupDelaySeconds)); @@ -64,7 +63,6 @@ return; } - context_state_->context->DirtyVirtualContextState(); context_state_->need_context_state_reset = true; context_state_->gr_context->freeGpuResources(); }
diff --git a/gpu/command_buffer/service/gr_cache_controller_unittest.cc b/gpu/command_buffer/service/gr_cache_controller_unittest.cc index ccd865d..b4c489cc 100644 --- a/gpu/command_buffer/service/gr_cache_controller_unittest.cc +++ b/gpu/command_buffer/service/gr_cache_controller_unittest.cc
@@ -8,6 +8,7 @@ #include "base/test/test_mock_time_task_runner.h" #include "gpu/command_buffer/service/raster_decoder_context_state.h" #include "gpu/config/gpu_driver_bug_workarounds.h" +#include "gpu/config/gpu_feature_info.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkImage.h" @@ -38,6 +39,7 @@ std::move(share_group), std::move(surface), std::move(context), false /* use_virtualized_gl_contexts */, base::DoNothing()); context_state_->InitializeGrContext(workarounds, nullptr); + context_state_->InitializeGL(workarounds, GpuFeatureInfo()); controller_ = std::make_unique<GrCacheController>(context_state_.get(), task_runner_);
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc index 7b9f9d8..e34d92f 100644 --- a/gpu/command_buffer/service/raster_decoder.cc +++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -72,16 +72,16 @@ // Local versions of the SET_GL_ERROR macros #define LOCAL_SET_GL_ERROR(error, function_name, msg) \ - ERRORSTATE_SET_GL_ERROR(GetErrorState(), error, function_name, msg) -#define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \ - ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(GetErrorState(), function_name, \ + ERRORSTATE_SET_GL_ERROR(error_state_.get(), error, function_name, msg) +#define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \ + ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(error_state_.get(), function_name, \ static_cast<uint32_t>(value), label) #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \ - ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(GetErrorState(), function_name) + ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(error_state_.get(), function_name) #define LOCAL_PEEK_GL_ERROR(function_name) \ - ERRORSTATE_PEEK_GL_ERROR(GetErrorState(), function_name) + ERRORSTATE_PEEK_GL_ERROR(error_state_.get(), function_name) #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \ - ERRORSTATE_CLEAR_REAL_GL_ERRORS(GetErrorState(), function_name) + ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_.get(), function_name) #define LOCAL_PERFORMANCE_WARNING(msg) \ PerformanceWarning(__FILE__, __LINE__, msg) #define LOCAL_RENDER_WARNING(msg) RenderWarning(__FILE__, __LINE__, msg) @@ -284,6 +284,8 @@ } Capabilities GetCapabilities() override; const gles2::ContextState* GetContextState() override; + + // TODO(penghuang): Remove unused context state related methods. void RestoreGlobalState() const override; void ClearAllAttributes() const override; void RestoreAllAttributes() const override; @@ -302,6 +304,7 @@ void RestoreVertexAttribArray(unsigned index) override; void RestoreAllExternalTextureBindingsIfNeeded() override; QueryManager* GetQueryManager() override; + void SetQueryCallback(unsigned int query_client_id, base::OnceClosure callback) override; gles2::GpuFenceManager* GetGpuFenceManager() override; @@ -404,7 +407,10 @@ return &it->second; } - gl::GLApi* api() const { return state_.api(); } + gles2::ContextState* state() const { + return raster_decoder_context_state_->context_state(); + } + gl::GLApi* api() const { return state()->api(); } GrContext* gr_context() const { return raster_decoder_context_state_->gr_context; } @@ -422,7 +428,8 @@ bool IsRobustnessSupported() { return has_robustness_extension_ && - context_->WasAllocatedUsingRobustnessExtension(); + raster_decoder_context_state_->context() + ->WasAllocatedUsingRobustnessExtension(); } const gl::GLVersionInfo& gl_version_info() { @@ -598,7 +605,6 @@ // only if not returning an error. error::Error current_decoder_error_ = error::kNoError; - scoped_refptr<gl::GLSurface> surface_; scoped_refptr<gl::GLContext> context_; DecoderClient* client_; @@ -606,6 +612,7 @@ gles2::DebugMarkerManager debug_marker_manager_; gles2::Logger logger_; std::unique_ptr<gles2::ErrorState> error_state_; + bool context_lost_ = false; // The ContextGroup for this decoder uses to track resources. scoped_refptr<gles2::ContextGroup> group_; @@ -615,9 +622,6 @@ std::unique_ptr<QueryManager> query_manager_; - // All the state for this context. - gles2::ContextState state_; - gles2::GLES2Util util_; // An optional behaviour to lose the context and group when OOM. @@ -737,8 +741,6 @@ raster_decoder_context_state_(std::move(raster_decoder_context_state)), validators_(new Validators), feature_info_(group_->feature_info()), - state_(group_->feature_info(), - false /* track_texture_and_sampler_units */), service_logging_( group_->gpu_preferences().enable_gpu_service_logging_gpu), gpu_decoder_category_(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( @@ -767,8 +769,6 @@ DCHECK(context->IsCurrent(surface.get())); DCHECK(!context_.get()); - state_.set_api(gl::g_current_gl_context); - set_initialized(); if (!offscreen) { @@ -781,7 +781,8 @@ if (group_->gpu_preferences().enable_gpu_command_logging) SetLogCommands(true); - surface_ = surface; + DCHECK_EQ(surface.get(), raster_decoder_context_state_->surface()); + DCHECK_EQ(context.get(), raster_decoder_context_state_->context()); context_ = context; // Create GPU Tracer for timing values. @@ -799,22 +800,15 @@ Destroy(true); return result; } + CHECK_GL_ERROR(); - state_.InitGenericAttribs(group_->max_vertex_attribs()); - - query_manager_.reset(new QueryManager()); + query_manager_ = std::make_unique<QueryManager>(); has_robustness_extension_ = features().arb_robustness || features().khr_robustness || features().ext_robustness; - // Set all the default state because some GL drivers get it wrong. - // TODO(backer): Not all of this state needs to be initialized. Reduce the set - // if perf becomes a problem. - state_.InitCapabilities(nullptr); - state_.InitState(nullptr); - if (attrib_helper.enable_oop_rasterization) { if (!features().chromium_raster_transport) { LOG(ERROR) << "ContextResult::kFatalFailure: " @@ -836,7 +830,8 @@ if (!initialized()) return; - DCHECK(!have_context || context_->IsCurrent(nullptr)); + DCHECK(!have_context || + raster_decoder_context_state_->context()->IsCurrent(nullptr)); if (have_context) { if (copy_tex_image_blit_.get()) { @@ -861,14 +856,8 @@ if (group_ && group_->texture_manager()) { group_->texture_manager()->MarkContextLost(); } - - state_.MarkContextLost(); } - // Unbind everything. - state_.bound_pixel_pack_buffer = nullptr; - state_.bound_pixel_unpack_buffer = nullptr; - copy_tex_image_blit_.reset(); copy_texture_chromium_.reset(); @@ -884,8 +873,6 @@ // Destroy the surface before the context, some surface destructors make GL // calls. - surface_ = nullptr; - if (context_.get()) { context_->ReleaseCurrent(nullptr); context_ = nullptr; @@ -897,23 +884,22 @@ // Make this decoder's GL context current. bool RasterDecoderImpl::MakeCurrent() { - DCHECK(surface_); if (!context_.get()) return false; - if (WasContextLost()) { + if (context_lost_) { LOG(ERROR) << " RasterDecoderImpl: Trying to make lost context current."; return false; } - // TODO(https://crbug.com/902904): Switch to - // raster_decoder_context_state_->MakeCurrent(nullptr). - if (!context_->MakeCurrent(surface_.get())) { + if (raster_decoder_context_state_->context_lost() || + !raster_decoder_context_state_->MakeCurrent(nullptr)) { LOG(ERROR) << " RasterDecoderImpl: Context lost during MakeCurrent."; MarkContextLost(error::kMakeCurrentFailed); group_->LoseContexts(error::kUnknown); return false; } + DCHECK_EQ(api(), gl::g_current_gl_context); if (CheckResetStatus()) { @@ -934,7 +920,7 @@ } gl::GLSurface* RasterDecoderImpl::GetGLSurface() { - return surface_.get(); + return raster_decoder_context_state_->surface(); } Capabilities RasterDecoderImpl::GetCapabilities() { @@ -966,18 +952,12 @@ } const gles2::ContextState* RasterDecoderImpl::GetContextState() { - if (raster_decoder_context_state_->need_context_state_reset) { - // Returning nullptr to force full state restoration by the caller. We do - // this because GrContext changes to GL state are untracked in our state_. - return nullptr; - } - - return &state_; + NOTREACHED(); + return nullptr; } void RasterDecoderImpl::RestoreGlobalState() const { raster_decoder_context_state_->PessimisticallyResetGrContext(); - state_.RestoreGlobalState(nullptr); } void RasterDecoderImpl::ClearAllAttributes() const {} @@ -987,10 +967,6 @@ } void RasterDecoderImpl::RestoreState(const gles2::ContextState* prev_state) { - TRACE_EVENT1("gpu", "RasterDecoderImpl::RestoreState", "context", - logger_.GetLogPrefix()); - state_.RestoreState(prev_state); - raster_decoder_context_state_->need_context_state_reset = false; raster_decoder_context_state_->PessimisticallyResetGrContext(); } @@ -1010,36 +986,22 @@ void RasterDecoderImpl::RestoreBufferBinding(unsigned int target) { raster_decoder_context_state_->PessimisticallyResetGrContext(); - if (target == GL_PIXEL_PACK_BUFFER) { - state_.UpdatePackParameters(); - } else if (target == GL_PIXEL_UNPACK_BUFFER) { - state_.UpdateUnpackParameters(); - } - api()->glBindBufferFn(target, 0); } void RasterDecoderImpl::RestoreBufferBindings() const { raster_decoder_context_state_->PessimisticallyResetGrContext(); - state_.RestoreBufferBindings(); } void RasterDecoderImpl::RestoreFramebufferBindings() const { raster_decoder_context_state_->PessimisticallyResetGrContext(); - state_.fbo_binding_for_scissor_workaround_dirty = true; - state_.stencil_state_changed_since_validation = true; - - if (workarounds().flush_on_framebuffer_change) - api()->glFlushFn(); } void RasterDecoderImpl::RestoreRenderbufferBindings() { raster_decoder_context_state_->PessimisticallyResetGrContext(); - state_.RestoreRenderbufferBindings(); } void RasterDecoderImpl::RestoreProgramBindings() const { raster_decoder_context_state_->PessimisticallyResetGrContext(); - state_.RestoreProgramSettings(nullptr, false); } void RasterDecoderImpl::RestoreTextureState(unsigned service_id) const { @@ -1067,7 +1029,7 @@ } void RasterDecoderImpl::RestoreVertexAttribArray(unsigned index) { - NOTIMPLEMENTED(); + raster_decoder_context_state_->PessimisticallyResetGrContext(); } void RasterDecoderImpl::RestoreAllExternalTextureBindingsIfNeeded() { @@ -1096,13 +1058,12 @@ } bool RasterDecoderImpl::HasPendingQueries() const { - return query_manager_.get() && query_manager_->HavePendingQueries(); + return query_manager_ && query_manager_->HavePendingQueries(); } void RasterDecoderImpl::ProcessPendingQueries(bool did_finish) { - if (!query_manager_.get()) - return; - query_manager_->ProcessPendingQueries(did_finish); + if (query_manager_) + query_manager_->ProcessPendingQueries(did_finish); } bool RasterDecoderImpl::HasMoreIdleWork() const { @@ -1137,7 +1098,7 @@ } bool RasterDecoderImpl::WasContextLost() const { - return raster_decoder_context_state_->context_lost; + return context_lost_; } bool RasterDecoderImpl::WasContextLostByRobustnessExtension() const { @@ -1150,16 +1111,14 @@ return; // Don't make GL calls in here, the context might not be current. + context_lost_ = true; command_buffer_service()->SetContextLostReason(reason); current_decoder_error_ = error::kLostContext; - - state_.MarkContextLost(); - raster_decoder_context_state_->MarkContextLost(); } bool RasterDecoderImpl::CheckResetStatus() { DCHECK(!WasContextLost()); - DCHECK(context_->IsCurrent(nullptr)); + DCHECK(raster_decoder_context_state_->context()->IsCurrent(nullptr)); if (IsRobustnessSupported()) { // If the reason for the call was a GL error, we can try to determine the @@ -1201,7 +1160,7 @@ } void RasterDecoderImpl::SetIgnoreCachedStateForTest(bool ignore) { - state_.SetIgnoreCachedStateForTest(ignore); + state()->SetIgnoreCachedStateForTest(ignore); } gles2::ImageManager* RasterDecoderImpl::GetImageManagerForTest() { @@ -1440,12 +1399,12 @@ { const bool state_is_dirty = raster_decoder_context_state_->need_context_state_reset; - ScopedTextureBinder binder(&state_, texture->target(), + ScopedTextureBinder binder(state(), texture->target(), texture->service_id(), gr_context(), state_is_dirty); base::Optional<ScopedPixelUnpackState> pixel_unpack_state; if (raster_decoder_context_state_->need_context_state_reset) { - pixel_unpack_state.emplace(&state_, gr_context(), group_->feature_info()); + pixel_unpack_state.emplace(state(), gr_context(), group_->feature_info()); } // Add extra scope to destroy zero and the object it owns right // after its usage. @@ -1882,7 +1841,7 @@ GLint dest_level = 0; ScopedTextureBinder binder( - &state_, texture_manager(), dest_texture_ref, dest_target, gr_context(), + state(), texture_manager(), dest_texture_ref, dest_target, gr_context(), raster_decoder_context_state_->need_context_state_reset); base::Optional<ScopedPixelUnpackState> pixel_unpack_state; @@ -1921,7 +1880,7 @@ // If the image is in shared memory, we may need upload the pixel data // with SubTexImage2D, so we need reset pixel unpack state if gl context // state has been touched by skia. - pixel_unpack_state.emplace(&state_, gr_context(), group_->feature_info()); + pixel_unpack_state.emplace(state(), gr_context(), group_->feature_info()); } } else { if (!source_texture->GetLevelSize(source_target, 0 /* level */, @@ -1982,7 +1941,7 @@ source_internal_format) == GL_SRGB || gles2::GLES2Util::GetColorEncodingFromInternalFormat( dest_internal_format) == GL_SRGB; - state_.EnableDisableFramebufferSRGB(enable_framebuffer_srgb); + state()->EnableDisableFramebufferSRGB(enable_framebuffer_srgb); } // Clear the source texture if necessary. @@ -2095,7 +2054,8 @@ gl::GLImage* image = texture->GetLevelImage(textarget, 0, &image_state); if (image && image_state == gles2::Texture::UNBOUND) { ScopedGLErrorSuppressor suppressor( - "RasterDecoderImpl::DoBindOrCopyTexImageIfNeeded", GetErrorState()); + "RasterDecoderImpl::DoBindOrCopyTexImageIfNeeded", + error_state_.get()); api()->glBindTextureFn(textarget, texture->service_id()); if (!image->BindTexImage(textarget)) { // Note: We update the state to COPIED prior to calling CopyTexImage()
diff --git a/gpu/command_buffer/service/raster_decoder_context_state.cc b/gpu/command_buffer/service/raster_decoder_context_state.cc index 5ebefe8..9dc7b516 100644 --- a/gpu/command_buffer/service/raster_decoder_context_state.cc +++ b/gpu/command_buffer/service/raster_decoder_context_state.cc
@@ -7,6 +7,8 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" #include "gpu/command_buffer/common/activity_flags.h" +#include "gpu/command_buffer/service/context_state.h" +#include "gpu/command_buffer/service/gl_context_virtual.h" #include "gpu/command_buffer/service/service_transfer_cache.h" #include "gpu/config/gpu_driver_bug_workarounds.h" #include "gpu/vulkan/buildflags.h" @@ -30,17 +32,19 @@ bool use_virtualized_gl_contexts, base::OnceClosure context_lost_callback, viz::VulkanContextProvider* vulkan_context_provider) - : share_group(std::move(share_group)), - surface(std::move(surface)), - context(std::move(context)), - use_virtualized_gl_contexts(use_virtualized_gl_contexts), + : use_virtualized_gl_contexts(use_virtualized_gl_contexts), context_lost_callback(std::move(context_lost_callback)), vk_context_provider(vulkan_context_provider), #if BUILDFLAG(ENABLE_VULKAN) gr_context(vk_context_provider ? vk_context_provider->GetGrContext() : nullptr), #endif - use_vulkan_gr_context(!!gr_context) { + use_vulkan_gr_context(!!gr_context), + share_group_(std::move(share_group)), + context_(context), + real_context_(std::move(context)), + surface_(std::move(surface)), + weak_ptr_factory_(this) { if (base::ThreadTaskRunnerHandle::IsSet()) { base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( this, "RasterDecoderContextState", base::ThreadTaskRunnerHandle::Get()); @@ -60,10 +64,10 @@ GpuProcessActivityFlags* activity_flags, gl::ProgressReporter* progress_reporter) { if (!use_vulkan_gr_context) { - DCHECK(context->IsCurrent(surface.get())); + DCHECK(context_->IsCurrent(surface())); sk_sp<GrGLInterface> interface(gl::init::CreateGrGLInterface( - *context->GetVersionInfo(), workarounds.use_es2_for_oopr, + *context_->GetVersionInfo(), workarounds.use_es2_for_oopr, progress_reporter)); if (!interface) { LOG(ERROR) << "OOP raster support disabled: GrGLInterface creation " @@ -111,6 +115,77 @@ transfer_cache = std::make_unique<ServiceTransferCache>(); } +bool RasterDecoderContextState::InitializeGL( + const GpuDriverBugWorkarounds& gpu_driver_bug_workarounds, + const GpuFeatureInfo& gpu_feature_info) { + if (use_vulkan_gr_context) + return true; + DCHECK(!context_state_); + + feature_info_ = base::MakeRefCounted<gles2::FeatureInfo>( + gpu_driver_bug_workarounds, gpu_feature_info); + + feature_info_->Initialize(gpu::CONTEXT_TYPE_OPENGLES2, + false /* is_passthrough_cmd_decoder */, + gles2::DisallowedFeatures()); + + auto* api = gl::g_current_gl_context; + const GLint kGLES2RequiredMinimumVertexAttribs = 8u; + GLint max_vertex_attribs = 0; + api->glGetIntegervFn(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attribs); + if (max_vertex_attribs < kGLES2RequiredMinimumVertexAttribs) + return false; + + context_state_ = std::make_unique<gles2::ContextState>( + feature_info_.get(), false /* track_texture_and_sampler_units */); + + context_state_->set_api(api); + context_state_->InitGenericAttribs(max_vertex_attribs); + + // Set all the default state because some GL drivers get it wrong. + // TODO(backer): Not all of this state needs to be initialized. Reduce the set + // if perf becomes a problem. + context_state_->InitCapabilities(nullptr); + context_state_->InitState(nullptr); + + if (use_virtualized_gl_contexts) { + auto virtual_context = base::MakeRefCounted<GLContextVirtual>( + share_group_.get(), real_context_.get(), + weak_ptr_factory_.GetWeakPtr()); + if (!virtual_context->Initialize(surface_.get(), gl::GLContextAttribs())) + return false; + context_ = std::move(virtual_context); + MakeCurrent(nullptr); + } + return true; +} + +bool RasterDecoderContextState::MakeCurrent(gl::GLSurface* surface) { + if (context_lost_) + return false; + + if (!context_->MakeCurrent(surface ? surface : surface_.get())) { + MarkContextLost(); + return false; + } + return true; +} + +void RasterDecoderContextState::MarkContextLost() { + if (!context_lost_) { + context_lost_ = true; + context_state_->MarkContextLost(); + if (gr_context) + gr_context->abandonContext(); + std::move(context_lost_callback).Run(); + } + // TODO notify gpu channel manager. +} + +bool RasterDecoderContextState::IsCurrent(gl::GLSurface* surface) { + return context_->IsCurrent(surface); +} + bool RasterDecoderContextState::OnMemoryDump( const base::trace_event::MemoryDumpArgs& args, base::trace_event::ProcessMemoryDump* pmd) { @@ -127,7 +202,7 @@ } // Ensure the context is current before doing any GPU cleanup. - context->MakeCurrent(surface.get()); + MakeCurrent(nullptr); switch (memory_pressure_level) { case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: @@ -155,28 +230,92 @@ gr_context->resetContext(); } -void RasterDecoderContextState::MarkContextLost() { - if (!context_lost) { - context_lost = true; - if (gr_context) - gr_context->abandonContext(); - std::move(context_lost_callback).Run(); - } +bool RasterDecoderContextState::initialized() const { + return true; } -bool RasterDecoderContextState::MakeCurrent(gl::GLSurface* current_surface) { - if (context_lost) - return false; - - if (context->IsCurrent(current_surface)) - return true; - - if (!context->MakeCurrent(current_surface ? current_surface - : surface.get())) { - MarkContextLost(); - return false; +const gles2::ContextState* RasterDecoderContextState::GetContextState() { + if (need_context_state_reset) { + // Returning nullptr to force full state restoration by the caller. We do + // this because GrContext changes to GL state are untracked in our + // context_state_. + return nullptr; } - return true; + return context_state_.get(); +} + +void RasterDecoderContextState::RestoreState( + const gles2::ContextState* prev_state) { + PessimisticallyResetGrContext(); + context_state_->RestoreState(prev_state); +} + +void RasterDecoderContextState::RestoreGlobalState() const { + PessimisticallyResetGrContext(); + context_state_->RestoreGlobalState(nullptr); +} +void RasterDecoderContextState::ClearAllAttributes() const {} + +void RasterDecoderContextState::RestoreActiveTexture() const { + PessimisticallyResetGrContext(); +} + +void RasterDecoderContextState::RestoreAllTextureUnitAndSamplerBindings( + const gles2::ContextState* prev_state) const { + PessimisticallyResetGrContext(); +} + +void RasterDecoderContextState::RestoreActiveTextureUnitBinding( + unsigned int target) const { + PessimisticallyResetGrContext(); +} + +void RasterDecoderContextState::RestoreBufferBinding(unsigned int target) { + PessimisticallyResetGrContext(); + if (target == GL_PIXEL_PACK_BUFFER) { + context_state_->UpdatePackParameters(); + } else if (target == GL_PIXEL_UNPACK_BUFFER) { + context_state_->UpdateUnpackParameters(); + } + context_state_->api()->glBindBufferFn(target, 0); +} + +void RasterDecoderContextState::RestoreBufferBindings() const { + PessimisticallyResetGrContext(); + context_state_->RestoreBufferBindings(); +} + +void RasterDecoderContextState::RestoreFramebufferBindings() const { + PessimisticallyResetGrContext(); + context_state_->fbo_binding_for_scissor_workaround_dirty = true; + context_state_->stencil_state_changed_since_validation = true; +} + +void RasterDecoderContextState::RestoreRenderbufferBindings() { + PessimisticallyResetGrContext(); + context_state_->RestoreRenderbufferBindings(); +} + +void RasterDecoderContextState::RestoreProgramBindings() const { + PessimisticallyResetGrContext(); + context_state_->RestoreProgramSettings(nullptr, false); +} + +void RasterDecoderContextState::RestoreTextureUnitBindings( + unsigned unit) const { + PessimisticallyResetGrContext(); +} + +void RasterDecoderContextState::RestoreVertexAttribArray(unsigned index) { + NOTIMPLEMENTED(); +} + +void RasterDecoderContextState::RestoreAllExternalTextureBindingsIfNeeded() { + PessimisticallyResetGrContext(); +} + +QueryManager* RasterDecoderContextState::GetQueryManager() { + return nullptr; } } // namespace raster
diff --git a/gpu/command_buffer/service/raster_decoder_context_state.h b/gpu/command_buffer/service/raster_decoder_context_state.h index 84bed6c..d34c6222 100644 --- a/gpu/command_buffer/service/raster_decoder_context_state.h +++ b/gpu/command_buffer/service/raster_decoder_context_state.h
@@ -7,8 +7,10 @@ #include "base/memory/memory_pressure_listener.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "base/trace_event/memory_dump_provider.h" #include "gpu/command_buffer/common/skia_utils.h" +#include "gpu/command_buffer/service/gl_context_virtual_delegate.h" #include "gpu/gpu_gles2_export.h" #include "third_party/skia/include/gpu/GrContext.h" #include "ui/gl/progress_reporter.h" @@ -25,14 +27,21 @@ namespace gpu { class GpuDriverBugWorkarounds; +struct GpuFeatureInfo; class GpuProcessActivityFlags; class ServiceTransferCache; +namespace gles2 { +class FeatureInfo; +struct ContextState; +} // namespace gles2 namespace raster { +// TODO(penghuang): Make RasterDecoderContextState a class. struct GPU_GLES2_EXPORT RasterDecoderContextState - : public base::RefCounted<RasterDecoderContextState>, - public base::trace_event::MemoryDumpProvider { + : public base::trace_event::MemoryDumpProvider, + public gpu::GLContextVirtualDelegate, + public base::RefCounted<RasterDecoderContextState> { public: // TODO: Refactor code to have seperate constructor for GL and Vulkan and not // initialize/use GL related info for vulkan and vice-versa. @@ -48,20 +57,27 @@ GrContextOptions::PersistentCache* cache, GpuProcessActivityFlags* activity_flags = nullptr, gl::ProgressReporter* progress_reporter = nullptr); + + // TODO(penghuang) do not depend on ContextGroup. + bool InitializeGL(const GpuDriverBugWorkarounds& gpu_driver_bug_workarounds, + const GpuFeatureInfo& gpu_feature_info); + + bool MakeCurrent(gl::GLSurface* surface); + void MarkContextLost(); + bool IsCurrent(gl::GLSurface* surface); + void PurgeMemory( base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); void PessimisticallyResetGrContext() const; - void MarkContextLost(); + gl::GLShareGroup* share_group() { return share_group_.get(); } + gl::GLContext* context() { return context_.get(); } + gl::GLContext* real_context() { return real_context_.get(); } + gl::GLSurface* surface() { return surface_.get(); } + gles2::ContextState* context_state() const { return context_state_.get(); } + bool context_lost() const { return context_lost_; } - // surface == nullptr indicates that caller doesn't care what surface is - // current with the context. - bool MakeCurrent(gl::GLSurface* current_surface); - - scoped_refptr<gl::GLShareGroup> share_group; - scoped_refptr<gl::GLSurface> surface; - scoped_refptr<gl::GLContext> context; sk_sp<GrContext> owned_gr_context; std::unique_ptr<ServiceTransferCache> transfer_cache; const bool use_virtualized_gl_contexts = false; @@ -69,7 +85,6 @@ viz::VulkanContextProvider* vk_context_provider = nullptr; GrContext* gr_context = nullptr; const bool use_vulkan_gr_context = false; - bool context_lost = false; size_t glyph_cache_max_texture_bytes = 0u; // |need_context_state_reset| is set whenever Skia may have altered the @@ -84,7 +99,43 @@ private: friend class base::RefCounted<RasterDecoderContextState>; + ~RasterDecoderContextState() override; + + // gpu::GLContextVirtualDelegate implementation. + bool initialized() const override; + const gles2::ContextState* GetContextState() override; + void RestoreState(const gles2::ContextState* prev_state) override; + void RestoreGlobalState() const override; + void ClearAllAttributes() const override; + void RestoreActiveTexture() const override; + void RestoreAllTextureUnitAndSamplerBindings( + const gles2::ContextState* prev_state) const override; + void RestoreActiveTextureUnitBinding(unsigned int target) const override; + void RestoreBufferBinding(unsigned int target) override; + void RestoreBufferBindings() const override; + void RestoreFramebufferBindings() const override; + void RestoreRenderbufferBindings() override; + void RestoreProgramBindings() const override; + void RestoreTextureUnitBindings(unsigned unit) const override; + void RestoreVertexAttribArray(unsigned index) override; + void RestoreAllExternalTextureBindingsIfNeeded() override; + QueryManager* GetQueryManager() override; + + scoped_refptr<gl::GLShareGroup> share_group_; + scoped_refptr<gl::GLContext> context_; + scoped_refptr<gl::GLContext> real_context_; + scoped_refptr<gl::GLSurface> surface_; + scoped_refptr<gles2::FeatureInfo> feature_info_; + + // raster decoders and display compositor share this context_state_. + std::unique_ptr<gles2::ContextState> context_state_; + + bool context_lost_ = false; + + base::WeakPtrFactory<RasterDecoderContextState> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(RasterDecoderContextState); }; } // namespace raster
diff --git a/gpu/command_buffer/service/raster_decoder_unittest.cc b/gpu/command_buffer/service/raster_decoder_unittest.cc index 89d2836..efce9b9 100644 --- a/gpu/command_buffer/service/raster_decoder_unittest.cc +++ b/gpu/command_buffer/service/raster_decoder_unittest.cc
@@ -214,6 +214,10 @@ gl::GLSurfaceTestSupport::InitializeOneOff(); gpu::GpuDriverBugWorkarounds workarounds; + GpuFeatureInfo gpu_feature_info; + gpu_feature_info.status_values[GPU_FEATURE_TYPE_OOP_RASTERIZATION] = + kGpuFeatureStatusEnabled; + scoped_refptr<gl::GLShareGroup> share_group = new gl::GLShareGroup(); scoped_refptr<gl::GLSurface> surface = gl::init::CreateOffscreenGLSurface(gfx::Size()); @@ -225,10 +229,8 @@ std::move(share_group), std::move(surface), std::move(context), false /* use_virtualized_gl_contexts */, base::DoNothing()); context_state_->InitializeGrContext(workarounds, nullptr); + context_state_->InitializeGL(workarounds, gpu_feature_info); - GpuFeatureInfo gpu_feature_info; - gpu_feature_info.status_values[GPU_FEATURE_TYPE_OOP_RASTERIZATION] = - kGpuFeatureStatusEnabled; scoped_refptr<gles2::FeatureInfo> feature_info = new gles2::FeatureInfo(workarounds, gpu_feature_info); group_ = new gles2::ContextGroup( @@ -263,10 +265,10 @@ ContextCreationAttribs attribs; attribs.enable_oop_rasterization = true; attribs.enable_raster_interface = true; - CHECK_EQ( - decoder->Initialize(context_state_->surface, context_state_->context, - true, gles2::DisallowedFeatures(), attribs), - ContextResult::kSuccess); + CHECK_EQ(decoder->Initialize(context_state_->surface(), + context_state_->context(), true, + gles2::DisallowedFeatures(), attribs), + ContextResult::kSuccess); return decoder; } @@ -313,7 +315,7 @@ EXPECT_TRUE(context_state_->need_context_state_reset); decoder1->Destroy(true); - context_state_->context->MakeCurrent(context_state_->surface.get()); + context_state_->MakeCurrent(nullptr); decoder2->Destroy(true); // Make sure the context is preserved across decoders.
diff --git a/gpu/command_buffer/service/raster_decoder_unittest_base.cc b/gpu/command_buffer/service/raster_decoder_unittest_base.cc index 0c9edddb..af44348 100644 --- a/gpu/command_buffer/service/raster_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/raster_decoder_unittest_base.cc
@@ -230,7 +230,10 @@ // we can use the ContextGroup to figure out how the real RasterDecoder // will initialize itself. command_buffer_service_.reset(new FakeCommandBufferServiceBase()); - mock_decoder_.reset(new MockRasterDecoder(command_buffer_service_.get())); + command_buffer_service_for_mock_decoder_.reset( + new FakeCommandBufferServiceBase()); + mock_decoder_.reset( + new MockRasterDecoder(command_buffer_service_for_mock_decoder_.get())); EXPECT_EQ(group_->Initialize(mock_decoder_.get(), context_type, gles2::DisallowedFeatures()), @@ -250,6 +253,14 @@ init.lose_context_when_out_of_memory; attribs.context_type = context_type; + // Setup expections for RasterDecoderContextState::InitializeGL() + // It will initialize a FeatureInfo and + gles2::TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( + gl_.get(), all_extensions.c_str(), "" /* gl_renderer */, + init.gl_version.c_str(), CONTEXT_TYPE_OPENGLES2); + EXPECT_CALL(*gl_, GetIntegerv(GL_MAX_VERTEX_ATTRIBS, _)) + .WillOnce(SetArgPointee<1>(8u)) + .RetiresOnSaturation(); SetupInitCapabilitiesExpectations(group_->feature_info()->IsES3Capable()); SetupInitStateExpectations(group_->feature_info()->IsES3Capable()); @@ -257,6 +268,10 @@ new gl::GLShareGroup(), surface_, context_, feature_info->workarounds().use_virtualized_gl_contexts, base::DoNothing()); + + raster_decoder_context_state_->InitializeGL(init.workarounds, + gpu_feature_info); + decoder_.reset(RasterDecoder::Create(this, command_buffer_service_.get(), &outputter_, group_.get(), raster_decoder_context_state_)); @@ -266,9 +281,10 @@ copy_texture_manager_ = new gles2::MockCopyTextureResourceManager(); decoder_->SetCopyTextureResourceManagerForTest(copy_texture_manager_); - ASSERT_EQ(decoder_->Initialize(surface_, context_, true, - gles2::DisallowedFeatures(), attribs), - gpu::ContextResult::kSuccess); + ASSERT_EQ( + decoder_->Initialize(surface_, raster_decoder_context_state_->context(), + true, gles2::DisallowedFeatures(), attribs), + gpu::ContextResult::kSuccess); EXPECT_CALL(*context_, MakeCurrent(surface_.get())).WillOnce(Return(true)); if (context_->WasAllocatedUsingRobustnessExtension()) { @@ -302,6 +318,7 @@ decoder_.reset(); group_->Destroy(mock_decoder_.get(), false); command_buffer_service_.reset(); + command_buffer_service_for_mock_decoder_.reset(); ::gl::MockGLInterface::SetGLInterface(nullptr); gl_.reset(); gl::init::ShutdownGL(false);
diff --git a/gpu/command_buffer/service/raster_decoder_unittest_base.h b/gpu/command_buffer/service/raster_decoder_unittest_base.h index 1eae7d8..84e84f9b 100644 --- a/gpu/command_buffer/service/raster_decoder_unittest_base.h +++ b/gpu/command_buffer/service/raster_decoder_unittest_base.h
@@ -250,6 +250,8 @@ std::unique_ptr<FakeCommandBufferServiceBase> command_buffer_service_; gles2::TraceOutputter outputter_; std::unique_ptr<MockRasterDecoder> mock_decoder_; + std::unique_ptr<FakeCommandBufferServiceBase> + command_buffer_service_for_mock_decoder_; std::unique_ptr<RasterDecoder> decoder_; GLuint client_texture_id_;
diff --git a/gpu/command_buffer/service/raster_decoder_unittest_context_lost.cc b/gpu/command_buffer/service/raster_decoder_unittest_context_lost.cc index be57e397a..57bd17f7 100644 --- a/gpu/command_buffer/service/raster_decoder_unittest_context_lost.cc +++ b/gpu/command_buffer/service/raster_decoder_unittest_context_lost.cc
@@ -145,6 +145,7 @@ EXPECT_CALL(*context_, MakeCurrent(surface_.get())).WillOnce(Return(false)); // Expect the group to be lost. EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown)).Times(1); + EXPECT_FALSE(decoder_->WasContextLost()); decoder_->MakeCurrent(); EXPECT_TRUE(decoder_->WasContextLost()); EXPECT_EQ(error::kMakeCurrentFailed, GetContextLostReason()); @@ -285,18 +286,6 @@ EXPECT_EQ(error::kInnocent, GetContextLostReason()); } -TEST_P(RasterDecoderLostContextTest, LoseVirtualContextWithRobustness) { - InitWithVirtualContextsAndRobustness(); - EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown)).Times(1); - // Signal guilty.... - DoGetErrorWithContextLost(GL_GUILTY_CONTEXT_RESET_KHR); - EXPECT_TRUE(decoder_->WasContextLost()); - EXPECT_TRUE(decoder_->WasContextLostByRobustnessExtension()); - // ...but make sure we don't pretend, since for virtual contexts we don't - // know if this was really the guilty client. - EXPECT_EQ(error::kUnknown, GetContextLostReason()); -} - TEST_P(RasterDecoderLostContextTest, LoseGroupFromRobustness) { // If one context in a group is lost through robustness, // the other ones should also get lost and query the reset status.
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer_unittest.cc b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer_unittest.cc index 99fde99..a810817 100644 --- a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer_unittest.cc +++ b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer_unittest.cc
@@ -16,6 +16,7 @@ #include "gpu/command_buffer/service/shared_image_representation.h" #include "gpu/command_buffer/service/texture_manager.h" #include "gpu/config/gpu_driver_bug_workarounds.h" +#include "gpu/config/gpu_feature_info.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkSurface.h" @@ -56,6 +57,7 @@ std::move(share_group), surface_, context_, false /* use_virtualized_gl_contexts */, base::DoNothing()); context_state_->InitializeGrContext(workarounds, nullptr); + context_state_->InitializeGL(workarounds, GpuFeatureInfo()); memory_type_tracker_ = std::make_unique<MemoryTypeTracker>(nullptr); shared_image_representation_factory_ =
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc index 6e6b802..c813a51 100644 --- a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc +++ b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc
@@ -59,6 +59,7 @@ std::move(share_group), surface_, context_, false /* use_virtualized_gl_contexts */, base::DoNothing()); context_state_->InitializeGrContext(workarounds, nullptr); + context_state_->InitializeGL(workarounds, GpuFeatureInfo()); memory_type_tracker_ = std::make_unique<MemoryTypeTracker>(nullptr); shared_image_representation_factory_ =
diff --git a/gpu/command_buffer/service/wrapped_sk_image.cc b/gpu/command_buffer/service/wrapped_sk_image.cc index 911e917..ae7940f 100644 --- a/gpu/command_buffer/service/wrapped_sk_image.cc +++ b/gpu/command_buffer/service/wrapped_sk_image.cc
@@ -30,9 +30,9 @@ class WrappedSkImage : public SharedImageBacking { public: ~WrappedSkImage() override { - DCHECK(context_state_->context_lost || - context_state_->context->IsCurrent(nullptr)); - if (!context_state_->context_lost) + DCHECK(context_state_->context_lost() || + context_state_->context()->IsCurrent(nullptr)); + if (!context_state_->context_lost()) context_state_->need_context_state_reset = true; } @@ -70,9 +70,9 @@ sk_sp<SkSurface> GetSkSurface(int final_msaa_count, SkColorType color_type, const SkSurfaceProps& surface_props) { - if (context_state_->context_lost) + if (context_state_->context_lost()) return nullptr; - DCHECK(context_state_->context->IsCurrent(nullptr)); + DCHECK(context_state_->context()->IsCurrent(nullptr)); GrBackendTexture gr_texture = image_->getBackendTexture(/*flushPendingGrContextIO=*/true); DCHECK(gr_texture.isValid()); @@ -113,9 +113,9 @@ } bool Initialize(const SkImageInfo& info) { - if (context_state_->context_lost) + if (context_state_->context_lost()) return false; - DCHECK(context_state_->context->IsCurrent(nullptr)); + DCHECK(context_state_->context()->IsCurrent(nullptr)); context_state_->need_context_state_reset = true;
diff --git a/gpu/command_buffer/tests/fuzzer_main.cc b/gpu/command_buffer/tests/fuzzer_main.cc index daad321..cf0e8a5 100644 --- a/gpu/command_buffer/tests/fuzzer_main.cc +++ b/gpu/command_buffer/tests/fuzzer_main.cc
@@ -366,10 +366,13 @@ share_group_, surface_, context_, config_.workarounds.use_virtualized_gl_contexts, base::DoNothing()); context_state->InitializeGrContext(config_.workarounds, nullptr); + context_state->InitializeGL(config_.workarounds, gpu_feature_info); + auto* context = context_state->context(); decoder_.reset(raster::RasterDecoder::Create( command_buffer_.get(), command_buffer_->service(), &outputter_, context_group.get(), std::move(context_state))); #else + auto* context = context_.get(); decoder_.reset(gles2::GLES2Decoder::Create( command_buffer_.get(), command_buffer_->service(), &outputter_, context_group.get())); @@ -377,7 +380,7 @@ decoder_->GetLogger()->set_log_synthesized_gl_errors(false); - auto result = decoder_->Initialize(surface_.get(), context_.get(), true, + auto result = decoder_->Initialize(surface_.get(), context, true, gles2::DisallowedFeatures(), config_.attrib_helper); if (result != gpu::ContextResult::kSuccess)
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc index 827a1f5..9cd41524 100644 --- a/gpu/ipc/in_process_command_buffer.cc +++ b/gpu/ipc/in_process_command_buffer.cc
@@ -563,6 +563,8 @@ context_state_ = base::MakeRefCounted<raster::RasterDecoderContextState>( gl_share_group_, surface_, real_context, use_virtualized_gl_context_, base::DoNothing()); + context_state_->InitializeGL(workarounds, + task_executor_->gpu_feature_info()); gr_shader_cache_ = params.gr_shader_cache; context_state_->InitializeGrContext(workarounds, params.gr_shader_cache, params.activity_flags); @@ -582,18 +584,22 @@ } if (use_virtualized_gl_context_) { - context_ = base::MakeRefCounted<GLContextVirtual>( - gl_share_group_.get(), real_context.get(), decoder_->AsWeakPtr()); - if (!context_->Initialize( - surface_.get(), - GenerateGLContextAttribs(params.attribs, context_group_.get()))) { - // TODO(piman): This might not be fatal, we could recurse into - // CreateGLContext to get more info, tho it should be exceedingly - // rare and may not be recoverable anyway. - DestroyOnGpuThread(); - LOG(ERROR) << "ContextResult::kFatalFailure: " - "Failed to initialize virtual GL context."; - return gpu::ContextResult::kFatalFailure; + if (context_state_) { + context_ = context_state_->context(); + } else { + context_ = base::MakeRefCounted<GLContextVirtual>( + gl_share_group_.get(), real_context.get(), decoder_->AsWeakPtr()); + if (!context_->Initialize(surface_.get(), + GenerateGLContextAttribs( + params.attribs, context_group_.get()))) { + // TODO(piman): This might not be fatal, we could recurse into + // CreateGLContext to get more info, tho it should be exceedingly + // rare and may not be recoverable anyway. + DestroyOnGpuThread(); + LOG(ERROR) << "ContextResult::kFatalFailure: " + "Failed to initialize virtual GL context."; + return gpu::ContextResult::kFatalFailure; + } } if (!context_->MakeCurrent(surface_.get())) {
diff --git a/gpu/ipc/service/gpu_channel_manager.cc b/gpu/ipc/service/gpu_channel_manager.cc index e72dc596..124f6865 100644 --- a/gpu/ipc/service/gpu_channel_manager.cc +++ b/gpu/ipc/service/gpu_channel_manager.cc
@@ -319,7 +319,7 @@ if (raster_decoder_context_state_) { gr_cache_controller_.reset(); - raster_decoder_context_state_->context_lost = true; + raster_decoder_context_state_->MarkContextLost(); raster_decoder_context_state_.reset(); } @@ -353,7 +353,7 @@ scoped_refptr<raster::RasterDecoderContextState> GpuChannelManager::GetRasterDecoderContextState(ContextResult* result) { if (raster_decoder_context_state_ && - !raster_decoder_context_state_->context_lost) { + !raster_decoder_context_state_->context_lost()) { *result = ContextResult::kSuccess; return raster_decoder_context_state_; } @@ -442,6 +442,14 @@ /*synthetic_loss=*/false), vulkan_context_provider_); + if (!vulkan_context_provider_) { + if (!raster_decoder_context_state_->InitializeGL( + gpu_driver_bug_workarounds(), gpu_feature_info())) { + raster_decoder_context_state_ = nullptr; + return nullptr; + } + } + const bool enable_raster_transport = gpu_feature_info_.status_values[GPU_FEATURE_TYPE_OOP_RASTERIZATION] == gpu::kGpuFeatureStatusEnabled;
diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc index 90c49730..1c5b6fdf 100644 --- a/gpu/ipc/service/gpu_init.cc +++ b/gpu/ipc/service/gpu_init.cc
@@ -519,4 +519,8 @@ CollectContextGraphicsInfo(&gpu_info_, gpu_preferences_); } +scoped_refptr<gl::GLSurface> GpuInit::TakeDefaultOffscreenSurface() { + return std::move(default_offscreen_surface_); +} + } // namespace gpu
diff --git a/gpu/ipc/service/gpu_init.h b/gpu/ipc/service/gpu_init.h index eeba59e..0889c59d 100644 --- a/gpu/ipc/service/gpu_init.h +++ b/gpu/ipc/service/gpu_init.h
@@ -66,9 +66,7 @@ std::unique_ptr<GpuWatchdogThread> TakeWatchdogThread() { return std::move(watchdog_thread_); } - scoped_refptr<gl::GLSurface> TakeDefaultOffscreenSurface() { - return std::move(default_offscreen_surface_); - } + scoped_refptr<gl::GLSurface> TakeDefaultOffscreenSurface(); bool init_successful() const { return init_successful_; } #if BUILDFLAG(ENABLE_VULKAN) VulkanImplementation* vulkan_implementation() {
diff --git a/gpu/ipc/service/raster_command_buffer_stub.cc b/gpu/ipc/service/raster_command_buffer_stub.cc index 78adb55..1751107 100644 --- a/gpu/ipc/service/raster_command_buffer_stub.cc +++ b/gpu/ipc/service/raster_command_buffer_stub.cc
@@ -119,8 +119,8 @@ return result; } - surface_ = raster_decoder_context_state->surface; - share_group_ = raster_decoder_context_state->share_group; + surface_ = raster_decoder_context_state->surface(); + share_group_ = raster_decoder_context_state->share_group(); use_virtualized_gl_context_ = raster_decoder_context_state->use_virtualized_gl_contexts; @@ -138,26 +138,9 @@ crash_keys::gpu_gl_context_is_virtual.Set(use_virtualized_gl_context_ ? "1" : "0"); - scoped_refptr<gl::GLContext> context = raster_decoder_context_state->context; - if (use_virtualized_gl_context_) { - context = base::MakeRefCounted<GLContextVirtual>( - share_group_.get(), context.get(), decoder->AsWeakPtr()); - if (!context->Initialize(surface_.get(), - GenerateGLContextAttribs(init_params.attribs, - context_group_.get()))) { - // The real context created above for the default offscreen surface - // might not be compatible with this surface. - context = nullptr; - // TODO(piman): This might not be fatal, we could recurse into - // CreateGLContext to get more info, tho it should be exceedingly - // rare and may not be recoverable anyway. - LOG(ERROR) << "ContextResult::kFatalFailure: " - "Failed to initialize virtual GL context."; - return gpu::ContextResult::kFatalFailure; - } - } - - if (!context->MakeCurrent(surface_.get())) { + scoped_refptr<gl::GLContext> context = + raster_decoder_context_state->context(); + if (!raster_decoder_context_state->MakeCurrent(nullptr)) { LOG(ERROR) << "ContextResult::kTransientFailure: " "Failed to make context current."; return gpu::ContextResult::kTransientFailure; @@ -196,22 +179,6 @@ if (!active_url_.is_empty()) manager->delegate()->DidCreateOffscreenContext(active_url_); - if (use_virtualized_gl_context_) { - // If virtualized GL contexts are in use, then real GL context state - // is in an indeterminate state, since the GLStateRestorer was not - // initialized at the time the GLContextVirtual was made current. In - // the case that this command decoder is the next one to be - // processed, force a "full virtual" MakeCurrent to be performed. - // Note that GpuChannel's initialization of the gpu::Capabilities - // expects the context to be left current. - context->ForceReleaseVirtuallyCurrent(); - if (!context->MakeCurrent(surface_.get())) { - LOG(ERROR) << "ContextResult::kTransientFailure: " - "Failed to make context current after initialization."; - return gpu::ContextResult::kTransientFailure; - } - } - manager->delegate()->DidCreateContextSuccessfully(); initialized_ = true; return gpu::ContextResult::kSuccess;
diff --git a/gpu/ipc/service/shared_image_stub.cc b/gpu/ipc/service/shared_image_stub.cc index 6b7ed3ec..26aebcd 100644 --- a/gpu/ipc/service/shared_image_stub.cc +++ b/gpu/ipc/service/shared_image_stub.cc
@@ -146,13 +146,16 @@ bool SharedImageStub::MakeContextCurrent() { DCHECK(context_state_); - DCHECK(!context_state_->context_lost); + DCHECK(!context_state_->context_lost()); // |factory_| never writes to the surface, so pass nullptr to // improve performance. https://crbug.com/457431 - if (context_state_->MakeCurrent(nullptr)) { + auto* context = context_state_->real_context(); + if (context->IsCurrent(nullptr) || + context_state_->real_context()->MakeCurrent(context_state_->surface())) { return true; } else { + context_state_->MarkContextLost(); LOG(ERROR) << "SharedImageStub: MakeCurrent failed"; return false; } @@ -169,7 +172,7 @@ return false; } DCHECK(context_state_); - DCHECK(!context_state_->context_lost); + DCHECK(!context_state_->context_lost()); if (!MakeContextCurrent()) return false; gpu::GpuMemoryBufferFactory* gmb_factory = @@ -184,13 +187,12 @@ return true; } else { DCHECK(context_state_); - if (context_state_->context_lost) { + if (context_state_->context_lost()) { LOG(ERROR) << "SharedImageStub: context already lost"; return false; } else { if (MakeContextCurrent()) return true; - context_state_->context_lost = true; return false; } }
diff --git a/gpu/vulkan/BUILD.gn b/gpu/vulkan/BUILD.gn index 3e8862d..9e910c5 100644 --- a/gpu/vulkan/BUILD.gn +++ b/gpu/vulkan/BUILD.gn
@@ -2,11 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("features.gni") +import("//build/buildflag_header.gni") import("//build/config/jumbo.gni") import("//build/config/ui.gni") -import("//build/buildflag_header.gni") import("//testing/test.gni") +import("features.gni") # Generate a buildflag header for compile-time checking of Vulkan support. buildflag_header("buildflags") { @@ -40,6 +40,9 @@ configs += [ "//build/config:precompiled_headers" ] defines = [ "VULKAN_IMPLEMENTATION" ] + if (is_android) { + defines += [ "VK_USE_PLATFORM_ANDROID_KHR" ] + } all_dependent_configs = [ "//third_party/vulkan:vulkan_config" ]
diff --git a/gpu/vulkan/android/vulkan_android_unittests.cc b/gpu/vulkan/android/vulkan_android_unittests.cc index 61618a10..a27c8e08 100644 --- a/gpu/vulkan/android/vulkan_android_unittests.cc +++ b/gpu/vulkan/android/vulkan_android_unittests.cc
@@ -4,6 +4,8 @@ #include <sys/eventfd.h> +#include "base/android/android_hardware_buffer_compat.h" +#include "base/android/scoped_hardware_buffer_handle.h" #include "base/files/scoped_file.h" #include "components/viz/common/gpu/vulkan_in_process_context_provider.h" #include "gpu/vulkan/android/vulkan_implementation_android.h" @@ -18,20 +20,33 @@ // Create a vulkan implementation. vk_implementation_ = std::make_unique<VulkanImplementationAndroid>(); ASSERT_TRUE(vk_implementation_); - ASSERT_TRUE(vk_implementation_->InitializeVulkanInstance()); - // Create vulkan context provider. + // This call checks for all instance extensions. Let the test pass if this + // call fails since many bots would not have this extension present. + if (!vk_implementation_->InitializeVulkanInstance()) + return; + + // Create vulkan context provider. This call checks for all device + // extensions. Let the test pass if this call fails since many bots would + // not have this extension present. vk_context_provider_ = viz::VulkanInProcessContextProvider::Create(vk_implementation_.get()); - ASSERT_TRUE(vk_context_provider_); + if (!vk_context_provider_) + return; // Get the VkDevice. vk_device_ = vk_context_provider_->GetDeviceQueue()->GetVulkanDevice(); ASSERT_TRUE(vk_device_); + + // Get the physical device. + vk_phy_device_ = + vk_context_provider_->GetDeviceQueue()->GetVulkanPhysicalDevice(); + ASSERT_TRUE(vk_phy_device_); } void TearDown() override { - vk_context_provider_->Destroy(); + if (vk_context_provider_) + vk_context_provider_->Destroy(); vk_device_ = VK_NULL_HANDLE; } @@ -39,9 +54,13 @@ std::unique_ptr<VulkanImplementationAndroid> vk_implementation_; scoped_refptr<viz::VulkanInProcessContextProvider> vk_context_provider_; VkDevice vk_device_; + VkPhysicalDevice vk_phy_device_; }; TEST_F(VulkanImplementationAndroidTest, ExportImportSyncFd) { + if (!vk_implementation_ || !vk_context_provider_) + return; + // Create a vk semaphore which can be exported. // To create a semaphore whose payload can be exported to external handles, // add the VkExportSemaphoreCreateInfo structure to the pNext chain of the @@ -93,4 +112,41 @@ vkDestroySemaphore(vk_device_, semaphore2, nullptr); } +TEST_F(VulkanImplementationAndroidTest, CreateVkImageFromAHB) { + if (!vk_implementation_ || !vk_context_provider_) + return; + + // Setup and Create an AHardwareBuffer. + AHardwareBuffer* buffer = nullptr; + AHardwareBuffer_Desc hwb_desc; + hwb_desc.width = 128; + hwb_desc.height = 128; + hwb_desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; + hwb_desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | + AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT; + hwb_desc.layers = 1; + hwb_desc.stride = 0; + hwb_desc.rfu0 = 0; + hwb_desc.rfu1 = 0; + + // Allocate an AHardwareBuffer. + base::AndroidHardwareBufferCompat::GetInstance().Allocate(&hwb_desc, &buffer); + EXPECT_TRUE(buffer); + + // Create a vkimage and import the AHB into it. + const gfx::Size size(hwb_desc.width, hwb_desc.height); + VkImage vk_image; + VkImageCreateInfo vk_image_info; + VkDeviceMemory vk_device_memory; + VkDeviceSize mem_allocation_size; + EXPECT_TRUE(vk_implementation_->CreateVkImageAndImportAHB( + vk_device_, vk_phy_device_, size, + base::android::ScopedHardwareBufferHandle::Adopt(buffer), &vk_image, + &vk_image_info, &vk_device_memory, &mem_allocation_size)); + + // Free up resources. + vkDestroyImage(vk_device_, vk_image, nullptr); + vkFreeMemory(vk_device_, vk_device_memory, nullptr); +} + } // namespace gpu
diff --git a/gpu/vulkan/android/vulkan_implementation_android.cc b/gpu/vulkan/android/vulkan_implementation_android.cc index 54cb905..e2bfe44 100644 --- a/gpu/vulkan/android/vulkan_implementation_android.cc +++ b/gpu/vulkan/android/vulkan_implementation_android.cc
@@ -4,6 +4,7 @@ #include "gpu/vulkan/android/vulkan_implementation_android.h" +#include "base/android/android_hardware_buffer_compat.h" #include "base/bind_helpers.h" #include "base/files/file_path.h" #include "base/logging.h" @@ -22,7 +23,6 @@ bool VulkanImplementationAndroid::InitializeVulkanInstance() { std::vector<const char*> required_extensions = { VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME}; @@ -86,9 +86,15 @@ std::vector<const char*> VulkanImplementationAndroid::GetRequiredDeviceExtensions() { + // VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME also requires + // VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME as per spec. return {VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME, - VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME}; + VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, + VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME, + VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, + VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, + VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME}; } VkFence VulkanImplementationAndroid::CreateVkFenceForGpuFence( @@ -165,4 +171,195 @@ return true; } +bool VulkanImplementationAndroid::CreateVkImageAndImportAHB( + const VkDevice& vk_device, + const VkPhysicalDevice& vk_physical_device, + const gfx::Size& size, + base::android::ScopedHardwareBufferHandle ahb_handle, + VkImage* vk_image, + VkImageCreateInfo* vk_image_info, + VkDeviceMemory* vk_device_memory, + VkDeviceSize* mem_allocation_size) { + DCHECK(ahb_handle.is_valid()); + DCHECK(vk_image); + DCHECK(vk_image_info); + DCHECK(vk_device_memory); + DCHECK(mem_allocation_size); + + // To obtain format properties of an Android hardware buffer, include an + // instance of VkAndroidHardwareBufferFormatPropertiesANDROID in the pNext + // chain of the VkAndroidHardwareBufferPropertiesANDROID instance passed to + // vkGetAndroidHardwareBufferPropertiesANDROID. + VkAndroidHardwareBufferFormatPropertiesANDROID ahb_format_props; + ahb_format_props.sType = + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID; + ahb_format_props.pNext = nullptr; + + VkAndroidHardwareBufferPropertiesANDROID ahb_props; + ahb_props.sType = + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID; + ahb_props.pNext = &ahb_format_props; + + bool result = vkGetAndroidHardwareBufferPropertiesANDROID( + vk_device, ahb_handle.get(), &ahb_props); + if (result != VK_SUCCESS) { + LOG(ERROR) << "GetAndroidHardwareBufferProperties failed : " << result; + return false; + } + + // To create an image with an external format, include an instance of + // VkExternalFormatANDROID in the pNext chain of VkImageCreateInfo. + VkExternalFormatANDROID external_format; + external_format.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID; + external_format.pNext = nullptr; + + // If externalFormat is zero, the effect is as if the VkExternalFormatANDROID + // structure was not present. Otherwise, the image will have the specified + // external format. + external_format.externalFormat = 0; + + // If image has an external format, format must be VK_FORMAT_UNDEFINED. + if (ahb_format_props.format == VK_FORMAT_UNDEFINED) { + // externalFormat must be 0 or a value returned in the externalFormat member + // of VkAndroidHardwareBufferFormatPropertiesANDROID by an earlier call to + // vkGetAndroidHardwareBufferPropertiesANDROID. + external_format.externalFormat = ahb_format_props.externalFormat; + } + + // To define a set of external memory handle types that may be used as backing + // store for an image, add a VkExternalMemoryImageCreateInfo structure to the + // pNext chain of the VkImageCreateInfo structure. + VkExternalMemoryImageCreateInfo external_memory_image_info; + external_memory_image_info.sType = + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; + external_memory_image_info.pNext = &external_format; + external_memory_image_info.handleTypes = + VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID; + + // Intended usage of the image. + VkImageUsageFlags usage_flags = 0; + + // Get the AHB description. + AHardwareBuffer_Desc ahb_desc = {}; + base::AndroidHardwareBufferCompat::GetInstance().Describe(ahb_handle.get(), + &ahb_desc); + + // Get Vulkan Image usage flag equivalence of AHB usage. + if (ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) { + usage_flags = usage_flags | VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; + } + if (ahb_desc.usage & AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT) { + usage_flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + } + if (ahb_desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) { + usage_flags |= VK_IMAGE_CREATE_PROTECTED_BIT; + } + + // TODO(vikassoni) : AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP is supported from API + // level 28 which is not part of current android_ndk version in chromium. Add + // equvalent VK usage later. + + if (!usage_flags) { + LOG(ERROR) << "No valid usage flags found"; + return false; + } + + // Find the first set bit to use as memoryTypeIndex. + uint32_t memory_type_bits = ahb_props.memoryTypeBits; + int32_t type_index = -1; + for (uint32_t i = 0; memory_type_bits; + memory_type_bits = memory_type_bits >> 0x1, ++i) { + if (memory_type_bits & 0x1) { + type_index = i; + break; + } + } + if (type_index == -1) { + LOG(ERROR) << "No valid memoryTypeIndex found"; + return false; + } + + // Populate VkImageCreateInfo. + vk_image_info->sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + vk_image_info->pNext = &external_memory_image_info; + vk_image_info->flags = 0; + vk_image_info->imageType = VK_IMAGE_TYPE_2D; + vk_image_info->format = ahb_format_props.format; + vk_image_info->extent = {static_cast<uint32_t>(size.width()), + static_cast<uint32_t>(size.height()), 1}; + vk_image_info->mipLevels = 1; + vk_image_info->arrayLayers = 1; + vk_image_info->samples = VK_SAMPLE_COUNT_1_BIT; + vk_image_info->tiling = VK_IMAGE_TILING_OPTIMAL; + vk_image_info->usage = usage_flags; + vk_image_info->sharingMode = VK_SHARING_MODE_EXCLUSIVE; + vk_image_info->queueFamilyIndexCount = 0; + vk_image_info->pQueueFamilyIndices = 0; + vk_image_info->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + // Create Vk Image. + result = vkCreateImage(vk_device, vk_image_info, nullptr, vk_image); + if (result != VK_SUCCESS) { + LOG(ERROR) << "vkCreateImage failed : " << result; + return false; + } + + // To import memory created outside of the current Vulkan instance from an + // Android hardware buffer, add a VkImportAndroidHardwareBufferInfoANDROID + // structure to the pNext chain of the VkMemoryAllocateInfo structure. + VkImportAndroidHardwareBufferInfoANDROID ahb_import_info; + ahb_import_info.sType = + VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID; + ahb_import_info.pNext = nullptr; + ahb_import_info.buffer = ahb_handle.get(); + + // If the VkMemoryAllocateInfo pNext chain includes a + // VkMemoryDedicatedAllocateInfo structure, then that structure includes a + // handle of the sole buffer or image resource that the memory can be bound + // to. + VkMemoryDedicatedAllocateInfo dedicated_alloc_info; + dedicated_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO; + dedicated_alloc_info.pNext = &ahb_import_info; + dedicated_alloc_info.image = *vk_image; + dedicated_alloc_info.buffer = VK_NULL_HANDLE; + + // An instance of the VkMemoryAllocateInfo structure defines a memory import + // operation. + VkMemoryAllocateInfo mem_alloc_info; + mem_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + mem_alloc_info.pNext = &dedicated_alloc_info; + + // If the parameters define an import operation and the external handle type + // is VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, + // allocationSize must be the size returned by + // vkGetAndroidHardwareBufferPropertiesANDROID for the Android hardware + // buffer. + mem_alloc_info.allocationSize = ahb_props.allocationSize; + mem_alloc_info.memoryTypeIndex = type_index; + + // A Vulkan device operates on data in device memory via memory objects that + // are represented in the API by a VkDeviceMemory handle. + // Allocate memory. + result = + vkAllocateMemory(vk_device, &mem_alloc_info, nullptr, vk_device_memory); + if (result != VK_SUCCESS) { + LOG(ERROR) << "vkAllocateMemory failed : " << result; + vkDestroyImage(vk_device, *vk_image, nullptr); + return false; + } + + // Attach memory to the image object. + result = vkBindImageMemory(vk_device, *vk_image, *vk_device_memory, 0); + if (result != VK_SUCCESS) { + LOG(ERROR) << "vkBindImageMemory failed : " << result; + vkDestroyImage(vk_device, *vk_image, nullptr); + vkFreeMemory(vk_device, *vk_device_memory, nullptr); + return false; + } + + *mem_allocation_size = mem_alloc_info.allocationSize; + return true; +} + } // namespace gpu
diff --git a/gpu/vulkan/android/vulkan_implementation_android.h b/gpu/vulkan/android/vulkan_implementation_android.h index af97c76b..145320d 100644 --- a/gpu/vulkan/android/vulkan_implementation_android.h +++ b/gpu/vulkan/android/vulkan_implementation_android.h
@@ -7,6 +7,7 @@ #include <memory> +#include "base/android/scoped_hardware_buffer_handle.h" #include "base/component_export.h" #include "gpu/vulkan/vulkan_implementation.h" #include "gpu/vulkan/vulkan_instance.h" @@ -40,6 +41,15 @@ bool GetSemaphoreFdKHR(VkDevice vk_device, VkSemaphore vk_semaphore, base::ScopedFD* sync_fd) override; + bool CreateVkImageAndImportAHB( + const VkDevice& vk_device, + const VkPhysicalDevice& vk_physical_device, + const gfx::Size& size, + base::android::ScopedHardwareBufferHandle ahb_handle, + VkImage* vk_image, + VkImageCreateInfo* vk_image_info, + VkDeviceMemory* vk_device_memory, + VkDeviceSize* mem_allocation_size) override; private: VulkanInstance vulkan_instance_;
diff --git a/gpu/vulkan/generate_bindings.py b/gpu/vulkan/generate_bindings.py index eefd051c..4896ace 100755 --- a/gpu/vulkan/generate_bindings.py +++ b/gpu/vulkan/generate_bindings.py
@@ -39,11 +39,14 @@ VULKAN_DEVICE_FUNCTIONS = [ { 'name': 'vkAllocateCommandBuffers' }, { 'name': 'vkAllocateDescriptorSets' }, +{ 'name': 'vkAllocateMemory' }, +{ 'name': 'vkBindImageMemory' }, { 'name': 'vkCreateCommandPool' }, { 'name': 'vkCreateDescriptorPool' }, { 'name': 'vkCreateDescriptorSetLayout' }, { 'name': 'vkCreateFence' }, { 'name': 'vkCreateFramebuffer' }, +{ 'name': 'vkCreateImage' }, { 'name': 'vkCreateImageView' }, { 'name': 'vkCreateRenderPass' }, { 'name': 'vkCreateSampler' }, @@ -74,6 +77,7 @@ VULKAN_DEVICE_FUNCTIONS_ANDROID = [ { 'name': 'vkImportSemaphoreFdKHR' }, +{ 'name': 'vkGetAndroidHardwareBufferPropertiesANDROID' }, { 'name': 'vkGetSemaphoreFdKHR' }, ]
diff --git a/gpu/vulkan/vulkan_function_pointers.cc b/gpu/vulkan/vulkan_function_pointers.cc index b1524be..ef19bfb 100644 --- a/gpu/vulkan/vulkan_function_pointers.cc +++ b/gpu/vulkan/vulkan_function_pointers.cc
@@ -111,6 +111,16 @@ if (!vkAllocateDescriptorSetsFn) return false; + vkAllocateMemoryFn = reinterpret_cast<PFN_vkAllocateMemory>( + vkGetDeviceProcAddrFn(vk_device, "vkAllocateMemory")); + if (!vkAllocateMemoryFn) + return false; + + vkBindImageMemoryFn = reinterpret_cast<PFN_vkBindImageMemory>( + vkGetDeviceProcAddrFn(vk_device, "vkBindImageMemory")); + if (!vkBindImageMemoryFn) + return false; + vkCreateCommandPoolFn = reinterpret_cast<PFN_vkCreateCommandPool>( vkGetDeviceProcAddrFn(vk_device, "vkCreateCommandPool")); if (!vkCreateCommandPoolFn) @@ -137,6 +147,11 @@ if (!vkCreateFramebufferFn) return false; + vkCreateImageFn = reinterpret_cast<PFN_vkCreateImage>( + vkGetDeviceProcAddrFn(vk_device, "vkCreateImage")); + if (!vkCreateImageFn) + return false; + vkCreateImageViewFn = reinterpret_cast<PFN_vkCreateImageView>( vkGetDeviceProcAddrFn(vk_device, "vkCreateImageView")); if (!vkCreateImageViewFn) @@ -275,6 +290,13 @@ if (!vkImportSemaphoreFdKHRFn) return false; + vkGetAndroidHardwareBufferPropertiesANDROIDFn = + reinterpret_cast<PFN_vkGetAndroidHardwareBufferPropertiesANDROID>( + vkGetDeviceProcAddrFn(vk_device, + "vkGetAndroidHardwareBufferPropertiesANDROID")); + if (!vkGetAndroidHardwareBufferPropertiesANDROIDFn) + return false; + vkGetSemaphoreFdKHRFn = reinterpret_cast<PFN_vkGetSemaphoreFdKHR>( vkGetDeviceProcAddrFn(vk_device, "vkGetSemaphoreFdKHR")); if (!vkGetSemaphoreFdKHRFn)
diff --git a/gpu/vulkan/vulkan_function_pointers.h b/gpu/vulkan/vulkan_function_pointers.h index 6c6b0ce..fbf0d73 100644 --- a/gpu/vulkan/vulkan_function_pointers.h +++ b/gpu/vulkan/vulkan_function_pointers.h
@@ -69,11 +69,14 @@ // Device functions PFN_vkAllocateCommandBuffers vkAllocateCommandBuffersFn = nullptr; PFN_vkAllocateDescriptorSets vkAllocateDescriptorSetsFn = nullptr; + PFN_vkAllocateMemory vkAllocateMemoryFn = nullptr; + PFN_vkBindImageMemory vkBindImageMemoryFn = nullptr; PFN_vkCreateCommandPool vkCreateCommandPoolFn = nullptr; PFN_vkCreateDescriptorPool vkCreateDescriptorPoolFn = nullptr; PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayoutFn = nullptr; PFN_vkCreateFence vkCreateFenceFn = nullptr; PFN_vkCreateFramebuffer vkCreateFramebufferFn = nullptr; + PFN_vkCreateImage vkCreateImageFn = nullptr; PFN_vkCreateImageView vkCreateImageViewFn = nullptr; PFN_vkCreateRenderPass vkCreateRenderPassFn = nullptr; PFN_vkCreateSampler vkCreateSamplerFn = nullptr; @@ -101,9 +104,11 @@ PFN_vkUpdateDescriptorSets vkUpdateDescriptorSetsFn = nullptr; PFN_vkWaitForFences vkWaitForFencesFn = nullptr; -// Android only device functions. + // Android only device functions. #if defined(OS_ANDROID) PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHRFn = nullptr; + PFN_vkGetAndroidHardwareBufferPropertiesANDROID + vkGetAndroidHardwareBufferPropertiesANDROIDFn = nullptr; PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHRFn = nullptr; #endif @@ -167,6 +172,8 @@ gpu::GetVulkanFunctionPointers()->vkAllocateCommandBuffersFn #define vkAllocateDescriptorSets \ gpu::GetVulkanFunctionPointers()->vkAllocateDescriptorSetsFn +#define vkAllocateMemory gpu::GetVulkanFunctionPointers()->vkAllocateMemoryFn +#define vkBindImageMemory gpu::GetVulkanFunctionPointers()->vkBindImageMemoryFn #define vkCreateCommandPool \ gpu::GetVulkanFunctionPointers()->vkCreateCommandPoolFn #define vkCreateDescriptorPool \ @@ -176,6 +183,7 @@ #define vkCreateFence gpu::GetVulkanFunctionPointers()->vkCreateFenceFn #define vkCreateFramebuffer \ gpu::GetVulkanFunctionPointers()->vkCreateFramebufferFn +#define vkCreateImage gpu::GetVulkanFunctionPointers()->vkCreateImageFn #define vkCreateImageView gpu::GetVulkanFunctionPointers()->vkCreateImageViewFn #define vkCreateRenderPass \ gpu::GetVulkanFunctionPointers()->vkCreateRenderPassFn @@ -219,6 +227,9 @@ #if defined(OS_ANDROID) #define vkImportSemaphoreFdKHR \ gpu::GetVulkanFunctionPointers()->vkImportSemaphoreFdKHRFn +#define vkGetAndroidHardwareBufferPropertiesANDROID \ + gpu::GetVulkanFunctionPointers() \ + ->vkGetAndroidHardwareBufferPropertiesANDROIDFn #define vkGetSemaphoreFdKHR \ gpu::GetVulkanFunctionPointers()->vkGetSemaphoreFdKHRFn #endif
diff --git a/gpu/vulkan/vulkan_implementation.h b/gpu/vulkan/vulkan_implementation.h index 2cb6be5..78470bc 100644 --- a/gpu/vulkan/vulkan_implementation.h +++ b/gpu/vulkan/vulkan_implementation.h
@@ -14,6 +14,12 @@ #include "gpu/vulkan/vulkan_export.h" #include "ui/gfx/native_widget_types.h" +#if defined(OS_ANDROID) +#include "base/android/scoped_hardware_buffer_handle.h" +#include "base/files/scoped_file.h" +#include "ui/gfx/geometry/size.h" +#endif + namespace gfx { class GpuFence; } @@ -69,6 +75,18 @@ virtual bool GetSemaphoreFdKHR(VkDevice vk_device, VkSemaphore vk_semaphore, base::ScopedFD* sync_fd) = 0; + + // Create a VkImage, import Android AHardwareBuffer object created outside of + // the Vulkan device into Vulkan memory object and bind it to the VkImage. + virtual bool CreateVkImageAndImportAHB( + const VkDevice& vk_device, + const VkPhysicalDevice& vk_physical_device, + const gfx::Size& size, + base::android::ScopedHardwareBufferHandle ahb_handle, + VkImage* vk_image, + VkImageCreateInfo* vk_image_info, + VkDeviceMemory* vk_device_memory, + VkDeviceSize* mem_allocation_size) = 0; #endif private:
diff --git a/headless/test/test_network_interceptor.cc b/headless/test/test_network_interceptor.cc index 573f6b4b..23799573 100644 --- a/headless/test/test_network_interceptor.cc +++ b/headless/test/test_network_interceptor.cc
@@ -51,6 +51,7 @@ void NotifyRedirect(const std::string& location) { auto redirect_info = net::RedirectInfo::ComputeRedirectInfo( url_request_.method, url_request_.url, url_request_.site_for_cookies, + url_request_.top_frame_origin, net::URLRequest::FirstPartyURLPolicy:: UPDATE_FIRST_PARTY_URL_ON_REDIRECT, url_request_.referrer_policy, url_request_.referrer.spec(),
diff --git a/infra/config/branch/cq.cfg b/infra/config/branch/cq.cfg index 062f0a8..b837fb1 100644 --- a/infra/config/branch/cq.cfg +++ b/infra/config/branch/cq.cfg
@@ -148,15 +148,7 @@ path_regexp: "build/.*check_gn_headers.*" } builders { - name: "linux_layout_tests_layout_ng" - path_regexp: "third_party/blink/renderer/core/(layout|paint)/ng/.+" - path_regexp: "third_party/blink/renderer/core/editing/.+" - path_regexp: "third_party/blink/renderer/platform/fonts/shaping/.+" - path_regexp: "third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG" - path_regexp: "third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/.+" - } - builders { - name: "linux_layout_tests_slimming_paint_v2" + name: "linux_layout_tests_composite_after_paint" path_regexp: "third_party/blink/renderer/core/paint/compositing/.+" path_regexp: "third_party/blink/renderer/core/(svg|paint)/.+" path_regexp: "third_party/blink/renderer/platform/graphics/.+" @@ -166,6 +158,14 @@ path_regexp: "third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/.+" } builders { + name: "linux_layout_tests_layout_ng" + path_regexp: "third_party/blink/renderer/core/(layout|paint)/ng/.+" + path_regexp: "third_party/blink/renderer/core/editing/.+" + path_regexp: "third_party/blink/renderer/platform/fonts/shaping/.+" + path_regexp: "third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG" + path_regexp: "third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/.+" + } + builders { name: "linux_mojo" path_regexp: "services/network/.+" path_regexp: "testing/buildbot/filters/mojo\\.fyi\\.network_.*"
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg index d2bec0f..b0327c7 100644 --- a/infra/config/global/cr-buildbucket.cfg +++ b/infra/config/global/cr-buildbucket.cfg
@@ -2363,6 +2363,11 @@ mixins: "fuzz-ci" } builders { + name: "mac-hermetic-upgrade-rel" + dimensions: "os:Mac-10.13" + mixins: "fyi-ci" + } + builders { name: "mac-osxbeta-rel" mixins: "fyi-ci" # This is launching & collecting entirely isolated tests. @@ -2556,6 +2561,20 @@ mixins: "goma-j80" } builders { + name: "Chromium Mac Goma RBE Staging" + dimensions: "os:Mac-10.13" + dimensions: "cores:4" + mixins: "goma-ci" + mixins: "goma-j80" + } + builders { + name: "Chromium Mac Goma RBE Staging (dbg)" + dimensions: "os:Mac-10.13" + dimensions: "cores:4" + mixins: "goma-ci" + mixins: "goma-j80" + } + builders { name: "Chromium Android ARM 32-bit Goma RBE Staging" dimensions: "os:Ubuntu-14.04" mixins: "goma-ci" @@ -3141,8 +3160,8 @@ } builders { mixins: "linux-try" name: "linux_chromium_ubsan_rel_ng" } builders { mixins: "linux-dawn-try" name: "linux-dawn-rel" } + builders { mixins: "linux-try" name: "linux_layout_tests_composite_after_paint" } builders { mixins: "linux-try" name: "linux_layout_tests_layout_ng" } - builders { mixins: "linux-try" name: "linux_layout_tests_slimming_paint_v2" } builders { mixins: "linux-try" name: "linux_mojo" } builders { mixins: "linux-try" name: "linux_mojo_chromeos" } builders { mixins: "linux-optional-gpu-try" name: "linux_optional_gpu_tests_rel" }
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg index d62ab98..701d107 100644 --- a/infra/config/global/luci-milo.cfg +++ b/infra/config/global/luci-milo.cfg
@@ -2633,6 +2633,11 @@ category: "cronet" } builders { + name: "buildbucket/luci.chromium.ci/mac-hermetic-upgrade-rel" + category: "mac" + short_name: "herm" + } + builders { name: "buildbucket/luci.chromium.ci/mac-osxbeta-rel" category: "mac" short_name: "beta" @@ -2937,6 +2942,18 @@ name: "buildbucket/luci.chromium.ci/Win 10 Fast Ring" category: "win10" } + builders { + name: "buildbucket/luci.chromium.ci/linux-autofill-captured-sites-rel" + category: "autofill" + } + builders { + name: "buildbucket/luci.chromium.ci/mac-autofill-captured-sites-rel" + category: "autofill" + } + builders { + name: "buildbucket/luci.chromium.ci/win-autofill-captured-sites-rel" + category: "autofill" + } } consoles { @@ -3025,6 +3042,14 @@ short_name: "clb" } builders { + name: "buildbucket/luci.chromium.ci/Chromium Mac Goma RBE Staging" + category: "rbe|mac|rel" + } + builders { + name: "buildbucket/luci.chromium.ci/Chromium Mac Goma RBE Staging (dbg)" + category: "rbe|mac|debug" + } + builders { name: "buildbucket/luci.chromium.ci/Chromium Android ARM 32-bit Goma RBE Staging" category: "rbe|android arm|rel" } @@ -3933,6 +3958,9 @@ name: "buildbucket/luci.chromium.try/android-binary-size" } builders { + name: "buildbot/tryserver.chromium.android/android_blink_rel" + } + builders { name: "buildbot/tryserver.chromium.android/android_cfi_rel_ng" } builders { @@ -4145,10 +4173,10 @@ name: "buildbucket/luci.chromium.try/layout_test_leak_detection" } builders { - name: "buildbucket/luci.chromium.try/linux_layout_tests_layout_ng" + name: "buildbucket/luci.chromium.try/linux_layout_tests_composite_after_paint" } builders { - name: "buildbucket/luci.chromium.try/linux_layout_tests_slimming_paint_v2" + name: "buildbucket/luci.chromium.try/linux_layout_tests_layout_ng" } builders { name: "buildbucket/luci.chromium.try/linux-libfuzzer-asan-rel" @@ -4672,10 +4700,10 @@ name: "buildbucket/luci.chromium.try/linux_chromium_ubsan_rel_ng" } builders { - name: "buildbucket/luci.chromium.try/linux_layout_tests_layout_ng" + name: "buildbucket/luci.chromium.try/linux_layout_tests_composite_after_paint" } builders { - name: "buildbucket/luci.chromium.try/linux_layout_tests_slimming_paint_v2" + name: "buildbucket/luci.chromium.try/linux_layout_tests_layout_ng" } builders { name: "buildbucket/luci.chromium.try/linux_mojo"
diff --git a/infra/config/global/luci-notify.cfg b/infra/config/global/luci-notify.cfg new file mode 100644 index 0000000..88d6a6fd --- /dev/null +++ b/infra/config/global/luci-notify.cfg
@@ -0,0 +1,27 @@ +# Defines email notifications for builders. +# See schema at +# https://chromium.googlesource.com/infra/luci/luci-go/+/master/luci_notify/api/config/notify.proto +# +# Please keep this list sorted by name. + +notifiers { + name: "bpastene-test" + notifications { + on_change: true + on_success: false + on_failure: false + on_new_failure: false + email { + recipients: "bpastene@google.com" + } + } + # Two sufficiently flaky builders that should trigger notifications. + builders { + name: "linux-xenial-rel" + bucket: "ci" + } + builders { + name: "Mojo Linux" + bucket: "ci" + } +}
diff --git a/infra/config/global/luci-scheduler.cfg b/infra/config/global/luci-scheduler.cfg index 4f7d8aa6..ca0fc41 100644 --- a/infra/config/global/luci-scheduler.cfg +++ b/infra/config/global/luci-scheduler.cfg
@@ -112,6 +112,8 @@ triggers: "Chromium Mac 10.13" triggers: "Chromium Mac Goma GCE Staging" triggers: "Chromium Mac Goma RBE Staging (clobber)" + triggers: "Chromium Mac Goma RBE Staging (dbg)" + triggers: "Chromium Mac Goma RBE Staging" triggers: "Chromium Mac Goma Staging" triggers: "Chromium Windows Analyze" triggers: "ChromiumOS ASAN Release" @@ -325,6 +327,7 @@ triggers: "linux-xenial-rel" triggers: "mac-code-coverage-generation" triggers: "mac-dbg" + triggers: "mac-hermetic-upgrade-rel" triggers: "mac-jumbo-rel" triggers: "mac-mojo-rel" triggers: "mac-rel" @@ -1556,6 +1559,16 @@ } job { + id: "linux-autofill-captured-sites-rel" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "linux-autofill_captured_sites-rel" + } +} + +job { id: "linux-blink-animation-use-time-delta" acl_sets: "default" buildbucket { @@ -1894,6 +1907,16 @@ } job { + id: "mac-autofill-captured-sites-rel" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "mac-autofill_captured_sites-rel" + } +} + +job { id: "mac-code-coverage-generation" acl_sets: "default" buildbucket: { @@ -4074,6 +4097,16 @@ } job { + id: "win-autofill-captured-sites-rel" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "win-autofill_captured_sites-rel" + } +} + +job { id: "win-dbg" acl_sets: "default" buildbucket: { @@ -4244,6 +4277,16 @@ } job { + id: "mac-hermetic-upgrade-rel" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "mac-hermetic-upgrade-rel" + } +} + +job { id: "mac-views-rel" acl_sets: "default" buildbucket: { @@ -4384,6 +4427,26 @@ } job { + id: "Chromium Mac Goma RBE Staging" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "Chromium Mac Goma RBE Staging" + } +} + +job { + id: "Chromium Mac Goma RBE Staging (dbg)" + acl_sets: "default" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "Chromium Mac Goma RBE Staging (dbg)" + } +} + +job { id: "Chromium Mac Goma Staging" acl_sets: "default" buildbucket: {
diff --git a/ios/build/bots/chromium.mac/ios-slimnav.json b/ios/build/bots/chromium.mac/ios-slimnav.json index f2300889..08dd0e9 100644 --- a/ios/build/bots/chromium.mac/ios-slimnav.json +++ b/ios/build/bots/chromium.mac/ios-slimnav.json
@@ -159,7 +159,7 @@ { "app": "ios_chrome_manual_fill_egtests", "test args": [ - "--enable-features=AutofillManualFallback,WebFrameMessaging,SlimNavigationManager" + "--enable-features=AutofillManualFallback,AutofillManualFallbackPhaseTwo,WebFrameMessaging,SlimNavigationManager" ], "device type": "iPad Air 2", "os": "11.4", @@ -250,7 +250,7 @@ { "app": "ios_chrome_manual_fill_egtests", "test args": [ - "--enable-features=AutofillManualFallback,WebFrameMessaging,SlimNavigationManager" + "--enable-features=AutofillManualFallback,AutofillManualFallbackPhaseTwo,WebFrameMessaging,SlimNavigationManager" ], "xctest": true, "device type": "iPad Air 2", @@ -342,7 +342,7 @@ { "app": "ios_chrome_manual_fill_egtests", "test args": [ - "--enable-features=AutofillManualFallback,WebFrameMessaging,SlimNavigationManager" + "--enable-features=AutofillManualFallback,AutofillManualFallbackPhaseTwo,WebFrameMessaging,SlimNavigationManager" ], "xctest": true, "device type": "iPhone X", @@ -433,7 +433,7 @@ { "app": "ios_chrome_manual_fill_egtests", "test args": [ - "--enable-features=AutofillManualFallback,WebFrameMessaging,SlimNavigationManager" + "--enable-features=AutofillManualFallback,AutofillManualFallbackPhaseTwo,WebFrameMessaging,SlimNavigationManager" ], "device type": "iPhone X", "os": "12.1",
diff --git a/ios/build/bots/tests/eg_tests.json b/ios/build/bots/tests/eg_tests.json index caa3150..7174f79d 100644 --- a/ios/build/bots/tests/eg_tests.json +++ b/ios/build/bots/tests/eg_tests.json
@@ -11,7 +11,7 @@ { "app": "ios_chrome_manual_fill_egtests", "test args": [ - "--enable-features=AutofillManualFallback,WebFrameMessaging" + "--enable-features=AutofillManualFallback,AutofillManualFallbackPhaseTwo,WebFrameMessaging" ], "xctest": true },
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index f7b50bb..d6751c7 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -108,6 +108,7 @@ #import "ios/chrome/browser/tabs/tab.h" #import "ios/chrome/browser/tabs/tab_model.h" #import "ios/chrome/browser/tabs/tab_model_observer.h" +#import "ios/chrome/browser/tabs/tab_util.h" #import "ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.h" #import "ios/chrome/browser/ui/browser_view_controller.h" #include "ios/chrome/browser/ui/commands/browser_commands.h" @@ -2272,14 +2273,19 @@ tabOpenedCompletion:(ProceduralBlock)tabOpenedCompletion { BrowserViewController* targetBVC = targetMode == ApplicationMode::NORMAL ? self.mainBVC : self.otrBVC; + TabModel* targetTabModel = targetBVC.tabModel; - Tab* currentTabInTargetBVC = [[targetBVC tabModel] currentTab]; + Tab* currentTabInTargetBVC = [targetTabModel currentTab]; if (!(currentTabInTargetBVC.webState && IsURLNtp(currentTabInTargetBVC.webState->GetVisibleURL()))) { [targetBVC appendTabAddedCompletion:tabOpenedCompletion]; - return [targetBVC addSelectedTabWithURL:URL - atIndex:targetBVC.tabModel.count - transition:transition]; + [targetTabModel + insertTabWithLoadParams:CreateWebLoadParams(URL, transition, + /*post_data=*/nullptr) + opener:nil + openedByDOM:NO + atIndex:targetTabModel.count + inBackground:NO]; } Tab* newTab = currentTabInTargetBVC; @@ -2321,8 +2327,8 @@ BrowserCoordinator* targetBrowserCoordinator = targetMode == ApplicationMode::NORMAL ? self.mainBrowserCoordinator : self.incognitoBrowserCoordinator; - NSUInteger tabIndex = NSNotFound; - + TabModel* targetTabModel = targetBrowserCoordinator.tabModel; + NSUInteger tabIndex = targetTabModel.count; ProceduralBlock startupCompletion = [self completionBlockForTriggeringAction:[_startupParameters postOpeningAction]]; @@ -2355,21 +2361,23 @@ : TabSwitcherDismissalMode::INCOGNITO; [targetBrowserCoordinator.viewController appendTabAddedCompletion:tabOpenedCompletion]; - tab = [targetBrowserCoordinator.viewController - addSelectedTabWithURL:url - atIndex:tabIndex - transition:transition]; + tab = [targetTabModel + insertTabWithLoadParams:CreateWebLoadParams(url, transition, + /*post_data=*/nullptr) + opener:nil + openedByDOM:NO + atIndex:tabIndex + inBackground:NO]; } else { // Voice search, QRScanner and the omnibox are presented by the BVC. // They must be started after the BVC view is added in the hierarchy. self.NTPActionAfterTabSwitcherDismissal = [_startupParameters postOpeningAction]; [self setStartupParameters:nil]; - tab = [_tabSwitcher - dismissWithNewTabAnimationToModel:targetBrowserCoordinator.tabModel - withURL:url - atIndex:tabIndex - transition:transition]; + tab = [_tabSwitcher dismissWithNewTabAnimationToModel:targetTabModel + withURL:url + atIndex:tabIndex + transition:transition]; } } else { if (!self.currentBVC.presentedViewController) {
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 2e84e93..cb45783 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -883,7 +883,7 @@ Use Other Password... </message> <message name="IDS_IOS_MANUAL_FALLBACK_MANAGE_CREDIT_CARDS" desc="The title for the button in the manual fallback UI that takes the user to the payments settings. In this screen they see all the credit cards and can erase them. [30em]"> - Manage Credit Cards... + Manage Payment Methods... </message> <message name="IDS_IOS_MANUAL_FALLBACK_MANAGE_ADDRESSES" desc="The title for the button in the manual fallback UI that takes the user to the addresses settings. In this screen they see all the addresses and can erase them. [30em]"> Manage Addresses...
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn index 12b816d..5262925 100644 --- a/ios/chrome/browser/BUILD.gn +++ b/ios/chrome/browser/BUILD.gn
@@ -124,6 +124,7 @@ "//ios/chrome/browser/download", "//ios/chrome/browser/download:features", "//ios/chrome/browser/drag_and_drop", + "//ios/chrome/browser/find_in_page:feature_flags", "//ios/chrome/browser/itunes_urls", "//ios/chrome/browser/payments:constants", "//ios/chrome/browser/search_engines:feature_flags",
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm index c6ae15c6..db13155c 100644 --- a/ios/chrome/browser/about_flags.mm +++ b/ios/chrome/browser/about_flags.mm
@@ -48,6 +48,7 @@ #include "ios/chrome/browser/crash_report/crash_report_flags.h" #include "ios/chrome/browser/download/features.h" #include "ios/chrome/browser/drag_and_drop/drag_and_drop_flag.h" +#include "ios/chrome/browser/find_in_page/features.h" #include "ios/chrome/browser/ios_chrome_flag_descriptions.h" #include "ios/chrome/browser/itunes_urls/itunes_urls_flag.h" #include "ios/chrome/browser/search_engines/feature_flags.h" @@ -490,6 +491,9 @@ {"infobar-ui-reboot", flag_descriptions::kInfobarUIRebootName, flag_descriptions::kInfobarUIRebootDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kInfobarUIReboot)}, + {"find-in-page-iframe", flag_descriptions::kFindInPageiFrameName, + flag_descriptions::kFindInPageiFrameDescription, flags_ui::kOsIos, + FEATURE_VALUE_TYPE(kFindInPageiFrame)}, }; // Add all switches from experimental flags to |command_line|.
diff --git a/ios/chrome/browser/find_in_page/BUILD.gn b/ios/chrome/browser/find_in_page/BUILD.gn index 63251473..f5fdc41 100644 --- a/ios/chrome/browser/find_in_page/BUILD.gn +++ b/ios/chrome/browser/find_in_page/BUILD.gn
@@ -35,6 +35,17 @@ ] } +source_set("feature_flags") { + sources = [ + "features.h", + "features.mm", + ] + deps = [ + "//base", + ] + configs += [ "//build/config/compiler:enable_arc" ] +} + source_set("unit_tests") { testonly = true configs += [ "//build/config/compiler:enable_arc" ]
diff --git a/ios/chrome/browser/find_in_page/OWNERS b/ios/chrome/browser/find_in_page/OWNERS index b127701..30ecf2f 100644 --- a/ios/chrome/browser/find_in_page/OWNERS +++ b/ios/chrome/browser/find_in_page/OWNERS
@@ -1,4 +1,5 @@ rohitrao@chromium.org +mrsuyi@chromium.org # TEAM: ios-directory-owners@chromium.org # OS: iOS
diff --git a/ios/chrome/browser/find_in_page/features.h b/ios/chrome/browser/find_in_page/features.h new file mode 100644 index 0000000..e8ddbf0f --- /dev/null +++ b/ios/chrome/browser/find_in_page/features.h
@@ -0,0 +1,13 @@ +// 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 IOS_CHROME_BROWSER_FIND_IN_PAGE_FEATURES_H_ +#define IOS_CHROME_BROWSER_FIND_IN_PAGE_FEATURES_H_ + +#include "base/feature_list.h" + +// Used to enable Find in Page iFrame searching. +extern const base::Feature kFindInPageiFrame; + +#endif // IOS_CHROME_BROWSER_FIND_IN_PAGE_FEATURES_H_
diff --git a/ios/chrome/browser/find_in_page/features.mm b/ios/chrome/browser/find_in_page/features.mm new file mode 100644 index 0000000..6e92de3d --- /dev/null +++ b/ios/chrome/browser/find_in_page/features.mm
@@ -0,0 +1,12 @@ +// 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. + +#import "ios/chrome/browser/find_in_page/features.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +const base::Feature kFindInPageiFrame{"FindInPageiFrame", + base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ios/chrome/browser/find_in_page/resources/find_in_page.js b/ios/chrome/browser/find_in_page/resources/find_in_page.js index 9c05d80..b77dfb8 100644 --- a/ios/chrome/browser/find_in_page/resources/find_in_page.js +++ b/ios/chrome/browser/find_in_page/resources/find_in_page.js
@@ -11,11 +11,9 @@ * selected one in orange color; */ +// Requires __crWeb.findInPage provided by __crWeb.allFramesWebBundle. + (function() { -/** - * Namespace for this file. Depends on __gCrWeb having already been injected. - */ -__gCrWeb.findInPage = {}; /** * A string made by concatenating textContent.toLowerCase() of all TEXT nodes @@ -731,16 +729,7 @@ // Perform the scroll. // window.scrollTo(xPos, yPos); - if (xPos < window.pageXOffset || - xPos >= (window.pageXOffset + window.innerWidth) || - yPos < window.pageYOffset || - yPos >= (window.pageYOffset + window.innerHeight)) { - // If it's off the screen. Wait a bit to start the highlight animation so - // that scrolling can get there first. - window.setTimeout(() => match.addSelectHighlight(), 250); - } else { - match.addSelectHighlight(); - } + match.addSelectHighlight(); let scaled = scaleCoordinates_(normalized); let index = match.visibleIndex; scaled.unshift(index);
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/ios_chrome_flag_descriptions.cc index 599d86b3..2f0b29d 100644 --- a/ios/chrome/browser/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
@@ -379,6 +379,10 @@ const char kCustomSearchEnginesDescription[] = "When enabled, user can add custom search engines in settings."; +const char kFindInPageiFrameName[] = "Find in Page in iFrames."; +const char kFindInPageiFrameDescription[] = + "When enabled, Find In Page will search in iFrames."; + // Please insert your name/description above in alphabetical order. } // namespace flag_descriptions
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.h b/ios/chrome/browser/ios_chrome_flag_descriptions.h index ea0d688a..5adeaee 100644 --- a/ios/chrome/browser/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/ios_chrome_flag_descriptions.h
@@ -315,6 +315,10 @@ extern const char kCustomSearchEnginesName[]; extern const char kCustomSearchEnginesDescription[]; +// Title and description for the flag to search in iFrames in Find In Page. +extern const char kFindInPageiFrameName[]; +extern const char kFindInPageiFrameDescription[]; + // Please insert your name/description above in alphabetical order. } // namespace flag_descriptions
diff --git a/ios/chrome/browser/passwords/BUILD.gn b/ios/chrome/browser/passwords/BUILD.gn index 3b8dfc66..37387b2 100644 --- a/ios/chrome/browser/passwords/BUILD.gn +++ b/ios/chrome/browser/passwords/BUILD.gn
@@ -65,6 +65,7 @@ "//components/signin/core/browser", "//components/strings", "//components/sync", + "//components/translate/core/browser:browser", "//components/ukm", "//google_apis", "//ios/chrome/app/strings", @@ -76,6 +77,7 @@ "//ios/chrome/browser/signin", "//ios/chrome/browser/ssl", "//ios/chrome/browser/sync/glue", + "//ios/chrome/browser/translate:translate", "//ios/chrome/browser/ui", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/elements",
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h index 2ef66bc..dc9aaab 100644 --- a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h +++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h
@@ -87,6 +87,7 @@ void NotifyStorePasswordCalled() override; bool IsSavingAndFillingEnabledForCurrentPage() const override; const GURL& GetLastCommittedEntryURL() const override; + std::string GetPageLanguage() const override; const password_manager::CredentialsFilter* GetStoreResultFilter() const override; const password_manager::LogManager* GetLogManager() const override;
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm index 7666f198..011a7e5 100644 --- a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm +++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm
@@ -18,6 +18,7 @@ #include "components/password_manager/core/browser/password_manager_util.h" #include "components/password_manager/core/browser/store_metrics_reporter.h" #include "components/password_manager/core/common/password_manager_pref_names.h" +#include "components/translate/core/browser/translate_manager.h" #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/experimental_flags.h" @@ -25,6 +26,7 @@ #include "ios/chrome/browser/passwords/password_manager_internals_service_factory.h" #include "ios/chrome/browser/signin/identity_manager_factory.h" #include "ios/chrome/browser/sync/profile_sync_service_factory.h" +#include "ios/chrome/browser/translate/chrome_ios_translate_client.h" #include "net/cert/cert_status_flags.h" #include "services/metrics/public/cpp/ukm_recorder.h" #include "url/gurl.h" @@ -170,6 +172,12 @@ return delegate_.lastCommittedURL; } +std::string IOSChromePasswordManagerClient::GetPageLanguage() const { + // TODO(crbug.com/912597): Add WebState to the IOSChromePasswordManagerClient + // to be able to get the pages LanguageState from the TranslateManager. + return std::string(); +} + const password_manager::CredentialsFilter* IOSChromePasswordManagerClient::GetStoreResultFilter() const { return &credentials_filter_;
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm index fb20eca..45febbae 100644 --- a/ios/chrome/browser/passwords/password_controller.mm +++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -285,7 +285,7 @@ // Notify the password manager that the page loaded so it can clear its own // per-page state. - self.passwordManager->DidNavigateMainFrame(); + self.passwordManager->DidNavigateMainFrame(/*form_may_be_submitted=*/false); if (!webState->ContentIsHTML()) { // If the current page is not HTML, it does not contain any HTML forms.
diff --git a/ios/chrome/browser/prerender/preload_controller.mm b/ios/chrome/browser/prerender/preload_controller.mm index df89122b..9042d96bb 100644 --- a/ios/chrome/browser/prerender/preload_controller.mm +++ b/ios/chrome/browser/prerender/preload_controller.mm
@@ -59,6 +59,9 @@ // The name of the histogram for recording the number of successful prerenders. const char kPrerendersPerSessionCountHistogramName[] = "Prerender.PrerendersPerSessionCount"; +// The name of the histogram for recording time until a successful prerender. +const char kPrerenderStartToReleaseContentsTime[] = + "Prerender.PrerenderStartToReleaseContentsTime"; // Is this install selected for this particular experiment. bool IsPrerenderTabEvictionExperimentalGroup() { @@ -91,6 +94,9 @@ // empty URL. - (void)removeScheduledPrerenderRequests; +// Records metric on a successful prerender. +- (void)recordReleaseMetrics; + @end @interface PreloadController ()<CRWWebStateObserver, @@ -150,6 +156,10 @@ // during the lifetime of this controller. int successfulPrerendersPerSessionCount_; + // Tracks the last time of the last attempt to load a |prerenderedURL_|. Used + // for UMA reporting of load durations. + base::TimeTicks startTime_; + // Bridge to provide navigation policies for |webState_|. std::unique_ptr<web::WebStatePolicyDeciderBridge> policyDeciderBridge_; } @@ -244,12 +254,10 @@ - (std::unique_ptr<web::WebState>)releasePrerenderContents { successfulPrerendersPerSessionCount_++; - UMA_HISTOGRAM_ENUMERATION(kPrerenderFinalStatusHistogramName, - PRERENDER_FINAL_STATUS_USED, - PRERENDER_FINAL_STATUS_MAX); + [self recordReleaseMetrics]; [self removeScheduledPrerenderRequests]; prerenderedURL_ = GURL(); - + startTime_ = base::TimeTicks(); if (!webState_) return nullptr; @@ -410,6 +418,8 @@ // LoadIfNecessary is needed because the view is not created (but needed) when // loading the page. TODO(crbug.com/705819): Remove this call. webState_->GetNavigationManager()->LoadIfNecessary(); + + startTime_ = base::TimeTicks::Now(); } - (void)destroyPreviewContents { @@ -430,6 +440,7 @@ webState_.reset(); prerenderedURL_ = GURL(); + startTime_ = base::TimeTicks(); } - (void)schedulePrerenderCancel { @@ -475,6 +486,16 @@ } } +- (void)recordReleaseMetrics { + UMA_HISTOGRAM_ENUMERATION(kPrerenderFinalStatusHistogramName, + PRERENDER_FINAL_STATUS_USED, + PRERENDER_FINAL_STATUS_MAX); + + DCHECK_NE(base::TimeTicks(), startTime_); + UMA_HISTOGRAM_TIMES(kPrerenderStartToReleaseContentsTime, + base::TimeTicks::Now() - startTime_); +} + #pragma mark - CRWWebStateObserver - (void)webState:(web::WebState*)webState
diff --git a/ios/chrome/browser/rlz/rlz_tracker_delegate_impl.cc b/ios/chrome/browser/rlz/rlz_tracker_delegate_impl.cc index e95171a..90cf72d 100644 --- a/ios/chrome/browser/rlz/rlz_tracker_delegate_impl.cc +++ b/ios/chrome/browser/rlz/rlz_tracker_delegate_impl.cc
@@ -114,6 +114,11 @@ NOTREACHED(); } +bool RLZTrackerDelegateImpl::ShouldUpdateExistingAccessPointRlz() { + NOTREACHED(); + return false; +} + void RLZTrackerDelegateImpl::OnURLOpenedFromOmnibox(OmniboxLog* log) { // In M-36, we made NOTIFICATION_OMNIBOX_OPENED_URL fire more often than // it did previously. The RLZ folks want RLZ's "first search" detection
diff --git a/ios/chrome/browser/rlz/rlz_tracker_delegate_impl.h b/ios/chrome/browser/rlz/rlz_tracker_delegate_impl.h index 89795d80..ee26016 100644 --- a/ios/chrome/browser/rlz/rlz_tracker_delegate_impl.h +++ b/ios/chrome/browser/rlz/rlz_tracker_delegate_impl.h
@@ -43,6 +43,7 @@ bool ClearReferral() override; void SetOmniboxSearchCallback(const base::Closure& callback) override; void SetHomepageSearchCallback(const base::Closure& callback) override; + bool ShouldUpdateExistingAccessPointRlz() override; // Called when user open an URL from the Omnibox. void OnURLOpenedFromOmnibox(OmniboxLog* log);
diff --git a/ios/chrome/browser/signin/BUILD.gn b/ios/chrome/browser/signin/BUILD.gn index a0686d1..93bba5f 100644 --- a/ios/chrome/browser/signin/BUILD.gn +++ b/ios/chrome/browser/signin/BUILD.gn
@@ -140,6 +140,7 @@ "authentication_service_unittest.mm", "chrome_identity_service_observer_bridge_unittest.mm", "gaia_auth_fetcher_ios_unittest.mm", + "signin_browser_state_info_updater_unittest.mm", ] deps = [ ":signin", @@ -151,10 +152,12 @@ "//components/signin/core/browser", "//components/signin/core/browser:test_support", "//components/signin/ios/browser", + "//components/signin/ios/browser:test_support", "//components/sync_preferences", "//components/sync_preferences:test_support", "//google_apis", "//ios/chrome/browser", + "//ios/chrome/browser/browser_state:browser_state_impl", "//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/content_settings", "//ios/chrome/browser/prefs:browser_prefs",
diff --git a/ios/chrome/browser/signin/about_signin_internals_factory.cc b/ios/chrome/browser/signin/about_signin_internals_factory.cc index 707190f9..be36cbb 100644 --- a/ios/chrome/browser/signin/about_signin_internals_factory.cc +++ b/ios/chrome/browser/signin/about_signin_internals_factory.cc
@@ -18,7 +18,6 @@ #include "ios/chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "ios/chrome/browser/signin/signin_client_factory.h" #include "ios/chrome/browser/signin/signin_error_controller_factory.h" -#include "ios/chrome/browser/signin/signin_manager_factory.h" namespace ios { @@ -32,7 +31,6 @@ DependsOn(IdentityManagerFactory::GetInstance()); DependsOn(SigninClientFactory::GetInstance()); DependsOn(SigninErrorControllerFactory::GetInstance()); - DependsOn(SigninManagerFactory::GetInstance()); } AboutSigninInternalsFactory::~AboutSigninInternalsFactory() {} @@ -59,7 +57,6 @@ chrome_browser_state), AccountTrackerServiceFactory::GetForBrowserState(chrome_browser_state), IdentityManagerFactory::GetForBrowserState(chrome_browser_state), - SigninManagerFactory::GetForBrowserState(chrome_browser_state), SigninErrorControllerFactory::GetForBrowserState(chrome_browser_state), GaiaCookieManagerServiceFactory::GetForBrowserState(chrome_browser_state), signin::AccountConsistencyMethod::kMirror));
diff --git a/ios/chrome/browser/signin/signin_browser_state_info_updater.h b/ios/chrome/browser/signin/signin_browser_state_info_updater.h index dcba3219..92c3dde 100644 --- a/ios/chrome/browser/signin/signin_browser_state_info_updater.h +++ b/ios/chrome/browser/signin/signin_browser_state_info_updater.h
@@ -29,6 +29,9 @@ // KeyedService: void Shutdown() override; + // Updates the browser state info on signin and signout events. + void UpdateBrowserStateInfo(); + // SigninErrorController::Observer: void OnErrorChanged() override; @@ -37,6 +40,7 @@ void GoogleSignedOut(const AccountInfo& account_info) override; SigninErrorController* signin_error_controller_ = nullptr; + SigninManagerBase* signin_manager_ = nullptr; const base::FilePath browser_state_path_; ScopedObserver<SigninErrorController, SigninBrowserStateInfoUpdater> signin_error_controller_observer_;
diff --git a/ios/chrome/browser/signin/signin_browser_state_info_updater.mm b/ios/chrome/browser/signin/signin_browser_state_info_updater.mm index 2145ff5..cc41bb44 100644 --- a/ios/chrome/browser/signin/signin_browser_state_info_updater.mm +++ b/ios/chrome/browser/signin/signin_browser_state_info_updater.mm
@@ -22,10 +22,18 @@ SigninErrorController* signin_error_controller, const base::FilePath& browser_state_path) : signin_error_controller_(signin_error_controller), + signin_manager_(signin_manager), browser_state_path_(browser_state_path), signin_error_controller_observer_(this), signin_manager_observer_(this) { + // Some tests don't have a ChromeBrowserStateManager, disable this service. + if (!GetApplicationContext()->GetChromeBrowserStateManager()) + return; + + signin_manager_observer_.Add(signin_manager_); signin_error_controller_observer_.Add(signin_error_controller); + + UpdateBrowserStateInfo(); // TODO(crbug.com/908457): Call OnErrorChanged() here, to catch any change // that happened since the construction of SigninErrorController. BrowserState // metrics depend on this bug and must be fixed first. @@ -38,6 +46,26 @@ signin_manager_observer_.RemoveAll(); } +void SigninBrowserStateInfoUpdater::UpdateBrowserStateInfo() { + ios::ChromeBrowserStateManager* browser_state_manager = + GetApplicationContext()->GetChromeBrowserStateManager(); + BrowserStateInfoCache* cache = + browser_state_manager->GetBrowserStateInfoCache(); + size_t index = cache->GetIndexOfBrowserStateWithPath(browser_state_path_); + + if (index == std::string::npos) + return; + + if (signin_manager_->IsAuthenticated()) { + AccountInfo account_info = signin_manager_->GetAuthenticatedAccountInfo(); + cache->SetAuthInfoOfBrowserStateAtIndex( + index, account_info.gaia, base::UTF8ToUTF16(account_info.email)); + } else { + cache->SetAuthInfoOfBrowserStateAtIndex(index, /*gaia_id=*/std::string(), + /*user_name=*/base::string16()); + } +} + void SigninBrowserStateInfoUpdater::OnErrorChanged() { BrowserStateInfoCache* cache = GetApplicationContext() ->GetChromeBrowserStateManager() @@ -52,31 +80,10 @@ void SigninBrowserStateInfoUpdater::GoogleSigninSucceeded( const AccountInfo& account_info) { - ios::ChromeBrowserStateManager* browser_state_manager = - GetApplicationContext()->GetChromeBrowserStateManager(); - BrowserStateInfoCache* cache = - browser_state_manager->GetBrowserStateInfoCache(); - size_t index = cache->GetIndexOfBrowserStateWithPath(browser_state_path_); - - if (index == std::string::npos) - return; - - cache->SetAuthInfoOfBrowserStateAtIndex( - index, account_info.gaia, base::UTF8ToUTF16(account_info.email)); + UpdateBrowserStateInfo(); } void SigninBrowserStateInfoUpdater::GoogleSignedOut( const AccountInfo& account_info) { - BrowserStateInfoCache* cache = GetApplicationContext() - ->GetChromeBrowserStateManager() - ->GetBrowserStateInfoCache(); - size_t index = cache->GetIndexOfBrowserStateWithPath(browser_state_path_); - - // If sign out occurs because Sync setup was in progress and the browser state - // got deleted, then it is no longer in the cache. - if (index == std::string::npos) - return; - - cache->SetAuthInfoOfBrowserStateAtIndex(index, /*gaia_id=*/std::string(), - /*user_name=*/base::string16()); + UpdateBrowserStateInfo(); }
diff --git a/ios/chrome/browser/signin/signin_browser_state_info_updater_unittest.mm b/ios/chrome/browser/signin/signin_browser_state_info_updater_unittest.mm new file mode 100644 index 0000000..3526f64 --- /dev/null +++ b/ios/chrome/browser/signin/signin_browser_state_info_updater_unittest.mm
@@ -0,0 +1,171 @@ +// 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. + +#import "ios/chrome/browser/signin/signin_browser_state_info_updater.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#include <memory> + +#include "base/bind.h" +#include "base/files/file_path.h" +#include "base/files/scoped_temp_dir.h" +#include "base/strings/utf_string_conversions.h" +#include "components/signin/core/browser/account_tracker_service.h" +#include "components/signin/core/browser/fake_profile_oauth2_token_service.h" +#include "components/signin/core/browser/signin_manager.h" +#include "components/signin/core/browser/test_signin_client.h" +#include "components/signin/ios/browser/fake_profile_oauth2_token_service_ios_provider.h" +#include "components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h" +#include "components/sync_preferences/pref_service_syncable.h" +#include "google_apis/gaia/google_service_auth_error.h" +#include "ios/chrome/browser/application_context.h" +#include "ios/chrome/browser/browser_state/browser_state_info_cache.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state_manager.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state_manager.h" +#include "ios/chrome/browser/signin/account_tracker_service_factory.h" +#include "ios/chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "ios/chrome/browser/signin/signin_client_factory.h" +#include "ios/chrome/browser/signin/signin_manager_factory.h" +#include "ios/chrome/test/ios_chrome_scoped_testing_chrome_browser_state_manager.h" +#include "ios/web/public/test/test_web_thread_bundle.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +namespace { +// Returns a TestSigninClient. +std::unique_ptr<KeyedService> BuildTestSigninClient(web::BrowserState* state) { + return std::make_unique<TestSigninClient>( + ios::ChromeBrowserState::FromBrowserState(state)->GetPrefs()); +} + +// Builds a token service with a fake provider. +std::unique_ptr<KeyedService> BuildTestTokenService(web::BrowserState* state) { + ios::ChromeBrowserState* browser_state = + ios::ChromeBrowserState::FromBrowserState(state); + std::unique_ptr<ProfileOAuth2TokenServiceIOSDelegate> delegate = + std::make_unique<ProfileOAuth2TokenServiceIOSDelegate>( + SigninClientFactory::GetForBrowserState(browser_state), + std::make_unique<FakeProfileOAuth2TokenServiceIOSProvider>(), + ios::AccountTrackerServiceFactory::GetForBrowserState(browser_state)); + return std::make_unique<FakeProfileOAuth2TokenService>( + browser_state->GetPrefs(), std::move(delegate)); +} +} // namespace + +class SigninBrowserStateInfoUpdaterTest : public PlatformTest { + public: + SigninBrowserStateInfoUpdaterTest() { + EXPECT_TRUE(temp_directory_.CreateUniqueTempDir()); + // Setup the browser state manager. + scoped_browser_state_manager_ = + std::make_unique<IOSChromeScopedTestingChromeBrowserStateManager>( + std::make_unique<TestChromeBrowserStateManager>( + temp_directory_.GetPath().DirName())); + browser_state_info_ = GetApplicationContext() + ->GetChromeBrowserStateManager() + ->GetBrowserStateInfoCache(); + browser_state_info_->AddBrowserState(temp_directory_.GetPath(), + /*gaia_id=*/std::string(), + /*user_name=*/base::string16()); + // Create the browser state. + TestChromeBrowserState::Builder test_cbs_builder; + test_cbs_builder.SetPath(temp_directory_.GetPath()); + test_cbs_builder.AddTestingFactory( + SigninClientFactory::GetInstance(), + base::BindRepeating(&BuildTestSigninClient)); + test_cbs_builder.AddTestingFactory( + ProfileOAuth2TokenServiceFactory::GetInstance(), + base::BindRepeating(&BuildTestTokenService)); + chrome_browser_state_ = test_cbs_builder.Build(); + + cache_index_ = browser_state_info_->GetIndexOfBrowserStateWithPath( + chrome_browser_state_->GetStatePath()); + } + + web::TestWebThreadBundle thread_bundle_; + base::ScopedTempDir temp_directory_; + std::unique_ptr<IOSChromeScopedTestingChromeBrowserStateManager> + scoped_browser_state_manager_; + size_t cache_index_ = 0u; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; + + // Weak, owned by scoped_browser_state_manager_. + BrowserStateInfoCache* browser_state_info_ = nullptr; +}; + +// Tests that the browser state info is updated on signin and signout. +TEST_F(SigninBrowserStateInfoUpdaterTest, SigninSignout) { + ASSERT_FALSE( + browser_state_info_->BrowserStateIsAuthenticatedAtIndex(cache_index_)); + + // Signin. + AccountTrackerService* account_tracker = + ios::AccountTrackerServiceFactory::GetForBrowserState( + chrome_browser_state_.get()); + SigninManager* signin_manager = ios::SigninManagerFactory::GetForBrowserState( + chrome_browser_state_.get()); + std::string account_id = + account_tracker->SeedAccountInfo("gaia", "example@email.com"); + signin_manager->OnExternalSigninCompleted("example@email.com"); + EXPECT_TRUE( + browser_state_info_->BrowserStateIsAuthenticatedAtIndex(cache_index_)); + EXPECT_EQ("gaia", + browser_state_info_->GetGAIAIdOfBrowserStateAtIndex(cache_index_)); + EXPECT_EQ( + "example@email.com", + base::UTF16ToUTF8( + browser_state_info_->GetUserNameOfBrowserStateAtIndex(cache_index_))); + + // Signout. + signin_manager->SignOut(signin_metrics::SIGNOUT_TEST, + signin_metrics::SignoutDelete::IGNORE_METRIC); + EXPECT_FALSE( + browser_state_info_->BrowserStateIsAuthenticatedAtIndex(cache_index_)); +} + +// Tests that the browser state info is updated on auth error change. +TEST_F(SigninBrowserStateInfoUpdaterTest, AuthError) { + ASSERT_FALSE( + browser_state_info_->BrowserStateIsAuthenticatedAtIndex(cache_index_)); + + // Signin. + AccountTrackerService* account_tracker = + ios::AccountTrackerServiceFactory::GetForBrowserState( + chrome_browser_state_.get()); + SigninManager* signin_manager = ios::SigninManagerFactory::GetForBrowserState( + chrome_browser_state_.get()); + FakeProfileOAuth2TokenService* token_service = + static_cast<FakeProfileOAuth2TokenService*>( + ProfileOAuth2TokenServiceFactory::GetForBrowserState( + chrome_browser_state_.get())); + std::string account_id = + account_tracker->SeedAccountInfo("gaia", "example@email.com"); + ProfileOAuth2TokenServiceIOSDelegate* token_service_delegate = + static_cast<ProfileOAuth2TokenServiceIOSDelegate*>( + token_service->GetDelegate()); + token_service_delegate->AddOrUpdateAccount(account_id); + signin_manager->OnExternalSigninCompleted("example@email.com"); + + EXPECT_TRUE( + browser_state_info_->BrowserStateIsAuthenticatedAtIndex(cache_index_)); + EXPECT_FALSE( + browser_state_info_->BrowserStateIsAuthErrorAtIndex(cache_index_)); + + // Set auth error. + token_service->UpdateAuthErrorForTesting( + account_id, + GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); + EXPECT_TRUE( + browser_state_info_->BrowserStateIsAuthErrorAtIndex(cache_index_)); + + // Remove auth error. + token_service->UpdateAuthErrorForTesting( + account_id, GoogleServiceAuthError::AuthErrorNone()); + EXPECT_FALSE( + browser_state_info_->BrowserStateIsAuthErrorAtIndex(cache_index_)); +}
diff --git a/ios/chrome/browser/sync/BUILD.gn b/ios/chrome/browser/sync/BUILD.gn index b225d03..1f9e4e0 100644 --- a/ios/chrome/browser/sync/BUILD.gn +++ b/ios/chrome/browser/sync/BUILD.gn
@@ -21,8 +21,8 @@ "model_type_store_service_factory.h", "profile_sync_service_factory.cc", "profile_sync_service_factory.h", - "session_sync_service_factory.cc", "session_sync_service_factory.h", + "session_sync_service_factory.mm", "sync_observer_bridge.h", "sync_observer_bridge.mm", "sync_setup_service.cc",
diff --git a/ios/chrome/browser/sync/session_sync_service_factory.cc b/ios/chrome/browser/sync/session_sync_service_factory.cc deleted file mode 100644 index 56ed6f8..0000000 --- a/ios/chrome/browser/sync/session_sync_service_factory.cc +++ /dev/null
@@ -1,163 +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 "ios/chrome/browser/sync/session_sync_service_factory.h" - -#include <utility> - -#include "base/memory/singleton.h" -#include "base/task/post_task.h" -#include "base/time/time.h" -#include "components/browser_sync/profile_sync_service.h" -#include "components/keyed_service/core/service_access_type.h" -#include "components/keyed_service/ios/browser_state_dependency_manager.h" -#include "components/sync/device_info/local_device_info_provider.h" -#include "components/sync/model/model_type_store_service.h" -#include "components/sync_sessions/local_session_event_router.h" -#include "components/sync_sessions/session_sync_prefs.h" -#include "components/sync_sessions/session_sync_service_impl.h" -#include "components/sync_sessions/sync_sessions_client.h" -#include "components/sync_sessions/synced_window_delegates_getter.h" -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/chrome_url_constants.h" -#include "ios/chrome/browser/favicon/favicon_service_factory.h" -#include "ios/chrome/browser/history/history_service_factory.h" -#include "ios/chrome/browser/sync/glue/sync_start_util.h" -#include "ios/chrome/browser/sync/model_type_store_service_factory.h" -#include "ios/chrome/browser/sync/profile_sync_service_factory.h" -#include "ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.h" -#include "ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.h" -#include "ios/chrome/common/channel_info.h" -#include "ios/web/public/web_thread.h" -#include "url/gurl.h" - -using sync_sessions::SessionSyncService; - -namespace { - -bool ShouldSyncURLImpl(const GURL& url) { - if (url == kChromeUIHistoryURL) { - // Whitelist the chrome history page, home for "Tabs from other devices", - // so it can trigger starting up the sync engine. - return true; - } - return url.is_valid() && !url.SchemeIs(kChromeUIScheme) && - !url.SchemeIsFile(); -} - -// iOS implementation of SyncSessionsClient. Needs to be in a separate class -// due to possible multiple inheritance issues, wherein IOSChromeSyncClient -// might inherit from other interfaces with same methods. -class SyncSessionsClientImpl : public sync_sessions::SyncSessionsClient { - public: - explicit SyncSessionsClientImpl(ios::ChromeBrowserState* browser_state) - : browser_state_(browser_state), - window_delegates_getter_( - std::make_unique<TabModelSyncedWindowDelegatesGetter>()), - local_session_event_router_( - std::make_unique<IOSChromeLocalSessionEventRouter>( - browser_state_, - this, - ios::sync_start_util::GetFlareForSyncableService( - browser_state_->GetStatePath()))), - session_sync_prefs_(browser_state->GetPrefs()) {} - - ~SyncSessionsClientImpl() override {} - - // SyncSessionsClient implementation. - favicon::FaviconService* GetFaviconService() override { - DCHECK_CURRENTLY_ON(web::WebThread::UI); - return ios::FaviconServiceFactory::GetForBrowserState( - browser_state_, ServiceAccessType::IMPLICIT_ACCESS); - } - - history::HistoryService* GetHistoryService() override { - DCHECK_CURRENTLY_ON(web::WebThread::UI); - return ios::HistoryServiceFactory::GetForBrowserState( - browser_state_, ServiceAccessType::EXPLICIT_ACCESS); - } - - sync_sessions::SessionSyncPrefs* GetSessionSyncPrefs() override { - return &session_sync_prefs_; - } - - syncer::RepeatingModelTypeStoreFactory GetStoreFactory() override { - return ModelTypeStoreServiceFactory::GetForBrowserState(browser_state_) - ->GetStoreFactory(); - } - - const syncer::DeviceInfo* GetLocalDeviceInfo() override { - DCHECK_CURRENTLY_ON(web::WebThread::UI); - browser_sync::ProfileSyncService* profile_sync_service = - ProfileSyncServiceFactory::GetForBrowserStateIfExists(browser_state_); - if (!profile_sync_service) { - return nullptr; - } - return profile_sync_service->GetLocalDeviceInfoProvider() - ->GetLocalDeviceInfo(); - } - - bool ShouldSyncURL(const GURL& url) const override { - return ShouldSyncURLImpl(url); - } - - sync_sessions::SyncedWindowDelegatesGetter* GetSyncedWindowDelegatesGetter() - override { - return window_delegates_getter_.get(); - } - - sync_sessions::LocalSessionEventRouter* GetLocalSessionEventRouter() - override { - return local_session_event_router_.get(); - } - - private: - ios::ChromeBrowserState* const browser_state_; - const std::unique_ptr<sync_sessions::SyncedWindowDelegatesGetter> - window_delegates_getter_; - const std::unique_ptr<IOSChromeLocalSessionEventRouter> - local_session_event_router_; - sync_sessions::SessionSyncPrefs session_sync_prefs_; - - DISALLOW_COPY_AND_ASSIGN(SyncSessionsClientImpl); -}; - -} // namespace - -// static -SessionSyncServiceFactory* SessionSyncServiceFactory::GetInstance() { - return base::Singleton<SessionSyncServiceFactory>::get(); -} - -// static -bool SessionSyncServiceFactory::ShouldSyncURLForTesting(const GURL& url) { - return ShouldSyncURLImpl(url); -} - -// static -SessionSyncService* SessionSyncServiceFactory::GetForBrowserState( - ios::ChromeBrowserState* browser_state) { - return static_cast<SessionSyncService*>( - GetInstance()->GetServiceForBrowserState(browser_state, true)); -} - -SessionSyncServiceFactory::SessionSyncServiceFactory() - : BrowserStateKeyedServiceFactory( - "SessionSyncService", - BrowserStateDependencyManager::GetInstance()) { - DependsOn(ios::FaviconServiceFactory::GetInstance()); - DependsOn(ios::HistoryServiceFactory::GetInstance()); - DependsOn(ModelTypeStoreServiceFactory::GetInstance()); -} - -SessionSyncServiceFactory::~SessionSyncServiceFactory() {} - -std::unique_ptr<KeyedService> -SessionSyncServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ios::ChromeBrowserState* browser_state = - ios::ChromeBrowserState::FromBrowserState(context); - return std::make_unique<sync_sessions::SessionSyncServiceImpl>( - ::GetChannel(), std::make_unique<SyncSessionsClientImpl>(browser_state)); -}
diff --git a/ios/chrome/browser/sync/session_sync_service_factory.mm b/ios/chrome/browser/sync/session_sync_service_factory.mm new file mode 100644 index 0000000..21a536d --- /dev/null +++ b/ios/chrome/browser/sync/session_sync_service_factory.mm
@@ -0,0 +1,167 @@ +// 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 "ios/chrome/browser/sync/session_sync_service_factory.h" + +#include <utility> + +#include "base/memory/singleton.h" +#include "base/task/post_task.h" +#include "base/time/time.h" +#include "components/browser_sync/profile_sync_service.h" +#include "components/keyed_service/core/service_access_type.h" +#include "components/keyed_service/ios/browser_state_dependency_manager.h" +#include "components/sync/device_info/local_device_info_provider.h" +#include "components/sync/model/model_type_store_service.h" +#include "components/sync_sessions/local_session_event_router.h" +#include "components/sync_sessions/session_sync_prefs.h" +#include "components/sync_sessions/session_sync_service_impl.h" +#include "components/sync_sessions/sync_sessions_client.h" +#include "components/sync_sessions/synced_window_delegates_getter.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#include "ios/chrome/browser/chrome_url_constants.h" +#include "ios/chrome/browser/favicon/favicon_service_factory.h" +#include "ios/chrome/browser/history/history_service_factory.h" +#include "ios/chrome/browser/sync/glue/sync_start_util.h" +#include "ios/chrome/browser/sync/model_type_store_service_factory.h" +#include "ios/chrome/browser/sync/profile_sync_service_factory.h" +#import "ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.h" +#include "ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.h" +#include "ios/chrome/common/channel_info.h" +#include "ios/web/public/web_thread.h" +#include "url/gurl.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +using sync_sessions::SessionSyncService; + +namespace { + +bool ShouldSyncURLImpl(const GURL& url) { + if (url == kChromeUIHistoryURL) { + // Whitelist the chrome history page, home for "Tabs from other devices", + // so it can trigger starting up the sync engine. + return true; + } + return url.is_valid() && !url.SchemeIs(kChromeUIScheme) && + !url.SchemeIsFile(); +} + +// iOS implementation of SyncSessionsClient. Needs to be in a separate class +// due to possible multiple inheritance issues, wherein IOSChromeSyncClient +// might inherit from other interfaces with same methods. +class SyncSessionsClientImpl : public sync_sessions::SyncSessionsClient { + public: + explicit SyncSessionsClientImpl(ios::ChromeBrowserState* browser_state) + : browser_state_(browser_state), + window_delegates_getter_( + std::make_unique<TabModelSyncedWindowDelegatesGetter>()), + local_session_event_router_( + std::make_unique<IOSChromeLocalSessionEventRouter>( + browser_state_, + this, + ios::sync_start_util::GetFlareForSyncableService( + browser_state_->GetStatePath()))), + session_sync_prefs_(browser_state->GetPrefs()) {} + + ~SyncSessionsClientImpl() override {} + + // SyncSessionsClient implementation. + favicon::FaviconService* GetFaviconService() override { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + return ios::FaviconServiceFactory::GetForBrowserState( + browser_state_, ServiceAccessType::IMPLICIT_ACCESS); + } + + history::HistoryService* GetHistoryService() override { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + return ios::HistoryServiceFactory::GetForBrowserState( + browser_state_, ServiceAccessType::EXPLICIT_ACCESS); + } + + sync_sessions::SessionSyncPrefs* GetSessionSyncPrefs() override { + return &session_sync_prefs_; + } + + syncer::RepeatingModelTypeStoreFactory GetStoreFactory() override { + return ModelTypeStoreServiceFactory::GetForBrowserState(browser_state_) + ->GetStoreFactory(); + } + + const syncer::DeviceInfo* GetLocalDeviceInfo() override { + DCHECK_CURRENTLY_ON(web::WebThread::UI); + browser_sync::ProfileSyncService* profile_sync_service = + ProfileSyncServiceFactory::GetForBrowserStateIfExists(browser_state_); + if (!profile_sync_service) { + return nullptr; + } + return profile_sync_service->GetLocalDeviceInfoProvider() + ->GetLocalDeviceInfo(); + } + + bool ShouldSyncURL(const GURL& url) const override { + return ShouldSyncURLImpl(url); + } + + sync_sessions::SyncedWindowDelegatesGetter* GetSyncedWindowDelegatesGetter() + override { + return window_delegates_getter_.get(); + } + + sync_sessions::LocalSessionEventRouter* GetLocalSessionEventRouter() + override { + return local_session_event_router_.get(); + } + + private: + ios::ChromeBrowserState* const browser_state_; + const std::unique_ptr<sync_sessions::SyncedWindowDelegatesGetter> + window_delegates_getter_; + const std::unique_ptr<IOSChromeLocalSessionEventRouter> + local_session_event_router_; + sync_sessions::SessionSyncPrefs session_sync_prefs_; + + DISALLOW_COPY_AND_ASSIGN(SyncSessionsClientImpl); +}; + +} // namespace + +// static +SessionSyncServiceFactory* SessionSyncServiceFactory::GetInstance() { + return base::Singleton<SessionSyncServiceFactory>::get(); +} + +// static +bool SessionSyncServiceFactory::ShouldSyncURLForTesting(const GURL& url) { + return ShouldSyncURLImpl(url); +} + +// static +SessionSyncService* SessionSyncServiceFactory::GetForBrowserState( + ios::ChromeBrowserState* browser_state) { + return static_cast<SessionSyncService*>( + GetInstance()->GetServiceForBrowserState(browser_state, true)); +} + +SessionSyncServiceFactory::SessionSyncServiceFactory() + : BrowserStateKeyedServiceFactory( + "SessionSyncService", + BrowserStateDependencyManager::GetInstance()) { + DependsOn(ios::FaviconServiceFactory::GetInstance()); + DependsOn(ios::HistoryServiceFactory::GetInstance()); + DependsOn(ModelTypeStoreServiceFactory::GetInstance()); +} + +SessionSyncServiceFactory::~SessionSyncServiceFactory() {} + +std::unique_ptr<KeyedService> +SessionSyncServiceFactory::BuildServiceInstanceFor( + web::BrowserState* context) const { + ios::ChromeBrowserState* browser_state = + ios::ChromeBrowserState::FromBrowserState(context); + return std::make_unique<sync_sessions::SessionSyncServiceImpl>( + ::GetChannel(), std::make_unique<SyncSessionsClientImpl>(browser_state)); +}
diff --git a/ios/chrome/browser/sync/sessions/BUILD.gn b/ios/chrome/browser/sync/sessions/BUILD.gn index ee69c4b..75f3e1a 100644 --- a/ios/chrome/browser/sync/sessions/BUILD.gn +++ b/ios/chrome/browser/sync/sessions/BUILD.gn
@@ -18,6 +18,8 @@ "//ios/chrome/browser/browser_state", "//ios/chrome/browser/history", "//ios/chrome/browser/sync/glue", + "//ios/chrome/browser/tabs", + "//ios/chrome/browser/web_state_list", "//ios/web", ] }
diff --git a/ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.h b/ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.h index 832ceb2..baed17a 100644 --- a/ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.h +++ b/ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.h
@@ -14,7 +14,9 @@ #include "base/macros.h" #include "components/sync/model/syncable_service.h" #include "components/sync_sessions/local_session_event_router.h" -#include "ios/web/public/web_state/global_web_state_observer.h" +#import "ios/chrome/browser/tabs/tab_model_list_observer.h" +#include "ios/chrome/browser/web_state_list/web_state_list_observer.h" +#include "ios/web/public/web_state/web_state_observer.h" class GURL; @@ -30,7 +32,9 @@ // web::WebState-related events. class IOSChromeLocalSessionEventRouter : public sync_sessions::LocalSessionEventRouter, - public web::GlobalWebStateObserver { + public web::WebStateObserver, + public WebStateListObserver, + public TabModelListObserver { public: IOSChromeLocalSessionEventRouter( ios::ChromeBrowserState* browser_state, @@ -43,7 +47,15 @@ sync_sessions::LocalSessionEventHandler* handler) override; void Stop() override; - // web::GlobalWebStateObserver: + // TabModelListObserver: + void TabModelRegisteredWithBrowserState( + TabModel* tab_model, + ios::ChromeBrowserState* browser_state) override; + void TabModelUnregisteredFromBrowserState( + TabModel* tab_model, + ios::ChromeBrowserState* browser_state) override; + + // web::WebStateObserver: void NavigationItemsPruned(web::WebState* web_state, size_t pruned_item_count) override; void NavigationItemChanged(web::WebState* web_state) override; @@ -55,7 +67,24 @@ web::PageLoadCompletionStatus load_completion_status) override; void WebStateDestroyed(web::WebState* web_state) override; + // web::WebStateListObserver: + void WebStateInsertedAt(WebStateList* web_state_list, + web::WebState* web_state, + int index, + bool activating) override; + void WebStateReplacedAt(WebStateList* web_state_list, + web::WebState* old_web_state, + web::WebState* new_web_state, + int index) override; + void WebStateDetachedAt(WebStateList* web_state_list, + web::WebState* web_state, + int index) override; + private: + // Methods to add and remove WebStateList observer. + void StartObservingWebStateList(WebStateList* web_state_list); + void StopObservingWebStateList(WebStateList* web_state_list); + // Called when a tab is parented. void OnTabParented(web::WebState* web_state);
diff --git a/ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.mm b/ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.mm index d0aab08d..e5563e0 100644 --- a/ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.mm +++ b/ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.mm
@@ -16,6 +16,9 @@ #include "ios/chrome/browser/sync/glue/sync_start_util.h" #include "ios/chrome/browser/sync/ios_chrome_synced_tab_delegate.h" #include "ios/chrome/browser/tab_parenting_global_observer.h" +#import "ios/chrome/browser/tabs/tab_model.h" +#import "ios/chrome/browser/tabs/tab_model_list.h" +#import "ios/chrome/browser/web_state_list/web_state_list.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -53,9 +56,60 @@ base::Bind(&IOSChromeLocalSessionEventRouter::OnFaviconsChanged, base::Unretained(this))); } + + for (TabModel* tab_model in TabModelList::GetTabModelsForChromeBrowserState( + browser_state_)) { + StartObservingWebStateList(tab_model.webStateList); + } + + TabModelList::AddObserver(this); } -IOSChromeLocalSessionEventRouter::~IOSChromeLocalSessionEventRouter() {} +IOSChromeLocalSessionEventRouter::~IOSChromeLocalSessionEventRouter() { + for (TabModel* tab_model in TabModelList::GetTabModelsForChromeBrowserState( + browser_state_)) { + StopObservingWebStateList(tab_model.webStateList); + } + TabModelList::RemoveObserver(this); +} + +void IOSChromeLocalSessionEventRouter::TabModelRegisteredWithBrowserState( + TabModel* tab_model, + ios::ChromeBrowserState* browser_state) { + StartObservingWebStateList(tab_model.webStateList); +} + +void IOSChromeLocalSessionEventRouter::TabModelUnregisteredFromBrowserState( + TabModel* tab_model, + ios::ChromeBrowserState* browser_state) { + StopObservingWebStateList(tab_model.webStateList); +} + +void IOSChromeLocalSessionEventRouter::WebStateInsertedAt( + WebStateList* web_state_list, + web::WebState* web_state, + int index, + bool activating) { + web_state->AddObserver(this); +} + +void IOSChromeLocalSessionEventRouter::WebStateReplacedAt( + WebStateList* web_state_list, + web::WebState* old_web_state, + web::WebState* new_web_state, + int index) { + old_web_state->RemoveObserver(this); + + if (new_web_state) + new_web_state->AddObserver(this); +} + +void IOSChromeLocalSessionEventRouter::WebStateDetachedAt( + WebStateList* web_state_list, + web::WebState* web_state, + int index) { + web_state->RemoveObserver(this); +} void IOSChromeLocalSessionEventRouter::NavigationItemsPruned( web::WebState* web_state, @@ -85,14 +139,30 @@ OnWebStateChange(web_state); } +void IOSChromeLocalSessionEventRouter::StartObservingWebStateList( + WebStateList* web_state_list) { + web_state_list->AddObserver(this); + for (int index = 0; index < web_state_list->count(); ++index) { + web::WebState* web_state = web_state_list->GetWebStateAt(index); + web_state->AddObserver(this); + } +} + +void IOSChromeLocalSessionEventRouter::StopObservingWebStateList( + WebStateList* web_state_list) { + for (int index = 0; index < web_state_list->count(); ++index) { + web::WebState* web_state = web_state_list->GetWebStateAt(index); + web_state->RemoveObserver(this); + } + web_state_list->RemoveObserver(this); +} + void IOSChromeLocalSessionEventRouter::OnTabParented(web::WebState* web_state) { OnWebStateChange(web_state); } void IOSChromeLocalSessionEventRouter::OnWebStateChange( web::WebState* web_state) { - if (web_state->GetBrowserState() != browser_state_) - return; sync_sessions::SyncedTabDelegate* tab = GetSyncedTabDelegateFromWebState(web_state); if (!tab)
diff --git a/ios/chrome/browser/tabs/tab.h b/ios/chrome/browser/tabs/tab.h index 8248ce8..127f02a6e 100644 --- a/ios/chrome/browser/tabs/tab.h +++ b/ios/chrome/browser/tabs/tab.h
@@ -121,11 +121,6 @@ // Called before capturing a snapshot for Tab. - (void)willUpdateSnapshot; -// Loads the original url of the last non-redirect item (including non-history -// items). Used by request desktop/mobile site so that the updated user agent is -// used. -- (void)reloadWithUserAgentType:(web::UserAgentType)userAgentType; - // Evaluates U2F result. - (void)evaluateU2FResultFromURL:(const GURL&)url;
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm index 5bd9f0b..db88974 100644 --- a/ios/chrome/browser/tabs/tab.mm +++ b/ios/chrome/browser/tabs/tab.mm
@@ -286,14 +286,6 @@ } } -#pragma mark - Public API (relatinge to User agent) - -- (void)reloadWithUserAgentType:(web::UserAgentType)userAgentType { - web::NavigationManager* navigationManager = [self navigationManager]; - DCHECK(navigationManager); - navigationManager->ReloadWithUserAgentType(userAgentType); -} - #pragma mark - Public API (relating to U2F) - (void)evaluateU2FResultFromURL:(const GURL&)URL {
diff --git a/ios/chrome/browser/translate/BUILD.gn b/ios/chrome/browser/translate/BUILD.gn index 34e1241..9f1d2fd4 100644 --- a/ios/chrome/browser/translate/BUILD.gn +++ b/ios/chrome/browser/translate/BUILD.gn
@@ -38,7 +38,6 @@ "//components/metrics", "//components/prefs", "//components/strings", - "//components/sync", "//components/translate/core/browser", "//components/translate/core/common", "//components/translate/ios/browser", @@ -49,7 +48,6 @@ "//ios/chrome/browser/browser_state", "//ios/chrome/browser/infobars", "//ios/chrome/browser/language", - "//ios/chrome/browser/sync", "//ios/chrome/browser/ui/infobars:infobars_ui", "//ios/chrome/browser/ui/util", "//ios/web",
diff --git a/ios/chrome/browser/translate/chrome_ios_translate_client.mm b/ios/chrome/browser/translate/chrome_ios_translate_client.mm index b1a518fc..cc9b1c1 100644 --- a/ios/chrome/browser/translate/chrome_ios_translate_client.mm +++ b/ios/chrome/browser/translate/chrome_ios_translate_client.mm
@@ -13,9 +13,6 @@ #include "components/infobars/core/infobar.h" #include "components/language/core/browser/language_model_manager.h" #include "components/prefs/pref_service.h" -#include "components/sync/driver/sync_driver_switches.h" -#include "components/sync/protocol/user_event_specifics.pb.h" -#include "components/sync/user_events/user_event_service.h" #include "components/translate/core/browser/page_translated_details.h" #include "components/translate/core/browser/translate_accept_languages.h" #include "components/translate/core/browser/translate_infobar_delegate.h" @@ -31,7 +28,6 @@ #include "ios/chrome/browser/infobars/infobar_manager_impl.h" #include "ios/chrome/browser/language/language_model_manager_factory.h" #include "ios/chrome/browser/pref_names.h" -#import "ios/chrome/browser/sync/ios_user_event_service_factory.h" #import "ios/chrome/browser/translate/after_translate_infobar_controller.h" #import "ios/chrome/browser/translate/before_translate_infobar_controller.h" #import "ios/chrome/browser/translate/never_translate_infobar_controller.h" @@ -135,31 +131,7 @@ } void ChromeIOSTranslateClient::RecordTranslateEvent( - const metrics::TranslateEventProto& translate_event) { - if (!base::FeatureList::IsEnabled(switches::kSyncUserTranslationEvents)) - return; - - syncer::UserEventService* const user_event_service = - IOSUserEventServiceFactory::GetForBrowserState( - ios::ChromeBrowserState::FromBrowserState( - web_state_->GetBrowserState())); - const auto* const item = - web_state_->GetNavigationManager()->GetLastCommittedItem(); - - // If entry is null, we don't record the page. - // The navigation entry can be null in situations like download or initial - // blank page. - if (item == nullptr) - return; - - auto specifics = std::make_unique<sync_pb::UserEventSpecifics>(); - // We only log the event we care about. - const bool needs_logging = translate::ConstructTranslateEvent( - item->GetTimestamp().ToInternalValue(), translate_event, specifics.get()); - if (needs_logging) { - user_event_service->RecordUserEvent(std::move(specifics)); - } -} + const metrics::TranslateEventProto& translate_event) {} bool ChromeIOSTranslateClient::ShowTranslateUI( translate::TranslateStep step, @@ -213,27 +185,7 @@ } void ChromeIOSTranslateClient::RecordLanguageDetectionEvent( - const translate::LanguageDetectionDetails& details) const { - if (!base::FeatureList::IsEnabled(switches::kSyncUserLanguageDetectionEvents)) - return; - - syncer::UserEventService* const user_event_service = - IOSUserEventServiceFactory::GetForBrowserState( - ios::ChromeBrowserState::FromBrowserState( - web_state_->GetBrowserState())); - const auto* const item = - web_state_->GetNavigationManager()->GetLastCommittedItem(); - - // If entry is null, we don't record the page. - // The navigation entry can be null in situations like download or initial - // blank page. - if (item != nullptr && - TranslateServiceIOS::IsTranslatableURL(item->GetVirtualURL())) { - user_event_service->RecordUserEvent( - translate::ConstructLanguageDetectionEvent( - item->GetTimestamp().ToInternalValue(), details)); - } -} + const translate::LanguageDetectionDetails& details) const {} bool ChromeIOSTranslateClient::IsTranslatableURL(const GURL& url) { return TranslateServiceIOS::IsTranslatableURL(url);
diff --git a/ios/chrome/browser/ui/autofill/BUILD.gn b/ios/chrome/browser/ui/autofill/BUILD.gn index 8697d205..052e7ab 100644 --- a/ios/chrome/browser/ui/autofill/BUILD.gn +++ b/ios/chrome/browser/ui/autofill/BUILD.gn
@@ -29,6 +29,7 @@ "//components/password_manager/core/browser", "//components/prefs", "//components/strings", + "//components/translate/core/browser:browser", "//google_apis", "//ios/chrome/app/strings", "//ios/chrome/browser", @@ -43,6 +44,7 @@ "//ios/chrome/browser/signin", "//ios/chrome/browser/ssl", "//ios/chrome/browser/sync", + "//ios/chrome/browser/translate:translate", "//ios/chrome/browser/ui", "//ios/chrome/browser/ui/autofill/cells", "//ios/chrome/browser/ui/autofill/manual_fill:manual_fill",
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h index ee71a815..c21f03f 100644 --- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h +++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h
@@ -57,6 +57,8 @@ ukm::SourceId GetUkmSourceId() override; AddressNormalizer* GetAddressNormalizer() override; security_state::SecurityLevel GetSecurityLevelForUmaHistograms() override; + std::string GetPageLanguage() const override; + void ShowAutofillSettings(bool show_credit_card_settings) override; void ShowUnmaskPrompt(const CreditCard& card, UnmaskCardReason reason, @@ -74,16 +76,17 @@ MigrationDeleteCardCallback delete_local_card_callback) override; void ConfirmSaveAutofillProfile(const AutofillProfile& profile, base::OnceClosure callback) override; - void ConfirmSaveCreditCardLocally(const CreditCard& card, - bool show_prompt, - base::OnceClosure callback) override; + void ConfirmSaveCreditCardLocally( + const CreditCard& card, + bool show_prompt, + LocalSaveCardPromptCallback callback) override; void ConfirmSaveCreditCardToCloud( const CreditCard& card, std::unique_ptr<base::DictionaryValue> legal_message, bool should_request_name_from_user, bool should_request_expiration_date_from_user, bool show_prompt, - UserAcceptedUploadCallback callback) override; + UploadSaveCardPromptCallback callback) override; void ConfirmCreditCardFillAssist(const CreditCard& card, base::OnceClosure callback) override; bool HasCreditCardScanFeature() override;
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm index 46a9088..c190bfa9 100644 --- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm +++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
@@ -22,6 +22,7 @@ #include "components/browser_sync/profile_sync_service.h" #include "components/infobars/core/infobar.h" #include "components/keyed_service/core/service_access_type.h" +#include "components/translate/core/browser/translate_manager.h" #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/autofill/address_normalizer_factory.h" #include "ios/chrome/browser/autofill/legacy_strike_database_factory.h" @@ -33,6 +34,7 @@ #import "ios/chrome/browser/ssl/insecure_input_tab_helper.h" #include "ios/chrome/browser/ssl/ios_security_state_tab_helper.h" #include "ios/chrome/browser/sync/profile_sync_service_factory.h" +#include "ios/chrome/browser/translate/chrome_ios_translate_client.h" #include "ios/chrome/browser/ui/autofill/card_unmask_prompt_view_bridge.h" #include "ios/chrome/browser/ui/autofill/save_card_infobar_controller.h" #include "ios/chrome/browser/web_data_service_factory.h" @@ -170,6 +172,18 @@ return result.security_level; } +std::string ChromeAutofillClientIOS::GetPageLanguage() const { + // TODO(crbug.com/912597): iOS vs other platforms extracts language from + // the top level frame vs whatever frame directly holds the form. + auto* translate_client = ChromeIOSTranslateClient::FromWebState(web_state_); + if (translate_client) { + auto* translate_manager = translate_client->GetTranslateManager(); + if (translate_manager) + return translate_manager->GetLanguageState().original_language(); + } + return std::string(); +} + void ChromeAutofillClientIOS::ShowAutofillSettings( bool show_credit_card_settings) { NOTREACHED(); @@ -222,13 +236,13 @@ void ChromeAutofillClientIOS::ConfirmSaveCreditCardLocally( const CreditCard& card, bool show_prompt, - base::OnceClosure callback) { + LocalSaveCardPromptCallback callback) { DCHECK(show_prompt); infobar_manager_->AddInfoBar(CreateSaveCardInfoBarMobile( std::make_unique<AutofillSaveCardInfoBarDelegateMobile>( /*upload=*/false, /*should_request_name_from_user=*/false, card, - std::make_unique<base::DictionaryValue>(), GetLegacyStrikeDatabase(), - /*upload_save_card_callback=*/UserAcceptedUploadCallback(), + std::make_unique<base::DictionaryValue>(), + /*upload_save_card_callback=*/UploadSaveCardPromptCallback(), /*local_save_card_callback=*/std::move(callback), GetPrefs()))); } @@ -238,14 +252,15 @@ bool should_request_name_from_user, bool should_request_expiration_date_from_user, bool show_prompt, - UserAcceptedUploadCallback callback) { + UploadSaveCardPromptCallback callback) { DCHECK(show_prompt); auto save_card_info_bar_delegate_mobile = std::make_unique<AutofillSaveCardInfoBarDelegateMobile>( /*upload=*/true, /*should_request_name_from_user=*/false, card, - std::move(legal_message), GetLegacyStrikeDatabase(), + std::move(legal_message), /*upload_save_card_callback=*/std::move(callback), - /*local_save_card_callback=*/base::Closure(), GetPrefs()); + /*local_save_card_callback=*/LocalSaveCardPromptCallback(), + GetPrefs()); // Allow user to save card only if legal messages are successfully parsed. // Legal messages are provided only for the upload case, not for local save. if (save_card_info_bar_delegate_mobile->LegalMessagesParsedSuccessfully()) {
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/BUILD.gn b/ios/chrome/browser/ui/autofill/manual_fill/BUILD.gn index 6ad4eae..2a56d38e 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/BUILD.gn +++ b/ios/chrome/browser/ui/autofill/manual_fill/BUILD.gn
@@ -185,6 +185,7 @@ configs += [ "//build/config/compiler:enable_arc" ] testonly = true sources = [ + "card_view_controller_egtest.mm", "keyboard_observer_egtest.mm", "password_view_controller_egtest.mm", ] @@ -193,10 +194,13 @@ ":manual_fill_ui", "//base", "//base/test:test_support", + "//components/autofill/core/browser", + "//components/autofill/core/browser:test_support", "//components/autofill/core/common", "//components/autofill/ios/browser", "//components/keyed_service/core", "//components/password_manager/core/browser", + "//ios/chrome/browser/autofill", "//ios/chrome/browser/passwords", "//ios/chrome/browser/ui/util", "//ios/chrome/test/app:test_support",
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/action_cell.mm b/ios/chrome/browser/ui/autofill/manual_fill/action_cell.mm index a9533d0..b1097c2 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/action_cell.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/action_cell.mm
@@ -16,10 +16,10 @@ namespace { // The multiplier for the base system spacing at the top margin. -static const CGFloat TopBaseSystemSpacingMultiplier = 1.1; +static const CGFloat TopBaseSystemSpacingMultiplier = 0.8; // The multiplier for the base system spacing at the bottom margin. -static const CGFloat BottomBaseSystemSpacingMultiplier = 1.5; +static const CGFloat BottomBaseSystemSpacingMultiplier = 1.8; } // namespace @@ -89,6 +89,7 @@ [self.titleButton setTitleColor:UIColor.cr_manualFillTintColor forState:UIControlStateNormal]; self.titleButton.enabled = YES; + self.grayLine.hidden = YES; } - (void)setUpWithTitle:(NSString*)title @@ -114,10 +115,17 @@ NSMutableArray<UIView*>* verticalLeadViews = [[NSMutableArray alloc] init]; [verticalLeadViews addObject:self.titleButton]; + // When disabled, the label is in 'message' mode, and needs to be centered + // differently because it is in the data area rather than in the action area. + CGFloat topMultiplier = + enabled ? TopBaseSystemSpacingMultiplier : TopSystemSpacingMultiplier; + CGFloat bottomMultiplier = enabled ? BottomBaseSystemSpacingMultiplier + : MiddleSystemSpacingMultiplier; + self.verticalConstraints = VerticalConstraintsSpacingForViewsInContainerWithMultipliers( - verticalLeadViews, self.contentView, TopBaseSystemSpacingMultiplier, - BottomBaseSystemSpacingMultiplier, BottomBaseSystemSpacingMultiplier); + verticalLeadViews, self.contentView, topMultiplier, + MiddleSystemSpacingMultiplier, bottomMultiplier); } #pragma mark - Private @@ -132,8 +140,8 @@ @selector(userDidTapTitleButton:), self); self.titleButton.titleLabel.lineBreakMode = NSLineBreakByTruncatingTail; [self.contentView addSubview:self.titleButton]; - HorizontalConstraintsForViewsOnGuideWithShift(@[ self.titleButton ], guide, - 0); + HorizontalConstraintsForViewsOnGuideWithMargin(@[ self.titleButton ], guide, + 0); self.verticalConstraints = @[]; }
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/card_mediator.h b/ios/chrome/browser/ui/autofill/manual_fill/card_mediator.h index fc6d6614..f3bad60 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/card_mediator.h +++ b/ios/chrome/browser/ui/autofill/manual_fill/card_mediator.h
@@ -20,7 +20,6 @@ namespace manual_fill { extern NSString* const ManageCardsAccessibilityIdentifier; -extern NSString* const OtherCardsAccessibilityIdentifier; } // namespace manual_fill // Object in charge of getting the cards relevant for the manual fill
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/card_view_controller_egtest.mm b/ios/chrome/browser/ui/autofill/manual_fill/card_view_controller_egtest.mm new file mode 100644 index 0000000..a36a33f --- /dev/null +++ b/ios/chrome/browser/ui/autofill/manual_fill/card_view_controller_egtest.mm
@@ -0,0 +1,513 @@ +// 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. + +#import <EarlGrey/EarlGrey.h> +#import <EarlGrey/GREYKeyboard.h> + +#include "base/ios/ios_util.h" +#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#import "base/test/ios/wait_util.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/credit_card.h" +#include "components/autofill/core/browser/personal_data_manager.h" +#include "components/autofill/core/common/autofill_features.h" +#include "components/keyed_service/core/service_access_type.h" +#include "ios/chrome/browser/autofill/personal_data_manager_factory.h" +#import "ios/chrome/browser/ui/autofill/manual_fill/card_coordinator.h" +#import "ios/chrome/browser/ui/autofill/manual_fill/card_mediator.h" +#import "ios/chrome/browser/ui/autofill/manual_fill/card_view_controller.h" +#import "ios/chrome/browser/ui/autofill/manual_fill/manual_fill_accessory_view_controller.h" +#import "ios/chrome/browser/ui/util/ui_util.h" +#import "ios/chrome/test/app/chrome_test_util.h" +#import "ios/chrome/test/earl_grey/chrome_actions.h" +#import "ios/chrome/test/earl_grey/chrome_earl_grey.h" +#import "ios/chrome/test/earl_grey/chrome_matchers.h" +#import "ios/chrome/test/earl_grey/chrome_test_case.h" +#include "ios/web/public/features.h" +#import "ios/web/public/test/earl_grey/web_view_matchers.h" +#include "ios/web/public/test/element_selector.h" +#import "ios/web/public/test/web_view_interaction_test_util.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "url/gurl.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { + +const char kFormElementUsername[] = "username"; +const char kFormElementOtherStuff[] = "otherstuff"; + +NSString* kLocalCardNumber = @"4111111111111111"; +NSString* kLocalCardHolder = @"Test User"; +NSString* kLocalCardExpirationMonth = @"11"; +NSString* kLocalCardExpirationYear = @"22"; + +// Unicode characters used in card number: +// - 0x0020 - Space. +// - 0x2060 - WORD-JOINER (makes string undivisible). +constexpr base::char16 separator[] = {0x2060, 0x0020, 0}; +NSString* kObfuscatedNumberPrefix = base::SysUTF16ToNSString( + autofill::kMidlineEllipsis + base::string16(separator) + + autofill::kMidlineEllipsis + base::string16(separator) + + autofill::kMidlineEllipsis + base::string16(separator)); + +NSString* kLocalNumberObfuscated = + [NSString stringWithFormat:@"%@1111", kObfuscatedNumberPrefix]; + +NSString* kServerNumberObfuscated = + [NSString stringWithFormat:@"%@2109", kObfuscatedNumberPrefix]; + +const char kFormHTMLFile[] = "/multi_field_form.html"; + +// Timeout in seconds while waiting for a profile or a credit to be added to the +// PersonalDataManager. +const NSTimeInterval kPDMMaxDelaySeconds = 10.0; + +// Returns a matcher for the credit card icon in the keyboard accessory bar. +id<GREYMatcher> CreditCardIconMatcher() { + return grey_accessibilityID( + manual_fill::AccessoryCreditCardAccessibilityIdentifier); +} + +id<GREYMatcher> KeyboardIconMatcher() { + return grey_accessibilityID( + manual_fill::AccessoryKeyboardAccessibilityIdentifier); +} + +// Returns a matcher for the credit card table view in manual fallback. +id<GREYMatcher> CreditCardTableViewMatcher() { + return grey_accessibilityID( + manual_fill::CardTableViewAccessibilityIdentifier); +} + +// Returns a matcher for the button to open password settings in manual +// fallback. +id<GREYMatcher> ManageCreditCardsMatcher() { + return grey_accessibilityID(manual_fill::ManageCardsAccessibilityIdentifier); +} + +// Returns a matcher for the credit card settings collection view. +id<GREYMatcher> CreditCardSettingsMatcher() { + return grey_accessibilityID(@"kAutofillCollectionViewId"); +} + +// Returns a matcher for the CreditCardTableView window. +id<GREYMatcher> CreditCardTableViewWindowMatcher() { + id<GREYMatcher> classMatcher = grey_kindOfClass([UIWindow class]); + id<GREYMatcher> parentMatcher = grey_descendant(CreditCardTableViewMatcher()); + return grey_allOf(classMatcher, parentMatcher, nil); +} + +// Polls the JavaScript query |java_script_condition| until the returned +// |boolValue| is YES with a kWaitForActionTimeout timeout. +BOOL WaitForJavaScriptCondition(NSString* java_script_condition) { + auto verify_block = ^BOOL { + id value = chrome_test_util::ExecuteJavaScript(java_script_condition, nil); + return [value isEqual:@YES]; + }; + NSTimeInterval timeout = base::test::ios::kWaitForActionTimeout; + NSString* condition_name = [NSString + stringWithFormat:@"Wait for JS condition: %@", java_script_condition]; + GREYCondition* condition = [GREYCondition conditionWithName:condition_name + block:verify_block]; + return [condition waitWithTimeout:timeout]; +} + +} // namespace + +// Integration Tests for Manual Fallback credit cards View Controller. +@interface CreditCardViewControllerTestCase : ChromeTestCase { + // The PersonalDataManager instance for the current browser state. + autofill::PersonalDataManager* _personalDataManager; + + // Credit Cards added to the PersonalDataManager. + std::vector<autofill::CreditCard> _cards; +} +@end + +@implementation CreditCardViewControllerTestCase + +- (void)setUp { + [super setUp]; + GREYAssert(autofill::features::IsPasswordManualFallbackEnabled(), + @"Manual Fallback must be enabled for this Test Case"); + GREYAssert(autofill::features::IsAutofillManualFallbackEnabled(), + @"Manual Fallback phase 2 must be enabled for this Test Case"); + + GREYAssertTrue(self.testServer->Start(), @"Test server failed to start."); + const GURL URL = self.testServer->GetURL(kFormHTMLFile); + [ChromeEarlGrey loadURL:URL]; + [ChromeEarlGrey waitForWebViewContainingText:"hello!"]; + + _personalDataManager = + autofill::PersonalDataManagerFactory::GetForBrowserState( + chrome_test_util::GetOriginalBrowserState()); + _personalDataManager->SetSyncingForTest(true); +} + +- (void)tearDown { + for (const auto& card : _cards) { + _personalDataManager->RemoveByGUID(card.guid()); + } + _cards.clear(); + + [EarlGrey rotateDeviceToOrientation:UIDeviceOrientationPortrait + errorOrNil:nil]; + [super tearDown]; +} + +#pragma mark - Helpers + +// Adds a local credit card, one that doesn't need CVC unlocking. +- (void)addCreditCard:(const autofill::CreditCard&)card { + _cards.push_back(card); + size_t card_count = _personalDataManager->GetCreditCards().size(); + _personalDataManager->AddCreditCard(card); + GREYAssert(base::test::ios::WaitUntilConditionOrTimeout( + kPDMMaxDelaySeconds, + ^bool() { + return card_count < + _personalDataManager->GetCreditCards().size(); + }), + @"Failed to add credit card."); + _personalDataManager->NotifyPersonalDataChangedForTest(); +} + +// Adds a server credit card, one that needs CVC unlocking. +- (void)addServerCreditCard:(const autofill::CreditCard&)card { + DCHECK(card.record_type() != autofill::CreditCard::LOCAL_CARD); + _personalDataManager->AddServerCreditCardForTest( + std::make_unique<autofill::CreditCard>(card)); + _personalDataManager->NotifyPersonalDataChangedForTest(); +} + +- (void)saveLocalCreditCard { + autofill::CreditCard card = autofill::test::GetCreditCard(); + [self addCreditCard:card]; +} + +- (void)saveMaskedCreditCard { + autofill::CreditCard card = autofill::test::GetMaskedServerCard(); + [self addServerCreditCard:card]; +} + +#pragma mark - Tests + +// Tests that the credit card view butotn is absent when there are no cards +// available. +- (void)testCreditCardsButtonAbsentWhenNoCreditCardsAvailable { + // Bring up the keyboard. + [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] + performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; + + // Verify there's no credit card icon. + [[EarlGrey selectElementWithMatcher:CreditCardIconMatcher()] + assertWithMatcher:grey_notVisible()]; +} + +// Tests that the credit card view controller appears on screen. +- (void)testCreditCardsViewControllerIsPresented { + [self saveLocalCreditCard]; + + // Bring up the keyboard. + [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] + performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; + + // Tap on the credit card icon. + [[EarlGrey selectElementWithMatcher:CreditCardIconMatcher()] + performAction:grey_tap()]; + + // Verify the credit cards controller table view is visible. + [[EarlGrey selectElementWithMatcher:CreditCardTableViewMatcher()] + assertWithMatcher:grey_sufficientlyVisible()]; +} + +// Tests that the credit cards view controller contains the "Manage Credit +// Cards..." action. +- (void)testCreditCardsViewControllerContainsManageCreditCardsAction { + [self saveLocalCreditCard]; + + // Bring up the keyboard. + [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] + performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; + + // Tap on the credit card icon. + [[EarlGrey selectElementWithMatcher:CreditCardIconMatcher()] + performAction:grey_tap()]; + + // Try to scroll. + [[EarlGrey selectElementWithMatcher:CreditCardTableViewMatcher()] + performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)]; + + // Verify the credit cards controller contains the "Manage Credit Cards..." + // action. + [[EarlGrey selectElementWithMatcher:ManageCreditCardsMatcher()] + assertWithMatcher:grey_interactable()]; +} + +// Tests that the "Manage Credt Cards..." action works. +- (void)testManageCreditCardsActionOpensCreditCardSettings { + [self saveLocalCreditCard]; + + // Bring up the keyboard. + [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] + performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; + + // Tap on the credit card icon. + [[EarlGrey selectElementWithMatcher:CreditCardIconMatcher()] + performAction:grey_tap()]; + + // Try to scroll. + [[EarlGrey selectElementWithMatcher:CreditCardTableViewMatcher()] + performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)]; + + // Tap the "Manage Credit Cards..." action. + [[EarlGrey selectElementWithMatcher:ManageCreditCardsMatcher()] + performAction:grey_tap()]; + + // Verify the credit cards settings opened. + [[EarlGrey selectElementWithMatcher:CreditCardSettingsMatcher()] + assertWithMatcher:grey_sufficientlyVisible()]; +} + +// Tests that the credit card View Controller is dismissed when tapping the +// keyboard icon. +- (void)testKeyboardIconDismissCreditCardController { + if (IsIPadIdiom()) { + // The keyboard icon is never present in iPads. + return; + } + [self saveLocalCreditCard]; + + // Bring up the keyboard. + [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] + performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; + + // Tap on the credit cards icon. + [[EarlGrey selectElementWithMatcher:CreditCardIconMatcher()] + performAction:grey_tap()]; + + // Verify the credit card controller table view is visible. + [[EarlGrey selectElementWithMatcher:CreditCardTableViewMatcher()] + assertWithMatcher:grey_sufficientlyVisible()]; + + // Tap on the keyboard icon. + [[EarlGrey selectElementWithMatcher:KeyboardIconMatcher()] + performAction:grey_tap()]; + + // Verify the credit card controller table view and the credit card icon is + // NOT visible. + [[EarlGrey selectElementWithMatcher:CreditCardTableViewMatcher()] + assertWithMatcher:grey_notVisible()]; + [[EarlGrey selectElementWithMatcher:KeyboardIconMatcher()] + assertWithMatcher:grey_notVisible()]; +} + +// Tests that the credit card View Controller is dismissed when tapping the +// outside the popover on iPad. +- (void)testIPadTappingOutsidePopOverDismissCreditCardController { + if (!IsIPadIdiom()) { + return; + } + [self saveLocalCreditCard]; + + // Bring up the keyboard. + [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] + performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; + + // Tap on the credit cards icon. + [[EarlGrey selectElementWithMatcher:CreditCardIconMatcher()] + performAction:grey_tap()]; + + // Verify the credit card controller table view is visible. + [[EarlGrey selectElementWithMatcher:CreditCardTableViewMatcher()] + assertWithMatcher:grey_sufficientlyVisible()]; + + // Tap on a point outside of the popover. + // The way EarlGrey taps doesn't go through the window hierarchy. Because of + // this, the tap needs to be done in the same window as the popover. + [[EarlGrey selectElementWithMatcher:CreditCardTableViewWindowMatcher()] + performAction:grey_tapAtPoint(CGPointMake(0, 0))]; + + // Verify the credit card controller table view and the credit card icon is + // NOT visible. + [[EarlGrey selectElementWithMatcher:CreditCardTableViewMatcher()] + assertWithMatcher:grey_notVisible()]; + [[EarlGrey selectElementWithMatcher:KeyboardIconMatcher()] + assertWithMatcher:grey_notVisible()]; +} + +// Tests that the credit card View Controller is dismissed when tapping the +// keyboard. +- (void)testTappingKeyboardDismissCreditCardControllerPopOver { + if (!IsIPadIdiom()) { + return; + } + [self saveLocalCreditCard]; + + // Bring up the keyboard. + [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] + performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; + + // Tap on the credit cards icon. + [[EarlGrey selectElementWithMatcher:CreditCardIconMatcher()] + performAction:grey_tap()]; + + // Verify the credit card controller table view is visible. + [[EarlGrey selectElementWithMatcher:CreditCardTableViewMatcher()] + assertWithMatcher:grey_sufficientlyVisible()]; + + [[EarlGrey selectElementWithMatcher:CreditCardTableViewMatcher()] + performAction:grey_typeText(@"text")]; + + // Verify the credit card controller table view and the credit card icon is + // NOT visible. + [[EarlGrey selectElementWithMatcher:CreditCardTableViewMatcher()] + assertWithMatcher:grey_notVisible()]; + [[EarlGrey selectElementWithMatcher:KeyboardIconMatcher()] + assertWithMatcher:grey_notVisible()]; +} + +// Tests that after switching fields the content size of the table view didn't +// grow. +- (void)testCreditCardControllerKeepsRightSize { + [self saveLocalCreditCard]; + + // Bring up the keyboard. + [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] + performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; + + // Tap on the credit cards icon. + [[EarlGrey selectElementWithMatcher:CreditCardIconMatcher()] + performAction:grey_tap()]; + + // Tap the second element. + [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] + performAction:chrome_test_util::TapWebElement(kFormElementOtherStuff)]; + + // Try to scroll. + [[EarlGrey selectElementWithMatcher:CreditCardTableViewMatcher()] + performAction:grey_scrollToContentEdge(kGREYContentEdgeBottom)]; +} + +// Tests that the credit card View Controller stays on rotation. +- (void)testCreditCardControllerSupportsRotation { + [self saveLocalCreditCard]; + + // Bring up the keyboard. + [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] + performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; + + // Tap on the credit cards icon. + [[EarlGrey selectElementWithMatcher:CreditCardIconMatcher()] + performAction:grey_tap()]; + + // Verify the credit card controller table view is visible. + [[EarlGrey selectElementWithMatcher:CreditCardTableViewMatcher()] + assertWithMatcher:grey_sufficientlyVisible()]; + + [EarlGrey rotateDeviceToOrientation:UIDeviceOrientationLandscapeLeft + errorOrNil:nil]; + + // Verify the credit card controller table view is still visible. + [[EarlGrey selectElementWithMatcher:CreditCardTableViewMatcher()] + assertWithMatcher:grey_sufficientlyVisible()]; +} + +// Tests that credit card number (for local card) is injected. +// TODO(crbug.com/845472): maybe figure a way to test successfull injection +// when page is https, but right now if we use the https embedded server, +// there's a warning page that stops the flow because of a +// NET::ERR_CERT_AUTHORITY_INVALID. +- (void)testCreditCardLocalNumberDoesntInjectOnHttp { + [self verifyCreditCardButtonWithTitle:kLocalNumberObfuscated + doesInjectValue:@""]; +} + +// Tests that credit card cardholder is injected. +- (void)testCreditCardCardHolderInjectsCorrectly { + [self verifyCreditCardButtonWithTitle:kLocalCardHolder + doesInjectValue:kLocalCardHolder]; +} + +// Tests that credit card expiration month is injected. +- (void)testCreditCardExpirationMonthInjectsCorrectly { + [self verifyCreditCardButtonWithTitle:kLocalCardExpirationMonth + doesInjectValue:kLocalCardExpirationMonth]; +} + +// Tests that credit card expiration year is injected. +- (void)testCreditCardExpirationYearInjectsCorrectly { + [self verifyCreditCardButtonWithTitle:kLocalCardExpirationYear + doesInjectValue:kLocalCardExpirationYear]; +} + +// Tests that masked credit card offer CVC input. +// TODOD(crbug.com/909748) can't test this one until https tests are possible. +- (void)DISABLED_testCreditCardServerNumberRequiresCVC { + [self saveMaskedCreditCard]; + + // Bring up the keyboard. + [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] + performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; + + // Wait for the accessory icon to appear. + [GREYKeyboard waitForKeyboardToAppear]; + + // Tap on the passwords icon. + [[EarlGrey selectElementWithMatcher:CreditCardIconMatcher()] + performAction:grey_tap()]; + + // Verify the password controller table view is visible. + [[EarlGrey selectElementWithMatcher:CreditCardTableViewMatcher()] + assertWithMatcher:grey_sufficientlyVisible()]; + + // Select a the masked number. + [[EarlGrey selectElementWithMatcher:grey_buttonTitle(kServerNumberObfuscated)] + performAction:grey_tap()]; + + // Verify the CVC requester is visible. + [[EarlGrey selectElementWithMatcher:grey_text(@"Confirm Card")] + assertWithMatcher:grey_notNil()]; + + // TODO(crbug.com/845472): maybe figure a way to enter CVC and get the + // unlocked card result. +} + +#pragma mark - Private + +- (void)verifyCreditCardButtonWithTitle:(NSString*)title + doesInjectValue:(NSString*)result { + [self saveLocalCreditCard]; + + // Bring up the keyboard. + [[EarlGrey selectElementWithMatcher:chrome_test_util::WebViewMatcher()] + performAction:chrome_test_util::TapWebElement(kFormElementUsername)]; + + // Wait for the accessory icon to appear. + [GREYKeyboard waitForKeyboardToAppear]; + + // Tap on the passwords icon. + [[EarlGrey selectElementWithMatcher:CreditCardIconMatcher()] + performAction:grey_tap()]; + + // Verify the password controller table view is visible. + [[EarlGrey selectElementWithMatcher:CreditCardTableViewMatcher()] + assertWithMatcher:grey_sufficientlyVisible()]; + + // Select a field. + [[EarlGrey selectElementWithMatcher:grey_buttonTitle(title)] + performAction:grey_tap()]; + + // Verify Web Content. + NSString* javaScriptCondition = [NSString + stringWithFormat:@"window.document.getElementById('%s').value === '%@'", + kFormElementUsername, result]; + XCTAssertTrue(WaitForJavaScriptCondition(javaScriptCondition)); +} + +@end
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/credit_card.h b/ios/chrome/browser/ui/autofill/manual_fill/credit_card.h index a087951..b39fe75 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/credit_card.h +++ b/ios/chrome/browser/ui/autofill/manual_fill/credit_card.h
@@ -35,10 +35,14 @@ // The credit card expiration month. @property(nonatomic, readonly) NSString* expirationMonth; +// The credit card icon id. +@property(nonatomic, readonly) int issuerNetworkIconID; + // Default init. |GUID| and |number| are the only fields considered for // equality, so we can differentiate between an obfuscated and a comlete one. - (instancetype)initWithGUID:(NSString*)GUID network:(NSString*)network + issuerNetworkIconID:(int)issuerNetworkIconID bankName:(NSString*)bankName cardHolder:(NSString*)cardHolder number:(NSString*)number
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/credit_card.mm b/ios/chrome/browser/ui/autofill/manual_fill/credit_card.mm index 726aefa..d108d46 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/credit_card.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/credit_card.mm
@@ -12,6 +12,7 @@ - (instancetype)initWithGUID:(NSString*)GUID network:(NSString*)network + issuerNetworkIconID:(int)issuerNetworkIconID bankName:(NSString*)bankName cardHolder:(NSString*)cardHolder number:(NSString*)number @@ -22,6 +23,7 @@ if (self) { _GUID = [GUID copy]; _network = [network copy]; + _issuerNetworkIconID = issuerNetworkIconID; _bankName = [bankName copy]; _cardHolder = [cardHolder copy]; _number = [number copy]; @@ -63,10 +65,11 @@ // logs. return [NSString stringWithFormat: - @"<%@ (%p): GUID: %@, network: %@, bankName: %@, cardHolder: %@, " - @"obfuscatedNumber: %@, expirationYear: %@, expirationMonth: %@>", + @"<%@ (%p): GUID: %@, network: %@, issuerNetworkIconID:%d, " + @"bankName: %@, cardHolder: %@, obfuscatedNumber: %@, " + @"expirationYear: %@, expirationMonth: %@>", NSStringFromClass([self class]), self, self.GUID, self.network, - self.bankName, self.cardHolder, self.obfuscatedNumber, - self.expirationYear, self.expirationMonth]; + self.issuerNetworkIconID, self.bankName, self.cardHolder, + self.obfuscatedNumber, self.expirationYear, self.expirationMonth]; } @end
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/credit_card_form.mm b/ios/chrome/browser/ui/autofill/manual_fill/credit_card_form.mm index 0e72ba2..6916af3 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/credit_card_form.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/credit_card_form.mm
@@ -6,6 +6,7 @@ #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/autofill_data_util.h" #include "components/autofill/core/browser/credit_card.h" #import "components/autofill/ios/browser/credit_card_util.h" #include "ios/chrome/browser/application_context.h" @@ -30,6 +31,9 @@ number = base::SysUTF16ToNSString(autofill::CreditCard::StripSeparators( creditCard.GetRawInfo(autofill::CREDIT_CARD_NUMBER))); } + const int issuerNetworkIconID = + autofill::data_util::GetPaymentRequestData(creditCard.network()) + .icon_resource_id; // Unicode characters used in card number: // - 0x0020 - Space. @@ -49,6 +53,7 @@ return [self initWithGUID:GUID network:network + issuerNetworkIconID:issuerNetworkIconID bankName:bankName cardHolder:cardHolder number:number
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/credit_card_unittest.mm b/ios/chrome/browser/ui/autofill/manual_fill/credit_card_unittest.mm index dccc0595..e76bef37 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/credit_card_unittest.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/credit_card_unittest.mm
@@ -25,6 +25,7 @@ ManualFillCreditCard* card = [[ManualFillCreditCard alloc] initWithGUID:GUID network:network + issuerNetworkIconID:1 bankName:bankName cardHolder:cardHolder number:number @@ -34,6 +35,7 @@ EXPECT_TRUE(card); EXPECT_TRUE([GUID isEqualToString:card.GUID]); EXPECT_TRUE([network isEqualToString:card.network]); + EXPECT_TRUE(card.issuerNetworkIconID == 1); EXPECT_TRUE([cardHolder isEqualToString:card.cardHolder]); EXPECT_TRUE([number isEqualToString:card.number]); EXPECT_TRUE([obfuscatedNumber isEqualToString:card.obfuscatedNumber]); @@ -54,6 +56,7 @@ ManualFillCreditCard* card = [[ManualFillCreditCard alloc] initWithGUID:GUID network:network + issuerNetworkIconID:1 bankName:bankName cardHolder:cardHolder number:number @@ -64,6 +67,7 @@ ManualFillCreditCard* equalCard = [[ManualFillCreditCard alloc] initWithGUID:GUID network:network + issuerNetworkIconID:1 bankName:bankName cardHolder:cardHolder number:number @@ -76,6 +80,7 @@ ManualFillCreditCard* differentGuidCredential = [[ManualFillCreditCard alloc] initWithGUID:@"wxyz-8765-4321" network:network + issuerNetworkIconID:1 bankName:bankName cardHolder:cardHolder number:number
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/fallback_view_controller.mm b/ios/chrome/browser/ui/autofill/manual_fill/fallback_view_controller.mm index 8b47cd1f..16a6184b 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/fallback_view_controller.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/fallback_view_controller.mm
@@ -65,8 +65,9 @@ self.tableView.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0); self.tableView.allowsSelection = NO; self.definesPresentationContext = YES; - - [self startLoadingIndicatorWithLoadingMessage:@""]; + if (!self.tableViewModel) { + [self startLoadingIndicatorWithLoadingMessage:@""]; + } } - (void)presentDataItems:(NSArray<TableViewItem*>*)items {
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_address_cell.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_address_cell.mm index 302330a9..17cd76a 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_address_cell.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_address_cell.mm
@@ -233,7 +233,7 @@ } self.nameLineConstraints = - HorizontalConstraintsForViewsOnGuideWithShift(nameLineViews, guide, 0); + HorizontalConstraintsForViewsOnGuideWithMargin(nameLineViews, guide, 0); if (nameLineViews.count) { [verticalLeadViews addObject:nameLineViews.firstObject]; @@ -292,8 +292,8 @@ self.cityButton.hidden = YES; } - self.zipCityLineConstraints = - HorizontalConstraintsForViewsOnGuideWithShift(zipCityLineViews, guide, 0); + self.zipCityLineConstraints = HorizontalConstraintsForViewsOnGuideWithMargin( + zipCityLineViews, guide, 0); if (zipCityLineViews.count) { [verticalLeadViews addObject:zipCityLineViews.firstObject]; } @@ -326,8 +326,8 @@ } self.stateCountryLineConstraints = - HorizontalConstraintsForViewsOnGuideWithShift(stateCountryLineViews, - guide, 0); + HorizontalConstraintsForViewsOnGuideWithMargin(stateCountryLineViews, + guide, 0); if (stateCountryLineViews.count) { [verticalLeadViews addObject:stateCountryLineViews.firstObject]; } @@ -365,8 +365,8 @@ self.addressLabel = CreateLabel(); [self.contentView addSubview:self.addressLabel]; - HorizontalConstraintsForViewsOnGuideWithShift(@[ self.addressLabel ], guide, - ButtonHorizontalMargin); + HorizontalConstraintsForViewsOnGuideWithMargin(@[ self.addressLabel ], guide, + ButtonHorizontalMargin); self.firstNameButton = CreateButtonWithSelectorAndTarget( @selector(userDidTapAddressInfo:), self); @@ -398,20 +398,20 @@ self.companyButton = CreateButtonWithSelectorAndTarget( @selector(userDidTapAddressInfo:), self); [self.contentView addSubview:self.companyButton]; - HorizontalConstraintsForViewsOnGuideWithShift(@[ self.companyButton ], guide, - 0); + HorizontalConstraintsForViewsOnGuideWithMargin(@[ self.companyButton ], guide, + 0); self.line1Button = CreateButtonWithSelectorAndTarget( @selector(userDidTapAddressInfo:), self); [self.contentView addSubview:self.line1Button]; - HorizontalConstraintsForViewsOnGuideWithShift(@[ self.line1Button ], guide, - 0); + HorizontalConstraintsForViewsOnGuideWithMargin(@[ self.line1Button ], guide, + 0); self.line2Button = CreateButtonWithSelectorAndTarget( @selector(userDidTapAddressInfo:), self); [self.contentView addSubview:self.line2Button]; - HorizontalConstraintsForViewsOnGuideWithShift(@[ self.line2Button ], guide, - 0); + HorizontalConstraintsForViewsOnGuideWithMargin(@[ self.line2Button ], guide, + 0); self.zipButton = CreateButtonWithSelectorAndTarget( @selector(userDidTapAddressInfo:), self); @@ -446,14 +446,14 @@ self.phoneNumberButton = CreateButtonWithSelectorAndTarget( @selector(userDidTapAddressInfo:), self); [self.contentView addSubview:self.phoneNumberButton]; - HorizontalConstraintsForViewsOnGuideWithShift(@[ self.phoneNumberButton ], - guide, 0); + HorizontalConstraintsForViewsOnGuideWithMargin(@[ self.phoneNumberButton ], + guide, 0); self.emailAddressButton = CreateButtonWithSelectorAndTarget( @selector(userDidTapAddressInfo:), self); [self.contentView addSubview:self.emailAddressButton]; - HorizontalConstraintsForViewsOnGuideWithShift(@[ self.emailAddressButton ], - guide, 0); + HorizontalConstraintsForViewsOnGuideWithMargin(@[ self.emailAddressButton ], + guide, 0); self.nameLineConstraints = @[]; self.zipCityLineConstraints = @[];
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_card_cell.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_card_cell.mm index 9295faa..8d15b5f2 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_card_cell.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_card_cell.mm
@@ -13,6 +13,7 @@ #import "ios/chrome/browser/ui/autofill/manual_fill/manual_fill_content_delegate.h" #import "ios/chrome/browser/ui/autofill/manual_fill/uicolor_manualfill.h" #import "ios/chrome/browser/ui/list_model/list_model.h" +#import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/ui_util/constraints_ui_util.h" #include "ios/chrome/grit/ios_strings.h" #include "ui/base/l10n/l10n_util_mac.h" @@ -66,9 +67,12 @@ @interface ManualFillCardCell () -// The label with the site name and host. +// The label with bank name and network. @property(nonatomic, strong) UILabel* cardLabel; +// The credit card icon. +@property(nonatomic, strong) UIImageView* cardIcon; + // A button showing the card number. @property(nonatomic, strong) UIButton* cardNumberButton; @@ -105,6 +109,7 @@ [self.expirationYearButton setTitle:@"" forState:UIControlStateNormal]; self.contentDelegate = nil; self.navigationDelegate = nil; + self.cardIcon.image = nil; self.card = nil; } @@ -136,6 +141,8 @@ }]; self.cardLabel.attributedText = attributedString; + self.cardIcon.image = NativeImage(card.issuerNetworkIconID); + [self.cardNumberButton setTitle:card.obfuscatedNumber forState:UIControlStateNormal]; [self.cardholderButton setTitle:card.cardHolder @@ -158,20 +165,28 @@ self.cardLabel = CreateLabel(); [self.contentView addSubview:self.cardLabel]; - HorizontalConstraintsForViewsOnGuideWithShift(@[ self.cardLabel ], guide, - ButtonHorizontalMargin); + + self.cardIcon = [[UIImageView alloc] init]; + self.cardIcon.translatesAutoresizingMaskIntoConstraints = NO; + [self.contentView addSubview:self.cardIcon]; + HorizontalConstraintsForViewsOnGuideWithMargin( + @[ self.cardLabel, self.cardIcon ], guide, ButtonHorizontalMargin, YES); + [NSLayoutConstraint activateConstraints:@[ + [self.cardIcon.bottomAnchor + constraintEqualToAnchor:self.cardLabel.firstBaselineAnchor] + ]]; self.cardNumberButton = CreateButtonWithSelectorAndTarget(@selector(userDidTapCardNumber:), self); [self.contentView addSubview:self.cardNumberButton]; - HorizontalConstraintsForViewsOnGuideWithShift(@[ self.cardNumberButton ], - guide, 0); + HorizontalConstraintsForViewsOnGuideWithMargin(@[ self.cardNumberButton ], + guide, 0); self.cardholderButton = CreateButtonWithSelectorAndTarget(@selector(userDidTapCardInfo:), self); [self.contentView addSubview:self.cardholderButton]; - HorizontalConstraintsForViewsOnGuideWithShift(@[ self.cardholderButton ], - guide, 0); + HorizontalConstraintsForViewsOnGuideWithMargin(@[ self.cardholderButton ], + guide, 0); // Expiration line. self.expirationMonthButton = @@ -186,7 +201,7 @@ SyncBaselinesForViewsOnView( @[ expirationSeparatorLabel, self.expirationYearButton ], self.expirationMonthButton); - HorizontalConstraintsForViewsOnGuideWithShift( + HorizontalConstraintsForViewsOnGuideWithMargin( @[ self.expirationMonthButton, expirationSeparatorLabel, self.expirationYearButton
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_cell_utils.h b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_cell_utils.h index a221e9c..a5f57dd8 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_cell_utils.h +++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_cell_utils.h
@@ -50,13 +50,22 @@ CGFloat BottomSystemSpacingMultiplier); // Sets constraints for the given |views|, so as to lay them out horizontally, -// parallel to the given |guide| view, and applying the given constant |shift| -// to the whole row. Returns the applied constraints to allow caller to -// deactivate them later. -NSArray<NSLayoutConstraint*>* HorizontalConstraintsForViewsOnGuideWithShift( +// parallel to the given |guide| view, and applying the given constant |margin| +// at both ends of the whole row. Returns the applied constraints to allow +// caller to deactivate them later. +NSArray<NSLayoutConstraint*>* HorizontalConstraintsForViewsOnGuideWithMargin( NSArray<UIView*>* views, UIView* guide, - CGFloat shift); + CGFloat margin); + +// Set constraints like |HorizontalConstraintsForViewsOnGuideWithMargin| but +// optionaly give remaining space on the line to leftmost item +// (useExtraSpaceAtLeft = YES). +NSArray<NSLayoutConstraint*>* HorizontalConstraintsForViewsOnGuideWithMargin( + NSArray<UIView*>* views, + UIView* guide, + CGFloat margin, + BOOL useExtraSpaceAtLeft); // Sets all baseline anchors for the gievn |views| to match the one on |onView|. // Returns the applied constrainst to allow caller to deactivate them later.
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_cell_utils.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_cell_utils.mm index 2577e9d..626e387 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_cell_utils.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_cell_utils.mm
@@ -74,20 +74,37 @@ return verticalConstraints; } -NSArray<NSLayoutConstraint*>* HorizontalConstraintsForViewsOnGuideWithShift( +NSArray<NSLayoutConstraint*>* HorizontalConstraintsForViewsOnGuideWithMargin( NSArray<UIView*>* views, UIView* guide, - CGFloat shift) { + CGFloat margin) { + return HorizontalConstraintsForViewsOnGuideWithMargin(views, guide, margin, + NO); +} + +NSArray<NSLayoutConstraint*>* HorizontalConstraintsForViewsOnGuideWithMargin( + NSArray<UIView*>* views, + UIView* guide, + CGFloat margin, + BOOL useExtraSpaceAtLeft) { NSMutableArray* horizontalConstraints = [[NSMutableArray alloc] init]; NSLayoutXAxisAnchor* previousAnchor = guide.leadingAnchor; + UILayoutPriority firstPriority = useExtraSpaceAtLeft + ? UILayoutPriorityDefaultHigh + : UILayoutPriorityDefaultLow; + UILayoutPriority lastPriority = useExtraSpaceAtLeft + ? UILayoutPriorityDefaultLow + : UILayoutPriorityDefaultHigh; + + CGFloat shift = margin; for (UIView* view in views) { [horizontalConstraints addObject:[view.leadingAnchor constraintEqualToAnchor:previousAnchor constant:shift]]; - [view setContentCompressionResistancePriority:UILayoutPriorityDefaultLow + [view setContentCompressionResistancePriority:firstPriority forAxis: UILayoutConstraintAxisHorizontal]; - [view setContentHuggingPriority:UILayoutPriorityDefaultHigh + [view setContentHuggingPriority:lastPriority forAxis:UILayoutConstraintAxisHorizontal]; previousAnchor = view.trailingAnchor; shift = 0; @@ -96,14 +113,14 @@ [horizontalConstraints addObject:[views.lastObject.trailingAnchor constraintEqualToAnchor:guide.trailingAnchor - constant:shift]]; - // Give all remaining space to the last button, as per UX. + constant:-margin]]; + // Give all remaining space to the last button, minus margin, as per UX. [views.lastObject - setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh + setContentCompressionResistancePriority:lastPriority forAxis: UILayoutConstraintAxisHorizontal]; [views.lastObject - setContentHuggingPriority:UILayoutPriorityDefaultLow + setContentHuggingPriority:firstPriority forAxis:UILayoutConstraintAxisHorizontal]; } [NSLayoutConstraint activateConstraints:horizontalConstraints]; @@ -127,6 +144,7 @@ UILabel* label = [[UILabel alloc] init]; label.translatesAutoresizingMaskIntoConstraints = NO; label.adjustsFontForContentSizeCategory = YES; + label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; return label; }
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_cell.mm b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_cell.mm index 2377926f..1a279a9 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_cell.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_cell.mm
@@ -220,20 +220,20 @@ self.siteNameLabel.translatesAutoresizingMaskIntoConstraints = NO; self.siteNameLabel.adjustsFontForContentSizeCategory = YES; [self.contentView addSubview:self.siteNameLabel]; - HorizontalConstraintsForViewsOnGuideWithShift(@[ self.siteNameLabel ], guide, - ButtonHorizontalMargin); + HorizontalConstraintsForViewsOnGuideWithMargin(@[ self.siteNameLabel ], guide, + ButtonHorizontalMargin); self.usernameButton = CreateButtonWithSelectorAndTarget( @selector(userDidTapUsernameButton:), self); [self.contentView addSubview:self.usernameButton]; - HorizontalConstraintsForViewsOnGuideWithShift(@[ self.usernameButton ], guide, - 0); + HorizontalConstraintsForViewsOnGuideWithMargin(@[ self.usernameButton ], + guide, 0); self.passwordButton = CreateButtonWithSelectorAndTarget( @selector(userDidTapPasswordButton:), self); [self.contentView addSubview:self.passwordButton]; - HorizontalConstraintsForViewsOnGuideWithShift(@[ self.passwordButton ], guide, - 0); + HorizontalConstraintsForViewsOnGuideWithMargin(@[ self.passwordButton ], + guide, 0); } - (void)userDidTapUsernameButton:(UIButton*)button {
diff --git a/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller.mm b/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller.mm index 0f559ab..16af88fb 100644 --- a/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller.mm +++ b/ios/chrome/browser/ui/autofill/manual_fill/password_view_controller.mm
@@ -9,6 +9,7 @@ #import "ios/chrome/browser/ui/autofill/manual_fill/action_cell.h" #import "ios/chrome/browser/ui/autofill/manual_fill/manual_fill_password_cell.h" #import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" +#import "ios/chrome/browser/ui/table_view/table_view_navigation_controller_constants.h" #include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #include "ios/chrome/grit/ios_strings.h" @@ -60,6 +61,41 @@ NSString* titleString = l10n_util::GetNSString(IDS_IOS_MANUAL_FALLBACK_USE_OTHER_PASSWORD); self.title = titleString; + + // Center search bar vertically so it looks centered in the header when + // searching. The cancel button is centered / decentered on + // viewWillAppear and viewDidDisappear. + UIOffset offset = + UIOffsetMake(0.0f, kTableViewNavigationVerticalOffsetForSearchHeader); + self.searchController.searchBar.searchFieldBackgroundPositionAdjustment = + offset; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + // Center search bar's cancel button vertically so it looks centered. + // We change the cancel button proxy styles, so we will return it to + // default in viewDidDisappear. + if (self.searchController) { + UIOffset offset = + UIOffsetMake(0.0f, kTableViewNavigationVerticalOffsetForSearchHeader); + UIBarButtonItem* cancelButton = [UIBarButtonItem + appearanceWhenContainedInInstancesOfClasses:@ [[UISearchBar class]]]; + [cancelButton setTitlePositionAdjustment:offset + forBarMetrics:UIBarMetricsDefault]; + } +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + + // Restore to default origin offset for cancel button proxy style. + if (self.searchController) { + UIBarButtonItem* cancelButton = [UIBarButtonItem + appearanceWhenContainedInInstancesOfClasses:@ [[UISearchBar class]]]; + [cancelButton setTitlePositionAdjustment:UIOffsetZero + forBarMetrics:UIBarMetricsDefault]; + } } #pragma mark - ManualFillPasswordConsumer
diff --git a/ios/chrome/browser/ui/autofill/save_card_infobar_egtest.mm b/ios/chrome/browser/ui/autofill/save_card_infobar_egtest.mm index ba014a83..e467cfed 100644 --- a/ios/chrome/browser/ui/autofill/save_card_infobar_egtest.mm +++ b/ios/chrome/browser/ui/autofill/save_card_infobar_egtest.mm
@@ -209,7 +209,7 @@ [self onEvent:InfobarEvent::RECEIVED_UPLOAD_CARD_RESPONSE]; } -- (void)ccsmStrikeChangeComplete { +- (void)strikeChangeComplete { [self onEvent:InfobarEvent::STRIKE_CHANGE_COMPLETE]; }
diff --git a/ios/chrome/browser/ui/browser_view_controller.h b/ios/chrome/browser/ui/browser_view_controller.h index 7aa54a8..740d3584 100644 --- a/ios/chrome/browser/ui/browser_view_controller.h +++ b/ios/chrome/browser/ui/browser_view_controller.h
@@ -115,13 +115,6 @@ - (void)openNewTabFromOriginPoint:(CGPoint)originPoint focusOmnibox:(BOOL)focusOmnibox; -// Add a new tab with the given url, at the given |position|, -// and makes it the selected tab. The selected tab is returned. -// If |position| == NSNotFound the tab will be added at the end of the stack. -- (Tab*)addSelectedTabWithURL:(const GURL&)url - atIndex:(NSUInteger)position - transition:(ui::PageTransition)transition; - // Adds |tabAddedCompletion| to the completion block (if any) that will be run // the next time a tab is added to the TabModel this object was initialized // with.
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 93927a7..663e81e 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -142,7 +142,7 @@ #import "ios/chrome/browser/ui/fullscreen/fullscreen_ui_updater.h" #import "ios/chrome/browser/ui/image_util/image_copier.h" #import "ios/chrome/browser/ui/image_util/image_saver.h" -#import "ios/chrome/browser/ui/infobars/infobar_coordinator.h" +#import "ios/chrome/browser/ui/infobars/infobar_container_coordinator.h" #import "ios/chrome/browser/ui/infobars/infobar_positioner.h" #import "ios/chrome/browser/ui/key_commands_provider.h" #include "ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.h" @@ -597,7 +597,8 @@ // Coordinator for tablet tab strip. @property(nonatomic, strong) TabStripLegacyCoordinator* tabStripCoordinator; // Coordinator for Infobars. -@property(nonatomic, strong) InfobarCoordinator* infoBarCoordinator; +@property(nonatomic, strong) + InfobarContainerCoordinator* infobarContainerCoordinator; // A weak reference to the view of the tab strip on tablet. @property(nonatomic, weak) UIView* tabStripView; // Helper for saving images. @@ -767,20 +768,6 @@ // Tab creation and selection // -------------------------- -// Adds a new tab with |url| and |postData| at the end of the model, and make it -// the selected tab and return it. -- (Tab*)addSelectedTabWithURL:(const GURL&)url - postData:(TemplateURLRef::PostContent*)postData - transition:(ui::PageTransition)transition; -// Internal method that all of the similar public and private methods call. -// Adds a new tab with |url| and |postData| (if not null) at |position| in the -// tab model (or at the end if |position is NSNotFound|, with |transition| as -// the page transition type. If |tabAddedCompletion| is nonnull, it's called -// synchronously after the tab is added. -- (Tab*)addSelectedTabWithURL:(const GURL&)url - postData:(TemplateURLRef::PostContent*)postData - atIndex:(NSUInteger)position - transition:(ui::PageTransition)transition; // Whether the given tab's URL is an application specific URL. - (BOOL)isTabNativePage:(Tab*)tab; // Returns the view to use when animating a page in or out, positioning it to @@ -1331,18 +1318,14 @@ SnapshotTabHelper::FromWebState(currentTab.webState) ->UpdateSnapshot(/*with_overlays=*/true, /*visible_frame_only=*/true); } - [self addSelectedTabWithURL:GURL(kChromeUINewTabURL) - atIndex:self.tabModel.count - transition:ui::PAGE_TRANSITION_TYPED]; -} -- (Tab*)addSelectedTabWithURL:(const GURL&)url - atIndex:(NSUInteger)position - transition:(ui::PageTransition)transition { - return [self addSelectedTabWithURL:url - postData:NULL - atIndex:position - transition:transition]; + [self.tabModel insertTabWithLoadParams:CreateWebLoadParams( + GURL(kChromeUINewTabURL), + ui::PAGE_TRANSITION_TYPED, nullptr) + opener:nil + openedByDOM:NO + atIndex:self.tabModel.count + inBackground:NO]; } - (void)appendTabAddedCompletion:(ProceduralBlock)tabAddedCompletion { @@ -1471,8 +1454,8 @@ _downloadManagerCoordinator = nil; self.toolbarInterface = nil; self.tabStripView = nil; - [self.infoBarCoordinator stop]; - self.infoBarCoordinator = nil; + [self.infobarContainerCoordinator stop]; + self.infobarContainerCoordinator = nil; // SideSwipeController is a tab model observer, so it needs to stop observing // before self.tabModel is released. _sideSwipeController = nil; @@ -1692,7 +1675,7 @@ [super didReceiveMemoryWarning]; if (![self isViewLoaded]) { - // Do not release |_infoBarCoordinator|, as this must have the same + // Do not release |_infobarContainerCoordinator|, as this must have the same // lifecycle as the BrowserViewController. [_browserContainerCoordinator stop]; _browserContainerCoordinator = nil; @@ -2057,15 +2040,15 @@ [self.tabStripCoordinator start]; } - // Create the Infobar Coordinator. - self.infoBarCoordinator = - [[InfobarCoordinator alloc] initWithBaseViewController:self - browserState:_browserState - tabModel:self.tabModel]; - self.infoBarCoordinator.dispatcher = self.dispatcher; - self.infoBarCoordinator.positioner = self; - self.infoBarCoordinator.syncPresenter = self; - [self.infoBarCoordinator start]; + // Create the Infobar Container Coordinator. + self.infobarContainerCoordinator = [[InfobarContainerCoordinator alloc] + initWithBaseViewController:self + browserState:_browserState + tabModel:self.tabModel]; + self.infobarContainerCoordinator.dispatcher = self.dispatcher; + self.infobarContainerCoordinator.positioner = self; + self.infobarContainerCoordinator.syncPresenter = self; + [self.infobarContainerCoordinator start]; } // Called by NSNotificationCenter when the view's window becomes key to account @@ -2329,8 +2312,9 @@ // Place the toolbar controller above the infobar container and adds the // layout guides. if (initialLayout) { - UIView* bottomView = - IsIPadIdiom() ? _fakeStatusBarView : [self.infoBarCoordinator view]; + UIView* bottomView = IsIPadIdiom() + ? _fakeStatusBarView + : [self.infobarContainerCoordinator view]; [[self view] insertSubview:self.primaryToolbarCoordinator.viewController.view aboveSubview:bottomView]; @@ -2606,6 +2590,105 @@ return webState->GetView(); } +// Switch to the tab corresponding to |params|. +- (void)switchToTabWithParams: + (const web::NavigationManager::WebLoadParams&)params { + const GURL& URL = params.url; + + NSInteger newWebStateIndex = 0; + WebStateList* webStateList = self.tabModel.webStateList; + NSInteger currentWebStateIndex = webStateList->active_index(); + web::WebState* currentWebState = webStateList->GetActiveWebState(); + + // TODO(crbug.com/893121): This should probably live in the WebStateList. + while (newWebStateIndex < webStateList->count()) { + web::WebState* webState = webStateList->GetWebStateAt(newWebStateIndex); + + if (webState != currentWebState && URL == webState->GetVisibleURL()) { + break; + } + newWebStateIndex++; + } + + BOOL isNTPWithoutHistory = + IsVisibleURLNewTabPage(currentWebState) && + currentWebState->GetNavigationManager() && + !currentWebState->GetNavigationManager()->CanGoBack() && + !currentWebState->GetNavigationManager()->CanGoForward(); + + if (newWebStateIndex >= webStateList->count()) { + // If the tab containing the URL has been closed. + if (isNTPWithoutHistory) { + // It is NTP, just load the URL. + ChromeLoadParams currentPageParams(params); + [self loadURLWithParams:currentPageParams]; + } else { + // Open the URL in foreground. + OpenNewTabCommand* newTabCommand = + [[OpenNewTabCommand alloc] initWithURL:URL + referrer:web::Referrer() + inIncognito:self.isOffTheRecord + inBackground:NO + appendTo:kCurrentTab]; + [self.dispatcher openURLInNewTab:newTabCommand]; + } + return; + } + + web::WebState* webStateBeingActivated = + webStateList->GetWebStateAt(newWebStateIndex); + + if (![self canShowTabStrip]) { + // Add animations only if the tab strip isn't shown. + UIView* snapshotView = [self.view snapshotViewAfterScreenUpdates:NO]; + + // TODO(crbug.com/904992): Do not repurpose SnapshotGeneratorDelegate. + SwipeView* swipeView = [[SwipeView alloc] + initWithFrame:self.contentArea.frame + topMargin:[self snapshotGenerator:nil + snapshotEdgeInsetsForWebState:webStateBeingActivated] + .top]; + + [swipeView setTopToolbarImage:[self.primaryToolbarCoordinator + toolbarSideSwipeSnapshotForWebState: + webStateBeingActivated]]; + [swipeView setBottomToolbarImage:[self.secondaryToolbarCoordinator + toolbarSideSwipeSnapshotForWebState: + webStateBeingActivated]]; + + SnapshotTabHelper::FromWebState(webStateBeingActivated) + ->RetrieveColorSnapshot(^(UIImage* image) { + if (PagePlaceholderTabHelper::FromWebState(webStateBeingActivated) + ->will_add_placeholder_for_next_navigation()) { + [swipeView setImage:SnapshotTabHelper::GetDefaultSnapshotImage()]; + } else { + [swipeView setImage:image]; + } + }); + + SwitchToTabAnimationView* animationView = + [[SwitchToTabAnimationView alloc] initWithFrame:self.view.bounds]; + + [self.view addSubview:animationView]; + + SwitchToTabAnimationPosition position = + newWebStateIndex > webStateList->active_index() + ? SwitchToTabAnimationPositionAfter + : SwitchToTabAnimationPositionBefore; + [animationView animateFromCurrentView:snapshotView + toNewView:swipeView + inPosition:position]; + } + webStateList->ActivateWebStateAt(newWebStateIndex); + + // Close the tab if it is NTP with no back/forward history to avoid having + // empty tabs. + if (isNTPWithoutHistory) { + webStateList->CloseWebStateAt(currentWebStateIndex, + WebStateList::CLOSE_USER_ACTION); + } +} + #pragma mark - Private Methods: Find Bar UI - (void)hideFindBarWithAnimation:(BOOL)animate { @@ -2697,27 +2780,6 @@ #pragma mark - Private Methods: Tab creation and selection -- (Tab*)addSelectedTabWithURL:(const GURL&)url - postData:(TemplateURLRef::PostContent*)postData - transition:(ui::PageTransition)transition { - return [self addSelectedTabWithURL:url - postData:postData - atIndex:self.tabModel.count - transition:transition]; -} - -- (Tab*)addSelectedTabWithURL:(const GURL&)URL - postData:(TemplateURLRef::PostContent*)postData - atIndex:(NSUInteger)position - transition:(ui::PageTransition)transition { - return [self.tabModel - insertTabWithLoadParams:CreateWebLoadParams(URL, transition, postData) - opener:nil - openedByDOM:NO - atIndex:position - inBackground:NO]; -} - - (BOOL)isTabNativePage:(Tab*)tab { web::WebState* webState = tab.webState; if (!webState) @@ -2800,7 +2862,8 @@ // TODO(crbug.com/785238): Remove the need for this check. if (tab.webState->GetJSInjectionReceiver()) { ChromeIOSTranslateClient::CreateForWebState( - tab.webState, self.infoBarCoordinator.languageSelectionHandler); + tab.webState, + self.infobarContainerCoordinator.languageSelectionHandler); language::IOSLanguageDetectionTabHelper::CreateForWebState( tab.webState, ChromeIOSTranslateClient::FromWebState(tab.webState) @@ -3076,10 +3139,10 @@ Tab* currentTab = self.tabModel.currentTab; if (currentTab && tab == currentTab) { DCHECK(currentTab.webState); - DCHECK(self.infoBarCoordinator); - if ([self.infoBarCoordinator + DCHECK(self.infobarContainerCoordinator); + if ([self.infobarContainerCoordinator isInfobarPresentingForWebState:currentTab.webState]) { - return [self.infoBarCoordinator view]; + return [self.infobarContainerCoordinator view]; } } return nil; @@ -3087,9 +3150,9 @@ // Returns a vertical infobar offset relative to the tab content. - (CGFloat)infoBarOverlayYOffsetForTab:(Tab*)tab { - if (tab != self.tabModel.currentTab || !self.infoBarCoordinator) { + if (tab != self.tabModel.currentTab || !self.infobarContainerCoordinator) { // There is no UI representation for non-current tabs or there is - // no _infoBarCoordinator instantiated yet. + // no _infobarContainerCoordinator instantiated yet. // Return offset outside of tab. return CGRectGetMaxY(self.view.frame); } else if (IsIPadIdiom()) { @@ -3099,7 +3162,7 @@ // The infobars on iPhone are displayed at the bottom of a tab. CGRect visibleFrame = [self visibleFrameForTab:self.tabModel.currentTab]; return CGRectGetMaxY(visibleFrame) - - CGRectGetHeight([self.infoBarCoordinator view].frame); + CGRectGetHeight([self.infobarContainerCoordinator view].frame); } } @@ -3527,12 +3590,16 @@ // Generate the URL and populate |post_content| with the content type and // HTTP body for the request. - TemplateURLRef::PostContent post_content; + TemplateURLRef::PostContent postContent; GURL result(defaultURL->image_url_ref().ReplaceSearchTerms( - search_args, templateUrlService->search_terms_data(), &post_content)); - [self addSelectedTabWithURL:result - postData:&post_content - transition:ui::PAGE_TRANSITION_TYPED]; + search_args, templateUrlService->search_terms_data(), &postContent)); + [self.tabModel insertTabWithLoadParams:CreateWebLoadParams( + result, ui::PAGE_TRANSITION_TYPED, + &postContent) + opener:nil + openedByDOM:NO + atIndex:self.tabModel.count + inBackground:NO]; } // Saves the image at the given URL on the system's album. The referrer is used @@ -3852,8 +3919,9 @@ [self.secondaryToolbarContainerView layoutIfNeeded]; } - // Resize the infobars to take into account the changes in the toolbar. - [self.infoBarCoordinator updateInfobarContainer]; + // Resize the InfobarContainer to take into account the changes in the + // toolbar. + [self.infobarContainerCoordinator updateInfobarContainer]; // Resize the NTP's contentInset.bottom to be above the secondary toolbar. id nativeController = [self nativeControllerForTab:self.tabModel.currentTab]; @@ -4085,6 +4153,14 @@ prerenderService->ReleasePrerenderContents(); DCHECK(newWebState); + int lastIndex = self.currentWebState->GetNavigationManager() + ->GetLastCommittedItemIndex(); + UMA_HISTOGRAM_COUNTS_100("Prerender.PrerenderLoadedOnIndex", lastIndex); + + BOOL onFirstNTP = + IsVisibleURLNewTabPage(self.currentWebState) && lastIndex == 0; + UMA_HISTOGRAM_BOOLEAN("Prerender.PrerenderLoadedOnFirstNTP", onFirstNTP); + Tab* oldTab = self.tabModel.currentTab; Tab* newTab = LegacyTabHelper::GetTabForWebState(newWebState.get()); DCHECK(oldTab); @@ -4494,16 +4570,11 @@ } - (void)requestDesktopSite { - if (self.userAgentType != web::UserAgentType::MOBILE) - return; - [self.tabModel.currentTab - reloadWithUserAgentType:web::UserAgentType::DESKTOP]; + [self reloadWithUserAgentType:web::UserAgentType::DESKTOP]; } - (void)requestMobileSite { - if (self.userAgentType != web::UserAgentType::DESKTOP) - return; - [self.tabModel.currentTab reloadWithUserAgentType:web::UserAgentType::MOBILE]; + [self reloadWithUserAgentType:web::UserAgentType::MOBILE]; } - (void)closeCurrentTab { @@ -4561,100 +4632,16 @@ [nativeController focusFakebox]; } -- (void)switchToTabWithParams: - (const web::NavigationManager::WebLoadParams&)params { - const GURL& URL = params.url; +#pragma mark - BrowserCommands helpers - NSInteger newWebStateIndex = 0; - WebStateList* webStateList = self.tabModel.webStateList; - NSInteger currentWebStateIndex = webStateList->active_index(); - web::WebState* currentWebState = webStateList->GetActiveWebState(); - - // TODO(crbug.com/893121): This should probably live in the WebStateList. - while (newWebStateIndex < webStateList->count()) { - web::WebState* webState = webStateList->GetWebStateAt(newWebStateIndex); - - if (webState != currentWebState && URL == webState->GetVisibleURL()) { - break; - } - newWebStateIndex++; - } - - BOOL isNTPWithoutHistory = - IsVisibleURLNewTabPage(currentWebState) && - currentWebState->GetNavigationManager()->GetItemCount() <= 1; - - if (newWebStateIndex >= webStateList->count()) { - // If the tab containing the URL has been closed. - if (isNTPWithoutHistory) { - // It is NTP, just load the URL. - ChromeLoadParams currentPageParams(params); - [self loadURLWithParams:currentPageParams]; - } else { - // Open the URL in foreground. - OpenNewTabCommand* newTabCommand = - [[OpenNewTabCommand alloc] initWithURL:URL - referrer:params.referrer - inIncognito:_isOffTheRecord - inBackground:NO - appendTo:kCurrentTab]; - [self.dispatcher openURLInNewTab:newTabCommand]; - } +// Reloads the original url of the last non-redirect item (including non-history +// items) with |userAgentType|. +- (void)reloadWithUserAgentType:(web::UserAgentType)userAgentType { + if (self.userAgentType == userAgentType) return; - } - - web::WebState* webStateBeingActivated = - webStateList->GetWebStateAt(newWebStateIndex); - - if (![self canShowTabStrip]) { - // Add animations only if the tab strip isn't shown. - UIView* snapshotView = [self.view snapshotViewAfterScreenUpdates:NO]; - - // TODO(crbug.com/904992): Do not repurpose SnapshotGeneratorDelegate. - SwipeView* swipeView = [[SwipeView alloc] - initWithFrame:self.contentArea.frame - topMargin:[self snapshotGenerator:nil - snapshotEdgeInsetsForWebState:webStateBeingActivated] - .top]; - - [swipeView setTopToolbarImage:[self.primaryToolbarCoordinator - toolbarSideSwipeSnapshotForWebState: - webStateBeingActivated]]; - [swipeView setBottomToolbarImage:[self.secondaryToolbarCoordinator - toolbarSideSwipeSnapshotForWebState: - webStateBeingActivated]]; - - SnapshotTabHelper::FromWebState(webStateBeingActivated) - ->RetrieveColorSnapshot(^(UIImage* image) { - if (PagePlaceholderTabHelper::FromWebState(webStateBeingActivated) - ->will_add_placeholder_for_next_navigation()) { - [swipeView setImage:SnapshotTabHelper::GetDefaultSnapshotImage()]; - } else { - [swipeView setImage:image]; - } - }); - - SwitchToTabAnimationView* animationView = - [[SwitchToTabAnimationView alloc] initWithFrame:self.view.bounds]; - - [self.view addSubview:animationView]; - - SwitchToTabAnimationPosition position = - newWebStateIndex > webStateList->active_index() - ? SwitchToTabAnimationPositionAfter - : SwitchToTabAnimationPositionBefore; - [animationView animateFromCurrentView:snapshotView - toNewView:swipeView - inPosition:position]; - } - webStateList->ActivateWebStateAt(newWebStateIndex); - - // Close the tab if it is NTP with no back/forward history to avoid having - // empty tabs. - if (isNTPWithoutHistory) { - webStateList->CloseWebStateAt(currentWebStateIndex, - WebStateList::CLOSE_USER_ACTION); - } + web::WebState* webState = self.tabModel.currentTab.webState; + web::NavigationManager* navigationManager = webState->GetNavigationManager(); + navigationManager->ReloadWithUserAgentType(userAgentType); } #pragma mark - TabModelObserver methods @@ -4987,7 +4974,7 @@ // Reset horizontal stack view. [sideSwipeView removeFromSuperview]; [self.sideSwipeController setInSwipe:NO]; - [[self.infoBarCoordinator view] setHidden:NO]; + [[self.infobarContainerCoordinator view] setHidden:NO]; if (base::FeatureList::IsEnabled(kPresentSadTabInViewController)) { web::WebState* webState = self.tabModel.currentTab.webState; @@ -5030,12 +5017,12 @@ - (void)updateAccessoryViewsForSideSwipeWithVisibility:(BOOL)visible { if (visible) { [self updateToolbar]; - [[self.infoBarCoordinator view] setHidden:NO]; + [[self.infobarContainerCoordinator view] setHidden:NO]; } else { // Hide UI accessories such as find bar and first visit overlays // for welcome page. [self hideFindBarWithAnimation:NO]; - [[self.infoBarCoordinator view] setHidden:YES]; + [[self.infobarContainerCoordinator view] setHidden:YES]; } } @@ -5048,7 +5035,7 @@ BOOL seenInfoBarContainer = NO; BOOL seenContentArea = NO; for (UIView* view in views.subviews) { - if (view == [self.infoBarCoordinator view]) + if (view == [self.infobarContainerCoordinator view]) seenInfoBarContainer = YES; else if (view == self.contentArea) seenContentArea = YES; @@ -5179,9 +5166,13 @@ - (void)captivePortalDetectorTabHelper: (CaptivePortalDetectorTabHelper*)tabHelper connectWithLandingURL:(const GURL&)landingURL { - [self addSelectedTabWithURL:landingURL - atIndex:self.tabModel.count - transition:ui::PAGE_TRANSITION_TYPED]; + [self.tabModel insertTabWithLoadParams:CreateWebLoadParams( + landingURL, + ui::PAGE_TRANSITION_TYPED, nullptr) + opener:nil + openedByDOM:NO + atIndex:self.tabModel.count + inBackground:NO]; } #pragma mark - PageInfoPresentation
diff --git a/ios/chrome/browser/ui/infobars/BUILD.gn b/ios/chrome/browser/ui/infobars/BUILD.gn index b793d55..a95724c 100644 --- a/ios/chrome/browser/ui/infobars/BUILD.gn +++ b/ios/chrome/browser/ui/infobars/BUILD.gn
@@ -5,10 +5,10 @@ source_set("infobars") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ + "infobar_container_coordinator.h", + "infobar_container_coordinator.mm", "infobar_container_mediator.h", "infobar_container_mediator.mm", - "infobar_coordinator.h", - "infobar_coordinator.mm", ] deps = [ ":infobars_ui", @@ -54,8 +54,8 @@ "infobar_constants.h", "infobar_constants.mm", "infobar_container_consumer.h", - "infobar_container_view_controller.h", - "infobar_container_view_controller.mm", + "legacy_infobar_container_view_controller.h", + "legacy_infobar_container_view_controller.mm", ] deps = [ ":public",
diff --git a/ios/chrome/browser/ui/infobars/infobar_container_coordinator.h b/ios/chrome/browser/ui/infobars/infobar_container_coordinator.h new file mode 100644 index 0000000..a41878d --- /dev/null +++ b/ios/chrome/browser/ui/infobars/infobar_container_coordinator.h
@@ -0,0 +1,63 @@ +// 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 IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_CONTAINER_COORDINATOR_H_ +#define IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_CONTAINER_COORDINATOR_H_ + +#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" + +namespace web { +class WebState; +} + +@class TabModel; +@protocol ApplicationCommands; +@protocol InfobarPositioner; +@protocol LanguageSelectionHandler; +@protocol SyncPresenter; + +// Coordinator that owns and manages an InfobarContainer. +@interface InfobarContainerCoordinator : ChromeCoordinator + +// TODO(crbug.com/892376): Stop passing TabModel and use WebStateList instead. +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browserState: + (ios::ChromeBrowserState*)browserState + tabModel:(TabModel*)tabModel + NS_DESIGNATED_INITIALIZER; +; + +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + NS_UNAVAILABLE; + +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browserState: + (ios::ChromeBrowserState*)browserState + NS_UNAVAILABLE; + +// The InfobarContainer View. +- (UIView*)view; + +// Updates the InfobarContainer according to the positioner information. +- (void)updateInfobarContainer; + +// YES if an Infobar is being presented for |webState|. +- (BOOL)isInfobarPresentingForWebState:(web::WebState*)webState; + +// The dispatcher for this Coordinator. +@property(nonatomic, weak) id<ApplicationCommands> dispatcher; + +// The delegate used to position the InfobarContainer in the view. +@property(nonatomic, weak) id<InfobarPositioner> positioner; + +// The SyncPresenter delegate for this Coordinator. +@property(nonatomic, weak) id<SyncPresenter> syncPresenter; + +// The delegate that allows user to select a language from a list of languages. +@property(nonatomic, readonly) id<LanguageSelectionHandler> + languageSelectionHandler; + +@end + +#endif // IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_CONTAINER_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm b/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm new file mode 100644 index 0000000..ec422b5 --- /dev/null +++ b/ios/chrome/browser/ui/infobars/infobar_container_coordinator.mm
@@ -0,0 +1,119 @@ +// 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. + +#import "ios/chrome/browser/ui/infobars/infobar_container_coordinator.h" + +#include <memory> + +#include "ios/chrome/browser/infobars/infobar_manager_impl.h" +#import "ios/chrome/browser/ui/commands/application_commands.h" +#include "ios/chrome/browser/ui/infobars/infobar_container_mediator.h" +#import "ios/chrome/browser/ui/infobars/infobar_positioner.h" +#include "ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.h" +#import "ios/chrome/browser/ui/signin_interaction/public/signin_presenter.h" +#import "ios/chrome/browser/ui/translate/language_selection_coordinator.h" +#include "ios/chrome/browser/upgrade/upgrade_center.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface InfobarContainerCoordinator () <SigninPresenter> + +@property(nonatomic, assign) TabModel* tabModel; + +// UIViewController that contains Infobars. +@property(nonatomic, strong) + LegacyInfobarContainerViewController* containerViewController; +// The mediator for this Coordinator. +@property(nonatomic, strong) InfobarContainerMediator* mediator; + +// Coordinator for the language selection UI. +@property(nonatomic, strong) + LanguageSelectionCoordinator* languageSelectionCoordinator; + +@end + +@implementation InfobarContainerCoordinator + +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browserState: + (ios::ChromeBrowserState*)browserState + tabModel:(TabModel*)tabModel { + self = [super initWithBaseViewController:viewController + browserState:browserState]; + if (self) { + _tabModel = tabModel; + } + return self; +} + +- (void)start { + DCHECK(self.positioner); + DCHECK(self.dispatcher); + + // Create and setup the ViewController. + self.containerViewController = + [[LegacyInfobarContainerViewController alloc] init]; + [self.baseViewController addChildViewController:self.containerViewController]; + // TODO(crbug.com/892376): We shouldn't modify the BaseVC hierarchy, BVC needs + // to handle this. + [self.baseViewController.view insertSubview:self.containerViewController.view + aboveSubview:self.positioner.parentView]; + [self.containerViewController + didMoveToParentViewController:self.baseViewController]; + self.containerViewController.positioner = self.positioner; + + self.languageSelectionCoordinator = [[LanguageSelectionCoordinator alloc] + initWithBaseViewController:self.baseViewController]; + + // Create the mediator once the VC has been added to the View hierarchy. + self.mediator = [[InfobarContainerMediator alloc] + initWithConsumer:self.containerViewController + browserState:self.browserState + tabModel:self.tabModel]; + self.mediator.syncPresenter = self.syncPresenter; + self.mediator.signinPresenter = self; + self.mediator.languageSelectionHandler = self.languageSelectionCoordinator; + + [[UpgradeCenter sharedInstance] registerClient:self.mediator + withDispatcher:self.dispatcher]; +} + +- (void)stop { + [[UpgradeCenter sharedInstance] unregisterClient:self.mediator]; + self.mediator = nil; +} + +#pragma mark - Public Interface + +- (UIView*)view { + return self.containerViewController.view; +} + +- (void)updateInfobarContainer { + [self.containerViewController updateLayoutAnimated:NO]; +} + +- (BOOL)isInfobarPresentingForWebState:(web::WebState*)webState { + infobars::InfoBarManager* infoBarManager = + InfoBarManagerImpl::FromWebState(webState); + if (infoBarManager->infobar_count() > 0) { + return YES; + } + return NO; +} + +- (id<LanguageSelectionHandler>)languageSelectionHandler { + return self.languageSelectionCoordinator; +} + +#pragma mark - SigninPresenter + +- (void)showSignin:(ShowSigninCommand*)command { + [self.dispatcher showSignin:command + baseViewController:self.baseViewController]; +} + +@end
diff --git a/ios/chrome/browser/ui/infobars/infobar_container_view_controller.h b/ios/chrome/browser/ui/infobars/infobar_container_view_controller.h deleted file mode 100644 index 332bbd5..0000000 --- a/ios/chrome/browser/ui/infobars/infobar_container_view_controller.h +++ /dev/null
@@ -1,24 +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 IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_CONTAINER_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_CONTAINER_VIEW_CONTROLLER_H_ - -#import <UIKit/UIKit.h> - -#import "ios/chrome/browser/ui/infobars/infobar_container_consumer.h" - -@protocol InfobarPositioner; - -// ViewController that contains all Infobars. It can contain various at the -// same time but only the top most one will be visible. -@interface InfobarContainerViewController - : UIViewController<InfobarContainerConsumer> - -// The delegate used to position the InfoBarContainer in the view. -@property(nonatomic, weak) id<InfobarPositioner> positioner; - -@end - -#endif // IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_CONTAINER_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/infobars/infobar_container_view_controller.mm b/ios/chrome/browser/ui/infobars/infobar_container_view_controller.mm deleted file mode 100644 index 541728f..0000000 --- a/ios/chrome/browser/ui/infobars/infobar_container_view_controller.mm +++ /dev/null
@@ -1,124 +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. - -#import "ios/chrome/browser/ui/infobars/infobar_container_view_controller.h" - -#include "base/ios/block_types.h" -#include "base/logging.h" -#import "ios/chrome/browser/ui/infobars/infobar_positioner.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { -// Duration for the alpha change animation. -const CGFloat kAlphaChangeAnimationDuration = 0.35; -} // namespace - -@interface InfobarContainerViewController () - -// Whether the controller's view is currently available. -// YES from viewDidAppear to viewDidDisappear. -@property(nonatomic, assign, getter=isVisible) BOOL visible; - -@end - -@implementation InfobarContainerViewController - -// Whenever the container or contained views are re-drawn update the layout to -// match their new size or position. -- (void)viewDidLayoutSubviews { - [super viewDidLayoutSubviews]; - [self updateLayoutAnimated:YES]; -} - -- (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - self.visible = YES; -} - -- (void)viewDidDisappear:(BOOL)animated { - self.visible = NO; - [super viewDidDisappear:animated]; -} - -#pragma mark - InfobarConsumer - -- (void)addInfoBarView:(UIView*)infoBarView position:(NSInteger)position { - DCHECK_LE(static_cast<NSUInteger>(position), [[self.view subviews] count]); - [self.view insertSubview:infoBarView atIndex:position]; - infoBarView.translatesAutoresizingMaskIntoConstraints = NO; - [NSLayoutConstraint activateConstraints:@[ - [infoBarView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], - [infoBarView.trailingAnchor - constraintEqualToAnchor:self.view.trailingAnchor], - [infoBarView.topAnchor constraintEqualToAnchor:self.view.topAnchor], - [infoBarView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] - ]]; -} - -- (void)setUserInteractionEnabled:(BOOL)enabled { - [self.view setUserInteractionEnabled:enabled]; -} - -- (void)updateLayoutAnimated:(BOOL)animated { - // Update the infobarContainer height. - CGRect containerFrame = self.view.frame; - CGFloat height = [self topmostVisibleInfoBarHeight]; - containerFrame.origin.y = - CGRectGetMaxY([self.positioner parentView].frame) - height; - containerFrame.size.height = height; - - auto completion = ^(BOOL finished) { - if (!self.visible) - return; - UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, - self.view); - }; - - ProceduralBlock frameUpdates = ^{ - [self.view setFrame:containerFrame]; - }; - if (animated) { - [UIView animateWithDuration:0.1 - animations:frameUpdates - completion:completion]; - } else { - frameUpdates(); - completion(YES); - } -} - -#pragma mark - Private Methods - -// Animates |self.view| alpha to |alpha|. -- (void)animateInfoBarContainerToAlpha:(CGFloat)alpha { - CGFloat oldAlpha = self.view.alpha; - if (oldAlpha > 0 && alpha == 0) { - [self.view setUserInteractionEnabled:NO]; - } - - [UIView transitionWithView:self.view - duration:kAlphaChangeAnimationDuration - options:UIViewAnimationOptionCurveEaseInOut - animations:^{ - [self.view setAlpha:alpha]; - } - completion:^(BOOL) { - if (oldAlpha == 0 && alpha > 0) { - [self.view setUserInteractionEnabled:YES]; - }; - }]; -} - -// Height of the frontmost infobar contained in |self.view| that is not hidden. -- (CGFloat)topmostVisibleInfoBarHeight { - for (UIView* view in [self.view.subviews reverseObjectEnumerator]) { - return [view sizeThatFits:self.view.frame.size].height; - } - return 0; -} - -@end
diff --git a/ios/chrome/browser/ui/infobars/infobar_coordinator.h b/ios/chrome/browser/ui/infobars/infobar_coordinator.h deleted file mode 100644 index c604ef0..0000000 --- a/ios/chrome/browser/ui/infobars/infobar_coordinator.h +++ /dev/null
@@ -1,66 +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 IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_COORDINATOR_H_ -#define IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_COORDINATOR_H_ - -#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" - -namespace infobars { -class InfoBarManager; -} -namespace web { -class WebState; -} - -@class TabModel; -@protocol ApplicationCommands; -@protocol InfobarPositioner; -@protocol LanguageSelectionHandler; -@protocol SyncPresenter; - -// Coordinator that owns and manages an InfoBarContainer. -@interface InfobarCoordinator : ChromeCoordinator - -// TODO(crbug.com/892376): Stop passing TabModel and use WebStateList instead. -- (instancetype)initWithBaseViewController:(UIViewController*)viewController - browserState: - (ios::ChromeBrowserState*)browserState - tabModel:(TabModel*)tabModel - NS_DESIGNATED_INITIALIZER; -; - -- (instancetype)initWithBaseViewController:(UIViewController*)viewController - NS_UNAVAILABLE; - -- (instancetype)initWithBaseViewController:(UIViewController*)viewController - browserState: - (ios::ChromeBrowserState*)browserState - NS_UNAVAILABLE; - -// The InfoBarContainer View. -- (UIView*)view; - -// Updates the InfobarContainer according to the positioner information. -- (void)updateInfobarContainer; - -// YES if an infobar is being presented for |webState|. -- (BOOL)isInfobarPresentingForWebState:(web::WebState*)webState; - -// The dispatcher for this Coordinator. -@property(nonatomic, weak) id<ApplicationCommands> dispatcher; - -// The delegate used to position the InfoBarContainer in the view. -@property(nonatomic, weak) id<InfobarPositioner> positioner; - -// The SyncPresenter delegate for this Coordinator. -@property(nonatomic, weak) id<SyncPresenter> syncPresenter; - -// The delegate that allows user to select a language from a list of languages. -@property(nonatomic, readonly) id<LanguageSelectionHandler> - languageSelectionHandler; - -@end - -#endif // IOS_CHROME_BROWSER_UI_INFOBARS_INFOBAR_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/infobars/infobar_coordinator.mm b/ios/chrome/browser/ui/infobars/infobar_coordinator.mm deleted file mode 100644 index 34fdf91..0000000 --- a/ios/chrome/browser/ui/infobars/infobar_coordinator.mm +++ /dev/null
@@ -1,118 +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. - -#import "ios/chrome/browser/ui/infobars/infobar_coordinator.h" - -#include <memory> - -#include "ios/chrome/browser/infobars/infobar_manager_impl.h" -#import "ios/chrome/browser/ui/commands/application_commands.h" -#include "ios/chrome/browser/ui/infobars/infobar_container_mediator.h" -#include "ios/chrome/browser/ui/infobars/infobar_container_view_controller.h" -#import "ios/chrome/browser/ui/infobars/infobar_positioner.h" -#import "ios/chrome/browser/ui/signin_interaction/public/signin_presenter.h" -#import "ios/chrome/browser/ui/translate/language_selection_coordinator.h" -#include "ios/chrome/browser/upgrade/upgrade_center.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface InfobarCoordinator ()<SigninPresenter> - -@property(nonatomic, assign) TabModel* tabModel; - -// UIViewController that contains Infobars. -@property(nonatomic, strong) - InfobarContainerViewController* containerViewController; -// The mediator for this Coordinator. -@property(nonatomic, strong) InfobarContainerMediator* mediator; - -// Coordinator for the language selection UI. -@property(nonatomic, strong) - LanguageSelectionCoordinator* languageSelectionCoordinator; - -@end - -@implementation InfobarCoordinator - -- (instancetype)initWithBaseViewController:(UIViewController*)viewController - browserState: - (ios::ChromeBrowserState*)browserState - tabModel:(TabModel*)tabModel { - self = [super initWithBaseViewController:viewController - browserState:browserState]; - if (self) { - _tabModel = tabModel; - } - return self; -} - -- (void)start { - DCHECK(self.positioner); - DCHECK(self.dispatcher); - - // Create and setup the ViewController. - self.containerViewController = [[InfobarContainerViewController alloc] init]; - [self.baseViewController addChildViewController:self.containerViewController]; - // TODO(crbug.com/892376): We shouldn't modify the BaseVC hierarchy, BVC needs - // to handle this. - [self.baseViewController.view insertSubview:self.containerViewController.view - aboveSubview:self.positioner.parentView]; - [self.containerViewController - didMoveToParentViewController:self.baseViewController]; - self.containerViewController.positioner = self.positioner; - - self.languageSelectionCoordinator = [[LanguageSelectionCoordinator alloc] - initWithBaseViewController:self.baseViewController]; - - // Create the mediator once the VC has been added to the View hierarchy. - self.mediator = [[InfobarContainerMediator alloc] - initWithConsumer:self.containerViewController - browserState:self.browserState - tabModel:self.tabModel]; - self.mediator.syncPresenter = self.syncPresenter; - self.mediator.signinPresenter = self; - self.mediator.languageSelectionHandler = self.languageSelectionCoordinator; - - [[UpgradeCenter sharedInstance] registerClient:self.mediator - withDispatcher:self.dispatcher]; -} - -- (void)stop { - [[UpgradeCenter sharedInstance] unregisterClient:self.mediator]; - self.mediator = nil; -} - -#pragma mark - Public Interface - -- (UIView*)view { - return self.containerViewController.view; -} - -- (void)updateInfobarContainer { - [self.containerViewController updateLayoutAnimated:NO]; -} - -- (BOOL)isInfobarPresentingForWebState:(web::WebState*)webState { - infobars::InfoBarManager* infoBarManager = - InfoBarManagerImpl::FromWebState(webState); - if (infoBarManager->infobar_count() > 0) { - return YES; - } - return NO; -} - -- (id<LanguageSelectionHandler>)languageSelectionHandler { - return self.languageSelectionCoordinator; -} - -#pragma mark - SigninPresenter - -- (void)showSignin:(ShowSigninCommand*)command { - [self.dispatcher showSignin:command - baseViewController:self.baseViewController]; -} - -@end
diff --git a/ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.h b/ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.h new file mode 100644 index 0000000..4b0b7c0 --- /dev/null +++ b/ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.h
@@ -0,0 +1,24 @@ +// 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 IOS_CHROME_BROWSER_UI_INFOBARS_LEGACY_INFOBAR_CONTAINER_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_INFOBARS_LEGACY_INFOBAR_CONTAINER_VIEW_CONTROLLER_H_ + +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/ui/infobars/infobar_container_consumer.h" + +@protocol InfobarPositioner; + +// ViewController that contains all Infobars. It can contain various at the +// same time but only the top most one will be visible. +@interface LegacyInfobarContainerViewController + : UIViewController <InfobarContainerConsumer> + +// The delegate used to position the InfoBarContainer in the view. +@property(nonatomic, weak) id<InfobarPositioner> positioner; + +@end + +#endif // IOS_CHROME_BROWSER_UI_INFOBARS_LEGACY_INFOBAR_CONTAINER_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.mm b/ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.mm new file mode 100644 index 0000000..224ae32 --- /dev/null +++ b/ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.mm
@@ -0,0 +1,124 @@ +// 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. + +#import "ios/chrome/browser/ui/infobars/legacy_infobar_container_view_controller.h" + +#include "base/ios/block_types.h" +#include "base/logging.h" +#import "ios/chrome/browser/ui/infobars/infobar_positioner.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +// Duration for the alpha change animation. +const CGFloat kAlphaChangeAnimationDuration = 0.35; +} // namespace + +@interface LegacyInfobarContainerViewController () + +// Whether the controller's view is currently available. +// YES from viewDidAppear to viewDidDisappear. +@property(nonatomic, assign, getter=isVisible) BOOL visible; + +@end + +@implementation LegacyInfobarContainerViewController + +// Whenever the container or contained views are re-drawn update the layout to +// match their new size or position. +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + [self updateLayoutAnimated:YES]; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + self.visible = YES; +} + +- (void)viewDidDisappear:(BOOL)animated { + self.visible = NO; + [super viewDidDisappear:animated]; +} + +#pragma mark - InfobarConsumer + +- (void)addInfoBarView:(UIView*)infoBarView position:(NSInteger)position { + DCHECK_LE(static_cast<NSUInteger>(position), [[self.view subviews] count]); + [self.view insertSubview:infoBarView atIndex:position]; + infoBarView.translatesAutoresizingMaskIntoConstraints = NO; + [NSLayoutConstraint activateConstraints:@[ + [infoBarView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], + [infoBarView.trailingAnchor + constraintEqualToAnchor:self.view.trailingAnchor], + [infoBarView.topAnchor constraintEqualToAnchor:self.view.topAnchor], + [infoBarView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] + ]]; +} + +- (void)setUserInteractionEnabled:(BOOL)enabled { + [self.view setUserInteractionEnabled:enabled]; +} + +- (void)updateLayoutAnimated:(BOOL)animated { + // Update the infobarContainer height. + CGRect containerFrame = self.view.frame; + CGFloat height = [self topmostVisibleInfoBarHeight]; + containerFrame.origin.y = + CGRectGetMaxY([self.positioner parentView].frame) - height; + containerFrame.size.height = height; + + auto completion = ^(BOOL finished) { + if (!self.visible) + return; + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, + self.view); + }; + + ProceduralBlock frameUpdates = ^{ + [self.view setFrame:containerFrame]; + }; + if (animated) { + [UIView animateWithDuration:0.1 + animations:frameUpdates + completion:completion]; + } else { + frameUpdates(); + completion(YES); + } +} + +#pragma mark - Private Methods + +// Animates |self.view| alpha to |alpha|. +- (void)animateInfoBarContainerToAlpha:(CGFloat)alpha { + CGFloat oldAlpha = self.view.alpha; + if (oldAlpha > 0 && alpha == 0) { + [self.view setUserInteractionEnabled:NO]; + } + + [UIView transitionWithView:self.view + duration:kAlphaChangeAnimationDuration + options:UIViewAnimationOptionCurveEaseInOut + animations:^{ + [self.view setAlpha:alpha]; + } + completion:^(BOOL) { + if (oldAlpha == 0 && alpha > 0) { + [self.view setUserInteractionEnabled:YES]; + }; + }]; +} + +// Height of the frontmost infobar contained in |self.view| that is not hidden. +- (CGFloat)topmostVisibleInfoBarHeight { + for (UIView* view in [self.view.subviews reverseObjectEnumerator]) { + return [view sizeThatFits:self.view.frame.size].height; + } + return 0; +} + +@end
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm index 8de4be5..334064a 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
@@ -144,6 +144,11 @@ [self setSmartQuotesType:UITextSmartQuotesTypeNo]; + // Disable drag on iPhone because there's nowhere to drag to + if (!IsIPadIdiom()) { + self.textDragInteraction.enabled = NO; + } + // Sanity check: DCHECK([self conformsToProtocol:@protocol(UITextInput)]);
diff --git a/ios/chrome/browser/ui/open_in_toolbar.mm b/ios/chrome/browser/ui/open_in_toolbar.mm index 062389f5..45b42f2 100644 --- a/ios/chrome/browser/ui/open_in_toolbar.mm +++ b/ios/chrome/browser/ui/open_in_toolbar.mm
@@ -171,8 +171,8 @@ return CGSizeMake(size.width, requiredHeight); } -- (void)didMoveToSuperview { - if (!self.superview) { +- (void)didMoveToWindow { + if (!self.window) { self.bottomMarginConstraint = nil; return; }
diff --git a/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.h b/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.h index 35e8213..e9b9897 100644 --- a/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.h +++ b/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.h
@@ -26,9 +26,8 @@ // ImportDataMultilineDetailCell implements an UITableViewCell // subclass containing two text labels: a "main" label and a "detail" label. -// The two labels are laid out on top of each other. The detail text can span -// multiple lines. -// This is to be used with a ImportDataMultilineDetailItem. +// The two labels are laid out on top of each other and can span on multiple +// lines. This is to be used with a ImportDataMultilineDetailItem. @interface ImportDataMultilineDetailCell : UITableViewCell // UILabels corresponding to |text| and |detailText| from the item.
diff --git a/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.mm b/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.mm index 61fe6c1c2..eb557276 100644 --- a/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.mm +++ b/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item.mm
@@ -13,6 +13,10 @@ #error "This file requires ARC support." #endif +namespace { +const CGFloat kAccessoryWidth = 40; +} // namespace + @implementation ImportDataMultilineDetailItem @synthesize accessoryType = _accessoryType; @@ -53,6 +57,7 @@ _textLabel = [[UILabel alloc] init]; _textLabel.translatesAutoresizingMaskIntoConstraints = NO; + _textLabel.numberOfLines = 0; _textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; _textLabel.adjustsFontForContentSizeCategory = YES; _textLabel.textColor = UIColor.blackColor; @@ -69,25 +74,42 @@ // Set up the constraints. [NSLayoutConstraint activateConstraints:@[ + [_textLabel.topAnchor + constraintEqualToAnchor:contentView.topAnchor + constant:kTableViewLargeVerticalSpacing], [_textLabel.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor constant:kTableViewHorizontalSpacing], [_textLabel.trailingAnchor - constraintEqualToAnchor:contentView.trailingAnchor - constant:-kTableViewHorizontalSpacing], + constraintLessThanOrEqualToAnchor:contentView.trailingAnchor + constant:-kTableViewHorizontalSpacing], + [_textLabel.bottomAnchor + constraintEqualToAnchor:_detailTextLabel.topAnchor], [_detailTextLabel.leadingAnchor constraintEqualToAnchor:_textLabel.leadingAnchor], [_detailTextLabel.trailingAnchor - constraintEqualToAnchor:_textLabel.trailingAnchor], - [_textLabel.bottomAnchor - constraintEqualToAnchor:_detailTextLabel.topAnchor], + constraintLessThanOrEqualToAnchor:contentView.trailingAnchor + constant:-kTableViewHorizontalSpacing], + [_detailTextLabel.bottomAnchor + constraintEqualToAnchor:contentView.bottomAnchor + constant:-kTableViewLargeVerticalSpacing], ]]; - AddOptionalVerticalPadding(contentView, _textLabel, _detailTextLabel, - kTableViewLargeVerticalSpacing); } return self; } +- (void)layoutSubviews { + // Make sure that the multiline labels' width isn't changed when the accessory + // is set. + self.detailTextLabel.preferredMaxLayoutWidth = + self.bounds.size.width - + (kAccessoryWidth + 2 * kTableViewHorizontalSpacing); + self.textLabel.preferredMaxLayoutWidth = + self.bounds.size.width - + (kAccessoryWidth + 2 * kTableViewHorizontalSpacing); + [super layoutSubviews]; +} + #pragma mark Accessibility - (NSString*)accessibilityLabel {
diff --git a/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item_unittest.mm b/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item_unittest.mm index 9abcd70..f4f5532 100644 --- a/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item_unittest.mm +++ b/ios/chrome/browser/ui/settings/cells/import_data_multiline_detail_item_unittest.mm
@@ -49,7 +49,7 @@ TEST_F(ImportDataMultilineDetailItemTest, MultipleLines) { ImportDataMultilineDetailCell* cell = [[ImportDataMultilineDetailCell alloc] init]; - EXPECT_EQ(1, cell.textLabel.numberOfLines); + EXPECT_EQ(0, cell.textLabel.numberOfLines); EXPECT_EQ(0, cell.detailTextLabel.numberOfLines); }
diff --git a/ios/chrome/browser/ui/settings/password_details_table_view_controller.mm b/ios/chrome/browser/ui/settings/password_details_table_view_controller.mm index 22cfe91c24..a9e2bf0 100644 --- a/ios/chrome/browser/ui/settings/password_details_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/password_details_table_view_controller.mm
@@ -73,9 +73,6 @@ BOOL _plainTextPasswordShown; // The password form. autofill::PasswordForm _passwordForm; - // Instance of the parent view controller needed in order to update the - // password list when a password is deleted. - __weak id<PasswordDetailsTableViewControllerDelegate> _weakDelegate; // Module containing the reauthentication mechanism for viewing and copying // passwords. __weak id<ReauthenticationProtocol> _weakReauthenticationModule; @@ -87,6 +84,11 @@ // button. @property(nonatomic, strong) UIAlertController* deleteConfirmation; +// Instance of the parent view controller needed in order to update the +// password list when a password is deleted. +@property(nonatomic, weak) id<PasswordDetailsTableViewControllerDelegate> + delegate; + @end @implementation PasswordDetailsTableViewController @@ -105,7 +107,7 @@ [super initWithTableViewStyle:UITableViewStyleGrouped appBarStyle:ChromeTableViewControllerStyleWithAppBar]; if (self) { - _weakDelegate = delegate; + _delegate = delegate; _weakReauthenticationModule = reauthenticationModule; _passwordForm = passwordForm; @@ -493,13 +495,9 @@ actionWithTitle:l10n_util::GetNSString(IDS_IOS_CONFIRM_PASSWORD_DELETION) style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action) { - PasswordDetailsTableViewController* strongSelf = weakSelf; - if (!strongSelf) { - return; - } - strongSelf.deleteConfirmation = nil; - [strongSelf->_weakDelegate - passwordDetailsTableViewController:strongSelf + weakSelf.deleteConfirmation = nil; + [weakSelf.delegate + passwordDetailsTableViewController:weakSelf deletePassword:_passwordForm]; }]; [_deleteConfirmation addAction:deleteAction];
diff --git a/ios/chrome/browser/ui/settings/password_details_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password_details_table_view_controller_unittest.mm index d6a4c545..f964145f 100644 --- a/ios/chrome/browser/ui/settings/password_details_table_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/password_details_table_view_controller_unittest.mm
@@ -16,6 +16,7 @@ #include "ios/web/public/test/test_web_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" #import "testing/gtest_mac.h" +#include "third_party/ocmock/OCMock/OCMock.h" #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" @@ -23,26 +24,6 @@ #error "This file requires ARC support." #endif -@interface MockSavePasswordsTableViewController - : NSObject <PasswordDetailsTableViewControllerDelegate> - -- (void)passwordDetailsTableViewController: - (PasswordDetailsTableViewController*)constroller - deletePassword: - (const autofill::PasswordForm&)passwordForm; - -@end - -@implementation MockSavePasswordsTableViewController - -- (void)passwordDetailsTableViewController: - (PasswordDetailsTableViewController*)constroller - deletePassword: - (const autofill::PasswordForm&)passwordForm { -} - -@end - namespace { NSString* const kSite = @"https://testorigin.com/"; @@ -79,7 +60,6 @@ void SetUp() override { ChromeTableViewControllerTest::SetUp(); - delegate_ = [[MockSavePasswordsTableViewController alloc] init]; reauthentication_module_ = [[MockReauthenticationModule alloc] init]; reauthentication_module_.shouldSucceed = YES; } @@ -87,12 +67,12 @@ ChromeTableViewController* InstantiateController() override { return [[PasswordDetailsTableViewController alloc] initWithPasswordForm:form_ - delegate:delegate_ + delegate:OCMProtocolMock(@protocol( + PasswordDetailsTableViewControllerDelegate)) reauthenticationModule:reauthentication_module_]; } web::TestWebThreadBundle thread_bundle_; - MockSavePasswordsTableViewController* delegate_; MockReauthenticationModule* reauthentication_module_; NSString* origin_; autofill::PasswordForm form_;
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm index ce3ff078..843aa21c 100644 --- a/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm +++ b/ios/chrome/browser/ui/table_view/chrome_table_view_controller.mm
@@ -277,14 +277,6 @@ #pragma mark - MDCAppBarViewController support -- (UIViewController*)childViewControllerForStatusBarHidden { - return self.appBarViewController; -} - -- (UIViewController*)childViewControllerForStatusBarStyle { - return self.appBarViewController; -} - - (void)scrollViewDidScroll:(UIScrollView*)scrollView { MDCFlexibleHeaderView* headerView = self.appBarViewController.headerView; if (scrollView == headerView.trackingScrollView) {
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.h b/ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.h index c814b4d5..fad2bb2 100644 --- a/ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.h +++ b/ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.h
@@ -112,6 +112,19 @@ int section, int item); + // Verifies that the text button cell at |item| in |section| has the given + // |buttonText|. + void CheckTextButtonCellButtonText(NSString* expected_button_text, + int section, + int item); + + // Verifies that the text button cell at |item| in |section| has a + // |buttonText| property which matches the l10n string for + // |expected_button_text_id|. + void CheckTextButtonCellButtonTextWithId(int expected_button_text_id, + int section, + int item); + // For |section|, deletes the item at |item|. |completion_block| is called at // the end of the call to -performBatchUpdates:completion:. void DeleteItem(int section, int item, ProceduralBlock completion_block);
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.mm b/ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.mm index bc05219..280c225 100644 --- a/ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.mm +++ b/ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.mm
@@ -6,6 +6,7 @@ #include "base/logging.h" #import "base/mac/foundation_util.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_text_button_item.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_text_item.h" #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h" @@ -187,6 +188,23 @@ EXPECT_EQ(accessory_type, [text_item accessoryType]); } +void ChromeTableViewControllerTest::CheckTextButtonCellButtonText( + NSString* expected_button_text, + int section, + int item) { + id text_button_item = GetTableViewItem(section, item); + ASSERT_TRUE([text_button_item respondsToSelector:@selector(buttonText)]); + EXPECT_NSEQ(expected_button_text, [text_button_item buttonText]); +} + +void ChromeTableViewControllerTest::CheckTextButtonCellButtonTextWithId( + int expected_button_text_id, + int section, + int item) { + CheckTextButtonCellButtonText(l10n_util::GetNSString(expected_button_text_id), + section, item); +} + void ChromeTableViewControllerTest::DeleteItem( int section, int item,
diff --git a/ios/third_party/motion_interchange_objc/README.chromium b/ios/third_party/motion_interchange_objc/README.chromium index 05fff511..3b67ddfa 100644 --- a/ios/third_party/motion_interchange_objc/README.chromium +++ b/ios/third_party/motion_interchange_objc/README.chromium
@@ -1,7 +1,7 @@ Name: Motion Interchange for Objective-C URL: https://github.com/material-motion/motion-interchange-objc Version: 0 -Revision: 02e2308e1c68cd966a91807b17bcdf57f92af401 +Revision: 6c385396ae7d3ee6752c3d625e322138eb8e25fc License: Apache 2.0 License File: LICENSE Security Critical: yes @@ -12,4 +12,4 @@ describe the duration, delay, timing curve, and repetition for an animation. Local Modifications: -None +None \ No newline at end of file
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn index 8372df9..6e8926e 100644 --- a/ios/web/BUILD.gn +++ b/ios/web/BUILD.gn
@@ -630,6 +630,7 @@ "web_state/js/resources/all_frames_web_bundle.js", "web_state/js/resources/base.js", "web_state/js/resources/common.js", + "web_state/js/resources/find_in_page.js", "web_state/js/resources/message.js", ] }
diff --git a/ios/web/navigation/legacy_navigation_manager_impl.h b/ios/web/navigation/legacy_navigation_manager_impl.h index dba9d742..2782708 100644 --- a/ios/web/navigation/legacy_navigation_manager_impl.h +++ b/ios/web/navigation/legacy_navigation_manager_impl.h
@@ -87,7 +87,7 @@ NavigationItemImpl* GetNavigationItemImplAtIndex(size_t index) const override; NavigationItemImpl* GetLastCommittedItemInCurrentOrRestoredSession() const override; - NavigationItemImpl* GetPendingItemImpl() const override; + NavigationItemImpl* GetPendingItemInCurrentOrRestoredSession() const override; NavigationItemImpl* GetTransientItemImpl() const override; void FinishGoToIndex(int index, NavigationInitiationType type,
diff --git a/ios/web/navigation/legacy_navigation_manager_impl.mm b/ios/web/navigation/legacy_navigation_manager_impl.mm index 4c12a50..5888d65 100644 --- a/ios/web/navigation/legacy_navigation_manager_impl.mm +++ b/ios/web/navigation/legacy_navigation_manager_impl.mm
@@ -108,13 +108,13 @@ initiationType:initiation_type userAgentOverrideOption:user_agent_override_option]; - if (!GetPendingItem()) { + if (!GetPendingItemInCurrentOrRestoredSession()) { return; } UpdatePendingItemUserAgentType(user_agent_override_option, GetLastCommittedItemWithUserAgentType(), - GetPendingItem()); + GetPendingItemInCurrentOrRestoredSession()); } void LegacyNavigationManagerImpl::CommitPendingItem() { @@ -302,7 +302,8 @@ return [session_controller_ lastCommittedItem]; } -NavigationItemImpl* LegacyNavigationManagerImpl::GetPendingItemImpl() const { +NavigationItemImpl* +LegacyNavigationManagerImpl::GetPendingItemInCurrentOrRestoredSession() const { return [session_controller_ pendingItem]; }
diff --git a/ios/web/navigation/navigation_manager_impl.h b/ios/web/navigation/navigation_manager_impl.h index 776255d..2941923c 100644 --- a/ios/web/navigation/navigation_manager_impl.h +++ b/ios/web/navigation/navigation_manager_impl.h
@@ -143,7 +143,10 @@ NSString* state_object, ui::PageTransition transition) = 0; - // Returns true if session restoration is in progress. + // Returns true after session restoration has started, until the first + // post-restore navigation is finished. Returns true when first post-restore + // navigation is started, even though technically session restoration is + // complete. virtual bool IsRestoreSessionInProgress() const = 0; // Resets the transient url rewriter list. @@ -197,7 +200,8 @@ void AddRestoreCompletionCallback(base::OnceClosure callback) override; // Implementation for corresponding NavigationManager getters. - virtual NavigationItemImpl* GetPendingItemImpl() const = 0; + virtual NavigationItemImpl* GetPendingItemInCurrentOrRestoredSession() + const = 0; virtual NavigationItemImpl* GetTransientItemImpl() const = 0; // Unlike GetLastCommittedItem(), this method does not return null during // session restoration (and returns last known committed item instead).
diff --git a/ios/web/navigation/navigation_manager_impl.mm b/ios/web/navigation/navigation_manager_impl.mm index 4f1565d..64ea073 100644 --- a/ios/web/navigation/navigation_manager_impl.mm +++ b/ios/web/navigation/navigation_manager_impl.mm
@@ -158,7 +158,7 @@ void NavigationManagerImpl::UpdatePendingItemUrl(const GURL& url) const { // If there is no pending item, navigation is probably happening within the // back forward history. Don't modify the item list. - NavigationItemImpl* pending_item = GetPendingItemImpl(); + NavigationItemImpl* pending_item = GetPendingItemInCurrentOrRestoredSession(); if (!pending_item || url == pending_item->GetURL()) return; @@ -178,7 +178,7 @@ if (transient_item) return transient_item; - NavigationItemImpl* pending_item = GetPendingItemImpl(); + NavigationItemImpl* pending_item = GetPendingItemInCurrentOrRestoredSession(); if (pending_item) return pending_item; @@ -236,6 +236,10 @@ } NavigationItem* NavigationManagerImpl::GetLastCommittedItem() const { + // GetLastCommittedItem() should return null while session restoration is in + // progress and real item after the first post-restore navigation is + // finished. IsRestoreSessionInProgress(), will return true until the first + // post-restore is finished. if (IsRestoreSessionInProgress()) return nullptr; @@ -243,6 +247,10 @@ } int NavigationManagerImpl::GetLastCommittedItemIndex() const { + // GetLastCommittedItemIndex() should return -1 while session restoration is + // in progress and real item after the first post-restore navigation is + // finished. IsRestoreSessionInProgress(), will return true until the first + // post-restore is finished. if (IsRestoreSessionInProgress()) return -1; @@ -250,7 +258,18 @@ } NavigationItem* NavigationManagerImpl::GetPendingItem() const { - return GetPendingItemImpl(); + NavigationItem* item = GetPendingItemInCurrentOrRestoredSession(); + + // GetPendingItem() should return null while session restoration is in + // progress and real item when the first post-restore navigation has started. + // It's not possible to rely on IsRestoreSessionInProgress(), because this + // method may return true until the first post-restore is finished, hence + // this code relies on actual navigation URL to determine if restoration is + // complete. + if (item && wk_navigation_util::IsRestoreSessionUrl(item->GetURL())) + return nullptr; + + return item; } NavigationItem* NavigationManagerImpl::GetTransientItem() const { @@ -272,7 +291,7 @@ // Mark pending item as created from hash change if necessary. This is needed // because window.hashchange message may not arrive on time. - NavigationItemImpl* pending_item = GetPendingItemImpl(); + NavigationItemImpl* pending_item = GetPendingItemInCurrentOrRestoredSession(); if (pending_item) { NavigationItem* last_committed_item = GetLastCommittedItemInCurrentOrRestoredSession();
diff --git a/ios/web/navigation/navigation_manager_impl_unittest.mm b/ios/web/navigation/navigation_manager_impl_unittest.mm index f5d15845..07113d2 100644 --- a/ios/web/navigation/navigation_manager_impl_unittest.mm +++ b/ios/web/navigation/navigation_manager_impl_unittest.mm
@@ -1767,7 +1767,8 @@ navigation_manager()->ReloadWithUserAgentType(UserAgentType::DESKTOP); - NavigationItem* pending_item = navigation_manager()->GetPendingItem(); + NavigationItem* pending_item = + navigation_manager()->GetPendingItemInCurrentOrRestoredSession(); if (!web::GetWebClient()->IsSlimNavigationManagerEnabled()) { EXPECT_EQ(url, pending_item->GetURL()); } else { @@ -1788,13 +1789,16 @@ NavigationInitiationType::BROWSER_INITIATED, NavigationManager::UserAgentOverrideOption::MOBILE); GURL virtual_url("http://www.1.com/virtual"); - navigation_manager()->GetPendingItem()->SetVirtualURL(virtual_url); + navigation_manager() + ->GetPendingItemInCurrentOrRestoredSession() + ->SetVirtualURL(virtual_url); [mock_wk_list_ setCurrentURL:base::SysUTF8ToNSString(url.spec())]; navigation_manager()->CommitPendingItem(); navigation_manager()->ReloadWithUserAgentType(UserAgentType::DESKTOP); - NavigationItem* pending_item = navigation_manager()->GetPendingItem(); + NavigationItem* pending_item = + navigation_manager()->GetPendingItemInCurrentOrRestoredSession(); if (!web::GetWebClient()->IsSlimNavigationManagerEnabled()) { EXPECT_EQ(url, pending_item->GetURL()); } else { @@ -1988,8 +1992,10 @@ ASSERT_FALSE(restore_done); // Verify that restore session URL is pending. - NavigationItem* pending_item = navigation_manager()->GetPendingItem(); - ASSERT_TRUE(pending_item != nullptr); + EXPECT_FALSE(navigation_manager()->GetPendingItem()); + NavigationItem* pending_item = + navigation_manager()->GetPendingItemInCurrentOrRestoredSession(); + ASSERT_TRUE(pending_item); GURL pending_url = pending_item->GetURL(); EXPECT_TRUE(pending_url.SchemeIsFile()); EXPECT_EQ("restore_session.html", pending_url.ExtractFileName()); @@ -2377,7 +2383,9 @@ GURL("http://www.url.com/#hash"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::BROWSER_INITIATED, web::NavigationManager::UserAgentOverrideOption::INHERIT); - navigation_manager()->GetPendingItemImpl()->SetIsCreatedFromHashChange(true); + navigation_manager() + ->GetPendingItemInCurrentOrRestoredSession() + ->SetIsCreatedFromHashChange(true); [mock_wk_list_ setCurrentURL:@"http://www.url.com/#hash" backListURLs:@[ @"http://www.url.com" ] forwardListURLs:nil];
diff --git a/ios/web/navigation/navigation_manager_util.mm b/ios/web/navigation/navigation_manager_util.mm index 58157536..b6cafd6 100644 --- a/ios/web/navigation/navigation_manager_util.mm +++ b/ios/web/navigation/navigation_manager_util.mm
@@ -21,7 +21,8 @@ if (transient_item && transient_item->GetUniqueID() == unique_id) return transient_item; - NavigationItemImpl* pending_item = navigation_manager->GetPendingItemImpl(); + NavigationItemImpl* pending_item = + navigation_manager->GetPendingItemInCurrentOrRestoredSession(); if (pending_item && pending_item->GetUniqueID() == unique_id) return pending_item;
diff --git a/ios/web/navigation/wk_based_navigation_manager_impl.h b/ios/web/navigation/wk_based_navigation_manager_impl.h index 34956156..458fee9 100644 --- a/ios/web/navigation/wk_based_navigation_manager_impl.h +++ b/ios/web/navigation/wk_based_navigation_manager_impl.h
@@ -203,8 +203,10 @@ NavigationItemImpl* GetLastCommittedItemInCurrentOrRestoredSession() const override; int GetLastCommittedItemIndexInCurrentOrRestoredSession() const override; - // Returns the pending navigation item in the main frame. - NavigationItemImpl* GetPendingItemImpl() const override; + // Returns the pending navigation item in the main frame. Unlike + // GetPendingItem(), this method does not return null during session + // restoration (and returns last known pending item instead). + NavigationItemImpl* GetPendingItemInCurrentOrRestoredSession() const override; NavigationItemImpl* GetTransientItemImpl() const override; void FinishGoToIndex(int index, NavigationInitiationType initiation_type,
diff --git a/ios/web/navigation/wk_based_navigation_manager_impl.mm b/ios/web/navigation/wk_based_navigation_manager_impl.mm index 51ee896..224d66b 100644 --- a/ios/web/navigation/wk_based_navigation_manager_impl.mm +++ b/ios/web/navigation/wk_based_navigation_manager_impl.mm
@@ -320,7 +320,7 @@ // Only return pending_item_ for new (non-history), user-initiated // navigations in order to prevent URL spoof attacks. - NavigationItemImpl* pending_item = GetPendingItemImpl(); + NavigationItemImpl* pending_item = GetPendingItemInCurrentOrRestoredSession(); if (pending_item) { bool is_user_initiated = pending_item->NavigationInitiationType() == NavigationInitiationType::BROWSER_INITIATED; @@ -516,7 +516,7 @@ // On restore prime the first navigation item with the title. The remaining // navItem titles will be set from the WKBackForwardListItem title value. - NavigationItemImpl* pendingItem = GetPendingItemImpl(); + NavigationItemImpl* pendingItem = GetPendingItemInCurrentOrRestoredSession(); if (pendingItem) { pendingItem->SetTitle(firstTitle); } @@ -586,7 +586,8 @@ return web_view_cache_.GetCurrentItemIndex(); } -NavigationItemImpl* WKBasedNavigationManagerImpl::GetPendingItemImpl() const { +NavigationItemImpl* +WKBasedNavigationManagerImpl::GetPendingItemInCurrentOrRestoredSession() const { return (pending_item_index_ == -1) ? pending_item_.get() : GetNavigationItemImplAtIndex(pending_item_index_);
diff --git a/ios/web/navigation/wk_based_navigation_manager_impl_unittest.mm b/ios/web/navigation/wk_based_navigation_manager_impl_unittest.mm index 9b48234d..75500b9 100644 --- a/ios/web/navigation/wk_based_navigation_manager_impl_unittest.mm +++ b/ios/web/navigation/wk_based_navigation_manager_impl_unittest.mm
@@ -613,8 +613,10 @@ manager_->Restore(1 /* last_committed_item_index */, std::move(items)); EXPECT_TRUE(manager_->IsRestoreSessionInProgress()); - NavigationItem* pending_item = manager_->GetPendingItem(); - ASSERT_TRUE(pending_item != nullptr); + ASSERT_FALSE(manager_->GetPendingItem()); + NavigationItem* pending_item = + manager_->GetPendingItemInCurrentOrRestoredSession(); + ASSERT_TRUE(pending_item); GURL pending_url = pending_item->GetURL(); EXPECT_TRUE(pending_url.SchemeIsFile()); EXPECT_EQ("restore_session.html", pending_url.ExtractFileName()); @@ -689,7 +691,9 @@ EXPECT_EQ(-1, manager_->GetPendingItemIndex()); // Check that the only pending item is restore_session.html. - NavigationItem* pending_item = manager_->GetPendingItem(); + ASSERT_FALSE(manager_->GetPendingItem()); + NavigationItem* pending_item = + manager_->GetPendingItemInCurrentOrRestoredSession(); ASSERT_TRUE(pending_item != nullptr); GURL pending_url = pending_item->GetURL(); EXPECT_TRUE(pending_url.SchemeIsFile()); @@ -896,11 +900,14 @@ delegate_.RemoveWebView(); manager_->Reload(web::ReloadType::NORMAL, false /* check_for_repost */); + NavigationItem* pending_item = + manager_->GetPendingItemInCurrentOrRestoredSession(); EXPECT_EQ( "{\"offset\":-1,\"titles\":[\"\",\"\",\"\"],\"urls\":[\"http://www.0.com/" "\",\"http://www.1.com/\",\"http://www.2.com/\"]}", - ExtractRestoredSession(manager_->GetPendingItem()->GetURL())); - EXPECT_EQ(url0_, manager_->GetPendingItem()->GetVirtualURL()); + ExtractRestoredSession(pending_item->GetURL())); + + EXPECT_EQ(url0_, pending_item->GetVirtualURL()); EXPECT_EQ(url1_, manager_->GetVisibleItem()->GetURL()); histogram_tester_.ExpectTotalCount(kRestoreNavigationItemCount, 1); @@ -914,11 +921,14 @@ delegate_.RemoveWebView(); manager_->GoToIndex(0); + NavigationItem* pending_item = + manager_->GetPendingItemInCurrentOrRestoredSession(); + EXPECT_EQ( "{\"offset\":-2,\"titles\":[\"\",\"\",\"\"],\"urls\":[\"http://www.0.com/" "\",\"http://www.1.com/\",\"http://www.2.com/\"]}", - ExtractRestoredSession(manager_->GetPendingItem()->GetURL())); - EXPECT_EQ(url0_, manager_->GetPendingItem()->GetVirtualURL()); + ExtractRestoredSession(pending_item->GetURL())); + EXPECT_EQ(url0_, pending_item->GetVirtualURL()); EXPECT_EQ(url0_, manager_->GetVisibleItem()->GetURL()); histogram_tester_.ExpectTotalCount(kRestoreNavigationItemCount, 1); @@ -931,11 +941,14 @@ delegate_.RemoveWebView(); manager_->LoadIfNecessary(); + NavigationItem* pending_item = + manager_->GetPendingItemInCurrentOrRestoredSession(); + EXPECT_EQ( "{\"offset\":-1,\"titles\":[\"\",\"\",\"\"],\"urls\":[\"http://www.0.com/" "\",\"http://www.1.com/\",\"http://www.2.com/\"]}", - ExtractRestoredSession(manager_->GetPendingItem()->GetURL())); - EXPECT_EQ(url0_, manager_->GetPendingItem()->GetVirtualURL()); + ExtractRestoredSession(pending_item->GetURL())); + EXPECT_EQ(url0_, pending_item->GetVirtualURL()); EXPECT_EQ(url1_, manager_->GetVisibleItem()->GetURL()); histogram_tester_.ExpectTotalCount(kRestoreNavigationItemCount, 1); @@ -951,11 +964,13 @@ GURL url("http://www.3.com"); NavigationManager::WebLoadParams params(url); manager_->LoadURLWithParams(params); + NavigationItem* pending_item = + manager_->GetPendingItemInCurrentOrRestoredSession(); EXPECT_EQ( "{\"offset\":0,\"titles\":[\"\",\"\",\"\"],\"urls\":[\"http://www.0.com/" "\",\"http://www.1.com/\",\"http://www.3.com/\"]}", - ExtractRestoredSession(manager_->GetPendingItem()->GetURL())); - EXPECT_EQ(url0_, manager_->GetPendingItem()->GetVirtualURL()); + ExtractRestoredSession(pending_item->GetURL())); + EXPECT_EQ(url0_, pending_item->GetVirtualURL()); EXPECT_EQ(url, manager_->GetVisibleItem()->GetURL()); histogram_tester_.ExpectTotalCount(kRestoreNavigationItemCount, 1);
diff --git a/ios/web/public/web_state/web_state_observer.h b/ios/web/public/web_state/web_state_observer.h index f52a3f7..1cc5cf6 100644 --- a/ios/web/public/web_state/web_state_observer.h +++ b/ios/web/public/web_state/web_state_observer.h
@@ -33,6 +33,12 @@ virtual void WasHidden(WebState* web_state) {} // This method is invoked when committed navigation items have been pruned. + // DEPRECATED. DidChangeBackForwardState is a superset of this callback and + // should be used instead of NavigationItemsPruned in the future. + // NavigationItemsPruned is not called when slim-navigation-manager is enabled + // and DidChangeBackForwardState is not called when slim-navigation-manager is + // disabled. So for now the clients should implement both callbacks. + // TODO(crbug.com/910894): Remove this method. virtual void NavigationItemsPruned(WebState* web_state, size_t pruned_item_count) {}
diff --git a/ios/web/web_state/js/resources/all_frames_web_bundle.js b/ios/web/web_state/js/resources/all_frames_web_bundle.js index 704c4dc..8048e90 100644 --- a/ios/web/web_state/js/resources/all_frames_web_bundle.js +++ b/ios/web/web_state/js/resources/all_frames_web_bundle.js
@@ -8,5 +8,6 @@ goog.require('__crWeb.allFramesContextMenu'); goog.require('__crWeb.base'); goog.require('__crWeb.common'); +goog.require('__crWeb.findInPage'); goog.require('__crWeb.message');
diff --git a/ios/web/web_state/js/resources/find_in_page.js b/ios/web/web_state/js/resources/find_in_page.js new file mode 100644 index 0000000..c3e99cec --- /dev/null +++ b/ios/web/web_state/js/resources/find_in_page.js
@@ -0,0 +1,29 @@ +// 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. + +goog.provide('__crWeb.findInPage'); + +goog.require('__crWeb.base'); + +/** + * Based on code from the Google iOS app. + * + * @fileoverview A find in page tool. It can: + * 1. Search for given string in the DOM, and highlight them in yellow color; + * 2. Allow users to navigate through all match results, and highlight the + * selected one in orange color; + */ + +(function() { +/** + * Namespace for this file. + */ +__gCrWeb.findInPage = {}; + + // Store common namespace object in a global __gCrWeb object referenced by a + // string, so it does not get renamed by closure compiler during the + // minification. + __gCrWeb['findInPage'] = __gCrWeb.findInPage; + +})();
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 5d14681f7..760058d 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -226,6 +226,9 @@ @property(nonatomic, assign) BOOL cancelled; // Whether the navigation was initiated by a user gesture. @property(nonatomic, assign) BOOL hasUserGesture; +// The back/forward navigation context for this pending navigation. +@property(nonatomic, readonly) + web::NavigationContextImpl* pendingBackForwardContext; // Used by |webView:decidePolicyForNavigationAction| during a new back/forward // navigation to store the navigation context temporarily until it can be @@ -264,6 +267,10 @@ releasePendingBackForwardContext { return std::move(_pendingBackForwardContext); } + +- (web::NavigationContextImpl*)pendingBackForwardContext { + return _pendingBackForwardContext.get(); +} @end @interface CRWWebController ()<CRWContextMenuDelegate, @@ -1377,6 +1384,19 @@ : WKNavigationTypeOther; ui::PageTransition transition = [self pageTransitionFromNavigationType:navigationType]; + + if (web::GetWebClient()->IsSlimNavigationManagerEnabled() && + navigationType == WKNavigationTypeBackForward && + _webView.backForwardList.currentItem) { + web::NavigationItem* currentItem = [[CRWNavigationItemHolder + holderForBackForwardListItem:_webView.backForwardList.currentItem] + navigationItem]; + if (currentItem) { + transition = ui::PageTransitionFromInt(transition | + currentItem->GetTransitionType()); + } + } + // The referrer is not known yet, and will be updated later. const web::Referrer emptyReferrer; std::unique_ptr<web::NavigationContextImpl> context = @@ -1403,7 +1423,8 @@ // Add or update pending item before any WebStateObserver callbacks. // See https://crbug.com/842151 for a scenario where this is important. - web::NavigationItem* item = self.navigationManagerImpl->GetPendingItem(); + web::NavigationItem* item = + self.navigationManagerImpl->GetPendingItemInCurrentOrRestoredSession(); if (item) { // Update the existing pending entry. // Typically on PAGE_TRANSITION_CLIENT_REDIRECT. @@ -1422,7 +1443,8 @@ requestURL, referrer, transition, web::NavigationInitiationType::RENDERER_INITIATED, NavigationManager::UserAgentOverrideOption::INHERIT); - item = self.navigationManagerImpl->GetPendingItem(); + item = + self.navigationManagerImpl->GetPendingItemInCurrentOrRestoredSession(); } bool redirect = transition & ui::PAGE_TRANSITION_IS_REDIRECT_MASK; @@ -4393,7 +4415,8 @@ web::NavigationContextImpl* context = [self contextForPendingMainFrameNavigationWithURL:requestURL]; if (context) { - DCHECK(!context->IsRendererInitiated()); + DCHECK(!context->IsRendererInitiated() || + (context->GetPageTransition() & ui::PAGE_TRANSITION_FORWARD_BACK)); transition = context->GetPageTransition(); if (context->IsLoadingErrorPage()) { // loadHTMLString: navigation which loads error page into WKWebView. @@ -5584,6 +5607,11 @@ - (web::NavigationContextImpl*)contextForPendingMainFrameNavigationWithURL: (const GURL&)URL { + if (_pendingNavigationInfo.pendingBackForwardContext && + _pendingNavigationInfo.pendingBackForwardContext->GetUrl() == URL) { + return _pendingNavigationInfo.pendingBackForwardContext; + } + // Here the enumeration variable |navigation| is __strong to allow setting it // to nil. for (__strong id navigation in [_navigationStates pendingNavigations]) {
diff --git a/ios/web/web_state/web_state_observer_inttest.mm b/ios/web/web_state/web_state_observer_inttest.mm index 4636eff..5bb5952 100644 --- a/ios/web/web_state/web_state_observer_inttest.mm +++ b/ios/web/web_state/web_state_observer_inttest.mm
@@ -1539,10 +1539,6 @@ // Tests going forward to a page rendered from post response. TEST_P(WebStateObserverTest, ForwardPostNavigation) { - // TODO(crbug.com/851119): temporarily disable this failing test. - if (GetParam() == TEST_WK_BASED_NAVIGATION_MANAGER) { - return; - } const GURL url = test_server_->GetURL("/form?echo"); const GURL action = test_server_->GetURL("/echo"); @@ -1599,16 +1595,11 @@ /*target_main_frame=*/true, /*has_user_gesture=*/false); if (GetWebClient()->IsSlimNavigationManagerEnabled()) { EXPECT_CALL(observer_, DidChangeBackForwardState(web_state())).Times(2); - EXPECT_CALL(*decider_, - ShouldAllowRequest(_, RequestInfoMatch(back_request_info))) - .WillOnce(Return(true)); - EXPECT_CALL(observer_, DidStartLoading(web_state())); - } else { - EXPECT_CALL(observer_, DidStartLoading(web_state())); - EXPECT_CALL(*decider_, - ShouldAllowRequest(_, RequestInfoMatch(back_request_info))) - .WillOnce(Return(true)); } + EXPECT_CALL(observer_, DidStartLoading(web_state())); + EXPECT_CALL(*decider_, + ShouldAllowRequest(_, RequestInfoMatch(back_request_info))) + .WillOnce(Return(true)); EXPECT_CALL(observer_, DidStartNavigation(web_state(), _)); if (@available(iOS 12, *)) { @@ -1637,22 +1628,29 @@ int32_t nav_id = 0; if (GetWebClient()->IsSlimNavigationManagerEnabled()) { EXPECT_CALL(observer_, DidChangeBackForwardState(web_state())).Times(2); - // ShouldAllowRequest() not called on repost. - EXPECT_CALL(observer_, DidStartLoading(web_state())); - } else { - EXPECT_CALL(observer_, DidStartLoading(web_state())); - EXPECT_CALL(*decider_, - ShouldAllowRequest(_, RequestInfoMatch(forward_request_info))) - .WillOnce(Return(true)); } + + EXPECT_CALL(observer_, DidStartLoading(web_state())); + EXPECT_CALL(*decider_, + ShouldAllowRequest(_, RequestInfoMatch(forward_request_info))) + .WillOnce(Return(true)); + + // TODO(crbug.com/913052): propagate |has_user_gesture| on back/forward + // navigation in slim nav. + bool forward_navigation_has_user_gesture = + !GetWebClient()->IsSlimNavigationManagerEnabled(); + EXPECT_CALL(observer_, DidStartNavigation(web_state(), _)) - .WillOnce(VerifyPostStartedContext( - web_state(), action, /*has_user_gesture=*/true, &context, &nav_id, - /*renderer_initiated=*/false)); + .WillOnce(VerifyPostStartedContext(web_state(), action, + forward_navigation_has_user_gesture, + &context, &nav_id, + /*renderer_initiated=*/false)); + EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _)) - .WillOnce(VerifyPostFinishedContext( - web_state(), action, /*has_user_gesture=*/true, &context, &nav_id, - /*renderer_initiated=*/false)); + .WillOnce(VerifyPostFinishedContext(web_state(), action, + forward_navigation_has_user_gesture, + &context, &nav_id, + /*renderer_initiated=*/false)); EXPECT_CALL(observer_, TitleWasSet(web_state())) .WillOnce(VerifyTitle(action.GetContent())); EXPECT_CALL(observer_, DidStopLoading(web_state())); @@ -1889,11 +1887,6 @@ if (!GetWebClient()->IsSlimNavigationManagerEnabled()) return; - // TODO(crbug.com/851119): temporarily disable this failing test. - if (GetParam() == TEST_WK_BASED_NAVIGATION_MANAGER) { - return; - } - GURL url = test_server_->GetURL("/iframe_host.html"); // Callbacks due to loading of the main frame. @@ -1908,10 +1901,12 @@ EXPECT_CALL(*decider_, ShouldAllowResponse(_, /*for_main_frame=*/true)) .WillOnce(Return(true)); EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _)); + EXPECT_CALL(observer_, TitleWasSet(web_state())); + // Callbacks due to initial loading of iframe. WebStatePolicyDecider::RequestInfo iframe_request_info( ui::PageTransition::PAGE_TRANSITION_CLIENT_REDIRECT, - /*target_main_frame=*/false, /*has_user_gesture=*/true); + /*target_main_frame=*/false, /*has_user_gesture=*/false); EXPECT_CALL(*decider_, ShouldAllowRequest(_, RequestInfoMatch(iframe_request_info))) .WillOnce(Return(true)); @@ -1925,37 +1920,47 @@ ASSERT_TRUE(test::WaitForPageToFinishLoading(web_state())); // Trigger different-document load in iframe. - EXPECT_CALL(*decider_, - ShouldAllowRequest(_, RequestInfoMatch(iframe_request_info))) + WebStatePolicyDecider::RequestInfo link_clicked_request_info( + ui::PageTransition::PAGE_TRANSITION_LINK, + /*target_main_frame=*/false, /*has_user_gesture=*/true); + EXPECT_CALL(*decider_, ShouldAllowRequest( + _, RequestInfoMatch(link_clicked_request_info))) .WillOnce(Return(true)); EXPECT_CALL(*decider_, ShouldAllowResponse(_, /*for_main_frame=*/false)) .WillOnce(Return(true)); EXPECT_CALL(observer_, DidChangeBackForwardState(web_state())); test::TapWebViewElementWithIdInIframe(web_state(), "normal-link"); EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{ - return web_state()->GetNavigationManager()->CanGoBack(); + id URL = ExecuteJavaScript(@"window.frames[0].location.pathname;"); + return [@"/pony.html" isEqualToString:URL]; })); + ASSERT_TRUE(web_state()->GetNavigationManager()->CanGoBack()); + ASSERT_FALSE(web_state()->GetNavigationManager()->CanGoForward()); id history_length = ExecuteJavaScript(@"history.length;"); ASSERT_NSEQ(@2, history_length); - EXPECT_FALSE(web_state()->GetNavigationManager()->CanGoForward()); // Go back to top. + WebStatePolicyDecider::RequestInfo forward_back_request_info( + ui::PageTransition::PAGE_TRANSITION_FORWARD_BACK, + /*target_main_frame=*/false, /*has_user_gesture=*/true); EXPECT_CALL(observer_, DidChangeBackForwardState(web_state())) .Times(2); // called once each for canGoBack and canGoForward - EXPECT_CALL(*decider_, - ShouldAllowRequest(_, RequestInfoMatch(iframe_request_info))) + EXPECT_CALL(*decider_, ShouldAllowRequest( + _, RequestInfoMatch(forward_back_request_info))) .WillOnce(Return(true)); EXPECT_CALL(*decider_, ShouldAllowResponse(_, /*for_main_frame=*/false)) .WillOnce(Return(true)); web_state()->GetNavigationManager()->GoBack(); EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{ - return web_state()->GetNavigationManager()->CanGoForward(); + id URL = ExecuteJavaScript(@"window.frames[0].location.pathname;"); + return [@"/links.html" isEqualToString:URL]; })); - EXPECT_FALSE(web_state()->GetNavigationManager()->CanGoBack()); + ASSERT_TRUE(web_state()->GetNavigationManager()->CanGoForward()); + ASSERT_FALSE(web_state()->GetNavigationManager()->CanGoBack()); // Trigger same-document load in iframe. - EXPECT_CALL(*decider_, - ShouldAllowRequest(_, RequestInfoMatch(iframe_request_info))) + EXPECT_CALL(*decider_, ShouldAllowRequest( + _, RequestInfoMatch(link_clicked_request_info))) .WillOnce(Return(true)); // ShouldAllowResponse() is not called for same-document navigation. EXPECT_CALL(observer_, DidChangeBackForwardState(web_state()))
diff --git a/ios/web/web_state/web_state_unittest.mm b/ios/web/web_state/web_state_unittest.mm index cbff6b0e..42d2ffa 100644 --- a/ios/web/web_state/web_state_unittest.mm +++ b/ios/web/web_state/web_state_unittest.mm
@@ -344,6 +344,18 @@ // LoadIfNecessary call. Fix the bug and remove extra call. navigation_manager->LoadIfNecessary(); + if (web::GetWebClient()->IsSlimNavigationManagerEnabled()) { + // After restoration is started GetPendingItemIndex() will return -1 and + // GetPendingItem() will return null. Pending item will be returned after + // the first post-restore navigation is started, but before session + // restoration is complete. Session restoration will be completed when the + // fist post-restore navigation is finished. This is why it is not possible + // to assert that pending item does not exist during the session + // restoration. + EXPECT_EQ(-1, navigation_manager->GetPendingItemIndex()); + EXPECT_FALSE(navigation_manager->GetPendingItem()); + } + // Verify that session was fully restored. int kExpectedItemCount = web::GetWebClient()->IsSlimNavigationManagerEnabled() ? wk_navigation_util::kMaxSessionSize @@ -358,11 +370,25 @@ EXPECT_FALSE(navigation_manager->CanGoForward()); EXPECT_TRUE(navigation_manager->GetBackwardItems().empty()); EXPECT_TRUE(navigation_manager->GetForwardItems().empty()); - DCHECK_EQ(0.0, web_state_ptr->GetLoadingProgress()); - // TODO(crbug.com/877671): Ensure that the following API work correctly: - // - NavigationManager::GetPendingItem - // - NavigationManager::GetPendingItemIndex + EXPECT_EQ("Test0", base::UTF16ToASCII(web_state_ptr->GetTitle())); + EXPECT_EQ(0.0, web_state_ptr->GetLoadingProgress()); + NavigationItem* pendig_item = navigation_manager->GetPendingItem(); + if (pendig_item) { + // Pending item is non-null after the first post-restore navigation is + // started (when happens before session restoration is complete). But + // pending item should never be an internal placeholder or session + // restoration URL. + EXPECT_FALSE(IsWKInternalUrl(pendig_item->GetURL())); + } } else { + if (web::GetWebClient()->IsSlimNavigationManagerEnabled()) { + EXPECT_EQ("www.0.com", base::UTF16ToASCII(web_state_ptr->GetTitle())); + } else { + // This page never loads and does not actually have a title, so + // returning cached title is a bug. However there is not much value in + // fixing this bug for legacy navigation manager. + EXPECT_EQ("Test0", base::UTF16ToASCII(web_state_ptr->GetTitle())); + } EXPECT_EQ("http://www.0.com/", web_state_ptr->GetLastCommittedURL()); NavigationItem* last_committed_item = navigation_manager->GetLastCommittedItem(); @@ -374,8 +400,6 @@ EXPECT_EQ(std::max(navigation_manager->GetItemCount() - 1, 0), static_cast<int>(navigation_manager->GetForwardItems().size())); } - // TODO(crbug.com/877671): Ensure that the following API work correctly: - // - WebState::GetTitle EXPECT_FALSE(web_state_ptr->IsCrashed()); EXPECT_FALSE(web_state_ptr->IsEvicted()); EXPECT_EQ("http://www.0.com/", web_state_ptr->GetVisibleURL());
diff --git a/ios/web_view/internal/autofill/cwv_autofill_client_ios_bridge.h b/ios/web_view/internal/autofill/cwv_autofill_client_ios_bridge.h index ca139131..fb60015 100644 --- a/ios/web_view/internal/autofill/cwv_autofill_client_ios_bridge.h +++ b/ios/web_view/internal/autofill/cwv_autofill_client_ios_bridge.h
@@ -22,7 +22,8 @@ // Bridge for AutofillClient's method |ConfirmSaveCreditCardLocally|. - (void)confirmSaveCreditCardLocally:(const autofill::CreditCard&)creditCard - callback:(base::OnceClosure)callback; + callback:(autofill::AutofillClient:: + LocalSaveCardPromptCallback)callback; // Bridge for AutofillClient's method |ShowUnmaskPrompt|. - (void)
diff --git a/ios/web_view/internal/autofill/cwv_autofill_controller.mm b/ios/web_view/internal/autofill/cwv_autofill_controller.mm index bae4990..138a343a 100644 --- a/ios/web_view/internal/autofill/cwv_autofill_controller.mm +++ b/ios/web_view/internal/autofill/cwv_autofill_controller.mm
@@ -414,18 +414,22 @@ } - (void)confirmSaveCreditCardLocally:(const autofill::CreditCard&)creditCard - callback:(base::OnceClosure)callback { + callback:(autofill::AutofillClient:: + LocalSaveCardPromptCallback)callback { if ([_delegate respondsToSelector:@selector (autofillController:decidePolicyForLocalStorageOfCreditCard :decisionHandler:)]) { CWVCreditCard* card = [[CWVCreditCard alloc] initWithCreditCard:creditCard]; - __block base::OnceClosure scopedCallback = std::move(callback); + __block autofill::AutofillClient::LocalSaveCardPromptCallback + scopedCallback = std::move(callback); [_delegate autofillController:self decidePolicyForLocalStorageOfCreditCard:card decisionHandler:^(CWVStoragePolicy policy) { if (policy == CWVStoragePolicyAllow) { if (scopedCallback) - std::move(scopedCallback).Run(); + std::move(scopedCallback) + .Run(autofill::AutofillClient:: + ACCEPTED); } }]; }
diff --git a/ios/web_view/internal/autofill/cwv_autofill_suggestion.mm b/ios/web_view/internal/autofill/cwv_autofill_suggestion.mm index 65d79f1..bb42904 100644 --- a/ios/web_view/internal/autofill/cwv_autofill_suggestion.mm +++ b/ios/web_view/internal/autofill/cwv_autofill_suggestion.mm
@@ -64,6 +64,10 @@ return _isPasswordSuggestion; } +- (NSInteger)uniqueIdentifier { + return _formSuggestion.identifier; +} + #pragma mark - NSObject - (NSString*)debugDescription {
diff --git a/ios/web_view/internal/autofill/cwv_autofill_suggestion_unittest.mm b/ios/web_view/internal/autofill/cwv_autofill_suggestion_unittest.mm index d6969f5..eb9e0424 100644 --- a/ios/web_view/internal/autofill/cwv_autofill_suggestion_unittest.mm +++ b/ios/web_view/internal/autofill/cwv_autofill_suggestion_unittest.mm
@@ -28,7 +28,7 @@ [FormSuggestion suggestionWithValue:@"TestValue" displayDescription:@"TestDisplayDescription" icon:@"TestIcon" - identifier:0]; + identifier:1337]; CWVAutofillSuggestion* suggestion = [[CWVAutofillSuggestion alloc] initWithFormSuggestion:formSuggestion formName:formName @@ -40,6 +40,7 @@ EXPECT_NSEQ(frameID, suggestion.frameID); EXPECT_NSEQ(formSuggestion.displayDescription, suggestion.displayDescription); EXPECT_NSEQ(formSuggestion.value, suggestion.value); + EXPECT_EQ(1337, suggestion.uniqueIdentifier); EXPECT_EQ(formSuggestion, suggestion.formSuggestion); EXPECT_FALSE([suggestion isPasswordSuggestion]); }
diff --git a/ios/web_view/internal/autofill/web_view_autofill_client_ios.h b/ios/web_view/internal/autofill/web_view_autofill_client_ios.h index 7e02fcb..e9b93f8d 100644 --- a/ios/web_view/internal/autofill/web_view_autofill_client_ios.h +++ b/ios/web_view/internal/autofill/web_view_autofill_client_ios.h
@@ -67,16 +67,17 @@ MigrationDeleteCardCallback delete_local_card_callback) override; void ConfirmSaveAutofillProfile(const AutofillProfile& profile, base::OnceClosure callback) override; - void ConfirmSaveCreditCardLocally(const CreditCard& card, - bool show_prompt, - base::OnceClosure callback) override; + void ConfirmSaveCreditCardLocally( + const CreditCard& card, + bool show_prompt, + LocalSaveCardPromptCallback callback) override; void ConfirmSaveCreditCardToCloud( const CreditCard& card, std::unique_ptr<base::DictionaryValue> legal_message, bool should_request_name_from_user, bool should_request_expiration_date_from_user, bool show_prompt, - UserAcceptedUploadCallback callback) override; + UploadSaveCardPromptCallback callback) override; void ConfirmCreditCardFillAssist(const CreditCard& card, base::OnceClosure callback) override; bool HasCreditCardScanFeature() override;
diff --git a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm index 0da2fcbc..ef36c05 100644 --- a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm +++ b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
@@ -159,7 +159,7 @@ void WebViewAutofillClientIOS::ConfirmSaveCreditCardLocally( const CreditCard& card, bool show_prompt, - base::OnceClosure callback) { + LocalSaveCardPromptCallback callback) { DCHECK(show_prompt); [bridge_ confirmSaveCreditCardLocally:card callback:std::move(callback)]; } @@ -170,7 +170,7 @@ bool should_request_name_from_user, bool should_request_expiration_date_from_user, bool show_prompt, - UserAcceptedUploadCallback callback) { + UploadSaveCardPromptCallback callback) { DCHECK(show_prompt); }
diff --git a/ios/web_view/internal/passwords/OWNERS b/ios/web_view/internal/passwords/OWNERS new file mode 100644 index 0000000..ed365631 --- /dev/null +++ b/ios/web_view/internal/passwords/OWNERS
@@ -0,0 +1,10 @@ +ichikawa@chromium.org +jzw@chromium.org + +# These are for the common case of adding or renaming files. If you're doing +# structural changes, please get a review from an OWNER. +per-file BUILD.gn=* + +# COMPONENT: Mobile>iOSWebView +# TEAM: ios-directory-owners@chromium.org +# OS: iOS
diff --git a/ios/web_view/internal/passwords/cwv_password_controller.mm b/ios/web_view/internal/passwords/cwv_password_controller.mm index 6f3697c..62a88d9 100644 --- a/ios/web_view/internal/passwords/cwv_password_controller.mm +++ b/ios/web_view/internal/passwords/cwv_password_controller.mm
@@ -160,7 +160,7 @@ // Notify the password manager that the page loaded so it can clear its own // per-page state. - _passwordManager->DidNavigateMainFrame(); + _passwordManager->DidNavigateMainFrame(/*form_may_be_submitted=*/false); if (!webState->ContentIsHTML()) { // If the current page is not HTML, it does not contain any HTML forms.
diff --git a/ios/web_view/public/cwv_autofill_suggestion.h b/ios/web_view/public/cwv_autofill_suggestion.h index e8c6d35..df91a47 100644 --- a/ios/web_view/public/cwv_autofill_suggestion.h +++ b/ios/web_view/public/cwv_autofill_suggestion.h
@@ -60,6 +60,9 @@ // credit card network icon. @property(nonatomic, readonly, nullable) UIImage* icon; +// The unique identifier associated with the suggestion. +@property(nonatomic, readonly) NSInteger uniqueIdentifier; + - (instancetype)init NS_UNAVAILABLE; // YES if this is a password autofill suggestion.
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn index b089236..3b4709240 100644 --- a/media/audio/BUILD.gn +++ b/media/audio/BUILD.gn
@@ -117,6 +117,8 @@ "audio_system_impl.cc", "audio_system_impl.h", "audio_thread.h", + "audio_thread_hang_monitor.cc", + "audio_thread_hang_monitor.h", "audio_thread_impl.cc", "audio_thread_impl.h", "clockless_audio_sink.cc", @@ -374,6 +376,7 @@ "audio_power_monitor_unittest.cc", "audio_sync_reader_unittest.cc", "audio_system_impl_unittest.cc", + "audio_thread_hang_monitor_unittest.cc", "power_observer_helper_unittest.cc", "simple_sources_unittest.cc", "virtual_audio_input_stream_unittest.cc",
diff --git a/media/audio/audio_features.cc b/media/audio/audio_features.cc index dc57b3af..32b8ba82 100644 --- a/media/audio/audio_features.cc +++ b/media/audio/audio_features.cc
@@ -6,6 +6,11 @@ namespace features { +// If enabled, base::DumpWithoutCrashing is called whenever an audio service +// hang is detected. +const base::Feature kDumpOnAudioServiceHang{"DumpOnAudioServiceHang", + base::FEATURE_ENABLED_BY_DEFAULT}; + #if defined(OS_CHROMEOS) // Allows experimentally enables mediaDevices.enumerateDevices() on ChromeOS. // Default disabled (crbug.com/554168). @@ -23,4 +28,9 @@ "IncreaseInputAudioBufferSize", base::FEATURE_ENABLED_BY_DEFAULT}; #endif +#if defined(OS_MACOSX) || defined(OS_CHROMEOS) +const base::Feature kForceEnableSystemAec{"ForceEnableSystemAec", + base::FEATURE_DISABLED_BY_DEFAULT}; +#endif + } // namespace features
diff --git a/media/audio/audio_features.h b/media/audio/audio_features.h index 1afbaea..614edd51 100644 --- a/media/audio/audio_features.h +++ b/media/audio/audio_features.h
@@ -11,6 +11,8 @@ namespace features { +MEDIA_EXPORT extern const base::Feature kDumpOnAudioServiceHang; + #if defined(OS_CHROMEOS) MEDIA_EXPORT extern const base::Feature kEnumerateAudioDevices; MEDIA_EXPORT extern const base::Feature kCrOSSystemAEC; @@ -21,6 +23,10 @@ MEDIA_EXPORT extern const base::Feature kIncreaseInputAudioBufferSize; #endif +#if defined(OS_MACOSX) || defined(OS_CHROMEOS) +MEDIA_EXPORT extern const base::Feature kForceEnableSystemAec; +#endif + } // namespace features #endif // MEDIA_AUDIO_AUDIO_FEATURES_H_
diff --git a/media/audio/audio_manager.cc b/media/audio/audio_manager.cc index b82cf28..737933721 100644 --- a/media/audio/audio_manager.cc +++ b/media/audio/audio_manager.cc
@@ -32,58 +32,11 @@ // The singleton instance of AudioManager. This is set when Create() is called. AudioManager* g_last_created = nullptr; -// Maximum number of failed pings to the audio thread allowed. A UMA will be -// recorded once this count is reached; if enabled, a non-crash dump will be -// captured as well. We require at least three failed pings before recording to -// ensure unobservable power events aren't mistakenly caught (e.g., the system -// suspends before a OnSuspend() event can be fired). -const int kMaxFailedPingsCount = 3; - -// Helper class for managing global AudioManager data and hang monitor. If the -// audio thread is hung for > |kMaxFailedPingsCount| * |max_hung_task_time_|, we -// want to record a UMA and optionally a non-crash dump to find offenders in the -// field. -class AudioManagerHelper : public base::PowerObserver { +// Helper class for managing global AudioManager data. +class AudioManagerHelper { public: - // These values are histogrammed over time; do not change their ordinal - // values. - enum ThreadStatus { - THREAD_NONE = 0, - THREAD_STARTED, - THREAD_HUNG, - THREAD_RECOVERED, - THREAD_MAX = THREAD_RECOVERED - }; - AudioManagerHelper() = default; - ~AudioManagerHelper() override = default; - - void StartHangTimer( - scoped_refptr<base::SingleThreadTaskRunner> monitor_task_runner) { - CHECK(!monitor_task_runner_); - CHECK(!audio_task_runner_); - monitor_task_runner_ = std::move(monitor_task_runner); - audio_task_runner_ = AudioManager::Get()->GetTaskRunner(); - base::PowerMonitor::Get()->AddObserver(this); - - io_task_running_ = audio_task_running_ = true; - audio_task_runner_->PostTask( - FROM_HERE, - base::Bind(&AudioManagerHelper::UpdateLastAudioThreadTimeTick, - base::Unretained(this))); - monitor_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&AudioManagerHelper::RecordAudioThreadStatus, - base::Unretained(this))); - } - - bool IsAudioThreadHung() { - base::AutoLock lock(hang_lock_); - return audio_thread_status_ == THREAD_HUNG; - } - - base::SingleThreadTaskRunner* monitor_task_runner() const { - return monitor_task_runner_.get(); - } + ~AudioManagerHelper() = default; AudioLogFactory* fake_log_factory() { return &fake_log_factory_; } @@ -100,134 +53,8 @@ const std::string& app_name() const { return app_name_; } #endif - private: - // base::PowerObserver overrides. - // Disable hang detection when the system goes into the suspend state. - void OnSuspend() override { - base::AutoLock lock(hang_lock_); - hang_detection_enabled_ = false; - failed_pings_ = successful_pings_ = 0; - } - // Reenable hang detection once the system comes out of the suspend state. - void OnResume() override { - base::AutoLock lock(hang_lock_); - hang_detection_enabled_ = true; - last_audio_thread_timer_tick_ = base::TimeTicks::Now(); - failed_pings_ = successful_pings_ = 0; - - // If either of the tasks were stopped during suspend, start them now. - if (!audio_task_running_) { - audio_task_running_ = true; - - base::AutoUnlock unlock(hang_lock_); - audio_task_runner_->PostTask( - FROM_HERE, - base::Bind(&AudioManagerHelper::UpdateLastAudioThreadTimeTick, - base::Unretained(this))); - } - - if (!io_task_running_) { - io_task_running_ = true; - - base::AutoUnlock unlock(hang_lock_); - monitor_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&AudioManagerHelper::RecordAudioThreadStatus, - base::Unretained(this))); - } - } - - // Runs on |monitor_task_runner|. - void RecordAudioThreadStatus() { - DCHECK(monitor_task_runner_->BelongsToCurrentThread()); - { - base::AutoLock lock(hang_lock_); - - // Don't attempt to verify the tick time or post our task if the system is - // in the process of suspending or resuming. - if (!hang_detection_enabled_) { - io_task_running_ = false; - return; - } - - DCHECK(io_task_running_); - const base::TimeTicks now = base::TimeTicks::Now(); - const base::TimeDelta tick_delta = now - last_audio_thread_timer_tick_; - if (tick_delta > max_hung_task_time_) { - successful_pings_ = 0; - if (++failed_pings_ >= kMaxFailedPingsCount && - audio_thread_status_ < THREAD_HUNG) { - HistogramThreadStatus(THREAD_HUNG); - } - } else { - failed_pings_ = 0; - ++successful_pings_; - if (audio_thread_status_ == THREAD_NONE) { - HistogramThreadStatus(THREAD_STARTED); - } else if (audio_thread_status_ == THREAD_HUNG && - successful_pings_ >= kMaxFailedPingsCount) { - // Require just as many successful pings to recover from failure. - HistogramThreadStatus(THREAD_RECOVERED); - } - } - } - - // Don't hold the lock while posting the next task. - monitor_task_runner_->PostDelayedTask( - FROM_HERE, - base::BindOnce(&AudioManagerHelper::RecordAudioThreadStatus, - base::Unretained(this)), - max_hung_task_time_); - } - - // Runs on the audio thread. - void UpdateLastAudioThreadTimeTick() { - DCHECK(audio_task_runner_->BelongsToCurrentThread()); - { - base::AutoLock lock(hang_lock_); - last_audio_thread_timer_tick_ = base::TimeTicks::Now(); - failed_pings_ = 0; - - // Don't post our task if the system is or will be suspended. - if (!hang_detection_enabled_) { - audio_task_running_ = false; - return; - } - - DCHECK(audio_task_running_); - } - - // Don't hold the lock while posting the next task. - audio_task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind(&AudioManagerHelper::UpdateLastAudioThreadTimeTick, - base::Unretained(this)), - max_hung_task_time_ / 5); - } - - void HistogramThreadStatus(ThreadStatus status) { - DCHECK(monitor_task_runner_->BelongsToCurrentThread()); - hang_lock_.AssertAcquired(); - audio_thread_status_ = status; - UMA_HISTOGRAM_ENUMERATION("Media.AudioThreadStatus", audio_thread_status_, - THREAD_MAX + 1); - } - FakeAudioLogFactory fake_log_factory_; - const base::TimeDelta max_hung_task_time_ = base::TimeDelta::FromMinutes(1); - scoped_refptr<base::SingleThreadTaskRunner> monitor_task_runner_; - scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner_; - - base::Lock hang_lock_; - bool hang_detection_enabled_ GUARDED_BY(hang_lock_) = true; - base::TimeTicks last_audio_thread_timer_tick_ GUARDED_BY(hang_lock_); - uint32_t failed_pings_ = 0; - bool io_task_running_ = false; - bool audio_task_running_ = false; - ThreadStatus audio_thread_status_ = THREAD_NONE; - uint32_t successful_pings_ = 0; - #if defined(OS_WIN) std::unique_ptr<base::win::ScopedCOMInitializer> com_initializer_for_testing_; #endif @@ -301,19 +128,6 @@ return Create(std::move(audio_thread), GetHelper()->fake_log_factory()); } -// static -void AudioManager::StartHangMonitorIfNeeded( - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - if (GetHelper()->monitor_task_runner()) - return; - - DCHECK(AudioManager::Get()); - DCHECK(task_runner); - DCHECK_NE(task_runner, AudioManager::Get()->GetTaskRunner()); - - GetHelper()->StartHangTimer(std::move(task_runner)); -} - #if defined(OS_LINUX) // static void AudioManager::SetGlobalAppName(const std::string& app_name) { @@ -337,10 +151,9 @@ // Do not attempt to stop the audio thread if it is hung. // Otherwise the current thread will hang too: crbug.com/729494 // TODO(olka, grunell): Will be fixed when audio is its own process. - if (GetHelper()->IsAudioThreadHung()) + if (audio_thread_->IsHung()) return false; - // TODO(alokp): Suspend hang monitor. if (audio_thread_->GetTaskRunner()->BelongsToCurrentThread()) { ShutdownOnAudioThread(); } else {
diff --git a/media/audio/audio_manager.h b/media/audio/audio_manager.h index 6376261..45e48d2 100644 --- a/media/audio/audio_manager.h +++ b/media/audio/audio_manager.h
@@ -34,9 +34,6 @@ // Manages all audio resources. Provides some convenience functions that avoid // the need to provide iterators over the existing streams. -// -// Except on OSX, a hang monitor for the audio thread is always created. When a -// thread hang is detected, it is reported to UMA. class MEDIA_EXPORT AudioManager { public: virtual ~AudioManager(); @@ -63,13 +60,6 @@ static std::unique_ptr<AudioManager> CreateForTesting( std::unique_ptr<AudioThread> audio_thread); - // Starts monitoring AudioManager task runner for hangs. - // Runs the monitor on the given |task_runner|, which must be different from - // AudioManager::GetTaskRunner to be meaningful. - // This must be called only after an AudioManager instance is created. - static void StartHangMonitorIfNeeded( - scoped_refptr<base::SingleThreadTaskRunner> task_runner); - #if defined(OS_LINUX) // Sets the name of the audio source as seen by external apps. Only actually // used with PulseAudio as of this writing.
diff --git a/media/audio/audio_thread.h b/media/audio/audio_thread.h index 52352106..b014b89 100644 --- a/media/audio/audio_thread.h +++ b/media/audio/audio_thread.h
@@ -22,6 +22,10 @@ // Synchronously stops all underlying threads. virtual void Stop() = 0; + // Indicates whether the audio thread is responsive. If false, calling Stop() + // will likely block forever. + virtual bool IsHung() const = 0; + // Returns the task runner used for audio IO. // It always returns a non-null task runner (even after Stop has been called). virtual base::SingleThreadTaskRunner* GetTaskRunner() = 0;
diff --git a/media/audio/audio_thread_hang_monitor.cc b/media/audio/audio_thread_hang_monitor.cc new file mode 100644 index 0000000..fdff50c --- /dev/null +++ b/media/audio/audio_thread_hang_monitor.cc
@@ -0,0 +1,177 @@ +// 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 "media/audio/audio_thread_hang_monitor.h" + +#include <algorithm> +#include <utility> + +#include "base/bind.h" +#include "base/debug/alias.h" +#include "base/debug/dump_without_crashing.h" +#include "base/location.h" +#include "base/metrics/histogram_macros.h" +#include "base/power_monitor/power_monitor.h" +#include "base/single_thread_task_runner.h" +#include "base/task/post_task.h" +#include "base/task/task_traits.h" +#include "base/threading/thread_checker.h" +#include "base/time/tick_clock.h" + +namespace media { + +namespace { + +// Maximum number of failed pings to the audio thread allowed. A UMA will be +// recorded once this count is reached. We require at least three failed pings +// before recording to ensure unobservable power events aren't mistakenly +// caught (e.g., the system suspends before a OnSuspend() event can be fired). +constexpr int kMaxFailedPingsCount = 3; + +constexpr base::TimeDelta kHungDeadline = base::TimeDelta::FromMinutes(1); + +} // namespace + +AudioThreadHangMonitor::SharedAtomicFlag::SharedAtomicFlag() {} +AudioThreadHangMonitor::SharedAtomicFlag::~SharedAtomicFlag() {} + +// static +AudioThreadHangMonitor::Ptr AudioThreadHangMonitor::Create( + bool dump_on_hang, + const base::TickClock* clock, + scoped_refptr<base::SingleThreadTaskRunner> audio_thread_task_runner, + scoped_refptr<base::SequencedTaskRunner> monitor_task_runner) { + if (!monitor_task_runner) + monitor_task_runner = base::CreateSequencedTaskRunnerWithTraits({}); + + auto monitor = + Ptr(new AudioThreadHangMonitor(dump_on_hang, clock, + std::move(audio_thread_task_runner)), + base::OnTaskRunnerDeleter(monitor_task_runner)); + + // |monitor| is destroyed on |monitor_task_runner|, so Unretained is safe. + monitor_task_runner->PostTask( + FROM_HERE, base::BindOnce(&AudioThreadHangMonitor::StartTimer, + base::Unretained(monitor.get()))); + return monitor; +} + +AudioThreadHangMonitor::~AudioThreadHangMonitor() { + DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_); +} + +bool AudioThreadHangMonitor::IsAudioThreadHung() const { + return audio_thread_status_ == ThreadStatus::kHung; +} + +AudioThreadHangMonitor::AudioThreadHangMonitor( + bool dump_on_hang, + const base::TickClock* clock, + scoped_refptr<base::SingleThreadTaskRunner> audio_thread_task_runner) + : clock_(clock), + alive_flag_(base::MakeRefCounted<SharedAtomicFlag>()), + audio_task_runner_(std::move(audio_thread_task_runner)), + dump_on_hang_(dump_on_hang), + timer_(clock_) { + DETACH_FROM_SEQUENCE(monitor_sequence_); +} + +void AudioThreadHangMonitor::StartTimer() { + DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_); + + auto* pm = base::PowerMonitor::Get(); + if (pm) { + // May be null in unit tests. + pm->AddObserver(this); + } + + // Set the flag to true so that the first run doesn't detect a hang. + alive_flag_->flag_ = true; + + last_check_time_ = clock_->NowTicks(); + + LogHistogramThreadStatus(); + + // |this| owns |timer_|, so Unretained is safe. + timer_.Start( + FROM_HERE, kHungDeadline, + base::BindRepeating(&AudioThreadHangMonitor::CheckIfAudioThreadIsAlive, + base::Unretained(this))); +} + +bool AudioThreadHangMonitor::NeverLoggedThreadHung() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_); + return audio_thread_status_ == ThreadStatus::kStarted; +} + +bool AudioThreadHangMonitor::NeverLoggedThreadRecoveredAfterHung() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_); + return audio_thread_status_ == ThreadStatus::kHung; +} + +void AudioThreadHangMonitor::OnResume() { + DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_); + last_resume_time_ = clock_->NowTicks(); + recent_ping_state_ = 0; +} + +void AudioThreadHangMonitor::CheckIfAudioThreadIsAlive() { + DCHECK_CALLED_ON_VALID_SEQUENCE(monitor_sequence_); + + const base::TimeDelta time_since_last_check = + clock_->NowTicks() - last_check_time_; + + // An unexpected |time_since_last_check| may indicate that the system has been + // in sleep mode, in which case the audio thread may have had insufficient + // time to respond to the ping. In such a case, skip the check for now. + if (time_since_last_check > kHungDeadline + base::TimeDelta::FromSeconds(1)) + return; + + const bool audio_thread_responded_to_last_ping = alive_flag_->flag_; + if (audio_thread_responded_to_last_ping) { + recent_ping_state_ = std::max(recent_ping_state_, 0) + 1; + + // Update the thread status if it was previously hung. Will only log + // "recovered" once for the lifetime of this object. + if (NeverLoggedThreadRecoveredAfterHung() && + recent_ping_state_ >= kMaxFailedPingsCount) { + // Require just as many successful pings to recover from failure. + audio_thread_status_ = ThreadStatus::kRecovered; + LogHistogramThreadStatus(); + } + } else { + recent_ping_state_ = std::min(recent_ping_state_, 0) - 1; + + // Update the thread status if it was previously live and has never been + // considered hung before. Will only log "hung" once for the lifetime of + // this object. + if (-recent_ping_state_ >= kMaxFailedPingsCount && + NeverLoggedThreadHung()) { + audio_thread_status_ = ThreadStatus::kHung; + LogHistogramThreadStatus(); + + if (dump_on_hang_) { + int64_t time_since_resume = + (clock_->NowTicks() - last_resume_time_).InMilliseconds(); + base::debug::Alias(&time_since_resume); + base::debug::DumpWithoutCrashing(); + } + } + } + + alive_flag_->flag_ = false; + last_check_time_ = clock_->NowTicks(); + audio_task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + [](scoped_refptr<SharedAtomicFlag> flag) { flag->flag_ = true; }, + alive_flag_)); +} + +void AudioThreadHangMonitor::LogHistogramThreadStatus() { + UMA_HISTOGRAM_ENUMERATION("Media.AudioThreadStatus", + audio_thread_status_.load()); +} + +} // namespace media
diff --git a/media/audio/audio_thread_hang_monitor.h b/media/audio/audio_thread_hang_monitor.h new file mode 100644 index 0000000..e4ab0a66 --- /dev/null +++ b/media/audio/audio_thread_hang_monitor.h
@@ -0,0 +1,143 @@ +// 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 MEDIA_AUDIO_AUDIO_THREAD_HANG_MONITOR_H_ +#define MEDIA_AUDIO_AUDIO_THREAD_HANG_MONITOR_H_ + +#include "media/audio/audio_manager.h" + +#include <atomic> +#include <memory> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" +#include "base/power_monitor/power_observer.h" +#include "base/sequence_checker.h" +#include "base/sequenced_task_runner.h" +#include "base/time/time.h" +#include "base/timer/timer.h" +#include "media/base/media_export.h" +#include "media/base/media_switches.h" + +namespace base { +class TickClock; +class SingleThreadTaskRunner; +} // namespace base + +namespace media { + +// This class detects if the audio manager thread is hung. It logs a histogram, +// and can optionally (if |dump_on_hang| is set) upload a crash dump when a hang +// is detected. It runs on a task runner from the task scheduler. It works by +// posting a task to the audio thread every minute and checking that it was +// executed. If three consecutive such pings are missed, the thread is +// considered hung. +class MEDIA_EXPORT AudioThreadHangMonitor final : public base::PowerObserver { + public: + using Ptr = + std::unique_ptr<AudioThreadHangMonitor, base::OnTaskRunnerDeleter>; + + // These values are histogrammed over time; do not change their ordinal + // values. + enum class ThreadStatus { + // kNone = 0, obsolete. + kStarted = 1, + kHung, + kRecovered, + kMaxValue = kRecovered + }; + + // |monitor_task_runner| may be set explicitly by tests only. Other callers + // should use the default. + static Ptr Create( + bool dump_on_hang, + const base::TickClock* clock, + scoped_refptr<base::SingleThreadTaskRunner> audio_thread_task_runner, + scoped_refptr<base::SequencedTaskRunner> monitor_task_runner = nullptr); + + ~AudioThreadHangMonitor() final; + + // Thread-safe. + bool IsAudioThreadHung() const; + + private: + class SharedAtomicFlag final + : public base::RefCountedThreadSafe<SharedAtomicFlag> { + public: + SharedAtomicFlag(); + + std::atomic_bool flag_ = {false}; + + private: + friend class base::RefCountedThreadSafe<SharedAtomicFlag>; + ~SharedAtomicFlag(); + }; + + AudioThreadHangMonitor( + bool dump_on_hang, + const base::TickClock* clock, + scoped_refptr<base::SingleThreadTaskRunner> audio_thread_task_runner); + + void StartTimer(); + + bool NeverLoggedThreadHung() const; + bool NeverLoggedThreadRecoveredAfterHung() const; + + // base::PowerObserver overrides. + // Reset hang detection state when the system comes out of the suspend state. + void OnResume() final; + + // This function is run by the |timer_|. It checks if the audio thread has + // shown signs of life since the last time it was called (by checking the + // |alive_flag_|) and updates the value of |successful_pings_| and + // |failed_pings_| as appropriate. It also changes the thread status and logs + // its value to a histogram. + void CheckIfAudioThreadIsAlive(); + + // LogHistogramThreadStatus logs |thread_status_| to a histogram. + void LogHistogramThreadStatus(); + + const base::TickClock* const clock_; + + // This flag is set to false on the monitor sequence and then set to true on + // the audio thread to indicate that the audio thread is alive. + const scoped_refptr<SharedAtomicFlag> alive_flag_; + + // |audio_task_runner_| is the task runner of the audio thread. + const scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner_; + + // If |dump_on_hang_| is set, a crash dump will be collected the first time + // the thread is detected as hung (note that no actual crashing is involved). + const bool dump_on_hang_; + + std::atomic<ThreadStatus> audio_thread_status_ = {ThreadStatus::kStarted}; + + // All fields below are accessed on |monitor_sequence|. + SEQUENCE_CHECKER(monitor_sequence_); + + // Timer to check |alive_flag_| regularly. + base::RepeatingTimer timer_; + + // This variable is used to check to detect suspend/resume cycles. + // If a long time has passed since the timer was last fired, it is likely due + // to the machine being suspended. In such a case, we want to avoid falsely + // detecting the audio thread as hung. + base::TimeTicks last_check_time_ = base::TimeTicks(); + + // Used to investigate hangs. + base::TimeTicks last_resume_time_ = base::TimeTicks(); + + // |recent_ping_state_| tracks the recent life signs from the audio thread. If + // the most recent ping was successful, the number indicates the number of + // successive successful pings. If the most recent ping was failed, the number + // is the negative of the number of successive failed pings. + int recent_ping_state_ = 0; + + DISALLOW_COPY_AND_ASSIGN(AudioThreadHangMonitor); +}; + +} // namespace media + +#endif // MEDIA_AUDIO_AUDIO_THREAD_HANG_MONITOR_H_
diff --git a/media/audio/audio_thread_hang_monitor_unittest.cc b/media/audio/audio_thread_hang_monitor_unittest.cc new file mode 100644 index 0000000..c90d4f6 --- /dev/null +++ b/media/audio/audio_thread_hang_monitor_unittest.cc
@@ -0,0 +1,132 @@ +// 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 "media/audio/audio_thread_hang_monitor.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/synchronization/waitable_event.h" +#include "base/task/post_task.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_task_environment.h" +#include "base/threading/thread.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::ElementsAre; +using testing::Test; + +namespace media { + +namespace { + +constexpr int kStarted = + static_cast<int>(AudioThreadHangMonitor::ThreadStatus::kStarted); +constexpr int kHung = + static_cast<int>(AudioThreadHangMonitor::ThreadStatus::kHung); +constexpr int kRecovered = + static_cast<int>(AudioThreadHangMonitor::ThreadStatus::kRecovered); + +} // namespace + +class AudioThreadHangMonitorTest : public Test { + public: + AudioThreadHangMonitorTest() + : task_env_(base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME), + histograms_(), + audio_thread_("Audio thread"), + hang_monitor_({nullptr, base::OnTaskRunnerDeleter(nullptr)}) { + CHECK(audio_thread_.Start()); + // We must inject the main thread task runner as the hang monitor task + // runner since ScopedTaskEnvironment::FastForwardBy only works for the main + // thread. + hang_monitor_ = AudioThreadHangMonitor::Create( + false, task_env_.GetMockTickClock(), audio_thread_.task_runner(), + task_env_.GetMainThreadTaskRunner()); + } + + ~AudioThreadHangMonitorTest() override { + hang_monitor_.reset(); + task_env_.RunUntilIdle(); + } + + void RunUntilIdle() { task_env_.RunUntilIdle(); } + + void FlushAudioThread() { + base::WaitableEvent ev; + audio_thread_.task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&ev))); + ev.Wait(); + } + + void BlockAudioThreadUntilEvent() { + // We keep |event_| as a member of the test fixture to make sure that the + // audio thread terminates before |event_| is destructed. + event_.Reset(); + audio_thread_.task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&base::WaitableEvent::Wait, base::Unretained(&event_))); + } + + base::WaitableEvent event_; + base::test::ScopedTaskEnvironment task_env_; + base::HistogramTester histograms_; + base::Thread audio_thread_; + AudioThreadHangMonitor::Ptr hang_monitor_; +}; + +TEST_F(AudioThreadHangMonitorTest, LogsThreadStarted) { + RunUntilIdle(); + + EXPECT_THAT(histograms_.GetAllSamples("Media.AudioThreadStatus"), + ElementsAre(base::Bucket(kStarted, 1))); +} + +TEST_F(AudioThreadHangMonitorTest, DoesNotLogThreadHungWhenOk) { + RunUntilIdle(); + + for (int i = 0; i < 10; ++i) { + // Flush the audio thread, then advance the clock. The audio thread should + // register as "alive" every time. + FlushAudioThread(); + task_env_.FastForwardBy(base::TimeDelta::FromMinutes(1)); + } + + EXPECT_THAT(histograms_.GetAllSamples("Media.AudioThreadStatus"), + ElementsAre(base::Bucket(kStarted, 1))); +} + +TEST_F(AudioThreadHangMonitorTest, LogsHungWhenAudioThreadIsBlocked) { + RunUntilIdle(); + + BlockAudioThreadUntilEvent(); + task_env_.FastForwardBy(base::TimeDelta::FromMinutes(10)); + event_.Signal(); + + EXPECT_THAT(histograms_.GetAllSamples("Media.AudioThreadStatus"), + ElementsAre(base::Bucket(kStarted, 1), base::Bucket(kHung, 1))); +} + +TEST_F(AudioThreadHangMonitorTest, + LogsRecoveredWhenAudioThreadIsBlockedThenRecovers) { + RunUntilIdle(); + + BlockAudioThreadUntilEvent(); + task_env_.FastForwardBy(base::TimeDelta::FromMinutes(10)); + event_.Signal(); + + for (int i = 0; i < 10; ++i) { + // Flush the audio thread, then advance the clock. The audio thread should + // register as "alive" every time. + FlushAudioThread(); + task_env_.FastForwardBy(base::TimeDelta::FromMinutes(1)); + } + + EXPECT_THAT(histograms_.GetAllSamples("Media.AudioThreadStatus"), + ElementsAre(base::Bucket(kStarted, 1), base::Bucket(kHung, 1), + base::Bucket(kRecovered, 1))); +} + +} // namespace media
diff --git a/media/audio/audio_thread_impl.cc b/media/audio/audio_thread_impl.cc index 96109ef..87a2eab 100644 --- a/media/audio/audio_thread_impl.cc +++ b/media/audio/audio_thread_impl.cc
@@ -5,11 +5,15 @@ #include "media/audio/audio_thread_impl.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/default_tick_clock.h" #include "build/build_config.h" +#include "media/audio/audio_thread_hang_monitor.h" namespace media { -AudioThreadImpl::AudioThreadImpl() : thread_("AudioThread") { +AudioThreadImpl::AudioThreadImpl() + : thread_("AudioThread"), + hang_monitor_(nullptr, base::OnTaskRunnerDeleter(nullptr)) { base::Thread::Options thread_options; #if defined(OS_WIN) thread_.init_com_with_mta(true); @@ -27,6 +31,12 @@ task_runner_ = thread_.task_runner(); #endif worker_task_runner_ = thread_.task_runner(); + +#if !defined(OS_MACOSX) + // Since we run on the main thread on Mac, we don't need a hang monitor. + hang_monitor_ = AudioThreadHangMonitor::Create( + false, base::DefaultTickClock::GetInstance(), task_runner_); +#endif } AudioThreadImpl::~AudioThreadImpl() { @@ -36,12 +46,23 @@ void AudioThreadImpl::Stop() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + hang_monitor_.reset(); + // Note that on MACOSX, we can still have tasks posted on the |task_runner_|, // since it is the main thread task runner and we do not stop the main thread. // But this is fine becuase none of those tasks will actually run. thread_.Stop(); } +bool AudioThreadImpl::IsHung() const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); +#if defined(OS_MACOSX) + return false; +#else + return hang_monitor_->IsAudioThreadHung(); +#endif +} + base::SingleThreadTaskRunner* AudioThreadImpl::GetTaskRunner() { return task_runner_.get(); }
diff --git a/media/audio/audio_thread_impl.h b/media/audio/audio_thread_impl.h index 89a40df..77b0fcd 100644 --- a/media/audio/audio_thread_impl.h +++ b/media/audio/audio_thread_impl.h
@@ -5,31 +5,39 @@ #ifndef MEDIA_AUDIO_AUDIO_THREAD_IMPL_H_ #define MEDIA_AUDIO_AUDIO_THREAD_IMPL_H_ +#include <memory> + +#include "base/sequenced_task_runner.h" #include "base/threading/thread.h" #include "base/threading/thread_checker.h" #include "media/audio/audio_thread.h" +#include "media/audio/audio_thread_hang_monitor.h" namespace media { -class MEDIA_EXPORT AudioThreadImpl : public AudioThread { +class MEDIA_EXPORT AudioThreadImpl final : public AudioThread { public: AudioThreadImpl(); - ~AudioThreadImpl() override; + ~AudioThreadImpl() final; // AudioThread implementation. - void Stop() override; - base::SingleThreadTaskRunner* GetTaskRunner() override; - base::SingleThreadTaskRunner* GetWorkerTaskRunner() override; + void Stop() final; + bool IsHung() const final; + base::SingleThreadTaskRunner* GetTaskRunner() final; + base::SingleThreadTaskRunner* GetWorkerTaskRunner() final; private: base::Thread thread_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner_; + // Null on Mac OS, initialized in the constructor on other platforms. + AudioThreadHangMonitor::Ptr hang_monitor_; + THREAD_CHECKER(thread_checker_); DISALLOW_COPY_AND_ASSIGN(AudioThreadImpl); }; -} // namespace content +} // namespace media #endif // MEDIA_AUDIO_AUDIO_THREAD_IMPL_H_
diff --git a/media/audio/mac/audio_device_listener_mac.cc b/media/audio/mac/audio_device_listener_mac.cc index f36c3eb..30c31f8e 100644 --- a/media/audio/mac/audio_device_listener_mac.cc +++ b/media/audio/mac/audio_device_listener_mac.cc
@@ -12,6 +12,9 @@ #include "base/mac/mac_logging.h" #include "base/optional.h" #include "base/single_thread_task_runner.h" +#include "base/stl_util.h" +#include "base/threading/thread_task_runner_handle.h" +#include "base/time/time.h" #include "media/audio/audio_manager.h" #include "media/audio/mac/core_audio_util_mac.h" #include "media/base/bind_to_current_loop.h" @@ -43,6 +46,8 @@ class AudioDeviceListenerMac::PropertyListener { public: + static constexpr base::TimeDelta kPruneTime = + base::TimeDelta::FromSeconds(15); PropertyListener(AudioObjectID monitored_object, const AudioObjectPropertyAddress* property, base::RepeatingClosure callback) @@ -53,13 +58,28 @@ AudioObjectID monitored_object() const { return monitored_object_; } const base::RepeatingClosure& callback() const { return callback_; } const AudioObjectPropertyAddress* property() const { return address_; } + base::TimeTicks deletion_time() const { return deletion_time_; } + bool IsActive() const { return deletion_time_.is_null(); } + void MarkAsInactive() { deletion_time_ = base::TimeTicks::Now(); } + void MarkAsActive() { deletion_time_ = base::TimeTicks(); } private: AudioObjectID monitored_object_; const AudioObjectPropertyAddress* address_; base::RepeatingClosure callback_; + // Stores a deletion time, used for pruning the listener after it is + // deregistered from the OS. This helps prevent a race between destroying the + // listener after the OS reports the device is removed, and notifications + // about the same device that could originate concurrently on another thread. + // This can for example, when unplugging a device with input and output + // sources, where the noification about source changes might arrive after the + // OS reports the device as removed (and therefore marked as deleted). A null + // |deletion_time_| means the listener has not been marked as deleted. + base::TimeTicks deletion_time_; }; +constexpr base::TimeDelta AudioDeviceListenerMac::PropertyListener::kPruneTime; + // Callback from the system when an event occurs; this must be called on the // MessageLoop that created the AudioManager. // static @@ -168,6 +188,7 @@ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); std::vector<AudioObjectID> device_ids = core_audio_mac::GetAllAudioDeviceIDs(); + bool did_mark_as_deleted = false; for (bool is_input : {true, false}) { for (auto device_id : device_ids) { const AudioObjectPropertyAddress* property_address = @@ -188,15 +209,37 @@ } else { source_listener.reset(); } + } else { + it_key->second->MarkAsActive(); } } else if (is_monitored) { // Stop monitoring if the device has no source but is currently being // monitored. RemovePropertyListener(it_key->second.get()); - source_listeners_.erase(it_key); + it_key->second->MarkAsInactive(); + did_mark_as_deleted = true; } } } + if (did_mark_as_deleted) { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&AudioDeviceListenerMac::PruneDeletedListeners, + weak_factory_.GetWeakPtr()), + 2 * PropertyListener::kPruneTime); + } +} + +void AudioDeviceListenerMac::PruneDeletedListeners() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + base::EraseIf(source_listeners_, [](const auto& elem) { + if (elem.second->IsActive()) + return false; + + base::TimeDelta elapsed = + base::TimeTicks::Now() - elem.second->deletion_time(); + return elapsed >= PropertyListener::kPruneTime; + }); } } // namespace media
diff --git a/media/audio/mac/audio_device_listener_mac.h b/media/audio/mac/audio_device_listener_mac.h index 09c64cf..b881d2e 100644 --- a/media/audio/mac/audio_device_listener_mac.h +++ b/media/audio/mac/audio_device_listener_mac.h
@@ -7,7 +7,6 @@ #include <CoreAudio/AudioHardware.h> -#include <map> #include <memory> #include <utility> @@ -51,6 +50,7 @@ void RemovePropertyListener(PropertyListener* property_listener); void OnDevicesAddedOrRemoved(); void UpdateSourceListeners(); + void PruneDeletedListeners(); base::RepeatingClosure listener_cb_; std::unique_ptr<PropertyListener> default_output_listener_;
diff --git a/media/audio/test_audio_thread.cc b/media/audio/test_audio_thread.cc index aef2ea41..e8c307f 100644 --- a/media/audio/test_audio_thread.cc +++ b/media/audio/test_audio_thread.cc
@@ -36,6 +36,11 @@ base::RunLoop().RunUntilIdle(); } +bool TestAudioThread::IsHung() const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return false; +} + base::SingleThreadTaskRunner* TestAudioThread::GetTaskRunner() { return task_runner_.get(); }
diff --git a/media/audio/test_audio_thread.h b/media/audio/test_audio_thread.h index eff718ec..ddcffb7e 100644 --- a/media/audio/test_audio_thread.h +++ b/media/audio/test_audio_thread.h
@@ -5,6 +5,8 @@ #ifndef MEDIA_AUDIO_TEST_AUDIO_THREAD_H_ #define MEDIA_AUDIO_TEST_AUDIO_THREAD_H_ +#include <memory> + #include "base/memory/ref_counted.h" #include "base/threading/thread.h" #include "base/threading/thread_checker.h" @@ -12,16 +14,17 @@ namespace media { -class TestAudioThread : public AudioThread { +class TestAudioThread final : public AudioThread { public: TestAudioThread(); explicit TestAudioThread(bool use_real_thread); - ~TestAudioThread() override; + ~TestAudioThread() final; // AudioThread implementation. - void Stop() override; - base::SingleThreadTaskRunner* GetTaskRunner() override; - base::SingleThreadTaskRunner* GetWorkerTaskRunner() override; + void Stop() final; + bool IsHung() const final; + base::SingleThreadTaskRunner* GetTaskRunner() final; + base::SingleThreadTaskRunner* GetWorkerTaskRunner() final; private: std::unique_ptr<base::Thread> thread_;
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn index 7afd69d..b10c175 100644 --- a/media/base/BUILD.gn +++ b/media/base/BUILD.gn
@@ -6,8 +6,8 @@ import("//build/config/arm.gni") import("//build/config/features.gni") import("//build/config/jumbo.gni") -import("//build/config/ui.gni") import("//build/config/linux/pkg_config.gni") +import("//build/config/ui.gni") import("//media/media_options.gni") import("//testing/libfuzzer/fuzzer_test.gni") @@ -112,8 +112,6 @@ "data_buffer.h", "data_source.cc", "data_source.h", - "decode_capabilities.cc", - "decode_capabilities.h", "decode_status.cc", "decode_status.h", "decoder_buffer.cc", @@ -182,6 +180,7 @@ "media_track.h", "media_tracks.cc", "media_tracks.h", + "media_types.h", "media_url_demuxer.cc", "media_url_demuxer.h", "media_url_params.h", @@ -239,6 +238,8 @@ "stream_parser_buffer.h", "subsample_entry.cc", "subsample_entry.h", + "supported_types.cc", + "supported_types.h", "text_cue.cc", "text_cue.h", "text_ranges.cc", @@ -484,7 +485,6 @@ "channel_mixing_matrix_unittest.cc", "container_names_unittest.cc", "data_buffer_unittest.cc", - "decode_capabilities_unittest.cc", "decoder_buffer_queue_unittest.cc", "decoder_buffer_unittest.cc", "decrypt_config_unittest.cc", @@ -510,6 +510,7 @@ "sinc_resampler_unittest.cc", "stream_parser_unittest.cc", "subsample_entry_unittest.cc", + "supported_types_unittest.cc", "text_ranges_unittest.cc", "text_renderer_unittest.cc", "time_delta_interpolator_unittest.cc",
diff --git a/media/base/decode_capabilities.cc b/media/base/decode_capabilities.cc deleted file mode 100644 index 9799a04..0000000 --- a/media/base/decode_capabilities.cc +++ /dev/null
@@ -1,193 +0,0 @@ -// Copyright 2017 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 "media/base/decode_capabilities.h" - -#include "base/command_line.h" -#include "base/feature_list.h" -#include "media/base/media_switches.h" -#include "media/media_buildflags.h" -#include "third_party/libaom/av1_buildflags.h" -#include "ui/display/display_switches.h" - -#if BUILDFLAG(ENABLE_LIBVPX) -#include "third_party/libvpx/source/libvpx/vpx/vp8dx.h" -#include "third_party/libvpx/source/libvpx/vpx/vpx_codec.h" -#endif - -namespace media { - -bool IsColorSpaceSupported(const media::VideoColorSpace& color_space) { - switch (color_space.primaries) { - case media::VideoColorSpace::PrimaryID::EBU_3213_E: - case media::VideoColorSpace::PrimaryID::INVALID: - return false; - - // Transfers supported before color management. - case media::VideoColorSpace::PrimaryID::BT709: - case media::VideoColorSpace::PrimaryID::UNSPECIFIED: - case media::VideoColorSpace::PrimaryID::BT470M: - case media::VideoColorSpace::PrimaryID::BT470BG: - case media::VideoColorSpace::PrimaryID::SMPTE170M: - break; - - // Supported with color management. - case media::VideoColorSpace::PrimaryID::SMPTE240M: - case media::VideoColorSpace::PrimaryID::FILM: - case media::VideoColorSpace::PrimaryID::BT2020: - case media::VideoColorSpace::PrimaryID::SMPTEST428_1: - case media::VideoColorSpace::PrimaryID::SMPTEST431_2: - case media::VideoColorSpace::PrimaryID::SMPTEST432_1: - break; - } - - switch (color_space.transfer) { - // Transfers supported before color management. - case media::VideoColorSpace::TransferID::UNSPECIFIED: - case media::VideoColorSpace::TransferID::GAMMA22: - case media::VideoColorSpace::TransferID::BT709: - case media::VideoColorSpace::TransferID::SMPTE170M: - case media::VideoColorSpace::TransferID::BT2020_10: - case media::VideoColorSpace::TransferID::BT2020_12: - case media::VideoColorSpace::TransferID::IEC61966_2_1: - break; - - // Supported with color management. - case media::VideoColorSpace::TransferID::GAMMA28: - case media::VideoColorSpace::TransferID::SMPTE240M: - case media::VideoColorSpace::TransferID::LINEAR: - case media::VideoColorSpace::TransferID::LOG: - case media::VideoColorSpace::TransferID::LOG_SQRT: - case media::VideoColorSpace::TransferID::BT1361_ECG: - case media::VideoColorSpace::TransferID::SMPTEST2084: - case media::VideoColorSpace::TransferID::IEC61966_2_4: - case media::VideoColorSpace::TransferID::SMPTEST428_1: - case media::VideoColorSpace::TransferID::ARIB_STD_B67: - break; - - // Never supported. - case media::VideoColorSpace::TransferID::INVALID: - return false; - } - - switch (color_space.matrix) { - // Supported before color management. - case media::VideoColorSpace::MatrixID::BT709: - case media::VideoColorSpace::MatrixID::UNSPECIFIED: - case media::VideoColorSpace::MatrixID::BT470BG: - case media::VideoColorSpace::MatrixID::SMPTE170M: - case media::VideoColorSpace::MatrixID::BT2020_NCL: - break; - - // Supported with color management. - case media::VideoColorSpace::MatrixID::RGB: - case media::VideoColorSpace::MatrixID::FCC: - case media::VideoColorSpace::MatrixID::SMPTE240M: - case media::VideoColorSpace::MatrixID::YCOCG: - case media::VideoColorSpace::MatrixID::YDZDX: - case media::VideoColorSpace::MatrixID::BT2020_CL: - break; - - // Never supported. - case media::VideoColorSpace::MatrixID::INVALID: - return false; - } - - if (color_space.range == gfx::ColorSpace::RangeID::INVALID) - return false; - - return true; -} - -bool IsVp9ProfileSupported(VideoCodecProfile profile) { -#if BUILDFLAG(ENABLE_LIBVPX) - // High bit depth capabilities may be toggled via LibVPX config flags. - static bool vpx_supports_high_bit_depth = - (vpx_codec_get_caps(vpx_codec_vp9_dx()) & VPX_CODEC_CAP_HIGHBITDEPTH) != - 0; - - switch (profile) { - // LibVPX always supports Profiles 0 and 1. - case VP9PROFILE_PROFILE0: - case VP9PROFILE_PROFILE1: - return true; - case VP9PROFILE_PROFILE2: - case VP9PROFILE_PROFILE3: - return vpx_supports_high_bit_depth; - default: - NOTREACHED(); - } -#endif - return false; -} - -bool IsSupportedAudioConfig(const AudioConfig& config) { - switch (config.codec) { - case media::kCodecAAC: - case media::kCodecFLAC: - case media::kCodecMP3: - case media::kCodecOpus: - case media::kCodecPCM: - case media::kCodecPCM_MULAW: - case media::kCodecPCM_S16BE: - case media::kCodecPCM_S24BE: - case media::kCodecPCM_ALAW: - case media::kCodecVorbis: - return true; - - case media::kCodecAMR_NB: - case media::kCodecAMR_WB: - case media::kCodecGSM_MS: -#if defined(OS_CHROMEOS) - return true; -#else - return false; -#endif - - case media::kCodecEAC3: - case media::kCodecALAC: - case media::kCodecAC3: - case media::kCodecMpegHAudio: - case media::kUnknownAudioCodec: - return false; - } - - NOTREACHED(); - return false; -} - -// TODO(chcunningham): Query decoders for codec profile support. Add platform -// specific logic for Android (move from MimeUtilIntenral). -bool IsSupportedVideoConfig(const VideoConfig& config) { - switch (config.codec) { - case media::kCodecAV1: -#if BUILDFLAG(ENABLE_AV1_DECODER) - return IsColorSpaceSupported(config.color_space); -#else - return false; -#endif - - case media::kCodecVP9: - // Color management required for HDR to not look terrible. - return IsColorSpaceSupported(config.color_space) && - IsVp9ProfileSupported(config.profile); - case media::kCodecH264: - case media::kCodecVP8: - case media::kCodecTheora: - return true; - - case media::kUnknownVideoCodec: - case media::kCodecVC1: - case media::kCodecMPEG2: - case media::kCodecMPEG4: - case media::kCodecHEVC: - case media::kCodecDolbyVision: - return false; - } - - NOTREACHED(); - return false; -} - -} // namespace media
diff --git a/media/base/decode_capabilities.h b/media/base/decode_capabilities.h deleted file mode 100644 index 4ae095fc..0000000 --- a/media/base/decode_capabilities.h +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2017 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 MEDIA_BASE_DECODE_CAPABILITIES_ -#define MEDIA_BASE_DECODE_CAPABILITIES_ - -#include "media/base/audio_codecs.h" -#include "media/base/media_export.h" -#include "media/base/video_codecs.h" -#include "media/base/video_color_space.h" - -namespace media { - -// APIs to media's decoder capabilities. Embedders may customize decoder -// capabilities via MediaClient. See usage in mime_util_internal.cc. -struct MEDIA_EXPORT AudioConfig { - AudioCodec codec; -}; - -struct MEDIA_EXPORT VideoConfig { - VideoCodec codec; - VideoCodecProfile profile; - int level; - VideoColorSpace color_space; -}; - -MEDIA_EXPORT bool IsSupportedAudioConfig(const AudioConfig& config); -MEDIA_EXPORT bool IsSupportedVideoConfig(const VideoConfig& config); - -} // namespace media - -#endif // MEDIA_BASE_DECODE_CAPABILITIES_
diff --git a/media/base/decode_capabilities_unittest.cc b/media/base/decode_capabilities_unittest.cc deleted file mode 100644 index 7c8b79c3..0000000 --- a/media/base/decode_capabilities_unittest.cc +++ /dev/null
@@ -1,150 +0,0 @@ -// Copyright 2017 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 "media/base/decode_capabilities.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace media { - -TEST(DecodeCapabilitiesTest, IsSupportedVideoConfigBasics) { - // Default to common 709. - const media::VideoColorSpace kColorSpace = media::VideoColorSpace::REC709(); - - // Some codecs do not have a notion of level. - const int kUnspecifiedLevel = 0; - - // Expect support for baseline configuration of known codecs. - EXPECT_TRUE(IsSupportedVideoConfig( - {media::kCodecH264, media::H264PROFILE_BASELINE, 1, kColorSpace})); - EXPECT_TRUE(IsSupportedVideoConfig({media::kCodecVP8, media::VP8PROFILE_ANY, - kUnspecifiedLevel, kColorSpace})); - EXPECT_TRUE( - IsSupportedVideoConfig({media::kCodecVP9, media::VP9PROFILE_PROFILE0, - kUnspecifiedLevel, kColorSpace})); - EXPECT_TRUE(IsSupportedVideoConfig({media::kCodecTheora, - media::VIDEO_CODEC_PROFILE_UNKNOWN, - kUnspecifiedLevel, kColorSpace})); - - // Expect non-support for the following. - EXPECT_FALSE(IsSupportedVideoConfig({media::kUnknownVideoCodec, - media::VIDEO_CODEC_PROFILE_UNKNOWN, - kUnspecifiedLevel, kColorSpace})); - EXPECT_FALSE(IsSupportedVideoConfig({media::kCodecVC1, - media::VIDEO_CODEC_PROFILE_UNKNOWN, - kUnspecifiedLevel, kColorSpace})); - EXPECT_FALSE(IsSupportedVideoConfig({media::kCodecMPEG2, - media::VIDEO_CODEC_PROFILE_UNKNOWN, - kUnspecifiedLevel, kColorSpace})); - EXPECT_FALSE(IsSupportedVideoConfig({media::kCodecMPEG4, - media::VIDEO_CODEC_PROFILE_UNKNOWN, - kUnspecifiedLevel, kColorSpace})); - EXPECT_FALSE(IsSupportedVideoConfig({media::kCodecHEVC, - media::VIDEO_CODEC_PROFILE_UNKNOWN, - kUnspecifiedLevel, kColorSpace})); -} - -TEST(DecodeCapabilitiesTest, IsSupportedVideoConfig_VP9TransferFunctions) { - size_t num_found = 0; - // TODO(hubbe): Verify support for HDR codecs when color management enabled. - const std::set<media::VideoColorSpace::TransferID> kSupportedTransfers = { - media::VideoColorSpace::TransferID::GAMMA22, - media::VideoColorSpace::TransferID::UNSPECIFIED, - media::VideoColorSpace::TransferID::BT709, - media::VideoColorSpace::TransferID::SMPTE170M, - media::VideoColorSpace::TransferID::BT2020_10, - media::VideoColorSpace::TransferID::BT2020_12, - media::VideoColorSpace::TransferID::IEC61966_2_1, - media::VideoColorSpace::TransferID::GAMMA28, - media::VideoColorSpace::TransferID::SMPTE240M, - media::VideoColorSpace::TransferID::LINEAR, - media::VideoColorSpace::TransferID::LOG, - media::VideoColorSpace::TransferID::LOG_SQRT, - media::VideoColorSpace::TransferID::BT1361_ECG, - media::VideoColorSpace::TransferID::SMPTEST2084, - media::VideoColorSpace::TransferID::IEC61966_2_4, - media::VideoColorSpace::TransferID::SMPTEST428_1, - media::VideoColorSpace::TransferID::ARIB_STD_B67, - }; - - for (int i = 0; i <= (1 << (8 * sizeof(media::VideoColorSpace::TransferID))); - i++) { - media::VideoColorSpace color_space = media::VideoColorSpace::REC709(); - color_space.transfer = media::VideoColorSpace::GetTransferID(i); - bool found = kSupportedTransfers.find(color_space.transfer) != - kSupportedTransfers.end(); - if (found) - num_found++; - EXPECT_EQ(found, IsSupportedVideoConfig({media::kCodecVP9, - media::VP9PROFILE_PROFILE0, 1, - color_space})); - } - EXPECT_EQ(kSupportedTransfers.size(), num_found); -} - -TEST(DecodeCapabilitiesTest, IsSupportedVideoConfig_VP9Primaries) { - size_t num_found = 0; - // TODO(hubbe): Verify support for HDR codecs when color management enabled. - const std::set<media::VideoColorSpace::PrimaryID> kSupportedPrimaries = { - media::VideoColorSpace::PrimaryID::BT709, - media::VideoColorSpace::PrimaryID::UNSPECIFIED, - media::VideoColorSpace::PrimaryID::BT470M, - media::VideoColorSpace::PrimaryID::BT470BG, - media::VideoColorSpace::PrimaryID::SMPTE170M, - media::VideoColorSpace::PrimaryID::SMPTE240M, - media::VideoColorSpace::PrimaryID::FILM, - media::VideoColorSpace::PrimaryID::BT2020, - media::VideoColorSpace::PrimaryID::SMPTEST428_1, - media::VideoColorSpace::PrimaryID::SMPTEST431_2, - media::VideoColorSpace::PrimaryID::SMPTEST432_1, - }; - - for (int i = 0; i <= (1 << (8 * sizeof(media::VideoColorSpace::PrimaryID))); - i++) { - media::VideoColorSpace color_space = media::VideoColorSpace::REC709(); - color_space.primaries = media::VideoColorSpace::GetPrimaryID(i); - bool found = kSupportedPrimaries.find(color_space.primaries) != - kSupportedPrimaries.end(); - if (found) - num_found++; - EXPECT_EQ(found, IsSupportedVideoConfig({media::kCodecVP9, - media::VP9PROFILE_PROFILE0, 1, - color_space})); - } - EXPECT_EQ(kSupportedPrimaries.size(), num_found); -} - -TEST(DecodeCapabilitiesTest, IsSupportedVideoConfig_VP9Matrix) { - size_t num_found = 0; - // TODO(hubbe): Verify support for HDR codecs when color management enabled. - const std::set<media::VideoColorSpace::MatrixID> kSupportedMatrix = { - media::VideoColorSpace::MatrixID::BT709, - media::VideoColorSpace::MatrixID::UNSPECIFIED, - media::VideoColorSpace::MatrixID::BT470BG, - media::VideoColorSpace::MatrixID::SMPTE170M, - media::VideoColorSpace::MatrixID::BT2020_NCL, - media::VideoColorSpace::MatrixID::RGB, - media::VideoColorSpace::MatrixID::FCC, - media::VideoColorSpace::MatrixID::SMPTE240M, - media::VideoColorSpace::MatrixID::YCOCG, - media::VideoColorSpace::MatrixID::YDZDX, - media::VideoColorSpace::MatrixID::BT2020_CL, - }; - - for (int i = 0; i <= (1 << (8 * sizeof(media::VideoColorSpace::MatrixID))); - i++) { - media::VideoColorSpace color_space = media::VideoColorSpace::REC709(); - color_space.matrix = media::VideoColorSpace::GetMatrixID(i); - bool found = - kSupportedMatrix.find(color_space.matrix) != kSupportedMatrix.end(); - if (found) - num_found++; - EXPECT_EQ(found, IsSupportedVideoConfig({media::kCodecVP9, - media::VP9PROFILE_PROFILE0, 1, - color_space})); - } - EXPECT_EQ(kSupportedMatrix.size(), num_found); -} - -} // namespace media
diff --git a/media/base/key_systems_unittest.cc b/media/base/key_systems_unittest.cc index cbfc657..b2f3e288 100644 --- a/media/base/key_systems_unittest.cc +++ b/media/base/key_systems_unittest.cc
@@ -259,8 +259,8 @@ bool IsKeySystemsUpdateNeeded() final; void AddSupportedKeySystems(std::vector<std::unique_ptr<KeySystemProperties>>* key_systems_properties) override; - bool IsSupportedAudioConfig(const media::AudioConfig& config) final; - bool IsSupportedVideoConfig(const media::VideoConfig& config) final; + bool IsSupportedAudioType(const media::AudioType& type) final; + bool IsSupportedVideoType(const media::VideoType& type) final; bool IsSupportedBitstreamAudioCodec(AudioCodec codec) final; // Helper function to test the case where IsKeySystemsUpdateNeeded() is true @@ -297,11 +297,11 @@ is_update_needed_ = false; } -bool TestMediaClient::IsSupportedAudioConfig(const media::AudioConfig& config) { +bool TestMediaClient::IsSupportedAudioType(const media::AudioType& type) { return true; } -bool TestMediaClient::IsSupportedVideoConfig(const media::VideoConfig& config) { +bool TestMediaClient::IsSupportedVideoType(const media::VideoType& type) { return true; }
diff --git a/media/base/media_client.h b/media/base/media_client.h index da43b06..f60faa0 100644 --- a/media/base/media_client.h +++ b/media/base/media_client.h
@@ -10,9 +10,9 @@ #include <vector> #include "media/base/audio_codecs.h" -#include "media/base/decode_capabilities.h" #include "media/base/key_system_properties.h" #include "media/base/media_export.h" +#include "media/base/media_types.h" #include "media/base/video_codecs.h" #include "media/base/video_color_space.h" #include "ui/gfx/color_space.h" @@ -49,10 +49,10 @@ virtual bool IsKeySystemsUpdateNeeded() = 0; // Returns true if the given audio config is supported. - virtual bool IsSupportedAudioConfig(const AudioConfig& config) = 0; + virtual bool IsSupportedAudioType(const AudioType& type) = 0; // Returns true if the given video config is supported. - virtual bool IsSupportedVideoConfig(const VideoConfig& config) = 0; + virtual bool IsSupportedVideoType(const VideoType& type) = 0; // Returns true if the compressed audio |codec| format is supported by the // audio sink.
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index a316b2ae..5c25cc3 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -184,11 +184,6 @@ // Autoplay policy to require a user gesture in order to play. const char kUserGestureRequiredPolicy[] = "user-gesture-required"; -// Autoplay policy to require a user gesture in order to play for cross origin -// iframes. -const char kUserGestureRequiredForCrossOriginPolicy[] = - "user-gesture-required-for-cross-origin"; - } // namespace autoplay } // namespace switches
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index 20373c9..8f6ca8c 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -87,7 +87,6 @@ MEDIA_EXPORT extern const char kDocumentUserActivationRequiredPolicy[]; MEDIA_EXPORT extern const char kNoUserGestureRequiredPolicy[]; MEDIA_EXPORT extern const char kUserGestureRequiredPolicy[]; -MEDIA_EXPORT extern const char kUserGestureRequiredForCrossOriginPolicy[]; } // namespace autoplay
diff --git a/media/base/media_types.h b/media/base/media_types.h new file mode 100644 index 0000000..b1b9498e --- /dev/null +++ b/media/base/media_types.h
@@ -0,0 +1,32 @@ +// 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 MEDIA_BASE_MEDIA_TYPES_H_ +#define MEDIA_BASE_MEDIA_TYPES_H_ + +#include "media/base/audio_codecs.h" +#include "media/base/media_export.h" +#include "media/base/video_codecs.h" +#include "media/base/video_color_space.h" + +namespace media { + +// These structures represent parsed audio/video content types (mime strings). +// These are a subset of {Audio|Video}DecoderConfig classes, which can only be +// created after demuxing. + +struct MEDIA_EXPORT AudioType { + AudioCodec codec; +}; + +struct MEDIA_EXPORT VideoType { + VideoCodec codec; + VideoCodecProfile profile; + int level; + VideoColorSpace color_space; +}; + +} // namespace media + +#endif // MEDIA_BASE_MEDIA_TYPES_H_
diff --git a/media/base/mime_util_internal.cc b/media/base/mime_util_internal.cc index 424e101..c546010f 100644 --- a/media/base/mime_util_internal.cc +++ b/media/base/mime_util_internal.cc
@@ -11,8 +11,8 @@ #include "base/strings/string_util.h" #include "build/build_config.h" #include "media/base/media.h" -#include "media/base/media_client.h" #include "media/base/media_switches.h" +#include "media/base/supported_types.h" #include "media/base/video_codecs.h" #include "media/base/video_color_space.h" #include "media/media_buildflags.h" @@ -123,7 +123,7 @@ (level_idc >= 50 && level_idc <= 52)); } -MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { +MimeUtil::MimeUtil() { #if defined(OS_ANDROID) // When the unified media pipeline is enabled, we need support for both GPU // video decoders and MediaCodec; indicated by HasPlatformDecoderSupport(). @@ -255,10 +255,6 @@ } void MimeUtil::InitializeMimeTypeMaps() { -#if BUILDFLAG(USE_PROPRIETARY_CODECS) - allow_proprietary_codecs_ = true; -#endif - AddSupportedMediaFormats(); } @@ -329,36 +325,36 @@ mp4_codecs.insert(mp4_video_codecs.begin(), mp4_video_codecs.end()); const CodecSet implicit_codec; - AddContainerWithCodecs("audio/wav", wav_codecs, false); - AddContainerWithCodecs("audio/x-wav", wav_codecs, false); - AddContainerWithCodecs("audio/webm", webm_audio_codecs, false); + AddContainerWithCodecs("audio/wav", wav_codecs); + AddContainerWithCodecs("audio/x-wav", wav_codecs); + AddContainerWithCodecs("audio/webm", webm_audio_codecs); DCHECK(!webm_video_codecs.empty()); - AddContainerWithCodecs("video/webm", webm_codecs, false); - AddContainerWithCodecs("audio/ogg", ogg_audio_codecs, false); + AddContainerWithCodecs("video/webm", webm_codecs); + AddContainerWithCodecs("audio/ogg", ogg_audio_codecs); // video/ogg is only supported if an appropriate video codec is supported. // Note: This assumes such codecs cannot be later excluded. if (!ogg_video_codecs.empty()) - AddContainerWithCodecs("video/ogg", ogg_codecs, false); + AddContainerWithCodecs("video/ogg", ogg_codecs); // TODO(ddorwin): Should the application type support Opus? - AddContainerWithCodecs("application/ogg", ogg_codecs, false); - AddContainerWithCodecs("audio/flac", implicit_codec, false); - AddContainerWithCodecs("audio/mpeg", mp3_codecs, false); // Allow "mp3". - AddContainerWithCodecs("audio/mp3", implicit_codec, false); - AddContainerWithCodecs("audio/x-mp3", implicit_codec, false); - AddContainerWithCodecs("audio/mp4", mp4_audio_codecs, false); + AddContainerWithCodecs("application/ogg", ogg_codecs); + AddContainerWithCodecs("audio/flac", implicit_codec); + AddContainerWithCodecs("audio/mpeg", mp3_codecs); // Allow "mp3". + AddContainerWithCodecs("audio/mp3", implicit_codec); + AddContainerWithCodecs("audio/x-mp3", implicit_codec); + AddContainerWithCodecs("audio/mp4", mp4_audio_codecs); DCHECK(!mp4_video_codecs.empty()); - AddContainerWithCodecs("video/mp4", mp4_codecs, false); + AddContainerWithCodecs("video/mp4", mp4_codecs); #if BUILDFLAG(USE_PROPRIETARY_CODECS) - AddContainerWithCodecs("audio/aac", implicit_codec, true); // AAC / ADTS. + AddContainerWithCodecs("audio/aac", implicit_codec); // AAC / ADTS. // These strings are supported for backwards compatibility only and thus only // support the codecs needed for compatibility. - AddContainerWithCodecs("audio/x-m4a", aac, true); - AddContainerWithCodecs("video/x-m4v", avc_and_aac, true); + AddContainerWithCodecs("audio/x-m4a", aac); + AddContainerWithCodecs("video/x-m4v", avc_and_aac); #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) CodecSet mp2t_codecs{H264, MPEG2_AAC, MPEG4_AAC, MP3}; - AddContainerWithCodecs("video/mp2t", mp2t_codecs, true); + AddContainerWithCodecs("video/mp2t", mp2t_codecs); #endif // BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) #if defined(OS_ANDROID) // HTTP Live Streaming (HLS). @@ -369,28 +365,20 @@ // Android HLS only supports MPEG4_AAC (missing demuxer // support for MPEG2_AAC) MPEG4_AAC}; - AddContainerWithCodecs("application/x-mpegurl", hls_codecs, true); - AddContainerWithCodecs("application/vnd.apple.mpegurl", hls_codecs, true); - AddContainerWithCodecs("audio/mpegurl", hls_codecs, true); + AddContainerWithCodecs("application/x-mpegurl", hls_codecs); + AddContainerWithCodecs("application/vnd.apple.mpegurl", hls_codecs); + AddContainerWithCodecs("audio/mpegurl", hls_codecs); // Not documented by Apple, but unfortunately used extensively by Apple and // others for both audio-only and audio+video playlists. See // https://crbug.com/675552 for details and examples. - AddContainerWithCodecs("audio/x-mpegurl", hls_codecs, true); + AddContainerWithCodecs("audio/x-mpegurl", hls_codecs); #endif // defined(OS_ANDROID) #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) } void MimeUtil::AddContainerWithCodecs(const std::string& mime_type, - const CodecSet& codecs, - bool is_proprietary_mime_type) { -#if !BUILDFLAG(USE_PROPRIETARY_CODECS) - DCHECK(!is_proprietary_mime_type); -#endif - + const CodecSet& codecs) { media_format_map_[mime_type] = codecs; - - if (is_proprietary_mime_type) - proprietary_media_containers_.push_back(mime_type); } bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { @@ -879,11 +867,6 @@ DCHECK_GT(video_level, 0); } - // Bail early for disabled proprietary codecs - if (!allow_proprietary_codecs_ && IsCodecProprietary(codec)) { - return IsNotSupported; - } - // Check for cases of ambiguous platform support. // TODO(chcunningham): DELETE THIS. Platform should know its capabilities. // Answer should come from MediaClient. @@ -911,37 +894,19 @@ AudioCodec audio_codec = MimeUtilToAudioCodec(codec); if (audio_codec != kUnknownAudioCodec) { - AudioConfig audio_config = {audio_codec}; - - // If MediaClient is provided use it to check for decoder support. - MediaClient* media_client = GetMediaClient(); - if (media_client && !media_client->IsSupportedAudioConfig(audio_config)) - return IsNotSupported; - - // When no MediaClient is provided, assume default decoders are available - // as described by media::IsSupportedAudioConfig(). - if (!media_client && !IsSupportedAudioConfig(audio_config)) + if (!IsSupportedAudioType({audio_codec})) return IsNotSupported; } if (video_codec != kUnknownVideoCodec) { - VideoConfig video_config = {video_codec, video_profile, video_level, - color_space}; - - // If MediaClient is provided use it to check for decoder support. - MediaClient* media_client = GetMediaClient(); - if (media_client && !media_client->IsSupportedVideoConfig(video_config)) - return IsNotSupported; - - // When no MediaClient is provided, assume default decoders are available - // as described by media::IsSupportedVideoConfig(). - if (!media_client && !IsSupportedVideoConfig(video_config)) + if (!IsSupportedVideoType( + {video_codec, video_profile, video_level, color_space})) return IsNotSupported; } #if defined(OS_ANDROID) // TODO(chcunningham): Delete this. Android platform support should be - // handled by (android specific) media::IsSupportedVideoConfig() above. + // handled by (android specific) media::IsSupportedVideoType() above. if (!IsCodecSupportedOnAndroid(codec, mime_type_lower_case, is_encrypted, platform_info_)) { return IsNotSupported; @@ -951,34 +916,6 @@ return ambiguous_platform_support ? MayBeSupported : IsSupported; } -bool MimeUtil::IsCodecProprietary(Codec codec) const { - switch (codec) { - case INVALID_CODEC: - case AC3: - case EAC3: - case MPEG_H_AUDIO: - case MPEG2_AAC: - case MPEG4_AAC: - case H264: - case HEVC: - case DOLBY_VISION: - return true; - - case MP3: - case PCM: - case VORBIS: - case OPUS: - case FLAC: - case VP8: - case VP9: - case THEORA: - case AV1: - return false; - } - - return true; -} - bool MimeUtil::GetDefaultCodec(const std::string& mime_type, Codec* default_codec) const { // Codecs below are unambiguously implied by the mime type string. DO NOT add
diff --git a/media/base/mime_util_internal.h b/media/base/mime_util_internal.h index 38fe068..1bd0196e 100644 --- a/media/base/mime_util_internal.h +++ b/media/base/mime_util_internal.h
@@ -109,8 +109,7 @@ // Adds |mime_type| with the specified codecs to |media_format_map_|. void AddContainerWithCodecs(const std::string& mime_type, - const CodecSet& codecs_list, - bool is_proprietary_mime_type); + const CodecSet& codecs_list); // Returns IsSupported if all codec IDs in |codecs| are unambiguous and are // supported in |mime_type_lower_case|. MayBeSupported is returned if at least @@ -190,11 +189,6 @@ // A map of mime_types and hash map of the supported codecs for the mime_type. MediaFormatMappings media_format_map_; - // List of proprietary containers in |media_format_map_|. - std::vector<std::string> proprietary_media_containers_; - // Whether proprietary codec support should be advertised to callers. - bool allow_proprietary_codecs_; - DISALLOW_COPY_AND_ASSIGN(MimeUtil); };
diff --git a/media/base/supported_types.cc b/media/base/supported_types.cc new file mode 100644 index 0000000..1795a783 --- /dev/null +++ b/media/base/supported_types.cc
@@ -0,0 +1,264 @@ +// Copyright 2017 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 "media/base/supported_types.h" + +#include "base/command_line.h" +#include "base/feature_list.h" +#include "media/base/media_client.h" +#include "media/base/media_switches.h" +#include "media/media_buildflags.h" +#include "third_party/libaom/av1_buildflags.h" +#include "ui/display/display_switches.h" + +#if BUILDFLAG(ENABLE_LIBVPX) +#include "third_party/libvpx/source/libvpx/vpx/vp8dx.h" +#include "third_party/libvpx/source/libvpx/vpx/vpx_codec.h" +#endif + +namespace media { + +bool IsSupportedAudioType(const AudioType& type) { + MediaClient* media_client = GetMediaClient(); + if (media_client) + return media_client->IsSupportedAudioType(type); + + return IsDefaultSupportedAudioType(type); +} + +bool IsSupportedVideoType(const VideoType& type) { + MediaClient* media_client = GetMediaClient(); + if (media_client) + return media_client->IsSupportedVideoType(type); + + return IsDefaultSupportedVideoType(type); +} + +bool IsColorSpaceSupported(const media::VideoColorSpace& color_space) { + switch (color_space.primaries) { + case media::VideoColorSpace::PrimaryID::EBU_3213_E: + case media::VideoColorSpace::PrimaryID::INVALID: + return false; + + // Transfers supported before color management. + case media::VideoColorSpace::PrimaryID::BT709: + case media::VideoColorSpace::PrimaryID::UNSPECIFIED: + case media::VideoColorSpace::PrimaryID::BT470M: + case media::VideoColorSpace::PrimaryID::BT470BG: + case media::VideoColorSpace::PrimaryID::SMPTE170M: + break; + + // Supported with color management. + case media::VideoColorSpace::PrimaryID::SMPTE240M: + case media::VideoColorSpace::PrimaryID::FILM: + case media::VideoColorSpace::PrimaryID::BT2020: + case media::VideoColorSpace::PrimaryID::SMPTEST428_1: + case media::VideoColorSpace::PrimaryID::SMPTEST431_2: + case media::VideoColorSpace::PrimaryID::SMPTEST432_1: + break; + } + + switch (color_space.transfer) { + // Transfers supported before color management. + case media::VideoColorSpace::TransferID::UNSPECIFIED: + case media::VideoColorSpace::TransferID::GAMMA22: + case media::VideoColorSpace::TransferID::BT709: + case media::VideoColorSpace::TransferID::SMPTE170M: + case media::VideoColorSpace::TransferID::BT2020_10: + case media::VideoColorSpace::TransferID::BT2020_12: + case media::VideoColorSpace::TransferID::IEC61966_2_1: + break; + + // Supported with color management. + case media::VideoColorSpace::TransferID::GAMMA28: + case media::VideoColorSpace::TransferID::SMPTE240M: + case media::VideoColorSpace::TransferID::LINEAR: + case media::VideoColorSpace::TransferID::LOG: + case media::VideoColorSpace::TransferID::LOG_SQRT: + case media::VideoColorSpace::TransferID::BT1361_ECG: + case media::VideoColorSpace::TransferID::SMPTEST2084: + case media::VideoColorSpace::TransferID::IEC61966_2_4: + case media::VideoColorSpace::TransferID::SMPTEST428_1: + case media::VideoColorSpace::TransferID::ARIB_STD_B67: + break; + + // Never supported. + case media::VideoColorSpace::TransferID::INVALID: + return false; + } + + switch (color_space.matrix) { + // Supported before color management. + case media::VideoColorSpace::MatrixID::BT709: + case media::VideoColorSpace::MatrixID::UNSPECIFIED: + case media::VideoColorSpace::MatrixID::BT470BG: + case media::VideoColorSpace::MatrixID::SMPTE170M: + case media::VideoColorSpace::MatrixID::BT2020_NCL: + break; + + // Supported with color management. + case media::VideoColorSpace::MatrixID::RGB: + case media::VideoColorSpace::MatrixID::FCC: + case media::VideoColorSpace::MatrixID::SMPTE240M: + case media::VideoColorSpace::MatrixID::YCOCG: + case media::VideoColorSpace::MatrixID::YDZDX: + case media::VideoColorSpace::MatrixID::BT2020_CL: + break; + + // Never supported. + case media::VideoColorSpace::MatrixID::INVALID: + return false; + } + + if (color_space.range == gfx::ColorSpace::RangeID::INVALID) + return false; + + return true; +} + +bool IsVp9ProfileSupported(VideoCodecProfile profile) { +#if BUILDFLAG(ENABLE_LIBVPX) + // High bit depth capabilities may be toggled via LibVPX config flags. + static bool vpx_supports_high_bit_depth = + (vpx_codec_get_caps(vpx_codec_vp9_dx()) & VPX_CODEC_CAP_HIGHBITDEPTH) != + 0; + + switch (profile) { + // LibVPX always supports Profiles 0 and 1. + case VP9PROFILE_PROFILE0: + case VP9PROFILE_PROFILE1: + return true; + case VP9PROFILE_PROFILE2: + case VP9PROFILE_PROFILE3: + return vpx_supports_high_bit_depth; + default: + NOTREACHED(); + } +#endif + return false; +} + +bool IsAudioCodecProprietary(AudioCodec codec) { + switch (codec) { + case media::kCodecAAC: + case media::kCodecAC3: + case media::kCodecEAC3: + case media::kCodecAMR_NB: + case media::kCodecAMR_WB: + case media::kCodecGSM_MS: + case media::kCodecALAC: + case media::kCodecMpegHAudio: + return true; + + case media::kCodecFLAC: + case media::kCodecMP3: + case media::kCodecOpus: + case media::kCodecVorbis: + case media::kCodecPCM: + case media::kCodecPCM_MULAW: + case media::kCodecPCM_S16BE: + case media::kCodecPCM_S24BE: + case media::kCodecPCM_ALAW: + case media::kUnknownAudioCodec: + return false; + } +} + +bool IsDefaultSupportedAudioType(const AudioType& type) { +#if !BUILDFLAG(USE_PROPRIETARY_CODECS) + if (IsAudioCodecProprietary(type.codec)) + return false; +#endif + + switch (type.codec) { + case media::kCodecAAC: + case media::kCodecFLAC: + case media::kCodecMP3: + case media::kCodecOpus: + case media::kCodecPCM: + case media::kCodecPCM_MULAW: + case media::kCodecPCM_S16BE: + case media::kCodecPCM_S24BE: + case media::kCodecPCM_ALAW: + case media::kCodecVorbis: + return true; + + case media::kCodecAMR_NB: + case media::kCodecAMR_WB: + case media::kCodecGSM_MS: +#if defined(OS_CHROMEOS) + return true; +#else + return false; +#endif + + case media::kCodecEAC3: + case media::kCodecALAC: + case media::kCodecAC3: + case media::kCodecMpegHAudio: + case media::kUnknownAudioCodec: + return false; + } + + NOTREACHED(); + return false; +} + +bool IsVideoCodecProprietary(VideoCodec codec) { + switch (codec) { + case kCodecVC1: + case kCodecH264: + case kCodecMPEG2: + case kCodecMPEG4: + case kCodecHEVC: + case kCodecDolbyVision: + return true; + case kUnknownVideoCodec: + case kCodecTheora: + case kCodecVP8: + case kCodecVP9: + case kCodecAV1: + return false; + } +} + +// TODO(chcunningham): Add platform specific logic for Android (move from +// MimeUtilIntenral). +bool IsDefaultSupportedVideoType(const VideoType& type) { +#if !BUILDFLAG(USE_PROPRIETARY_CODECS) + if (IsVideoCodecProprietary(type.codec)) + return false; +#endif + + switch (type.codec) { + case media::kCodecAV1: +#if BUILDFLAG(ENABLE_AV1_DECODER) + return IsColorSpaceSupported(type.color_space); +#else + return false; +#endif + + case media::kCodecVP9: + // Color management required for HDR to not look terrible. + return IsColorSpaceSupported(type.color_space) && + IsVp9ProfileSupported(type.profile); + case media::kCodecH264: + case media::kCodecVP8: + case media::kCodecTheora: + return true; + + case media::kUnknownVideoCodec: + case media::kCodecVC1: + case media::kCodecMPEG2: + case media::kCodecMPEG4: + case media::kCodecHEVC: + case media::kCodecDolbyVision: + return false; + } + + NOTREACHED(); + return false; +} + +} // namespace media
diff --git a/media/base/supported_types.h b/media/base/supported_types.h new file mode 100644 index 0000000..ba4ab01 --- /dev/null +++ b/media/base/supported_types.h
@@ -0,0 +1,26 @@ +// 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 MEDIA_BASE_SUPPORTED_TYPES_H_ +#define MEDIA_BASE_SUPPORTED_TYPES_H_ + +#include "media/base/media_types.h" + +namespace media { + +// These functions will attempt to delegate to MediaClient (when present) to +// describe what types of media are supported. When no MediaClient is provided, +// they will fall back to calling the Default functions below. +MEDIA_EXPORT bool IsSupportedAudioType(const AudioType& type); +MEDIA_EXPORT bool IsSupportedVideoType(const VideoType& type); + +// These functions describe what media/ alone supports. They do not call out to +// MediaClient and do not describe media/ embedder customization. Callers should +// generally prefer the non-Default APIs above. +MEDIA_EXPORT bool IsDefaultSupportedAudioType(const AudioType& type); +MEDIA_EXPORT bool IsDefaultSupportedVideoType(const VideoType& type); + +} // namespace media + +#endif // MEDIA_BASE_SUPPORTED_TYPES_H_
diff --git a/media/base/supported_types_unittest.cc b/media/base/supported_types_unittest.cc new file mode 100644 index 0000000..b8b2c7a9 --- /dev/null +++ b/media/base/supported_types_unittest.cc
@@ -0,0 +1,160 @@ +// Copyright 2017 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 "media/base/supported_types.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +#if BUILDFLAG(USE_PROPRIETARY_CODECS) +const bool kPropCodecsEnabled = true; +#else +const bool kPropCodecsEnabled = false; +#endif + +TEST(SupportedTypesTest, IsSupportedVideoTypeBasics) { + // Default to common 709. + const media::VideoColorSpace kColorSpace = media::VideoColorSpace::REC709(); + + // Some codecs do not have a notion of level. + const int kUnspecifiedLevel = 0; + + // Expect support for baseline configuration of known codecs. + EXPECT_TRUE(IsSupportedVideoType({media::kCodecVP8, media::VP8PROFILE_ANY, + kUnspecifiedLevel, kColorSpace})); + EXPECT_TRUE( + IsSupportedVideoType({media::kCodecVP9, media::VP9PROFILE_PROFILE0, + kUnspecifiedLevel, kColorSpace})); + EXPECT_TRUE(IsSupportedVideoType({media::kCodecTheora, + media::VIDEO_CODEC_PROFILE_UNKNOWN, + kUnspecifiedLevel, kColorSpace})); + + // Expect non-support for the following. + EXPECT_FALSE(IsSupportedVideoType({media::kUnknownVideoCodec, + media::VIDEO_CODEC_PROFILE_UNKNOWN, + kUnspecifiedLevel, kColorSpace})); + EXPECT_FALSE(IsSupportedVideoType({media::kCodecVC1, + media::VIDEO_CODEC_PROFILE_UNKNOWN, + kUnspecifiedLevel, kColorSpace})); + EXPECT_FALSE(IsSupportedVideoType({media::kCodecMPEG2, + media::VIDEO_CODEC_PROFILE_UNKNOWN, + kUnspecifiedLevel, kColorSpace})); + EXPECT_FALSE(IsSupportedVideoType({media::kCodecMPEG4, + media::VIDEO_CODEC_PROFILE_UNKNOWN, + kUnspecifiedLevel, kColorSpace})); + EXPECT_FALSE(IsSupportedVideoType({media::kCodecHEVC, + media::VIDEO_CODEC_PROFILE_UNKNOWN, + kUnspecifiedLevel, kColorSpace})); + + // Expect conditional support for the following. + EXPECT_EQ( + kPropCodecsEnabled, + IsSupportedVideoType( + {media::kCodecH264, media::H264PROFILE_BASELINE, 1, kColorSpace})); +} + +TEST(SupportedTypesTest, IsSupportedVideoType_VP9TransferFunctions) { + size_t num_found = 0; + // TODO(hubbe): Verify support for HDR codecs when color management enabled. + const std::set<media::VideoColorSpace::TransferID> kSupportedTransfers = { + media::VideoColorSpace::TransferID::GAMMA22, + media::VideoColorSpace::TransferID::UNSPECIFIED, + media::VideoColorSpace::TransferID::BT709, + media::VideoColorSpace::TransferID::SMPTE170M, + media::VideoColorSpace::TransferID::BT2020_10, + media::VideoColorSpace::TransferID::BT2020_12, + media::VideoColorSpace::TransferID::IEC61966_2_1, + media::VideoColorSpace::TransferID::GAMMA28, + media::VideoColorSpace::TransferID::SMPTE240M, + media::VideoColorSpace::TransferID::LINEAR, + media::VideoColorSpace::TransferID::LOG, + media::VideoColorSpace::TransferID::LOG_SQRT, + media::VideoColorSpace::TransferID::BT1361_ECG, + media::VideoColorSpace::TransferID::SMPTEST2084, + media::VideoColorSpace::TransferID::IEC61966_2_4, + media::VideoColorSpace::TransferID::SMPTEST428_1, + media::VideoColorSpace::TransferID::ARIB_STD_B67, + }; + + for (int i = 0; i <= (1 << (8 * sizeof(media::VideoColorSpace::TransferID))); + i++) { + media::VideoColorSpace color_space = media::VideoColorSpace::REC709(); + color_space.transfer = media::VideoColorSpace::GetTransferID(i); + bool found = kSupportedTransfers.find(color_space.transfer) != + kSupportedTransfers.end(); + if (found) + num_found++; + EXPECT_EQ(found, IsSupportedVideoType({media::kCodecVP9, + media::VP9PROFILE_PROFILE0, 1, + color_space})); + } + EXPECT_EQ(kSupportedTransfers.size(), num_found); +} + +TEST(SupportedTypesTest, IsSupportedVideoType_VP9Primaries) { + size_t num_found = 0; + // TODO(hubbe): Verify support for HDR codecs when color management enabled. + const std::set<media::VideoColorSpace::PrimaryID> kSupportedPrimaries = { + media::VideoColorSpace::PrimaryID::BT709, + media::VideoColorSpace::PrimaryID::UNSPECIFIED, + media::VideoColorSpace::PrimaryID::BT470M, + media::VideoColorSpace::PrimaryID::BT470BG, + media::VideoColorSpace::PrimaryID::SMPTE170M, + media::VideoColorSpace::PrimaryID::SMPTE240M, + media::VideoColorSpace::PrimaryID::FILM, + media::VideoColorSpace::PrimaryID::BT2020, + media::VideoColorSpace::PrimaryID::SMPTEST428_1, + media::VideoColorSpace::PrimaryID::SMPTEST431_2, + media::VideoColorSpace::PrimaryID::SMPTEST432_1, + }; + + for (int i = 0; i <= (1 << (8 * sizeof(media::VideoColorSpace::PrimaryID))); + i++) { + media::VideoColorSpace color_space = media::VideoColorSpace::REC709(); + color_space.primaries = media::VideoColorSpace::GetPrimaryID(i); + bool found = kSupportedPrimaries.find(color_space.primaries) != + kSupportedPrimaries.end(); + if (found) + num_found++; + EXPECT_EQ(found, IsSupportedVideoType({media::kCodecVP9, + media::VP9PROFILE_PROFILE0, 1, + color_space})); + } + EXPECT_EQ(kSupportedPrimaries.size(), num_found); +} + +TEST(SupportedTypesTest, IsSupportedVideoType_VP9Matrix) { + size_t num_found = 0; + // TODO(hubbe): Verify support for HDR codecs when color management enabled. + const std::set<media::VideoColorSpace::MatrixID> kSupportedMatrix = { + media::VideoColorSpace::MatrixID::BT709, + media::VideoColorSpace::MatrixID::UNSPECIFIED, + media::VideoColorSpace::MatrixID::BT470BG, + media::VideoColorSpace::MatrixID::SMPTE170M, + media::VideoColorSpace::MatrixID::BT2020_NCL, + media::VideoColorSpace::MatrixID::RGB, + media::VideoColorSpace::MatrixID::FCC, + media::VideoColorSpace::MatrixID::SMPTE240M, + media::VideoColorSpace::MatrixID::YCOCG, + media::VideoColorSpace::MatrixID::YDZDX, + media::VideoColorSpace::MatrixID::BT2020_CL, + }; + + for (int i = 0; i <= (1 << (8 * sizeof(media::VideoColorSpace::MatrixID))); + i++) { + media::VideoColorSpace color_space = media::VideoColorSpace::REC709(); + color_space.matrix = media::VideoColorSpace::GetMatrixID(i); + bool found = + kSupportedMatrix.find(color_space.matrix) != kSupportedMatrix.end(); + if (found) + num_found++; + EXPECT_EQ(found, IsSupportedVideoType({media::kCodecVP9, + media::VP9PROFILE_PROFILE0, 1, + color_space})); + } + EXPECT_EQ(kSupportedMatrix.size(), num_found); +} + +} // namespace media
diff --git a/media/blink/resource_multibuffer_data_provider.cc b/media/blink/resource_multibuffer_data_provider.cc index 8aa78dc..4d5ff55 100644 --- a/media/blink/resource_multibuffer_data_provider.cc +++ b/media/blink/resource_multibuffer_data_provider.cc
@@ -357,8 +357,18 @@ return; // "this" may be deleted now. } + // Get the response URL since it can differ from the request URL when a + // service worker provided the response. Normally we would just use + // ResponseUrl(), but ResourceMultibufferDataProvider disallows mixing + // constructed responses (new Response()) and native server responses, even if + // they have the same response URL. + GURL response_url; + if (!response.WasFetchedViaServiceWorker() || + response.HasUrlListViaServiceWorker()) { + response_url = response.ResponseUrl(); + } + // This test is vital for security! - const GURL& response_url = response.ResponseUrl(); if (!url_data_->ValidateDataOrigin(response_url.GetOrigin())) { active_loader_.reset(); url_data_->Fail();
diff --git a/media/blink/webmediacapabilitiesclient_impl.cc b/media/blink/webmediacapabilitiesclient_impl.cc index 886ede2..e4993cb 100644 --- a/media/blink/webmediacapabilitiesclient_impl.cc +++ b/media/blink/webmediacapabilitiesclient_impl.cc
@@ -9,9 +9,9 @@ #include "base/bind_helpers.h" #include "media/base/audio_codecs.h" -#include "media/base/decode_capabilities.h" #include "media/base/key_system_names.h" #include "media/base/mime_util.h" +#include "media/base/supported_types.h" #include "media/base/video_codecs.h" #include "media/base/video_color_space.h" #include "media/blink/webcontentdecryptionmoduleaccess_impl.h" @@ -56,8 +56,7 @@ << audio_config.codec.Ascii(); audio_supported = false; } else { - AudioConfig audio_config = {audio_codec}; - audio_supported = IsSupportedAudioConfig(audio_config); + audio_supported = IsSupportedAudioType({audio_codec}); } return audio_supported; @@ -84,7 +83,7 @@ << video_config.codec.Ascii(); video_supported = false; } else { - video_supported = IsSupportedVideoConfig( + video_supported = IsSupportedVideoType( {video_codec, *out_video_profile, video_level, video_color_space}); }
diff --git a/media/blink/webmediaplayer_cast_android.cc b/media/blink/webmediaplayer_cast_android.cc index 4244e073..898ab6c16 100644 --- a/media/blink/webmediaplayer_cast_android.cc +++ b/media/blink/webmediaplayer_cast_android.cc
@@ -15,6 +15,7 @@ #include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_local_frame.h" #include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkFont.h" #include "third_party/skia/include/core/SkFontStyle.h" #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkTypeface.h" @@ -61,20 +62,21 @@ const SkScalar kMinPadding(40); SkPaint paint; - paint.setAntiAlias(true); - paint.setFilterQuality(kHigh_SkFilterQuality); paint.setColor(SK_ColorWHITE); - paint.setTypeface(SkTypeface::MakeFromName("sans", SkFontStyle::Bold())); - paint.setTextSize(kTextSize); + + SkFont font; + font.setTypeface(SkTypeface::MakeFromName("sans", SkFontStyle::Bold())); + font.setSize(kTextSize); // Calculate the vertical margin from the top SkFontMetrics font_metrics; - paint.getFontMetrics(&font_metrics); + font.getMetrics(&font_metrics); SkScalar sk_vertical_margin = kMinPadding - font_metrics.fAscent; // Measure the width of the entire text to display - size_t display_text_width = paint.measureText(remote_playback_message.c_str(), - remote_playback_message.size()); + size_t display_text_width = + font.measureText(remote_playback_message.c_str(), + remote_playback_message.size(), kUTF8_SkTextEncoding); std::string display_text(remote_playback_message); if (display_text_width + (kMinPadding * 2) > canvas_size.width()) { @@ -83,31 +85,33 @@ // First, figure out how much of the canvas the '...' will take up. const std::string kTruncationEllipsis("\xE2\x80\xA6"); - SkScalar sk_ellipse_width = paint.measureText(kTruncationEllipsis.c_str(), - kTruncationEllipsis.size()); + SkScalar sk_ellipse_width = + font.measureText(kTruncationEllipsis.c_str(), + kTruncationEllipsis.size(), kUTF8_SkTextEncoding); // Then calculate how much of the text can be drawn with the '...' appended // to the end of the string. SkScalar sk_max_original_text_width(canvas_size.width() - (kMinPadding * 2) - sk_ellipse_width); - size_t sk_max_original_text_length = paint.breakText( + size_t sk_max_original_text_length = font.breakText( remote_playback_message.c_str(), remote_playback_message.size(), - sk_max_original_text_width); + kUTF8_SkTextEncoding, sk_max_original_text_width); // Remove the part of the string that doesn't fit and append '...'. display_text.erase( sk_max_original_text_length, remote_playback_message.size() - sk_max_original_text_length); display_text.append(kTruncationEllipsis); - display_text_width = - paint.measureText(display_text.c_str(), display_text.size()); + display_text_width = font.measureText( + display_text.c_str(), display_text.size(), kUTF8_SkTextEncoding); } // Center the text horizontally. SkScalar sk_horizontal_margin = (canvas_size.width() - display_text_width) / 2.0; - canvas.drawText(display_text.c_str(), display_text.size(), - sk_horizontal_margin, sk_vertical_margin, paint); + canvas.drawSimpleText(display_text.c_str(), display_text.size(), + kUTF8_SkTextEncoding, sk_horizontal_margin, + sk_vertical_margin, font, paint); GLES2Interface* gl = context_3d_cb.Run();
diff --git a/media/gpu/test/video_player/video.cc b/media/gpu/test/video_player/video.cc index 4d16f61f..d59c8894 100644 --- a/media/gpu/test/video_player/video.cc +++ b/media/gpu/test/video_player/video.cc
@@ -51,6 +51,7 @@ data_ = std::move(data); // TODO(keiitchiw@) Get this from the metadata accompanying each video file. profile_ = H264PROFILE_BASELINE; + num_frames_ = 250u; return true; } @@ -59,14 +60,18 @@ return data_.size() > 0; } -const std::vector<uint8_t>& Video::GetData() const { +const std::vector<uint8_t>& Video::Data() const { return data_; } -VideoCodecProfile Video::GetProfile() const { +VideoCodecProfile Video::Profile() const { return profile_; } +uint32_t Video::NumFrames() const { + return num_frames_; +} + // static void Video::SetTestDataPath(const base::FilePath& test_data_path) { test_data_path_ = test_data_path;
diff --git a/media/gpu/test/video_player/video.h b/media/gpu/test/video_player/video.h index da20676..c996031 100644 --- a/media/gpu/test/video_player/video.h +++ b/media/gpu/test/video_player/video.h
@@ -33,10 +33,12 @@ bool IsLoaded() const; // Get the video data, will be empty if the video hasn't been loaded yet. - const std::vector<uint8_t>& GetData() const; + const std::vector<uint8_t>& Data() const; // Get the video's codec. - VideoCodecProfile GetProfile() const; + VideoCodecProfile Profile() const; + // Get the number of frames in the video. + uint32_t NumFrames() const; // Set the default path to the test video data. static void SetTestDataPath(const base::FilePath& test_data_path); @@ -51,6 +53,7 @@ std::vector<uint8_t> data_; VideoCodecProfile profile_ = VIDEO_CODEC_PROFILE_UNKNOWN; + uint32_t num_frames_ = 0; DISALLOW_COPY_AND_ASSIGN(Video); };
diff --git a/media/gpu/test/video_player/video_decoder_client.cc b/media/gpu/test/video_player/video_decoder_client.cc index bc29800..21e2c1d 100644 --- a/media/gpu/test/video_player/video_decoder_client.cc +++ b/media/gpu/test/video_player/video_decoder_client.cc
@@ -26,6 +26,7 @@ : event_cb_(event_cb), frame_renderer_(renderer), decoder_client_thread_("VDAClientDecoderThread"), + decoder_client_state_(VideoDecoderClientState::kUninitialized), weak_this_factory_(this) { DETACH_FROM_SEQUENCE(decoder_client_sequence_checker_); weak_this_ = weak_this_factory_.GetWeakPtr(); @@ -97,12 +98,25 @@ done.Wait(); } -void VideoDecoderClient::DecodeNextFragment() { +void VideoDecoderClient::Play() { DCHECK_CALLED_ON_VALID_SEQUENCE(video_player_sequence_checker_); decoder_client_thread_.task_runner()->PostTask( - FROM_HERE, - base::BindOnce(&VideoDecoderClient::DecodeNextFragmentTask, weak_this_)); + FROM_HERE, base::BindOnce(&VideoDecoderClient::PlayTask, weak_this_)); +} + +void VideoDecoderClient::Flush() { + DCHECK_CALLED_ON_VALID_SEQUENCE(video_player_sequence_checker_); + + decoder_client_thread_.task_runner()->PostTask( + FROM_HERE, base::BindOnce(&VideoDecoderClient::FlushTask, weak_this_)); +} + +void VideoDecoderClient::Reset() { + DCHECK_CALLED_ON_VALID_SEQUENCE(video_player_sequence_checker_); + + decoder_client_thread_.task_runner()->PostTask( + FROM_HERE, base::BindOnce(&VideoDecoderClient::ResetTask, weak_this_)); } void VideoDecoderClient::ProvidePictureBuffers( @@ -152,20 +166,27 @@ // Queue the next fragment to be decoded. Flush when we reached the end of the // stream. if (encoded_data_helper_->ReachEndOfStream()) { - decoder_->Flush(); + decoder_client_thread_.task_runner()->PostTask( + FROM_HERE, base::BindOnce(&VideoDecoderClient::FlushTask, weak_this_)); } else { - DecodeNextFragmentTask(); + decoder_client_thread_.task_runner()->PostTask( + FROM_HERE, base::BindOnce(&VideoDecoderClient::DecodeNextFragmentTask, + weak_this_)); } } void VideoDecoderClient::NotifyFlushDone() { DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_); + decoder_client_state_ = VideoDecoderClientState::kIdle; event_cb_.Run(VideoPlayerEvent::kFlushDone); } void VideoDecoderClient::NotifyResetDone() { - NOTIMPLEMENTED(); + DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_); + + decoder_client_state_ = VideoDecoderClientState::kIdle; + event_cb_.Run(VideoPlayerEvent::kResetDone); } void VideoDecoderClient::NotifyError(VideoDecodeAccelerator::Error error) { @@ -226,11 +247,12 @@ gpu::GpuPreferences gpu_preferences; decoder_ = decoder_factory_->CreateVDA( this, config, gpu_driver_bug_workarounds, gpu_preferences); - LOG_ASSERT(decoder_) << "Failed creating a VDA"; + decoder_->TryToSetupDecodeOnSeparateThread( weak_this_, base::ThreadTaskRunnerHandle::Get()); + decoder_client_state_ = VideoDecoderClientState::kIdle; done->Signal(); } @@ -249,6 +271,7 @@ frame_renderer_->ReleaseGLContext(); } + decoder_client_state_ = VideoDecoderClientState::kUninitialized; done->Signal(); } @@ -256,6 +279,10 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_); DVLOGF(4); + // Stop decoding fragments if we're no longer in the decoding state. + if (decoder_client_state_ != VideoDecoderClientState::kDecoding) + return; + if (encoded_data_helper_->ReachEndOfStream()) { LOG(ERROR) << "End of stream reached"; return; @@ -284,6 +311,43 @@ decoder_->Decode(bitstream_buffer); } +void VideoDecoderClient::PlayTask() { + DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_); + DVLOGF(4); + + // This method should only be called when the decoder client is idle. If + // called e.g. while flushing, the behavior is undefined. + ASSERT_EQ(decoder_client_state_, VideoDecoderClientState::kIdle); + + // Start decoding the first fragment. While in the decoding state new + // fragments will automatically be fed to the decoder, when the decoder + // notifies us it reached the end of the current bitstream. + decoder_client_state_ = VideoDecoderClientState::kDecoding; + DecodeNextFragmentTask(); +} + +void VideoDecoderClient::FlushTask() { + DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_); + DVLOGF(4); + + // Changing the state to flushing will abort any pending decodes. + decoder_client_state_ = VideoDecoderClientState::kFlushing; + decoder_->Flush(); + event_cb_.Run(VideoPlayerEvent::kFlushing); +} + +void VideoDecoderClient::ResetTask() { + DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_); + DVLOGF(4); + + // Changing the state to resetting will abort any pending decodes. + decoder_client_state_ = VideoDecoderClientState::kResetting; + // TODO(dstaessens@) Allow resetting to any point in the stream. + encoded_data_helper_->Rewind(); + decoder_->Reset(); + event_cb_.Run(VideoPlayerEvent::kResetting); +} + void VideoDecoderClient::OnPictureBuffersCreatedTask( std::vector<PictureBuffer> buffers) { DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_client_sequence_checker_);
diff --git a/media/gpu/test/video_player/video_decoder_client.h b/media/gpu/test/video_player/video_decoder_client.h index e04c33f..6600f0f 100644 --- a/media/gpu/test/video_player/video_decoder_client.h +++ b/media/gpu/test/video_player/video_decoder_client.h
@@ -55,10 +55,26 @@ // Destroy the currently active decoder. void DestroyDecoder(); - // Queue the next video stream fragment to be decoded. - void DecodeNextFragment(); + // Start decoding the video stream, decoder should be idle when this function + // is called. This function is non-blocking, for each frame decoded a + // 'kFrameDecoded' event will be thrown. + void Play(); + // Queue decoder flush. This function is non-blocking, a kFlushing/kFlushDone + // event is thrown upon start/finish. + void Flush(); + // Queue decoder reset. This function is non-blocking, a kResetting/kResetDone + // event is thrown upon start/finish. + void Reset(); private: + enum class VideoDecoderClientState : size_t { + kUninitialized = 0, + kIdle, + kDecoding, + kFlushing, + kResetting, + }; + VideoDecoderClient(const VideoPlayer::EventCallback& event_cb, FrameRenderer* renderer); @@ -83,7 +99,15 @@ const std::vector<uint8_t>* stream, base::WaitableEvent* done); void DestroyDecoderTask(base::WaitableEvent* done); + + // Instruct the decoder to decode the next video stream fragment. void DecodeNextFragmentTask(); + // Start decoding video stream fragments. + void PlayTask(); + // Instruct the decoder to perform a flush. + void FlushTask(); + // Instruct the decoder to perform a Reset. + void ResetTask(); // Called by the renderer in response to a CreatePictureBuffers request. void OnPictureBuffersCreatedTask(std::vector<PictureBuffer> buffers); @@ -100,6 +124,9 @@ std::unique_ptr<VideoDecodeAccelerator> decoder_; base::Thread decoder_client_thread_; + // Decoder client state, should only be accessed on the decoder client thread. + VideoDecoderClientState decoder_client_state_; + int32_t next_bitstream_buffer_id_ = 0; // TODO(dstaessens@) Replace with StreamParser. std::unique_ptr<media::test::EncodedDataHelper> encoded_data_helper_;
diff --git a/media/gpu/test/video_player/video_player.cc b/media/gpu/test/video_player/video_player.cc index a740ab5..bff3b5f 100644 --- a/media/gpu/test/video_player/video_player.cc +++ b/media/gpu/test/video_player/video_player.cc
@@ -14,11 +14,12 @@ namespace media { namespace test { -VideoPlayer::VideoPlayer(const Video* video) - : video_(video), +VideoPlayer::VideoPlayer() + : video_(nullptr), video_player_state_(VideoPlayerState::kUninitialized), event_cv_(&event_lock_), - video_player_event_counts_{} {} + video_player_event_counts_{}, + event_id_(0) {} VideoPlayer::~VideoPlayer() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -29,10 +30,8 @@ // static std::unique_ptr<VideoPlayer> VideoPlayer::Create( - const Video* video, FrameRenderer* frame_renderer) { - DCHECK(video); - auto video_player = base::WrapUnique(new VideoPlayer(video)); + auto video_player = base::WrapUnique(new VideoPlayer()); if (!video_player->Initialize(frame_renderer)) { return nullptr; } @@ -65,18 +64,32 @@ video_player_state_ = VideoPlayerState::kDestroyed; } +void VideoPlayer::SetStream(const Video* const video) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(video); + DVLOGF(4); + + // Destroy the currently active decoder. + if (video_) { + decoder_client_->DestroyDecoder(); + } + + // Create a decoder for the specified video. + VideoDecodeAccelerator::Config decoder_config(video->Profile()); + decoder_client_->CreateDecoder(decoder_config, video->Data()); + + video_ = video; +} + void VideoPlayer::Play() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_EQ(video_player_state_, VideoPlayerState::kIdle); + DCHECK(video_); DVLOGF(4); - // Create a decoder for the specified video. - VideoDecodeAccelerator::Config decoder_config(video_->GetProfile()); - decoder_client_->CreateDecoder(decoder_config, video_->GetData()); - // Start decoding the video. video_player_state_ = VideoPlayerState::kDecoding; - decoder_client_->DecodeNextFragment(); + decoder_client_->Play(); } void VideoPlayer::Stop() { @@ -84,11 +97,17 @@ } void VideoPlayer::Reset() { - NOTIMPLEMENTED(); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DVLOGF(4); + + decoder_client_->Reset(); } void VideoPlayer::Flush() { - NOTIMPLEMENTED(); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DVLOGF(4); + + decoder_client_->Flush(); } base::TimeDelta VideoPlayer::GetCurrentTime() const { @@ -116,24 +135,28 @@ } bool VideoPlayer::WaitForEvent(VideoPlayerEvent event, + size_t times, base::TimeDelta max_wait) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_GE(times, 1u); DVLOGF(4) << "Event ID: " << static_cast<size_t>(event); - static size_t event_id = 0; base::TimeDelta time_waiting; - base::AutoLock auto_lock(event_lock_); while (true) { const base::TimeTicks start_time = base::TimeTicks::Now(); event_cv_.TimedWait(max_wait); time_waiting += base::TimeTicks::Now() - start_time; + // TODO(dstaessens@) Investigate whether we really need to keep the full + // list of events for more complex testcases. // Go through list of events since last wait, looking for the event we're // interested in. - for (; event_id < video_player_events_.size(); ++event_id) { - if (video_player_events_[event_id] == event) { - event_id++; + for (; event_id_ < video_player_events_.size(); ++event_id_) { + if (video_player_events_[event_id_] == event) + times--; + if (times == 0) { + event_id_++; return true; } } @@ -146,8 +169,10 @@ void VideoPlayer::NotifyEvent(VideoPlayerEvent event) { base::AutoLock auto_lock(event_lock_); - if (event == VideoPlayerEvent::kFlushDone) + if (event == VideoPlayerEvent::kFlushDone || + event == VideoPlayerEvent::kResetDone) { video_player_state_ = VideoPlayerState::kIdle; + } video_player_events_.push_back(event); video_player_event_counts_[static_cast<size_t>(event)]++; event_cv_.Signal();
diff --git a/media/gpu/test/video_player/video_player.h b/media/gpu/test/video_player/video_player.h index 4e229f98..d21b3d1 100644 --- a/media/gpu/test/video_player/video_player.h +++ b/media/gpu/test/video_player/video_player.h
@@ -22,6 +22,9 @@ class VideoDecoderClient; class Video; +// Default timeout used when waiting for events. +constexpr base::TimeDelta kDefaultTimeout = base::TimeDelta::FromSeconds(10); + enum class VideoPlayerState : size_t { kUninitialized = 0, kIdle, @@ -30,8 +33,11 @@ }; enum class VideoPlayerEvent : size_t { - kFlushDone, kFrameDecoded, + kFlushing, + kFlushDone, + kResetting, + kResetDone, kNumEvents, }; @@ -44,11 +50,14 @@ ~VideoPlayer(); - // Return an instance of the video player. The |video| and |frame_renderer| - // will not be owned by the video player. The caller should guarantee they - // exist for the entire lifetime of the video player. - static std::unique_ptr<VideoPlayer> Create(const Video* video, - FrameRenderer* frame_renderer); + // Create an instance of the video player. The |frame_renderer| will not be + // owned by the video player. The caller should guarantee it exists for the + // entire lifetime of the video player. + static std::unique_ptr<VideoPlayer> Create(FrameRenderer* frame_renderer); + + // Set the video stream to be played. The |video| will not be owned by the + // video player. A decoder will be set up for the specified video stream. + void SetStream(const Video* video); void Play(); void Stop(); @@ -62,19 +71,19 @@ // Get the current state of the video player. VideoPlayerState GetState() const; - // Wait for the specified event to occur, will return immediately if the event - // already occurred. All events with different types that precede the - // specified event will be consumed. Will return false if the specified - // timeout is exceeded while waiting for the event. - bool WaitForEvent( - VideoPlayerEvent event, - base::TimeDelta max_wait = base::TimeDelta::FromSeconds(10)); + // Wait for an event to occur the specified number of times. All events that + // occurred since last calling this function will be taken into account. All + // events with different types will be consumed. Will return false if the + // specified timeout is exceeded while waiting for the events. + bool WaitForEvent(VideoPlayerEvent event, + size_t times = 1, + base::TimeDelta max_wait = kDefaultTimeout); // Get the number of times the specified event occurred. size_t GetEventCount(VideoPlayerEvent event) const; private: - explicit VideoPlayer(const Video* video); + VideoPlayer(); bool Initialize(FrameRenderer* frame_renderer); void Destroy(); @@ -88,9 +97,12 @@ mutable base::Lock event_lock_; base::ConditionVariable event_cv_; + std::vector<VideoPlayerEvent> video_player_events_ GUARDED_BY(event_lock_); size_t video_player_event_counts_[static_cast<size_t>( VideoPlayerEvent::kNumEvents)] GUARDED_BY(event_lock_); + // The next event ID to start at, when waiting for events. + size_t event_id_ GUARDED_BY(event_lock_); SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(VideoPlayer);
diff --git a/media/gpu/v4l2/generic_v4l2_device.cc b/media/gpu/v4l2/generic_v4l2_device.cc index a1294ae0b..4292534 100644 --- a/media/gpu/v4l2/generic_v4l2_device.cc +++ b/media/gpu/v4l2/generic_v4l2_device.cc
@@ -379,11 +379,11 @@ return GL_TEXTURE_EXTERNAL_OES; } -uint32_t GenericV4L2Device::PreferredInputFormat(Type type) { +std::vector<uint32_t> GenericV4L2Device::PreferredInputFormat(Type type) { if (type == Type::kEncoder) - return V4L2_PIX_FMT_NV12M; + return {V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_NV12}; - return 0; + return {}; } std::vector<uint32_t> GenericV4L2Device::GetSupportedImageProcessorPixelformats(
diff --git a/media/gpu/v4l2/generic_v4l2_device.h b/media/gpu/v4l2/generic_v4l2_device.h index 3738bb3..fa2baec4 100644 --- a/media/gpu/v4l2/generic_v4l2_device.h +++ b/media/gpu/v4l2/generic_v4l2_device.h
@@ -12,6 +12,7 @@ #include <stdint.h> #include <map> +#include <vector> #include "base/files/scoped_file.h" #include "base/macros.h" @@ -60,7 +61,7 @@ EGLBoolean DestroyEGLImage(EGLDisplay egl_display, EGLImageKHR egl_image) override; GLenum GetTextureTarget() override; - uint32_t PreferredInputFormat(Type type) override; + std::vector<uint32_t> PreferredInputFormat(Type type) override; std::vector<uint32_t> GetSupportedImageProcessorPixelformats( v4l2_buf_type buf_type) override;
diff --git a/media/gpu/v4l2/tegra_v4l2_device.cc b/media/gpu/v4l2/tegra_v4l2_device.cc index 7ed27f1ee..2e0a85c2 100644 --- a/media/gpu/v4l2/tegra_v4l2_device.cc +++ b/media/gpu/v4l2/tegra_v4l2_device.cc
@@ -256,11 +256,12 @@ return GL_TEXTURE_2D; } -uint32_t TegraV4L2Device::PreferredInputFormat(Type type) { - if (type == Type::kEncoder) - return V4L2_PIX_FMT_YUV420M; +std::vector<uint32_t> TegraV4L2Device::PreferredInputFormat(Type type) { + if (type == Type::kEncoder) { + return {V4L2_PIX_FMT_YUV420M}; + } - return 0; + return {}; } std::vector<uint32_t> TegraV4L2Device::GetSupportedImageProcessorPixelformats(
diff --git a/media/gpu/v4l2/tegra_v4l2_device.h b/media/gpu/v4l2/tegra_v4l2_device.h index 2c473df..bcea952 100644 --- a/media/gpu/v4l2/tegra_v4l2_device.h +++ b/media/gpu/v4l2/tegra_v4l2_device.h
@@ -11,6 +11,8 @@ #include <stddef.h> #include <stdint.h> +#include <vector> + #include "base/macros.h" #include "media/gpu/v4l2/v4l2_device.h" #include "ui/gl/gl_bindings.h" @@ -56,7 +58,7 @@ EGLBoolean DestroyEGLImage(EGLDisplay egl_display, EGLImageKHR egl_image) override; GLenum GetTextureTarget() override; - uint32_t PreferredInputFormat(Type type) override; + std::vector<uint32_t> PreferredInputFormat(Type type) override; std::vector<uint32_t> GetSupportedImageProcessorPixelformats( v4l2_buf_type buf_type) override;
diff --git a/media/gpu/v4l2/v4l2_device.h b/media/gpu/v4l2/v4l2_device.h index 5b8b3e5..e7bda8d5 100644 --- a/media/gpu/v4l2/v4l2_device.h +++ b/media/gpu/v4l2/v4l2_device.h
@@ -415,8 +415,8 @@ // Returns the supported texture target for the V4L2Device. virtual GLenum GetTextureTarget() = 0; - // Returns the preferred V4L2 input format for |type| or 0 if none. - virtual uint32_t PreferredInputFormat(Type type) = 0; + // Returns the preferred V4L2 input formats for |type| or empty if none. + virtual std::vector<uint32_t> PreferredInputFormat(Type type) = 0; // NOTE: The below methods to query capabilities have a side effect of // closing the previously-open device, if any, and should not be called after
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc index 12cfb276..43771ad 100644 --- a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc +++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
@@ -1124,13 +1124,16 @@ device_input_format_ = PIXEL_FORMAT_UNKNOWN; input_planes_count_ = 0; - const std::vector<uint32_t> pix_fmt_candidates = { - // First see if the device can use the provided format directly. - // V4L2 VEA only supports multi plane input pixel format. - V4L2Device::VideoPixelFormatToV4L2PixFmt(input_format, false), - // Second try preferred input format. - device_->PreferredInputFormat(V4L2Device::Type::kEncoder), - }; + // First see if the device can use the provided format directly. + // V4L2 VEA only supports multi plane input pixel format. + std::vector<uint32_t> pix_fmt_candidates = { + V4L2Device::VideoPixelFormatToV4L2PixFmt(input_format, false)}; + // Second try preferred input formats for both single-planar and + // multi-planar. + for (auto preferred_format : + device_->PreferredInputFormat(V4L2Device::Type::kEncoder)) { + pix_fmt_candidates.push_back(preferred_format); + } for (const auto pix_fmt : pix_fmt_candidates) { auto trying_format = V4L2Device::V4L2PixFmtToVideoPixelFormat(pix_fmt);
diff --git a/media/gpu/video_decode_accelerator_tests.cc b/media/gpu/video_decode_accelerator_tests.cc index 5a7e8a28..77fd385 100644 --- a/media/gpu/video_decode_accelerator_tests.cc +++ b/media/gpu/video_decode_accelerator_tests.cc
@@ -26,16 +26,17 @@ // Test environment for video decode tests. class VideoDecoderTestEnvironment : public ::testing::Environment { public: - VideoDecoderTestEnvironment() {} + explicit VideoDecoderTestEnvironment(const Video* video) : video_(video) {} virtual ~VideoDecoderTestEnvironment() {} - // Setup up the video decode test environment, only called once. + // Set up the video decode test environment, only called once. void SetUp() override; // Tear down the video decode test environment, only called once. void TearDown() override; std::unique_ptr<base::test::ScopedTaskEnvironment> task_environment_; std::unique_ptr<FrameRendererDummy> dummy_frame_renderer_; + const Video* const video_; // An exit manager is required to run callbacks on shutdown. base::AtExitManager at_exit_manager; @@ -70,18 +71,143 @@ } // namespace -// TODO(dstaessens@) -// * Fetch the expected number of frames from the video file's metadata. -TEST(VideoDecodeAcceleratorTest, BasicPlayTest) { - const Video* video = &kDefaultTestVideoCollection[0]; - auto tvp = VideoPlayer::Create(video, g_env->dummy_frame_renderer_.get()); +// Play video from start to end. Wait for the kFlushDone event at the end of the +// stream, that notifies us all frames have been decoded. +TEST(VideoDecodeAcceleratorTest, FlushAtEndOfStream) { + auto tvp = VideoPlayer::Create(g_env->dummy_frame_renderer_.get()); ASSERT_NE(tvp, nullptr); + tvp->SetStream(g_env->video_); tvp->Play(); EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kFlushDone)); EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kFlushDone), 1u); - EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kFrameDecoded), 250u); + EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kFrameDecoded), + g_env->video_->NumFrames()); +} + +// Flush the decoder immediately after initialization. +TEST(VideoDecodeAcceleratorTest, FlushAfterInitialize) { + auto tvp = VideoPlayer::Create(g_env->dummy_frame_renderer_.get()); + ASSERT_NE(tvp, nullptr); + tvp->SetStream(g_env->video_); + + tvp->Flush(); + EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kFlushDone)); + tvp->Play(); + EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kFlushDone)); + + EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kFlushDone), 2u); + EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kFrameDecoded), + g_env->video_->NumFrames()); +} + +// Flush the decoder immediately after doing a mid-stream reset, without waiting +// for a kResetDone event. +TEST(VideoDecodeAcceleratorTest, FlushBeforeResetDone) { + auto tvp = VideoPlayer::Create(g_env->dummy_frame_renderer_.get()); + ASSERT_NE(tvp, nullptr); + tvp->SetStream(g_env->video_); + + tvp->Play(); + EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kFrameDecoded, + g_env->video_->NumFrames() / 2)); + tvp->Reset(); + tvp->Flush(); + EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kResetDone)); + EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kFlushDone)); + + // As flush doesn't cancel reset, we should have received a single kResetDone + // and kFlushDone event. We didn't decode the entire video, but more frames + // might be decoded by the time we called reset, so we can only check whether + // the decoded frame count is <= the total number of frames. + EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kResetDone), 1u); + EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kFlushDone), 1u); + EXPECT_LE(tvp->GetEventCount(VideoPlayerEvent::kFrameDecoded), + g_env->video_->NumFrames()); +} + +// Reset the decoder immediately after initialization. +TEST(VideoDecodeAcceleratorTest, ResetAfterInitialize) { + auto tvp = VideoPlayer::Create(g_env->dummy_frame_renderer_.get()); + ASSERT_NE(tvp, nullptr); + + tvp->SetStream(g_env->video_); + tvp->Reset(); + EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kResetDone)); + tvp->Play(); + EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kFlushDone)); + + EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kResetDone), 1u); + EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kFlushDone), 1u); + EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kFrameDecoded), + g_env->video_->NumFrames()); +} + +// Reset the decoder when the middle of the stream is reached. +TEST(VideoDecodeAcceleratorTest, ResetMidStream) { + auto tvp = VideoPlayer::Create(g_env->dummy_frame_renderer_.get()); + ASSERT_NE(tvp, nullptr); + tvp->SetStream(g_env->video_); + + tvp->Play(); + EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kFrameDecoded, + g_env->video_->NumFrames() / 2)); + tvp->Reset(); + EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kResetDone)); + size_t numFramesDecoded = tvp->GetEventCount(VideoPlayerEvent::kFrameDecoded); + tvp->Play(); + EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kFlushDone)); + + EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kResetDone), 1u); + EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kFlushDone), 1u); + EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kFrameDecoded), + numFramesDecoded + g_env->video_->NumFrames()); +} + +// Reset the decoder when the end of the stream is reached. +TEST(VideoDecodeAcceleratorTest, ResetEndOfStream) { + auto tvp = VideoPlayer::Create(g_env->dummy_frame_renderer_.get()); + ASSERT_NE(tvp, nullptr); + tvp->SetStream(g_env->video_); + + tvp->Play(); + EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kFlushDone)); + EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kFrameDecoded), + g_env->video_->NumFrames()); + tvp->Reset(); + EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kResetDone)); + tvp->Play(); + EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kFlushDone)); + + EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kResetDone), 1u); + EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kFlushDone), 2u); + EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kFrameDecoded), + g_env->video_->NumFrames() * 2); +} + +// Reset the decoder immediately when the end-of-stream flush starts, without +// waiting for a kFlushDone event. +TEST(VideoDecodeAcceleratorTest, ResetBeforeFlushDone) { + auto tvp = VideoPlayer::Create(g_env->dummy_frame_renderer_.get()); + ASSERT_NE(tvp, nullptr); + tvp->SetStream(g_env->video_); + + // Reset when a kFlushing event is received. + tvp->Play(); + EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kFlushing)); + tvp->Reset(); + EXPECT_TRUE(tvp->WaitForEvent(VideoPlayerEvent::kResetDone)); + + // Reset will cause the decoder to drop everything it's doing, including the + // ongoing flush operation. However the flush might have been completed + // already by the time reset is called. So depending on the timing of the + // calls we should see 0 or 1 flushes, and the last few video frames might + // have been dropped. + EXPECT_LE(tvp->GetEventCount(VideoPlayerEvent::kFlushDone), 1u); + EXPECT_EQ(tvp->GetEventCount(VideoPlayerEvent::kResetDone), 1u); + EXPECT_LE(tvp->GetEventCount(VideoPlayerEvent::kFrameDecoded), + g_env->video_->NumFrames()); } } // namespace test @@ -99,9 +225,12 @@ settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; LOG_ASSERT(logging::InitLogging(settings)); + // Set up our test environment + const media::test::Video* video = + &media::test::kDefaultTestVideoCollection[0]; media::test::g_env = static_cast<media::test::VideoDecoderTestEnvironment*>( testing::AddGlobalTestEnvironment( - new media::test::VideoDecoderTestEnvironment())); + new media::test::VideoDecoderTestEnvironment(video))); return RUN_ALL_TESTS(); }
diff --git a/media/learning/common/learning_task.h b/media/learning/common/learning_task.h index 82c02cb..43e5ccb7 100644 --- a/media/learning/common/learning_task.h +++ b/media/learning/common/learning_task.h
@@ -93,6 +93,19 @@ // Should the accuracy of this model be recorded to UMA? bool record_accuracy_via_uma = true; + + // RandomTree parameters + + // How RandomTree handles unknown feature values. + enum class RTUnknownValueHandling { + // Return an empty distribution as the prediction. + kEmptyDistribution, + + // Return the sum of the traversal of all splits. + kUseAllSplits, + }; + RTUnknownValueHandling rt_unknown_value_handling = + RTUnknownValueHandling::kUseAllSplits; }; } // namespace learning
diff --git a/media/learning/common/value.cc b/media/learning/common/value.cc index ff80a847..2c9ccf1 100644 --- a/media/learning/common/value.cc +++ b/media/learning/common/value.cc
@@ -37,6 +37,10 @@ return value_ < rhs.value_; } +bool Value::operator>(const Value& rhs) const { + return value_ > rhs.value_; +} + std::ostream& operator<<(std::ostream& out, const Value& value) { return out << value.value_; }
diff --git a/media/learning/common/value.h b/media/learning/common/value.h index c468deb2..b19542a 100644 --- a/media/learning/common/value.h +++ b/media/learning/common/value.h
@@ -34,6 +34,7 @@ bool operator==(const Value& rhs) const; bool operator!=(const Value& rhs) const; bool operator<(const Value& rhs) const; + bool operator>(const Value& rhs) const; int64_t value() const { return value_; }
diff --git a/media/learning/common/value_unittest.cc b/media/learning/common/value_unittest.cc index f4c9e0a..a20b231 100644 --- a/media/learning/common/value_unittest.cc +++ b/media/learning/common/value_unittest.cc
@@ -42,6 +42,12 @@ EXPECT_TRUE(v1 != v3); EXPECT_TRUE(v1 < v3); EXPECT_FALSE(v3 < v1); + EXPECT_FALSE(v3 < v3); + EXPECT_FALSE(v1 < v1); + EXPECT_TRUE(v3 > v1); + EXPECT_FALSE(v1 > v3); + EXPECT_FALSE(v1 > v1); + EXPECT_FALSE(v3 > v3); } } // namespace learning
diff --git a/media/learning/impl/learning_task_controller_impl.cc b/media/learning/impl/learning_task_controller_impl.cc index 484ae15..7687e7af 100644 --- a/media/learning/impl/learning_task_controller_impl.cc +++ b/media/learning/impl/learning_task_controller_impl.cc
@@ -16,9 +16,8 @@ : task_(task), storage_(base::MakeRefCounted<TrainingDataStorage>()) { switch (task_.model) { case LearningTask::Model::kRandomForest: - // TODO(liberato): send in the task, so that it can get params. // TODO(liberato): forest! - training_cb_ = RandomTreeTrainer::GetTrainingAlgorithmCB(); + training_cb_ = RandomTreeTrainer::GetTrainingAlgorithmCB(task_); break; }
diff --git a/media/learning/impl/random_tree_trainer.cc b/media/learning/impl/random_tree_trainer.cc index ea90845..9eb9fbc 100644 --- a/media/learning/impl/random_tree_trainer.cc +++ b/media/learning/impl/random_tree_trainer.cc
@@ -8,16 +8,20 @@ #include "base/bind.h" #include "base/logging.h" +#include "base/optional.h" namespace media { namespace learning { // static -TrainingAlgorithmCB RandomTreeTrainer::GetTrainingAlgorithmCB() { +TrainingAlgorithmCB RandomTreeTrainer::GetTrainingAlgorithmCB( + const LearningTask& task) { return base::BindRepeating( - [](TrainingData training_data, TrainedModelCB model_cb) { - std::move(model_cb).Run(RandomTreeTrainer().Train(training_data)); - }); + [](LearningTask task, TrainingData training_data, + TrainedModelCB model_cb) { + std::move(model_cb).Run(RandomTreeTrainer().Train(task, training_data)); + }, + task); } RandomTreeTrainer::Split::Split() = default; @@ -40,19 +44,61 @@ RandomTreeTrainer::Split::BranchInfo::~BranchInfo() = default; struct InteriorNode : public Model { - InteriorNode(int split_index) : split_index_(split_index) {} + InteriorNode(const LearningTask& task, + int split_index, + FeatureValue split_point) + : split_index_(split_index), + rt_unknown_value_handling_(task.rt_unknown_value_handling), + ordering_(task.feature_descriptions[split_index].ordering), + split_point_(split_point) {} // Model TargetDistribution PredictDistribution( const FeatureVector& features) override { - auto iter = children_.find(features[split_index_]); - // If we've never seen this feature value, then make no prediction. - if (iter == children_.end()) - return TargetDistribution(); + // Figure out what feature value we should use for the split. + FeatureValue f; + switch (ordering_) { + case LearningTask::Ordering::kUnordered: + // Use the nominal value directly. + f = features[split_index_]; + break; + case LearningTask::Ordering::kNumeric: + // Use 0 for "<=" and 1 for ">". + f = FeatureValue(features[split_index_] > split_point_); + break; + } + + auto iter = children_.find(f); + + // If we've never seen this feature value, then average all our branches. + // This is an attempt to mimic one-hot encoding, where we'll take the zero + // branch but it depends on the tree structure which of the one-hot values + // we're choosing. + if (iter == children_.end()) { + switch (rt_unknown_value_handling_) { + case LearningTask::RTUnknownValueHandling::kEmptyDistribution: + return TargetDistribution(); + case LearningTask::RTUnknownValueHandling::kUseAllSplits: + return PredictDistributionWithMissingValues(features); + } + } return iter->second->PredictDistribution(features); } + TargetDistribution PredictDistributionWithMissingValues( + const FeatureVector& features) { + TargetDistribution total; + for (auto& child_pair : children_) { + TargetDistribution predicted = + child_pair.second->PredictDistribution(features); + // TODO(liberato): Normalize? Weight? + total += predicted; + } + + return total; + } + // Add |child| has the node for feature value |v|. void AddChild(FeatureValue v, std::unique_ptr<Model> child) { DCHECK_EQ(children_.count(v), 0u); @@ -63,6 +109,15 @@ // Feature value that we split on. int split_index_ = -1; base::flat_map<FeatureValue, std::unique_ptr<Model>> children_; + + // How we handle unknown values. + LearningTask::RTUnknownValueHandling rt_unknown_value_handling_; + + // How is our feature value ordered? + LearningTask::Ordering ordering_; + + // For kNumeric features, this is the split point. + FeatureValue split_point_; }; struct LeafNode : public Model { @@ -85,14 +140,16 @@ RandomTreeTrainer::~RandomTreeTrainer() = default; std::unique_ptr<Model> RandomTreeTrainer::Train( + const LearningTask& task, const TrainingData& training_data) { if (training_data.empty()) - return std::make_unique<InteriorNode>(-1); + return std::make_unique<LeafNode>(training_data); - return Build(training_data, FeatureSet()); + return Build(task, training_data, FeatureSet()); } std::unique_ptr<Model> RandomTreeTrainer::Build( + const LearningTask& task, const TrainingData& training_data, const FeatureSet& used_set) { DCHECK(training_data.size()); @@ -111,7 +168,7 @@ // Find the best split among the candidates that we have. for (int i : feature_candidates) { - Split potential_split = ConstructSplit(training_data, i); + Split potential_split = ConstructSplit(task, training_data, i); if (potential_split.nats_remaining < best_potential_split.nats_remaining) { best_potential_split = std::move(potential_split); } @@ -126,22 +183,29 @@ } // Build an interior node - std::unique_ptr<InteriorNode> node = - std::make_unique<InteriorNode>(best_potential_split.split_index); + std::unique_ptr<InteriorNode> node = std::make_unique<InteriorNode>( + task, best_potential_split.split_index, best_potential_split.split_point); - // Don't let the subtree use this feature. + // Don't let the subtree use this feature if this is nominal split, since + // there's nothing left to split. For numeric splits, we might want to split + // it further. Note that if there is only one branch for this split, then + // we returned a leaf anyway. FeatureSet new_used_set(used_set); - new_used_set.insert(best_potential_split.split_index); + if (task.feature_descriptions[best_potential_split.split_index].ordering == + LearningTask::Ordering::kUnordered) { + new_used_set.insert(best_potential_split.split_index); + } for (auto& branch_iter : best_potential_split.branch_infos) { node->AddChild(branch_iter.first, - Build(branch_iter.second.training_data, new_used_set)); + Build(task, branch_iter.second.training_data, new_used_set)); } return node; } RandomTreeTrainer::Split RandomTreeTrainer::ConstructSplit( + const LearningTask& task, const TrainingData& training_data, int index) { // We should not be given a training set of size 0, since there's no need to @@ -149,6 +213,15 @@ DCHECK_GT(training_data.size(), 0u); Split split(index); + base::Optional<FeatureValue> split_point; + + // For a numeric split, find the split point. Otherwise, we'll split on every + // nominal value that this feature has in |training_data|. + if (task.feature_descriptions[index].ordering == + LearningTask::Ordering::kNumeric) { + split_point = FindNumericSplitPoint(split.split_index, training_data); + split.split_point = *split_point; + } // Find the split's feature values and construct the training set for each. // I think we want to iterate on the underlying vector, and look up the int in @@ -157,10 +230,19 @@ // Get the value of the |index|-th feature for FeatureValue v_i = example->features[split.split_index]; + // Figure out what value this example would use for splitting. For nominal, + // it's just |v_i|. For numeric, it's whether |v_i| is <= the split point + // or not (0 for <=, 1 for >). + FeatureValue split_feature; + if (split_point) + split_feature = FeatureValue(v_i > *split_point); + else + split_feature = v_i; + // Add |v_i| to the right training set. Remember that emplace will do // nothing if the key already exists. auto result = split.branch_infos.emplace( - v_i, Split::BranchInfo(training_data.storage())); + split_feature, Split::BranchInfo(training_data.storage())); auto iter = result.first; Split::BranchInfo& branch_info = iter->second; @@ -174,14 +256,58 @@ Split::BranchInfo& branch_info = info_iter.second; const int total_counts = branch_info.training_data.size(); + // |p_branch| is the probability of following this branch. + const double p_branch = ((double)total_counts) / training_data.size(); for (auto& iter : branch_info.class_counts) { double p = ((double)iter.second) / total_counts; - split.nats_remaining -= p * log(p); + // p*log(p) is the expected nats if the answer is |iter|. We multiply + // that by the probability of being in this bucket at all. + split.nats_remaining -= (p * log(p)) * p_branch; } } return split; } +FeatureValue RandomTreeTrainer::FindNumericSplitPoint( + size_t index, + const TrainingData& training_data) { + // We should not be given a training set of size 0, since there's no need to + // check an empty split. + DCHECK_GT(training_data.size(), 0u); + + // We should either (a) choose the single best split point given all our + // training data (i.e., choosing between the splits that are equally between + // adjacent feature values), or (b) choose the best split point by drawing + // uniformly over the range that contains our feature values. (a) is + // appropriate with RandomForest, while (b) is appropriate with ExtraTrees. + FeatureValue v_min = (*training_data.begin())->features[index]; + FeatureValue v_max = (*training_data.begin())->features[index]; + for (const TrainingExample* example : training_data) { + // Get the value of the |index|-th feature for + FeatureValue v_i = example->features[index]; + if (v_i < v_min) + v_min = v_i; + + if (v_i > v_max) + v_max = v_i; + } + + FeatureValue v_split; + if (v_max == v_min) { + // Pick |v_split| to return a trivial split, so that this ends up as a + // leaf node anyway. + v_split = v_max; + } else { + // Choose a random split point. Note that we want to end up with two + // buckets, so we don't have a trivial split. By picking [v_min, v_max), + // |v_min| will always be in one bucket and |v_max| will always not be. + v_split = FeatureValue((rand() % (v_max.value() - v_min.value())) + + v_min.value()); + } + + return v_split; +} + } // namespace learning } // namespace media
diff --git a/media/learning/impl/random_tree_trainer.h b/media/learning/impl/random_tree_trainer.h index 57bd6d4..a673407 100644 --- a/media/learning/impl/random_tree_trainer.h +++ b/media/learning/impl/random_tree_trainer.h
@@ -13,6 +13,7 @@ #include "base/component_export.h" #include "base/containers/flat_map.h" #include "base/macros.h" +#include "media/learning/common/learning_task.h" #include "media/learning/impl/training_algorithm.h" namespace media { @@ -62,9 +63,10 @@ ~RandomTreeTrainer(); // Return a callback that can be used to train a random tree. - static TrainingAlgorithmCB GetTrainingAlgorithmCB(); + static TrainingAlgorithmCB GetTrainingAlgorithmCB(const LearningTask& task); - std::unique_ptr<Model> Train(const TrainingData& examples); + std::unique_ptr<Model> Train(const LearningTask& task, + const TrainingData& examples); private: // Set of feature indices. @@ -83,6 +85,9 @@ // Feature index to split on. size_t split_index = 0; + // For numeric splits, branch 0 is <= |split_point|, and 1 is > . + FeatureValue split_point; + // Expected nats needed to compute the class, given that we're at this // node in the tree. // "nat" == entropy measured with natural log rather than base-2. @@ -117,11 +122,18 @@ // Build this node from |training_data|. |used_set| is the set of features // that we already used higher in the tree. - std::unique_ptr<Model> Build(const TrainingData& training_data, + std::unique_ptr<Model> Build(const LearningTask& task, + const TrainingData& training_data, const FeatureSet& used_set); // Compute and return a split of |training_data| on the |index|-th feature. - Split ConstructSplit(const TrainingData& training_data, int index); + Split ConstructSplit(const LearningTask& task, + const TrainingData& training_data, + int index); + + // Compute the split point for |training_data| for a numeric feature. + FeatureValue FindNumericSplitPoint(size_t index, + const TrainingData& training_data); DISALLOW_COPY_AND_ASSIGN(RandomTreeTrainer); };
diff --git a/media/learning/impl/random_tree_trainer_unittest.cc b/media/learning/impl/random_tree_trainer_unittest.cc index 5c976bc3..c8973cc 100644 --- a/media/learning/impl/random_tree_trainer_unittest.cc +++ b/media/learning/impl/random_tree_trainer_unittest.cc
@@ -12,31 +12,46 @@ namespace media { namespace learning { -class RandomTreeTest : public testing::Test { +class RandomTreeTest : public testing::TestWithParam<LearningTask::Ordering> { public: - RandomTreeTest() : storage_(base::MakeRefCounted<TrainingDataStorage>()) {} + RandomTreeTest() + : storage_(base::MakeRefCounted<TrainingDataStorage>()), + ordering_(GetParam()) {} base::test::ScopedTaskEnvironment scoped_task_environment_; + // Set up |task_| to have |n| features with the given ordering. + void SetupFeatures(size_t n) { + for (size_t i = 0; i < n; i++) { + LearningTask::ValueDescription desc; + desc.ordering = ordering_; + task_.feature_descriptions.push_back(desc); + } + } + RandomTreeTrainer trainer_; + LearningTask task_; scoped_refptr<TrainingDataStorage> storage_; + // Feature ordering. + LearningTask::Ordering ordering_; }; -TEST_F(RandomTreeTest, EmptyTrainingDataWorks) { +TEST_P(RandomTreeTest, EmptyTrainingDataWorks) { TrainingData empty(storage_); - std::unique_ptr<Model> model = trainer_.Train(empty); + std::unique_ptr<Model> model = trainer_.Train(task_, empty); EXPECT_NE(model.get(), nullptr); EXPECT_EQ(model->PredictDistribution(FeatureVector()), TargetDistribution()); } -TEST_F(RandomTreeTest, UniformTrainingDataWorks) { +TEST_P(RandomTreeTest, UniformTrainingDataWorks) { + SetupFeatures(2); TrainingExample example({FeatureValue(123), FeatureValue(456)}, TargetValue(789)); const int n_examples = 10; for (int i = 0; i < n_examples; i++) storage_->push_back(example); TrainingData training_data(storage_, storage_->begin(), storage_->end()); - std::unique_ptr<Model> model = trainer_.Train(training_data); + std::unique_ptr<Model> model = trainer_.Train(task_, training_data); // The tree should produce a distribution for one value (our target), which // has |n_examples| counts. @@ -46,7 +61,8 @@ EXPECT_EQ(distribution[example.target_value], n_examples); } -TEST_F(RandomTreeTest, UniformTrainingDataWorksWithCallback) { +TEST_P(RandomTreeTest, UniformTrainingDataWorksWithCallback) { + SetupFeatures(2); TrainingExample example({FeatureValue(123), FeatureValue(456)}, TargetValue(789)); const int n_examples = 10; @@ -63,8 +79,8 @@ &model); // Run the trainer. - RandomTreeTrainer::GetTrainingAlgorithmCB().Run(training_data, - std::move(model_cb)); + RandomTreeTrainer::GetTrainingAlgorithmCB(task_).Run(training_data, + std::move(model_cb)); base::RunLoop().RunUntilIdle(); TargetDistribution distribution = @@ -73,13 +89,14 @@ EXPECT_EQ(distribution[example.target_value], n_examples); } -TEST_F(RandomTreeTest, SimpleSeparableTrainingData) { +TEST_P(RandomTreeTest, SimpleSeparableTrainingData) { + SetupFeatures(1); TrainingExample example_1({FeatureValue(123)}, TargetValue(1)); TrainingExample example_2({FeatureValue(456)}, TargetValue(2)); storage_->push_back(example_1); storage_->push_back(example_2); TrainingData training_data(storage_, storage_->begin(), storage_->end()); - std::unique_ptr<Model> model = trainer_.Train(training_data); + std::unique_ptr<Model> model = trainer_.Train(task_, training_data); // Each value should have a distribution with one target value with one count. TargetDistribution distribution = @@ -93,7 +110,8 @@ EXPECT_EQ(distribution[example_2.target_value], 1); } -TEST_F(RandomTreeTest, ComplexSeparableTrainingData) { +TEST_P(RandomTreeTest, ComplexSeparableTrainingData) { + SetupFeatures(4); // Build a four-feature training set that's completely separable, but one // needs all four features to do it. for (int f1 = 0; f1 < 2; f1++) { @@ -117,25 +135,29 @@ training_data.push_back(&example); } - std::unique_ptr<Model> model = trainer_.Train(training_data); + std::unique_ptr<Model> model = trainer_.Train(task_, training_data); EXPECT_NE(model.get(), nullptr); // Each example should have a distribution by itself, with two counts. for (const TrainingExample* example : training_data) { TargetDistribution distribution = model->PredictDistribution(example->features); - EXPECT_EQ(distribution.size(), 1u); - EXPECT_EQ(distribution[example->target_value], 2); + TargetValue singular_max; + EXPECT_TRUE(distribution.FindSingularMax(&singular_max)); + EXPECT_EQ(singular_max, example->target_value); + // EXPECT_EQ(distribution.size(), 1u); + // EXPECT_EQ(distribution[example->target_value], 2); } } -TEST_F(RandomTreeTest, UnseparableTrainingData) { +TEST_P(RandomTreeTest, UnseparableTrainingData) { + SetupFeatures(2); TrainingExample example_1({FeatureValue(123)}, TargetValue(1)); TrainingExample example_2({FeatureValue(123)}, TargetValue(2)); storage_->push_back(example_1); storage_->push_back(example_2); TrainingData training_data(storage_, storage_->begin(), storage_->end()); - std::unique_ptr<Model> model = trainer_.Train(training_data); + std::unique_ptr<Model> model = trainer_.Train(task_, training_data); EXPECT_NE(model.get(), nullptr); // Each value should have a distribution with two targets with one count each. @@ -151,5 +173,77 @@ EXPECT_EQ(distribution[example_2.target_value], 1); } +TEST_P(RandomTreeTest, UnknownFeatureValueHandling) { + // Verify how a previously unseen feature value is handled. + SetupFeatures(2); + TrainingExample example_1({FeatureValue(123)}, TargetValue(1)); + TrainingExample example_2({FeatureValue(456)}, TargetValue(2)); + storage_->push_back(example_1); + storage_->push_back(example_2); + TrainingData training_data(storage_, storage_->begin(), storage_->end()); + + task_.rt_unknown_value_handling = + LearningTask::RTUnknownValueHandling::kEmptyDistribution; + std::unique_ptr<Model> model = trainer_.Train(task_, training_data); + TargetDistribution distribution = + model->PredictDistribution(FeatureVector({FeatureValue(789)})); + if (ordering_ == LearningTask::Ordering::kUnordered) { + // OOV data should return an empty distribution (nominal). + EXPECT_EQ(distribution.size(), 0u); + } else { + // OOV data should end up in the |example_2| bucket, since the feature is + // numerically higher. + EXPECT_EQ(distribution.size(), 1u); + EXPECT_EQ(distribution[example_2.target_value], 1); + } + + task_.rt_unknown_value_handling = + LearningTask::RTUnknownValueHandling::kUseAllSplits; + model = trainer_.Train(task_, training_data); + distribution = model->PredictDistribution(FeatureVector({FeatureValue(789)})); + if (ordering_ == LearningTask::Ordering::kUnordered) { + // OOV data should return with the sum of all splits. + EXPECT_EQ(distribution.size(), 2u); + EXPECT_EQ(distribution[example_1.target_value], 1); + EXPECT_EQ(distribution[example_2.target_value], 1); + } else { + // The unknown feature is numerically higher than |example_2|, so we + // expect it to fall into that bucket. + EXPECT_EQ(distribution.size(), 1u); + EXPECT_EQ(distribution[example_2.target_value], 1); + } +} + +TEST_P(RandomTreeTest, NumericFeaturesSplitMultipleTimes) { + // Verify that numeric features can be split more than once in the tree. + // This should also pass for nominal features, though it's less interesting. + SetupFeatures(2); + const int feature_mult = 10; + for (size_t i = 0; i < 4; i++) { + TrainingExample example({FeatureValue(i * feature_mult)}, TargetValue(i)); + storage_->push_back(example); + } + TrainingData training_data(storage_, storage_->begin(), storage_->end()); + + task_.rt_unknown_value_handling = + LearningTask::RTUnknownValueHandling::kEmptyDistribution; + std::unique_ptr<Model> model = trainer_.Train(task_, training_data); + for (size_t i = 0; i < 4; i++) { + // Get a prediction for the |i|-th feature value. + TargetDistribution distribution = model->PredictDistribution( + FeatureVector({FeatureValue(i * feature_mult)})); + // The distribution should have one count that should be correct. If + // the feature isn't split four times, then some feature value will have too + // many or too few counts. + EXPECT_EQ(distribution.total_counts(), 1); + EXPECT_EQ(distribution[TargetValue(i)], 1); + } +} + +INSTANTIATE_TEST_CASE_P(RandomTreeTest, + RandomTreeTest, + testing::ValuesIn({LearningTask::Ordering::kUnordered, + LearningTask::Ordering::kNumeric})); + } // namespace learning } // namespace media
diff --git a/media/renderers/audio_renderer_impl_unittest.cc b/media/renderers/audio_renderer_impl_unittest.cc index ad4f11e..db63baa 100644 --- a/media/renderers/audio_renderer_impl_unittest.cc +++ b/media/renderers/audio_renderer_impl_unittest.cc
@@ -57,12 +57,8 @@ std::vector<std::unique_ptr<KeySystemProperties>>* key_systems) override { } bool IsKeySystemsUpdateNeeded() override { return false; } - bool IsSupportedAudioConfig(const AudioConfig& config) override { - return true; - } - bool IsSupportedVideoConfig(const VideoConfig& config) override { - return true; - } + bool IsSupportedAudioType(const AudioType& type) override { return true; } + bool IsSupportedVideoType(const VideoType& type) override { return true; } bool IsSupportedBitstreamAudioCodec(AudioCodec codec) override { return true; }
diff --git a/mojo/public/tools/bindings/chromium_bindings_configuration.gni b/mojo/public/tools/bindings/chromium_bindings_configuration.gni index 60a48c1..42f0b18 100644 --- a/mojo/public/tools/bindings/chromium_bindings_configuration.gni +++ b/mojo/public/tools/bindings/chromium_bindings_configuration.gni
@@ -10,7 +10,7 @@ "//chrome/typemaps.gni", "//chromecast/common/mojom/typemaps.gni", "//chromeos/typemaps.gni", - "//chromeos/services/device_sync/public/mojom/typemaps.gni", + "//chromeos/components/multidevice/mojom/typemaps.gni", "//chromeos/services/secure_channel/public/mojom/typemaps.gni", "//components/arc/common/typemaps.gni", "//components/sync/mojo/typemaps.gni",
diff --git a/net/BUILD.gn b/net/BUILD.gn index 1802c10b..c406fb89 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -842,6 +842,21 @@ "http/url_security_manager.cc", "http/url_security_manager.h", "http/url_security_manager_win.cc", + "http2/platform/impl/http2_arraysize_impl.h", + "http2/platform/impl/http2_bug_tracker_impl.h", + "http2/platform/impl/http2_containers_impl.h", + "http2/platform/impl/http2_estimate_memory_usage_impl.h", + "http2/platform/impl/http2_export_impl.h", + "http2/platform/impl/http2_flag_utils_impl.h", + "http2/platform/impl/http2_flags_impl.cc", + "http2/platform/impl/http2_flags_impl.h", + "http2/platform/impl/http2_macros_impl.h", + "http2/platform/impl/http2_optional_impl.h", + "http2/platform/impl/http2_ptr_util_impl.h", + "http2/platform/impl/http2_reconstruct_object_impl.h", + "http2/platform/impl/http2_string_impl.h", + "http2/platform/impl/http2_string_piece_impl.h", + "http2/platform/impl/http2_string_utils_impl.h", "log/file_net_log_observer.cc", "log/file_net_log_observer.h", "log/net_log_util.cc", @@ -1124,112 +1139,6 @@ "ssl/test_ssl_private_key.h", "ssl/threaded_ssl_private_key.cc", "ssl/threaded_ssl_private_key.h", - "third_party/http2/decoder/decode_buffer.cc", - "third_party/http2/decoder/decode_buffer.h", - "third_party/http2/decoder/decode_http2_structures.cc", - "third_party/http2/decoder/decode_http2_structures.h", - "third_party/http2/decoder/decode_status.cc", - "third_party/http2/decoder/decode_status.h", - "third_party/http2/decoder/frame_decoder_state.cc", - "third_party/http2/decoder/frame_decoder_state.h", - "third_party/http2/decoder/http2_frame_decoder.cc", - "third_party/http2/decoder/http2_frame_decoder.h", - "third_party/http2/decoder/http2_frame_decoder_listener.cc", - "third_party/http2/decoder/http2_frame_decoder_listener.h", - "third_party/http2/decoder/http2_structure_decoder.cc", - "third_party/http2/decoder/http2_structure_decoder.h", - "third_party/http2/decoder/payload_decoders/altsvc_payload_decoder.cc", - "third_party/http2/decoder/payload_decoders/altsvc_payload_decoder.h", - "third_party/http2/decoder/payload_decoders/continuation_payload_decoder.cc", - "third_party/http2/decoder/payload_decoders/continuation_payload_decoder.h", - "third_party/http2/decoder/payload_decoders/data_payload_decoder.cc", - "third_party/http2/decoder/payload_decoders/data_payload_decoder.h", - "third_party/http2/decoder/payload_decoders/goaway_payload_decoder.cc", - "third_party/http2/decoder/payload_decoders/goaway_payload_decoder.h", - "third_party/http2/decoder/payload_decoders/headers_payload_decoder.cc", - "third_party/http2/decoder/payload_decoders/headers_payload_decoder.h", - "third_party/http2/decoder/payload_decoders/ping_payload_decoder.cc", - "third_party/http2/decoder/payload_decoders/ping_payload_decoder.h", - "third_party/http2/decoder/payload_decoders/priority_payload_decoder.cc", - "third_party/http2/decoder/payload_decoders/priority_payload_decoder.h", - "third_party/http2/decoder/payload_decoders/push_promise_payload_decoder.cc", - "third_party/http2/decoder/payload_decoders/push_promise_payload_decoder.h", - "third_party/http2/decoder/payload_decoders/rst_stream_payload_decoder.cc", - "third_party/http2/decoder/payload_decoders/rst_stream_payload_decoder.h", - "third_party/http2/decoder/payload_decoders/settings_payload_decoder.cc", - "third_party/http2/decoder/payload_decoders/settings_payload_decoder.h", - "third_party/http2/decoder/payload_decoders/unknown_payload_decoder.cc", - "third_party/http2/decoder/payload_decoders/unknown_payload_decoder.h", - "third_party/http2/decoder/payload_decoders/window_update_payload_decoder.cc", - "third_party/http2/decoder/payload_decoders/window_update_payload_decoder.h", - "third_party/http2/hpack/decoder/hpack_block_decoder.cc", - "third_party/http2/hpack/decoder/hpack_block_decoder.h", - "third_party/http2/hpack/decoder/hpack_decoder.cc", - "third_party/http2/hpack/decoder/hpack_decoder.h", - "third_party/http2/hpack/decoder/hpack_decoder_listener.cc", - "third_party/http2/hpack/decoder/hpack_decoder_listener.h", - "third_party/http2/hpack/decoder/hpack_decoder_state.cc", - "third_party/http2/hpack/decoder/hpack_decoder_state.h", - "third_party/http2/hpack/decoder/hpack_decoder_string_buffer.cc", - "third_party/http2/hpack/decoder/hpack_decoder_string_buffer.h", - "third_party/http2/hpack/decoder/hpack_decoder_tables.cc", - "third_party/http2/hpack/decoder/hpack_decoder_tables.h", - "third_party/http2/hpack/decoder/hpack_entry_decoder.cc", - "third_party/http2/hpack/decoder/hpack_entry_decoder.h", - "third_party/http2/hpack/decoder/hpack_entry_decoder_listener.cc", - "third_party/http2/hpack/decoder/hpack_entry_decoder_listener.h", - "third_party/http2/hpack/decoder/hpack_entry_type_decoder.cc", - "third_party/http2/hpack/decoder/hpack_entry_type_decoder.h", - "third_party/http2/hpack/decoder/hpack_string_decoder.cc", - "third_party/http2/hpack/decoder/hpack_string_decoder.h", - "third_party/http2/hpack/decoder/hpack_string_decoder_listener.cc", - "third_party/http2/hpack/decoder/hpack_string_decoder_listener.h", - "third_party/http2/hpack/decoder/hpack_whole_entry_buffer.cc", - "third_party/http2/hpack/decoder/hpack_whole_entry_buffer.h", - "third_party/http2/hpack/decoder/hpack_whole_entry_listener.cc", - "third_party/http2/hpack/decoder/hpack_whole_entry_listener.h", - "third_party/http2/hpack/hpack_static_table_entries.inc", - "third_party/http2/hpack/hpack_string.cc", - "third_party/http2/hpack/hpack_string.h", - "third_party/http2/hpack/http2_hpack_constants.cc", - "third_party/http2/hpack/http2_hpack_constants.h", - "third_party/http2/hpack/huffman/hpack_huffman_decoder.cc", - "third_party/http2/hpack/huffman/hpack_huffman_decoder.h", - "third_party/http2/hpack/huffman/hpack_huffman_encoder.cc", - "third_party/http2/hpack/huffman/hpack_huffman_encoder.h", - "third_party/http2/hpack/huffman/huffman_spec_tables.cc", - "third_party/http2/hpack/huffman/huffman_spec_tables.h", - "third_party/http2/hpack/varint/hpack_varint_decoder.cc", - "third_party/http2/hpack/varint/hpack_varint_decoder.h", - "third_party/http2/hpack/varint/hpack_varint_encoder.cc", - "third_party/http2/hpack/varint/hpack_varint_encoder.h", - "third_party/http2/http2_constants.cc", - "third_party/http2/http2_constants.h", - "third_party/http2/http2_structures.cc", - "third_party/http2/http2_structures.h", - "third_party/http2/platform/api/http2_arraysize.h", - "third_party/http2/platform/api/http2_bug_tracker.h", - "third_party/http2/platform/api/http2_export.h", - "third_party/http2/platform/api/http2_flag_utils.h", - "third_party/http2/platform/api/http2_flags.h", - "third_party/http2/platform/api/http2_optional.h", - "third_party/http2/platform/api/http2_ptr_util.h", - "third_party/http2/platform/api/http2_reconstruct_object.h", - "third_party/http2/platform/api/http2_string.h", - "third_party/http2/platform/api/http2_string_piece.h", - "third_party/http2/platform/api/http2_string_utils.h", - "third_party/http2/platform/impl/http2_arraysize_impl.h", - "third_party/http2/platform/impl/http2_bug_tracker_impl.h", - "third_party/http2/platform/impl/http2_export_impl.h", - "third_party/http2/platform/impl/http2_flag_utils_impl.h", - "third_party/http2/platform/impl/http2_flags_impl.cc", - "third_party/http2/platform/impl/http2_flags_impl.h", - "third_party/http2/platform/impl/http2_optional_impl.h", - "third_party/http2/platform/impl/http2_ptr_util_impl.h", - "third_party/http2/platform/impl/http2_reconstruct_object_impl.h", - "third_party/http2/platform/impl/http2_string_impl.h", - "third_party/http2/platform/impl/http2_string_piece_impl.h", - "third_party/http2/platform/impl/http2_string_utils_impl.h", "third_party/mozilla_security_manager/nsNSSCertificateDB.cpp", "third_party/mozilla_security_manager/nsNSSCertificateDB.h", "third_party/mozilla_security_manager/nsPKCS12Blob.cpp", @@ -1624,6 +1533,100 @@ "third_party/quic/quartc/quartc_session.h", "third_party/quic/quartc/quartc_stream.cc", "third_party/quic/quartc/quartc_stream.h", + "third_party/quiche/src/http2/decoder/decode_buffer.cc", + "third_party/quiche/src/http2/decoder/decode_buffer.h", + "third_party/quiche/src/http2/decoder/decode_http2_structures.cc", + "third_party/quiche/src/http2/decoder/decode_http2_structures.h", + "third_party/quiche/src/http2/decoder/decode_status.cc", + "third_party/quiche/src/http2/decoder/decode_status.h", + "third_party/quiche/src/http2/decoder/frame_decoder_state.cc", + "third_party/quiche/src/http2/decoder/frame_decoder_state.h", + "third_party/quiche/src/http2/decoder/http2_frame_decoder.cc", + "third_party/quiche/src/http2/decoder/http2_frame_decoder.h", + "third_party/quiche/src/http2/decoder/http2_frame_decoder_listener.cc", + "third_party/quiche/src/http2/decoder/http2_frame_decoder_listener.h", + "third_party/quiche/src/http2/decoder/http2_structure_decoder.cc", + "third_party/quiche/src/http2/decoder/http2_structure_decoder.h", + "third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder.h", + "third_party/quiche/src/http2/decoder/payload_decoders/continuation_payload_decoder.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/continuation_payload_decoder.h", + "third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder.h", + "third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder.h", + "third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder.h", + "third_party/quiche/src/http2/decoder/payload_decoders/ping_payload_decoder.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/ping_payload_decoder.h", + "third_party/quiche/src/http2/decoder/payload_decoders/priority_payload_decoder.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/priority_payload_decoder.h", + "third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder.h", + "third_party/quiche/src/http2/decoder/payload_decoders/rst_stream_payload_decoder.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/rst_stream_payload_decoder.h", + "third_party/quiche/src/http2/decoder/payload_decoders/settings_payload_decoder.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/settings_payload_decoder.h", + "third_party/quiche/src/http2/decoder/payload_decoders/unknown_payload_decoder.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/unknown_payload_decoder.h", + "third_party/quiche/src/http2/decoder/payload_decoders/window_update_payload_decoder.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/window_update_payload_decoder.h", + "third_party/quiche/src/http2/hpack/decoder/hpack_block_decoder.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_block_decoder.h", + "third_party/quiche/src/http2/hpack/decoder/hpack_decoder.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h", + "third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.h", + "third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h", + "third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.h", + "third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.h", + "third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder.h", + "third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder_listener.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder_listener.h", + "third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder.h", + "third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder.h", + "third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder_listener.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder_listener.h", + "third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.h", + "third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_listener.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_listener.h", + "third_party/quiche/src/http2/hpack/hpack_static_table_entries.inc", + "third_party/quiche/src/http2/hpack/hpack_string.cc", + "third_party/quiche/src/http2/hpack/hpack_string.h", + "third_party/quiche/src/http2/hpack/http2_hpack_constants.cc", + "third_party/quiche/src/http2/hpack/http2_hpack_constants.h", + "third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder.cc", + "third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder.h", + "third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder.cc", + "third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder.h", + "third_party/quiche/src/http2/hpack/huffman/huffman_spec_tables.cc", + "third_party/quiche/src/http2/hpack/huffman/huffman_spec_tables.h", + "third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.cc", + "third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.h", + "third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder.cc", + "third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder.h", + "third_party/quiche/src/http2/http2_constants.cc", + "third_party/quiche/src/http2/http2_constants.h", + "third_party/quiche/src/http2/http2_structures.cc", + "third_party/quiche/src/http2/http2_structures.h", + "third_party/quiche/src/http2/platform/api/http2_arraysize.h", + "third_party/quiche/src/http2/platform/api/http2_bug_tracker.h", + "third_party/quiche/src/http2/platform/api/http2_export.h", + "third_party/quiche/src/http2/platform/api/http2_flag_utils.h", + "third_party/quiche/src/http2/platform/api/http2_flags.h", + "third_party/quiche/src/http2/platform/api/http2_optional.h", + "third_party/quiche/src/http2/platform/api/http2_ptr_util.h", + "third_party/quiche/src/http2/platform/api/http2_reconstruct_object.h", + "third_party/quiche/src/http2/platform/api/http2_string.h", + "third_party/quiche/src/http2/platform/api/http2_string_piece.h", + "third_party/quiche/src/http2/platform/api/http2_string_utils.h", "third_party/spdy/core/hpack/hpack_constants.cc", "third_party/spdy/core/hpack/hpack_constants.h", "third_party/spdy/core/hpack/hpack_decoder_adapter.cc", @@ -1772,6 +1775,8 @@ "reporting/reporting_browsing_data_remover.h", "reporting/reporting_cache.cc", "reporting/reporting_cache.h", + "reporting/reporting_cache_observer.cc", + "reporting/reporting_cache_observer.h", "reporting/reporting_client.cc", "reporting/reporting_client.h", "reporting/reporting_context.cc", @@ -1788,8 +1793,6 @@ "reporting/reporting_header_parser.h", "reporting/reporting_network_change_observer.cc", "reporting/reporting_network_change_observer.h", - "reporting/reporting_observer.cc", - "reporting/reporting_observer.h", "reporting/reporting_policy.cc", "reporting/reporting_policy.h", "reporting/reporting_report.cc", @@ -4888,6 +4891,9 @@ "http/transport_security_persister_unittest.cc", "http/transport_security_state_unittest.cc", "http/url_security_manager_unittest.cc", + "http2/platform/impl/http2_mock_log_impl.h", + "http2/platform/impl/http2_test_helpers_impl.cc", + "http2/platform/impl/http2_test_helpers_impl.h", "log/file_net_log_observer_unittest.cc", "log/net_log_capture_mode_unittest.cc", "log/net_log_unittest.cc", @@ -5022,85 +5028,6 @@ "test/embedded_test_server/http_response_unittest.cc", "test/run_all_unittests.cc", "test/tcp_socket_proxy_unittest.cc", - "third_party/http2/decoder/decode_buffer_test.cc", - "third_party/http2/decoder/decode_http2_structures_test.cc", - "third_party/http2/decoder/frame_decoder_state_test_util.cc", - "third_party/http2/decoder/frame_decoder_state_test_util.h", - "third_party/http2/decoder/http2_frame_decoder_listener_test_util.cc", - "third_party/http2/decoder/http2_frame_decoder_listener_test_util.h", - "third_party/http2/decoder/http2_frame_decoder_test.cc", - "third_party/http2/decoder/http2_structure_decoder_test.cc", - "third_party/http2/decoder/http2_structure_decoder_test_util.cc", - "third_party/http2/decoder/http2_structure_decoder_test_util.h", - "third_party/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc", - "third_party/http2/decoder/payload_decoders/continuation_payload_decoder_test.cc", - "third_party/http2/decoder/payload_decoders/data_payload_decoder_test.cc", - "third_party/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc", - "third_party/http2/decoder/payload_decoders/headers_payload_decoder_test.cc", - "third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.cc", - "third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h", - "third_party/http2/decoder/payload_decoders/ping_payload_decoder_test.cc", - "third_party/http2/decoder/payload_decoders/priority_payload_decoder_test.cc", - "third_party/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc", - "third_party/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc", - "third_party/http2/decoder/payload_decoders/settings_payload_decoder_test.cc", - "third_party/http2/decoder/payload_decoders/unknown_payload_decoder_test.cc", - "third_party/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc", - "third_party/http2/hpack/decoder/hpack_block_collector.cc", - "third_party/http2/hpack/decoder/hpack_block_collector.h", - "third_party/http2/hpack/decoder/hpack_block_decoder_test.cc", - "third_party/http2/hpack/decoder/hpack_decoder_state_test.cc", - "third_party/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc", - "third_party/http2/hpack/decoder/hpack_decoder_tables_test.cc", - "third_party/http2/hpack/decoder/hpack_decoder_test.cc", - "third_party/http2/hpack/decoder/hpack_entry_collector.cc", - "third_party/http2/hpack/decoder/hpack_entry_collector.h", - "third_party/http2/hpack/decoder/hpack_entry_decoder_test.cc", - "third_party/http2/hpack/decoder/hpack_entry_type_decoder_test.cc", - "third_party/http2/hpack/decoder/hpack_string_collector.cc", - "third_party/http2/hpack/decoder/hpack_string_collector.h", - "third_party/http2/hpack/decoder/hpack_string_decoder_test.cc", - "third_party/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc", - "third_party/http2/hpack/hpack_string_test.cc", - "third_party/http2/hpack/http2_hpack_constants_test.cc", - "third_party/http2/hpack/huffman/hpack_huffman_decoder_test.cc", - "third_party/http2/hpack/huffman/hpack_huffman_encoder_test.cc", - "third_party/http2/hpack/huffman/hpack_huffman_transcoder_test.cc", - "third_party/http2/hpack/tools/hpack_block_builder.cc", - "third_party/http2/hpack/tools/hpack_block_builder.h", - "third_party/http2/hpack/tools/hpack_block_builder_test.cc", - "third_party/http2/hpack/tools/hpack_example.cc", - "third_party/http2/hpack/tools/hpack_example.h", - "third_party/http2/hpack/varint/hpack_varint_decoder_test.cc", - "third_party/http2/hpack/varint/hpack_varint_encoder_test.cc", - "third_party/http2/hpack/varint/hpack_varint_round_trip_test.cc", - "third_party/http2/http2_constants_test.cc", - "third_party/http2/http2_constants_test_util.cc", - "third_party/http2/http2_constants_test_util.h", - "third_party/http2/http2_structures_test.cc", - "third_party/http2/http2_structures_test_util.cc", - "third_party/http2/http2_structures_test_util.h", - "third_party/http2/platform/api/http2_mock_log.h", - "third_party/http2/platform/api/http2_string_utils_test.cc", - "third_party/http2/platform/api/http2_test_helpers.h", - "third_party/http2/platform/impl/http2_mock_log_impl.h", - "third_party/http2/platform/impl/http2_test_helpers_impl.cc", - "third_party/http2/platform/impl/http2_test_helpers_impl.h", - "third_party/http2/test_tools/frame_parts.cc", - "third_party/http2/test_tools/frame_parts.h", - "third_party/http2/test_tools/frame_parts_collector.cc", - "third_party/http2/test_tools/frame_parts_collector.h", - "third_party/http2/test_tools/frame_parts_collector_listener.cc", - "third_party/http2/test_tools/frame_parts_collector_listener.h", - "third_party/http2/test_tools/http2_random.cc", - "third_party/http2/test_tools/http2_random.h", - "third_party/http2/test_tools/http2_random_test.cc", - "third_party/http2/tools/http2_frame_builder.cc", - "third_party/http2/tools/http2_frame_builder.h", - "third_party/http2/tools/random_decoder_test.cc", - "third_party/http2/tools/random_decoder_test.h", - "third_party/http2/tools/random_util.cc", - "third_party/http2/tools/random_util.h", "third_party/nist-pkits/pkits_testcases-inl.h", "third_party/quic/core/congestion_control/bandwidth_sampler_test.cc", "third_party/quic/core/congestion_control/bbr_sender_test.cc", @@ -5235,6 +5162,82 @@ "third_party/quic/test_tools/simple_session_notifier_test.cc", "third_party/quic/test_tools/simulator/quic_endpoint_test.cc", "third_party/quic/test_tools/simulator/simulator_test.cc", + "third_party/quiche/src/http2/decoder/decode_buffer_test.cc", + "third_party/quiche/src/http2/decoder/decode_http2_structures_test.cc", + "third_party/quiche/src/http2/decoder/frame_decoder_state_test_util.cc", + "third_party/quiche/src/http2/decoder/frame_decoder_state_test_util.h", + "third_party/quiche/src/http2/decoder/http2_frame_decoder_listener_test_util.cc", + "third_party/quiche/src/http2/decoder/http2_frame_decoder_listener_test_util.h", + "third_party/quiche/src/http2/decoder/http2_frame_decoder_test.cc", + "third_party/quiche/src/http2/decoder/http2_structure_decoder_test.cc", + "third_party/quiche/src/http2/decoder/http2_structure_decoder_test_util.cc", + "third_party/quiche/src/http2/decoder/http2_structure_decoder_test_util.h", + "third_party/quiche/src/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/continuation_payload_decoder_test.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/data_payload_decoder_test.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/headers_payload_decoder_test.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/payload_decoder_base_test_util.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/payload_decoder_base_test_util.h", + "third_party/quiche/src/http2/decoder/payload_decoders/ping_payload_decoder_test.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/priority_payload_decoder_test.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/settings_payload_decoder_test.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/unknown_payload_decoder_test.cc", + "third_party/quiche/src/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_block_collector.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_block_collector.h", + "third_party/quiche/src/http2/hpack/decoder/hpack_block_decoder_test.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state_test.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables_test.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_decoder_test.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_entry_collector.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_entry_collector.h", + "third_party/quiche/src/http2/hpack/decoder/hpack_entry_decoder_test.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_entry_type_decoder_test.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_string_collector.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_string_collector.h", + "third_party/quiche/src/http2/hpack/decoder/hpack_string_decoder_test.cc", + "third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc", + "third_party/quiche/src/http2/hpack/hpack_string_test.cc", + "third_party/quiche/src/http2/hpack/http2_hpack_constants_test.cc", + "third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder_test.cc", + "third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder_test.cc", + "third_party/quiche/src/http2/hpack/huffman/hpack_huffman_transcoder_test.cc", + "third_party/quiche/src/http2/hpack/tools/hpack_block_builder.cc", + "third_party/quiche/src/http2/hpack/tools/hpack_block_builder.h", + "third_party/quiche/src/http2/hpack/tools/hpack_block_builder_test.cc", + "third_party/quiche/src/http2/hpack/tools/hpack_example.cc", + "third_party/quiche/src/http2/hpack/tools/hpack_example.h", + "third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder_test.cc", + "third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder_test.cc", + "third_party/quiche/src/http2/hpack/varint/hpack_varint_round_trip_test.cc", + "third_party/quiche/src/http2/http2_constants_test.cc", + "third_party/quiche/src/http2/http2_constants_test_util.cc", + "third_party/quiche/src/http2/http2_constants_test_util.h", + "third_party/quiche/src/http2/http2_structures_test.cc", + "third_party/quiche/src/http2/http2_structures_test_util.cc", + "third_party/quiche/src/http2/http2_structures_test_util.h", + "third_party/quiche/src/http2/platform/api/http2_mock_log.h", + "third_party/quiche/src/http2/platform/api/http2_string_utils_test.cc", + "third_party/quiche/src/http2/platform/api/http2_test_helpers.h", + "third_party/quiche/src/http2/test_tools/frame_parts.cc", + "third_party/quiche/src/http2/test_tools/frame_parts.h", + "third_party/quiche/src/http2/test_tools/frame_parts_collector.cc", + "third_party/quiche/src/http2/test_tools/frame_parts_collector.h", + "third_party/quiche/src/http2/test_tools/frame_parts_collector_listener.cc", + "third_party/quiche/src/http2/test_tools/frame_parts_collector_listener.h", + "third_party/quiche/src/http2/test_tools/http2_random.cc", + "third_party/quiche/src/http2/test_tools/http2_random.h", + "third_party/quiche/src/http2/test_tools/http2_random_test.cc", + "third_party/quiche/src/http2/tools/http2_frame_builder.cc", + "third_party/quiche/src/http2/tools/http2_frame_builder.h", + "third_party/quiche/src/http2/tools/random_decoder_test.cc", + "third_party/quiche/src/http2/tools/random_decoder_test.h", + "third_party/quiche/src/http2/tools/random_util.cc", + "third_party/quiche/src/http2/tools/random_util.h", "third_party/spdy/core/array_output_buffer.cc", "third_party/spdy/core/array_output_buffer.h", "third_party/spdy/core/array_output_buffer_test.cc", @@ -6240,7 +6243,7 @@ fuzzer_test("net_http2_frame_decoder_fuzzer") { sources = [ - "third_party/http2/decoder/http2_frame_decoder_fuzzer.cc", + "spdy/fuzzing/http2_frame_decoder_fuzzer.cc", ] deps = [ ":net_fuzzer_test_support", @@ -6252,7 +6255,7 @@ fuzzer_test("net_hpack_decoder_fuzzer") { sources = [ - "third_party/http2/hpack/decoder/hpack_decoder_fuzzer.cc", + "spdy/fuzzing/hpack_decoder_fuzzer.cc", ] deps = [ ":net_fuzzer_test_support",
diff --git a/net/base/escape.cc b/net/base/escape.cc index 39c0eae..103e6f4 100644 --- a/net/base/escape.cc +++ b/net/base/escape.cc
@@ -390,11 +390,10 @@ 0xffffffffL, 0xffffffffL, 0xffffffffL, 0xffffffffL }}; -// non-7bit -static const Charmap kNonASCIICharmap = {{ - 0x00000000L, 0x00000000L, 0x00000000L, 0x00000000L, - 0xffffffffL, 0xffffffffL, 0xffffffffL, 0xffffffffL -}}; +// non-7bit, as well as %. +static const Charmap kNonASCIICharmapAndPercent = { + {0x00000000L, 0x00000020L, 0x00000000L, 0x00000000L, 0xffffffffL, + 0xffffffffL, 0xffffffffL, 0xffffffffL}}; // Everything except alphanumerics, the reserved characters(;/?:@&=+$,) and // !'()*-._~#[] @@ -427,8 +426,8 @@ return Escape(path, kUrlEscape, use_plus); } -std::string EscapeNonASCII(base::StringPiece input) { - return Escape(input, kNonASCIICharmap, false); +std::string EscapeNonASCIIAndPercent(base::StringPiece input) { + return Escape(input, kNonASCIICharmapAndPercent, false); } std::string EscapeExternalHandlerValue(base::StringPiece text) {
diff --git a/net/base/escape.h b/net/base/escape.h index 0dde0c4a..7a98ff8d 100644 --- a/net/base/escape.h +++ b/net/base/escape.h
@@ -47,8 +47,8 @@ NET_EXPORT std::string EscapeUrlEncodedData(base::StringPiece path, bool use_plus); -// Escapes all non-ASCII input. -NET_EXPORT std::string EscapeNonASCII(base::StringPiece input); +// Escapes all non-ASCII input, as well as escaping % to %25. +NET_EXPORT std::string EscapeNonASCIIAndPercent(base::StringPiece input); // Escapes characters in text suitable for use as an external protocol handler // command.
diff --git a/net/http/http_request_headers.cc b/net/http/http_request_headers.cc index 080772d..7ee9a40 100644 --- a/net/http/http_request_headers.cc +++ b/net/http/http_request_headers.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/logging.h" +#include "base/strings/strcat.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" @@ -14,6 +15,7 @@ #include "net/base/escape.h" #include "net/http/http_log_util.h" #include "net/http/http_util.h" +#include "net/log/net_log.h" #include "net/log/net_log_capture_mode.h" namespace net { @@ -186,15 +188,13 @@ const std::string* request_line, NetLogCaptureMode capture_mode) const { auto dict = std::make_unique<base::DictionaryValue>(); - dict->SetString("line", EscapeNonASCII(*request_line)); + dict->SetKey("line", NetLogStringValue(*request_line)); auto headers = std::make_unique<base::ListValue>(); for (auto it = headers_.begin(); it != headers_.end(); ++it) { std::string log_value = ElideHeaderValueForNetLog(capture_mode, it->key, it->value); - std::string escaped_name = EscapeNonASCII(it->key); - std::string escaped_value = EscapeNonASCII(log_value); - headers->AppendString(base::StringPrintf("%s: %s", escaped_name.c_str(), - escaped_value.c_str())); + headers->GetList().push_back( + NetLogStringValue(base::StrCat({it->key, ": ", log_value}))); } dict->Set("headers", std::move(headers)); return std::move(dict);
diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc index def138fb..2c034e1 100644 --- a/net/http/http_response_headers.cc +++ b/net/http/http_response_headers.cc
@@ -19,6 +19,7 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/pickle.h" +#include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" @@ -30,6 +31,7 @@ #include "net/http/http_byte_range.h" #include "net/http/http_log_util.h" #include "net/http/http_util.h" +#include "net/log/net_log.h" #include "net/log/net_log_capture_mode.h" using base::StringPiece; @@ -917,10 +919,13 @@ } while (parsed_[i].value_begin == parsed_[i].value_end); if (location) { + base::StringPiece location_strpiece(parsed_[i].value_begin, + parsed_[i].value_end); // Escape any non-ASCII characters to preserve them. The server should // only be returning ASCII here, but for compat we need to do this. - *location = EscapeNonASCII( - std::string(parsed_[i].value_begin, parsed_[i].value_end)); + *location = base::IsStringASCII(location_strpiece) + ? location_strpiece.as_string() + : EscapeNonASCIIAndPercent(location_strpiece); } return true; @@ -1327,17 +1332,15 @@ NetLogCaptureMode capture_mode) const { auto dict = std::make_unique<base::DictionaryValue>(); auto headers = std::make_unique<base::ListValue>(); - headers->AppendString(EscapeNonASCII(GetStatusLine())); + headers->GetList().push_back(NetLogStringValue(GetStatusLine())); size_t iterator = 0; std::string name; std::string value; while (EnumerateHeaderLines(&iterator, &name, &value)) { std::string log_value = ElideHeaderValueForNetLog(capture_mode, name, value); - std::string escaped_name = EscapeNonASCII(name); - std::string escaped_value = EscapeNonASCII(log_value); - headers->AppendString(base::StringPrintf("%s: %s", escaped_name.c_str(), - escaped_value.c_str())); + headers->GetList().push_back( + NetLogStringValue(base::StrCat({name, ": ", log_value}))); } dict->Set("headers", std::move(headers)); return std::move(dict);
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index 4c4939e..8dd4c29 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -63010,6 +63010,9 @@ { "name": "typewritten.net", "policy": "custom", "mode": "force-https", "include_subdomains": true }, { "name": "airbnb.com", "policy": "custom", "mode": "force-https", "include_subdomains": true }, { "name": "airbnb.tools", "policy": "custom", "mode": "force-https", "include_subdomains": true }, + { "name": "account.bbc.com", "policy": "custom", "mode": "force-https", "include_subdomains": true }, + { "name": "session.bbc.com", "policy": "custom", "mode": "force-https", "include_subdomains": true }, + { "name": "session.bbc.co.uk", "policy": "custom", "mode": "force-https", "include_subdomains": true }, // IP Address { "name": "1.0.0.1", "policy": "custom", "mode": "force-https", "include_subdomains": false }, // No subdomains
diff --git a/net/http2/platform/impl/http2_arraysize_impl.h b/net/http2/platform/impl/http2_arraysize_impl.h new file mode 100644 index 0000000..5a927234 --- /dev/null +++ b/net/http2/platform/impl/http2_arraysize_impl.h
@@ -0,0 +1,12 @@ +// 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 NET_HTTP2_PLATFORM_IMPL_HTTP2_ARRAYSIZE_IMPL_H_ +#define NET_HTTP2_PLATFORM_IMPL_HTTP2_ARRAYSIZE_IMPL_H_ + +#include "base/stl_util.h" + +#define HTTP2_ARRAYSIZE_IMPL(x) base::size(x) + +#endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_ARRAYSIZE_IMPL_H_
diff --git a/net/http2/platform/impl/http2_bug_tracker_impl.h b/net/http2/platform/impl/http2_bug_tracker_impl.h new file mode 100644 index 0000000..8ee3bd0 --- /dev/null +++ b/net/http2/platform/impl/http2_bug_tracker_impl.h
@@ -0,0 +1,14 @@ +// Copyright 2016 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 NET_HTTP2_PLATFORM_IMPL_HTTP2_BUG_TRACKER_IMPL_H_ +#define NET_HTTP2_PLATFORM_IMPL_HTTP2_BUG_TRACKER_IMPL_H_ + +#include "base/logging.h" + +#define HTTP2_BUG_IMPL LOG(DFATAL) +#define HTTP2_BUG_IF_IMPL LOG_IF(DFATAL, (condition)) +#define FLAGS_http2_always_log_bugs_for_tests_IMPL (true) + +#endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_BUG_TRACKER_IMPL_H_
diff --git a/net/http2/platform/impl/http2_containers_impl.h b/net/http2/platform/impl/http2_containers_impl.h new file mode 100644 index 0000000..51044a5e --- /dev/null +++ b/net/http2/platform/impl/http2_containers_impl.h
@@ -0,0 +1,17 @@ +// Copyright (c) 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 NET_HTTP2_PLATFORM_IMPL_HTTP2_CONTAINERS_IMPL_H_ +#define NET_HTTP2_PLATFORM_IMPL_HTTP2_CONTAINERS_IMPL_H_ + +#include "base/containers/circular_deque.h" + +namespace http2 { + +template <typename T> +using Http2DequeImpl = base::circular_deque<T>; + +} + +#endif /* NET_HTTP2_PLATFORM_IMPL_HTTP2_CONTAINERS_IMPL_H_ */
diff --git a/net/http2/platform/impl/http2_estimate_memory_usage_impl.h b/net/http2/platform/impl/http2_estimate_memory_usage_impl.h new file mode 100644 index 0000000..4581adc --- /dev/null +++ b/net/http2/platform/impl/http2_estimate_memory_usage_impl.h
@@ -0,0 +1,21 @@ +// Copyright 2017 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 NET_HTTP2_PLATFORM_IMPL_HTTP2_ESTIMATE_MEMORY_USAGE_IMPL_H_ +#define NET_HTTP2_PLATFORM_IMPL_HTTP2_ESTIMATE_MEMORY_USAGE_IMPL_H_ + +#include <cstddef> + +#include "base/trace_event/memory_usage_estimator.h" + +namespace http2 { + +template <class T> +size_t Http2EstimateMemoryUsageImpl(const T& object) { + return base::trace_event::EstimateMemoryUsage(object); +} + +} // namespace http2 + +#endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_ESTIMATE_MEMORY_USAGE_IMPL_H_
diff --git a/net/http2/platform/impl/http2_export_impl.h b/net/http2/platform/impl/http2_export_impl.h new file mode 100644 index 0000000..f2321c6 --- /dev/null +++ b/net/http2/platform/impl/http2_export_impl.h
@@ -0,0 +1,13 @@ +// Copyright 2017 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 NET_HTTP2_PLATFORM_IMPL_HTTP2_EXPORT_IMPL_H_ +#define NET_HTTP2_PLATFORM_IMPL_HTTP2_EXPORT_IMPL_H_ + +#include "net/base/net_export.h" + +#define HTTP2_EXPORT NET_EXPORT +#define HTTP2_EXPORT_PRIVATE NET_EXPORT_PRIVATE + +#endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_EXPORT_IMPL_H_
diff --git a/net/http2/platform/impl/http2_flag_utils_impl.h b/net/http2/platform/impl/http2_flag_utils_impl.h new file mode 100644 index 0000000..73b8718 --- /dev/null +++ b/net/http2/platform/impl/http2_flag_utils_impl.h
@@ -0,0 +1,13 @@ +// 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 NET_HTTP2_PLATFORM_IMPL_HTTP2_FLAG_UTILS_IMPL_H_ +#define NET_HTTP2_PLATFORM_IMPL_HTTP2_FLAG_UTILS_IMPL_H_ + +#include "base/logging.h" + +#define HTTP2_RELOADABLE_FLAG_COUNT_IMPL(flag) \ + DVLOG(1) << "FLAG_" #flag ": " << FLAGS_##flag + +#endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_FLAG_UTILS_IMPL_H_
diff --git a/net/http2/platform/impl/http2_flags_impl.cc b/net/http2/platform/impl/http2_flags_impl.cc new file mode 100644 index 0000000..21704559 --- /dev/null +++ b/net/http2/platform/impl/http2_flags_impl.cc
@@ -0,0 +1,7 @@ +// 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 "net/http2/platform/impl/http2_flags_impl.h" + +bool FLAGS_http2_varint_decode_64_bits = true;
diff --git a/net/http2/platform/impl/http2_flags_impl.h b/net/http2/platform/impl/http2_flags_impl.h new file mode 100644 index 0000000..e9dbdc0 --- /dev/null +++ b/net/http2/platform/impl/http2_flags_impl.h
@@ -0,0 +1,31 @@ +// 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 NET_HTTP2_PLATFORM_IMPL_HTTP2_FLAGS_IMPL_H_ +#define NET_HTTP2_PLATFORM_IMPL_HTTP2_FLAGS_IMPL_H_ + +#include "net/third_party/quiche/src/http2/platform/api/http2_export.h" + +HTTP2_EXPORT_PRIVATE extern bool FLAGS_http2_varint_decode_64_bits; + +namespace http2 { + +inline bool GetHttp2FlagImpl(bool flag) { + return flag; +} + +inline void SetHttp2FlagImpl(bool* f, bool v) { + *f = v; +} + +#define HTTP2_RELOADABLE_FLAG(flag) FLAGS_##flag + +#define GetHttp2ReloadableFlagImpl(flag) \ + GetHttp2FlagImpl(HTTP2_RELOADABLE_FLAG(flag)) +#define SetHttp2ReloadableFlagImpl(flag, value) \ + SetHttp2FlagImpl(&HTTP2_RELOADABLE_FLAG(flag), value) + +} // namespace http2 + +#endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_FLAGS_IMPL_H_
diff --git a/net/http2/platform/impl/http2_macros_impl.h b/net/http2/platform/impl/http2_macros_impl.h new file mode 100644 index 0000000..17628d3 --- /dev/null +++ b/net/http2/platform/impl/http2_macros_impl.h
@@ -0,0 +1,15 @@ +// Copyright (c) 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 NET_HTTP2_PLATFORM_IMPL_HTTP2_MACROS_IMPL_H_ +#define NET_HTTP2_PLATFORM_IMPL_HTTP2_MACROS_IMPL_H_ + +#include "base/compiler_specific.h" +#include "base/logging.h" + +#define HTTP2_FALLTHROUGH_IMPL FALLTHROUGH +#define HTTP2_UNREACHABLE_IMPL() DCHECK(false) +#define HTTP2_DIE_IF_NULL_IMPL(ptr) (ptr) + +#endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_MACROS_IMPL_H_
diff --git a/net/http2/platform/impl/http2_mock_log_impl.h b/net/http2/platform/impl/http2_mock_log_impl.h new file mode 100644 index 0000000..254f56d --- /dev/null +++ b/net/http2/platform/impl/http2_mock_log_impl.h
@@ -0,0 +1,22 @@ +// 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 NET_HTTP2_PLATFORM_IMPL_HTTP2_MOCK_LOG_IMPL_H_ +#define NET_HTTP2_PLATFORM_IMPL_HTTP2_MOCK_LOG_IMPL_H_ + +#include "base/test/mock_log.h" +#include "testing/gmock/include/gmock/gmock.h" // IWYU pragma: export + +using Http2MockLogImpl = base::test::MockLog; +#define CREATE_HTTP2_MOCK_LOG_IMPL(log) Http2MockLog log + +#define EXPECT_HTTP2_LOG_CALL_IMPL(log) \ + EXPECT_CALL(log, \ + Log(testing::_, testing::_, testing::_, testing::_, testing::_)) + +#define EXPECT_HTTP2_LOG_CALL_CONTAINS_IMPL(log, level, content) \ + EXPECT_CALL(log, Log(logging::LOG_##level, testing::_, testing::_, \ + testing::_, testing::HasSubstr(content))) + +#endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_MOCK_LOG_IMPL_H_
diff --git a/net/http2/platform/impl/http2_optional_impl.h b/net/http2/platform/impl/http2_optional_impl.h new file mode 100644 index 0000000..f6d5703 --- /dev/null +++ b/net/http2/platform/impl/http2_optional_impl.h
@@ -0,0 +1,17 @@ +// 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 NET_HTTP2_PLATFORM_IMPL_HTTP2_OPTIONAL_IMPL_H_ +#define NET_HTTP2_PLATFORM_IMPL_HTTP2_OPTIONAL_IMPL_H_ + +#include "base/optional.h" + +namespace http2 { + +template <typename T> +using Http2OptionalImpl = base::Optional<T>; + +} // namespace http2 + +#endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_OPTIONAL_IMPL_H_
diff --git a/net/http2/platform/impl/http2_ptr_util_impl.h b/net/http2/platform/impl/http2_ptr_util_impl.h new file mode 100644 index 0000000..af84848 --- /dev/null +++ b/net/http2/platform/impl/http2_ptr_util_impl.h
@@ -0,0 +1,20 @@ +// 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 NET_HTTP2_PLATFORM_IMPL_HTTP2_PTR_UTIL_IMPL_H_ +#define NET_HTTP2_PLATFORM_IMPL_HTTP2_PTR_UTIL_IMPL_H_ + +#include <memory> +#include <utility> + +namespace http2 { + +template <typename T, typename... Args> +std::unique_ptr<T> Http2MakeUniqueImpl(Args&&... args) { + return std::make_unique<T>(std::forward<Args>(args)...); +} + +} // namespace http2 + +#endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_PTR_UTIL_IMPL_H_
diff --git a/net/http2/platform/impl/http2_reconstruct_object_impl.h b/net/http2/platform/impl/http2_reconstruct_object_impl.h new file mode 100644 index 0000000..4f4588fe --- /dev/null +++ b/net/http2/platform/impl/http2_reconstruct_object_impl.h
@@ -0,0 +1,34 @@ +// Copyright 2017 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 NET_HTTP2_PLATFORM_IMPL_HTTP2_RECONSTRUCT_OBJECT_IMPL_H_ +#define NET_HTTP2_PLATFORM_IMPL_HTTP2_RECONSTRUCT_OBJECT_IMPL_H_ + +#include <utility> + +namespace http2 { +namespace test { + +class Http2Random; + +// Reconstruct an object so that it is initialized as when it was first +// constructed. Runs the destructor to handle objects that might own resources, +// and runs the constructor with the provided arguments, if any. +template <class T, class... Args> +void Http2ReconstructObjectImpl(T* ptr, Http2Random* rng, Args&&... args) { + ptr->~T(); + ::new (ptr) T(std::forward<Args>(args)...); +} + +// This version applies default-initialization to the object. +template <class T> +void Http2DefaultReconstructObjectImpl(T* ptr, Http2Random* rng) { + ptr->~T(); + ::new (ptr) T; +} + +} // namespace test +} // namespace http2 + +#endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_RECONSTRUCT_OBJECT_IMPL_H_
diff --git a/net/http2/platform/impl/http2_string_impl.h b/net/http2/platform/impl/http2_string_impl.h new file mode 100644 index 0000000..1379674c --- /dev/null +++ b/net/http2/platform/impl/http2_string_impl.h
@@ -0,0 +1,16 @@ +// Copyright (c) 2017 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 NET_HTTP2_PLATFORM_IMPL_HTTP2_STRING_IMPL_H_ +#define NET_HTTP2_PLATFORM_IMPL_HTTP2_STRING_IMPL_H_ + +#include <string> + +namespace http2 { + +using Http2StringImpl = std::string; + +} // namespace http2 + +#endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_STRING_IMPL_H_
diff --git a/net/http2/platform/impl/http2_string_piece_impl.h b/net/http2/platform/impl/http2_string_piece_impl.h new file mode 100644 index 0000000..b952c5e --- /dev/null +++ b/net/http2/platform/impl/http2_string_piece_impl.h
@@ -0,0 +1,16 @@ +// Copyright (c) 2017 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 NET_HTTP2_PLATFORM_IMPL_HTTP2_STRING_PIECE_IMPL_H_ +#define NET_HTTP2_PLATFORM_IMPL_HTTP2_STRING_PIECE_IMPL_H_ + +#include "base/strings/string_piece.h" + +namespace http2 { + +using Http2StringPieceImpl = base::StringPiece; + +} // namespace http2 + +#endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_STRING_PIECE_IMPL_H_
diff --git a/net/http2/platform/impl/http2_string_utils_impl.h b/net/http2/platform/impl/http2_string_utils_impl.h new file mode 100644 index 0000000..5b648b0 --- /dev/null +++ b/net/http2/platform/impl/http2_string_utils_impl.h
@@ -0,0 +1,65 @@ +// Copyright 2017 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 NET_HTTP2_PLATFORM_IMPL_HTTP2_STRING_UTILS_IMPL_H_ +#define NET_HTTP2_PLATFORM_IMPL_HTTP2_STRING_UTILS_IMPL_H_ + +#include <sstream> +#include <utility> + +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "net/base/escape.h" +#include "net/base/hex_utils.h" +#include "net/third_party/quiche/src/http2/platform/api/http2_export.h" +#include "net/third_party/quiche/src/http2/platform/api/http2_string.h" +#include "net/third_party/quiche/src/http2/platform/api/http2_string_piece.h" + +namespace http2 { + +template <typename... Args> +inline Http2String Http2StrCatImpl(const Args&... args) { + std::ostringstream oss; + int dummy[] = {1, (oss << args, 0)...}; + static_cast<void>(dummy); + return oss.str(); +} + +template <typename... Args> +inline void Http2StrAppendImpl(Http2String* output, Args... args) { + output->append(Http2StrCatImpl(args...)); +} + +template <typename... Args> +inline Http2String Http2StringPrintfImpl(const Args&... args) { + return base::StringPrintf(std::forward<const Args&>(args)...); +} + +inline Http2String Http2HexEncodeImpl(const void* bytes, size_t size) { + return base::HexEncode(bytes, size); +} + +inline Http2String Http2HexDecodeImpl(Http2StringPiece data) { + return net::HexDecode(data); +} + +inline Http2String Http2HexDumpImpl(Http2StringPiece data) { + return net::HexDump(data); +} + +inline Http2String Http2HexEscapeImpl(Http2StringPiece data) { + return net::EscapeQueryParamValue(data, false); +} + +template <typename Number> +inline Http2String Http2HexImpl(Number number) { + std::stringstream str; + str << std::hex << number; + return str.str(); +} + +} // namespace http2 + +#endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_STRING_UTILS_IMPL_H_
diff --git a/net/http2/platform/impl/http2_test_helpers_impl.cc b/net/http2/platform/impl/http2_test_helpers_impl.cc new file mode 100644 index 0000000..a00de1e --- /dev/null +++ b/net/http2/platform/impl/http2_test_helpers_impl.cc
@@ -0,0 +1,29 @@ +// Copyright 2016 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 "net/third_party/quiche/src/http2/platform/api/http2_test_helpers.h" + +namespace http2 { +namespace test { + +// This is a copy of the same named method in ::testing::internal. +// TODO(jamessynge): See about getting something like VERIFY_* adopted by +// gUnit (probably a very difficult task!). +Http2String GetBoolAssertionFailureMessage( + const ::testing::AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value) { + const char* actual_message = assertion_result.message(); + ::testing::Message msg; + msg << "Value of: " << expression_text + << "\n Actual: " << actual_predicate_value; + if (actual_message[0] != '\0') + msg << " (" << actual_message << ")"; + msg << "\nExpected: " << expected_predicate_value; + return msg.GetString(); +} + +} // namespace test +} // namespace http2
diff --git a/net/http2/platform/impl/http2_test_helpers_impl.h b/net/http2/platform/impl/http2_test_helpers_impl.h new file mode 100644 index 0000000..535b2171 --- /dev/null +++ b/net/http2/platform/impl/http2_test_helpers_impl.h
@@ -0,0 +1,167 @@ +// Copyright 2016 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 NET_HTTP2_PLATFORM_IMPL_HTTP2_TEST_HELPERS_IMPL_H_ +#define NET_HTTP2_PLATFORM_IMPL_HTTP2_TEST_HELPERS_IMPL_H_ + +// Defines VERIFY_* macros, analogous to gUnit's EXPECT_* and ASSERT_* macros, +// but these return an appropriate AssertionResult if the condition is not +// satisfied. This enables one to create a function for verifying expectations +// that are needed by multiple callers or that rely on arguments not accessible +// to the main test method. Using VERIFY_SUCCESS allows one to annotate the +// a failing AssertionResult with more context. + +#include <iosfwd> +#include <sstream> + +#include "net/test/gtest_util.h" +#include "net/third_party/quiche/src/http2/platform/api/http2_string.h" +#include "testing/gmock/include/gmock/gmock-matchers.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace http2 { +namespace test { + +template <typename T> +class VerifyThatHelper { + public: + VerifyThatHelper(const T& value, ::testing::Matcher<T> matcher) { + matches_ = matcher.Matches(value); + if (!matches_) { + printed_value_ = ::testing::PrintToString(value); + + std::ostringstream os; + matcher.DescribeTo(&os); + matcher_description_ = os.str(); + } + } + + VerifyThatHelper(const VerifyThatHelper&) = delete; + VerifyThatHelper& operator=(const VerifyThatHelper&) = delete; + + operator bool() const { return matches_; } + + const Http2String& printed_value() const { return printed_value_; } + const Http2String& matcher_description() const { + return matcher_description_; + } + + private: + bool matches_; + Http2String printed_value_; + Http2String matcher_description_; +}; + +// Constructs a failure message for Boolean assertions such as VERIFY_TRUE. +Http2String GetBoolAssertionFailureMessage( + const ::testing::AssertionResult& assertion_result, + const char* expression_text, + const char* actual_predicate_value, + const char* expected_predicate_value); + +namespace { +// Define HasSubstr() for Http2StringPiece arguments. +// This shadows ::testing::HasSubstr(), which only works on argument types +// that can be implicitly converted to a Http2String. +inline ::testing::PolymorphicMatcher<net::test::StringPieceHasSubstrMatcher> +HasSubstr(const Http2String& substring) { + return ::testing::MakePolymorphicMatcher( + net::test::StringPieceHasSubstrMatcher(substring)); +} +} // namespace + +} // namespace test +} // namespace http2 + +// Macro for adding verification location to output stream or AssertionResult. +// Starts with a new-line because of the way that gUnit displays failures for +// EXPECT_TRUE(CallToFunctionThatFailsToVerify()). +#define VERIFY_FAILED_LOCATION_ \ + "\n" \ + << "(VERIFY failed in " << __func__ << "\n" \ + << " at " __FILE__ " : " << __LINE__ << ")\n" + +// Implements Boolean test verifications VERIFY_TRUE and VERIFY_FALSE. +// text is a textual represenation of expression as it was passed into +// VERIFY_TRUE or VERIFY_FALSE. +// clang-format off +#define VERIFY_TEST_BOOLEAN_(condition, text, actual, expected) \ + if (const ::testing::AssertionResult __assertion_result = \ + ::testing::AssertionResult((condition) ? expected : actual)) \ + ; \ + else \ + return ::testing::AssertionFailure() \ + << VERIFY_FAILED_LOCATION_ \ + << ::http2::test::GetBoolAssertionFailureMessage( \ + __assertion_result, text, #actual, #expected) +// clang-format on + +// Boolean assertions. condition can be either a Boolean expression or an +// expression convertable to a boolean (such as a ::gtl::labs::optional). +#define VERIFY_TRUE(condition) \ + VERIFY_TEST_BOOLEAN_(condition, #condition, false, true) + +#define VERIFY_FALSE(condition) \ + VERIFY_TEST_BOOLEAN_(condition, #condition, true, false) + +// Convenient helper macro for writing methods that return an AssertionFailure +// that includes the tested condition in the message (in the manner of +// ASSERT_THAT and EXPECT_THAT). +// +// This macro avoids the do {} while(false) trick and putting braces around +// the if so you can do things like: +// VERIFY_THAT(foo, Lt(4)) << "foo too big in iteration " << i; +// (This parallels the implementation of CHECK().) +// +// We use an if statement with an empty true branch so that this doesn't eat +// a neighboring else when used in an unbraced if statement like: +// if (condition) +// VERIFY_THAT(foo, Eq(bar)); +// else +// FAIL(); +#define VERIFY_THAT(value, matcher) \ + if (const auto& _verify_that_helper = \ + ::http2::test::VerifyThatHelper<decltype(value)>(value, matcher)) \ + ; \ + else \ + return ::testing::AssertionFailure() \ + << "Failed to verify that '" #value "' (" \ + << _verify_that_helper.printed_value() << ") " \ + << _verify_that_helper.matcher_description() \ + << " (on " __FILE__ ":" << __LINE__ << "). " + +// Useful variants of VERIFY_THAT, similar to the corresponding EXPECT_X or +// ASSERT_X defined by gUnit. +#define VERIFY_EQ(val1, val2) VERIFY_THAT(val1, ::testing::Eq(val2)) +#define VERIFY_NE(val1, val2) VERIFY_THAT(val1, ::testing::Ne(val2)) +#define VERIFY_GT(val1, val2) VERIFY_THAT(val1, ::testing::Gt(val2)) +#define VERIFY_LT(val1, val2) VERIFY_THAT(val1, ::testing::Lt(val2)) +#define VERIFY_GE(val1, val2) VERIFY_THAT(val1, ::testing::Ge(val2)) +#define VERIFY_LE(val1, val2) VERIFY_THAT(val1, ::testing::Le(val2)) + +// Convenience macro matching EXPECT_OK +#define VERIFY_OK(statement) VERIFY_EQ(::util::Status::OK, (statement)) + +// This version verifies that an expression of type AssertionResult is +// AssertionSuccess. If instead the value is an AssertionFailure, it appends +// info about the current code location to the failure's message and returns +// the failure to the caller of the current method. It permits the code site +// to append further messages to the failure message. For example: +// VERIFY_SUCCESS(SomeCall()) << "Some more context about SomeCall"; +// clang-format off +#define VERIFY_SUCCESS(expr) \ + if (::testing::AssertionResult __assertion_result = (expr)) \ + ; \ + else \ + return __assertion_result << VERIFY_FAILED_LOCATION_ +// clang-format on + +#define VERIFY_AND_RETURN_SUCCESS(expression) \ + { \ + VERIFY_SUCCESS(expression); \ + return ::testing::AssertionSuccess(); \ + } + +#endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_TEST_HELPERS_IMPL_H_
diff --git a/net/log/net_log.cc b/net/log/net_log.cc index 40a7d18f..b49fcfc6 100644 --- a/net/log/net_log.cc +++ b/net/log/net_log.cc
@@ -13,8 +13,10 @@ #include "base/logging.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" +#include "net/base/escape.h" namespace net { @@ -297,4 +299,19 @@ observer->OnAddEntryData(entry_data); } +base::Value NetLogStringValue(base::StringPiece raw) { + // The common case is that |raw| is ASCII. Represent this directly. + if (base::IsStringASCII(raw)) + return base::Value(raw); + + // For everything else (including valid UTF-8) percent-escape |raw|, and add a + // prefix that "tags" the value as being a percent-escaped representation. + // + // Note that the sequence E2 80 8B is U+200B (zero-width space) in UTF-8. It + // is added so the escaped string is not itself also ASCII (otherwise there + // would be ambiguity for consumers as to when the value needs to be + // unescaped). + return base::Value("%ESCAPED:\xE2\x80\x8B " + EscapeNonASCIIAndPercent(raw)); +} + } // namespace net
diff --git a/net/log/net_log.h b/net/log/net_log.h index 425c7ca..e2c46112 100644 --- a/net/log/net_log.h +++ b/net/log/net_log.h
@@ -237,6 +237,18 @@ DISALLOW_COPY_AND_ASSIGN(NetLog); }; +// Creates a base::Value() to represent the byte string |raw| when adding it to +// the NetLog. +// +// When |raw| is an ASCII string, the returned value is a base::Value() +// containing that exact string. Otherwise it is represented by a +// percent-escaped version of the original string, along with a special prefix. +// +// This wrapper exists because base::Value strings are required to be UTF-8. +// Often times NetLog consumers just want to log a std::string, and that string +// may not be UTF-8. +NET_EXPORT base::Value NetLogStringValue(base::StringPiece raw); + } // namespace net #endif // NET_LOG_NET_LOG_H_
diff --git a/net/log/net_log_unittest.cc b/net/log/net_log_unittest.cc index b9763ac..1384106c 100644 --- a/net/log/net_log_unittest.cc +++ b/net/log/net_log_unittest.cc
@@ -399,6 +399,43 @@ RunTestThreads<AddRemoveObserverTestThread>(&net_log); } +// Calls NetLogASCIIStringValue() on |raw| and returns the resulting string +// (rather than the base::Value). +std::string GetNetLogString(base::StringPiece raw) { + base::Value value = NetLogStringValue(raw); + std::string result; + EXPECT_TRUE(value.GetAsString(&result)); + return result; +} + +TEST(NetLogTest, NetLogASCIIStringValue) { + // ASCII strings should not be transformed. + EXPECT_EQ("ascii\nstrin\0g", GetNetLogString("ascii\nstrin\0g")); + + // Non-ASCII UTF-8 strings should be escaped. + EXPECT_EQ("%ESCAPED:\xE2\x80\x8B utf-8 string %E2%98%83", + GetNetLogString("utf-8 string \xE2\x98\x83")); + + // The presence of percent should not trigger escaping. + EXPECT_EQ("%20", GetNetLogString("%20")); + + // However if the value to be escaped contains percent, it should be escaped + // (so can unescape to restore the original string). + EXPECT_EQ("%ESCAPED:\xE2\x80\x8B %E2%98%83 %2520", + GetNetLogString("\xE2\x98\x83 %20")); + + // Test that when percent escaping, no ASCII value is escaped (excluding %). + for (uint8_t c = 0; c <= 0x7F; ++c) { + if (c == '%') + continue; + + std::string s; + s.push_back(c); + + EXPECT_EQ("%ESCAPED:\xE2\x80\x8B %E2 " + s, GetNetLogString("\xE2 " + s)); + } +} + } // namespace } // namespace net
diff --git a/net/proxy_resolution/proxy_list.cc b/net/proxy_resolution/proxy_list.cc index 2c4ba1a..5b397f3 100644 --- a/net/proxy_resolution/proxy_list.cc +++ b/net/proxy_resolution/proxy_list.cc
@@ -106,7 +106,7 @@ } const ProxyServer& ProxyList::Get() const { - DCHECK(!proxies_.empty()); + CHECK(!proxies_.empty()); return proxies_[0]; }
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index d5e9442..9d70a559 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -107,12 +107,9 @@ NUM_LOCATIONS); } -std::unique_ptr<base::Value> NetLogQuicConnectionMigrationTriggerCallback( - std::string trigger, - NetLogCaptureMode capture_mode) { - std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); - dict->SetString("trigger", trigger); - return std::move(dict); +NetLogParametersCallback NetLogQuicConnectionMigrationTriggerCallback( + const char* trigger) { + return NetLog::StringCallback("trigger", trigger); } std::unique_ptr<base::Value> NetLogQuicConnectionMigrationFailureCallback( @@ -1761,7 +1758,7 @@ net_log_.net_log(), NetLogSourceType::QUIC_CONNECTION_MIGRATION); migration_net_log.BeginEvent( NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED, - base::Bind(&NetLogQuicConnectionMigrationTriggerCallback, "WriteError")); + NetLogQuicConnectionMigrationTriggerCallback("WriteError")); MigrationResult result = Migrate(new_network, connection()->peer_address().impl().socket_address(), /*close_session_on_error=*/false, migration_net_log); @@ -2161,8 +2158,7 @@ net_log_.net_log(), NetLogSourceType::QUIC_CONNECTION_MIGRATION); migration_net_log.BeginEvent( NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED, - base::Bind(&NetLogQuicConnectionMigrationTriggerCallback, - "PathDegrading")); + NetLogQuicConnectionMigrationTriggerCallback("PathDegrading")); // Probe alternative network, session will migrate to the probed // network and decide whether it wants to migrate back to the default // network on success.
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index b16e1fb8..710197d 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc
@@ -113,24 +113,19 @@ return std::move(dict); } -std::unique_ptr<base::Value> NetLogQuicConnectionMigrationTriggerCallback( - std::string trigger, - NetLogCaptureMode capture_mode) { - std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); - dict->SetString("trigger", trigger); - return std::move(dict); +NetLogParametersCallback NetLogQuicConnectionMigrationTriggerCallback( + const char* trigger) { + return NetLog::StringCallback("trigger", trigger); } - // Helper class that is used to log a connection migration event. class ScopedConnectionMigrationEventLog { public: - ScopedConnectionMigrationEventLog(NetLog* net_log, std::string trigger) + ScopedConnectionMigrationEventLog(NetLog* net_log, const char* trigger) : net_log_(NetLogWithSource::Make( net_log, NetLogSourceType::QUIC_CONNECTION_MIGRATION)) { - net_log_.BeginEvent( - NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED, - base::Bind(&NetLogQuicConnectionMigrationTriggerCallback, trigger)); + net_log_.BeginEvent(NetLogEventType::QUIC_CONNECTION_MIGRATION_TRIGGERED, + NetLogQuicConnectionMigrationTriggerCallback(trigger)); } ~ScopedConnectionMigrationEventLog() {
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc index 27f6d9f..b4599e0 100644 --- a/net/quic/quic_stream_factory_test.cc +++ b/net/quic/quic_stream_factory_test.cc
@@ -3287,10 +3287,7 @@ // processing the initial connectivity probe response, which may cause a // connection being closed with INTERNAL_ERROR as pending ACK frame is not // allowed when processing a new packet. -// Test temporarily disabled so that it can be reworked to handle -// migration/etc with version 99 and sending an ACK+PING when -// migration is complete. -TEST_P(QuicStreamFactoryTest, DISABLED_MigrateToProbingSocket) { +TEST_P(QuicStreamFactoryTest, MigrateToProbingSocket) { InitializeConnectionMigrationV2Test( {kDefaultNetworkForTests, kNewNetworkForTests}); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
diff --git a/net/reporting/reporting_cache.cc b/net/reporting/reporting_cache.cc index 9756fc9..02f76b4c 100644 --- a/net/reporting/reporting_cache.cc +++ b/net/reporting/reporting_cache.cc
@@ -97,7 +97,7 @@ RemoveReportInternal(to_evict); } - context_->NotifyCacheUpdated(); + context_->NotifyCachedReportsUpdated(); } void GetReports( @@ -195,7 +195,7 @@ reports_[report]->attempts++; } - context_->NotifyCacheUpdated(); + context_->NotifyCachedReportsUpdated(); } void IncrementEndpointDeliveries(const url::Origin& origin, @@ -227,7 +227,7 @@ } } - context_->NotifyCacheUpdated(); + context_->NotifyCachedReportsUpdated(); } void RemoveAllReports(ReportingReport::Outcome outcome) override { @@ -244,7 +244,7 @@ for (const ReportingReport* report : reports_to_remove) RemoveReportInternal(report); - context_->NotifyCacheUpdated(); + context_->NotifyCachedReportsUpdated(); } void SetClient(const url::Origin& origin, @@ -282,7 +282,7 @@ RemoveClient(to_evict); } - context_->NotifyCacheUpdated(); + context_->NotifyCachedClientsUpdated(); } void MarkClientUsed(const ReportingClient* client) override { @@ -407,7 +407,7 @@ for (const ReportingClient* client : clients_to_remove) RemoveClient(client); - context_->NotifyCacheUpdated(); + context_->NotifyCachedClientsUpdated(); } void RemoveClientForOriginAndEndpoint(const url::Origin& origin, @@ -416,7 +416,7 @@ GetClientByOriginAndEndpoint(origin, endpoint); RemoveClient(client); - context_->NotifyCacheUpdated(); + context_->NotifyCachedClientsUpdated(); } void RemoveClientsForEndpoint(const GURL& endpoint) override { @@ -431,7 +431,7 @@ RemoveClient(client); if (!clients_to_remove.empty()) - context_->NotifyCacheUpdated(); + context_->NotifyCachedClientsUpdated(); } void RemoveAllClients() override { @@ -439,7 +439,7 @@ wildcard_clients_.clear(); client_metadata_.clear(); - context_->NotifyCacheUpdated(); + context_->NotifyCachedClientsUpdated(); } ClientStatistics GetStatisticsForOriginAndEndpoint(
diff --git a/net/reporting/reporting_cache_observer.cc b/net/reporting/reporting_cache_observer.cc new file mode 100644 index 0000000..444fdb97 --- /dev/null +++ b/net/reporting/reporting_cache_observer.cc
@@ -0,0 +1,17 @@ +// Copyright 2017 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 "net/reporting/reporting_cache_observer.h" + +namespace net { + +void ReportingCacheObserver::OnReportsUpdated() {} + +void ReportingCacheObserver::OnClientsUpdated() {} + +ReportingCacheObserver::ReportingCacheObserver() = default; + +ReportingCacheObserver::~ReportingCacheObserver() = default; + +} // namespace net
diff --git a/net/reporting/reporting_cache_observer.h b/net/reporting/reporting_cache_observer.h new file mode 100644 index 0000000..aec11835 --- /dev/null +++ b/net/reporting/reporting_cache_observer.h
@@ -0,0 +1,32 @@ +// Copyright 2017 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 NET_REPORTING_REPORTING_CACHE_OBSERVER_H_ +#define NET_REPORTING_REPORTING_CACHE_OBSERVER_H_ + +#include "base/macros.h" +#include "net/base/net_export.h" + +namespace net { + +class NET_EXPORT ReportingCacheObserver { + public: + // Called whenever any change is made to the reports in the ReportingCache. + virtual void OnReportsUpdated(); + + // Called whenever any change is made to the client entries in the + // ReportingCache. + virtual void OnClientsUpdated(); + + protected: + ReportingCacheObserver(); + + ~ReportingCacheObserver(); + + DISALLOW_COPY_AND_ASSIGN(ReportingCacheObserver); +}; + +} // namespace net + +#endif // NET_REPORTING_REPORTING_CACHE_OBSERVER_H_
diff --git a/net/reporting/reporting_cache_unittest.cc b/net/reporting/reporting_cache_unittest.cc index 93fd1e6..a6d1f6a3 100644 --- a/net/reporting/reporting_cache_unittest.cc +++ b/net/reporting/reporting_cache_unittest.cc
@@ -12,8 +12,8 @@ #include "base/test/values_test_util.h" #include "base/time/time.h" #include "base/values.h" +#include "net/reporting/reporting_cache_observer.h" #include "net/reporting/reporting_client.h" -#include "net/reporting/reporting_observer.h" #include "net/reporting/reporting_report.h" #include "net/reporting/reporting_test_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -23,16 +23,24 @@ namespace net { namespace { -class TestReportingObserver : public ReportingObserver { +class TestReportingCacheObserver : public ReportingCacheObserver { public: - TestReportingObserver() : cache_update_count_(0) {} + TestReportingCacheObserver() + : cached_reports_update_count_(0), cached_clients_update_count_(0) {} - void OnCacheUpdated() override { ++cache_update_count_; } + void OnReportsUpdated() override { ++cached_reports_update_count_; } + void OnClientsUpdated() override { ++cached_clients_update_count_; } - int cache_update_count() const { return cache_update_count_; } + int cached_reports_update_count() const { + return cached_reports_update_count_; + } + int cached_clients_update_count() const { + return cached_clients_update_count_; + } private: - int cache_update_count_; + int cached_reports_update_count_; + int cached_clients_update_count_; }; class ReportingCacheTest : public ReportingTestBase { @@ -43,12 +51,12 @@ policy.max_client_count = 5; UsePolicy(policy); - context()->AddObserver(&observer_); + context()->AddCacheObserver(&observer_); } - ~ReportingCacheTest() override { context()->RemoveObserver(&observer_); } + ~ReportingCacheTest() override { context()->RemoveCacheObserver(&observer_); } - TestReportingObserver* observer() { return &observer_; } + TestReportingCacheObserver* observer() { return &observer_; } size_t report_count() { std::vector<const ReportingReport*> reports; @@ -134,7 +142,7 @@ const base::TimeTicks kExpires2_ = kExpires1_ + base::TimeDelta::FromDays(7); private: - TestReportingObserver observer_; + TestReportingCacheObserver observer_; }; TEST_F(ReportingCacheTest, Reports) { @@ -144,7 +152,7 @@ cache()->AddReport(kUrl1_, kUserAgent_, kGroup1_, kType_, std::make_unique<base::DictionaryValue>(), 0, kNow_, 0); - EXPECT_EQ(1, observer()->cache_update_count()); + EXPECT_EQ(1, observer()->cached_reports_update_count()); cache()->GetReports(&reports); ASSERT_EQ(1u, reports.size()); @@ -161,7 +169,7 @@ EXPECT_FALSE(cache()->IsReportDoomedForTesting(report)); cache()->IncrementReportsAttempts(reports); - EXPECT_EQ(2, observer()->cache_update_count()); + EXPECT_EQ(2, observer()->cached_reports_update_count()); cache()->GetReports(&reports); ASSERT_EQ(1u, reports.size()); @@ -170,7 +178,7 @@ EXPECT_EQ(1, report->attempts); cache()->RemoveReports(reports, ReportingReport::Outcome::UNKNOWN); - EXPECT_EQ(3, observer()->cache_update_count()); + EXPECT_EQ(3, observer()->cached_reports_update_count()); cache()->GetReports(&reports); EXPECT_TRUE(reports.empty()); @@ -181,14 +189,14 @@ std::make_unique<base::DictionaryValue>(), 0, kNow_, 0); cache()->AddReport(kUrl1_, kUserAgent_, kGroup1_, kType_, std::make_unique<base::DictionaryValue>(), 0, kNow_, 0); - EXPECT_EQ(2, observer()->cache_update_count()); + EXPECT_EQ(2, observer()->cached_reports_update_count()); std::vector<const ReportingReport*> reports; cache()->GetReports(&reports); EXPECT_EQ(2u, reports.size()); cache()->RemoveAllReports(ReportingReport::Outcome::UNKNOWN); - EXPECT_EQ(3, observer()->cache_update_count()); + EXPECT_EQ(3, observer()->cached_reports_update_count()); cache()->GetReports(&reports); EXPECT_TRUE(reports.empty()); @@ -197,7 +205,7 @@ TEST_F(ReportingCacheTest, RemovePendingReports) { cache()->AddReport(kUrl1_, kUserAgent_, kGroup1_, kType_, std::make_unique<base::DictionaryValue>(), 0, kNow_, 0); - EXPECT_EQ(1, observer()->cache_update_count()); + EXPECT_EQ(1, observer()->cached_reports_update_count()); std::vector<const ReportingReport*> reports; cache()->GetReports(&reports); @@ -212,7 +220,7 @@ cache()->RemoveReports(reports, ReportingReport::Outcome::UNKNOWN); EXPECT_TRUE(cache()->IsReportPendingForTesting(reports[0])); EXPECT_TRUE(cache()->IsReportDoomedForTesting(reports[0])); - EXPECT_EQ(2, observer()->cache_update_count()); + EXPECT_EQ(2, observer()->cached_reports_update_count()); // After removing report, future calls to GetReports should not return it. std::vector<const ReportingReport*> visible_reports; @@ -228,7 +236,7 @@ TEST_F(ReportingCacheTest, RemoveAllPendingReports) { cache()->AddReport(kUrl1_, kUserAgent_, kGroup1_, kType_, std::make_unique<base::DictionaryValue>(), 0, kNow_, 0); - EXPECT_EQ(1, observer()->cache_update_count()); + EXPECT_EQ(1, observer()->cached_reports_update_count()); std::vector<const ReportingReport*> reports; cache()->GetReports(&reports); @@ -243,7 +251,7 @@ cache()->RemoveAllReports(ReportingReport::Outcome::UNKNOWN); EXPECT_TRUE(cache()->IsReportPendingForTesting(reports[0])); EXPECT_TRUE(cache()->IsReportDoomedForTesting(reports[0])); - EXPECT_EQ(2, observer()->cache_update_count()); + EXPECT_EQ(2, observer()->cached_reports_update_count()); // After removing report, future calls to GetReports should not return it. std::vector<const ReportingReport*> visible_reports; @@ -327,7 +335,7 @@ TEST_F(ReportingCacheTest, Endpoints) { SetClient(kOrigin1_, kEndpoint1_, false, kGroup1_, kExpires1_); - EXPECT_EQ(1, observer()->cache_update_count()); + EXPECT_EQ(1, observer()->cached_clients_update_count()); const ReportingClient* client = FindClientInCache(cache(), kOrigin1_, kEndpoint1_); @@ -339,7 +347,7 @@ EXPECT_EQ(kExpires1_, client->expires); SetClient(kOrigin1_, kEndpoint1_, true, kGroup2, kExpires2_); - EXPECT_EQ(2, observer()->cache_update_count()); + EXPECT_EQ(2, observer()->cached_clients_update_count()); client = FindClientInCache(cache(), kOrigin1_, kEndpoint1_); ASSERT_TRUE(client); @@ -350,7 +358,7 @@ EXPECT_EQ(kExpires2_, client->expires); cache()->RemoveClients(std::vector<const ReportingClient*>{client}); - EXPECT_EQ(3, observer()->cache_update_count()); + EXPECT_EQ(3, observer()->cached_clients_update_count()); client = FindClientInCache(cache(), kOrigin1_, kEndpoint1_); EXPECT_FALSE(client); @@ -374,10 +382,10 @@ SetClient(kOrigin1_, kEndpoint1_, false, kGroup1_, kExpires1_); SetClient(kOrigin1_, kEndpoint2_, false, kGroup2, kExpires1_); SetClient(kOrigin2_, kEndpoint1_, false, kGroup1_, kExpires1_); - EXPECT_EQ(3, observer()->cache_update_count()); + EXPECT_EQ(3, observer()->cached_clients_update_count()); cache()->RemoveClientForOriginAndEndpoint(kOrigin1_, kEndpoint1_); - EXPECT_EQ(4, observer()->cache_update_count()); + EXPECT_EQ(4, observer()->cached_clients_update_count()); std::vector<const ReportingClient*> clients; cache()->GetClientsForOriginAndGroup(kOrigin1_, kGroup1_, &clients); @@ -394,10 +402,10 @@ SetClient(kOrigin1_, kEndpoint1_, false, kGroup1_, kExpires1_); SetClient(kOrigin1_, kEndpoint2_, false, kGroup2, kExpires1_); SetClient(kOrigin2_, kEndpoint1_, false, kGroup1_, kExpires1_); - EXPECT_EQ(3, observer()->cache_update_count()); + EXPECT_EQ(3, observer()->cached_clients_update_count()); cache()->RemoveClientsForEndpoint(kEndpoint1_); - EXPECT_EQ(4, observer()->cache_update_count()); + EXPECT_EQ(4, observer()->cached_clients_update_count()); std::vector<const ReportingClient*> clients; cache()->GetClientsForOriginAndGroup(kOrigin1_, kGroup1_, &clients); @@ -461,10 +469,10 @@ TEST_F(ReportingCacheTest, RemoveAllClients) { SetClient(kOrigin1_, kEndpoint1_, false, kGroup1_, kExpires1_); SetClient(kOrigin2_, kEndpoint2_, false, kGroup1_, kExpires1_); - EXPECT_EQ(2, observer()->cache_update_count()); + EXPECT_EQ(2, observer()->cached_clients_update_count()); cache()->RemoveAllClients(); - EXPECT_EQ(3, observer()->cache_update_count()); + EXPECT_EQ(3, observer()->cached_clients_update_count()); std::vector<const ReportingClient*> clients; cache()->GetClients(&clients);
diff --git a/net/reporting/reporting_context.cc b/net/reporting/reporting_context.cc index 04ee3b5d..8dd28a4 100644 --- a/net/reporting/reporting_context.cc +++ b/net/reporting/reporting_context.cc
@@ -17,12 +17,12 @@ #include "net/base/backoff_entry.h" #include "net/base/rand_callback.h" #include "net/reporting/reporting_cache.h" +#include "net/reporting/reporting_cache_observer.h" #include "net/reporting/reporting_delegate.h" #include "net/reporting/reporting_delivery_agent.h" #include "net/reporting/reporting_endpoint_manager.h" #include "net/reporting/reporting_garbage_collector.h" #include "net/reporting/reporting_network_change_observer.h" -#include "net/reporting/reporting_observer.h" #include "net/reporting/reporting_policy.h" #include "net/reporting/reporting_uploader.h" @@ -55,19 +55,24 @@ ReportingContext::~ReportingContext() = default; -void ReportingContext::AddObserver(ReportingObserver* observer) { - DCHECK(!observers_.HasObserver(observer)); - observers_.AddObserver(observer); +void ReportingContext::AddCacheObserver(ReportingCacheObserver* observer) { + DCHECK(!cache_observers_.HasObserver(observer)); + cache_observers_.AddObserver(observer); } -void ReportingContext::RemoveObserver(ReportingObserver* observer) { - DCHECK(observers_.HasObserver(observer)); - observers_.RemoveObserver(observer); +void ReportingContext::RemoveCacheObserver(ReportingCacheObserver* observer) { + DCHECK(cache_observers_.HasObserver(observer)); + cache_observers_.RemoveObserver(observer); } -void ReportingContext::NotifyCacheUpdated() { - for (auto& observer : observers_) - observer.OnCacheUpdated(); +void ReportingContext::NotifyCachedReportsUpdated() { + for (auto& observer : cache_observers_) + observer.OnReportsUpdated(); +} + +void ReportingContext::NotifyCachedClientsUpdated() { + for (auto& observer : cache_observers_) + observer.OnClientsUpdated(); } ReportingContext::ReportingContext(const ReportingPolicy& policy,
diff --git a/net/reporting/reporting_context.h b/net/reporting/reporting_context.h index 0c63bba..2c27c75 100644 --- a/net/reporting/reporting_context.h +++ b/net/reporting/reporting_context.h
@@ -22,12 +22,12 @@ namespace net { class ReportingCache; +class ReportingCacheObserver; class ReportingDelegate; class ReportingDeliveryAgent; class ReportingEndpointManager; class ReportingGarbageCollector; class ReportingNetworkChangeObserver; -class ReportingObserver; class ReportingUploader; class URLRequestContext; @@ -57,10 +57,11 @@ return garbage_collector_.get(); } - void AddObserver(ReportingObserver* observer); - void RemoveObserver(ReportingObserver* observer); + void AddCacheObserver(ReportingCacheObserver* observer); + void RemoveCacheObserver(ReportingCacheObserver* observer); - void NotifyCacheUpdated(); + void NotifyCachedReportsUpdated(); + void NotifyCachedClientsUpdated(); protected: ReportingContext(const ReportingPolicy& policy, @@ -77,8 +78,8 @@ const base::TickClock* tick_clock_; std::unique_ptr<ReportingUploader> uploader_; - base::ObserverList<ReportingObserver, /* check_empty= */ true>::Unchecked - observers_; + base::ObserverList<ReportingCacheObserver, /* check_empty= */ true>::Unchecked + cache_observers_; std::unique_ptr<ReportingDelegate> delegate_;
diff --git a/net/reporting/reporting_delivery_agent.cc b/net/reporting/reporting_delivery_agent.cc index a0f87af..c6daa0ecbd 100644 --- a/net/reporting/reporting_delivery_agent.cc +++ b/net/reporting/reporting_delivery_agent.cc
@@ -17,9 +17,9 @@ #include "base/timer/timer.h" #include "base/values.h" #include "net/reporting/reporting_cache.h" +#include "net/reporting/reporting_cache_observer.h" #include "net/reporting/reporting_delegate.h" #include "net/reporting/reporting_endpoint_manager.h" -#include "net/reporting/reporting_observer.h" #include "net/reporting/reporting_report.h" #include "net/reporting/reporting_uploader.h" #include "url/gurl.h" @@ -52,26 +52,28 @@ } class ReportingDeliveryAgentImpl : public ReportingDeliveryAgent, - public ReportingObserver { + public ReportingCacheObserver { public: ReportingDeliveryAgentImpl(ReportingContext* context) : context_(context), timer_(std::make_unique<base::OneShotTimer>()), weak_factory_(this) { - context_->AddObserver(this); + context_->AddCacheObserver(this); } // ReportingDeliveryAgent implementation: - ~ReportingDeliveryAgentImpl() override { context_->RemoveObserver(this); } + ~ReportingDeliveryAgentImpl() override { + context_->RemoveCacheObserver(this); + } void SetTimerForTesting(std::unique_ptr<base::OneShotTimer> timer) override { DCHECK(!timer_->IsRunning()); timer_ = std::move(timer); } - // ReportingObserver implementation: - void OnCacheUpdated() override { + // ReportingCacheObserver implementation: + void OnReportsUpdated() override { if (CacheHasReports() && !timer_->IsRunning()) { SendReports(); StartTimer();
diff --git a/net/reporting/reporting_garbage_collector.cc b/net/reporting/reporting_garbage_collector.cc index e56cd904..62f9bb5 100644 --- a/net/reporting/reporting_garbage_collector.cc +++ b/net/reporting/reporting_garbage_collector.cc
@@ -11,8 +11,8 @@ #include "base/time/time.h" #include "base/timer/timer.h" #include "net/reporting/reporting_cache.h" +#include "net/reporting/reporting_cache_observer.h" #include "net/reporting/reporting_context.h" -#include "net/reporting/reporting_observer.h" #include "net/reporting/reporting_policy.h" #include "net/reporting/reporting_report.h" @@ -21,17 +21,17 @@ namespace { class ReportingGarbageCollectorImpl : public ReportingGarbageCollector, - public ReportingObserver { + public ReportingCacheObserver { public: ReportingGarbageCollectorImpl(ReportingContext* context) : context_(context), timer_(std::make_unique<base::OneShotTimer>()) { - context_->AddObserver(this); + context_->AddCacheObserver(this); } // ReportingGarbageCollector implementation: ~ReportingGarbageCollectorImpl() override { - context_->RemoveObserver(this); + context_->RemoveCacheObserver(this); } void SetTimerForTesting(std::unique_ptr<base::OneShotTimer> timer) override { @@ -39,7 +39,7 @@ } // ReportingObserver implementation: - void OnCacheUpdated() override { + void OnReportsUpdated() override { if (timer_->IsRunning()) return; @@ -67,12 +67,12 @@ } // Don't restart the timer on the garbage collector's own updates. - context_->RemoveObserver(this); + context_->RemoveCacheObserver(this); context_->cache()->RemoveReports(failed_reports, ReportingReport::Outcome::ERASED_FAILED); context_->cache()->RemoveReports(expired_reports, ReportingReport::Outcome::ERASED_EXPIRED); - context_->AddObserver(this); + context_->AddCacheObserver(this); } ReportingContext* context_;
diff --git a/net/reporting/reporting_observer.cc b/net/reporting/reporting_observer.cc deleted file mode 100644 index a37548c..0000000 --- a/net/reporting/reporting_observer.cc +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2017 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 "net/reporting/reporting_observer.h" - -namespace net { - -void ReportingObserver::OnCacheUpdated() {} - -ReportingObserver::ReportingObserver() = default; - -ReportingObserver::~ReportingObserver() = default; - -} // namespace net
diff --git a/net/reporting/reporting_observer.h b/net/reporting/reporting_observer.h deleted file mode 100644 index cb05389..0000000 --- a/net/reporting/reporting_observer.h +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2017 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 NET_REPORTING_REPORTING_OBSERVER_H_ -#define NET_REPORTING_REPORTING_OBSERVER_H_ - -#include "base/macros.h" -#include "net/base/net_export.h" - -namespace net { - -class NET_EXPORT ReportingObserver { - public: - // Called whenever any change is made to the ReportingCache. - virtual void OnCacheUpdated(); - - protected: - ReportingObserver(); - - ~ReportingObserver(); - - DISALLOW_COPY_AND_ASSIGN(ReportingObserver); -}; - -} // namespace net - -#endif // NET_REPORTING_REPORTING_OBSERVER_H_
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc index 2cb8747..858942e1 100644 --- a/net/socket/client_socket_pool_base_unittest.cc +++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -707,7 +707,10 @@ class ClientSocketPoolBaseTest : public TestWithScopedTaskEnvironment { protected: - ClientSocketPoolBaseTest() : params_(new TestSocketParams()) { + ClientSocketPoolBaseTest() + : TestWithScopedTaskEnvironment( + base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME), + params_(new TestSocketParams()) { connect_backup_jobs_enabled_ = internal::ClientSocketPoolBaseHelper::connect_backup_jobs_enabled(); internal::ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(true); @@ -820,7 +823,7 @@ &client_socket_factory_, &log); ASSERT_THAT(job->Connect(), IsError(ERR_IO_PENDING)); - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); + FastForwardBy(base::TimeDelta::FromMilliseconds(1)); EXPECT_THAT(delegate.WaitForResult(), IsError(ERR_TIMED_OUT)); TestNetLogEntry::List entries; @@ -1169,8 +1172,7 @@ // actually become pending until 2ms after they have been created. In order // to flush all tasks, we need to wait so that we know there are no // soon-to-be-pending tasks waiting. - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); - base::RunLoop().RunUntilIdle(); + FastForwardBy(base::TimeDelta::FromMilliseconds(10)); // The next synchronous request should wait for its turn. connect_job_factory_->set_job_type(TestConnectJob::kMockJob); @@ -2387,8 +2389,7 @@ // actually become pending until 2ms after they have been created. In order // to flush all tasks, we need to wait so that we know there are no // soon-to-be-pending tasks waiting. - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); - base::RunLoop().RunUntilIdle(); + FastForwardBy(base::TimeDelta::FromMilliseconds(10)); // Both sockets should now be idle. ASSERT_EQ(2, pool_->IdleSocketCount()); @@ -2779,10 +2780,9 @@ handle.Reset(); // Wait for the backup timer to fire (add some slop to ensure it fires) - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds( + FastForwardBy(base::TimeDelta::FromMilliseconds( ClientSocketPool::kMaxConnectRetryIntervalMs / 2 * 3)); - base::RunLoop().RunUntilIdle(); EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count()); } @@ -2808,9 +2808,8 @@ // the backup time to see if it indeed got canceled. handle.Reset(); // Wait for the backup timer to fire (add some slop to ensure it fires) - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds( + FastForwardBy(base::TimeDelta::FromMilliseconds( ClientSocketPool::kMaxConnectRetryIntervalMs / 2 * 3)); - base::RunLoop().RunUntilIdle(); ASSERT_TRUE(pool_->HasGroup("bar")); EXPECT_EQ(1, pool_->NumConnectJobsInGroup("bar")); } @@ -2844,9 +2843,8 @@ handle.Reset(); EXPECT_THAT(callback2.WaitForResult(), IsOk()); // Wait for the backup timer to fire (add some slop to ensure it fires) - base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds( + FastForwardBy(base::TimeDelta::FromMilliseconds( ClientSocketPool::kMaxConnectRetryIntervalMs / 2 * 3)); - base::RunLoop().RunUntilIdle(); } // Test delayed socket binding for the case where we have two connects,
diff --git a/net/spdy/OWNERS b/net/spdy/OWNERS index a2dbce8d..b608e73 100644 --- a/net/spdy/OWNERS +++ b/net/spdy/OWNERS
@@ -1,3 +1,8 @@ -file://net/third_party/http2/OWNERS +birenroy@chromium.org +bnc@chromium.org +dahollings@chromium.org +diannahu@chromium.org +rch@chromium.org +yasong@chromium.org # COMPONENT: Internals>Network>HTTP2
diff --git a/net/spdy/fuzzing/hpack_decoder_fuzzer.cc b/net/spdy/fuzzing/hpack_decoder_fuzzer.cc new file mode 100644 index 0000000..99917fc4 --- /dev/null +++ b/net/spdy/fuzzing/hpack_decoder_fuzzer.cc
@@ -0,0 +1,39 @@ +// Copyright 2017 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 <stddef.h> +#include <stdint.h> + +#include <vector> + +#include "base/test/fuzzed_data_provider.h" +#include "net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h" + +// Entry point for LibFuzzer. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + // At least 4 bytes of fuzz data are needed to generate a max string size. + if (size < 4) + return 0; + + base::FuzzedDataProvider fuzzed_data_provider(data, size); + size_t max_string_size = + fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 10 * size); + http2::HpackDecoder decoder(http2::HpackDecoderNoOpListener::NoOpListener(), + max_string_size); + decoder.StartDecodingBlock(); + while (fuzzed_data_provider.remaining_bytes() > 0) { + size_t chunk_size = fuzzed_data_provider.ConsumeIntegralInRange(1, 32); + std::vector<char> chunk = + fuzzed_data_provider.ConsumeBytes<char>(chunk_size); + + // http2::DecodeBuffer constructor does not accept nullptr buffer. + if (chunk.data() == nullptr) + continue; + + http2::DecodeBuffer fragment(chunk.data(), chunk.size()); + decoder.DecodeFragment(&fragment); + } + decoder.EndDecodingBlock(); + return 0; +}
diff --git a/net/spdy/fuzzing/http2_frame_decoder_fuzzer.cc b/net/spdy/fuzzing/http2_frame_decoder_fuzzer.cc new file mode 100644 index 0000000..bdf709f --- /dev/null +++ b/net/spdy/fuzzing/http2_frame_decoder_fuzzer.cc
@@ -0,0 +1,30 @@ +// Copyright 2017 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 <stddef.h> +#include <stdint.h> + +#include <vector> + +#include "base/test/fuzzed_data_provider.h" +#include "net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h" + +// Entry point for LibFuzzer. +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + base::FuzzedDataProvider fuzzed_data_provider(data, size); + http2::Http2FrameDecoder decoder; + while (fuzzed_data_provider.remaining_bytes() > 0) { + size_t chunk_size = fuzzed_data_provider.ConsumeIntegralInRange(1, 32); + std::vector<char> chunk = + fuzzed_data_provider.ConsumeBytes<char>(chunk_size); + + // http2::DecodeBuffer constructor does not accept nullptr buffer. + if (chunk.data() == nullptr) + continue; + + http2::DecodeBuffer frame_data(chunk.data(), chunk.size()); + decoder.DecodeFrame(&frame_data); + } + return 0; +}
diff --git a/net/spdy/spdy_log_util.cc b/net/spdy/spdy_log_util.cc index 7bc3822b..ba7c52fc 100644 --- a/net/spdy/spdy_log_util.cc +++ b/net/spdy/spdy_log_util.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/values.h" #include "net/http/http_log_util.h" @@ -26,12 +27,13 @@ const spdy::SpdyHeaderBlock& headers, NetLogCaptureMode capture_mode) { auto headers_list = std::make_unique<base::ListValue>(); - for (spdy::SpdyHeaderBlock::const_iterator it = headers.begin(); - it != headers.end(); ++it) { + for (const auto& header : headers) { + base::StringPiece key = header.first; + base::StringPiece value = header.second; headers_list->AppendString( - it->first.as_string() + ": " + - ElideHeaderValueForNetLog(capture_mode, it->first.as_string(), - it->second.as_string())); + base::StrCat({key, ": ", + ElideHeaderValueForNetLog(capture_mode, key.as_string(), + value.as_string())})); } return headers_list; } @@ -40,15 +42,7 @@ const spdy::SpdyHeaderBlock* headers, NetLogCaptureMode capture_mode) { auto dict = std::make_unique<base::DictionaryValue>(); - auto headers_dict = std::make_unique<base::DictionaryValue>(); - for (spdy::SpdyHeaderBlock::const_iterator it = headers->begin(); - it != headers->end(); ++it) { - headers_dict->SetKey( - it->first.as_string(), - base::Value(ElideHeaderValueForNetLog( - capture_mode, it->first.as_string(), it->second.as_string()))); - } - dict->Set("headers", std::move(headers_dict)); + dict->Set("headers", ElideSpdyHeaderBlockForNetLog(*headers, capture_mode)); return std::move(dict); }
diff --git a/net/spdy/spdy_log_util_unittest.cc b/net/spdy/spdy_log_util_unittest.cc index 5f2d107..e28aa8bed 100644 --- a/net/spdy/spdy_log_util_unittest.cc +++ b/net/spdy/spdy_log_util_unittest.cc
@@ -26,20 +26,70 @@ std::unique_ptr<base::ListValue> list = ElideSpdyHeaderBlockForNetLog(headers, NetLogCaptureMode::Default()); - EXPECT_EQ(2u, list->GetSize()); - std::string field; - EXPECT_TRUE(list->GetString(0, &field)); - EXPECT_EQ("foo: bar", field); - EXPECT_TRUE(list->GetString(1, &field)); - EXPECT_EQ("cookie: [10 bytes were stripped]", field); + + ASSERT_TRUE(list); + ASSERT_EQ(2u, list->GetList().size()); + + ASSERT_TRUE(list->GetList()[0].is_string()); + EXPECT_EQ("foo: bar", list->GetList()[0].GetString()); + + ASSERT_TRUE(list->GetList()[1].is_string()); + EXPECT_EQ("cookie: [10 bytes were stripped]", list->GetList()[1].GetString()); list = ElideSpdyHeaderBlockForNetLog( headers, NetLogCaptureMode::IncludeCookiesAndCredentials()); - EXPECT_EQ(2u, list->GetSize()); - EXPECT_TRUE(list->GetString(0, &field)); - EXPECT_EQ("foo: bar", field); - EXPECT_TRUE(list->GetString(1, &field)); - EXPECT_EQ("cookie: name=value", field); + + ASSERT_TRUE(list); + ASSERT_EQ(2u, list->GetList().size()); + + ASSERT_TRUE(list->GetList()[0].is_string()); + EXPECT_EQ("foo: bar", list->GetList()[0].GetString()); + + ASSERT_TRUE(list->GetList()[1].is_string()); + EXPECT_EQ("cookie: name=value", list->GetList()[1].GetString()); +} + +TEST(SpdyLogUtilTest, SpdyHeaderBlockNetLogCallback) { + spdy::SpdyHeaderBlock headers; + headers["foo"] = "bar"; + headers["cookie"] = "name=value"; + + std::unique_ptr<base::Value> dict = + SpdyHeaderBlockNetLogCallback(&headers, NetLogCaptureMode::Default()); + + ASSERT_TRUE(dict); + ASSERT_TRUE(dict->is_dict()); + ASSERT_EQ(1u, dict->DictSize()); + + auto* header_list = dict->FindKey("headers"); + ASSERT_TRUE(header_list); + ASSERT_TRUE(header_list->is_list()); + ASSERT_EQ(2u, header_list->GetList().size()); + + ASSERT_TRUE(header_list->GetList()[0].is_string()); + EXPECT_EQ("foo: bar", header_list->GetList()[0].GetString()); + + ASSERT_TRUE(header_list->GetList()[1].is_string()); + EXPECT_EQ("cookie: [10 bytes were stripped]", + header_list->GetList()[1].GetString()); + + dict = SpdyHeaderBlockNetLogCallback( + &headers, NetLogCaptureMode::IncludeCookiesAndCredentials()); + + ASSERT_TRUE(dict); + ASSERT_TRUE(dict->is_dict()); + ASSERT_EQ(1u, dict->DictSize()); + + header_list = dict->FindKey("headers"); + ASSERT_TRUE(header_list); + ASSERT_TRUE(header_list->is_list()); + ASSERT_EQ(2u, header_list->GetList().size()); + + ASSERT_TRUE(header_list->GetList()[0].is_string()); + EXPECT_EQ("foo: bar", header_list->GetList()[0].GetString()); + + ASSERT_TRUE(header_list->GetList()[1].is_string()); + EXPECT_EQ("cookie: name=value", header_list->GetList()[1].GetString()); } } // namespace net
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc index da973a2..fb3f2de 100644 --- a/net/spdy/spdy_network_transaction_unittest.cc +++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -4319,25 +4319,27 @@ NetLogEventType::HTTP2_SESSION_SEND_HEADERS, NetLogEventPhase::NONE); - base::ListValue* header_list; - ASSERT_TRUE(entries[pos].params.get()); - ASSERT_TRUE(entries[pos].params->GetList("headers", &header_list)); + ASSERT_TRUE(entries[pos].params); + auto* header_list = entries[pos].params->FindKey("headers"); + ASSERT_TRUE(header_list); + ASSERT_TRUE(header_list->is_list()); + ASSERT_EQ(5u, header_list->GetList().size()); - std::vector<std::string> expected; - expected.push_back(std::string(spdy::kHttp2AuthorityHeader) + - ": www.example.org"); - expected.push_back(std::string(spdy::kHttp2PathHeader) + ": /"); - expected.push_back(std::string(spdy::kHttp2SchemeHeader) + ": " + - default_url_.scheme()); - expected.push_back(std::string(spdy::kHttp2MethodHeader) + ": GET"); - expected.push_back("user-agent: Chrome"); - EXPECT_EQ(expected.size(), header_list->GetSize()); - for (std::vector<std::string>::const_iterator it = expected.begin(); - it != expected.end(); ++it) { - base::Value header(*it); - EXPECT_NE(header_list->end(), header_list->Find(header)) << - "Header not found: " << *it; - } + ASSERT_TRUE(header_list->GetList()[0].is_string()); + EXPECT_EQ(":method: GET", header_list->GetList()[0].GetString()); + + ASSERT_TRUE(header_list->GetList()[1].is_string()); + EXPECT_EQ(":authority: www.example.org", + header_list->GetList()[1].GetString()); + + ASSERT_TRUE(header_list->GetList()[2].is_string()); + EXPECT_EQ(":scheme: https", header_list->GetList()[2].GetString()); + + ASSERT_TRUE(header_list->GetList()[3].is_string()); + EXPECT_EQ(":path: /", header_list->GetList()[3].GetString()); + + ASSERT_TRUE(header_list->GetList()[4].is_string()); + EXPECT_EQ("user-agent: Chrome", header_list->GetList()[4].GetString()); } // Since we buffer the IO from the stream to the renderer, this test verifies
diff --git a/net/third_party/http2/OWNERS b/net/third_party/http2/OWNERS deleted file mode 100644 index b608e73..0000000 --- a/net/third_party/http2/OWNERS +++ /dev/null
@@ -1,8 +0,0 @@ -birenroy@chromium.org -bnc@chromium.org -dahollings@chromium.org -diannahu@chromium.org -rch@chromium.org -yasong@chromium.org - -# COMPONENT: Internals>Network>HTTP2
diff --git a/net/third_party/http2/PRESUBMIT.py b/net/third_party/http2/PRESUBMIT.py deleted file mode 100644 index 0c425cca..0000000 --- a/net/third_party/http2/PRESUBMIT.py +++ /dev/null
@@ -1,68 +0,0 @@ -# Copyright 2017 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. - -import re - -def CheckForbiddenRegex(change, forbidden_regex, message_type, message): - problems = [] - for path, change_per_file in change: - line_num = 1 - for line in change_per_file: - if forbidden_regex.match(line): - problems.extend([" %s:%d" % (path, line_num)]) - line_num += 1 - if not problems: - return [] - return [message_type(message + ":\n" + "\n".join(problems))] - - -def CheckChange(input_api, message_type): - result = [] - shared_source_files = re.compile("^net/third_party/http2/(?!platform/impl/).*\.(h|cc)$") - change = [(affected_file.LocalPath(), affected_file.NewContents()) - for affected_file in input_api.AffectedTestableFiles() - if shared_source_files.match(affected_file.LocalPath())] - forbidden_regex_list = [ - r"^#include \"net/base/net_export.h\"$", - r"\bNET_EXPORT\b", - r"\bNET_EXPORT_PRIVATE\b", - "^#include <string>$", - r"\bstd::string\b", - r"^#include \"base/strings/string_piece.h\"$", - r"\bbase::StringPiece\b", - r"\bbase::StringPrintf\b", - r"\bbase::StringAppendF\b", - r"\bbase::HexDigitToInt\b", - r"\bbase::HexEncode\b", - r"\bHexDecode\b", - r"\bHexDump\b", - ] - messages = [ - "Include \"http2/platform/api/http2_export.h\" " - "instead of \"net/base/net_export.h\"", - "Use HTTP2_EXPORT instead of NET_EXPORT", - "Use HTTP2_EXPORT_PRIVATE instead of NET_EXPORT_PRIVATE", - "Include \"http2/platform/api/http2_string.h\" instead of <string>", - "Use Http2String instead of std::string", - "Include \"http2/platform/api/http2_string_piece.h\" " - "instead of \"base/strings/string_piece.h\"", - "Use Http2StringPiece instead of base::StringPiece", - "Use Http2StringPrintf instead of base::StringPrintf", - "Use Http2HexEncode instead of base::HexEncode", - "Use Http2HexDecode instead of HexDecode", - "Use Http2HexDump instead of HexDump", - ] - for forbidden_regex, message in zip(forbidden_regex_list, messages): - result.extend(CheckForbiddenRegex( - change, re.compile(forbidden_regex), message_type, message)) - return result - -# Warn before uploading but allow developer to skip warning -# so that CLs can be shared and reviewed before addressing all issues. -def CheckChangeOnUpload(input_api, output_api): - return CheckChange(input_api, output_api.PresubmitPromptWarning) - -# Do not allow code with forbidden patterns to be checked in. -def CheckChangeOnCommit(input_api, output_api): - return CheckChange(input_api, output_api.PresubmitError)
diff --git a/net/third_party/http2/decoder/decode_buffer.cc b/net/third_party/http2/decoder/decode_buffer.cc deleted file mode 100644 index 2db632a..0000000 --- a/net/third_party/http2/decoder/decode_buffer.cc +++ /dev/null
@@ -1,93 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/decode_buffer.h" - -namespace http2 { - -uint8_t DecodeBuffer::DecodeUInt8() { - return static_cast<uint8_t>(DecodeChar()); -} - -uint16_t DecodeBuffer::DecodeUInt16() { - DCHECK_LE(2u, Remaining()); - const uint8_t b1 = DecodeUInt8(); - const uint8_t b2 = DecodeUInt8(); - // Note that chars are automatically promoted to ints during arithmetic, - // so the b1 << 8 doesn't end up as zero before being or-ed with b2. - // And the left-shift operator has higher precedence than the or operator. - return b1 << 8 | b2; -} - -uint32_t DecodeBuffer::DecodeUInt24() { - DCHECK_LE(3u, Remaining()); - const uint8_t b1 = DecodeUInt8(); - const uint8_t b2 = DecodeUInt8(); - const uint8_t b3 = DecodeUInt8(); - return b1 << 16 | b2 << 8 | b3; -} - -uint32_t DecodeBuffer::DecodeUInt31() { - DCHECK_LE(4u, Remaining()); - const uint8_t b1 = DecodeUInt8() & 0x7f; // Mask out the high order bit. - const uint8_t b2 = DecodeUInt8(); - const uint8_t b3 = DecodeUInt8(); - const uint8_t b4 = DecodeUInt8(); - return b1 << 24 | b2 << 16 | b3 << 8 | b4; -} - -uint32_t DecodeBuffer::DecodeUInt32() { - DCHECK_LE(4u, Remaining()); - const uint8_t b1 = DecodeUInt8(); - const uint8_t b2 = DecodeUInt8(); - const uint8_t b3 = DecodeUInt8(); - const uint8_t b4 = DecodeUInt8(); - return b1 << 24 | b2 << 16 | b3 << 8 | b4; -} - -#ifndef NDEBUG -void DecodeBuffer::set_subset_of_base(DecodeBuffer* base, - const DecodeBufferSubset* subset) { - DCHECK_EQ(this, subset); - base->set_subset(subset); -} -void DecodeBuffer::clear_subset_of_base(DecodeBuffer* base, - const DecodeBufferSubset* subset) { - DCHECK_EQ(this, subset); - base->clear_subset(subset); -} -void DecodeBuffer::set_subset(const DecodeBufferSubset* subset) { - DCHECK(subset != nullptr); - DCHECK_EQ(subset_, nullptr) << "There is already a subset"; - subset_ = subset; -} -void DecodeBuffer::clear_subset(const DecodeBufferSubset* subset) { - DCHECK(subset != nullptr); - DCHECK_EQ(subset_, subset); - subset_ = nullptr; -} -void DecodeBufferSubset::DebugSetup() { - start_base_offset_ = base_buffer_->Offset(); - max_base_offset_ = start_base_offset_ + FullSize(); - DCHECK_LE(max_base_offset_, base_buffer_->FullSize()); - - // Ensure that there is only one DecodeBufferSubset at a time for a base. - set_subset_of_base(base_buffer_, this); -} -void DecodeBufferSubset::DebugTearDown() { - // Ensure that the base hasn't been modified. - DCHECK_EQ(start_base_offset_, base_buffer_->Offset()) - << "The base buffer was modified"; - - // Ensure that we haven't gone beyond the maximum allowed offset. - size_t offset = Offset(); - DCHECK_LE(offset, FullSize()); - DCHECK_LE(start_base_offset_ + offset, max_base_offset_); - DCHECK_LE(max_base_offset_, base_buffer_->FullSize()); - - clear_subset_of_base(base_buffer_, this); -} -#endif - -} // namespace http2
diff --git a/net/third_party/http2/decoder/decode_buffer.h b/net/third_party/http2/decoder/decode_buffer.h deleted file mode 100644 index 379b30e..0000000 --- a/net/third_party/http2/decoder/decode_buffer.h +++ /dev/null
@@ -1,166 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_DECODE_BUFFER_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_DECODE_BUFFER_H_ - -// DecodeBuffer provides primitives for decoding various integer types found in -// HTTP/2 frames. It wraps a byte array from which we can read and decode -// serialized HTTP/2 frames, or parts thereof. DecodeBuffer is intended only for -// stack allocation, where the caller is typically going to use the DecodeBuffer -// instance as part of decoding the entire buffer before returning to its own -// caller. - -#include <stddef.h> - -#include <algorithm> -#include <cstdint> - -#include "base/logging.h" -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" - -namespace http2 { -class DecodeBufferSubset; - -class HTTP2_EXPORT_PRIVATE DecodeBuffer { - public: - DecodeBuffer(const char* buffer, size_t len) - : buffer_(buffer), cursor_(buffer), beyond_(buffer + len) { - DCHECK(buffer != nullptr); - // We assume the decode buffers will typically be modest in size (i.e. often - // a few KB, perhaps as high as 100KB). Let's make sure during testing that - // we don't go very high, with 32MB selected rather arbitrarily. - const size_t kMaxDecodeBufferLength = 1 << 25; - DCHECK_LE(len, kMaxDecodeBufferLength); - } - explicit DecodeBuffer(Http2StringPiece s) - : DecodeBuffer(s.data(), s.size()) {} - // Constructor for character arrays, typically in tests. For example: - // const char input[] = { 0x11 }; - // DecodeBuffer b(input); - template <size_t N> - explicit DecodeBuffer(const char (&buf)[N]) : DecodeBuffer(buf, N) {} - - DecodeBuffer(const DecodeBuffer&) = delete; - DecodeBuffer operator=(const DecodeBuffer&) = delete; - - bool Empty() const { return cursor_ >= beyond_; } - bool HasData() const { return cursor_ < beyond_; } - size_t Remaining() const { - DCHECK_LE(cursor_, beyond_); - return beyond_ - cursor_; - } - size_t Offset() const { return cursor_ - buffer_; } - size_t FullSize() const { return beyond_ - buffer_; } - - // Returns the minimum of the number of bytes remaining in this DecodeBuffer - // and |length|, in support of determining how much of some structure/payload - // is in this DecodeBuffer. - size_t MinLengthRemaining(size_t length) const { - return std::min(length, Remaining()); - } - - // For string decoding, returns a pointer to the next byte/char to be decoded. - const char* cursor() const { return cursor_; } - // Advances the cursor (pointer to the next byte/char to be decoded). - void AdvanceCursor(size_t amount) { - DCHECK_LE(amount, Remaining()); // Need at least that much remaining. - DCHECK_EQ(subset_, nullptr) << "Access via subset only when present."; - cursor_ += amount; - } - - // Only call methods starting "Decode" when there is enough input remaining. - char DecodeChar() { - DCHECK_LE(1u, Remaining()); // Need at least one byte remaining. - DCHECK_EQ(subset_, nullptr) << "Access via subset only when present."; - return *cursor_++; - } - - uint8_t DecodeUInt8(); - uint16_t DecodeUInt16(); - uint32_t DecodeUInt24(); - - // For 31-bit unsigned integers, where the 32nd bit is reserved for future - // use (i.e. the high-bit of the first byte of the encoding); examples: - // the Stream Id in a frame header or the Window Size Increment in a - // WINDOW_UPDATE frame. - uint32_t DecodeUInt31(); - - uint32_t DecodeUInt32(); - - protected: -#ifndef NDEBUG - // These are part of validating during tests that there is at most one - // DecodeBufferSubset instance at a time for any DecodeBuffer instance. - void set_subset_of_base(DecodeBuffer* base, const DecodeBufferSubset* subset); - void clear_subset_of_base(DecodeBuffer* base, - const DecodeBufferSubset* subset); -#endif - - private: -#ifndef NDEBUG - void set_subset(const DecodeBufferSubset* subset); - void clear_subset(const DecodeBufferSubset* subset); -#endif - - // Prevent heap allocation of DecodeBuffer. - static void* operator new(size_t s); - static void* operator new[](size_t s); - static void operator delete(void* p); - static void operator delete[](void* p); - - const char* const buffer_; - const char* cursor_; - const char* const beyond_; - const DecodeBufferSubset* subset_ = nullptr; // Used for DCHECKs. -}; - -// DecodeBufferSubset is used when decoding a known sized chunk of data, which -// starts at base->cursor(), and continues for subset_len, which may be -// entirely in |base|, or may extend beyond it (hence the MinLengthRemaining -// in the constructor). -// There are two benefits to using DecodeBufferSubset: it ensures that the -// cursor of |base| is advanced when the subset's destructor runs, and it -// ensures that the consumer of the subset can't go beyond the subset which -// it is intended to decode. -// There must be only a single DecodeBufferSubset at a time for a base -// DecodeBuffer, though they can be nested (i.e. a DecodeBufferSubset's -// base may itself be a DecodeBufferSubset). This avoids the AdvanceCursor -// being called erroneously. -class HTTP2_EXPORT_PRIVATE DecodeBufferSubset : public DecodeBuffer { - public: - DecodeBufferSubset(DecodeBuffer* base, size_t subset_len) - : DecodeBuffer(base->cursor(), base->MinLengthRemaining(subset_len)), - base_buffer_(base) { -#ifndef NDEBUG - DebugSetup(); -#endif - } - - DecodeBufferSubset(const DecodeBufferSubset&) = delete; - DecodeBufferSubset operator=(const DecodeBufferSubset&) = delete; - - ~DecodeBufferSubset() { - size_t offset = Offset(); -#ifndef NDEBUG - DebugTearDown(); -#endif - base_buffer_->AdvanceCursor(offset); - } - - private: - DecodeBuffer* const base_buffer_; -#ifndef NDEBUG - size_t start_base_offset_; // Used for DCHECKs. - size_t max_base_offset_; // Used for DCHECKs. - - void DebugSetup(); - void DebugTearDown(); -#endif -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_DECODE_BUFFER_H_
diff --git a/net/third_party/http2/decoder/decode_buffer_test.cc b/net/third_party/http2/decoder/decode_buffer_test.cc deleted file mode 100644 index d0814f17..0000000 --- a/net/third_party/http2/decoder/decode_buffer_test.cc +++ /dev/null
@@ -1,203 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/decode_buffer.h" - -#include <functional> - -#include "base/logging.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { -namespace { - -enum class TestEnumClass32 { - kValue1 = 1, - kValue99 = 99, - kValue1M = 1000000, -}; - -enum class TestEnumClass8 { - kValue1 = 1, - kValue2 = 1, - kValue99 = 99, - kValue255 = 255, -}; - -enum TestEnum8 { - kMaskLo = 0x01, - kMaskHi = 0x80, -}; - -struct TestStruct { - uint8_t f1; - uint16_t f2; - uint32_t f3; // Decoded as a uint24 - uint32_t f4; - uint32_t f5; // Decoded as if uint31 - TestEnumClass32 f6; - TestEnumClass8 f7; - TestEnum8 f8; -}; - -class DecodeBufferTest : public ::testing::Test { - protected: - Http2Random random_; - uint32_t decode_offset_; -}; - -TEST_F(DecodeBufferTest, DecodesFixedInts) { - const char data[] = "\x01\x12\x23\x34\x45\x56\x67\x78\x89\x9a"; - DecodeBuffer b1(data, strlen(data)); - EXPECT_EQ(1, b1.DecodeUInt8()); - EXPECT_EQ(0x1223u, b1.DecodeUInt16()); - EXPECT_EQ(0x344556u, b1.DecodeUInt24()); - EXPECT_EQ(0x6778899Au, b1.DecodeUInt32()); -} - -// Make sure that DecodeBuffer is not copying input, just pointing into -// provided input buffer. -TEST_F(DecodeBufferTest, HasNotCopiedInput) { - const char data[] = "ab"; - DecodeBuffer b1(data, 2); - - EXPECT_EQ(2u, b1.Remaining()); - EXPECT_EQ(0u, b1.Offset()); - EXPECT_FALSE(b1.Empty()); - EXPECT_EQ(data, b1.cursor()); // cursor points to input buffer - EXPECT_TRUE(b1.HasData()); - - b1.AdvanceCursor(1); - - EXPECT_EQ(1u, b1.Remaining()); - EXPECT_EQ(1u, b1.Offset()); - EXPECT_FALSE(b1.Empty()); - EXPECT_EQ(&data[1], b1.cursor()); - EXPECT_TRUE(b1.HasData()); - - b1.AdvanceCursor(1); - - EXPECT_EQ(0u, b1.Remaining()); - EXPECT_EQ(2u, b1.Offset()); - EXPECT_TRUE(b1.Empty()); - EXPECT_EQ(&data[2], b1.cursor()); - EXPECT_FALSE(b1.HasData()); - - DecodeBuffer b2(data, 0); - - EXPECT_EQ(0u, b2.Remaining()); - EXPECT_EQ(0u, b2.Offset()); - EXPECT_TRUE(b2.Empty()); - EXPECT_EQ(data, b2.cursor()); - EXPECT_FALSE(b2.HasData()); -} - -// DecodeBufferSubset can't go beyond the end of the base buffer. -TEST_F(DecodeBufferTest, DecodeBufferSubsetLimited) { - const char data[] = "abc"; - DecodeBuffer base(data, 3); - base.AdvanceCursor(1); - DecodeBufferSubset subset(&base, 100); - EXPECT_EQ(2u, subset.FullSize()); -} - -// DecodeBufferSubset advances the cursor of its base upon destruction. -TEST_F(DecodeBufferTest, DecodeBufferSubsetAdvancesCursor) { - const char data[] = "abc"; - const size_t size = sizeof(data) - 1; - EXPECT_EQ(3u, size); - DecodeBuffer base(data, size); - { - // First no change to the cursor. - DecodeBufferSubset subset(&base, size + 100); - EXPECT_EQ(size, subset.FullSize()); - EXPECT_EQ(base.FullSize(), subset.FullSize()); - EXPECT_EQ(0u, subset.Offset()); - } - EXPECT_EQ(0u, base.Offset()); - EXPECT_EQ(size, base.Remaining()); -} - -// Make sure that DecodeBuffer ctor complains about bad args. -#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) -TEST(DecodeBufferDeathTest, NonNullBufferRequired) { - EXPECT_DEBUG_DEATH({ DecodeBuffer b(nullptr, 3); }, "nullptr"); -} - -// Make sure that DecodeBuffer ctor complains about bad args. -TEST(DecodeBufferDeathTest, ModestBufferSizeRequired) { - EXPECT_DEBUG_DEATH( - { - const char data[] = "abc"; - size_t len = 0; - DecodeBuffer b(data, ~len); - }, - "Max.*Length"); -} - -// Make sure that DecodeBuffer detects advance beyond end, in debug mode. -TEST(DecodeBufferDeathTest, LimitedAdvance) { - { - // Advance right up to end is OK. - const char data[] = "abc"; - DecodeBuffer b(data, 3); - b.AdvanceCursor(3); // OK - EXPECT_TRUE(b.Empty()); - } - EXPECT_DEBUG_DEATH( - { - // Going beyond is not OK. - const char data[] = "abc"; - DecodeBuffer b(data, 3); - b.AdvanceCursor(4); - }, - "4 vs. 3"); -} - -// Make sure that DecodeBuffer detects decode beyond end, in debug mode. -TEST(DecodeBufferDeathTest, DecodeUInt8PastEnd) { - const char data[] = {0x12, 0x23}; - DecodeBuffer b(data, sizeof data); - EXPECT_EQ(2u, b.FullSize()); - EXPECT_EQ(0x1223, b.DecodeUInt16()); - EXPECT_DEBUG_DEATH({ b.DecodeUInt8(); }, "1 vs. 0"); -} - -// Make sure that DecodeBuffer detects decode beyond end, in debug mode. -TEST(DecodeBufferDeathTest, DecodeUInt16OverEnd) { - const char data[] = {0x12, 0x23, 0x34}; - DecodeBuffer b(data, sizeof data); - EXPECT_EQ(3u, b.FullSize()); - EXPECT_EQ(0x1223, b.DecodeUInt16()); - EXPECT_DEBUG_DEATH({ b.DecodeUInt16(); }, "2 vs. 1"); -} - -// Make sure that DecodeBuffer doesn't agree with having two subsets. -TEST(DecodeBufferSubsetDeathTest, TwoSubsets) { - const char data[] = "abc"; - DecodeBuffer base(data, 3); - DecodeBufferSubset subset1(&base, 1); - EXPECT_DEBUG_DEATH({ DecodeBufferSubset subset2(&base, 1); }, - "There is already a subset"); -} - -// Make sure that DecodeBufferSubset notices when the base's cursor has moved. -TEST(DecodeBufferSubsetDeathTest, BaseCursorAdvanced) { - const char data[] = "abc"; - DecodeBuffer base(data, 3); - base.AdvanceCursor(1); - EXPECT_DEBUG_DEATH( - { - DecodeBufferSubset subset1(&base, 2); - base.AdvanceCursor(1); - }, - "Access via subset only when present"); -} -#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/decode_http2_structures.cc b/net/third_party/http2/decoder/decode_http2_structures.cc deleted file mode 100644 index f8dbeb2..0000000 --- a/net/third_party/http2/decoder/decode_http2_structures.cc +++ /dev/null
@@ -1,111 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/decode_http2_structures.h" - -#include <cstdint> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/http2_constants.h" - -namespace http2 { - -// Http2FrameHeader decoding: - -void DoDecode(Http2FrameHeader* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_LE(Http2FrameHeader::EncodedSize(), b->Remaining()); - out->payload_length = b->DecodeUInt24(); - out->type = static_cast<Http2FrameType>(b->DecodeUInt8()); - out->flags = static_cast<Http2FrameFlag>(b->DecodeUInt8()); - out->stream_id = b->DecodeUInt31(); -} - -// Http2PriorityFields decoding: - -void DoDecode(Http2PriorityFields* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_LE(Http2PriorityFields::EncodedSize(), b->Remaining()); - uint32_t stream_id_and_flag = b->DecodeUInt32(); - out->stream_dependency = stream_id_and_flag & StreamIdMask(); - if (out->stream_dependency == stream_id_and_flag) { - out->is_exclusive = false; - } else { - out->is_exclusive = true; - } - // Note that chars are automatically promoted to ints during arithmetic, - // so 255 + 1 doesn't end up as zero. - out->weight = b->DecodeUInt8() + 1; -} - -// Http2RstStreamFields decoding: - -void DoDecode(Http2RstStreamFields* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_LE(Http2RstStreamFields::EncodedSize(), b->Remaining()); - out->error_code = static_cast<Http2ErrorCode>(b->DecodeUInt32()); -} - -// Http2SettingFields decoding: - -void DoDecode(Http2SettingFields* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_LE(Http2SettingFields::EncodedSize(), b->Remaining()); - out->parameter = static_cast<Http2SettingsParameter>(b->DecodeUInt16()); - out->value = b->DecodeUInt32(); -} - -// Http2PushPromiseFields decoding: - -void DoDecode(Http2PushPromiseFields* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_LE(Http2PushPromiseFields::EncodedSize(), b->Remaining()); - out->promised_stream_id = b->DecodeUInt31(); -} - -// Http2PingFields decoding: - -void DoDecode(Http2PingFields* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_LE(Http2PingFields::EncodedSize(), b->Remaining()); - memcpy(out->opaque_bytes, b->cursor(), Http2PingFields::EncodedSize()); - b->AdvanceCursor(Http2PingFields::EncodedSize()); -} - -// Http2GoAwayFields decoding: - -void DoDecode(Http2GoAwayFields* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_LE(Http2GoAwayFields::EncodedSize(), b->Remaining()); - out->last_stream_id = b->DecodeUInt31(); - out->error_code = static_cast<Http2ErrorCode>(b->DecodeUInt32()); -} - -// Http2WindowUpdateFields decoding: - -void DoDecode(Http2WindowUpdateFields* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_LE(Http2WindowUpdateFields::EncodedSize(), b->Remaining()); - out->window_size_increment = b->DecodeUInt31(); -} - -// Http2AltSvcFields decoding: - -void DoDecode(Http2AltSvcFields* out, DecodeBuffer* b) { - DCHECK_NE(nullptr, out); - DCHECK_NE(nullptr, b); - DCHECK_LE(Http2AltSvcFields::EncodedSize(), b->Remaining()); - out->origin_length = b->DecodeUInt16(); -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/decode_http2_structures.h b/net/third_party/http2/decoder/decode_http2_structures.h deleted file mode 100644 index 7875334..0000000 --- a/net/third_party/http2/decoder/decode_http2_structures.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_DECODE_HTTP2_STRUCTURES_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_DECODE_HTTP2_STRUCTURES_H_ - -// Provides functions for decoding the fixed size structures in the HTTP/2 spec. - -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { - -// DoDecode(STRUCTURE* out, DecodeBuffer* b) decodes the structure from start -// to end, advancing the cursor by STRUCTURE::EncodedSize(). The decode buffer -// must be large enough (i.e. b->Remaining() >= STRUCTURE::EncodedSize()). - -HTTP2_EXPORT_PRIVATE void DoDecode(Http2FrameHeader* out, DecodeBuffer* b); -HTTP2_EXPORT_PRIVATE void DoDecode(Http2PriorityFields* out, DecodeBuffer* b); -HTTP2_EXPORT_PRIVATE void DoDecode(Http2RstStreamFields* out, DecodeBuffer* b); -HTTP2_EXPORT_PRIVATE void DoDecode(Http2SettingFields* out, DecodeBuffer* b); -HTTP2_EXPORT_PRIVATE void DoDecode(Http2PushPromiseFields* out, - DecodeBuffer* b); -HTTP2_EXPORT_PRIVATE void DoDecode(Http2PingFields* out, DecodeBuffer* b); -HTTP2_EXPORT_PRIVATE void DoDecode(Http2GoAwayFields* out, DecodeBuffer* b); -HTTP2_EXPORT_PRIVATE void DoDecode(Http2WindowUpdateFields* out, - DecodeBuffer* b); -HTTP2_EXPORT_PRIVATE void DoDecode(Http2AltSvcFields* out, DecodeBuffer* b); - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_DECODE_HTTP2_STRUCTURES_H_
diff --git a/net/third_party/http2/decoder/decode_http2_structures_test.cc b/net/third_party/http2/decoder/decode_http2_structures_test.cc deleted file mode 100644 index a9d6e733..0000000 --- a/net/third_party/http2/decoder/decode_http2_structures_test.cc +++ /dev/null
@@ -1,461 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/decode_http2_structures.h" - -// Tests decoding all of the fixed size HTTP/2 structures (i.e. those defined -// in net/third_party/http2/http2_structures.h). - -#include <stddef.h> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures_test_util.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/http2_frame_builder.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionResult; - -namespace http2 { -namespace test { -namespace { - -template <typename T, size_t N> -Http2StringPiece ToStringPiece(T (&data)[N]) { - return Http2StringPiece(reinterpret_cast<const char*>(data), N * sizeof(T)); -} - -template <class S> -Http2String SerializeStructure(const S& s) { - Http2FrameBuilder fb; - fb.Append(s); - EXPECT_EQ(S::EncodedSize(), fb.size()); - return fb.buffer(); -} - -template <class S> -class StructureDecoderTest : public ::testing::Test { - protected: - typedef S Structure; - - StructureDecoderTest() : random_(), random_decode_count_(100) {} - - // Set the fields of |*p| to random values. - void Randomize(S* p) { ::http2::test::Randomize(p, &random_); } - - // Fully decodes the Structure at the start of data, and confirms it matches - // *expected (if provided). - void DecodeLeadingStructure(const S* expected, Http2StringPiece data) { - ASSERT_LE(S::EncodedSize(), data.size()); - DecodeBuffer db(data); - Randomize(&structure_); - DoDecode(&structure_, &db); - EXPECT_EQ(db.Offset(), S::EncodedSize()); - if (expected != nullptr) { - EXPECT_EQ(structure_, *expected); - } - } - - template <size_t N> - void DecodeLeadingStructure(const char (&data)[N]) { - DecodeLeadingStructure(nullptr, Http2StringPiece(data, N)); - } - - // Encode the structure |in_s| into bytes, then decode the bytes - // and validate that the decoder produced the same field values. - void EncodeThenDecode(const S& in_s) { - Http2String bytes = SerializeStructure(in_s); - EXPECT_EQ(S::EncodedSize(), bytes.size()); - DecodeLeadingStructure(&in_s, bytes); - } - - // Generate - void TestDecodingRandomizedStructures(size_t count) { - for (size_t i = 0; i < count && !HasFailure(); ++i) { - Structure input; - Randomize(&input); - EncodeThenDecode(input); - } - } - - void TestDecodingRandomizedStructures() { - TestDecodingRandomizedStructures(random_decode_count_); - } - - Http2Random random_; - const size_t random_decode_count_; - uint32_t decode_offset_ = 0; - S structure_; - size_t fast_decode_count_ = 0; - size_t slow_decode_count_ = 0; -}; - -class FrameHeaderDecoderTest : public StructureDecoderTest<Http2FrameHeader> {}; - -TEST_F(FrameHeaderDecoderTest, DecodesLiteral) { - { - // Realistic input. - const char kData[] = { - '\x00', '\x00', '\x05', // Payload length: 5 - '\x01', // Frame type: HEADERS - '\x08', // Flags: PADDED - '\x00', '\x00', '\x00', '\x01', // Stream ID: 1 - '\x04', // Padding length: 4 - '\x00', '\x00', '\x00', '\x00', // Padding bytes - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(5u, structure_.payload_length); - EXPECT_EQ(Http2FrameType::HEADERS, structure_.type); - EXPECT_EQ(Http2FrameFlag::PADDED, structure_.flags); - EXPECT_EQ(1u, structure_.stream_id); - } - } - { - // Unlikely input. - const char kData[] = { - '\xff', '\xff', '\xff', // Payload length: uint24 max - '\xff', // Frame type: Unknown - '\xff', // Flags: Unknown/All - '\xff', '\xff', '\xff', '\xff', // Stream ID: uint31 max, plus R-bit - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ((1u << 24) - 1, structure_.payload_length); - EXPECT_EQ(static_cast<Http2FrameType>(255), structure_.type); - EXPECT_EQ(255, structure_.flags); - EXPECT_EQ(0x7FFFFFFFu, structure_.stream_id); - } - } -} - -TEST_F(FrameHeaderDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class PriorityFieldsDecoderTest - : public StructureDecoderTest<Http2PriorityFields> {}; - -TEST_F(PriorityFieldsDecoderTest, DecodesLiteral) { - { - const char kData[] = { - '\x80', '\x00', '\x00', '\x05', // Exclusive (yes) and Dependency (5) - '\xff', // Weight: 256 (after adding 1) - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(5u, structure_.stream_dependency); - EXPECT_EQ(256u, structure_.weight); - EXPECT_EQ(true, structure_.is_exclusive); - } - } - { - const char kData[] = { - '\x7f', '\xff', - '\xff', '\xff', // Exclusive (no) and Dependency (0x7fffffff) - '\x00', // Weight: 1 (after adding 1) - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(StreamIdMask(), structure_.stream_dependency); - EXPECT_EQ(1u, structure_.weight); - EXPECT_FALSE(structure_.is_exclusive); - } - } -} - -TEST_F(PriorityFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class RstStreamFieldsDecoderTest - : public StructureDecoderTest<Http2RstStreamFields> {}; - -TEST_F(RstStreamFieldsDecoderTest, DecodesLiteral) { - { - const char kData[] = { - '\x00', '\x00', '\x00', '\x01', // Error: PROTOCOL_ERROR - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_TRUE(structure_.IsSupportedErrorCode()); - EXPECT_EQ(Http2ErrorCode::PROTOCOL_ERROR, structure_.error_code); - } - } - { - const char kData[] = { - '\xff', '\xff', '\xff', - '\xff', // Error: max uint32 (Unknown error code) - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_FALSE(structure_.IsSupportedErrorCode()); - EXPECT_EQ(static_cast<Http2ErrorCode>(0xffffffff), structure_.error_code); - } - } -} - -TEST_F(RstStreamFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class SettingFieldsDecoderTest - : public StructureDecoderTest<Http2SettingFields> {}; - -TEST_F(SettingFieldsDecoderTest, DecodesLiteral) { - { - const char kData[] = { - '\x00', '\x01', // Setting: HEADER_TABLE_SIZE - '\x00', '\x00', '\x40', '\x00', // Value: 16K - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_TRUE(structure_.IsSupportedParameter()); - EXPECT_EQ(Http2SettingsParameter::HEADER_TABLE_SIZE, - structure_.parameter); - EXPECT_EQ(1u << 14, structure_.value); - } - } - { - const char kData[] = { - '\x00', '\x00', // Setting: Unknown (0) - '\xff', '\xff', '\xff', '\xff', // Value: max uint32 - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_FALSE(structure_.IsSupportedParameter()); - EXPECT_EQ(static_cast<Http2SettingsParameter>(0), structure_.parameter); - } - } -} - -TEST_F(SettingFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class PushPromiseFieldsDecoderTest - : public StructureDecoderTest<Http2PushPromiseFields> {}; - -TEST_F(PushPromiseFieldsDecoderTest, DecodesLiteral) { - { - const char kData[] = { - '\x00', '\x01', '\x8a', '\x92', // Promised Stream ID: 101010 - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(101010u, structure_.promised_stream_id); - } - } - { - // Promised stream id has R-bit (reserved for future use) set, which - // should be cleared by the decoder. - const char kData[] = { - '\xff', '\xff', '\xff', - '\xff', // Promised Stream ID: max uint31 and R-bit - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(StreamIdMask(), structure_.promised_stream_id); - } - } -} - -TEST_F(PushPromiseFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class PingFieldsDecoderTest : public StructureDecoderTest<Http2PingFields> {}; - -TEST_F(PingFieldsDecoderTest, DecodesLiteral) { - { - // Each byte is different, so can detect if order changed. - const char kData[] = { - '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(Http2StringPiece(kData, 8), - ToStringPiece(structure_.opaque_bytes)); - } - } - { - // All zeros, detect problems handling NULs. - const char kData[] = { - '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(Http2StringPiece(kData, 8), - ToStringPiece(structure_.opaque_bytes)); - } - } - { - const char kData[] = { - '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(Http2StringPiece(kData, 8), - ToStringPiece(structure_.opaque_bytes)); - } - } -} - -TEST_F(PingFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class GoAwayFieldsDecoderTest : public StructureDecoderTest<Http2GoAwayFields> { -}; - -TEST_F(GoAwayFieldsDecoderTest, DecodesLiteral) { - { - const char kData[] = { - '\x00', '\x00', '\x00', '\x00', // Last Stream ID: 0 - '\x00', '\x00', '\x00', '\x00', // Error: NO_ERROR (0) - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(0u, structure_.last_stream_id); - EXPECT_TRUE(structure_.IsSupportedErrorCode()); - EXPECT_EQ(Http2ErrorCode::HTTP2_NO_ERROR, structure_.error_code); - } - } - { - const char kData[] = { - '\x00', '\x00', '\x00', '\x01', // Last Stream ID: 1 - '\x00', '\x00', '\x00', '\x0d', // Error: HTTP_1_1_REQUIRED - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(1u, structure_.last_stream_id); - EXPECT_TRUE(structure_.IsSupportedErrorCode()); - EXPECT_EQ(Http2ErrorCode::HTTP_1_1_REQUIRED, structure_.error_code); - } - } - { - const char kData[] = { - '\xff', '\xff', - '\xff', '\xff', // Last Stream ID: max uint31 and R-bit - '\xff', '\xff', - '\xff', '\xff', // Error: max uint32 (Unknown error code) - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(StreamIdMask(), structure_.last_stream_id); // No high-bit. - EXPECT_FALSE(structure_.IsSupportedErrorCode()); - EXPECT_EQ(static_cast<Http2ErrorCode>(0xffffffff), structure_.error_code); - } - } -} - -TEST_F(GoAwayFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class WindowUpdateFieldsDecoderTest - : public StructureDecoderTest<Http2WindowUpdateFields> {}; - -TEST_F(WindowUpdateFieldsDecoderTest, DecodesLiteral) { - { - const char kData[] = { - '\x00', '\x01', '\x00', '\x00', // Window Size Increment: 2 ^ 16 - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(1u << 16, structure_.window_size_increment); - } - } - { - // Increment must be non-zero, but we need to be able to decode the invalid - // zero to detect it. - const char kData[] = { - '\x00', '\x00', '\x00', '\x00', // Window Size Increment: 0 - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(0u, structure_.window_size_increment); - } - } - { - // Increment has R-bit (reserved for future use) set, which - // should be cleared by the decoder. - // clang-format off - const char kData[] = { - // Window Size Increment: max uint31 and R-bit - '\xff', '\xff', '\xff', '\xff', - }; - // clang-format on - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(StreamIdMask(), structure_.window_size_increment); - } - } -} - -TEST_F(WindowUpdateFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class AltSvcFieldsDecoderTest : public StructureDecoderTest<Http2AltSvcFields> { -}; - -TEST_F(AltSvcFieldsDecoderTest, DecodesLiteral) { - { - const char kData[] = { - '\x00', '\x00', // Origin Length: 0 - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(0, structure_.origin_length); - } - } - { - const char kData[] = { - '\x00', '\x14', // Origin Length: 20 - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(20, structure_.origin_length); - } - } - { - const char kData[] = { - '\xff', '\xff', // Origin Length: uint16 max - }; - DecodeLeadingStructure(kData); - if (!HasFailure()) { - EXPECT_EQ(65535, structure_.origin_length); - } - } -} - -TEST_F(AltSvcFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/decode_status.cc b/net/third_party/http2/decoder/decode_status.cc deleted file mode 100644 index 01faee73c..0000000 --- a/net/third_party/http2/decoder/decode_status.cc +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/decode_status.h" - -#include "base/logging.h" -#include "net/third_party/http2/platform/api/http2_bug_tracker.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, DecodeStatus v) { - switch (v) { - case DecodeStatus::kDecodeDone: - return out << "DecodeDone"; - case DecodeStatus::kDecodeInProgress: - return out << "DecodeInProgress"; - case DecodeStatus::kDecodeError: - return out << "DecodeError"; - } - // Since the value doesn't come over the wire, only a programming bug should - // result in reaching this point. - int unknown = static_cast<int>(v); - HTTP2_BUG << "Unknown DecodeStatus " << unknown; - return out << "DecodeStatus(" << unknown << ")"; -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/decode_status.h b/net/third_party/http2/decoder/decode_status.h deleted file mode 100644 index 51f2847..0000000 --- a/net/third_party/http2/decoder/decode_status.h +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_DECODE_STATUS_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_DECODE_STATUS_H_ - -// Enum DecodeStatus is used to report the status of decoding of many -// types of HTTP/2 and HPACK objects. - -#include <ostream> - -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { - -enum class DecodeStatus { - // Decoding is done. - kDecodeDone, - - // Decoder needs more input to be able to make progress. - kDecodeInProgress, - - // Decoding failed (e.g. HPACK variable length integer is too large, or - // an HTTP/2 frame has padding declared to be larger than the payload). - kDecodeError, -}; -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - DecodeStatus v); - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_DECODE_STATUS_H_
diff --git a/net/third_party/http2/decoder/frame_decoder_state.cc b/net/third_party/http2/decoder/frame_decoder_state.cc deleted file mode 100644 index c464282b..0000000 --- a/net/third_party/http2/decoder/frame_decoder_state.cc +++ /dev/null
@@ -1,81 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/frame_decoder_state.h" - -namespace http2 { - -DecodeStatus FrameDecoderState::ReadPadLength(DecodeBuffer* db, - bool report_pad_length) { - DVLOG(2) << "ReadPadLength db->Remaining=" << db->Remaining() - << "; payload_length=" << frame_header().payload_length; - DCHECK(IsPaddable()); - DCHECK(frame_header().IsPadded()); - - // Pad Length is always at the start of the frame, so remaining_payload_ - // should equal payload_length at this point. - const uint32_t total_payload = frame_header().payload_length; - DCHECK_EQ(total_payload, remaining_payload_); - DCHECK_EQ(0u, remaining_padding_); - - if (db->HasData()) { - const uint32_t pad_length = db->DecodeUInt8(); - const uint32_t total_padding = pad_length + 1; - if (total_padding <= total_payload) { - remaining_padding_ = pad_length; - remaining_payload_ = total_payload - total_padding; - if (report_pad_length) { - listener()->OnPadLength(pad_length); - } - return DecodeStatus::kDecodeDone; - } - const uint32_t missing_length = total_padding - total_payload; - // To allow for the possibility of recovery, record the number of - // remaining bytes of the frame's payload (invalid though it is) - // in remaining_payload_. - remaining_payload_ = total_payload - 1; // 1 for sizeof(Pad Length). - remaining_padding_ = 0; - listener()->OnPaddingTooLong(frame_header(), missing_length); - return DecodeStatus::kDecodeError; - } - - if (total_payload == 0) { - remaining_payload_ = 0; - remaining_padding_ = 0; - listener()->OnPaddingTooLong(frame_header(), 1); - return DecodeStatus::kDecodeError; - } - // Need to wait for another buffer. - return DecodeStatus::kDecodeInProgress; -} - -bool FrameDecoderState::SkipPadding(DecodeBuffer* db) { - DVLOG(2) << "SkipPadding remaining_padding_=" << remaining_padding_ - << ", db->Remaining=" << db->Remaining() - << ", header: " << frame_header(); - DCHECK_EQ(remaining_payload_, 0u); - DCHECK(IsPaddable()) << "header: " << frame_header(); - DCHECK_GE(remaining_padding_, 0u); - DCHECK(remaining_padding_ == 0 || frame_header().IsPadded()) - << "remaining_padding_=" << remaining_padding_ - << ", header: " << frame_header(); - const size_t avail = AvailablePadding(db); - if (avail > 0) { - listener()->OnPadding(db->cursor(), avail); - db->AdvanceCursor(avail); - remaining_padding_ -= avail; - } - return remaining_padding_ == 0; -} - -DecodeStatus FrameDecoderState::ReportFrameSizeError() { - DVLOG(2) << "FrameDecoderState::ReportFrameSizeError: " - << " remaining_payload_=" << remaining_payload_ - << "; remaining_padding_=" << remaining_padding_ - << ", header: " << frame_header(); - listener()->OnFrameSizeError(frame_header()); - return DecodeStatus::kDecodeError; -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/frame_decoder_state.h b/net/third_party/http2/decoder/frame_decoder_state.h deleted file mode 100644 index 707740b..0000000 --- a/net/third_party/http2/decoder/frame_decoder_state.h +++ /dev/null
@@ -1,250 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_FRAME_DECODER_STATE_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_FRAME_DECODER_STATE_H_ - -// FrameDecoderState provides state and behaviors in support of decoding -// the common frame header and the payload of all frame types. -// It is an input to all of the payload decoders. - -// TODO(jamessynge): Since FrameDecoderState has far more than state in it, -// rename to FrameDecoderHelper, or similar. - -#include <stddef.h> - -#include <cstdint> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/decoder/http2_structure_decoder.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { -namespace test { -class FrameDecoderStatePeer; -} // namespace test - -class HTTP2_EXPORT_PRIVATE FrameDecoderState { - public: - FrameDecoderState() {} - - // Sets the listener which the decoders should call as they decode HTTP/2 - // frames. The listener can be changed at any time, which allows for replacing - // it with a no-op listener when an error is detected, either by the payload - // decoder (OnPaddingTooLong or OnFrameSizeError) or by the "real" listener. - // That in turn allows us to define Http2FrameDecoderListener such that all - // methods have return type void, with no direct way to indicate whether the - // decoder should stop, and to eliminate from the decoder all checks of the - // return value. Instead the listener/caller can simply replace the current - // listener with a no-op listener implementation. - // TODO(jamessynge): Make set_listener private as only Http2FrameDecoder - // and tests need to set it, so it doesn't need to be public. - void set_listener(Http2FrameDecoderListener* listener) { - listener_ = listener; - } - Http2FrameDecoderListener* listener() const { return listener_; } - - // The most recently decoded frame header. - const Http2FrameHeader& frame_header() const { return frame_header_; } - - // Decode a structure in the payload, adjusting remaining_payload_ to account - // for the consumed portion of the payload. Returns kDecodeDone when fully - // decoded, kDecodeError if it ran out of payload before decoding completed, - // and kDecodeInProgress if the decode buffer didn't have enough of the - // remaining payload. - template <class S> - DecodeStatus StartDecodingStructureInPayload(S* out, DecodeBuffer* db) { - DVLOG(2) << __func__ << "\n\tdb->Remaining=" << db->Remaining() - << "\n\tremaining_payload_=" << remaining_payload_ - << "\n\tneed=" << S::EncodedSize(); - DecodeStatus status = - structure_decoder_.Start(out, db, &remaining_payload_); - if (status != DecodeStatus::kDecodeError) { - return status; - } - DVLOG(2) << "StartDecodingStructureInPayload: detected frame size error"; - return ReportFrameSizeError(); - } - - // Resume decoding of a structure that has been split across buffers, - // adjusting remaining_payload_ to account for the consumed portion of - // the payload. Returns values are as for StartDecodingStructureInPayload. - template <class S> - DecodeStatus ResumeDecodingStructureInPayload(S* out, DecodeBuffer* db) { - DVLOG(2) << __func__ << "\n\tdb->Remaining=" << db->Remaining() - << "\n\tremaining_payload_=" << remaining_payload_; - if (structure_decoder_.Resume(out, db, &remaining_payload_)) { - return DecodeStatus::kDecodeDone; - } else if (remaining_payload_ > 0) { - return DecodeStatus::kDecodeInProgress; - } else { - DVLOG(2) << "ResumeDecodingStructureInPayload: detected frame size error"; - return ReportFrameSizeError(); - } - } - - // Initializes the two remaining* fields, which is needed if the frame's - // payload is split across buffers, or the decoder calls ReadPadLength or - // StartDecodingStructureInPayload, and of course the methods below which - // read those fields, as their names imply. - void InitializeRemainders() { - remaining_payload_ = frame_header().payload_length; - // Note that remaining_total_payload() relies on remaining_padding_ being - // zero for frames that have no padding. - remaining_padding_ = 0; - } - - // Returns the number of bytes of the frame's payload that remain to be - // decoded, including any trailing padding. This method must only be called - // after the variables have been initialized, which in practice means once a - // payload decoder has called InitializeRemainders and/or ReadPadLength. - size_t remaining_total_payload() const { - DCHECK(IsPaddable() || remaining_padding_ == 0) << frame_header(); - return remaining_payload_ + remaining_padding_; - } - - // Returns the number of bytes of the frame's payload that remain to be - // decoded, excluding any trailing padding. This method must only be called - // after the variable has been initialized, which in practice means once a - // payload decoder has called InitializeRemainders; ReadPadLength will deduct - // the total number of padding bytes from remaining_payload_, including the - // size of the Pad Length field itself (1 byte). - size_t remaining_payload() const { return remaining_payload_; } - - // Returns the number of bytes of the frame's payload that remain to be - // decoded, including any trailing padding. This method must only be called if - // the frame type allows padding, and after the variable has been initialized, - // which in practice means once a payload decoder has called - // InitializeRemainders and/or ReadPadLength. - size_t remaining_payload_and_padding() const { - DCHECK(IsPaddable()) << frame_header(); - return remaining_payload_ + remaining_padding_; - } - - // Returns the number of bytes of trailing padding after the payload that - // remain to be decoded. This method must only be called if the frame type - // allows padding, and after the variable has been initialized, which in - // practice means once a payload decoder has called InitializeRemainders, - // and isn't set to a non-zero value until ReadPadLength has been called. - uint32_t remaining_padding() const { - DCHECK(IsPaddable()) << frame_header(); - return remaining_padding_; - } - - // How many bytes of the remaining payload are in db? - size_t AvailablePayload(DecodeBuffer* db) const { - return db->MinLengthRemaining(remaining_payload_); - } - - // How many bytes of the remaining payload and padding are in db? - // Call only for frames whose type is paddable. - size_t AvailablePayloadAndPadding(DecodeBuffer* db) const { - DCHECK(IsPaddable()) << frame_header(); - return db->MinLengthRemaining(remaining_payload_ + remaining_padding_); - } - - // How many bytes of the padding that have not yet been skipped are in db? - // Call only after remaining_padding_ has been set (for padded frames), or - // been cleared (for unpadded frames); and after all of the non-padding - // payload has been decoded. - size_t AvailablePadding(DecodeBuffer* db) const { - DCHECK(IsPaddable()) << frame_header(); - DCHECK_EQ(remaining_payload_, 0u); - return db->MinLengthRemaining(remaining_padding_); - } - - // Reduces remaining_payload_ by amount. To be called by a payload decoder - // after it has passed a variable length portion of the payload to the - // listener; remaining_payload_ will be automatically reduced when fixed - // size structures and padding, including the Pad Length field, are decoded. - void ConsumePayload(size_t amount) { - DCHECK_LE(amount, remaining_payload_); - remaining_payload_ -= amount; - } - - // Reads the Pad Length field into remaining_padding_, and appropriately sets - // remaining_payload_. When present, the Pad Length field is always the first - // field in the payload, which this method relies on so that the caller need - // not set remaining_payload_ before calling this method. - // If report_pad_length is true, calls the listener's OnPadLength method when - // it decodes the Pad Length field. - // Returns kDecodeDone if the decode buffer was not empty (i.e. because the - // field is only a single byte long, it can always be decoded if the buffer is - // not empty). - // Returns kDecodeError if the buffer is empty because the frame has no - // payload (i.e. payload_length() == 0). - // Returns kDecodeInProgress if the buffer is empty but the frame has a - // payload. - DecodeStatus ReadPadLength(DecodeBuffer* db, bool report_pad_length); - - // Skip the trailing padding bytes; only call once remaining_payload_==0. - // Returns true when the padding has been skipped. - // Does NOT check that the padding is all zeroes. - bool SkipPadding(DecodeBuffer* db); - - // Calls the listener's OnFrameSizeError method and returns kDecodeError. - DecodeStatus ReportFrameSizeError(); - - private: - friend class Http2FrameDecoder; - friend class test::FrameDecoderStatePeer; - - // Starts the decoding of a common frame header. Returns true if completed the - // decoding, false if the decode buffer didn't have enough data in it, in - // which case the decode buffer will have been drained and the caller should - // call ResumeDecodingFrameHeader when more data is available. This is called - // from Http2FrameDecoder, a friend class. - bool StartDecodingFrameHeader(DecodeBuffer* db) { - return structure_decoder_.Start(&frame_header_, db); - } - - // Resumes decoding the common frame header after the preceding call to - // StartDecodingFrameHeader returned false, as did any subsequent calls to - // ResumeDecodingFrameHeader. This is called from Http2FrameDecoder, - // a friend class. - bool ResumeDecodingFrameHeader(DecodeBuffer* db) { - return structure_decoder_.Resume(&frame_header_, db); - } - - // Clear any of the flags in the frame header that aren't set in valid_flags. - void RetainFlags(uint8_t valid_flags) { - frame_header_.RetainFlags(valid_flags); - } - - // Clear all of the flags in the frame header; for use with frame types that - // don't define any flags, such as WINDOW_UPDATE. - void ClearFlags() { frame_header_.flags = Http2FrameFlag(); } - - // Returns true if the type of frame being decoded can have padding. - bool IsPaddable() const { - return frame_header().type == Http2FrameType::DATA || - frame_header().type == Http2FrameType::HEADERS || - frame_header().type == Http2FrameType::PUSH_PROMISE; - } - - Http2FrameDecoderListener* listener_ = nullptr; - Http2FrameHeader frame_header_; - - // Number of bytes remaining to be decoded, if set; does not include the - // trailing padding once the length of padding has been determined. - // See ReadPadLength. - uint32_t remaining_payload_; - - // The amount of trailing padding after the payload that remains to be - // decoded. See ReadPadLength. - uint32_t remaining_padding_; - - // Generic decoder of structures, which takes care of buffering the needed - // bytes if the encoded structure is split across decode buffers. - Http2StructureDecoder structure_decoder_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_FRAME_DECODER_STATE_H_
diff --git a/net/third_party/http2/decoder/frame_decoder_state_test_util.cc b/net/third_party/http2/decoder/frame_decoder_state_test_util.cc deleted file mode 100644 index b7363df..0000000 --- a/net/third_party/http2/decoder/frame_decoder_state_test_util.cc +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/frame_decoder_state_test_util.h" - -#include "base/logging.h" -#include "net/third_party/http2/decoder/http2_structure_decoder_test_util.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/http2_structures_test_util.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/random_decoder_test.h" - -namespace http2 { -namespace test { - -// static -void FrameDecoderStatePeer::Randomize(FrameDecoderState* p, Http2Random* rng) { - VLOG(1) << "FrameDecoderStatePeer::Randomize"; - ::http2::test::Randomize(&p->frame_header_, rng); - p->remaining_payload_ = rng->Rand32(); - p->remaining_padding_ = rng->Rand32(); - Http2StructureDecoderPeer::Randomize(&p->structure_decoder_, rng); -} - -// static -void FrameDecoderStatePeer::set_frame_header(const Http2FrameHeader& header, - FrameDecoderState* p) { - VLOG(1) << "FrameDecoderStatePeer::set_frame_header " << header; - p->frame_header_ = header; -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/frame_decoder_state_test_util.h b/net/third_party/http2/decoder/frame_decoder_state_test_util.h deleted file mode 100644 index a118f1b..0000000 --- a/net/third_party/http2/decoder/frame_decoder_state_test_util.h +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_FRAME_DECODER_STATE_TEST_UTIL_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_FRAME_DECODER_STATE_TEST_UTIL_H_ - -#include "net/third_party/http2/decoder/frame_decoder_state.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/tools/random_decoder_test.h" - -namespace http2 { -namespace test { - -class FrameDecoderStatePeer { - public: - // Randomizes (i.e. corrupts) the fields of the FrameDecoderState. - // PayloadDecoderBaseTest::StartDecoding calls this before passing the first - // decode buffer to the payload decoder, which increases the likelihood of - // detecting any use of prior states of the decoder on the decoding of - // future payloads. - static void Randomize(FrameDecoderState* p, Http2Random* rng); - - // Inject a frame header into the FrameDecoderState. - // PayloadDecoderBaseTest::StartDecoding calls this just after calling - // Randomize (above), to simulate a full frame decoder having just finished - // decoding the common frame header and then calling the appropriate payload - // decoder based on the frame type in that frame header. - static void set_frame_header(const Http2FrameHeader& header, - FrameDecoderState* p); -}; - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_FRAME_DECODER_STATE_TEST_UTIL_H_
diff --git a/net/third_party/http2/decoder/http2_frame_decoder.cc b/net/third_party/http2/decoder/http2_frame_decoder.cc deleted file mode 100644 index c96cfc9d..0000000 --- a/net/third_party/http2/decoder/http2_frame_decoder.cc +++ /dev/null
@@ -1,433 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/http2_frame_decoder.h" - -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/hpack/varint/hpack_varint_decoder.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/platform/api/http2_bug_tracker.h" -#include "net/third_party/http2/platform/api/http2_macros.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, Http2FrameDecoder::State v) { - switch (v) { - case Http2FrameDecoder::State::kStartDecodingHeader: - return out << "kStartDecodingHeader"; - case Http2FrameDecoder::State::kResumeDecodingHeader: - return out << "kResumeDecodingHeader"; - case Http2FrameDecoder::State::kResumeDecodingPayload: - return out << "kResumeDecodingPayload"; - case Http2FrameDecoder::State::kDiscardPayload: - return out << "kDiscardPayload"; - } - // Since the value doesn't come over the wire, only a programming bug should - // result in reaching this point. - int unknown = static_cast<int>(v); - HTTP2_BUG << "Http2FrameDecoder::State " << unknown; - return out << "Http2FrameDecoder::State(" << unknown << ")"; -} - -Http2FrameDecoder::Http2FrameDecoder(Http2FrameDecoderListener* listener) - : state_(State::kStartDecodingHeader), - maximum_payload_size_(Http2SettingsInfo::DefaultMaxFrameSize()) { - set_listener(listener); -} - -void Http2FrameDecoder::set_listener(Http2FrameDecoderListener* listener) { - if (listener == nullptr) { - listener = &no_op_listener_; - } - frame_decoder_state_.set_listener(listener); -} - -Http2FrameDecoderListener* Http2FrameDecoder::listener() const { - return frame_decoder_state_.listener(); -} - -DecodeStatus Http2FrameDecoder::DecodeFrame(DecodeBuffer* db) { - DVLOG(2) << "Http2FrameDecoder::DecodeFrame state=" << state_; - switch (state_) { - case State::kStartDecodingHeader: - if (frame_decoder_state_.StartDecodingFrameHeader(db)) { - return StartDecodingPayload(db); - } - state_ = State::kResumeDecodingHeader; - return DecodeStatus::kDecodeInProgress; - - case State::kResumeDecodingHeader: - if (frame_decoder_state_.ResumeDecodingFrameHeader(db)) { - return StartDecodingPayload(db); - } - return DecodeStatus::kDecodeInProgress; - - case State::kResumeDecodingPayload: - return ResumeDecodingPayload(db); - - case State::kDiscardPayload: - return DiscardPayload(db); - } - - HTTP2_UNREACHABLE(); - return DecodeStatus::kDecodeError; -} - -size_t Http2FrameDecoder::remaining_payload() const { - return frame_decoder_state_.remaining_payload(); -} - -uint32_t Http2FrameDecoder::remaining_padding() const { - return frame_decoder_state_.remaining_padding(); -} - -DecodeStatus Http2FrameDecoder::StartDecodingPayload(DecodeBuffer* db) { - const Http2FrameHeader& header = frame_header(); - - // TODO(jamessynge): Remove OnFrameHeader once done with supporting - // SpdyFramer's exact states. - if (!listener()->OnFrameHeader(header)) { - DVLOG(2) << "OnFrameHeader rejected the frame, will discard; header: " - << header; - state_ = State::kDiscardPayload; - frame_decoder_state_.InitializeRemainders(); - return DecodeStatus::kDecodeError; - } - - if (header.payload_length > maximum_payload_size_) { - DVLOG(2) << "Payload length is greater than allowed: " - << header.payload_length << " > " << maximum_payload_size_ - << "\n header: " << header; - state_ = State::kDiscardPayload; - frame_decoder_state_.InitializeRemainders(); - listener()->OnFrameSizeError(header); - return DecodeStatus::kDecodeError; - } - - // The decode buffer can extend across many frames. Make sure that the - // buffer we pass to the start method that is specific to the frame type - // does not exend beyond this frame. - DecodeBufferSubset subset(db, header.payload_length); - DecodeStatus status; - switch (header.type) { - case Http2FrameType::DATA: - status = StartDecodingDataPayload(&subset); - break; - - case Http2FrameType::HEADERS: - status = StartDecodingHeadersPayload(&subset); - break; - - case Http2FrameType::PRIORITY: - status = StartDecodingPriorityPayload(&subset); - break; - - case Http2FrameType::RST_STREAM: - status = StartDecodingRstStreamPayload(&subset); - break; - - case Http2FrameType::SETTINGS: - status = StartDecodingSettingsPayload(&subset); - break; - - case Http2FrameType::PUSH_PROMISE: - status = StartDecodingPushPromisePayload(&subset); - break; - - case Http2FrameType::PING: - status = StartDecodingPingPayload(&subset); - break; - - case Http2FrameType::GOAWAY: - status = StartDecodingGoAwayPayload(&subset); - break; - - case Http2FrameType::WINDOW_UPDATE: - status = StartDecodingWindowUpdatePayload(&subset); - break; - - case Http2FrameType::CONTINUATION: - status = StartDecodingContinuationPayload(&subset); - break; - - case Http2FrameType::ALTSVC: - status = StartDecodingAltSvcPayload(&subset); - break; - - default: - status = StartDecodingUnknownPayload(&subset); - break; - } - - if (status == DecodeStatus::kDecodeDone) { - state_ = State::kStartDecodingHeader; - return status; - } else if (status == DecodeStatus::kDecodeInProgress) { - state_ = State::kResumeDecodingPayload; - return status; - } else { - state_ = State::kDiscardPayload; - return status; - } -} - -DecodeStatus Http2FrameDecoder::ResumeDecodingPayload(DecodeBuffer* db) { - // The decode buffer can extend across many frames. Make sure that the - // buffer we pass to the start method that is specific to the frame type - // does not exend beyond this frame. - size_t remaining = frame_decoder_state_.remaining_total_payload(); - DCHECK_LE(remaining, frame_header().payload_length); - DecodeBufferSubset subset(db, remaining); - DecodeStatus status; - switch (frame_header().type) { - case Http2FrameType::DATA: - status = ResumeDecodingDataPayload(&subset); - break; - - case Http2FrameType::HEADERS: - status = ResumeDecodingHeadersPayload(&subset); - break; - - case Http2FrameType::PRIORITY: - status = ResumeDecodingPriorityPayload(&subset); - break; - - case Http2FrameType::RST_STREAM: - status = ResumeDecodingRstStreamPayload(&subset); - break; - - case Http2FrameType::SETTINGS: - status = ResumeDecodingSettingsPayload(&subset); - break; - - case Http2FrameType::PUSH_PROMISE: - status = ResumeDecodingPushPromisePayload(&subset); - break; - - case Http2FrameType::PING: - status = ResumeDecodingPingPayload(&subset); - break; - - case Http2FrameType::GOAWAY: - status = ResumeDecodingGoAwayPayload(&subset); - break; - - case Http2FrameType::WINDOW_UPDATE: - status = ResumeDecodingWindowUpdatePayload(&subset); - break; - - case Http2FrameType::CONTINUATION: - status = ResumeDecodingContinuationPayload(&subset); - break; - - case Http2FrameType::ALTSVC: - status = ResumeDecodingAltSvcPayload(&subset); - break; - - default: - status = ResumeDecodingUnknownPayload(&subset); - break; - } - - if (status == DecodeStatus::kDecodeDone) { - state_ = State::kStartDecodingHeader; - return status; - } else if (status == DecodeStatus::kDecodeInProgress) { - return status; - } else { - state_ = State::kDiscardPayload; - return status; - } -} - -// Clear any of the flags in the frame header that aren't set in valid_flags. -void Http2FrameDecoder::RetainFlags(uint8_t valid_flags) { - frame_decoder_state_.RetainFlags(valid_flags); -} - -// Clear all of the flags in the frame header; for use with frame types that -// don't define any flags, such as WINDOW_UPDATE. -void Http2FrameDecoder::ClearFlags() { - frame_decoder_state_.ClearFlags(); -} - -DecodeStatus Http2FrameDecoder::StartDecodingAltSvcPayload(DecodeBuffer* db) { - ClearFlags(); - return altsvc_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, - db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingAltSvcPayload(DecodeBuffer* db) { - // The frame is not paddable. - DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return altsvc_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, - db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingContinuationPayload( - DecodeBuffer* db) { - RetainFlags(Http2FrameFlag::END_HEADERS); - return continuation_payload_decoder_.StartDecodingPayload( - &frame_decoder_state_, db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingContinuationPayload( - DecodeBuffer* db) { - // The frame is not paddable. - DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return continuation_payload_decoder_.ResumeDecodingPayload( - &frame_decoder_state_, db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingDataPayload(DecodeBuffer* db) { - RetainFlags(Http2FrameFlag::END_STREAM | Http2FrameFlag::PADDED); - return data_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingDataPayload(DecodeBuffer* db) { - return data_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingGoAwayPayload(DecodeBuffer* db) { - ClearFlags(); - return goaway_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, - db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingGoAwayPayload(DecodeBuffer* db) { - // The frame is not paddable. - DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return goaway_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, - db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingHeadersPayload(DecodeBuffer* db) { - RetainFlags(Http2FrameFlag::END_STREAM | Http2FrameFlag::END_HEADERS | - Http2FrameFlag::PADDED | Http2FrameFlag::PRIORITY); - return headers_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, - db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingHeadersPayload(DecodeBuffer* db) { - DCHECK_LE(frame_decoder_state_.remaining_payload_and_padding(), - frame_header().payload_length); - return headers_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, - db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingPingPayload(DecodeBuffer* db) { - RetainFlags(Http2FrameFlag::ACK); - return ping_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingPingPayload(DecodeBuffer* db) { - // The frame is not paddable. - DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return ping_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingPriorityPayload(DecodeBuffer* db) { - ClearFlags(); - return priority_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, - db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingPriorityPayload( - DecodeBuffer* db) { - // The frame is not paddable. - DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return priority_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, - db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingPushPromisePayload( - DecodeBuffer* db) { - RetainFlags(Http2FrameFlag::END_HEADERS | Http2FrameFlag::PADDED); - return push_promise_payload_decoder_.StartDecodingPayload( - &frame_decoder_state_, db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingPushPromisePayload( - DecodeBuffer* db) { - DCHECK_LE(frame_decoder_state_.remaining_payload_and_padding(), - frame_header().payload_length); - return push_promise_payload_decoder_.ResumeDecodingPayload( - &frame_decoder_state_, db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingRstStreamPayload( - DecodeBuffer* db) { - ClearFlags(); - return rst_stream_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, - db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingRstStreamPayload( - DecodeBuffer* db) { - // The frame is not paddable. - DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return rst_stream_payload_decoder_.ResumeDecodingPayload( - &frame_decoder_state_, db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingSettingsPayload(DecodeBuffer* db) { - RetainFlags(Http2FrameFlag::ACK); - return settings_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, - db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingSettingsPayload( - DecodeBuffer* db) { - // The frame is not paddable. - DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return settings_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, - db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingUnknownPayload(DecodeBuffer* db) { - // We don't known what type of frame this is, so we don't know which flags - // are valid, so we don't touch them. - return unknown_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, - db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingUnknownPayload(DecodeBuffer* db) { - // We don't known what type of frame this is, so we treat it as not paddable. - DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return unknown_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, - db); -} - -DecodeStatus Http2FrameDecoder::StartDecodingWindowUpdatePayload( - DecodeBuffer* db) { - ClearFlags(); - return window_update_payload_decoder_.StartDecodingPayload( - &frame_decoder_state_, db); -} -DecodeStatus Http2FrameDecoder::ResumeDecodingWindowUpdatePayload( - DecodeBuffer* db) { - // The frame is not paddable. - DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), - frame_decoder_state_.remaining_payload()); - return window_update_payload_decoder_.ResumeDecodingPayload( - &frame_decoder_state_, db); -} - -DecodeStatus Http2FrameDecoder::DiscardPayload(DecodeBuffer* db) { - DVLOG(2) << "remaining_payload=" << frame_decoder_state_.remaining_payload_ - << "; remaining_padding=" << frame_decoder_state_.remaining_padding_; - frame_decoder_state_.remaining_payload_ += - frame_decoder_state_.remaining_padding_; - frame_decoder_state_.remaining_padding_ = 0; - const size_t avail = frame_decoder_state_.AvailablePayload(db); - DVLOG(2) << "avail=" << avail; - if (avail > 0) { - frame_decoder_state_.ConsumePayload(avail); - db->AdvanceCursor(avail); - } - if (frame_decoder_state_.remaining_payload_ == 0) { - state_ = State::kStartDecodingHeader; - return DecodeStatus::kDecodeDone; - } - return DecodeStatus::kDecodeInProgress; -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/http2_frame_decoder.h b/net/third_party/http2/decoder/http2_frame_decoder.h deleted file mode 100644 index ed15f65..0000000 --- a/net/third_party/http2/decoder/http2_frame_decoder.h +++ /dev/null
@@ -1,205 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_HTTP2_FRAME_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_HTTP2_FRAME_DECODER_H_ - -// Http2FrameDecoder decodes the available input until it reaches the end of -// the input or it reaches the end of the first frame in the input. -// Note that Http2FrameDecoder does only minimal validation; for example, -// stream ids are not checked, nor is the sequence of frames such as -// CONTINUATION frame placement. -// -// Http2FrameDecoder enters state kError once it has called the listener's -// OnFrameSizeError or OnPaddingTooLong methods, and at this time has no -// provision for leaving that state. While the HTTP/2 spec (RFC7540) allows -// for some such errors to be considered as just stream errors in some cases, -// this implementation treats them all as connection errors. - -#include <stddef.h> - -#include <cstdint> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/decoder/frame_decoder_state.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/decoder/payload_decoders/altsvc_payload_decoder.h" -#include "net/third_party/http2/decoder/payload_decoders/continuation_payload_decoder.h" -#include "net/third_party/http2/decoder/payload_decoders/data_payload_decoder.h" -#include "net/third_party/http2/decoder/payload_decoders/goaway_payload_decoder.h" -#include "net/third_party/http2/decoder/payload_decoders/headers_payload_decoder.h" -#include "net/third_party/http2/decoder/payload_decoders/ping_payload_decoder.h" -#include "net/third_party/http2/decoder/payload_decoders/priority_payload_decoder.h" -#include "net/third_party/http2/decoder/payload_decoders/push_promise_payload_decoder.h" -#include "net/third_party/http2/decoder/payload_decoders/rst_stream_payload_decoder.h" -#include "net/third_party/http2/decoder/payload_decoders/settings_payload_decoder.h" -#include "net/third_party/http2/decoder/payload_decoders/unknown_payload_decoder.h" -#include "net/third_party/http2/decoder/payload_decoders/window_update_payload_decoder.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { -namespace test { -class Http2FrameDecoderPeer; -} // namespace test - -class HTTP2_EXPORT_PRIVATE Http2FrameDecoder { - public: - explicit Http2FrameDecoder(Http2FrameDecoderListener* listener); - Http2FrameDecoder() : Http2FrameDecoder(nullptr) {} - - Http2FrameDecoder(const Http2FrameDecoder&) = delete; - Http2FrameDecoder& operator=(const Http2FrameDecoder&) = delete; - - // The decoder will call the listener's methods as it decodes a frame. - void set_listener(Http2FrameDecoderListener* listener); - Http2FrameDecoderListener* listener() const; - - // The decoder will reject frame's whose payload - // length field exceeds the maximum payload size. - void set_maximum_payload_size(size_t v) { maximum_payload_size_ = v; } - size_t maximum_payload_size() const { return maximum_payload_size_; } - - // Decodes the input up to the next frame boundary (i.e. at most one frame). - // - // Returns kDecodeDone if it decodes the final byte of a frame, OR if there - // is no input and it is awaiting the start of a new frame (e.g. if this - // is the first call to DecodeFrame, or if the previous call returned - // kDecodeDone). - // - // Returns kDecodeInProgress if it decodes all of the decode buffer, but has - // not reached the end of the frame. - // - // Returns kDecodeError if the frame's padding or length wasn't valid (i.e. if - // the decoder called either the listener's OnPaddingTooLong or - // OnFrameSizeError method). - DecodeStatus DecodeFrame(DecodeBuffer* db); - - ////////////////////////////////////////////////////////////////////////////// - // Methods that support Http2FrameDecoderAdapter. - - // Is the remainder of the frame's payload being discarded? - bool IsDiscardingPayload() const { return state_ == State::kDiscardPayload; } - - // Returns the number of bytes of the frame's payload that remain to be - // decoded, excluding any trailing padding. This method must only be called - // after the frame header has been decoded AND DecodeFrame has returned - // kDecodeInProgress. - size_t remaining_payload() const; - - // Returns the number of bytes of trailing padding after the payload that - // remain to be decoded. This method must only be called if the frame type - // allows padding, and after the frame header has been decoded AND - // DecodeFrame has returned. Will return 0 if the Pad Length field has not - // yet been decoded. - uint32_t remaining_padding() const; - - private: - enum class State { - // Ready to start decoding a new frame's header. - kStartDecodingHeader, - // Was in state kStartDecodingHeader, but unable to read the entire frame - // header, so needs more input to complete decoding the header. - kResumeDecodingHeader, - - // Have decoded the frame header, and started decoding the available bytes - // of the frame's payload, but need more bytes to finish the job. - kResumeDecodingPayload, - - // Decoding of the most recently started frame resulted in an error: - // OnPaddingTooLong or OnFrameSizeError was called to indicate that the - // decoder detected a problem, or OnFrameHeader returned false, indicating - // that the listener detected a problem. Regardless of which, the decoder - // will stay in state kDiscardPayload until it has been passed the rest - // of the bytes of the frame's payload that it hasn't yet seen, after - // which it will be ready to decode another frame. - kDiscardPayload, - }; - - friend class test::Http2FrameDecoderPeer; - friend std::ostream& operator<<(std::ostream& out, State v); - - DecodeStatus StartDecodingPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingPayload(DecodeBuffer* db); - DecodeStatus DiscardPayload(DecodeBuffer* db); - - const Http2FrameHeader& frame_header() const { - return frame_decoder_state_.frame_header(); - } - - // Clear any of the flags in the frame header that aren't set in valid_flags. - void RetainFlags(uint8_t valid_flags); - - // Clear all of the flags in the frame header; for use with frame types that - // don't define any flags, such as WINDOW_UPDATE. - void ClearFlags(); - - // These methods call the StartDecodingPayload() method of the frame type's - // payload decoder, after first clearing invalid flags in the header. The - // caller must ensure that the decode buffer does not extend beyond the - // end of the payload (handled by Http2FrameDecoder::StartDecodingPayload). - DecodeStatus StartDecodingAltSvcPayload(DecodeBuffer* db); - DecodeStatus StartDecodingContinuationPayload(DecodeBuffer* db); - DecodeStatus StartDecodingDataPayload(DecodeBuffer* db); - DecodeStatus StartDecodingGoAwayPayload(DecodeBuffer* db); - DecodeStatus StartDecodingHeadersPayload(DecodeBuffer* db); - DecodeStatus StartDecodingPingPayload(DecodeBuffer* db); - DecodeStatus StartDecodingPriorityPayload(DecodeBuffer* db); - DecodeStatus StartDecodingPushPromisePayload(DecodeBuffer* db); - DecodeStatus StartDecodingRstStreamPayload(DecodeBuffer* db); - DecodeStatus StartDecodingSettingsPayload(DecodeBuffer* db); - DecodeStatus StartDecodingUnknownPayload(DecodeBuffer* db); - DecodeStatus StartDecodingWindowUpdatePayload(DecodeBuffer* db); - - // These methods call the ResumeDecodingPayload() method of the frame type's - // payload decoder; they are called only if the preceding call to the - // corresponding Start method (above) returned kDecodeInProgress, as did any - // subsequent calls to the resume method. - // Unlike the Start methods, the decode buffer may extend beyond the - // end of the payload, so the method will create a DecodeBufferSubset - // before calling the ResumeDecodingPayload method of the frame type's - // payload decoder. - DecodeStatus ResumeDecodingAltSvcPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingContinuationPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingDataPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingGoAwayPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingHeadersPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingPingPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingPriorityPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingPushPromisePayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingRstStreamPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingSettingsPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingUnknownPayload(DecodeBuffer* db); - DecodeStatus ResumeDecodingWindowUpdatePayload(DecodeBuffer* db); - - FrameDecoderState frame_decoder_state_; - - // We only need one payload decoder at a time, so they share the same storage. - union { - AltSvcPayloadDecoder altsvc_payload_decoder_; - ContinuationPayloadDecoder continuation_payload_decoder_; - DataPayloadDecoder data_payload_decoder_; - GoAwayPayloadDecoder goaway_payload_decoder_; - HeadersPayloadDecoder headers_payload_decoder_; - PingPayloadDecoder ping_payload_decoder_; - PriorityPayloadDecoder priority_payload_decoder_; - PushPromisePayloadDecoder push_promise_payload_decoder_; - RstStreamPayloadDecoder rst_stream_payload_decoder_; - SettingsPayloadDecoder settings_payload_decoder_; - UnknownPayloadDecoder unknown_payload_decoder_; - WindowUpdatePayloadDecoder window_update_payload_decoder_; - }; - - State state_; - size_t maximum_payload_size_; - - // Listener used whenever caller passes nullptr to set_listener. - Http2FrameDecoderNoOpListener no_op_listener_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_HTTP2_FRAME_DECODER_H_
diff --git a/net/third_party/http2/decoder/http2_frame_decoder_fuzzer.cc b/net/third_party/http2/decoder/http2_frame_decoder_fuzzer.cc deleted file mode 100644 index 7e8942e..0000000 --- a/net/third_party/http2/decoder/http2_frame_decoder_fuzzer.cc +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2017 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 <stddef.h> -#include <stdint.h> - -#include <vector> - -#include "base/test/fuzzed_data_provider.h" -#include "net/third_party/http2/decoder/http2_frame_decoder.h" - -// Entry point for LibFuzzer. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - base::FuzzedDataProvider fuzzed_data_provider(data, size); - http2::Http2FrameDecoder decoder; - while (fuzzed_data_provider.remaining_bytes() > 0) { - size_t chunk_size = fuzzed_data_provider.ConsumeIntegralInRange(1, 32); - std::vector<char> chunk = - fuzzed_data_provider.ConsumeBytes<char>(chunk_size); - - // http2::DecodeBuffer constructor does not accept nullptr buffer. - if (chunk.data() == nullptr) - continue; - - http2::DecodeBuffer frame_data(chunk.data(), chunk.size()); - decoder.DecodeFrame(&frame_data); - } - return 0; -}
diff --git a/net/third_party/http2/decoder/http2_frame_decoder_listener.cc b/net/third_party/http2/decoder/http2_frame_decoder_listener.cc deleted file mode 100644 index 21d7979..0000000 --- a/net/third_party/http2/decoder/http2_frame_decoder_listener.cc +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/http2_frame_decoder_listener.h" - -namespace http2 { - -bool Http2FrameDecoderNoOpListener::OnFrameHeader( - const Http2FrameHeader& header) { - return true; -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/http2_frame_decoder_listener.h b/net/third_party/http2/decoder/http2_frame_decoder_listener.h deleted file mode 100644 index 61e1e2ba0..0000000 --- a/net/third_party/http2/decoder/http2_frame_decoder_listener.h +++ /dev/null
@@ -1,357 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_H_ - -// Http2FrameDecoderListener is the interface which the HTTP/2 decoder uses -// to report the decoded frames to a listener. -// -// The general design is to assume that the listener will copy the data it needs -// (e.g. frame headers) and will keep track of the implicit state of the -// decoding process (i.e. the decoder maintains just the information it needs in -// order to perform the decoding). Therefore, the parameters are just those with -// (potentially) new data, not previously provided info about the current frame. -// -// The calls are described as if they are made in quick succession, i.e. one -// after another, but of course the decoder needs input to decode, and the -// decoder will only call the listener once the necessary input has been -// provided. For example: OnDataStart can only be called once the 9 bytes of -// of an HTTP/2 common frame header have been received. The decoder will call -// the listener methods as soon as possible to avoid almost all buffering. -// -// The listener interface is designed so that it is possible to exactly -// reconstruct the serialized frames, with the exception of reserved bits, -// including in the frame header's flags and stream_id fields, which will have -// been cleared before the methods below are called. - -#include <stddef.h> - -#include <cstdint> -#include <type_traits> - -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" - -namespace http2 { - -// TODO(jamessynge): Consider sorting the methods by frequency of call, if that -// helps at all. -class Http2FrameDecoderListener { - public: - Http2FrameDecoderListener() {} - virtual ~Http2FrameDecoderListener() {} - - // Called once the common frame header has been decoded for any frame, and - // before any of the methods below, which will also be called. This method is - // included in this interface only for the purpose of supporting SpdyFramer - // semantics via an adapter. This is the only method that has a non-void - // return type, and this is just so that Http2FrameDecoderAdapter (called - // from SpdyFramer) can more readily pass existing tests that expect decoding - // to stop if the headers alone indicate an error. Return false to stop - // decoding just after decoding the header, else return true to continue - // decoding. - // TODO(jamessynge): Remove OnFrameHeader once done with supporting - // SpdyFramer's exact states. - virtual bool OnFrameHeader(const Http2FrameHeader& header) = 0; - - ////////////////////////////////////////////////////////////////////////////// - - // Called once the common frame header has been decoded for a DATA frame, - // before examining the frame's payload, after which: - // OnPadLength will be called if header.IsPadded() is true, i.e. if the - // PADDED flag is set; - // OnDataPayload will be called as the non-padding portion of the payload - // is available until all of it has been provided; - // OnPadding will be called if the frame is padded AND the Pad Length field - // is greater than zero; - // OnDataEnd will be called last. If the frame is unpadded and has no - // payload, then this will be called immediately after OnDataStart. - virtual void OnDataStart(const Http2FrameHeader& header) = 0; - - // Called when the next non-padding portion of a DATA frame's payload is - // received. - // |data| The start of |len| bytes of data. - // |len| The length of the data buffer. Maybe zero in some cases, which does - // not mean anything special. - virtual void OnDataPayload(const char* data, size_t len) = 0; - - // Called after an entire DATA frame has been received. - // If header.IsEndStream() == true, this is the last data for the stream. - virtual void OnDataEnd() = 0; - - // Called once the common frame header has been decoded for a HEADERS frame, - // before examining the frame's payload, after which: - // OnPadLength will be called if header.IsPadded() is true, i.e. if the - // PADDED flag is set; - // OnHeadersPriority will be called if header.HasPriority() is true, i.e. if - // the frame has the PRIORITY flag; - // OnHpackFragment as the remainder of the non-padding payload is available - // until all if has been provided; - // OnPadding will be called if the frame is padded AND the Pad Length field - // is greater than zero; - // OnHeadersEnd will be called last; If the frame is unpadded and has no - // payload, then this will be called immediately after OnHeadersStart; - // OnHeadersEnd indicates the end of the HPACK block only if the frame - // header had the END_HEADERS flag set, else the END_HEADERS should be - // looked for on a subsequent CONTINUATION frame. - virtual void OnHeadersStart(const Http2FrameHeader& header) = 0; - - // Called when a HEADERS frame is received with the PRIORITY flag set and - // the priority fields have been decoded. - virtual void OnHeadersPriority( - const Http2PriorityFields& priority_fields) = 0; - - // Called when a fragment (i.e. some or all of an HPACK Block) is received; - // this may be part of a HEADERS, PUSH_PROMISE or CONTINUATION frame. - // |data| The start of |len| bytes of data. - // |len| The length of the data buffer. Maybe zero in some cases, which does - // not mean anything special, except that it simplified the decoder. - virtual void OnHpackFragment(const char* data, size_t len) = 0; - - // Called after an entire HEADERS frame has been received. The frame is the - // end of the HEADERS if the END_HEADERS flag is set; else there should be - // CONTINUATION frames after this frame. - virtual void OnHeadersEnd() = 0; - - // Called when an entire PRIORITY frame has been decoded. - virtual void OnPriorityFrame(const Http2FrameHeader& header, - const Http2PriorityFields& priority_fields) = 0; - - // Called once the common frame header has been decoded for a CONTINUATION - // frame, before examining the frame's payload, after which: - // OnHpackFragment as the frame's payload is available until all of it - // has been provided; - // OnContinuationEnd will be called last; If the frame has no payload, - // then this will be called immediately after OnContinuationStart; - // the HPACK block is at an end if and only if the frame header passed - // to OnContinuationStart had the END_HEADERS flag set. - virtual void OnContinuationStart(const Http2FrameHeader& header) = 0; - - // Called after an entire CONTINUATION frame has been received. The frame is - // the end of the HEADERS if the END_HEADERS flag is set. - virtual void OnContinuationEnd() = 0; - - // Called when Pad Length field has been read. Applies to DATA and HEADERS - // frames. For PUSH_PROMISE frames, the Pad Length + 1 is provided in the - // OnPushPromiseStart call as total_padding_length. - virtual void OnPadLength(size_t pad_length) = 0; - - // Called when padding is skipped over. - virtual void OnPadding(const char* padding, size_t skipped_length) = 0; - - // Called when an entire RST_STREAM frame has been decoded. - // This is the only callback for RST_STREAM frames. - virtual void OnRstStream(const Http2FrameHeader& header, - Http2ErrorCode error_code) = 0; - - // Called once the common frame header has been decoded for a SETTINGS frame - // without the ACK flag, before examining the frame's payload, after which: - // OnSetting will be called in turn for each pair of settings parameter and - // value found in the payload; - // OnSettingsEnd will be called last; If the frame has no payload, - // then this will be called immediately after OnSettingsStart. - // The frame header is passed so that the caller can check the stream_id, - // which should be zero, but that hasn't been checked by the decoder. - virtual void OnSettingsStart(const Http2FrameHeader& header) = 0; - - // Called for each setting parameter and value within a SETTINGS frame. - virtual void OnSetting(const Http2SettingFields& setting_fields) = 0; - - // Called after parsing the complete payload of SETTINGS frame (non-ACK). - virtual void OnSettingsEnd() = 0; - - // Called when an entire SETTINGS frame, with the ACK flag, has been decoded. - virtual void OnSettingsAck(const Http2FrameHeader& header) = 0; - - // Called just before starting to process the HPACK block of a PUSH_PROMISE - // frame. The Pad Length field has already been decoded at this point, so - // OnPadLength will not be called; note that total_padding_length is Pad - // Length + 1. After OnPushPromiseStart: - // OnHpackFragment as the remainder of the non-padding payload is available - // until all if has been provided; - // OnPadding will be called if the frame is padded AND the Pad Length field - // is greater than zero (i.e. total_padding_length > 1); - // OnPushPromiseEnd will be called last; If the frame is unpadded and has no - // payload, then this will be called immediately after OnPushPromiseStart. - virtual void OnPushPromiseStart(const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) = 0; - - // Called after all of the HPACK block fragment and padding of a PUSH_PROMISE - // has been decoded and delivered to the listener. This call indicates the end - // of the HPACK block if and only if the frame header had the END_HEADERS flag - // set (i.e. header.IsEndHeaders() is true); otherwise the next block must be - // a CONTINUATION frame with the same stream id (not the same promised stream - // id). - virtual void OnPushPromiseEnd() = 0; - - // Called when an entire PING frame, without the ACK flag, has been decoded. - virtual void OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) = 0; - - // Called when an entire PING frame, with the ACK flag, has been decoded. - virtual void OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) = 0; - - // Called after parsing a GOAWAY frame's header and fixed size fields, after - // which: - // OnGoAwayOpaqueData will be called as opaque data of the payload becomes - // available to the decoder, until all of it has been provided to the - // listener; - // OnGoAwayEnd will be called last, after all the opaque data has been - // provided to the listener; if there is no opaque data, then OnGoAwayEnd - // will be called immediately after OnGoAwayStart. - virtual void OnGoAwayStart(const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) = 0; - - // Called when the next portion of a GOAWAY frame's payload is received. - // |data| The start of |len| bytes of opaque data. - // |len| The length of the opaque data buffer. Maybe zero in some cases, - // which does not mean anything special. - virtual void OnGoAwayOpaqueData(const char* data, size_t len) = 0; - - // Called after finishing decoding all of a GOAWAY frame. - virtual void OnGoAwayEnd() = 0; - - // Called when an entire WINDOW_UPDATE frame has been decoded. The - // window_size_increment is required to be non-zero, but that has not been - // checked. If header.stream_id==0, the connection's flow control window is - // being increased, else the specified stream's flow control is being - // increased. - virtual void OnWindowUpdate(const Http2FrameHeader& header, - uint32_t window_size_increment) = 0; - - // Called when an ALTSVC frame header and origin length have been parsed. - // Either or both lengths may be zero. After OnAltSvcStart: - // OnAltSvcOriginData will be called until all of the (optional) Origin - // has been provided; - // OnAltSvcValueData will be called until all of the Alt-Svc-Field-Value - // has been provided; - // OnAltSvcEnd will called last, after all of the origin and - // Alt-Svc-Field-Value have been delivered to the listener. - virtual void OnAltSvcStart(const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) = 0; - - // Called when decoding the (optional) origin of an ALTSVC; - // the field is uninterpreted. - virtual void OnAltSvcOriginData(const char* data, size_t len) = 0; - - // Called when decoding the Alt-Svc-Field-Value of an ALTSVC; - // the field is uninterpreted. - virtual void OnAltSvcValueData(const char* data, size_t len) = 0; - - // Called after decoding all of a ALTSVC frame and providing to the listener - // via the above methods. - virtual void OnAltSvcEnd() = 0; - - // Called when the common frame header has been decoded, but the frame type - // is unknown, after which: - // OnUnknownPayload is called as the payload of the frame is provided to the - // decoder, until all of the payload has been decoded; - // OnUnknownEnd will called last, after the entire frame of the unknown type - // has been decoded and provided to the listener. - virtual void OnUnknownStart(const Http2FrameHeader& header) = 0; - - // Called when the payload of an unknown frame type is received. - // |data| A buffer containing the data received. - // |len| The length of the data buffer. - virtual void OnUnknownPayload(const char* data, size_t len) = 0; - - // Called after decoding all of the payload of an unknown frame type. - virtual void OnUnknownEnd() = 0; - - ////////////////////////////////////////////////////////////////////////////// - // Below here are events indicating a problem has been detected during - // decoding (i.e. the received frames are malformed in some way). - - // Padding field (uint8) has a value that is too large (i.e. the amount of - // padding is greater than the remainder of the payload that isn't required). - // From RFC Section 6.1, DATA: - // If the length of the padding is the length of the frame payload or - // greater, the recipient MUST treat this as a connection error - // (Section 5.4.1) of type PROTOCOL_ERROR. - // The same is true for HEADERS and PUSH_PROMISE. - virtual void OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) = 0; - - // Frame size error. Depending upon the effected frame, this may or may not - // require terminating the connection, though that is probably the best thing - // to do. - // From RFC Section 4.2, Frame Size: - // An endpoint MUST send an error code of FRAME_SIZE_ERROR if a frame - // exceeds the size defined in SETTINGS_MAX_FRAME_SIZE, exceeds any limit - // defined for the frame type, or is too small to contain mandatory frame - // data. A frame size error in a frame that could alter the state of the - // the entire connection MUST be treated as a connection error - // (Section 5.4.1); this includes any frame carrying a header block - // (Section 4.3) (that is, HEADERS, PUSH_PROMISE, and CONTINUATION), - // SETTINGS, and any frame with a stream identifier of 0. - virtual void OnFrameSizeError(const Http2FrameHeader& header) = 0; -}; - -// Do nothing for each call. Useful for ignoring a frame that is invalid. -class Http2FrameDecoderNoOpListener : public Http2FrameDecoderListener { - public: - Http2FrameDecoderNoOpListener() {} - ~Http2FrameDecoderNoOpListener() override {} - - // TODO(jamessynge): Remove OnFrameHeader once done with supporting - // SpdyFramer's exact states. - bool OnFrameHeader(const Http2FrameHeader& header) override; - - void OnDataStart(const Http2FrameHeader& header) override {} - void OnDataPayload(const char* data, size_t len) override {} - void OnDataEnd() override {} - void OnHeadersStart(const Http2FrameHeader& header) override {} - void OnHeadersPriority(const Http2PriorityFields& priority) override {} - void OnHpackFragment(const char* data, size_t len) override {} - void OnHeadersEnd() override {} - void OnPriorityFrame(const Http2FrameHeader& header, - const Http2PriorityFields& priority) override {} - void OnContinuationStart(const Http2FrameHeader& header) override {} - void OnContinuationEnd() override {} - void OnPadLength(size_t trailing_length) override {} - void OnPadding(const char* padding, size_t skipped_length) override {} - void OnRstStream(const Http2FrameHeader& header, - Http2ErrorCode error_code) override {} - void OnSettingsStart(const Http2FrameHeader& header) override {} - void OnSetting(const Http2SettingFields& setting_fields) override {} - void OnSettingsEnd() override {} - void OnSettingsAck(const Http2FrameHeader& header) override {} - void OnPushPromiseStart(const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) override {} - void OnPushPromiseEnd() override {} - void OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) override {} - void OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) override {} - void OnGoAwayStart(const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) override {} - void OnGoAwayOpaqueData(const char* data, size_t len) override {} - void OnGoAwayEnd() override {} - void OnWindowUpdate(const Http2FrameHeader& header, - uint32_t increment) override {} - void OnAltSvcStart(const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) override {} - void OnAltSvcOriginData(const char* data, size_t len) override {} - void OnAltSvcValueData(const char* data, size_t len) override {} - void OnAltSvcEnd() override {} - void OnUnknownStart(const Http2FrameHeader& header) override {} - void OnUnknownPayload(const char* data, size_t len) override {} - void OnUnknownEnd() override {} - void OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) override {} - void OnFrameSizeError(const Http2FrameHeader& header) override {} -}; - -static_assert(!std::is_abstract<Http2FrameDecoderNoOpListener>(), - "Http2FrameDecoderNoOpListener ought to be concrete."); - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_H_
diff --git a/net/third_party/http2/decoder/http2_frame_decoder_listener_test_util.cc b/net/third_party/http2/decoder/http2_frame_decoder_listener_test_util.cc deleted file mode 100644 index be649a5..0000000 --- a/net/third_party/http2/decoder/http2_frame_decoder_listener_test_util.cc +++ /dev/null
@@ -1,488 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/http2_frame_decoder_listener_test_util.h" - -#include "base/logging.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { - -FailingHttp2FrameDecoderListener::FailingHttp2FrameDecoderListener() = default; -FailingHttp2FrameDecoderListener::~FailingHttp2FrameDecoderListener() = default; - -bool FailingHttp2FrameDecoderListener::OnFrameHeader( - const Http2FrameHeader& header) { - ADD_FAILURE() << "OnFrameHeader: " << header; - return false; -} - -void FailingHttp2FrameDecoderListener::OnDataStart( - const Http2FrameHeader& header) { - FAIL() << "OnDataStart: " << header; -} - -void FailingHttp2FrameDecoderListener::OnDataPayload(const char* data, - size_t len) { - FAIL() << "OnDataPayload: len=" << len; -} - -void FailingHttp2FrameDecoderListener::OnDataEnd() { - FAIL() << "OnDataEnd"; -} - -void FailingHttp2FrameDecoderListener::OnHeadersStart( - const Http2FrameHeader& header) { - FAIL() << "OnHeadersStart: " << header; -} - -void FailingHttp2FrameDecoderListener::OnHeadersPriority( - const Http2PriorityFields& priority) { - FAIL() << "OnHeadersPriority: " << priority; -} - -void FailingHttp2FrameDecoderListener::OnHpackFragment(const char* data, - size_t len) { - FAIL() << "OnHpackFragment: len=" << len; -} - -void FailingHttp2FrameDecoderListener::OnHeadersEnd() { - FAIL() << "OnHeadersEnd"; -} - -void FailingHttp2FrameDecoderListener::OnPriorityFrame( - const Http2FrameHeader& header, - const Http2PriorityFields& priority) { - FAIL() << "OnPriorityFrame: " << header << "; priority: " << priority; -} - -void FailingHttp2FrameDecoderListener::OnContinuationStart( - const Http2FrameHeader& header) { - FAIL() << "OnContinuationStart: " << header; -} - -void FailingHttp2FrameDecoderListener::OnContinuationEnd() { - FAIL() << "OnContinuationEnd"; -} - -void FailingHttp2FrameDecoderListener::OnPadLength(size_t trailing_length) { - FAIL() << "OnPadLength: trailing_length=" << trailing_length; -} - -void FailingHttp2FrameDecoderListener::OnPadding(const char* padding, - size_t skipped_length) { - FAIL() << "OnPadding: skipped_length=" << skipped_length; -} - -void FailingHttp2FrameDecoderListener::OnRstStream( - const Http2FrameHeader& header, - Http2ErrorCode error_code) { - FAIL() << "OnRstStream: " << header << "; code=" << error_code; -} - -void FailingHttp2FrameDecoderListener::OnSettingsStart( - const Http2FrameHeader& header) { - FAIL() << "OnSettingsStart: " << header; -} - -void FailingHttp2FrameDecoderListener::OnSetting( - const Http2SettingFields& setting_fields) { - FAIL() << "OnSetting: " << setting_fields; -} - -void FailingHttp2FrameDecoderListener::OnSettingsEnd() { - FAIL() << "OnSettingsEnd"; -} - -void FailingHttp2FrameDecoderListener::OnSettingsAck( - const Http2FrameHeader& header) { - FAIL() << "OnSettingsAck: " << header; -} - -void FailingHttp2FrameDecoderListener::OnPushPromiseStart( - const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) { - FAIL() << "OnPushPromiseStart: " << header << "; promise: " << promise - << "; total_padding_length: " << total_padding_length; -} - -void FailingHttp2FrameDecoderListener::OnPushPromiseEnd() { - FAIL() << "OnPushPromiseEnd"; -} - -void FailingHttp2FrameDecoderListener::OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) { - FAIL() << "OnPing: " << header << "; ping: " << ping; -} - -void FailingHttp2FrameDecoderListener::OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) { - FAIL() << "OnPingAck: " << header << "; ping: " << ping; -} - -void FailingHttp2FrameDecoderListener::OnGoAwayStart( - const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) { - FAIL() << "OnGoAwayStart: " << header << "; goaway: " << goaway; -} - -void FailingHttp2FrameDecoderListener::OnGoAwayOpaqueData(const char* data, - size_t len) { - FAIL() << "OnGoAwayOpaqueData: len=" << len; -} - -void FailingHttp2FrameDecoderListener::OnGoAwayEnd() { - FAIL() << "OnGoAwayEnd"; -} - -void FailingHttp2FrameDecoderListener::OnWindowUpdate( - const Http2FrameHeader& header, - uint32_t increment) { - FAIL() << "OnWindowUpdate: " << header << "; increment=" << increment; -} - -void FailingHttp2FrameDecoderListener::OnAltSvcStart( - const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) { - FAIL() << "OnAltSvcStart: " << header << "; origin_length: " << origin_length - << "; value_length: " << value_length; -} - -void FailingHttp2FrameDecoderListener::OnAltSvcOriginData(const char* data, - size_t len) { - FAIL() << "OnAltSvcOriginData: len=" << len; -} - -void FailingHttp2FrameDecoderListener::OnAltSvcValueData(const char* data, - size_t len) { - FAIL() << "OnAltSvcValueData: len=" << len; -} - -void FailingHttp2FrameDecoderListener::OnAltSvcEnd() { - FAIL() << "OnAltSvcEnd"; -} - -void FailingHttp2FrameDecoderListener::OnUnknownStart( - const Http2FrameHeader& header) { - FAIL() << "OnUnknownStart: " << header; -} - -void FailingHttp2FrameDecoderListener::OnUnknownPayload(const char* data, - size_t len) { - FAIL() << "OnUnknownPayload: len=" << len; -} - -void FailingHttp2FrameDecoderListener::OnUnknownEnd() { - FAIL() << "OnUnknownEnd"; -} - -void FailingHttp2FrameDecoderListener::OnPaddingTooLong( - const Http2FrameHeader& header, - size_t missing_length) { - FAIL() << "OnPaddingTooLong: " << header - << "; missing_length: " << missing_length; -} - -void FailingHttp2FrameDecoderListener::OnFrameSizeError( - const Http2FrameHeader& header) { - FAIL() << "OnFrameSizeError: " << header; -} - -LoggingHttp2FrameDecoderListener::LoggingHttp2FrameDecoderListener() - : wrapped_(nullptr) {} -LoggingHttp2FrameDecoderListener::LoggingHttp2FrameDecoderListener( - Http2FrameDecoderListener* wrapped) - : wrapped_(wrapped) {} -LoggingHttp2FrameDecoderListener::~LoggingHttp2FrameDecoderListener() = default; - -bool LoggingHttp2FrameDecoderListener::OnFrameHeader( - const Http2FrameHeader& header) { - VLOG(1) << "OnFrameHeader: " << header; - if (wrapped_ != nullptr) { - return wrapped_->OnFrameHeader(header); - } - return true; -} - -void LoggingHttp2FrameDecoderListener::OnDataStart( - const Http2FrameHeader& header) { - VLOG(1) << "OnDataStart: " << header; - if (wrapped_ != nullptr) { - wrapped_->OnDataStart(header); - } -} - -void LoggingHttp2FrameDecoderListener::OnDataPayload(const char* data, - size_t len) { - VLOG(1) << "OnDataPayload: len=" << len; - if (wrapped_ != nullptr) { - wrapped_->OnDataPayload(data, len); - } -} - -void LoggingHttp2FrameDecoderListener::OnDataEnd() { - VLOG(1) << "OnDataEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnDataEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnHeadersStart( - const Http2FrameHeader& header) { - VLOG(1) << "OnHeadersStart: " << header; - if (wrapped_ != nullptr) { - wrapped_->OnHeadersStart(header); - } -} - -void LoggingHttp2FrameDecoderListener::OnHeadersPriority( - const Http2PriorityFields& priority) { - VLOG(1) << "OnHeadersPriority: " << priority; - if (wrapped_ != nullptr) { - wrapped_->OnHeadersPriority(priority); - } -} - -void LoggingHttp2FrameDecoderListener::OnHpackFragment(const char* data, - size_t len) { - VLOG(1) << "OnHpackFragment: len=" << len; - if (wrapped_ != nullptr) { - wrapped_->OnHpackFragment(data, len); - } -} - -void LoggingHttp2FrameDecoderListener::OnHeadersEnd() { - VLOG(1) << "OnHeadersEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnHeadersEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnPriorityFrame( - const Http2FrameHeader& header, - const Http2PriorityFields& priority) { - VLOG(1) << "OnPriorityFrame: " << header << "; priority: " << priority; - if (wrapped_ != nullptr) { - wrapped_->OnPriorityFrame(header, priority); - } -} - -void LoggingHttp2FrameDecoderListener::OnContinuationStart( - const Http2FrameHeader& header) { - VLOG(1) << "OnContinuationStart: " << header; - if (wrapped_ != nullptr) { - wrapped_->OnContinuationStart(header); - } -} - -void LoggingHttp2FrameDecoderListener::OnContinuationEnd() { - VLOG(1) << "OnContinuationEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnContinuationEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnPadLength(size_t trailing_length) { - VLOG(1) << "OnPadLength: trailing_length=" << trailing_length; - if (wrapped_ != nullptr) { - wrapped_->OnPadLength(trailing_length); - } -} - -void LoggingHttp2FrameDecoderListener::OnPadding(const char* padding, - size_t skipped_length) { - VLOG(1) << "OnPadding: skipped_length=" << skipped_length; - if (wrapped_ != nullptr) { - wrapped_->OnPadding(padding, skipped_length); - } -} - -void LoggingHttp2FrameDecoderListener::OnRstStream( - const Http2FrameHeader& header, - Http2ErrorCode error_code) { - VLOG(1) << "OnRstStream: " << header << "; code=" << error_code; - if (wrapped_ != nullptr) { - wrapped_->OnRstStream(header, error_code); - } -} - -void LoggingHttp2FrameDecoderListener::OnSettingsStart( - const Http2FrameHeader& header) { - VLOG(1) << "OnSettingsStart: " << header; - if (wrapped_ != nullptr) { - wrapped_->OnSettingsStart(header); - } -} - -void LoggingHttp2FrameDecoderListener::OnSetting( - const Http2SettingFields& setting_fields) { - VLOG(1) << "OnSetting: " << setting_fields; - if (wrapped_ != nullptr) { - wrapped_->OnSetting(setting_fields); - } -} - -void LoggingHttp2FrameDecoderListener::OnSettingsEnd() { - VLOG(1) << "OnSettingsEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnSettingsEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnSettingsAck( - const Http2FrameHeader& header) { - VLOG(1) << "OnSettingsAck: " << header; - if (wrapped_ != nullptr) { - wrapped_->OnSettingsAck(header); - } -} - -void LoggingHttp2FrameDecoderListener::OnPushPromiseStart( - const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) { - VLOG(1) << "OnPushPromiseStart: " << header << "; promise: " << promise - << "; total_padding_length: " << total_padding_length; - if (wrapped_ != nullptr) { - wrapped_->OnPushPromiseStart(header, promise, total_padding_length); - } -} - -void LoggingHttp2FrameDecoderListener::OnPushPromiseEnd() { - VLOG(1) << "OnPushPromiseEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnPushPromiseEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) { - VLOG(1) << "OnPing: " << header << "; ping: " << ping; - if (wrapped_ != nullptr) { - wrapped_->OnPing(header, ping); - } -} - -void LoggingHttp2FrameDecoderListener::OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) { - VLOG(1) << "OnPingAck: " << header << "; ping: " << ping; - if (wrapped_ != nullptr) { - wrapped_->OnPingAck(header, ping); - } -} - -void LoggingHttp2FrameDecoderListener::OnGoAwayStart( - const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) { - VLOG(1) << "OnGoAwayStart: " << header << "; goaway: " << goaway; - if (wrapped_ != nullptr) { - wrapped_->OnGoAwayStart(header, goaway); - } -} - -void LoggingHttp2FrameDecoderListener::OnGoAwayOpaqueData(const char* data, - size_t len) { - VLOG(1) << "OnGoAwayOpaqueData: len=" << len; - if (wrapped_ != nullptr) { - wrapped_->OnGoAwayOpaqueData(data, len); - } -} - -void LoggingHttp2FrameDecoderListener::OnGoAwayEnd() { - VLOG(1) << "OnGoAwayEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnGoAwayEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnWindowUpdate( - const Http2FrameHeader& header, - uint32_t increment) { - VLOG(1) << "OnWindowUpdate: " << header << "; increment=" << increment; - if (wrapped_ != nullptr) { - wrapped_->OnWindowUpdate(header, increment); - } -} - -void LoggingHttp2FrameDecoderListener::OnAltSvcStart( - const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) { - VLOG(1) << "OnAltSvcStart: " << header << "; origin_length: " << origin_length - << "; value_length: " << value_length; - if (wrapped_ != nullptr) { - wrapped_->OnAltSvcStart(header, origin_length, value_length); - } -} - -void LoggingHttp2FrameDecoderListener::OnAltSvcOriginData(const char* data, - size_t len) { - VLOG(1) << "OnAltSvcOriginData: len=" << len; - if (wrapped_ != nullptr) { - wrapped_->OnAltSvcOriginData(data, len); - } -} - -void LoggingHttp2FrameDecoderListener::OnAltSvcValueData(const char* data, - size_t len) { - VLOG(1) << "OnAltSvcValueData: len=" << len; - if (wrapped_ != nullptr) { - wrapped_->OnAltSvcValueData(data, len); - } -} - -void LoggingHttp2FrameDecoderListener::OnAltSvcEnd() { - VLOG(1) << "OnAltSvcEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnAltSvcEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnUnknownStart( - const Http2FrameHeader& header) { - VLOG(1) << "OnUnknownStart: " << header; - if (wrapped_ != nullptr) { - wrapped_->OnUnknownStart(header); - } -} - -void LoggingHttp2FrameDecoderListener::OnUnknownPayload(const char* data, - size_t len) { - VLOG(1) << "OnUnknownPayload: len=" << len; - if (wrapped_ != nullptr) { - wrapped_->OnUnknownPayload(data, len); - } -} - -void LoggingHttp2FrameDecoderListener::OnUnknownEnd() { - VLOG(1) << "OnUnknownEnd"; - if (wrapped_ != nullptr) { - wrapped_->OnUnknownEnd(); - } -} - -void LoggingHttp2FrameDecoderListener::OnPaddingTooLong( - const Http2FrameHeader& header, - size_t missing_length) { - VLOG(1) << "OnPaddingTooLong: " << header - << "; missing_length: " << missing_length; - if (wrapped_ != nullptr) { - wrapped_->OnPaddingTooLong(header, missing_length); - } -} - -void LoggingHttp2FrameDecoderListener::OnFrameSizeError( - const Http2FrameHeader& header) { - VLOG(1) << "OnFrameSizeError: " << header; - if (wrapped_ != nullptr) { - wrapped_->OnFrameSizeError(header); - } -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/http2_frame_decoder_listener_test_util.h b/net/third_party/http2/decoder/http2_frame_decoder_listener_test_util.h deleted file mode 100644 index ed484254..0000000 --- a/net/third_party/http2/decoder/http2_frame_decoder_listener_test_util.h +++ /dev/null
@@ -1,143 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_TEST_UTIL_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_TEST_UTIL_H_ - -#include <stddef.h> - -#include <cstdint> - -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" - -namespace http2 { - -// Fail if any of the methods are called. Allows a test to override only the -// expected calls. -class FailingHttp2FrameDecoderListener : public Http2FrameDecoderListener { - public: - FailingHttp2FrameDecoderListener(); - ~FailingHttp2FrameDecoderListener() override; - - // TODO(jamessynge): Remove OnFrameHeader once done with supporting - // SpdyFramer's exact states. - bool OnFrameHeader(const Http2FrameHeader& header) override; - void OnDataStart(const Http2FrameHeader& header) override; - void OnDataPayload(const char* data, size_t len) override; - void OnDataEnd() override; - void OnHeadersStart(const Http2FrameHeader& header) override; - void OnHeadersPriority(const Http2PriorityFields& priority) override; - void OnHpackFragment(const char* data, size_t len) override; - void OnHeadersEnd() override; - void OnPriorityFrame(const Http2FrameHeader& header, - const Http2PriorityFields& priority) override; - void OnContinuationStart(const Http2FrameHeader& header) override; - void OnContinuationEnd() override; - void OnPadLength(size_t trailing_length) override; - void OnPadding(const char* padding, size_t skipped_length) override; - void OnRstStream(const Http2FrameHeader& header, - Http2ErrorCode error_code) override; - void OnSettingsStart(const Http2FrameHeader& header) override; - void OnSetting(const Http2SettingFields& setting_fields) override; - void OnSettingsEnd() override; - void OnSettingsAck(const Http2FrameHeader& header) override; - void OnPushPromiseStart(const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) override; - void OnPushPromiseEnd() override; - void OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) override; - void OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) override; - void OnGoAwayStart(const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) override; - void OnGoAwayOpaqueData(const char* data, size_t len) override; - void OnGoAwayEnd() override; - void OnWindowUpdate(const Http2FrameHeader& header, - uint32_t increment) override; - void OnAltSvcStart(const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) override; - void OnAltSvcOriginData(const char* data, size_t len) override; - void OnAltSvcValueData(const char* data, size_t len) override; - void OnAltSvcEnd() override; - void OnUnknownStart(const Http2FrameHeader& header) override; - void OnUnknownPayload(const char* data, size_t len) override; - void OnUnknownEnd() override; - void OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) override; - void OnFrameSizeError(const Http2FrameHeader& header) override; - - private: - void EnsureNotAbstract() { FailingHttp2FrameDecoderListener instance; } -}; - -// VLOG's all the calls it receives, and forwards those calls to an optional -// listener. -class LoggingHttp2FrameDecoderListener : public Http2FrameDecoderListener { - public: - LoggingHttp2FrameDecoderListener(); - explicit LoggingHttp2FrameDecoderListener(Http2FrameDecoderListener* wrapped); - ~LoggingHttp2FrameDecoderListener() override; - - // TODO(jamessynge): Remove OnFrameHeader once done with supporting - // SpdyFramer's exact states. - bool OnFrameHeader(const Http2FrameHeader& header) override; - void OnDataStart(const Http2FrameHeader& header) override; - void OnDataPayload(const char* data, size_t len) override; - void OnDataEnd() override; - void OnHeadersStart(const Http2FrameHeader& header) override; - void OnHeadersPriority(const Http2PriorityFields& priority) override; - void OnHpackFragment(const char* data, size_t len) override; - void OnHeadersEnd() override; - void OnPriorityFrame(const Http2FrameHeader& header, - const Http2PriorityFields& priority) override; - void OnContinuationStart(const Http2FrameHeader& header) override; - void OnContinuationEnd() override; - void OnPadLength(size_t trailing_length) override; - void OnPadding(const char* padding, size_t skipped_length) override; - void OnRstStream(const Http2FrameHeader& header, - Http2ErrorCode error_code) override; - void OnSettingsStart(const Http2FrameHeader& header) override; - void OnSetting(const Http2SettingFields& setting_fields) override; - void OnSettingsEnd() override; - void OnSettingsAck(const Http2FrameHeader& header) override; - void OnPushPromiseStart(const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) override; - void OnPushPromiseEnd() override; - void OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) override; - void OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) override; - void OnGoAwayStart(const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) override; - void OnGoAwayOpaqueData(const char* data, size_t len) override; - void OnGoAwayEnd() override; - void OnWindowUpdate(const Http2FrameHeader& header, - uint32_t increment) override; - void OnAltSvcStart(const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) override; - void OnAltSvcOriginData(const char* data, size_t len) override; - void OnAltSvcValueData(const char* data, size_t len) override; - void OnAltSvcEnd() override; - void OnUnknownStart(const Http2FrameHeader& header) override; - void OnUnknownPayload(const char* data, size_t len) override; - void OnUnknownEnd() override; - void OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) override; - void OnFrameSizeError(const Http2FrameHeader& header) override; - - private: - void EnsureNotAbstract() { LoggingHttp2FrameDecoderListener instance; } - - Http2FrameDecoderListener* wrapped_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_HTTP2_FRAME_DECODER_LISTENER_TEST_UTIL_H_
diff --git a/net/third_party/http2/decoder/http2_frame_decoder_test.cc b/net/third_party/http2/decoder/http2_frame_decoder_test.cc deleted file mode 100644 index c34aebb..0000000 --- a/net/third_party/http2/decoder/http2_frame_decoder_test.cc +++ /dev/null
@@ -1,929 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/http2_frame_decoder.h" - -// Tests of Http2FrameDecoder. - -#include <vector> - -#include "base/logging.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/platform/api/http2_reconstruct_object.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "net/third_party/http2/test_tools/frame_parts.h" -#include "net/third_party/http2/test_tools/frame_parts_collector_listener.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; - -namespace http2 { -namespace test { -class Http2FrameDecoderPeer { - public: - static size_t remaining_total_payload(Http2FrameDecoder* decoder) { - return decoder->frame_decoder_state_.remaining_total_payload(); - } -}; - -namespace { - -class Http2FrameDecoderTest : public RandomDecoderTest { - protected: - void SetUp() override { - // On any one run of this suite, we'll always choose the same value for - // use_default_reconstruct_ because the random seed is the same for each - // test case, but across runs the random seed changes. - use_default_reconstruct_ = Random().OneIn(2); - } - - DecodeStatus StartDecoding(DecodeBuffer* db) override { - DVLOG(2) << "StartDecoding, db->Remaining=" << db->Remaining(); - collector_.Reset(); - PrepareDecoder(); - - DecodeStatus status = decoder_.DecodeFrame(db); - if (status != DecodeStatus::kDecodeInProgress) { - // Keep track of this so that a concrete test can verify that both fast - // and slow decoding paths have been tested. - ++fast_decode_count_; - if (status == DecodeStatus::kDecodeError) { - ConfirmDiscardsRemainingPayload(); - } - } - return status; - } - - DecodeStatus ResumeDecoding(DecodeBuffer* db) override { - DVLOG(2) << "ResumeDecoding, db->Remaining=" << db->Remaining(); - DecodeStatus status = decoder_.DecodeFrame(db); - if (status != DecodeStatus::kDecodeInProgress) { - // Keep track of this so that a concrete test can verify that both fast - // and slow decoding paths have been tested. - ++slow_decode_count_; - if (status == DecodeStatus::kDecodeError) { - ConfirmDiscardsRemainingPayload(); - } - } - return status; - } - - // When an error is returned, the decoder is in state kDiscardPayload, and - // stays there until the remaining bytes of the frame's payload have been - // skipped over. There are no callbacks for this situation. - void ConfirmDiscardsRemainingPayload() { - ASSERT_TRUE(decoder_.IsDiscardingPayload()); - size_t remaining = - Http2FrameDecoderPeer::remaining_total_payload(&decoder_); - // The decoder will discard the remaining bytes, but not go beyond that, - // which these conditions verify. - size_t extra = 10; - Http2String junk(remaining + extra, '0'); - DecodeBuffer tmp(junk); - EXPECT_EQ(DecodeStatus::kDecodeDone, decoder_.DecodeFrame(&tmp)); - EXPECT_EQ(remaining, tmp.Offset()); - EXPECT_EQ(extra, tmp.Remaining()); - EXPECT_FALSE(decoder_.IsDiscardingPayload()); - } - - void PrepareDecoder() { - // Save and restore the maximum_payload_size when reconstructing - // the decoder. - size_t maximum_payload_size = decoder_.maximum_payload_size(); - - // Alternate which constructor is used. - if (use_default_reconstruct_) { - Http2DefaultReconstructObject(&decoder_, RandomPtr()); - decoder_.set_listener(&collector_); - } else { - Http2ReconstructObject(&decoder_, RandomPtr(), &collector_); - } - decoder_.set_maximum_payload_size(maximum_payload_size); - - use_default_reconstruct_ = !use_default_reconstruct_; - } - - void ResetDecodeSpeedCounters() { - fast_decode_count_ = 0; - slow_decode_count_ = 0; - } - - AssertionResult VerifyCollected(const FrameParts& expected) { - VERIFY_FALSE(collector_.IsInProgress()); - VERIFY_EQ(1u, collector_.size()); - VERIFY_AND_RETURN_SUCCESS(expected.VerifyEquals(*collector_.frame(0))); - } - - AssertionResult DecodePayloadAndValidateSeveralWays(Http2StringPiece payload, - Validator validator) { - DecodeBuffer db(payload); - bool start_decoding_requires_non_empty = false; - return DecodeAndValidateSeveralWays(&db, start_decoding_requires_non_empty, - validator); - } - - // Decode one frame's payload and confirm that the listener recorded the - // expected FrameParts instance, and only one FrameParts instance. The - // payload will be decoded several times with different partitionings - // of the payload, and after each the validator will be called. - AssertionResult DecodePayloadAndValidateSeveralWays( - Http2StringPiece payload, - const FrameParts& expected) { - auto validator = [&expected, this](const DecodeBuffer& input, - DecodeStatus status) -> AssertionResult { - VERIFY_EQ(status, DecodeStatus::kDecodeDone); - VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected)); - }; - ResetDecodeSpeedCounters(); - VERIFY_SUCCESS(DecodePayloadAndValidateSeveralWays( - payload, ValidateDoneAndEmpty(validator))); - VERIFY_GT(fast_decode_count_, 0u); - VERIFY_GT(slow_decode_count_, 0u); - - // Repeat with more input; it should stop without reading that input. - Http2String next_frame = Random().RandString(10); - Http2String input(payload.data(), payload.size()); - input += next_frame; - - ResetDecodeSpeedCounters(); - VERIFY_SUCCESS(DecodePayloadAndValidateSeveralWays( - payload, ValidateDoneAndOffset(payload.size(), validator))); - VERIFY_GT(fast_decode_count_, 0u); - VERIFY_GT(slow_decode_count_, 0u); - - return AssertionSuccess(); - } - - template <size_t N> - AssertionResult DecodePayloadAndValidateSeveralWays( - const char (&buf)[N], - const FrameParts& expected) { - return DecodePayloadAndValidateSeveralWays(Http2StringPiece(buf, N), - expected); - } - - template <size_t N> - AssertionResult DecodePayloadAndValidateSeveralWays( - const char (&buf)[N], - const Http2FrameHeader& header) { - return DecodePayloadAndValidateSeveralWays(Http2StringPiece(buf, N), - FrameParts(header)); - } - - template <size_t N> - AssertionResult DecodePayloadExpectingError(const char (&buf)[N], - const FrameParts& expected) { - auto validator = [&expected, this](const DecodeBuffer& input, - DecodeStatus status) -> AssertionResult { - VERIFY_EQ(status, DecodeStatus::kDecodeError); - VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected)); - }; - ResetDecodeSpeedCounters(); - EXPECT_TRUE( - DecodePayloadAndValidateSeveralWays(ToStringPiece(buf), validator)); - EXPECT_GT(fast_decode_count_, 0u); - EXPECT_GT(slow_decode_count_, 0u); - return AssertionSuccess(); - } - - template <size_t N> - AssertionResult DecodePayloadExpectingFrameSizeError(const char (&buf)[N], - FrameParts expected) { - expected.SetHasFrameSizeError(true); - VERIFY_AND_RETURN_SUCCESS(DecodePayloadExpectingError(buf, expected)); - } - - template <size_t N> - AssertionResult DecodePayloadExpectingFrameSizeError( - const char (&buf)[N], - const Http2FrameHeader& header) { - return DecodePayloadExpectingFrameSizeError(buf, FrameParts(header)); - } - - // Count of payloads that are fully decoded by StartDecodingPayload or for - // which an error was detected by StartDecodingPayload. - size_t fast_decode_count_ = 0; - - // Count of payloads that required calling ResumeDecodingPayload in order to - // decode completely, or for which an error was detected by - // ResumeDecodingPayload. - size_t slow_decode_count_ = 0; - - FramePartsCollectorListener collector_; - Http2FrameDecoder decoder_; - bool use_default_reconstruct_; -}; - -//////////////////////////////////////////////////////////////////////////////// -// Tests that pass the minimum allowed size for the frame type, which is often -// empty. The tests are in order by frame type value (i.e. 0 for DATA frames). - -TEST_F(Http2FrameDecoderTest, DataEmpty) { - const char kFrameData[] = { - '\x00', '\x00', '\x00', // Payload length: 0 - '\x00', // DATA - '\x00', // Flags: none - '\x00', '\x00', '\x00', - '\x00', // Stream ID: 0 (invalid but unchecked here) - }; - Http2FrameHeader header(0, Http2FrameType::DATA, 0, 0); - FrameParts expected(header, ""); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, HeadersEmpty) { - const char kFrameData[] = { - '\x00', '\x00', '\x00', // Payload length: 0 - '\x01', // HEADERS - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x01', // Stream ID: 0 (REQUIRES ID) - }; - Http2FrameHeader header(0, Http2FrameType::HEADERS, 0, 1); - FrameParts expected(header, ""); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, Priority) { - const char kFrameData[] = { - '\x00', '\x00', '\x05', // Length: 5 - '\x02', // Type: PRIORITY - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x02', // Stream: 2 - '\x80', '\x00', '\x00', '\x01', // Parent: 1 (Exclusive) - '\x10', // Weight: 17 - }; - Http2FrameHeader header(5, Http2FrameType::PRIORITY, 0, 2); - FrameParts expected(header); - expected.SetOptPriority(Http2PriorityFields(1, 17, true)); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, RstStream) { - const char kFrameData[] = { - '\x00', '\x00', '\x04', // Length: 4 - '\x03', // Type: RST_STREAM - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x01', // Stream: 1 - '\x00', '\x00', '\x00', '\x01', // Error: PROTOCOL_ERROR - }; - Http2FrameHeader header(4, Http2FrameType::RST_STREAM, 0, 1); - FrameParts expected(header); - expected.SetOptRstStreamErrorCode(Http2ErrorCode::PROTOCOL_ERROR); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, SettingsEmpty) { - const char kFrameData[] = { - '\x00', '\x00', '\x00', // Length: 0 - '\x04', // Type: SETTINGS - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x01', // Stream: 1 (invalid but unchecked here) - }; - Http2FrameHeader header(0, Http2FrameType::SETTINGS, 0, 1); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, SettingsAck) { - const char kFrameData[] = { - '\x00', '\x00', '\x00', // Length: 6 - '\x04', // Type: SETTINGS - '\x01', // Flags: ACK - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - }; - Http2FrameHeader header(0, Http2FrameType::SETTINGS, Http2FrameFlag::ACK, 0); - FrameParts expected(header); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, PushPromiseMinimal) { - const char kFrameData[] = { - '\x00', '\x00', '\x04', // Payload length: 4 - '\x05', // PUSH_PROMISE - '\x04', // Flags: END_HEADERS - '\x00', '\x00', '\x00', - '\x02', // Stream: 2 (invalid but unchecked here) - '\x00', '\x00', '\x00', - '\x01', // Promised: 1 (invalid but unchecked here) - }; - Http2FrameHeader header(4, Http2FrameType::PUSH_PROMISE, - Http2FrameFlag::END_HEADERS, 2); - FrameParts expected(header, ""); - expected.SetOptPushPromise(Http2PushPromiseFields{1}); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, Ping) { - const char kFrameData[] = { - '\x00', '\x00', '\x08', // Length: 8 - '\x06', // Type: PING - '\xfe', // Flags: no valid flags - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - 's', 'o', 'm', 'e', // "some" - 'd', 'a', 't', 'a', // "data" - }; - Http2FrameHeader header(8, Http2FrameType::PING, 0, 0); - FrameParts expected(header); - expected.SetOptPing( - Http2PingFields{{'s', 'o', 'm', 'e', 'd', 'a', 't', 'a'}}); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, PingAck) { - const char kFrameData[] = { - '\x00', '\x00', '\x08', // Length: 8 - '\x06', // Type: PING - '\xff', // Flags: ACK (plus all invalid flags) - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - 's', 'o', 'm', 'e', // "some" - 'd', 'a', 't', 'a', // "data" - }; - Http2FrameHeader header(8, Http2FrameType::PING, Http2FrameFlag::ACK, 0); - FrameParts expected(header); - expected.SetOptPing( - Http2PingFields{{'s', 'o', 'm', 'e', 'd', 'a', 't', 'a'}}); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, GoAwayMinimal) { - const char kFrameData[] = { - '\x00', '\x00', '\x08', // Length: 8 (no opaque data) - '\x07', // Type: GOAWAY - '\xff', // Flags: 0xff (no valid flags) - '\x00', '\x00', '\x00', '\x01', // Stream: 1 (invalid but unchecked here) - '\x80', '\x00', '\x00', '\xff', // Last: 255 (plus R bit) - '\x00', '\x00', '\x00', '\x09', // Error: COMPRESSION_ERROR - }; - Http2FrameHeader header(8, Http2FrameType::GOAWAY, 0, 1); - FrameParts expected(header); - expected.SetOptGoaway( - Http2GoAwayFields(255, Http2ErrorCode::COMPRESSION_ERROR)); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, WindowUpdate) { - const char kFrameData[] = { - '\x00', '\x00', '\x04', // Length: 4 - '\x08', // Type: WINDOW_UPDATE - '\x0f', // Flags: 0xff (no valid flags) - '\x00', '\x00', '\x00', '\x01', // Stream: 1 - '\x80', '\x00', '\x04', '\x00', // Incr: 1024 (plus R bit) - }; - Http2FrameHeader header(4, Http2FrameType::WINDOW_UPDATE, 0, 1); - FrameParts expected(header); - expected.SetOptWindowUpdateIncrement(1024); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, ContinuationEmpty) { - const char kFrameData[] = { - '\x00', '\x00', '\x00', // Payload length: 0 - '\x09', // CONTINUATION - '\x00', // Flags: none - '\x00', '\x00', '\x00', - '\x00', // Stream ID: 0 (invalid but unchecked here) - }; - Http2FrameHeader header(0, Http2FrameType::CONTINUATION, 0, 0); - FrameParts expected(header); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, AltSvcMinimal) { - const char kFrameData[] = { - '\x00', '\x00', '\x02', // Payload length: 2 - '\x0a', // ALTSVC - '\xff', // Flags: none (plus 0xff) - '\x00', '\x00', '\x00', - '\x00', // Stream ID: 0 (invalid but unchecked here) - '\x00', '\x00', // Origin Length: 0 - }; - Http2FrameHeader header(2, Http2FrameType::ALTSVC, 0, 0); - FrameParts expected(header); - expected.SetOptAltsvcOriginLength(0); - expected.SetOptAltsvcValueLength(0); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, UnknownEmpty) { - const char kFrameData[] = { - '\x00', '\x00', '\x00', // Payload length: 0 - '\x20', // 32 (unknown) - '\xff', // Flags: all - '\x00', '\x00', '\x00', '\x00', // Stream ID: 0 - }; - Http2FrameHeader header(0, static_cast<Http2FrameType>(32), 0xff, 0); - FrameParts expected(header); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -//////////////////////////////////////////////////////////////////////////////// -// Tests of longer payloads, for those frame types that allow longer payloads. - -TEST_F(Http2FrameDecoderTest, DataPayload) { - const char kFrameData[] = { - '\x00', '\x00', '\x03', // Payload length: 7 - '\x00', // DATA - '\x80', // Flags: 0x80 - '\x00', '\x00', '\x02', '\x02', // Stream ID: 514 - 'a', 'b', 'c', // Data - }; - Http2FrameHeader header(3, Http2FrameType::DATA, 0, 514); - FrameParts expected(header, "abc"); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, HeadersPayload) { - const char kFrameData[] = { - '\x00', '\x00', '\x03', // Payload length: 3 - '\x01', // HEADERS - '\x05', // Flags: END_STREAM | END_HEADERS - '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) - 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) - }; - Http2FrameHeader header( - 3, Http2FrameType::HEADERS, - Http2FrameFlag::END_STREAM | Http2FrameFlag::END_HEADERS, 2); - FrameParts expected(header, "abc"); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, HeadersPriority) { - const char kFrameData[] = { - '\x00', '\x00', '\x05', // Payload length: 5 - '\x01', // HEADERS - '\x20', // Flags: PRIORITY - '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) - '\x00', '\x00', '\x00', '\x01', // Parent: 1 (Not Exclusive) - '\xff', // Weight: 256 - }; - Http2FrameHeader header(5, Http2FrameType::HEADERS, Http2FrameFlag::PRIORITY, - 2); - FrameParts expected(header); - expected.SetOptPriority(Http2PriorityFields(1, 256, false)); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, Settings) { - const char kFrameData[] = { - '\x00', '\x00', '\x0c', // Length: 12 - '\x04', // Type: SETTINGS - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - '\x00', '\x04', // Param: INITIAL_WINDOW_SIZE - '\x0a', '\x0b', '\x0c', '\x0d', // Value: 168496141 - '\x00', '\x02', // Param: ENABLE_PUSH - '\x00', '\x00', '\x00', '\x03', // Value: 3 (invalid but unchecked here) - }; - Http2FrameHeader header(12, Http2FrameType::SETTINGS, 0, 0); - FrameParts expected(header); - expected.AppendSetting(Http2SettingFields( - Http2SettingsParameter::INITIAL_WINDOW_SIZE, 168496141)); - expected.AppendSetting( - Http2SettingFields(Http2SettingsParameter::ENABLE_PUSH, 3)); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, PushPromisePayload) { - const char kFrameData[] = { - '\x00', '\x00', 7, // Payload length: 7 - '\x05', // PUSH_PROMISE - '\x04', // Flags: END_HEADERS - '\x00', '\x00', '\x00', '\xff', // Stream ID: 255 - '\x00', '\x00', '\x01', '\x00', // Promised: 256 - 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) - }; - Http2FrameHeader header(7, Http2FrameType::PUSH_PROMISE, - Http2FrameFlag::END_HEADERS, 255); - FrameParts expected(header, "abc"); - expected.SetOptPushPromise(Http2PushPromiseFields{256}); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, GoAwayOpaqueData) { - const char kFrameData[] = { - '\x00', '\x00', '\x0e', // Length: 14 - '\x07', // Type: GOAWAY - '\xff', // Flags: 0xff (no valid flags) - '\x80', '\x00', '\x00', '\x00', // Stream: 0 (plus R bit) - '\x00', '\x00', '\x01', '\x00', // Last: 256 - '\x00', '\x00', '\x00', '\x03', // Error: FLOW_CONTROL_ERROR - 'o', 'p', 'a', 'q', 'u', 'e', - }; - Http2FrameHeader header(14, Http2FrameType::GOAWAY, 0, 0); - FrameParts expected(header, "opaque"); - expected.SetOptGoaway( - Http2GoAwayFields(256, Http2ErrorCode::FLOW_CONTROL_ERROR)); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, ContinuationPayload) { - const char kFrameData[] = { - '\x00', '\x00', '\x03', // Payload length: 3 - '\x09', // CONTINUATION - '\xff', // Flags: END_HEADERS | 0xfb - '\x00', '\x00', '\x00', '\x02', // Stream ID: 2 - 'a', 'b', 'c', // Data - }; - Http2FrameHeader header(3, Http2FrameType::CONTINUATION, - Http2FrameFlag::END_HEADERS, 2); - FrameParts expected(header, "abc"); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, AltSvcPayload) { - const char kFrameData[] = { - '\x00', '\x00', '\x08', // Payload length: 3 - '\x0a', // ALTSVC - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x02', // Stream ID: 2 - '\x00', '\x03', // Origin Length: 0 - 'a', 'b', 'c', // Origin - 'd', 'e', 'f', // Value - }; - Http2FrameHeader header(8, Http2FrameType::ALTSVC, 0, 2); - FrameParts expected(header); - expected.SetAltSvcExpected("abc", "def"); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, UnknownPayload) { - const char kFrameData[] = { - '\x00', '\x00', '\x03', // Payload length: 3 - '\x30', // 48 (unknown) - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x02', // Stream ID: 2 - 'a', 'b', 'c', // Payload - }; - Http2FrameHeader header(3, static_cast<Http2FrameType>(48), 0, 2); - FrameParts expected(header, "abc"); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -//////////////////////////////////////////////////////////////////////////////// -// Tests of padded payloads, for those frame types that allow padding. - -TEST_F(Http2FrameDecoderTest, DataPayloadAndPadding) { - const char kFrameData[] = { - '\x00', '\x00', '\x07', // Payload length: 7 - '\x00', // DATA - '\x09', // Flags: END_STREAM | PADDED - '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) - '\x03', // Pad Len - 'a', 'b', 'c', // Data - '\x00', '\x00', '\x00', // Padding - }; - Http2FrameHeader header(7, Http2FrameType::DATA, - Http2FrameFlag::END_STREAM | Http2FrameFlag::PADDED, - 2); - size_t total_pad_length = 4; // Including the Pad Length field. - FrameParts expected(header, "abc", total_pad_length); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, HeadersPayloadAndPadding) { - const char kFrameData[] = { - '\x00', '\x00', '\x07', // Payload length: 7 - '\x01', // HEADERS - '\x08', // Flags: PADDED - '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) - '\x03', // Pad Len - 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) - '\x00', '\x00', '\x00', // Padding - }; - Http2FrameHeader header(7, Http2FrameType::HEADERS, Http2FrameFlag::PADDED, - 2); - size_t total_pad_length = 4; // Including the Pad Length field. - FrameParts expected(header, "abc", total_pad_length); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, HeadersPayloadPriorityAndPadding) { - const char kFrameData[] = { - '\x00', '\x00', '\x0c', // Payload length: 12 - '\x01', // HEADERS - '\xff', // Flags: all, including undefined - '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) - '\x03', // Pad Len - '\x80', '\x00', '\x00', '\x01', // Parent: 1 (Exclusive) - '\x10', // Weight: 17 - 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) - '\x00', '\x00', '\x00', // Padding - }; - Http2FrameHeader header(12, Http2FrameType::HEADERS, - Http2FrameFlag::END_STREAM | - Http2FrameFlag::END_HEADERS | - Http2FrameFlag::PADDED | Http2FrameFlag::PRIORITY, - 2); - size_t total_pad_length = 4; // Including the Pad Length field. - FrameParts expected(header, "abc", total_pad_length); - expected.SetOptPriority(Http2PriorityFields(1, 17, true)); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, PushPromisePayloadAndPadding) { - const char kFrameData[] = { - '\x00', '\x00', 11, // Payload length: 11 - '\x05', // PUSH_PROMISE - '\xff', // Flags: END_HEADERS | PADDED | 0xf3 - '\x00', '\x00', '\x00', '\x01', // Stream ID: 1 - '\x03', // Pad Len - '\x00', '\x00', '\x00', '\x02', // Promised: 2 - 'a', 'b', 'c', // HPACK fragment (doesn't have to be valid) - '\x00', '\x00', '\x00', // Padding - }; - Http2FrameHeader header(11, Http2FrameType::PUSH_PROMISE, - Http2FrameFlag::END_HEADERS | Http2FrameFlag::PADDED, - 1); - size_t total_pad_length = 4; // Including the Pad Length field. - FrameParts expected(header, "abc", total_pad_length); - expected.SetOptPushPromise(Http2PushPromiseFields{2}); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected)); -} - -//////////////////////////////////////////////////////////////////////////////// -// Payload too short errors. - -TEST_F(Http2FrameDecoderTest, DataMissingPadLengthField) { - const char kFrameData[] = { - '\x00', '\x00', '\x00', // Payload length: 0 - '\x00', // DATA - '\x08', // Flags: PADDED - '\x00', '\x00', '\x00', '\x01', // Stream ID: 1 - }; - Http2FrameHeader header(0, Http2FrameType::DATA, Http2FrameFlag::PADDED, 1); - FrameParts expected(header); - expected.SetOptMissingLength(1); - EXPECT_TRUE(DecodePayloadExpectingError(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, HeaderPaddingTooLong) { - const char kFrameData[] = { - '\x00', '\x00', '\x02', // Payload length: 0 - '\x01', // HEADERS - '\x08', // Flags: PADDED - '\x00', '\x01', '\x00', '\x00', // Stream ID: 65536 - '\xff', // Pad Len: 255 - '\x00', // Only one byte of padding - }; - Http2FrameHeader header(2, Http2FrameType::HEADERS, Http2FrameFlag::PADDED, - 65536); - FrameParts expected(header); - expected.SetOptMissingLength(254); - EXPECT_TRUE(DecodePayloadExpectingError(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, HeaderMissingPriority) { - const char kFrameData[] = { - '\x00', '\x00', '\x04', // Payload length: 0 - '\x01', // HEADERS - '\x20', // Flags: PRIORITY - '\x00', '\x01', '\x00', '\x00', // Stream ID: 65536 - '\x00', '\x00', '\x00', '\x00', // Priority (truncated) - }; - Http2FrameHeader header(4, Http2FrameType::HEADERS, Http2FrameFlag::PRIORITY, - 65536); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, PriorityTooShort) { - const char kFrameData[] = { - '\x00', '\x00', '\x04', // Length: 5 - '\x02', // Type: PRIORITY - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x02', // Stream: 2 - '\x80', '\x00', '\x00', '\x01', // Parent: 1 (Exclusive) - }; - Http2FrameHeader header(4, Http2FrameType::PRIORITY, 0, 2); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, RstStreamTooShort) { - const char kFrameData[] = { - '\x00', '\x00', '\x03', // Length: 4 - '\x03', // Type: RST_STREAM - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x01', // Stream: 1 - '\x00', '\x00', '\x00', // Truncated - }; - Http2FrameHeader header(3, Http2FrameType::RST_STREAM, 0, 1); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -// SETTINGS frames must a multiple of 6 bytes long, so an 9 byte payload is -// invalid. -TEST_F(Http2FrameDecoderTest, SettingsWrongSize) { - const char kFrameData[] = { - '\x00', '\x00', '\x09', // Length: 2 - '\x04', // Type: SETTINGS - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - '\x00', '\x02', // Param: ENABLE_PUSH - '\x00', '\x00', '\x00', '\x03', // Value: 1 - '\x00', '\x04', // Param: INITIAL_WINDOW_SIZE - '\x00', // Value: Truncated - }; - Http2FrameHeader header(9, Http2FrameType::SETTINGS, 0, 0); - FrameParts expected(header); - expected.AppendSetting( - Http2SettingFields(Http2SettingsParameter::ENABLE_PUSH, 3)); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, expected)); -} - -TEST_F(Http2FrameDecoderTest, PushPromiseTooShort) { - const char kFrameData[] = { - '\x00', '\x00', 3, // Payload length: 3 - '\x05', // PUSH_PROMISE - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x01', // Stream ID: 1 - '\x00', '\x00', '\x00', // Truncated promise id - }; - Http2FrameHeader header(3, Http2FrameType::PUSH_PROMISE, 0, 1); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, PushPromisePaddedTruncatedPromise) { - const char kFrameData[] = { - '\x00', '\x00', 4, // Payload length: 4 - '\x05', // PUSH_PROMISE - '\x08', // Flags: PADDED - '\x00', '\x00', '\x00', '\x01', // Stream ID: 1 - '\x00', // Pad Len - '\x00', '\x00', '\x00', // Truncated promise id - }; - Http2FrameHeader header(4, Http2FrameType::PUSH_PROMISE, - Http2FrameFlag::PADDED, 1); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, PingTooShort) { - const char kFrameData[] = { - '\x00', '\x00', '\x07', // Length: 8 - '\x06', // Type: PING - '\xfe', // Flags: no valid flags - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - 's', 'o', 'm', 'e', // "some" - 'd', 'a', 't', // Too little - }; - Http2FrameHeader header(7, Http2FrameType::PING, 0, 0); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, GoAwayTooShort) { - const char kFrameData[] = { - '\x00', '\x00', '\x00', // Length: 0 - '\x07', // Type: GOAWAY - '\xff', // Flags: 0xff (no valid flags) - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - }; - Http2FrameHeader header(0, Http2FrameType::GOAWAY, 0, 0); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, WindowUpdateTooShort) { - const char kFrameData[] = { - '\x00', '\x00', '\x03', // Length: 3 - '\x08', // Type: WINDOW_UPDATE - '\x0f', // Flags: 0xff (no valid flags) - '\x00', '\x00', '\x00', '\x01', // Stream: 1 - '\x80', '\x00', '\x04', // Truncated - }; - Http2FrameHeader header(3, Http2FrameType::WINDOW_UPDATE, 0, 1); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, AltSvcTruncatedOriginLength) { - const char kFrameData[] = { - '\x00', '\x00', '\x01', // Payload length: 3 - '\x0a', // ALTSVC - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x02', // Stream ID: 2 - '\x00', // Origin Length: truncated - }; - Http2FrameHeader header(1, Http2FrameType::ALTSVC, 0, 2); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, AltSvcTruncatedOrigin) { - const char kFrameData[] = { - '\x00', '\x00', '\x05', // Payload length: 3 - '\x0a', // ALTSVC - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x02', // Stream ID: 2 - '\x00', '\x04', // Origin Length: 4 (too long) - 'a', 'b', 'c', // Origin - }; - Http2FrameHeader header(5, Http2FrameType::ALTSVC, 0, 2); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -//////////////////////////////////////////////////////////////////////////////// -// Payload too long errors. - -// The decoder calls the listener's OnFrameSizeError method if the frame's -// payload is longer than the currently configured maximum payload size. -TEST_F(Http2FrameDecoderTest, BeyondMaximum) { - decoder_.set_maximum_payload_size(2); - const char kFrameData[] = { - '\x00', '\x00', '\x07', // Payload length: 7 - '\x00', // DATA - '\x09', // Flags: END_STREAM | PADDED - '\x00', '\x00', '\x00', '\x02', // Stream ID: 0 (REQUIRES ID) - '\x03', // Pad Len - 'a', 'b', 'c', // Data - '\x00', '\x00', '\x00', // Padding - }; - Http2FrameHeader header(7, Http2FrameType::DATA, - Http2FrameFlag::END_STREAM | Http2FrameFlag::PADDED, - 2); - FrameParts expected(header); - expected.SetHasFrameSizeError(true); - auto validator = [&expected, this](const DecodeBuffer& input, - DecodeStatus status) -> AssertionResult { - VERIFY_EQ(status, DecodeStatus::kDecodeError); - // The decoder detects this error after decoding the header, and without - // trying to decode the payload. - VERIFY_EQ(input.Offset(), Http2FrameHeader::EncodedSize()); - VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected)); - }; - ResetDecodeSpeedCounters(); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(ToStringPiece(kFrameData), - validator)); - EXPECT_GT(fast_decode_count_, 0u); - EXPECT_GT(slow_decode_count_, 0u); -} - -TEST_F(Http2FrameDecoderTest, PriorityTooLong) { - const char kFrameData[] = { - '\x00', '\x00', '\x06', // Length: 5 - '\x02', // Type: PRIORITY - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x02', // Stream: 2 - '\x80', '\x00', '\x00', '\x01', // Parent: 1 (Exclusive) - '\x10', // Weight: 17 - '\x00', // Too much - }; - Http2FrameHeader header(6, Http2FrameType::PRIORITY, 0, 2); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, RstStreamTooLong) { - const char kFrameData[] = { - '\x00', '\x00', '\x05', // Length: 4 - '\x03', // Type: RST_STREAM - '\x00', // Flags: none - '\x00', '\x00', '\x00', '\x01', // Stream: 1 - '\x00', '\x00', '\x00', '\x01', // Error: PROTOCOL_ERROR - '\x00', // Too much - }; - Http2FrameHeader header(5, Http2FrameType::RST_STREAM, 0, 1); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, SettingsAckTooLong) { - const char kFrameData[] = { - '\x00', '\x00', '\x06', // Length: 6 - '\x04', // Type: SETTINGS - '\x01', // Flags: ACK - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - '\x00', '\x00', // Extra - '\x00', '\x00', '\x00', '\x00', // Extra - }; - Http2FrameHeader header(6, Http2FrameType::SETTINGS, Http2FrameFlag::ACK, 0); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, PingAckTooLong) { - const char kFrameData[] = { - '\x00', '\x00', '\x09', // Length: 8 - '\x06', // Type: PING - '\xff', // Flags: ACK | 0xfe - '\x00', '\x00', '\x00', '\x00', // Stream: 0 - 's', 'o', 'm', 'e', // "some" - 'd', 'a', 't', 'a', // "data" - '\x00', // Too much - }; - Http2FrameHeader header(9, Http2FrameType::PING, Http2FrameFlag::ACK, 0); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -TEST_F(Http2FrameDecoderTest, WindowUpdateTooLong) { - const char kFrameData[] = { - '\x00', '\x00', '\x05', // Length: 5 - '\x08', // Type: WINDOW_UPDATE - '\x0f', // Flags: 0xff (no valid flags) - '\x00', '\x00', '\x00', '\x01', // Stream: 1 - '\x80', '\x00', '\x04', '\x00', // Incr: 1024 (plus R bit) - '\x00', // Too much - }; - Http2FrameHeader header(5, Http2FrameType::WINDOW_UPDATE, 0, 1); - EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header)); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/http2_structure_decoder.cc b/net/third_party/http2/decoder/http2_structure_decoder.cc deleted file mode 100644 index 0d0e58c..0000000 --- a/net/third_party/http2/decoder/http2_structure_decoder.cc +++ /dev/null
@@ -1,90 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/http2_structure_decoder.h" - -#include <algorithm> - -#include "net/third_party/http2/platform/api/http2_bug_tracker.h" - -namespace http2 { - -// Below we have some defensive coding: if we somehow run off the end, don't -// overwrite lots of memory. Note that most of this decoder is not defensive -// against bugs in the decoder, only against malicious encoders, but since -// we're copying memory into a buffer here, let's make sure we don't allow a -// small mistake to grow larger. The decoder will get stuck if we hit the -// HTTP2_BUG conditions, but shouldn't corrupt memory. - -uint32_t Http2StructureDecoder::IncompleteStart(DecodeBuffer* db, - uint32_t target_size) { - if (target_size > sizeof buffer_) { - HTTP2_BUG << "target_size too large for buffer: " << target_size; - return 0; - } - const uint32_t num_to_copy = db->MinLengthRemaining(target_size); - memcpy(buffer_, db->cursor(), num_to_copy); - offset_ = num_to_copy; - db->AdvanceCursor(num_to_copy); - return num_to_copy; -} - -DecodeStatus Http2StructureDecoder::IncompleteStart(DecodeBuffer* db, - uint32_t* remaining_payload, - uint32_t target_size) { - DVLOG(1) << "IncompleteStart@" << this - << ": *remaining_payload=" << *remaining_payload - << "; target_size=" << target_size - << "; db->Remaining=" << db->Remaining(); - *remaining_payload -= - IncompleteStart(db, std::min(target_size, *remaining_payload)); - if (*remaining_payload > 0 && db->Empty()) { - return DecodeStatus::kDecodeInProgress; - } - DVLOG(1) << "IncompleteStart: kDecodeError"; - return DecodeStatus::kDecodeError; -} - -bool Http2StructureDecoder::ResumeFillingBuffer(DecodeBuffer* db, - uint32_t target_size) { - DVLOG(2) << "ResumeFillingBuffer@" << this << ": target_size=" << target_size - << "; offset_=" << offset_ << "; db->Remaining=" << db->Remaining(); - if (target_size < offset_) { - HTTP2_BUG << "Already filled buffer_! target_size=" << target_size - << " offset_=" << offset_; - return false; - } - const uint32_t needed = target_size - offset_; - const uint32_t num_to_copy = db->MinLengthRemaining(needed); - DVLOG(2) << "ResumeFillingBuffer num_to_copy=" << num_to_copy; - memcpy(&buffer_[offset_], db->cursor(), num_to_copy); - db->AdvanceCursor(num_to_copy); - offset_ += num_to_copy; - return needed == num_to_copy; -} - -bool Http2StructureDecoder::ResumeFillingBuffer(DecodeBuffer* db, - uint32_t* remaining_payload, - uint32_t target_size) { - DVLOG(2) << "ResumeFillingBuffer@" << this << ": target_size=" << target_size - << "; offset_=" << offset_ - << "; *remaining_payload=" << *remaining_payload - << "; db->Remaining=" << db->Remaining(); - if (target_size < offset_) { - HTTP2_BUG << "Already filled buffer_! target_size=" << target_size - << " offset_=" << offset_; - return false; - } - const uint32_t needed = target_size - offset_; - const uint32_t num_to_copy = - db->MinLengthRemaining(std::min(needed, *remaining_payload)); - DVLOG(2) << "ResumeFillingBuffer num_to_copy=" << num_to_copy; - memcpy(&buffer_[offset_], db->cursor(), num_to_copy); - db->AdvanceCursor(num_to_copy); - offset_ += num_to_copy; - *remaining_payload -= num_to_copy; - return needed == num_to_copy; -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/http2_structure_decoder.h b/net/third_party/http2/decoder/http2_structure_decoder.h deleted file mode 100644 index 49f2dbce..0000000 --- a/net/third_party/http2/decoder/http2_structure_decoder.h +++ /dev/null
@@ -1,131 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_H_ - -// Http2StructureDecoder is a class for decoding the fixed size structures in -// the HTTP/2 spec, defined in net/third_party/http2/http2_structures.h. This -// class is in aid of deciding whether to keep the SlowDecode methods which I -// (jamessynge) now think may not be worth their complexity. In particular, -// if most transport buffers are large, so it is rare that a structure is -// split across buffer boundaries, than the cost of buffering upon -// those rare occurrences is small, which then simplifies the callers. - -#include <cstdint> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_http2_structures.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { -namespace test { -class Http2StructureDecoderPeer; -} // namespace test - -class HTTP2_EXPORT_PRIVATE Http2StructureDecoder { - public: - // The caller needs to keep track of whether to call Start or Resume. - // - // Start has an optimization for the case where the DecodeBuffer holds the - // entire encoded structure; in that case it decodes into *out and returns - // true, and does NOT touch the data members of the Http2StructureDecoder - // instance because the caller won't be calling Resume later. - // - // However, if the DecodeBuffer is too small to hold the entire encoded - // structure, Start copies the available bytes into the Http2StructureDecoder - // instance, and returns false to indicate that it has not been able to - // complete the decoding. - // - template <class S> - bool Start(S* out, DecodeBuffer* db) { - static_assert(S::EncodedSize() <= sizeof buffer_, "buffer_ is too small"); - DVLOG(2) << __func__ << "@" << this << ": db->Remaining=" << db->Remaining() - << "; EncodedSize=" << S::EncodedSize(); - if (db->Remaining() >= S::EncodedSize()) { - DoDecode(out, db); - return true; - } - IncompleteStart(db, S::EncodedSize()); - return false; - } - - template <class S> - bool Resume(S* out, DecodeBuffer* db) { - DVLOG(2) << __func__ << "@" << this << ": offset_=" << offset_ - << "; db->Remaining=" << db->Remaining(); - if (ResumeFillingBuffer(db, S::EncodedSize())) { - // We have the whole thing now. - DVLOG(2) << __func__ << "@" << this << " offset_=" << offset_ - << " Ready to decode from buffer_."; - DecodeBuffer buffer_db(buffer_, S::EncodedSize()); - DoDecode(out, &buffer_db); - return true; - } - DCHECK_LT(offset_, S::EncodedSize()); - return false; - } - - // A second pair of Start and Resume, where the caller has a variable, - // |remaining_payload| that is both tested for sufficiency and updated - // during decoding. Note that the decode buffer may extend beyond the - // remaining payload because the buffer may include padding. - template <class S> - DecodeStatus Start(S* out, DecodeBuffer* db, uint32_t* remaining_payload) { - static_assert(S::EncodedSize() <= sizeof buffer_, "buffer_ is too small"); - DVLOG(2) << __func__ << "@" << this - << ": *remaining_payload=" << *remaining_payload - << "; db->Remaining=" << db->Remaining() - << "; EncodedSize=" << S::EncodedSize(); - if (db->MinLengthRemaining(*remaining_payload) >= S::EncodedSize()) { - DoDecode(out, db); - *remaining_payload -= S::EncodedSize(); - return DecodeStatus::kDecodeDone; - } - return IncompleteStart(db, remaining_payload, S::EncodedSize()); - } - - template <class S> - bool Resume(S* out, DecodeBuffer* db, uint32_t* remaining_payload) { - DVLOG(3) << __func__ << "@" << this << ": offset_=" << offset_ - << "; *remaining_payload=" << *remaining_payload - << "; db->Remaining=" << db->Remaining() - << "; EncodedSize=" << S::EncodedSize(); - if (ResumeFillingBuffer(db, remaining_payload, S::EncodedSize())) { - // We have the whole thing now. - DVLOG(2) << __func__ << "@" << this << ": offset_=" << offset_ - << "; Ready to decode from buffer_."; - DecodeBuffer buffer_db(buffer_, S::EncodedSize()); - DoDecode(out, &buffer_db); - return true; - } - DCHECK_LT(offset_, S::EncodedSize()); - return false; - } - - uint32_t offset() const { return offset_; } - - private: - friend class test::Http2StructureDecoderPeer; - - uint32_t IncompleteStart(DecodeBuffer* db, uint32_t target_size); - DecodeStatus IncompleteStart(DecodeBuffer* db, - uint32_t* remaining_payload, - uint32_t target_size); - - bool ResumeFillingBuffer(DecodeBuffer* db, uint32_t target_size); - bool ResumeFillingBuffer(DecodeBuffer* db, - uint32_t* remaining_payload, - uint32_t target_size); - - uint32_t offset_; - char buffer_[Http2FrameHeader::EncodedSize()]; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_H_
diff --git a/net/third_party/http2/decoder/http2_structure_decoder_test.cc b/net/third_party/http2/decoder/http2_structure_decoder_test.cc deleted file mode 100644 index 67fe8a52..0000000 --- a/net/third_party/http2/decoder/http2_structure_decoder_test.cc +++ /dev/null
@@ -1,541 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/http2_structure_decoder.h" - -// Tests decoding all of the fixed size HTTP/2 structures (i.e. those defined in -// net/third_party/http2/http2_structures.h) using Http2StructureDecoder, which -// handles buffering of structures split across input buffer boundaries, and in -// turn uses DoDecode when it has all of a structure in a contiguous buffer. - -// NOTE: This tests the first pair of Start and Resume, which don't take -// a remaining_payload parameter. The other pair are well tested via the -// payload decoder tests, though... -// TODO(jamessynge): Create type parameterized tests for Http2StructureDecoder -// where the type is the type of structure, and with testing of both pairs of -// Start and Resume methods; note that it appears that the first pair will be -// used only for Http2FrameHeader, and the other pair only for structures in the -// frame payload. - -#include <stddef.h> - -#include <cstdint> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures_test_util.h" -#include "net/third_party/http2/platform/api/http2_reconstruct_object.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "net/third_party/http2/tools/http2_frame_builder.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionFailure; -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; - -namespace http2 { -namespace test { -namespace { -const bool kMayReturnZeroOnFirst = false; - -template <class S> -class Http2StructureDecoderTest : public RandomDecoderTest { - protected: - typedef S Structure; - - Http2StructureDecoderTest() { - // IF the test adds more data after the encoded structure, stop as - // soon as the structure is decoded. - stop_decode_on_done_ = true; - } - - DecodeStatus StartDecoding(DecodeBuffer* b) override { - // Overwrite the current contents of |structure_|, in to which we'll - // decode the buffer, so that we can be confident that we really decoded - // the structure every time. - Http2DefaultReconstructObject(&structure_, RandomPtr()); - uint32_t old_remaining = b->Remaining(); - if (structure_decoder_.Start(&structure_, b)) { - EXPECT_EQ(old_remaining - S::EncodedSize(), b->Remaining()); - ++fast_decode_count_; - return DecodeStatus::kDecodeDone; - } else { - EXPECT_LT(structure_decoder_.offset(), S::EncodedSize()); - EXPECT_EQ(0u, b->Remaining()); - EXPECT_EQ(old_remaining - structure_decoder_.offset(), b->Remaining()); - ++incomplete_start_count_; - return DecodeStatus::kDecodeInProgress; - } - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - uint32_t old_offset = structure_decoder_.offset(); - EXPECT_LT(old_offset, S::EncodedSize()); - uint32_t avail = b->Remaining(); - if (structure_decoder_.Resume(&structure_, b)) { - EXPECT_LE(S::EncodedSize(), old_offset + avail); - EXPECT_EQ(b->Remaining(), avail - (S::EncodedSize() - old_offset)); - ++slow_decode_count_; - return DecodeStatus::kDecodeDone; - } else { - EXPECT_LT(structure_decoder_.offset(), S::EncodedSize()); - EXPECT_EQ(0u, b->Remaining()); - EXPECT_GT(S::EncodedSize(), old_offset + avail); - ++incomplete_resume_count_; - return DecodeStatus::kDecodeInProgress; - } - } - - // Fully decodes the Structure at the start of data, and confirms it matches - // *expected (if provided). - AssertionResult DecodeLeadingStructure(const S* expected, - Http2StringPiece data) { - VERIFY_LE(S::EncodedSize(), data.size()); - DecodeBuffer original(data); - - // The validator is called after each of the several times that the input - // DecodeBuffer is decoded, each with a different segmentation of the input. - // Validate that structure_ matches the expected value, if provided. - Validator validator; - if (expected != nullptr) { - validator = [expected, this](const DecodeBuffer& db, - DecodeStatus status) -> AssertionResult { - VERIFY_EQ(*expected, structure_); - return AssertionSuccess(); - }; - } - - // Before that, validate that decoding is done and that we've advanced - // the cursor the expected amount. - validator = ValidateDoneAndOffset(S::EncodedSize(), validator); - - // Decode several times, with several segmentations of the input buffer. - fast_decode_count_ = 0; - slow_decode_count_ = 0; - incomplete_start_count_ = 0; - incomplete_resume_count_ = 0; - VERIFY_SUCCESS(DecodeAndValidateSeveralWays( - &original, kMayReturnZeroOnFirst, validator)); - VERIFY_FALSE(HasFailure()); - VERIFY_EQ(S::EncodedSize(), structure_decoder_.offset()); - VERIFY_EQ(S::EncodedSize(), original.Offset()); - VERIFY_LT(0u, fast_decode_count_); - VERIFY_LT(0u, slow_decode_count_); - VERIFY_LT(0u, incomplete_start_count_); - - // If the structure is large enough so that SelectZeroOrOne will have - // caused Resume to return false, check that occurred. - if (S::EncodedSize() >= 2) { - VERIFY_LE(0u, incomplete_resume_count_); - } else { - VERIFY_EQ(0u, incomplete_resume_count_); - } - if (expected != nullptr) { - DVLOG(1) << "DecodeLeadingStructure expected: " << *expected; - DVLOG(1) << "DecodeLeadingStructure actual: " << structure_; - VERIFY_EQ(*expected, structure_); - } - return AssertionSuccess(); - } - - template <size_t N> - AssertionResult DecodeLeadingStructure(const char (&data)[N]) { - VERIFY_AND_RETURN_SUCCESS( - DecodeLeadingStructure(nullptr, Http2StringPiece(data, N))); - } - - template <size_t N> - AssertionResult DecodeLeadingStructure(const unsigned char (&data)[N]) { - VERIFY_AND_RETURN_SUCCESS( - DecodeLeadingStructure(nullptr, ToStringPiece(data))); - } - - // Encode the structure |in_s| into bytes, then decode the bytes - // and validate that the decoder produced the same field values. - AssertionResult EncodeThenDecode(const S& in_s) { - Http2String bytes = SerializeStructure(in_s); - VERIFY_EQ(S::EncodedSize(), bytes.size()); - VERIFY_AND_RETURN_SUCCESS(DecodeLeadingStructure(&in_s, bytes)); - } - - // Repeatedly fill a structure with random but valid contents, encode it, then - // decode it, and finally validate that the decoded structure matches the - // random input. Lather-rinse-and-repeat. - AssertionResult TestDecodingRandomizedStructures(size_t count) { - for (size_t i = 0; i < count; ++i) { - Structure input; - Randomize(&input, RandomPtr()); - VERIFY_SUCCESS(EncodeThenDecode(input)); - } - return AssertionSuccess(); - } - - AssertionResult TestDecodingRandomizedStructures() { - VERIFY_SUCCESS(TestDecodingRandomizedStructures(100)); - return AssertionSuccess(); - } - - uint32_t decode_offset_ = 0; - S structure_; - Http2StructureDecoder structure_decoder_; - size_t fast_decode_count_ = 0; - size_t slow_decode_count_ = 0; - size_t incomplete_start_count_ = 0; - size_t incomplete_resume_count_ = 0; -}; - -class Http2FrameHeaderDecoderTest - : public Http2StructureDecoderTest<Http2FrameHeader> {}; - -TEST_F(Http2FrameHeaderDecoderTest, DecodesLiteral) { - { - // Realistic input. - // clang-format off - const char kData[] = { - 0x00, 0x00, 0x05, // Payload length: 5 - 0x01, // Frame type: HEADERS - 0x08, // Flags: PADDED - 0x00, 0x00, 0x00, 0x01, // Stream ID: 1 - 0x04, // Padding length: 4 - 0x00, 0x00, 0x00, 0x00, // Padding bytes - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(5u, structure_.payload_length); - EXPECT_EQ(Http2FrameType::HEADERS, structure_.type); - EXPECT_EQ(Http2FrameFlag::PADDED, structure_.flags); - EXPECT_EQ(1u, structure_.stream_id); - } - { - // Unlikely input. - // clang-format off - const unsigned char kData[] = { - 0xff, 0xff, 0xff, // Payload length: uint24 max - 0xff, // Frame type: Unknown - 0xff, // Flags: Unknown/All - 0xff, 0xff, 0xff, 0xff, // Stream ID: uint31 max, plus R-bit - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ((1u << 24) - 1u, structure_.payload_length); - EXPECT_EQ(static_cast<Http2FrameType>(255), structure_.type); - EXPECT_EQ(255, structure_.flags); - EXPECT_EQ(0x7FFFFFFFu, structure_.stream_id); - } -} - -TEST_F(Http2FrameHeaderDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class Http2PriorityFieldsDecoderTest - : public Http2StructureDecoderTest<Http2PriorityFields> {}; - -TEST_F(Http2PriorityFieldsDecoderTest, DecodesLiteral) { - { - // clang-format off - const unsigned char kData[] = { - 0x80, 0x00, 0x00, 0x05, // Exclusive (yes) and Dependency (5) - 0xff, // Weight: 256 (after adding 1) - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(5u, structure_.stream_dependency); - EXPECT_EQ(256u, structure_.weight); - EXPECT_EQ(true, structure_.is_exclusive); - } - { - // clang-format off - const unsigned char kData[] = { - 0x7f, 0xff, 0xff, 0xff, // Excl. (no) and Dependency (uint31 max) - 0x00, // Weight: 1 (after adding 1) - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(StreamIdMask(), structure_.stream_dependency); - EXPECT_EQ(1u, structure_.weight); - EXPECT_FALSE(structure_.is_exclusive); - } -} - -TEST_F(Http2PriorityFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class Http2RstStreamFieldsDecoderTest - : public Http2StructureDecoderTest<Http2RstStreamFields> {}; - -TEST_F(Http2RstStreamFieldsDecoderTest, DecodesLiteral) { - { - // clang-format off - const char kData[] = { - 0x00, 0x00, 0x00, 0x01, // Error: PROTOCOL_ERROR - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_TRUE(structure_.IsSupportedErrorCode()); - EXPECT_EQ(Http2ErrorCode::PROTOCOL_ERROR, structure_.error_code); - } - { - // clang-format off - const unsigned char kData[] = { - 0xff, 0xff, 0xff, 0xff, // Error: max uint32 (Unknown error code) - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_FALSE(structure_.IsSupportedErrorCode()); - EXPECT_EQ(static_cast<Http2ErrorCode>(0xffffffff), structure_.error_code); - } -} - -TEST_F(Http2RstStreamFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class Http2SettingFieldsDecoderTest - : public Http2StructureDecoderTest<Http2SettingFields> {}; - -TEST_F(Http2SettingFieldsDecoderTest, DecodesLiteral) { - { - // clang-format off - const char kData[] = { - 0x00, 0x01, // Setting: HEADER_TABLE_SIZE - 0x00, 0x00, 0x40, 0x00, // Value: 16K - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_TRUE(structure_.IsSupportedParameter()); - EXPECT_EQ(Http2SettingsParameter::HEADER_TABLE_SIZE, structure_.parameter); - EXPECT_EQ(1u << 14, structure_.value); - } - { - // clang-format off - const unsigned char kData[] = { - 0x00, 0x00, // Setting: Unknown (0) - 0xff, 0xff, 0xff, 0xff, // Value: max uint32 - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_FALSE(structure_.IsSupportedParameter()); - EXPECT_EQ(static_cast<Http2SettingsParameter>(0), structure_.parameter); - } -} - -TEST_F(Http2SettingFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class Http2PushPromiseFieldsDecoderTest - : public Http2StructureDecoderTest<Http2PushPromiseFields> {}; - -TEST_F(Http2PushPromiseFieldsDecoderTest, DecodesLiteral) { - { - // clang-format off - const unsigned char kData[] = { - 0x00, 0x01, 0x8a, 0x92, // Promised Stream ID: 101010 - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(101010u, structure_.promised_stream_id); - } - { - // Promised stream id has R-bit (reserved for future use) set, which - // should be cleared by the decoder. - // clang-format off - const unsigned char kData[] = { - // Promised Stream ID: max uint31 and R-bit - 0xff, 0xff, 0xff, 0xff, - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(StreamIdMask(), structure_.promised_stream_id); - } -} - -TEST_F(Http2PushPromiseFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class Http2PingFieldsDecoderTest - : public Http2StructureDecoderTest<Http2PingFields> {}; - -TEST_F(Http2PingFieldsDecoderTest, DecodesLiteral) { - { - // Each byte is different, so can detect if order changed. - const char kData[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - }; - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(ToStringPiece(kData), ToStringPiece(structure_.opaque_bytes)); - } - { - // All zeros, detect problems handling NULs. - const char kData[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(ToStringPiece(kData), ToStringPiece(structure_.opaque_bytes)); - } - { - const unsigned char kData[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }; - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(ToStringPiece(kData), ToStringPiece(structure_.opaque_bytes)); - } -} - -TEST_F(Http2PingFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class Http2GoAwayFieldsDecoderTest - : public Http2StructureDecoderTest<Http2GoAwayFields> {}; - -TEST_F(Http2GoAwayFieldsDecoderTest, DecodesLiteral) { - { - // clang-format off - const char kData[] = { - 0x00, 0x00, 0x00, 0x00, // Last Stream ID: 0 - 0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR (0) - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(0u, structure_.last_stream_id); - EXPECT_TRUE(structure_.IsSupportedErrorCode()); - EXPECT_EQ(Http2ErrorCode::HTTP2_NO_ERROR, structure_.error_code); - } - { - // clang-format off - const char kData[] = { - 0x00, 0x00, 0x00, 0x01, // Last Stream ID: 1 - 0x00, 0x00, 0x00, 0x0d, // Error: HTTP_1_1_REQUIRED - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(1u, structure_.last_stream_id); - EXPECT_TRUE(structure_.IsSupportedErrorCode()); - EXPECT_EQ(Http2ErrorCode::HTTP_1_1_REQUIRED, structure_.error_code); - } - { - // clang-format off - const unsigned char kData[] = { - 0xff, 0xff, 0xff, 0xff, // Last Stream ID: max uint31 and R-bit - 0xff, 0xff, 0xff, 0xff, // Error: max uint32 (Unknown error code) - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(StreamIdMask(), structure_.last_stream_id); // No high-bit. - EXPECT_FALSE(structure_.IsSupportedErrorCode()); - EXPECT_EQ(static_cast<Http2ErrorCode>(0xffffffff), structure_.error_code); - } -} - -TEST_F(Http2GoAwayFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class Http2WindowUpdateFieldsDecoderTest - : public Http2StructureDecoderTest<Http2WindowUpdateFields> {}; - -TEST_F(Http2WindowUpdateFieldsDecoderTest, DecodesLiteral) { - { - // clang-format off - const char kData[] = { - 0x00, 0x01, 0x00, 0x00, // Window Size Increment: 2 ^ 16 - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(1u << 16, structure_.window_size_increment); - } - { - // Increment must be non-zero, but we need to be able to decode the invalid - // zero to detect it. - // clang-format off - const char kData[] = { - 0x00, 0x00, 0x00, 0x00, // Window Size Increment: 0 - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(0u, structure_.window_size_increment); - } - { - // Increment has R-bit (reserved for future use) set, which - // should be cleared by the decoder. - // clang-format off - const unsigned char kData[] = { - // Window Size Increment: max uint31 and R-bit - 0xff, 0xff, 0xff, 0xff, - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(StreamIdMask(), structure_.window_size_increment); - } -} - -TEST_F(Http2WindowUpdateFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -//------------------------------------------------------------------------------ - -class Http2AltSvcFieldsDecoderTest - : public Http2StructureDecoderTest<Http2AltSvcFields> {}; - -TEST_F(Http2AltSvcFieldsDecoderTest, DecodesLiteral) { - { - // clang-format off - const char kData[] = { - 0x00, 0x00, // Origin Length: 0 - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(0, structure_.origin_length); - } - { - // clang-format off - const char kData[] = { - 0x00, 0x14, // Origin Length: 20 - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(20, structure_.origin_length); - } - { - // clang-format off - const unsigned char kData[] = { - 0xff, 0xff, // Origin Length: uint16 max - }; - // clang-format on - ASSERT_TRUE(DecodeLeadingStructure(kData)); - EXPECT_EQ(65535, structure_.origin_length); - } -} - -TEST_F(Http2AltSvcFieldsDecoderTest, DecodesRandomized) { - TestDecodingRandomizedStructures(); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/http2_structure_decoder_test_util.cc b/net/third_party/http2/decoder/http2_structure_decoder_test_util.cc deleted file mode 100644 index e24d70e..0000000 --- a/net/third_party/http2/decoder/http2_structure_decoder_test_util.cc +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2017 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 "net/third_party/http2/decoder/http2_structure_decoder_test_util.h" - -#include <cstddef> - -namespace http2 { -namespace test { - -// static -void Http2StructureDecoderPeer::Randomize(Http2StructureDecoder* p, - Http2Random* rng) { - p->offset_ = rng->Rand32(); - for (size_t i = 0; i < sizeof p->buffer_; ++i) { - p->buffer_[i] = rng->Rand8(); - } -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/http2_structure_decoder_test_util.h b/net/third_party/http2/decoder/http2_structure_decoder_test_util.h deleted file mode 100644 index 8740896..0000000 --- a/net/third_party/http2/decoder/http2_structure_decoder_test_util.h +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_TEST_UTIL_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_TEST_UTIL_H_ - -#include "net/third_party/http2/decoder/http2_structure_decoder.h" - -#include "net/third_party/http2/test_tools/http2_random.h" - -namespace http2 { -namespace test { - -class Http2StructureDecoderPeer { - public: - // Overwrite the Http2StructureDecoder instance with random values. - static void Randomize(Http2StructureDecoder* p, Http2Random* rng); -}; - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_HTTP2_STRUCTURE_DECODER_TEST_UTIL_H_
diff --git a/net/third_party/http2/decoder/payload_decoders/altsvc_payload_decoder.cc b/net/third_party/http2/decoder/payload_decoders/altsvc_payload_decoder.cc deleted file mode 100644 index 151702d..0000000 --- a/net/third_party/http2/decoder/payload_decoders/altsvc_payload_decoder.cc +++ /dev/null
@@ -1,148 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/altsvc_payload_decoder.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "base/macros.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_bug_tracker.h" -#include "net/third_party/http2/platform/api/http2_macros.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, - AltSvcPayloadDecoder::PayloadState v) { - switch (v) { - case AltSvcPayloadDecoder::PayloadState::kStartDecodingStruct: - return out << "kStartDecodingStruct"; - case AltSvcPayloadDecoder::PayloadState::kMaybeDecodedStruct: - return out << "kMaybeDecodedStruct"; - case AltSvcPayloadDecoder::PayloadState::kDecodingStrings: - return out << "kDecodingStrings"; - case AltSvcPayloadDecoder::PayloadState::kResumeDecodingStruct: - return out << "kResumeDecodingStruct"; - } - // Since the value doesn't come over the wire, only a programming bug should - // result in reaching this point. - int unknown = static_cast<int>(v); - HTTP2_BUG << "Invalid AltSvcPayloadDecoder::PayloadState: " << unknown; - return out << "AltSvcPayloadDecoder::PayloadState(" << unknown << ")"; -} - -DecodeStatus AltSvcPayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "AltSvcPayloadDecoder::StartDecodingPayload: " - << state->frame_header(); - DCHECK_EQ(Http2FrameType::ALTSVC, state->frame_header().type); - DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - DCHECK_EQ(0, state->frame_header().flags); - - state->InitializeRemainders(); - payload_state_ = PayloadState::kStartDecodingStruct; - - return ResumeDecodingPayload(state, db); -} - -DecodeStatus AltSvcPayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - DVLOG(2) << "AltSvcPayloadDecoder::ResumeDecodingPayload: " << frame_header; - DCHECK_EQ(Http2FrameType::ALTSVC, frame_header.type); - DCHECK_LE(state->remaining_payload(), frame_header.payload_length); - DCHECK_LE(db->Remaining(), state->remaining_payload()); - DCHECK_NE(PayloadState::kMaybeDecodedStruct, payload_state_); - // |status| has to be initialized to some value to avoid compiler error in - // case PayloadState::kMaybeDecodedStruct below, but value does not matter, - // see DCHECK_NE above. - DecodeStatus status = DecodeStatus::kDecodeError; - while (true) { - DVLOG(2) << "AltSvcPayloadDecoder::ResumeDecodingPayload payload_state_=" - << payload_state_; - switch (payload_state_) { - case PayloadState::kStartDecodingStruct: - status = state->StartDecodingStructureInPayload(&altsvc_fields_, db); - HTTP2_FALLTHROUGH; - - case PayloadState::kMaybeDecodedStruct: - if (status == DecodeStatus::kDecodeDone && - altsvc_fields_.origin_length <= state->remaining_payload()) { - size_t origin_length = altsvc_fields_.origin_length; - size_t value_length = state->remaining_payload() - origin_length; - state->listener()->OnAltSvcStart(frame_header, origin_length, - value_length); - } else if (status != DecodeStatus::kDecodeDone) { - DCHECK(state->remaining_payload() > 0 || - status == DecodeStatus::kDecodeError) - << "\nremaining_payload: " << state->remaining_payload() - << "\nstatus: " << status << "\nheader: " << frame_header; - // Assume in progress. - payload_state_ = PayloadState::kResumeDecodingStruct; - return status; - } else { - // The origin's length is longer than the remaining payload. - DCHECK_GT(altsvc_fields_.origin_length, state->remaining_payload()); - return state->ReportFrameSizeError(); - } - HTTP2_FALLTHROUGH; - - case PayloadState::kDecodingStrings: - return DecodeStrings(state, db); - - case PayloadState::kResumeDecodingStruct: - status = state->ResumeDecodingStructureInPayload(&altsvc_fields_, db); - payload_state_ = PayloadState::kMaybeDecodedStruct; - continue; - } - HTTP2_BUG << "PayloadState: " << payload_state_; - } -} - -DecodeStatus AltSvcPayloadDecoder::DecodeStrings(FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "AltSvcPayloadDecoder::DecodeStrings remaining_payload=" - << state->remaining_payload() - << ", db->Remaining=" << db->Remaining(); - // Note that we don't explicitly keep track of exactly how far through the - // origin; instead we compute it from how much is left of the original - // payload length and the decoded total length of the origin. - size_t origin_length = altsvc_fields_.origin_length; - size_t value_length = state->frame_header().payload_length - origin_length - - Http2AltSvcFields::EncodedSize(); - if (state->remaining_payload() > value_length) { - size_t remaining_origin_length = state->remaining_payload() - value_length; - size_t avail = db->MinLengthRemaining(remaining_origin_length); - state->listener()->OnAltSvcOriginData(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - if (remaining_origin_length > avail) { - payload_state_ = PayloadState::kDecodingStrings; - return DecodeStatus::kDecodeInProgress; - } - } - // All that is left is the value string. - DCHECK_LE(state->remaining_payload(), value_length); - DCHECK_LE(db->Remaining(), state->remaining_payload()); - if (db->HasData()) { - size_t avail = db->Remaining(); - state->listener()->OnAltSvcValueData(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - } - if (state->remaining_payload() == 0) { - state->listener()->OnAltSvcEnd(); - return DecodeStatus::kDecodeDone; - } - payload_state_ = PayloadState::kDecodingStrings; - return DecodeStatus::kDecodeInProgress; -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/altsvc_payload_decoder.h b/net/third_party/http2/decoder/payload_decoders/altsvc_payload_decoder.h deleted file mode 100644 index 7057bb6a..0000000 --- a/net/third_party/http2/decoder/payload_decoders/altsvc_payload_decoder.h +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_ALTSVC_PAYLOAD_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_ALTSVC_PAYLOAD_DECODER_H_ - -// Decodes the payload of a ALTSVC frame. - -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/decoder/frame_decoder_state.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { -namespace test { -class AltSvcPayloadDecoderPeer; -} // namespace test - -class HTTP2_EXPORT_PRIVATE AltSvcPayloadDecoder { - public: - // States during decoding of a ALTSVC frame. - enum class PayloadState { - // Start decoding the fixed size structure at the start of an ALTSVC - // frame (Http2AltSvcFields). - kStartDecodingStruct, - - // Handle the DecodeStatus returned from starting or resuming the - // decoding of Http2AltSvcFields. If complete, calls OnAltSvcStart. - kMaybeDecodedStruct, - - // Reports the value of the strings (origin and value) of an ALTSVC frame - // to the listener. - kDecodingStrings, - - // The initial decode buffer wasn't large enough for the Http2AltSvcFields, - // so this state resumes the decoding when ResumeDecodingPayload is called - // later with a new DecodeBuffer. - kResumeDecodingStruct, - }; - - // Starts the decoding of a ALTSVC frame's payload, and completes it if the - // entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a ALTSVC frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::AltSvcPayloadDecoderPeer; - - // Implements state kDecodingStrings. - DecodeStatus DecodeStrings(FrameDecoderState* state, DecodeBuffer* db); - - Http2AltSvcFields altsvc_fields_; - PayloadState payload_state_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_ALTSVC_PAYLOAD_DECODER_H_
diff --git a/net/third_party/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc b/net/third_party/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc deleted file mode 100644 index b31d605f..0000000 --- a/net/third_party/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc +++ /dev/null
@@ -1,121 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/altsvc_payload_decoder.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures_test_util.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/test_tools/frame_parts.h" -#include "net/third_party/http2/test_tools/frame_parts_collector.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/http2_frame_builder.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -// Provides friend access to an instance of the payload decoder, and also -// provides info to aid in testing. -class AltSvcPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { return Http2FrameType::ALTSVC; } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnAltSvcStart(const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) override { - VLOG(1) << "OnAltSvcStart header: " << header - << "; origin_length=" << origin_length - << "; value_length=" << value_length; - StartFrame(header)->OnAltSvcStart(header, origin_length, value_length); - } - - void OnAltSvcOriginData(const char* data, size_t len) override { - VLOG(1) << "OnAltSvcOriginData: len=" << len; - CurrentFrame()->OnAltSvcOriginData(data, len); - } - - void OnAltSvcValueData(const char* data, size_t len) override { - VLOG(1) << "OnAltSvcValueData: len=" << len; - CurrentFrame()->OnAltSvcValueData(data, len); - } - - void OnAltSvcEnd() override { - VLOG(1) << "OnAltSvcEnd"; - EndFrame()->OnAltSvcEnd(); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class AltSvcPayloadDecoderTest - : public AbstractPayloadDecoderTest<AltSvcPayloadDecoder, - AltSvcPayloadDecoderPeer, - Listener> {}; - -// Confirm we get an error if the payload is not long enough to hold -// Http2AltSvcFields and the indicated length of origin. -TEST_F(AltSvcPayloadDecoderTest, Truncated) { - Http2FrameBuilder fb; - fb.Append(Http2AltSvcFields{0xffff}); // The longest possible origin length. - fb.Append("Too little origin!"); - EXPECT_TRUE( - VerifyDetectsFrameSizeError(0, fb.buffer(), /*approve_size*/ nullptr)); -} - -class AltSvcPayloadLengthTests : public AltSvcPayloadDecoderTest, - public ::testing::WithParamInterface< - ::testing::tuple<uint16_t, uint32_t>> { - protected: - AltSvcPayloadLengthTests() - : origin_length_(::testing::get<0>(GetParam())), - value_length_(::testing::get<1>(GetParam())) { - VLOG(1) << "################ origin_length_=" << origin_length_ - << " value_length_=" << value_length_ << " ################"; - } - - const uint16_t origin_length_; - const uint32_t value_length_; -}; - -INSTANTIATE_TEST_CASE_P(VariousOriginAndValueLengths, - AltSvcPayloadLengthTests, - ::testing::Combine(::testing::Values(0, 1, 3, 65535), - ::testing::Values(0, 1, 3, 65537))); - -TEST_P(AltSvcPayloadLengthTests, ValidOriginAndValueLength) { - Http2String origin = Random().RandString(origin_length_); - Http2String value = Random().RandString(value_length_); - Http2FrameBuilder fb; - fb.Append(Http2AltSvcFields{origin_length_}); - fb.Append(origin); - fb.Append(value); - Http2FrameHeader header(fb.size(), Http2FrameType::ALTSVC, RandFlags(), - RandStreamId()); - set_frame_header(header); - FrameParts expected(header); - expected.SetAltSvcExpected(origin, value); - ASSERT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/continuation_payload_decoder.cc b/net/third_party/http2/decoder/payload_decoders/continuation_payload_decoder.cc deleted file mode 100644 index 90f5360..0000000 --- a/net/third_party/http2/decoder/payload_decoders/continuation_payload_decoder.cc +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/continuation_payload_decoder.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" - -namespace http2 { - -DecodeStatus ContinuationPayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - const uint32_t total_length = frame_header.payload_length; - - DVLOG(2) << "ContinuationPayloadDecoder::StartDecodingPayload: " - << frame_header; - DCHECK_EQ(Http2FrameType::CONTINUATION, frame_header.type); - DCHECK_LE(db->Remaining(), total_length); - DCHECK_EQ(0, frame_header.flags & ~(Http2FrameFlag::END_HEADERS)); - - state->InitializeRemainders(); - state->listener()->OnContinuationStart(frame_header); - return ResumeDecodingPayload(state, db); -} - -DecodeStatus ContinuationPayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "ContinuationPayloadDecoder::ResumeDecodingPayload" - << " remaining_payload=" << state->remaining_payload() - << " db->Remaining=" << db->Remaining(); - DCHECK_EQ(Http2FrameType::CONTINUATION, state->frame_header().type); - DCHECK_LE(state->remaining_payload(), state->frame_header().payload_length); - DCHECK_LE(db->Remaining(), state->remaining_payload()); - - size_t avail = db->Remaining(); - DCHECK_LE(avail, state->remaining_payload()); - if (avail > 0) { - state->listener()->OnHpackFragment(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - } - if (state->remaining_payload() == 0) { - state->listener()->OnContinuationEnd(); - return DecodeStatus::kDecodeDone; - } - return DecodeStatus::kDecodeInProgress; -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/continuation_payload_decoder.h b/net/third_party/http2/decoder/payload_decoders/continuation_payload_decoder.h deleted file mode 100644 index 6ca2b5fa..0000000 --- a/net/third_party/http2/decoder/payload_decoders/continuation_payload_decoder.h +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_CONTINUATION_PAYLOAD_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_CONTINUATION_PAYLOAD_DECODER_H_ - -// Decodes the payload of a CONTINUATION frame. - -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/decoder/frame_decoder_state.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { - -class HTTP2_EXPORT_PRIVATE ContinuationPayloadDecoder { - public: - // Starts the decoding of a CONTINUATION frame's payload, and completes - // it if the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a CONTINUATION frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_CONTINUATION_PAYLOAD_DECODER_H_
diff --git a/net/third_party/http2/decoder/payload_decoders/continuation_payload_decoder_test.cc b/net/third_party/http2/decoder/payload_decoders/continuation_payload_decoder_test.cc deleted file mode 100644 index 62075a6..0000000 --- a/net/third_party/http2/decoder/payload_decoders/continuation_payload_decoder_test.cc +++ /dev/null
@@ -1,85 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/continuation_payload_decoder.h" - -#include <stddef.h> - -#include <type_traits> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/test_tools/frame_parts.h" -#include "net/third_party/http2/test_tools/frame_parts_collector.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -// Provides friend access to an instance of the payload decoder, and also -// provides info to aid in testing. -class ContinuationPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { - return Http2FrameType::CONTINUATION; - } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnContinuationStart(const Http2FrameHeader& header) override { - VLOG(1) << "OnContinuationStart: " << header; - StartFrame(header)->OnContinuationStart(header); - } - - void OnHpackFragment(const char* data, size_t len) override { - VLOG(1) << "OnHpackFragment: len=" << len; - CurrentFrame()->OnHpackFragment(data, len); - } - - void OnContinuationEnd() override { - VLOG(1) << "OnContinuationEnd"; - EndFrame()->OnContinuationEnd(); - } -}; - -class ContinuationPayloadDecoderTest - : public AbstractPayloadDecoderTest<ContinuationPayloadDecoder, - ContinuationPayloadDecoderPeer, - Listener>, - public ::testing::WithParamInterface<uint32_t> { - protected: - ContinuationPayloadDecoderTest() : length_(GetParam()) { - VLOG(1) << "################ length_=" << length_ << " ################"; - } - - const uint32_t length_; -}; - -INSTANTIATE_TEST_CASE_P(VariousLengths, - ContinuationPayloadDecoderTest, - ::testing::Values(0, 1, 2, 3, 4, 5, 6)); - -TEST_P(ContinuationPayloadDecoderTest, ValidLength) { - Http2String hpack_payload = Random().RandString(length_); - Http2FrameHeader frame_header(length_, Http2FrameType::CONTINUATION, - RandFlags(), RandStreamId()); - set_frame_header(frame_header); - FrameParts expected(frame_header, hpack_payload); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(hpack_payload, expected)); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/data_payload_decoder.cc b/net/third_party/http2/decoder/payload_decoders/data_payload_decoder.cc deleted file mode 100644 index 41873449..0000000 --- a/net/third_party/http2/decoder/payload_decoders/data_payload_decoder.cc +++ /dev/null
@@ -1,127 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/data_payload_decoder.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "base/macros.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_bug_tracker.h" -#include "net/third_party/http2/platform/api/http2_macros.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, - DataPayloadDecoder::PayloadState v) { - switch (v) { - case DataPayloadDecoder::PayloadState::kReadPadLength: - return out << "kReadPadLength"; - case DataPayloadDecoder::PayloadState::kReadPayload: - return out << "kReadPayload"; - case DataPayloadDecoder::PayloadState::kSkipPadding: - return out << "kSkipPadding"; - } - // Since the value doesn't come over the wire, only a programming bug should - // result in reaching this point. - int unknown = static_cast<int>(v); - HTTP2_BUG << "Invalid DataPayloadDecoder::PayloadState: " << unknown; - return out << "DataPayloadDecoder::PayloadState(" << unknown << ")"; -} - -DecodeStatus DataPayloadDecoder::StartDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - const uint32_t total_length = frame_header.payload_length; - - DVLOG(2) << "DataPayloadDecoder::StartDecodingPayload: " << frame_header; - DCHECK_EQ(Http2FrameType::DATA, frame_header.type); - DCHECK_LE(db->Remaining(), total_length); - DCHECK_EQ(0, frame_header.flags & - ~(Http2FrameFlag::END_STREAM | Http2FrameFlag::PADDED)); - - // Special case for the hoped for common case: unpadded and fits fully into - // the decode buffer. TO BE SEEN if that is true. It certainly requires that - // the transport buffers be large (e.g. >> 16KB typically). - // TODO(jamessynge) Add counters. - DVLOG(2) << "StartDecodingPayload total_length=" << total_length; - if (!frame_header.IsPadded()) { - DVLOG(2) << "StartDecodingPayload !IsPadded"; - if (db->Remaining() == total_length) { - DVLOG(2) << "StartDecodingPayload all present"; - // Note that we don't cache the listener field so that the callee can - // replace it if the frame is bad. - // If this case is common enough, consider combining the 3 callbacks - // into one. - state->listener()->OnDataStart(frame_header); - if (total_length > 0) { - state->listener()->OnDataPayload(db->cursor(), total_length); - db->AdvanceCursor(total_length); - } - state->listener()->OnDataEnd(); - return DecodeStatus::kDecodeDone; - } - payload_state_ = PayloadState::kReadPayload; - } else { - payload_state_ = PayloadState::kReadPadLength; - } - state->InitializeRemainders(); - state->listener()->OnDataStart(frame_header); - return ResumeDecodingPayload(state, db); -} - -DecodeStatus DataPayloadDecoder::ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "DataPayloadDecoder::ResumeDecodingPayload payload_state_=" - << payload_state_; - const Http2FrameHeader& frame_header = state->frame_header(); - DCHECK_EQ(Http2FrameType::DATA, frame_header.type); - DCHECK_LE(state->remaining_payload_and_padding(), - frame_header.payload_length); - DCHECK_LE(db->Remaining(), state->remaining_payload_and_padding()); - DecodeStatus status; - size_t avail; - switch (payload_state_) { - case PayloadState::kReadPadLength: - // ReadPadLength handles the OnPadLength callback, and updating the - // remaining_payload and remaining_padding fields. If the amount of - // padding is too large to fit in the frame's payload, ReadPadLength - // instead calls OnPaddingTooLong and returns kDecodeError. - status = state->ReadPadLength(db, /*report_pad_length*/ true); - if (status != DecodeStatus::kDecodeDone) { - return status; - } - HTTP2_FALLTHROUGH; - - case PayloadState::kReadPayload: - avail = state->AvailablePayload(db); - if (avail > 0) { - state->listener()->OnDataPayload(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - } - if (state->remaining_payload() > 0) { - payload_state_ = PayloadState::kReadPayload; - return DecodeStatus::kDecodeInProgress; - } - HTTP2_FALLTHROUGH; - - case PayloadState::kSkipPadding: - // SkipPadding handles the OnPadding callback. - if (state->SkipPadding(db)) { - state->listener()->OnDataEnd(); - return DecodeStatus::kDecodeDone; - } - payload_state_ = PayloadState::kSkipPadding; - return DecodeStatus::kDecodeInProgress; - } - HTTP2_BUG << "PayloadState: " << payload_state_; - return DecodeStatus::kDecodeError; -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/data_payload_decoder.h b/net/third_party/http2/decoder/payload_decoders/data_payload_decoder.h deleted file mode 100644 index 218631b..0000000 --- a/net/third_party/http2/decoder/payload_decoders/data_payload_decoder.h +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_DATA_PAYLOAD_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_DATA_PAYLOAD_DECODER_H_ - -// Decodes the payload of a DATA frame. - -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/decoder/frame_decoder_state.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { -namespace test { -class DataPayloadDecoderPeer; -} // namespace test - -class HTTP2_EXPORT_PRIVATE DataPayloadDecoder { - public: - // States during decoding of a DATA frame. - enum class PayloadState { - // The frame is padded and we need to read the PAD_LENGTH field (1 byte), - // and then call OnPadLength - kReadPadLength, - - // Report the non-padding portion of the payload to the listener's - // OnDataPayload method. - kReadPayload, - - // The decoder has finished with the non-padding portion of the payload, - // and is now ready to skip the trailing padding, if the frame has any. - kSkipPadding, - }; - - // Starts decoding a DATA frame's payload, and completes it if - // the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a DATA frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::DataPayloadDecoderPeer; - - PayloadState payload_state_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_DATA_PAYLOAD_DECODER_H_
diff --git a/net/third_party/http2/decoder/payload_decoders/data_payload_decoder_test.cc b/net/third_party/http2/decoder/payload_decoders/data_payload_decoder_test.cc deleted file mode 100644 index f60779c..0000000 --- a/net/third_party/http2/decoder/payload_decoders/data_payload_decoder_test.cc +++ /dev/null
@@ -1,113 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/data_payload_decoder.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/http2_structures_test_util.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "net/third_party/http2/test_tools/frame_parts.h" -#include "net/third_party/http2/test_tools/frame_parts_collector.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/http2_frame_builder.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionResult; - -namespace http2 { -namespace test { - -// Provides friend access to an instance of the payload decoder, and also -// provides info to aid in testing. -class DataPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { return Http2FrameType::DATA; } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { - return Http2FrameFlag::PADDED; - } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnDataStart(const Http2FrameHeader& header) override { - VLOG(1) << "OnDataStart: " << header; - StartFrame(header)->OnDataStart(header); - } - - void OnDataPayload(const char* data, size_t len) override { - VLOG(1) << "OnDataPayload: len=" << len; - CurrentFrame()->OnDataPayload(data, len); - } - - void OnDataEnd() override { - VLOG(1) << "OnDataEnd"; - EndFrame()->OnDataEnd(); - } - - void OnPadLength(size_t pad_length) override { - VLOG(1) << "OnPadLength: " << pad_length; - CurrentFrame()->OnPadLength(pad_length); - } - - void OnPadding(const char* padding, size_t skipped_length) override { - VLOG(1) << "OnPadding: " << skipped_length; - CurrentFrame()->OnPadding(padding, skipped_length); - } - - void OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) override { - VLOG(1) << "OnPaddingTooLong: " << header - << " missing_length: " << missing_length; - EndFrame()->OnPaddingTooLong(header, missing_length); - } -}; - -class DataPayloadDecoderTest - : public AbstractPaddablePayloadDecoderTest<DataPayloadDecoder, - DataPayloadDecoderPeer, - Listener> { - protected: - AssertionResult CreateAndDecodeDataOfSize(size_t data_size) { - Reset(); - uint8_t flags = RandFlags(); - - Http2String data_payload = Random().RandString(data_size); - frame_builder_.Append(data_payload); - MaybeAppendTrailingPadding(); - - Http2FrameHeader frame_header(frame_builder_.size(), Http2FrameType::DATA, - flags, RandStreamId()); - set_frame_header(frame_header); - ScrubFlagsOfHeader(&frame_header); - FrameParts expected(frame_header, data_payload, total_pad_length_); - VERIFY_AND_RETURN_SUCCESS( - DecodePayloadAndValidateSeveralWays(frame_builder_.buffer(), expected)); - } -}; - -INSTANTIATE_TEST_CASE_P(VariousPadLengths, - DataPayloadDecoderTest, - ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256)); - -TEST_P(DataPayloadDecoderTest, VariousDataPayloadSizes) { - for (size_t data_size : {0, 1, 2, 3, 255, 256, 1024}) { - EXPECT_TRUE(CreateAndDecodeDataOfSize(data_size)); - } -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/goaway_payload_decoder.cc b/net/third_party/http2/decoder/payload_decoders/goaway_payload_decoder.cc deleted file mode 100644 index 89329e2b..0000000 --- a/net/third_party/http2/decoder/payload_decoders/goaway_payload_decoder.cc +++ /dev/null
@@ -1,121 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/goaway_payload_decoder.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "base/macros.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_bug_tracker.h" -#include "net/third_party/http2/platform/api/http2_macros.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, - GoAwayPayloadDecoder::PayloadState v) { - switch (v) { - case GoAwayPayloadDecoder::PayloadState::kStartDecodingFixedFields: - return out << "kStartDecodingFixedFields"; - case GoAwayPayloadDecoder::PayloadState::kHandleFixedFieldsStatus: - return out << "kHandleFixedFieldsStatus"; - case GoAwayPayloadDecoder::PayloadState::kReadOpaqueData: - return out << "kReadOpaqueData"; - case GoAwayPayloadDecoder::PayloadState::kResumeDecodingFixedFields: - return out << "kResumeDecodingFixedFields"; - } - // Since the value doesn't come over the wire, only a programming bug should - // result in reaching this point. - int unknown = static_cast<int>(v); - HTTP2_BUG << "Invalid GoAwayPayloadDecoder::PayloadState: " << unknown; - return out << "GoAwayPayloadDecoder::PayloadState(" << unknown << ")"; -} - -DecodeStatus GoAwayPayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "GoAwayPayloadDecoder::StartDecodingPayload: " - << state->frame_header(); - DCHECK_EQ(Http2FrameType::GOAWAY, state->frame_header().type); - DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - DCHECK_EQ(0, state->frame_header().flags); - - state->InitializeRemainders(); - payload_state_ = PayloadState::kStartDecodingFixedFields; - return ResumeDecodingPayload(state, db); -} - -DecodeStatus GoAwayPayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "GoAwayPayloadDecoder::ResumeDecodingPayload: remaining_payload=" - << state->remaining_payload() - << ", db->Remaining=" << db->Remaining(); - - const Http2FrameHeader& frame_header = state->frame_header(); - DCHECK_EQ(Http2FrameType::GOAWAY, frame_header.type); - DCHECK_LE(db->Remaining(), frame_header.payload_length); - DCHECK_NE(PayloadState::kHandleFixedFieldsStatus, payload_state_); - - // |status| has to be initialized to some value to avoid compiler error in - // case PayloadState::kHandleFixedFieldsStatus below, but value does not - // matter, see DCHECK_NE above. - DecodeStatus status = DecodeStatus::kDecodeError; - size_t avail; - while (true) { - DVLOG(2) << "GoAwayPayloadDecoder::ResumeDecodingPayload payload_state_=" - << payload_state_; - switch (payload_state_) { - case PayloadState::kStartDecodingFixedFields: - status = state->StartDecodingStructureInPayload(&goaway_fields_, db); - HTTP2_FALLTHROUGH; - - case PayloadState::kHandleFixedFieldsStatus: - if (status == DecodeStatus::kDecodeDone) { - state->listener()->OnGoAwayStart(frame_header, goaway_fields_); - } else { - // Not done decoding the structure. Either we've got more payload - // to decode, or we've run out because the payload is too short, - // in which case OnFrameSizeError will have already been called. - DCHECK((status == DecodeStatus::kDecodeInProgress && - state->remaining_payload() > 0) || - (status == DecodeStatus::kDecodeError && - state->remaining_payload() == 0)) - << "\n status=" << status - << "; remaining_payload=" << state->remaining_payload(); - payload_state_ = PayloadState::kResumeDecodingFixedFields; - return status; - } - HTTP2_FALLTHROUGH; - - case PayloadState::kReadOpaqueData: - // The opaque data is all the remains to be decoded, so anything left - // in the decode buffer is opaque data. - avail = db->Remaining(); - if (avail > 0) { - state->listener()->OnGoAwayOpaqueData(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - } - if (state->remaining_payload() > 0) { - payload_state_ = PayloadState::kReadOpaqueData; - return DecodeStatus::kDecodeInProgress; - } - state->listener()->OnGoAwayEnd(); - return DecodeStatus::kDecodeDone; - - case PayloadState::kResumeDecodingFixedFields: - status = state->ResumeDecodingStructureInPayload(&goaway_fields_, db); - payload_state_ = PayloadState::kHandleFixedFieldsStatus; - continue; - } - HTTP2_BUG << "PayloadState: " << payload_state_; - } -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/goaway_payload_decoder.h b/net/third_party/http2/decoder/payload_decoders/goaway_payload_decoder.h deleted file mode 100644 index f0868fb..0000000 --- a/net/third_party/http2/decoder/payload_decoders/goaway_payload_decoder.h +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_GOAWAY_PAYLOAD_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_GOAWAY_PAYLOAD_DECODER_H_ - -// Decodes the payload of a GOAWAY frame. - -// TODO(jamessynge): Sweep through all payload decoders, changing the names of -// the PayloadState enums so that they are really states, and not actions. - -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/decoder/frame_decoder_state.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { -namespace test { -class GoAwayPayloadDecoderPeer; -} // namespace test - -class HTTP2_EXPORT_PRIVATE GoAwayPayloadDecoder { - public: - // States during decoding of a GOAWAY frame. - enum class PayloadState { - // At the start of the GOAWAY frame payload, ready to start decoding the - // fixed size fields into goaway_fields_. - kStartDecodingFixedFields, - - // Handle the DecodeStatus returned from starting or resuming the - // decoding of Http2GoAwayFields into goaway_fields_. If complete, - // calls OnGoAwayStart. - kHandleFixedFieldsStatus, - - // Report the Opaque Data portion of the payload to the listener's - // OnGoAwayOpaqueData method, and call OnGoAwayEnd when the end of the - // payload is reached. - kReadOpaqueData, - - // The fixed size fields weren't all available when the decoder first - // tried to decode them (state kStartDecodingFixedFields); this state - // resumes the decoding when ResumeDecodingPayload is called later. - kResumeDecodingFixedFields, - }; - - // Starts the decoding of a GOAWAY frame's payload, and completes it if - // the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a GOAWAY frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::GoAwayPayloadDecoderPeer; - - Http2GoAwayFields goaway_fields_; - PayloadState payload_state_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_GOAWAY_PAYLOAD_DECODER_H_
diff --git a/net/third_party/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc b/net/third_party/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc deleted file mode 100644 index fdba2529..0000000 --- a/net/third_party/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc +++ /dev/null
@@ -1,107 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/goaway_payload_decoder.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures_test_util.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/test_tools/frame_parts.h" -#include "net/third_party/http2/test_tools/frame_parts_collector.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/http2_frame_builder.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -class GoAwayPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { return Http2FrameType::GOAWAY; } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnGoAwayStart(const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) override { - VLOG(1) << "OnGoAwayStart header: " << header << "; goaway: " << goaway; - StartFrame(header)->OnGoAwayStart(header, goaway); - } - - void OnGoAwayOpaqueData(const char* data, size_t len) override { - VLOG(1) << "OnGoAwayOpaqueData: len=" << len; - CurrentFrame()->OnGoAwayOpaqueData(data, len); - } - - void OnGoAwayEnd() override { - VLOG(1) << "OnGoAwayEnd"; - EndFrame()->OnGoAwayEnd(); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class GoAwayPayloadDecoderTest - : public AbstractPayloadDecoderTest<GoAwayPayloadDecoder, - GoAwayPayloadDecoderPeer, - Listener> {}; - -// Confirm we get an error if the payload is not long enough to hold -// Http2GoAwayFields. -TEST_F(GoAwayPayloadDecoderTest, Truncated) { - auto approve_size = [](size_t size) { - return size != Http2GoAwayFields::EncodedSize(); - }; - Http2FrameBuilder fb; - fb.Append(Http2GoAwayFields(123, Http2ErrorCode::ENHANCE_YOUR_CALM)); - EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); -} - -class GoAwayOpaqueDataLengthTests - : public GoAwayPayloadDecoderTest, - public ::testing::WithParamInterface<uint32_t> { - protected: - GoAwayOpaqueDataLengthTests() : length_(GetParam()) { - VLOG(1) << "################ length_=" << length_ << " ################"; - } - - const uint32_t length_; -}; - -INSTANTIATE_TEST_CASE_P(VariousLengths, - GoAwayOpaqueDataLengthTests, - ::testing::Values(0, 1, 2, 3, 4, 5, 6)); - -TEST_P(GoAwayOpaqueDataLengthTests, ValidLength) { - Http2GoAwayFields goaway; - Randomize(&goaway, RandomPtr()); - Http2String opaque_data = Random().RandString(length_); - Http2FrameBuilder fb; - fb.Append(goaway); - fb.Append(opaque_data); - Http2FrameHeader header(fb.size(), Http2FrameType::GOAWAY, RandFlags(), - RandStreamId()); - set_frame_header(header); - FrameParts expected(header, opaque_data); - expected.SetOptGoaway(goaway); - ASSERT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/headers_payload_decoder.cc b/net/third_party/http2/decoder/payload_decoders/headers_payload_decoder.cc deleted file mode 100644 index 7dd3801..0000000 --- a/net/third_party/http2/decoder/payload_decoders/headers_payload_decoder.cc +++ /dev/null
@@ -1,175 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/headers_payload_decoder.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "base/macros.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_bug_tracker.h" -#include "net/third_party/http2/platform/api/http2_macros.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, - HeadersPayloadDecoder::PayloadState v) { - switch (v) { - case HeadersPayloadDecoder::PayloadState::kReadPadLength: - return out << "kReadPadLength"; - case HeadersPayloadDecoder::PayloadState::kStartDecodingPriorityFields: - return out << "kStartDecodingPriorityFields"; - case HeadersPayloadDecoder::PayloadState::kResumeDecodingPriorityFields: - return out << "kResumeDecodingPriorityFields"; - case HeadersPayloadDecoder::PayloadState::kReadPayload: - return out << "kReadPayload"; - case HeadersPayloadDecoder::PayloadState::kSkipPadding: - return out << "kSkipPadding"; - } - // Since the value doesn't come over the wire, only a programming bug should - // result in reaching this point. - int unknown = static_cast<int>(v); - HTTP2_BUG << "Invalid HeadersPayloadDecoder::PayloadState: " << unknown; - return out << "HeadersPayloadDecoder::PayloadState(" << unknown << ")"; -} - -DecodeStatus HeadersPayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - const uint32_t total_length = frame_header.payload_length; - - DVLOG(2) << "HeadersPayloadDecoder::StartDecodingPayload: " << frame_header; - - DCHECK_EQ(Http2FrameType::HEADERS, frame_header.type); - DCHECK_LE(db->Remaining(), total_length); - DCHECK_EQ(0, frame_header.flags & - ~(Http2FrameFlag::END_STREAM | Http2FrameFlag::END_HEADERS | - Http2FrameFlag::PADDED | Http2FrameFlag::PRIORITY)); - - // Special case for HEADERS frames that contain only the HPACK block - // (fragment or whole) and that fit fully into the decode buffer. - // Why? Unencoded browser GET requests are typically under 1K and HPACK - // commonly shrinks request headers by 80%, so we can expect this to - // be common. - // TODO(jamessynge) Add counters here and to Spdy for determining how - // common this situation is. A possible approach is to create a - // Http2FrameDecoderListener that counts the callbacks and then forwards - // them on to another listener, which makes it easy to add and remove - // counting on a connection or even frame basis. - - // PADDED and PRIORITY both extra steps to decode, but if neither flag is - // set then we can decode faster. - const auto payload_flags = Http2FrameFlag::PADDED | Http2FrameFlag::PRIORITY; - if (!frame_header.HasAnyFlags(payload_flags)) { - DVLOG(2) << "StartDecodingPayload !IsPadded && !HasPriority"; - if (db->Remaining() == total_length) { - DVLOG(2) << "StartDecodingPayload all present"; - // Note that we don't cache the listener field so that the callee can - // replace it if the frame is bad. - // If this case is common enough, consider combining the 3 callbacks - // into one, especially if END_HEADERS is also set. - state->listener()->OnHeadersStart(frame_header); - if (total_length > 0) { - state->listener()->OnHpackFragment(db->cursor(), total_length); - db->AdvanceCursor(total_length); - } - state->listener()->OnHeadersEnd(); - return DecodeStatus::kDecodeDone; - } - payload_state_ = PayloadState::kReadPayload; - } else if (frame_header.IsPadded()) { - payload_state_ = PayloadState::kReadPadLength; - } else { - DCHECK(frame_header.HasPriority()) << frame_header; - payload_state_ = PayloadState::kStartDecodingPriorityFields; - } - state->InitializeRemainders(); - state->listener()->OnHeadersStart(frame_header); - return ResumeDecodingPayload(state, db); -} - -DecodeStatus HeadersPayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "HeadersPayloadDecoder::ResumeDecodingPayload " - << "remaining_payload=" << state->remaining_payload() - << "; db->Remaining=" << db->Remaining(); - - const Http2FrameHeader& frame_header = state->frame_header(); - - DCHECK_EQ(Http2FrameType::HEADERS, frame_header.type); - DCHECK_LE(state->remaining_payload_and_padding(), - frame_header.payload_length); - DCHECK_LE(db->Remaining(), state->remaining_payload_and_padding()); - DecodeStatus status; - size_t avail; - while (true) { - DVLOG(2) << "HeadersPayloadDecoder::ResumeDecodingPayload payload_state_=" - << payload_state_; - switch (payload_state_) { - case PayloadState::kReadPadLength: - // ReadPadLength handles the OnPadLength callback, and updating the - // remaining_payload and remaining_padding fields. If the amount of - // padding is too large to fit in the frame's payload, ReadPadLength - // instead calls OnPaddingTooLong and returns kDecodeError. - status = state->ReadPadLength(db, /*report_pad_length*/ true); - if (status != DecodeStatus::kDecodeDone) { - return status; - } - if (!frame_header.HasPriority()) { - payload_state_ = PayloadState::kReadPayload; - continue; - } - HTTP2_FALLTHROUGH; - - case PayloadState::kStartDecodingPriorityFields: - status = state->StartDecodingStructureInPayload(&priority_fields_, db); - if (status != DecodeStatus::kDecodeDone) { - payload_state_ = PayloadState::kResumeDecodingPriorityFields; - return status; - } - state->listener()->OnHeadersPriority(priority_fields_); - HTTP2_FALLTHROUGH; - - case PayloadState::kReadPayload: - avail = state->AvailablePayload(db); - if (avail > 0) { - state->listener()->OnHpackFragment(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - } - if (state->remaining_payload() > 0) { - payload_state_ = PayloadState::kReadPayload; - return DecodeStatus::kDecodeInProgress; - } - HTTP2_FALLTHROUGH; - - case PayloadState::kSkipPadding: - // SkipPadding handles the OnPadding callback. - if (state->SkipPadding(db)) { - state->listener()->OnHeadersEnd(); - return DecodeStatus::kDecodeDone; - } - payload_state_ = PayloadState::kSkipPadding; - return DecodeStatus::kDecodeInProgress; - - case PayloadState::kResumeDecodingPriorityFields: - status = state->ResumeDecodingStructureInPayload(&priority_fields_, db); - if (status != DecodeStatus::kDecodeDone) { - return status; - } - state->listener()->OnHeadersPriority(priority_fields_); - payload_state_ = PayloadState::kReadPayload; - continue; - } - HTTP2_BUG << "PayloadState: " << payload_state_; - } -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/headers_payload_decoder.h b/net/third_party/http2/decoder/payload_decoders/headers_payload_decoder.h deleted file mode 100644 index 82ca2032..0000000 --- a/net/third_party/http2/decoder/payload_decoders/headers_payload_decoder.h +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_HEADERS_PAYLOAD_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_HEADERS_PAYLOAD_DECODER_H_ - -// Decodes the payload of a HEADERS frame. - -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/decoder/frame_decoder_state.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { -namespace test { -class HeadersPayloadDecoderPeer; -} // namespace test - -class HTTP2_EXPORT_PRIVATE HeadersPayloadDecoder { - public: - // States during decoding of a HEADERS frame, unless the fast path kicks - // in, in which case the state machine will be bypassed. - enum class PayloadState { - // The PADDED flag is set, and we now need to read the Pad Length field - // (the first byte of the payload, after the common frame header). - kReadPadLength, - - // The PRIORITY flag is set, and we now need to read the fixed size priority - // fields (E, Stream Dependency, Weight) into priority_fields_. Calls on - // OnHeadersPriority if completely decodes those fields. - kStartDecodingPriorityFields, - - // The decoder passes the non-padding portion of the remaining payload - // (i.e. the HPACK block fragment) to the listener's OnHpackFragment method. - kReadPayload, - - // The decoder has finished with the HPACK block fragment, and is now - // ready to skip the trailing padding, if the frame has any. - kSkipPadding, - - // The fixed size fields weren't all available when the decoder first tried - // to decode them (state kStartDecodingPriorityFields); this state resumes - // the decoding when ResumeDecodingPayload is called later. - kResumeDecodingPriorityFields, - }; - - // Starts the decoding of a HEADERS frame's payload, and completes it if - // the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a HEADERS frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::HeadersPayloadDecoderPeer; - - PayloadState payload_state_; - Http2PriorityFields priority_fields_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_HEADERS_PAYLOAD_DECODER_H_
diff --git a/net/third_party/http2/decoder/payload_decoders/headers_payload_decoder_test.cc b/net/third_party/http2/decoder/payload_decoders/headers_payload_decoder_test.cc deleted file mode 100644 index 252ad88..0000000 --- a/net/third_party/http2/decoder/payload_decoders/headers_payload_decoder_test.cc +++ /dev/null
@@ -1,158 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/headers_payload_decoder.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures_test_util.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/test_tools/frame_parts.h" -#include "net/third_party/http2/test_tools/frame_parts_collector.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/http2_frame_builder.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -class HeadersPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { - return Http2FrameType::HEADERS; - } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { - return Http2FrameFlag::PADDED | Http2FrameFlag::PRIORITY; - } -}; - -namespace { - -// Listener handles all On* methods that are expected to be called. If any other -// On* methods of Http2FrameDecoderListener is called then the test fails; this -// is achieved by way of FailingHttp2FrameDecoderListener, the base class of -// FramePartsCollector. -// These On* methods make use of StartFrame, EndFrame, etc. of the base class -// to create and access to FrameParts instance(s) that will record the details. -// After decoding, the test validation code can access the FramePart instance(s) -// via the public methods of FramePartsCollector. -struct Listener : public FramePartsCollector { - void OnHeadersStart(const Http2FrameHeader& header) override { - VLOG(1) << "OnHeadersStart: " << header; - StartFrame(header)->OnHeadersStart(header); - } - - void OnHeadersPriority(const Http2PriorityFields& priority) override { - VLOG(1) << "OnHeadersPriority: " << priority; - CurrentFrame()->OnHeadersPriority(priority); - } - - void OnHpackFragment(const char* data, size_t len) override { - VLOG(1) << "OnHpackFragment: len=" << len; - CurrentFrame()->OnHpackFragment(data, len); - } - - void OnHeadersEnd() override { - VLOG(1) << "OnHeadersEnd"; - EndFrame()->OnHeadersEnd(); - } - - void OnPadLength(size_t pad_length) override { - VLOG(1) << "OnPadLength: " << pad_length; - CurrentFrame()->OnPadLength(pad_length); - } - - void OnPadding(const char* padding, size_t skipped_length) override { - VLOG(1) << "OnPadding: " << skipped_length; - CurrentFrame()->OnPadding(padding, skipped_length); - } - - void OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) override { - VLOG(1) << "OnPaddingTooLong: " << header - << "; missing_length: " << missing_length; - FrameError(header)->OnPaddingTooLong(header, missing_length); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class HeadersPayloadDecoderTest - : public AbstractPaddablePayloadDecoderTest<HeadersPayloadDecoder, - HeadersPayloadDecoderPeer, - Listener> {}; - -INSTANTIATE_TEST_CASE_P(VariousPadLengths, - HeadersPayloadDecoderTest, - ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256)); - -// Decode various sizes of (fake) HPACK payload, both with and without the -// PRIORITY flag set. -TEST_P(HeadersPayloadDecoderTest, VariousHpackPayloadSizes) { - for (size_t hpack_size : {0, 1, 2, 3, 255, 256, 1024}) { - LOG(INFO) << "########### hpack_size = " << hpack_size << " ###########"; - Http2PriorityFields priority(RandStreamId(), 1 + Random().Rand8(), - Random().OneIn(2)); - - for (bool has_priority : {false, true}) { - Reset(); - ASSERT_EQ(IsPadded() ? 1u : 0u, frame_builder_.size()); - uint8_t flags = RandFlags(); - if (has_priority) { - flags |= Http2FrameFlag::PRIORITY; - frame_builder_.Append(priority); - } - - Http2String hpack_payload = Random().RandString(hpack_size); - frame_builder_.Append(hpack_payload); - - MaybeAppendTrailingPadding(); - Http2FrameHeader frame_header(frame_builder_.size(), - Http2FrameType::HEADERS, flags, - RandStreamId()); - set_frame_header(frame_header); - ScrubFlagsOfHeader(&frame_header); - FrameParts expected(frame_header, hpack_payload, total_pad_length_); - if (has_priority) { - expected.SetOptPriority(priority); - } - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(frame_builder_.buffer(), - expected)); - } - } -} - -// Confirm we get an error if the PRIORITY flag is set but the payload is -// not long enough, regardless of the amount of (valid) padding. -TEST_P(HeadersPayloadDecoderTest, Truncated) { - auto approve_size = [](size_t size) { - return size != Http2PriorityFields::EncodedSize(); - }; - Http2FrameBuilder fb; - fb.Append(Http2PriorityFields(RandStreamId(), 1 + Random().Rand8(), - Random().OneIn(2))); - EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors( - Http2FrameFlag::PRIORITY, fb.buffer(), approve_size, total_pad_length_)); -} - -// Confirm we get an error if the PADDED flag is set but the payload is not -// long enough to hold even the Pad Length amount of padding. -TEST_P(HeadersPayloadDecoderTest, PaddingTooLong) { - EXPECT_TRUE(VerifyDetectsPaddingTooLong()); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.cc b/net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.cc deleted file mode 100644 index bf829510..0000000 --- a/net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.cc +++ /dev/null
@@ -1,97 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h" - -#include "net/third_party/http2/decoder/frame_decoder_state_test_util.h" -#include "net/third_party/http2/http2_structures_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { -PayloadDecoderBaseTest::PayloadDecoderBaseTest() { - // If the test adds more data after the frame payload, - // stop as soon as the payload is decoded. - stop_decode_on_done_ = true; - frame_header_is_set_ = false; - Randomize(&frame_header_, RandomPtr()); -} - -DecodeStatus PayloadDecoderBaseTest::StartDecoding(DecodeBuffer* db) { - DVLOG(2) << "StartDecoding, db->Remaining=" << db->Remaining(); - // Make sure sub-class has set frame_header_ so that we can inject it - // into the payload decoder below. - if (!frame_header_is_set_) { - ADD_FAILURE() << "frame_header_ is not set"; - return DecodeStatus::kDecodeError; - } - // The contract with the payload decoders is that they won't receive a - // decode buffer that extends beyond the end of the frame. - if (db->Remaining() > frame_header_.payload_length) { - ADD_FAILURE() << "DecodeBuffer has too much data: " << db->Remaining() - << " > " << frame_header_.payload_length; - return DecodeStatus::kDecodeError; - } - - // Prepare the payload decoder. - PreparePayloadDecoder(); - - // Reconstruct the FrameDecoderState, prepare the listener, and add it to - // the FrameDecoderState. - Http2DefaultReconstructObject(&frame_decoder_state_, RandomPtr()); - frame_decoder_state_.set_listener(PrepareListener()); - - // Make sure that a listener was provided. - if (frame_decoder_state_.listener() == nullptr) { - ADD_FAILURE() << "PrepareListener must return a listener."; - return DecodeStatus::kDecodeError; - } - - // Now that nothing in the payload decoder should be valid, inject the - // Http2FrameHeader whose payload we're about to decode. That header is the - // only state that a payload decoder should expect is valid when its Start - // method is called. - FrameDecoderStatePeer::set_frame_header(frame_header_, &frame_decoder_state_); - DecodeStatus status = StartDecodingPayload(db); - if (status != DecodeStatus::kDecodeInProgress) { - // Keep track of this so that a concrete test can verify that both fast - // and slow decoding paths have been tested. - ++fast_decode_count_; - } - return status; -} - -DecodeStatus PayloadDecoderBaseTest::ResumeDecoding(DecodeBuffer* db) { - DVLOG(2) << "ResumeDecoding, db->Remaining=" << db->Remaining(); - DecodeStatus status = ResumeDecodingPayload(db); - if (status != DecodeStatus::kDecodeInProgress) { - // Keep track of this so that a concrete test can verify that both fast - // and slow decoding paths have been tested. - ++slow_decode_count_; - } - return status; -} - -::testing::AssertionResult -PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays( - Http2StringPiece payload, - Validator validator) { - VERIFY_TRUE(frame_header_is_set_); - // Cap the payload to be decoded at the declared payload length. This is - // required by the decoders' preconditions; they are designed on the - // assumption that they're never passed more than they're permitted to - // consume. - // Note that it is OK if the payload is too short; the validator may be - // designed to check for that. - if (payload.size() > frame_header_.payload_length) { - payload = Http2StringPiece(payload.data(), frame_header_.payload_length); - } - DecodeBuffer db(payload); - ResetDecodeSpeedCounters(); - const bool kMayReturnZeroOnFirst = false; - return DecodeAndValidateSeveralWays(&db, kMayReturnZeroOnFirst, validator); -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h b/net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h deleted file mode 100644 index 4a287e413..0000000 --- a/net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h +++ /dev/null
@@ -1,455 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_PAYLOAD_DECODER_BASE_TEST_UTIL_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_PAYLOAD_DECODER_BASE_TEST_UTIL_H_ - -// Base class for testing concrete payload decoder classes. - -#include <stddef.h> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/decoder/frame_decoder_state.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_constants_test_util.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_reconstruct_object.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "net/third_party/http2/test_tools/frame_parts.h" -#include "net/third_party/http2/tools/http2_frame_builder.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -// Base class for tests of payload decoders. Below this there is a templated -// sub-class that adds a bunch of type specific features. -class PayloadDecoderBaseTest : public RandomDecoderTest { - protected: - PayloadDecoderBaseTest(); - - // Virtual functions to be implemented by the test classes for the individual - // payload decoders... - - // Start decoding the payload. - virtual DecodeStatus StartDecodingPayload(DecodeBuffer* db) = 0; - - // Resume decoding the payload. - virtual DecodeStatus ResumeDecodingPayload(DecodeBuffer* db) = 0; - - // In support of ensuring that we're really accessing and updating the - // decoder, prepare the decoder by, for example, overwriting the decoder. - virtual void PreparePayloadDecoder() = 0; - - // Get the listener to be inserted into the FrameDecoderState, ready for - // listening (e.g. reset if it is a FramePartsCollector). - virtual Http2FrameDecoderListener* PrepareListener() = 0; - - // Record a frame header for use on each call to StartDecoding. - void set_frame_header(const Http2FrameHeader& header) { - EXPECT_EQ(0, InvalidFlagMaskForFrameType(header.type) & header.flags); - if (!frame_header_is_set_ || frame_header_ != header) { - VLOG(2) << "set_frame_header: " << frame_header_; - } - frame_header_ = header; - frame_header_is_set_ = true; - } - - FrameDecoderState* mutable_state() { return &frame_decoder_state_; } - - // Randomize the payload decoder, sets the payload decoder's frame_header_, - // then start decoding the payload. Called by RandomDecoderTest. This method - // is final so that we can always perform certain actions when - // RandomDecoderTest starts the decoding of a payload, such as randomizing the - // the payload decoder, injecting the frame header and counting fast decoding - // cases. Sub-classes must implement StartDecodingPayload to perform their - // initial decoding of a frame's payload. - DecodeStatus StartDecoding(DecodeBuffer* db) final; - - // Called by RandomDecoderTest. This method is final so that we can always - // perform certain actions when RandomDecoderTest calls it, such as counting - // slow decode cases. Sub-classes must implement ResumeDecodingPayload to - // continue decoding the frame's payload, which must not all be in one buffer. - DecodeStatus ResumeDecoding(DecodeBuffer* db) final; - - // Given the specified payload (without the common frame header), decode - // it with several partitionings of the payload. - ::testing::AssertionResult DecodePayloadAndValidateSeveralWays( - Http2StringPiece payload, - Validator validator); - - // TODO(jamessynge): Add helper method for verifying these are both non-zero, - // and call the new method from tests that expect successful decoding. - void ResetDecodeSpeedCounters() { - fast_decode_count_ = 0; - slow_decode_count_ = 0; - } - - // Count of payloads that are full decoded by StartDecodingPayload, or that - // an error was detected by StartDecodingPayload. - size_t fast_decode_count_ = 0; - - // Count of payloads that require calling ResumeDecodingPayload in order to - // decode them completely (or to detect an error during decoding). - size_t slow_decode_count_ = 0; - - private: - bool frame_header_is_set_ = false; - Http2FrameHeader frame_header_; - FrameDecoderState frame_decoder_state_; -}; - -// Base class for payload decoders of type Decoder, with corresponding test -// peer of type DecoderPeer, and using class Listener as the implementation -// of Http2FrameDecoderListenerInterface to be used during decoding. -// Typically Listener is a sub-class of FramePartsCollector. -// SupportedFrameType is set to false only for UnknownPayloadDecoder. -template <class Decoder, - class DecoderPeer, - class Listener, - bool SupportedFrameType = true> -class AbstractPayloadDecoderTest : public PayloadDecoderBaseTest { - protected: - // An ApproveSize function returns true to approve decoding the specified - // size of payload, else false to skip that size. Typically used for negative - // tests; for example, decoding a SETTINGS frame at all sizes except for - // multiples of 6. - typedef std::function<bool(size_t size)> ApproveSize; - - AbstractPayloadDecoderTest() {} - - // These tests are in setup rather than the constructor for two reasons: - // 1) Constructors are not allowed to fail, so gUnit documents that EXPECT_* - // and ASSERT_* are not allowed in constructors, and should instead be in - // SetUp if they are needed before the body of the test is executed. - // 2) To allow the sub-class constructor to make any desired modifications to - // the DecoderPeer before these tests are executed; in particular, - // UnknownPayloadDecoderPeer has not got a fixed frame type, but it is - // instead set during the test's constructor. - void SetUp() override { - PayloadDecoderBaseTest::SetUp(); - - // Confirm that DecoderPeer et al returns sensible values. Using auto as the - // variable type so that no (narrowing) conversions take place that hide - // problems; i.e. if someone changes KnownFlagsMaskForFrameType so that it - // doesn't return a uint8, and has bits above the low-order 8 bits set, this - // bit of paranoia should detect the problem before we get too far. - auto frame_type = DecoderPeer::FrameType(); - if (SupportedFrameType) { - EXPECT_TRUE(IsSupportedHttp2FrameType(frame_type)) << frame_type; - } else { - EXPECT_FALSE(IsSupportedHttp2FrameType(frame_type)) << frame_type; - } - - auto known_flags = KnownFlagsMaskForFrameType(frame_type); - EXPECT_EQ(known_flags, known_flags & 0xff); - - auto flags_to_avoid = DecoderPeer::FlagsAffectingPayloadDecoding(); - EXPECT_EQ(flags_to_avoid, flags_to_avoid & known_flags); - } - - void PreparePayloadDecoder() override { - Http2DefaultReconstructObject(&payload_decoder_, RandomPtr()); - } - - Http2FrameDecoderListener* PrepareListener() override { - listener_.Reset(); - return &listener_; - } - - // Returns random flags, but only those valid for the frame type, yet not - // those that the DecoderPeer says will affect the decoding of the payload - // (e.g. the PRIORTY flag on a HEADERS frame or PADDED on DATA frames). - uint8_t RandFlags() { - return Random().Rand8() & - KnownFlagsMaskForFrameType(DecoderPeer::FrameType()) & - ~DecoderPeer::FlagsAffectingPayloadDecoding(); - } - - // Start decoding the payload. - DecodeStatus StartDecodingPayload(DecodeBuffer* db) override { - DVLOG(2) << "StartDecodingPayload, db->Remaining=" << db->Remaining(); - return payload_decoder_.StartDecodingPayload(mutable_state(), db); - } - - // Resume decoding the payload. - DecodeStatus ResumeDecodingPayload(DecodeBuffer* db) override { - DVLOG(2) << "ResumeDecodingPayload, db->Remaining=" << db->Remaining(); - return payload_decoder_.ResumeDecodingPayload(mutable_state(), db); - } - - // Decode one frame's payload and confirm that the listener recorded the - // expected FrameParts instance, and only FrameParts instance. The payload - // will be decoded several times with different partitionings of the payload, - // and after each the validator will be called. - AssertionResult DecodePayloadAndValidateSeveralWays( - Http2StringPiece payload, - const FrameParts& expected) { - auto validator = [&expected, this]() -> AssertionResult { - VERIFY_FALSE(listener_.IsInProgress()); - VERIFY_EQ(1u, listener_.size()); - VERIFY_AND_RETURN_SUCCESS(expected.VerifyEquals(*listener_.frame(0))); - }; - return PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays( - payload, ValidateDoneAndEmpty(validator)); - } - - // Decode one frame's payload, expecting that the final status will be - // kDecodeError, and that OnFrameSizeError will have been called on the - // listener. The payload will be decoded several times with different - // partitionings of the payload. The type WrappedValidator is either - // RandomDecoderTest::Validator, RandomDecoderTest::NoArgValidator or - // std::nullptr_t (not extra validation). - template <typename WrappedValidator> - ::testing::AssertionResult VerifyDetectsFrameSizeError( - Http2StringPiece payload, - const Http2FrameHeader& header, - WrappedValidator wrapped_validator) { - set_frame_header(header); - // If wrapped_validator is not a RandomDecoderTest::Validator, make it so. - Validator validator = ToValidator(wrapped_validator); - // And wrap that validator in another which will check that we've reached - // the expected state of kDecodeError with OnFrameSizeError having been - // called by the payload decoder. - validator = [header, validator, this]( - const DecodeBuffer& input, - DecodeStatus status) -> ::testing::AssertionResult { - DVLOG(2) << "VerifyDetectsFrameSizeError validator; status=" << status - << "; input.Remaining=" << input.Remaining(); - VERIFY_EQ(DecodeStatus::kDecodeError, status); - VERIFY_FALSE(listener_.IsInProgress()); - VERIFY_EQ(1u, listener_.size()); - const FrameParts* frame = listener_.frame(0); - VERIFY_EQ(header, frame->GetFrameHeader()); - VERIFY_TRUE(frame->GetHasFrameSizeError()); - // Verify did not get OnPaddingTooLong, as we should only ever produce - // one of these two errors for a single frame. - VERIFY_FALSE(frame->GetOptMissingLength()); - return validator(input, status); - }; - VERIFY_AND_RETURN_SUCCESS( - PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(payload, - validator)); - } - - // Confirm that we get OnFrameSizeError when trying to decode unpadded_payload - // at all sizes from zero to unpadded_payload.size(), except those sizes not - // approved by approve_size. - // If total_pad_length is greater than zero, then that amount of padding - // is added to the payload (including the Pad Length field). - // The flags will be required_flags, PADDED if total_pad_length > 0, and some - // randomly selected flag bits not excluded by FlagsAffectingPayloadDecoding. - ::testing::AssertionResult VerifyDetectsMultipleFrameSizeErrors( - uint8_t required_flags, - Http2StringPiece unpadded_payload, - ApproveSize approve_size, - int total_pad_length) { - // required_flags should come from those that are defined for the frame - // type AND are those that affect the decoding of the payload (otherwise, - // the flag shouldn't be required). - Http2FrameType frame_type = DecoderPeer::FrameType(); - VERIFY_EQ(required_flags, - required_flags & KnownFlagsMaskForFrameType(frame_type)); - VERIFY_EQ(required_flags, - required_flags & DecoderPeer::FlagsAffectingPayloadDecoding()); - - if (0 != - (Http2FrameFlag::PADDED & KnownFlagsMaskForFrameType(frame_type))) { - // Frame type supports padding. - if (total_pad_length == 0) { - required_flags &= ~Http2FrameFlag::PADDED; - } else { - required_flags |= Http2FrameFlag::PADDED; - } - } else { - VERIFY_EQ(0, total_pad_length); - } - - bool validated = false; - for (size_t real_payload_size = 0; - real_payload_size <= unpadded_payload.size(); ++real_payload_size) { - if (approve_size != nullptr && !approve_size(real_payload_size)) { - continue; - } - VLOG(1) << "real_payload_size=" << real_payload_size; - uint8_t flags = required_flags | RandFlags(); - Http2FrameBuilder fb; - if (total_pad_length > 0) { - // total_pad_length_ includes the size of the Pad Length field, and thus - // ranges from 0 (no PADDED flag) to 256 (Pad Length == 255). - fb.AppendUInt8(total_pad_length - 1); - } - // Append a subset of the unpadded_payload, which the decoder should - // determine is not a valid amount. - fb.Append(unpadded_payload.substr(0, real_payload_size)); - if (total_pad_length > 0) { - fb.AppendZeroes(total_pad_length - 1); - } - // We choose a random stream id because the payload decoders aren't - // checking stream ids. - uint32_t stream_id = RandStreamId(); - Http2FrameHeader header(fb.size(), frame_type, flags, stream_id); - VERIFY_SUCCESS(VerifyDetectsFrameSizeError(fb.buffer(), header, nullptr)); - validated = true; - } - VERIFY_TRUE(validated); - return ::testing::AssertionSuccess(); - } - - // As above, but for frames without padding. - ::testing::AssertionResult VerifyDetectsFrameSizeError( - uint8_t required_flags, - Http2StringPiece unpadded_payload, - const ApproveSize& approve_size) { - Http2FrameType frame_type = DecoderPeer::FrameType(); - uint8_t known_flags = KnownFlagsMaskForFrameType(frame_type); - VERIFY_EQ(0, known_flags & Http2FrameFlag::PADDED); - VERIFY_EQ(0, required_flags & Http2FrameFlag::PADDED); - VERIFY_AND_RETURN_SUCCESS(VerifyDetectsMultipleFrameSizeErrors( - required_flags, unpadded_payload, approve_size, 0)); - } - - Listener listener_; - union { - // Confirm at compile time that Decoder can be in an anonymous union, - // i.e. complain loudly if Decoder has members that prevent this, as it - // becomes annoying and possibly difficult to deal with non-anonymous - // unions and such union members. - Decoder payload_decoder_; - }; -}; - -// A base class for tests parameterized by the total number of bytes of -// padding, including the Pad Length field (i.e. a total_pad_length of 0 -// means unpadded as there is then no room for the Pad Length field). -// The frame type must support padding. -template <class Decoder, class DecoderPeer, class Listener> -class AbstractPaddablePayloadDecoderTest - : public AbstractPayloadDecoderTest<Decoder, DecoderPeer, Listener>, - public ::testing::WithParamInterface<int> { - typedef AbstractPayloadDecoderTest<Decoder, DecoderPeer, Listener> Base; - - protected: - using Base::listener_; - using Base::Random; - using Base::RandStreamId; - using Base::set_frame_header; - typedef typename Base::Validator Validator; - - AbstractPaddablePayloadDecoderTest() : total_pad_length_(GetParam()) { - LOG(INFO) << "total_pad_length_ = " << total_pad_length_; - } - - // Note that total_pad_length_ includes the size of the Pad Length field, - // and thus ranges from 0 (no PADDED flag) to 256 (Pad Length == 255). - bool IsPadded() const { return total_pad_length_ > 0; } - - // Value of the Pad Length field. Only call if IsPadded. - size_t pad_length() const { - EXPECT_TRUE(IsPadded()); - return total_pad_length_ - 1; - } - - // Clear the frame builder and add the Pad Length field if appropriate. - void Reset() { - frame_builder_ = Http2FrameBuilder(); - if (IsPadded()) { - frame_builder_.AppendUInt8(pad_length()); - } - } - - void MaybeAppendTrailingPadding() { - if (IsPadded()) { - frame_builder_.AppendZeroes(pad_length()); - } - } - - uint8_t RandFlags() { - uint8_t flags = Base::RandFlags(); - if (IsPadded()) { - flags |= Http2FrameFlag::PADDED; - } else { - flags &= ~Http2FrameFlag::PADDED; - } - return flags; - } - - // Verify that we get OnPaddingTooLong when decoding payload, and that the - // amount of missing padding is as specified. header.IsPadded must be true, - // and the payload must be empty or the PadLength field must be too large. - ::testing::AssertionResult VerifyDetectsPaddingTooLong( - Http2StringPiece payload, - const Http2FrameHeader& header, - size_t expected_missing_length) { - set_frame_header(header); - auto& listener = listener_; - Validator validator = - [header, expected_missing_length, &listener]( - const DecodeBuffer& input, - DecodeStatus status) -> ::testing::AssertionResult { - VERIFY_EQ(DecodeStatus::kDecodeError, status); - VERIFY_FALSE(listener.IsInProgress()); - VERIFY_EQ(1u, listener.size()); - const FrameParts* frame = listener.frame(0); - VERIFY_EQ(header, frame->GetFrameHeader()); - VERIFY_TRUE(frame->GetOptMissingLength()); - VERIFY_EQ(expected_missing_length, frame->GetOptMissingLength().value()); - // Verify did not get OnFrameSizeError. - VERIFY_FALSE(frame->GetHasFrameSizeError()); - return ::testing::AssertionSuccess(); - }; - VERIFY_AND_RETURN_SUCCESS( - PayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(payload, - validator)); - } - - // Verifies that we get OnPaddingTooLong for a padded frame payload whose - // (randomly selected) payload length is less than total_pad_length_. - // Flags will be selected at random, except PADDED will be set and - // flags_to_avoid will not be set. The stream id is selected at random. - ::testing::AssertionResult VerifyDetectsPaddingTooLong() { - uint8_t flags = RandFlags() | Http2FrameFlag::PADDED; - - // Create an all padding payload for total_pad_length_. - int payload_length = 0; - Http2FrameBuilder fb; - if (IsPadded()) { - fb.AppendUInt8(pad_length()); - fb.AppendZeroes(pad_length()); - VLOG(1) << "fb.size=" << fb.size(); - // Pick a random length for the payload that is shorter than neccesary. - payload_length = Random().Uniform(fb.size()); - } - - VLOG(1) << "payload_length=" << payload_length; - Http2String payload = fb.buffer().substr(0, payload_length); - - // The missing length is the amount we cut off the end, unless - // payload_length is zero, in which case the decoder knows only that 1 - // byte, the Pad Length field, is missing. - size_t missing_length = - payload_length == 0 ? 1 : fb.size() - payload_length; - VLOG(1) << "missing_length=" << missing_length; - - const Http2FrameHeader header(payload_length, DecoderPeer::FrameType(), - flags, RandStreamId()); - VERIFY_AND_RETURN_SUCCESS( - VerifyDetectsPaddingTooLong(payload, header, missing_length)); - } - - // total_pad_length_ includes the size of the Pad Length field, and thus - // ranges from 0 (no PADDED flag) to 256 (Pad Length == 255). - const size_t total_pad_length_; - Http2FrameBuilder frame_builder_; -}; - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_PAYLOAD_DECODER_BASE_TEST_UTIL_H_
diff --git a/net/third_party/http2/decoder/payload_decoders/ping_payload_decoder.cc b/net/third_party/http2/decoder/payload_decoders/ping_payload_decoder.cc deleted file mode 100644 index b3c1883..0000000 --- a/net/third_party/http2/decoder/payload_decoders/ping_payload_decoder.cc +++ /dev/null
@@ -1,89 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/ping_payload_decoder.h" - -#include "base/logging.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" - -namespace http2 { -namespace { -constexpr auto kOpaqueSize = Http2PingFields::EncodedSize(); -} - -DecodeStatus PingPayloadDecoder::StartDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - const uint32_t total_length = frame_header.payload_length; - - DVLOG(2) << "PingPayloadDecoder::StartDecodingPayload: " << frame_header; - DCHECK_EQ(Http2FrameType::PING, frame_header.type); - DCHECK_LE(db->Remaining(), total_length); - DCHECK_EQ(0, frame_header.flags & ~(Http2FrameFlag::ACK)); - - // Is the payload entirely in the decode buffer and is it the correct size? - // Given the size of the header and payload (17 bytes total), this is most - // likely the case the vast majority of the time. - if (db->Remaining() == kOpaqueSize && total_length == kOpaqueSize) { - // Special case this situation as it allows us to avoid any copying; - // the other path makes two copies, first into the buffer in - // Http2StructureDecoder as it accumulates the 8 bytes of opaque data, - // and a second copy into the Http2PingFields member of in this class. - // This supports the claim that this decoder is (mostly) non-buffering. - static_assert(sizeof(Http2PingFields) == kOpaqueSize, - "If not, then can't enter this block!"); - auto* ping = reinterpret_cast<const Http2PingFields*>(db->cursor()); - if (frame_header.IsAck()) { - state->listener()->OnPingAck(frame_header, *ping); - } else { - state->listener()->OnPing(frame_header, *ping); - } - db->AdvanceCursor(kOpaqueSize); - return DecodeStatus::kDecodeDone; - } - state->InitializeRemainders(); - return HandleStatus( - state, state->StartDecodingStructureInPayload(&ping_fields_, db)); -} - -DecodeStatus PingPayloadDecoder::ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "ResumeDecodingPayload: remaining_payload=" - << state->remaining_payload(); - DCHECK_EQ(Http2FrameType::PING, state->frame_header().type); - DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - return HandleStatus( - state, state->ResumeDecodingStructureInPayload(&ping_fields_, db)); -} - -DecodeStatus PingPayloadDecoder::HandleStatus(FrameDecoderState* state, - DecodeStatus status) { - DVLOG(2) << "HandleStatus: status=" << status - << "; remaining_payload=" << state->remaining_payload(); - if (status == DecodeStatus::kDecodeDone) { - if (state->remaining_payload() == 0) { - const Http2FrameHeader& frame_header = state->frame_header(); - if (frame_header.IsAck()) { - state->listener()->OnPingAck(frame_header, ping_fields_); - } else { - state->listener()->OnPing(frame_header, ping_fields_); - } - return DecodeStatus::kDecodeDone; - } - // Payload is too long. - return state->ReportFrameSizeError(); - } - // Not done decoding the structure. Either we've got more payload to decode, - // or we've run out because the payload is too short. - DCHECK( - (status == DecodeStatus::kDecodeInProgress && - state->remaining_payload() > 0) || - (status == DecodeStatus::kDecodeError && state->remaining_payload() == 0)) - << "\n status=" << status - << "; remaining_payload=" << state->remaining_payload(); - return status; -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/ping_payload_decoder.h b/net/third_party/http2/decoder/payload_decoders/ping_payload_decoder.h deleted file mode 100644 index 6cb661a9..0000000 --- a/net/third_party/http2/decoder/payload_decoders/ping_payload_decoder.h +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_PING_PAYLOAD_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_PING_PAYLOAD_DECODER_H_ - -// Decodes the payload of a PING frame; for the RFC, see: -// http://httpwg.org/specs/rfc7540.html#PING - -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/decoder/frame_decoder_state.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { -namespace test { -class PingPayloadDecoderPeer; -} // namespace test - -class HTTP2_EXPORT_PRIVATE PingPayloadDecoder { - public: - // Starts the decoding of a PING frame's payload, and completes it if the - // entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a PING frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::PingPayloadDecoderPeer; - - DecodeStatus HandleStatus(FrameDecoderState* state, DecodeStatus status); - - Http2PingFields ping_fields_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_PING_PAYLOAD_DECODER_H_
diff --git a/net/third_party/http2/decoder/payload_decoders/ping_payload_decoder_test.cc b/net/third_party/http2/decoder/payload_decoders/ping_payload_decoder_test.cc deleted file mode 100644 index 16e3e65..0000000 --- a/net/third_party/http2/decoder/payload_decoders/ping_payload_decoder_test.cc +++ /dev/null
@@ -1,110 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/ping_payload_decoder.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures_test_util.h" -#include "net/third_party/http2/test_tools/frame_parts.h" -#include "net/third_party/http2/test_tools/frame_parts_collector.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/http2_frame_builder.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -class PingPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { return Http2FrameType::PING; } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) override { - VLOG(1) << "OnPing: " << header << "; " << ping; - StartAndEndFrame(header)->OnPing(header, ping); - } - - void OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) override { - VLOG(1) << "OnPingAck: " << header << "; " << ping; - StartAndEndFrame(header)->OnPingAck(header, ping); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class PingPayloadDecoderTest - : public AbstractPayloadDecoderTest<PingPayloadDecoder, - PingPayloadDecoderPeer, - Listener> { - protected: - Http2PingFields RandPingFields() { - Http2PingFields fields; - test::Randomize(&fields, RandomPtr()); - return fields; - } -}; - -// Confirm we get an error if the payload is not the correct size to hold -// exactly one Http2PingFields. -TEST_F(PingPayloadDecoderTest, WrongSize) { - auto approve_size = [](size_t size) { - return size != Http2PingFields::EncodedSize(); - }; - Http2FrameBuilder fb; - fb.Append(RandPingFields()); - fb.Append(RandPingFields()); - fb.Append(RandPingFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); -} - -TEST_F(PingPayloadDecoderTest, Ping) { - for (int n = 0; n < 100; ++n) { - Http2PingFields fields = RandPingFields(); - Http2FrameBuilder fb; - fb.Append(fields); - Http2FrameHeader header(fb.size(), Http2FrameType::PING, - RandFlags() & ~Http2FrameFlag::ACK, RandStreamId()); - set_frame_header(header); - FrameParts expected(header); - expected.SetOptPing(fields); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); - } -} - -TEST_F(PingPayloadDecoderTest, PingAck) { - for (int n = 0; n < 100; ++n) { - Http2PingFields fields; - Randomize(&fields, RandomPtr()); - Http2FrameBuilder fb; - fb.Append(fields); - Http2FrameHeader header(fb.size(), Http2FrameType::PING, - RandFlags() | Http2FrameFlag::ACK, RandStreamId()); - set_frame_header(header); - FrameParts expected(header); - expected.SetOptPing(fields); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); - } -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/priority_payload_decoder.cc b/net/third_party/http2/decoder/payload_decoders/priority_payload_decoder.cc deleted file mode 100644 index dd503bb..0000000 --- a/net/third_party/http2/decoder/payload_decoders/priority_payload_decoder.cc +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/priority_payload_decoder.h" - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" - -namespace http2 { - -DecodeStatus PriorityPayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "PriorityPayloadDecoder::StartDecodingPayload: " - << state->frame_header(); - DCHECK_EQ(Http2FrameType::PRIORITY, state->frame_header().type); - DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - // PRIORITY frames have no flags. - DCHECK_EQ(0, state->frame_header().flags); - state->InitializeRemainders(); - return HandleStatus( - state, state->StartDecodingStructureInPayload(&priority_fields_, db)); -} - -DecodeStatus PriorityPayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "PriorityPayloadDecoder::ResumeDecodingPayload" - << " remaining_payload=" << state->remaining_payload() - << " db->Remaining=" << db->Remaining(); - DCHECK_EQ(Http2FrameType::PRIORITY, state->frame_header().type); - DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - return HandleStatus( - state, state->ResumeDecodingStructureInPayload(&priority_fields_, db)); -} - -DecodeStatus PriorityPayloadDecoder::HandleStatus(FrameDecoderState* state, - DecodeStatus status) { - if (status == DecodeStatus::kDecodeDone) { - if (state->remaining_payload() == 0) { - state->listener()->OnPriorityFrame(state->frame_header(), - priority_fields_); - return DecodeStatus::kDecodeDone; - } - // Payload is too long. - return state->ReportFrameSizeError(); - } - // Not done decoding the structure. Either we've got more payload to decode, - // or we've run out because the payload is too short, in which case - // OnFrameSizeError will have already been called. - DCHECK( - (status == DecodeStatus::kDecodeInProgress && - state->remaining_payload() > 0) || - (status == DecodeStatus::kDecodeError && state->remaining_payload() == 0)) - << "\n status=" << status - << "; remaining_payload=" << state->remaining_payload(); - return status; -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/priority_payload_decoder.h b/net/third_party/http2/decoder/payload_decoders/priority_payload_decoder.h deleted file mode 100644 index d258475..0000000 --- a/net/third_party/http2/decoder/payload_decoders/priority_payload_decoder.h +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_PRIORITY_PAYLOAD_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_PRIORITY_PAYLOAD_DECODER_H_ - -// Decodes the payload of a PRIORITY frame. - -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/decoder/frame_decoder_state.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { -namespace test { -class PriorityPayloadDecoderPeer; -} // namespace test - -class HTTP2_EXPORT_PRIVATE PriorityPayloadDecoder { - public: - // Starts the decoding of a PRIORITY frame's payload, and completes it if - // the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a PRIORITY frame that has been split across decode - // buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::PriorityPayloadDecoderPeer; - - // Determines whether to report the PRIORITY to the listener, wait for more - // input, or to report a Frame Size Error. - DecodeStatus HandleStatus(FrameDecoderState* state, DecodeStatus status); - - Http2PriorityFields priority_fields_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_PRIORITY_PAYLOAD_DECODER_H_
diff --git a/net/third_party/http2/decoder/payload_decoders/priority_payload_decoder_test.cc b/net/third_party/http2/decoder/payload_decoders/priority_payload_decoder_test.cc deleted file mode 100644 index 3ef328474..0000000 --- a/net/third_party/http2/decoder/payload_decoders/priority_payload_decoder_test.cc +++ /dev/null
@@ -1,90 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/priority_payload_decoder.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures_test_util.h" -#include "net/third_party/http2/test_tools/frame_parts.h" -#include "net/third_party/http2/test_tools/frame_parts_collector.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/http2_frame_builder.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -class PriorityPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { - return Http2FrameType::PRIORITY; - } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnPriorityFrame(const Http2FrameHeader& header, - const Http2PriorityFields& priority_fields) override { - VLOG(1) << "OnPriority: " << header << "; " << priority_fields; - StartAndEndFrame(header)->OnPriorityFrame(header, priority_fields); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class PriorityPayloadDecoderTest - : public AbstractPayloadDecoderTest<PriorityPayloadDecoder, - PriorityPayloadDecoderPeer, - Listener> { - protected: - Http2PriorityFields RandPriorityFields() { - Http2PriorityFields fields; - test::Randomize(&fields, RandomPtr()); - return fields; - } -}; - -// Confirm we get an error if the payload is not the correct size to hold -// exactly one Http2PriorityFields. -TEST_F(PriorityPayloadDecoderTest, WrongSize) { - auto approve_size = [](size_t size) { - return size != Http2PriorityFields::EncodedSize(); - }; - Http2FrameBuilder fb; - fb.Append(RandPriorityFields()); - fb.Append(RandPriorityFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); -} - -TEST_F(PriorityPayloadDecoderTest, VariousPayloads) { - for (int n = 0; n < 100; ++n) { - Http2PriorityFields fields = RandPriorityFields(); - Http2FrameBuilder fb; - fb.Append(fields); - Http2FrameHeader header(fb.size(), Http2FrameType::PRIORITY, RandFlags(), - RandStreamId()); - set_frame_header(header); - FrameParts expected(header); - expected.SetOptPriority(fields); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); - } -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/push_promise_payload_decoder.cc b/net/third_party/http2/decoder/payload_decoders/push_promise_payload_decoder.cc deleted file mode 100644 index 03687a5..0000000 --- a/net/third_party/http2/decoder/payload_decoders/push_promise_payload_decoder.cc +++ /dev/null
@@ -1,172 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/push_promise_payload_decoder.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "base/macros.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_bug_tracker.h" -#include "net/third_party/http2/platform/api/http2_macros.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, - PushPromisePayloadDecoder::PayloadState v) { - switch (v) { - case PushPromisePayloadDecoder::PayloadState::kReadPadLength: - return out << "kReadPadLength"; - case PushPromisePayloadDecoder::PayloadState:: - kStartDecodingPushPromiseFields: - return out << "kStartDecodingPushPromiseFields"; - case PushPromisePayloadDecoder::PayloadState::kReadPayload: - return out << "kReadPayload"; - case PushPromisePayloadDecoder::PayloadState::kSkipPadding: - return out << "kSkipPadding"; - case PushPromisePayloadDecoder::PayloadState:: - kResumeDecodingPushPromiseFields: - return out << "kResumeDecodingPushPromiseFields"; - } - return out << static_cast<int>(v); -} - -DecodeStatus PushPromisePayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - const uint32_t total_length = frame_header.payload_length; - - DVLOG(2) << "PushPromisePayloadDecoder::StartDecodingPayload: " - << frame_header; - - DCHECK_EQ(Http2FrameType::PUSH_PROMISE, frame_header.type); - DCHECK_LE(db->Remaining(), total_length); - DCHECK_EQ(0, frame_header.flags & - ~(Http2FrameFlag::END_HEADERS | Http2FrameFlag::PADDED)); - - if (!frame_header.IsPadded()) { - // If it turns out that PUSH_PROMISE frames without padding are sufficiently - // common, and that they are usually short enough that they fit entirely - // into one DecodeBuffer, we can detect that here and implement a special - // case, avoiding the state machine in ResumeDecodingPayload. - payload_state_ = PayloadState::kStartDecodingPushPromiseFields; - } else { - payload_state_ = PayloadState::kReadPadLength; - } - state->InitializeRemainders(); - return ResumeDecodingPayload(state, db); -} - -DecodeStatus PushPromisePayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "UnknownPayloadDecoder::ResumeDecodingPayload" - << " remaining_payload=" << state->remaining_payload() - << " db->Remaining=" << db->Remaining(); - - const Http2FrameHeader& frame_header = state->frame_header(); - DCHECK_EQ(Http2FrameType::PUSH_PROMISE, frame_header.type); - DCHECK_LE(state->remaining_payload(), frame_header.payload_length); - DCHECK_LE(db->Remaining(), frame_header.payload_length); - - DecodeStatus status; - while (true) { - DVLOG(2) - << "PushPromisePayloadDecoder::ResumeDecodingPayload payload_state_=" - << payload_state_; - switch (payload_state_) { - case PayloadState::kReadPadLength: - DCHECK_EQ(state->remaining_payload(), frame_header.payload_length); - // ReadPadLength handles the OnPadLength callback, and updating the - // remaining_payload and remaining_padding fields. If the amount of - // padding is too large to fit in the frame's payload, ReadPadLength - // instead calls OnPaddingTooLong and returns kDecodeError. - // Suppress the call to OnPadLength because we haven't yet called - // OnPushPromiseStart, which needs to wait until we've decoded the - // Promised Stream ID. - status = state->ReadPadLength(db, /*report_pad_length*/ false); - if (status != DecodeStatus::kDecodeDone) { - payload_state_ = PayloadState::kReadPadLength; - return status; - } - HTTP2_FALLTHROUGH; - - case PayloadState::kStartDecodingPushPromiseFields: - status = - state->StartDecodingStructureInPayload(&push_promise_fields_, db); - if (status != DecodeStatus::kDecodeDone) { - payload_state_ = PayloadState::kResumeDecodingPushPromiseFields; - return status; - } - // Finished decoding the Promised Stream ID. Can now tell the listener - // that we're starting to decode a PUSH_PROMISE frame. - ReportPushPromise(state); - HTTP2_FALLTHROUGH; - - case PayloadState::kReadPayload: - DCHECK_LT(state->remaining_payload(), frame_header.payload_length); - DCHECK_LE(state->remaining_payload(), - frame_header.payload_length - - Http2PushPromiseFields::EncodedSize()); - DCHECK_LE( - state->remaining_payload(), - frame_header.payload_length - - Http2PushPromiseFields::EncodedSize() - - (frame_header.IsPadded() ? (1 + state->remaining_padding()) - : 0)); - { - size_t avail = state->AvailablePayload(db); - state->listener()->OnHpackFragment(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - } - if (state->remaining_payload() > 0) { - payload_state_ = PayloadState::kReadPayload; - return DecodeStatus::kDecodeInProgress; - } - HTTP2_FALLTHROUGH; - - case PayloadState::kSkipPadding: - // SkipPadding handles the OnPadding callback. - if (state->SkipPadding(db)) { - state->listener()->OnPushPromiseEnd(); - return DecodeStatus::kDecodeDone; - } - payload_state_ = PayloadState::kSkipPadding; - return DecodeStatus::kDecodeInProgress; - - case PayloadState::kResumeDecodingPushPromiseFields: - status = - state->ResumeDecodingStructureInPayload(&push_promise_fields_, db); - if (status == DecodeStatus::kDecodeDone) { - // Finished decoding the Promised Stream ID. Can now tell the listener - // that we're starting to decode a PUSH_PROMISE frame. - ReportPushPromise(state); - payload_state_ = PayloadState::kReadPayload; - continue; - } - payload_state_ = PayloadState::kResumeDecodingPushPromiseFields; - return status; - } - HTTP2_BUG << "PayloadState: " << payload_state_; - } -} - -void PushPromisePayloadDecoder::ReportPushPromise(FrameDecoderState* state) { - const Http2FrameHeader& frame_header = state->frame_header(); - if (frame_header.IsPadded()) { - state->listener()->OnPushPromiseStart(frame_header, push_promise_fields_, - 1 + state->remaining_padding()); - } else { - state->listener()->OnPushPromiseStart(frame_header, push_promise_fields_, - 0); - } -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/push_promise_payload_decoder.h b/net/third_party/http2/decoder/payload_decoders/push_promise_payload_decoder.h deleted file mode 100644 index 1861805..0000000 --- a/net/third_party/http2/decoder/payload_decoders/push_promise_payload_decoder.h +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_PUSH_PROMISE_PAYLOAD_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_PUSH_PROMISE_PAYLOAD_DECODER_H_ - -// Decodes the payload of a PUSH_PROMISE frame. - -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/decoder/frame_decoder_state.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { -namespace test { -class PushPromisePayloadDecoderPeer; -} // namespace test - -class HTTP2_EXPORT_PRIVATE PushPromisePayloadDecoder { - public: - // States during decoding of a PUSH_PROMISE frame. - enum class PayloadState { - // The frame is padded and we need to read the PAD_LENGTH field (1 byte). - kReadPadLength, - - // Ready to start decoding the fixed size fields of the PUSH_PROMISE - // frame into push_promise_fields_. - kStartDecodingPushPromiseFields, - - // The decoder has already called OnPushPromiseStart, and is now reporting - // the HPACK block fragment to the listener's OnHpackFragment method. - kReadPayload, - - // The decoder has finished with the HPACK block fragment, and is now - // ready to skip the trailing padding, if the frame has any. - kSkipPadding, - - // The fixed size fields weren't all available when the decoder first tried - // to decode them (state kStartDecodingPushPromiseFields); this state - // resumes the decoding when ResumeDecodingPayload is called later. - kResumeDecodingPushPromiseFields, - }; - - // Starts the decoding of a PUSH_PROMISE frame's payload, and completes it if - // the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a PUSH_PROMISE frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::PushPromisePayloadDecoderPeer; - - void ReportPushPromise(FrameDecoderState* state); - - PayloadState payload_state_; - Http2PushPromiseFields push_promise_fields_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_PUSH_PROMISE_PAYLOAD_DECODER_H_
diff --git a/net/third_party/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc b/net/third_party/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc deleted file mode 100644 index 1e9887d..0000000 --- a/net/third_party/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc +++ /dev/null
@@ -1,137 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/push_promise_payload_decoder.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures_test_util.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/test_tools/frame_parts.h" -#include "net/third_party/http2/test_tools/frame_parts_collector.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/http2_frame_builder.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -// Provides friend access to an instance of the payload decoder, and also -// provides info to aid in testing. -class PushPromisePayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { - return Http2FrameType::PUSH_PROMISE; - } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { - return Http2FrameFlag::PADDED; - } -}; - -namespace { - -// Listener listens for only those methods expected by the payload decoder -// under test, and forwards them onto the FrameParts instance for the current -// frame. -struct Listener : public FramePartsCollector { - void OnPushPromiseStart(const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) override { - VLOG(1) << "OnPushPromiseStart header: " << header - << " promise: " << promise - << " total_padding_length: " << total_padding_length; - EXPECT_EQ(Http2FrameType::PUSH_PROMISE, header.type); - StartFrame(header)->OnPushPromiseStart(header, promise, - total_padding_length); - } - - void OnHpackFragment(const char* data, size_t len) override { - VLOG(1) << "OnHpackFragment: len=" << len; - CurrentFrame()->OnHpackFragment(data, len); - } - - void OnPushPromiseEnd() override { - VLOG(1) << "OnPushPromiseEnd"; - EndFrame()->OnPushPromiseEnd(); - } - - void OnPadding(const char* padding, size_t skipped_length) override { - VLOG(1) << "OnPadding: " << skipped_length; - CurrentFrame()->OnPadding(padding, skipped_length); - } - - void OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) override { - VLOG(1) << "OnPaddingTooLong: " << header - << "; missing_length: " << missing_length; - FrameError(header)->OnPaddingTooLong(header, missing_length); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class PushPromisePayloadDecoderTest - : public AbstractPaddablePayloadDecoderTest<PushPromisePayloadDecoder, - PushPromisePayloadDecoderPeer, - Listener> {}; - -INSTANTIATE_TEST_CASE_P(VariousPadLengths, - PushPromisePayloadDecoderTest, - ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256)); - -// Payload contains the required Http2PushPromiseFields, followed by some -// (fake) HPACK payload. -TEST_P(PushPromisePayloadDecoderTest, VariousHpackPayloadSizes) { - for (size_t hpack_size : {0, 1, 2, 3, 255, 256, 1024}) { - LOG(INFO) << "########### hpack_size = " << hpack_size << " ###########"; - Reset(); - Http2String hpack_payload = Random().RandString(hpack_size); - Http2PushPromiseFields push_promise{RandStreamId()}; - frame_builder_.Append(push_promise); - frame_builder_.Append(hpack_payload); - MaybeAppendTrailingPadding(); - Http2FrameHeader frame_header(frame_builder_.size(), - Http2FrameType::PUSH_PROMISE, RandFlags(), - RandStreamId()); - set_frame_header(frame_header); - FrameParts expected(frame_header, hpack_payload, total_pad_length_); - expected.SetOptPushPromise(push_promise); - EXPECT_TRUE( - DecodePayloadAndValidateSeveralWays(frame_builder_.buffer(), expected)); - } -} - -// Confirm we get an error if the payload is not long enough for the required -// portion of the payload, regardless of the amount of (valid) padding. -TEST_P(PushPromisePayloadDecoderTest, Truncated) { - auto approve_size = [](size_t size) { - return size != Http2PushPromiseFields::EncodedSize(); - }; - Http2PushPromiseFields push_promise{RandStreamId()}; - Http2FrameBuilder fb; - fb.Append(push_promise); - EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors(0, fb.buffer(), approve_size, - total_pad_length_)); -} - -// Confirm we get an error if the PADDED flag is set but the payload is not -// long enough to hold even the Pad Length amount of padding. -TEST_P(PushPromisePayloadDecoderTest, PaddingTooLong) { - EXPECT_TRUE(VerifyDetectsPaddingTooLong()); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/rst_stream_payload_decoder.cc b/net/third_party/http2/decoder/payload_decoders/rst_stream_payload_decoder.cc deleted file mode 100644 index a2000e5a..0000000 --- a/net/third_party/http2/decoder/payload_decoders/rst_stream_payload_decoder.cc +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/rst_stream_payload_decoder.h" - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" - -namespace http2 { - -DecodeStatus RstStreamPayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "RstStreamPayloadDecoder::StartDecodingPayload: " - << state->frame_header(); - DCHECK_EQ(Http2FrameType::RST_STREAM, state->frame_header().type); - DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - // RST_STREAM has no flags. - DCHECK_EQ(0, state->frame_header().flags); - state->InitializeRemainders(); - return HandleStatus( - state, state->StartDecodingStructureInPayload(&rst_stream_fields_, db)); -} - -DecodeStatus RstStreamPayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "RstStreamPayloadDecoder::ResumeDecodingPayload" - << " remaining_payload=" << state->remaining_payload() - << " db->Remaining=" << db->Remaining(); - DCHECK_EQ(Http2FrameType::RST_STREAM, state->frame_header().type); - DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - return HandleStatus( - state, state->ResumeDecodingStructureInPayload(&rst_stream_fields_, db)); -} - -DecodeStatus RstStreamPayloadDecoder::HandleStatus(FrameDecoderState* state, - DecodeStatus status) { - DVLOG(2) << "HandleStatus: status=" << status - << "; remaining_payload=" << state->remaining_payload(); - if (status == DecodeStatus::kDecodeDone) { - if (state->remaining_payload() == 0) { - state->listener()->OnRstStream(state->frame_header(), - rst_stream_fields_.error_code); - return DecodeStatus::kDecodeDone; - } - // Payload is too long. - return state->ReportFrameSizeError(); - } - // Not done decoding the structure. Either we've got more payload to decode, - // or we've run out because the payload is too short, in which case - // OnFrameSizeError will have already been called by the FrameDecoderState. - DCHECK( - (status == DecodeStatus::kDecodeInProgress && - state->remaining_payload() > 0) || - (status == DecodeStatus::kDecodeError && state->remaining_payload() == 0)) - << "\n status=" << status - << "; remaining_payload=" << state->remaining_payload(); - return status; -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/rst_stream_payload_decoder.h b/net/third_party/http2/decoder/payload_decoders/rst_stream_payload_decoder.h deleted file mode 100644 index c92da53..0000000 --- a/net/third_party/http2/decoder/payload_decoders/rst_stream_payload_decoder.h +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_RST_STREAM_PAYLOAD_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_RST_STREAM_PAYLOAD_DECODER_H_ - -// Decodes the payload of a RST_STREAM frame. - -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/decoder/frame_decoder_state.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { -namespace test { -class RstStreamPayloadDecoderPeer; -} // namespace test - -class HTTP2_EXPORT_PRIVATE RstStreamPayloadDecoder { - public: - // Starts the decoding of a RST_STREAM frame's payload, and completes it if - // the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a RST_STREAM frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::RstStreamPayloadDecoderPeer; - - DecodeStatus HandleStatus(FrameDecoderState* state, DecodeStatus status); - - Http2RstStreamFields rst_stream_fields_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_RST_STREAM_PAYLOAD_DECODER_H_
diff --git a/net/third_party/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc b/net/third_party/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc deleted file mode 100644 index 47389f4..0000000 --- a/net/third_party/http2/decoder/payload_decoders/rst_stream_payload_decoder_test.cc +++ /dev/null
@@ -1,92 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/rst_stream_payload_decoder.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_constants_test_util.h" -#include "net/third_party/http2/http2_structures_test_util.h" -#include "net/third_party/http2/test_tools/frame_parts.h" -#include "net/third_party/http2/test_tools/frame_parts_collector.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/http2_frame_builder.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -class RstStreamPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { - return Http2FrameType::RST_STREAM; - } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnRstStream(const Http2FrameHeader& header, - Http2ErrorCode error_code) override { - VLOG(1) << "OnRstStream: " << header << "; error_code=" << error_code; - StartAndEndFrame(header)->OnRstStream(header, error_code); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class RstStreamPayloadDecoderTest - : public AbstractPayloadDecoderTest<RstStreamPayloadDecoder, - RstStreamPayloadDecoderPeer, - Listener> { - protected: - Http2RstStreamFields RandRstStreamFields() { - Http2RstStreamFields fields; - test::Randomize(&fields, RandomPtr()); - return fields; - } -}; - -// Confirm we get an error if the payload is not the correct size to hold -// exactly one Http2RstStreamFields. -TEST_F(RstStreamPayloadDecoderTest, WrongSize) { - auto approve_size = [](size_t size) { - return size != Http2RstStreamFields::EncodedSize(); - }; - Http2FrameBuilder fb; - fb.Append(RandRstStreamFields()); - fb.Append(RandRstStreamFields()); - fb.Append(RandRstStreamFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); -} - -TEST_F(RstStreamPayloadDecoderTest, AllErrors) { - for (auto error_code : AllHttp2ErrorCodes()) { - Http2RstStreamFields fields{error_code}; - Http2FrameBuilder fb; - fb.Append(fields); - Http2FrameHeader header(fb.size(), Http2FrameType::RST_STREAM, RandFlags(), - RandStreamId()); - set_frame_header(header); - FrameParts expected(header); - expected.SetOptRstStreamErrorCode(error_code); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); - } -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/settings_payload_decoder.cc b/net/third_party/http2/decoder/payload_decoders/settings_payload_decoder.cc deleted file mode 100644 index 2981a26..0000000 --- a/net/third_party/http2/decoder/payload_decoders/settings_payload_decoder.cc +++ /dev/null
@@ -1,97 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/settings_payload_decoder.h" - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" - -namespace http2 { - -DecodeStatus SettingsPayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - const uint32_t total_length = frame_header.payload_length; - - DVLOG(2) << "SettingsPayloadDecoder::StartDecodingPayload: " << frame_header; - DCHECK_EQ(Http2FrameType::SETTINGS, frame_header.type); - DCHECK_LE(db->Remaining(), total_length); - DCHECK_EQ(0, frame_header.flags & ~(Http2FrameFlag::ACK)); - - if (frame_header.IsAck()) { - if (total_length == 0) { - state->listener()->OnSettingsAck(frame_header); - return DecodeStatus::kDecodeDone; - } else { - state->InitializeRemainders(); - return state->ReportFrameSizeError(); - } - } else { - state->InitializeRemainders(); - state->listener()->OnSettingsStart(frame_header); - return StartDecodingSettings(state, db); - } -} - -DecodeStatus SettingsPayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "SettingsPayloadDecoder::ResumeDecodingPayload" - << " remaining_payload=" << state->remaining_payload() - << " db->Remaining=" << db->Remaining(); - DCHECK_EQ(Http2FrameType::SETTINGS, state->frame_header().type); - DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - - DecodeStatus status = - state->ResumeDecodingStructureInPayload(&setting_fields_, db); - if (status == DecodeStatus::kDecodeDone) { - state->listener()->OnSetting(setting_fields_); - return StartDecodingSettings(state, db); - } - return HandleNotDone(state, db, status); -} - -DecodeStatus SettingsPayloadDecoder::StartDecodingSettings( - FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "SettingsPayloadDecoder::StartDecodingSettings" - << " remaining_payload=" << state->remaining_payload() - << " db->Remaining=" << db->Remaining(); - while (state->remaining_payload() > 0) { - DecodeStatus status = - state->StartDecodingStructureInPayload(&setting_fields_, db); - if (status == DecodeStatus::kDecodeDone) { - state->listener()->OnSetting(setting_fields_); - continue; - } - return HandleNotDone(state, db, status); - } - DVLOG(2) << "LEAVING SettingsPayloadDecoder::StartDecodingSettings" - << "\n\tdb->Remaining=" << db->Remaining() - << "\n\t remaining_payload=" << state->remaining_payload(); - state->listener()->OnSettingsEnd(); - return DecodeStatus::kDecodeDone; -} - -DecodeStatus SettingsPayloadDecoder::HandleNotDone(FrameDecoderState* state, - DecodeBuffer* db, - DecodeStatus status) { - // Not done decoding the structure. Either we've got more payload to decode, - // or we've run out because the payload is too short, in which case - // OnFrameSizeError will have already been called. - DCHECK( - (status == DecodeStatus::kDecodeInProgress && - state->remaining_payload() > 0) || - (status == DecodeStatus::kDecodeError && state->remaining_payload() == 0)) - << "\n status=" << status - << "; remaining_payload=" << state->remaining_payload() - << "; db->Remaining=" << db->Remaining(); - return status; -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/settings_payload_decoder.h b/net/third_party/http2/decoder/payload_decoders/settings_payload_decoder.h deleted file mode 100644 index 3f58a5e..0000000 --- a/net/third_party/http2/decoder/payload_decoders/settings_payload_decoder.h +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_SETTINGS_PAYLOAD_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_SETTINGS_PAYLOAD_DECODER_H_ - -// Decodes the payload of a SETTINGS frame; for the RFC, see: -// http://httpwg.org/specs/rfc7540.html#SETTINGS - -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/decoder/frame_decoder_state.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { -namespace test { -class SettingsPayloadDecoderPeer; -} // namespace test - -class HTTP2_EXPORT_PRIVATE SettingsPayloadDecoder { - public: - // Starts the decoding of a SETTINGS frame's payload, and completes it if - // the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a SETTINGS frame that has been split across decode - // buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::SettingsPayloadDecoderPeer; - - // Decodes as many settings as are available in the decode buffer, starting at - // the first byte of one setting; if a single setting is split across buffers, - // ResumeDecodingPayload will handle starting from where the previous call - // left off, and then will call StartDecodingSettings. - DecodeStatus StartDecodingSettings(FrameDecoderState* state, - DecodeBuffer* db); - - // Decoding a single SETTING returned a status other than kDecodeDone; this - // method just brings together the DCHECKs to reduce duplication. - DecodeStatus HandleNotDone(FrameDecoderState* state, - DecodeBuffer* db, - DecodeStatus status); - - Http2SettingFields setting_fields_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_SETTINGS_PAYLOAD_DECODER_H_
diff --git a/net/third_party/http2/decoder/payload_decoders/settings_payload_decoder_test.cc b/net/third_party/http2/decoder/payload_decoders/settings_payload_decoder_test.cc deleted file mode 100644 index 96aa42a..0000000 --- a/net/third_party/http2/decoder/payload_decoders/settings_payload_decoder_test.cc +++ /dev/null
@@ -1,160 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/settings_payload_decoder.h" - -#include <stddef.h> - -#include <vector> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_constants_test_util.h" -#include "net/third_party/http2/http2_structures_test_util.h" -#include "net/third_party/http2/test_tools/frame_parts.h" -#include "net/third_party/http2/test_tools/frame_parts_collector.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/http2_frame_builder.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -class SettingsPayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { - return Http2FrameType::SETTINGS; - } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { - return Http2FrameFlag::ACK; - } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnSettingsStart(const Http2FrameHeader& header) override { - VLOG(1) << "OnSettingsStart: " << header; - EXPECT_EQ(Http2FrameType::SETTINGS, header.type) << header; - EXPECT_EQ(Http2FrameFlag(), header.flags) << header; - StartFrame(header)->OnSettingsStart(header); - } - - void OnSetting(const Http2SettingFields& setting_fields) override { - VLOG(1) << "Http2SettingFields: setting_fields=" << setting_fields; - CurrentFrame()->OnSetting(setting_fields); - } - - void OnSettingsEnd() override { - VLOG(1) << "OnSettingsEnd"; - EndFrame()->OnSettingsEnd(); - } - - void OnSettingsAck(const Http2FrameHeader& header) override { - VLOG(1) << "OnSettingsAck: " << header; - StartAndEndFrame(header)->OnSettingsAck(header); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class SettingsPayloadDecoderTest - : public AbstractPayloadDecoderTest<SettingsPayloadDecoder, - SettingsPayloadDecoderPeer, - Listener> { - protected: - Http2SettingFields RandSettingsFields() { - Http2SettingFields fields; - test::Randomize(&fields, RandomPtr()); - return fields; - } -}; - -// Confirm we get an error if the SETTINGS payload is not the correct size -// to hold exactly zero or more whole Http2SettingFields. -TEST_F(SettingsPayloadDecoderTest, SettingsWrongSize) { - auto approve_size = [](size_t size) { - // Should get an error if size is not an integral multiple of the size - // of one setting. - return 0 != (size % Http2SettingFields::EncodedSize()); - }; - Http2FrameBuilder fb; - fb.Append(RandSettingsFields()); - fb.Append(RandSettingsFields()); - fb.Append(RandSettingsFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); -} - -// Confirm we get an error if the SETTINGS ACK payload is not empty. -TEST_F(SettingsPayloadDecoderTest, SettingsAkcWrongSize) { - auto approve_size = [](size_t size) { return size != 0; }; - Http2FrameBuilder fb; - fb.Append(RandSettingsFields()); - fb.Append(RandSettingsFields()); - fb.Append(RandSettingsFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError(Http2FrameFlag::ACK, fb.buffer(), - approve_size)); -} - -// SETTINGS must have stream_id==0, but the payload decoder doesn't check that. -TEST_F(SettingsPayloadDecoderTest, SettingsAck) { - for (int stream_id = 0; stream_id < 3; ++stream_id) { - Http2FrameHeader header(0, Http2FrameType::SETTINGS, - RandFlags() | Http2FrameFlag::ACK, stream_id); - set_frame_header(header); - FrameParts expected(header); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays("", expected)); - } -} - -// Try several values of each known SETTINGS parameter. -TEST_F(SettingsPayloadDecoderTest, OneRealSetting) { - std::vector<uint32_t> values = {0, 1, 0xffffffff, Random().Rand32()}; - for (auto param : AllHttp2SettingsParameters()) { - for (uint32_t value : values) { - Http2SettingFields fields(param, value); - Http2FrameBuilder fb; - fb.Append(fields); - Http2FrameHeader header(fb.size(), Http2FrameType::SETTINGS, RandFlags(), - RandStreamId()); - set_frame_header(header); - FrameParts expected(header); - expected.AppendSetting(fields); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); - } - } -} - -// Decode a SETTINGS frame with lots of fields. -TEST_F(SettingsPayloadDecoderTest, ManySettings) { - const size_t num_settings = 100; - const size_t size = Http2SettingFields::EncodedSize() * num_settings; - Http2FrameHeader header(size, Http2FrameType::SETTINGS, - RandFlags(), // & ~Http2FrameFlag::ACK, - RandStreamId()); - set_frame_header(header); - FrameParts expected(header); - Http2FrameBuilder fb; - for (size_t n = 0; n < num_settings; ++n) { - Http2SettingFields fields(static_cast<Http2SettingsParameter>(n), - Random().Rand32()); - fb.Append(fields); - expected.AppendSetting(fields); - } - ASSERT_EQ(size, fb.size()); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/unknown_payload_decoder.cc b/net/third_party/http2/decoder/payload_decoders/unknown_payload_decoder.cc deleted file mode 100644 index 3f7cbf4..0000000 --- a/net/third_party/http2/decoder/payload_decoders/unknown_payload_decoder.cc +++ /dev/null
@@ -1,55 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/unknown_payload_decoder.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" - -namespace http2 { - -DecodeStatus UnknownPayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - - DVLOG(2) << "UnknownPayloadDecoder::StartDecodingPayload: " << frame_header; - DCHECK(!IsSupportedHttp2FrameType(frame_header.type)) << frame_header; - DCHECK_LE(db->Remaining(), frame_header.payload_length); - - state->InitializeRemainders(); - state->listener()->OnUnknownStart(frame_header); - return ResumeDecodingPayload(state, db); -} - -DecodeStatus UnknownPayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "UnknownPayloadDecoder::ResumeDecodingPayload " - << "remaining_payload=" << state->remaining_payload() - << "; db->Remaining=" << db->Remaining(); - DCHECK(!IsSupportedHttp2FrameType(state->frame_header().type)) - << state->frame_header(); - DCHECK_LE(state->remaining_payload(), state->frame_header().payload_length); - DCHECK_LE(db->Remaining(), state->remaining_payload()); - - size_t avail = db->Remaining(); - if (avail > 0) { - state->listener()->OnUnknownPayload(db->cursor(), avail); - db->AdvanceCursor(avail); - state->ConsumePayload(avail); - } - if (state->remaining_payload() == 0) { - state->listener()->OnUnknownEnd(); - return DecodeStatus::kDecodeDone; - } - return DecodeStatus::kDecodeInProgress; -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/unknown_payload_decoder.h b/net/third_party/http2/decoder/payload_decoders/unknown_payload_decoder.h deleted file mode 100644 index c649f7b8..0000000 --- a/net/third_party/http2/decoder/payload_decoders/unknown_payload_decoder.h +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_UNKNOWN_PAYLOAD_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_UNKNOWN_PAYLOAD_DECODER_H_ - -// Decodes the payload of a frame whose type unknown. According to the HTTP/2 -// specification (http://httpwg.org/specs/rfc7540.html#FrameHeader): -// Implementations MUST ignore and discard any frame that has -// a type that is unknown. - -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/decoder/frame_decoder_state.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { - -class HTTP2_EXPORT_PRIVATE UnknownPayloadDecoder { - public: - // Starts decoding a payload of unknown type; just passes it to the listener. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a payload of unknown type that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_UNKNOWN_PAYLOAD_DECODER_H_
diff --git a/net/third_party/http2/decoder/payload_decoders/unknown_payload_decoder_test.cc b/net/third_party/http2/decoder/payload_decoders/unknown_payload_decoder_test.cc deleted file mode 100644 index f4467e39..0000000 --- a/net/third_party/http2/decoder/payload_decoders/unknown_payload_decoder_test.cc +++ /dev/null
@@ -1,100 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/unknown_payload_decoder.h" - -#include <stddef.h> - -#include <type_traits> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/test_tools/frame_parts.h" -#include "net/third_party/http2/test_tools/frame_parts_collector.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { -namespace { -Http2FrameType g_unknown_frame_type; -} // namespace - -// Provides friend access to an instance of the payload decoder, and also -// provides info to aid in testing. -class UnknownPayloadDecoderPeer { - public: - static Http2FrameType FrameType() { return g_unknown_frame_type; } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnUnknownStart(const Http2FrameHeader& header) override { - VLOG(1) << "OnUnknownStart: " << header; - StartFrame(header)->OnUnknownStart(header); - } - - void OnUnknownPayload(const char* data, size_t len) override { - VLOG(1) << "OnUnknownPayload: len=" << len; - CurrentFrame()->OnUnknownPayload(data, len); - } - - void OnUnknownEnd() override { - VLOG(1) << "OnUnknownEnd"; - EndFrame()->OnUnknownEnd(); - } -}; - -constexpr bool SupportedFrameType = false; - -class UnknownPayloadDecoderTest - : public AbstractPayloadDecoderTest<UnknownPayloadDecoder, - UnknownPayloadDecoderPeer, - Listener, - SupportedFrameType>, - public ::testing::WithParamInterface<uint32_t> { - protected: - UnknownPayloadDecoderTest() : length_(GetParam()) { - VLOG(1) << "################ length_=" << length_ << " ################"; - - // Each test case will choose a random frame type that isn't supported. - do { - g_unknown_frame_type = static_cast<Http2FrameType>(Random().Rand8()); - } while (IsSupportedHttp2FrameType(g_unknown_frame_type)); - } - - const uint32_t length_; -}; - -INSTANTIATE_TEST_CASE_P(VariousLengths, - UnknownPayloadDecoderTest, - ::testing::Values(0, 1, 2, 3, 255, 256)); - -TEST_P(UnknownPayloadDecoderTest, ValidLength) { - Http2String unknown_payload = Random().RandString(length_); - Http2FrameHeader frame_header(length_, g_unknown_frame_type, Random().Rand8(), - RandStreamId()); - set_frame_header(frame_header); - FrameParts expected(frame_header, unknown_payload); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(unknown_payload, expected)); - // TODO(jamessynge): Check here (and in other such tests) that the fast - // and slow decode counts are both non-zero. Perhaps also add some kind of - // test for the listener having been called. That could simply be a test - // that there is a single collected FrameParts instance, and that it matches - // expected. -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/window_update_payload_decoder.cc b/net/third_party/http2/decoder/payload_decoders/window_update_payload_decoder.cc deleted file mode 100644 index 97b1cdf..0000000 --- a/net/third_party/http2/decoder/payload_decoders/window_update_payload_decoder.cc +++ /dev/null
@@ -1,82 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/window_update_payload_decoder.h" - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_http2_structures.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" - -namespace http2 { - -DecodeStatus WindowUpdatePayloadDecoder::StartDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - const Http2FrameHeader& frame_header = state->frame_header(); - const uint32_t total_length = frame_header.payload_length; - - DVLOG(2) << "WindowUpdatePayloadDecoder::StartDecodingPayload: " - << frame_header; - - DCHECK_EQ(Http2FrameType::WINDOW_UPDATE, frame_header.type); - DCHECK_LE(db->Remaining(), total_length); - - // WINDOW_UPDATE frames have no flags. - DCHECK_EQ(0, frame_header.flags); - - // Special case for when the payload is the correct size and entirely in - // the buffer. - if (db->Remaining() == Http2WindowUpdateFields::EncodedSize() && - total_length == Http2WindowUpdateFields::EncodedSize()) { - DoDecode(&window_update_fields_, db); - state->listener()->OnWindowUpdate( - frame_header, window_update_fields_.window_size_increment); - return DecodeStatus::kDecodeDone; - } - state->InitializeRemainders(); - return HandleStatus(state, state->StartDecodingStructureInPayload( - &window_update_fields_, db)); -} - -DecodeStatus WindowUpdatePayloadDecoder::ResumeDecodingPayload( - FrameDecoderState* state, - DecodeBuffer* db) { - DVLOG(2) << "ResumeDecodingPayload: remaining_payload=" - << state->remaining_payload() - << "; db->Remaining=" << db->Remaining(); - DCHECK_EQ(Http2FrameType::WINDOW_UPDATE, state->frame_header().type); - DCHECK_LE(db->Remaining(), state->frame_header().payload_length); - return HandleStatus(state, state->ResumeDecodingStructureInPayload( - &window_update_fields_, db)); -} - -DecodeStatus WindowUpdatePayloadDecoder::HandleStatus(FrameDecoderState* state, - DecodeStatus status) { - DVLOG(2) << "HandleStatus: status=" << status - << "; remaining_payload=" << state->remaining_payload(); - if (status == DecodeStatus::kDecodeDone) { - if (state->remaining_payload() == 0) { - state->listener()->OnWindowUpdate( - state->frame_header(), window_update_fields_.window_size_increment); - return DecodeStatus::kDecodeDone; - } - // Payload is too long. - return state->ReportFrameSizeError(); - } - // Not done decoding the structure. Either we've got more payload to decode, - // or we've run out because the payload is too short, in which case - // OnFrameSizeError will have already been called. - DCHECK( - (status == DecodeStatus::kDecodeInProgress && - state->remaining_payload() > 0) || - (status == DecodeStatus::kDecodeError && state->remaining_payload() == 0)) - << "\n status=" << status - << "; remaining_payload=" << state->remaining_payload(); - return status; -} - -} // namespace http2
diff --git a/net/third_party/http2/decoder/payload_decoders/window_update_payload_decoder.h b/net/third_party/http2/decoder/payload_decoders/window_update_payload_decoder.h deleted file mode 100644 index 0344b25d..0000000 --- a/net/third_party/http2/decoder/payload_decoders/window_update_payload_decoder.h +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_WINDOW_UPDATE_PAYLOAD_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_WINDOW_UPDATE_PAYLOAD_DECODER_H_ - -// Decodes the payload of a WINDOW_UPDATE frame. - -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/decoder/frame_decoder_state.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { -namespace test { -class WindowUpdatePayloadDecoderPeer; -} // namespace test - -class HTTP2_EXPORT_PRIVATE WindowUpdatePayloadDecoder { - public: - // Starts decoding a WINDOW_UPDATE frame's payload, and completes it if - // the entire payload is in the provided decode buffer. - DecodeStatus StartDecodingPayload(FrameDecoderState* state, DecodeBuffer* db); - - // Resumes decoding a WINDOW_UPDATE frame's payload that has been split across - // decode buffers. - DecodeStatus ResumeDecodingPayload(FrameDecoderState* state, - DecodeBuffer* db); - - private: - friend class test::WindowUpdatePayloadDecoderPeer; - - DecodeStatus HandleStatus(FrameDecoderState* state, DecodeStatus status); - - Http2WindowUpdateFields window_update_fields_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_DECODER_PAYLOAD_DECODERS_WINDOW_UPDATE_PAYLOAD_DECODER_H_
diff --git a/net/third_party/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc b/net/third_party/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc deleted file mode 100644 index 784a970..0000000 --- a/net/third_party/http2/decoder/payload_decoders/window_update_payload_decoder_test.cc +++ /dev/null
@@ -1,95 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/decoder/payload_decoders/window_update_payload_decoder.h" - -#include <stddef.h> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/decoder/payload_decoders/payload_decoder_base_test_util.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures_test_util.h" -#include "net/third_party/http2/test_tools/frame_parts.h" -#include "net/third_party/http2/test_tools/frame_parts_collector.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/http2_frame_builder.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -class WindowUpdatePayloadDecoderPeer { - public: - static constexpr Http2FrameType FrameType() { - return Http2FrameType::WINDOW_UPDATE; - } - - // Returns the mask of flags that affect the decoding of the payload (i.e. - // flags that that indicate the presence of certain fields or padding). - static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; } -}; - -namespace { - -struct Listener : public FramePartsCollector { - void OnWindowUpdate(const Http2FrameHeader& header, - uint32_t window_size_increment) override { - VLOG(1) << "OnWindowUpdate: " << header - << "; window_size_increment=" << window_size_increment; - EXPECT_EQ(Http2FrameType::WINDOW_UPDATE, header.type); - StartAndEndFrame(header)->OnWindowUpdate(header, window_size_increment); - } - - void OnFrameSizeError(const Http2FrameHeader& header) override { - VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); - } -}; - -class WindowUpdatePayloadDecoderTest - : public AbstractPayloadDecoderTest<WindowUpdatePayloadDecoder, - WindowUpdatePayloadDecoderPeer, - Listener> { - protected: - Http2WindowUpdateFields RandWindowUpdateFields() { - Http2WindowUpdateFields fields; - test::Randomize(&fields, RandomPtr()); - VLOG(3) << "RandWindowUpdateFields: " << fields; - return fields; - } -}; - -// Confirm we get an error if the payload is not the correct size to hold -// exactly one Http2WindowUpdateFields. -TEST_F(WindowUpdatePayloadDecoderTest, WrongSize) { - auto approve_size = [](size_t size) { - return size != Http2WindowUpdateFields::EncodedSize(); - }; - Http2FrameBuilder fb; - fb.Append(RandWindowUpdateFields()); - fb.Append(RandWindowUpdateFields()); - fb.Append(RandWindowUpdateFields()); - EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size)); -} - -TEST_F(WindowUpdatePayloadDecoderTest, VariousPayloads) { - for (int n = 0; n < 100; ++n) { - uint32_t stream_id = n == 0 ? 0 : RandStreamId(); - Http2WindowUpdateFields fields = RandWindowUpdateFields(); - Http2FrameBuilder fb; - fb.Append(fields); - Http2FrameHeader header(fb.size(), Http2FrameType::WINDOW_UPDATE, - RandFlags(), stream_id); - set_frame_header(header); - FrameParts expected(header); - expected.SetOptWindowUpdateIncrement(fields.window_size_increment); - EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected)); - } -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/README.md b/net/third_party/http2/hpack/decoder/README.md deleted file mode 100644 index 7799084..0000000 --- a/net/third_party/http2/hpack/decoder/README.md +++ /dev/null
@@ -1,50 +0,0 @@ -Copyright 2017 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. - -## gfe/http2/hpack/decoder - -These are the most popular C++ files defined in this directory. - -* [hpack_entry_decoder_listener.h] - (http://google3/gfe/http2/hpack/decoder/hpack_entry_decoder_listener.h) (1 - imports): Defines HpackEntryDecoderListener, the base class of listeners - that HpackEntryDecoder calls. -* [hpack_decoder_string_buffer.h] - (http://google3/gfe/http2/hpack/decoder/hpack_decoder_string_buffer.h) (1 - imports): HpackDecoderStringBuffer helps an HPACK decoder to avoid copies of - a string literal (name or value) except when necessary (e.g. -* [hpack_block_decoder.h] - (http://google3/gfe/http2/hpack/decoder/hpack_block_decoder.h) (1 imports): - HpackBlockDecoder decodes an entire HPACK block (or the available portion - thereof in the DecodeBuffer) into entries, but doesn't include HPACK static - or dynamic table support, so table indices remain indices at this level. -* [hpack_varint_decoder.h] - (http://google3/gfe/http2/hpack/decoder/hpack_varint_decoder.h) (zero - imports): HpackVarintDecoder decodes HPACK variable length unsigned - integers. -* [hpack_entry_collector.h] - (http://google3/gfe/http2/hpack/decoder/hpack_entry_collector.h) (zero - imports): HpackEntryCollector records calls to HpackEntryDecoderListener in - support of tests of HpackEntryDecoder, or which use it. -* [hpack_string_collector.h] - (http://google3/gfe/http2/hpack/decoder/hpack_string_collector.h) (zero - imports): Supports tests of decoding HPACK strings. -* [hpack_string_decoder.h] - (http://google3/gfe/http2/hpack/decoder/hpack_string_decoder.h) (zero - imports): HpackStringDecoder decodes strings encoded per the HPACK spec; - this does not mean decompressing Huffman encoded strings, just identifying - the length, encoding and contents for a listener. -* [hpack_block_collector.h] - (http://google3/gfe/http2/hpack/decoder/hpack_block_collector.h) (zero - imports): HpackBlockCollector implements HpackEntryDecoderListener in order - to record the calls using HpackEntryCollector instances (one per HPACK - entry). -* [hpack_entry_decoder.h] - (http://google3/gfe/http2/hpack/decoder/hpack_entry_decoder.h) (zero - imports): HpackEntryDecoder decodes a single HPACK entry (i.e. -* [hpack_entry_type_decoder.h] - (http://google3/gfe/http2/hpack/decoder/hpack_entry_type_decoder.h) (zero - imports): Decodes the type of an HPACK entry, and the variable length - integer whose prefix is in the low-order bits of the same byte, "below" the - type bits.
diff --git a/net/third_party/http2/hpack/decoder/hpack_block_collector.cc b/net/third_party/http2/hpack/decoder/hpack_block_collector.cc deleted file mode 100644 index 693b5816..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_block_collector.cc +++ /dev/null
@@ -1,151 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_block_collector.h" - -#include <algorithm> -#include <memory> - -#include "base/logging.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" - -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; - -namespace http2 { -namespace test { - -HpackBlockCollector::HpackBlockCollector() = default; -HpackBlockCollector::HpackBlockCollector(const HpackBlockCollector& other) - : pending_entry_(other.pending_entry_), entries_(other.entries_) {} -HpackBlockCollector::~HpackBlockCollector() = default; - -void HpackBlockCollector::OnIndexedHeader(size_t index) { - pending_entry_.OnIndexedHeader(index); - PushPendingEntry(); -} -void HpackBlockCollector::OnDynamicTableSizeUpdate(size_t size) { - pending_entry_.OnDynamicTableSizeUpdate(size); - PushPendingEntry(); -} -void HpackBlockCollector::OnStartLiteralHeader(HpackEntryType header_type, - size_t maybe_name_index) { - pending_entry_.OnStartLiteralHeader(header_type, maybe_name_index); -} -void HpackBlockCollector::OnNameStart(bool huffman_encoded, size_t len) { - pending_entry_.OnNameStart(huffman_encoded, len); -} -void HpackBlockCollector::OnNameData(const char* data, size_t len) { - pending_entry_.OnNameData(data, len); -} -void HpackBlockCollector::OnNameEnd() { - pending_entry_.OnNameEnd(); -} -void HpackBlockCollector::OnValueStart(bool huffman_encoded, size_t len) { - pending_entry_.OnValueStart(huffman_encoded, len); -} -void HpackBlockCollector::OnValueData(const char* data, size_t len) { - pending_entry_.OnValueData(data, len); -} -void HpackBlockCollector::OnValueEnd() { - pending_entry_.OnValueEnd(); - PushPendingEntry(); -} - -void HpackBlockCollector::PushPendingEntry() { - EXPECT_TRUE(pending_entry_.IsComplete()); - DVLOG(2) << "PushPendingEntry: " << pending_entry_; - entries_.push_back(pending_entry_); - EXPECT_TRUE(entries_.back().IsComplete()); - pending_entry_.Clear(); -} -void HpackBlockCollector::Clear() { - pending_entry_.Clear(); - entries_.clear(); -} - -void HpackBlockCollector::ExpectIndexedHeader(size_t index) { - entries_.push_back( - HpackEntryCollector(HpackEntryType::kIndexedHeader, index)); -} -void HpackBlockCollector::ExpectDynamicTableSizeUpdate(size_t size) { - entries_.push_back( - HpackEntryCollector(HpackEntryType::kDynamicTableSizeUpdate, size)); -} -void HpackBlockCollector::ExpectNameIndexAndLiteralValue( - HpackEntryType type, - size_t index, - bool value_huffman, - const Http2String& value) { - entries_.push_back(HpackEntryCollector(type, index, value_huffman, value)); -} -void HpackBlockCollector::ExpectLiteralNameAndValue(HpackEntryType type, - bool name_huffman, - const Http2String& name, - bool value_huffman, - const Http2String& value) { - entries_.push_back( - HpackEntryCollector(type, name_huffman, name, value_huffman, value)); -} - -void HpackBlockCollector::ShuffleEntries(Http2Random* rng) { - std::shuffle(entries_.begin(), entries_.end(), *rng); -} - -void HpackBlockCollector::AppendToHpackBlockBuilder( - HpackBlockBuilder* hbb) const { - CHECK(IsNotPending()); - for (const auto& entry : entries_) { - entry.AppendToHpackBlockBuilder(hbb); - } -} - -AssertionResult HpackBlockCollector::ValidateSoleIndexedHeader( - size_t ndx) const { - VERIFY_TRUE(pending_entry_.IsClear()); - VERIFY_EQ(1u, entries_.size()); - VERIFY_TRUE(entries_.front().ValidateIndexedHeader(ndx)); - return AssertionSuccess(); -} -AssertionResult HpackBlockCollector::ValidateSoleLiteralValueHeader( - HpackEntryType expected_type, - size_t expected_index, - bool expected_value_huffman, - Http2StringPiece expected_value) const { - VERIFY_TRUE(pending_entry_.IsClear()); - VERIFY_EQ(1u, entries_.size()); - VERIFY_TRUE(entries_.front().ValidateLiteralValueHeader( - expected_type, expected_index, expected_value_huffman, expected_value)); - return AssertionSuccess(); -} -AssertionResult HpackBlockCollector::ValidateSoleLiteralNameValueHeader( - HpackEntryType expected_type, - bool expected_name_huffman, - Http2StringPiece expected_name, - bool expected_value_huffman, - Http2StringPiece expected_value) const { - VERIFY_TRUE(pending_entry_.IsClear()); - VERIFY_EQ(1u, entries_.size()); - VERIFY_TRUE(entries_.front().ValidateLiteralNameValueHeader( - expected_type, expected_name_huffman, expected_name, - expected_value_huffman, expected_value)); - return AssertionSuccess(); -} -AssertionResult HpackBlockCollector::ValidateSoleDynamicTableSizeUpdate( - size_t size) const { - VERIFY_TRUE(pending_entry_.IsClear()); - VERIFY_EQ(1u, entries_.size()); - VERIFY_TRUE(entries_.front().ValidateDynamicTableSizeUpdate(size)); - return AssertionSuccess(); -} - -AssertionResult HpackBlockCollector::VerifyEq( - const HpackBlockCollector& that) const { - VERIFY_EQ(pending_entry_, that.pending_entry_); - VERIFY_EQ(entries_, that.entries_); - return AssertionSuccess(); -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_block_collector.h b/net/third_party/http2/hpack/decoder/hpack_block_collector.h deleted file mode 100644 index 03414ce..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_block_collector.h +++ /dev/null
@@ -1,129 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_BLOCK_COLLECTOR_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_BLOCK_COLLECTOR_H_ - -// HpackBlockCollector implements HpackEntryDecoderListener in order to record -// the calls using HpackEntryCollector instances (one per HPACK entry). This -// supports testing of HpackBlockDecoder, which decodes entire HPACK blocks. -// -// In addition to implementing the callback methods, HpackBlockCollector also -// supports comparing two HpackBlockCollector instances (i.e. an expected and -// an actual), or a sole HPACK entry against an expected value. - -#include <stddef.h> - -#include <vector> - -#include "net/third_party/http2/hpack/decoder/hpack_entry_collector.h" -#include "net/third_party/http2/hpack/decoder/hpack_entry_decoder_listener.h" -#include "net/third_party/http2/hpack/http2_hpack_constants.h" -#include "net/third_party/http2/hpack/tools/hpack_block_builder.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -class HpackBlockCollector : public HpackEntryDecoderListener { - public: - HpackBlockCollector(); - HpackBlockCollector(const HpackBlockCollector& other); - ~HpackBlockCollector() override; - - // Implementations of HpackEntryDecoderListener, forwarding to pending_entry_, - // an HpackEntryCollector for the "in-progress" HPACK entry. OnIndexedHeader - // and OnDynamicTableSizeUpdate are pending only for that one call, while - // OnStartLiteralHeader is followed by many calls, ending with OnValueEnd. - // Once all the calls for one HPACK entry have been received, PushPendingEntry - // is used to append the pending_entry_ entry to the collected entries_. - void OnIndexedHeader(size_t index) override; - void OnDynamicTableSizeUpdate(size_t size) override; - void OnStartLiteralHeader(HpackEntryType header_type, - size_t maybe_name_index) override; - void OnNameStart(bool huffman_encoded, size_t len) override; - void OnNameData(const char* data, size_t len) override; - void OnNameEnd() override; - void OnValueStart(bool huffman_encoded, size_t len) override; - void OnValueData(const char* data, size_t len) override; - void OnValueEnd() override; - - // Methods for creating a set of expectations (i.e. HPACK entries to compare - // against those collected by another instance of HpackBlockCollector). - - // Add an HPACK entry for an indexed header. - void ExpectIndexedHeader(size_t index); - - // Add an HPACK entry for a dynamic table size update. - void ExpectDynamicTableSizeUpdate(size_t size); - - // Add an HPACK entry for a header entry with an index for the name, and a - // literal value. - void ExpectNameIndexAndLiteralValue(HpackEntryType type, - size_t index, - bool value_huffman, - const Http2String& value); - - // Add an HPACK entry for a header entry with a literal name and value. - void ExpectLiteralNameAndValue(HpackEntryType type, - bool name_huffman, - const Http2String& name, - bool value_huffman, - const Http2String& value); - - // Shuffle the entries, in support of generating an HPACK block of entries - // in some random order. - void ShuffleEntries(Http2Random* rng); - - // Serialize entries_ to the HpackBlockBuilder. - void AppendToHpackBlockBuilder(HpackBlockBuilder* hbb) const; - - // Return AssertionSuccess if there is just one entry, and it is an - // Indexed Header with the specified index. - ::testing::AssertionResult ValidateSoleIndexedHeader(size_t ndx) const; - - // Return AssertionSuccess if there is just one entry, and it is a - // Dynamic Table Size Update with the specified size. - ::testing::AssertionResult ValidateSoleDynamicTableSizeUpdate( - size_t size) const; - - // Return AssertionSuccess if there is just one entry, and it is a Header - // entry with an index for the name and a literal value. - ::testing::AssertionResult ValidateSoleLiteralValueHeader( - HpackEntryType expected_type, - size_t expected_index, - bool expected_value_huffman, - Http2StringPiece expected_value) const; - - // Return AssertionSuccess if there is just one entry, and it is a Header - // with a literal name and literal value. - ::testing::AssertionResult ValidateSoleLiteralNameValueHeader( - HpackEntryType expected_type, - bool expected_name_huffman, - Http2StringPiece expected_name, - bool expected_value_huffman, - Http2StringPiece expected_value) const; - - bool IsNotPending() const { return pending_entry_.IsClear(); } - bool IsClear() const { return IsNotPending() && entries_.empty(); } - void Clear(); - - ::testing::AssertionResult VerifyEq(const HpackBlockCollector& that) const; - - private: - // Push the value of pending_entry_ onto entries_, and clear pending_entry_. - // The pending_entry_ must be complete. - void PushPendingEntry(); - - HpackEntryCollector pending_entry_; - std::vector<HpackEntryCollector> entries_; -}; - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_BLOCK_COLLECTOR_H_
diff --git a/net/third_party/http2/hpack/decoder/hpack_block_decoder.cc b/net/third_party/http2/hpack/decoder/hpack_block_decoder.cc deleted file mode 100644 index 17ba557..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_block_decoder.cc +++ /dev/null
@@ -1,62 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_block_decoder.h" - -#include <cstdint> - -#include "base/logging.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" - -namespace http2 { - -DecodeStatus HpackBlockDecoder::Decode(DecodeBuffer* db) { - if (!before_entry_) { - DVLOG(2) << "HpackBlockDecoder::Decode resume entry, db->Remaining=" - << db->Remaining(); - DecodeStatus status = entry_decoder_.Resume(db, listener_); - switch (status) { - case DecodeStatus::kDecodeDone: - before_entry_ = true; - break; - case DecodeStatus::kDecodeInProgress: - DCHECK_EQ(0u, db->Remaining()); - return DecodeStatus::kDecodeInProgress; - case DecodeStatus::kDecodeError: - return DecodeStatus::kDecodeError; - } - } - DCHECK(before_entry_); - while (db->HasData()) { - DVLOG(2) << "HpackBlockDecoder::Decode start entry, db->Remaining=" - << db->Remaining(); - DecodeStatus status = entry_decoder_.Start(db, listener_); - switch (status) { - case DecodeStatus::kDecodeDone: - continue; - case DecodeStatus::kDecodeInProgress: - DCHECK_EQ(0u, db->Remaining()); - before_entry_ = false; - return DecodeStatus::kDecodeInProgress; - case DecodeStatus::kDecodeError: - return DecodeStatus::kDecodeError; - } - DCHECK(false); - } - DCHECK(before_entry_); - return DecodeStatus::kDecodeDone; -} - -Http2String HpackBlockDecoder::DebugString() const { - return Http2StrCat("HpackBlockDecoder(", entry_decoder_.DebugString(), - ", listener@", - Http2Hex(reinterpret_cast<intptr_t>(listener_)), - (before_entry_ ? ", between entries)" : ", in an entry)")); -} - -std::ostream& operator<<(std::ostream& out, const HpackBlockDecoder& v) { - return out << v.DebugString(); -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_block_decoder.h b/net/third_party/http2/hpack/decoder/hpack_block_decoder.h deleted file mode 100644 index 0889dc6..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_block_decoder.h +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_BLOCK_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_BLOCK_DECODER_H_ - -// HpackBlockDecoder decodes an entire HPACK block (or the available portion -// thereof in the DecodeBuffer) into entries, but doesn't include HPACK static -// or dynamic table support, so table indices remain indices at this level. -// Reports the entries to an HpackEntryDecoderListener. - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/hpack/decoder/hpack_entry_decoder.h" -#include "net/third_party/http2/hpack/decoder/hpack_entry_decoder_listener.h" -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string.h" - -namespace http2 { - -class HTTP2_EXPORT_PRIVATE HpackBlockDecoder { - public: - explicit HpackBlockDecoder(HpackEntryDecoderListener* listener) - : listener_(listener) { - DCHECK_NE(listener_, nullptr); - } - ~HpackBlockDecoder() {} - - HpackBlockDecoder(const HpackBlockDecoder&) = delete; - HpackBlockDecoder& operator=(const HpackBlockDecoder&) = delete; - - // Prepares the decoder to start decoding a new HPACK block. Expected - // to be called from an implementation of Http2FrameDecoderListener's - // OnHeadersStart or OnPushPromiseStart methods. - void Reset() { - DVLOG(2) << "HpackBlockDecoder::Reset"; - before_entry_ = true; - } - - // Decode the fragment of the HPACK block contained in the decode buffer. - // Expected to be called from an implementation of Http2FrameDecoderListener's - // OnHpackFragment method. - DecodeStatus Decode(DecodeBuffer* db); - - // Is the decoding process between entries (i.e. would the next byte be the - // first byte of a new HPACK entry)? - bool before_entry() const { return before_entry_; } - - Http2String DebugString() const; - - private: - HpackEntryDecoder entry_decoder_; - HpackEntryDecoderListener* const listener_; - bool before_entry_ = true; -}; - -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const HpackBlockDecoder& v); - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_BLOCK_DECODER_H_
diff --git a/net/third_party/http2/hpack/decoder/hpack_block_decoder_test.cc b/net/third_party/http2/hpack/decoder/hpack_block_decoder_test.cc deleted file mode 100644 index e9232ad..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_block_decoder_test.cc +++ /dev/null
@@ -1,294 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_block_decoder.h" - -// Tests of HpackBlockDecoder. - -#include <cstdint> - -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/hpack/decoder/hpack_block_collector.h" -#include "net/third_party/http2/hpack/http2_hpack_constants.h" -#include "net/third_party/http2/hpack/tools/hpack_block_builder.h" -#include "net/third_party/http2/hpack/tools/hpack_example.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionSuccess; - -namespace http2 { -namespace test { -namespace { - -class HpackBlockDecoderTest : public RandomDecoderTest { - protected: - HpackBlockDecoderTest() : listener_(&collector_), decoder_(&listener_) { - stop_decode_on_done_ = false; - decoder_.Reset(); - // Make sure logging doesn't crash. Not examining the result. - std::ostringstream strm; - strm << decoder_; - } - - DecodeStatus StartDecoding(DecodeBuffer* db) override { - collector_.Clear(); - decoder_.Reset(); - return ResumeDecoding(db); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* db) override { - DecodeStatus status = decoder_.Decode(db); - - // Make sure logging doesn't crash. Not examining the result. - std::ostringstream strm; - strm << decoder_; - - return status; - } - - AssertionResult DecodeAndValidateSeveralWays(DecodeBuffer* db, - const Validator& validator) { - bool return_non_zero_on_first = false; - return RandomDecoderTest::DecodeAndValidateSeveralWays( - db, return_non_zero_on_first, validator); - } - - AssertionResult DecodeAndValidateSeveralWays(const HpackBlockBuilder& hbb, - const Validator& validator) { - DecodeBuffer db(hbb.buffer()); - return DecodeAndValidateSeveralWays(&db, validator); - } - - AssertionResult DecodeHpackExampleAndValidateSeveralWays( - Http2StringPiece hpack_example, - Validator validator) { - Http2String input = HpackExampleToStringOrDie(hpack_example); - DecodeBuffer db(input); - return DecodeAndValidateSeveralWays(&db, validator); - } - - uint8_t Rand8() { return Random().Rand8(); } - - Http2String Rand8String() { return Random().RandString(Rand8()); } - - HpackBlockCollector collector_; - HpackEntryDecoderVLoggingListener listener_; - HpackBlockDecoder decoder_; -}; - -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.1 -TEST_F(HpackBlockDecoderTest, SpecExample_C_2_1) { - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader( - HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false, - "custom-header")); - }; - const char hpack_example[] = R"( - 40 | == Literal indexed == - 0a | Literal name (len = 10) - 6375 7374 6f6d 2d6b 6579 | custom-key - 0d | Literal value (len = 13) - 6375 7374 6f6d 2d68 6561 6465 72 | custom-header - | -> custom-key: - | custom-header - )"; - EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays( - hpack_example, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.2 -TEST_F(HpackBlockDecoderTest, SpecExample_C_2_2) { - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralValueHeader( - HpackEntryType::kUnindexedLiteralHeader, 4, false, "/sample/path")); - }; - const char hpack_example[] = R"( - 04 | == Literal not indexed == - | Indexed name (idx = 4) - | :path - 0c | Literal value (len = 12) - 2f73 616d 706c 652f 7061 7468 | /sample/path - | -> :path: /sample/path - )"; - EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays( - hpack_example, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.3 -TEST_F(HpackBlockDecoderTest, SpecExample_C_2_3) { - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleLiteralNameValueHeader( - HpackEntryType::kNeverIndexedLiteralHeader, false, "password", false, - "secret")); - }; - const char hpack_example[] = R"( - 10 | == Literal never indexed == - 08 | Literal name (len = 8) - 7061 7373 776f 7264 | password - 06 | Literal value (len = 6) - 7365 6372 6574 | secret - | -> password: secret - )"; - EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays( - hpack_example, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.2.4 -TEST_F(HpackBlockDecoderTest, SpecExample_C_2_4) { - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateSoleIndexedHeader(2)); - }; - const char hpack_example[] = R"( - 82 | == Indexed - Add == - | idx = 2 - | -> :method: GET - )"; - EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays( - hpack_example, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.3.1 -TEST_F(HpackBlockDecoderTest, SpecExample_C_3_1) { - Http2String example = R"( - 82 | == Indexed - Add == - | idx = 2 - | -> :method: GET - 86 | == Indexed - Add == - | idx = 6 - | -> :scheme: http - 84 | == Indexed - Add == - | idx = 4 - | -> :path: / - 41 | == Literal indexed == - | Indexed name (idx = 1) - | :authority - 0f | Literal value (len = 15) - 7777 772e 6578 616d 706c 652e 636f 6d | www.example.com - | -> :authority: - | www.example.com - )"; - HpackBlockCollector expected; - expected.ExpectIndexedHeader(2); - expected.ExpectIndexedHeader(6); - expected.ExpectIndexedHeader(4); - expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, - 1, false, "www.example.com"); - NoArgValidator do_check = [expected, this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected)); - }; - EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays( - example, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.5.1 -TEST_F(HpackBlockDecoderTest, SpecExample_C_5_1) { - Http2String example = R"( - 48 | == Literal indexed == - | Indexed name (idx = 8) - | :status - 03 | Literal value (len = 3) - 3330 32 | 302 - | -> :status: 302 - 58 | == Literal indexed == - | Indexed name (idx = 24) - | cache-control - 07 | Literal value (len = 7) - 7072 6976 6174 65 | private - | -> cache-control: private - 61 | == Literal indexed == - | Indexed name (idx = 33) - | date - 1d | Literal value (len = 29) - 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013 - 2032 303a 3133 3a32 3120 474d 54 | 20:13:21 GMT - | -> date: Mon, 21 Oct 2013 - | 20:13:21 GMT - 6e | == Literal indexed == - | Indexed name (idx = 46) - | location - 17 | Literal value (len = 23) - 6874 7470 733a 2f2f 7777 772e 6578 616d | https://www.exam - 706c 652e 636f 6d | ple.com - | -> location: - | https://www.example.com - )"; - HpackBlockCollector expected; - expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, - 8, false, "302"); - expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, - 24, false, "private"); - expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, - 33, false, - "Mon, 21 Oct 2013 20:13:21 GMT"); - expected.ExpectNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, - 46, false, "https://www.example.com"); - NoArgValidator do_check = [expected, this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected)); - }; - EXPECT_TRUE(DecodeHpackExampleAndValidateSeveralWays( - example, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -// Generate a bunch of HPACK block entries to expect, use those expectations -// to generate an HPACK block, then decode it and confirm it matches those -// expectations. Some of these are invalid (such as Indexed, with index=0), -// but well-formed, and the decoder doesn't check for validity, just -// well-formedness. That includes the validity of the strings not being checked, -// such as lower-case ascii for the names, and valid Huffman encodings. -TEST_F(HpackBlockDecoderTest, Computed) { - HpackBlockCollector expected; - expected.ExpectIndexedHeader(0); - expected.ExpectIndexedHeader(1); - expected.ExpectIndexedHeader(126); - expected.ExpectIndexedHeader(127); - expected.ExpectIndexedHeader(128); - expected.ExpectDynamicTableSizeUpdate(0); - expected.ExpectDynamicTableSizeUpdate(1); - expected.ExpectDynamicTableSizeUpdate(14); - expected.ExpectDynamicTableSizeUpdate(15); - expected.ExpectDynamicTableSizeUpdate(30); - expected.ExpectDynamicTableSizeUpdate(31); - expected.ExpectDynamicTableSizeUpdate(4095); - expected.ExpectDynamicTableSizeUpdate(4096); - expected.ExpectDynamicTableSizeUpdate(8192); - for (auto type : {HpackEntryType::kIndexedLiteralHeader, - HpackEntryType::kUnindexedLiteralHeader, - HpackEntryType::kNeverIndexedLiteralHeader}) { - for (bool value_huffman : {false, true}) { - // An entry with an index for the name. Ensure the name index - // is not zero by adding one to the Rand8() result. - expected.ExpectNameIndexAndLiteralValue(type, Rand8() + 1, value_huffman, - Rand8String()); - // And two entries with literal names, one plain, one huffman encoded. - expected.ExpectLiteralNameAndValue(type, false, Rand8String(), - value_huffman, Rand8String()); - expected.ExpectLiteralNameAndValue(type, true, Rand8String(), - value_huffman, Rand8String()); - } - } - // Shuffle the entries and serialize them to produce an HPACK block. - expected.ShuffleEntries(RandomPtr()); - HpackBlockBuilder hbb; - expected.AppendToHpackBlockBuilder(&hbb); - - NoArgValidator do_check = [expected, this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.VerifyEq(expected)); - }; - EXPECT_TRUE( - DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_decoder.cc b/net/third_party/http2/hpack/decoder/hpack_decoder.cc deleted file mode 100644 index 33240491..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_decoder.cc +++ /dev/null
@@ -1,122 +0,0 @@ -// Copyright 2017 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 "net/third_party/http2/hpack/decoder/hpack_decoder.h" - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/platform/api/http2_estimate_memory_usage.h" - -namespace http2 { - -HpackDecoder::HpackDecoder(HpackDecoderListener* listener, - size_t max_string_size) - : decoder_state_(listener), - entry_buffer_(&decoder_state_, max_string_size), - block_decoder_(&entry_buffer_), - error_detected_(false) {} - -HpackDecoder::~HpackDecoder() = default; - -void HpackDecoder::set_tables_debug_listener( - HpackDecoderTablesDebugListener* debug_listener) { - decoder_state_.set_tables_debug_listener(debug_listener); -} - -void HpackDecoder::set_max_string_size_bytes(size_t max_string_size_bytes) { - entry_buffer_.set_max_string_size_bytes(max_string_size_bytes); -} - -void HpackDecoder::ApplyHeaderTableSizeSetting(uint32_t max_header_table_size) { - decoder_state_.ApplyHeaderTableSizeSetting(max_header_table_size); -} - -bool HpackDecoder::StartDecodingBlock() { - DVLOG(3) << "HpackDecoder::StartDecodingBlock, error_detected=" - << (error_detected() ? "true" : "false"); - if (error_detected()) { - return false; - } - // TODO(jamessynge): Eliminate Reset(), which shouldn't be necessary - // if there are no errors, and shouldn't be necessary with errors if - // we never resume decoding after an error has been detected. - block_decoder_.Reset(); - decoder_state_.OnHeaderBlockStart(); - return true; -} - -bool HpackDecoder::DecodeFragment(DecodeBuffer* db) { - DVLOG(3) << "HpackDecoder::DecodeFragment, error_detected=" - << (error_detected() ? "true" : "false") - << ", size=" << db->Remaining(); - if (error_detected()) { - return false; - } - // Decode contents of db as an HPACK block fragment, forwards the decoded - // entries to entry_buffer_, which in turn forwards them to decode_state_, - // which finally forwards them to the HpackDecoderListener. - DecodeStatus status = block_decoder_.Decode(db); - if (status == DecodeStatus::kDecodeError) { - // This has probably already been reported, but just in case... - ReportError("HPACK block malformed."); - return false; - } else if (error_detected()) { - return false; - } - // Should be positioned between entries iff decoding is complete. - DCHECK_EQ(block_decoder_.before_entry(), status == DecodeStatus::kDecodeDone) - << status; - if (!block_decoder_.before_entry()) { - entry_buffer_.BufferStringsIfUnbuffered(); - } - return true; -} - -bool HpackDecoder::EndDecodingBlock() { - DVLOG(3) << "HpackDecoder::EndDecodingBlock, error_detected=" - << (error_detected() ? "true" : "false"); - if (error_detected()) { - return false; - } - if (!block_decoder_.before_entry()) { - // The HPACK block ended in the middle of an entry. - ReportError("HPACK block truncated."); - return false; - } - decoder_state_.OnHeaderBlockEnd(); - if (error_detected()) { - // HpackDecoderState will have reported the error. - return false; - } - return true; -} - -bool HpackDecoder::error_detected() { - if (!error_detected_) { - if (entry_buffer_.error_detected()) { - DVLOG(2) << "HpackDecoder::error_detected in entry_buffer_"; - error_detected_ = true; - } else if (decoder_state_.error_detected()) { - DVLOG(2) << "HpackDecoder::error_detected in decoder_state_"; - error_detected_ = true; - } - } - return error_detected_; -} - -size_t HpackDecoder::EstimateMemoryUsage() const { - return Http2EstimateMemoryUsage(entry_buffer_); -} - -void HpackDecoder::ReportError(Http2StringPiece error_message) { - DVLOG(3) << "HpackDecoder::ReportError is new=" - << (!error_detected_ ? "true" : "false") - << ", error_message: " << error_message; - if (!error_detected_) { - error_detected_ = true; - decoder_state_.listener()->OnHeaderErrorDetected(error_message); - } -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_decoder.h b/net/third_party/http2/hpack/decoder/hpack_decoder.h deleted file mode 100644 index e4846c2..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_decoder.h +++ /dev/null
@@ -1,123 +0,0 @@ -// Copyright 2017 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 NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_DECODER_H_ - -// Decodes HPACK blocks, calls an HpackDecoderListener with the decoded header -// entries. Also notifies the listener of errors and of the boundaries of the -// HPACK blocks. - -// TODO(jamessynge): Add feature allowing an HpackEntryDecoderListener -// sub-class (and possibly others) to be passed in for counting events, -// so that deciding whether to count is not done by having lots of if -// statements, but instead by inserting an indirection only when needed. - -// TODO(jamessynge): Consider whether to return false from methods below -// when an error has been previously detected. It protects calling code -// from its failure to pay attention to previous errors, but should we -// spend time to do that? - -#include <stddef.h> - -#include <cstdint> - -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/hpack/decoder/hpack_block_decoder.h" -#include "net/third_party/http2/hpack/decoder/hpack_decoder_listener.h" -#include "net/third_party/http2/hpack/decoder/hpack_decoder_state.h" -#include "net/third_party/http2/hpack/decoder/hpack_decoder_tables.h" -#include "net/third_party/http2/hpack/decoder/hpack_whole_entry_buffer.h" -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" - -namespace http2 { -namespace test { -class HpackDecoderPeer; -} // namespace test - -class HTTP2_EXPORT_PRIVATE HpackDecoder { - public: - HpackDecoder(HpackDecoderListener* listener, size_t max_string_size); - virtual ~HpackDecoder(); - - HpackDecoder(const HpackDecoder&) = delete; - HpackDecoder& operator=(const HpackDecoder&) = delete; - - // Set listener to be notified of insertions into the HPACK dynamic table, - // and uses of those entries. - void set_tables_debug_listener( - HpackDecoderTablesDebugListener* debug_listener); - - // max_string_size specifies the maximum size of an on-the-wire string (name - // or value, plain or Huffman encoded) that will be accepted. See sections - // 5.1 and 5.2 of RFC 7541. This is a defense against OOM attacks; HTTP/2 - // allows a decoder to enforce any limit of the size of the header lists - // that it is willing to decode, including less than the MAX_HEADER_LIST_SIZE - // setting, a setting that is initially unlimited. For example, we might - // choose to send a MAX_HEADER_LIST_SIZE of 64KB, and to use that same value - // as the upper bound for individual strings. - void set_max_string_size_bytes(size_t max_string_size_bytes); - - // ApplyHeaderTableSizeSetting notifies this object that this endpoint has - // received a SETTINGS ACK frame acknowledging an earlier SETTINGS frame from - // this endpoint specifying a new value for SETTINGS_HEADER_TABLE_SIZE (the - // maximum size of the dynamic table that this endpoint will use to decode - // HPACK blocks). - // Because a SETTINGS frame can contain SETTINGS_HEADER_TABLE_SIZE values, - // the caller must keep track of those multiple changes, and make - // corresponding calls to this method. In particular, a call must be made - // with the lowest value acknowledged by the peer, and a call must be made - // with the final value acknowledged, in that order; additional calls may - // be made if additional values were sent. These calls must be made between - // decoding the SETTINGS ACK, and before the next HPACK block is decoded. - void ApplyHeaderTableSizeSetting(uint32_t max_header_table_size); - - // Prepares the decoder for decoding a new HPACK block, and announces this to - // its listener. Returns true if OK to continue with decoding, false if an - // error has been detected, which for StartDecodingBlock means the error was - // detected while decoding a previous HPACK block. - bool StartDecodingBlock(); - - // Decodes a fragment (some or all of the remainder) of an HPACK block, - // reporting header entries (name & value pairs) that it completely decodes - // in the process to the listener. Returns true successfully decoded, false if - // an error has been detected, either during decoding of the fragment, or - // prior to this call. - bool DecodeFragment(DecodeBuffer* db); - - // Completes the process of decoding an HPACK block: if the HPACK block was - // properly terminated, announces the end of the header list to the listener - // and returns true; else returns false. - bool EndDecodingBlock(); - - // Was an error detected? - bool error_detected(); - - // Returns the estimate of dynamically allocated memory in bytes. - size_t EstimateMemoryUsage() const; - - private: - friend class test::HpackDecoderPeer; - - // Reports an error to the listener IF this is the first error detected. - void ReportError(Http2StringPiece error_message); - - // The decompressor state, as defined by HPACK (i.e. the static and dynamic - // tables). - HpackDecoderState decoder_state_; - - // Assembles the various parts of a header entry into whole entries. - HpackWholeEntryBuffer entry_buffer_; - - // The decoder of HPACK blocks into entry parts, passed to entry_buffer_. - HpackBlockDecoder block_decoder_; - - // Has an error been detected? - bool error_detected_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_DECODER_H_
diff --git a/net/third_party/http2/hpack/decoder/hpack_decoder_fuzzer.cc b/net/third_party/http2/hpack/decoder/hpack_decoder_fuzzer.cc deleted file mode 100644 index 2e1c09e..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_decoder_fuzzer.cc +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2017 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 <stddef.h> -#include <stdint.h> - -#include <vector> - -#include "base/test/fuzzed_data_provider.h" -#include "net/third_party/http2/hpack/decoder/hpack_decoder.h" - -// Entry point for LibFuzzer. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - // At least 4 bytes of fuzz data are needed to generate a max string size. - if (size < 4) - return 0; - - base::FuzzedDataProvider fuzzed_data_provider(data, size); - size_t max_string_size = - fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 10 * size); - http2::HpackDecoder decoder(http2::HpackDecoderNoOpListener::NoOpListener(), - max_string_size); - decoder.StartDecodingBlock(); - while (fuzzed_data_provider.remaining_bytes() > 0) { - size_t chunk_size = fuzzed_data_provider.ConsumeIntegralInRange(1, 32); - std::vector<char> chunk = - fuzzed_data_provider.ConsumeBytes<char>(chunk_size); - - // http2::DecodeBuffer constructor does not accept nullptr buffer. - if (chunk.data() == nullptr) - continue; - - http2::DecodeBuffer fragment(chunk.data(), chunk.size()); - decoder.DecodeFragment(&fragment); - } - decoder.EndDecodingBlock(); - return 0; -}
diff --git a/net/third_party/http2/hpack/decoder/hpack_decoder_listener.cc b/net/third_party/http2/hpack/decoder/hpack_decoder_listener.cc deleted file mode 100644 index c68937df..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_decoder_listener.cc +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_decoder_listener.h" - -namespace http2 { - -HpackDecoderListener::HpackDecoderListener() = default; -HpackDecoderListener::~HpackDecoderListener() = default; - -HpackDecoderNoOpListener::HpackDecoderNoOpListener() = default; -HpackDecoderNoOpListener::~HpackDecoderNoOpListener() = default; - -void HpackDecoderNoOpListener::OnHeaderListStart() {} -void HpackDecoderNoOpListener::OnHeader(HpackEntryType entry_type, - const HpackString& name, - const HpackString& value) {} -void HpackDecoderNoOpListener::OnHeaderListEnd() {} -void HpackDecoderNoOpListener::OnHeaderErrorDetected( - Http2StringPiece error_message) {} - -// static -HpackDecoderNoOpListener* HpackDecoderNoOpListener::NoOpListener() { - static HpackDecoderNoOpListener* static_instance = - new HpackDecoderNoOpListener(); - return static_instance; -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_decoder_listener.h b/net/third_party/http2/hpack/decoder/hpack_decoder_listener.h deleted file mode 100644 index 40afafd..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_decoder_listener.h +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright 2016 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. - -// Defines HpackDecoderListener, the base class of listeners for HTTP header -// lists decoded from an HPACK block. - -#ifndef NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_DECODER_LISTENER_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_DECODER_LISTENER_H_ - -#include "net/third_party/http2/hpack/hpack_string.h" -#include "net/third_party/http2/hpack/http2_hpack_constants.h" -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" - -namespace http2 { - -class HTTP2_EXPORT_PRIVATE HpackDecoderListener { - public: - HpackDecoderListener(); - virtual ~HpackDecoderListener(); - - // OnHeaderListStart is called at the start of decoding an HPACK block into - // an HTTP/2 header list. Will only be called once per block, even if it - // extends into CONTINUATION frames. - virtual void OnHeaderListStart() = 0; - - // Called for each header name-value pair that is decoded, in the order they - // appear in the HPACK block. Multiple values for a given key will be emitted - // as multiple calls to OnHeader. - virtual void OnHeader(HpackEntryType entry_type, - const HpackString& name, - const HpackString& value) = 0; - - // OnHeaderListEnd is called after successfully decoding an HPACK block into - // an HTTP/2 header list. Will only be called once per block, even if it - // extends into CONTINUATION frames. - virtual void OnHeaderListEnd() = 0; - - // OnHeaderErrorDetected is called if an error is detected while decoding. - // error_message may be used in a GOAWAY frame as the Opaque Data. - virtual void OnHeaderErrorDetected(Http2StringPiece error_message) = 0; -}; - -// A no-op implementation of HpackDecoderListener, useful for ignoring -// callbacks once an error is detected. -class HTTP2_EXPORT_PRIVATE HpackDecoderNoOpListener - : public HpackDecoderListener { - public: - HpackDecoderNoOpListener(); - ~HpackDecoderNoOpListener() override; - - void OnHeaderListStart() override; - void OnHeader(HpackEntryType entry_type, - const HpackString& name, - const HpackString& value) override; - void OnHeaderListEnd() override; - void OnHeaderErrorDetected(Http2StringPiece error_message) override; - - // Returns a listener that ignores all the calls. - static HpackDecoderNoOpListener* NoOpListener(); -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_DECODER_LISTENER_H_
diff --git a/net/third_party/http2/hpack/decoder/hpack_decoder_state.cc b/net/third_party/http2/hpack/decoder/hpack_decoder_state.cc deleted file mode 100644 index 175a763..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_decoder_state.cc +++ /dev/null
@@ -1,218 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_decoder_state.h" - -#include "base/logging.h" -#include "net/third_party/http2/hpack/hpack_string.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/platform/api/http2_macros.h" - -namespace http2 { -namespace { - -HpackString ExtractHpackString(HpackDecoderStringBuffer* string_buffer) { - if (string_buffer->IsBuffered()) { - return HpackString(string_buffer->ReleaseString()); - } else { - auto result = HpackString(string_buffer->str()); - string_buffer->Reset(); - return result; - } -} - -} // namespace - -HpackDecoderState::HpackDecoderState(HpackDecoderListener* listener) - : listener_(HTTP2_DIE_IF_NULL(listener)), - final_header_table_size_(Http2SettingsInfo::DefaultHeaderTableSize()), - lowest_header_table_size_(final_header_table_size_), - require_dynamic_table_size_update_(false), - allow_dynamic_table_size_update_(true), - saw_dynamic_table_size_update_(false), - error_detected_(false) {} -HpackDecoderState::~HpackDecoderState() = default; - -void HpackDecoderState::set_tables_debug_listener( - HpackDecoderTablesDebugListener* debug_listener) { - decoder_tables_.set_debug_listener(debug_listener); -} - -void HpackDecoderState::ApplyHeaderTableSizeSetting( - uint32_t header_table_size) { - DVLOG(2) << "HpackDecoderState::ApplyHeaderTableSizeSetting(" - << header_table_size << ")"; - DCHECK_LE(lowest_header_table_size_, final_header_table_size_); - if (header_table_size < lowest_header_table_size_) { - lowest_header_table_size_ = header_table_size; - } - final_header_table_size_ = header_table_size; - DVLOG(2) << "low water mark: " << lowest_header_table_size_; - DVLOG(2) << "final limit: " << final_header_table_size_; -} - -// Called to notify this object that we're starting to decode an HPACK block -// (e.g. a HEADERS or PUSH_PROMISE frame's header has been decoded). -void HpackDecoderState::OnHeaderBlockStart() { - DVLOG(2) << "HpackDecoderState::OnHeaderBlockStart"; - // This instance can't be reused after an error has been detected, as we must - // assume that the encoder and decoder compression states are no longer - // synchronized. - DCHECK(!error_detected_); - DCHECK_LE(lowest_header_table_size_, final_header_table_size_); - allow_dynamic_table_size_update_ = true; - saw_dynamic_table_size_update_ = false; - // If the peer has acknowledged a HEADER_TABLE_SIZE smaller than that which - // its HPACK encoder has been using, then the next HPACK block it sends MUST - // start with a Dynamic Table Size Update entry that is at least as low as - // lowest_header_table_size_. That may be followed by another as great as - // final_header_table_size_, if those are different. - require_dynamic_table_size_update_ = - (lowest_header_table_size_ < - decoder_tables_.current_header_table_size() || - final_header_table_size_ < decoder_tables_.header_table_size_limit()); - DVLOG(2) << "HpackDecoderState::OnHeaderListStart " - << "require_dynamic_table_size_update_=" - << require_dynamic_table_size_update_; - listener_->OnHeaderListStart(); -} - -void HpackDecoderState::OnIndexedHeader(size_t index) { - DVLOG(2) << "HpackDecoderState::OnIndexedHeader: " << index; - if (error_detected_) { - return; - } - if (require_dynamic_table_size_update_) { - ReportError("Missing dynamic table size update."); - return; - } - allow_dynamic_table_size_update_ = false; - const HpackStringPair* entry = decoder_tables_.Lookup(index); - if (entry != nullptr) { - listener_->OnHeader(HpackEntryType::kIndexedHeader, entry->name, - entry->value); - } else { - ReportError("Invalid index."); - } -} - -void HpackDecoderState::OnNameIndexAndLiteralValue( - HpackEntryType entry_type, - size_t name_index, - HpackDecoderStringBuffer* value_buffer) { - DVLOG(2) << "HpackDecoderState::OnNameIndexAndLiteralValue " << entry_type - << ", " << name_index << ", " << value_buffer->str(); - if (error_detected_) { - return; - } - if (require_dynamic_table_size_update_) { - ReportError("Missing dynamic table size update."); - return; - } - allow_dynamic_table_size_update_ = false; - const HpackStringPair* entry = decoder_tables_.Lookup(name_index); - if (entry != nullptr) { - HpackString value(ExtractHpackString(value_buffer)); - listener_->OnHeader(entry_type, entry->name, value); - if (entry_type == HpackEntryType::kIndexedLiteralHeader) { - decoder_tables_.Insert(entry->name, value); - } - } else { - ReportError("Invalid name index."); - } -} - -void HpackDecoderState::OnLiteralNameAndValue( - HpackEntryType entry_type, - HpackDecoderStringBuffer* name_buffer, - HpackDecoderStringBuffer* value_buffer) { - DVLOG(2) << "HpackDecoderState::OnLiteralNameAndValue " << entry_type << ", " - << name_buffer->str() << ", " << value_buffer->str(); - if (error_detected_) { - return; - } - if (require_dynamic_table_size_update_) { - ReportError("Missing dynamic table size update."); - return; - } - allow_dynamic_table_size_update_ = false; - HpackString name(ExtractHpackString(name_buffer)); - HpackString value(ExtractHpackString(value_buffer)); - listener_->OnHeader(entry_type, name, value); - if (entry_type == HpackEntryType::kIndexedLiteralHeader) { - decoder_tables_.Insert(name, value); - } -} - -void HpackDecoderState::OnDynamicTableSizeUpdate(size_t size_limit) { - DVLOG(2) << "HpackDecoderState::OnDynamicTableSizeUpdate " << size_limit - << ", required=" - << (require_dynamic_table_size_update_ ? "true" : "false") - << ", allowed=" - << (allow_dynamic_table_size_update_ ? "true" : "false"); - if (error_detected_) { - return; - } - DCHECK_LE(lowest_header_table_size_, final_header_table_size_); - if (!allow_dynamic_table_size_update_) { - // At most two dynamic table size updates allowed at the start, and not - // after a header. - ReportError("Dynamic table size update not allowed."); - return; - } - if (require_dynamic_table_size_update_) { - // The new size must not be greater than the low water mark. - if (size_limit > lowest_header_table_size_) { - ReportError("Initial dynamic table size update is above low water mark."); - return; - } - require_dynamic_table_size_update_ = false; - } else if (size_limit > final_header_table_size_) { - // The new size must not be greater than the final max header table size - // that the peer acknowledged. - ReportError("Dynamic table size update is above acknowledged setting."); - return; - } - decoder_tables_.DynamicTableSizeUpdate(size_limit); - if (saw_dynamic_table_size_update_) { - allow_dynamic_table_size_update_ = false; - } else { - saw_dynamic_table_size_update_ = true; - } - // We no longer need to keep an eye out for a lower header table size. - lowest_header_table_size_ = final_header_table_size_; -} - -void HpackDecoderState::OnHpackDecodeError(Http2StringPiece error_message) { - DVLOG(2) << "HpackDecoderState::OnHpackDecodeError " << error_message; - if (!error_detected_) { - ReportError(error_message); - } -} - -void HpackDecoderState::OnHeaderBlockEnd() { - DVLOG(2) << "HpackDecoderState::OnHeaderBlockEnd"; - if (error_detected_) { - return; - } - if (require_dynamic_table_size_update_) { - // Apparently the HPACK block was empty, but we needed it to contain at - // least 1 dynamic table size update. - ReportError("Missing dynamic table size update."); - } else { - listener_->OnHeaderListEnd(); - } -} - -void HpackDecoderState::ReportError(Http2StringPiece error_message) { - DVLOG(2) << "HpackDecoderState::ReportError is new=" - << (!error_detected_ ? "true" : "false") - << ", error_message: " << error_message; - if (!error_detected_) { - listener_->OnHeaderErrorDetected(error_message); - error_detected_ = true; - } -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_decoder_state.h b/net/third_party/http2/hpack/decoder/hpack_decoder_state.h deleted file mode 100644 index 135424e..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_decoder_state.h +++ /dev/null
@@ -1,129 +0,0 @@ -// Copyright 2016 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. - -// HpackDecoderState maintains the HPACK decompressor state; i.e. updates the -// HPACK dynamic table according to RFC 7541 as the entries in an HPACK block -// are decoded, and reads from the static and dynamic tables in order to build -// complete header entries. Calls an HpackDecoderListener with the completely -// decoded headers (i.e. after resolving table indices into names or values), -// thus translating the decoded HPACK entries into HTTP/2 headers. - -#ifndef NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_DECODER_STATE_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_DECODER_STATE_H_ - -#include <stddef.h> - -#include <cstdint> - -#include "net/third_party/http2/hpack/decoder/hpack_decoder_listener.h" -#include "net/third_party/http2/hpack/decoder/hpack_decoder_string_buffer.h" -#include "net/third_party/http2/hpack/decoder/hpack_decoder_tables.h" -#include "net/third_party/http2/hpack/decoder/hpack_whole_entry_listener.h" -#include "net/third_party/http2/hpack/http2_hpack_constants.h" -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" - -namespace http2 { -namespace test { -class HpackDecoderStatePeer; -} // namespace test - -class HTTP2_EXPORT_PRIVATE HpackDecoderState : public HpackWholeEntryListener { - public: - explicit HpackDecoderState(HpackDecoderListener* listener); - ~HpackDecoderState() override; - - HpackDecoderState(const HpackDecoderState&) = delete; - HpackDecoderState& operator=(const HpackDecoderState&) = delete; - - // Set the listener to be notified when a whole entry has been decoded, - // including resolving name or name and value references. - // The listener may be changed at any time. - HpackDecoderListener* listener() const { return listener_; } - - // Set listener to be notified of insertions into the HPACK dynamic table, - // and uses of those entries. - void set_tables_debug_listener( - HpackDecoderTablesDebugListener* debug_listener); - - // ApplyHeaderTableSizeSetting notifies this object that this endpoint has - // received a SETTINGS ACK frame acknowledging an earlier SETTINGS frame from - // this endpoint specifying a new value for SETTINGS_HEADER_TABLE_SIZE (the - // maximum size of the dynamic table that this endpoint will use to decode - // HPACK blocks). - // Because a SETTINGS frame can contain SETTINGS_HEADER_TABLE_SIZE values, - // the caller must keep track of those multiple changes, and make - // corresponding calls to this method. In particular, a call must be made - // with the lowest value acknowledged by the peer, and a call must be made - // with the final value acknowledged, in that order; additional calls may - // be made if additional values were sent. These calls must be made between - // decoding the SETTINGS ACK, and before the next HPACK block is decoded. - void ApplyHeaderTableSizeSetting(uint32_t max_header_table_size); - - // OnHeaderBlockStart notifies this object that we're starting to decode the - // HPACK payload of a HEADERS or PUSH_PROMISE frame. - void OnHeaderBlockStart(); - - // Implement the HpackWholeEntryListener methods, each of which notifies this - // object when an entire entry has been decoded. - void OnIndexedHeader(size_t index) override; - void OnNameIndexAndLiteralValue( - HpackEntryType entry_type, - size_t name_index, - HpackDecoderStringBuffer* value_buffer) override; - void OnLiteralNameAndValue(HpackEntryType entry_type, - HpackDecoderStringBuffer* name_buffer, - HpackDecoderStringBuffer* value_buffer) override; - void OnDynamicTableSizeUpdate(size_t size) override; - void OnHpackDecodeError(Http2StringPiece error_message) override; - - // OnHeaderBlockEnd notifies this object that an entire HPACK block has been - // decoded, which might have extended into CONTINUATION blocks. - void OnHeaderBlockEnd(); - - // Was an error detected? After an error has been detected and reported, - // no further callbacks will be made to the listener. - bool error_detected() const { return error_detected_; } - - const HpackDecoderTables& decoder_tables_for_test() const { - return decoder_tables_; - } - - private: - friend class test::HpackDecoderStatePeer; - - // Reports an error to the listener IF this is the first error detected. - void ReportError(Http2StringPiece error_message); - - // The static and dynamic HPACK tables. - HpackDecoderTables decoder_tables_; - - // The listener to be notified of headers, the start and end of header - // lists, and of errors. - HpackDecoderListener* listener_; - - // The most recent HEADER_TABLE_SIZE setting acknowledged by the peer. - uint32_t final_header_table_size_; - - // The lowest HEADER_TABLE_SIZE setting acknowledged by the peer; valid until - // the next HPACK block is decoded. - // TODO(jamessynge): Test raising the HEADER_TABLE_SIZE. - uint32_t lowest_header_table_size_; - - // Must the next (first) HPACK entry be a dynamic table size update? - bool require_dynamic_table_size_update_; - - // May the next (first or second) HPACK entry be a dynamic table size update? - bool allow_dynamic_table_size_update_; - - // Have we already seen a dynamic table size update in this HPACK block? - bool saw_dynamic_table_size_update_; - - // Has an error already been detected and reported to the listener? - bool error_detected_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_DECODER_STATE_H_
diff --git a/net/third_party/http2/hpack/decoder/hpack_decoder_state_test.cc b/net/third_party/http2/hpack/decoder/hpack_decoder_state_test.cc deleted file mode 100644 index c24e1b2b..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_decoder_state_test.cc +++ /dev/null
@@ -1,539 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_decoder_state.h" - -// Tests of HpackDecoderState. - -#include <utility> -#include <vector> - -#include "base/logging.h" -#include "net/third_party/http2/hpack/hpack_string.h" -#include "net/third_party/http2/hpack/http2_hpack_constants.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; -using ::testing::Eq; -using ::testing::HasSubstr; -using ::testing::Mock; -using ::testing::StrictMock; - -namespace http2 { -namespace test { -class HpackDecoderStatePeer { - public: - static HpackDecoderTables* GetDecoderTables(HpackDecoderState* state) { - return &state->decoder_tables_; - } -}; - -namespace { - -class MockHpackDecoderListener : public HpackDecoderListener { - public: - MOCK_METHOD0(OnHeaderListStart, void()); - MOCK_METHOD3(OnHeader, - void(HpackEntryType entry_type, - const HpackString& name, - const HpackString& value)); - MOCK_METHOD0(OnHeaderListEnd, void()); - MOCK_METHOD1(OnHeaderErrorDetected, void(Http2StringPiece error_message)); -}; - -enum StringBacking { STATIC, UNBUFFERED, BUFFERED }; - -class HpackDecoderStateTest : public ::testing::Test { - protected: - HpackDecoderStateTest() : decoder_state_(&listener_) {} - - HpackDecoderTables* GetDecoderTables() { - return HpackDecoderStatePeer::GetDecoderTables(&decoder_state_); - } - - const HpackStringPair* Lookup(size_t index) { - return GetDecoderTables()->Lookup(index); - } - - size_t current_header_table_size() { - return GetDecoderTables()->current_header_table_size(); - } - - size_t header_table_size_limit() { - return GetDecoderTables()->header_table_size_limit(); - } - - void set_header_table_size_limit(size_t size) { - GetDecoderTables()->DynamicTableSizeUpdate(size); - } - - void SetStringBuffer(const char* s, - StringBacking backing, - HpackDecoderStringBuffer* string_buffer) { - switch (backing) { - case STATIC: - string_buffer->Set(s, true); - break; - case UNBUFFERED: - string_buffer->Set(s, false); - break; - case BUFFERED: - string_buffer->Set(s, false); - string_buffer->BufferStringIfUnbuffered(); - break; - } - } - - void SetName(const char* s, StringBacking backing) { - SetStringBuffer(s, backing, &name_buffer_); - } - - void SetValue(const char* s, StringBacking backing) { - SetStringBuffer(s, backing, &value_buffer_); - } - - void SendStartAndVerifyCallback() { - EXPECT_CALL(listener_, OnHeaderListStart()); - decoder_state_.OnHeaderBlockStart(); - Mock::VerifyAndClearExpectations(&listener_); - } - - void SendSizeUpdate(size_t size) { - decoder_state_.OnDynamicTableSizeUpdate(size); - Mock::VerifyAndClearExpectations(&listener_); - } - - void SendIndexAndVerifyCallback(size_t index, - HpackEntryType expected_type, - const char* expected_name, - const char* expected_value) { - EXPECT_CALL(listener_, - OnHeader(expected_type, Eq(expected_name), Eq(expected_value))); - decoder_state_.OnIndexedHeader(index); - Mock::VerifyAndClearExpectations(&listener_); - } - - void SendValueAndVerifyCallback(size_t name_index, - HpackEntryType entry_type, - const char* name, - const char* value, - StringBacking value_backing) { - SetValue(value, value_backing); - EXPECT_CALL(listener_, OnHeader(entry_type, Eq(name), Eq(value))); - decoder_state_.OnNameIndexAndLiteralValue(entry_type, name_index, - &value_buffer_); - Mock::VerifyAndClearExpectations(&listener_); - } - - void SendNameAndValueAndVerifyCallback(HpackEntryType entry_type, - const char* name, - StringBacking name_backing, - const char* value, - StringBacking value_backing) { - SetName(name, name_backing); - SetValue(value, value_backing); - EXPECT_CALL(listener_, OnHeader(entry_type, Eq(name), Eq(value))); - decoder_state_.OnLiteralNameAndValue(entry_type, &name_buffer_, - &value_buffer_); - Mock::VerifyAndClearExpectations(&listener_); - } - - void SendEndAndVerifyCallback() { - EXPECT_CALL(listener_, OnHeaderListEnd()); - decoder_state_.OnHeaderBlockEnd(); - Mock::VerifyAndClearExpectations(&listener_); - } - - // dynamic_index is one-based, because that is the way RFC 7541 shows it. - AssertionResult VerifyEntry(size_t dynamic_index, - const char* name, - const char* value) { - const HpackStringPair* entry = - Lookup(dynamic_index + kFirstDynamicTableIndex - 1); - VERIFY_NE(entry, nullptr); - VERIFY_EQ(entry->name.ToStringPiece(), name); - VERIFY_EQ(entry->value.ToStringPiece(), value); - return AssertionSuccess(); - } - AssertionResult VerifyNoEntry(size_t dynamic_index) { - const HpackStringPair* entry = - Lookup(dynamic_index + kFirstDynamicTableIndex - 1); - VERIFY_EQ(entry, nullptr); - return AssertionSuccess(); - } - AssertionResult VerifyDynamicTableContents( - const std::vector<std::pair<const char*, const char*>>& entries) { - size_t index = 1; - for (const auto& entry : entries) { - VERIFY_SUCCESS(VerifyEntry(index, entry.first, entry.second)); - ++index; - } - VERIFY_SUCCESS(VerifyNoEntry(index)); - return AssertionSuccess(); - } - - StrictMock<MockHpackDecoderListener> listener_; - HpackDecoderState decoder_state_; - HpackDecoderStringBuffer name_buffer_, value_buffer_; -}; - -// Test based on RFC 7541, section C.3: Request Examples without Huffman Coding. -// This section shows several consecutive header lists, corresponding to HTTP -// requests, on the same connection. -TEST_F(HpackDecoderStateTest, C3_RequestExamples) { - // C.3.1 First Request - // - // Header list to encode: - // - // :method: GET - // :scheme: http - // :path: / - // :authority: www.example.com - - SendStartAndVerifyCallback(); - SendIndexAndVerifyCallback(2, HpackEntryType::kIndexedHeader, ":method", - "GET"); - SendIndexAndVerifyCallback(6, HpackEntryType::kIndexedHeader, ":scheme", - "http"); - SendIndexAndVerifyCallback(4, HpackEntryType::kIndexedHeader, ":path", "/"); - SendValueAndVerifyCallback(1, HpackEntryType::kIndexedLiteralHeader, - ":authority", "www.example.com", UNBUFFERED); - SendEndAndVerifyCallback(); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 57) :authority: www.example.com - // Table size: 57 - - ASSERT_TRUE(VerifyDynamicTableContents({{":authority", "www.example.com"}})); - ASSERT_EQ(57u, current_header_table_size()); - - // C.3.2 Second Request - // - // Header list to encode: - // - // :method: GET - // :scheme: http - // :path: / - // :authority: www.example.com - // cache-control: no-cache - - SendStartAndVerifyCallback(); - SendIndexAndVerifyCallback(2, HpackEntryType::kIndexedHeader, ":method", - "GET"); - SendIndexAndVerifyCallback(6, HpackEntryType::kIndexedHeader, ":scheme", - "http"); - SendIndexAndVerifyCallback(4, HpackEntryType::kIndexedHeader, ":path", "/"); - SendIndexAndVerifyCallback(62, HpackEntryType::kIndexedHeader, ":authority", - "www.example.com"); - SendValueAndVerifyCallback(24, HpackEntryType::kIndexedLiteralHeader, - "cache-control", "no-cache", UNBUFFERED); - SendEndAndVerifyCallback(); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 53) cache-control: no-cache - // [ 2] (s = 57) :authority: www.example.com - // Table size: 110 - - ASSERT_TRUE(VerifyDynamicTableContents( - {{"cache-control", "no-cache"}, {":authority", "www.example.com"}})); - ASSERT_EQ(110u, current_header_table_size()); - - // C.3.3 Third Request - // - // Header list to encode: - // - // :method: GET - // :scheme: https - // :path: /index.html - // :authority: www.example.com - // custom-key: custom-value - - SendStartAndVerifyCallback(); - SendIndexAndVerifyCallback(2, HpackEntryType::kIndexedHeader, ":method", - "GET"); - SendIndexAndVerifyCallback(7, HpackEntryType::kIndexedHeader, ":scheme", - "https"); - SendIndexAndVerifyCallback(5, HpackEntryType::kIndexedHeader, ":path", - "/index.html"); - SendIndexAndVerifyCallback(63, HpackEntryType::kIndexedHeader, ":authority", - "www.example.com"); - SendNameAndValueAndVerifyCallback(HpackEntryType::kIndexedLiteralHeader, - "custom-key", UNBUFFERED, "custom-value", - UNBUFFERED); - SendEndAndVerifyCallback(); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 54) custom-key: custom-value - // [ 2] (s = 53) cache-control: no-cache - // [ 3] (s = 57) :authority: www.example.com - // Table size: 164 - - ASSERT_TRUE(VerifyDynamicTableContents({{"custom-key", "custom-value"}, - {"cache-control", "no-cache"}, - {":authority", "www.example.com"}})); - ASSERT_EQ(164u, current_header_table_size()); -} - -// Test based on RFC 7541, section C.5: Response Examples without Huffman -// Coding. This section shows several consecutive header lists, corresponding -// to HTTP responses, on the same connection. The HTTP/2 setting parameter -// SETTINGS_HEADER_TABLE_SIZE is set to the value of 256 octets, causing -// some evictions to occur. -TEST_F(HpackDecoderStateTest, C5_ResponseExamples) { - set_header_table_size_limit(256); - - // C.5.1 First Response - // - // Header list to encode: - // - // :status: 302 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:21 GMT - // location: https://www.example.com - - SendStartAndVerifyCallback(); - SendValueAndVerifyCallback(8, HpackEntryType::kIndexedLiteralHeader, - ":status", "302", BUFFERED); - SendValueAndVerifyCallback(24, HpackEntryType::kIndexedLiteralHeader, - "cache-control", "private", UNBUFFERED); - SendValueAndVerifyCallback(33, HpackEntryType::kIndexedLiteralHeader, "date", - "Mon, 21 Oct 2013 20:13:21 GMT", UNBUFFERED); - SendValueAndVerifyCallback(46, HpackEntryType::kIndexedLiteralHeader, - "location", "https://www.example.com", UNBUFFERED); - SendEndAndVerifyCallback(); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 63) location: https://www.example.com - // [ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT - // [ 3] (s = 52) cache-control: private - // [ 4] (s = 42) :status: 302 - // Table size: 222 - - ASSERT_TRUE( - VerifyDynamicTableContents({{"location", "https://www.example.com"}, - {"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - {"cache-control", "private"}, - {":status", "302"}})); - ASSERT_EQ(222u, current_header_table_size()); - - // C.5.2 Second Response - // - // The (":status", "302") header field is evicted from the dynamic table to - // free space to allow adding the (":status", "307") header field. - // - // Header list to encode: - // - // :status: 307 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:21 GMT - // location: https://www.example.com - - SendStartAndVerifyCallback(); - SendValueAndVerifyCallback(8, HpackEntryType::kIndexedLiteralHeader, - ":status", "307", BUFFERED); - SendIndexAndVerifyCallback(65, HpackEntryType::kIndexedHeader, - "cache-control", "private"); - SendIndexAndVerifyCallback(64, HpackEntryType::kIndexedHeader, "date", - "Mon, 21 Oct 2013 20:13:21 GMT"); - SendIndexAndVerifyCallback(63, HpackEntryType::kIndexedHeader, "location", - "https://www.example.com"); - SendEndAndVerifyCallback(); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 42) :status: 307 - // [ 2] (s = 63) location: https://www.example.com - // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT - // [ 4] (s = 52) cache-control: private - // Table size: 222 - - ASSERT_TRUE( - VerifyDynamicTableContents({{":status", "307"}, - {"location", "https://www.example.com"}, - {"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - {"cache-control", "private"}})); - ASSERT_EQ(222u, current_header_table_size()); - - // C.5.3 Third Response - // - // Several header fields are evicted from the dynamic table during the - // processing of this header list. - // - // Header list to encode: - // - // :status: 200 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:22 GMT - // location: https://www.example.com - // content-encoding: gzip - // set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1 - - SendStartAndVerifyCallback(); - SendIndexAndVerifyCallback(8, HpackEntryType::kIndexedHeader, ":status", - "200"); - SendIndexAndVerifyCallback(65, HpackEntryType::kIndexedHeader, - "cache-control", "private"); - SendValueAndVerifyCallback(33, HpackEntryType::kIndexedLiteralHeader, "date", - "Mon, 21 Oct 2013 20:13:22 GMT", BUFFERED); - SendIndexAndVerifyCallback(64, HpackEntryType::kIndexedHeader, "location", - "https://www.example.com"); - SendValueAndVerifyCallback(26, HpackEntryType::kIndexedLiteralHeader, - "content-encoding", "gzip", UNBUFFERED); - SendValueAndVerifyCallback( - 55, HpackEntryType::kIndexedLiteralHeader, "set-cookie", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", BUFFERED); - SendEndAndVerifyCallback(); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; - // max-age=3600; version=1 - // [ 2] (s = 52) content-encoding: gzip - // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT - // Table size: 215 - - ASSERT_TRUE(VerifyDynamicTableContents( - {{"set-cookie", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"}, - {"content-encoding", "gzip"}, - {"date", "Mon, 21 Oct 2013 20:13:22 GMT"}})); - ASSERT_EQ(215u, current_header_table_size()); -} - -// Confirm that the table size can be changed, but at most twice. -TEST_F(HpackDecoderStateTest, OptionalTableSizeChanges) { - SendStartAndVerifyCallback(); - EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(), - header_table_size_limit()); - SendSizeUpdate(1024); - EXPECT_EQ(1024u, header_table_size_limit()); - SendSizeUpdate(0); - EXPECT_EQ(0u, header_table_size_limit()); - - // Three updates aren't allowed. - EXPECT_CALL(listener_, - OnHeaderErrorDetected(HasSubstr("size update not allowed"))); - SendSizeUpdate(0); -} - -// Confirm that required size updates are indeed required before headers. -TEST_F(HpackDecoderStateTest, RequiredTableSizeChangeBeforeHeader) { - decoder_state_.ApplyHeaderTableSizeSetting(1024); - decoder_state_.ApplyHeaderTableSizeSetting(2048); - - // First provide the required update, and an allowed second update. - SendStartAndVerifyCallback(); - EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(), - header_table_size_limit()); - SendSizeUpdate(1024); - EXPECT_EQ(1024u, header_table_size_limit()); - SendSizeUpdate(1500); - EXPECT_EQ(1500u, header_table_size_limit()); - SendEndAndVerifyCallback(); - - // Another HPACK block, but this time missing the required size update. - decoder_state_.ApplyHeaderTableSizeSetting(1024); - SendStartAndVerifyCallback(); - EXPECT_CALL(listener_, OnHeaderErrorDetected( - HasSubstr("Missing dynamic table size update"))); - decoder_state_.OnIndexedHeader(1); - - // Further decoded entries are ignored. - decoder_state_.OnIndexedHeader(1); - decoder_state_.OnDynamicTableSizeUpdate(1); - SetValue("value", UNBUFFERED); - decoder_state_.OnNameIndexAndLiteralValue( - HpackEntryType::kIndexedLiteralHeader, 4, &value_buffer_); - SetName("name", UNBUFFERED); - decoder_state_.OnLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader, - &name_buffer_, &value_buffer_); - decoder_state_.OnHeaderBlockEnd(); - decoder_state_.OnHpackDecodeError("NOT FORWARDED"); -} - -// Confirm that required size updates are validated. -TEST_F(HpackDecoderStateTest, InvalidRequiredSizeUpdate) { - // Require a size update, but provide one that isn't small enough. - decoder_state_.ApplyHeaderTableSizeSetting(1024); - SendStartAndVerifyCallback(); - EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(), - header_table_size_limit()); - EXPECT_CALL(listener_, - OnHeaderErrorDetected(HasSubstr("above low water mark"))); - SendSizeUpdate(2048); -} - -// Confirm that required size updates are indeed required before the end. -TEST_F(HpackDecoderStateTest, RequiredTableSizeChangeBeforeEnd) { - decoder_state_.ApplyHeaderTableSizeSetting(1024); - SendStartAndVerifyCallback(); - EXPECT_CALL(listener_, OnHeaderErrorDetected( - HasSubstr("Missing dynamic table size update"))); - decoder_state_.OnHeaderBlockEnd(); -} - -// Confirm that optional size updates are validated. -TEST_F(HpackDecoderStateTest, InvalidOptionalSizeUpdate) { - // Require a size update, but provide one that isn't small enough. - SendStartAndVerifyCallback(); - EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(), - header_table_size_limit()); - EXPECT_CALL(listener_, - OnHeaderErrorDetected(HasSubstr("size update is above"))); - SendSizeUpdate(Http2SettingsInfo::DefaultHeaderTableSize() + 1); -} - -TEST_F(HpackDecoderStateTest, InvalidStaticIndex) { - SendStartAndVerifyCallback(); - EXPECT_CALL(listener_, OnHeaderErrorDetected(HasSubstr("Invalid index"))); - decoder_state_.OnIndexedHeader(0); -} - -TEST_F(HpackDecoderStateTest, InvalidDynamicIndex) { - SendStartAndVerifyCallback(); - EXPECT_CALL(listener_, OnHeaderErrorDetected(HasSubstr("Invalid index"))); - decoder_state_.OnIndexedHeader(kFirstDynamicTableIndex); -} - -TEST_F(HpackDecoderStateTest, InvalidNameIndex) { - SendStartAndVerifyCallback(); - EXPECT_CALL(listener_, - OnHeaderErrorDetected(HasSubstr("Invalid name index"))); - SetValue("value", UNBUFFERED); - decoder_state_.OnNameIndexAndLiteralValue( - HpackEntryType::kIndexedLiteralHeader, kFirstDynamicTableIndex, - &value_buffer_); -} - -TEST_F(HpackDecoderStateTest, ErrorsSuppressCallbacks) { - SendStartAndVerifyCallback(); - EXPECT_CALL(listener_, - OnHeaderErrorDetected(Http2StringPiece("Huffman decode error."))); - decoder_state_.OnHpackDecodeError("Huffman decode error."); - - // Further decoded entries are ignored. - decoder_state_.OnIndexedHeader(1); - decoder_state_.OnDynamicTableSizeUpdate(1); - SetValue("value", UNBUFFERED); - decoder_state_.OnNameIndexAndLiteralValue( - HpackEntryType::kIndexedLiteralHeader, 4, &value_buffer_); - SetName("name", UNBUFFERED); - decoder_state_.OnLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader, - &name_buffer_, &value_buffer_); - decoder_state_.OnHeaderBlockEnd(); - decoder_state_.OnHpackDecodeError("NOT FORWARDED"); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_decoder_string_buffer.cc b/net/third_party/http2/hpack/decoder/hpack_decoder_string_buffer.cc deleted file mode 100644 index 2b459ab..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_decoder_string_buffer.cc +++ /dev/null
@@ -1,235 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_decoder_string_buffer.h" - -#include <utility> - -#include "base/logging.h" -#include "net/third_party/http2/platform/api/http2_bug_tracker.h" -#include "net/third_party/http2/platform/api/http2_estimate_memory_usage.h" -#include "net/third_party/http2/platform/api/http2_string.h" - -namespace http2 { - -std::ostream& operator<<(std::ostream& out, - const HpackDecoderStringBuffer::State v) { - switch (v) { - case HpackDecoderStringBuffer::State::RESET: - return out << "RESET"; - case HpackDecoderStringBuffer::State::COLLECTING: - return out << "COLLECTING"; - case HpackDecoderStringBuffer::State::COMPLETE: - return out << "COMPLETE"; - } - // Since the value doesn't come over the wire, only a programming bug should - // result in reaching this point. - int unknown = static_cast<int>(v); - HTTP2_BUG << "Invalid HpackDecoderStringBuffer::State: " << unknown; - return out << "HpackDecoderStringBuffer::State(" << unknown << ")"; -} - -std::ostream& operator<<(std::ostream& out, - const HpackDecoderStringBuffer::Backing v) { - switch (v) { - case HpackDecoderStringBuffer::Backing::RESET: - return out << "RESET"; - case HpackDecoderStringBuffer::Backing::UNBUFFERED: - return out << "UNBUFFERED"; - case HpackDecoderStringBuffer::Backing::BUFFERED: - return out << "BUFFERED"; - case HpackDecoderStringBuffer::Backing::STATIC: - return out << "STATIC"; - } - // Since the value doesn't come over the wire, only a programming bug should - // result in reaching this point. - auto v2 = static_cast<int>(v); - HTTP2_BUG << "Invalid HpackDecoderStringBuffer::Backing: " << v2; - return out << "HpackDecoderStringBuffer::Backing(" << v2 << ")"; -} - -HpackDecoderStringBuffer::HpackDecoderStringBuffer() - : remaining_len_(0), - is_huffman_encoded_(false), - state_(State::RESET), - backing_(Backing::RESET) {} -HpackDecoderStringBuffer::~HpackDecoderStringBuffer() = default; - -void HpackDecoderStringBuffer::Reset() { - DVLOG(3) << "HpackDecoderStringBuffer::Reset"; - state_ = State::RESET; -} - -void HpackDecoderStringBuffer::Set(Http2StringPiece value, bool is_static) { - DVLOG(2) << "HpackDecoderStringBuffer::Set"; - DCHECK_EQ(state_, State::RESET); - value_ = value; - state_ = State::COMPLETE; - backing_ = is_static ? Backing::STATIC : Backing::UNBUFFERED; - // TODO(jamessynge): Determine which of these two fields must be set. - remaining_len_ = 0; - is_huffman_encoded_ = false; -} - -void HpackDecoderStringBuffer::OnStart(bool huffman_encoded, size_t len) { - DVLOG(2) << "HpackDecoderStringBuffer::OnStart"; - DCHECK_EQ(state_, State::RESET); - - remaining_len_ = len; - is_huffman_encoded_ = huffman_encoded; - state_ = State::COLLECTING; - - if (huffman_encoded) { - // We don't set, clear or use value_ for buffered strings until OnEnd. - decoder_.Reset(); - buffer_.clear(); - backing_ = Backing::BUFFERED; - - // Reserve space in buffer_ for the uncompressed string, assuming the - // maximum expansion. The shortest Huffman codes in the RFC are 5 bits long, - // which then expand to 8 bits during decoding (i.e. each code is for one - // plain text octet, aka byte), so the maximum size is 60% longer than the - // encoded size. - len = len * 8 / 5; - if (buffer_.capacity() < len) { - buffer_.reserve(len); - } - } else { - // Assume for now that we won't need to use buffer_, so don't reserve space - // in it. - backing_ = Backing::RESET; - // OnData is not called for empty (zero length) strings, so make sure that - // value_ is cleared. - value_ = Http2StringPiece(); - } -} - -bool HpackDecoderStringBuffer::OnData(const char* data, size_t len) { - DVLOG(2) << "HpackDecoderStringBuffer::OnData state=" << state_ - << ", backing=" << backing_; - DCHECK_EQ(state_, State::COLLECTING); - DCHECK_LE(len, remaining_len_); - remaining_len_ -= len; - - if (is_huffman_encoded_) { - DCHECK_EQ(backing_, Backing::BUFFERED); - return decoder_.Decode(Http2StringPiece(data, len), &buffer_); - } - - if (backing_ == Backing::RESET) { - // This is the first call to OnData. If data contains the entire string, - // don't copy the string. If we later find that the HPACK entry is split - // across input buffers, then we'll copy the string into buffer_. - if (remaining_len_ == 0) { - value_ = Http2StringPiece(data, len); - backing_ = Backing::UNBUFFERED; - return true; - } - - // We need to buffer the string because it is split across input buffers. - // Reserve space in buffer_ for the entire string. - backing_ = Backing::BUFFERED; - buffer_.reserve(remaining_len_ + len); - buffer_.assign(data, len); - return true; - } - - // This is not the first call to OnData for this string, so it should be - // buffered. - DCHECK_EQ(backing_, Backing::BUFFERED); - - // Append to the current contents of the buffer. - buffer_.append(data, len); - return true; -} - -bool HpackDecoderStringBuffer::OnEnd() { - DVLOG(2) << "HpackDecoderStringBuffer::OnEnd"; - DCHECK_EQ(state_, State::COLLECTING); - DCHECK_EQ(0u, remaining_len_); - - if (is_huffman_encoded_) { - DCHECK_EQ(backing_, Backing::BUFFERED); - // Did the Huffman encoding of the string end properly? - if (!decoder_.InputProperlyTerminated()) { - return false; // No, it didn't. - } - value_ = buffer_; - } else if (backing_ == Backing::BUFFERED) { - value_ = buffer_; - } - state_ = State::COMPLETE; - return true; -} - -void HpackDecoderStringBuffer::BufferStringIfUnbuffered() { - DVLOG(3) << "HpackDecoderStringBuffer::BufferStringIfUnbuffered state=" - << state_ << ", backing=" << backing_; - if (state_ != State::RESET && backing_ == Backing::UNBUFFERED) { - DVLOG(2) << "HpackDecoderStringBuffer buffering Http2String of length " - << value_.size(); - buffer_.assign(value_.data(), value_.size()); - if (state_ == State::COMPLETE) { - value_ = buffer_; - } - backing_ = Backing::BUFFERED; - } -} - -bool HpackDecoderStringBuffer::IsBuffered() const { - DVLOG(3) << "HpackDecoderStringBuffer::IsBuffered"; - return state_ != State::RESET && backing_ == Backing::BUFFERED; -} - -size_t HpackDecoderStringBuffer::BufferedLength() const { - DVLOG(3) << "HpackDecoderStringBuffer::BufferedLength"; - return IsBuffered() ? buffer_.size() : 0; -} - -Http2StringPiece HpackDecoderStringBuffer::str() const { - DVLOG(3) << "HpackDecoderStringBuffer::str"; - DCHECK_EQ(state_, State::COMPLETE); - return value_; -} - -Http2String HpackDecoderStringBuffer::ReleaseString() { - DVLOG(3) << "HpackDecoderStringBuffer::ReleaseString"; - DCHECK_EQ(state_, State::COMPLETE); - DCHECK_EQ(backing_, Backing::BUFFERED); - if (state_ == State::COMPLETE) { - state_ = State::RESET; - if (backing_ == Backing::BUFFERED) { - return std::move(buffer_); - } else { - return Http2String(value_); - } - } - return ""; -} - -void HpackDecoderStringBuffer::OutputDebugStringTo(std::ostream& out) const { - out << "{state=" << state_; - if (state_ != State::RESET) { - out << ", backing=" << backing_; - out << ", remaining_len=" << remaining_len_; - out << ", is_huffman_encoded=" << is_huffman_encoded_; - if (backing_ == Backing::BUFFERED) { - out << ", buffer: " << buffer_; - } else { - out << ", value: " << value_; - } - } - out << "}"; -} - -size_t HpackDecoderStringBuffer::EstimateMemoryUsage() const { - return Http2EstimateMemoryUsage(buffer_); -} - -std::ostream& operator<<(std::ostream& out, const HpackDecoderStringBuffer& v) { - v.OutputDebugStringTo(out); - return out; -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_decoder_string_buffer.h b/net/third_party/http2/hpack/decoder/hpack_decoder_string_buffer.h deleted file mode 100644 index 064808e..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_decoder_string_buffer.h +++ /dev/null
@@ -1,102 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_DECODER_STRING_BUFFER_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_DECODER_STRING_BUFFER_H_ - -// HpackDecoderStringBuffer helps an HPACK decoder to avoid copies of a string -// literal (name or value) except when necessary (e.g. when split across two -// or more HPACK block fragments). - -#include <stddef.h> - -#include <ostream> - -#include "net/third_party/http2/hpack/huffman/hpack_huffman_decoder.h" -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" - -namespace http2 { - -class HTTP2_EXPORT_PRIVATE HpackDecoderStringBuffer { - public: - enum class State : uint8_t { RESET, COLLECTING, COMPLETE }; - enum class Backing : uint8_t { RESET, UNBUFFERED, BUFFERED, STATIC }; - - HpackDecoderStringBuffer(); - ~HpackDecoderStringBuffer(); - - HpackDecoderStringBuffer(const HpackDecoderStringBuffer&) = delete; - HpackDecoderStringBuffer& operator=(const HpackDecoderStringBuffer&) = delete; - - void Reset(); - void Set(Http2StringPiece value, bool is_static); - - // Note that for Huffman encoded strings the length of the string after - // decoding may be larger (expected), the same or even smaller; the latter - // are unlikely, but possible if the encoder makes odd choices. - void OnStart(bool huffman_encoded, size_t len); - bool OnData(const char* data, size_t len); - bool OnEnd(); - void BufferStringIfUnbuffered(); - bool IsBuffered() const; - size_t BufferedLength() const; - - // Accessors for the completely collected string (i.e. Set or OnEnd has just - // been called, and no reset of the state has occurred). - - // Returns a Http2StringPiece pointing to the backing store for the string, - // either the internal buffer or the original transport buffer (e.g. for a - // literal value that wasn't Huffman encoded, and that wasn't split across - // transport buffers). - Http2StringPiece str() const; - - // Returns the completely collected string by value, using std::move in an - // effort to avoid unnecessary copies. ReleaseString() must not be called - // unless the string has been buffered (to avoid forcing a potentially - // unnecessary copy). ReleaseString() also resets the instance so that it can - // be used to collect another string. - Http2String ReleaseString(); - - State state_for_testing() const { return state_; } - Backing backing_for_testing() const { return backing_; } - void OutputDebugStringTo(std::ostream& out) const; - - // Returns the estimate of dynamically allocated memory in bytes. - size_t EstimateMemoryUsage() const; - - private: - // Storage for the string being buffered, if buffering is necessary - // (e.g. if Huffman encoded, buffer_ is storage for the decoded string). - Http2String buffer_; - - // The Http2StringPiece to be returned by HpackDecoderStringBuffer::str(). If - // a string has been collected, but not buffered, value_ points to that - // string. - Http2StringPiece value_; - - // The decoder to use if the string is Huffman encoded. - HpackHuffmanDecoder decoder_; - - // Count of bytes not yet passed to OnData. - size_t remaining_len_; - - // Is the HPACK string Huffman encoded? - bool is_huffman_encoded_; - - // State of the string decoding process. - State state_; - - // Where is the string stored? - Backing backing_; -}; - -HTTP2_EXPORT_PRIVATE std::ostream& operator<<( - std::ostream& out, - const HpackDecoderStringBuffer& v); - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_DECODER_STRING_BUFFER_H_
diff --git a/net/third_party/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc b/net/third_party/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc deleted file mode 100644 index e12380d..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc +++ /dev/null
@@ -1,251 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_decoder_string_buffer.h" - -// Tests of HpackDecoderStringBuffer. - -#include <initializer_list> - -#include "base/logging.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; -using ::testing::HasSubstr; - -namespace http2 { -namespace test { -namespace { - -class HpackDecoderStringBufferTest : public ::testing::Test { - protected: - typedef HpackDecoderStringBuffer::State State; - typedef HpackDecoderStringBuffer::Backing Backing; - - State state() const { return buf_.state_for_testing(); } - Backing backing() const { return buf_.backing_for_testing(); } - - // We want to know that LOG(x) << buf_ will work in production should that - // be needed, so we test that it outputs the expected values. - AssertionResult VerifyLogHasSubstrs(std::initializer_list<Http2String> strs) { - VLOG(1) << buf_; - std::ostringstream ss; - buf_.OutputDebugStringTo(ss); - Http2String dbg_str(ss.str()); - for (const auto& expected : strs) { - VERIFY_THAT(dbg_str, HasSubstr(expected)); - } - return AssertionSuccess(); - } - - HpackDecoderStringBuffer buf_; -}; - -TEST_F(HpackDecoderStringBufferTest, SetStatic) { - Http2StringPiece data("static string"); - - EXPECT_EQ(state(), State::RESET); - EXPECT_TRUE(VerifyLogHasSubstrs({"state=RESET"})); - - buf_.Set(data, /*is_static*/ true); - LOG(INFO) << buf_; - EXPECT_EQ(state(), State::COMPLETE); - EXPECT_EQ(backing(), Backing::STATIC); - EXPECT_EQ(data, buf_.str()); - EXPECT_EQ(data.data(), buf_.str().data()); - EXPECT_TRUE(VerifyLogHasSubstrs( - {"state=COMPLETE", "backing=STATIC", "value: static string"})); - - // The string is static, so BufferStringIfUnbuffered won't change anything. - buf_.BufferStringIfUnbuffered(); - EXPECT_EQ(state(), State::COMPLETE); - EXPECT_EQ(backing(), Backing::STATIC); - EXPECT_EQ(data, buf_.str()); - EXPECT_EQ(data.data(), buf_.str().data()); - EXPECT_TRUE(VerifyLogHasSubstrs( - {"state=COMPLETE", "backing=STATIC", "value: static string"})); -} - -TEST_F(HpackDecoderStringBufferTest, PlainWhole) { - Http2StringPiece data("some text."); - - LOG(INFO) << buf_; - EXPECT_EQ(state(), State::RESET); - - buf_.OnStart(/*huffman_encoded*/ false, data.size()); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::RESET); - LOG(INFO) << buf_; - - EXPECT_TRUE(buf_.OnData(data.data(), data.size())); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::UNBUFFERED); - - EXPECT_TRUE(buf_.OnEnd()); - EXPECT_EQ(state(), State::COMPLETE); - EXPECT_EQ(backing(), Backing::UNBUFFERED); - EXPECT_EQ(0u, buf_.BufferedLength()); - EXPECT_TRUE(VerifyLogHasSubstrs( - {"state=COMPLETE", "backing=UNBUFFERED", "value: some text."})); - - // We expect that the string buffer points to the passed in Http2StringPiece's - // backing store. - EXPECT_EQ(data.data(), buf_.str().data()); - - // Now force it to buffer the string, after which it will still have the same - // string value, but the backing store will be different. - buf_.BufferStringIfUnbuffered(); - LOG(INFO) << buf_; - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(buf_.BufferedLength(), data.size()); - EXPECT_EQ(data, buf_.str()); - EXPECT_NE(data.data(), buf_.str().data()); - EXPECT_TRUE(VerifyLogHasSubstrs( - {"state=COMPLETE", "backing=BUFFERED", "buffer: some text."})); -} - -TEST_F(HpackDecoderStringBufferTest, PlainSplit) { - Http2StringPiece data("some text."); - Http2StringPiece part1 = data.substr(0, 1); - Http2StringPiece part2 = data.substr(1); - - EXPECT_EQ(state(), State::RESET); - buf_.OnStart(/*huffman_encoded*/ false, data.size()); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::RESET); - - // OnData with only a part of the data, not the whole, so buf_ will buffer - // the data. - EXPECT_TRUE(buf_.OnData(part1.data(), part1.size())); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(buf_.BufferedLength(), part1.size()); - LOG(INFO) << buf_; - - EXPECT_TRUE(buf_.OnData(part2.data(), part2.size())); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(buf_.BufferedLength(), data.size()); - - EXPECT_TRUE(buf_.OnEnd()); - EXPECT_EQ(state(), State::COMPLETE); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(buf_.BufferedLength(), data.size()); - LOG(INFO) << buf_; - - Http2StringPiece buffered = buf_.str(); - EXPECT_EQ(data, buffered); - EXPECT_NE(data.data(), buffered.data()); - - // The string is already buffered, so BufferStringIfUnbuffered should not make - // any change. - buf_.BufferStringIfUnbuffered(); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(buf_.BufferedLength(), data.size()); - EXPECT_EQ(buffered, buf_.str()); - EXPECT_EQ(buffered.data(), buf_.str().data()); -} - -TEST_F(HpackDecoderStringBufferTest, HuffmanWhole) { - Http2String encoded = Http2HexDecode("f1e3c2e5f23a6ba0ab90f4ff"); - Http2StringPiece decoded("www.example.com"); - - EXPECT_EQ(state(), State::RESET); - buf_.OnStart(/*huffman_encoded*/ true, encoded.size()); - EXPECT_EQ(state(), State::COLLECTING); - - EXPECT_TRUE(buf_.OnData(encoded.data(), encoded.size())); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::BUFFERED); - - EXPECT_TRUE(buf_.OnEnd()); - EXPECT_EQ(state(), State::COMPLETE); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(buf_.BufferedLength(), decoded.size()); - EXPECT_EQ(decoded, buf_.str()); - EXPECT_TRUE(VerifyLogHasSubstrs( - {"{state=COMPLETE", "backing=BUFFERED", "buffer: www.example.com}"})); - - Http2String s = buf_.ReleaseString(); - EXPECT_EQ(s, decoded); - EXPECT_EQ(state(), State::RESET); -} - -TEST_F(HpackDecoderStringBufferTest, HuffmanSplit) { - Http2String encoded = Http2HexDecode("f1e3c2e5f23a6ba0ab90f4ff"); - Http2String part1 = encoded.substr(0, 5); - Http2String part2 = encoded.substr(5); - Http2StringPiece decoded("www.example.com"); - - EXPECT_EQ(state(), State::RESET); - buf_.OnStart(/*huffman_encoded*/ true, encoded.size()); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(0u, buf_.BufferedLength()); - LOG(INFO) << buf_; - - EXPECT_TRUE(buf_.OnData(part1.data(), part1.size())); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_GT(buf_.BufferedLength(), 0u); - EXPECT_LT(buf_.BufferedLength(), decoded.size()); - LOG(INFO) << buf_; - - EXPECT_TRUE(buf_.OnData(part2.data(), part2.size())); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(buf_.BufferedLength(), decoded.size()); - LOG(INFO) << buf_; - - EXPECT_TRUE(buf_.OnEnd()); - EXPECT_EQ(state(), State::COMPLETE); - EXPECT_EQ(backing(), Backing::BUFFERED); - EXPECT_EQ(buf_.BufferedLength(), decoded.size()); - EXPECT_EQ(decoded, buf_.str()); - LOG(INFO) << buf_; - - buf_.Reset(); - EXPECT_EQ(state(), State::RESET); - LOG(INFO) << buf_; -} - -TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnData) { - // Explicitly encode the End-of-String symbol, a no-no. - Http2String encoded = Http2HexDecode("ffffffff"); - - buf_.OnStart(/*huffman_encoded*/ true, encoded.size()); - EXPECT_EQ(state(), State::COLLECTING); - - EXPECT_FALSE(buf_.OnData(encoded.data(), encoded.size())); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::BUFFERED); - - LOG(INFO) << buf_; -} - -TEST_F(HpackDecoderStringBufferTest, InvalidHuffmanOnEnd) { - // Last byte of string doesn't end with prefix of End-of-String symbol. - Http2String encoded = Http2HexDecode("00"); - - buf_.OnStart(/*huffman_encoded*/ true, encoded.size()); - EXPECT_EQ(state(), State::COLLECTING); - - EXPECT_TRUE(buf_.OnData(encoded.data(), encoded.size())); - EXPECT_EQ(state(), State::COLLECTING); - EXPECT_EQ(backing(), Backing::BUFFERED); - - EXPECT_FALSE(buf_.OnEnd()); - LOG(INFO) << buf_; -} - -// TODO(jamessynge): Add tests for ReleaseString(). - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_decoder_tables.cc b/net/third_party/http2/hpack/decoder/hpack_decoder_tables.cc deleted file mode 100644 index 3ab13c6..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_decoder_tables.cc +++ /dev/null
@@ -1,153 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_decoder_tables.h" - -#include "base/logging.h" -#include "net/third_party/http2/hpack/http2_hpack_constants.h" - -namespace http2 { -namespace { - -std::vector<HpackStringPair>* MakeStaticTable() { - auto* ptr = new std::vector<HpackStringPair>(); - ptr->reserve(kFirstDynamicTableIndex); - ptr->emplace_back("", ""); - -#define STATIC_TABLE_ENTRY(name, value, index) \ - DCHECK_EQ(ptr->size(), index); \ - ptr->emplace_back(name, value) - -#include "net/third_party/http2/hpack/hpack_static_table_entries.inc" - -#undef STATIC_TABLE_ENTRY - - return ptr; -} - -const std::vector<HpackStringPair>* GetStaticTable() { - static const std::vector<HpackStringPair>* const g_static_table = - MakeStaticTable(); - return g_static_table; -} - -} // namespace - -HpackDecoderTablesDebugListener::HpackDecoderTablesDebugListener() = default; -HpackDecoderTablesDebugListener::~HpackDecoderTablesDebugListener() = default; - -HpackDecoderStaticTable::HpackDecoderStaticTable( - const std::vector<HpackStringPair>* table) - : table_(table) {} - -HpackDecoderStaticTable::HpackDecoderStaticTable() : table_(GetStaticTable()) {} - -const HpackStringPair* HpackDecoderStaticTable::Lookup(size_t index) const { - if (0 < index && index < kFirstDynamicTableIndex) { - return &((*table_)[index]); - } - return nullptr; -} - -HpackDecoderDynamicTable::HpackDecoderTableEntry::HpackDecoderTableEntry( - const HpackString& name, - const HpackString& value) - : HpackStringPair(name, value) {} - -HpackDecoderDynamicTable::HpackDecoderDynamicTable() - : insert_count_(kFirstDynamicTableIndex - 1), debug_listener_(nullptr) {} -HpackDecoderDynamicTable::~HpackDecoderDynamicTable() = default; - -void HpackDecoderDynamicTable::DynamicTableSizeUpdate(size_t size_limit) { - DVLOG(3) << "HpackDecoderDynamicTable::DynamicTableSizeUpdate " << size_limit; - EnsureSizeNoMoreThan(size_limit); - DCHECK_LE(current_size_, size_limit); - size_limit_ = size_limit; -} - -// TODO(jamessynge): Check somewhere before here that names received from the -// peer are valid (e.g. are lower-case, no whitespace, etc.). -bool HpackDecoderDynamicTable::Insert(const HpackString& name, - const HpackString& value) { - HpackDecoderTableEntry entry(name, value); - size_t entry_size = entry.size(); - DVLOG(2) << "InsertEntry of size=" << entry_size << "\n name: " << name - << "\n value: " << value; - if (entry_size > size_limit_) { - DVLOG(2) << "InsertEntry: entry larger than table, removing " - << table_.size() << " entries, of total size " << current_size_ - << " bytes."; - table_.clear(); - current_size_ = 0; - return false; // Not inserted because too large. - } - ++insert_count_; - if (debug_listener_ != nullptr) { - entry.time_added = debug_listener_->OnEntryInserted(entry, insert_count_); - DVLOG(2) << "OnEntryInserted returned time_added=" << entry.time_added - << " for insert_count_=" << insert_count_; - } - size_t insert_limit = size_limit_ - entry_size; - EnsureSizeNoMoreThan(insert_limit); - table_.push_front(entry); - current_size_ += entry_size; - DVLOG(2) << "InsertEntry: current_size_=" << current_size_; - DCHECK_GE(current_size_, entry_size); - DCHECK_LE(current_size_, size_limit_); - return true; -} - -const HpackStringPair* HpackDecoderDynamicTable::Lookup(size_t index) const { - if (index < table_.size()) { - const HpackDecoderTableEntry& entry = table_[index]; - if (debug_listener_ != nullptr) { - size_t insert_count_of_index = insert_count_ + table_.size() - index; - debug_listener_->OnUseEntry(entry, insert_count_of_index, - entry.time_added); - } - return &entry; - } - return nullptr; -} - -void HpackDecoderDynamicTable::EnsureSizeNoMoreThan(size_t limit) { - DVLOG(2) << "EnsureSizeNoMoreThan limit=" << limit - << ", current_size_=" << current_size_; - // Not the most efficient choice, but any easy way to start. - while (current_size_ > limit) { - RemoveLastEntry(); - } - DCHECK_LE(current_size_, limit); -} - -void HpackDecoderDynamicTable::RemoveLastEntry() { - DCHECK(!table_.empty()); - if (!table_.empty()) { - DVLOG(2) << "RemoveLastEntry current_size_=" << current_size_ - << ", last entry size=" << table_.back().size(); - DCHECK_GE(current_size_, table_.back().size()); - current_size_ -= table_.back().size(); - table_.pop_back(); - // Empty IFF current_size_ == 0. - DCHECK_EQ(table_.empty(), current_size_ == 0); - } -} - -HpackDecoderTables::HpackDecoderTables() = default; -HpackDecoderTables::~HpackDecoderTables() = default; - -void HpackDecoderTables::set_debug_listener( - HpackDecoderTablesDebugListener* debug_listener) { - dynamic_table_.set_debug_listener(debug_listener); -} - -const HpackStringPair* HpackDecoderTables::Lookup(size_t index) const { - if (index < kFirstDynamicTableIndex) { - return static_table_.Lookup(index); - } else { - return dynamic_table_.Lookup(index - kFirstDynamicTableIndex); - } -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_decoder_tables.h b/net/third_party/http2/hpack/decoder/hpack_decoder_tables.h deleted file mode 100644 index fe9da6c0..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_decoder_tables.h +++ /dev/null
@@ -1,197 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_DECODER_TABLES_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_DECODER_TABLES_H_ - -// Static and dynamic tables for the HPACK decoder. See: -// http://httpwg.org/specs/rfc7541.html#indexing.tables - -// Note that the Lookup methods return nullptr if the requested index was not -// found. This should be treated as a COMPRESSION error according to the HTTP/2 -// spec, which is a connection level protocol error (i.e. the connection must -// be terminated). See these sections in the two RFCs: -// http://httpwg.org/specs/rfc7541.html#indexed.header.representation -// http://httpwg.org/specs/rfc7541.html#index.address.space -// http://httpwg.org/specs/rfc7540.html#HeaderBlock - -#include <stddef.h> - -#include <cstdint> -#include <vector> - -#include "net/third_party/http2/hpack/hpack_string.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/platform/api/http2_containers.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { -namespace test { -class HpackDecoderTablesPeer; -} // namespace test - -// HpackDecoderTablesDebugListener supports a QUIC experiment, enabling -// the gathering of information about the time-line of use of HPACK -// dynamic table entries. -class HTTP2_EXPORT_PRIVATE HpackDecoderTablesDebugListener { - public: - HpackDecoderTablesDebugListener(); - virtual ~HpackDecoderTablesDebugListener(); - - HpackDecoderTablesDebugListener(const HpackDecoderTablesDebugListener&) = - delete; - HpackDecoderTablesDebugListener& operator=( - const HpackDecoderTablesDebugListener&) = delete; - - // The entry has been inserted into the dynamic table. insert_count starts at - // 62 because 61 is the last index in the static table; insert_count increases - // by 1 with each insert into the dynamic table; it is not incremented when - // when a entry is too large to fit into the dynamic table at all (which has - // the effect of emptying the dynamic table). - // Returns a value that can be used as time_added in OnUseEntry. - virtual int64_t OnEntryInserted(const HpackStringPair& entry, - size_t insert_count) = 0; - - // The entry has been used, either for the name or for the name and value. - // insert_count is the same as passed to OnEntryInserted when entry was - // inserted to the dynamic table, and time_added is the value that was - // returned by OnEntryInserted. - virtual void OnUseEntry(const HpackStringPair& entry, - size_t insert_count, - int64_t time_added) = 0; -}; - -// See http://httpwg.org/specs/rfc7541.html#static.table.definition for the -// contents, and http://httpwg.org/specs/rfc7541.html#index.address.space for -// info about accessing the static table. -class HTTP2_EXPORT_PRIVATE HpackDecoderStaticTable { - public: - explicit HpackDecoderStaticTable(const std::vector<HpackStringPair>* table); - // Uses a global table shared by all threads. - HpackDecoderStaticTable(); - - // If index is valid, returns a pointer to the entry, otherwise returns - // nullptr. - const HpackStringPair* Lookup(size_t index) const; - - private: - friend class test::HpackDecoderTablesPeer; - const std::vector<HpackStringPair>* const table_; -}; - -// HpackDecoderDynamicTable implements HPACK compression feature "indexed -// headers"; previously sent headers may be referenced later by their index -// in the dynamic table. See these sections of the RFC: -// http://httpwg.org/specs/rfc7541.html#dynamic.table -// http://httpwg.org/specs/rfc7541.html#dynamic.table.management -class HTTP2_EXPORT_PRIVATE HpackDecoderDynamicTable { - public: - HpackDecoderDynamicTable(); - ~HpackDecoderDynamicTable(); - - HpackDecoderDynamicTable(const HpackDecoderDynamicTable&) = delete; - HpackDecoderDynamicTable& operator=(const HpackDecoderDynamicTable&) = delete; - - // Set the listener to be notified of insertions into this table, and later - // uses of those entries. Added for evaluation of changes to QUIC's use - // of HPACK. - void set_debug_listener(HpackDecoderTablesDebugListener* debug_listener) { - debug_listener_ = debug_listener; - } - - // Sets a new size limit, received from the peer; performs evictions if - // necessary to ensure that the current size does not exceed the new limit. - // The caller needs to have validated that size_limit does not - // exceed the acknowledged value of SETTINGS_HEADER_TABLE_SIZE. - void DynamicTableSizeUpdate(size_t size_limit); - - // Returns true if inserted, false if too large (at which point the - // dynamic table will be empty.) - bool Insert(const HpackString& name, const HpackString& value); - - // If index is valid, returns a pointer to the entry, otherwise returns - // nullptr. - const HpackStringPair* Lookup(size_t index) const; - - size_t size_limit() const { return size_limit_; } - size_t current_size() const { return current_size_; } - - private: - friend class test::HpackDecoderTablesPeer; - struct HpackDecoderTableEntry : public HpackStringPair { - HpackDecoderTableEntry(const HpackString& name, const HpackString& value); - int64_t time_added; - }; - - // Drop older entries to ensure the size is not greater than limit. - void EnsureSizeNoMoreThan(size_t limit); - - // Removes the oldest dynamic table entry. - void RemoveLastEntry(); - - Http2Deque<HpackDecoderTableEntry> table_; - - // The last received DynamicTableSizeUpdate value, initialized to - // SETTINGS_HEADER_TABLE_SIZE. - size_t size_limit_ = Http2SettingsInfo::DefaultHeaderTableSize(); - - size_t current_size_ = 0; - - // insert_count_ and debug_listener_ are used by a QUIC experiment; remove - // when the experiment is done. - size_t insert_count_; - HpackDecoderTablesDebugListener* debug_listener_; -}; - -class HTTP2_EXPORT_PRIVATE HpackDecoderTables { - public: - HpackDecoderTables(); - ~HpackDecoderTables(); - - HpackDecoderTables(const HpackDecoderTables&) = delete; - HpackDecoderTables& operator=(const HpackDecoderTables&) = delete; - - // Set the listener to be notified of insertions into the dynamic table, and - // later uses of those entries. Added for evaluation of changes to QUIC's use - // of HPACK. - void set_debug_listener(HpackDecoderTablesDebugListener* debug_listener); - - // Sets a new size limit, received from the peer; performs evictions if - // necessary to ensure that the current size does not exceed the new limit. - // The caller needs to have validated that size_limit does not - // exceed the acknowledged value of SETTINGS_HEADER_TABLE_SIZE. - void DynamicTableSizeUpdate(size_t size_limit) { - dynamic_table_.DynamicTableSizeUpdate(size_limit); - } - - // Returns true if inserted, false if too large (at which point the - // dynamic table will be empty.) - // TODO(jamessynge): Add methods for moving the string(s) into the table, - // or for otherwise avoiding unnecessary copies. - bool Insert(const HpackString& name, const HpackString& value) { - return dynamic_table_.Insert(name, value); - } - - // If index is valid, returns a pointer to the entry, otherwise returns - // nullptr. - const HpackStringPair* Lookup(size_t index) const; - - // The size limit that the peer (the HPACK encoder) has told the decoder it is - // currently operating with. Defaults to SETTINGS_HEADER_TABLE_SIZE, 4096. - size_t header_table_size_limit() const { return dynamic_table_.size_limit(); } - - // Sum of the sizes of the dynamic table entries. - size_t current_header_table_size() const { - return dynamic_table_.current_size(); - } - - private: - friend class test::HpackDecoderTablesPeer; - HpackDecoderStaticTable static_table_; - HpackDecoderDynamicTable dynamic_table_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_DECODER_TABLES_H_
diff --git a/net/third_party/http2/hpack/decoder/hpack_decoder_tables_test.cc b/net/third_party/http2/hpack/decoder/hpack_decoder_tables_test.cc deleted file mode 100644 index f7be363..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_decoder_tables_test.cc +++ /dev/null
@@ -1,266 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_decoder_tables.h" - -#include <algorithm> -#include <tuple> -#include <vector> - -#include "base/logging.h" -#include "net/third_party/http2/hpack/http2_hpack_constants.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/random_util.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; - -namespace http2 { -namespace test { -class HpackDecoderTablesPeer { - public: - static size_t num_dynamic_entries(const HpackDecoderTables& tables) { - return tables.dynamic_table_.table_.size(); - } -}; - -namespace { -struct StaticEntry { - const char* name; - const char* value; - size_t index; -}; - -std::vector<StaticEntry> MakeSpecStaticEntries() { - std::vector<StaticEntry> static_entries; - -#define STATIC_TABLE_ENTRY(name, value, index) \ - DCHECK_EQ(static_entries.size() + 1, index); \ - static_entries.push_back({name, value, index}); - -#include "net/third_party/http2/hpack/hpack_static_table_entries.inc" - -#undef STATIC_TABLE_ENTRY - - return static_entries; -} - -template <class C> -void ShuffleCollection(C* collection, Http2Random* r) { - std::shuffle(collection->begin(), collection->end(), *r); -} - -class HpackDecoderStaticTableTest : public ::testing::Test { - protected: - HpackDecoderStaticTableTest() = default; - - std::vector<StaticEntry> shuffled_static_entries() { - std::vector<StaticEntry> entries = MakeSpecStaticEntries(); - ShuffleCollection(&entries, &random_); - return entries; - } - - // This test is in a function so that it can be applied to both the static - // table and the combined static+dynamic tables. - AssertionResult VerifyStaticTableContents() { - for (const auto& expected : shuffled_static_entries()) { - const HpackStringPair* found = Lookup(expected.index); - VERIFY_NE(found, nullptr); - VERIFY_EQ(expected.name, found->name) << expected.index; - VERIFY_EQ(expected.value, found->value) << expected.index; - } - - // There should be no entry with index 0. - VERIFY_EQ(nullptr, Lookup(0)); - return AssertionSuccess(); - } - - virtual const HpackStringPair* Lookup(size_t index) { - return static_table_.Lookup(index); - } - - Http2Random* RandomPtr() { return &random_; } - - Http2Random random_; - - private: - HpackDecoderStaticTable static_table_; -}; - -TEST_F(HpackDecoderStaticTableTest, StaticTableContents) { - EXPECT_TRUE(VerifyStaticTableContents()); -} - -size_t Size(const Http2String& name, const Http2String& value) { - return name.size() + value.size() + 32; -} - -// To support tests with more than a few of hand crafted changes to the dynamic -// table, we have another, exceedingly simple, implementation of the HPACK -// dynamic table containing FakeHpackEntry instances. We can thus compare the -// contents of the actual table with those in fake_dynamic_table_. - -typedef std::tuple<Http2String, Http2String, size_t> FakeHpackEntry; -const Http2String& Name(const FakeHpackEntry& entry) { - return std::get<0>(entry); -} -const Http2String& Value(const FakeHpackEntry& entry) { - return std::get<1>(entry); -} -size_t Size(const FakeHpackEntry& entry) { - return std::get<2>(entry); -} - -class HpackDecoderTablesTest : public HpackDecoderStaticTableTest { - protected: - const HpackStringPair* Lookup(size_t index) override { - return tables_.Lookup(index); - } - - size_t dynamic_size_limit() const { - return tables_.header_table_size_limit(); - } - size_t current_dynamic_size() const { - return tables_.current_header_table_size(); - } - size_t num_dynamic_entries() const { - return HpackDecoderTablesPeer::num_dynamic_entries(tables_); - } - - // Insert the name and value into fake_dynamic_table_. - void FakeInsert(const Http2String& name, const Http2String& value) { - FakeHpackEntry entry(name, value, Size(name, value)); - fake_dynamic_table_.insert(fake_dynamic_table_.begin(), entry); - } - - // Add up the size of all entries in fake_dynamic_table_. - size_t FakeSize() { - size_t sz = 0; - for (const auto& entry : fake_dynamic_table_) { - sz += Size(entry); - } - return sz; - } - - // If the total size of the fake_dynamic_table_ is greater than limit, - // keep the first N entries such that those N entries have a size not - // greater than limit, and such that keeping entry N+1 would have a size - // greater than limit. Returns the count of removed bytes. - size_t FakeTrim(size_t limit) { - size_t original_size = FakeSize(); - size_t total_size = 0; - for (size_t ndx = 0; ndx < fake_dynamic_table_.size(); ++ndx) { - total_size += Size(fake_dynamic_table_[ndx]); - if (total_size > limit) { - // Need to get rid of ndx and all following entries. - fake_dynamic_table_.erase(fake_dynamic_table_.begin() + ndx, - fake_dynamic_table_.end()); - return original_size - FakeSize(); - } - } - return 0; - } - - // Verify that the contents of the actual dynamic table match those in - // fake_dynamic_table_. - AssertionResult VerifyDynamicTableContents() { - VERIFY_EQ(current_dynamic_size(), FakeSize()); - VERIFY_EQ(num_dynamic_entries(), fake_dynamic_table_.size()); - - for (size_t ndx = 0; ndx < fake_dynamic_table_.size(); ++ndx) { - const HpackStringPair* found = Lookup(ndx + kFirstDynamicTableIndex); - VERIFY_NE(found, nullptr); - - const auto& expected = fake_dynamic_table_[ndx]; - VERIFY_EQ(Name(expected), found->name); - VERIFY_EQ(Value(expected), found->value); - } - - // Make sure there are no more entries. - VERIFY_EQ(nullptr, - Lookup(fake_dynamic_table_.size() + kFirstDynamicTableIndex)); - return AssertionSuccess(); - } - - // Apply an update to the limit on the maximum size of the dynamic table. - AssertionResult DynamicTableSizeUpdate(size_t size_limit) { - VERIFY_EQ(current_dynamic_size(), FakeSize()); - if (size_limit < current_dynamic_size()) { - // Will need to trim the dynamic table's oldest entries. - tables_.DynamicTableSizeUpdate(size_limit); - FakeTrim(size_limit); - return VerifyDynamicTableContents(); - } - // Shouldn't change the size. - tables_.DynamicTableSizeUpdate(size_limit); - return VerifyDynamicTableContents(); - } - - // Insert an entry into the dynamic table, confirming that trimming of entries - // occurs if the total size is greater than the limit, and that older entries - // move up by 1 index. - AssertionResult Insert(const Http2String& name, const Http2String& value) { - size_t old_count = num_dynamic_entries(); - if (tables_.Insert(HpackString(name), HpackString(value))) { - VERIFY_GT(current_dynamic_size(), 0u); - VERIFY_GT(num_dynamic_entries(), 0u); - } else { - VERIFY_EQ(current_dynamic_size(), 0u); - VERIFY_EQ(num_dynamic_entries(), 0u); - } - FakeInsert(name, value); - VERIFY_EQ(old_count + 1, fake_dynamic_table_.size()); - FakeTrim(dynamic_size_limit()); - VERIFY_EQ(current_dynamic_size(), FakeSize()); - VERIFY_EQ(num_dynamic_entries(), fake_dynamic_table_.size()); - return VerifyDynamicTableContents(); - } - - private: - HpackDecoderTables tables_; - - std::vector<FakeHpackEntry> fake_dynamic_table_; -}; - -TEST_F(HpackDecoderTablesTest, StaticTableContents) { - EXPECT_TRUE(VerifyStaticTableContents()); -} - -// Generate a bunch of random header entries, insert them, and confirm they -// present, as required by the RFC, using VerifyDynamicTableContents above on -// each Insert. Also apply various resizings of the dynamic table. -TEST_F(HpackDecoderTablesTest, RandomDynamicTable) { - EXPECT_EQ(0u, current_dynamic_size()); - EXPECT_TRUE(VerifyStaticTableContents()); - EXPECT_TRUE(VerifyDynamicTableContents()); - - std::vector<size_t> table_sizes; - table_sizes.push_back(dynamic_size_limit()); - table_sizes.push_back(0); - table_sizes.push_back(dynamic_size_limit() / 2); - table_sizes.push_back(dynamic_size_limit()); - table_sizes.push_back(dynamic_size_limit() / 2); - table_sizes.push_back(0); - table_sizes.push_back(dynamic_size_limit()); - - for (size_t limit : table_sizes) { - ASSERT_TRUE(DynamicTableSizeUpdate(limit)); - for (int insert_count = 0; insert_count < 100; ++insert_count) { - Http2String name = - GenerateHttp2HeaderName(random_.UniformInRange(2, 40), RandomPtr()); - Http2String value = - GenerateWebSafeString(random_.UniformInRange(2, 600), RandomPtr()); - ASSERT_TRUE(Insert(name, value)); - } - EXPECT_TRUE(VerifyStaticTableContents()); - } -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_decoder_test.cc b/net/third_party/http2/hpack/decoder/hpack_decoder_test.cc deleted file mode 100644 index 99aec80..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_decoder_test.cc +++ /dev/null
@@ -1,1219 +0,0 @@ -// Copyright 2017 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 "net/third_party/http2/hpack/decoder/hpack_decoder.h" - -// Tests of HpackDecoder. - -#include <tuple> -#include <utility> -#include <vector> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/hpack/decoder/hpack_decoder_listener.h" -#include "net/third_party/http2/hpack/decoder/hpack_decoder_state.h" -#include "net/third_party/http2/hpack/decoder/hpack_decoder_tables.h" -#include "net/third_party/http2/hpack/hpack_string.h" -#include "net/third_party/http2/hpack/http2_hpack_constants.h" -#include "net/third_party/http2/hpack/tools/hpack_block_builder.h" -#include "net/third_party/http2/hpack/tools/hpack_example.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/random_util.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionFailure; -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; -using ::testing::ElementsAreArray; -using ::testing::HasSubstr; - -namespace http2 { -namespace test { -class HpackDecoderStatePeer { - public: - static HpackDecoderTables* GetDecoderTables(HpackDecoderState* state) { - return &state->decoder_tables_; - } - static void set_listener(HpackDecoderState* state, - HpackDecoderListener* listener) { - state->listener_ = listener; - } -}; -class HpackDecoderPeer { - public: - static HpackDecoderState* GetDecoderState(HpackDecoder* decoder) { - return &decoder->decoder_state_; - } - static HpackDecoderTables* GetDecoderTables(HpackDecoder* decoder) { - return HpackDecoderStatePeer::GetDecoderTables(GetDecoderState(decoder)); - } -}; - -namespace { - -typedef std::tuple<HpackEntryType, Http2String, Http2String> HpackHeaderEntry; -typedef std::vector<HpackHeaderEntry> HpackHeaderEntries; - -// TODO(jamessynge): Create a ...test_utils.h file with the mock listener -// and with VerifyDynamicTableContents. -class MockHpackDecoderListener : public HpackDecoderListener { - public: - MOCK_METHOD0(OnHeaderListStart, void()); - MOCK_METHOD3(OnHeader, - void(HpackEntryType entry_type, - const HpackString& name, - const HpackString& value)); - MOCK_METHOD0(OnHeaderListEnd, void()); - MOCK_METHOD1(OnHeaderErrorDetected, void(Http2StringPiece error_message)); -}; - -class HpackDecoderTest : public ::testing::TestWithParam<bool>, - public HpackDecoderListener { - protected: - // Note that we initialize the random number generator with the same seed - // for each individual test, therefore the order in which the tests are - // executed does not effect the sequence produced by the RNG within any - // one test. - HpackDecoderTest() : decoder_(this, 4096) { - fragment_the_hpack_block_ = GetParam(); - } - ~HpackDecoderTest() override = default; - - void OnHeaderListStart() override { - ASSERT_FALSE(saw_start_); - ASSERT_FALSE(saw_end_); - saw_start_ = true; - header_entries_.clear(); - } - - // Called for each header name-value pair that is decoded, in the order they - // appear in the HPACK block. Multiple values for a given key will be emitted - // as multiple calls to OnHeader. - void OnHeader(HpackEntryType entry_type, - const HpackString& name, - const HpackString& value) override { - ASSERT_TRUE(saw_start_); - ASSERT_FALSE(saw_end_); - // header_entries_.push_back({entry_type, name.ToString(), - // value.ToString()}); - header_entries_.emplace_back(entry_type, name.ToString(), value.ToString()); - } - - // OnHeaderBlockEnd is called after successfully decoding an HPACK block. Will - // only be called once per block, even if it extends into CONTINUATION frames. - // A callback method which notifies when the parser finishes handling a - // header block (i.e. the containing frame has the END_STREAM flag set). - // Also indicates the total number of bytes in this block. - void OnHeaderListEnd() override { - ASSERT_TRUE(saw_start_); - ASSERT_FALSE(saw_end_); - ASSERT_TRUE(error_messages_.empty()); - saw_end_ = true; - } - - // OnHeaderErrorDetected is called if an error is detected while decoding. - // error_message may be used in a GOAWAY frame as the Opaque Data. - void OnHeaderErrorDetected(Http2StringPiece error_message) override { - ASSERT_TRUE(saw_start_); - error_messages_.push_back(Http2String(error_message)); - // No further callbacks should be made at this point, so replace 'this' as - // the listener with mock_listener_, which is a strict mock, so will - // generate an error for any calls. - HpackDecoderStatePeer::set_listener( - HpackDecoderPeer::GetDecoderState(&decoder_), &mock_listener_); - } - - AssertionResult DecodeBlock(Http2StringPiece block) { - VLOG(1) << "HpackDecoderTest::DecodeBlock"; - - VERIFY_FALSE(decoder_.error_detected()); - VERIFY_TRUE(error_messages_.empty()); - VERIFY_FALSE(saw_start_); - VERIFY_FALSE(saw_end_); - header_entries_.clear(); - - VERIFY_FALSE(decoder_.error_detected()); - VERIFY_TRUE(decoder_.StartDecodingBlock()); - VERIFY_FALSE(decoder_.error_detected()); - - if (fragment_the_hpack_block_) { - // See note in ctor regarding RNG. - while (!block.empty()) { - size_t fragment_size = random_.RandomSizeSkewedLow(block.size()); - DecodeBuffer db(block.substr(0, fragment_size)); - VERIFY_TRUE(decoder_.DecodeFragment(&db)); - VERIFY_EQ(0u, db.Remaining()); - block.remove_prefix(fragment_size); - } - } else { - DecodeBuffer db(block); - VERIFY_TRUE(decoder_.DecodeFragment(&db)); - VERIFY_EQ(0u, db.Remaining()); - } - VERIFY_FALSE(decoder_.error_detected()); - - VERIFY_TRUE(decoder_.EndDecodingBlock()); - if (saw_end_) { - VERIFY_FALSE(decoder_.error_detected()); - VERIFY_TRUE(error_messages_.empty()); - } else { - VERIFY_TRUE(decoder_.error_detected()); - VERIFY_FALSE(error_messages_.empty()); - } - - saw_start_ = saw_end_ = false; - return AssertionSuccess(); - } - - const HpackDecoderTables& GetDecoderTables() { - return *HpackDecoderPeer::GetDecoderTables(&decoder_); - } - const HpackStringPair* Lookup(size_t index) { - return GetDecoderTables().Lookup(index); - } - size_t current_header_table_size() { - return GetDecoderTables().current_header_table_size(); - } - size_t header_table_size_limit() { - return GetDecoderTables().header_table_size_limit(); - } - void set_header_table_size_limit(size_t size) { - HpackDecoderPeer::GetDecoderTables(&decoder_)->DynamicTableSizeUpdate(size); - } - - // dynamic_index is one-based, because that is the way RFC 7541 shows it. - AssertionResult VerifyEntry(size_t dynamic_index, - const char* name, - const char* value) { - const HpackStringPair* entry = - Lookup(dynamic_index + kFirstDynamicTableIndex - 1); - VERIFY_NE(entry, nullptr); - VERIFY_EQ(entry->name.ToStringPiece(), name); - VERIFY_EQ(entry->value.ToStringPiece(), value); - return AssertionSuccess(); - } - AssertionResult VerifyNoEntry(size_t dynamic_index) { - const HpackStringPair* entry = - Lookup(dynamic_index + kFirstDynamicTableIndex - 1); - VERIFY_EQ(entry, nullptr); - return AssertionSuccess(); - } - AssertionResult VerifyDynamicTableContents( - const std::vector<std::pair<const char*, const char*>>& entries) { - size_t index = 1; - for (const auto& entry : entries) { - VERIFY_SUCCESS(VerifyEntry(index, entry.first, entry.second)); - ++index; - } - VERIFY_SUCCESS(VerifyNoEntry(index)); - return AssertionSuccess(); - } - - Http2Random random_; - HpackDecoder decoder_; - testing::StrictMock<MockHpackDecoderListener> mock_listener_; - HpackHeaderEntries header_entries_; - std::vector<Http2String> error_messages_; - bool fragment_the_hpack_block_; - bool saw_start_ = false; - bool saw_end_ = false; -}; -INSTANTIATE_TEST_CASE_P(AllWays, HpackDecoderTest, ::testing::Bool()); - -// Test based on RFC 7541, section C.3: Request Examples without Huffman Coding. -// This section shows several consecutive header lists, corresponding to HTTP -// requests, on the same connection. -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.3 -TEST_P(HpackDecoderTest, C3_RequestExamples) { - // C.3.1 First Request - Http2String hpack_block = HpackExampleToStringOrDie(R"( - 82 | == Indexed - Add == - | idx = 2 - | -> :method: GET - 86 | == Indexed - Add == - | idx = 6 - | -> :scheme: http - 84 | == Indexed - Add == - | idx = 4 - | -> :path: / - 41 | == Literal indexed == - | Indexed name (idx = 1) - | :authority - 0f | Literal value (len = 15) - 7777 772e 6578 616d 706c 652e 636f 6d | www.example.com - | -> :authority: - | www.example.com - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT( - header_entries_, - ElementsAreArray({ - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":method", "GET"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":scheme", "http"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":path", "/"}, - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, ":authority", - "www.example.com"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 57) :authority: www.example.com - // Table size: 57 - ASSERT_TRUE(VerifyDynamicTableContents({{":authority", "www.example.com"}})); - ASSERT_EQ(57u, current_header_table_size()); - - // C.3.2 Second Request - hpack_block = HpackExampleToStringOrDie(R"( - 82 | == Indexed - Add == - | idx = 2 - | -> :method: GET - 86 | == Indexed - Add == - | idx = 6 - | -> :scheme: http - 84 | == Indexed - Add == - | idx = 4 - | -> :path: / - be | == Indexed - Add == - | idx = 62 - | -> :authority: - | www.example.com - 58 | == Literal indexed == - | Indexed name (idx = 24) - | cache-control - 08 | Literal value (len = 8) - 6e6f 2d63 6163 6865 | no-cache - | -> cache-control: no-cache - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT( - header_entries_, - ElementsAreArray({ - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":method", "GET"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":scheme", "http"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":path", "/"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":authority", - "www.example.com"}, - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, - "cache-control", "no-cache"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 53) cache-control: no-cache - // [ 2] (s = 57) :authority: www.example.com - // Table size: 110 - ASSERT_TRUE(VerifyDynamicTableContents( - {{"cache-control", "no-cache"}, {":authority", "www.example.com"}})); - ASSERT_EQ(110u, current_header_table_size()); - - // C.3.2 Third Request - hpack_block = HpackExampleToStringOrDie(R"( - 82 | == Indexed - Add == - | idx = 2 - | -> :method: GET - 87 | == Indexed - Add == - | idx = 7 - | -> :scheme: https - 85 | == Indexed - Add == - | idx = 5 - | -> :path: /index.html - bf | == Indexed - Add == - | idx = 63 - | -> :authority: - | www.example.com - 40 | == Literal indexed == - 0a | Literal name (len = 10) - 6375 7374 6f6d 2d6b 6579 | custom-key - 0c | Literal value (len = 12) - 6375 7374 6f6d 2d76 616c 7565 | custom-value - | -> custom-key: - | custom-value - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT( - header_entries_, - ElementsAreArray({ - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":method", "GET"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":scheme", "https"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":path", - "/index.html"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":authority", - "www.example.com"}, - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, "custom-key", - "custom-value"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 54) custom-key: custom-value - // [ 2] (s = 53) cache-control: no-cache - // [ 3] (s = 57) :authority: www.example.com - // Table size: 164 - ASSERT_TRUE(VerifyDynamicTableContents({{"custom-key", "custom-value"}, - {"cache-control", "no-cache"}, - {":authority", "www.example.com"}})); - ASSERT_EQ(164u, current_header_table_size()); -} - -// Test based on RFC 7541, section C.4 Request Examples with Huffman Coding. -// This section shows the same examples as the previous section but uses -// Huffman encoding for the literal values. -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.4 -TEST_P(HpackDecoderTest, C4_RequestExamplesWithHuffmanEncoding) { - // C.4.1 First Request - Http2String hpack_block = HpackExampleToStringOrDie(R"( - 82 | == Indexed - Add == - | idx = 2 - | -> :method: GET - 86 | == Indexed - Add == - | idx = 6 - | -> :scheme: http - 84 | == Indexed - Add == - | idx = 4 - | -> :path: / - 41 | == Literal indexed == - | Indexed name (idx = 1) - | :authority - 8c | Literal value (len = 12) - | Huffman encoded: - f1e3 c2e5 f23a 6ba0 ab90 f4ff | .....:k..... - | Decoded: - | www.example.com - | -> :authority: - | www.example.com - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT( - header_entries_, - ElementsAreArray({ - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":method", "GET"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":scheme", "http"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":path", "/"}, - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, ":authority", - "www.example.com"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 57) :authority: www.example.com - // Table size: 57 - ASSERT_TRUE(VerifyDynamicTableContents({{":authority", "www.example.com"}})); - ASSERT_EQ(57u, current_header_table_size()); - - // C.4.2 Second Request - hpack_block = HpackExampleToStringOrDie(R"( - 82 | == Indexed - Add == - | idx = 2 - | -> :method: GET - 86 | == Indexed - Add == - | idx = 6 - | -> :scheme: http - 84 | == Indexed - Add == - | idx = 4 - | -> :path: / - be | == Indexed - Add == - | idx = 62 - | -> :authority: - | www.example.com - 58 | == Literal indexed == - | Indexed name (idx = 24) - | cache-control - 86 | Literal value (len = 6) - | Huffman encoded: - a8eb 1064 9cbf | ...d.. - | Decoded: - | no-cache - | -> cache-control: no-cache - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT( - header_entries_, - ElementsAreArray({ - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":method", "GET"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":scheme", "http"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":path", "/"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":authority", - "www.example.com"}, - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, - "cache-control", "no-cache"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 53) cache-control: no-cache - // [ 2] (s = 57) :authority: www.example.com - // Table size: 110 - ASSERT_TRUE(VerifyDynamicTableContents( - {{"cache-control", "no-cache"}, {":authority", "www.example.com"}})); - ASSERT_EQ(110u, current_header_table_size()); - - // C.4.2 Third Request - hpack_block = HpackExampleToStringOrDie(R"( - 82 | == Indexed - Add == - | idx = 2 - | -> :method: GET - 87 | == Indexed - Add == - | idx = 7 - | -> :scheme: https - 85 | == Indexed - Add == - | idx = 5 - | -> :path: /index.html - bf | == Indexed - Add == - | idx = 63 - | -> :authority: - | www.example.com - 40 | == Literal indexed == - 88 | Literal name (len = 8) - | Huffman encoded: - 25a8 49e9 5ba9 7d7f | %.I.[.}. - | Decoded: - | custom-key - 89 | Literal value (len = 9) - | Huffman encoded: - 25a8 49e9 5bb8 e8b4 bf | %.I.[.... - | Decoded: - | custom-value - | -> custom-key: - | custom-value - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT( - header_entries_, - ElementsAreArray({ - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":method", "GET"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":scheme", "https"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":path", - "/index.html"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":authority", - "www.example.com"}, - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, "custom-key", - "custom-value"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 54) custom-key: custom-value - // [ 2] (s = 53) cache-control: no-cache - // [ 3] (s = 57) :authority: www.example.com - // Table size: 164 - ASSERT_TRUE(VerifyDynamicTableContents({{"custom-key", "custom-value"}, - {"cache-control", "no-cache"}, - {":authority", "www.example.com"}})); - ASSERT_EQ(164u, current_header_table_size()); -} - -// Test based on RFC 7541, section C.5: Response Examples without Huffman -// Coding. This section shows several consecutive header lists, corresponding -// to HTTP responses, on the same connection. The HTTP/2 setting parameter -// SETTINGS_HEADER_TABLE_SIZE is set to the value of 256 octets, causing -// some evictions to occur. -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.5 -TEST_P(HpackDecoderTest, C5_ResponseExamples) { - set_header_table_size_limit(256); - - // C.5.1 First Response - // - // Header list to encode: - // - // :status: 302 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:21 GMT - // location: https://www.example.com - - Http2String hpack_block = HpackExampleToStringOrDie(R"( - 48 | == Literal indexed == - | Indexed name (idx = 8) - | :status - 03 | Literal value (len = 3) - 3330 32 | 302 - | -> :status: 302 - 58 | == Literal indexed == - | Indexed name (idx = 24) - | cache-control - 07 | Literal value (len = 7) - 7072 6976 6174 65 | private - | -> cache-control: private - 61 | == Literal indexed == - | Indexed name (idx = 33) - | date - 1d | Literal value (len = 29) - 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013 - 2032 303a 3133 3a32 3120 474d 54 | 20:13:21 GMT - | -> date: Mon, 21 Oct 2013 - | 20:13:21 GMT - 6e | == Literal indexed == - | Indexed name (idx = 46) - | location - 17 | Literal value (len = 23) - 6874 7470 733a 2f2f 7777 772e 6578 616d | https://www.exam - 706c 652e 636f 6d | ple.com - | -> location: - | https://www.example.com - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT(header_entries_, - ElementsAreArray({ - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, - ":status", "302"}, - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, - "cache-control", "private"}, - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, - "date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, - "location", "https://www.example.com"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 63) location: https://www.example.com - // [ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT - // [ 3] (s = 52) cache-control: private - // [ 4] (s = 42) :status: 302 - // Table size: 222 - ASSERT_TRUE( - VerifyDynamicTableContents({{"location", "https://www.example.com"}, - {"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - {"cache-control", "private"}, - {":status", "302"}})); - ASSERT_EQ(222u, current_header_table_size()); - - // C.5.2 Second Response - // - // The (":status", "302") header field is evicted from the dynamic table to - // free space to allow adding the (":status", "307") header field. - // - // Header list to encode: - // - // :status: 307 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:21 GMT - // location: https://www.example.com - - hpack_block = HpackExampleToStringOrDie(R"( - 48 | == Literal indexed == - | Indexed name (idx = 8) - | :status - 03 | Literal value (len = 3) - 3330 37 | 307 - | - evict: :status: 302 - | -> :status: 307 - c1 | == Indexed - Add == - | idx = 65 - | -> cache-control: private - c0 | == Indexed - Add == - | idx = 64 - | -> date: Mon, 21 Oct 2013 - | 20:13:21 GMT - bf | == Indexed - Add == - | idx = 63 - | -> location: - | https://www.example.com - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT(header_entries_, - ElementsAreArray({ - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, - ":status", "307"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, - "cache-control", "private"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, "date", - "Mon, 21 Oct 2013 20:13:21 GMT"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, "location", - "https://www.example.com"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 42) :status: 307 - // [ 2] (s = 63) location: https://www.example.com - // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT - // [ 4] (s = 52) cache-control: private - // Table size: 222 - - ASSERT_TRUE( - VerifyDynamicTableContents({{":status", "307"}, - {"location", "https://www.example.com"}, - {"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - {"cache-control", "private"}})); - ASSERT_EQ(222u, current_header_table_size()); - - // C.5.3 Third Response - // - // Several header fields are evicted from the dynamic table during the - // processing of this header list. - // - // Header list to encode: - // - // :status: 200 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:22 GMT - // location: https://www.example.com - // content-encoding: gzip - // set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1 - hpack_block = HpackExampleToStringOrDie(R"( - 88 | == Indexed - Add == - | idx = 8 - | -> :status: 200 - c1 | == Indexed - Add == - | idx = 65 - | -> cache-control: private - 61 | == Literal indexed == - | Indexed name (idx = 33) - | date - 1d | Literal value (len = 29) - 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013 - 2032 303a 3133 3a32 3220 474d 54 | 20:13:22 GMT - | - evict: cache-control: - | private - | -> date: Mon, 21 Oct 2013 - | 20:13:22 GMT - c0 | == Indexed - Add == - | idx = 64 - | -> location: - | https://www.example.com - 5a | == Literal indexed == - | Indexed name (idx = 26) - | content-encoding - 04 | Literal value (len = 4) - 677a 6970 | gzip - | - evict: date: Mon, 21 Oct - | 2013 20:13:21 GMT - | -> content-encoding: gzip - 77 | == Literal indexed == - | Indexed name (idx = 55) - | set-cookie - 38 | Literal value (len = 56) - 666f 6f3d 4153 444a 4b48 514b 425a 584f | foo=ASDJKHQKBZXO - 5157 454f 5049 5541 5851 5745 4f49 553b | QWEOPIUAXQWEOIU; - 206d 6178 2d61 6765 3d33 3630 303b 2076 | max-age=3600; v - 6572 7369 6f6e 3d31 | ersion=1 - | - evict: location: - | https://www.example.com - | - evict: :status: 307 - | -> set-cookie: foo=ASDJKHQ - | KBZXOQWEOPIUAXQWEOIU; ma - | x-age=3600; version=1 - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT( - header_entries_, - ElementsAreArray({ - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":status", "200"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, "cache-control", - "private"}, - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, "date", - "Mon, 21 Oct 2013 20:13:22 GMT"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, "location", - "https://www.example.com"}, - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, - "content-encoding", "gzip"}, - HpackHeaderEntry{ - HpackEntryType::kIndexedLiteralHeader, "set-cookie", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; - // max-age=3600; version=1 - // [ 2] (s = 52) content-encoding: gzip - // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT - // Table size: 215 - ASSERT_TRUE(VerifyDynamicTableContents( - {{"set-cookie", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"}, - {"content-encoding", "gzip"}, - {"date", "Mon, 21 Oct 2013 20:13:22 GMT"}})); - ASSERT_EQ(215u, current_header_table_size()); -} - -// Test based on RFC 7541, section C.6: Response Examples with Huffman Coding. -// This section shows the same examples as the previous section but uses Huffman -// encoding for the literal values. The HTTP/2 setting parameter -// SETTINGS_HEADER_TABLE_SIZE is set to the value of 256 octets, causing some -// evictions to occur. The eviction mechanism uses the length of the decoded -// literal values, so the same evictions occur as in the previous section. -// http://httpwg.org/specs/rfc7541.html#rfc.section.C.6 -TEST_P(HpackDecoderTest, C6_ResponseExamplesWithHuffmanEncoding) { - set_header_table_size_limit(256); - - // C.5.1 First Response - // - // Header list to encode: - // - // :status: 302 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:21 GMT - // location: https://www.example.com - Http2String hpack_block = HpackExampleToStringOrDie(R"( - 48 | == Literal indexed == - | Indexed name (idx = 8) - | :status - 03 | Literal value (len = 3) - 3330 32 | 302 - | -> :status: 302 - 58 | == Literal indexed == - | Indexed name (idx = 24) - | cache-control - 07 | Literal value (len = 7) - 7072 6976 6174 65 | private - | -> cache-control: private - 61 | == Literal indexed == - | Indexed name (idx = 33) - | date - 1d | Literal value (len = 29) - 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013 - 2032 303a 3133 3a32 3120 474d 54 | 20:13:21 GMT - | -> date: Mon, 21 Oct 2013 - | 20:13:21 GMT - 6e | == Literal indexed == - | Indexed name (idx = 46) - | location - 17 | Literal value (len = 23) - 6874 7470 733a 2f2f 7777 772e 6578 616d | https://www.exam - 706c 652e 636f 6d | ple.com - | -> location: - | https://www.example.com - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT(header_entries_, - ElementsAreArray({ - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, - ":status", "302"}, - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, - "cache-control", "private"}, - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, - "date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, - "location", "https://www.example.com"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 63) location: https://www.example.com - // [ 2] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT - // [ 3] (s = 52) cache-control: private - // [ 4] (s = 42) :status: 302 - // Table size: 222 - ASSERT_TRUE( - VerifyDynamicTableContents({{"location", "https://www.example.com"}, - {"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - {"cache-control", "private"}, - {":status", "302"}})); - ASSERT_EQ(222u, current_header_table_size()); - - // C.5.2 Second Response - // - // The (":status", "302") header field is evicted from the dynamic table to - // free space to allow adding the (":status", "307") header field. - // - // Header list to encode: - // - // :status: 307 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:21 GMT - // location: https://www.example.com - hpack_block = HpackExampleToStringOrDie(R"( - 48 | == Literal indexed == - | Indexed name (idx = 8) - | :status - 03 | Literal value (len = 3) - 3330 37 | 307 - | - evict: :status: 302 - | -> :status: 307 - c1 | == Indexed - Add == - | idx = 65 - | -> cache-control: private - c0 | == Indexed - Add == - | idx = 64 - | -> date: Mon, 21 Oct 2013 - | 20:13:21 GMT - bf | == Indexed - Add == - | idx = 63 - | -> location: - | https://www.example.com - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT(header_entries_, - ElementsAreArray({ - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, - ":status", "307"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, - "cache-control", "private"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, "date", - "Mon, 21 Oct 2013 20:13:21 GMT"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, "location", - "https://www.example.com"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 42) :status: 307 - // [ 2] (s = 63) location: https://www.example.com - // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:21 GMT - // [ 4] (s = 52) cache-control: private - // Table size: 222 - ASSERT_TRUE( - VerifyDynamicTableContents({{":status", "307"}, - {"location", "https://www.example.com"}, - {"date", "Mon, 21 Oct 2013 20:13:21 GMT"}, - {"cache-control", "private"}})); - ASSERT_EQ(222u, current_header_table_size()); - - // C.5.3 Third Response - // - // Several header fields are evicted from the dynamic table during the - // processing of this header list. - // - // Header list to encode: - // - // :status: 200 - // cache-control: private - // date: Mon, 21 Oct 2013 20:13:22 GMT - // location: https://www.example.com - // content-encoding: gzip - // set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1 - hpack_block = HpackExampleToStringOrDie(R"( - 88 | == Indexed - Add == - | idx = 8 - | -> :status: 200 - c1 | == Indexed - Add == - | idx = 65 - | -> cache-control: private - 61 | == Literal indexed == - | Indexed name (idx = 33) - | date - 1d | Literal value (len = 29) - 4d6f 6e2c 2032 3120 4f63 7420 3230 3133 | Mon, 21 Oct 2013 - 2032 303a 3133 3a32 3220 474d 54 | 20:13:22 GMT - | - evict: cache-control: - | private - | -> date: Mon, 21 Oct 2013 - | 20:13:22 GMT - c0 | == Indexed - Add == - | idx = 64 - | -> location: - | https://www.example.com - 5a | == Literal indexed == - | Indexed name (idx = 26) - | content-encoding - 04 | Literal value (len = 4) - 677a 6970 | gzip - | - evict: date: Mon, 21 Oct - | 2013 20:13:21 GMT - | -> content-encoding: gzip - 77 | == Literal indexed == - | Indexed name (idx = 55) - | set-cookie - 38 | Literal value (len = 56) - 666f 6f3d 4153 444a 4b48 514b 425a 584f | foo=ASDJKHQKBZXO - 5157 454f 5049 5541 5851 5745 4f49 553b | QWEOPIUAXQWEOIU; - 206d 6178 2d61 6765 3d33 3630 303b 2076 | max-age=3600; v - 6572 7369 6f6e 3d31 | ersion=1 - | - evict: location: - | https://www.example.com - | - evict: :status: 307 - | -> set-cookie: foo=ASDJKHQ - | KBZXOQWEOPIUAXQWEOIU; ma - | x-age=3600; version=1 - )"); - EXPECT_TRUE(DecodeBlock(hpack_block)); - ASSERT_THAT( - header_entries_, - ElementsAreArray({ - HpackHeaderEntry{HpackEntryType::kIndexedHeader, ":status", "200"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, "cache-control", - "private"}, - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, "date", - "Mon, 21 Oct 2013 20:13:22 GMT"}, - HpackHeaderEntry{HpackEntryType::kIndexedHeader, "location", - "https://www.example.com"}, - HpackHeaderEntry{HpackEntryType::kIndexedLiteralHeader, - "content-encoding", "gzip"}, - HpackHeaderEntry{ - HpackEntryType::kIndexedLiteralHeader, "set-cookie", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"}, - })); - - // Dynamic Table (after decoding): - // - // [ 1] (s = 98) set-cookie: foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; - // max-age=3600; version=1 - // [ 2] (s = 52) content-encoding: gzip - // [ 3] (s = 65) date: Mon, 21 Oct 2013 20:13:22 GMT - // Table size: 215 - ASSERT_TRUE(VerifyDynamicTableContents( - {{"set-cookie", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"}, - {"content-encoding", "gzip"}, - {"date", "Mon, 21 Oct 2013 20:13:22 GMT"}})); - ASSERT_EQ(215u, current_header_table_size()); -} - -// Confirm that the table size can be changed, but at most twice. -TEST_P(HpackDecoderTest, ProcessesOptionalTableSizeUpdates) { - EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(), - header_table_size_limit()); - // One update allowed. - { - HpackBlockBuilder hbb; - hbb.AppendDynamicTableSizeUpdate(3000); - EXPECT_TRUE(DecodeBlock(hbb.buffer())); - EXPECT_EQ(3000u, header_table_size_limit()); - EXPECT_EQ(0u, current_header_table_size()); - EXPECT_TRUE(header_entries_.empty()); - } - // Two updates allowed. - { - HpackBlockBuilder hbb; - hbb.AppendDynamicTableSizeUpdate(2000); - hbb.AppendDynamicTableSizeUpdate(2500); - EXPECT_TRUE(DecodeBlock(hbb.buffer())); - EXPECT_EQ(2500u, header_table_size_limit()); - EXPECT_EQ(0u, current_header_table_size()); - EXPECT_TRUE(header_entries_.empty()); - } - // A third update in the same HPACK block is rejected, so the final - // size is 1000, not 500. - { - HpackBlockBuilder hbb; - hbb.AppendDynamicTableSizeUpdate(1500); - hbb.AppendDynamicTableSizeUpdate(1000); - hbb.AppendDynamicTableSizeUpdate(500); - EXPECT_FALSE(DecodeBlock(hbb.buffer())); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], HasSubstr("size update not allowed")); - EXPECT_EQ(1000u, header_table_size_limit()); - EXPECT_EQ(0u, current_header_table_size()); - EXPECT_TRUE(header_entries_.empty()); - } - // An error has been detected, so calls to HpackDecoder::DecodeFragment - // should return immediately. - DecodeBuffer db("\x80"); - EXPECT_FALSE(decoder_.DecodeFragment(&db)); - EXPECT_EQ(0u, db.Offset()); - EXPECT_EQ(1u, error_messages_.size()); -} - -// Confirm that the table size can be changed when required, but at most twice. -TEST_P(HpackDecoderTest, ProcessesRequiredTableSizeUpdate) { - // One update required, two allowed, one provided, followed by a header. - decoder_.ApplyHeaderTableSizeSetting(1024); - decoder_.ApplyHeaderTableSizeSetting(2048); - EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(), - header_table_size_limit()); - { - HpackBlockBuilder hbb; - hbb.AppendDynamicTableSizeUpdate(1024); - hbb.AppendIndexedHeader(4); // :path: / - EXPECT_TRUE(DecodeBlock(hbb.buffer())); - EXPECT_THAT(header_entries_, - ElementsAreArray({HpackHeaderEntry{ - HpackEntryType::kIndexedHeader, ":path", "/"}})); - EXPECT_EQ(1024u, header_table_size_limit()); - EXPECT_EQ(0u, current_header_table_size()); - } - // One update required, two allowed, two provided, followed by a header. - decoder_.ApplyHeaderTableSizeSetting(1000); - decoder_.ApplyHeaderTableSizeSetting(1500); - { - HpackBlockBuilder hbb; - hbb.AppendDynamicTableSizeUpdate(500); - hbb.AppendDynamicTableSizeUpdate(1250); - hbb.AppendIndexedHeader(5); // :path: /index.html - EXPECT_TRUE(DecodeBlock(hbb.buffer())); - EXPECT_THAT(header_entries_, - ElementsAreArray({HpackHeaderEntry{ - HpackEntryType::kIndexedHeader, ":path", "/index.html"}})); - EXPECT_EQ(1250u, header_table_size_limit()); - EXPECT_EQ(0u, current_header_table_size()); - } - // One update required, two allowed, three provided, followed by a header. - // The third update is rejected, so the final size is 1000, not 500. - decoder_.ApplyHeaderTableSizeSetting(500); - decoder_.ApplyHeaderTableSizeSetting(1000); - { - HpackBlockBuilder hbb; - hbb.AppendDynamicTableSizeUpdate(200); - hbb.AppendDynamicTableSizeUpdate(700); - hbb.AppendDynamicTableSizeUpdate(900); - hbb.AppendIndexedHeader(5); // Not decoded. - EXPECT_FALSE(DecodeBlock(hbb.buffer())); - EXPECT_FALSE(saw_end_); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], HasSubstr("size update not allowed")); - EXPECT_EQ(700u, header_table_size_limit()); - EXPECT_EQ(0u, current_header_table_size()); - EXPECT_TRUE(header_entries_.empty()); - } - // Now that an error has been detected, StartDecodingBlock should return - // false. - EXPECT_FALSE(decoder_.StartDecodingBlock()); -} - -// Confirm that required size updates are validated. -TEST_P(HpackDecoderTest, InvalidRequiredSizeUpdate) { - // Require a size update, but provide one that isn't small enough (must be - // zero or one, in this case). - decoder_.ApplyHeaderTableSizeSetting(1); - decoder_.ApplyHeaderTableSizeSetting(1024); - HpackBlockBuilder hbb; - hbb.AppendDynamicTableSizeUpdate(2); - EXPECT_TRUE(decoder_.StartDecodingBlock()); - DecodeBuffer db(hbb.buffer()); - EXPECT_FALSE(decoder_.DecodeFragment(&db)); - EXPECT_FALSE(saw_end_); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], HasSubstr("above low water mark")); - EXPECT_EQ(Http2SettingsInfo::DefaultHeaderTableSize(), - header_table_size_limit()); -} - -// Confirm that required size updates are indeed required before the end. -TEST_P(HpackDecoderTest, RequiredTableSizeChangeBeforeEnd) { - decoder_.ApplyHeaderTableSizeSetting(1024); - EXPECT_FALSE(DecodeBlock("")); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], - HasSubstr("Missing dynamic table size update")); - EXPECT_FALSE(saw_end_); -} - -// Confirm that required size updates are indeed required before an -// indexed header. -TEST_P(HpackDecoderTest, RequiredTableSizeChangeBeforeIndexedHeader) { - decoder_.ApplyHeaderTableSizeSetting(1024); - HpackBlockBuilder hbb; - hbb.AppendIndexedHeader(1); - EXPECT_FALSE(DecodeBlock(hbb.buffer())); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], - HasSubstr("Missing dynamic table size update")); - EXPECT_FALSE(saw_end_); - EXPECT_TRUE(header_entries_.empty()); -} - -// Confirm that required size updates are indeed required before an indexed -// header name. -// TODO(jamessynge): Move some of these to hpack_decoder_state_test.cc. -TEST_P(HpackDecoderTest, RequiredTableSizeChangeBeforeIndexedHeaderName) { - decoder_.ApplyHeaderTableSizeSetting(1024); - HpackBlockBuilder hbb; - hbb.AppendNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, 2, - false, "PUT"); - EXPECT_FALSE(DecodeBlock(hbb.buffer())); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], - HasSubstr("Missing dynamic table size update")); - EXPECT_FALSE(saw_end_); - EXPECT_TRUE(header_entries_.empty()); -} - -// Confirm that required size updates are indeed required before a literal -// header name. -TEST_P(HpackDecoderTest, RequiredTableSizeChangeBeforeLiteralName) { - decoder_.ApplyHeaderTableSizeSetting(1024); - HpackBlockBuilder hbb; - hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader, - false, "name", false, "some data."); - EXPECT_FALSE(DecodeBlock(hbb.buffer())); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], - HasSubstr("Missing dynamic table size update")); - EXPECT_FALSE(saw_end_); - EXPECT_TRUE(header_entries_.empty()); -} - -// Confirm that an excessively long varint is detected, in this case an -// index of 127, but with lots of additional high-order 0 bits provided, -// too many to be allowed. -TEST_P(HpackDecoderTest, InvalidIndexedHeaderVarint) { - EXPECT_TRUE(decoder_.StartDecodingBlock()); - DecodeBuffer db("\xff\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x00"); - EXPECT_FALSE(decoder_.DecodeFragment(&db)); - EXPECT_TRUE(decoder_.error_detected()); - EXPECT_FALSE(saw_end_); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], HasSubstr("malformed")); - EXPECT_TRUE(header_entries_.empty()); - // Now that an error has been detected, EndDecodingBlock should not succeed. - EXPECT_FALSE(decoder_.EndDecodingBlock()); -} - -// Confirm that an invalid index into the tables is detected, in this case an -// index of 0. -TEST_P(HpackDecoderTest, InvalidIndex) { - EXPECT_TRUE(decoder_.StartDecodingBlock()); - DecodeBuffer db("\x80"); - EXPECT_FALSE(decoder_.DecodeFragment(&db)); - EXPECT_TRUE(decoder_.error_detected()); - EXPECT_FALSE(saw_end_); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], HasSubstr("Invalid index")); - EXPECT_TRUE(header_entries_.empty()); - // Now that an error has been detected, EndDecodingBlock should not succeed. - EXPECT_FALSE(decoder_.EndDecodingBlock()); -} - -// Confirm that EndDecodingBlock detects a truncated HPACK block. -TEST_P(HpackDecoderTest, TruncatedBlock) { - HpackBlockBuilder hbb; - hbb.AppendDynamicTableSizeUpdate(3000); - EXPECT_EQ(3u, hbb.size()); - hbb.AppendDynamicTableSizeUpdate(4000); - EXPECT_EQ(6u, hbb.size()); - // Decodes this block if the whole thing is provided. - EXPECT_TRUE(DecodeBlock(hbb.buffer())); - EXPECT_EQ(4000u, header_table_size_limit()); - // Multiple times even. - EXPECT_TRUE(DecodeBlock(hbb.buffer())); - EXPECT_EQ(4000u, header_table_size_limit()); - // But not if the block is truncated. - EXPECT_FALSE(DecodeBlock(hbb.buffer().substr(0, hbb.size() - 1))); - EXPECT_FALSE(saw_end_); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], HasSubstr("truncated")); - // The first update was decoded. - EXPECT_EQ(3000u, header_table_size_limit()); - EXPECT_EQ(0u, current_header_table_size()); - EXPECT_TRUE(header_entries_.empty()); -} - -// Confirm that an oversized string is detected, ending decoding. -TEST_P(HpackDecoderTest, OversizeStringDetected) { - HpackBlockBuilder hbb; - hbb.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader, - false, "name", false, "some data."); - hbb.AppendLiteralNameAndValue(HpackEntryType::kUnindexedLiteralHeader, false, - "name2", false, "longer data"); - - // Normally able to decode this block. - EXPECT_TRUE(DecodeBlock(hbb.buffer())); - EXPECT_THAT(header_entries_, - ElementsAreArray( - {HpackHeaderEntry{HpackEntryType::kNeverIndexedLiteralHeader, - "name", "some data."}, - HpackHeaderEntry{HpackEntryType::kUnindexedLiteralHeader, - "name2", "longer data"}})); - - // But not if the maximum size of strings is less than the longest string. - decoder_.set_max_string_size_bytes(10); - EXPECT_FALSE(DecodeBlock(hbb.buffer())); - EXPECT_THAT( - header_entries_, - ElementsAreArray({HpackHeaderEntry{ - HpackEntryType::kNeverIndexedLiteralHeader, "name", "some data."}})); - EXPECT_FALSE(saw_end_); - EXPECT_EQ(1u, error_messages_.size()); - EXPECT_THAT(error_messages_[0], HasSubstr("too long")); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_entry_collector.cc b/net/third_party/http2/hpack/decoder/hpack_entry_collector.cc deleted file mode 100644 index 3640b99..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_entry_collector.cc +++ /dev/null
@@ -1,301 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_entry_collector.h" - -#include "base/logging.h" -#include "net/third_party/http2/hpack/decoder/hpack_string_collector.h" -#include "net/third_party/http2/hpack/http2_hpack_constants.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionResult; - -namespace http2 { -namespace test { -namespace { - -const HpackEntryType kInvalidHeaderType = static_cast<HpackEntryType>(99); -const size_t kInvalidIndex = 99999999; - -} // namespace - -HpackEntryCollector::HpackEntryCollector() { - Clear(); -} - -HpackEntryCollector::HpackEntryCollector(const HpackEntryCollector& other) = - default; - -HpackEntryCollector::HpackEntryCollector(HpackEntryType type, - size_t index_or_size) - : header_type_(type), index_(index_or_size), started_(true), ended_(true) {} -HpackEntryCollector::HpackEntryCollector(HpackEntryType type, - size_t index, - bool value_huffman, - const Http2String& value) - : header_type_(type), - index_(index), - value_(value, value_huffman), - started_(true), - ended_(true) {} -HpackEntryCollector::HpackEntryCollector(HpackEntryType type, - bool name_huffman, - const Http2String& name, - bool value_huffman, - const Http2String& value) - : header_type_(type), - index_(0), - name_(name, name_huffman), - value_(value, value_huffman), - started_(true), - ended_(true) {} - -HpackEntryCollector::~HpackEntryCollector() = default; - -void HpackEntryCollector::OnIndexedHeader(size_t index) { - ASSERT_FALSE(started_); - ASSERT_TRUE(IsClear()) << ToString(); - Init(HpackEntryType::kIndexedHeader, index); - ended_ = true; -} -void HpackEntryCollector::OnStartLiteralHeader(HpackEntryType header_type, - size_t maybe_name_index) { - ASSERT_FALSE(started_); - ASSERT_TRUE(IsClear()) << ToString(); - Init(header_type, maybe_name_index); -} -void HpackEntryCollector::OnNameStart(bool huffman_encoded, size_t len) { - ASSERT_TRUE(started_); - ASSERT_FALSE(ended_); - ASSERT_FALSE(IsClear()); - ASSERT_TRUE(LiteralNameExpected()) << ToString(); - name_.OnStringStart(huffman_encoded, len); -} -void HpackEntryCollector::OnNameData(const char* data, size_t len) { - ASSERT_TRUE(started_); - ASSERT_FALSE(ended_); - ASSERT_TRUE(LiteralNameExpected()) << ToString(); - ASSERT_TRUE(name_.IsInProgress()); - name_.OnStringData(data, len); -} -void HpackEntryCollector::OnNameEnd() { - ASSERT_TRUE(started_); - ASSERT_FALSE(ended_); - ASSERT_TRUE(LiteralNameExpected()) << ToString(); - ASSERT_TRUE(name_.IsInProgress()); - name_.OnStringEnd(); -} -void HpackEntryCollector::OnValueStart(bool huffman_encoded, size_t len) { - ASSERT_TRUE(started_); - ASSERT_FALSE(ended_); - if (LiteralNameExpected()) { - ASSERT_TRUE(name_.HasEnded()); - } - ASSERT_TRUE(LiteralValueExpected()) << ToString(); - ASSERT_TRUE(value_.IsClear()) << value_.ToString(); - value_.OnStringStart(huffman_encoded, len); -} -void HpackEntryCollector::OnValueData(const char* data, size_t len) { - ASSERT_TRUE(started_); - ASSERT_FALSE(ended_); - ASSERT_TRUE(LiteralValueExpected()) << ToString(); - ASSERT_TRUE(value_.IsInProgress()); - value_.OnStringData(data, len); -} -void HpackEntryCollector::OnValueEnd() { - ASSERT_TRUE(started_); - ASSERT_FALSE(ended_); - ASSERT_TRUE(LiteralValueExpected()) << ToString(); - ASSERT_TRUE(value_.IsInProgress()); - value_.OnStringEnd(); - ended_ = true; -} -void HpackEntryCollector::OnDynamicTableSizeUpdate(size_t size) { - ASSERT_FALSE(started_); - ASSERT_TRUE(IsClear()) << ToString(); - Init(HpackEntryType::kDynamicTableSizeUpdate, size); - ended_ = true; -} - -void HpackEntryCollector::Clear() { - header_type_ = kInvalidHeaderType; - index_ = kInvalidIndex; - name_.Clear(); - value_.Clear(); - started_ = ended_ = false; -} -bool HpackEntryCollector::IsClear() const { - return header_type_ == kInvalidHeaderType && index_ == kInvalidIndex && - name_.IsClear() && value_.IsClear() && !started_ && !ended_; -} -bool HpackEntryCollector::IsComplete() const { - return started_ && ended_; -} -bool HpackEntryCollector::LiteralNameExpected() const { - switch (header_type_) { - case HpackEntryType::kIndexedLiteralHeader: - case HpackEntryType::kUnindexedLiteralHeader: - case HpackEntryType::kNeverIndexedLiteralHeader: - return index_ == 0; - default: - return false; - } -} -bool HpackEntryCollector::LiteralValueExpected() const { - switch (header_type_) { - case HpackEntryType::kIndexedLiteralHeader: - case HpackEntryType::kUnindexedLiteralHeader: - case HpackEntryType::kNeverIndexedLiteralHeader: - return true; - default: - return false; - } -} -AssertionResult HpackEntryCollector::ValidateIndexedHeader( - size_t expected_index) const { - VERIFY_TRUE(started_); - VERIFY_TRUE(ended_); - VERIFY_EQ(HpackEntryType::kIndexedHeader, header_type_); - VERIFY_EQ(expected_index, index_); - return ::testing::AssertionSuccess(); -} -AssertionResult HpackEntryCollector::ValidateLiteralValueHeader( - HpackEntryType expected_type, - size_t expected_index, - bool expected_value_huffman, - Http2StringPiece expected_value) const { - VERIFY_TRUE(started_); - VERIFY_TRUE(ended_); - VERIFY_EQ(expected_type, header_type_); - VERIFY_NE(0u, expected_index); - VERIFY_EQ(expected_index, index_); - VERIFY_TRUE(name_.IsClear()); - VERIFY_SUCCESS(value_.Collected(expected_value, expected_value_huffman)); - return ::testing::AssertionSuccess(); -} -AssertionResult HpackEntryCollector::ValidateLiteralNameValueHeader( - HpackEntryType expected_type, - bool expected_name_huffman, - Http2StringPiece expected_name, - bool expected_value_huffman, - Http2StringPiece expected_value) const { - VERIFY_TRUE(started_); - VERIFY_TRUE(ended_); - VERIFY_EQ(expected_type, header_type_); - VERIFY_EQ(0u, index_); - VERIFY_SUCCESS(name_.Collected(expected_name, expected_name_huffman)); - VERIFY_SUCCESS(value_.Collected(expected_value, expected_value_huffman)); - return ::testing::AssertionSuccess(); -} -AssertionResult HpackEntryCollector::ValidateDynamicTableSizeUpdate( - size_t size) const { - VERIFY_TRUE(started_); - VERIFY_TRUE(ended_); - VERIFY_EQ(HpackEntryType::kDynamicTableSizeUpdate, header_type_); - VERIFY_EQ(index_, size); - return ::testing::AssertionSuccess(); -} - -void HpackEntryCollector::AppendToHpackBlockBuilder( - HpackBlockBuilder* hbb) const { - ASSERT_TRUE(started_ && ended_) << *this; - switch (header_type_) { - case HpackEntryType::kIndexedHeader: - hbb->AppendIndexedHeader(index_); - return; - - case HpackEntryType::kDynamicTableSizeUpdate: - hbb->AppendDynamicTableSizeUpdate(index_); - return; - - case HpackEntryType::kIndexedLiteralHeader: - case HpackEntryType::kUnindexedLiteralHeader: - case HpackEntryType::kNeverIndexedLiteralHeader: - ASSERT_TRUE(value_.HasEnded()) << *this; - if (index_ != 0) { - CHECK(name_.IsClear()); - hbb->AppendNameIndexAndLiteralValue(header_type_, index_, - value_.huffman_encoded, value_.s); - } else { - CHECK(name_.HasEnded()) << *this; - hbb->AppendLiteralNameAndValue(header_type_, name_.huffman_encoded, - name_.s, value_.huffman_encoded, - value_.s); - } - return; - - default: - ADD_FAILURE() << *this; - } -} - -Http2String HpackEntryCollector::ToString() const { - Http2String result("Type="); - switch (header_type_) { - case HpackEntryType::kIndexedHeader: - result += "IndexedHeader"; - break; - case HpackEntryType::kDynamicTableSizeUpdate: - result += "DynamicTableSizeUpdate"; - break; - case HpackEntryType::kIndexedLiteralHeader: - result += "IndexedLiteralHeader"; - break; - case HpackEntryType::kUnindexedLiteralHeader: - result += "UnindexedLiteralHeader"; - break; - case HpackEntryType::kNeverIndexedLiteralHeader: - result += "NeverIndexedLiteralHeader"; - break; - default: - if (header_type_ == kInvalidHeaderType) { - result += "<unset>"; - } else { - Http2StrAppend(&result, header_type_); - } - } - if (index_ != 0) { - Http2StrAppend(&result, " Index=", index_); - } - if (!name_.IsClear()) { - Http2StrAppend(&result, " Name", name_.ToString()); - } - if (!value_.IsClear()) { - Http2StrAppend(&result, " Value", value_.ToString()); - } - if (!started_) { - EXPECT_FALSE(ended_); - Http2StrAppend(&result, " !started"); - } else if (!ended_) { - Http2StrAppend(&result, " !ended"); - } else { - Http2StrAppend(&result, " Complete"); - } - return result; -} - -void HpackEntryCollector::Init(HpackEntryType type, size_t maybe_index) { - ASSERT_TRUE(IsClear()) << ToString(); - header_type_ = type; - index_ = maybe_index; - started_ = true; -} - -bool operator==(const HpackEntryCollector& a, const HpackEntryCollector& b) { - return a.name() == b.name() && a.value() == b.value() && - a.index() == b.index() && a.header_type() == b.header_type() && - a.started() == b.started() && a.ended() == b.ended(); -} -bool operator!=(const HpackEntryCollector& a, const HpackEntryCollector& b) { - return !(a == b); -} - -std::ostream& operator<<(std::ostream& out, const HpackEntryCollector& v) { - return out << v.ToString(); -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_entry_collector.h b/net/third_party/http2/hpack/decoder/hpack_entry_collector.h deleted file mode 100644 index 071e5c6..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_entry_collector.h +++ /dev/null
@@ -1,155 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_ENTRY_COLLECTOR_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_ENTRY_COLLECTOR_H_ - -// HpackEntryCollector records calls to HpackEntryDecoderListener in support -// of tests of HpackEntryDecoder, or which use it. Can only record the callbacks -// for the decoding of a single entry; call Clear() between decoding successive -// entries or use a distinct HpackEntryCollector for each entry. - -#include <stddef.h> - -#include <iosfwd> - -#include "net/third_party/http2/hpack/decoder/hpack_entry_decoder_listener.h" -#include "net/third_party/http2/hpack/decoder/hpack_string_collector.h" -#include "net/third_party/http2/hpack/http2_hpack_constants.h" -#include "net/third_party/http2/hpack/tools/hpack_block_builder.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -class HpackEntryCollector : public HpackEntryDecoderListener { - public: - HpackEntryCollector(); - HpackEntryCollector(const HpackEntryCollector& other); - - // These next three constructors are intended for use in tests that create - // an HpackEntryCollector "manually", and then compare it against another - // that is populated via calls to the HpackEntryDecoderListener methods. - HpackEntryCollector(HpackEntryType type, size_t index_or_size); - HpackEntryCollector(HpackEntryType type, - size_t index, - bool value_huffman, - const Http2String& value); - HpackEntryCollector(HpackEntryType type, - bool name_huffman, - const Http2String& name, - bool value_huffman, - const Http2String& value); - - ~HpackEntryCollector() override; - - // Methods defined by HpackEntryDecoderListener. - void OnIndexedHeader(size_t index) override; - void OnStartLiteralHeader(HpackEntryType header_type, - size_t maybe_name_index) override; - void OnNameStart(bool huffman_encoded, size_t len) override; - void OnNameData(const char* data, size_t len) override; - void OnNameEnd() override; - void OnValueStart(bool huffman_encoded, size_t len) override; - void OnValueData(const char* data, size_t len) override; - void OnValueEnd() override; - void OnDynamicTableSizeUpdate(size_t size) override; - - // Clears the fields of the collector so that it is ready to start collecting - // another HPACK block entry. - void Clear(); - - // Is the collector ready to start collecting another HPACK block entry. - bool IsClear() const; - - // Has a complete entry been collected? - bool IsComplete() const; - - // Based on the HpackEntryType, is a literal name expected? - bool LiteralNameExpected() const; - - // Based on the HpackEntryType, is a literal value expected? - bool LiteralValueExpected() const; - - // Returns success if collected an Indexed Header (i.e. OnIndexedHeader was - // called). - ::testing::AssertionResult ValidateIndexedHeader(size_t expected_index) const; - - // Returns success if collected a Header with an indexed name and literal - // value (i.e. OnStartLiteralHeader was called with a non-zero index for - // the name, which must match expected_index). - ::testing::AssertionResult ValidateLiteralValueHeader( - HpackEntryType expected_type, - size_t expected_index, - bool expected_value_huffman, - Http2StringPiece expected_value) const; - - // Returns success if collected a Header with an literal name and literal - // value. - ::testing::AssertionResult ValidateLiteralNameValueHeader( - HpackEntryType expected_type, - bool expected_name_huffman, - Http2StringPiece expected_name, - bool expected_value_huffman, - Http2StringPiece expected_value) const; - - // Returns success if collected a Dynamic Table Size Update, - // with the specified size. - ::testing::AssertionResult ValidateDynamicTableSizeUpdate( - size_t expected_size) const; - - void set_header_type(HpackEntryType v) { header_type_ = v; } - HpackEntryType header_type() const { return header_type_; } - - void set_index(size_t v) { index_ = v; } - size_t index() const { return index_; } - - void set_name(const HpackStringCollector& v) { name_ = v; } - const HpackStringCollector& name() const { return name_; } - - void set_value(const HpackStringCollector& v) { value_ = v; } - const HpackStringCollector& value() const { return value_; } - - void set_started(bool v) { started_ = v; } - bool started() const { return started_; } - - void set_ended(bool v) { ended_ = v; } - bool ended() const { return ended_; } - - void AppendToHpackBlockBuilder(HpackBlockBuilder* hbb) const; - - // Returns a debug string. - Http2String ToString() const; - - private: - void Init(HpackEntryType type, size_t maybe_index); - - HpackEntryType header_type_; - size_t index_; - - HpackStringCollector name_; - HpackStringCollector value_; - - // True if has received a call to an HpackEntryDecoderListener method - // indicating the start of decoding an HPACK entry; for example, - // OnIndexedHeader set it true, but OnNameStart does not change it. - bool started_ = false; - - // True if has received a call to an HpackEntryDecoderListener method - // indicating the end of decoding an HPACK entry; for example, - // OnIndexedHeader and OnValueEnd both set it true, but OnNameEnd does - // not change it. - bool ended_ = false; -}; - -bool operator==(const HpackEntryCollector& a, const HpackEntryCollector& b); -bool operator!=(const HpackEntryCollector& a, const HpackEntryCollector& b); -std::ostream& operator<<(std::ostream& out, const HpackEntryCollector& v); - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_ENTRY_COLLECTOR_H_
diff --git a/net/third_party/http2/hpack/decoder/hpack_entry_decoder.cc b/net/third_party/http2/hpack/decoder/hpack_entry_decoder.cc deleted file mode 100644 index 686bc557..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_entry_decoder.cc +++ /dev/null
@@ -1,267 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_entry_decoder.h" - -#include <stddef.h> - -#include <cstdint> - -#include "base/logging.h" -#include "base/macros.h" -#include "net/third_party/http2/platform/api/http2_bug_tracker.h" -#include "net/third_party/http2/platform/api/http2_macros.h" - -namespace http2 { -namespace { -// Converts calls from HpackStringDecoder when decoding a header name into the -// appropriate HpackEntryDecoderListener::OnName* calls. -class NameDecoderListener { - public: - explicit NameDecoderListener(HpackEntryDecoderListener* listener) - : listener_(listener) {} - bool OnStringStart(bool huffman_encoded, size_t len) { - listener_->OnNameStart(huffman_encoded, len); - return true; - } - void OnStringData(const char* data, size_t len) { - listener_->OnNameData(data, len); - } - void OnStringEnd() { listener_->OnNameEnd(); } - - private: - HpackEntryDecoderListener* listener_; -}; - -// Converts calls from HpackStringDecoder when decoding a header value into -// the appropriate HpackEntryDecoderListener::OnValue* calls. -class ValueDecoderListener { - public: - explicit ValueDecoderListener(HpackEntryDecoderListener* listener) - : listener_(listener) {} - bool OnStringStart(bool huffman_encoded, size_t len) { - listener_->OnValueStart(huffman_encoded, len); - return true; - } - void OnStringData(const char* data, size_t len) { - listener_->OnValueData(data, len); - } - void OnStringEnd() { listener_->OnValueEnd(); } - - private: - HpackEntryDecoderListener* listener_; -}; -} // namespace - -DecodeStatus HpackEntryDecoder::Start(DecodeBuffer* db, - HpackEntryDecoderListener* listener) { - DCHECK(db != nullptr); - DCHECK(listener != nullptr); - DCHECK(db->HasData()); - DecodeStatus status = entry_type_decoder_.Start(db); - switch (status) { - case DecodeStatus::kDecodeDone: - // The type of the entry and its varint fit into the current decode - // buffer. - if (entry_type_decoder_.entry_type() == HpackEntryType::kIndexedHeader) { - // The entry consists solely of the entry type and varint. - // This is by far the most common case in practice. - listener->OnIndexedHeader(entry_type_decoder_.varint()); - return DecodeStatus::kDecodeDone; - } - state_ = EntryDecoderState::kDecodedType; - return Resume(db, listener); - case DecodeStatus::kDecodeInProgress: - // Hit the end of the decode buffer before fully decoding - // the entry type and varint. - DCHECK_EQ(0u, db->Remaining()); - state_ = EntryDecoderState::kResumeDecodingType; - return status; - case DecodeStatus::kDecodeError: - // The varint must have been invalid (too long). - return status; - } - - HTTP2_BUG << "Unreachable"; - return DecodeStatus::kDecodeError; -} - -DecodeStatus HpackEntryDecoder::Resume(DecodeBuffer* db, - HpackEntryDecoderListener* listener) { - DCHECK(db != nullptr); - DCHECK(listener != nullptr); - - DecodeStatus status; - - do { - switch (state_) { - case EntryDecoderState::kResumeDecodingType: - // entry_type_decoder_ returned kDecodeInProgress when last called. - DVLOG(1) << "kResumeDecodingType: db->Remaining=" << db->Remaining(); - status = entry_type_decoder_.Resume(db); - if (status != DecodeStatus::kDecodeDone) { - return status; - } - state_ = EntryDecoderState::kDecodedType; - HTTP2_FALLTHROUGH; - - case EntryDecoderState::kDecodedType: - // entry_type_decoder_ returned kDecodeDone, now need to decide how - // to proceed. - DVLOG(1) << "kDecodedType: db->Remaining=" << db->Remaining(); - if (DispatchOnType(listener)) { - // All done. - return DecodeStatus::kDecodeDone; - } - continue; - - case EntryDecoderState::kStartDecodingName: - DVLOG(1) << "kStartDecodingName: db->Remaining=" << db->Remaining(); - { - NameDecoderListener ncb(listener); - status = string_decoder_.Start(db, &ncb); - } - if (status != DecodeStatus::kDecodeDone) { - // On the assumption that the status is kDecodeInProgress, set - // state_ accordingly; unnecessary if status is kDecodeError, but - // that will only happen if the varint encoding the name's length - // is too long. - state_ = EntryDecoderState::kResumeDecodingName; - return status; - } - state_ = EntryDecoderState::kStartDecodingValue; - HTTP2_FALLTHROUGH; - - case EntryDecoderState::kStartDecodingValue: - DVLOG(1) << "kStartDecodingValue: db->Remaining=" << db->Remaining(); - { - ValueDecoderListener vcb(listener); - status = string_decoder_.Start(db, &vcb); - } - if (status == DecodeStatus::kDecodeDone) { - // Done with decoding the literal value, so we've reached the - // end of the header entry. - return status; - } - // On the assumption that the status is kDecodeInProgress, set - // state_ accordingly; unnecessary if status is kDecodeError, but - // that will only happen if the varint encoding the value's length - // is too long. - state_ = EntryDecoderState::kResumeDecodingValue; - return status; - - case EntryDecoderState::kResumeDecodingName: - // The literal name was split across decode buffers. - DVLOG(1) << "kResumeDecodingName: db->Remaining=" << db->Remaining(); - { - NameDecoderListener ncb(listener); - status = string_decoder_.Resume(db, &ncb); - } - if (status != DecodeStatus::kDecodeDone) { - // On the assumption that the status is kDecodeInProgress, set - // state_ accordingly; unnecessary if status is kDecodeError, but - // that will only happen if the varint encoding the name's length - // is too long. - state_ = EntryDecoderState::kResumeDecodingName; - return status; - } - state_ = EntryDecoderState::kStartDecodingValue; - break; - - case EntryDecoderState::kResumeDecodingValue: - // The literal value was split across decode buffers. - DVLOG(1) << "kResumeDecodingValue: db->Remaining=" << db->Remaining(); - { - ValueDecoderListener vcb(listener); - status = string_decoder_.Resume(db, &vcb); - } - if (status == DecodeStatus::kDecodeDone) { - // Done with decoding the value, therefore the entry as a whole. - return status; - } - // On the assumption that the status is kDecodeInProgress, set - // state_ accordingly; unnecessary if status is kDecodeError, but - // that will only happen if the varint encoding the value's length - // is too long. - state_ = EntryDecoderState::kResumeDecodingValue; - return status; - } - } while (true); -} - -bool HpackEntryDecoder::DispatchOnType(HpackEntryDecoderListener* listener) { - const HpackEntryType entry_type = entry_type_decoder_.entry_type(); - const uint32_t varint = entry_type_decoder_.varint(); - switch (entry_type) { - case HpackEntryType::kIndexedHeader: - // The entry consists solely of the entry type and varint. See: - // http://httpwg.org/specs/rfc7541.html#indexed.header.representation - listener->OnIndexedHeader(varint); - return true; - - case HpackEntryType::kIndexedLiteralHeader: - case HpackEntryType::kUnindexedLiteralHeader: - case HpackEntryType::kNeverIndexedLiteralHeader: - // The entry has a literal value, and if the varint is zero also has a - // literal name preceding the value. See: - // http://httpwg.org/specs/rfc7541.html#literal.header.representation - listener->OnStartLiteralHeader(entry_type, varint); - if (varint == 0) { - state_ = EntryDecoderState::kStartDecodingName; - } else { - state_ = EntryDecoderState::kStartDecodingValue; - } - return false; - - case HpackEntryType::kDynamicTableSizeUpdate: - // The entry consists solely of the entry type and varint. FWIW, I've - // never seen this type of entry in production (primarily browser - // traffic) so if you're designing an HPACK successor someday, consider - // dropping it or giving it a much longer prefix. See: - // http://httpwg.org/specs/rfc7541.html#encoding.context.update - listener->OnDynamicTableSizeUpdate(varint); - return true; - } - - HTTP2_BUG << "Unreachable, entry_type=" << entry_type; - return true; -} - -void HpackEntryDecoder::OutputDebugString(std::ostream& out) const { - out << "HpackEntryDecoder(state=" << state_ << ", " << entry_type_decoder_ - << ", " << string_decoder_ << ")"; -} - -Http2String HpackEntryDecoder::DebugString() const { - std::stringstream s; - s << *this; - return s.str(); -} - -std::ostream& operator<<(std::ostream& out, const HpackEntryDecoder& v) { - v.OutputDebugString(out); - return out; -} - -std::ostream& operator<<(std::ostream& out, - HpackEntryDecoder::EntryDecoderState state) { - typedef HpackEntryDecoder::EntryDecoderState EntryDecoderState; - switch (state) { - case EntryDecoderState::kResumeDecodingType: - return out << "kResumeDecodingType"; - case EntryDecoderState::kDecodedType: - return out << "kDecodedType"; - case EntryDecoderState::kStartDecodingName: - return out << "kStartDecodingName"; - case EntryDecoderState::kResumeDecodingName: - return out << "kResumeDecodingName"; - case EntryDecoderState::kStartDecodingValue: - return out << "kStartDecodingValue"; - case EntryDecoderState::kResumeDecodingValue: - return out << "kResumeDecodingValue"; - } - return out << static_cast<int>(state); -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_entry_decoder.h b/net/third_party/http2/hpack/decoder/hpack_entry_decoder.h deleted file mode 100644 index b1ff138..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_entry_decoder.h +++ /dev/null
@@ -1,85 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_H_ - -// HpackEntryDecoder decodes a single HPACK entry (i.e. one header or one -// dynamic table size update), in a resumable fashion. The first call, Start(), -// must provide a non-empty decode buffer. Continue with calls to Resume() if -// Start, and any subsequent calls to Resume, returns kDecodeInProgress. - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/hpack/decoder/hpack_entry_decoder_listener.h" -#include "net/third_party/http2/hpack/decoder/hpack_entry_type_decoder.h" -#include "net/third_party/http2/hpack/decoder/hpack_string_decoder.h" -#include "net/third_party/http2/hpack/http2_hpack_constants.h" -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string.h" - -namespace http2 { - -class HTTP2_EXPORT_PRIVATE HpackEntryDecoder { - public: - enum class EntryDecoderState { - // Have started decoding the type/varint, but didn't finish on the previous - // attempt. Next state is kResumeDecodingType or kDecodedType. - kResumeDecodingType, - - // Have just finished decoding the type/varint. Final state if the type is - // kIndexedHeader or kDynamicTableSizeUpdate. Otherwise, the next state is - // kStartDecodingName (if the varint is 0), else kStartDecodingValue. - kDecodedType, - - // Ready to start decoding the literal name of a header entry. Next state - // is kResumeDecodingName (if the name is split across decode buffers), - // else kStartDecodingValue. - kStartDecodingName, - - // Resume decoding the literal name of a header that is split across decode - // buffers. - kResumeDecodingName, - - // Ready to start decoding the literal value of a header entry. Final state - // if the value string is entirely in the decode buffer, else the next state - // is kResumeDecodingValue. - kStartDecodingValue, - - // Resume decoding the literal value of a header that is split across decode - // buffers. - kResumeDecodingValue, - }; - - // Only call when the decode buffer has data (i.e. HpackBlockDecoder must - // not call until there is data). - DecodeStatus Start(DecodeBuffer* db, HpackEntryDecoderListener* listener); - - // Only call Resume if the previous call (Start or Resume) returned - // kDecodeInProgress; Resume is also called from Start when it has succeeded - // in decoding the entry type and its varint. - DecodeStatus Resume(DecodeBuffer* db, HpackEntryDecoderListener* listener); - - Http2String DebugString() const; - void OutputDebugString(std::ostream& out) const; - - private: - // Implements handling state kDecodedType. - bool DispatchOnType(HpackEntryDecoderListener* listener); - - HpackEntryTypeDecoder entry_type_decoder_; - HpackStringDecoder string_decoder_; - EntryDecoderState state_ = EntryDecoderState(); -}; - -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const HpackEntryDecoder& v); -HTTP2_EXPORT_PRIVATE std::ostream& operator<<( - std::ostream& out, - HpackEntryDecoder::EntryDecoderState state); - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_H_
diff --git a/net/third_party/http2/hpack/decoder/hpack_entry_decoder_listener.cc b/net/third_party/http2/hpack/decoder/hpack_entry_decoder_listener.cc deleted file mode 100644 index 8c73301..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_entry_decoder_listener.cc +++ /dev/null
@@ -1,81 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_entry_decoder_listener.h" - -#include "base/logging.h" - -namespace http2 { - -void HpackEntryDecoderVLoggingListener::OnIndexedHeader(size_t index) { - VLOG(1) << "OnIndexedHeader, index=" << index; - if (wrapped_) { - wrapped_->OnIndexedHeader(index); - } -} - -void HpackEntryDecoderVLoggingListener::OnStartLiteralHeader( - HpackEntryType entry_type, - size_t maybe_name_index) { - VLOG(1) << "OnStartLiteralHeader: entry_type=" << entry_type - << ", maybe_name_index=" << maybe_name_index; - if (wrapped_) { - wrapped_->OnStartLiteralHeader(entry_type, maybe_name_index); - } -} - -void HpackEntryDecoderVLoggingListener::OnNameStart(bool huffman_encoded, - size_t len) { - VLOG(1) << "OnNameStart: H=" << huffman_encoded << ", len=" << len; - if (wrapped_) { - wrapped_->OnNameStart(huffman_encoded, len); - } -} - -void HpackEntryDecoderVLoggingListener::OnNameData(const char* data, - size_t len) { - VLOG(1) << "OnNameData: len=" << len; - if (wrapped_) { - wrapped_->OnNameData(data, len); - } -} - -void HpackEntryDecoderVLoggingListener::OnNameEnd() { - VLOG(1) << "OnNameEnd"; - if (wrapped_) { - wrapped_->OnNameEnd(); - } -} - -void HpackEntryDecoderVLoggingListener::OnValueStart(bool huffman_encoded, - size_t len) { - VLOG(1) << "OnValueStart: H=" << huffman_encoded << ", len=" << len; - if (wrapped_) { - wrapped_->OnValueStart(huffman_encoded, len); - } -} - -void HpackEntryDecoderVLoggingListener::OnValueData(const char* data, - size_t len) { - VLOG(1) << "OnValueData: len=" << len; - if (wrapped_) { - wrapped_->OnValueData(data, len); - } -} - -void HpackEntryDecoderVLoggingListener::OnValueEnd() { - VLOG(1) << "OnValueEnd"; - if (wrapped_) { - wrapped_->OnValueEnd(); - } -} - -void HpackEntryDecoderVLoggingListener::OnDynamicTableSizeUpdate(size_t size) { - VLOG(1) << "OnDynamicTableSizeUpdate: size=" << size; - if (wrapped_) { - wrapped_->OnDynamicTableSizeUpdate(size); - } -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_entry_decoder_listener.h b/net/third_party/http2/hpack/decoder/hpack_entry_decoder_listener.h deleted file mode 100644 index d60119a..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_entry_decoder_listener.h +++ /dev/null
@@ -1,110 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_LISTENER_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_LISTENER_H_ - -// Defines HpackEntryDecoderListener, the base class of listeners that -// HpackEntryDecoder calls. Also defines HpackEntryDecoderVLoggingListener -// which logs before calling another HpackEntryDecoderListener implementation. - -#include <stddef.h> - -#include "net/third_party/http2/hpack/http2_hpack_constants.h" -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { - -class HTTP2_EXPORT_PRIVATE HpackEntryDecoderListener { - public: - virtual ~HpackEntryDecoderListener() {} - - // Called when an indexed header (i.e. one in the static or dynamic table) has - // been decoded from an HPACK block. index is supposed to be non-zero, but - // that has not been checked by the caller. - virtual void OnIndexedHeader(size_t index) = 0; - - // Called when the start of a header with a literal value, and maybe a literal - // name, has been decoded. maybe_name_index is zero if the header has a - // literal name, else it is a reference into the static or dynamic table, from - // which the name should be determined. When the name is literal, the next - // call will be to OnNameStart; else it will be to OnValueStart. entry_type - // indicates whether the peer has added the entry to its dynamic table, and - // whether a proxy is permitted to do so when forwarding the entry. - virtual void OnStartLiteralHeader(HpackEntryType entry_type, - size_t maybe_name_index) = 0; - - // Called when the encoding (Huffman compressed or plain text) and the encoded - // length of a literal name has been decoded. OnNameData will be called next, - // and repeatedly until the sum of lengths passed to OnNameData is len. - virtual void OnNameStart(bool huffman_encoded, size_t len) = 0; - - // Called when len bytes of an encoded header name have been decoded. - virtual void OnNameData(const char* data, size_t len) = 0; - - // Called after the entire name has been passed to OnNameData. - // OnValueStart will be called next. - virtual void OnNameEnd() = 0; - - // Called when the encoding (Huffman compressed or plain text) and the encoded - // length of a literal value has been decoded. OnValueData will be called - // next, and repeatedly until the sum of lengths passed to OnValueData is len. - virtual void OnValueStart(bool huffman_encoded, size_t len) = 0; - - // Called when len bytes of an encoded header value have been decoded. - virtual void OnValueData(const char* data, size_t len) = 0; - - // Called after the entire value has been passed to OnValueData, marking the - // end of a header entry with a literal value, and maybe a literal name. - virtual void OnValueEnd() = 0; - - // Called when an update to the size of the peer's dynamic table has been - // decoded. - virtual void OnDynamicTableSizeUpdate(size_t size) = 0; -}; - -class HTTP2_EXPORT_PRIVATE HpackEntryDecoderVLoggingListener - : public HpackEntryDecoderListener { - public: - HpackEntryDecoderVLoggingListener() : wrapped_(nullptr) {} - explicit HpackEntryDecoderVLoggingListener(HpackEntryDecoderListener* wrapped) - : wrapped_(wrapped) {} - ~HpackEntryDecoderVLoggingListener() override {} - - void OnIndexedHeader(size_t index) override; - void OnStartLiteralHeader(HpackEntryType entry_type, - size_t maybe_name_index) override; - void OnNameStart(bool huffman_encoded, size_t len) override; - void OnNameData(const char* data, size_t len) override; - void OnNameEnd() override; - void OnValueStart(bool huffman_encoded, size_t len) override; - void OnValueData(const char* data, size_t len) override; - void OnValueEnd() override; - void OnDynamicTableSizeUpdate(size_t size) override; - - private: - HpackEntryDecoderListener* const wrapped_; -}; - -// A no-op implementation of HpackEntryDecoderListener. -class HTTP2_EXPORT_PRIVATE HpackEntryDecoderNoOpListener - : public HpackEntryDecoderListener { - public: - ~HpackEntryDecoderNoOpListener() override {} - - void OnIndexedHeader(size_t index) override {} - void OnStartLiteralHeader(HpackEntryType entry_type, - size_t maybe_name_index) override {} - void OnNameStart(bool huffman_encoded, size_t len) override {} - void OnNameData(const char* data, size_t len) override {} - void OnNameEnd() override {} - void OnValueStart(bool huffman_encoded, size_t len) override {} - void OnValueData(const char* data, size_t len) override {} - void OnValueEnd() override {} - void OnDynamicTableSizeUpdate(size_t size) override {} -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_ENTRY_DECODER_LISTENER_H_
diff --git a/net/third_party/http2/hpack/decoder/hpack_entry_decoder_test.cc b/net/third_party/http2/hpack/decoder/hpack_entry_decoder_test.cc deleted file mode 100644 index d7e32d7..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_entry_decoder_test.cc +++ /dev/null
@@ -1,211 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_entry_decoder.h" - -// Tests of HpackEntryDecoder. - -#include <cstdint> - -#include "net/third_party/http2/hpack/decoder/hpack_entry_collector.h" -#include "net/third_party/http2/hpack/tools/hpack_block_builder.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionResult; - -namespace http2 { -namespace test { -namespace { - -class HpackEntryDecoderTest : public RandomDecoderTest { - protected: - HpackEntryDecoderTest() : listener_(&collector_) {} - - DecodeStatus StartDecoding(DecodeBuffer* b) override { - collector_.Clear(); - return decoder_.Start(b, &listener_); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - return decoder_.Resume(b, &listener_); - } - - AssertionResult DecodeAndValidateSeveralWays(DecodeBuffer* db, - const Validator& validator) { - // StartDecoding, above, requires the DecodeBuffer be non-empty so that it - // can call Start with the prefix byte. - bool return_non_zero_on_first = true; - return RandomDecoderTest::DecodeAndValidateSeveralWays( - db, return_non_zero_on_first, validator); - } - - AssertionResult DecodeAndValidateSeveralWays(const HpackBlockBuilder& hbb, - const Validator& validator) { - DecodeBuffer db(hbb.buffer()); - return DecodeAndValidateSeveralWays(&db, validator); - } - - HpackEntryDecoder decoder_; - HpackEntryCollector collector_; - HpackEntryDecoderVLoggingListener listener_; -}; - -TEST_F(HpackEntryDecoderTest, IndexedHeader_Literals) { - { - const char input[] = {'\x82'}; // == Index 2 == - DecodeBuffer b(input); - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(2)); - }; - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); - } - collector_.Clear(); - { - const char input[] = {'\xfe'}; // == Index 126 == - DecodeBuffer b(input); - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(126)); - }; - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); - } - collector_.Clear(); - { - const char input[] = {'\xff', '\x00'}; // == Index 127 == - DecodeBuffer b(input); - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(127)); - }; - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); - } -} - -TEST_F(HpackEntryDecoderTest, IndexedHeader_Various) { - // Indices chosen to hit encoding and table boundaries. - for (const uint32_t ndx : {1, 2, 61, 62, 63, 126, 127, 254, 255, 256}) { - HpackBlockBuilder hbb; - hbb.AppendIndexedHeader(ndx); - - auto do_check = [this, ndx]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateIndexedHeader(ndx)); - }; - EXPECT_TRUE( - DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); - } -} - -TEST_F(HpackEntryDecoderTest, IndexedLiteralValue_Literal) { - const char input[] = - "\x7f" // == Literal indexed, name index 0x40 == - "\x01" // 2nd byte of name index (0x01 + 0x3f == 0x40) - "\x0d" // Value length (13) - "custom-header"; // Value - DecodeBuffer b(input, sizeof input - 1); - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader( - HpackEntryType::kIndexedLiteralHeader, 0x40, false, "custom-header")); - }; - EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -TEST_F(HpackEntryDecoderTest, IndexedLiteralNameValue_Literal) { - const char input[] = - "\x40" // == Literal indexed == - "\x0a" // Name length (10) - "custom-key" // Name - "\x0d" // Value length (13) - "custom-header"; // Value - - DecodeBuffer b(input, sizeof input - 1); - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader( - HpackEntryType::kIndexedLiteralHeader, false, "custom-key", false, - "custom-header")); - }; - EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -TEST_F(HpackEntryDecoderTest, DynamicTableSizeUpdate_Literal) { - // Size update, length 31. - const char input[] = "\x3f\x00"; - DecodeBuffer b(input, 2); - auto do_check = [this]() { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateDynamicTableSizeUpdate(31)); - }; - EXPECT_TRUE(DecodeAndValidateSeveralWays(&b, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); -} - -class HpackLiteralEntryDecoderTest - : public HpackEntryDecoderTest, - public ::testing::WithParamInterface<HpackEntryType> { - protected: - HpackLiteralEntryDecoderTest() : entry_type_(GetParam()) {} - - const HpackEntryType entry_type_; -}; - -INSTANTIATE_TEST_CASE_P( - AllLiteralTypes, - HpackLiteralEntryDecoderTest, - testing::Values(HpackEntryType::kIndexedLiteralHeader, - HpackEntryType::kUnindexedLiteralHeader, - HpackEntryType::kNeverIndexedLiteralHeader)); - -TEST_P(HpackLiteralEntryDecoderTest, RandNameIndexAndLiteralValue) { - for (int n = 0; n < 10; n++) { - const uint32_t ndx = 1 + Random().Rand8(); - const bool value_is_huffman_encoded = (n % 2) == 0; - const Http2String value = Random().RandString(Random().Rand8()); - HpackBlockBuilder hbb; - hbb.AppendNameIndexAndLiteralValue(entry_type_, ndx, - value_is_huffman_encoded, value); - auto do_check = [this, ndx, value_is_huffman_encoded, - value]() -> AssertionResult { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralValueHeader( - entry_type_, ndx, value_is_huffman_encoded, value)); - }; - EXPECT_TRUE( - DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); - } -} - -TEST_P(HpackLiteralEntryDecoderTest, RandLiteralNameAndValue) { - for (int n = 0; n < 10; n++) { - const bool name_is_huffman_encoded = (n & 1) == 0; - const int name_len = 1 + Random().Rand8(); - const Http2String name = Random().RandString(name_len); - const bool value_is_huffman_encoded = (n & 2) == 0; - const int value_len = Random().Skewed(10); - const Http2String value = Random().RandString(value_len); - HpackBlockBuilder hbb; - hbb.AppendLiteralNameAndValue(entry_type_, name_is_huffman_encoded, name, - value_is_huffman_encoded, value); - auto do_check = [this, name_is_huffman_encoded, name, - value_is_huffman_encoded, value]() -> AssertionResult { - VERIFY_AND_RETURN_SUCCESS(collector_.ValidateLiteralNameValueHeader( - entry_type_, name_is_huffman_encoded, name, value_is_huffman_encoded, - value)); - }; - EXPECT_TRUE( - DecodeAndValidateSeveralWays(hbb, ValidateDoneAndEmpty(do_check))); - EXPECT_TRUE(do_check()); - } -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_entry_type_decoder.cc b/net/third_party/http2/hpack/decoder/hpack_entry_type_decoder.cc deleted file mode 100644 index 1699fdb..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_entry_type_decoder.cc +++ /dev/null
@@ -1,358 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_entry_type_decoder.h" - -#include "base/logging.h" -#include "net/third_party/http2/platform/api/http2_bug_tracker.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" - -namespace http2 { - -Http2String HpackEntryTypeDecoder::DebugString() const { - return Http2StrCat( - "HpackEntryTypeDecoder(varint_decoder=", varint_decoder_.DebugString(), - ", entry_type=", entry_type_, ")"); -} - -std::ostream& operator<<(std::ostream& out, const HpackEntryTypeDecoder& v) { - return out << v.DebugString(); -} - -// This ridiculous looking function turned out to be the winner in benchmarking -// of several very different alternative implementations. It would be even -// faster (~7%) if inlined in the header file, but I'm not sure if that is -// worth doing... yet. -// TODO(jamessynge): Benchmark again at a higher level (e.g. at least at the -// full HTTP/2 decoder level, but preferably still higher) to determine if the -// alternatives that take less code/data space are preferable in that situation. -DecodeStatus HpackEntryTypeDecoder::Start(DecodeBuffer* db) { - DCHECK(db != nullptr); - DCHECK(db->HasData()); - - // The high four bits (nibble) of first byte of the entry determine the type - // of the entry, and may also be the initial bits of the varint that - // represents an index or table size. Note the use of the word 'initial' - // rather than 'high'; the HPACK encoding of varints is not in network - // order (i.e. not big-endian, the high-order byte isn't first), nor in - // little-endian order. See: - // http://httpwg.org/specs/rfc7541.html#integer.representation - uint8_t byte = db->DecodeUInt8(); - switch (byte) { - case 0b00000000: - case 0b00000001: - case 0b00000010: - case 0b00000011: - case 0b00000100: - case 0b00000101: - case 0b00000110: - case 0b00000111: - case 0b00001000: - case 0b00001001: - case 0b00001010: - case 0b00001011: - case 0b00001100: - case 0b00001101: - case 0b00001110: - // The low 4 bits of |byte| are the initial bits of the varint. - // One of those bits is 0, so the varint is only one byte long. - entry_type_ = HpackEntryType::kUnindexedLiteralHeader; - varint_decoder_.set_value(byte); - return DecodeStatus::kDecodeDone; - - case 0b00001111: - // The low 4 bits of |byte| are the initial bits of the varint. All 4 - // are 1, so the varint extends into another byte. - entry_type_ = HpackEntryType::kUnindexedLiteralHeader; - return varint_decoder_.StartExtended(4, db); - - case 0b00010000: - case 0b00010001: - case 0b00010010: - case 0b00010011: - case 0b00010100: - case 0b00010101: - case 0b00010110: - case 0b00010111: - case 0b00011000: - case 0b00011001: - case 0b00011010: - case 0b00011011: - case 0b00011100: - case 0b00011101: - case 0b00011110: - // The low 4 bits of |byte| are the initial bits of the varint. - // One of those bits is 0, so the varint is only one byte long. - entry_type_ = HpackEntryType::kNeverIndexedLiteralHeader; - varint_decoder_.set_value(byte & 0x0f); - return DecodeStatus::kDecodeDone; - - case 0b00011111: - // The low 4 bits of |byte| are the initial bits of the varint. - // All of those bits are 1, so the varint extends into another byte. - entry_type_ = HpackEntryType::kNeverIndexedLiteralHeader; - return varint_decoder_.StartExtended(4, db); - - case 0b00100000: - case 0b00100001: - case 0b00100010: - case 0b00100011: - case 0b00100100: - case 0b00100101: - case 0b00100110: - case 0b00100111: - case 0b00101000: - case 0b00101001: - case 0b00101010: - case 0b00101011: - case 0b00101100: - case 0b00101101: - case 0b00101110: - case 0b00101111: - case 0b00110000: - case 0b00110001: - case 0b00110010: - case 0b00110011: - case 0b00110100: - case 0b00110101: - case 0b00110110: - case 0b00110111: - case 0b00111000: - case 0b00111001: - case 0b00111010: - case 0b00111011: - case 0b00111100: - case 0b00111101: - case 0b00111110: - entry_type_ = HpackEntryType::kDynamicTableSizeUpdate; - // The low 5 bits of |byte| are the initial bits of the varint. - // One of those bits is 0, so the varint is only one byte long. - varint_decoder_.set_value(byte & 0x01f); - return DecodeStatus::kDecodeDone; - - case 0b00111111: - entry_type_ = HpackEntryType::kDynamicTableSizeUpdate; - // The low 5 bits of |byte| are the initial bits of the varint. - // All of those bits are 1, so the varint extends into another byte. - return varint_decoder_.StartExtended(5, db); - - case 0b01000000: - case 0b01000001: - case 0b01000010: - case 0b01000011: - case 0b01000100: - case 0b01000101: - case 0b01000110: - case 0b01000111: - case 0b01001000: - case 0b01001001: - case 0b01001010: - case 0b01001011: - case 0b01001100: - case 0b01001101: - case 0b01001110: - case 0b01001111: - case 0b01010000: - case 0b01010001: - case 0b01010010: - case 0b01010011: - case 0b01010100: - case 0b01010101: - case 0b01010110: - case 0b01010111: - case 0b01011000: - case 0b01011001: - case 0b01011010: - case 0b01011011: - case 0b01011100: - case 0b01011101: - case 0b01011110: - case 0b01011111: - case 0b01100000: - case 0b01100001: - case 0b01100010: - case 0b01100011: - case 0b01100100: - case 0b01100101: - case 0b01100110: - case 0b01100111: - case 0b01101000: - case 0b01101001: - case 0b01101010: - case 0b01101011: - case 0b01101100: - case 0b01101101: - case 0b01101110: - case 0b01101111: - case 0b01110000: - case 0b01110001: - case 0b01110010: - case 0b01110011: - case 0b01110100: - case 0b01110101: - case 0b01110110: - case 0b01110111: - case 0b01111000: - case 0b01111001: - case 0b01111010: - case 0b01111011: - case 0b01111100: - case 0b01111101: - case 0b01111110: - entry_type_ = HpackEntryType::kIndexedLiteralHeader; - // The low 6 bits of |byte| are the initial bits of the varint. - // One of those bits is 0, so the varint is only one byte long. - varint_decoder_.set_value(byte & 0x03f); - return DecodeStatus::kDecodeDone; - - case 0b01111111: - entry_type_ = HpackEntryType::kIndexedLiteralHeader; - // The low 6 bits of |byte| are the initial bits of the varint. - // All of those bits are 1, so the varint extends into another byte. - return varint_decoder_.StartExtended(6, db); - - case 0b10000000: - case 0b10000001: - case 0b10000010: - case 0b10000011: - case 0b10000100: - case 0b10000101: - case 0b10000110: - case 0b10000111: - case 0b10001000: - case 0b10001001: - case 0b10001010: - case 0b10001011: - case 0b10001100: - case 0b10001101: - case 0b10001110: - case 0b10001111: - case 0b10010000: - case 0b10010001: - case 0b10010010: - case 0b10010011: - case 0b10010100: - case 0b10010101: - case 0b10010110: - case 0b10010111: - case 0b10011000: - case 0b10011001: - case 0b10011010: - case 0b10011011: - case 0b10011100: - case 0b10011101: - case 0b10011110: - case 0b10011111: - case 0b10100000: - case 0b10100001: - case 0b10100010: - case 0b10100011: - case 0b10100100: - case 0b10100101: - case 0b10100110: - case 0b10100111: - case 0b10101000: - case 0b10101001: - case 0b10101010: - case 0b10101011: - case 0b10101100: - case 0b10101101: - case 0b10101110: - case 0b10101111: - case 0b10110000: - case 0b10110001: - case 0b10110010: - case 0b10110011: - case 0b10110100: - case 0b10110101: - case 0b10110110: - case 0b10110111: - case 0b10111000: - case 0b10111001: - case 0b10111010: - case 0b10111011: - case 0b10111100: - case 0b10111101: - case 0b10111110: - case 0b10111111: - case 0b11000000: - case 0b11000001: - case 0b11000010: - case 0b11000011: - case 0b11000100: - case 0b11000101: - case 0b11000110: - case 0b11000111: - case 0b11001000: - case 0b11001001: - case 0b11001010: - case 0b11001011: - case 0b11001100: - case 0b11001101: - case 0b11001110: - case 0b11001111: - case 0b11010000: - case 0b11010001: - case 0b11010010: - case 0b11010011: - case 0b11010100: - case 0b11010101: - case 0b11010110: - case 0b11010111: - case 0b11011000: - case 0b11011001: - case 0b11011010: - case 0b11011011: - case 0b11011100: - case 0b11011101: - case 0b11011110: - case 0b11011111: - case 0b11100000: - case 0b11100001: - case 0b11100010: - case 0b11100011: - case 0b11100100: - case 0b11100101: - case 0b11100110: - case 0b11100111: - case 0b11101000: - case 0b11101001: - case 0b11101010: - case 0b11101011: - case 0b11101100: - case 0b11101101: - case 0b11101110: - case 0b11101111: - case 0b11110000: - case 0b11110001: - case 0b11110010: - case 0b11110011: - case 0b11110100: - case 0b11110101: - case 0b11110110: - case 0b11110111: - case 0b11111000: - case 0b11111001: - case 0b11111010: - case 0b11111011: - case 0b11111100: - case 0b11111101: - case 0b11111110: - entry_type_ = HpackEntryType::kIndexedHeader; - // The low 7 bits of |byte| are the initial bits of the varint. - // One of those bits is 0, so the varint is only one byte long. - varint_decoder_.set_value(byte & 0x07f); - return DecodeStatus::kDecodeDone; - - case 0b11111111: - entry_type_ = HpackEntryType::kIndexedHeader; - // The low 7 bits of |byte| are the initial bits of the varint. - // All of those bits are 1, so the varint extends into another byte. - return varint_decoder_.StartExtended(7, db); - } - HTTP2_BUG << "Unreachable, byte=" << std::hex << static_cast<uint32_t>(byte); - return DecodeStatus::kDecodeError; -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_entry_type_decoder.h b/net/third_party/http2/hpack/decoder/hpack_entry_type_decoder.h deleted file mode 100644 index 5b0665e..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_entry_type_decoder.h +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_ENTRY_TYPE_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_ENTRY_TYPE_DECODER_H_ - -// Decodes the type of an HPACK entry, and the variable length integer whose -// prefix is in the low-order bits of the same byte, "below" the type bits. -// The integer represents an index into static or dynamic table, which may be -// zero, or is the new size limit of the dynamic table. - -#include <cstdint> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/hpack/http2_hpack_constants.h" -#include "net/third_party/http2/hpack/varint/hpack_varint_decoder.h" -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string.h" - -namespace http2 { - -class HTTP2_EXPORT_PRIVATE HpackEntryTypeDecoder { - public: - // Only call when the decode buffer has data (i.e. HpackEntryDecoder must - // not call until there is data). - DecodeStatus Start(DecodeBuffer* db); - - // Only call Resume if the previous call (Start or Resume) returned - // DecodeStatus::kDecodeInProgress. - DecodeStatus Resume(DecodeBuffer* db) { return varint_decoder_.Resume(db); } - - // Returns the decoded entry type. Only call if the preceding call to Start - // or Resume returned kDecodeDone. - HpackEntryType entry_type() const { return entry_type_; } - - // Returns the decoded variable length integer. Only call if the - // preceding call to Start or Resume returned kDecodeDone. - uint32_t varint() const { return varint_decoder_.value(); } - - Http2String DebugString() const; - - private: - HpackVarintDecoder varint_decoder_; - - // This field is initialized just to keep ASAN happy about reading it - // from DebugString(). - HpackEntryType entry_type_ = HpackEntryType::kIndexedHeader; -}; - -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const HpackEntryTypeDecoder& v); - -} // namespace http2 -#endif // NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_ENTRY_TYPE_DECODER_H_
diff --git a/net/third_party/http2/hpack/decoder/hpack_entry_type_decoder_test.cc b/net/third_party/http2/hpack/decoder/hpack_entry_type_decoder_test.cc deleted file mode 100644 index dae8f7f..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_entry_type_decoder_test.cc +++ /dev/null
@@ -1,87 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_entry_type_decoder.h" - -#include <vector> - -#include "base/logging.h" -#include "net/third_party/http2/hpack/tools/hpack_block_builder.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionFailure; -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; - -namespace http2 { -namespace test { -namespace { -const bool kReturnNonZeroOnFirst = true; - -class HpackEntryTypeDecoderTest : public RandomDecoderTest { - protected: - DecodeStatus StartDecoding(DecodeBuffer* b) override { - CHECK_LT(0u, b->Remaining()); - return decoder_.Start(b); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - return decoder_.Resume(b); - } - - HpackEntryTypeDecoder decoder_; -}; - -TEST_F(HpackEntryTypeDecoderTest, DynamicTableSizeUpdate) { - for (uint32_t size = 0; size < 1000 * 1000; size += 256) { - HpackBlockBuilder bb; - bb.AppendDynamicTableSizeUpdate(size); - DecodeBuffer db(bb.buffer()); - auto validator = [size, this]() -> AssertionResult { - VERIFY_EQ(HpackEntryType::kDynamicTableSizeUpdate, decoder_.entry_type()); - VERIFY_EQ(size, decoder_.varint()); - return AssertionSuccess(); - }; - EXPECT_TRUE(DecodeAndValidateSeveralWays(&db, kReturnNonZeroOnFirst, - ValidateDoneAndEmpty(validator))) - << "\nentry_type=kDynamicTableSizeUpdate, size=" << size; - // Run the validator again to make sure that DecodeAndValidateSeveralWays - // did the right thing. - EXPECT_TRUE(validator()); - } -} - -TEST_F(HpackEntryTypeDecoderTest, HeaderWithIndex) { - std::vector<HpackEntryType> entry_types = { - HpackEntryType::kIndexedHeader, - HpackEntryType::kIndexedLiteralHeader, - HpackEntryType::kUnindexedLiteralHeader, - HpackEntryType::kNeverIndexedLiteralHeader, - }; - for (const HpackEntryType entry_type : entry_types) { - const uint32_t first = entry_type == HpackEntryType::kIndexedHeader ? 1 : 0; - for (uint32_t index = first; index < 1000; ++index) { - HpackBlockBuilder bb; - bb.AppendEntryTypeAndVarint(entry_type, index); - DecodeBuffer db(bb.buffer()); - auto validator = [entry_type, index, this]() -> AssertionResult { - VERIFY_EQ(entry_type, decoder_.entry_type()); - VERIFY_EQ(index, decoder_.varint()); - return AssertionSuccess(); - }; - EXPECT_TRUE(DecodeAndValidateSeveralWays(&db, kReturnNonZeroOnFirst, - ValidateDoneAndEmpty(validator))) - << "\nentry_type=" << entry_type << ", index=" << index; - // Run the validator again to make sure that DecodeAndValidateSeveralWays - // did the right thing. - EXPECT_TRUE(validator()); - } - } -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_string_collector.cc b/net/third_party/http2/hpack/decoder/hpack_string_collector.cc deleted file mode 100644 index c58094b..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_string_collector.cc +++ /dev/null
@@ -1,123 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_string_collector.h" - -#include <stddef.h> - -#include <iosfwd> -#include <ostream> - -#include "net/third_party/http2/platform/api/http2_string_utils.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { -namespace { - -std::ostream& operator<<(std::ostream& out, - HpackStringCollector::CollectorState v) { - switch (v) { - case HpackStringCollector::CollectorState::kGenesis: - return out << "kGenesis"; - case HpackStringCollector::CollectorState::kStarted: - return out << "kStarted"; - case HpackStringCollector::CollectorState::kEnded: - return out << "kEnded"; - } - return out << "UnknownCollectorState"; -} - -} // namespace - -HpackStringCollector::HpackStringCollector() { - Clear(); -} - -HpackStringCollector::HpackStringCollector(const Http2String& str, bool huffman) - : s(str), len(str.size()), huffman_encoded(huffman), state(kEnded) {} - -void HpackStringCollector::Clear() { - s = ""; - len = 0; - huffman_encoded = false; - state = kGenesis; -} - -bool HpackStringCollector::IsClear() const { - return s.empty() && len == 0 && huffman_encoded == false && state == kGenesis; -} - -bool HpackStringCollector::IsInProgress() const { - return state == kStarted; -} - -bool HpackStringCollector::HasEnded() const { - return state == kEnded; -} - -void HpackStringCollector::OnStringStart(bool huffman, size_t length) { - EXPECT_TRUE(IsClear()) << ToString(); - state = kStarted; - huffman_encoded = huffman; - len = length; -} - -void HpackStringCollector::OnStringData(const char* data, size_t length) { - Http2StringPiece sp(data, length); - EXPECT_TRUE(IsInProgress()) << ToString(); - EXPECT_LE(sp.size(), len) << ToString(); - Http2StrAppend(&s, sp); - EXPECT_LE(s.size(), len) << ToString(); -} - -void HpackStringCollector::OnStringEnd() { - EXPECT_TRUE(IsInProgress()) << ToString(); - EXPECT_EQ(s.size(), len) << ToString(); - state = kEnded; -} - -::testing::AssertionResult HpackStringCollector::Collected( - Http2StringPiece str, - bool is_huffman_encoded) const { - VERIFY_TRUE(HasEnded()); - VERIFY_EQ(str.size(), len); - VERIFY_EQ(is_huffman_encoded, huffman_encoded); - VERIFY_EQ(str, s); - return ::testing::AssertionSuccess(); -} - -Http2String HpackStringCollector::ToString() const { - std::stringstream ss; - ss << *this; - return ss.str(); -} - -bool operator==(const HpackStringCollector& a, const HpackStringCollector& b) { - return a.s == b.s && a.len == b.len && - a.huffman_encoded == b.huffman_encoded && a.state == b.state; -} - -bool operator!=(const HpackStringCollector& a, const HpackStringCollector& b) { - return !(a == b); -} - -std::ostream& operator<<(std::ostream& out, const HpackStringCollector& v) { - out << "HpackStringCollector(state=" << v.state; - if (v.state == HpackStringCollector::kGenesis) { - return out << ")"; - } - if (v.huffman_encoded) { - out << ", Huffman Encoded"; - } - out << ", Length=" << v.len; - if (!v.s.empty() && v.len != v.s.size()) { - out << " (" << v.s.size() << ")"; - } - return out << ", String=\"" << Http2HexEscape(v.s) << "\")"; -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_string_collector.h b/net/third_party/http2/hpack/decoder/hpack_string_collector.h deleted file mode 100644 index af4aa6e8..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_string_collector.h +++ /dev/null
@@ -1,63 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_STRING_COLLECTOR_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_STRING_COLLECTOR_H_ - -// Supports tests of decoding HPACK strings. - -#include <stddef.h> - -#include <iosfwd> - -#include "net/third_party/http2/hpack/decoder/hpack_string_decoder_listener.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -// Records the callbacks associated with a decoding a string; must -// call Clear() between decoding successive strings. -struct HpackStringCollector : public HpackStringDecoderListener { - enum CollectorState { - kGenesis, - kStarted, - kEnded, - }; - - HpackStringCollector(); - HpackStringCollector(const Http2String& str, bool huffman); - - void Clear(); - bool IsClear() const; - bool IsInProgress() const; - bool HasEnded() const; - - void OnStringStart(bool huffman, size_t length) override; - void OnStringData(const char* data, size_t length) override; - void OnStringEnd() override; - - ::testing::AssertionResult Collected(Http2StringPiece str, - bool is_huffman_encoded) const; - - Http2String ToString() const; - - Http2String s; - size_t len; - bool huffman_encoded; - CollectorState state; -}; - -bool operator==(const HpackStringCollector& a, const HpackStringCollector& b); - -bool operator!=(const HpackStringCollector& a, const HpackStringCollector& b); - -std::ostream& operator<<(std::ostream& out, const HpackStringCollector& v); - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_STRING_COLLECTOR_H_
diff --git a/net/third_party/http2/hpack/decoder/hpack_string_decoder.cc b/net/third_party/http2/hpack/decoder/hpack_string_decoder.cc deleted file mode 100644 index 4ffabc8..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_string_decoder.cc +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_string_decoder.h" - -#include "net/third_party/http2/platform/api/http2_string_utils.h" - -namespace http2 { - -Http2String HpackStringDecoder::DebugString() const { - return Http2StrCat("HpackStringDecoder(state=", StateToString(state_), - ", length=", length_decoder_.DebugString(), - ", remaining=", remaining_, - ", huffman=", huffman_encoded_ ? "true)" : "false)"); -} - -// static -Http2String HpackStringDecoder::StateToString(StringDecoderState v) { - switch (v) { - case kStartDecodingLength: - return "kStartDecodingLength"; - case kDecodingString: - return "kDecodingString"; - case kResumeDecodingLength: - return "kResumeDecodingLength"; - } - return Http2StrCat("UNKNOWN_STATE(", static_cast<uint32_t>(v), ")"); -} - -std::ostream& operator<<(std::ostream& out, const HpackStringDecoder& v) { - return out << v.DebugString(); -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_string_decoder.h b/net/third_party/http2/hpack/decoder/hpack_string_decoder.h deleted file mode 100644 index 6cce067..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_string_decoder.h +++ /dev/null
@@ -1,208 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_H_ - -// HpackStringDecoder decodes strings encoded per the HPACK spec; this does -// not mean decompressing Huffman encoded strings, just identifying the length, -// encoding and contents for a listener. - -#include <stddef.h> - -#include <algorithm> -#include <cstdint> - -#include "base/logging.h" -#include "base/macros.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/hpack/varint/hpack_varint_decoder.h" -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_macros.h" -#include "net/third_party/http2/platform/api/http2_string.h" - -namespace http2 { - -// Decodes a single string in an HPACK header entry. The high order bit of -// the first byte of the length is the H (Huffman) bit indicating whether -// the value is Huffman encoded, and the remainder of the byte is the first -// 7 bits of an HPACK varint. -// -// Call Start() to begin decoding; if it returns kDecodeInProgress, then call -// Resume() when more input is available, repeating until kDecodeInProgress is -// not returned. If kDecodeDone or kDecodeError is returned, then Resume() must -// not be called until Start() has been called to start decoding a new string. -class HTTP2_EXPORT_PRIVATE HpackStringDecoder { - public: - enum StringDecoderState { - kStartDecodingLength, - kDecodingString, - kResumeDecodingLength, - }; - - template <class Listener> - DecodeStatus Start(DecodeBuffer* db, Listener* cb) { - // Fast decode path is used if the string is under 127 bytes and the - // entire length of the string is in the decode buffer. More than 83% of - // string lengths are encoded in just one byte. - if (db->HasData() && (*db->cursor() & 0x7f) != 0x7f) { - // The string is short. - uint8_t h_and_prefix = db->DecodeUInt8(); - uint8_t length = h_and_prefix & 0x7f; - bool huffman_encoded = (h_and_prefix & 0x80) == 0x80; - cb->OnStringStart(huffman_encoded, length); - if (length <= db->Remaining()) { - // Yeah, we've got the whole thing in the decode buffer. - // Ideally this will be the common case. Note that we don't - // update any of the member variables in this path. - cb->OnStringData(db->cursor(), length); - db->AdvanceCursor(length); - cb->OnStringEnd(); - return DecodeStatus::kDecodeDone; - } - // Not all in the buffer. - huffman_encoded_ = huffman_encoded; - remaining_ = length; - // Call Resume to decode the string body, which is only partially - // in the decode buffer (or not at all). - state_ = kDecodingString; - return Resume(db, cb); - } - // Call Resume to decode the string length, which is either not in - // the decode buffer, or spans multiple bytes. - state_ = kStartDecodingLength; - return Resume(db, cb); - } - - template <class Listener> - DecodeStatus Resume(DecodeBuffer* db, Listener* cb) { - DecodeStatus status; - while (true) { - switch (state_) { - case kStartDecodingLength: - DVLOG(2) << "kStartDecodingLength: db->Remaining=" << db->Remaining(); - if (!StartDecodingLength(db, cb, &status)) { - // The length is split across decode buffers. - return status; - } - // We've finished decoding the length, which spanned one or more - // bytes. Approximately 17% of strings have a length that is greater - // than 126 bytes, and thus the length is encoded in more than one - // byte, and so doesn't get the benefit of the optimization in - // Start() for single byte lengths. But, we still expect that most - // of such strings will be contained entirely in a single decode - // buffer, and hence this fall through skips another trip through the - // switch above and more importantly skips setting the state_ variable - // again in those cases where we don't need it. - HTTP2_FALLTHROUGH; - - case kDecodingString: - DVLOG(2) << "kDecodingString: db->Remaining=" << db->Remaining() - << " remaining_=" << remaining_; - return DecodeString(db, cb); - - case kResumeDecodingLength: - DVLOG(2) << "kResumeDecodingLength: db->Remaining=" - << db->Remaining(); - if (!ResumeDecodingLength(db, cb, &status)) { - return status; - } - } - } - } - - Http2String DebugString() const; - - private: - static Http2String StateToString(StringDecoderState v); - - // Returns true if the length is fully decoded and the listener wants the - // decoding to continue, false otherwise; status is set to the status from - // the varint decoder. - // If the length is not fully decoded, case state_ is set appropriately - // for the next call to Resume. - template <class Listener> - bool StartDecodingLength(DecodeBuffer* db, - Listener* cb, - DecodeStatus* status) { - if (db->Empty()) { - *status = DecodeStatus::kDecodeInProgress; - state_ = kStartDecodingLength; - return false; - } - uint8_t h_and_prefix = db->DecodeUInt8(); - huffman_encoded_ = (h_and_prefix & 0x80) == 0x80; - *status = length_decoder_.Start(h_and_prefix, 7, db); - if (*status == DecodeStatus::kDecodeDone) { - OnStringStart(cb, status); - return true; - } - // Set the state to cover the DecodeStatus::kDecodeInProgress case. - // Won't be needed if the status is kDecodeError. - state_ = kResumeDecodingLength; - return false; - } - - // Returns true if the length is fully decoded and the listener wants the - // decoding to continue, false otherwise; status is set to the status from - // the varint decoder; state_ is updated when fully decoded. - // If the length is not fully decoded, case state_ is set appropriately - // for the next call to Resume. - template <class Listener> - bool ResumeDecodingLength(DecodeBuffer* db, - Listener* cb, - DecodeStatus* status) { - DCHECK_EQ(state_, kResumeDecodingLength); - *status = length_decoder_.Resume(db); - if (*status == DecodeStatus::kDecodeDone) { - state_ = kDecodingString; - OnStringStart(cb, status); - return true; - } - return false; - } - - // Returns true if the listener wants the decoding to continue, and - // false otherwise, in which case status set. - template <class Listener> - void OnStringStart(Listener* cb, DecodeStatus* status) { - remaining_ = length_decoder_.value(); - // Make callback so consumer knows what is coming. - cb->OnStringStart(huffman_encoded_, remaining_); - } - - // Passes the available portion of the string to the listener, and signals - // the end of the string when it is reached. Returns kDecodeDone or - // kDecodeInProgress as appropriate. - template <class Listener> - DecodeStatus DecodeString(DecodeBuffer* db, Listener* cb) { - size_t len = std::min(remaining_, db->Remaining()); - if (len > 0) { - cb->OnStringData(db->cursor(), len); - db->AdvanceCursor(len); - remaining_ -= len; - } - if (remaining_ == 0) { - cb->OnStringEnd(); - return DecodeStatus::kDecodeDone; - } - state_ = kDecodingString; - return DecodeStatus::kDecodeInProgress; - } - - HpackVarintDecoder length_decoder_; - - // These fields are initialized just to keep ASAN happy about reading - // them from DebugString(). - size_t remaining_ = 0; - StringDecoderState state_ = kStartDecodingLength; - bool huffman_encoded_ = false; -}; - -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const HpackStringDecoder& v); - -} // namespace http2 -#endif // NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_H_
diff --git a/net/third_party/http2/hpack/decoder/hpack_string_decoder_listener.cc b/net/third_party/http2/hpack/decoder/hpack_string_decoder_listener.cc deleted file mode 100644 index b373408b..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_string_decoder_listener.cc +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_string_decoder_listener.h" - -#include "base/logging.h" - -namespace http2 { -namespace test { - -void HpackStringDecoderVLoggingListener::OnStringStart(bool huffman_encoded, - size_t len) { - VLOG(1) << "OnStringStart: H=" << huffman_encoded << ", len=" << len; - if (wrapped_) { - wrapped_->OnStringStart(huffman_encoded, len); - } -} - -void HpackStringDecoderVLoggingListener::OnStringData(const char* data, - size_t len) { - VLOG(1) << "OnStringData: len=" << len; - if (wrapped_) { - return wrapped_->OnStringData(data, len); - } -} - -void HpackStringDecoderVLoggingListener::OnStringEnd() { - VLOG(1) << "OnStringEnd"; - if (wrapped_) { - return wrapped_->OnStringEnd(); - } -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_string_decoder_listener.h b/net/third_party/http2/hpack/decoder/hpack_string_decoder_listener.h deleted file mode 100644 index b5bd3cc..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_string_decoder_listener.h +++ /dev/null
@@ -1,62 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_LISTENER_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_LISTENER_H_ - -// Defines HpackStringDecoderListener which defines the methods required by an -// HpackStringDecoder. Also defines HpackStringDecoderVLoggingListener which -// logs before calling another HpackStringDecoderListener implementation. -// For now these are only used by tests, so placed in the test namespace. - -#include <stddef.h> - -#include "net/third_party/http2/platform/api/http2_export.h" - -namespace http2 { -namespace test { - -// HpackStringDecoder methods require a listener that implements the methods -// below, but it is NOT necessary to extend this class because the methods -// are templates. -class HTTP2_EXPORT_PRIVATE HpackStringDecoderListener { - public: - virtual ~HpackStringDecoderListener() {} - - // Called at the start of decoding an HPACK string. The encoded length of the - // string is |len| bytes, which may be zero. The string is Huffman encoded - // if huffman_encoded is true, else it is plain text (i.e. the encoded length - // is then the plain text length). - virtual void OnStringStart(bool huffman_encoded, size_t len) = 0; - - // Called when some data is available, or once when the string length is zero - // (to simplify the decoder, it doesn't have a special case for len==0). - virtual void OnStringData(const char* data, size_t len) = 0; - - // Called after OnStringData has provided all of the encoded bytes of the - // string. - virtual void OnStringEnd() = 0; -}; - -class HTTP2_EXPORT_PRIVATE HpackStringDecoderVLoggingListener - : public HpackStringDecoderListener { - public: - HpackStringDecoderVLoggingListener() : wrapped_(nullptr) {} - explicit HpackStringDecoderVLoggingListener( - HpackStringDecoderListener* wrapped) - : wrapped_(wrapped) {} - ~HpackStringDecoderVLoggingListener() override {} - - void OnStringStart(bool huffman_encoded, size_t len) override; - void OnStringData(const char* data, size_t len) override; - void OnStringEnd() override; - - private: - HpackStringDecoderListener* const wrapped_; -}; - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_STRING_DECODER_LISTENER_H_
diff --git a/net/third_party/http2/hpack/decoder/hpack_string_decoder_test.cc b/net/third_party/http2/hpack/decoder/hpack_string_decoder_test.cc deleted file mode 100644 index f1cd7314..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_string_decoder_test.cc +++ /dev/null
@@ -1,155 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_string_decoder.h" - -// Tests of HpackStringDecoder. - -#include "net/third_party/http2/hpack/decoder/hpack_string_collector.h" -#include "net/third_party/http2/hpack/decoder/hpack_string_decoder_listener.h" -#include "net/third_party/http2/hpack/tools/hpack_block_builder.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionResult; - -namespace http2 { -namespace test { -namespace { - -const bool kMayReturnZeroOnFirst = false; -const bool kCompressed = true; -const bool kUncompressed = false; - -class HpackStringDecoderTest : public RandomDecoderTest { - protected: - HpackStringDecoderTest() : listener_(&collector_) {} - - DecodeStatus StartDecoding(DecodeBuffer* b) override { - ++start_decoding_calls_; - collector_.Clear(); - return decoder_.Start(b, &listener_); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - // Provides coverage of DebugString and StateToString. - // Not validating output. - VLOG(1) << decoder_.DebugString(); - VLOG(2) << collector_; - return decoder_.Resume(b, &listener_); - } - - AssertionResult Collected(Http2StringPiece s, bool huffman_encoded) { - VLOG(1) << collector_; - return collector_.Collected(s, huffman_encoded); - } - - // expected_str is a Http2String rather than a const Http2String& or - // Http2StringPiece so that the lambda makes a copy of the string, and thus - // the string to be passed to Collected outlives the call to MakeValidator. - Validator MakeValidator(const Http2String& expected_str, - bool expected_huffman) { - return - [expected_str, expected_huffman, this]( - const DecodeBuffer& input, DecodeStatus status) -> AssertionResult { - AssertionResult result = Collected(expected_str, expected_huffman); - if (result) { - VERIFY_EQ(collector_, - HpackStringCollector(expected_str, expected_huffman)); - } else { - VERIFY_NE(collector_, - HpackStringCollector(expected_str, expected_huffman)); - } - VLOG(2) << collector_.ToString(); - collector_.Clear(); - VLOG(2) << collector_; - return result; - }; - } - - HpackStringDecoder decoder_; - HpackStringCollector collector_; - HpackStringDecoderVLoggingListener listener_; - size_t start_decoding_calls_ = 0; -}; - -TEST_F(HpackStringDecoderTest, DecodeEmptyString) { - { - Validator validator = ValidateDoneAndEmpty(MakeValidator("", kCompressed)); - const char kData[] = {'\x80'}; - DecodeBuffer b(kData); - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator)); - } - { - // Make sure it stops after decoding the empty string. - Validator validator = - ValidateDoneAndOffset(1, MakeValidator("", kUncompressed)); - const char kData[] = {'\x00', '\xff'}; - DecodeBuffer b(kData); - EXPECT_EQ(2u, b.Remaining()); - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator)); - EXPECT_EQ(1u, b.Remaining()); - } -} - -TEST_F(HpackStringDecoderTest, DecodeShortString) { - { - // Make sure it stops after decoding the non-empty string. - Validator validator = - ValidateDoneAndOffset(11, MakeValidator("start end.", kCompressed)); - const char kData[] = "\x8astart end.Don't peek at this."; - DecodeBuffer b(kData); - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator)); - } - { - Validator validator = - ValidateDoneAndOffset(11, MakeValidator("start end.", kUncompressed)); - Http2StringPiece data("\x0astart end."); - DecodeBuffer b(data); - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, kMayReturnZeroOnFirst, validator)); - } -} - -TEST_F(HpackStringDecoderTest, DecodeLongStrings) { - Http2String name = Random().RandString(1024); - Http2String value = Random().RandString(65536); - HpackBlockBuilder hbb; - - hbb.AppendString(false, name); - uint32_t offset_after_name = hbb.size(); - EXPECT_EQ(3 + name.size(), offset_after_name); - - hbb.AppendString(true, value); - uint32_t offset_after_value = hbb.size(); - EXPECT_EQ(3 + name.size() + 4 + value.size(), offset_after_value); - - DecodeBuffer b(hbb.buffer()); - - // Decode the name... - EXPECT_TRUE(DecodeAndValidateSeveralWays( - &b, kMayReturnZeroOnFirst, - ValidateDoneAndOffset(offset_after_name, - MakeValidator(name, kUncompressed)))); - EXPECT_EQ(offset_after_name, b.Offset()); - EXPECT_EQ(offset_after_value - offset_after_name, b.Remaining()); - - // Decode the value... - EXPECT_TRUE(DecodeAndValidateSeveralWays( - &b, kMayReturnZeroOnFirst, - ValidateDoneAndOffset(offset_after_value - offset_after_name, - MakeValidator(value, kCompressed)))); - EXPECT_EQ(offset_after_value, b.Offset()); - EXPECT_EQ(0u, b.Remaining()); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_whole_entry_buffer.cc b/net/third_party/http2/hpack/decoder/hpack_whole_entry_buffer.cc deleted file mode 100644 index 722846a..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_whole_entry_buffer.cc +++ /dev/null
@@ -1,139 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_whole_entry_buffer.h" - -#include "base/logging.h" -#include "net/third_party/http2/platform/api/http2_estimate_memory_usage.h" -#include "net/third_party/http2/platform/api/http2_macros.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" - -namespace http2 { - -HpackWholeEntryBuffer::HpackWholeEntryBuffer(HpackWholeEntryListener* listener, - size_t max_string_size_bytes) - : max_string_size_bytes_(max_string_size_bytes) { - set_listener(listener); -} -HpackWholeEntryBuffer::~HpackWholeEntryBuffer() = default; - -void HpackWholeEntryBuffer::set_listener(HpackWholeEntryListener* listener) { - listener_ = HTTP2_DIE_IF_NULL(listener); -} - -void HpackWholeEntryBuffer::set_max_string_size_bytes( - size_t max_string_size_bytes) { - max_string_size_bytes_ = max_string_size_bytes; -} - -void HpackWholeEntryBuffer::BufferStringsIfUnbuffered() { - name_.BufferStringIfUnbuffered(); - value_.BufferStringIfUnbuffered(); -} - -size_t HpackWholeEntryBuffer::EstimateMemoryUsage() const { - return Http2EstimateMemoryUsage(name_) + Http2EstimateMemoryUsage(value_); -} - -void HpackWholeEntryBuffer::OnIndexedHeader(size_t index) { - DVLOG(2) << "HpackWholeEntryBuffer::OnIndexedHeader: index=" << index; - listener_->OnIndexedHeader(index); -} - -void HpackWholeEntryBuffer::OnStartLiteralHeader(HpackEntryType entry_type, - size_t maybe_name_index) { - DVLOG(2) << "HpackWholeEntryBuffer::OnStartLiteralHeader: entry_type=" - << entry_type << ", maybe_name_index=" << maybe_name_index; - entry_type_ = entry_type; - maybe_name_index_ = maybe_name_index; -} - -void HpackWholeEntryBuffer::OnNameStart(bool huffman_encoded, size_t len) { - DVLOG(2) << "HpackWholeEntryBuffer::OnNameStart: huffman_encoded=" - << (huffman_encoded ? "true" : "false") << ", len=" << len; - DCHECK_EQ(maybe_name_index_, 0u); - if (!error_detected_) { - if (len > max_string_size_bytes_) { - DVLOG(1) << "Name length (" << len << ") is longer than permitted (" - << max_string_size_bytes_ << ")"; - ReportError("HPACK entry name size is too long."); - return; - } - name_.OnStart(huffman_encoded, len); - } -} - -void HpackWholeEntryBuffer::OnNameData(const char* data, size_t len) { - DVLOG(2) << "HpackWholeEntryBuffer::OnNameData: len=" << len << " data:\n" - << Http2HexDump(Http2StringPiece(data, len)); - DCHECK_EQ(maybe_name_index_, 0u); - if (!error_detected_ && !name_.OnData(data, len)) { - ReportError("Error decoding HPACK entry name."); - } -} - -void HpackWholeEntryBuffer::OnNameEnd() { - DVLOG(2) << "HpackWholeEntryBuffer::OnNameEnd"; - DCHECK_EQ(maybe_name_index_, 0u); - if (!error_detected_ && !name_.OnEnd()) { - ReportError("Error decoding HPACK entry name."); - } -} - -void HpackWholeEntryBuffer::OnValueStart(bool huffman_encoded, size_t len) { - DVLOG(2) << "HpackWholeEntryBuffer::OnValueStart: huffman_encoded=" - << (huffman_encoded ? "true" : "false") << ", len=" << len; - if (!error_detected_) { - if (len > max_string_size_bytes_) { - DVLOG(1) << "Value length (" << len << ") is longer than permitted (" - << max_string_size_bytes_ << ")"; - ReportError("HPACK entry value size is too long."); - return; - } - value_.OnStart(huffman_encoded, len); - } -} - -void HpackWholeEntryBuffer::OnValueData(const char* data, size_t len) { - DVLOG(2) << "HpackWholeEntryBuffer::OnValueData: len=" << len << " data:\n" - << Http2HexDump(Http2StringPiece(data, len)); - if (!error_detected_ && !value_.OnData(data, len)) { - ReportError("Error decoding HPACK entry value."); - } -} - -void HpackWholeEntryBuffer::OnValueEnd() { - DVLOG(2) << "HpackWholeEntryBuffer::OnValueEnd"; - if (error_detected_) { - return; - } - if (!value_.OnEnd()) { - ReportError("Error decoding HPACK entry value."); - return; - } - if (maybe_name_index_ == 0) { - listener_->OnLiteralNameAndValue(entry_type_, &name_, &value_); - name_.Reset(); - } else { - listener_->OnNameIndexAndLiteralValue(entry_type_, maybe_name_index_, - &value_); - } - value_.Reset(); -} - -void HpackWholeEntryBuffer::OnDynamicTableSizeUpdate(size_t size) { - DVLOG(2) << "HpackWholeEntryBuffer::OnDynamicTableSizeUpdate: size=" << size; - listener_->OnDynamicTableSizeUpdate(size); -} - -void HpackWholeEntryBuffer::ReportError(Http2StringPiece error_message) { - if (!error_detected_) { - DVLOG(1) << "HpackWholeEntryBuffer::ReportError: " << error_message; - error_detected_ = true; - listener_->OnHpackDecodeError(error_message); - listener_ = HpackWholeEntryNoOpListener::NoOpListener(); - } -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_whole_entry_buffer.h b/net/third_party/http2/hpack/decoder/hpack_whole_entry_buffer.h deleted file mode 100644 index eff038a..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_whole_entry_buffer.h +++ /dev/null
@@ -1,104 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_BUFFER_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_BUFFER_H_ - -// HpackWholeEntryBuffer isolates a listener from the fact that an entry may -// be split across multiple input buffers, providing one callback per entry. -// HpackWholeEntryBuffer requires that the HpackEntryDecoderListener be made in -// the correct order, which is tested by hpack_entry_decoder_test.cc. - -#include <stddef.h> - -#include "net/third_party/http2/hpack/decoder/hpack_decoder_string_buffer.h" -#include "net/third_party/http2/hpack/decoder/hpack_entry_decoder_listener.h" -#include "net/third_party/http2/hpack/decoder/hpack_whole_entry_listener.h" -#include "net/third_party/http2/hpack/http2_hpack_constants.h" -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" - -namespace http2 { - -// TODO(jamessynge): Consider renaming HpackEntryDecoderListener to -// HpackEntryPartsListener or HpackEntryFragmentsListener. -class HTTP2_EXPORT_PRIVATE HpackWholeEntryBuffer - : public HpackEntryDecoderListener { - public: - // max_string_size specifies the maximum size of an on-the-wire string (name - // or value, plain or Huffman encoded) that will be accepted. See sections - // 5.1 and 5.2 of RFC 7541. This is a defense against OOM attacks; HTTP/2 - // allows a decoder to enforce any limit of the size of the header lists - // that it is willing decode, including less than the MAX_HEADER_LIST_SIZE - // setting, a setting that is initially unlimited. For example, we might - // choose to send a MAX_HEADER_LIST_SIZE of 64KB, and to use that same value - // as the upper bound for individual strings. - HpackWholeEntryBuffer(HpackWholeEntryListener* listener, - size_t max_string_size); - ~HpackWholeEntryBuffer() override; - - HpackWholeEntryBuffer(const HpackWholeEntryBuffer&) = delete; - HpackWholeEntryBuffer& operator=(const HpackWholeEntryBuffer&) = delete; - - // Set the listener to be notified when a whole entry has been decoded. - // The listener may be changed at any time. - void set_listener(HpackWholeEntryListener* listener); - - // Set how much encoded data this decoder is willing to buffer. - // TODO(jamessynge): Come up with consistent semantics for this protection - // across the various decoders; e.g. should it be for a single string or - // a single header entry? - void set_max_string_size_bytes(size_t max_string_size_bytes); - - // Ensure that decoded strings pointed to by the HpackDecoderStringBuffer - // instances name_ and value_ are buffered, which allows any underlying - // transport buffer to be freed or reused without overwriting the decoded - // strings. This is needed only when an HPACK entry is split across transport - // buffers. See HpackDecoder::DecodeFragment. - void BufferStringsIfUnbuffered(); - - // Was an error detected? After an error has been detected and reported, - // no further callbacks will be made to the listener. - bool error_detected() const { return error_detected_; } - - // Returns the estimate of dynamically allocated memory in bytes. - size_t EstimateMemoryUsage() const; - - // Implement the HpackEntryDecoderListener methods. - - void OnIndexedHeader(size_t index) override; - void OnStartLiteralHeader(HpackEntryType entry_type, - size_t maybe_name_index) override; - void OnNameStart(bool huffman_encoded, size_t len) override; - void OnNameData(const char* data, size_t len) override; - void OnNameEnd() override; - void OnValueStart(bool huffman_encoded, size_t len) override; - void OnValueData(const char* data, size_t len) override; - void OnValueEnd() override; - void OnDynamicTableSizeUpdate(size_t size) override; - - private: - void ReportError(Http2StringPiece error_message); - - HpackWholeEntryListener* listener_; - HpackDecoderStringBuffer name_, value_; - - // max_string_size_bytes_ specifies the maximum allowed size of an on-the-wire - // string. Larger strings will be reported as errors to the listener; the - // endpoint should treat these as COMPRESSION errors, which are CONNECTION - // level errors. - size_t max_string_size_bytes_; - - // The name index (or zero) of the current header entry with a literal value. - size_t maybe_name_index_; - - // The type of the current header entry (with literals) that is being decoded. - HpackEntryType entry_type_; - - bool error_detected_ = false; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_BUFFER_H_
diff --git a/net/third_party/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc b/net/third_party/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc deleted file mode 100644 index b1d9ecb..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_whole_entry_buffer_test.cc +++ /dev/null
@@ -1,206 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_whole_entry_buffer.h" - -// Tests of HpackWholeEntryBuffer: does it buffer correctly, and does it -// detect Huffman decoding errors and oversize string errors? - -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AllOf; -using ::testing::HasSubstr; -using ::testing::InSequence; -using ::testing::Property; -using ::testing::StrictMock; - -namespace http2 { -namespace test { -namespace { - -constexpr size_t kMaxStringSize = 20; - -class MockHpackWholeEntryListener : public HpackWholeEntryListener { - public: - ~MockHpackWholeEntryListener() override = default; - - MOCK_METHOD1(OnIndexedHeader, void(size_t index)); - MOCK_METHOD3(OnNameIndexAndLiteralValue, - void(HpackEntryType entry_type, - size_t name_index, - HpackDecoderStringBuffer* value_buffer)); - MOCK_METHOD3(OnLiteralNameAndValue, - void(HpackEntryType entry_type, - HpackDecoderStringBuffer* name_buffer, - HpackDecoderStringBuffer* value_buffer)); - MOCK_METHOD1(OnDynamicTableSizeUpdate, void(size_t size)); - MOCK_METHOD1(OnHpackDecodeError, void(Http2StringPiece error_message)); -}; - -class HpackWholeEntryBufferTest : public ::testing::Test { - protected: - HpackWholeEntryBufferTest() : entry_buffer_(&listener_, kMaxStringSize) {} - ~HpackWholeEntryBufferTest() override = default; - - StrictMock<MockHpackWholeEntryListener> listener_; - HpackWholeEntryBuffer entry_buffer_; -}; - -// OnIndexedHeader is an immediate pass through. -TEST_F(HpackWholeEntryBufferTest, OnIndexedHeader) { - { - InSequence seq; - EXPECT_CALL(listener_, OnIndexedHeader(17)); - entry_buffer_.OnIndexedHeader(17); - } - { - InSequence seq; - EXPECT_CALL(listener_, OnIndexedHeader(62)); - entry_buffer_.OnIndexedHeader(62); - } - { - InSequence seq; - EXPECT_CALL(listener_, OnIndexedHeader(62)); - entry_buffer_.OnIndexedHeader(62); - } - { - InSequence seq; - EXPECT_CALL(listener_, OnIndexedHeader(128)); - entry_buffer_.OnIndexedHeader(128); - } - StrictMock<MockHpackWholeEntryListener> listener2; - entry_buffer_.set_listener(&listener2); - { - InSequence seq; - EXPECT_CALL(listener2, OnIndexedHeader(100)); - entry_buffer_.OnIndexedHeader(100); - } -} - -// OnDynamicTableSizeUpdate is an immediate pass through. -TEST_F(HpackWholeEntryBufferTest, OnDynamicTableSizeUpdate) { - { - InSequence seq; - EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(4096)); - entry_buffer_.OnDynamicTableSizeUpdate(4096); - } - { - InSequence seq; - EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(0)); - entry_buffer_.OnDynamicTableSizeUpdate(0); - } - { - InSequence seq; - EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(1024)); - entry_buffer_.OnDynamicTableSizeUpdate(1024); - } - { - InSequence seq; - EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(1024)); - entry_buffer_.OnDynamicTableSizeUpdate(1024); - } - StrictMock<MockHpackWholeEntryListener> listener2; - entry_buffer_.set_listener(&listener2); - { - InSequence seq; - EXPECT_CALL(listener2, OnDynamicTableSizeUpdate(0)); - entry_buffer_.OnDynamicTableSizeUpdate(0); - } -} - -TEST_F(HpackWholeEntryBufferTest, OnNameIndexAndLiteralValue) { - entry_buffer_.OnStartLiteralHeader(HpackEntryType::kNeverIndexedLiteralHeader, - 123); - entry_buffer_.OnValueStart(false, 10); - entry_buffer_.OnValueData("some data.", 10); - - // Force the value to be buffered. - entry_buffer_.BufferStringsIfUnbuffered(); - - EXPECT_CALL( - listener_, - OnNameIndexAndLiteralValue( - HpackEntryType::kNeverIndexedLiteralHeader, 123, - AllOf(Property(&HpackDecoderStringBuffer::str, "some data."), - Property(&HpackDecoderStringBuffer::BufferedLength, 10)))); - - entry_buffer_.OnValueEnd(); -} - -TEST_F(HpackWholeEntryBufferTest, OnLiteralNameAndValue) { - entry_buffer_.OnStartLiteralHeader(HpackEntryType::kIndexedLiteralHeader, 0); - // Force the name to be buffered by delivering it in two pieces. - entry_buffer_.OnNameStart(false, 9); - entry_buffer_.OnNameData("some-", 5); - entry_buffer_.OnNameData("name", 4); - entry_buffer_.OnNameEnd(); - entry_buffer_.OnValueStart(false, 12); - entry_buffer_.OnValueData("Header Value", 12); - - EXPECT_CALL( - listener_, - OnLiteralNameAndValue( - HpackEntryType::kIndexedLiteralHeader, - AllOf(Property(&HpackDecoderStringBuffer::str, "some-name"), - Property(&HpackDecoderStringBuffer::BufferedLength, 9)), - AllOf(Property(&HpackDecoderStringBuffer::str, "Header Value"), - Property(&HpackDecoderStringBuffer::BufferedLength, 0)))); - - entry_buffer_.OnValueEnd(); -} - -// Verify that a name longer than the allowed size generates an error. -TEST_F(HpackWholeEntryBufferTest, NameTooLong) { - entry_buffer_.OnStartLiteralHeader(HpackEntryType::kIndexedLiteralHeader, 0); - EXPECT_CALL(listener_, OnHpackDecodeError(HasSubstr("HPACK entry name"))); - entry_buffer_.OnNameStart(false, kMaxStringSize + 1); -} - -// Verify that a name longer than the allowed size generates an error. -TEST_F(HpackWholeEntryBufferTest, ValueTooLong) { - entry_buffer_.OnStartLiteralHeader(HpackEntryType::kIndexedLiteralHeader, 1); - EXPECT_CALL(listener_, OnHpackDecodeError(HasSubstr("HPACK entry value"))); - entry_buffer_.OnValueStart(false, kMaxStringSize + 1); -} - -// Verify that a Huffman encoded name with an explicit EOS generates an error -// for an explicit EOS. -TEST_F(HpackWholeEntryBufferTest, NameHuffmanError) { - const char data[] = "\xff\xff\xff"; - entry_buffer_.OnStartLiteralHeader(HpackEntryType::kUnindexedLiteralHeader, - 0); - entry_buffer_.OnNameStart(true, 4); - entry_buffer_.OnNameData(data, 3); - - EXPECT_CALL(listener_, OnHpackDecodeError(HasSubstr("HPACK entry name"))); - - entry_buffer_.OnNameData(data, 1); - - // After an error is reported, the listener is not called again. - EXPECT_CALL(listener_, OnDynamicTableSizeUpdate(8096)).Times(0); - entry_buffer_.OnDynamicTableSizeUpdate(8096); -} - -// Verify that a Huffman encoded value that isn't properly terminated with -// a partial EOS symbol generates an error. -TEST_F(HpackWholeEntryBufferTest, ValueeHuffmanError) { - const char data[] = "\x00\x00\x00"; - entry_buffer_.OnStartLiteralHeader(HpackEntryType::kNeverIndexedLiteralHeader, - 61); - entry_buffer_.OnValueStart(true, 3); - entry_buffer_.OnValueData(data, 3); - - EXPECT_CALL(listener_, OnHpackDecodeError(HasSubstr("HPACK entry value"))); - - entry_buffer_.OnValueEnd(); - - // After an error is reported, the listener is not called again. - EXPECT_CALL(listener_, OnIndexedHeader(17)).Times(0); - entry_buffer_.OnIndexedHeader(17); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_whole_entry_listener.cc b/net/third_party/http2/hpack/decoder/hpack_whole_entry_listener.cc deleted file mode 100644 index cf0a8538..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_whole_entry_listener.cc +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/decoder/hpack_whole_entry_listener.h" - -namespace http2 { - -HpackWholeEntryListener::~HpackWholeEntryListener() = default; - -HpackWholeEntryNoOpListener::~HpackWholeEntryNoOpListener() = default; - -void HpackWholeEntryNoOpListener::OnIndexedHeader(size_t index) {} -void HpackWholeEntryNoOpListener::OnNameIndexAndLiteralValue( - HpackEntryType entry_type, - size_t name_index, - HpackDecoderStringBuffer* value_buffer) {} -void HpackWholeEntryNoOpListener::OnLiteralNameAndValue( - HpackEntryType entry_type, - HpackDecoderStringBuffer* name_buffer, - HpackDecoderStringBuffer* value_buffer) {} -void HpackWholeEntryNoOpListener::OnDynamicTableSizeUpdate(size_t size) {} -void HpackWholeEntryNoOpListener::OnHpackDecodeError( - Http2StringPiece error_message) {} - -// static -HpackWholeEntryNoOpListener* HpackWholeEntryNoOpListener::NoOpListener() { - static HpackWholeEntryNoOpListener* static_instance = - new HpackWholeEntryNoOpListener(); - return static_instance; -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/decoder/hpack_whole_entry_listener.h b/net/third_party/http2/hpack/decoder/hpack_whole_entry_listener.h deleted file mode 100644 index ca47099..0000000 --- a/net/third_party/http2/hpack/decoder/hpack_whole_entry_listener.h +++ /dev/null
@@ -1,80 +0,0 @@ -// Copyright 2016 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. - -// Defines HpackWholeEntryListener, the base class of listeners for decoded -// complete HPACK entries, as opposed to HpackEntryDecoderListener which -// receives multiple callbacks for some single entries. - -#ifndef NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_LISTENER_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_LISTENER_H_ - -#include <stddef.h> - -#include "net/third_party/http2/hpack/decoder/hpack_decoder_string_buffer.h" -#include "net/third_party/http2/hpack/http2_hpack_constants.h" -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" - -namespace http2 { - -class HTTP2_EXPORT_PRIVATE HpackWholeEntryListener { - public: - virtual ~HpackWholeEntryListener(); - - // Called when an indexed header (i.e. one in the static or dynamic table) has - // been decoded from an HPACK block. index is supposed to be non-zero, but - // that has not been checked by the caller. - virtual void OnIndexedHeader(size_t index) = 0; - - // Called when a header entry with a name index and literal value has - // been fully decoded from an HPACK block. name_index is NOT zero. - // entry_type will be kIndexedLiteralHeader, kUnindexedLiteralHeader, or - // kNeverIndexedLiteralHeader. - virtual void OnNameIndexAndLiteralValue( - HpackEntryType entry_type, - size_t name_index, - HpackDecoderStringBuffer* value_buffer) = 0; - - // Called when a header entry with a literal name and literal value - // has been fully decoded from an HPACK block. entry_type will be - // kIndexedLiteralHeader, kUnindexedLiteralHeader, or - // kNeverIndexedLiteralHeader. - virtual void OnLiteralNameAndValue( - HpackEntryType entry_type, - HpackDecoderStringBuffer* name_buffer, - HpackDecoderStringBuffer* value_buffer) = 0; - - // Called when an update to the size of the peer's dynamic table has been - // decoded. - virtual void OnDynamicTableSizeUpdate(size_t size) = 0; - - // OnHpackDecodeError is called if an error is detected while decoding. - // error_message may be used in a GOAWAY frame as the Opaque Data. - virtual void OnHpackDecodeError(Http2StringPiece error_message) = 0; -}; - -// A no-op implementation of HpackWholeEntryDecoderListener, useful for ignoring -// callbacks once an error is detected. -class HpackWholeEntryNoOpListener : public HpackWholeEntryListener { - public: - ~HpackWholeEntryNoOpListener() override; - - void OnIndexedHeader(size_t index) override; - void OnNameIndexAndLiteralValue( - HpackEntryType entry_type, - size_t name_index, - HpackDecoderStringBuffer* value_buffer) override; - void OnLiteralNameAndValue(HpackEntryType entry_type, - HpackDecoderStringBuffer* name_buffer, - HpackDecoderStringBuffer* value_buffer) override; - void OnDynamicTableSizeUpdate(size_t size) override; - void OnHpackDecodeError(Http2StringPiece error_message) override; - - // Returns a listener that ignores all the calls. - static HpackWholeEntryNoOpListener* NoOpListener(); -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_DECODER_HPACK_WHOLE_ENTRY_LISTENER_H_
diff --git a/net/third_party/http2/hpack/hpack_static_table_entries.inc b/net/third_party/http2/hpack/hpack_static_table_entries.inc deleted file mode 100644 index 3d2f1087..0000000 --- a/net/third_party/http2/hpack/hpack_static_table_entries.inc +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2016 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. - -// This file is designed to be included by C/C++ files which need the contents -// of the HPACK static table. It may be included more than once if necessary. -// See http://httpwg.org/specs/rfc7541.html#static.table.definition - -STATIC_TABLE_ENTRY(":authority", "", 1u); -STATIC_TABLE_ENTRY(":method", "GET", 2u); -STATIC_TABLE_ENTRY(":method", "POST", 3u); -STATIC_TABLE_ENTRY(":path", "/", 4u); -STATIC_TABLE_ENTRY(":path", "/index.html", 5u); -STATIC_TABLE_ENTRY(":scheme", "http", 6u); -STATIC_TABLE_ENTRY(":scheme", "https", 7u); -STATIC_TABLE_ENTRY(":status", "200", 8u); -STATIC_TABLE_ENTRY(":status", "204", 9u); -STATIC_TABLE_ENTRY(":status", "206", 10u); -STATIC_TABLE_ENTRY(":status", "304", 11u); -STATIC_TABLE_ENTRY(":status", "400", 12u); -STATIC_TABLE_ENTRY(":status", "404", 13u); -STATIC_TABLE_ENTRY(":status", "500", 14u); -STATIC_TABLE_ENTRY("accept-charset", "", 15u); -STATIC_TABLE_ENTRY("accept-encoding", "gzip, deflate", 16u); -STATIC_TABLE_ENTRY("accept-language", "", 17u); -STATIC_TABLE_ENTRY("accept-ranges", "", 18u); -STATIC_TABLE_ENTRY("accept", "", 19u); -STATIC_TABLE_ENTRY("access-control-allow-origin", "", 20u); -STATIC_TABLE_ENTRY("age", "", 21u); -STATIC_TABLE_ENTRY("allow", "", 22u); -STATIC_TABLE_ENTRY("authorization", "", 23u); -STATIC_TABLE_ENTRY("cache-control", "", 24u); -STATIC_TABLE_ENTRY("content-disposition", "", 25u); -STATIC_TABLE_ENTRY("content-encoding", "", 26u); -STATIC_TABLE_ENTRY("content-language", "", 27u); -STATIC_TABLE_ENTRY("content-length", "", 28u); -STATIC_TABLE_ENTRY("content-location", "", 29u); -STATIC_TABLE_ENTRY("content-range", "", 30u); -STATIC_TABLE_ENTRY("content-type", "", 31u); -STATIC_TABLE_ENTRY("cookie", "", 32u); -STATIC_TABLE_ENTRY("date", "", 33u); -STATIC_TABLE_ENTRY("etag", "", 34u); -STATIC_TABLE_ENTRY("expect", "", 35u); -STATIC_TABLE_ENTRY("expires", "", 36u); -STATIC_TABLE_ENTRY("from", "", 37u); -STATIC_TABLE_ENTRY("host", "", 38u); -STATIC_TABLE_ENTRY("if-match", "", 39u); -STATIC_TABLE_ENTRY("if-modified-since", "", 40u); -STATIC_TABLE_ENTRY("if-none-match", "", 41u); -STATIC_TABLE_ENTRY("if-range", "", 42u); -STATIC_TABLE_ENTRY("if-unmodified-since", "", 43u); -STATIC_TABLE_ENTRY("last-modified", "", 44u); -STATIC_TABLE_ENTRY("link", "", 45u); -STATIC_TABLE_ENTRY("location", "", 46u); -STATIC_TABLE_ENTRY("max-forwards", "", 47u); -STATIC_TABLE_ENTRY("proxy-authenticate", "", 48u); -STATIC_TABLE_ENTRY("proxy-authorization", "", 49u); -STATIC_TABLE_ENTRY("range", "", 50u); -STATIC_TABLE_ENTRY("referer", "", 51u); -STATIC_TABLE_ENTRY("refresh", "", 52u); -STATIC_TABLE_ENTRY("retry-after", "", 53u); -STATIC_TABLE_ENTRY("server", "", 54u); -STATIC_TABLE_ENTRY("set-cookie", "", 55u); -STATIC_TABLE_ENTRY("strict-transport-security", "", 56u); -STATIC_TABLE_ENTRY("transfer-encoding", "", 57u); -STATIC_TABLE_ENTRY("user-agent", "", 58u); -STATIC_TABLE_ENTRY("vary", "", 59u); -STATIC_TABLE_ENTRY("via", "", 60u); -STATIC_TABLE_ENTRY("www-authenticate", "", 61u);
diff --git a/net/third_party/http2/hpack/hpack_string.cc b/net/third_party/http2/hpack/hpack_string.cc deleted file mode 100644 index 54feec0..0000000 --- a/net/third_party/http2/hpack/hpack_string.cc +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/hpack_string.h" - -#include <utility> - -#include "base/logging.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" - -namespace http2 { - -HpackString::HpackString(const char* data) : str_(data) {} -HpackString::HpackString(Http2StringPiece str) : str_(Http2String(str)) {} -HpackString::HpackString(Http2String str) : str_(std::move(str)) {} -HpackString::HpackString(const HpackString& other) = default; -HpackString::~HpackString() = default; - -Http2StringPiece HpackString::ToStringPiece() const { - return str_; -} - -bool HpackString::operator==(const HpackString& other) const { - return str_ == other.str_; -} -bool HpackString::operator==(Http2StringPiece str) const { - return str == str_; -} - -bool operator==(Http2StringPiece a, const HpackString& b) { - return b == a; -} -bool operator!=(Http2StringPiece a, const HpackString& b) { - return !(b == a); -} -bool operator!=(const HpackString& a, const HpackString& b) { - return !(a == b); -} -bool operator!=(const HpackString& a, Http2StringPiece b) { - return !(a == b); -} -std::ostream& operator<<(std::ostream& out, const HpackString& v) { - return out << v.ToString(); -} - -HpackStringPair::HpackStringPair(const HpackString& name, - const HpackString& value) - : name(name), value(value) { - DVLOG(3) << DebugString() << " ctor"; -} - -HpackStringPair::HpackStringPair(Http2StringPiece name, Http2StringPiece value) - : name(name), value(value) { - DVLOG(3) << DebugString() << " ctor"; -} - -HpackStringPair::~HpackStringPair() { - DVLOG(3) << DebugString() << " dtor"; -} - -Http2String HpackStringPair::DebugString() const { - return Http2StrCat("HpackStringPair(name=", name.ToString(), - ", value=", value.ToString(), ")"); -} - -std::ostream& operator<<(std::ostream& os, const HpackStringPair& p) { - os << p.DebugString(); - return os; -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/hpack_string.h b/net/third_party/http2/hpack/hpack_string.h deleted file mode 100644 index 7806b31..0000000 --- a/net/third_party/http2/hpack/hpack_string.h +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_HPACK_STRING_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_HPACK_STRING_H_ - -// HpackString is currently a very simple container for a string, but allows us -// to relatively easily experiment with alternate string storage mechanisms for -// handling strings to be encoded with HPACK, or decoded from HPACK, such as -// a ref-counted string. - -#include <stddef.h> - -#include <iosfwd> - -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" - -namespace http2 { - -class HTTP2_EXPORT_PRIVATE HpackString { - public: - explicit HpackString(const char* data); - explicit HpackString(Http2StringPiece str); - explicit HpackString(Http2String str); - HpackString(const HpackString& other); - - // Not sure yet whether this move ctor is required/sensible. - HpackString(HpackString&& other) = default; - - ~HpackString(); - - size_t size() const { return str_.size(); } - const Http2String& ToString() const { return str_; } - Http2StringPiece ToStringPiece() const; - - bool operator==(const HpackString& other) const; - - bool operator==(Http2StringPiece str) const; - - private: - Http2String str_; -}; - -HTTP2_EXPORT_PRIVATE bool operator==(Http2StringPiece a, const HpackString& b); -HTTP2_EXPORT_PRIVATE bool operator!=(Http2StringPiece a, const HpackString& b); -HTTP2_EXPORT_PRIVATE bool operator!=(const HpackString& a, - const HpackString& b); -HTTP2_EXPORT_PRIVATE bool operator!=(const HpackString& a, Http2StringPiece b); -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const HpackString& v); - -struct HTTP2_EXPORT_PRIVATE HpackStringPair { - HpackStringPair(const HpackString& name, const HpackString& value); - HpackStringPair(Http2StringPiece name, Http2StringPiece value); - ~HpackStringPair(); - - // Returns the size of a header entry with this name and value, per the RFC: - // http://httpwg.org/specs/rfc7541.html#calculating.table.size - size_t size() const { return 32 + name.size() + value.size(); } - - Http2String DebugString() const; - - const HpackString name; - const HpackString value; -}; - -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, - const HpackStringPair& p); - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_HPACK_STRING_H_
diff --git a/net/third_party/http2/hpack/hpack_string_test.cc b/net/third_party/http2/hpack/hpack_string_test.cc deleted file mode 100644 index 90ed2a7b8..0000000 --- a/net/third_party/http2/hpack/hpack_string_test.cc +++ /dev/null
@@ -1,149 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/hpack_string.h" - -// Tests of HpackString. - -#include <utility> - -#include "base/logging.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionFailure; -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; - -namespace http2 { -namespace test { -namespace { - -const char kStr0[] = "s0: Some string to be copied into another string."; -const char kStr1[] = "S1 - some string to be copied into yet another string."; - -class HpackStringTest : public ::testing::Test { - protected: - AssertionResult VerifyNotEqual(HpackString* actual, - const Http2String& not_expected_str) { - const char* not_expected_ptr = not_expected_str.c_str(); - Http2StringPiece not_expected_sp(not_expected_str); - - VERIFY_NE(*actual, not_expected_ptr); - VERIFY_NE(*actual, not_expected_sp); - VERIFY_NE(*actual, not_expected_str); - VERIFY_NE(actual->ToStringPiece(), not_expected_sp); - - if (!(not_expected_ptr != *actual)) { - return AssertionFailure(); - } - if (!(not_expected_sp != *actual)) { - return AssertionFailure(); - } - if (!(not_expected_str != *actual)) { - return AssertionFailure(); - } - if (!(not_expected_sp != actual->ToStringPiece())) { - return AssertionFailure(); - } - - return AssertionSuccess(); - } - - AssertionResult VerifyEqual(HpackString* actual, - const Http2String& expected_str) { - VERIFY_EQ(actual->size(), expected_str.size()); - - const char* expected_ptr = expected_str.c_str(); - const Http2StringPiece expected_sp(expected_str); - - VERIFY_EQ(*actual, expected_ptr); - VERIFY_EQ(*actual, expected_sp); - VERIFY_EQ(*actual, expected_str); - VERIFY_EQ(actual->ToStringPiece(), expected_sp); - - if (!(expected_sp == *actual)) { - return AssertionFailure(); - } - if (!(expected_ptr == *actual)) { - return AssertionFailure(); - } - if (!(expected_str == *actual)) { - return AssertionFailure(); - } - if (!(expected_sp == actual->ToStringPiece())) { - return AssertionFailure(); - } - - return AssertionSuccess(); - } -}; - -TEST_F(HpackStringTest, CharArrayConstructor) { - HpackString hs0(kStr0); - EXPECT_TRUE(VerifyEqual(&hs0, kStr0)); - EXPECT_TRUE(VerifyNotEqual(&hs0, kStr1)); - - HpackString hs1(kStr1); - EXPECT_TRUE(VerifyEqual(&hs1, kStr1)); - EXPECT_TRUE(VerifyNotEqual(&hs1, kStr0)); -} - -TEST_F(HpackStringTest, StringPieceConstructor) { - Http2StringPiece sp0(kStr0); - HpackString hs0(sp0); - EXPECT_TRUE(VerifyEqual(&hs0, kStr0)); - EXPECT_TRUE(VerifyNotEqual(&hs0, kStr1)); - - Http2StringPiece sp1(kStr1); - HpackString hs1(sp1); - EXPECT_TRUE(VerifyEqual(&hs1, kStr1)); - EXPECT_TRUE(VerifyNotEqual(&hs1, kStr0)); -} - -TEST_F(HpackStringTest, MoveStringConstructor) { - Http2String str0(kStr0); - HpackString hs0(str0); - EXPECT_TRUE(VerifyEqual(&hs0, kStr0)); - EXPECT_TRUE(VerifyNotEqual(&hs0, kStr1)); - - Http2String str1(kStr1); - HpackString hs1(str1); - EXPECT_TRUE(VerifyEqual(&hs1, kStr1)); - EXPECT_TRUE(VerifyNotEqual(&hs1, kStr0)); -} - -TEST_F(HpackStringTest, CopyConstructor) { - Http2StringPiece sp0(kStr0); - HpackString hs0(sp0); - HpackString hs1(hs0); - EXPECT_EQ(hs0, hs1); - - EXPECT_TRUE(VerifyEqual(&hs0, kStr0)); - EXPECT_TRUE(VerifyEqual(&hs1, kStr0)); - - EXPECT_TRUE(VerifyNotEqual(&hs0, kStr1)); - EXPECT_TRUE(VerifyNotEqual(&hs1, kStr1)); -} - -TEST_F(HpackStringTest, MoveConstructor) { - Http2StringPiece sp0(kStr0); - HpackString hs0(sp0); - EXPECT_TRUE(VerifyEqual(&hs0, kStr0)); - EXPECT_TRUE(VerifyNotEqual(&hs0, "")); - - HpackString hs1(std::move(hs0)); - EXPECT_NE(hs0, hs1); - - EXPECT_TRUE(VerifyEqual(&hs1, kStr0)); - EXPECT_TRUE(VerifyEqual(&hs0, "")); - EXPECT_TRUE(VerifyNotEqual(&hs1, "")); - - LOG(INFO) << hs0; - LOG(INFO) << hs1; -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/http2_hpack_constants.cc b/net/third_party/http2/hpack/http2_hpack_constants.cc deleted file mode 100644 index da9b067..0000000 --- a/net/third_party/http2/hpack/http2_hpack_constants.cc +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/http2_hpack_constants.h" - -#include "net/third_party/http2/platform/api/http2_string_utils.h" - -namespace http2 { - -Http2String HpackEntryTypeToString(HpackEntryType v) { - switch (v) { - case HpackEntryType::kIndexedHeader: - return "kIndexedHeader"; - case HpackEntryType::kDynamicTableSizeUpdate: - return "kDynamicTableSizeUpdate"; - case HpackEntryType::kIndexedLiteralHeader: - return "kIndexedLiteralHeader"; - case HpackEntryType::kUnindexedLiteralHeader: - return "kUnindexedLiteralHeader"; - case HpackEntryType::kNeverIndexedLiteralHeader: - return "kNeverIndexedLiteralHeader"; - } - return Http2StrCat("UnknownHpackEntryType(", static_cast<int>(v), ")"); -} - -std::ostream& operator<<(std::ostream& out, HpackEntryType v) { - return out << HpackEntryTypeToString(v); -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/http2_hpack_constants.h b/net/third_party/http2/hpack/http2_hpack_constants.h deleted file mode 100644 index cc515a6..0000000 --- a/net/third_party/http2/hpack/http2_hpack_constants.h +++ /dev/null
@@ -1,63 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_HTTP2_HPACK_CONSTANTS_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_HTTP2_HPACK_CONSTANTS_H_ - -// Enum HpackEntryType identifies the 5 basic types of HPACK Block Entries. -// -// See the spec for details: -// https://http2.github.io/http2-spec/compression.html#rfc.section.6 - -#include <ostream> - -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string.h" - -namespace http2 { - -const size_t kFirstDynamicTableIndex = 62; - -enum class HpackEntryType { - // Entry is an index into the static or dynamic table. Decoding it has no - // effect on the dynamic table. - kIndexedHeader, - - // The entry contains a literal value. The name may be either a literal or a - // reference to an entry in the static or dynamic table. - // The entry is added to the dynamic table after decoding. - kIndexedLiteralHeader, - - // The entry contains a literal value. The name may be either a literal or a - // reference to an entry in the static or dynamic table. - // The entry is not added to the dynamic table after decoding, but a proxy - // may choose to insert the entry into its dynamic table when forwarding - // to another endpoint. - kUnindexedLiteralHeader, - - // The entry contains a literal value. The name may be either a literal or a - // reference to an entry in the static or dynamic table. - // The entry is not added to the dynamic table after decoding, and a proxy - // must NOT insert the entry into its dynamic table when forwarding to another - // endpoint. - kNeverIndexedLiteralHeader, - - // Entry conveys the size limit of the dynamic table of the encoder to - // the decoder. May be used to flush the table by sending a zero and then - // resetting the size back up to the maximum that the encoder will use - // (within the limits of SETTINGS_HEADER_TABLE_SIZE sent by the - // decoder to the encoder, with the default of 4096 assumed). - kDynamicTableSizeUpdate, -}; - -// Returns the name of the enum member. -HTTP2_EXPORT_PRIVATE Http2String HpackEntryTypeToString(HpackEntryType v); - -// Inserts the name of the enum member into |out|. -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - HpackEntryType v); - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_HTTP2_HPACK_CONSTANTS_H_
diff --git a/net/third_party/http2/hpack/http2_hpack_constants_test.cc b/net/third_party/http2/hpack/http2_hpack_constants_test.cc deleted file mode 100644 index 7e9e4f9..0000000 --- a/net/third_party/http2/hpack/http2_hpack_constants_test.cc +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/http2_hpack_constants.h" - -#include "base/logging.h" -#include "net/third_party/http2/platform/api/http2_mock_log.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { -namespace { - -TEST(HpackEntryTypeTest, HpackEntryTypeToString) { - EXPECT_EQ("kIndexedHeader", - HpackEntryTypeToString(HpackEntryType::kIndexedHeader)); - EXPECT_EQ("kDynamicTableSizeUpdate", - HpackEntryTypeToString(HpackEntryType::kDynamicTableSizeUpdate)); - EXPECT_EQ("kIndexedLiteralHeader", - HpackEntryTypeToString(HpackEntryType::kIndexedLiteralHeader)); - EXPECT_EQ("kUnindexedLiteralHeader", - HpackEntryTypeToString(HpackEntryType::kUnindexedLiteralHeader)); - EXPECT_EQ("kNeverIndexedLiteralHeader", - HpackEntryTypeToString(HpackEntryType::kNeverIndexedLiteralHeader)); - EXPECT_EQ("UnknownHpackEntryType(12321)", - HpackEntryTypeToString(static_cast<HpackEntryType>(12321))); -} - -TEST(HpackEntryTypeTest, OutputHpackEntryType) { - { - CREATE_HTTP2_MOCK_LOG(log); - log.StartCapturingLogs(); - EXPECT_HTTP2_LOG_CALL_CONTAINS(log, INFO, "kIndexedHeader"); - LOG(INFO) << HpackEntryType::kIndexedHeader; - } - { - CREATE_HTTP2_MOCK_LOG(log); - log.StartCapturingLogs(); - EXPECT_HTTP2_LOG_CALL_CONTAINS(log, INFO, "kDynamicTableSizeUpdate"); - LOG(INFO) << HpackEntryType::kDynamicTableSizeUpdate; - } - { - CREATE_HTTP2_MOCK_LOG(log); - log.StartCapturingLogs(); - EXPECT_HTTP2_LOG_CALL_CONTAINS(log, INFO, "kIndexedLiteralHeader"); - LOG(INFO) << HpackEntryType::kIndexedLiteralHeader; - } - { - CREATE_HTTP2_MOCK_LOG(log); - log.StartCapturingLogs(); - EXPECT_HTTP2_LOG_CALL_CONTAINS(log, INFO, "kUnindexedLiteralHeader"); - LOG(INFO) << HpackEntryType::kUnindexedLiteralHeader; - } - { - CREATE_HTTP2_MOCK_LOG(log); - log.StartCapturingLogs(); - EXPECT_HTTP2_LOG_CALL_CONTAINS(log, INFO, "kNeverIndexedLiteralHeader"); - LOG(INFO) << HpackEntryType::kNeverIndexedLiteralHeader; - } - { - CREATE_HTTP2_MOCK_LOG(log); - log.StartCapturingLogs(); - EXPECT_HTTP2_LOG_CALL_CONTAINS(log, INFO, "UnknownHpackEntryType(1234321)"); - LOG(INFO) << static_cast<HpackEntryType>(1234321); - } -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/huffman/hpack_huffman_decoder.cc b/net/third_party/http2/hpack/huffman/hpack_huffman_decoder.cc deleted file mode 100644 index fd6e17db..0000000 --- a/net/third_party/http2/hpack/huffman/hpack_huffman_decoder.cc +++ /dev/null
@@ -1,487 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/huffman/hpack_huffman_decoder.h" - -#include <bitset> -#include <limits> - -#include "base/logging.h" - -// Terminology: -// -// Symbol - a plain text (unencoded) character (uint8), or the End-of-String -// (EOS) symbol, 256. -// -// Code - the sequence of bits used to encode a symbol, varying in length from -// 5 bits for the most common symbols (e.g. '0', '1', and 'a'), to -// 30 bits for the least common (e.g. the EOS symbol). -// For those symbols whose codes have the same length, their code values -// are sorted such that the lower symbol value has a lower code value. -// -// Canonical - a symbol's cardinal value when sorted first by code length, and -// then by symbol value. For example, canonical 0 is for ASCII '0' -// (uint8 value 0x30), which is the first of the symbols whose code -// is 5 bits long, and the last canonical is EOS, which is the last -// of the symbols whose code is 30 bits long. - -// TODO(jamessynge): Remove use of binary literals, that is a C++ 14 feature. - -namespace http2 { -namespace { - -// HuffmanCode is used to store the codes associated with symbols (a pattern of -// from 5 to 30 bits). -typedef uint32_t HuffmanCode; - -// HuffmanCodeBitCount is used to store a count of bits in a code. -typedef uint16_t HuffmanCodeBitCount; - -// HuffmanCodeBitSet is used for producing a string version of a code because -// std::bitset logs nicely. -typedef std::bitset<32> HuffmanCodeBitSet; -typedef std::bitset<64> HuffmanAccumulatorBitSet; - -static constexpr HuffmanCodeBitCount kMinCodeBitCount = 5; -static constexpr HuffmanCodeBitCount kMaxCodeBitCount = 30; -static constexpr HuffmanCodeBitCount kHuffmanCodeBitCount = - std::numeric_limits<HuffmanCode>::digits; - -static_assert(std::numeric_limits<HuffmanCode>::digits >= kMaxCodeBitCount, - "HuffmanCode isn't big enough."); - -static_assert(std::numeric_limits<HuffmanAccumulator>::digits >= - kMaxCodeBitCount, - "HuffmanAccumulator isn't big enough."); - -static constexpr HuffmanAccumulatorBitCount kHuffmanAccumulatorBitCount = - std::numeric_limits<HuffmanAccumulator>::digits; -static constexpr HuffmanAccumulatorBitCount kExtraAccumulatorBitCount = - kHuffmanAccumulatorBitCount - kHuffmanCodeBitCount; - -// PrefixInfo holds info about a group of codes that are all of the same length. -struct PrefixInfo { - // Given the leading bits (32 in this case) of the encoded string, and that - // they start with a code of length |code_length|, return the corresponding - // canonical for that leading code. - uint32_t DecodeToCanonical(HuffmanCode bits) const { - // What is the position of the canonical symbol being decoded within - // the canonical symbols of |length|? - HuffmanCode ordinal_in_length = - ((bits - first_code) >> (kHuffmanCodeBitCount - code_length)); - - // Combined with |canonical| to produce the position of the canonical symbol - // being decoded within all of the canonical symbols. - return first_canonical + ordinal_in_length; - } - - const HuffmanCode first_code; // First code of this length, left justified in - // the field (i.e. the first bit of the code is - // the high-order bit). - const uint16_t code_length; // Length of the prefix code |base|. - const uint16_t first_canonical; // First canonical symbol of this length. -}; - -inline std::ostream& operator<<(std::ostream& out, const PrefixInfo& v) { - return out << "{first_code: " << HuffmanCodeBitSet(v.first_code) - << ", code_length: " << v.code_length - << ", first_canonical: " << v.first_canonical << "}"; -} - -// Given |value|, a sequence of the leading bits remaining to be decoded, -// figure out which group of canonicals (by code length) that value starts -// with. This function was generated. -PrefixInfo PrefixToInfo(HuffmanCode value) { - if (value < 0b10111000000000000000000000000000) { - if (value < 0b01010000000000000000000000000000) { - return {0b00000000000000000000000000000000, 5, 0}; - } else { - return {0b01010000000000000000000000000000, 6, 10}; - } - } else { - if (value < 0b11111110000000000000000000000000) { - if (value < 0b11111000000000000000000000000000) { - return {0b10111000000000000000000000000000, 7, 36}; - } else { - return {0b11111000000000000000000000000000, 8, 68}; - } - } else { - if (value < 0b11111111110000000000000000000000) { - if (value < 0b11111111101000000000000000000000) { - if (value < 0b11111111010000000000000000000000) { - return {0b11111110000000000000000000000000, 10, 74}; - } else { - return {0b11111111010000000000000000000000, 11, 79}; - } - } else { - return {0b11111111101000000000000000000000, 12, 82}; - } - } else { - if (value < 0b11111111111111100000000000000000) { - if (value < 0b11111111111110000000000000000000) { - if (value < 0b11111111111100000000000000000000) { - return {0b11111111110000000000000000000000, 13, 84}; - } else { - return {0b11111111111100000000000000000000, 14, 90}; - } - } else { - return {0b11111111111110000000000000000000, 15, 92}; - } - } else { - if (value < 0b11111111111111110100100000000000) { - if (value < 0b11111111111111101110000000000000) { - if (value < 0b11111111111111100110000000000000) { - return {0b11111111111111100000000000000000, 19, 95}; - } else { - return {0b11111111111111100110000000000000, 20, 98}; - } - } else { - return {0b11111111111111101110000000000000, 21, 106}; - } - } else { - if (value < 0b11111111111111111110101000000000) { - if (value < 0b11111111111111111011000000000000) { - return {0b11111111111111110100100000000000, 22, 119}; - } else { - return {0b11111111111111111011000000000000, 23, 145}; - } - } else { - if (value < 0b11111111111111111111101111000000) { - if (value < 0b11111111111111111111100000000000) { - if (value < 0b11111111111111111111011000000000) { - return {0b11111111111111111110101000000000, 24, 174}; - } else { - return {0b11111111111111111111011000000000, 25, 186}; - } - } else { - return {0b11111111111111111111100000000000, 26, 190}; - } - } else { - if (value < 0b11111111111111111111111111110000) { - if (value < 0b11111111111111111111111000100000) { - return {0b11111111111111111111101111000000, 27, 205}; - } else { - return {0b11111111111111111111111000100000, 28, 224}; - } - } else { - return {0b11111111111111111111111111110000, 30, 253}; - } - } - } - } - } - } - } - } -} - -// Mapping from canonical symbol (0 to 255) to actual symbol. -// clang-format off -constexpr unsigned char kCanonicalToSymbol[] = { - '0', '1', '2', 'a', 'c', 'e', 'i', 'o', - 's', 't', 0x20, '%', '-', '.', '/', '3', - '4', '5', '6', '7', '8', '9', '=', 'A', - '_', 'b', 'd', 'f', 'g', 'h', 'l', 'm', - 'n', 'p', 'r', 'u', ':', 'B', 'C', 'D', - 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', - 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'Y', 'j', 'k', 'q', 'v', - 'w', 'x', 'y', 'z', '&', '*', ',', ';', - 'X', 'Z', '!', '\"', '(', ')', '?', '\'', - '+', '|', '#', '>', 0x00, '$', '@', '[', - ']', '~', '^', '}', '<', '`', '{', '\\', - 0xc3, 0xd0, 0x80, 0x82, 0x83, 0xa2, 0xb8, 0xc2, - 0xe0, 0xe2, 0x99, 0xa1, 0xa7, 0xac, 0xb0, 0xb1, - 0xb3, 0xd1, 0xd8, 0xd9, 0xe3, 0xe5, 0xe6, 0x81, - 0x84, 0x85, 0x86, 0x88, 0x92, 0x9a, 0x9c, 0xa0, - 0xa3, 0xa4, 0xa9, 0xaa, 0xad, 0xb2, 0xb5, 0xb9, - 0xba, 0xbb, 0xbd, 0xbe, 0xc4, 0xc6, 0xe4, 0xe8, - 0xe9, 0x01, 0x87, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, - 0x8f, 0x93, 0x95, 0x96, 0x97, 0x98, 0x9b, 0x9d, - 0x9e, 0xa5, 0xa6, 0xa8, 0xae, 0xaf, 0xb4, 0xb6, - 0xb7, 0xbc, 0xbf, 0xc5, 0xe7, 0xef, 0x09, 0x8e, - 0x90, 0x91, 0x94, 0x9f, 0xab, 0xce, 0xd7, 0xe1, - 0xec, 0xed, 0xc7, 0xcf, 0xea, 0xeb, 0xc0, 0xc1, - 0xc8, 0xc9, 0xca, 0xcd, 0xd2, 0xd5, 0xda, 0xdb, - 0xee, 0xf0, 0xf2, 0xf3, 0xff, 0xcb, 0xcc, 0xd3, - 0xd4, 0xd6, 0xdd, 0xde, 0xdf, 0xf1, 0xf4, 0xf5, - 0xf6, 0xf7, 0xf8, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, - 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0b, - 0x0c, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, - 0x15, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, - 0x1e, 0x1f, 0x7f, 0xdc, 0xf9, 0x0a, 0x0d, 0x16, -}; -// clang-format on - -constexpr size_t kShortCodeTableSize = 124; -struct ShortCodeInfo { - uint8_t symbol; - uint8_t length; -} kShortCodeTable[kShortCodeTableSize] = { - {0x30, 5}, // Match: 0b0000000, Symbol: 0 - {0x30, 5}, // Match: 0b0000001, Symbol: 0 - {0x30, 5}, // Match: 0b0000010, Symbol: 0 - {0x30, 5}, // Match: 0b0000011, Symbol: 0 - {0x31, 5}, // Match: 0b0000100, Symbol: 1 - {0x31, 5}, // Match: 0b0000101, Symbol: 1 - {0x31, 5}, // Match: 0b0000110, Symbol: 1 - {0x31, 5}, // Match: 0b0000111, Symbol: 1 - {0x32, 5}, // Match: 0b0001000, Symbol: 2 - {0x32, 5}, // Match: 0b0001001, Symbol: 2 - {0x32, 5}, // Match: 0b0001010, Symbol: 2 - {0x32, 5}, // Match: 0b0001011, Symbol: 2 - {0x61, 5}, // Match: 0b0001100, Symbol: a - {0x61, 5}, // Match: 0b0001101, Symbol: a - {0x61, 5}, // Match: 0b0001110, Symbol: a - {0x61, 5}, // Match: 0b0001111, Symbol: a - {0x63, 5}, // Match: 0b0010000, Symbol: c - {0x63, 5}, // Match: 0b0010001, Symbol: c - {0x63, 5}, // Match: 0b0010010, Symbol: c - {0x63, 5}, // Match: 0b0010011, Symbol: c - {0x65, 5}, // Match: 0b0010100, Symbol: e - {0x65, 5}, // Match: 0b0010101, Symbol: e - {0x65, 5}, // Match: 0b0010110, Symbol: e - {0x65, 5}, // Match: 0b0010111, Symbol: e - {0x69, 5}, // Match: 0b0011000, Symbol: i - {0x69, 5}, // Match: 0b0011001, Symbol: i - {0x69, 5}, // Match: 0b0011010, Symbol: i - {0x69, 5}, // Match: 0b0011011, Symbol: i - {0x6f, 5}, // Match: 0b0011100, Symbol: o - {0x6f, 5}, // Match: 0b0011101, Symbol: o - {0x6f, 5}, // Match: 0b0011110, Symbol: o - {0x6f, 5}, // Match: 0b0011111, Symbol: o - {0x73, 5}, // Match: 0b0100000, Symbol: s - {0x73, 5}, // Match: 0b0100001, Symbol: s - {0x73, 5}, // Match: 0b0100010, Symbol: s - {0x73, 5}, // Match: 0b0100011, Symbol: s - {0x74, 5}, // Match: 0b0100100, Symbol: t - {0x74, 5}, // Match: 0b0100101, Symbol: t - {0x74, 5}, // Match: 0b0100110, Symbol: t - {0x74, 5}, // Match: 0b0100111, Symbol: t - {0x20, 6}, // Match: 0b0101000, Symbol: (space) - {0x20, 6}, // Match: 0b0101001, Symbol: (space) - {0x25, 6}, // Match: 0b0101010, Symbol: % - {0x25, 6}, // Match: 0b0101011, Symbol: % - {0x2d, 6}, // Match: 0b0101100, Symbol: - - {0x2d, 6}, // Match: 0b0101101, Symbol: - - {0x2e, 6}, // Match: 0b0101110, Symbol: . - {0x2e, 6}, // Match: 0b0101111, Symbol: . - {0x2f, 6}, // Match: 0b0110000, Symbol: / - {0x2f, 6}, // Match: 0b0110001, Symbol: / - {0x33, 6}, // Match: 0b0110010, Symbol: 3 - {0x33, 6}, // Match: 0b0110011, Symbol: 3 - {0x34, 6}, // Match: 0b0110100, Symbol: 4 - {0x34, 6}, // Match: 0b0110101, Symbol: 4 - {0x35, 6}, // Match: 0b0110110, Symbol: 5 - {0x35, 6}, // Match: 0b0110111, Symbol: 5 - {0x36, 6}, // Match: 0b0111000, Symbol: 6 - {0x36, 6}, // Match: 0b0111001, Symbol: 6 - {0x37, 6}, // Match: 0b0111010, Symbol: 7 - {0x37, 6}, // Match: 0b0111011, Symbol: 7 - {0x38, 6}, // Match: 0b0111100, Symbol: 8 - {0x38, 6}, // Match: 0b0111101, Symbol: 8 - {0x39, 6}, // Match: 0b0111110, Symbol: 9 - {0x39, 6}, // Match: 0b0111111, Symbol: 9 - {0x3d, 6}, // Match: 0b1000000, Symbol: = - {0x3d, 6}, // Match: 0b1000001, Symbol: = - {0x41, 6}, // Match: 0b1000010, Symbol: A - {0x41, 6}, // Match: 0b1000011, Symbol: A - {0x5f, 6}, // Match: 0b1000100, Symbol: _ - {0x5f, 6}, // Match: 0b1000101, Symbol: _ - {0x62, 6}, // Match: 0b1000110, Symbol: b - {0x62, 6}, // Match: 0b1000111, Symbol: b - {0x64, 6}, // Match: 0b1001000, Symbol: d - {0x64, 6}, // Match: 0b1001001, Symbol: d - {0x66, 6}, // Match: 0b1001010, Symbol: f - {0x66, 6}, // Match: 0b1001011, Symbol: f - {0x67, 6}, // Match: 0b1001100, Symbol: g - {0x67, 6}, // Match: 0b1001101, Symbol: g - {0x68, 6}, // Match: 0b1001110, Symbol: h - {0x68, 6}, // Match: 0b1001111, Symbol: h - {0x6c, 6}, // Match: 0b1010000, Symbol: l - {0x6c, 6}, // Match: 0b1010001, Symbol: l - {0x6d, 6}, // Match: 0b1010010, Symbol: m - {0x6d, 6}, // Match: 0b1010011, Symbol: m - {0x6e, 6}, // Match: 0b1010100, Symbol: n - {0x6e, 6}, // Match: 0b1010101, Symbol: n - {0x70, 6}, // Match: 0b1010110, Symbol: p - {0x70, 6}, // Match: 0b1010111, Symbol: p - {0x72, 6}, // Match: 0b1011000, Symbol: r - {0x72, 6}, // Match: 0b1011001, Symbol: r - {0x75, 6}, // Match: 0b1011010, Symbol: u - {0x75, 6}, // Match: 0b1011011, Symbol: u - {0x3a, 7}, // Match: 0b1011100, Symbol: : - {0x42, 7}, // Match: 0b1011101, Symbol: B - {0x43, 7}, // Match: 0b1011110, Symbol: C - {0x44, 7}, // Match: 0b1011111, Symbol: D - {0x45, 7}, // Match: 0b1100000, Symbol: E - {0x46, 7}, // Match: 0b1100001, Symbol: F - {0x47, 7}, // Match: 0b1100010, Symbol: G - {0x48, 7}, // Match: 0b1100011, Symbol: H - {0x49, 7}, // Match: 0b1100100, Symbol: I - {0x4a, 7}, // Match: 0b1100101, Symbol: J - {0x4b, 7}, // Match: 0b1100110, Symbol: K - {0x4c, 7}, // Match: 0b1100111, Symbol: L - {0x4d, 7}, // Match: 0b1101000, Symbol: M - {0x4e, 7}, // Match: 0b1101001, Symbol: N - {0x4f, 7}, // Match: 0b1101010, Symbol: O - {0x50, 7}, // Match: 0b1101011, Symbol: P - {0x51, 7}, // Match: 0b1101100, Symbol: Q - {0x52, 7}, // Match: 0b1101101, Symbol: R - {0x53, 7}, // Match: 0b1101110, Symbol: S - {0x54, 7}, // Match: 0b1101111, Symbol: T - {0x55, 7}, // Match: 0b1110000, Symbol: U - {0x56, 7}, // Match: 0b1110001, Symbol: V - {0x57, 7}, // Match: 0b1110010, Symbol: W - {0x59, 7}, // Match: 0b1110011, Symbol: Y - {0x6a, 7}, // Match: 0b1110100, Symbol: j - {0x6b, 7}, // Match: 0b1110101, Symbol: k - {0x71, 7}, // Match: 0b1110110, Symbol: q - {0x76, 7}, // Match: 0b1110111, Symbol: v - {0x77, 7}, // Match: 0b1111000, Symbol: w - {0x78, 7}, // Match: 0b1111001, Symbol: x - {0x79, 7}, // Match: 0b1111010, Symbol: y - {0x7a, 7}, // Match: 0b1111011, Symbol: z -}; - -} // namespace - -HuffmanBitBuffer::HuffmanBitBuffer() { - Reset(); -} - -void HuffmanBitBuffer::Reset() { - accumulator_ = 0; - count_ = 0; -} - -size_t HuffmanBitBuffer::AppendBytes(Http2StringPiece input) { - HuffmanAccumulatorBitCount free_cnt = free_count(); - size_t bytes_available = input.size(); - if (free_cnt < 8 || bytes_available == 0) { - return 0; - } - - // Top up |accumulator_| until there isn't room for a whole byte. - size_t bytes_used = 0; - auto* ptr = reinterpret_cast<const uint8_t*>(input.data()); - do { - auto b = static_cast<HuffmanAccumulator>(*ptr++); - free_cnt -= 8; - accumulator_ |= (b << free_cnt); - ++bytes_used; - } while (free_cnt >= 8 && bytes_used < bytes_available); - count_ += (bytes_used * 8); - return bytes_used; -} - -HuffmanAccumulatorBitCount HuffmanBitBuffer::free_count() const { - return kHuffmanAccumulatorBitCount - count_; -} - -void HuffmanBitBuffer::ConsumeBits(HuffmanAccumulatorBitCount code_length) { - DCHECK_LE(code_length, count_); - accumulator_ <<= code_length; - count_ -= code_length; -} - -bool HuffmanBitBuffer::InputProperlyTerminated() const { - auto cnt = count(); - if (cnt < 8) { - if (cnt == 0) { - return true; - } - HuffmanAccumulator expected = ~(~HuffmanAccumulator() >> cnt); - // We expect all the bits below the high order |cnt| bits of accumulator_ - // to be cleared as we perform left shift operations while decoding. - DCHECK_EQ(accumulator_ & ~expected, 0u) - << "\n expected: " << HuffmanAccumulatorBitSet(expected) << "\n " - << *this; - return accumulator_ == expected; - } - return false; -} - -Http2String HuffmanBitBuffer::DebugString() const { - std::stringstream ss; - ss << "{accumulator: " << HuffmanAccumulatorBitSet(accumulator_) - << "; count: " << count_ << "}"; - return ss.str(); -} - -HpackHuffmanDecoder::HpackHuffmanDecoder() = default; - -HpackHuffmanDecoder::~HpackHuffmanDecoder() = default; - -bool HpackHuffmanDecoder::Decode(Http2StringPiece input, Http2String* output) { - DVLOG(1) << "HpackHuffmanDecoder::Decode"; - - // Fill bit_buffer_ from input. - input.remove_prefix(bit_buffer_.AppendBytes(input)); - - while (true) { - DVLOG(3) << "Enter Decode Loop, bit_buffer_: " << bit_buffer_; - if (bit_buffer_.count() >= 7) { - // Get high 7 bits of the bit buffer, see if that contains a complete - // code of 5, 6 or 7 bits. - uint8_t short_code = - bit_buffer_.value() >> (kHuffmanAccumulatorBitCount - 7); - DCHECK_LT(short_code, 128); - if (short_code < kShortCodeTableSize) { - ShortCodeInfo info = kShortCodeTable[short_code]; - bit_buffer_.ConsumeBits(info.length); - output->push_back(static_cast<char>(info.symbol)); - continue; - } - // The code is more than 7 bits long. Use PrefixToInfo, etc. to decode - // longer codes. - } else { - // We may have (mostly) drained bit_buffer_. If we can top it up, try - // using the table decoder above. - size_t byte_count = bit_buffer_.AppendBytes(input); - if (byte_count > 0) { - input.remove_prefix(byte_count); - continue; - } - } - - HuffmanCode code_prefix = bit_buffer_.value() >> kExtraAccumulatorBitCount; - DVLOG(3) << "code_prefix: " << HuffmanCodeBitSet(code_prefix); - - PrefixInfo prefix_info = PrefixToInfo(code_prefix); - DVLOG(3) << "prefix_info: " << prefix_info; - DCHECK_LE(kMinCodeBitCount, prefix_info.code_length); - DCHECK_LE(prefix_info.code_length, kMaxCodeBitCount); - - if (prefix_info.code_length <= bit_buffer_.count()) { - // We have enough bits for one code. - uint32_t canonical = prefix_info.DecodeToCanonical(code_prefix); - if (canonical < 256) { - // Valid code. - char c = kCanonicalToSymbol[canonical]; - output->push_back(c); - bit_buffer_.ConsumeBits(prefix_info.code_length); - continue; - } - // Encoder is not supposed to explicity encode the EOS symbol. - DLOG(ERROR) << "EOS explicitly encoded!\n " << bit_buffer_ << "\n " - << prefix_info; - return false; - } - // bit_buffer_ doesn't have enough bits in it to decode the next symbol. - // Append to it as many bytes as are available AND fit. - size_t byte_count = bit_buffer_.AppendBytes(input); - if (byte_count == 0) { - DCHECK_EQ(input.size(), 0u); - return true; - } - input.remove_prefix(byte_count); - } -} - -Http2String HpackHuffmanDecoder::DebugString() const { - return bit_buffer_.DebugString(); -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/huffman/hpack_huffman_decoder.h b/net/third_party/http2/hpack/huffman/hpack_huffman_decoder.h deleted file mode 100644 index 536d088f..0000000 --- a/net/third_party/http2/hpack/huffman/hpack_huffman_decoder.h +++ /dev/null
@@ -1,134 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_HUFFMAN_HPACK_HUFFMAN_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_HUFFMAN_HPACK_HUFFMAN_DECODER_H_ - -// HpackHuffmanDecoder is an incremental decoder of strings that have been -// encoded using the Huffman table defined in the HPACK spec. -// By incremental, we mean that the HpackHuffmanDecoder::Decode method does -// not require the entire string to be provided, and can instead decode the -// string as fragments of it become available (e.g. as HPACK block fragments -// are received for decoding by HpackEntryDecoder). - -#include <stddef.h> - -#include <cstdint> -#include <iosfwd> - -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" - -namespace http2 { - -// HuffmanAccumulator is used to store bits during decoding, e.g. next N bits -// that have not yet been decoded, but have been extracted from the encoded -// string). An advantage of using a uint64 for the accumulator -// is that it has room for the bits of the longest code plus the bits of a full -// byte; that means that when adding more bits to the accumulator, it can always -// be done in whole bytes. For example, if we currently have 26 bits in the -// accumulator, and need more to decode the current symbol, we can add a whole -// byte to the accumulator, and not have to do juggling with adding 6 bits (to -// reach 30), and then keep track of the last two bits we've not been able to -// add to the accumulator. -typedef uint64_t HuffmanAccumulator; -typedef size_t HuffmanAccumulatorBitCount; - -// HuffmanBitBuffer stores the leading edge of bits to be decoded. The high -// order bit of accumulator_ is the next bit to be decoded. -class HTTP2_EXPORT_PRIVATE HuffmanBitBuffer { - public: - HuffmanBitBuffer(); - - // Prepare for decoding a new Huffman encoded string. - void Reset(); - - // Add as many whole bytes to the accumulator (accumulator_) as possible, - // returning the number of bytes added. - size_t AppendBytes(Http2StringPiece input); - - // Get the bits of the accumulator. - HuffmanAccumulator value() const { return accumulator_; } - - // Number of bits of the encoded string that are in the accumulator - // (accumulator_). - HuffmanAccumulatorBitCount count() const { return count_; } - - // Are there no bits in the accumulator? - bool IsEmpty() const { return count_ == 0; } - - // Number of additional bits that can be added to the accumulator. - HuffmanAccumulatorBitCount free_count() const; - - // Consume the leading |code_length| bits of the accumulator. - void ConsumeBits(HuffmanAccumulatorBitCount code_length); - - // Are the contents valid for the end of a Huffman encoded string? The RFC - // states that EOS (end-of-string) symbol must not be explicitly encoded in - // the bit stream, but any unused bits in the final byte must be set to the - // prefix of the EOS symbol, which is all 1 bits. So there can be at most 7 - // such bits. - // Returns true if the bit buffer is empty, or contains at most 7 bits, all - // of them 1. Otherwise returns false. - bool InputProperlyTerminated() const; - - Http2String DebugString() const; - - private: - HuffmanAccumulator accumulator_; - HuffmanAccumulatorBitCount count_; -}; - -inline std::ostream& operator<<(std::ostream& out, const HuffmanBitBuffer& v) { - return out << v.DebugString(); -} - -class HTTP2_EXPORT_PRIVATE HpackHuffmanDecoder { - public: - HpackHuffmanDecoder(); - ~HpackHuffmanDecoder(); - - // Prepare for decoding a new Huffman encoded string. - void Reset() { bit_buffer_.Reset(); } - - // Decode the portion of a HPACK Huffman encoded string that is in |input|, - // appending the decoded symbols into |*output|, stopping when more bits are - // needed to determine the next symbol, which/ means that the input has been - // drained, and also that the bit_buffer_ is empty or that the bits that are - // in it are not a whole symbol. - // If |input| is the start of a string, the caller must first call Reset. - // If |input| includes the end of the encoded string, the caller must call - // InputProperlyTerminated after Decode has returned true in order to - // determine if the encoded string was properly terminated. - // Returns false if something went wrong (e.g. the encoding contains the code - // EOS symbol). Otherwise returns true, in which case input has been fully - // decoded or buffered; in particular, if the low-order bit of the final byte - // of the input is not the last bit of an encoded symbol, then bit_buffer_ - // will contain the leading bits of the code for that symbol, but not the - // final bits of that code. - // Note that output should be empty, but that it is not cleared by Decode(). - bool Decode(Http2StringPiece input, Http2String* output); - - // Is what remains in the bit_buffer_ valid at the end of an encoded string? - // Call after passing the the final portion of a Huffman string to Decode, - // and getting true as the result. - bool InputProperlyTerminated() const { - return bit_buffer_.InputProperlyTerminated(); - } - - Http2String DebugString() const; - - private: - HuffmanBitBuffer bit_buffer_; -}; - -inline std::ostream& operator<<(std::ostream& out, - const HpackHuffmanDecoder& v) { - return out << v.DebugString(); -} - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_HUFFMAN_HPACK_HUFFMAN_DECODER_H_
diff --git a/net/third_party/http2/hpack/huffman/hpack_huffman_decoder_test.cc b/net/third_party/http2/hpack/huffman/hpack_huffman_decoder_test.cc deleted file mode 100644 index 1bed6ad..0000000 --- a/net/third_party/http2/hpack/huffman/hpack_huffman_decoder_test.cc +++ /dev/null
@@ -1,245 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/huffman/hpack_huffman_decoder.h" - -// Tests of HpackHuffmanDecoder and HuffmanBitBuffer. - -#include <iostream> - -#include "base/macros.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/platform/api/http2_arraysize.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionResult; - -namespace http2 { -namespace test { -namespace { - -TEST(HuffmanBitBufferTest, Reset) { - HuffmanBitBuffer bb; - EXPECT_TRUE(bb.IsEmpty()); - EXPECT_TRUE(bb.InputProperlyTerminated()); - EXPECT_EQ(bb.count(), 0u); - EXPECT_EQ(bb.free_count(), 64u); - EXPECT_EQ(bb.value(), 0u); -} - -TEST(HuffmanBitBufferTest, AppendBytesAligned) { - Http2String s; - s.push_back('\x11'); - s.push_back('\x22'); - s.push_back('\x33'); - Http2StringPiece sp(s); - - HuffmanBitBuffer bb; - sp.remove_prefix(bb.AppendBytes(sp)); - EXPECT_TRUE(sp.empty()); - EXPECT_FALSE(bb.IsEmpty()) << bb; - EXPECT_FALSE(bb.InputProperlyTerminated()); - EXPECT_EQ(bb.count(), 24u) << bb; - EXPECT_EQ(bb.free_count(), 40u) << bb; - EXPECT_EQ(bb.value(), HuffmanAccumulator(0x112233) << 40) << bb; - - s.clear(); - s.push_back('\x44'); - sp = s; - - sp.remove_prefix(bb.AppendBytes(sp)); - EXPECT_TRUE(sp.empty()); - EXPECT_EQ(bb.count(), 32u) << bb; - EXPECT_EQ(bb.free_count(), 32u) << bb; - EXPECT_EQ(bb.value(), HuffmanAccumulator(0x11223344) << 32) << bb; - - s.clear(); - s.push_back('\x55'); - s.push_back('\x66'); - s.push_back('\x77'); - s.push_back('\x88'); - s.push_back('\x99'); - sp = s; - - sp.remove_prefix(bb.AppendBytes(sp)); - EXPECT_EQ(sp.size(), 1u); - EXPECT_EQ('\x99', sp[0]); - EXPECT_EQ(bb.count(), 64u) << bb; - EXPECT_EQ(bb.free_count(), 0u) << bb; - EXPECT_EQ(bb.value(), HuffmanAccumulator(0x1122334455667788LL)) << bb; - - sp.remove_prefix(bb.AppendBytes(sp)); - EXPECT_EQ(sp.size(), 1u); - EXPECT_EQ('\x99', sp[0]); - EXPECT_EQ(bb.count(), 64u) << bb; - EXPECT_EQ(bb.free_count(), 0u) << bb; - EXPECT_EQ(bb.value(), HuffmanAccumulator(0x1122334455667788LL)) << bb; -} - -TEST(HuffmanBitBufferTest, ConsumeBits) { - Http2String s; - s.push_back('\x11'); - s.push_back('\x22'); - s.push_back('\x33'); - Http2StringPiece sp(s); - - HuffmanBitBuffer bb; - sp.remove_prefix(bb.AppendBytes(sp)); - EXPECT_TRUE(sp.empty()); - - bb.ConsumeBits(1); - EXPECT_EQ(bb.count(), 23u) << bb; - EXPECT_EQ(bb.free_count(), 41u) << bb; - EXPECT_EQ(bb.value(), HuffmanAccumulator(0x112233) << 41) << bb; - - bb.ConsumeBits(20); - EXPECT_EQ(bb.count(), 3u) << bb; - EXPECT_EQ(bb.free_count(), 61u) << bb; - EXPECT_EQ(bb.value(), HuffmanAccumulator(0x3) << 61) << bb; -} - -TEST(HuffmanBitBufferTest, AppendBytesUnaligned) { - Http2String s; - s.push_back('\x11'); - s.push_back('\x22'); - s.push_back('\x33'); - s.push_back('\x44'); - s.push_back('\x55'); - s.push_back('\x66'); - s.push_back('\x77'); - s.push_back('\x88'); - s.push_back('\x99'); - s.push_back('\xaa'); - s.push_back('\xbb'); - s.push_back('\xcc'); - s.push_back('\xdd'); - Http2StringPiece sp(s); - - HuffmanBitBuffer bb; - sp.remove_prefix(bb.AppendBytes(sp)); - EXPECT_EQ(sp.size(), 5u); - EXPECT_FALSE(bb.InputProperlyTerminated()); - - bb.ConsumeBits(15); - EXPECT_EQ(bb.count(), 49u) << bb; - EXPECT_EQ(bb.free_count(), 15u) << bb; - - HuffmanAccumulator expected(0x1122334455667788); - expected <<= 15; - EXPECT_EQ(bb.value(), expected); - - sp.remove_prefix(bb.AppendBytes(sp)); - EXPECT_EQ(sp.size(), 4u); - EXPECT_EQ(bb.count(), 57u) << bb; - EXPECT_EQ(bb.free_count(), 7u) << bb; - - expected |= (HuffmanAccumulator(0x99) << 7); - EXPECT_EQ(bb.value(), expected) - << bb << std::hex << "\n actual: " << bb.value() - << "\n expected: " << expected; -} - -class HpackHuffmanDecoderTest : public RandomDecoderTest { - protected: - HpackHuffmanDecoderTest() { - // The decoder may return true, and its accumulator may be empty, at - // many boundaries while decoding, and yet the whole string hasn't - // been decoded. - stop_decode_on_done_ = false; - } - - DecodeStatus StartDecoding(DecodeBuffer* b) override { - input_bytes_seen_ = 0; - output_buffer_.clear(); - decoder_.Reset(); - return ResumeDecoding(b); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - input_bytes_seen_ += b->Remaining(); - Http2StringPiece sp(b->cursor(), b->Remaining()); - if (decoder_.Decode(sp, &output_buffer_)) { - b->AdvanceCursor(b->Remaining()); - // Successfully decoded (or buffered) the bytes in Http2StringPiece. - EXPECT_LE(input_bytes_seen_, input_bytes_expected_); - // Have we reached the end of the encoded string? - if (input_bytes_expected_ == input_bytes_seen_) { - if (decoder_.InputProperlyTerminated()) { - return DecodeStatus::kDecodeDone; - } else { - return DecodeStatus::kDecodeError; - } - } - return DecodeStatus::kDecodeInProgress; - } - return DecodeStatus::kDecodeError; - } - - HpackHuffmanDecoder decoder_; - Http2String output_buffer_; - size_t input_bytes_seen_; - size_t input_bytes_expected_; -}; - -TEST_F(HpackHuffmanDecoderTest, SpecRequestExamples) { - HpackHuffmanDecoder decoder; - Http2String test_table[] = { - Http2HexDecode("f1e3c2e5f23a6ba0ab90f4ff"), - "www.example.com", - Http2HexDecode("a8eb10649cbf"), - "no-cache", - Http2HexDecode("25a849e95ba97d7f"), - "custom-key", - Http2HexDecode("25a849e95bb8e8b4bf"), - "custom-value", - }; - for (size_t i = 0; i != HTTP2_ARRAYSIZE(test_table); i += 2) { - const Http2String& huffman_encoded(test_table[i]); - const Http2String& plain_string(test_table[i + 1]); - Http2String buffer; - decoder.Reset(); - EXPECT_TRUE(decoder.Decode(huffman_encoded, &buffer)) << decoder; - EXPECT_TRUE(decoder.InputProperlyTerminated()) << decoder; - EXPECT_EQ(buffer, plain_string); - } -} - -TEST_F(HpackHuffmanDecoderTest, SpecResponseExamples) { - HpackHuffmanDecoder decoder; - // clang-format off - Http2String test_table[] = { - Http2HexDecode("6402"), - "302", - Http2HexDecode("aec3771a4b"), - "private", - Http2HexDecode("d07abe941054d444a8200595040b8166" - "e082a62d1bff"), - "Mon, 21 Oct 2013 20:13:21 GMT", - Http2HexDecode("9d29ad171863c78f0b97c8e9ae82ae43" - "d3"), - "https://www.example.com", - Http2HexDecode("94e7821dd7f2e6c7b335dfdfcd5b3960" - "d5af27087f3672c1ab270fb5291f9587" - "316065c003ed4ee5b1063d5007"), - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", - }; - // clang-format on - for (size_t i = 0; i != HTTP2_ARRAYSIZE(test_table); i += 2) { - const Http2String& huffman_encoded(test_table[i]); - const Http2String& plain_string(test_table[i + 1]); - Http2String buffer; - decoder.Reset(); - EXPECT_TRUE(decoder.Decode(huffman_encoded, &buffer)) << decoder; - EXPECT_TRUE(decoder.InputProperlyTerminated()) << decoder; - EXPECT_EQ(buffer, plain_string); - } -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/huffman/hpack_huffman_encoder.cc b/net/third_party/http2/hpack/huffman/hpack_huffman_encoder.cc deleted file mode 100644 index 1174335..0000000 --- a/net/third_party/http2/hpack/huffman/hpack_huffman_encoder.cc +++ /dev/null
@@ -1,110 +0,0 @@ -// Copyright (c) 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 "net/third_party/http2/hpack/huffman/hpack_huffman_encoder.h" - -#include "base/logging.h" -#include "net/third_party/http2/hpack/huffman/huffman_spec_tables.h" - -// TODO(jamessynge): Remove use of binary literals, that is a C++ 14 feature. - -namespace http2 { - -size_t ExactHuffmanSize(Http2StringPiece plain) { - size_t bits = 0; - for (const uint8_t c : plain) { - bits += HuffmanSpecTables::kCodeLengths[c]; - } - return (bits + 7) / 8; -} - -size_t BoundedHuffmanSize(Http2StringPiece plain) { - // TODO(jamessynge): Determine whether we should set the min size for Huffman - // encoding much higher (i.e. if less than N, then the savings isn't worth - // the cost of encoding and decoding). Of course, we need to decide on a - // value function, which might be throughput on a full load test, or a - // microbenchmark of the time to encode and then decode a HEADERS frame, - // possibly with the cost of crypto included (i.e. crypto is going to have - // a fairly constant per-byte cost, so reducing the number of bytes in-transit - // reduces the number that must be encrypted and later decrypted). - if (plain.size() < 3) { - // Huffman encoded string can't be smaller than the plain size for very - // short strings. - return plain.size(); - } - // TODO(jamessynge): Measure whether this can be done more efficiently with - // nested loops (e.g. make exact measurement of 8 bytes, then check if min - // remaining is too long). - // Compute the number of bits in an encoding that is shorter than the plain - // string (i.e. the number of bits in a string 1 byte shorter than plain), - // and use this as the limit of the size of the encoding. - const size_t limit_bits = (plain.size() - 1) * 8; - // The shortest code length in the Huffman table of the HPACK spec has 5 bits - // (e.g. for 0, 1, a and e). - const size_t min_code_length = 5; - // We can therefore say that all plain text bytes whose code length we've not - // yet looked up will take at least 5 bits. - size_t min_bits_remaining = plain.size() * min_code_length; - size_t bits = 0; - for (const uint8_t c : plain) { - bits += HuffmanSpecTables::kCodeLengths[c]; - min_bits_remaining -= min_code_length; - // If our minimum estimate of the total number of bits won't yield an - // encoding shorter the plain text, let's bail. - const size_t minimum_bits_total = bits + min_bits_remaining; - if (minimum_bits_total > limit_bits) { - bits += min_bits_remaining; - break; - } - } - return (bits + 7) / 8; -} - -void HuffmanEncode(Http2StringPiece plain, Http2String* huffman) { - DCHECK(huffman != nullptr); - huffman->clear(); // Note that this doesn't release memory. - uint64_t bit_buffer = 0; // High-bit is next bit to output. Not clear if that - // is more performant than having the low-bit be the - // last to be output. - size_t bits_unused = 64; // Number of bits available for the next code. - for (uint8_t c : plain) { - size_t code_length = HuffmanSpecTables::kCodeLengths[c]; - if (bits_unused < code_length) { - // There isn't enough room in bit_buffer for the code of c. - // Flush until bits_unused > 56 (i.e. 64 - 8). - do { - char h = static_cast<char>(bit_buffer >> 56); - bit_buffer <<= 8; - bits_unused += 8; - // Perhaps would be more efficient if we populated an array of chars, - // so we don't have to call push_back each time. Reconsider if used - // for production. - huffman->push_back(h); - } while (bits_unused <= 56); - } - uint64_t code = HuffmanSpecTables::kRightCodes[c]; - size_t shift_by = bits_unused - code_length; - bit_buffer |= (code << shift_by); - bits_unused -= code_length; - } - // bit_buffer contains (64-bits_unused) bits that still need to be flushed. - // Output whole bytes until we don't have any whole bytes left. - size_t bits_used = 64 - bits_unused; - while (bits_used >= 8) { - char h = static_cast<char>(bit_buffer >> 56); - bit_buffer <<= 8; - bits_used -= 8; - huffman->push_back(h); - } - if (bits_used > 0) { - // We have less than a byte left to output. The spec calls for padding out - // the final byte with the leading bits of the EOS symbol (30 1-bits). - constexpr uint64_t leading_eos_bits = 0b11111111; - bit_buffer |= (leading_eos_bits << (56 - bits_used)); - char h = static_cast<char>(bit_buffer >> 56); - huffman->push_back(h); - } -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/huffman/hpack_huffman_encoder.h b/net/third_party/http2/hpack/huffman/hpack_huffman_encoder.h deleted file mode 100644 index dd94d362..0000000 --- a/net/third_party/http2/hpack/huffman/hpack_huffman_encoder.h +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_HUFFMAN_HPACK_HUFFMAN_ENCODER_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_HUFFMAN_HPACK_HUFFMAN_ENCODER_H_ - -// Functions supporting the encoding of strings using the HPACK-defined Huffman -// table. - -#include <cstddef> // For size_t - -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" - -namespace http2 { - -// Returns the size of the Huffman encoding of |plain|, which may be greater -// than plain.size(). Mostly present for testing. -HTTP2_EXPORT_PRIVATE size_t ExactHuffmanSize(Http2StringPiece plain); - -// Returns the size of the Huffman encoding of |plain|, unless it is greater -// than or equal to plain.size(), in which case a value greater than or equal to -// plain.size() is returned. The advantage of this over ExactHuffmanSize is that -// it doesn't read as much of the input string in the event that the string is -// not compressible by HuffmanEncode (i.e. when the encoding is longer than the -// original string, it stops reading the input string as soon as it knows that). -HTTP2_EXPORT_PRIVATE size_t BoundedHuffmanSize(Http2StringPiece plain); - -// Encode the plain text string |plain| with the Huffman encoding defined in -// the HPACK RFC, 7541. |*huffman| does not have to be empty, it is cleared at -// the beginning of this function. This allows reusing the same string object -// across multiple invocations. -HTTP2_EXPORT_PRIVATE void HuffmanEncode(Http2StringPiece plain, - Http2String* huffman); - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_HUFFMAN_HPACK_HUFFMAN_ENCODER_H_
diff --git a/net/third_party/http2/hpack/huffman/hpack_huffman_encoder_test.cc b/net/third_party/http2/hpack/huffman/hpack_huffman_encoder_test.cc deleted file mode 100644 index c51e6167..0000000 --- a/net/third_party/http2/hpack/huffman/hpack_huffman_encoder_test.cc +++ /dev/null
@@ -1,97 +0,0 @@ -// Copyright (c) 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 "net/third_party/http2/hpack/huffman/hpack_huffman_encoder.h" - -#include "base/macros.h" -#include "net/third_party/http2/platform/api/http2_arraysize.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace { - -TEST(HuffmanEncoderTest, SpecRequestExamples) { - Http2String test_table[] = { - Http2HexDecode("f1e3c2e5f23a6ba0ab90f4ff"), - "www.example.com", - Http2HexDecode("a8eb10649cbf"), - "no-cache", - Http2HexDecode("25a849e95ba97d7f"), - "custom-key", - Http2HexDecode("25a849e95bb8e8b4bf"), - "custom-value", - }; - for (size_t i = 0; i != HTTP2_ARRAYSIZE(test_table); i += 2) { - const Http2String& huffman_encoded(test_table[i]); - const Http2String& plain_string(test_table[i + 1]); - EXPECT_EQ(ExactHuffmanSize(plain_string), huffman_encoded.size()); - EXPECT_EQ(BoundedHuffmanSize(plain_string), huffman_encoded.size()); - Http2String buffer; - buffer.reserve(); - HuffmanEncode(plain_string, &buffer); - EXPECT_EQ(buffer, huffman_encoded) << "Error encoding " << plain_string; - } -} - -TEST(HuffmanEncoderTest, SpecResponseExamples) { - // clang-format off - Http2String test_table[] = { - Http2HexDecode("6402"), - "302", - Http2HexDecode("aec3771a4b"), - "private", - Http2HexDecode("d07abe941054d444a8200595040b8166" - "e082a62d1bff"), - "Mon, 21 Oct 2013 20:13:21 GMT", - Http2HexDecode("9d29ad171863c78f0b97c8e9ae82ae43" - "d3"), - "https://www.example.com", - Http2HexDecode("94e7821dd7f2e6c7b335dfdfcd5b3960" - "d5af27087f3672c1ab270fb5291f9587" - "316065c003ed4ee5b1063d5007"), - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", - }; - // clang-format on - for (size_t i = 0; i != HTTP2_ARRAYSIZE(test_table); i += 2) { - const Http2String& huffman_encoded(test_table[i]); - const Http2String& plain_string(test_table[i + 1]); - EXPECT_EQ(ExactHuffmanSize(plain_string), huffman_encoded.size()); - EXPECT_EQ(BoundedHuffmanSize(plain_string), huffman_encoded.size()); - Http2String buffer; - buffer.reserve(huffman_encoded.size()); - const size_t capacity = buffer.capacity(); - HuffmanEncode(plain_string, &buffer); - EXPECT_EQ(buffer, huffman_encoded) << "Error encoding " << plain_string; - EXPECT_EQ(capacity, buffer.capacity()); - } -} - -TEST(HuffmanEncoderTest, EncodedSizeAgreesWithEncodeString) { - Http2String test_table[] = { - "", - "Mon, 21 Oct 2013 20:13:21 GMT", - "https://www.example.com", - "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", - Http2String(1, '\0'), - Http2String("foo\0bar", 7), - Http2String(256, '\0'), - }; - // Modify last |test_table| entry to cover all codes. - for (size_t i = 0; i != 256; ++i) { - test_table[HTTP2_ARRAYSIZE(test_table) - 1][i] = static_cast<char>(i); - } - - for (size_t i = 0; i != HTTP2_ARRAYSIZE(test_table); ++i) { - const Http2String& plain_string = test_table[i]; - Http2String huffman_encoded; - HuffmanEncode(plain_string, &huffman_encoded); - EXPECT_EQ(huffman_encoded.size(), ExactHuffmanSize(plain_string)); - EXPECT_LE(BoundedHuffmanSize(plain_string), plain_string.size()); - EXPECT_LE(BoundedHuffmanSize(plain_string), ExactHuffmanSize(plain_string)); - } -} - -} // namespace -} // namespace http2
diff --git a/net/third_party/http2/hpack/huffman/hpack_huffman_transcoder_test.cc b/net/third_party/http2/hpack/huffman/hpack_huffman_transcoder_test.cc deleted file mode 100644 index 49183d3..0000000 --- a/net/third_party/http2/hpack/huffman/hpack_huffman_transcoder_test.cc +++ /dev/null
@@ -1,184 +0,0 @@ -// Copyright (c) 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. - -// A test of roundtrips through the encoder and decoder. - -#include <stddef.h> - -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/hpack/huffman/hpack_huffman_decoder.h" -#include "net/third_party/http2/hpack/huffman/hpack_huffman_encoder.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; -using ::testing::tuple; - -namespace http2 { -namespace test { -namespace { - -Http2String GenAsciiNonControlSet() { - Http2String s; - const char space = ' '; // First character after the control characters: 0x20 - const char del = 127; // First character after the non-control characters. - for (char c = space; c < del; ++c) { - s.push_back(c); - } - return s; -} - -class HpackHuffmanTranscoderTest : public RandomDecoderTest { - protected: - HpackHuffmanTranscoderTest() - : ascii_non_control_set_(GenAsciiNonControlSet()) { - // The decoder may return true, and its accumulator may be empty, at - // many boundaries while decoding, and yet the whole string hasn't - // been decoded. - stop_decode_on_done_ = false; - } - - DecodeStatus StartDecoding(DecodeBuffer* b) override { - input_bytes_seen_ = 0; - output_buffer_.clear(); - decoder_.Reset(); - return ResumeDecoding(b); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - input_bytes_seen_ += b->Remaining(); - Http2StringPiece sp(b->cursor(), b->Remaining()); - if (decoder_.Decode(sp, &output_buffer_)) { - b->AdvanceCursor(b->Remaining()); - // Successfully decoded (or buffered) the bytes in Http2StringPiece. - EXPECT_LE(input_bytes_seen_, input_bytes_expected_); - // Have we reached the end of the encoded string? - if (input_bytes_expected_ == input_bytes_seen_) { - if (decoder_.InputProperlyTerminated()) { - return DecodeStatus::kDecodeDone; - } else { - return DecodeStatus::kDecodeError; - } - } - return DecodeStatus::kDecodeInProgress; - } - return DecodeStatus::kDecodeError; - } - - AssertionResult TranscodeAndValidateSeveralWays( - Http2StringPiece plain, - Http2StringPiece expected_huffman) { - Http2String encoded; - HuffmanEncode(plain, &encoded); - if (expected_huffman.size() > 0 || plain.empty()) { - VERIFY_EQ(encoded, expected_huffman); - } - input_bytes_expected_ = encoded.size(); - auto validator = [plain, this]() -> AssertionResult { - VERIFY_EQ(output_buffer_.size(), plain.size()); - VERIFY_EQ(output_buffer_, plain); - return AssertionSuccess(); - }; - DecodeBuffer db(encoded); - bool return_non_zero_on_first = false; - return DecodeAndValidateSeveralWays(&db, return_non_zero_on_first, - ValidateDoneAndEmpty(validator)); - } - - AssertionResult TranscodeAndValidateSeveralWays(Http2StringPiece plain) { - return TranscodeAndValidateSeveralWays(plain, ""); - } - - Http2String RandomAsciiNonControlString(int length) { - return Random().RandStringWithAlphabet(length, ascii_non_control_set_); - } - - Http2String RandomBytes(int length) { return Random().RandString(length); } - - const Http2String ascii_non_control_set_; - HpackHuffmanDecoder decoder_; - Http2String output_buffer_; - size_t input_bytes_seen_; - size_t input_bytes_expected_; -}; - -TEST_F(HpackHuffmanTranscoderTest, RoundTripRandomAsciiNonControlString) { - for (size_t length = 0; length != 20; length++) { - const Http2String s = RandomAsciiNonControlString(length); - ASSERT_TRUE(TranscodeAndValidateSeveralWays(s)) - << "Unable to decode:\n\n" - << Http2HexDump(s) << "\n\noutput_buffer_:\n" - << Http2HexDump(output_buffer_); - } -} - -TEST_F(HpackHuffmanTranscoderTest, RoundTripRandomBytes) { - for (size_t length = 0; length != 20; length++) { - const Http2String s = RandomBytes(length); - ASSERT_TRUE(TranscodeAndValidateSeveralWays(s)) - << "Unable to decode:\n\n" - << Http2HexDump(s) << "\n\noutput_buffer_:\n" - << Http2HexDump(output_buffer_); - } -} - -// Two parameters: decoder choice, and the character to round-trip. -class HpackHuffmanTranscoderAdjacentCharTest - : public HpackHuffmanTranscoderTest, - public ::testing::WithParamInterface<int> { - protected: - HpackHuffmanTranscoderAdjacentCharTest() - : c_(static_cast<char>(GetParam())) {} - - const char c_; -}; - -INSTANTIATE_TEST_CASE_P(HpackHuffmanTranscoderAdjacentCharTest, - HpackHuffmanTranscoderAdjacentCharTest, - ::testing::Range(0, 256)); - -// Test c_ adjacent to every other character, both before and after. -TEST_P(HpackHuffmanTranscoderAdjacentCharTest, RoundTripAdjacentChar) { - Http2String s; - for (int a = 0; a < 256; ++a) { - s.push_back(static_cast<char>(a)); - s.push_back(c_); - s.push_back(static_cast<char>(a)); - } - ASSERT_TRUE(TranscodeAndValidateSeveralWays(s)); -} - -// Two parameters: character to repeat, number of repeats. -class HpackHuffmanTranscoderRepeatedCharTest - : public HpackHuffmanTranscoderTest, - public ::testing::WithParamInterface<tuple<int, int>> { - protected: - HpackHuffmanTranscoderRepeatedCharTest() - : c_(static_cast<char>(::testing::get<0>(GetParam()))), - length_(::testing::get<1>(GetParam())) {} - Http2String MakeString() { return Http2String(length_, c_); } - - private: - const char c_; - const size_t length_; -}; - -INSTANTIATE_TEST_CASE_P( - HpackHuffmanTranscoderRepeatedCharTest, - HpackHuffmanTranscoderRepeatedCharTest, - ::testing::Combine(::testing::Range(0, 256), - ::testing::Values(1, 2, 3, 4, 8, 16, 32))); - -TEST_P(HpackHuffmanTranscoderRepeatedCharTest, RoundTripRepeatedChar) { - ASSERT_TRUE(TranscodeAndValidateSeveralWays(MakeString())); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/huffman/huffman_spec_tables.cc b/net/third_party/http2/hpack/huffman/huffman_spec_tables.cc deleted file mode 100644 index df709d0c..0000000 --- a/net/third_party/http2/hpack/huffman/huffman_spec_tables.cc +++ /dev/null
@@ -1,578 +0,0 @@ -// Copyright (c) 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 "net/third_party/http2/hpack/huffman/huffman_spec_tables.h" - -namespace http2 { - -// clang-format off -// static -const uint8_t HuffmanSpecTables::kCodeLengths[] = { - 13, 23, 28, 28, 28, 28, 28, 28, // 0 - 7 - 28, 24, 30, 28, 28, 30, 28, 28, // 8 - 15 - 28, 28, 28, 28, 28, 28, 30, 28, // 16 - 23 - 28, 28, 28, 28, 28, 28, 28, 28, // 24 - 31 - 6, 10, 10, 12, 13, 6, 8, 11, // 32 - 39 - 10, 10, 8, 11, 8, 6, 6, 6, // 40 - 47 - 5, 5, 5, 6, 6, 6, 6, 6, // 48 - 55 - 6, 6, 7, 8, 15, 6, 12, 10, // 56 - 63 - 13, 6, 7, 7, 7, 7, 7, 7, // 64 - 71 - 7, 7, 7, 7, 7, 7, 7, 7, // 72 - 79 - 7, 7, 7, 7, 7, 7, 7, 7, // 80 - 87 - 8, 7, 8, 13, 19, 13, 14, 6, // 88 - 95 - 15, 5, 6, 5, 6, 5, 6, 6, // 96 - 103 - 6, 5, 7, 7, 6, 6, 6, 5, // 104 - 111 - 6, 7, 6, 5, 5, 6, 7, 7, // 112 - 119 - 7, 7, 7, 15, 11, 14, 13, 28, // 120 - 127 - 20, 22, 20, 20, 22, 22, 22, 23, // 128 - 135 - 22, 23, 23, 23, 23, 23, 24, 23, // 136 - 143 - 24, 24, 22, 23, 24, 23, 23, 23, // 144 - 151 - 23, 21, 22, 23, 22, 23, 23, 24, // 152 - 159 - 22, 21, 20, 22, 22, 23, 23, 21, // 160 - 167 - 23, 22, 22, 24, 21, 22, 23, 23, // 168 - 175 - 21, 21, 22, 21, 23, 22, 23, 23, // 176 - 183 - 20, 22, 22, 22, 23, 22, 22, 23, // 184 - 191 - 26, 26, 20, 19, 22, 23, 22, 25, // 192 - 199 - 26, 26, 26, 27, 27, 26, 24, 25, // 200 - 207 - 19, 21, 26, 27, 27, 26, 27, 24, // 208 - 215 - 21, 21, 26, 26, 28, 27, 27, 27, // 216 - 223 - 20, 24, 20, 21, 22, 21, 21, 23, // 224 - 231 - 22, 22, 25, 25, 24, 24, 26, 23, // 232 - 239 - 26, 27, 26, 26, 27, 27, 27, 27, // 240 - 247 - 27, 28, 27, 27, 27, 27, 27, 26, // 248 - 255 - 30, // 256 -}; - -// TODO(jamessynge): Remove use of binary literals, that is a C++ 14 feature. - -// Uncomment these codes if needed for generating Huffman output, as opposed -// to decoding Huffman input. -/* -// The encoding of each symbol, left justified (as printed), which means that -// the first bit of the encoding is the high-order bit of the uint32. -// static -const uint32_t HuffmanSpecTables::kLeftCodes[] = { - 0b11111111110000000000000000000000, // 0x00 - 0b11111111111111111011000000000000, // 0x01 - 0b11111111111111111111111000100000, // 0x02 - 0b11111111111111111111111000110000, // 0x03 - 0b11111111111111111111111001000000, // 0x04 - 0b11111111111111111111111001010000, // 0x05 - 0b11111111111111111111111001100000, // 0x06 - 0b11111111111111111111111001110000, // 0x07 - 0b11111111111111111111111010000000, // 0x08 - 0b11111111111111111110101000000000, // 0x09 - 0b11111111111111111111111111110000, // 0x0a - 0b11111111111111111111111010010000, // 0x0b - 0b11111111111111111111111010100000, // 0x0c - 0b11111111111111111111111111110100, // 0x0d - 0b11111111111111111111111010110000, // 0x0e - 0b11111111111111111111111011000000, // 0x0f - 0b11111111111111111111111011010000, // 0x10 - 0b11111111111111111111111011100000, // 0x11 - 0b11111111111111111111111011110000, // 0x12 - 0b11111111111111111111111100000000, // 0x13 - 0b11111111111111111111111100010000, // 0x14 - 0b11111111111111111111111100100000, // 0x15 - 0b11111111111111111111111111111000, // 0x16 - 0b11111111111111111111111100110000, // 0x17 - 0b11111111111111111111111101000000, // 0x18 - 0b11111111111111111111111101010000, // 0x19 - 0b11111111111111111111111101100000, // 0x1a - 0b11111111111111111111111101110000, // 0x1b - 0b11111111111111111111111110000000, // 0x1c - 0b11111111111111111111111110010000, // 0x1d - 0b11111111111111111111111110100000, // 0x1e - 0b11111111111111111111111110110000, // 0x1f - 0b01010000000000000000000000000000, // 0x20 - 0b11111110000000000000000000000000, // '!' - 0b11111110010000000000000000000000, // '\"' - 0b11111111101000000000000000000000, // '#' - 0b11111111110010000000000000000000, // '$' - 0b01010100000000000000000000000000, // '%' - 0b11111000000000000000000000000000, // '&' - 0b11111111010000000000000000000000, // '\'' - 0b11111110100000000000000000000000, // '(' - 0b11111110110000000000000000000000, // ')' - 0b11111001000000000000000000000000, // '*' - 0b11111111011000000000000000000000, // '+' - 0b11111010000000000000000000000000, // ',' - 0b01011000000000000000000000000000, // '-' - 0b01011100000000000000000000000000, // '.' - 0b01100000000000000000000000000000, // '/' - 0b00000000000000000000000000000000, // '0' - 0b00001000000000000000000000000000, // '1' - 0b00010000000000000000000000000000, // '2' - 0b01100100000000000000000000000000, // '3' - 0b01101000000000000000000000000000, // '4' - 0b01101100000000000000000000000000, // '5' - 0b01110000000000000000000000000000, // '6' - 0b01110100000000000000000000000000, // '7' - 0b01111000000000000000000000000000, // '8' - 0b01111100000000000000000000000000, // '9' - 0b10111000000000000000000000000000, // ':' - 0b11111011000000000000000000000000, // ';' - 0b11111111111110000000000000000000, // '<' - 0b10000000000000000000000000000000, // '=' - 0b11111111101100000000000000000000, // '>' - 0b11111111000000000000000000000000, // '?' - 0b11111111110100000000000000000000, // '@' - 0b10000100000000000000000000000000, // 'A' - 0b10111010000000000000000000000000, // 'B' - 0b10111100000000000000000000000000, // 'C' - 0b10111110000000000000000000000000, // 'D' - 0b11000000000000000000000000000000, // 'E' - 0b11000010000000000000000000000000, // 'F' - 0b11000100000000000000000000000000, // 'G' - 0b11000110000000000000000000000000, // 'H' - 0b11001000000000000000000000000000, // 'I' - 0b11001010000000000000000000000000, // 'J' - 0b11001100000000000000000000000000, // 'K' - 0b11001110000000000000000000000000, // 'L' - 0b11010000000000000000000000000000, // 'M' - 0b11010010000000000000000000000000, // 'N' - 0b11010100000000000000000000000000, // 'O' - 0b11010110000000000000000000000000, // 'P' - 0b11011000000000000000000000000000, // 'Q' - 0b11011010000000000000000000000000, // 'R' - 0b11011100000000000000000000000000, // 'S' - 0b11011110000000000000000000000000, // 'T' - 0b11100000000000000000000000000000, // 'U' - 0b11100010000000000000000000000000, // 'V' - 0b11100100000000000000000000000000, // 'W' - 0b11111100000000000000000000000000, // 'X' - 0b11100110000000000000000000000000, // 'Y' - 0b11111101000000000000000000000000, // 'Z' - 0b11111111110110000000000000000000, // '[' - 0b11111111111111100000000000000000, // '\\' - 0b11111111111000000000000000000000, // ']' - 0b11111111111100000000000000000000, // '^' - 0b10001000000000000000000000000000, // '_' - 0b11111111111110100000000000000000, // '`' - 0b00011000000000000000000000000000, // 'a' - 0b10001100000000000000000000000000, // 'b' - 0b00100000000000000000000000000000, // 'c' - 0b10010000000000000000000000000000, // 'd' - 0b00101000000000000000000000000000, // 'e' - 0b10010100000000000000000000000000, // 'f' - 0b10011000000000000000000000000000, // 'g' - 0b10011100000000000000000000000000, // 'h' - 0b00110000000000000000000000000000, // 'i' - 0b11101000000000000000000000000000, // 'j' - 0b11101010000000000000000000000000, // 'k' - 0b10100000000000000000000000000000, // 'l' - 0b10100100000000000000000000000000, // 'm' - 0b10101000000000000000000000000000, // 'n' - 0b00111000000000000000000000000000, // 'o' - 0b10101100000000000000000000000000, // 'p' - 0b11101100000000000000000000000000, // 'q' - 0b10110000000000000000000000000000, // 'r' - 0b01000000000000000000000000000000, // 's' - 0b01001000000000000000000000000000, // 't' - 0b10110100000000000000000000000000, // 'u' - 0b11101110000000000000000000000000, // 'v' - 0b11110000000000000000000000000000, // 'w' - 0b11110010000000000000000000000000, // 'x' - 0b11110100000000000000000000000000, // 'y' - 0b11110110000000000000000000000000, // 'z' - 0b11111111111111000000000000000000, // '{' - 0b11111111100000000000000000000000, // '|' - 0b11111111111101000000000000000000, // '}' - 0b11111111111010000000000000000000, // '~' - 0b11111111111111111111111111000000, // 0x7f - 0b11111111111111100110000000000000, // 0x80 - 0b11111111111111110100100000000000, // 0x81 - 0b11111111111111100111000000000000, // 0x82 - 0b11111111111111101000000000000000, // 0x83 - 0b11111111111111110100110000000000, // 0x84 - 0b11111111111111110101000000000000, // 0x85 - 0b11111111111111110101010000000000, // 0x86 - 0b11111111111111111011001000000000, // 0x87 - 0b11111111111111110101100000000000, // 0x88 - 0b11111111111111111011010000000000, // 0x89 - 0b11111111111111111011011000000000, // 0x8a - 0b11111111111111111011100000000000, // 0x8b - 0b11111111111111111011101000000000, // 0x8c - 0b11111111111111111011110000000000, // 0x8d - 0b11111111111111111110101100000000, // 0x8e - 0b11111111111111111011111000000000, // 0x8f - 0b11111111111111111110110000000000, // 0x90 - 0b11111111111111111110110100000000, // 0x91 - 0b11111111111111110101110000000000, // 0x92 - 0b11111111111111111100000000000000, // 0x93 - 0b11111111111111111110111000000000, // 0x94 - 0b11111111111111111100001000000000, // 0x95 - 0b11111111111111111100010000000000, // 0x96 - 0b11111111111111111100011000000000, // 0x97 - 0b11111111111111111100100000000000, // 0x98 - 0b11111111111111101110000000000000, // 0x99 - 0b11111111111111110110000000000000, // 0x9a - 0b11111111111111111100101000000000, // 0x9b - 0b11111111111111110110010000000000, // 0x9c - 0b11111111111111111100110000000000, // 0x9d - 0b11111111111111111100111000000000, // 0x9e - 0b11111111111111111110111100000000, // 0x9f - 0b11111111111111110110100000000000, // 0xa0 - 0b11111111111111101110100000000000, // 0xa1 - 0b11111111111111101001000000000000, // 0xa2 - 0b11111111111111110110110000000000, // 0xa3 - 0b11111111111111110111000000000000, // 0xa4 - 0b11111111111111111101000000000000, // 0xa5 - 0b11111111111111111101001000000000, // 0xa6 - 0b11111111111111101111000000000000, // 0xa7 - 0b11111111111111111101010000000000, // 0xa8 - 0b11111111111111110111010000000000, // 0xa9 - 0b11111111111111110111100000000000, // 0xaa - 0b11111111111111111111000000000000, // 0xab - 0b11111111111111101111100000000000, // 0xac - 0b11111111111111110111110000000000, // 0xad - 0b11111111111111111101011000000000, // 0xae - 0b11111111111111111101100000000000, // 0xaf - 0b11111111111111110000000000000000, // 0xb0 - 0b11111111111111110000100000000000, // 0xb1 - 0b11111111111111111000000000000000, // 0xb2 - 0b11111111111111110001000000000000, // 0xb3 - 0b11111111111111111101101000000000, // 0xb4 - 0b11111111111111111000010000000000, // 0xb5 - 0b11111111111111111101110000000000, // 0xb6 - 0b11111111111111111101111000000000, // 0xb7 - 0b11111111111111101010000000000000, // 0xb8 - 0b11111111111111111000100000000000, // 0xb9 - 0b11111111111111111000110000000000, // 0xba - 0b11111111111111111001000000000000, // 0xbb - 0b11111111111111111110000000000000, // 0xbc - 0b11111111111111111001010000000000, // 0xbd - 0b11111111111111111001100000000000, // 0xbe - 0b11111111111111111110001000000000, // 0xbf - 0b11111111111111111111100000000000, // 0xc0 - 0b11111111111111111111100001000000, // 0xc1 - 0b11111111111111101011000000000000, // 0xc2 - 0b11111111111111100010000000000000, // 0xc3 - 0b11111111111111111001110000000000, // 0xc4 - 0b11111111111111111110010000000000, // 0xc5 - 0b11111111111111111010000000000000, // 0xc6 - 0b11111111111111111111011000000000, // 0xc7 - 0b11111111111111111111100010000000, // 0xc8 - 0b11111111111111111111100011000000, // 0xc9 - 0b11111111111111111111100100000000, // 0xca - 0b11111111111111111111101111000000, // 0xcb - 0b11111111111111111111101111100000, // 0xcc - 0b11111111111111111111100101000000, // 0xcd - 0b11111111111111111111000100000000, // 0xce - 0b11111111111111111111011010000000, // 0xcf - 0b11111111111111100100000000000000, // 0xd0 - 0b11111111111111110001100000000000, // 0xd1 - 0b11111111111111111111100110000000, // 0xd2 - 0b11111111111111111111110000000000, // 0xd3 - 0b11111111111111111111110000100000, // 0xd4 - 0b11111111111111111111100111000000, // 0xd5 - 0b11111111111111111111110001000000, // 0xd6 - 0b11111111111111111111001000000000, // 0xd7 - 0b11111111111111110010000000000000, // 0xd8 - 0b11111111111111110010100000000000, // 0xd9 - 0b11111111111111111111101000000000, // 0xda - 0b11111111111111111111101001000000, // 0xdb - 0b11111111111111111111111111010000, // 0xdc - 0b11111111111111111111110001100000, // 0xdd - 0b11111111111111111111110010000000, // 0xde - 0b11111111111111111111110010100000, // 0xdf - 0b11111111111111101100000000000000, // 0xe0 - 0b11111111111111111111001100000000, // 0xe1 - 0b11111111111111101101000000000000, // 0xe2 - 0b11111111111111110011000000000000, // 0xe3 - 0b11111111111111111010010000000000, // 0xe4 - 0b11111111111111110011100000000000, // 0xe5 - 0b11111111111111110100000000000000, // 0xe6 - 0b11111111111111111110011000000000, // 0xe7 - 0b11111111111111111010100000000000, // 0xe8 - 0b11111111111111111010110000000000, // 0xe9 - 0b11111111111111111111011100000000, // 0xea - 0b11111111111111111111011110000000, // 0xeb - 0b11111111111111111111010000000000, // 0xec - 0b11111111111111111111010100000000, // 0xed - 0b11111111111111111111101010000000, // 0xee - 0b11111111111111111110100000000000, // 0xef - 0b11111111111111111111101011000000, // 0xf0 - 0b11111111111111111111110011000000, // 0xf1 - 0b11111111111111111111101100000000, // 0xf2 - 0b11111111111111111111101101000000, // 0xf3 - 0b11111111111111111111110011100000, // 0xf4 - 0b11111111111111111111110100000000, // 0xf5 - 0b11111111111111111111110100100000, // 0xf6 - 0b11111111111111111111110101000000, // 0xf7 - 0b11111111111111111111110101100000, // 0xf8 - 0b11111111111111111111111111100000, // 0xf9 - 0b11111111111111111111110110000000, // 0xfa - 0b11111111111111111111110110100000, // 0xfb - 0b11111111111111111111110111000000, // 0xfc - 0b11111111111111111111110111100000, // 0xfd - 0b11111111111111111111111000000000, // 0xfe - 0b11111111111111111111101110000000, // 0xff - 0b11111111111111111111111111111100, // 0x100 -}; -*/ - -// static -const uint32_t HuffmanSpecTables::kRightCodes[] = { - 0b00000000000000000001111111111000, // 0x00 - 0b00000000011111111111111111011000, // 0x01 - 0b00001111111111111111111111100010, // 0x02 - 0b00001111111111111111111111100011, // 0x03 - 0b00001111111111111111111111100100, // 0x04 - 0b00001111111111111111111111100101, // 0x05 - 0b00001111111111111111111111100110, // 0x06 - 0b00001111111111111111111111100111, // 0x07 - 0b00001111111111111111111111101000, // 0x08 - 0b00000000111111111111111111101010, // 0x09 - 0b00111111111111111111111111111100, // 0x0a - 0b00001111111111111111111111101001, // 0x0b - 0b00001111111111111111111111101010, // 0x0c - 0b00111111111111111111111111111101, // 0x0d - 0b00001111111111111111111111101011, // 0x0e - 0b00001111111111111111111111101100, // 0x0f - 0b00001111111111111111111111101101, // 0x10 - 0b00001111111111111111111111101110, // 0x11 - 0b00001111111111111111111111101111, // 0x12 - 0b00001111111111111111111111110000, // 0x13 - 0b00001111111111111111111111110001, // 0x14 - 0b00001111111111111111111111110010, // 0x15 - 0b00111111111111111111111111111110, // 0x16 - 0b00001111111111111111111111110011, // 0x17 - 0b00001111111111111111111111110100, // 0x18 - 0b00001111111111111111111111110101, // 0x19 - 0b00001111111111111111111111110110, // 0x1a - 0b00001111111111111111111111110111, // 0x1b - 0b00001111111111111111111111111000, // 0x1c - 0b00001111111111111111111111111001, // 0x1d - 0b00001111111111111111111111111010, // 0x1e - 0b00001111111111111111111111111011, // 0x1f - 0b00000000000000000000000000010100, // 0x20 - 0b00000000000000000000001111111000, // '!' - 0b00000000000000000000001111111001, // '\"' - 0b00000000000000000000111111111010, // '#' - 0b00000000000000000001111111111001, // '$' - 0b00000000000000000000000000010101, // '%' - 0b00000000000000000000000011111000, // '&' - 0b00000000000000000000011111111010, // '\'' - 0b00000000000000000000001111111010, // '(' - 0b00000000000000000000001111111011, // ')' - 0b00000000000000000000000011111001, // '*' - 0b00000000000000000000011111111011, // '+' - 0b00000000000000000000000011111010, // ',' - 0b00000000000000000000000000010110, // '-' - 0b00000000000000000000000000010111, // '.' - 0b00000000000000000000000000011000, // '/' - 0b00000000000000000000000000000000, // '0' - 0b00000000000000000000000000000001, // '1' - 0b00000000000000000000000000000010, // '2' - 0b00000000000000000000000000011001, // '3' - 0b00000000000000000000000000011010, // '4' - 0b00000000000000000000000000011011, // '5' - 0b00000000000000000000000000011100, // '6' - 0b00000000000000000000000000011101, // '7' - 0b00000000000000000000000000011110, // '8' - 0b00000000000000000000000000011111, // '9' - 0b00000000000000000000000001011100, // ':' - 0b00000000000000000000000011111011, // ';' - 0b00000000000000000111111111111100, // '<' - 0b00000000000000000000000000100000, // '=' - 0b00000000000000000000111111111011, // '>' - 0b00000000000000000000001111111100, // '?' - 0b00000000000000000001111111111010, // '@' - 0b00000000000000000000000000100001, // 'A' - 0b00000000000000000000000001011101, // 'B' - 0b00000000000000000000000001011110, // 'C' - 0b00000000000000000000000001011111, // 'D' - 0b00000000000000000000000001100000, // 'E' - 0b00000000000000000000000001100001, // 'F' - 0b00000000000000000000000001100010, // 'G' - 0b00000000000000000000000001100011, // 'H' - 0b00000000000000000000000001100100, // 'I' - 0b00000000000000000000000001100101, // 'J' - 0b00000000000000000000000001100110, // 'K' - 0b00000000000000000000000001100111, // 'L' - 0b00000000000000000000000001101000, // 'M' - 0b00000000000000000000000001101001, // 'N' - 0b00000000000000000000000001101010, // 'O' - 0b00000000000000000000000001101011, // 'P' - 0b00000000000000000000000001101100, // 'Q' - 0b00000000000000000000000001101101, // 'R' - 0b00000000000000000000000001101110, // 'S' - 0b00000000000000000000000001101111, // 'T' - 0b00000000000000000000000001110000, // 'U' - 0b00000000000000000000000001110001, // 'V' - 0b00000000000000000000000001110010, // 'W' - 0b00000000000000000000000011111100, // 'X' - 0b00000000000000000000000001110011, // 'Y' - 0b00000000000000000000000011111101, // 'Z' - 0b00000000000000000001111111111011, // '[' - 0b00000000000001111111111111110000, // '\\' - 0b00000000000000000001111111111100, // ']' - 0b00000000000000000011111111111100, // '^' - 0b00000000000000000000000000100010, // '_' - 0b00000000000000000111111111111101, // '`' - 0b00000000000000000000000000000011, // 'a' - 0b00000000000000000000000000100011, // 'b' - 0b00000000000000000000000000000100, // 'c' - 0b00000000000000000000000000100100, // 'd' - 0b00000000000000000000000000000101, // 'e' - 0b00000000000000000000000000100101, // 'f' - 0b00000000000000000000000000100110, // 'g' - 0b00000000000000000000000000100111, // 'h' - 0b00000000000000000000000000000110, // 'i' - 0b00000000000000000000000001110100, // 'j' - 0b00000000000000000000000001110101, // 'k' - 0b00000000000000000000000000101000, // 'l' - 0b00000000000000000000000000101001, // 'm' - 0b00000000000000000000000000101010, // 'n' - 0b00000000000000000000000000000111, // 'o' - 0b00000000000000000000000000101011, // 'p' - 0b00000000000000000000000001110110, // 'q' - 0b00000000000000000000000000101100, // 'r' - 0b00000000000000000000000000001000, // 's' - 0b00000000000000000000000000001001, // 't' - 0b00000000000000000000000000101101, // 'u' - 0b00000000000000000000000001110111, // 'v' - 0b00000000000000000000000001111000, // 'w' - 0b00000000000000000000000001111001, // 'x' - 0b00000000000000000000000001111010, // 'y' - 0b00000000000000000000000001111011, // 'z' - 0b00000000000000000111111111111110, // '{' - 0b00000000000000000000011111111100, // '|' - 0b00000000000000000011111111111101, // '}' - 0b00000000000000000001111111111101, // '~' - 0b00001111111111111111111111111100, // 0x7f - 0b00000000000011111111111111100110, // 0x80 - 0b00000000001111111111111111010010, // 0x81 - 0b00000000000011111111111111100111, // 0x82 - 0b00000000000011111111111111101000, // 0x83 - 0b00000000001111111111111111010011, // 0x84 - 0b00000000001111111111111111010100, // 0x85 - 0b00000000001111111111111111010101, // 0x86 - 0b00000000011111111111111111011001, // 0x87 - 0b00000000001111111111111111010110, // 0x88 - 0b00000000011111111111111111011010, // 0x89 - 0b00000000011111111111111111011011, // 0x8a - 0b00000000011111111111111111011100, // 0x8b - 0b00000000011111111111111111011101, // 0x8c - 0b00000000011111111111111111011110, // 0x8d - 0b00000000111111111111111111101011, // 0x8e - 0b00000000011111111111111111011111, // 0x8f - 0b00000000111111111111111111101100, // 0x90 - 0b00000000111111111111111111101101, // 0x91 - 0b00000000001111111111111111010111, // 0x92 - 0b00000000011111111111111111100000, // 0x93 - 0b00000000111111111111111111101110, // 0x94 - 0b00000000011111111111111111100001, // 0x95 - 0b00000000011111111111111111100010, // 0x96 - 0b00000000011111111111111111100011, // 0x97 - 0b00000000011111111111111111100100, // 0x98 - 0b00000000000111111111111111011100, // 0x99 - 0b00000000001111111111111111011000, // 0x9a - 0b00000000011111111111111111100101, // 0x9b - 0b00000000001111111111111111011001, // 0x9c - 0b00000000011111111111111111100110, // 0x9d - 0b00000000011111111111111111100111, // 0x9e - 0b00000000111111111111111111101111, // 0x9f - 0b00000000001111111111111111011010, // 0xa0 - 0b00000000000111111111111111011101, // 0xa1 - 0b00000000000011111111111111101001, // 0xa2 - 0b00000000001111111111111111011011, // 0xa3 - 0b00000000001111111111111111011100, // 0xa4 - 0b00000000011111111111111111101000, // 0xa5 - 0b00000000011111111111111111101001, // 0xa6 - 0b00000000000111111111111111011110, // 0xa7 - 0b00000000011111111111111111101010, // 0xa8 - 0b00000000001111111111111111011101, // 0xa9 - 0b00000000001111111111111111011110, // 0xaa - 0b00000000111111111111111111110000, // 0xab - 0b00000000000111111111111111011111, // 0xac - 0b00000000001111111111111111011111, // 0xad - 0b00000000011111111111111111101011, // 0xae - 0b00000000011111111111111111101100, // 0xaf - 0b00000000000111111111111111100000, // 0xb0 - 0b00000000000111111111111111100001, // 0xb1 - 0b00000000001111111111111111100000, // 0xb2 - 0b00000000000111111111111111100010, // 0xb3 - 0b00000000011111111111111111101101, // 0xb4 - 0b00000000001111111111111111100001, // 0xb5 - 0b00000000011111111111111111101110, // 0xb6 - 0b00000000011111111111111111101111, // 0xb7 - 0b00000000000011111111111111101010, // 0xb8 - 0b00000000001111111111111111100010, // 0xb9 - 0b00000000001111111111111111100011, // 0xba - 0b00000000001111111111111111100100, // 0xbb - 0b00000000011111111111111111110000, // 0xbc - 0b00000000001111111111111111100101, // 0xbd - 0b00000000001111111111111111100110, // 0xbe - 0b00000000011111111111111111110001, // 0xbf - 0b00000011111111111111111111100000, // 0xc0 - 0b00000011111111111111111111100001, // 0xc1 - 0b00000000000011111111111111101011, // 0xc2 - 0b00000000000001111111111111110001, // 0xc3 - 0b00000000001111111111111111100111, // 0xc4 - 0b00000000011111111111111111110010, // 0xc5 - 0b00000000001111111111111111101000, // 0xc6 - 0b00000001111111111111111111101100, // 0xc7 - 0b00000011111111111111111111100010, // 0xc8 - 0b00000011111111111111111111100011, // 0xc9 - 0b00000011111111111111111111100100, // 0xca - 0b00000111111111111111111111011110, // 0xcb - 0b00000111111111111111111111011111, // 0xcc - 0b00000011111111111111111111100101, // 0xcd - 0b00000000111111111111111111110001, // 0xce - 0b00000001111111111111111111101101, // 0xcf - 0b00000000000001111111111111110010, // 0xd0 - 0b00000000000111111111111111100011, // 0xd1 - 0b00000011111111111111111111100110, // 0xd2 - 0b00000111111111111111111111100000, // 0xd3 - 0b00000111111111111111111111100001, // 0xd4 - 0b00000011111111111111111111100111, // 0xd5 - 0b00000111111111111111111111100010, // 0xd6 - 0b00000000111111111111111111110010, // 0xd7 - 0b00000000000111111111111111100100, // 0xd8 - 0b00000000000111111111111111100101, // 0xd9 - 0b00000011111111111111111111101000, // 0xda - 0b00000011111111111111111111101001, // 0xdb - 0b00001111111111111111111111111101, // 0xdc - 0b00000111111111111111111111100011, // 0xdd - 0b00000111111111111111111111100100, // 0xde - 0b00000111111111111111111111100101, // 0xdf - 0b00000000000011111111111111101100, // 0xe0 - 0b00000000111111111111111111110011, // 0xe1 - 0b00000000000011111111111111101101, // 0xe2 - 0b00000000000111111111111111100110, // 0xe3 - 0b00000000001111111111111111101001, // 0xe4 - 0b00000000000111111111111111100111, // 0xe5 - 0b00000000000111111111111111101000, // 0xe6 - 0b00000000011111111111111111110011, // 0xe7 - 0b00000000001111111111111111101010, // 0xe8 - 0b00000000001111111111111111101011, // 0xe9 - 0b00000001111111111111111111101110, // 0xea - 0b00000001111111111111111111101111, // 0xeb - 0b00000000111111111111111111110100, // 0xec - 0b00000000111111111111111111110101, // 0xed - 0b00000011111111111111111111101010, // 0xee - 0b00000000011111111111111111110100, // 0xef - 0b00000011111111111111111111101011, // 0xf0 - 0b00000111111111111111111111100110, // 0xf1 - 0b00000011111111111111111111101100, // 0xf2 - 0b00000011111111111111111111101101, // 0xf3 - 0b00000111111111111111111111100111, // 0xf4 - 0b00000111111111111111111111101000, // 0xf5 - 0b00000111111111111111111111101001, // 0xf6 - 0b00000111111111111111111111101010, // 0xf7 - 0b00000111111111111111111111101011, // 0xf8 - 0b00001111111111111111111111111110, // 0xf9 - 0b00000111111111111111111111101100, // 0xfa - 0b00000111111111111111111111101101, // 0xfb - 0b00000111111111111111111111101110, // 0xfc - 0b00000111111111111111111111101111, // 0xfd - 0b00000111111111111111111111110000, // 0xfe - 0b00000011111111111111111111101110, // 0xff - 0b00111111111111111111111111111111, // 0x100 -}; -// clang-format off - -} // namespace http2
diff --git a/net/third_party/http2/hpack/huffman/huffman_spec_tables.h b/net/third_party/http2/hpack/huffman/huffman_spec_tables.h deleted file mode 100644 index 93fd928..0000000 --- a/net/third_party/http2/hpack/huffman/huffman_spec_tables.h +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright (c) 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 NET_THIRD_PARTY_HTTP2_HPACK_HUFFMAN_HUFFMAN_SPEC_TABLES_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_HUFFMAN_HUFFMAN_SPEC_TABLES_H_ - -// Tables describing the Huffman encoding of bytes as specified by RFC7541. - -#include <cstdint> - -namespace http2 { - -struct HuffmanSpecTables { - // Number of bits in the encoding of each symbol (byte). - static const uint8_t kCodeLengths[257]; - - // The encoding of each symbol, right justified (as printed), which means that - // the last bit of the encoding is the low-order bit of the uint32. - static const uint32_t kRightCodes[257]; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_HUFFMAN_HUFFMAN_SPEC_TABLES_H_
diff --git a/net/third_party/http2/hpack/tools/hpack_block_builder.cc b/net/third_party/http2/hpack/tools/hpack_block_builder.cc deleted file mode 100644 index fc8c04b..0000000 --- a/net/third_party/http2/hpack/tools/hpack_block_builder.cc +++ /dev/null
@@ -1,80 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/tools/hpack_block_builder.h" - -#include "net/third_party/http2/hpack/varint/hpack_varint_encoder.h" -#include "net/third_party/http2/platform/api/http2_bug_tracker.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -void HpackBlockBuilder::AppendHighBitsAndVarint(uint8_t high_bits, - uint8_t prefix_length, - uint64_t varint) { - EXPECT_LE(3, prefix_length); - EXPECT_LE(prefix_length, 7); - - HpackVarintEncoder varint_encoder; - - unsigned char c = - varint_encoder.StartEncoding(high_bits, prefix_length, varint); - buffer_.push_back(c); - - if (!varint_encoder.IsEncodingInProgress()) { - return; - } - - // After the prefix, at most 63 bits can remain to be encoded. - // Each octet holds 7 bits, so at most 9 octets are necessary. - // TODO(bnc): Move this into a constant in HpackVarintEncoder. - varint_encoder.ResumeEncoding(/* max_encoded_bytes = */ 10, &buffer_); - DCHECK(!varint_encoder.IsEncodingInProgress()); -} - -void HpackBlockBuilder::AppendEntryTypeAndVarint(HpackEntryType entry_type, - uint64_t varint) { - uint8_t high_bits; - uint8_t prefix_length; // Bits of the varint prefix in the first byte. - switch (entry_type) { - case HpackEntryType::kIndexedHeader: - high_bits = 0x80; - prefix_length = 7; - break; - case HpackEntryType::kDynamicTableSizeUpdate: - high_bits = 0x20; - prefix_length = 5; - break; - case HpackEntryType::kIndexedLiteralHeader: - high_bits = 0x40; - prefix_length = 6; - break; - case HpackEntryType::kUnindexedLiteralHeader: - high_bits = 0x00; - prefix_length = 4; - break; - case HpackEntryType::kNeverIndexedLiteralHeader: - high_bits = 0x10; - prefix_length = 4; - break; - default: - HTTP2_BUG << "Unreached, entry_type=" << entry_type; - high_bits = 0; - prefix_length = 0; - break; - } - AppendHighBitsAndVarint(high_bits, prefix_length, varint); -} - -void HpackBlockBuilder::AppendString(bool is_huffman_encoded, - Http2StringPiece str) { - uint8_t high_bits = is_huffman_encoded ? 0x80 : 0; - uint8_t prefix_length = 7; - AppendHighBitsAndVarint(high_bits, prefix_length, str.size()); - buffer_.append(str.data(), str.size()); -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/tools/hpack_block_builder.h b/net/third_party/http2/hpack/tools/hpack_block_builder.h deleted file mode 100644 index 9886c7a..0000000 --- a/net/third_party/http2/hpack/tools/hpack_block_builder.h +++ /dev/null
@@ -1,96 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_TOOLS_HPACK_BLOCK_BUILDER_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_TOOLS_HPACK_BLOCK_BUILDER_H_ - -// HpackBlockBuilder builds wire-format HPACK blocks (or fragments thereof) -// from components. - -// Supports very large varints to enable tests to create HPACK blocks with -// values that the decoder should reject. For now, this is only intended for -// use in tests, and thus has EXPECT* in the code. If desired to use it in an -// encoder, it will need optimization work, especially w.r.t memory mgmt, and -// the EXPECT* will need to be removed or replaced with DCHECKs. And of course -// the support for very large varints will not be needed in production code. - -#include <stddef.h> - -#include <cstdint> - -#include "net/third_party/http2/hpack/http2_hpack_constants.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -class HpackBlockBuilder { - public: - explicit HpackBlockBuilder(Http2StringPiece initial_contents) - : buffer_(initial_contents.data(), initial_contents.size()) {} - HpackBlockBuilder() {} - ~HpackBlockBuilder() {} - - size_t size() const { return buffer_.size(); } - const Http2String& buffer() const { return buffer_; } - - //---------------------------------------------------------------------------- - // Methods for appending a valid HPACK entry. - - void AppendIndexedHeader(uint64_t index) { - AppendEntryTypeAndVarint(HpackEntryType::kIndexedHeader, index); - } - - void AppendDynamicTableSizeUpdate(uint64_t size) { - AppendEntryTypeAndVarint(HpackEntryType::kDynamicTableSizeUpdate, size); - } - - void AppendNameIndexAndLiteralValue(HpackEntryType entry_type, - uint64_t name_index, - bool value_is_huffman_encoded, - Http2StringPiece value) { - // name_index==0 would indicate that the entry includes a literal name. - // Call AppendLiteralNameAndValue in that case. - EXPECT_NE(0u, name_index); - AppendEntryTypeAndVarint(entry_type, name_index); - AppendString(value_is_huffman_encoded, value); - } - - void AppendLiteralNameAndValue(HpackEntryType entry_type, - bool name_is_huffman_encoded, - Http2StringPiece name, - bool value_is_huffman_encoded, - Http2StringPiece value) { - AppendEntryTypeAndVarint(entry_type, 0); - AppendString(name_is_huffman_encoded, name); - AppendString(value_is_huffman_encoded, value); - } - - //---------------------------------------------------------------------------- - // Primitive methods that are not guaranteed to write a valid HPACK entry. - - // Appends a varint, with the specified high_bits above the prefix of the - // varint. - void AppendHighBitsAndVarint(uint8_t high_bits, - uint8_t prefix_length, - uint64_t varint); - - // Append the start of an HPACK entry for the specified type, with the - // specified varint. - void AppendEntryTypeAndVarint(HpackEntryType entry_type, uint64_t varint); - - // Append a header string (i.e. a header name or value) in HPACK format. - // Does NOT perform Huffman encoding. - void AppendString(bool is_huffman_encoded, Http2StringPiece str); - - private: - Http2String buffer_; -}; - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_TOOLS_HPACK_BLOCK_BUILDER_H_
diff --git a/net/third_party/http2/hpack/tools/hpack_block_builder_test.cc b/net/third_party/http2/hpack/tools/hpack_block_builder_test.cc deleted file mode 100644 index 33e8a5f..0000000 --- a/net/third_party/http2/hpack/tools/hpack_block_builder_test.cc +++ /dev/null
@@ -1,169 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/tools/hpack_block_builder.h" - -#include "net/third_party/http2/platform/api/http2_string_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { -namespace { -const bool kUncompressed = false; -const bool kCompressed = true; - -// TODO(jamessynge): Once static table code is checked in, switch to using -// constants from there. -const uint32_t kStaticTableMethodGET = 2; -const uint32_t kStaticTablePathSlash = 4; -const uint32_t kStaticTableSchemeHttp = 6; - -// Tests of encoding per the RFC. See: -// http://httpwg.org/specs/rfc7541.html#header.field.representation.examples -// The expected values have been copied from the RFC. -TEST(HpackBlockBuilderTest, ExamplesFromSpecC2) { - { - HpackBlockBuilder b; - b.AppendLiteralNameAndValue(HpackEntryType::kIndexedLiteralHeader, - kUncompressed, "custom-key", kUncompressed, - "custom-header"); - EXPECT_EQ(26u, b.size()); - - const char kExpected[] = - "\x40" // == Literal indexed == - "\x0a" // Name length (10) - "custom-key" // Name - "\x0d" // Value length (13) - "custom-header"; // Value - EXPECT_EQ(kExpected, b.buffer()); - } - { - HpackBlockBuilder b; - b.AppendNameIndexAndLiteralValue(HpackEntryType::kUnindexedLiteralHeader, 4, - kUncompressed, "/sample/path"); - EXPECT_EQ(14u, b.size()); - - const char kExpected[] = - "\x04" // == Literal unindexed, name index 0x04 == - "\x0c" // Value length (12) - "/sample/path"; // Value - EXPECT_EQ(kExpected, b.buffer()); - } - { - HpackBlockBuilder b; - b.AppendLiteralNameAndValue(HpackEntryType::kNeverIndexedLiteralHeader, - kUncompressed, "password", kUncompressed, - "secret"); - EXPECT_EQ(17u, b.size()); - - const char kExpected[] = - "\x10" // == Literal never indexed == - "\x08" // Name length (8) - "password" // Name - "\x06" // Value length (6) - "secret"; // Value - EXPECT_EQ(kExpected, b.buffer()); - } - { - HpackBlockBuilder b; - b.AppendIndexedHeader(2); - EXPECT_EQ(1u, b.size()); - - const char kExpected[] = "\x82"; // == Indexed (2) == - EXPECT_EQ(kExpected, b.buffer()); - } -} - -// Tests of encoding per the RFC. See: -// http://httpwg.org/specs/rfc7541.html#request.examples.without.huffman.coding -TEST(HpackBlockBuilderTest, ExamplesFromSpecC3) { - { - // Header block to encode: - // :method: GET - // :scheme: http - // :path: / - // :authority: www.example.com - HpackBlockBuilder b; - b.AppendIndexedHeader(2); // :method: GET - b.AppendIndexedHeader(6); // :scheme: http - b.AppendIndexedHeader(4); // :path: / - b.AppendNameIndexAndLiteralValue(HpackEntryType::kIndexedLiteralHeader, 1, - kUncompressed, "www.example.com"); - EXPECT_EQ(20u, b.size()); - - // Hex dump of encoded data (copied from RFC): - // 0x0000: 8286 8441 0f77 7777 2e65 7861 6d70 6c65 ...A.www.example - // 0x0010: 2e63 6f6d .com - - const Http2String expected = - Http2HexDecode("828684410f7777772e6578616d706c652e636f6d"); - EXPECT_EQ(expected, b.buffer()); - } -} - -// Tests of encoding per the RFC. See: -// http://httpwg.org/specs/rfc7541.html#request.examples.with.huffman.coding -TEST(HpackBlockBuilderTest, ExamplesFromSpecC4) { - { - // Header block to encode: - // :method: GET - // :scheme: http - // :path: / - // :authority: www.example.com (Huffman encoded) - HpackBlockBuilder b; - b.AppendIndexedHeader(kStaticTableMethodGET); - b.AppendIndexedHeader(kStaticTableSchemeHttp); - b.AppendIndexedHeader(kStaticTablePathSlash); - const char kHuffmanWwwExampleCom[] = {'\xf1', '\xe3', '\xc2', '\xe5', - '\xf2', '\x3a', '\x6b', '\xa0', - '\xab', '\x90', '\xf4', '\xff'}; - b.AppendNameIndexAndLiteralValue( - HpackEntryType::kIndexedLiteralHeader, 1, kCompressed, - Http2StringPiece(kHuffmanWwwExampleCom, sizeof kHuffmanWwwExampleCom)); - EXPECT_EQ(17u, b.size()); - - // Hex dump of encoded data (copied from RFC): - // 0x0000: 8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4 ...A......:k.... - // 0x0010: ff . - - const Http2String expected = - Http2HexDecode("828684418cf1e3c2e5f23a6ba0ab90f4ff"); - EXPECT_EQ(expected, b.buffer()); - } -} - -TEST(HpackBlockBuilderTest, DynamicTableSizeUpdate) { - { - HpackBlockBuilder b; - b.AppendDynamicTableSizeUpdate(0); - EXPECT_EQ(1u, b.size()); - - const char kData[] = {'\x20'}; - Http2StringPiece expected(kData, sizeof kData); - EXPECT_EQ(expected, b.buffer()); - } - { - HpackBlockBuilder b; - b.AppendDynamicTableSizeUpdate(4096); // The default size. - EXPECT_EQ(3u, b.size()); - - const char kData[] = {'\x3f', '\xe1', '\x1f'}; - Http2StringPiece expected(kData, sizeof kData); - EXPECT_EQ(expected, b.buffer()); - } - { - HpackBlockBuilder b; - b.AppendDynamicTableSizeUpdate(1000000000000); // A very large value. - EXPECT_EQ(7u, b.size()); - - const char kData[] = {'\x3f', '\xe1', '\x9f', '\x94', - '\xa5', '\x8d', '\x1d'}; - Http2StringPiece expected(kData, sizeof kData); - EXPECT_EQ(expected, b.buffer()); - } -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/tools/hpack_example.cc b/net/third_party/http2/hpack/tools/hpack_example.cc deleted file mode 100644 index 0b6acfd..0000000 --- a/net/third_party/http2/hpack/tools/hpack_example.cc +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/tools/hpack_example.h" - -#include <ctype.h> - -#include "base/logging.h" -#include "net/third_party/http2/platform/api/http2_bug_tracker.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" - -namespace http2 { -namespace test { -namespace { - -void HpackExampleToStringOrDie(Http2StringPiece example, Http2String* output) { - while (!example.empty()) { - const char c0 = example[0]; - if (isxdigit(c0)) { - CHECK_GT(example.size(), 1u) << "Truncated hex byte?"; - const char c1 = example[1]; - CHECK(isxdigit(c1)) << "Found half a byte?"; - *output += Http2HexDecode(example.substr(0, 2)); - example.remove_prefix(2); - continue; - } - if (isspace(c0)) { - example.remove_prefix(1); - continue; - } - if (!example.empty() && example[0] == '|') { - // Start of a comment. Skip to end of line or of input. - auto pos = example.find('\n'); - if (pos == Http2StringPiece::npos) { - // End of input. - break; - } - example.remove_prefix(pos + 1); - continue; - } - HTTP2_BUG << "Can't parse byte " << static_cast<int>(c0) - << Http2StrCat(" (0x", Http2Hex(c0), ")") - << "\nExample: " << example; - } - CHECK_LT(0u, output->size()) << "Example is empty."; -} - -} // namespace - -Http2String HpackExampleToStringOrDie(Http2StringPiece example) { - Http2String output; - HpackExampleToStringOrDie(example, &output); - return output; -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/tools/hpack_example.h b/net/third_party/http2/hpack/tools/hpack_example.h deleted file mode 100644 index b122afe3b..0000000 --- a/net/third_party/http2/hpack/tools/hpack_example.h +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_TOOLS_HPACK_EXAMPLE_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_TOOLS_HPACK_EXAMPLE_H_ - -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" - -// Parses HPACK examples in the format seen in the HPACK specification, -// RFC 7541. For example: -// -// 10 | == Literal never indexed == -// 08 | Literal name (len = 8) -// 7061 7373 776f 7264 | password -// 06 | Literal value (len = 6) -// 7365 6372 6574 | secret -// | -> password: secret -// -// (excluding the leading "//"). - -namespace http2 { -namespace test { - -Http2String HpackExampleToStringOrDie(Http2StringPiece example); - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_TOOLS_HPACK_EXAMPLE_H_
diff --git a/net/third_party/http2/hpack/varint/hpack_varint_decoder.cc b/net/third_party/http2/hpack/varint/hpack_varint_decoder.cc deleted file mode 100644 index fe74b4c2..0000000 --- a/net/third_party/http2/hpack/varint/hpack_varint_decoder.cc +++ /dev/null
@@ -1,172 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/varint/hpack_varint_decoder.h" - -#include "net/third_party/http2/platform/api/http2_flag_utils.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" - -namespace http2 { - -DecodeStatus HpackVarintDecoder::Start(uint8_t prefix_value, - uint8_t prefix_length, - DecodeBuffer* db) { - DCHECK_LE(3u, prefix_length); - DCHECK_LE(prefix_length, 7u); - - // |prefix_mask| defines the sequence of low-order bits of the first byte - // that encode the prefix of the value. It is also the marker in those bits - // of the first byte indicating that at least one extension byte is needed. - const uint8_t prefix_mask = (1 << prefix_length) - 1; - - // Ignore the bits that aren't a part of the prefix of the varint. - value_ = prefix_value & prefix_mask; - - if (value_ < prefix_mask) { - MarkDone(); - return DecodeStatus::kDecodeDone; - } - - offset_ = 0; - return Resume(db); -} - -DecodeStatus HpackVarintDecoder::StartExtended(uint8_t prefix_length, - DecodeBuffer* db) { - DCHECK_LE(3u, prefix_length); - DCHECK_LE(prefix_length, 7u); - - value_ = (1 << prefix_length) - 1; - offset_ = 0; - return Resume(db); -} - -DecodeStatus HpackVarintDecoder::Resume(DecodeBuffer* db) { - if (decode_64_bits_) { - HTTP2_FLAG_COUNT(chromium_flag_http2_varint_decode_64_bits); - // There can be at most 10 continuation bytes. Offset is zero for the - // first one and increases by 7 for each subsequent one. - const uint8_t kMaxOffset = 63; - CheckNotDone(); - - // Process most extension bytes without the need for overflow checking. - while (offset_ < kMaxOffset) { - if (db->Empty()) { - return DecodeStatus::kDecodeInProgress; - } - - uint8_t byte = db->DecodeUInt8(); - uint64_t summand = byte & 0x7f; - - // Shifting a 7 bit value to the left by at most 56 places can never - // overflow on uint64_t. - DCHECK_LE(offset_, 56); - DCHECK_LE(summand, std::numeric_limits<uint64_t>::max() >> offset_); - - summand <<= offset_; - - // At this point, - // |value_| is at most (2^prefix_length - 1) + (2^49 - 1), and - // |summand| is at most 255 << 56 (which is smaller than 2^63), - // so adding them can never overflow on uint64_t. - DCHECK_LE(value_, std::numeric_limits<uint64_t>::max() - summand); - - value_ += summand; - - // Decoding ends if continuation flag is not set. - if ((byte & 0x80) == 0) { - MarkDone(); - return DecodeStatus::kDecodeDone; - } - - offset_ += 7; - } - - if (db->Empty()) { - return DecodeStatus::kDecodeInProgress; - } - - DCHECK_EQ(kMaxOffset, offset_); - - uint8_t byte = db->DecodeUInt8(); - // No more extension bytes are allowed after this. - if ((byte & 0x80) == 0) { - uint64_t summand = byte & 0x7f; - // Check for overflow in left shift. - if (summand <= std::numeric_limits<uint64_t>::max() >> offset_) { - summand <<= offset_; - // Check for overflow in addition. - if (value_ <= std::numeric_limits<uint64_t>::max() - summand) { - value_ += summand; - MarkDone(); - return DecodeStatus::kDecodeDone; - } - } - } - - // Signal error if value is too large or there are too many extension bytes. - DLOG(WARNING) << "Variable length int encoding is too large or too long. " - << DebugString(); - MarkDone(); - return DecodeStatus::kDecodeError; - } - - // Old code path. TODO(bnc): remove. - DCHECK(!decode_64_bits_); - const uint8_t kMaxOffset = 28; - CheckNotDone(); - do { - if (db->Empty()) { - return DecodeStatus::kDecodeInProgress; - } - uint8_t byte = db->DecodeUInt8(); - if (offset_ == kMaxOffset && byte != 0) - break; - DCHECK(offset_ <= kMaxOffset - 7 || byte == 0); - // Shifting a 7 bit value to the left by at most 21 places can never - // overflow on uint32_t. Shifting 0 to the left cannot overflow either. - value_ += (byte & 0x7f) << offset_; - if ((byte & 0x80) == 0) { - MarkDone(); - return DecodeStatus::kDecodeDone; - } - offset_ += 7; - } while (offset_ <= kMaxOffset); - DLOG(WARNING) << "Variable length int encoding is too large or too long. " - << DebugString(); - MarkDone(); - return DecodeStatus::kDecodeError; -} - -uint64_t HpackVarintDecoder::value() const { - CheckDone(); - return value_; -} - -void HpackVarintDecoder::set_value(uint64_t v) { - MarkDone(); - value_ = v; -} - -Http2String HpackVarintDecoder::DebugString() const { - return Http2StrCat("HpackVarintDecoder(value=", value_, ", offset=", offset_, - ")"); -} - -DecodeStatus HpackVarintDecoder::StartForTest(uint8_t prefix_value, - uint8_t prefix_length, - DecodeBuffer* db) { - return Start(prefix_value, prefix_length, db); -} - -DecodeStatus HpackVarintDecoder::StartExtendedForTest(uint8_t prefix_length, - DecodeBuffer* db) { - return StartExtended(prefix_length, db); -} - -DecodeStatus HpackVarintDecoder::ResumeForTest(DecodeBuffer* db) { - return Resume(db); -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/varint/hpack_varint_decoder.h b/net/third_party/http2/hpack/varint/hpack_varint_decoder.h deleted file mode 100644 index 6502b5bb..0000000 --- a/net/third_party/http2/hpack/varint/hpack_varint_decoder.h +++ /dev/null
@@ -1,144 +0,0 @@ -// Copyright 2016 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. - -// HpackVarintDecoder decodes HPACK variable length unsigned integers. In HPACK, -// these integers are used to identify static or dynamic table index entries, to -// specify string lengths, and to update the size limit of the dynamic table. -// In QPACK, in addition to these uses, these integers also identify streams. -// -// The caller will need to validate that the decoded value is in an acceptable -// range. -// -// For details of the encoding, see: -// http://httpwg.org/specs/rfc7541.html#integer.representation -// -// If GetHttp2ReloadableFlag(http2_varint_decode_64_bits) is true, then this -// decoder supports decoding any integer that can be represented on uint64_t, -// thereby exceeding the requirements for QPACK: "QPACK implementations MUST be -// able to decode integers up to 62 bits long." See -// https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5.1.1 -// -// If GetHttp2ReloadableFlag(http2_varint_decode_64_bits) is false, then this -// decoder supports decoding integers up to 2^28 + 2^prefix_length - 2. -// -// This decoder supports at most 10 extension bytes (bytes following the prefix, -// also called continuation bytes) if -// GetHttp2ReloadableFlag(http2_varint_decode_64_bits) is true, and at most 5 -// extension bytes if GetHttp2ReloadableFlag(http2_varint_decode_64_bits) is -// false. An encoder is allowed to zero pad the encoded integer on the left, -// thereby increasing the number of extension bytes. If an encoder uses so much -// padding that the number of extension bytes exceeds the limit, then this -// decoder signals an error. - -#ifndef NET_THIRD_PARTY_HTTP2_HPACK_VARINT_HPACK_VARINT_DECODER_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_VARINT_HPACK_VARINT_DECODER_H_ - -#include <cstdint> -#include <limits> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_flags.h" -#include "net/third_party/http2/platform/api/http2_string.h" - -namespace http2 { - -// Sentinel value for |HpackVarintDecoder::offset_| to signify that decoding is -// completed. Only used in debug builds. -#ifndef NDEBUG -const uint8_t kHpackVarintDecoderOffsetDone = - std::numeric_limits<uint8_t>::max(); -#endif - -// Decodes an HPACK variable length unsigned integer, in a resumable fashion -// so it can handle running out of input in the DecodeBuffer. Call Start or -// StartExtended the first time (when decoding the byte that contains the -// prefix), then call Resume later if it is necessary to resume. When done, -// call value() to retrieve the decoded value. -// -// No constructor or destructor. Holds no resources, so destruction isn't -// needed. Start and StartExtended handles the initialization of member -// variables. This is necessary in order for HpackVarintDecoder to be part -// of a union. -class HTTP2_EXPORT_PRIVATE HpackVarintDecoder { - public: - // |prefix_value| is the first byte of the encoded varint. - // |prefix_length| is number of bits in the first byte that are used for - // encoding the integer. |db| is the rest of the buffer, that is, not - // including the first byte. - DecodeStatus Start(uint8_t prefix_value, - uint8_t prefix_length, - DecodeBuffer* db); - - // The caller has already determined that the encoding requires multiple - // bytes, i.e. that the 3 to 7 low-order bits (the number determined by - // |prefix_length|) of the first byte are are all 1. |db| is the rest of the - // buffer, that is, not including the first byte. - DecodeStatus StartExtended(uint8_t prefix_length, DecodeBuffer* db); - - // Resume decoding a variable length integer after an earlier - // call to Start or StartExtended returned kDecodeInProgress. - DecodeStatus Resume(DecodeBuffer* db); - - uint64_t value() const; - - // This supports optimizations for the case of a varint with zero extension - // bytes, where the handling of the prefix is done by the caller. - void set_value(uint64_t v); - - // All the public methods below are for supporting assertions and tests. - - Http2String DebugString() const; - - // For benchmarking, these methods ensure the decoder - // is NOT inlined into the caller. - DecodeStatus StartForTest(uint8_t prefix_value, - uint8_t prefix_length, - DecodeBuffer* db); - DecodeStatus StartExtendedForTest(uint8_t prefix_length, DecodeBuffer* db); - DecodeStatus ResumeForTest(DecodeBuffer* db); - - private: - // Protection in case Resume is called when it shouldn't be. - void MarkDone() { -#ifndef NDEBUG - offset_ = kHpackVarintDecoderOffsetDone; -#endif - } - void CheckNotDone() const { -#ifndef NDEBUG - DCHECK_NE(kHpackVarintDecoderOffsetDone, offset_); -#endif - } - void CheckDone() const { -#ifndef NDEBUG - DCHECK_EQ(kHpackVarintDecoderOffsetDone, offset_); -#endif - } - - // If true, decode integers up to 2^64 - 1, and accept at most 10 extension - // bytes (some of which might be padding). - // If false, decode integers up to 2^28 + 2^prefix_length - 2, and accept at - // most 5 extension bytes (some of which might be padding). - bool decode_64_bits_ = GetHttp2ReloadableFlag(http2_varint_decode_64_bits); - - // These fields are initialized just to keep ASAN happy about reading - // them from DebugString(). - - // The encoded integer is being accumulated in |value_|. When decoding is - // complete, |value_| holds the result. - uint64_t value_ = 0; - - // Each extension byte encodes in its lowest 7 bits a segment of the integer. - // |offset_| is the number of places this segment has to be shifted to the - // left for decoding. It is zero for the first extension byte, and increases - // by 7 for each subsequent extension byte. - uint8_t offset_ = 0; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_VARINT_HPACK_VARINT_DECODER_H_
diff --git a/net/third_party/http2/hpack/varint/hpack_varint_decoder_test.cc b/net/third_party/http2/hpack/varint/hpack_varint_decoder_test.cc deleted file mode 100644 index 3b701b00..0000000 --- a/net/third_party/http2/hpack/varint/hpack_varint_decoder_test.cc +++ /dev/null
@@ -1,464 +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 "net/third_party/http2/hpack/varint/hpack_varint_decoder.h" - -// Test HpackVarintDecoder against hardcoded data. - -#include <stddef.h> - -#include "base/logging.h" -#include "net/third_party/http2/platform/api/http2_arraysize.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionFailure; -using ::testing::AssertionSuccess; - -namespace http2 { -namespace test { -namespace { - -// Save previous value of flag and restore on destruction. -class FlagSaver { - public: - FlagSaver() = delete; - explicit FlagSaver(bool decode_64_bits) - : saved_value_(GetHttp2ReloadableFlag(http2_varint_decode_64_bits)) { - SetHttp2ReloadableFlag(http2_varint_decode_64_bits, decode_64_bits); - } - ~FlagSaver() { - SetHttp2ReloadableFlag(http2_varint_decode_64_bits, saved_value_); - } - - private: - const bool saved_value_; -}; - -class HpackVarintDecoderTest - : public RandomDecoderTest, - public ::testing::WithParamInterface< - ::testing::tuple<bool, uint8_t, const char*>> { - protected: - HpackVarintDecoderTest() - : decode_64_bits_(::testing::get<0>(GetParam())), - high_bits_(::testing::get<1>(GetParam())), - suffix_(Http2HexDecode(::testing::get<2>(GetParam()))), - flag_saver_(decode_64_bits_), - prefix_length_(0) {} - - void DecodeExpectSuccess(Http2StringPiece data, - uint32_t prefix_length, - uint64_t expected_value) { - Validator validator = [expected_value, this]( - const DecodeBuffer& db, - DecodeStatus status) -> AssertionResult { - VERIFY_EQ(expected_value, decoder_.value()) - << "Value doesn't match expected: " << decoder_.value() - << " != " << expected_value; - return AssertionSuccess(); - }; - - // First validate that decoding is done and that we've advanced the cursor - // the expected amount. - validator = ValidateDoneAndOffset(/* offset = */ data.size(), validator); - - EXPECT_TRUE(Decode(data, prefix_length, validator)); - - EXPECT_EQ(expected_value, decoder_.value()); - } - - void DecodeExpectError(Http2StringPiece data, uint32_t prefix_length) { - Validator validator = [](const DecodeBuffer& db, - DecodeStatus status) -> AssertionResult { - VERIFY_EQ(DecodeStatus::kDecodeError, status); - return AssertionSuccess(); - }; - - EXPECT_TRUE(Decode(data, prefix_length, validator)); - } - - bool decode_64_bits() const { return decode_64_bits_; } - - private: - AssertionResult Decode(Http2StringPiece data, - uint32_t prefix_length, - const Validator validator) { - prefix_length_ = prefix_length; - - // Copy |data| so that it can be modified. - Http2String data_copy(data); - - // Bits of the first byte not part of the prefix should be ignored. - uint8_t high_bits_mask = 0b11111111 << prefix_length_; - data_copy[0] |= (high_bits_mask & high_bits_); - - // Extra bytes appended to the input should be ignored. - data_copy.append(suffix_); - - DecodeBuffer b(data_copy); - - // StartDecoding, above, requires the DecodeBuffer be non-empty so that it - // can call Start with the prefix byte. - bool return_non_zero_on_first = true; - - return DecodeAndValidateSeveralWays(&b, return_non_zero_on_first, - validator); - } - - DecodeStatus StartDecoding(DecodeBuffer* b) override { - CHECK_LT(0u, b->Remaining()); - uint8_t prefix = b->DecodeUInt8(); - return decoder_.Start(prefix, prefix_length_, b); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - return decoder_.Resume(b); - } - - // Test new or old behavior. - const bool decode_64_bits_; - // Bits of the first byte not part of the prefix. - const uint8_t high_bits_; - // Extra bytes appended to the input. - const Http2String suffix_; - - // |flag_saver_| must preceed |decoder_| so that the flag is already set when - // |decoder_| is constructed. - FlagSaver flag_saver_; - HpackVarintDecoder decoder_; - uint8_t prefix_length_; -}; - -INSTANTIATE_TEST_CASE_P( - HpackVarintDecoderTest, - HpackVarintDecoderTest, - ::testing::Combine( - // Test both the new version (supporting 64 bit integers) and the old - // one (only supporting up to 2^28 + 2^prefix_length - 2. - ::testing::Bool(), - // Bits of the first byte not part of the prefix should be ignored. - ::testing::Values(0b00000000, 0b11111111, 0b10101010), - // Extra bytes appended to the input should be ignored. - ::testing::Values("", "00", "666f6f"))); - -// Test data used when decode_64_bits() == true. -struct { - const char* data; - uint32_t prefix_length; - uint64_t expected_value; -} kSuccessTestData[] = { - // Zero value with different prefix lengths. - {"00", 3, 0}, - {"00", 4, 0}, - {"00", 5, 0}, - {"00", 6, 0}, - {"00", 7, 0}, - // Small values that fit in the prefix. - {"06", 3, 6}, - {"0d", 4, 13}, - {"10", 5, 16}, - {"29", 6, 41}, - {"56", 7, 86}, - // Values of 2^n-1, which have an all-zero extension byte. - {"0700", 3, 7}, - {"0f00", 4, 15}, - {"1f00", 5, 31}, - {"3f00", 6, 63}, - {"7f00", 7, 127}, - // Values of 2^n-1, plus one extra byte of padding. - {"078000", 3, 7}, - {"0f8000", 4, 15}, - {"1f8000", 5, 31}, - {"3f8000", 6, 63}, - {"7f8000", 7, 127}, - // Values requiring one extension byte. - {"0760", 3, 103}, - {"0f2a", 4, 57}, - {"1f7f", 5, 158}, - {"3f02", 6, 65}, - {"7f49", 7, 200}, - // Values requiring one extension byte, plus one byte of padding. - {"07e000", 3, 103}, - {"0faa00", 4, 57}, - {"1fff00", 5, 158}, - {"3f8200", 6, 65}, - {"7fc900", 7, 200}, - // Values requiring one extension byte, plus two bytes of padding. - {"07e08000", 3, 103}, - {"0faa8000", 4, 57}, - {"1fff8000", 5, 158}, - {"3f828000", 6, 65}, - {"7fc98000", 7, 200}, - // Values requiring one extension byte, plus the maximum amount of padding. - {"07e0808080808080808000", 3, 103}, - {"0faa808080808080808000", 4, 57}, - {"1fff808080808080808000", 5, 158}, - {"3f82808080808080808000", 6, 65}, - {"7fc9808080808080808000", 7, 200}, - // Values requiring two extension bytes. - {"07b260", 3, 12345}, - {"0f8a2a", 4, 5401}, - {"1fa87f", 5, 16327}, - {"3fd002", 6, 399}, - {"7fff49", 7, 9598}, - // Values requiring two extension bytes, plus one byte of padding. - {"07b2e000", 3, 12345}, - {"0f8aaa00", 4, 5401}, - {"1fa8ff00", 5, 16327}, - {"3fd08200", 6, 399}, - {"7fffc900", 7, 9598}, - // Values requiring two extension bytes, plus the maximum amount of padding. - {"07b2e080808080808000", 3, 12345}, - {"0f8aaa80808080808000", 4, 5401}, - {"1fa8ff80808080808000", 5, 16327}, - {"3fd08280808080808000", 6, 399}, - {"7fffc980808080808000", 7, 9598}, - // Values requiring three extension bytes. - {"078ab260", 3, 1579281}, - {"0fc18a2a", 4, 689488}, - {"1fada87f", 5, 2085964}, - {"3fa0d002", 6, 43103}, - {"7ffeff49", 7, 1212541}, - // Values requiring three extension bytes, plus one byte of padding. - {"078ab2e000", 3, 1579281}, - {"0fc18aaa00", 4, 689488}, - {"1fada8ff00", 5, 2085964}, - {"3fa0d08200", 6, 43103}, - {"7ffeffc900", 7, 1212541}, - // Values requiring four extension bytes. - {"079f8ab260", 3, 202147110}, - {"0fa2c18a2a", 4, 88252593}, - {"1fd0ada87f", 5, 266999535}, - {"3ff9a0d002", 6, 5509304}, - {"7f9efeff49", 7, 155189149}, - // Values requiring four extension bytes, plus one byte of padding. - {"079f8ab2e000", 3, 202147110}, - {"0fa2c18aaa00", 4, 88252593}, - {"1fd0ada8ff00", 5, 266999535}, - {"3ff9a0d08200", 6, 5509304}, - {"7f9efeffc900", 7, 155189149}, - // Values requiring six extension bytes. - {"0783aa9f8ab260", 3, 3311978140938}, - {"0ff0b0a2c18a2a", 4, 1445930244223}, - {"1fda84d0ada87f", 5, 4374519874169}, - {"3fb5fbf9a0d002", 6, 90263420404}, - {"7fcff19efeff49", 7, 2542616951118}, - // Values requiring eight extension bytes. - {"07f19883aa9f8ab260", 3, 54263449861016696}, - {"0f84fdf0b0a2c18a2a", 4, 23690121121119891}, - {"1fa0dfda84d0ada87f", 5, 71672133617889215}, - {"3f9ff0b5fbf9a0d002", 6, 1478875878881374}, - {"7ffbc1cff19efeff49", 7, 41658236125045114}, - // Values requiring ten extension bytes. - {"0794f1f19883aa9f8ab201", 3, 12832019021693745307u}, - {"0fa08f84fdf0b0a2c18a01", 4, 9980690937382242223u}, - {"1fbfdda0dfda84d0ada801", 5, 12131360551794650846u}, - {"3f9dc79ff0b5fbf9a0d001", 6, 15006530362736632796u}, - {"7f8790fbc1cff19efeff01", 7, 18445754019193211014u}, - // Maximum value: 2^64-1. - {"07f8ffffffffffffffff01", 3, 18446744073709551615u}, - {"0ff0ffffffffffffffff01", 4, 18446744073709551615u}, - {"1fe0ffffffffffffffff01", 5, 18446744073709551615u}, - {"3fc0ffffffffffffffff01", 6, 18446744073709551615u}, - {"7f80ffffffffffffffff01", 7, 18446744073709551615u}, - // Examples from RFC7541 C.1. - {"0a", 5, 10}, - {"1f9a0a", 5, 1337}, -}; - -// Test data used when decode_64_bits() == false. -struct { - const char* data; - uint32_t prefix_length; - uint64_t expected_value; -} kSuccessTestDataOld[] = { - // Zero value with different prefix lengths. - {"00", 3, 0}, - {"00", 4, 0}, - {"00", 5, 0}, - {"00", 6, 0}, - {"00", 7, 0}, - // Small values that fit in the prefix. - {"06", 3, 6}, - {"0d", 4, 13}, - {"10", 5, 16}, - {"29", 6, 41}, - {"56", 7, 86}, - // Values of 2^n-1, which have an all-zero extension byte. - {"0700", 3, 7}, - {"0f00", 4, 15}, - {"1f00", 5, 31}, - {"3f00", 6, 63}, - {"7f00", 7, 127}, - // Values of 2^n-1, plus one extra byte of padding. - {"078000", 3, 7}, - {"0f8000", 4, 15}, - {"1f8000", 5, 31}, - {"3f8000", 6, 63}, - {"7f8000", 7, 127}, - // Values requiring one extension byte. - {"0760", 3, 103}, - {"0f2a", 4, 57}, - {"1f7f", 5, 158}, - {"3f02", 6, 65}, - {"7f49", 7, 200}, - // Values requiring one extension byte, plus one byte of padding. - {"07e000", 3, 103}, - {"0faa00", 4, 57}, - {"1fff00", 5, 158}, - {"3f8200", 6, 65}, - {"7fc900", 7, 200}, - // Values requiring one extension byte, plus two bytes of padding. - {"07e08000", 3, 103}, - {"0faa8000", 4, 57}, - {"1fff8000", 5, 158}, - {"3f828000", 6, 65}, - {"7fc98000", 7, 200}, - // Values requiring one extension byte, plus the maximum amount of padding. - {"07e080808000", 3, 103}, - {"0faa80808000", 4, 57}, - {"1fff80808000", 5, 158}, - {"3f8280808000", 6, 65}, - {"7fc980808000", 7, 200}, - // Values requiring two extension bytes. - {"07b260", 3, 12345}, - {"0f8a2a", 4, 5401}, - {"1fa87f", 5, 16327}, - {"3fd002", 6, 399}, - {"7fff49", 7, 9598}, - // Values requiring two extension bytes, plus one byte of padding. - {"07b2e000", 3, 12345}, - {"0f8aaa00", 4, 5401}, - {"1fa8ff00", 5, 16327}, - {"3fd08200", 6, 399}, - {"7fffc900", 7, 9598}, - // Values requiring two extension bytes, plus the maximum amount of padding. - {"07b2e0808000", 3, 12345}, - {"0f8aaa808000", 4, 5401}, - {"1fa8ff808000", 5, 16327}, - {"3fd082808000", 6, 399}, - {"7fffc9808000", 7, 9598}, - // Values requiring three extension bytes. - {"078ab260", 3, 1579281}, - {"0fc18a2a", 4, 689488}, - {"1fada87f", 5, 2085964}, - {"3fa0d002", 6, 43103}, - {"7ffeff49", 7, 1212541}, - // Values requiring three extension bytes, plus one byte of padding. - {"078ab2e000", 3, 1579281}, - {"0fc18aaa00", 4, 689488}, - {"1fada8ff00", 5, 2085964}, - {"3fa0d08200", 6, 43103}, - {"7ffeffc900", 7, 1212541}, - // Values requiring four extension bytes. - {"079f8ab260", 3, 202147110}, - {"0fa2c18a2a", 4, 88252593}, - {"1fd0ada87f", 5, 266999535}, - {"3ff9a0d002", 6, 5509304}, - {"7f9efeff49", 7, 155189149}, - // Values requiring four extension bytes, plus one byte of padding. - {"079f8ab2e000", 3, 202147110}, - {"0fa2c18aaa00", 4, 88252593}, - {"1fd0ada8ff00", 5, 266999535}, - {"3ff9a0d08200", 6, 5509304}, - {"7f9efeffc900", 7, 155189149}, - // Examples from RFC7541 C.1. - {"0a", 5, 10}, - {"1f9a0a", 5, 1337}, -}; - -TEST_P(HpackVarintDecoderTest, Success) { - if (decode_64_bits()) { - for (size_t i = 0; i < HTTP2_ARRAYSIZE(kSuccessTestData); ++i) { - DecodeExpectSuccess(Http2HexDecode(kSuccessTestData[i].data), - kSuccessTestData[i].prefix_length, - kSuccessTestData[i].expected_value); - } - } else { - for (size_t i = 0; i < HTTP2_ARRAYSIZE(kSuccessTestDataOld); ++i) { - DecodeExpectSuccess(Http2HexDecode(kSuccessTestDataOld[i].data), - kSuccessTestDataOld[i].prefix_length, - kSuccessTestDataOld[i].expected_value); - } - } -} - -// Test data used when decode_64_bits() == true. -struct { - const char* data; - uint32_t prefix_length; -} kErrorTestData[] = { - // Too many extension bytes, all 0s (except for extension bit in each byte). - {"0780808080808080808080", 3}, - {"0f80808080808080808080", 4}, - {"1f80808080808080808080", 5}, - {"3f80808080808080808080", 6}, - {"7f80808080808080808080", 7}, - // Too many extension bytes, all 1s. - {"07ffffffffffffffffffff", 3}, - {"0fffffffffffffffffffff", 4}, - {"1fffffffffffffffffffff", 5}, - {"3fffffffffffffffffffff", 6}, - {"7fffffffffffffffffffff", 7}, - // Value of 2^64, one higher than maximum of 2^64-1. - {"07f9ffffffffffffffff01", 3}, - {"0ff1ffffffffffffffff01", 4}, - {"1fe1ffffffffffffffff01", 5}, - {"3fc1ffffffffffffffff01", 6}, - {"7f81ffffffffffffffff01", 7}, - // Maximum value: 2^64-1, with one byte of padding. - {"07f8ffffffffffffffff8100", 3}, - {"0ff0ffffffffffffffff8100", 4}, - {"1fe0ffffffffffffffff8100", 5}, - {"3fc0ffffffffffffffff8100", 6}, - {"7f80ffffffffffffffff8100", 7}, -}; - -// Test data used when decode_64_bits() == false. -// In this mode, HpackVarintDecoder allows at most five extension bytes, -// and fifth extension byte must be zero. -struct { - const char* data; - uint32_t prefix_length; -} kErrorTestDataOld[] = { - // Maximum number of extension bytes but last byte is non-zero. - {"078080808001", 3}, - {"0f8080808001", 4}, - {"1f8080808001", 5}, - {"3f8080808001", 6}, - {"7f8080808001", 7}, - // Too many extension bytes, all 0s (except for extension bit in each byte). - {"078080808080", 3}, - {"0f8080808080", 4}, - {"1f8080808080", 5}, - {"3f8080808080", 6}, - {"7f8080808080", 7}, - // Too many extension bytes, all 1s. - {"07ffffffffff", 3}, - {"0fffffffffff", 4}, - {"1fffffffffff", 5}, - {"3fffffffffff", 6}, - {"7fffffffffff", 7}, -}; - -TEST_P(HpackVarintDecoderTest, Error) { - if (decode_64_bits()) { - for (size_t i = 0; i < HTTP2_ARRAYSIZE(kErrorTestData); ++i) { - DecodeExpectError(Http2HexDecode(kErrorTestData[i].data), - kErrorTestData[i].prefix_length); - } - } else { - for (size_t i = 0; i < HTTP2_ARRAYSIZE(kErrorTestDataOld); ++i) { - DecodeExpectError(Http2HexDecode(kErrorTestDataOld[i].data), - kErrorTestDataOld[i].prefix_length); - } - } -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/varint/hpack_varint_encoder.cc b/net/third_party/http2/hpack/varint/hpack_varint_encoder.cc deleted file mode 100644 index 0bead9d..0000000 --- a/net/third_party/http2/hpack/varint/hpack_varint_encoder.cc +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/varint/hpack_varint_encoder.h" - -#include "base/logging.h" - -namespace http2 { - -HpackVarintEncoder::HpackVarintEncoder() - : varint_(0), encoding_in_progress_(false) {} - -unsigned char HpackVarintEncoder::StartEncoding(uint8_t high_bits, - uint8_t prefix_length, - uint64_t varint) { - DCHECK(!encoding_in_progress_); - DCHECK_EQ(0u, varint_); - DCHECK_LE(1u, prefix_length); - DCHECK_LE(prefix_length, 7u); - - // prefix_mask defines the sequence of low-order bits of the first byte - // that encode the prefix of the value. It is also the marker in those bits - // of the first byte indicating that at least one extension byte is needed. - const uint8_t prefix_mask = (1 << prefix_length) - 1; - DCHECK_EQ(0, high_bits & prefix_mask); - - if (varint < prefix_mask) { - // The integer fits into the prefix in its entirety. - return high_bits | static_cast<unsigned char>(varint); - } - - // We need extension bytes. - varint_ = varint - prefix_mask; - encoding_in_progress_ = true; - return high_bits | prefix_mask; -} - -size_t HpackVarintEncoder::ResumeEncoding(size_t max_encoded_bytes, - Http2String* output) { - DCHECK(encoding_in_progress_); - DCHECK_NE(0u, max_encoded_bytes); - - size_t encoded_bytes = 0; - while (encoded_bytes < max_encoded_bytes) { - ++encoded_bytes; - if (varint_ < 128) { - // Encode final seven bits, with continuation bit set to zero. - output->push_back(varint_); - varint_ = 0; - encoding_in_progress_ = false; - break; - } - // Encode the next seven bits, with continuation bit set to one. - output->push_back(0b10000000 | (varint_ % 128)); - varint_ >>= 7; - } - return encoded_bytes; -} - -bool HpackVarintEncoder::IsEncodingInProgress() const { - return encoding_in_progress_; -} - -} // namespace http2
diff --git a/net/third_party/http2/hpack/varint/hpack_varint_encoder.h b/net/third_party/http2/hpack/varint/hpack_varint_encoder.h deleted file mode 100644 index 9db09664..0000000 --- a/net/third_party/http2/hpack/varint/hpack_varint_encoder.h +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HPACK_VARINT_HPACK_VARINT_ENCODER_H_ -#define NET_THIRD_PARTY_HTTP2_HPACK_VARINT_HPACK_VARINT_ENCODER_H_ - -#include <cstdint> - -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string.h" - -namespace http2 { - -// HPACK integer encoder class implementing variable length integer -// representation defined in RFC7541, Section 5.1: -// https://httpwg.org/specs/rfc7541.html#integer.representation -class HTTP2_EXPORT_PRIVATE HpackVarintEncoder { - public: - HpackVarintEncoder(); - - // Start encoding an integer. Return the first encoded byte (composed of - // optional high bits and 1 to 8 bit long prefix). It is possible that this - // completes the encoding. Must not be called when previously started - // encoding is still in progress. - unsigned char StartEncoding(uint8_t high_bits, - uint8_t prefix_length, - uint64_t varint); - - // Continue encoding the integer |varint| passed in to StartEncoding(). - // Append the next at most |max_encoded_bytes| encoded octets to |output|. - // Returns the number of encoded octets. Must not be called unless a - // previously started encoding is still in progress. - size_t ResumeEncoding(size_t max_encoded_bytes, Http2String* output); - - // Returns true if encoding an integer has started and is not completed yet. - bool IsEncodingInProgress() const; - - private: - // The original integer shifted to the right by the number of bits already - // encoded. The lower bits shifted away have already been encoded, and - // |varint_| has the higher bits that remain to be encoded. - uint64_t varint_; - - // True when encoding an integer has started and is not completed yet. - bool encoding_in_progress_; -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HPACK_VARINT_HPACK_VARINT_ENCODER_H_
diff --git a/net/third_party/http2/hpack/varint/hpack_varint_encoder_test.cc b/net/third_party/http2/hpack/varint/hpack_varint_encoder_test.cc deleted file mode 100644 index a65bb37..0000000 --- a/net/third_party/http2/hpack/varint/hpack_varint_encoder_test.cc +++ /dev/null
@@ -1,178 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/varint/hpack_varint_encoder.h" - -#include "net/third_party/http2/platform/api/http2_arraysize.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { -namespace { - -// Freshly constructed encoder is not in the process of encoding. -TEST(HpackVarintEncoderTest, Done) { - HpackVarintEncoder varint_encoder; - EXPECT_FALSE(varint_encoder.IsEncodingInProgress()); -} - -struct { - uint8_t high_bits; - uint8_t prefix_length; - uint64_t value; - uint8_t expected_encoding; -} kShortTestData[] = {{0b10110010, 1, 0, 0b10110010}, - {0b10101100, 2, 2, 0b10101110}, - {0b10100000, 3, 6, 0b10100110}, - {0b10110000, 4, 13, 0b10111101}, - {0b10100000, 5, 8, 0b10101000}, - {0b11000000, 6, 48, 0b11110000}, - {0b10000000, 7, 99, 0b11100011}, - // Example from RFC7541 C.1. - {0b00000000, 5, 10, 0b00001010}}; - -// Encode integers that fit in the prefix. -TEST(HpackVarintEncoderTest, Short) { - HpackVarintEncoder varint_encoder; - - for (size_t i = 0; i < HTTP2_ARRAYSIZE(kShortTestData); ++i) { - EXPECT_EQ(kShortTestData[i].expected_encoding, - varint_encoder.StartEncoding(kShortTestData[i].high_bits, - kShortTestData[i].prefix_length, - kShortTestData[i].value)); - EXPECT_FALSE(varint_encoder.IsEncodingInProgress()); - } -} - -struct { - uint8_t high_bits; - uint8_t prefix_length; - uint64_t value; - const char* expected_encoding; -} kLongTestData[] = { - // One extension byte. - {0b10011000, 3, 103, "9f60"}, - {0b10010000, 4, 57, "9f2a"}, - {0b11000000, 5, 158, "df7f"}, - {0b01000000, 6, 65, "7f02"}, - {0b00000000, 7, 200, "7f49"}, - // Two extension bytes. - {0b10011000, 3, 12345, "9fb260"}, - {0b10010000, 4, 5401, "9f8a2a"}, - {0b11000000, 5, 16327, "dfa87f"}, - {0b01000000, 6, 399, "7fd002"}, - {0b00000000, 7, 9598, "7fff49"}, - // Three extension bytes. - {0b10011000, 3, 1579281, "9f8ab260"}, - {0b10010000, 4, 689488, "9fc18a2a"}, - {0b11000000, 5, 2085964, "dfada87f"}, - {0b01000000, 6, 43103, "7fa0d002"}, - {0b00000000, 7, 1212541, "7ffeff49"}, - // Four extension bytes. - {0b10011000, 3, 202147110, "9f9f8ab260"}, - {0b10010000, 4, 88252593, "9fa2c18a2a"}, - {0b11000000, 5, 266999535, "dfd0ada87f"}, - {0b01000000, 6, 5509304, "7ff9a0d002"}, - {0b00000000, 7, 155189149, "7f9efeff49"}, - // Six extension bytes. - {0b10011000, 3, 3311978140938, "9f83aa9f8ab260"}, - {0b10010000, 4, 1445930244223, "9ff0b0a2c18a2a"}, - {0b11000000, 5, 4374519874169, "dfda84d0ada87f"}, - {0b01000000, 6, 90263420404, "7fb5fbf9a0d002"}, - {0b00000000, 7, 2542616951118, "7fcff19efeff49"}, - // Eight extension bytes. - {0b10011000, 3, 54263449861016696, "9ff19883aa9f8ab260"}, - {0b10010000, 4, 23690121121119891, "9f84fdf0b0a2c18a2a"}, - {0b11000000, 5, 71672133617889215, "dfa0dfda84d0ada87f"}, - {0b01000000, 6, 1478875878881374, "7f9ff0b5fbf9a0d002"}, - {0b00000000, 7, 41658236125045114, "7ffbc1cff19efeff49"}, - // Ten extension bytes. - {0b10011000, 3, 12832019021693745307u, "9f94f1f19883aa9f8ab201"}, - {0b10010000, 4, 9980690937382242223u, "9fa08f84fdf0b0a2c18a01"}, - {0b11000000, 5, 12131360551794650846u, "dfbfdda0dfda84d0ada801"}, - {0b01000000, 6, 15006530362736632796u, "7f9dc79ff0b5fbf9a0d001"}, - {0b00000000, 7, 18445754019193211014u, "7f8790fbc1cff19efeff01"}, - // Maximum value: 2^64-1. - {0b10011000, 3, 18446744073709551615u, "9ff8ffffffffffffffff01"}, - {0b10010000, 4, 18446744073709551615u, "9ff0ffffffffffffffff01"}, - {0b11000000, 5, 18446744073709551615u, "dfe0ffffffffffffffff01"}, - {0b01000000, 6, 18446744073709551615u, "7fc0ffffffffffffffff01"}, - {0b00000000, 7, 18446744073709551615u, "7f80ffffffffffffffff01"}, - // Example from RFC7541 C.1. - {0b00000000, 5, 1337, "1f9a0a"}, -}; - -// Encode integers that do not fit in the prefix. -TEST(HpackVarintEncoderTest, Long) { - HpackVarintEncoder varint_encoder; - - // Test encoding byte by byte, also test encoding in - // a single ResumeEncoding() call. - for (bool byte_by_byte : {true, false}) { - for (size_t i = 0; i < HTTP2_ARRAYSIZE(kLongTestData); ++i) { - Http2String expected_encoding = - Http2HexDecode(kLongTestData[i].expected_encoding); - ASSERT_FALSE(expected_encoding.empty()); - - EXPECT_EQ(static_cast<unsigned char>(expected_encoding[0]), - varint_encoder.StartEncoding(kLongTestData[i].high_bits, - kLongTestData[i].prefix_length, - kLongTestData[i].value)); - EXPECT_TRUE(varint_encoder.IsEncodingInProgress()); - - Http2String output; - if (byte_by_byte) { - while (varint_encoder.IsEncodingInProgress()) { - EXPECT_EQ(1u, varint_encoder.ResumeEncoding(1, &output)); - } - } else { - // TODO(bnc): Factor out maximum number of extension bytes into a - // constant in HpackVarintEncoder. - EXPECT_EQ(expected_encoding.size() - 1, - varint_encoder.ResumeEncoding(10, &output)); - EXPECT_FALSE(varint_encoder.IsEncodingInProgress()); - } - EXPECT_EQ(expected_encoding.size() - 1, output.size()); - EXPECT_EQ(expected_encoding.substr(1), output); - } - } -} - -struct { - uint8_t high_bits; - uint8_t prefix_length; - uint64_t value; - uint8_t expected_encoding_first_byte; -} kLastByteIsZeroTestData[] = { - {0b10110010, 1, 1, 0b10110011}, {0b10101100, 2, 3, 0b10101111}, - {0b10101000, 3, 7, 0b10101111}, {0b10110000, 4, 15, 0b10111111}, - {0b10100000, 5, 31, 0b10111111}, {0b11000000, 6, 63, 0b11111111}, - {0b10000000, 7, 127, 0b11111111}}; - -// Make sure that the encoder outputs the last byte even when it is zero. This -// happens exactly when encoding the value 2^prefix_length - 1. -TEST(HpackVarintEncoderTest, LastByteIsZero) { - HpackVarintEncoder varint_encoder; - - for (size_t i = 0; i < HTTP2_ARRAYSIZE(kLastByteIsZeroTestData); ++i) { - EXPECT_EQ( - kLastByteIsZeroTestData[i].expected_encoding_first_byte, - varint_encoder.StartEncoding(kLastByteIsZeroTestData[i].high_bits, - kLastByteIsZeroTestData[i].prefix_length, - kLastByteIsZeroTestData[i].value)); - EXPECT_TRUE(varint_encoder.IsEncodingInProgress()); - - Http2String output; - EXPECT_EQ(1u, varint_encoder.ResumeEncoding(1, &output)); - ASSERT_EQ(1u, output.size()); - EXPECT_EQ(0b00000000, output[0]); - EXPECT_FALSE(varint_encoder.IsEncodingInProgress()); - } -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/hpack/varint/hpack_varint_round_trip_test.cc b/net/third_party/http2/hpack/varint/hpack_varint_round_trip_test.cc deleted file mode 100644 index bde9afd1..0000000 --- a/net/third_party/http2/hpack/varint/hpack_varint_round_trip_test.cc +++ /dev/null
@@ -1,512 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/hpack/varint/hpack_varint_decoder.h" - -// Test HpackVarintDecoder against data encoded via HpackBlockBuilder, -// which uses HpackVarintEncoder under the hood. - -#include <stddef.h> - -#include <iterator> -#include <set> -#include <vector> - -#include "base/logging.h" -#include "net/third_party/http2/hpack/tools/hpack_block_builder.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" -#include "net/third_party/http2/tools/random_decoder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionFailure; -using ::testing::AssertionSuccess; -using ::testing::Bool; -using ::testing::WithParamInterface; - -namespace http2 { -namespace test { -namespace { - -// Save previous value of flag and restore on destruction. -class FlagSaver { - public: - FlagSaver() = delete; - explicit FlagSaver(bool decode_64_bits) - : saved_value_(GetHttp2ReloadableFlag(http2_varint_decode_64_bits)) { - SetHttp2ReloadableFlag(http2_varint_decode_64_bits, decode_64_bits); - } - ~FlagSaver() { - SetHttp2ReloadableFlag(http2_varint_decode_64_bits, saved_value_); - } - - private: - const bool saved_value_; -}; - -// Returns the highest value with the specified number of extension bytes -// and the specified prefix length (bits). -uint64_t HiValueOfExtensionBytes(uint32_t extension_bytes, - uint32_t prefix_length) { - return (1 << prefix_length) - 2 + - (extension_bytes == 0 ? 0 : (1LLU << (extension_bytes * 7))); -} - -class HpackVarintRoundTripTest : public RandomDecoderTest, - public WithParamInterface<bool> { - protected: - HpackVarintRoundTripTest() - : decode_64_bits_(GetParam()), - flag_saver_(decode_64_bits_), - prefix_length_(0) {} - - DecodeStatus StartDecoding(DecodeBuffer* b) override { - CHECK_LT(0u, b->Remaining()); - uint8_t prefix = b->DecodeUInt8(); - return decoder_.Start(prefix, prefix_length_, b); - } - - DecodeStatus ResumeDecoding(DecodeBuffer* b) override { - return decoder_.Resume(b); - } - - void DecodeSeveralWays(uint64_t expected_value, uint32_t expected_offset) { - // The validator is called after each of the several times that the input - // DecodeBuffer is decoded, each with a different segmentation of the input. - // Validate that decoder_.value() matches the expected value. - Validator validator = [expected_value, this]( - const DecodeBuffer& db, - DecodeStatus status) -> AssertionResult { - if (decoder_.value() != expected_value) { - return AssertionFailure() - << "Value doesn't match expected: " << decoder_.value() - << " != " << expected_value; - } - return AssertionSuccess(); - }; - - // First validate that decoding is done and that we've advanced the cursor - // the expected amount. - validator = ValidateDoneAndOffset(expected_offset, validator); - - // StartDecoding, above, requires the DecodeBuffer be non-empty so that it - // can call Start with the prefix byte. - bool return_non_zero_on_first = true; - - DecodeBuffer b(buffer_); - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, return_non_zero_on_first, validator)); - - EXPECT_EQ(expected_value, decoder_.value()); - EXPECT_EQ(expected_offset, b.Offset()); - } - - void EncodeNoRandom(uint64_t value, uint8_t prefix_length) { - DCHECK_LE(3, prefix_length); - DCHECK_LE(prefix_length, 7); - prefix_length_ = prefix_length; - - HpackBlockBuilder bb; - bb.AppendHighBitsAndVarint(0, prefix_length_, value); - buffer_ = bb.buffer(); - ASSERT_LT(0u, buffer_.size()); - - const uint8_t prefix_mask = (1 << prefix_length_) - 1; - ASSERT_EQ(buffer_[0], buffer_[0] & prefix_mask); - } - - void Encode(uint64_t value, uint8_t prefix_length) { - EncodeNoRandom(value, prefix_length); - // Add some random bits to the prefix (the first byte) above the mask. - uint8_t prefix = buffer_[0]; - buffer_[0] = prefix | (Random().Rand8() << prefix_length); - const uint8_t prefix_mask = (1 << prefix_length_) - 1; - ASSERT_EQ(prefix, buffer_[0] & prefix_mask); - } - - // This is really a test of HpackBlockBuilder, making sure that the input to - // HpackVarintDecoder is as expected, which also acts as confirmation that - // my thinking about the encodings being used by the tests, i.e. cover the - // range desired. - void ValidateEncoding(uint64_t value, - uint64_t minimum, - uint64_t maximum, - size_t expected_bytes) { - ASSERT_EQ(expected_bytes, buffer_.size()); - if (expected_bytes > 1) { - const uint8_t prefix_mask = (1 << prefix_length_) - 1; - EXPECT_EQ(prefix_mask, buffer_[0] & prefix_mask); - size_t last = expected_bytes - 1; - for (size_t ndx = 1; ndx < last; ++ndx) { - // Before the last extension byte, we expect the high-bit set. - uint8_t byte = buffer_[ndx]; - if (value == minimum) { - EXPECT_EQ(0x80, byte) << "ndx=" << ndx; - } else if (value == maximum) { - if (expected_bytes < 11) { - EXPECT_EQ(0xff, byte) << "ndx=" << ndx; - } - } else { - EXPECT_EQ(0x80, byte & 0x80) << "ndx=" << ndx; - } - } - // The last extension byte should not have the high-bit set. - uint8_t byte = buffer_[last]; - if (value == minimum) { - if (expected_bytes == 2) { - EXPECT_EQ(0x00, byte); - } else { - EXPECT_EQ(0x01, byte); - } - } else if (value == maximum) { - if (expected_bytes < 11) { - EXPECT_EQ(0x7f, byte); - } - } else { - EXPECT_EQ(0x00, byte & 0x80); - } - } else { - const uint8_t prefix_mask = (1 << prefix_length_) - 1; - EXPECT_EQ(value, static_cast<uint32_t>(buffer_[0] & prefix_mask)); - EXPECT_LT(value, prefix_mask); - } - } - - void EncodeAndDecodeValues(const std::set<uint64_t>& values, - uint8_t prefix_length, - size_t expected_bytes) { - CHECK(!values.empty()); - const uint64_t minimum = *values.begin(); - const uint64_t maximum = *values.rbegin(); - for (const uint64_t value : values) { - Encode(value, prefix_length); // Sets buffer_. - - Http2String msg = Http2StrCat("value=", value, " (0x", Http2Hex(value), - "), prefix_length=", prefix_length, - ", expected_bytes=", expected_bytes, "\n", - Http2HexDump(buffer_)); - - if (value == minimum) { - LOG(INFO) << "Checking minimum; " << msg; - } else if (value == maximum) { - LOG(INFO) << "Checking maximum; " << msg; - } - - SCOPED_TRACE(msg); - ValidateEncoding(value, minimum, maximum, expected_bytes); - DecodeSeveralWays(value, expected_bytes); - - // Append some random data to the end of buffer_ and repeat. That random - // data should be ignored. - buffer_.append(Random().RandString(1 + Random().Uniform(10))); - DecodeSeveralWays(value, expected_bytes); - - // If possible, add extension bytes that don't change the value. - if (1 < expected_bytes) { - buffer_.resize(expected_bytes); - for (uint8_t total_bytes = expected_bytes + 1; total_bytes <= 6; - ++total_bytes) { - // Mark the current last byte as not being the last one. - EXPECT_EQ(0x00, 0x80 & buffer_.back()); - buffer_.back() |= 0x80; - buffer_.push_back('\0'); - DecodeSeveralWays(value, total_bytes); - } - } - } - } - - // Encode values (all or some of it) in [start, start+range). Check - // that |start| is the smallest value and |start+range-1| is the largest value - // corresponding to |expected_bytes|, except if |expected_bytes| is maximal. - void EncodeAndDecodeValuesInRange(uint64_t start, - uint64_t range, - uint8_t prefix_length, - size_t expected_bytes) { - const uint8_t prefix_mask = (1 << prefix_length) - 1; - const uint64_t beyond = start + range; - - LOG(INFO) << "############################################################"; - LOG(INFO) << "prefix_length=" << static_cast<int>(prefix_length); - LOG(INFO) << "prefix_mask=" << std::hex << static_cast<int>(prefix_mask); - LOG(INFO) << "start=" << start << " (" << std::hex << start << ")"; - LOG(INFO) << "range=" << range << " (" << std::hex << range << ")"; - LOG(INFO) << "beyond=" << beyond << " (" << std::hex << beyond << ")"; - LOG(INFO) << "expected_bytes=" << expected_bytes; - - if (expected_bytes < 11) { - // Confirm the claim that beyond requires more bytes. - Encode(beyond, prefix_length); - EXPECT_EQ(expected_bytes + 1, buffer_.size()) << Http2HexDump(buffer_); - } - - std::set<uint64_t> values; - if (range < 200) { - // Select all values in the range. - for (uint64_t offset = 0; offset < range; ++offset) { - values.insert(start + offset); - } - } else { - // Select some values in this range, including the minimum and maximum - // values that require exactly |expected_bytes| extension bytes. - values.insert({start, start + 1, beyond - 2, beyond - 1}); - while (values.size() < 100) { - values.insert(Random().UniformInRange(start, beyond - 1)); - } - } - - EncodeAndDecodeValues(values, prefix_length, expected_bytes); - } - - // |flag_saver_| must preceed |decoder_| so that the flag is already set when - // |decoder_| is constructed. - const bool decode_64_bits_; - FlagSaver flag_saver_; - HpackVarintDecoder decoder_; - Http2String buffer_; - uint8_t prefix_length_; -}; - -INSTANTIATE_TEST_CASE_P(HpackVarintRoundTripTest, - HpackVarintRoundTripTest, - Bool()); - -// To help me and future debuggers of varint encodings, this LOGs out the -// transition points where a new extension byte is added. -TEST_P(HpackVarintRoundTripTest, Encode) { - for (int prefix_length = 3; prefix_length <= 7; ++prefix_length) { - const uint64_t a = HiValueOfExtensionBytes(0, prefix_length); - const uint64_t b = HiValueOfExtensionBytes(1, prefix_length); - const uint64_t c = HiValueOfExtensionBytes(2, prefix_length); - const uint64_t d = HiValueOfExtensionBytes(3, prefix_length); - const uint64_t e = HiValueOfExtensionBytes(4, prefix_length); - const uint64_t f = HiValueOfExtensionBytes(5, prefix_length); - const uint64_t g = HiValueOfExtensionBytes(6, prefix_length); - const uint64_t h = HiValueOfExtensionBytes(7, prefix_length); - const uint64_t i = HiValueOfExtensionBytes(8, prefix_length); - const uint64_t j = HiValueOfExtensionBytes(9, prefix_length); - - LOG(INFO) << "############################################################"; - LOG(INFO) << "prefix_length=" << prefix_length << " a=" << a - << " b=" << b << " c=" << c << " d=" << d << " e=" << e - << " f=" << f << " g=" << g << " h=" << h << " i=" << i - << " j=" << j; - - std::vector<uint64_t> values = { - 0, 1, // Force line break. - a - 1, a, a + 1, a + 2, a + 3, // Force line break. - b - 1, b, b + 1, b + 2, b + 3, // Force line break. - c - 1, c, c + 1, c + 2, c + 3, // Force line break. - d - 1, d, d + 1, d + 2, d + 3, // Force line break. - e - 1, e, e + 1, e + 2, e + 3 // Force line break. - }; - if (decode_64_bits_) { - for (auto value : { - f - 1, f, f + 1, f + 2, f + 3, // Force line break. - g - 1, g, g + 1, g + 2, g + 3, // Force line break. - h - 1, h, h + 1, h + 2, h + 3, // Force line break. - i - 1, i, i + 1, i + 2, i + 3, // Force line break. - j - 1, j, j + 1, j + 2, j + 3, // Force line break. - }) { - values.push_back(value); - } - } - - for (uint64_t value : values) { - EncodeNoRandom(value, prefix_length); - Http2String dump = Http2HexDump(buffer_); - LOG(INFO) << Http2StringPrintf("%10llu %0#18x ", value, value) - << Http2HexDump(buffer_).substr(7); - } - } -} - -TEST_P(HpackVarintRoundTripTest, FromSpec1337) { - DecodeBuffer b(Http2StringPiece("\x1f\x9a\x0a")); - uint32_t prefix_length = 5; - uint8_t p = b.DecodeUInt8(); - EXPECT_EQ(1u, b.Offset()); - EXPECT_EQ(DecodeStatus::kDecodeDone, decoder_.Start(p, prefix_length, &b)); - EXPECT_EQ(3u, b.Offset()); - EXPECT_EQ(1337u, decoder_.value()); - - EncodeNoRandom(1337, prefix_length); - EXPECT_EQ(3u, buffer_.size()); - EXPECT_EQ('\x1f', buffer_[0]); - EXPECT_EQ('\x9a', buffer_[1]); - EXPECT_EQ('\x0a', buffer_[2]); -} - -// Test all the values that fit into the prefix (one less than the mask). -TEST_P(HpackVarintRoundTripTest, ValidatePrefixOnly) { - for (int prefix_length = 3; prefix_length <= 7; ++prefix_length) { - const uint8_t prefix_mask = (1 << prefix_length) - 1; - EncodeAndDecodeValuesInRange(0, prefix_mask, prefix_length, 1); - } -} - -// Test all values that require exactly 1 extension byte. -TEST_P(HpackVarintRoundTripTest, ValidateOneExtensionByte) { - for (int prefix_length = 3; prefix_length <= 7; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(0, prefix_length) + 1; - EncodeAndDecodeValuesInRange(start, 128, prefix_length, 2); - } -} - -// Test *some* values that require exactly 2 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateTwoExtensionBytes) { - for (int prefix_length = 3; prefix_length <= 7; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(1, prefix_length) + 1; - const uint64_t range = 127 << 7; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 3); - } -} - -// Test *some* values that require 3 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateThreeExtensionBytes) { - for (int prefix_length = 3; prefix_length <= 7; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(2, prefix_length) + 1; - const uint64_t range = 127 << 14; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 4); - } -} - -// Test *some* values that require 4 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateFourExtensionBytes) { - for (int prefix_length = 3; prefix_length <= 7; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(3, prefix_length) + 1; - const uint64_t range = 127 << 21; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 5); - } -} - -// Test *some* values that require 5 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateFiveExtensionBytes) { - if (!decode_64_bits_) { - return; - } - - for (int prefix_length = 3; prefix_length <= 7; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(4, prefix_length) + 1; - const uint64_t range = 127llu << 28; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 6); - } -} - -// Test *some* values that require 6 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateSixExtensionBytes) { - if (!decode_64_bits_) { - return; - } - - for (int prefix_length = 3; prefix_length <= 7; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(5, prefix_length) + 1; - const uint64_t range = 127llu << 35; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 7); - } -} - -// Test *some* values that require 7 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateSevenExtensionBytes) { - if (!decode_64_bits_) { - return; - } - - for (int prefix_length = 3; prefix_length <= 7; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(6, prefix_length) + 1; - const uint64_t range = 127llu << 42; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 8); - } -} - -// Test *some* values that require 8 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateEightExtensionBytes) { - if (!decode_64_bits_) { - return; - } - - for (int prefix_length = 3; prefix_length <= 7; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(7, prefix_length) + 1; - const uint64_t range = 127llu << 49; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 9); - } -} - -// Test *some* values that require 9 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateNineExtensionBytes) { - if (!decode_64_bits_) { - return; - } - - for (int prefix_length = 3; prefix_length <= 7; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(8, prefix_length) + 1; - const uint64_t range = 127llu << 56; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 10); - } -} - -// Test *some* values that require 10 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateTenExtensionBytes) { - if (!decode_64_bits_) { - return; - } - - for (int prefix_length = 3; prefix_length <= 7; ++prefix_length) { - const uint64_t start = HiValueOfExtensionBytes(9, prefix_length) + 1; - const uint64_t range = std::numeric_limits<uint64_t>::max() - start; - - EncodeAndDecodeValuesInRange(start, range, prefix_length, 11); - } -} - -// Test the value one larger than the largest that can be decoded. -TEST_P(HpackVarintRoundTripTest, ValueTooLarge) { - // New implementation can decode any integer that HpackVarintEncoder can - // encode. - if (decode_64_bits_) { - return; - } - - for (prefix_length_ = 3; prefix_length_ <= 7; ++prefix_length_) { - const uint64_t too_large = (1 << 28) + (1 << prefix_length_) - 1; - const uint32_t expected_offset = 6; - HpackBlockBuilder bb; - bb.AppendHighBitsAndVarint(0, prefix_length_, too_large); - buffer_ = bb.buffer(); - - // The validator is called after each of the several times that the input - // DecodeBuffer is decoded, each with a different segmentation of the input. - // Validate that decoder_.value() matches the expected value. - bool validated = false; - Validator validator = [&validated, expected_offset]( - const DecodeBuffer& db, - DecodeStatus status) -> AssertionResult { - validated = true; - VERIFY_EQ(DecodeStatus::kDecodeError, status); - VERIFY_EQ(expected_offset, db.Offset()); - return AssertionSuccess(); - }; - - // StartDecoding, above, requires the DecodeBuffer be non-empty so that it - // can call Start with the prefix byte. - bool return_non_zero_on_first = true; - DecodeBuffer b(buffer_); - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, return_non_zero_on_first, validator)); - EXPECT_EQ(expected_offset, b.Offset()); - EXPECT_TRUE(validated); - } -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/http2_constants.cc b/net/third_party/http2/http2_constants.cc deleted file mode 100644 index 11108bc..0000000 --- a/net/third_party/http2/http2_constants.cc +++ /dev/null
@@ -1,150 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/http2_constants.h" - -#include "base/logging.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" - -namespace http2 { - -Http2String Http2FrameTypeToString(Http2FrameType v) { - switch (v) { - case Http2FrameType::DATA: - return "DATA"; - case Http2FrameType::HEADERS: - return "HEADERS"; - case Http2FrameType::PRIORITY: - return "PRIORITY"; - case Http2FrameType::RST_STREAM: - return "RST_STREAM"; - case Http2FrameType::SETTINGS: - return "SETTINGS"; - case Http2FrameType::PUSH_PROMISE: - return "PUSH_PROMISE"; - case Http2FrameType::PING: - return "PING"; - case Http2FrameType::GOAWAY: - return "GOAWAY"; - case Http2FrameType::WINDOW_UPDATE: - return "WINDOW_UPDATE"; - case Http2FrameType::CONTINUATION: - return "CONTINUATION"; - case Http2FrameType::ALTSVC: - return "ALTSVC"; - } - return Http2StrCat("UnknownFrameType(", static_cast<int>(v), ")"); -} - -Http2String Http2FrameTypeToString(uint8_t v) { - return Http2FrameTypeToString(static_cast<Http2FrameType>(v)); -} - -Http2String Http2FrameFlagsToString(Http2FrameType type, uint8_t flags) { - Http2String s; - // Closure to append flag name |v| to the Http2String |s|, - // and to clear |bit| from |flags|. - auto append_and_clear = [&s, &flags](Http2StringPiece v, uint8_t bit) { - if (!s.empty()) { - s.push_back('|'); - } - Http2StrAppend(&s, v); - flags ^= bit; - }; - if (flags & 0x01) { - if (type == Http2FrameType::DATA || type == Http2FrameType::HEADERS) { - append_and_clear("END_STREAM", Http2FrameFlag::END_STREAM); - } else if (type == Http2FrameType::SETTINGS || - type == Http2FrameType::PING) { - append_and_clear("ACK", Http2FrameFlag::ACK); - } - } - if (flags & 0x04) { - if (type == Http2FrameType::HEADERS || - type == Http2FrameType::PUSH_PROMISE || - type == Http2FrameType::CONTINUATION) { - append_and_clear("END_HEADERS", Http2FrameFlag::END_HEADERS); - } - } - if (flags & 0x08) { - if (type == Http2FrameType::DATA || type == Http2FrameType::HEADERS || - type == Http2FrameType::PUSH_PROMISE) { - append_and_clear("PADDED", Http2FrameFlag::PADDED); - } - } - if (flags & 0x20) { - if (type == Http2FrameType::HEADERS) { - append_and_clear("PRIORITY", Http2FrameFlag::PRIORITY); - } - } - if (flags != 0) { - append_and_clear(Http2StringPrintf("0x%02x", flags), flags); - } - DCHECK_EQ(0, flags); - return s; -} -Http2String Http2FrameFlagsToString(uint8_t type, uint8_t flags) { - return Http2FrameFlagsToString(static_cast<Http2FrameType>(type), flags); -} - -Http2String Http2ErrorCodeToString(uint32_t v) { - switch (v) { - case 0x0: - return "NO_ERROR"; - case 0x1: - return "PROTOCOL_ERROR"; - case 0x2: - return "INTERNAL_ERROR"; - case 0x3: - return "FLOW_CONTROL_ERROR"; - case 0x4: - return "SETTINGS_TIMEOUT"; - case 0x5: - return "STREAM_CLOSED"; - case 0x6: - return "FRAME_SIZE_ERROR"; - case 0x7: - return "REFUSED_STREAM"; - case 0x8: - return "CANCEL"; - case 0x9: - return "COMPRESSION_ERROR"; - case 0xa: - return "CONNECT_ERROR"; - case 0xb: - return "ENHANCE_YOUR_CALM"; - case 0xc: - return "INADEQUATE_SECURITY"; - case 0xd: - return "HTTP_1_1_REQUIRED"; - } - return Http2StrCat("UnknownErrorCode(0x", Http2Hex(v), ")"); -} -Http2String Http2ErrorCodeToString(Http2ErrorCode v) { - return Http2ErrorCodeToString(static_cast<uint32_t>(v)); -} - -Http2String Http2SettingsParameterToString(uint32_t v) { - switch (v) { - case 0x1: - return "HEADER_TABLE_SIZE"; - case 0x2: - return "ENABLE_PUSH"; - case 0x3: - return "MAX_CONCURRENT_STREAMS"; - case 0x4: - return "INITIAL_WINDOW_SIZE"; - case 0x5: - return "MAX_FRAME_SIZE"; - case 0x6: - return "MAX_HEADER_LIST_SIZE"; - } - return Http2StrCat("UnknownSettingsParameter(0x", Http2Hex(v), ")"); -} -Http2String Http2SettingsParameterToString(Http2SettingsParameter v) { - return Http2SettingsParameterToString(static_cast<uint32_t>(v)); -} - -} // namespace http2
diff --git a/net/third_party/http2/http2_constants.h b/net/third_party/http2/http2_constants.h deleted file mode 100644 index a1f28f48..0000000 --- a/net/third_party/http2/http2_constants.h +++ /dev/null
@@ -1,261 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HTTP2_CONSTANTS_H_ -#define NET_THIRD_PARTY_HTTP2_HTTP2_CONSTANTS_H_ - -// Constants from the HTTP/2 spec, RFC 7540, and associated helper functions. - -#include <cstdint> -#include <iosfwd> -#include <ostream> - -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string.h" - -namespace http2 { - -// TODO(jamessynge): create http2_simple_types for types similar to -// SpdyStreamId, but not for structures like Http2FrameHeader. Then will be -// able to move these stream id functions there. -constexpr uint32_t UInt31Mask() { - return 0x7fffffff; -} -constexpr uint32_t StreamIdMask() { - return UInt31Mask(); -} - -// The value used to identify types of frames. Upper case to match the RFC. -// The comments indicate which flags are valid for that frame type. -// ALTSVC is defined in http://httpwg.org/http-extensions/alt-svc.html -// (not yet final standard as of March 2016, but close). -enum class Http2FrameType : uint8_t { - DATA = 0, // END_STREAM | PADDED - HEADERS = 1, // END_STREAM | END_HEADERS | PADDED | PRIORITY - PRIORITY = 2, // - RST_STREAM = 3, // - SETTINGS = 4, // ACK - PUSH_PROMISE = 5, // END_HEADERS | PADDED - PING = 6, // ACK - GOAWAY = 7, // - WINDOW_UPDATE = 8, // - CONTINUATION = 9, // END_HEADERS - ALTSVC = 10, // -}; - -// Is the frame type known/supported? -inline bool IsSupportedHttp2FrameType(uint32_t v) { - return v <= static_cast<uint32_t>(Http2FrameType::ALTSVC); -} -inline bool IsSupportedHttp2FrameType(Http2FrameType v) { - return IsSupportedHttp2FrameType(static_cast<uint32_t>(v)); -} - -// The return type is 'Http2String' so that they can generate a unique string -// for each unsupported value. Since these are just used for debugging/error -// messages, that isn't a cost to we need to worry about. The same applies to -// the functions later in this file. -HTTP2_EXPORT_PRIVATE Http2String Http2FrameTypeToString(Http2FrameType v); -HTTP2_EXPORT_PRIVATE Http2String Http2FrameTypeToString(uint8_t v); -HTTP2_EXPORT_PRIVATE inline std::ostream& operator<<(std::ostream& out, - Http2FrameType v) { - return out << Http2FrameTypeToString(v); -} - -// Flags that appear in supported frame types. These are treated as bit masks. -// The comments indicate for which frame types the flag is valid. -enum Http2FrameFlag { - END_STREAM = 0x01, // DATA, HEADERS - ACK = 0x01, // SETTINGS, PING - END_HEADERS = 0x04, // HEADERS, PUSH_PROMISE, CONTINUATION - PADDED = 0x08, // DATA, HEADERS, PUSH_PROMISE - PRIORITY = 0x20, // HEADERS -}; - -// Formats zero or more flags for the specified type of frame. Returns an -// empty string if flags==0. -HTTP2_EXPORT_PRIVATE Http2String Http2FrameFlagsToString(Http2FrameType type, - uint8_t flags); -HTTP2_EXPORT_PRIVATE Http2String Http2FrameFlagsToString(uint8_t type, - uint8_t flags); - -// Error codes for GOAWAY and RST_STREAM frames. -enum class Http2ErrorCode : uint32_t { - // The associated condition is not a result of an error. For example, a GOAWAY - // might include this code to indicate graceful shutdown of a connection. - HTTP2_NO_ERROR = 0x0, - - // The endpoint detected an unspecific protocol error. This error is for use - // when a more specific error code is not available. - PROTOCOL_ERROR = 0x1, - - // The endpoint encountered an unexpected internal error. - INTERNAL_ERROR = 0x2, - - // The endpoint detected that its peer violated the flow-control protocol. - FLOW_CONTROL_ERROR = 0x3, - - // The endpoint sent a SETTINGS frame but did not receive a response in a - // timely manner. See Section 6.5.3 ("Settings Synchronization"). - SETTINGS_TIMEOUT = 0x4, - - // The endpoint received a frame after a stream was half-closed. - STREAM_CLOSED = 0x5, - - // The endpoint received a frame with an invalid size. - FRAME_SIZE_ERROR = 0x6, - - // The endpoint refused the stream prior to performing any application - // processing (see Section 8.1.4 for details). - REFUSED_STREAM = 0x7, - - // Used by the endpoint to indicate that the stream is no longer needed. - CANCEL = 0x8, - - // The endpoint is unable to maintain the header compression context - // for the connection. - COMPRESSION_ERROR = 0x9, - - // The connection established in response to a CONNECT request (Section 8.3) - // was reset or abnormally closed. - CONNECT_ERROR = 0xa, - - // The endpoint detected that its peer is exhibiting a behavior that might - // be generating excessive load. - ENHANCE_YOUR_CALM = 0xb, - - // The underlying transport has properties that do not meet minimum - // security requirements (see Section 9.2). - INADEQUATE_SECURITY = 0xc, - - // The endpoint requires that HTTP/1.1 be used instead of HTTP/2. - HTTP_1_1_REQUIRED = 0xd, -}; - -// Is the error code supported? (So far that means it is in RFC 7540.) -inline bool IsSupportedHttp2ErrorCode(uint32_t v) { - return v <= static_cast<uint32_t>(Http2ErrorCode::HTTP_1_1_REQUIRED); -} -inline bool IsSupportedHttp2ErrorCode(Http2ErrorCode v) { - return IsSupportedHttp2ErrorCode(static_cast<uint32_t>(v)); -} - -// Format the specified error code. -HTTP2_EXPORT_PRIVATE Http2String Http2ErrorCodeToString(uint32_t v); -HTTP2_EXPORT_PRIVATE Http2String Http2ErrorCodeToString(Http2ErrorCode v); -HTTP2_EXPORT_PRIVATE inline std::ostream& operator<<(std::ostream& out, - Http2ErrorCode v) { - return out << Http2ErrorCodeToString(v); -} - -// Supported parameters in SETTINGS frames; so far just those in RFC 7540. -enum class Http2SettingsParameter : uint16_t { - // Allows the sender to inform the remote endpoint of the maximum size of the - // header compression table used to decode header blocks, in octets. The - // encoder can select any size equal to or less than this value by using - // signaling specific to the header compression format inside a header block - // (see [COMPRESSION]). The initial value is 4,096 octets. - HEADER_TABLE_SIZE = 0x1, - - // This setting can be used to disable server push (Section 8.2). An endpoint - // MUST NOT send a PUSH_PROMISE frame if it receives this parameter set to a - // value of 0. An endpoint that has both set this parameter to 0 and had it - // acknowledged MUST treat the receipt of a PUSH_PROMISE frame as a connection - // error (Section 5.4.1) of type PROTOCOL_ERROR. - // - // The initial value is 1, which indicates that server push is permitted. Any - // value other than 0 or 1 MUST be treated as a connection error (Section - // 5.4.1) of type PROTOCOL_ERROR. - ENABLE_PUSH = 0x2, - - // Indicates the maximum number of concurrent streams that the sender will - // allow. This limit is directional: it applies to the number of streams that - // the sender permits the receiver to create. Initially, there is no limit to - // this value. It is recommended that this value be no smaller than 100, so as - // to not unnecessarily limit parallelism. - // - // A value of 0 for MAX_CONCURRENT_STREAMS SHOULD NOT be treated as - // special by endpoints. A zero value does prevent the creation of new - // streams; however, this can also happen for any limit that is exhausted with - // active streams. Servers SHOULD only set a zero value for short durations; - // if a server does not wish to accept requests, closing the connection is - // more appropriate. - MAX_CONCURRENT_STREAMS = 0x3, - - // Indicates the sender's initial window size (in octets) for stream-level - // flow control. The initial value is 2^16-1 (65,535) octets. - // - // This setting affects the window size of all streams (see Section 6.9.2). - // - // Values above the maximum flow-control window size of 2^31-1 MUST be treated - // as a connection error (Section 5.4.1) of type FLOW_CONTROL_ERROR. - INITIAL_WINDOW_SIZE = 0x4, - - // Indicates the size of the largest frame payload that the sender is willing - // to receive, in octets. - // - // The initial value is 2^14 (16,384) octets. The value advertised by an - // endpoint MUST be between this initial value and the maximum allowed frame - // size (2^24-1 or 16,777,215 octets), inclusive. Values outside this range - // MUST be treated as a connection error (Section 5.4.1) of type - // PROTOCOL_ERROR. - MAX_FRAME_SIZE = 0x5, - - // This advisory setting informs a peer of the maximum size of header list - // that the sender is prepared to accept, in octets. The value is based on the - // uncompressed size of header fields, including the length of the name and - // value in octets plus an overhead of 32 octets for each header field. - // - // For any given request, a lower limit than what is advertised MAY be - // enforced. The initial value of this setting is unlimited. - MAX_HEADER_LIST_SIZE = 0x6, -}; - -// Is the settings parameter supported (so far that means it is in RFC 7540)? -inline bool IsSupportedHttp2SettingsParameter(uint32_t v) { - return 0 < v && v <= static_cast<uint32_t>( - Http2SettingsParameter::MAX_HEADER_LIST_SIZE); -} -inline bool IsSupportedHttp2SettingsParameter(Http2SettingsParameter v) { - return IsSupportedHttp2SettingsParameter(static_cast<uint32_t>(v)); -} - -// Format the specified settings parameter. -HTTP2_EXPORT_PRIVATE Http2String Http2SettingsParameterToString(uint32_t v); -HTTP2_EXPORT_PRIVATE Http2String -Http2SettingsParameterToString(Http2SettingsParameter v); -inline std::ostream& operator<<(std::ostream& out, Http2SettingsParameter v) { - return out << Http2SettingsParameterToString(v); -} - -// Information about the initial, minimum and maximum value of settings (not -// applicable to all settings parameters). -class Http2SettingsInfo { - public: - // Default value for HEADER_TABLE_SIZE. - static constexpr uint32_t DefaultHeaderTableSize() { return 4096; } - - // Default value for ENABLE_PUSH. - static constexpr bool DefaultEnablePush() { return true; } - - // Default value for INITIAL_WINDOW_SIZE. - static constexpr uint32_t DefaultInitialWindowSize() { return 65535; } - - // Maximum value for INITIAL_WINDOW_SIZE, and for the connection flow control - // window, and for each stream flow control window. - static constexpr uint32_t MaximumWindowSize() { return UInt31Mask(); } - - // Default value for MAX_FRAME_SIZE. - static constexpr uint32_t DefaultMaxFrameSize() { return 16384; } - - // Minimum value for MAX_FRAME_SIZE. - static constexpr uint32_t MinimumMaxFrameSize() { return 16384; } - - // Maximum value for MAX_FRAME_SIZE. - static constexpr uint32_t MaximumMaxFrameSize() { return (1 << 24) - 1; } -}; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HTTP2_CONSTANTS_H_
diff --git a/net/third_party/http2/http2_constants_test.cc b/net/third_party/http2/http2_constants_test.cc deleted file mode 100644 index d2a0f43b..0000000 --- a/net/third_party/http2/http2_constants_test.cc +++ /dev/null
@@ -1,271 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/http2_constants.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { -namespace { - -class Http2ConstantsTest : public testing::Test {}; - -TEST(Http2ConstantsTest, Http2FrameType) { - EXPECT_EQ(Http2FrameType::DATA, static_cast<Http2FrameType>(0)); - EXPECT_EQ(Http2FrameType::HEADERS, static_cast<Http2FrameType>(1)); - EXPECT_EQ(Http2FrameType::PRIORITY, static_cast<Http2FrameType>(2)); - EXPECT_EQ(Http2FrameType::RST_STREAM, static_cast<Http2FrameType>(3)); - EXPECT_EQ(Http2FrameType::SETTINGS, static_cast<Http2FrameType>(4)); - EXPECT_EQ(Http2FrameType::PUSH_PROMISE, static_cast<Http2FrameType>(5)); - EXPECT_EQ(Http2FrameType::PING, static_cast<Http2FrameType>(6)); - EXPECT_EQ(Http2FrameType::GOAWAY, static_cast<Http2FrameType>(7)); - EXPECT_EQ(Http2FrameType::WINDOW_UPDATE, static_cast<Http2FrameType>(8)); - EXPECT_EQ(Http2FrameType::CONTINUATION, static_cast<Http2FrameType>(9)); - EXPECT_EQ(Http2FrameType::ALTSVC, static_cast<Http2FrameType>(10)); -} - -TEST(Http2ConstantsTest, Http2FrameTypeToString) { - EXPECT_EQ("DATA", Http2FrameTypeToString(Http2FrameType::DATA)); - EXPECT_EQ("HEADERS", Http2FrameTypeToString(Http2FrameType::HEADERS)); - EXPECT_EQ("PRIORITY", Http2FrameTypeToString(Http2FrameType::PRIORITY)); - EXPECT_EQ("RST_STREAM", Http2FrameTypeToString(Http2FrameType::RST_STREAM)); - EXPECT_EQ("SETTINGS", Http2FrameTypeToString(Http2FrameType::SETTINGS)); - EXPECT_EQ("PUSH_PROMISE", - Http2FrameTypeToString(Http2FrameType::PUSH_PROMISE)); - EXPECT_EQ("PING", Http2FrameTypeToString(Http2FrameType::PING)); - EXPECT_EQ("GOAWAY", Http2FrameTypeToString(Http2FrameType::GOAWAY)); - EXPECT_EQ("WINDOW_UPDATE", - Http2FrameTypeToString(Http2FrameType::WINDOW_UPDATE)); - EXPECT_EQ("CONTINUATION", - Http2FrameTypeToString(Http2FrameType::CONTINUATION)); - EXPECT_EQ("ALTSVC", Http2FrameTypeToString(Http2FrameType::ALTSVC)); - - EXPECT_EQ("DATA", Http2FrameTypeToString(0)); - EXPECT_EQ("HEADERS", Http2FrameTypeToString(1)); - EXPECT_EQ("PRIORITY", Http2FrameTypeToString(2)); - EXPECT_EQ("RST_STREAM", Http2FrameTypeToString(3)); - EXPECT_EQ("SETTINGS", Http2FrameTypeToString(4)); - EXPECT_EQ("PUSH_PROMISE", Http2FrameTypeToString(5)); - EXPECT_EQ("PING", Http2FrameTypeToString(6)); - EXPECT_EQ("GOAWAY", Http2FrameTypeToString(7)); - EXPECT_EQ("WINDOW_UPDATE", Http2FrameTypeToString(8)); - EXPECT_EQ("CONTINUATION", Http2FrameTypeToString(9)); - EXPECT_EQ("ALTSVC", Http2FrameTypeToString(10)); - - EXPECT_EQ("UnknownFrameType(99)", Http2FrameTypeToString(99)); -} - -TEST(Http2ConstantsTest, Http2FrameFlag) { - EXPECT_EQ(Http2FrameFlag::END_STREAM, static_cast<Http2FrameFlag>(0x01)); - EXPECT_EQ(Http2FrameFlag::ACK, static_cast<Http2FrameFlag>(0x01)); - EXPECT_EQ(Http2FrameFlag::END_HEADERS, static_cast<Http2FrameFlag>(0x04)); - EXPECT_EQ(Http2FrameFlag::PADDED, static_cast<Http2FrameFlag>(0x08)); - EXPECT_EQ(Http2FrameFlag::PRIORITY, static_cast<Http2FrameFlag>(0x20)); - - EXPECT_EQ(Http2FrameFlag::END_STREAM, 0x01); - EXPECT_EQ(Http2FrameFlag::ACK, 0x01); - EXPECT_EQ(Http2FrameFlag::END_HEADERS, 0x04); - EXPECT_EQ(Http2FrameFlag::PADDED, 0x08); - EXPECT_EQ(Http2FrameFlag::PRIORITY, 0x20); -} - -TEST(Http2ConstantsTest, Http2FrameFlagsToString) { - // Single flags... - - // 0b00000001 - EXPECT_EQ("END_STREAM", Http2FrameFlagsToString(Http2FrameType::DATA, - Http2FrameFlag::END_STREAM)); - EXPECT_EQ("END_STREAM", - Http2FrameFlagsToString(Http2FrameType::HEADERS, 0x01)); - EXPECT_EQ("ACK", Http2FrameFlagsToString(Http2FrameType::SETTINGS, - Http2FrameFlag::ACK)); - EXPECT_EQ("ACK", Http2FrameFlagsToString(Http2FrameType::PING, 0x01)); - - // 0b00000010 - EXPECT_EQ("0x02", Http2FrameFlagsToString(0xff, 0x02)); - - // 0b00000100 - EXPECT_EQ("END_HEADERS", - Http2FrameFlagsToString(Http2FrameType::HEADERS, - Http2FrameFlag::END_HEADERS)); - EXPECT_EQ("END_HEADERS", - Http2FrameFlagsToString(Http2FrameType::PUSH_PROMISE, 0x04)); - EXPECT_EQ("END_HEADERS", Http2FrameFlagsToString(0x09, 0x04)); - EXPECT_EQ("0x04", Http2FrameFlagsToString(0xff, 0x04)); - - // 0b00001000 - EXPECT_EQ("PADDED", Http2FrameFlagsToString(Http2FrameType::DATA, - Http2FrameFlag::PADDED)); - EXPECT_EQ("PADDED", Http2FrameFlagsToString(Http2FrameType::HEADERS, 0x08)); - EXPECT_EQ("PADDED", Http2FrameFlagsToString(0x05, 0x08)); - EXPECT_EQ("0x08", Http2FrameFlagsToString(0xff, Http2FrameFlag::PADDED)); - - // 0b00010000 - EXPECT_EQ("0x10", Http2FrameFlagsToString(Http2FrameType::SETTINGS, 0x10)); - - // 0b00100000 - EXPECT_EQ("PRIORITY", Http2FrameFlagsToString(Http2FrameType::HEADERS, 0x20)); - EXPECT_EQ("0x20", - Http2FrameFlagsToString(Http2FrameType::PUSH_PROMISE, 0x20)); - - // 0b01000000 - EXPECT_EQ("0x40", Http2FrameFlagsToString(0xff, 0x40)); - - // 0b10000000 - EXPECT_EQ("0x80", Http2FrameFlagsToString(0xff, 0x80)); - - // Combined flags... - - EXPECT_EQ("END_STREAM|PADDED|0xf6", - Http2FrameFlagsToString(Http2FrameType::DATA, 0xff)); - EXPECT_EQ("END_STREAM|END_HEADERS|PADDED|PRIORITY|0xd2", - Http2FrameFlagsToString(Http2FrameType::HEADERS, 0xff)); - EXPECT_EQ("0xff", Http2FrameFlagsToString(Http2FrameType::PRIORITY, 0xff)); - EXPECT_EQ("0xff", Http2FrameFlagsToString(Http2FrameType::RST_STREAM, 0xff)); - EXPECT_EQ("ACK|0xfe", - Http2FrameFlagsToString(Http2FrameType::SETTINGS, 0xff)); - EXPECT_EQ("END_HEADERS|PADDED|0xf3", - Http2FrameFlagsToString(Http2FrameType::PUSH_PROMISE, 0xff)); - EXPECT_EQ("ACK|0xfe", Http2FrameFlagsToString(Http2FrameType::PING, 0xff)); - EXPECT_EQ("0xff", Http2FrameFlagsToString(Http2FrameType::GOAWAY, 0xff)); - EXPECT_EQ("0xff", - Http2FrameFlagsToString(Http2FrameType::WINDOW_UPDATE, 0xff)); - EXPECT_EQ("END_HEADERS|0xfb", - Http2FrameFlagsToString(Http2FrameType::CONTINUATION, 0xff)); - EXPECT_EQ("0xff", Http2FrameFlagsToString(Http2FrameType::ALTSVC, 0xff)); - EXPECT_EQ("0xff", Http2FrameFlagsToString(0xff, 0xff)); -} - -TEST(Http2ConstantsTest, Http2ErrorCode) { - EXPECT_EQ(Http2ErrorCode::HTTP2_NO_ERROR, static_cast<Http2ErrorCode>(0x0)); - EXPECT_EQ(Http2ErrorCode::PROTOCOL_ERROR, static_cast<Http2ErrorCode>(0x1)); - EXPECT_EQ(Http2ErrorCode::INTERNAL_ERROR, static_cast<Http2ErrorCode>(0x2)); - EXPECT_EQ(Http2ErrorCode::FLOW_CONTROL_ERROR, - static_cast<Http2ErrorCode>(0x3)); - EXPECT_EQ(Http2ErrorCode::SETTINGS_TIMEOUT, static_cast<Http2ErrorCode>(0x4)); - EXPECT_EQ(Http2ErrorCode::STREAM_CLOSED, static_cast<Http2ErrorCode>(0x5)); - EXPECT_EQ(Http2ErrorCode::FRAME_SIZE_ERROR, static_cast<Http2ErrorCode>(0x6)); - EXPECT_EQ(Http2ErrorCode::REFUSED_STREAM, static_cast<Http2ErrorCode>(0x7)); - EXPECT_EQ(Http2ErrorCode::CANCEL, static_cast<Http2ErrorCode>(0x8)); - EXPECT_EQ(Http2ErrorCode::COMPRESSION_ERROR, - static_cast<Http2ErrorCode>(0x9)); - EXPECT_EQ(Http2ErrorCode::CONNECT_ERROR, static_cast<Http2ErrorCode>(0xa)); - EXPECT_EQ(Http2ErrorCode::ENHANCE_YOUR_CALM, - static_cast<Http2ErrorCode>(0xb)); - EXPECT_EQ(Http2ErrorCode::INADEQUATE_SECURITY, - static_cast<Http2ErrorCode>(0xc)); - EXPECT_EQ(Http2ErrorCode::HTTP_1_1_REQUIRED, - static_cast<Http2ErrorCode>(0xd)); -} - -TEST(Http2ConstantsTest, Http2ErrorCodeToString) { - EXPECT_EQ("NO_ERROR", Http2ErrorCodeToString(Http2ErrorCode::HTTP2_NO_ERROR)); - EXPECT_EQ("NO_ERROR", Http2ErrorCodeToString(0x0)); - EXPECT_EQ("PROTOCOL_ERROR", - Http2ErrorCodeToString(Http2ErrorCode::PROTOCOL_ERROR)); - EXPECT_EQ("PROTOCOL_ERROR", Http2ErrorCodeToString(0x1)); - EXPECT_EQ("INTERNAL_ERROR", - Http2ErrorCodeToString(Http2ErrorCode::INTERNAL_ERROR)); - EXPECT_EQ("INTERNAL_ERROR", Http2ErrorCodeToString(0x2)); - EXPECT_EQ("FLOW_CONTROL_ERROR", - Http2ErrorCodeToString(Http2ErrorCode::FLOW_CONTROL_ERROR)); - EXPECT_EQ("FLOW_CONTROL_ERROR", Http2ErrorCodeToString(0x3)); - EXPECT_EQ("SETTINGS_TIMEOUT", - Http2ErrorCodeToString(Http2ErrorCode::SETTINGS_TIMEOUT)); - EXPECT_EQ("SETTINGS_TIMEOUT", Http2ErrorCodeToString(0x4)); - EXPECT_EQ("STREAM_CLOSED", - Http2ErrorCodeToString(Http2ErrorCode::STREAM_CLOSED)); - EXPECT_EQ("STREAM_CLOSED", Http2ErrorCodeToString(0x5)); - EXPECT_EQ("FRAME_SIZE_ERROR", - Http2ErrorCodeToString(Http2ErrorCode::FRAME_SIZE_ERROR)); - EXPECT_EQ("FRAME_SIZE_ERROR", Http2ErrorCodeToString(0x6)); - EXPECT_EQ("REFUSED_STREAM", - Http2ErrorCodeToString(Http2ErrorCode::REFUSED_STREAM)); - EXPECT_EQ("REFUSED_STREAM", Http2ErrorCodeToString(0x7)); - EXPECT_EQ("CANCEL", Http2ErrorCodeToString(Http2ErrorCode::CANCEL)); - EXPECT_EQ("CANCEL", Http2ErrorCodeToString(0x8)); - EXPECT_EQ("COMPRESSION_ERROR", - Http2ErrorCodeToString(Http2ErrorCode::COMPRESSION_ERROR)); - EXPECT_EQ("COMPRESSION_ERROR", Http2ErrorCodeToString(0x9)); - EXPECT_EQ("CONNECT_ERROR", - Http2ErrorCodeToString(Http2ErrorCode::CONNECT_ERROR)); - EXPECT_EQ("CONNECT_ERROR", Http2ErrorCodeToString(0xa)); - EXPECT_EQ("ENHANCE_YOUR_CALM", - Http2ErrorCodeToString(Http2ErrorCode::ENHANCE_YOUR_CALM)); - EXPECT_EQ("ENHANCE_YOUR_CALM", Http2ErrorCodeToString(0xb)); - EXPECT_EQ("INADEQUATE_SECURITY", - Http2ErrorCodeToString(Http2ErrorCode::INADEQUATE_SECURITY)); - EXPECT_EQ("INADEQUATE_SECURITY", Http2ErrorCodeToString(0xc)); - EXPECT_EQ("HTTP_1_1_REQUIRED", - Http2ErrorCodeToString(Http2ErrorCode::HTTP_1_1_REQUIRED)); - EXPECT_EQ("HTTP_1_1_REQUIRED", Http2ErrorCodeToString(0xd)); - - EXPECT_EQ("UnknownErrorCode(0x123)", Http2ErrorCodeToString(0x123)); -} - -TEST(Http2ConstantsTest, Http2SettingsParameter) { - EXPECT_EQ(Http2SettingsParameter::HEADER_TABLE_SIZE, - static_cast<Http2SettingsParameter>(0x1)); - EXPECT_EQ(Http2SettingsParameter::ENABLE_PUSH, - static_cast<Http2SettingsParameter>(0x2)); - EXPECT_EQ(Http2SettingsParameter::MAX_CONCURRENT_STREAMS, - static_cast<Http2SettingsParameter>(0x3)); - EXPECT_EQ(Http2SettingsParameter::INITIAL_WINDOW_SIZE, - static_cast<Http2SettingsParameter>(0x4)); - EXPECT_EQ(Http2SettingsParameter::MAX_FRAME_SIZE, - static_cast<Http2SettingsParameter>(0x5)); - EXPECT_EQ(Http2SettingsParameter::MAX_HEADER_LIST_SIZE, - static_cast<Http2SettingsParameter>(0x6)); - - EXPECT_TRUE(IsSupportedHttp2SettingsParameter( - Http2SettingsParameter::HEADER_TABLE_SIZE)); - EXPECT_TRUE( - IsSupportedHttp2SettingsParameter(Http2SettingsParameter::ENABLE_PUSH)); - EXPECT_TRUE(IsSupportedHttp2SettingsParameter( - Http2SettingsParameter::MAX_CONCURRENT_STREAMS)); - EXPECT_TRUE(IsSupportedHttp2SettingsParameter( - Http2SettingsParameter::INITIAL_WINDOW_SIZE)); - EXPECT_TRUE(IsSupportedHttp2SettingsParameter( - Http2SettingsParameter::MAX_FRAME_SIZE)); - EXPECT_TRUE(IsSupportedHttp2SettingsParameter( - Http2SettingsParameter::MAX_HEADER_LIST_SIZE)); - - EXPECT_FALSE(IsSupportedHttp2SettingsParameter( - static_cast<Http2SettingsParameter>(0))); - EXPECT_FALSE(IsSupportedHttp2SettingsParameter( - static_cast<Http2SettingsParameter>(7))); -} - -TEST(Http2ConstantsTest, Http2SettingsParameterToString) { - EXPECT_EQ("HEADER_TABLE_SIZE", - Http2SettingsParameterToString( - Http2SettingsParameter::HEADER_TABLE_SIZE)); - EXPECT_EQ("HEADER_TABLE_SIZE", Http2SettingsParameterToString(0x1)); - EXPECT_EQ("ENABLE_PUSH", Http2SettingsParameterToString( - Http2SettingsParameter::ENABLE_PUSH)); - EXPECT_EQ("ENABLE_PUSH", Http2SettingsParameterToString(0x2)); - EXPECT_EQ("MAX_CONCURRENT_STREAMS", - Http2SettingsParameterToString( - Http2SettingsParameter::MAX_CONCURRENT_STREAMS)); - EXPECT_EQ("MAX_CONCURRENT_STREAMS", Http2SettingsParameterToString(0x3)); - EXPECT_EQ("INITIAL_WINDOW_SIZE", - Http2SettingsParameterToString( - Http2SettingsParameter::INITIAL_WINDOW_SIZE)); - EXPECT_EQ("INITIAL_WINDOW_SIZE", Http2SettingsParameterToString(0x4)); - EXPECT_EQ("MAX_FRAME_SIZE", Http2SettingsParameterToString( - Http2SettingsParameter::MAX_FRAME_SIZE)); - EXPECT_EQ("MAX_FRAME_SIZE", Http2SettingsParameterToString(0x5)); - EXPECT_EQ("MAX_HEADER_LIST_SIZE", - Http2SettingsParameterToString( - Http2SettingsParameter::MAX_HEADER_LIST_SIZE)); - EXPECT_EQ("MAX_HEADER_LIST_SIZE", Http2SettingsParameterToString(0x6)); - - EXPECT_EQ("UnknownSettingsParameter(0x123)", - Http2SettingsParameterToString(0x123)); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/http2_constants_test_util.cc b/net/third_party/http2/http2_constants_test_util.cc deleted file mode 100644 index 340817c..0000000 --- a/net/third_party/http2/http2_constants_test_util.cc +++ /dev/null
@@ -1,84 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/http2_constants_test_util.h" - -namespace http2 { -namespace test { - -std::vector<Http2ErrorCode> AllHttp2ErrorCodes() { - // clang-format off - return { - Http2ErrorCode::HTTP2_NO_ERROR, - Http2ErrorCode::PROTOCOL_ERROR, - Http2ErrorCode::INTERNAL_ERROR, - Http2ErrorCode::FLOW_CONTROL_ERROR, - Http2ErrorCode::SETTINGS_TIMEOUT, - Http2ErrorCode::STREAM_CLOSED, - Http2ErrorCode::FRAME_SIZE_ERROR, - Http2ErrorCode::REFUSED_STREAM, - Http2ErrorCode::CANCEL, - Http2ErrorCode::COMPRESSION_ERROR, - Http2ErrorCode::CONNECT_ERROR, - Http2ErrorCode::ENHANCE_YOUR_CALM, - Http2ErrorCode::INADEQUATE_SECURITY, - Http2ErrorCode::HTTP_1_1_REQUIRED, - }; - // clang-format on -} - -std::vector<Http2SettingsParameter> AllHttp2SettingsParameters() { - // clang-format off - return { - Http2SettingsParameter::HEADER_TABLE_SIZE, - Http2SettingsParameter::ENABLE_PUSH, - Http2SettingsParameter::MAX_CONCURRENT_STREAMS, - Http2SettingsParameter::INITIAL_WINDOW_SIZE, - Http2SettingsParameter::MAX_FRAME_SIZE, - Http2SettingsParameter::MAX_HEADER_LIST_SIZE, - }; - // clang-format on -} - -// Returns a mask of flags supported for the specified frame type. Returns -// zero for unknown frame types. -uint8_t KnownFlagsMaskForFrameType(Http2FrameType type) { - switch (type) { - case Http2FrameType::DATA: - return Http2FrameFlag::END_STREAM | Http2FrameFlag::PADDED; - case Http2FrameType::HEADERS: - return Http2FrameFlag::END_STREAM | Http2FrameFlag::END_HEADERS | - Http2FrameFlag::PADDED | Http2FrameFlag::PRIORITY; - case Http2FrameType::PRIORITY: - return 0x00; - case Http2FrameType::RST_STREAM: - return 0x00; - case Http2FrameType::SETTINGS: - return Http2FrameFlag::ACK; - case Http2FrameType::PUSH_PROMISE: - return Http2FrameFlag::END_HEADERS | Http2FrameFlag::PADDED; - case Http2FrameType::PING: - return Http2FrameFlag::ACK; - case Http2FrameType::GOAWAY: - return 0x00; - case Http2FrameType::WINDOW_UPDATE: - return 0x00; - case Http2FrameType::CONTINUATION: - return Http2FrameFlag::END_HEADERS; - case Http2FrameType::ALTSVC: - return 0x00; - default: - return 0x00; - } -} - -uint8_t InvalidFlagMaskForFrameType(Http2FrameType type) { - if (IsSupportedHttp2FrameType(type)) { - return ~KnownFlagsMaskForFrameType(type); - } - return 0x00; -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/http2_constants_test_util.h b/net/third_party/http2/http2_constants_test_util.h deleted file mode 100644 index 5f88110..0000000 --- a/net/third_party/http2/http2_constants_test_util.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HTTP2_CONSTANTS_TEST_UTIL_H_ -#define NET_THIRD_PARTY_HTTP2_HTTP2_CONSTANTS_TEST_UTIL_H_ - -#include <cstdint> -#include <vector> - -#include "net/third_party/http2/http2_constants.h" - -namespace http2 { -namespace test { - -// Returns a vector of all supported RST_STREAM and GOAWAY error codes. -std::vector<Http2ErrorCode> AllHttp2ErrorCodes(); - -// Returns a vector of all supported parameters in SETTINGS frames. -std::vector<Http2SettingsParameter> AllHttp2SettingsParameters(); - -// Returns a mask of flags supported for the specified frame type. Returns -// zero for unknown frame types. -uint8_t KnownFlagsMaskForFrameType(Http2FrameType type); - -// Returns a mask of flag bits known to be invalid for the frame type. -// For unknown frame types, the mask is zero; i.e., we don't know that any -// are invalid. -uint8_t InvalidFlagMaskForFrameType(Http2FrameType type); - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HTTP2_CONSTANTS_TEST_UTIL_H_
diff --git a/net/third_party/http2/http2_structures.cc b/net/third_party/http2/http2_structures.cc deleted file mode 100644 index 5465ce2..0000000 --- a/net/third_party/http2/http2_structures.cc +++ /dev/null
@@ -1,132 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/http2_structures.h" - -#include <cstring> // For std::memcmp -#include <sstream> - -#include "net/third_party/http2/platform/api/http2_string_utils.h" - -namespace http2 { - -// Http2FrameHeader: - -bool Http2FrameHeader::IsProbableHttpResponse() const { - return (payload_length == 0x485454 && // "HTT" - static_cast<char>(type) == 'P' && // "P" - flags == '/'); // "/" -} - -Http2String Http2FrameHeader::ToString() const { - return Http2StrCat("length=", payload_length, - ", type=", Http2FrameTypeToString(type), - ", flags=", FlagsToString(), ", stream=", stream_id); -} - -Http2String Http2FrameHeader::FlagsToString() const { - return Http2FrameFlagsToString(type, flags); -} - -bool operator==(const Http2FrameHeader& a, const Http2FrameHeader& b) { - return a.payload_length == b.payload_length && a.stream_id == b.stream_id && - a.type == b.type && a.flags == b.flags; -} - -std::ostream& operator<<(std::ostream& out, const Http2FrameHeader& v) { - return out << v.ToString(); -} - -// Http2PriorityFields: - -bool operator==(const Http2PriorityFields& a, const Http2PriorityFields& b) { - return a.stream_dependency == b.stream_dependency && a.weight == b.weight; -} - -Http2String Http2PriorityFields::ToString() const { - std::stringstream ss; - ss << "E=" << (is_exclusive ? "true" : "false") - << ", stream=" << stream_dependency - << ", weight=" << static_cast<uint32_t>(weight); - return ss.str(); -} - -std::ostream& operator<<(std::ostream& out, const Http2PriorityFields& v) { - return out << v.ToString(); -} - -// Http2RstStreamFields: - -bool operator==(const Http2RstStreamFields& a, const Http2RstStreamFields& b) { - return a.error_code == b.error_code; -} - -std::ostream& operator<<(std::ostream& out, const Http2RstStreamFields& v) { - return out << "error_code=" << v.error_code; -} - -// Http2SettingFields: - -bool operator==(const Http2SettingFields& a, const Http2SettingFields& b) { - return a.parameter == b.parameter && a.value == b.value; -} -std::ostream& operator<<(std::ostream& out, const Http2SettingFields& v) { - return out << "parameter=" << v.parameter << ", value=" << v.value; -} - -// Http2PushPromiseFields: - -bool operator==(const Http2PushPromiseFields& a, - const Http2PushPromiseFields& b) { - return a.promised_stream_id == b.promised_stream_id; -} - -std::ostream& operator<<(std::ostream& out, const Http2PushPromiseFields& v) { - return out << "promised_stream_id=" << v.promised_stream_id; -} - -// Http2PingFields: - -bool operator==(const Http2PingFields& a, const Http2PingFields& b) { - static_assert((sizeof a.opaque_bytes) == Http2PingFields::EncodedSize(), - "Why not the same size?"); - return 0 == - std::memcmp(a.opaque_bytes, b.opaque_bytes, sizeof a.opaque_bytes); -} - -std::ostream& operator<<(std::ostream& out, const Http2PingFields& v) { - return out << "opaque_bytes=0x" - << Http2HexEncode(v.opaque_bytes, sizeof v.opaque_bytes); -} - -// Http2GoAwayFields: - -bool operator==(const Http2GoAwayFields& a, const Http2GoAwayFields& b) { - return a.last_stream_id == b.last_stream_id && a.error_code == b.error_code; -} -std::ostream& operator<<(std::ostream& out, const Http2GoAwayFields& v) { - return out << "last_stream_id=" << v.last_stream_id - << ", error_code=" << v.error_code; -} - -// Http2WindowUpdateFields: - -bool operator==(const Http2WindowUpdateFields& a, - const Http2WindowUpdateFields& b) { - return a.window_size_increment == b.window_size_increment; -} -std::ostream& operator<<(std::ostream& out, const Http2WindowUpdateFields& v) { - return out << "window_size_increment=" << v.window_size_increment; -} - -// Http2AltSvcFields: - -bool operator==(const Http2AltSvcFields& a, const Http2AltSvcFields& b) { - return a.origin_length == b.origin_length; -} -std::ostream& operator<<(std::ostream& out, const Http2AltSvcFields& v) { - return out << "origin_length=" << v.origin_length; -} - -} // namespace http2
diff --git a/net/third_party/http2/http2_structures.h b/net/third_party/http2/http2_structures.h deleted file mode 100644 index ef7613a..0000000 --- a/net/third_party/http2/http2_structures.h +++ /dev/null
@@ -1,325 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HTTP2_STRUCTURES_H_ -#define NET_THIRD_PARTY_HTTP2_HTTP2_STRUCTURES_H_ - -// Defines structs for various fixed sized structures in HTTP/2. -// -// Those structs with multiple fields have constructors that take arguments in -// the same order as their encoding (which may be different from their order -// in the struct). For single field structs, use aggregate initialization if -// desired, e.g.: -// -// Http2RstStreamFields var{Http2ErrorCode::ENHANCE_YOUR_CALM}; -// or: -// SomeFunc(Http2RstStreamFields{Http2ErrorCode::ENHANCE_YOUR_CALM}); -// -// Each struct includes a static method EncodedSize which returns the number -// of bytes of the encoding. -// -// With the exception of Http2FrameHeader, all the types are named -// Http2<X>Fields, where X is the title-case form of the frame which always -// includes the fields; the "always" is to cover the case of the PRIORITY frame; -// its fields optionally appear in the HEADERS frame, but the struct is called -// Http2PriorityFields. - -#include <stddef.h> - -#include <cstdint> -#include <ostream> - -#include "base/logging.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string.h" - -namespace http2 { - -struct HTTP2_EXPORT_PRIVATE Http2FrameHeader { - Http2FrameHeader() {} - Http2FrameHeader(uint32_t payload_length, - Http2FrameType type, - uint8_t flags, - uint32_t stream_id) - : payload_length(payload_length), - stream_id(stream_id), - type(type), - flags(static_cast<Http2FrameFlag>(flags)) { - DCHECK_LT(payload_length, static_cast<uint32_t>(1 << 24)) - << "Payload Length is only a 24 bit field\n" - << ToString(); - } - - static constexpr size_t EncodedSize() { return 9; } - - // Keep the current value of those flags that are in - // valid_flags, and clear all the others. - void RetainFlags(uint8_t valid_flags) { - flags = static_cast<Http2FrameFlag>(flags & valid_flags); - } - - // Returns true if any of the flags in flag_mask are set, - // otherwise false. - bool HasAnyFlags(uint8_t flag_mask) const { return 0 != (flags & flag_mask); } - - // Is the END_STREAM flag set? - bool IsEndStream() const { - DCHECK(type == Http2FrameType::DATA || type == Http2FrameType::HEADERS) - << ToString(); - return (flags & Http2FrameFlag::END_STREAM) != 0; - } - - // Is the ACK flag set? - bool IsAck() const { - DCHECK(type == Http2FrameType::SETTINGS || type == Http2FrameType::PING) - << ToString(); - return (flags & Http2FrameFlag::ACK) != 0; - } - - // Is the END_HEADERS flag set? - bool IsEndHeaders() const { - DCHECK(type == Http2FrameType::HEADERS || - type == Http2FrameType::PUSH_PROMISE || - type == Http2FrameType::CONTINUATION) - << ToString(); - return (flags & Http2FrameFlag::END_HEADERS) != 0; - } - - // Is the PADDED flag set? - bool IsPadded() const { - DCHECK(type == Http2FrameType::DATA || type == Http2FrameType::HEADERS || - type == Http2FrameType::PUSH_PROMISE) - << ToString(); - return (flags & Http2FrameFlag::PADDED) != 0; - } - - // Is the PRIORITY flag set? - bool HasPriority() const { - DCHECK_EQ(type, Http2FrameType::HEADERS) << ToString(); - return (flags & Http2FrameFlag::PRIORITY) != 0; - } - - // Does the encoding of this header start with "HTTP/", indicating that it - // might be from a non-HTTP/2 server. - bool IsProbableHttpResponse() const; - - // Produce strings useful for debugging/logging messages. - Http2String ToString() const; - Http2String FlagsToString() const; - - // 24 bit length of the payload after the header, including any padding. - // First field in encoding. - uint32_t payload_length; // 24 bits - - // 31 bit stream id, with high bit (32nd bit) reserved (must be zero), - // and is cleared during decoding. - // Fourth field in encoding. - uint32_t stream_id; - - // Type of the frame. - // Second field in encoding. - Http2FrameType type; - - // Flag bits, with interpretations that depend upon the frame type. - // Flag bits not used by the frame type are cleared. - // Third field in encoding. - Http2FrameFlag flags; -}; - -HTTP2_EXPORT_PRIVATE bool operator==(const Http2FrameHeader& a, - const Http2FrameHeader& b); -HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2FrameHeader& a, - const Http2FrameHeader& b) { - return !(a == b); -} -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const Http2FrameHeader& v); - -// Http2PriorityFields: - -struct HTTP2_EXPORT_PRIVATE Http2PriorityFields { - Http2PriorityFields() {} - Http2PriorityFields(uint32_t stream_dependency, - uint32_t weight, - bool is_exclusive) - : stream_dependency(stream_dependency), - weight(weight), - is_exclusive(is_exclusive) { - // Can't have the high-bit set in the stream id because we need to use - // that for the EXCLUSIVE flag bit. - DCHECK_EQ(stream_dependency, stream_dependency & StreamIdMask()) - << "Stream Dependency is only a 31-bit field.\n" - << ToString(); - DCHECK_LE(1u, weight) << "Weight is too small."; - DCHECK_LE(weight, 256u) << "Weight is too large."; - } - static constexpr size_t EncodedSize() { return 5; } - - // Produce strings useful for debugging/logging messages. - Http2String ToString() const; - - // A 31-bit stream identifier for the stream that this stream depends on. - uint32_t stream_dependency; - - // Weight (1 to 256) is encoded as a byte in the range 0 to 255, so we - // add one when decoding, and store it in a field larger than a byte. - uint32_t weight; - - // A single-bit flag indicating that the stream dependency is exclusive; - // extracted from high bit of stream dependency field during decoding. - bool is_exclusive; -}; - -HTTP2_EXPORT_PRIVATE bool operator==(const Http2PriorityFields& a, - const Http2PriorityFields& b); -HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2PriorityFields& a, - const Http2PriorityFields& b) { - return !(a == b); -} -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const Http2PriorityFields& v); - -// Http2RstStreamFields: - -struct Http2RstStreamFields { - static constexpr size_t EncodedSize() { return 4; } - bool IsSupportedErrorCode() const { - return IsSupportedHttp2ErrorCode(error_code); - } - - Http2ErrorCode error_code; -}; - -HTTP2_EXPORT_PRIVATE bool operator==(const Http2RstStreamFields& a, - const Http2RstStreamFields& b); -HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2RstStreamFields& a, - const Http2RstStreamFields& b) { - return !(a == b); -} -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const Http2RstStreamFields& v); - -// Http2SettingFields: - -struct Http2SettingFields { - Http2SettingFields() {} - Http2SettingFields(Http2SettingsParameter parameter, uint32_t value) - : parameter(parameter), value(value) {} - static constexpr size_t EncodedSize() { return 6; } - bool IsSupportedParameter() const { - return IsSupportedHttp2SettingsParameter(parameter); - } - - Http2SettingsParameter parameter; - uint32_t value; -}; - -HTTP2_EXPORT_PRIVATE bool operator==(const Http2SettingFields& a, - const Http2SettingFields& b); -HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2SettingFields& a, - const Http2SettingFields& b) { - return !(a == b); -} -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const Http2SettingFields& v); - -// Http2PushPromiseFields: - -struct Http2PushPromiseFields { - static constexpr size_t EncodedSize() { return 4; } - - uint32_t promised_stream_id; -}; - -HTTP2_EXPORT_PRIVATE bool operator==(const Http2PushPromiseFields& a, - const Http2PushPromiseFields& b); -HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2PushPromiseFields& a, - const Http2PushPromiseFields& b) { - return !(a == b); -} -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const Http2PushPromiseFields& v); - -// Http2PingFields: - -struct Http2PingFields { - static constexpr size_t EncodedSize() { return 8; } - - uint8_t opaque_bytes[8]; -}; - -HTTP2_EXPORT_PRIVATE bool operator==(const Http2PingFields& a, - const Http2PingFields& b); -HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2PingFields& a, - const Http2PingFields& b) { - return !(a == b); -} -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const Http2PingFields& v); - -// Http2GoAwayFields: - -struct Http2GoAwayFields { - Http2GoAwayFields() {} - Http2GoAwayFields(uint32_t last_stream_id, Http2ErrorCode error_code) - : last_stream_id(last_stream_id), error_code(error_code) {} - static constexpr size_t EncodedSize() { return 8; } - bool IsSupportedErrorCode() const { - return IsSupportedHttp2ErrorCode(error_code); - } - - uint32_t last_stream_id; - Http2ErrorCode error_code; -}; - -HTTP2_EXPORT_PRIVATE bool operator==(const Http2GoAwayFields& a, - const Http2GoAwayFields& b); -HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2GoAwayFields& a, - const Http2GoAwayFields& b) { - return !(a == b); -} -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const Http2GoAwayFields& v); - -// Http2WindowUpdateFields: - -struct Http2WindowUpdateFields { - static constexpr size_t EncodedSize() { return 4; } - - // 31-bit, unsigned increase in the window size (only positive values are - // allowed). The high-bit is reserved for the future. - uint32_t window_size_increment; -}; - -HTTP2_EXPORT_PRIVATE bool operator==(const Http2WindowUpdateFields& a, - const Http2WindowUpdateFields& b); -HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2WindowUpdateFields& a, - const Http2WindowUpdateFields& b) { - return !(a == b); -} -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const Http2WindowUpdateFields& v); - -// Http2AltSvcFields: - -struct Http2AltSvcFields { - static constexpr size_t EncodedSize() { return 2; } - - // This is the one fixed size portion of the ALTSVC payload. - uint16_t origin_length; -}; - -HTTP2_EXPORT_PRIVATE bool operator==(const Http2AltSvcFields& a, - const Http2AltSvcFields& b); -HTTP2_EXPORT_PRIVATE inline bool operator!=(const Http2AltSvcFields& a, - const Http2AltSvcFields& b) { - return !(a == b); -} -HTTP2_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out, - const Http2AltSvcFields& v); - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HTTP2_STRUCTURES_H_
diff --git a/net/third_party/http2/http2_structures_test.cc b/net/third_party/http2/http2_structures_test.cc deleted file mode 100644 index a5263622..0000000 --- a/net/third_party/http2/http2_structures_test.cc +++ /dev/null
@@ -1,537 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/http2_structures.h" - -// Tests are focused on Http2FrameHeader because it has by far the most -// methods of any of the structures. -// Note that EXPECT.*DEATH tests are slow (a fork is probably involved). - -// And in case you're wondering, yes, these are ridiculously thorough tests, -// but believe it or not, I've found stupid bugs this way. - -#include <memory> -#include <ostream> -#include <sstream> -#include <tuple> -#include <type_traits> -#include <vector> - -#include "net/third_party/http2/http2_structures_test_util.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; -using ::testing::Combine; -using ::testing::HasSubstr; -using ::testing::MatchesRegex; -using ::testing::Not; -using ::testing::Values; -using ::testing::ValuesIn; - -namespace http2 { -namespace test { -namespace { - -template <typename E> -E IncrementEnum(E e) { - using I = typename std::underlying_type<E>::type; - return static_cast<E>(1 + static_cast<I>(e)); -} - -template <class T> -AssertionResult VerifyRandomCalls() { - T t1; - Http2Random seq1; - Randomize(&t1, &seq1); - - T t2; - Http2Random seq2(seq1.Key()); - Randomize(&t2, &seq2); - - // The two Randomize calls should have made the same number of calls into - // the Http2Random implementations. - VERIFY_EQ(seq1.Rand64(), seq2.Rand64()); - - // And because Http2Random implementation is returning the same sequence, and - // Randomize should have been consistent in applying those results, the two - // Ts should have the same value. - VERIFY_EQ(t1, t2); - - Randomize(&t2, &seq2); - VERIFY_NE(t1, t2); - - Randomize(&t1, &seq1); - VERIFY_EQ(t1, t2); - - VERIFY_EQ(seq1.Rand64(), seq2.Rand64()); - - return AssertionSuccess(); -} - -#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) -std::vector<Http2FrameType> ValidFrameTypes() { - std::vector<Http2FrameType> valid_types{Http2FrameType::DATA}; - while (valid_types.back() != Http2FrameType::ALTSVC) { - valid_types.push_back(IncrementEnum(valid_types.back())); - } - return valid_types; -} -#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) - -TEST(Http2FrameHeaderTest, Constructor) { - Http2Random random; - uint8_t frame_type = 0; - do { - // Only the payload length is DCHECK'd in the constructor, so we need to - // make sure it is a "uint24". - uint32_t payload_length = random.Rand32() & 0xffffff; - Http2FrameType type = static_cast<Http2FrameType>(frame_type); - uint8_t flags = random.Rand8(); - uint32_t stream_id = random.Rand32(); - - Http2FrameHeader v(payload_length, type, flags, stream_id); - - EXPECT_EQ(payload_length, v.payload_length); - EXPECT_EQ(type, v.type); - EXPECT_EQ(flags, v.flags); - EXPECT_EQ(stream_id, v.stream_id); - } while (frame_type++ == 255); - -#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) - EXPECT_DEBUG_DEATH(Http2FrameHeader(0x01000000, Http2FrameType::DATA, 0, 1), - "payload_length"); -#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) -} - -TEST(Http2FrameHeaderTest, Eq) { - Http2Random random; - uint32_t payload_length = random.Rand32() & 0xffffff; - Http2FrameType type = static_cast<Http2FrameType>(random.Rand8()); - - uint8_t flags = random.Rand8(); - uint32_t stream_id = random.Rand32(); - - Http2FrameHeader v(payload_length, type, flags, stream_id); - - EXPECT_EQ(payload_length, v.payload_length); - EXPECT_EQ(type, v.type); - EXPECT_EQ(flags, v.flags); - EXPECT_EQ(stream_id, v.stream_id); - - Http2FrameHeader u(0, type, ~flags, stream_id); - - EXPECT_NE(u, v); - EXPECT_NE(v, u); - EXPECT_FALSE(u == v); - EXPECT_FALSE(v == u); - EXPECT_TRUE(u != v); - EXPECT_TRUE(v != u); - - u = v; - - EXPECT_EQ(u, v); - EXPECT_EQ(v, u); - EXPECT_TRUE(u == v); - EXPECT_TRUE(v == u); - EXPECT_FALSE(u != v); - EXPECT_FALSE(v != u); - - EXPECT_TRUE(VerifyRandomCalls<Http2FrameHeader>()); -} - -#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) -// The tests of the valid frame types include EXPECT_DEBUG_DEATH, which is -// quite slow, so using value parameterized tests in order to allow sharding. -class Http2FrameHeaderTypeAndFlagTest - : public ::testing::TestWithParam< - std::tuple<Http2FrameType, Http2FrameFlag>> { - protected: - Http2FrameHeaderTypeAndFlagTest() - : type_(std::get<0>(GetParam())), flags_(std::get<1>(GetParam())) { - LOG(INFO) << "Frame type: " << type_; - LOG(INFO) << "Frame flags: " << Http2FrameFlagsToString(type_, flags_); - } - - const Http2FrameType type_; - const Http2FrameFlag flags_; -}; - -class IsEndStreamTest : public Http2FrameHeaderTypeAndFlagTest {}; -INSTANTIATE_TEST_CASE_P(IsEndStream, - IsEndStreamTest, - Combine(ValuesIn(ValidFrameTypes()), - Values(~Http2FrameFlag::END_STREAM, 0xff))); -TEST_P(IsEndStreamTest, IsEndStream) { - const bool is_set = - (flags_ & Http2FrameFlag::END_STREAM) == Http2FrameFlag::END_STREAM; - Http2String flags_string; - Http2FrameHeader v(0, type_, flags_, 0); - switch (type_) { - case Http2FrameType::DATA: - case Http2FrameType::HEADERS: - EXPECT_EQ(is_set, v.IsEndStream()) << v; - flags_string = v.FlagsToString(); - if (is_set) { - EXPECT_THAT(flags_string, MatchesRegex(".*\\|?END_STREAM\\|.*")); - } else { - EXPECT_THAT(flags_string, Not(HasSubstr("END_STREAM"))); - } - v.RetainFlags(Http2FrameFlag::END_STREAM); - EXPECT_EQ(is_set, v.IsEndStream()) << v; - { - std::stringstream s; - s << v; - EXPECT_EQ(v.ToString(), s.str()); - if (is_set) { - EXPECT_THAT(s.str(), HasSubstr("flags=END_STREAM,")); - } else { - EXPECT_THAT(s.str(), HasSubstr("flags=,")); - } - } - break; - default: - EXPECT_DEBUG_DEATH(v.IsEndStream(), "DATA.*HEADERS") << v; - } -} - -class IsACKTest : public Http2FrameHeaderTypeAndFlagTest {}; -INSTANTIATE_TEST_CASE_P(IsAck, - IsACKTest, - Combine(ValuesIn(ValidFrameTypes()), - Values(~Http2FrameFlag::ACK, 0xff))); -TEST_P(IsACKTest, IsAck) { - const bool is_set = (flags_ & Http2FrameFlag::ACK) == Http2FrameFlag::ACK; - Http2String flags_string; - Http2FrameHeader v(0, type_, flags_, 0); - switch (type_) { - case Http2FrameType::SETTINGS: - case Http2FrameType::PING: - EXPECT_EQ(is_set, v.IsAck()) << v; - flags_string = v.FlagsToString(); - if (is_set) { - EXPECT_THAT(flags_string, MatchesRegex(".*\\|?ACK\\|.*")); - } else { - EXPECT_THAT(flags_string, Not(HasSubstr("ACK"))); - } - v.RetainFlags(Http2FrameFlag::ACK); - EXPECT_EQ(is_set, v.IsAck()) << v; - { - std::stringstream s; - s << v; - EXPECT_EQ(v.ToString(), s.str()); - if (is_set) { - EXPECT_THAT(s.str(), HasSubstr("flags=ACK,")); - } else { - EXPECT_THAT(s.str(), HasSubstr("flags=,")); - } - } - break; - default: - EXPECT_DEBUG_DEATH(v.IsAck(), "SETTINGS.*PING") << v; - } -} - -class IsEndHeadersTest : public Http2FrameHeaderTypeAndFlagTest {}; -INSTANTIATE_TEST_CASE_P(IsEndHeaders, - IsEndHeadersTest, - Combine(ValuesIn(ValidFrameTypes()), - Values(~Http2FrameFlag::END_HEADERS, 0xff))); -TEST_P(IsEndHeadersTest, IsEndHeaders) { - const bool is_set = - (flags_ & Http2FrameFlag::END_HEADERS) == Http2FrameFlag::END_HEADERS; - Http2String flags_string; - Http2FrameHeader v(0, type_, flags_, 0); - switch (type_) { - case Http2FrameType::HEADERS: - case Http2FrameType::PUSH_PROMISE: - case Http2FrameType::CONTINUATION: - EXPECT_EQ(is_set, v.IsEndHeaders()) << v; - flags_string = v.FlagsToString(); - if (is_set) { - EXPECT_THAT(flags_string, MatchesRegex(".*\\|?END_HEADERS\\|.*")); - } else { - EXPECT_THAT(flags_string, Not(HasSubstr("END_HEADERS"))); - } - v.RetainFlags(Http2FrameFlag::END_HEADERS); - EXPECT_EQ(is_set, v.IsEndHeaders()) << v; - { - std::stringstream s; - s << v; - EXPECT_EQ(v.ToString(), s.str()); - if (is_set) { - EXPECT_THAT(s.str(), HasSubstr("flags=END_HEADERS,")); - } else { - EXPECT_THAT(s.str(), HasSubstr("flags=,")); - } - } - break; - default: - EXPECT_DEBUG_DEATH(v.IsEndHeaders(), - "HEADERS.*PUSH_PROMISE.*CONTINUATION") - << v; - } -} - -class IsPaddedTest : public Http2FrameHeaderTypeAndFlagTest {}; -INSTANTIATE_TEST_CASE_P(IsPadded, - IsPaddedTest, - Combine(ValuesIn(ValidFrameTypes()), - Values(~Http2FrameFlag::PADDED, 0xff))); -TEST_P(IsPaddedTest, IsPadded) { - const bool is_set = - (flags_ & Http2FrameFlag::PADDED) == Http2FrameFlag::PADDED; - Http2String flags_string; - Http2FrameHeader v(0, type_, flags_, 0); - switch (type_) { - case Http2FrameType::DATA: - case Http2FrameType::HEADERS: - case Http2FrameType::PUSH_PROMISE: - EXPECT_EQ(is_set, v.IsPadded()) << v; - flags_string = v.FlagsToString(); - if (is_set) { - EXPECT_THAT(flags_string, MatchesRegex(".*\\|?PADDED\\|.*")); - } else { - EXPECT_THAT(flags_string, Not(HasSubstr("PADDED"))); - } - v.RetainFlags(Http2FrameFlag::PADDED); - EXPECT_EQ(is_set, v.IsPadded()) << v; - { - std::stringstream s; - s << v; - EXPECT_EQ(v.ToString(), s.str()); - if (is_set) { - EXPECT_THAT(s.str(), HasSubstr("flags=PADDED,")); - } else { - EXPECT_THAT(s.str(), HasSubstr("flags=,")); - } - } - break; - default: - EXPECT_DEBUG_DEATH(v.IsPadded(), "DATA.*HEADERS.*PUSH_PROMISE") << v; - } -} - -class HasPriorityTest : public Http2FrameHeaderTypeAndFlagTest {}; -INSTANTIATE_TEST_CASE_P(HasPriority, - HasPriorityTest, - Combine(ValuesIn(ValidFrameTypes()), - Values(~Http2FrameFlag::PRIORITY, 0xff))); -TEST_P(HasPriorityTest, HasPriority) { - const bool is_set = - (flags_ & Http2FrameFlag::PRIORITY) == Http2FrameFlag::PRIORITY; - Http2String flags_string; - Http2FrameHeader v(0, type_, flags_, 0); - switch (type_) { - case Http2FrameType::HEADERS: - EXPECT_EQ(is_set, v.HasPriority()) << v; - flags_string = v.FlagsToString(); - if (is_set) { - EXPECT_THAT(flags_string, MatchesRegex(".*\\|?PRIORITY\\|.*")); - } else { - EXPECT_THAT(flags_string, Not(HasSubstr("PRIORITY"))); - } - v.RetainFlags(Http2FrameFlag::PRIORITY); - EXPECT_EQ(is_set, v.HasPriority()) << v; - { - std::stringstream s; - s << v; - EXPECT_EQ(v.ToString(), s.str()); - if (is_set) { - EXPECT_THAT(s.str(), HasSubstr("flags=PRIORITY,")); - } else { - EXPECT_THAT(s.str(), HasSubstr("flags=,")); - } - } - break; - default: - EXPECT_DEBUG_DEATH(v.HasPriority(), "HEADERS") << v; - } -} - -TEST(Http2PriorityFieldsTest, Constructor) { - Http2Random random; - uint32_t stream_dependency = random.Rand32() & StreamIdMask(); - uint32_t weight = 1 + random.Rand8(); - bool is_exclusive = random.OneIn(2); - - Http2PriorityFields v(stream_dependency, weight, is_exclusive); - - EXPECT_EQ(stream_dependency, v.stream_dependency); - EXPECT_EQ(weight, v.weight); - EXPECT_EQ(is_exclusive, v.is_exclusive); - - // The high-bit must not be set on the stream id. - EXPECT_DEBUG_DEATH( - Http2PriorityFields(stream_dependency | 0x80000000, weight, is_exclusive), - "31-bit"); - - // The weight must be in the range 1-256. - EXPECT_DEBUG_DEATH(Http2PriorityFields(stream_dependency, 0, is_exclusive), - "too small"); - EXPECT_DEBUG_DEATH( - Http2PriorityFields(stream_dependency, weight + 256, is_exclusive), - "too large"); - - EXPECT_TRUE(VerifyRandomCalls<Http2PriorityFields>()); -} -#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) - -TEST(Http2RstStreamFieldsTest, IsSupported) { - Http2RstStreamFields v{Http2ErrorCode::HTTP2_NO_ERROR}; - EXPECT_TRUE(v.IsSupportedErrorCode()) << v; - - Http2RstStreamFields u{static_cast<Http2ErrorCode>(~0)}; - EXPECT_FALSE(u.IsSupportedErrorCode()) << v; - - EXPECT_TRUE(VerifyRandomCalls<Http2RstStreamFields>()); -} - -TEST(Http2SettingFieldsTest, Misc) { - Http2Random random; - Http2SettingsParameter parameter = - static_cast<Http2SettingsParameter>(random.Rand16()); - uint32_t value = random.Rand32(); - - Http2SettingFields v(parameter, value); - - EXPECT_EQ(v, v); - EXPECT_EQ(parameter, v.parameter); - EXPECT_EQ(value, v.value); - - if (static_cast<uint16_t>(parameter) < 7) { - EXPECT_TRUE(v.IsSupportedParameter()) << v; - } else { - EXPECT_FALSE(v.IsSupportedParameter()) << v; - } - - Http2SettingFields u(parameter, ~value); - EXPECT_NE(v, u); - EXPECT_EQ(v.parameter, u.parameter); - EXPECT_NE(v.value, u.value); - - Http2SettingFields w(IncrementEnum(parameter), value); - EXPECT_NE(v, w); - EXPECT_NE(v.parameter, w.parameter); - EXPECT_EQ(v.value, w.value); - - Http2SettingFields x(Http2SettingsParameter::MAX_FRAME_SIZE, 123); - std::stringstream s; - s << x; - EXPECT_EQ("parameter=MAX_FRAME_SIZE, value=123", s.str()); - - EXPECT_TRUE(VerifyRandomCalls<Http2SettingFields>()); -} - -TEST(Http2PushPromiseTest, Misc) { - Http2Random random; - uint32_t promised_stream_id = random.Rand32() & StreamIdMask(); - - Http2PushPromiseFields v{promised_stream_id}; - EXPECT_EQ(promised_stream_id, v.promised_stream_id); - EXPECT_EQ(v, v); - - std::stringstream s; - s << v; - EXPECT_EQ(Http2StrCat("promised_stream_id=", promised_stream_id), s.str()); - - // High-bit is reserved, but not used, so we can set it. - promised_stream_id |= 0x80000000; - Http2PushPromiseFields w{promised_stream_id}; - EXPECT_EQ(w, w); - EXPECT_NE(v, w); - - v.promised_stream_id = promised_stream_id; - EXPECT_EQ(v, w); - - EXPECT_TRUE(VerifyRandomCalls<Http2PushPromiseFields>()); -} - -TEST(Http2PingFieldsTest, Misc) { - Http2PingFields v{{'8', ' ', 'b', 'y', 't', 'e', 's', '\0'}}; - std::stringstream s; - s << v; - EXPECT_EQ("opaque_bytes=0x3820627974657300", s.str()); - - EXPECT_TRUE(VerifyRandomCalls<Http2PingFields>()); -} - -TEST(Http2GoAwayFieldsTest, Misc) { - Http2Random random; - uint32_t last_stream_id = random.Rand32() & StreamIdMask(); - Http2ErrorCode error_code = static_cast<Http2ErrorCode>(random.Rand32()); - - Http2GoAwayFields v(last_stream_id, error_code); - EXPECT_EQ(v, v); - EXPECT_EQ(last_stream_id, v.last_stream_id); - EXPECT_EQ(error_code, v.error_code); - - if (static_cast<uint32_t>(error_code) < 14) { - EXPECT_TRUE(v.IsSupportedErrorCode()) << v; - } else { - EXPECT_FALSE(v.IsSupportedErrorCode()) << v; - } - - Http2GoAwayFields u(~last_stream_id, error_code); - EXPECT_NE(v, u); - EXPECT_NE(v.last_stream_id, u.last_stream_id); - EXPECT_EQ(v.error_code, u.error_code); - - EXPECT_TRUE(VerifyRandomCalls<Http2GoAwayFields>()); -} - -TEST(Http2WindowUpdateTest, Misc) { - Http2Random random; - uint32_t window_size_increment = random.Rand32() & UInt31Mask(); - - Http2WindowUpdateFields v{window_size_increment}; - EXPECT_EQ(window_size_increment, v.window_size_increment); - EXPECT_EQ(v, v); - - std::stringstream s; - s << v; - EXPECT_EQ(Http2StrCat("window_size_increment=", window_size_increment), - s.str()); - - // High-bit is reserved, but not used, so we can set it. - window_size_increment |= 0x80000000; - Http2WindowUpdateFields w{window_size_increment}; - EXPECT_EQ(w, w); - EXPECT_NE(v, w); - - v.window_size_increment = window_size_increment; - EXPECT_EQ(v, w); - - EXPECT_TRUE(VerifyRandomCalls<Http2WindowUpdateFields>()); -} - -TEST(Http2AltSvcTest, Misc) { - Http2Random random; - uint16_t origin_length = random.Rand16(); - - Http2AltSvcFields v{origin_length}; - EXPECT_EQ(origin_length, v.origin_length); - EXPECT_EQ(v, v); - - std::stringstream s; - s << v; - EXPECT_EQ(Http2StrCat("origin_length=", origin_length), s.str()); - - Http2AltSvcFields w{++origin_length}; - EXPECT_EQ(w, w); - EXPECT_NE(v, w); - - v.origin_length = w.origin_length; - EXPECT_EQ(v, w); - - EXPECT_TRUE(VerifyRandomCalls<Http2AltSvcFields>()); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/http2_structures_test_util.cc b/net/third_party/http2/http2_structures_test_util.cc deleted file mode 100644 index e0f2cc7..0000000 --- a/net/third_party/http2/http2_structures_test_util.cc +++ /dev/null
@@ -1,109 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/http2_structures_test_util.h" - -#include <cstdint> - -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_constants_test_util.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/test_tools/http2_random.h" - -namespace http2 { -namespace test { - -void Randomize(Http2FrameHeader* p, Http2Random* rng) { - p->payload_length = rng->Rand32() & 0xffffff; - p->type = static_cast<Http2FrameType>(rng->Rand8()); - p->flags = static_cast<Http2FrameFlag>(rng->Rand8()); - p->stream_id = rng->Rand32() & StreamIdMask(); -} -void Randomize(Http2PriorityFields* p, Http2Random* rng) { - p->stream_dependency = rng->Rand32() & StreamIdMask(); - p->weight = rng->Rand8() + 1; - p->is_exclusive = rng->OneIn(2); -} -void Randomize(Http2RstStreamFields* p, Http2Random* rng) { - p->error_code = static_cast<Http2ErrorCode>(rng->Rand32()); -} -void Randomize(Http2SettingFields* p, Http2Random* rng) { - p->parameter = static_cast<Http2SettingsParameter>(rng->Rand16()); - p->value = rng->Rand32(); -} -void Randomize(Http2PushPromiseFields* p, Http2Random* rng) { - p->promised_stream_id = rng->Rand32() & StreamIdMask(); -} -void Randomize(Http2PingFields* p, Http2Random* rng) { - for (int ndx = 0; ndx < 8; ++ndx) { - p->opaque_bytes[ndx] = rng->Rand8(); - } -} -void Randomize(Http2GoAwayFields* p, Http2Random* rng) { - p->last_stream_id = rng->Rand32() & StreamIdMask(); - p->error_code = static_cast<Http2ErrorCode>(rng->Rand32()); -} -void Randomize(Http2WindowUpdateFields* p, Http2Random* rng) { - p->window_size_increment = rng->Rand32() & 0x7fffffff; -} -void Randomize(Http2AltSvcFields* p, Http2Random* rng) { - p->origin_length = rng->Rand16(); -} - -void ScrubFlagsOfHeader(Http2FrameHeader* header) { - uint8_t invalid_mask = InvalidFlagMaskForFrameType(header->type); - uint8_t keep_mask = ~invalid_mask; - header->RetainFlags(keep_mask); -} - -bool FrameIsPadded(const Http2FrameHeader& header) { - switch (header.type) { - case Http2FrameType::DATA: - case Http2FrameType::HEADERS: - case Http2FrameType::PUSH_PROMISE: - return header.IsPadded(); - default: - return false; - } -} - -bool FrameHasPriority(const Http2FrameHeader& header) { - switch (header.type) { - case Http2FrameType::HEADERS: - return header.HasPriority(); - case Http2FrameType::PRIORITY: - return true; - default: - return false; - } -} - -bool FrameCanHavePayload(const Http2FrameHeader& header) { - switch (header.type) { - case Http2FrameType::DATA: - case Http2FrameType::HEADERS: - case Http2FrameType::PUSH_PROMISE: - case Http2FrameType::CONTINUATION: - case Http2FrameType::PING: - case Http2FrameType::GOAWAY: - case Http2FrameType::ALTSVC: - return true; - default: - return false; - } -} - -bool FrameCanHaveHpackPayload(const Http2FrameHeader& header) { - switch (header.type) { - case Http2FrameType::HEADERS: - case Http2FrameType::PUSH_PROMISE: - case Http2FrameType::CONTINUATION: - return true; - default: - return false; - } -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/http2_structures_test_util.h b/net/third_party/http2/http2_structures_test_util.h deleted file mode 100644 index 318d50f..0000000 --- a/net/third_party/http2/http2_structures_test_util.h +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_HTTP2_STRUCTURES_TEST_UTIL_H_ -#define NET_THIRD_PARTY_HTTP2_HTTP2_STRUCTURES_TEST_UTIL_H_ - -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "net/third_party/http2/tools/http2_frame_builder.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -template <class S> -Http2String SerializeStructure(const S& s) { - Http2FrameBuilder fb; - fb.Append(s); - EXPECT_EQ(S::EncodedSize(), fb.size()); - return fb.buffer(); -} - -// Randomize the members of out, in a manner that yields encodeable contents -// (e.g. a "uint24" field has only the low 24 bits set). -void Randomize(Http2FrameHeader* out, Http2Random* rng); -void Randomize(Http2PriorityFields* out, Http2Random* rng); -void Randomize(Http2RstStreamFields* out, Http2Random* rng); -void Randomize(Http2SettingFields* out, Http2Random* rng); -void Randomize(Http2PushPromiseFields* out, Http2Random* rng); -void Randomize(Http2PingFields* out, Http2Random* rng); -void Randomize(Http2GoAwayFields* out, Http2Random* rng); -void Randomize(Http2WindowUpdateFields* out, Http2Random* rng); -void Randomize(Http2AltSvcFields* out, Http2Random* rng); - -// Clear bits of header->flags that are known to be invalid for the -// type. For unknown frame types, no change is made. -void ScrubFlagsOfHeader(Http2FrameHeader* header); - -// Is the frame with this header padded? Only true for known/supported frame -// types. -bool FrameIsPadded(const Http2FrameHeader& header); - -// Does the frame with this header have Http2PriorityFields? -bool FrameHasPriority(const Http2FrameHeader& header); - -// Does the frame with this header have a variable length payload (including -// empty) payload (e.g. DATA or HEADERS)? Really a test of the frame type. -bool FrameCanHavePayload(const Http2FrameHeader& header); - -// Does the frame with this header have a variable length HPACK payload -// (including empty) payload (e.g. HEADERS)? Really a test of the frame type. -bool FrameCanHaveHpackPayload(const Http2FrameHeader& header); - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_HTTP2_STRUCTURES_TEST_UTIL_H_
diff --git a/net/third_party/http2/platform/api/http2_arraysize.h b/net/third_party/http2/platform/api/http2_arraysize.h deleted file mode 100644 index f1ce149..0000000 --- a/net/third_party/http2/platform/api/http2_arraysize.h +++ /dev/null
@@ -1,12 +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 NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_ARRAYSIZE_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_ARRAYSIZE_H_ - -#include "net/third_party/http2/platform/impl/http2_arraysize_impl.h" - -#define HTTP2_ARRAYSIZE(x) HTTP2_ARRAYSIZE_IMPL(x) - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_ARRAYSIZE_H_
diff --git a/net/third_party/http2/platform/api/http2_bug_tracker.h b/net/third_party/http2/platform/api/http2_bug_tracker.h deleted file mode 100644 index 14b9961..0000000 --- a/net/third_party/http2/platform/api/http2_bug_tracker.h +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_BUG_TRACKER_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_BUG_TRACKER_H_ - -#include "net/third_party/http2/platform/impl/http2_bug_tracker_impl.h" - -#define HTTP2_BUG HTTP2_BUG_IMPL -#define HTTP2_BUG_IF HTTP2_BUG_IF_IMPL -#define FLAGS_http2_always_log_bugs_for_tests \ - FLAGS_http2_always_log_bugs_for_tests_IMPL - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_BUG_TRACKER_H_
diff --git a/net/third_party/http2/platform/api/http2_containers.h b/net/third_party/http2/platform/api/http2_containers.h deleted file mode 100644 index a924c28..0000000 --- a/net/third_party/http2/platform/api/http2_containers.h +++ /dev/null
@@ -1,17 +0,0 @@ -#ifndef NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_CONTAINERS_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_CONTAINERS_H_ - -#include "net/third_party/http2/platform/impl/http2_containers_impl.h" - -namespace http2 { - -// Represents a double-ended queue which may be backed by a list or a flat -// circular buffer. -// -// DOES NOT GUARANTEE POINTER OR ITERATOR STABILITY! -template <typename T> -using Http2Deque = Http2DequeImpl<T>; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_CONTAINERS_H_
diff --git a/net/third_party/http2/platform/api/http2_estimate_memory_usage.h b/net/third_party/http2/platform/api/http2_estimate_memory_usage.h deleted file mode 100644 index b2131d4..0000000 --- a/net/third_party/http2/platform/api/http2_estimate_memory_usage.h +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2017 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 NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_ESTIMATE_MEMORY_USAGE_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_ESTIMATE_MEMORY_USAGE_H_ - -#include <cstddef> - -#include "net/third_party/http2/platform/impl/http2_estimate_memory_usage_impl.h" - -namespace http2 { - -template <class T> -size_t Http2EstimateMemoryUsage(const T& object) { - return Http2EstimateMemoryUsageImpl(object); -} - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_ESTIMATE_MEMORY_USAGE_H_
diff --git a/net/third_party/http2/platform/api/http2_export.h b/net/third_party/http2/platform/api/http2_export.h deleted file mode 100644 index 438ba4e5..0000000 --- a/net/third_party/http2/platform/api/http2_export.h +++ /dev/null
@@ -1,10 +0,0 @@ -// Copyright 2017 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 NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_EXPORT_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_EXPORT_H_ - -#include "net/third_party/http2/platform/impl/http2_export_impl.h" - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_EXPORT_H_
diff --git a/net/third_party/http2/platform/api/http2_flag_utils.h b/net/third_party/http2/platform/api/http2_flag_utils.h deleted file mode 100644 index 72764ee..0000000 --- a/net/third_party/http2/platform/api/http2_flag_utils.h +++ /dev/null
@@ -1,16 +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 NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_FLAG_UTILS_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_FLAG_UTILS_H_ - -#include "net/third_party/http2/platform/impl/http2_flag_utils_impl.h" - -#define HTTP2_FLAG_COUNT HTTP2_FLAG_COUNT_IMPL -#define HTTP2_FLAG_COUNT_N HTTP2_FLAG_COUNT_N_IMPL - -#define HTTP2_CODE_COUNT HTTP2_CODE_COUNT_IMPL -#define HTTP2_CODE_COUNT_N HTTP2_CODE_COUNT_N_IMPL - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_FLAG_UTILS_H_
diff --git a/net/third_party/http2/platform/api/http2_flags.h b/net/third_party/http2/platform/api/http2_flags.h deleted file mode 100644 index e2ccd12c..0000000 --- a/net/third_party/http2/platform/api/http2_flags.h +++ /dev/null
@@ -1,14 +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 NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_FLAGS_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_FLAGS_H_ - -#include "net/third_party/http2/platform/impl/http2_flags_impl.h" - -#define GetHttp2ReloadableFlag(flag) GetHttp2ReloadableFlagImpl(flag) -#define SetHttp2ReloadableFlag(flag, value) \ - SetHttp2ReloadableFlagImpl(flag, value) - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_FLAGS_H_
diff --git a/net/third_party/http2/platform/api/http2_macros.h b/net/third_party/http2/platform/api/http2_macros.h deleted file mode 100644 index 71dea38..0000000 --- a/net/third_party/http2/platform/api/http2_macros.h +++ /dev/null
@@ -1,10 +0,0 @@ -#ifndef NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_MACROS_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_MACROS_H_ - -#include "net/third_party/http2/platform/impl/http2_macros_impl.h" - -#define HTTP2_FALLTHROUGH HTTP2_FALLTHROUGH_IMPL -#define HTTP2_UNREACHABLE() HTTP2_UNREACHABLE_IMPL() -#define HTTP2_DIE_IF_NULL(ptr) HTTP2_DIE_IF_NULL_IMPL(ptr) - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_MACROS_H_
diff --git a/net/third_party/http2/platform/api/http2_mock_log.h b/net/third_party/http2/platform/api/http2_mock_log.h deleted file mode 100644 index c9d8762..0000000 --- a/net/third_party/http2/platform/api/http2_mock_log.h +++ /dev/null
@@ -1,18 +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 NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_MOCK_LOG_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_MOCK_LOG_H_ - -#include "net/third_party/http2/platform/impl/http2_mock_log_impl.h" - -using Http2MockLog = Http2MockLogImpl; -#define CREATE_HTTP2_MOCK_LOG(log) CREATE_HTTP2_MOCK_LOG_IMPL(log) - -#define EXPECT_HTTP2_LOG_CALL(log) EXPECT_HTTP2_LOG_CALL_IMPL(log) - -#define EXPECT_HTTP2_LOG_CALL_CONTAINS(log, level, content) \ - EXPECT_HTTP2_LOG_CALL_CONTAINS_IMPL(log, level, content) - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_MOCK_LOG_H_
diff --git a/net/third_party/http2/platform/api/http2_optional.h b/net/third_party/http2/platform/api/http2_optional.h deleted file mode 100644 index b36e98db..0000000 --- a/net/third_party/http2/platform/api/http2_optional.h +++ /dev/null
@@ -1,19 +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 NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_OPTIONAL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_OPTIONAL_H_ - -#include <utility> - -#include "net/third_party/http2/platform/impl/http2_optional_impl.h" - -namespace http2 { - -template <typename T> -using Http2Optional = Http2OptionalImpl<T>; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_OPTIONAL_H_
diff --git a/net/third_party/http2/platform/api/http2_ptr_util.h b/net/third_party/http2/platform/api/http2_ptr_util.h deleted file mode 100644 index 6b4f0d6..0000000 --- a/net/third_party/http2/platform/api/http2_ptr_util.h +++ /dev/null
@@ -1,22 +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 NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_PTR_UTIL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_PTR_UTIL_H_ - -#include <memory> -#include <utility> - -#include "net/third_party/http2/platform/impl/http2_ptr_util_impl.h" - -namespace http2 { - -template <typename T, typename... Args> -std::unique_ptr<T> Http2MakeUnique(Args&&... args) { - return Http2MakeUniqueImpl<T>(std::forward<Args>(args)...); -} - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_PTR_UTIL_H_
diff --git a/net/third_party/http2/platform/api/http2_reconstruct_object.h b/net/third_party/http2/platform/api/http2_reconstruct_object.h deleted file mode 100644 index e84feb5..0000000 --- a/net/third_party/http2/platform/api/http2_reconstruct_object.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2017 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 NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_RECONSTRUCT_OBJECT_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_RECONSTRUCT_OBJECT_H_ - -#include <utility> - -#include "net/third_party/http2/platform/impl/http2_reconstruct_object_impl.h" - -namespace http2 { -namespace test { - -class Http2Random; - -// Reconstruct an object so that it is initialized as when it was first -// constructed. Runs the destructor to handle objects that might own resources, -// and runs the constructor with the provided arguments, if any. -template <class T, class... Args> -void Http2ReconstructObject(T* ptr, Http2Random* rng, Args&&... args) { - Http2ReconstructObjectImpl(ptr, rng, std::forward<Args>(args)...); -} - -// This version applies default-initialization to the object. -template <class T> -void Http2DefaultReconstructObject(T* ptr, Http2Random* rng) { - Http2DefaultReconstructObjectImpl(ptr, rng); -} - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_RECONSTRUCT_OBJECT_H_
diff --git a/net/third_party/http2/platform/api/http2_string.h b/net/third_party/http2/platform/api/http2_string.h deleted file mode 100644 index 078c2f14..0000000 --- a/net/third_party/http2/platform/api/http2_string.h +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright (c) 2017 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 NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_STRING_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_STRING_H_ - -#include "net/third_party/http2/platform/impl/http2_string_impl.h" - -namespace http2 { - -using Http2String = Http2StringImpl; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_STRING_H_
diff --git a/net/third_party/http2/platform/api/http2_string_piece.h b/net/third_party/http2/platform/api/http2_string_piece.h deleted file mode 100644 index 20d90ed..0000000 --- a/net/third_party/http2/platform/api/http2_string_piece.h +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright (c) 2017 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 NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_STRING_PIECE_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_STRING_PIECE_H_ - -#include "net/third_party/http2/platform/impl/http2_string_piece_impl.h" - -namespace http2 { - -using Http2StringPiece = Http2StringPieceImpl; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_STRING_PIECE_H_
diff --git a/net/third_party/http2/platform/api/http2_string_utils.h b/net/third_party/http2/platform/api/http2_string_utils.h deleted file mode 100644 index 6cf696a3..0000000 --- a/net/third_party/http2/platform/api/http2_string_utils.h +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2017 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 NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_STRING_UTILS_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_STRING_UTILS_H_ - -#include <type_traits> -#include <utility> - -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "net/third_party/http2/platform/impl/http2_string_utils_impl.h" - -namespace http2 { - -template <typename... Args> -inline Http2String Http2StrCat(const Args&... args) { - return Http2StrCatImpl(std::forward<const Args&>(args)...); -} - -template <typename... Args> -inline void Http2StrAppend(Http2String* output, const Args&... args) { - Http2StrAppendImpl(output, std::forward<const Args&>(args)...); -} - -template <typename... Args> -inline Http2String Http2StringPrintf(const Args&... args) { - return Http2StringPrintfImpl(std::forward<const Args&>(args)...); -} - -inline Http2String Http2HexEncode(const void* bytes, size_t size) { - return Http2HexEncodeImpl(bytes, size); -} - -inline Http2String Http2HexDecode(Http2StringPiece data) { - return Http2HexDecodeImpl(data); -} - -inline Http2String Http2HexDump(Http2StringPiece data) { - return Http2HexDumpImpl(data); -} - -inline Http2String Http2HexEscape(Http2StringPiece data) { - return Http2HexEscapeImpl(data); -} - -template <typename Number> -inline Http2String Http2Hex(Number number) { - static_assert(std::is_integral<Number>::value, "Number has to be an int"); - return Http2HexImpl(number); -} - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_STRING_UTILS_H_
diff --git a/net/third_party/http2/platform/api/http2_string_utils_test.cc b/net/third_party/http2/platform/api/http2_string_utils_test.cc deleted file mode 100644 index ca51ed6..0000000 --- a/net/third_party/http2/platform/api/http2_string_utils_test.cc +++ /dev/null
@@ -1,178 +0,0 @@ -// Copyright 2017 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 "net/third_party/http2/platform/api/http2_string_utils.h" - -#include <cstdint> - -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { -namespace { - -TEST(Http2StringUtilsTest, Http2StrCat) { - // No arguments. - EXPECT_EQ("", Http2StrCat()); - - // Single string-like argument. - const char kFoo[] = "foo"; - const Http2String string_foo(kFoo); - const Http2StringPiece stringpiece_foo(string_foo); - EXPECT_EQ("foo", Http2StrCat(kFoo)); - EXPECT_EQ("foo", Http2StrCat(string_foo)); - EXPECT_EQ("foo", Http2StrCat(stringpiece_foo)); - - // Two string-like arguments. - const char kBar[] = "bar"; - const Http2StringPiece stringpiece_bar(kBar); - const Http2String string_bar(kBar); - EXPECT_EQ("foobar", Http2StrCat(kFoo, kBar)); - EXPECT_EQ("foobar", Http2StrCat(kFoo, string_bar)); - EXPECT_EQ("foobar", Http2StrCat(kFoo, stringpiece_bar)); - EXPECT_EQ("foobar", Http2StrCat(string_foo, kBar)); - EXPECT_EQ("foobar", Http2StrCat(string_foo, string_bar)); - EXPECT_EQ("foobar", Http2StrCat(string_foo, stringpiece_bar)); - EXPECT_EQ("foobar", Http2StrCat(stringpiece_foo, kBar)); - EXPECT_EQ("foobar", Http2StrCat(stringpiece_foo, string_bar)); - EXPECT_EQ("foobar", Http2StrCat(stringpiece_foo, stringpiece_bar)); - - // Many-many arguments. - EXPECT_EQ( - "foobarbazquxquuxquuzcorgegraultgarplywaldofredplughxyzzythud", - Http2StrCat("foo", "bar", "baz", "qux", "quux", "quuz", "corge", "grault", - "garply", "waldo", "fred", "plugh", "xyzzy", "thud")); - - // Numerical arguments. - const int16_t i = 1; - const uint64_t u = 8; - const double d = 3.1415; - - EXPECT_EQ("1 8", Http2StrCat(i, " ", u)); - EXPECT_EQ("3.14151181", Http2StrCat(d, i, i, u, i)); - EXPECT_EQ("i: 1, u: 8, d: 3.1415", - Http2StrCat("i: ", i, ", u: ", u, ", d: ", d)); - - // Boolean arguments. - const bool t = true; - const bool f = false; - - EXPECT_EQ("1", Http2StrCat(t)); - EXPECT_EQ("0", Http2StrCat(f)); - EXPECT_EQ("0110", Http2StrCat(f, t, t, f)); - - // Mixed string-like, numerical, and Boolean arguments. - EXPECT_EQ("foo1foo081bar3.14151", - Http2StrCat(kFoo, i, string_foo, f, u, t, stringpiece_bar, d, t)); - EXPECT_EQ("3.141511bar18bar13.14150", - Http2StrCat(d, t, t, string_bar, i, u, kBar, t, d, f)); -} - -TEST(Http2StringUtilsTest, Http2StrAppend) { - // No arguments on empty string. - Http2String output; - Http2StrAppend(&output); - EXPECT_TRUE(output.empty()); - - // Single string-like argument. - const char kFoo[] = "foo"; - const Http2String string_foo(kFoo); - const Http2StringPiece stringpiece_foo(string_foo); - Http2StrAppend(&output, kFoo); - EXPECT_EQ("foo", output); - Http2StrAppend(&output, string_foo); - EXPECT_EQ("foofoo", output); - Http2StrAppend(&output, stringpiece_foo); - EXPECT_EQ("foofoofoo", output); - - // No arguments on non-empty string. - Http2StrAppend(&output); - EXPECT_EQ("foofoofoo", output); - - output.clear(); - - // Two string-like arguments. - const char kBar[] = "bar"; - const Http2StringPiece stringpiece_bar(kBar); - const Http2String string_bar(kBar); - Http2StrAppend(&output, kFoo, kBar); - EXPECT_EQ("foobar", output); - Http2StrAppend(&output, kFoo, string_bar); - EXPECT_EQ("foobarfoobar", output); - Http2StrAppend(&output, kFoo, stringpiece_bar); - EXPECT_EQ("foobarfoobarfoobar", output); - Http2StrAppend(&output, string_foo, kBar); - EXPECT_EQ("foobarfoobarfoobarfoobar", output); - - output.clear(); - - Http2StrAppend(&output, string_foo, string_bar); - EXPECT_EQ("foobar", output); - Http2StrAppend(&output, string_foo, stringpiece_bar); - EXPECT_EQ("foobarfoobar", output); - Http2StrAppend(&output, stringpiece_foo, kBar); - EXPECT_EQ("foobarfoobarfoobar", output); - Http2StrAppend(&output, stringpiece_foo, string_bar); - EXPECT_EQ("foobarfoobarfoobarfoobar", output); - - output.clear(); - - Http2StrAppend(&output, stringpiece_foo, stringpiece_bar); - EXPECT_EQ("foobar", output); - - // Many-many arguments. - Http2StrAppend(&output, "foo", "bar", "baz", "qux", "quux", "quuz", "corge", - "grault", "garply", "waldo", "fred", "plugh", "xyzzy", "thud"); - EXPECT_EQ( - "foobarfoobarbazquxquuxquuzcorgegraultgarplywaldofredplughxyzzythud", - output); - - output.clear(); - - // Numerical arguments. - const int16_t i = 1; - const uint64_t u = 8; - const double d = 3.1415; - - Http2StrAppend(&output, i, " ", u); - EXPECT_EQ("1 8", output); - Http2StrAppend(&output, d, i, i, u, i); - EXPECT_EQ("1 83.14151181", output); - Http2StrAppend(&output, "i: ", i, ", u: ", u, ", d: ", d); - EXPECT_EQ("1 83.14151181i: 1, u: 8, d: 3.1415", output); - - output.clear(); - - // Boolean arguments. - const bool t = true; - const bool f = false; - - Http2StrAppend(&output, t); - EXPECT_EQ("1", output); - Http2StrAppend(&output, f); - EXPECT_EQ("10", output); - Http2StrAppend(&output, f, t, t, f); - EXPECT_EQ("100110", output); - - output.clear(); - - // Mixed string-like, numerical, and Boolean arguments. - Http2StrAppend(&output, kFoo, i, string_foo, f, u, t, stringpiece_bar, d, t); - EXPECT_EQ("foo1foo081bar3.14151", output); - Http2StrAppend(&output, d, t, t, string_bar, i, u, kBar, t, d, f); - EXPECT_EQ("foo1foo081bar3.141513.141511bar18bar13.14150", output); -} - -TEST(Http2StringUtilsTest, Http2StringPrintf) { - EXPECT_EQ("", Http2StringPrintf("%s", "")); - EXPECT_EQ("foobar", Http2StringPrintf("%sbar", "foo")); - EXPECT_EQ("foobar", Http2StringPrintf("%s%s", "foo", "bar")); - EXPECT_EQ("foo: 1, bar: 2.0", - Http2StringPrintf("foo: %d, bar: %.1f", 1, 2.0)); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/platform/api/http2_test_helpers.h b/net/third_party/http2/platform/api/http2_test_helpers.h deleted file mode 100644 index 6f499ab..0000000 --- a/net/third_party/http2/platform/api/http2_test_helpers.h +++ /dev/null
@@ -1,16 +0,0 @@ -#ifndef NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_TEST_HELPERS_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_TEST_HELPERS_H_ - -// Provides VERIFY_* macros, similar to EXPECT_* and ASSERT_*, but they return -// an AssertionResult if the condition is not satisfied. -#include "net/third_party/http2/platform/impl/http2_test_helpers_impl.h" - -#include "testing/gtest/include/gtest/gtest.h" // For AssertionSuccess - -#define VERIFY_AND_RETURN_SUCCESS(expression) \ - { \ - VERIFY_SUCCESS(expression); \ - return ::testing::AssertionSuccess(); \ - } - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_API_HTTP2_TEST_HELPERS_H_
diff --git a/net/third_party/http2/platform/impl/http2_arraysize_impl.h b/net/third_party/http2/platform/impl/http2_arraysize_impl.h deleted file mode 100644 index 5a6dec9..0000000 --- a/net/third_party/http2/platform/impl/http2_arraysize_impl.h +++ /dev/null
@@ -1,12 +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 NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_ARRAYSIZE_IMPL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_ARRAYSIZE_IMPL_H_ - -#include "base/stl_util.h" - -#define HTTP2_ARRAYSIZE_IMPL(x) base::size(x) - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_ARRAYSIZE_IMPL_H_
diff --git a/net/third_party/http2/platform/impl/http2_bug_tracker_impl.h b/net/third_party/http2/platform/impl/http2_bug_tracker_impl.h deleted file mode 100644 index 9faf07ad..0000000 --- a/net/third_party/http2/platform/impl/http2_bug_tracker_impl.h +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_BUG_TRACKER_IMPL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_BUG_TRACKER_IMPL_H_ - -#include "base/logging.h" - -#define HTTP2_BUG_IMPL LOG(DFATAL) -#define HTTP2_BUG_IF_IMPL LOG_IF(DFATAL, (condition)) -#define FLAGS_http2_always_log_bugs_for_tests_IMPL (true) - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_BUG_TRACKER_IMPL_H_
diff --git a/net/third_party/http2/platform/impl/http2_containers_impl.h b/net/third_party/http2/platform/impl/http2_containers_impl.h deleted file mode 100644 index 83d7f0c..0000000 --- a/net/third_party/http2/platform/impl/http2_containers_impl.h +++ /dev/null
@@ -1,13 +0,0 @@ -#ifndef NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_CONTAINERS_IMPL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_CONTAINERS_IMPL_H_ - -#include "base/containers/circular_deque.h" - -namespace http2 { - -template <typename T> -using Http2DequeImpl = base::circular_deque<T>; - -} - -#endif /* NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_CONTAINERS_IMPL_H_ */
diff --git a/net/third_party/http2/platform/impl/http2_estimate_memory_usage_impl.h b/net/third_party/http2/platform/impl/http2_estimate_memory_usage_impl.h deleted file mode 100644 index f6099b0..0000000 --- a/net/third_party/http2/platform/impl/http2_estimate_memory_usage_impl.h +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2017 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 NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_ESTIMATE_MEMORY_USAGE_IMPL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_ESTIMATE_MEMORY_USAGE_IMPL_H_ - -#include <cstddef> - -#include "base/trace_event/memory_usage_estimator.h" - -namespace http2 { - -template <class T> -size_t Http2EstimateMemoryUsageImpl(const T& object) { - return base::trace_event::EstimateMemoryUsage(object); -} - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_ESTIMATE_MEMORY_USAGE_IMPL_H_
diff --git a/net/third_party/http2/platform/impl/http2_export_impl.h b/net/third_party/http2/platform/impl/http2_export_impl.h deleted file mode 100644 index 932748d..0000000 --- a/net/third_party/http2/platform/impl/http2_export_impl.h +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2017 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 NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_EXPORT_IMPL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_EXPORT_IMPL_H_ - -#include "net/base/net_export.h" - -#define HTTP2_EXPORT NET_EXPORT -#define HTTP2_EXPORT_PRIVATE NET_EXPORT_PRIVATE - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_EXPORT_IMPL_H_
diff --git a/net/third_party/http2/platform/impl/http2_flag_utils_impl.h b/net/third_party/http2/platform/impl/http2_flag_utils_impl.h deleted file mode 100644 index d9f744fb..0000000 --- a/net/third_party/http2/platform/impl/http2_flag_utils_impl.h +++ /dev/null
@@ -1,22 +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 NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_FLAG_UTILS_IMPL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_FLAG_UTILS_IMPL_H_ - -#include "base/logging.h" - -#define HTTP2_FLAG_COUNT_IMPL(flag) \ - DVLOG(1) << "FLAG_" #flag ": " << FLAGS_##flag -#define HTTP2_FLAG_COUNT_N_IMPL(flag, instance, total) \ - HTTP2_FLAG_COUNT_IMPL(flag) - -#define HTTP2_CODE_COUNT_IMPL(name) \ - do { \ - } while (0) -#define HTTP2_CODE_COUNT_N_IMPL(name, instance, total) \ - do { \ - } while (0) - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_FLAG_UTILS_IMPL_H_
diff --git a/net/third_party/http2/platform/impl/http2_flags_impl.cc b/net/third_party/http2/platform/impl/http2_flags_impl.cc deleted file mode 100644 index 9d886d6..0000000 --- a/net/third_party/http2/platform/impl/http2_flags_impl.cc +++ /dev/null
@@ -1,7 +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 "net/third_party/http2/platform/impl/http2_flags_impl.h" - -bool FLAGS_chromium_flag_http2_varint_decode_64_bits = true;
diff --git a/net/third_party/http2/platform/impl/http2_flags_impl.h b/net/third_party/http2/platform/impl/http2_flags_impl.h deleted file mode 100644 index e464d45..0000000 --- a/net/third_party/http2/platform/impl/http2_flags_impl.h +++ /dev/null
@@ -1,32 +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 NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_FLAGS_IMPL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_FLAGS_IMPL_H_ - -#include "net/third_party/http2/platform/api/http2_export.h" - -HTTP2_EXPORT_PRIVATE extern bool - FLAGS_chromium_flag_http2_varint_decode_64_bits; - -namespace http2 { - -inline bool GetHttp2FlagImpl(bool flag) { - return flag; -} - -inline void SetHttp2FlagImpl(bool* f, bool v) { - *f = v; -} - -#define HTTP2_RELOADABLE_FLAG(flag) FLAGS_chromium_flag_##flag - -#define GetHttp2ReloadableFlagImpl(flag) \ - GetHttp2FlagImpl(HTTP2_RELOADABLE_FLAG(flag)) -#define SetHttp2ReloadableFlagImpl(flag, value) \ - SetHttp2FlagImpl(&HTTP2_RELOADABLE_FLAG(flag), value) - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_FLAGS_IMPL_H_
diff --git a/net/third_party/http2/platform/impl/http2_macros_impl.h b/net/third_party/http2/platform/impl/http2_macros_impl.h deleted file mode 100644 index 2f855ae9..0000000 --- a/net/third_party/http2/platform/impl/http2_macros_impl.h +++ /dev/null
@@ -1,11 +0,0 @@ -#ifndef NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_MACROS_IMPL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_MACROS_IMPL_H_ - -#include "base/compiler_specific.h" -#include "base/logging.h" - -#define HTTP2_FALLTHROUGH_IMPL FALLTHROUGH -#define HTTP2_UNREACHABLE_IMPL() DCHECK(false) -#define HTTP2_DIE_IF_NULL_IMPL(ptr) (ptr) - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_MACROS_IMPL_H_
diff --git a/net/third_party/http2/platform/impl/http2_mock_log_impl.h b/net/third_party/http2/platform/impl/http2_mock_log_impl.h deleted file mode 100644 index b179681..0000000 --- a/net/third_party/http2/platform/impl/http2_mock_log_impl.h +++ /dev/null
@@ -1,22 +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 NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_MOCK_LOG_IMPL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_MOCK_LOG_IMPL_H_ - -#include "base/test/mock_log.h" -#include "testing/gmock/include/gmock/gmock.h" // IWYU pragma: export - -using Http2MockLogImpl = base::test::MockLog; -#define CREATE_HTTP2_MOCK_LOG_IMPL(log) Http2MockLog log - -#define EXPECT_HTTP2_LOG_CALL_IMPL(log) \ - EXPECT_CALL(log, \ - Log(testing::_, testing::_, testing::_, testing::_, testing::_)) - -#define EXPECT_HTTP2_LOG_CALL_CONTAINS_IMPL(log, level, content) \ - EXPECT_CALL(log, Log(logging::LOG_##level, testing::_, testing::_, \ - testing::_, testing::HasSubstr(content))) - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_MOCK_LOG_IMPL_H_
diff --git a/net/third_party/http2/platform/impl/http2_optional_impl.h b/net/third_party/http2/platform/impl/http2_optional_impl.h deleted file mode 100644 index e8a8add..0000000 --- a/net/third_party/http2/platform/impl/http2_optional_impl.h +++ /dev/null
@@ -1,17 +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 NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_OPTIONAL_IMPL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_OPTIONAL_IMPL_H_ - -#include "base/optional.h" - -namespace http2 { - -template <typename T> -using Http2OptionalImpl = base::Optional<T>; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_OPTIONAL_IMPL_H_
diff --git a/net/third_party/http2/platform/impl/http2_ptr_util_impl.h b/net/third_party/http2/platform/impl/http2_ptr_util_impl.h deleted file mode 100644 index c1fe2bd..0000000 --- a/net/third_party/http2/platform/impl/http2_ptr_util_impl.h +++ /dev/null
@@ -1,20 +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 NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_PTR_UTIL_IMPL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_PTR_UTIL_IMPL_H_ - -#include <memory> -#include <utility> - -namespace http2 { - -template <typename T, typename... Args> -std::unique_ptr<T> Http2MakeUniqueImpl(Args&&... args) { - return std::make_unique<T>(std::forward<Args>(args)...); -} - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_PTR_UTIL_IMPL_H_
diff --git a/net/third_party/http2/platform/impl/http2_reconstruct_object_impl.h b/net/third_party/http2/platform/impl/http2_reconstruct_object_impl.h deleted file mode 100644 index 09e21d690..0000000 --- a/net/third_party/http2/platform/impl/http2_reconstruct_object_impl.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2017 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 NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_RECONSTRUCT_OBJECT_IMPL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_RECONSTRUCT_OBJECT_IMPL_H_ - -#include <utility> - -namespace http2 { -namespace test { - -class Http2Random; - -// Reconstruct an object so that it is initialized as when it was first -// constructed. Runs the destructor to handle objects that might own resources, -// and runs the constructor with the provided arguments, if any. -template <class T, class... Args> -void Http2ReconstructObjectImpl(T* ptr, Http2Random* rng, Args&&... args) { - ptr->~T(); - ::new (ptr) T(std::forward<Args>(args)...); -} - -// This version applies default-initialization to the object. -template <class T> -void Http2DefaultReconstructObjectImpl(T* ptr, Http2Random* rng) { - ptr->~T(); - ::new (ptr) T; -} - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_RECONSTRUCT_OBJECT_IMPL_H_
diff --git a/net/third_party/http2/platform/impl/http2_string_impl.h b/net/third_party/http2/platform/impl/http2_string_impl.h deleted file mode 100644 index 91a23c6..0000000 --- a/net/third_party/http2/platform/impl/http2_string_impl.h +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright (c) 2017 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 NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_STRING_IMPL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_STRING_IMPL_H_ - -#include <string> - -namespace http2 { - -using Http2StringImpl = std::string; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_STRING_IMPL_H_
diff --git a/net/third_party/http2/platform/impl/http2_string_piece_impl.h b/net/third_party/http2/platform/impl/http2_string_piece_impl.h deleted file mode 100644 index 338fafd..0000000 --- a/net/third_party/http2/platform/impl/http2_string_piece_impl.h +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright (c) 2017 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 NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_STRING_PIECE_IMPL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_STRING_PIECE_IMPL_H_ - -#include "base/strings/string_piece.h" - -namespace http2 { - -using Http2StringPieceImpl = base::StringPiece; - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_STRING_PIECE_IMPL_H_
diff --git a/net/third_party/http2/platform/impl/http2_string_utils_impl.h b/net/third_party/http2/platform/impl/http2_string_utils_impl.h deleted file mode 100644 index 5cccc2e..0000000 --- a/net/third_party/http2/platform/impl/http2_string_utils_impl.h +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2017 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 NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_STRING_UTILS_IMPL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_STRING_UTILS_IMPL_H_ - -#include <sstream> -#include <utility> - -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "net/base/escape.h" -#include "net/base/hex_utils.h" -#include "net/third_party/http2/platform/api/http2_export.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" - -namespace http2 { - -template <typename... Args> -inline Http2String Http2StrCatImpl(const Args&... args) { - std::ostringstream oss; - int dummy[] = {1, (oss << args, 0)...}; - static_cast<void>(dummy); - return oss.str(); -} - -template <typename... Args> -inline void Http2StrAppendImpl(Http2String* output, Args... args) { - output->append(Http2StrCatImpl(args...)); -} - -template <typename... Args> -inline Http2String Http2StringPrintfImpl(const Args&... args) { - return base::StringPrintf(std::forward<const Args&>(args)...); -} - -inline Http2String Http2HexEncodeImpl(const void* bytes, size_t size) { - return base::HexEncode(bytes, size); -} - -inline Http2String Http2HexDecodeImpl(Http2StringPiece data) { - return net::HexDecode(data); -} - -inline Http2String Http2HexDumpImpl(Http2StringPiece data) { - return net::HexDump(data); -} - -inline Http2String Http2HexEscapeImpl(Http2StringPiece data) { - return net::EscapeQueryParamValue(data, false); -} - -template <typename Number> -inline Http2String Http2HexImpl(Number number) { - std::stringstream str; - str << std::hex << number; - return str.str(); -} - -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_STRING_UTILS_IMPL_H_
diff --git a/net/third_party/http2/platform/impl/http2_test_helpers_impl.cc b/net/third_party/http2/platform/impl/http2_test_helpers_impl.cc deleted file mode 100644 index 1436583..0000000 --- a/net/third_party/http2/platform/impl/http2_test_helpers_impl.cc +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/platform/api/http2_test_helpers.h" - -namespace http2 { -namespace test { - -// This is a copy of the same named method in ::testing::internal. -// TODO(jamessynge): See about getting something like VERIFY_* adopted by -// gUnit (probably a very difficult task!). -Http2String GetBoolAssertionFailureMessage( - const ::testing::AssertionResult& assertion_result, - const char* expression_text, - const char* actual_predicate_value, - const char* expected_predicate_value) { - const char* actual_message = assertion_result.message(); - ::testing::Message msg; - msg << "Value of: " << expression_text - << "\n Actual: " << actual_predicate_value; - if (actual_message[0] != '\0') - msg << " (" << actual_message << ")"; - msg << "\nExpected: " << expected_predicate_value; - return msg.GetString(); -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/platform/impl/http2_test_helpers_impl.h b/net/third_party/http2/platform/impl/http2_test_helpers_impl.h deleted file mode 100644 index f9109ed..0000000 --- a/net/third_party/http2/platform/impl/http2_test_helpers_impl.h +++ /dev/null
@@ -1,167 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_TEST_HELPERS_IMPL_H_ -#define NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_TEST_HELPERS_IMPL_H_ - -// Defines VERIFY_* macros, analogous to gUnit's EXPECT_* and ASSERT_* macros, -// but these return an appropriate AssertionResult if the condition is not -// satisfied. This enables one to create a function for verifying expectations -// that are needed by multiple callers or that rely on arguments not accessible -// to the main test method. Using VERIFY_SUCCESS allows one to annotate the -// a failing AssertionResult with more context. - -#include <iosfwd> -#include <sstream> - -#include "net/test/gtest_util.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "testing/gmock/include/gmock/gmock-matchers.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -template <typename T> -class VerifyThatHelper { - public: - VerifyThatHelper(const T& value, ::testing::Matcher<T> matcher) { - matches_ = matcher.Matches(value); - if (!matches_) { - printed_value_ = ::testing::PrintToString(value); - - std::ostringstream os; - matcher.DescribeTo(&os); - matcher_description_ = os.str(); - } - } - - VerifyThatHelper(const VerifyThatHelper&) = delete; - VerifyThatHelper& operator=(const VerifyThatHelper&) = delete; - - operator bool() const { return matches_; } - - const Http2String& printed_value() const { return printed_value_; } - const Http2String& matcher_description() const { - return matcher_description_; - } - - private: - bool matches_; - Http2String printed_value_; - Http2String matcher_description_; -}; - -// Constructs a failure message for Boolean assertions such as VERIFY_TRUE. -Http2String GetBoolAssertionFailureMessage( - const ::testing::AssertionResult& assertion_result, - const char* expression_text, - const char* actual_predicate_value, - const char* expected_predicate_value); - -namespace { -// Define HasSubstr() for Http2StringPiece arguments. -// This shadows ::testing::HasSubstr(), which only works on argument types -// that can be implicitly converted to a Http2String. -inline ::testing::PolymorphicMatcher<net::test::StringPieceHasSubstrMatcher> -HasSubstr(const Http2String& substring) { - return ::testing::MakePolymorphicMatcher( - net::test::StringPieceHasSubstrMatcher(substring)); -} -} // namespace - -} // namespace test -} // namespace http2 - -// Macro for adding verification location to output stream or AssertionResult. -// Starts with a new-line because of the way that gUnit displays failures for -// EXPECT_TRUE(CallToFunctionThatFailsToVerify()). -#define VERIFY_FAILED_LOCATION_ \ - "\n" \ - << "(VERIFY failed in " << __func__ << "\n" \ - << " at " __FILE__ " : " << __LINE__ << ")\n" - -// Implements Boolean test verifications VERIFY_TRUE and VERIFY_FALSE. -// text is a textual represenation of expression as it was passed into -// VERIFY_TRUE or VERIFY_FALSE. -// clang-format off -#define VERIFY_TEST_BOOLEAN_(condition, text, actual, expected) \ - if (const ::testing::AssertionResult __assertion_result = \ - ::testing::AssertionResult((condition) ? expected : actual)) \ - ; \ - else \ - return ::testing::AssertionFailure() \ - << VERIFY_FAILED_LOCATION_ \ - << ::http2::test::GetBoolAssertionFailureMessage( \ - __assertion_result, text, #actual, #expected) -// clang-format on - -// Boolean assertions. condition can be either a Boolean expression or an -// expression convertable to a boolean (such as a ::gtl::labs::optional). -#define VERIFY_TRUE(condition) \ - VERIFY_TEST_BOOLEAN_(condition, #condition, false, true) - -#define VERIFY_FALSE(condition) \ - VERIFY_TEST_BOOLEAN_(condition, #condition, true, false) - -// Convenient helper macro for writing methods that return an AssertionFailure -// that includes the tested condition in the message (in the manner of -// ASSERT_THAT and EXPECT_THAT). -// -// This macro avoids the do {} while(false) trick and putting braces around -// the if so you can do things like: -// VERIFY_THAT(foo, Lt(4)) << "foo too big in iteration " << i; -// (This parallels the implementation of CHECK().) -// -// We use an if statement with an empty true branch so that this doesn't eat -// a neighboring else when used in an unbraced if statement like: -// if (condition) -// VERIFY_THAT(foo, Eq(bar)); -// else -// FAIL(); -#define VERIFY_THAT(value, matcher) \ - if (const auto& _verify_that_helper = \ - ::http2::test::VerifyThatHelper<decltype(value)>(value, matcher)) \ - ; \ - else \ - return ::testing::AssertionFailure() \ - << "Failed to verify that '" #value "' (" \ - << _verify_that_helper.printed_value() << ") " \ - << _verify_that_helper.matcher_description() \ - << " (on " __FILE__ ":" << __LINE__ << "). " - -// Useful variants of VERIFY_THAT, similar to the corresponding EXPECT_X or -// ASSERT_X defined by gUnit. -#define VERIFY_EQ(val1, val2) VERIFY_THAT(val1, ::testing::Eq(val2)) -#define VERIFY_NE(val1, val2) VERIFY_THAT(val1, ::testing::Ne(val2)) -#define VERIFY_GT(val1, val2) VERIFY_THAT(val1, ::testing::Gt(val2)) -#define VERIFY_LT(val1, val2) VERIFY_THAT(val1, ::testing::Lt(val2)) -#define VERIFY_GE(val1, val2) VERIFY_THAT(val1, ::testing::Ge(val2)) -#define VERIFY_LE(val1, val2) VERIFY_THAT(val1, ::testing::Le(val2)) - -// Convenience macro matching EXPECT_OK -#define VERIFY_OK(statement) VERIFY_EQ(::util::Status::OK, (statement)) - -// This version verifies that an expression of type AssertionResult is -// AssertionSuccess. If instead the value is an AssertionFailure, it appends -// info about the current code location to the failure's message and returns -// the failure to the caller of the current method. It permits the code site -// to append further messages to the failure message. For example: -// VERIFY_SUCCESS(SomeCall()) << "Some more context about SomeCall"; -// clang-format off -#define VERIFY_SUCCESS(expr) \ - if (::testing::AssertionResult __assertion_result = (expr)) \ - ; \ - else \ - return __assertion_result << VERIFY_FAILED_LOCATION_ -// clang-format on - -#define VERIFY_AND_RETURN_SUCCESS(expression) \ - { \ - VERIFY_SUCCESS(expression); \ - return ::testing::AssertionSuccess(); \ - } - -#endif // NET_THIRD_PARTY_HTTP2_PLATFORM_IMPL_HTTP2_TEST_HELPERS_IMPL_H_
diff --git a/net/third_party/http2/test_tools/frame_parts.cc b/net/third_party/http2/test_tools/frame_parts.cc deleted file mode 100644 index 287533b..0000000 --- a/net/third_party/http2/test_tools/frame_parts.cc +++ /dev/null
@@ -1,526 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/test_tools/frame_parts.h" - -#include <type_traits> - -#include "base/logging.h" -#include "net/third_party/http2/http2_structures_test_util.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionFailure; -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; -using ::testing::ContainerEq; - -namespace http2 { -namespace test { -namespace { - -static_assert(std::is_base_of<Http2FrameDecoderListener, FrameParts>::value && - !std::is_abstract<FrameParts>::value, - "FrameParts needs to implement all of the methods of " - "Http2FrameDecoderListener"); - -// Compare two optional variables of the same type. -// TODO(jamessynge): Maybe create a ::testing::Matcher for this. -template <class T> -AssertionResult VerifyOptionalEq(const T& opt_a, const T& opt_b) { - if (opt_a) { - if (opt_b) { - VERIFY_EQ(opt_a.value(), opt_b.value()); - } else { - return AssertionFailure() - << "opt_b is not set; opt_a.value()=" << opt_a.value(); - } - } else if (opt_b) { - return AssertionFailure() - << "opt_a is not set; opt_b.value()=" << opt_b.value(); - } - return AssertionSuccess(); -} - -} // namespace - -FrameParts::FrameParts(const Http2FrameHeader& header) : frame_header_(header) { - VLOG(1) << "FrameParts, header: " << frame_header_; -} - -FrameParts::FrameParts(const Http2FrameHeader& header, Http2StringPiece payload) - : FrameParts(header) { - VLOG(1) << "FrameParts with payload.size() = " << payload.size(); - this->payload_.append(payload.data(), payload.size()); - opt_payload_length_ = payload.size(); -} -FrameParts::FrameParts(const Http2FrameHeader& header, - Http2StringPiece payload, - size_t total_pad_length) - : FrameParts(header, payload) { - VLOG(1) << "FrameParts with total_pad_length=" << total_pad_length; - SetTotalPadLength(total_pad_length); -} - -FrameParts::FrameParts(const FrameParts& header) = default; - -FrameParts::~FrameParts() = default; - -AssertionResult FrameParts::VerifyEquals(const FrameParts& that) const { -#define COMMON_MESSAGE "\n this: " << *this << "\n that: " << that - - VERIFY_EQ(frame_header_, that.frame_header_) << COMMON_MESSAGE; - VERIFY_EQ(payload_, that.payload_) << COMMON_MESSAGE; - VERIFY_EQ(padding_, that.padding_) << COMMON_MESSAGE; - VERIFY_EQ(altsvc_origin_, that.altsvc_origin_) << COMMON_MESSAGE; - VERIFY_EQ(altsvc_value_, that.altsvc_value_) << COMMON_MESSAGE; - VERIFY_THAT(settings_, ContainerEq(that.settings_)) << COMMON_MESSAGE; - -#define VERIFY_OPTIONAL_FIELD(field_name) \ - VERIFY_SUCCESS(VerifyOptionalEq(field_name, that.field_name)) - - VERIFY_OPTIONAL_FIELD(opt_altsvc_origin_length_) << COMMON_MESSAGE; - VERIFY_OPTIONAL_FIELD(opt_altsvc_value_length_) << COMMON_MESSAGE; - VERIFY_OPTIONAL_FIELD(opt_goaway_) << COMMON_MESSAGE; - VERIFY_OPTIONAL_FIELD(opt_missing_length_) << COMMON_MESSAGE; - VERIFY_OPTIONAL_FIELD(opt_pad_length_) << COMMON_MESSAGE; - VERIFY_OPTIONAL_FIELD(opt_ping_) << COMMON_MESSAGE; - VERIFY_OPTIONAL_FIELD(opt_priority_) << COMMON_MESSAGE; - VERIFY_OPTIONAL_FIELD(opt_push_promise_) << COMMON_MESSAGE; - VERIFY_OPTIONAL_FIELD(opt_rst_stream_error_code_) << COMMON_MESSAGE; - VERIFY_OPTIONAL_FIELD(opt_window_update_increment_) << COMMON_MESSAGE; - -#undef VERIFY_OPTIONAL_FIELD - - return AssertionSuccess(); -} - -void FrameParts::SetTotalPadLength(size_t total_pad_length) { - opt_pad_length_.reset(); - padding_.clear(); - if (total_pad_length > 0) { - ASSERT_LE(total_pad_length, 256u); - ASSERT_TRUE(frame_header_.IsPadded()); - opt_pad_length_ = total_pad_length - 1; - char zero = 0; - padding_.append(opt_pad_length_.value(), zero); - } - - if (opt_pad_length_) { - VLOG(1) << "SetTotalPadLength: pad_length=" << opt_pad_length_.value(); - } else { - VLOG(1) << "SetTotalPadLength: has no pad length"; - } -} - -void FrameParts::SetAltSvcExpected(Http2StringPiece origin, - Http2StringPiece value) { - altsvc_origin_.append(origin.data(), origin.size()); - altsvc_value_.append(value.data(), value.size()); - opt_altsvc_origin_length_ = origin.size(); - opt_altsvc_value_length_ = value.size(); -} - -bool FrameParts::OnFrameHeader(const Http2FrameHeader& header) { - ADD_FAILURE() << "OnFrameHeader: " << *this; - return true; -} - -void FrameParts::OnDataStart(const Http2FrameHeader& header) { - VLOG(1) << "OnDataStart: " << header; - ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::DATA)) << *this; - opt_payload_length_ = header.payload_length; -} - -void FrameParts::OnDataPayload(const char* data, size_t len) { - VLOG(1) << "OnDataPayload: len=" << len - << "; frame_header_: " << frame_header_; - ASSERT_TRUE(InFrameOfType(Http2FrameType::DATA)) << *this; - ASSERT_TRUE(AppendString(Http2StringPiece(data, len), &payload_, - &opt_payload_length_)); -} - -void FrameParts::OnDataEnd() { - VLOG(1) << "OnDataEnd; frame_header_: " << frame_header_; - ASSERT_TRUE(EndFrameOfType(Http2FrameType::DATA)) << *this; -} - -void FrameParts::OnHeadersStart(const Http2FrameHeader& header) { - VLOG(1) << "OnHeadersStart: " << header; - ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::HEADERS)) << *this; - opt_payload_length_ = header.payload_length; -} - -void FrameParts::OnHeadersPriority(const Http2PriorityFields& priority) { - VLOG(1) << "OnHeadersPriority: priority: " << priority - << "; frame_header_: " << frame_header_; - ASSERT_TRUE(InFrameOfType(Http2FrameType::HEADERS)) << *this; - ASSERT_FALSE(opt_priority_); - opt_priority_ = priority; - ASSERT_TRUE(opt_payload_length_); - opt_payload_length_ = - opt_payload_length_.value() - Http2PriorityFields::EncodedSize(); -} - -void FrameParts::OnHpackFragment(const char* data, size_t len) { - VLOG(1) << "OnHpackFragment: len=" << len - << "; frame_header_: " << frame_header_; - ASSERT_TRUE(got_start_callback_); - ASSERT_FALSE(got_end_callback_); - ASSERT_TRUE(FrameCanHaveHpackPayload(frame_header_)) << *this; - ASSERT_TRUE(AppendString(Http2StringPiece(data, len), &payload_, - &opt_payload_length_)); -} - -void FrameParts::OnHeadersEnd() { - VLOG(1) << "OnHeadersEnd; frame_header_: " << frame_header_; - ASSERT_TRUE(EndFrameOfType(Http2FrameType::HEADERS)) << *this; -} - -void FrameParts::OnPriorityFrame(const Http2FrameHeader& header, - const Http2PriorityFields& priority) { - VLOG(1) << "OnPriorityFrame: " << header << "; priority: " << priority; - ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PRIORITY)) << *this; - ASSERT_FALSE(opt_priority_); - opt_priority_ = priority; - ASSERT_TRUE(EndFrameOfType(Http2FrameType::PRIORITY)) << *this; -} - -void FrameParts::OnContinuationStart(const Http2FrameHeader& header) { - VLOG(1) << "OnContinuationStart: " << header; - ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::CONTINUATION)) << *this; - opt_payload_length_ = header.payload_length; -} - -void FrameParts::OnContinuationEnd() { - VLOG(1) << "OnContinuationEnd; frame_header_: " << frame_header_; - ASSERT_TRUE(EndFrameOfType(Http2FrameType::CONTINUATION)) << *this; -} - -void FrameParts::OnPadLength(size_t trailing_length) { - VLOG(1) << "OnPadLength: trailing_length=" << trailing_length; - ASSERT_TRUE(InPaddedFrame()) << *this; - ASSERT_FALSE(opt_pad_length_); - ASSERT_TRUE(opt_payload_length_); - size_t total_padding_length = trailing_length + 1; - ASSERT_GE(opt_payload_length_.value(), total_padding_length); - opt_payload_length_ = opt_payload_length_.value() - total_padding_length; - opt_pad_length_ = trailing_length; -} - -void FrameParts::OnPadding(const char* pad, size_t skipped_length) { - VLOG(1) << "OnPadding: skipped_length=" << skipped_length; - ASSERT_TRUE(InPaddedFrame()) << *this; - ASSERT_TRUE(opt_pad_length_); - ASSERT_TRUE(AppendString(Http2StringPiece(pad, skipped_length), &padding_, - &opt_pad_length_)); -} - -void FrameParts::OnRstStream(const Http2FrameHeader& header, - Http2ErrorCode error_code) { - VLOG(1) << "OnRstStream: " << header << "; code=" << error_code; - ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::RST_STREAM)) << *this; - ASSERT_FALSE(opt_rst_stream_error_code_); - opt_rst_stream_error_code_ = error_code; - ASSERT_TRUE(EndFrameOfType(Http2FrameType::RST_STREAM)) << *this; -} - -void FrameParts::OnSettingsStart(const Http2FrameHeader& header) { - VLOG(1) << "OnSettingsStart: " << header; - ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::SETTINGS)) << *this; - ASSERT_EQ(0u, settings_.size()); - ASSERT_FALSE(header.IsAck()) << header; -} - -void FrameParts::OnSetting(const Http2SettingFields& setting_fields) { - VLOG(1) << "OnSetting: " << setting_fields; - ASSERT_TRUE(InFrameOfType(Http2FrameType::SETTINGS)) << *this; - settings_.push_back(setting_fields); -} - -void FrameParts::OnSettingsEnd() { - VLOG(1) << "OnSettingsEnd; frame_header_: " << frame_header_; - ASSERT_TRUE(EndFrameOfType(Http2FrameType::SETTINGS)) << *this; -} - -void FrameParts::OnSettingsAck(const Http2FrameHeader& header) { - VLOG(1) << "OnSettingsAck: " << header; - ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::SETTINGS)) << *this; - ASSERT_EQ(0u, settings_.size()); - ASSERT_TRUE(header.IsAck()); - ASSERT_TRUE(EndFrameOfType(Http2FrameType::SETTINGS)) << *this; -} - -void FrameParts::OnPushPromiseStart(const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) { - VLOG(1) << "OnPushPromiseStart header: " << header << "; promise: " << promise - << "; total_padding_length: " << total_padding_length; - ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PUSH_PROMISE)) << *this; - ASSERT_GE(header.payload_length, Http2PushPromiseFields::EncodedSize()); - opt_payload_length_ = - header.payload_length - Http2PushPromiseFields::EncodedSize(); - ASSERT_FALSE(opt_push_promise_); - opt_push_promise_ = promise; - if (total_padding_length > 0) { - ASSERT_GE(opt_payload_length_.value(), total_padding_length); - OnPadLength(total_padding_length - 1); - } else { - ASSERT_FALSE(header.IsPadded()); - } -} - -void FrameParts::OnPushPromiseEnd() { - VLOG(1) << "OnPushPromiseEnd; frame_header_: " << frame_header_; - ASSERT_TRUE(EndFrameOfType(Http2FrameType::PUSH_PROMISE)) << *this; -} - -void FrameParts::OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) { - VLOG(1) << "OnPing header: " << header << " ping: " << ping; - ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PING)) << *this; - ASSERT_FALSE(header.IsAck()); - ASSERT_FALSE(opt_ping_); - opt_ping_ = ping; - ASSERT_TRUE(EndFrameOfType(Http2FrameType::PING)) << *this; -} - -void FrameParts::OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) { - VLOG(1) << "OnPingAck header: " << header << " ping: " << ping; - ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PING)) << *this; - ASSERT_TRUE(header.IsAck()); - ASSERT_FALSE(opt_ping_); - opt_ping_ = ping; - ASSERT_TRUE(EndFrameOfType(Http2FrameType::PING)) << *this; -} - -void FrameParts::OnGoAwayStart(const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) { - VLOG(1) << "OnGoAwayStart: " << goaway; - ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::GOAWAY)) << *this; - ASSERT_FALSE(opt_goaway_); - opt_goaway_ = goaway; - opt_payload_length_ = - header.payload_length - Http2GoAwayFields::EncodedSize(); -} - -void FrameParts::OnGoAwayOpaqueData(const char* data, size_t len) { - VLOG(1) << "OnGoAwayOpaqueData: len=" << len; - ASSERT_TRUE(InFrameOfType(Http2FrameType::GOAWAY)) << *this; - ASSERT_TRUE(AppendString(Http2StringPiece(data, len), &payload_, - &opt_payload_length_)); -} - -void FrameParts::OnGoAwayEnd() { - VLOG(1) << "OnGoAwayEnd; frame_header_: " << frame_header_; - ASSERT_TRUE(EndFrameOfType(Http2FrameType::GOAWAY)) << *this; -} - -void FrameParts::OnWindowUpdate(const Http2FrameHeader& header, - uint32_t increment) { - VLOG(1) << "OnWindowUpdate header: " << header - << " increment=" << increment; - ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::WINDOW_UPDATE)) << *this; - ASSERT_FALSE(opt_window_update_increment_); - opt_window_update_increment_ = increment; - ASSERT_TRUE(EndFrameOfType(Http2FrameType::WINDOW_UPDATE)) << *this; -} - -void FrameParts::OnAltSvcStart(const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) { - VLOG(1) << "OnAltSvcStart: " << header - << " origin_length: " << origin_length - << " value_length: " << value_length; - ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::ALTSVC)) << *this; - ASSERT_FALSE(opt_altsvc_origin_length_); - opt_altsvc_origin_length_ = origin_length; - ASSERT_FALSE(opt_altsvc_value_length_); - opt_altsvc_value_length_ = value_length; -} - -void FrameParts::OnAltSvcOriginData(const char* data, size_t len) { - VLOG(1) << "OnAltSvcOriginData: len=" << len; - ASSERT_TRUE(InFrameOfType(Http2FrameType::ALTSVC)) << *this; - ASSERT_TRUE(AppendString(Http2StringPiece(data, len), &altsvc_origin_, - &opt_altsvc_origin_length_)); -} - -void FrameParts::OnAltSvcValueData(const char* data, size_t len) { - VLOG(1) << "OnAltSvcValueData: len=" << len; - ASSERT_TRUE(InFrameOfType(Http2FrameType::ALTSVC)) << *this; - ASSERT_TRUE(AppendString(Http2StringPiece(data, len), &altsvc_value_, - &opt_altsvc_value_length_)); -} - -void FrameParts::OnAltSvcEnd() { - VLOG(1) << "OnAltSvcEnd; frame_header_: " << frame_header_; - ASSERT_TRUE(EndFrameOfType(Http2FrameType::ALTSVC)) << *this; -} - -void FrameParts::OnUnknownStart(const Http2FrameHeader& header) { - VLOG(1) << "OnUnknownStart: " << header; - ASSERT_FALSE(IsSupportedHttp2FrameType(header.type)) << header; - ASSERT_FALSE(got_start_callback_); - ASSERT_EQ(frame_header_, header); - got_start_callback_ = true; - opt_payload_length_ = header.payload_length; -} - -void FrameParts::OnUnknownPayload(const char* data, size_t len) { - VLOG(1) << "OnUnknownPayload: len=" << len; - ASSERT_FALSE(IsSupportedHttp2FrameType(frame_header_.type)) << *this; - ASSERT_TRUE(got_start_callback_); - ASSERT_FALSE(got_end_callback_); - ASSERT_TRUE(AppendString(Http2StringPiece(data, len), &payload_, - &opt_payload_length_)); -} - -void FrameParts::OnUnknownEnd() { - VLOG(1) << "OnUnknownEnd; frame_header_: " << frame_header_; - ASSERT_FALSE(IsSupportedHttp2FrameType(frame_header_.type)) << *this; - ASSERT_TRUE(got_start_callback_); - ASSERT_FALSE(got_end_callback_); - got_end_callback_ = true; -} - -void FrameParts::OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) { - VLOG(1) << "OnPaddingTooLong: " << header - << "; missing_length: " << missing_length; - ASSERT_EQ(frame_header_, header); - ASSERT_FALSE(got_end_callback_); - ASSERT_TRUE(FrameIsPadded(header)); - ASSERT_FALSE(opt_pad_length_); - ASSERT_FALSE(opt_missing_length_); - opt_missing_length_ = missing_length; - got_start_callback_ = true; - got_end_callback_ = true; -} - -void FrameParts::OnFrameSizeError(const Http2FrameHeader& header) { - VLOG(1) << "OnFrameSizeError: " << header; - ASSERT_EQ(frame_header_, header); - ASSERT_FALSE(got_end_callback_); - ASSERT_FALSE(has_frame_size_error_); - has_frame_size_error_ = true; - got_end_callback_ = true; -} - -void FrameParts::OutputTo(std::ostream& out) const { - out << "FrameParts{\n frame_header_: " << frame_header_ << "\n"; - if (!payload_.empty()) { - out << " payload_=\"" << Http2HexEscape(payload_) << "\"\n"; - } - if (!padding_.empty()) { - out << " padding_=\"" << Http2HexEscape(padding_) << "\"\n"; - } - if (!altsvc_origin_.empty()) { - out << " altsvc_origin_=\"" << Http2HexEscape(altsvc_origin_) << "\"\n"; - } - if (!altsvc_value_.empty()) { - out << " altsvc_value_=\"" << Http2HexEscape(altsvc_value_) << "\"\n"; - } - if (opt_priority_) { - out << " priority=" << opt_priority_.value() << "\n"; - } - if (opt_rst_stream_error_code_) { - out << " rst_stream=" << opt_rst_stream_error_code_.value() << "\n"; - } - if (opt_push_promise_) { - out << " push_promise=" << opt_push_promise_.value() << "\n"; - } - if (opt_ping_) { - out << " ping=" << opt_ping_.value() << "\n"; - } - if (opt_goaway_) { - out << " goaway=" << opt_goaway_.value() << "\n"; - } - if (opt_window_update_increment_) { - out << " window_update=" << opt_window_update_increment_.value() << "\n"; - } - if (opt_payload_length_) { - out << " payload_length=" << opt_payload_length_.value() << "\n"; - } - if (opt_pad_length_) { - out << " pad_length=" << opt_pad_length_.value() << "\n"; - } - if (opt_missing_length_) { - out << " missing_length=" << opt_missing_length_.value() << "\n"; - } - if (opt_altsvc_origin_length_) { - out << " origin_length=" << opt_altsvc_origin_length_.value() << "\n"; - } - if (opt_altsvc_value_length_) { - out << " value_length=" << opt_altsvc_value_length_.value() << "\n"; - } - if (has_frame_size_error_) { - out << " has_frame_size_error\n"; - } - if (got_start_callback_) { - out << " got_start_callback\n"; - } - if (got_end_callback_) { - out << " got_end_callback\n"; - } - for (size_t ndx = 0; ndx < settings_.size(); ++ndx) { - out << " setting[" << ndx << "]=" << settings_[ndx]; - } - out << "}"; -} - -AssertionResult FrameParts::StartFrameOfType( - const Http2FrameHeader& header, - Http2FrameType expected_frame_type) { - VERIFY_EQ(header.type, expected_frame_type); - VERIFY_FALSE(got_start_callback_); - VERIFY_FALSE(got_end_callback_); - VERIFY_EQ(frame_header_, header); - got_start_callback_ = true; - return AssertionSuccess(); -} - -AssertionResult FrameParts::InFrameOfType(Http2FrameType expected_frame_type) { - VERIFY_TRUE(got_start_callback_); - VERIFY_FALSE(got_end_callback_); - VERIFY_EQ(frame_header_.type, expected_frame_type); - return AssertionSuccess(); -} - -AssertionResult FrameParts::EndFrameOfType(Http2FrameType expected_frame_type) { - VERIFY_SUCCESS(InFrameOfType(expected_frame_type)); - got_end_callback_ = true; - return AssertionSuccess(); -} - -AssertionResult FrameParts::InPaddedFrame() { - VERIFY_TRUE(got_start_callback_); - VERIFY_FALSE(got_end_callback_); - VERIFY_TRUE(FrameIsPadded(frame_header_)); - return AssertionSuccess(); -} - -AssertionResult FrameParts::AppendString(Http2StringPiece source, - Http2String* target, - Http2Optional<size_t>* opt_length) { - target->append(source.data(), source.size()); - if (opt_length != nullptr) { - VERIFY_TRUE(*opt_length) << "Length is not set yet\n" << *this; - VERIFY_LE(target->size(), opt_length->value()) - << "String too large; source.size() = " << source.size() << "\n" - << *this; - } - return ::testing::AssertionSuccess(); -} - -std::ostream& operator<<(std::ostream& out, const FrameParts& v) { - v.OutputTo(out); - return out; -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/test_tools/frame_parts.h b/net/third_party/http2/test_tools/frame_parts.h deleted file mode 100644 index 7db0a2e..0000000 --- a/net/third_party/http2/test_tools/frame_parts.h +++ /dev/null
@@ -1,249 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_TEST_TOOLS_FRAME_PARTS_H_ -#define NET_THIRD_PARTY_HTTP2_TEST_TOOLS_FRAME_PARTS_H_ - -// FrameParts implements Http2FrameDecoderListener, recording the callbacks -// during the decoding of a single frame. It is also used for comparing the -// info that a test expects to be recorded during the decoding of a frame -// with the actual recorded value (i.e. by providing a comparator). - -#include <stddef.h> - -#include <cstdint> -#include <vector> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_optional.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -class FrameParts : public Http2FrameDecoderListener { - public: - // The first callback for every type of frame includes the frame header; this - // is the only constructor used during decoding of a frame. - explicit FrameParts(const Http2FrameHeader& header); - - // For use in tests where the expected frame has a variable size payload. - FrameParts(const Http2FrameHeader& header, Http2StringPiece payload); - - // For use in tests where the expected frame has a variable size payload - // and may be padded. - FrameParts(const Http2FrameHeader& header, - Http2StringPiece payload, - size_t total_pad_length); - - // Copy constructor. - FrameParts(const FrameParts& header); - - ~FrameParts() override; - - // Returns AssertionSuccess() if they're equal, else AssertionFailure() - // with info about the difference. - ::testing::AssertionResult VerifyEquals(const FrameParts& other) const; - - // Format this FrameParts object. - void OutputTo(std::ostream& out) const; - - // Set the total padding length (0 to 256). - void SetTotalPadLength(size_t total_pad_length); - - // Set the origin and value expected in an ALTSVC frame. - void SetAltSvcExpected(Http2StringPiece origin, Http2StringPiece value); - - // Http2FrameDecoderListener methods: - bool OnFrameHeader(const Http2FrameHeader& header) override; - void OnDataStart(const Http2FrameHeader& header) override; - void OnDataPayload(const char* data, size_t len) override; - void OnDataEnd() override; - void OnHeadersStart(const Http2FrameHeader& header) override; - void OnHeadersPriority(const Http2PriorityFields& priority) override; - void OnHpackFragment(const char* data, size_t len) override; - void OnHeadersEnd() override; - void OnPriorityFrame(const Http2FrameHeader& header, - const Http2PriorityFields& priority) override; - void OnContinuationStart(const Http2FrameHeader& header) override; - void OnContinuationEnd() override; - void OnPadLength(size_t trailing_length) override; - void OnPadding(const char* pad, size_t skipped_length) override; - void OnRstStream(const Http2FrameHeader& header, - Http2ErrorCode error_code) override; - void OnSettingsStart(const Http2FrameHeader& header) override; - void OnSetting(const Http2SettingFields& setting_fields) override; - void OnSettingsEnd() override; - void OnSettingsAck(const Http2FrameHeader& header) override; - void OnPushPromiseStart(const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) override; - void OnPushPromiseEnd() override; - void OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) override; - void OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) override; - void OnGoAwayStart(const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) override; - void OnGoAwayOpaqueData(const char* data, size_t len) override; - void OnGoAwayEnd() override; - void OnWindowUpdate(const Http2FrameHeader& header, - uint32_t increment) override; - void OnAltSvcStart(const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) override; - void OnAltSvcOriginData(const char* data, size_t len) override; - void OnAltSvcValueData(const char* data, size_t len) override; - void OnAltSvcEnd() override; - void OnUnknownStart(const Http2FrameHeader& header) override; - void OnUnknownPayload(const char* data, size_t len) override; - void OnUnknownEnd() override; - void OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) override; - void OnFrameSizeError(const Http2FrameHeader& header) override; - - void AppendSetting(const Http2SettingFields& setting_fields) { - settings_.push_back(setting_fields); - } - - const Http2FrameHeader& GetFrameHeader() const { return frame_header_; } - - Http2Optional<Http2PriorityFields> GetOptPriority() const { - return opt_priority_; - } - Http2Optional<Http2ErrorCode> GetOptRstStreamErrorCode() const { - return opt_rst_stream_error_code_; - } - Http2Optional<Http2PushPromiseFields> GetOptPushPromise() const { - return opt_push_promise_; - } - Http2Optional<Http2PingFields> GetOptPing() const { return opt_ping_; } - Http2Optional<Http2GoAwayFields> GetOptGoaway() const { return opt_goaway_; } - Http2Optional<size_t> GetOptPadLength() const { return opt_pad_length_; } - Http2Optional<size_t> GetOptPayloadLength() const { - return opt_payload_length_; - } - Http2Optional<size_t> GetOptMissingLength() const { - return opt_missing_length_; - } - Http2Optional<size_t> GetOptAltsvcOriginLength() const { - return opt_altsvc_origin_length_; - } - Http2Optional<size_t> GetOptAltsvcValueLength() const { - return opt_altsvc_value_length_; - } - Http2Optional<size_t> GetOptWindowUpdateIncrement() const { - return opt_window_update_increment_; - } - bool GetHasFrameSizeError() const { return has_frame_size_error_; } - - void SetOptPriority(Http2Optional<Http2PriorityFields> opt_priority) { - opt_priority_ = opt_priority; - } - void SetOptRstStreamErrorCode( - Http2Optional<Http2ErrorCode> opt_rst_stream_error_code) { - opt_rst_stream_error_code_ = opt_rst_stream_error_code; - } - void SetOptPushPromise( - Http2Optional<Http2PushPromiseFields> opt_push_promise) { - opt_push_promise_ = opt_push_promise; - } - void SetOptPing(Http2Optional<Http2PingFields> opt_ping) { - opt_ping_ = opt_ping; - } - void SetOptGoaway(Http2Optional<Http2GoAwayFields> opt_goaway) { - opt_goaway_ = opt_goaway; - } - void SetOptPadLength(Http2Optional<size_t> opt_pad_length) { - opt_pad_length_ = opt_pad_length; - } - void SetOptPayloadLength(Http2Optional<size_t> opt_payload_length) { - opt_payload_length_ = opt_payload_length; - } - void SetOptMissingLength(Http2Optional<size_t> opt_missing_length) { - opt_missing_length_ = opt_missing_length; - } - void SetOptAltsvcOriginLength( - Http2Optional<size_t> opt_altsvc_origin_length) { - opt_altsvc_origin_length_ = opt_altsvc_origin_length; - } - void SetOptAltsvcValueLength(Http2Optional<size_t> opt_altsvc_value_length) { - opt_altsvc_value_length_ = opt_altsvc_value_length; - } - void SetOptWindowUpdateIncrement( - Http2Optional<size_t> opt_window_update_increment) { - opt_window_update_increment_ = opt_window_update_increment; - } - - void SetHasFrameSizeError(bool has_frame_size_error) { - has_frame_size_error_ = has_frame_size_error; - } - - private: - // ASSERT during an On* method that we're handling a frame of type - // expected_frame_type, and have not already received other On* methods - // (i.e. got_start_callback is false). - ::testing::AssertionResult StartFrameOfType( - const Http2FrameHeader& header, - Http2FrameType expected_frame_type); - - // ASSERT that StartFrameOfType has already been called with - // expected_frame_type (i.e. got_start_callback has been called), and that - // EndFrameOfType has not yet been called (i.e. got_end_callback is false). - ::testing::AssertionResult InFrameOfType(Http2FrameType expected_frame_type); - - // ASSERT that we're InFrameOfType, and then sets got_end_callback=true. - ::testing::AssertionResult EndFrameOfType(Http2FrameType expected_frame_type); - - // ASSERT that we're in the middle of processing a frame that is padded. - ::testing::AssertionResult InPaddedFrame(); - - // Append source to target. If opt_length is not nullptr, then verifies that - // the optional has a value (i.e. that the necessary On*Start method has been - // called), and that target is not longer than opt_length->value(). - ::testing::AssertionResult AppendString(Http2StringPiece source, - Http2String* target, - Http2Optional<size_t>* opt_length); - - const Http2FrameHeader frame_header_; - - Http2String payload_; - Http2String padding_; - Http2String altsvc_origin_; - Http2String altsvc_value_; - - Http2Optional<Http2PriorityFields> opt_priority_; - Http2Optional<Http2ErrorCode> opt_rst_stream_error_code_; - Http2Optional<Http2PushPromiseFields> opt_push_promise_; - Http2Optional<Http2PingFields> opt_ping_; - Http2Optional<Http2GoAwayFields> opt_goaway_; - - Http2Optional<size_t> opt_pad_length_; - Http2Optional<size_t> opt_payload_length_; - Http2Optional<size_t> opt_missing_length_; - Http2Optional<size_t> opt_altsvc_origin_length_; - Http2Optional<size_t> opt_altsvc_value_length_; - - Http2Optional<size_t> opt_window_update_increment_; - - bool has_frame_size_error_ = false; - - std::vector<Http2SettingFields> settings_; - - // These booleans are not checked by CompareCollectedFrames. - bool got_start_callback_ = false; - bool got_end_callback_ = false; -}; - -std::ostream& operator<<(std::ostream& out, const FrameParts& v); - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_TEST_TOOLS_FRAME_PARTS_H_
diff --git a/net/third_party/http2/test_tools/frame_parts_collector.cc b/net/third_party/http2/test_tools/frame_parts_collector.cc deleted file mode 100644 index 69b6d8ad..0000000 --- a/net/third_party/http2/test_tools/frame_parts_collector.cc +++ /dev/null
@@ -1,113 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/test_tools/frame_parts_collector.h" - -#include <utility> - -#include "base/logging.h" -#include "net/third_party/http2/http2_structures_test_util.h" -#include "net/third_party/http2/platform/api/http2_ptr_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -FramePartsCollector::FramePartsCollector() = default; -FramePartsCollector::~FramePartsCollector() = default; - -void FramePartsCollector::Reset() { - current_frame_.reset(); - collected_frames_.clear(); - expected_header_set_ = false; -} - -const FrameParts* FramePartsCollector::frame(size_t n) const { - if (n < size()) { - return collected_frames_.at(n).get(); - } - CHECK(n == size()); - return current_frame(); -} - -void FramePartsCollector::ExpectFrameHeader(const Http2FrameHeader& header) { - EXPECT_FALSE(IsInProgress()); - EXPECT_FALSE(expected_header_set_) - << "expected_header_: " << expected_header_; - expected_header_ = header; - expected_header_set_ = true; - // OnFrameHeader is called before the flags are scrubbed, but the other - // methods are called after, so scrub the invalid flags from expected_header_. - ScrubFlagsOfHeader(&expected_header_); -} - -void FramePartsCollector::TestExpectedHeader(const Http2FrameHeader& header) { - if (expected_header_set_) { - EXPECT_EQ(header, expected_header_); - expected_header_set_ = false; - } -} - -Http2FrameDecoderListener* FramePartsCollector::StartFrame( - const Http2FrameHeader& header) { - TestExpectedHeader(header); - EXPECT_FALSE(IsInProgress()); - if (current_frame_ == nullptr) { - current_frame_ = Http2MakeUnique<FrameParts>(header); - } - return current_frame(); -} - -Http2FrameDecoderListener* FramePartsCollector::StartAndEndFrame( - const Http2FrameHeader& header) { - TestExpectedHeader(header); - EXPECT_FALSE(IsInProgress()); - if (current_frame_ == nullptr) { - current_frame_ = Http2MakeUnique<FrameParts>(header); - } - Http2FrameDecoderListener* result = current_frame(); - collected_frames_.push_back(std::move(current_frame_)); - return result; -} - -Http2FrameDecoderListener* FramePartsCollector::CurrentFrame() { - EXPECT_TRUE(IsInProgress()); - if (current_frame_ == nullptr) { - return &failing_listener_; - } - return current_frame(); -} - -Http2FrameDecoderListener* FramePartsCollector::EndFrame() { - EXPECT_TRUE(IsInProgress()); - if (current_frame_ == nullptr) { - return &failing_listener_; - } - Http2FrameDecoderListener* result = current_frame(); - collected_frames_.push_back(std::move(current_frame_)); - return result; -} - -Http2FrameDecoderListener* FramePartsCollector::FrameError( - const Http2FrameHeader& header) { - TestExpectedHeader(header); - if (current_frame_ == nullptr) { - // The decoder may detect an error before making any calls to the listener - // regarding the frame, in which case current_frame_==nullptr and we need - // to create a FrameParts instance. - current_frame_ = Http2MakeUnique<FrameParts>(header); - } else { - // Similarly, the decoder may have made calls to the listener regarding the - // frame before detecting the error; for example, the DATA payload decoder - // calls OnDataStart before it can detect padding errors, hence before it - // can call OnPaddingTooLong. - EXPECT_EQ(header, current_frame_->GetFrameHeader()); - } - Http2FrameDecoderListener* result = current_frame(); - collected_frames_.push_back(std::move(current_frame_)); - return result; -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/test_tools/frame_parts_collector.h b/net/third_party/http2/test_tools/frame_parts_collector.h deleted file mode 100644 index 209ccf1d..0000000 --- a/net/third_party/http2/test_tools/frame_parts_collector.h +++ /dev/null
@@ -1,111 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_TEST_TOOLS_FRAME_PARTS_COLLECTOR_H_ -#define NET_THIRD_PARTY_HTTP2_TEST_TOOLS_FRAME_PARTS_COLLECTOR_H_ - -// FramePartsCollector is a base class for Http2FrameDecoderListener -// implementations that create one FrameParts instance for each decoded frame. - -#include <stddef.h> - -#include <memory> -#include <vector> - -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener_test_util.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/test_tools/frame_parts.h" - -namespace http2 { -namespace test { - -class FramePartsCollector : public FailingHttp2FrameDecoderListener { - public: - FramePartsCollector(); - ~FramePartsCollector() override; - - // Toss out the collected data. - void Reset(); - - // Returns true if has started recording the info for a frame and has not yet - // finished doing so. - bool IsInProgress() const { return current_frame_ != nullptr; } - - // Returns the FrameParts instance into which we're currently recording - // callback info if IsInProgress, else nullptr. - const FrameParts* current_frame() const { return current_frame_.get(); } - - // Returns the number of completely collected FrameParts instances. - size_t size() const { return collected_frames_.size(); } - - // Returns the n'th frame, where 0 is the oldest of the collected frames, - // and n==size() is the frame currently being collected, if there is one. - // Returns nullptr if the requested index is not valid. - const FrameParts* frame(size_t n) const; - - protected: - // In support of OnFrameHeader, set the header that we expect to be used in - // the next call. - // TODO(jamessynge): Remove ExpectFrameHeader et al. once done with supporting - // SpdyFramer's exact states. - void ExpectFrameHeader(const Http2FrameHeader& header); - - // For use in implementing On*Start methods of Http2FrameDecoderListener, - // returns a FrameParts instance, which will be newly created if - // IsInProgress==false (which the caller should ensure), else will be the - // current_frame(); never returns nullptr. - // If called when IsInProgress==true, a test failure will be recorded. - Http2FrameDecoderListener* StartFrame(const Http2FrameHeader& header); - - // For use in implementing On* callbacks, such as OnPingAck, that are the only - // call expected for the frame being decoded; not for On*Start methods. - // Returns a FrameParts instance, which will be newly created if - // IsInProgress==false (which the caller should ensure), else will be the - // current_frame(); never returns nullptr. - // If called when IsInProgress==true, a test failure will be recorded. - Http2FrameDecoderListener* StartAndEndFrame(const Http2FrameHeader& header); - - // If IsInProgress==true, returns the FrameParts into which the current - // frame is being recorded; else records a test failure and returns - // failing_listener_, which will record a test failure when any of its - // On* methods is called. - Http2FrameDecoderListener* CurrentFrame(); - - // For use in implementing On*End methods, pushes the current frame onto - // the vector of completed frames, and returns a pointer to it for recording - // the info in the final call. If IsInProgress==false, records a test failure - // and returns failing_listener_, which will record a test failure when any - // of its On* methods is called. - Http2FrameDecoderListener* EndFrame(); - - // For use in implementing OnPaddingTooLong and OnFrameSizeError, is - // equivalent to EndFrame() if IsInProgress==true, else equivalent to - // StartAndEndFrame(). - Http2FrameDecoderListener* FrameError(const Http2FrameHeader& header); - - private: - // Returns the mutable FrameParts instance into which we're currently - // recording callback info if IsInProgress, else nullptr. - FrameParts* current_frame() { return current_frame_.get(); } - - // If expected header is set, verify that it matches the header param. - // TODO(jamessynge): Remove TestExpectedHeader et al. once done - // with supporting SpdyFramer's exact states. - void TestExpectedHeader(const Http2FrameHeader& header); - - std::unique_ptr<FrameParts> current_frame_; - std::vector<std::unique_ptr<FrameParts>> collected_frames_; - FailingHttp2FrameDecoderListener failing_listener_; - - // TODO(jamessynge): Remove expected_header_ et al. once done with supporting - // SpdyFramer's exact states. - Http2FrameHeader expected_header_; - bool expected_header_set_ = false; -}; - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_TEST_TOOLS_FRAME_PARTS_COLLECTOR_H_
diff --git a/net/third_party/http2/test_tools/frame_parts_collector_listener.cc b/net/third_party/http2/test_tools/frame_parts_collector_listener.cc deleted file mode 100644 index 4b1880d..0000000 --- a/net/third_party/http2/test_tools/frame_parts_collector_listener.cc +++ /dev/null
@@ -1,230 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/test_tools/frame_parts_collector_listener.h" - -#include "base/logging.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -bool FramePartsCollectorListener::OnFrameHeader( - const Http2FrameHeader& header) { - VLOG(1) << "OnFrameHeader: " << header; - ExpectFrameHeader(header); - return true; -} - -void FramePartsCollectorListener::OnDataStart(const Http2FrameHeader& header) { - VLOG(1) << "OnDataStart: " << header; - StartFrame(header)->OnDataStart(header); -} - -void FramePartsCollectorListener::OnDataPayload(const char* data, size_t len) { - VLOG(1) << "OnDataPayload: len=" << len; - CurrentFrame()->OnDataPayload(data, len); -} - -void FramePartsCollectorListener::OnDataEnd() { - VLOG(1) << "OnDataEnd"; - EndFrame()->OnDataEnd(); -} - -void FramePartsCollectorListener::OnHeadersStart( - const Http2FrameHeader& header) { - VLOG(1) << "OnHeadersStart: " << header; - StartFrame(header)->OnHeadersStart(header); -} - -void FramePartsCollectorListener::OnHeadersPriority( - const Http2PriorityFields& priority) { - VLOG(1) << "OnHeadersPriority: " << priority; - CurrentFrame()->OnHeadersPriority(priority); -} - -void FramePartsCollectorListener::OnHpackFragment(const char* data, - size_t len) { - VLOG(1) << "OnHpackFragment: len=" << len; - CurrentFrame()->OnHpackFragment(data, len); -} - -void FramePartsCollectorListener::OnHeadersEnd() { - VLOG(1) << "OnHeadersEnd"; - EndFrame()->OnHeadersEnd(); -} - -void FramePartsCollectorListener::OnPriorityFrame( - const Http2FrameHeader& header, - const Http2PriorityFields& priority_fields) { - VLOG(1) << "OnPriority: " << header << "; " << priority_fields; - StartAndEndFrame(header)->OnPriorityFrame(header, priority_fields); -} - -void FramePartsCollectorListener::OnContinuationStart( - const Http2FrameHeader& header) { - VLOG(1) << "OnContinuationStart: " << header; - StartFrame(header)->OnContinuationStart(header); -} - -void FramePartsCollectorListener::OnContinuationEnd() { - VLOG(1) << "OnContinuationEnd"; - EndFrame()->OnContinuationEnd(); -} - -void FramePartsCollectorListener::OnPadLength(size_t pad_length) { - VLOG(1) << "OnPadLength: " << pad_length; - CurrentFrame()->OnPadLength(pad_length); -} - -void FramePartsCollectorListener::OnPadding(const char* padding, - size_t skipped_length) { - VLOG(1) << "OnPadding: " << skipped_length; - CurrentFrame()->OnPadding(padding, skipped_length); -} - -void FramePartsCollectorListener::OnRstStream(const Http2FrameHeader& header, - Http2ErrorCode error_code) { - VLOG(1) << "OnRstStream: " << header << "; error_code=" << error_code; - StartAndEndFrame(header)->OnRstStream(header, error_code); -} - -void FramePartsCollectorListener::OnSettingsStart( - const Http2FrameHeader& header) { - VLOG(1) << "OnSettingsStart: " << header; - EXPECT_EQ(Http2FrameType::SETTINGS, header.type) << header; - EXPECT_EQ(Http2FrameFlag(), header.flags) << header; - StartFrame(header)->OnSettingsStart(header); -} - -void FramePartsCollectorListener::OnSetting( - const Http2SettingFields& setting_fields) { - VLOG(1) << "Http2SettingFields: setting_fields=" << setting_fields; - CurrentFrame()->OnSetting(setting_fields); -} - -void FramePartsCollectorListener::OnSettingsEnd() { - VLOG(1) << "OnSettingsEnd"; - EndFrame()->OnSettingsEnd(); -} - -void FramePartsCollectorListener::OnSettingsAck( - const Http2FrameHeader& header) { - VLOG(1) << "OnSettingsAck: " << header; - StartAndEndFrame(header)->OnSettingsAck(header); -} - -void FramePartsCollectorListener::OnPushPromiseStart( - const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) { - VLOG(1) << "OnPushPromiseStart header: " << header << " promise: " << promise - << " total_padding_length: " << total_padding_length; - EXPECT_EQ(Http2FrameType::PUSH_PROMISE, header.type); - StartFrame(header)->OnPushPromiseStart(header, promise, total_padding_length); -} - -void FramePartsCollectorListener::OnPushPromiseEnd() { - VLOG(1) << "OnPushPromiseEnd"; - EndFrame()->OnPushPromiseEnd(); -} - -void FramePartsCollectorListener::OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) { - VLOG(1) << "OnPing: " << header << "; " << ping; - StartAndEndFrame(header)->OnPing(header, ping); -} - -void FramePartsCollectorListener::OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) { - VLOG(1) << "OnPingAck: " << header << "; " << ping; - StartAndEndFrame(header)->OnPingAck(header, ping); -} - -void FramePartsCollectorListener::OnGoAwayStart( - const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) { - VLOG(1) << "OnGoAwayStart header: " << header << "; goaway: " << goaway; - StartFrame(header)->OnGoAwayStart(header, goaway); -} - -void FramePartsCollectorListener::OnGoAwayOpaqueData(const char* data, - size_t len) { - VLOG(1) << "OnGoAwayOpaqueData: len=" << len; - CurrentFrame()->OnGoAwayOpaqueData(data, len); -} - -void FramePartsCollectorListener::OnGoAwayEnd() { - VLOG(1) << "OnGoAwayEnd"; - EndFrame()->OnGoAwayEnd(); -} - -void FramePartsCollectorListener::OnWindowUpdate( - const Http2FrameHeader& header, - uint32_t window_size_increment) { - VLOG(1) << "OnWindowUpdate: " << header - << "; window_size_increment=" << window_size_increment; - EXPECT_EQ(Http2FrameType::WINDOW_UPDATE, header.type); - StartAndEndFrame(header)->OnWindowUpdate(header, window_size_increment); -} - -void FramePartsCollectorListener::OnAltSvcStart(const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) { - VLOG(1) << "OnAltSvcStart header: " << header - << "; origin_length=" << origin_length - << "; value_length=" << value_length; - StartFrame(header)->OnAltSvcStart(header, origin_length, value_length); -} - -void FramePartsCollectorListener::OnAltSvcOriginData(const char* data, - size_t len) { - VLOG(1) << "OnAltSvcOriginData: len=" << len; - CurrentFrame()->OnAltSvcOriginData(data, len); -} - -void FramePartsCollectorListener::OnAltSvcValueData(const char* data, - size_t len) { - VLOG(1) << "OnAltSvcValueData: len=" << len; - CurrentFrame()->OnAltSvcValueData(data, len); -} - -void FramePartsCollectorListener::OnAltSvcEnd() { - VLOG(1) << "OnAltSvcEnd"; - EndFrame()->OnAltSvcEnd(); -} - -void FramePartsCollectorListener::OnUnknownStart( - const Http2FrameHeader& header) { - VLOG(1) << "OnUnknownStart: " << header; - StartFrame(header)->OnUnknownStart(header); -} - -void FramePartsCollectorListener::OnUnknownPayload(const char* data, - size_t len) { - VLOG(1) << "OnUnknownPayload: len=" << len; - CurrentFrame()->OnUnknownPayload(data, len); -} - -void FramePartsCollectorListener::OnUnknownEnd() { - VLOG(1) << "OnUnknownEnd"; - EndFrame()->OnUnknownEnd(); -} - -void FramePartsCollectorListener::OnPaddingTooLong( - const Http2FrameHeader& header, - size_t missing_length) { - VLOG(1) << "OnPaddingTooLong: " << header - << " missing_length: " << missing_length; - EndFrame()->OnPaddingTooLong(header, missing_length); -} - -void FramePartsCollectorListener::OnFrameSizeError( - const Http2FrameHeader& header) { - VLOG(1) << "OnFrameSizeError: " << header; - FrameError(header)->OnFrameSizeError(header); -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/test_tools/frame_parts_collector_listener.h b/net/third_party/http2/test_tools/frame_parts_collector_listener.h deleted file mode 100644 index d371427..0000000 --- a/net/third_party/http2/test_tools/frame_parts_collector_listener.h +++ /dev/null
@@ -1,85 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_TEST_TOOLS_FRAME_PARTS_COLLECTOR_LISTENER_H_ -#define NET_THIRD_PARTY_HTTP2_TEST_TOOLS_FRAME_PARTS_COLLECTOR_LISTENER_H_ - -// FramePartsCollectorListener extends FramePartsCollector with an -// implementation of every method of Http2FrameDecoderListener; it is -// essentially the union of all the Listener classes in the tests of the -// payload decoders (i.e. in ./payload_decoders/*_test.cc files), with the -// addition of the OnFrameHeader method. -// FramePartsCollectorListener supports tests of Http2FrameDecoder. - -#include <stddef.h> - -#include <cstdint> - -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/test_tools/frame_parts_collector.h" - -namespace http2 { -namespace test { - -class FramePartsCollectorListener : public FramePartsCollector { - public: - FramePartsCollectorListener() {} - ~FramePartsCollectorListener() override {} - - // TODO(jamessynge): Remove OnFrameHeader once done with supporting - // SpdyFramer's exact states. - bool OnFrameHeader(const Http2FrameHeader& header) override; - void OnDataStart(const Http2FrameHeader& header) override; - void OnDataPayload(const char* data, size_t len) override; - void OnDataEnd() override; - void OnHeadersStart(const Http2FrameHeader& header) override; - void OnHeadersPriority(const Http2PriorityFields& priority) override; - void OnHpackFragment(const char* data, size_t len) override; - void OnHeadersEnd() override; - void OnPriorityFrame(const Http2FrameHeader& header, - const Http2PriorityFields& priority_fields) override; - void OnContinuationStart(const Http2FrameHeader& header) override; - void OnContinuationEnd() override; - void OnPadLength(size_t pad_length) override; - void OnPadding(const char* padding, size_t skipped_length) override; - void OnRstStream(const Http2FrameHeader& header, - Http2ErrorCode error_code) override; - void OnSettingsStart(const Http2FrameHeader& header) override; - void OnSetting(const Http2SettingFields& setting_fields) override; - void OnSettingsEnd() override; - void OnSettingsAck(const Http2FrameHeader& header) override; - void OnPushPromiseStart(const Http2FrameHeader& header, - const Http2PushPromiseFields& promise, - size_t total_padding_length) override; - void OnPushPromiseEnd() override; - void OnPing(const Http2FrameHeader& header, - const Http2PingFields& ping) override; - void OnPingAck(const Http2FrameHeader& header, - const Http2PingFields& ping) override; - void OnGoAwayStart(const Http2FrameHeader& header, - const Http2GoAwayFields& goaway) override; - void OnGoAwayOpaqueData(const char* data, size_t len) override; - void OnGoAwayEnd() override; - void OnWindowUpdate(const Http2FrameHeader& header, - uint32_t window_size_increment) override; - void OnAltSvcStart(const Http2FrameHeader& header, - size_t origin_length, - size_t value_length) override; - void OnAltSvcOriginData(const char* data, size_t len) override; - void OnAltSvcValueData(const char* data, size_t len) override; - void OnAltSvcEnd() override; - void OnUnknownStart(const Http2FrameHeader& header) override; - void OnUnknownPayload(const char* data, size_t len) override; - void OnUnknownEnd() override; - void OnPaddingTooLong(const Http2FrameHeader& header, - size_t missing_length) override; - void OnFrameSizeError(const Http2FrameHeader& header) override; -}; - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_TEST_TOOLS_FRAME_PARTS_COLLECTOR_LISTENER_H_
diff --git a/net/third_party/http2/test_tools/http2_random.cc b/net/third_party/http2/test_tools/http2_random.cc deleted file mode 100644 index 53cf4bb7a2..0000000 --- a/net/third_party/http2/test_tools/http2_random.cc +++ /dev/null
@@ -1,72 +0,0 @@ -#include "net/third_party/http2/test_tools/http2_random.h" - -#include "base/logging.h" -#include "net/third_party/http2/platform/api/http2_string_utils.h" -#include "third_party/boringssl/src/include/openssl/chacha.h" -#include "third_party/boringssl/src/include/openssl/rand.h" - -static const uint8_t kZeroNonce[12] = {0}; - -namespace http2 { -namespace test { - -Http2Random::Http2Random() { - RAND_bytes(key_, sizeof(key_)); - - LOG(INFO) << "Initialized test RNG with the following key: " << Key(); -} - -Http2Random::Http2Random(Http2StringPiece key) { - Http2String decoded_key = Http2HexDecode(key); - CHECK_EQ(sizeof(key_), decoded_key.size()); - memcpy(key_, decoded_key.data(), sizeof(key_)); -} - -Http2String Http2Random::Key() const { - return Http2HexEncode(key_, sizeof(key_)); -} - -void Http2Random::FillRandom(void* buffer, size_t buffer_size) { - memset(buffer, 0, buffer_size); - uint8_t* buffer_u8 = reinterpret_cast<uint8_t*>(buffer); - CRYPTO_chacha_20(buffer_u8, buffer_u8, buffer_size, key_, kZeroNonce, - counter_++); -} - -Http2String Http2Random::RandString(int length) { - Http2String result; - result.resize(length); - FillRandom(&result[0], length); - return result; -} - -uint64_t Http2Random::Rand64() { - union { - uint64_t number; - uint8_t bytes[sizeof(uint64_t)]; - } result; - FillRandom(result.bytes, sizeof(result.bytes)); - return result.number; -} - -double Http2Random::RandDouble() { - union { - double f; - uint64_t i; - } value; - value.i = (1023ull << 52ull) | (Rand64() & 0xfffffffffffffu); - return value.f - 1.0; -} - -Http2String Http2Random::RandStringWithAlphabet(int length, - Http2StringPiece alphabet) { - Http2String result; - result.resize(length); - for (int i = 0; i < length; i++) { - result[i] = alphabet[Uniform(alphabet.size())]; - } - return result; -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/test_tools/http2_random.h b/net/third_party/http2/test_tools/http2_random.h deleted file mode 100644 index 95933c1..0000000 --- a/net/third_party/http2/test_tools/http2_random.h +++ /dev/null
@@ -1,88 +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 NET_THIRD_PARTY_HTTP2_TEST_TOOLS_HTTP2_RANDOM_H_ -#define NET_THIRD_PARTY_HTTP2_TEST_TOOLS_HTTP2_RANDOM_H_ - -#include <cmath> -#include <cstdint> -#include <limits> -#include <random> - -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" - -namespace http2 { -namespace test { - -// The random number generator used for unit tests. Since the algorithm is -// deterministic and fixed, this can be used to reproduce flakes in the unit -// tests caused by specific random values. -class Http2Random { - public: - Http2Random(); - - Http2Random(const Http2Random&) = delete; - Http2Random& operator=(const Http2Random&) = delete; - - // Reproducible random number generation: by using the same key, the same - // sequence of results is obtained. - explicit Http2Random(Http2StringPiece key); - Http2String Key() const; - - void FillRandom(void* buffer, size_t buffer_size); - Http2String RandString(int length); - - // Returns a random 64-bit value. - uint64_t Rand64(); - - // Return a uniformly distrubted random number in [0, n). - uint32_t Uniform(uint32_t n) { return Rand64() % n; } - // Return a uniformly distrubted random number in [lo, hi). - uint64_t UniformInRange(uint64_t lo, uint64_t hi) { - return lo + Rand64() % (hi - lo); - } - // Return an integer of logarithmically random scale. - uint32_t Skewed(uint32_t max_log) { - const uint32_t base = Rand32() % (max_log + 1); - const uint32_t mask = ((base < 32) ? (1u << base) : 0u) - 1u; - return Rand32() & mask; - } - // Return a random number in [0, max] range that skews low. - uint64_t RandomSizeSkewedLow(uint64_t max) { - return std::round(max * std::pow(RandDouble(), 2)); - } - - // Returns a random double between 0 and 1. - double RandDouble(); - float RandFloat() { return RandDouble(); } - - // Has 1/n chance of returning true. - bool OneIn(int n) { return Uniform(n) == 0; } - - uint8_t Rand8() { return Rand64(); } - uint16_t Rand16() { return Rand64(); } - uint32_t Rand32() { return Rand64(); } - - // Return a random string consisting of the characters from the specified - // alphabet. - Http2String RandStringWithAlphabet(int length, Http2StringPiece alphabet); - - // STL UniformRandomNumberGenerator implementation. - using result_type = uint64_t; - static constexpr result_type min() { return 0; } - static constexpr result_type max() { - return std::numeric_limits<result_type>::max(); - } - result_type operator()() { return Rand64(); } - - private: - uint8_t key_[32]; - uint32_t counter_ = 0; -}; - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_TEST_TOOLS_HTTP2_RANDOM_H_
diff --git a/net/third_party/http2/test_tools/http2_random_test.cc b/net/third_party/http2/test_tools/http2_random_test.cc deleted file mode 100644 index a748e9fd..0000000 --- a/net/third_party/http2/test_tools/http2_random_test.cc +++ /dev/null
@@ -1,94 +0,0 @@ -#include "net/third_party/http2/test_tools/http2_random.h" - -#include <set> - -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { -namespace { - -TEST(Http2RandomTest, ProducesDifferentNumbers) { - Http2Random random; - uint64_t value1 = random.Rand64(); - uint64_t value2 = random.Rand64(); - uint64_t value3 = random.Rand64(); - - EXPECT_NE(value1, value2); - EXPECT_NE(value2, value3); - EXPECT_NE(value3, value1); -} - -TEST(Http2RandomTest, StartsWithDifferentKeys) { - Http2Random random1; - Http2Random random2; - - EXPECT_NE(random1.Key(), random2.Key()); - EXPECT_NE(random1.Rand64(), random2.Rand64()); - EXPECT_NE(random1.Rand64(), random2.Rand64()); - EXPECT_NE(random1.Rand64(), random2.Rand64()); -} - -TEST(Http2RandomTest, ReproducibleRandom) { - Http2Random random; - uint64_t value1 = random.Rand64(); - uint64_t value2 = random.Rand64(); - - Http2Random clone_random(random.Key()); - EXPECT_EQ(clone_random.Key(), random.Key()); - EXPECT_EQ(value1, clone_random.Rand64()); - EXPECT_EQ(value2, clone_random.Rand64()); -} - -TEST(Http2RandomTest, STLShuffle) { - Http2Random random; - const Http2String original = "abcdefghijklmonpqrsuvwxyz"; - - Http2String shuffled = original; - std::shuffle(shuffled.begin(), shuffled.end(), random); - EXPECT_NE(original, shuffled); -} - -TEST(Http2RandomTest, RandFloat) { - Http2Random random; - for (int i = 0; i < 10000; i++) { - float value = random.RandFloat(); - ASSERT_GE(value, 0.f); - ASSERT_LE(value, 1.f); - } -} - -TEST(Http2RandomTest, RandStringWithAlphabet) { - Http2Random random; - Http2String str = random.RandStringWithAlphabet(1000, "xyz"); - EXPECT_EQ(1000u, str.size()); - - std::set<char> characters(str.begin(), str.end()); - EXPECT_THAT(characters, testing::ElementsAre('x', 'y', 'z')); -} - -TEST(Http2RandomTest, SkewedLow) { - Http2Random random; - constexpr size_t kMax = 1234; - for (int i = 0; i < 10000; i++) { - size_t value = random.RandomSizeSkewedLow(kMax); - ASSERT_GE(value, 0u); - ASSERT_LE(value, kMax); - } -} - -// Checks that SkewedLow() generates full range. This is required, since in -// some unit tests would infinitely loop. -TEST(Http2RandomTest, SkewedLowFullRange) { - Http2Random random; - std::set<size_t> values; - for (int i = 0; i < 1000; i++) { - values.insert(random.RandomSizeSkewedLow(3)); - } - EXPECT_THAT(values, testing::ElementsAre(0, 1, 2, 3)); -} - -} // namespace -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/tools/http2_frame_builder.cc b/net/third_party/http2/tools/http2_frame_builder.cc deleted file mode 100644 index 22b482e..0000000 --- a/net/third_party/http2/tools/http2_frame_builder.cc +++ /dev/null
@@ -1,181 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/tools/http2_frame_builder.h" - -#ifdef WIN32 -#include <winsock2.h> // for htonl() functions -#else -#include <arpa/inet.h> -#include <netinet/in.h> // for htonl, htons -#endif - -#include "net/third_party/http2/platform/api/http2_string_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -Http2FrameBuilder::Http2FrameBuilder(Http2FrameType type, - uint8_t flags, - uint32_t stream_id) { - AppendUInt24(0); // Frame payload length, unknown so far. - Append(type); - AppendUInt8(flags); - AppendUInt31(stream_id); -} - -Http2FrameBuilder::Http2FrameBuilder(const Http2FrameHeader& v) { - Append(v); -} - -void Http2FrameBuilder::Append(Http2StringPiece s) { - Http2StrAppend(&buffer_, s); -} - -void Http2FrameBuilder::AppendBytes(const void* data, uint32_t num_bytes) { - Append(Http2StringPiece(static_cast<const char*>(data), num_bytes)); -} - -void Http2FrameBuilder::AppendZeroes(size_t num_zero_bytes) { - char zero = 0; - buffer_.append(num_zero_bytes, zero); -} - -void Http2FrameBuilder::AppendUInt8(uint8_t value) { - AppendBytes(&value, 1); -} - -void Http2FrameBuilder::AppendUInt16(uint16_t value) { - value = htons(value); - AppendBytes(&value, 2); -} - -void Http2FrameBuilder::AppendUInt24(uint32_t value) { - // Doesn't make sense to try to append a larger value, as that doesn't - // simulate something an encoder could do (i.e. the other 8 bits simply aren't - // there to be occupied). - EXPECT_EQ(value, value & 0xffffff); - value = htonl(value); - AppendBytes(reinterpret_cast<char*>(&value) + 1, 3); -} - -void Http2FrameBuilder::AppendUInt31(uint32_t value) { - // If you want to test the high-bit being set, call AppendUInt32 instead. - uint32_t tmp = value & StreamIdMask(); - EXPECT_EQ(value, value & StreamIdMask()) - << "High-bit of uint32_t should be clear."; - value = htonl(tmp); - AppendBytes(&value, 4); -} - -void Http2FrameBuilder::AppendUInt32(uint32_t value) { - value = htonl(value); - AppendBytes(&value, sizeof(value)); -} - -void Http2FrameBuilder::Append(Http2ErrorCode error_code) { - AppendUInt32(static_cast<uint32_t>(error_code)); -} - -void Http2FrameBuilder::Append(Http2FrameType type) { - AppendUInt8(static_cast<uint8_t>(type)); -} - -void Http2FrameBuilder::Append(Http2SettingsParameter parameter) { - AppendUInt16(static_cast<uint16_t>(parameter)); -} - -void Http2FrameBuilder::Append(const Http2FrameHeader& v) { - AppendUInt24(v.payload_length); - Append(v.type); - AppendUInt8(v.flags); - AppendUInt31(v.stream_id); -} - -void Http2FrameBuilder::Append(const Http2PriorityFields& v) { - // The EXCLUSIVE flag is the high-bit of the 32-bit stream dependency field. - uint32_t tmp = v.stream_dependency & StreamIdMask(); - EXPECT_EQ(tmp, v.stream_dependency); - if (v.is_exclusive) { - tmp |= 0x80000000; - } - AppendUInt32(tmp); - - // The PRIORITY frame's weight field is logically in the range [1, 256], - // but is encoded as a byte in the range [0, 255]. - ASSERT_LE(1u, v.weight); - ASSERT_LE(v.weight, 256u); - AppendUInt8(v.weight - 1); -} - -void Http2FrameBuilder::Append(const Http2RstStreamFields& v) { - Append(v.error_code); -} - -void Http2FrameBuilder::Append(const Http2SettingFields& v) { - Append(v.parameter); - AppendUInt32(v.value); -} - -void Http2FrameBuilder::Append(const Http2PushPromiseFields& v) { - AppendUInt31(v.promised_stream_id); -} - -void Http2FrameBuilder::Append(const Http2PingFields& v) { - AppendBytes(v.opaque_bytes, sizeof Http2PingFields::opaque_bytes); -} - -void Http2FrameBuilder::Append(const Http2GoAwayFields& v) { - AppendUInt31(v.last_stream_id); - Append(v.error_code); -} - -void Http2FrameBuilder::Append(const Http2WindowUpdateFields& v) { - EXPECT_NE(0u, v.window_size_increment) << "Increment must be non-zero."; - AppendUInt31(v.window_size_increment); -} - -void Http2FrameBuilder::Append(const Http2AltSvcFields& v) { - AppendUInt16(v.origin_length); -} - -// Methods for changing existing buffer contents. - -void Http2FrameBuilder::WriteAt(Http2StringPiece s, size_t offset) { - ASSERT_LE(offset, buffer_.size()); - size_t len = offset + s.size(); - if (len > buffer_.size()) { - buffer_.resize(len); - } - for (size_t ndx = 0; ndx < s.size(); ++ndx) { - buffer_[offset + ndx] = s[ndx]; - } -} - -void Http2FrameBuilder::WriteBytesAt(const void* data, - uint32_t num_bytes, - size_t offset) { - WriteAt(Http2StringPiece(static_cast<const char*>(data), num_bytes), offset); -} - -void Http2FrameBuilder::WriteUInt24At(uint32_t value, size_t offset) { - ASSERT_LT(value, static_cast<uint32_t>(1 << 24)); - value = htonl(value); - WriteBytesAt(reinterpret_cast<char*>(&value) + 1, sizeof(value) - 1, offset); -} - -void Http2FrameBuilder::SetPayloadLength(uint32_t payload_length) { - WriteUInt24At(payload_length, 0); -} - -size_t Http2FrameBuilder::SetPayloadLength() { - EXPECT_GE(size(), Http2FrameHeader::EncodedSize()); - uint32_t payload_length = size() - Http2FrameHeader::EncodedSize(); - SetPayloadLength(payload_length); - return payload_length; -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/tools/http2_frame_builder.h b/net/third_party/http2/tools/http2_frame_builder.h deleted file mode 100644 index 0c8b2ea..0000000 --- a/net/third_party/http2/tools/http2_frame_builder.h +++ /dev/null
@@ -1,101 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_TOOLS_HTTP2_FRAME_BUILDER_H_ -#define NET_THIRD_PARTY_HTTP2_TOOLS_HTTP2_FRAME_BUILDER_H_ - -// Http2FrameBuilder builds wire-format HTTP/2 frames (or fragments thereof) -// from components. -// -// For now, this is only intended for use in tests, and thus has EXPECT* in the -// code. If desired to use it in an encoder, it will need optimization work, -// especially w.r.t memory mgmt, and the EXPECT* will need to be removed or -// replaced with DCHECKs. - -#include <stddef.h> // for size_t - -#include <cstdint> - -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" - -namespace http2 { -namespace test { - -class Http2FrameBuilder { - public: - Http2FrameBuilder(Http2FrameType type, uint8_t flags, uint32_t stream_id); - explicit Http2FrameBuilder(const Http2FrameHeader& v); - Http2FrameBuilder() {} - ~Http2FrameBuilder() {} - - size_t size() const { return buffer_.size(); } - const Http2String& buffer() const { return buffer_; } - - //---------------------------------------------------------------------------- - // Methods for appending to the end of the buffer. - - // Append a sequence of bytes from various sources. - void Append(Http2StringPiece s); - void AppendBytes(const void* data, uint32_t num_bytes); - - // Append an array of type T[N] to the string. Intended for tests with arrays - // initialized from literals, such as: - // const char kData[] = {0x12, 0x23, ...}; - // builder.AppendBytes(kData); - template <typename T, size_t N> - void AppendBytes(T (&buf)[N]) { - AppendBytes(buf, N * sizeof(buf[0])); - } - - // Support for appending padding. Does not read or write the Pad Length field. - void AppendZeroes(size_t num_zero_bytes); - - // Append various sizes of unsigned integers. - void AppendUInt8(uint8_t value); - void AppendUInt16(uint16_t value); - void AppendUInt24(uint32_t value); - void AppendUInt31(uint32_t value); - void AppendUInt32(uint32_t value); - - // Append various enums. - void Append(Http2ErrorCode error_code); - void Append(Http2FrameType type); - void Append(Http2SettingsParameter parameter); - - // Append various structures. - void Append(const Http2FrameHeader& v); - void Append(const Http2PriorityFields& v); - void Append(const Http2RstStreamFields& v); - void Append(const Http2SettingFields& v); - void Append(const Http2PushPromiseFields& v); - void Append(const Http2PingFields& v); - void Append(const Http2GoAwayFields& v); - void Append(const Http2WindowUpdateFields& v); - void Append(const Http2AltSvcFields& v); - - // Methods for changing existing buffer contents (mostly focused on updating - // the payload length). - - void WriteAt(Http2StringPiece s, size_t offset); - void WriteBytesAt(const void* data, uint32_t num_bytes, size_t offset); - void WriteUInt24At(uint32_t value, size_t offset); - - // Set the payload length to the specified size. - void SetPayloadLength(uint32_t payload_length); - - // Sets the payload length to the size of the buffer minus the size of - // the frame header. - size_t SetPayloadLength(); - - private: - Http2String buffer_; -}; - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_TOOLS_HTTP2_FRAME_BUILDER_H_
diff --git a/net/third_party/http2/tools/random_decoder_test.cc b/net/third_party/http2/tools/random_decoder_test.cc deleted file mode 100644 index c146460..0000000 --- a/net/third_party/http2/tools/random_decoder_test.cc +++ /dev/null
@@ -1,167 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/tools/random_decoder_test.h" - -#include <stddef.h> - -#include <algorithm> -#include <memory> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::AssertionFailure; -using ::testing::AssertionResult; -using ::testing::AssertionSuccess; - -namespace http2 { -namespace test { - -RandomDecoderTest::RandomDecoderTest() = default; - -bool RandomDecoderTest::StopDecodeOnDone() { - return stop_decode_on_done_; -} - -DecodeStatus RandomDecoderTest::DecodeSegments(DecodeBuffer* original, - const SelectSize& select_size) { - DecodeStatus status = DecodeStatus::kDecodeInProgress; - bool first = true; - VLOG(2) << "DecodeSegments: input size=" << original->Remaining(); - while (first || original->HasData()) { - size_t remaining = original->Remaining(); - size_t size = - std::min(remaining, select_size(first, original->Offset(), remaining)); - DecodeBuffer db(original->cursor(), size); - VLOG(2) << "Decoding " << size << " bytes of " << remaining << " remaining"; - if (first) { - first = false; - status = StartDecoding(&db); - } else { - status = ResumeDecoding(&db); - } - // A decoder MUST consume some input (if any is available), else we could - // get stuck in infinite loops. - if (db.Offset() == 0 && db.HasData() && - status != DecodeStatus::kDecodeError) { - ADD_FAILURE() << "Decoder didn't make any progress; db.FullSize=" - << db.FullSize() - << " original.Offset=" << original->Offset(); - return DecodeStatus::kDecodeError; - } - original->AdvanceCursor(db.Offset()); - switch (status) { - case DecodeStatus::kDecodeDone: - if (original->Empty() || StopDecodeOnDone()) { - return DecodeStatus::kDecodeDone; - } - continue; - case DecodeStatus::kDecodeInProgress: - continue; - case DecodeStatus::kDecodeError: - return DecodeStatus::kDecodeError; - } - } - return status; -} - -// Decode |original| multiple times, with different segmentations, validating -// after each decode, returning on the first failure. -AssertionResult RandomDecoderTest::DecodeAndValidateSeveralWays( - DecodeBuffer* original, - bool return_non_zero_on_first, - const Validator& validator) { - const uint32_t original_remaining = original->Remaining(); - VLOG(1) << "DecodeAndValidateSeveralWays - Start, remaining = " - << original_remaining; - uint32_t first_consumed; - { - // Fast decode (no stopping unless decoder does so). - DecodeBuffer input(original->cursor(), original_remaining); - VLOG(2) << "DecodeSegmentsAndValidate with SelectRemaining"; - VERIFY_SUCCESS( - DecodeSegmentsAndValidate(&input, SelectRemaining(), validator)) - << "\nFailed with SelectRemaining; input.Offset=" << input.Offset() - << "; input.Remaining=" << input.Remaining(); - first_consumed = input.Offset(); - } - if (original_remaining <= 30) { - // Decode again, one byte at a time. - DecodeBuffer input(original->cursor(), original_remaining); - VLOG(2) << "DecodeSegmentsAndValidate with SelectOne"; - VERIFY_SUCCESS(DecodeSegmentsAndValidate(&input, SelectOne(), validator)) - << "\nFailed with SelectOne; input.Offset=" << input.Offset() - << "; input.Remaining=" << input.Remaining(); - VERIFY_EQ(first_consumed, input.Offset()) << "\nFailed with SelectOne"; - } - if (original_remaining <= 20) { - // Decode again, one or zero bytes at a time. - DecodeBuffer input(original->cursor(), original_remaining); - VLOG(2) << "DecodeSegmentsAndValidate with SelectZeroAndOne"; - VERIFY_SUCCESS(DecodeSegmentsAndValidate( - &input, SelectZeroAndOne(return_non_zero_on_first), validator)) - << "\nFailed with SelectZeroAndOne"; - VERIFY_EQ(first_consumed, input.Offset()) - << "\nFailed with SelectZeroAndOne; input.Offset=" << input.Offset() - << "; input.Remaining=" << input.Remaining(); - } - { - // Decode again, with randomly selected segment sizes. - DecodeBuffer input(original->cursor(), original_remaining); - VLOG(2) << "DecodeSegmentsAndValidate with SelectRandom"; - VERIFY_SUCCESS(DecodeSegmentsAndValidate( - &input, SelectRandom(return_non_zero_on_first), validator)) - << "\nFailed with SelectRandom; input.Offset=" << input.Offset() - << "; input.Remaining=" << input.Remaining(); - VERIFY_EQ(first_consumed, input.Offset()) << "\nFailed with SelectRandom"; - } - VERIFY_EQ(original_remaining, original->Remaining()); - original->AdvanceCursor(first_consumed); - VLOG(1) << "DecodeAndValidateSeveralWays - SUCCESS"; - return ::testing::AssertionSuccess(); -} - -// static -RandomDecoderTest::SelectSize RandomDecoderTest::SelectZeroAndOne( - bool return_non_zero_on_first) { - std::shared_ptr<bool> zero_next(new bool); - *zero_next = !return_non_zero_on_first; - return [zero_next](bool first, size_t offset, size_t remaining) -> size_t { - if (*zero_next) { - *zero_next = false; - return 0; - } else { - *zero_next = true; - return 1; - } - }; -} - -RandomDecoderTest::SelectSize RandomDecoderTest::SelectRandom( - bool return_non_zero_on_first) { - return [this, return_non_zero_on_first](bool first, size_t offset, - size_t remaining) -> size_t { - uint32_t r = random_.Rand32(); - if (first && return_non_zero_on_first) { - CHECK_LT(0u, remaining); - if (remaining == 1) { - return 1; - } - return 1 + (r % remaining); // size in range [1, remaining). - } - return r % (remaining + 1); // size in range [0, remaining]. - }; -} - -uint32_t RandomDecoderTest::RandStreamId() { - return random_.Rand32() & StreamIdMask(); -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/tools/random_decoder_test.h b/net/third_party/http2/tools/random_decoder_test.h deleted file mode 100644 index d3bfcc7..0000000 --- a/net/third_party/http2/tools/random_decoder_test.h +++ /dev/null
@@ -1,258 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_TOOLS_RANDOM_DECODER_TEST_H_ -#define NET_THIRD_PARTY_HTTP2_TOOLS_RANDOM_DECODER_TEST_H_ - -// RandomDecoderTest is a base class for tests of decoding various kinds -// of HTTP/2 and HPACK encodings. - -// TODO(jamessynge): Move more methods into .cc file. - -#include <stddef.h> - -#include <cstdint> -#include <functional> -#include <memory> -#include <type_traits> - -#include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/platform/api/http2_string_piece.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" -#include "net/third_party/http2/test_tools/http2_random.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace http2 { -namespace test { - -// Some helpers. - -template <typename T, size_t N> -Http2StringPiece ToStringPiece(T (&data)[N]) { - return Http2StringPiece(reinterpret_cast<const char*>(data), N * sizeof(T)); -} - -// Overwrite the enum with some random value, probably not a valid value for -// the enum type, but which fits into its storage. -template <typename T, - typename E = typename std::enable_if<std::is_enum<T>::value>::type> -void CorruptEnum(T* out, Http2Random* rng) { - // Per cppreference.com, if the destination type of a static_cast is - // smaller than the source type (i.e. type of r and uint32 below), the - // resulting value is the smallest unsigned value equal to the source value - // modulo 2^n, where n is the number of bits used to represent the - // destination type unsigned U. - using underlying_type_T = typename std::underlying_type<T>::type; - using unsigned_underlying_type_T = - typename std::make_unsigned<underlying_type_T>::type; - auto r = static_cast<unsigned_underlying_type_T>(rng->Rand32()); - *out = static_cast<T>(r); -} - -// Base class for tests of the ability to decode a sequence of bytes with -// various boundaries between the DecodeBuffers provided to the decoder. -class RandomDecoderTest : public ::testing::Test { - public: - // SelectSize returns the size of the next DecodeBuffer to be passed to the - // decoder. Note that RandomDecoderTest allows that size to be zero, though - // some decoders can't deal with that on the first byte, hence the |first| - // parameter. - typedef std::function<size_t(bool first, size_t offset, size_t remaining)> - SelectSize; - - // Validator returns an AssertionResult so test can do: - // EXPECT_THAT(DecodeAndValidate(..., validator)); - typedef ::testing::AssertionResult AssertionResult; - typedef std::function<AssertionResult(const DecodeBuffer& input, - DecodeStatus status)> - Validator; - typedef std::function<AssertionResult()> NoArgValidator; - - RandomDecoderTest(); - - protected: - // TODO(jamessynge): Modify StartDecoding, etc. to (somehow) return - // AssertionResult so that the VERIFY_* methods exported from - // gunit_helpers.h can be widely used. - - // Start decoding; call allows sub-class to Reset the decoder, or deal with - // the first byte if that is done in a unique fashion. Might be called with - // a zero byte buffer. - virtual DecodeStatus StartDecoding(DecodeBuffer* db) = 0; - - // Resume decoding of the input after a prior call to StartDecoding, and - // possibly many calls to ResumeDecoding. - virtual DecodeStatus ResumeDecoding(DecodeBuffer* db) = 0; - - // Return true if a decode status of kDecodeDone indicates that - // decoding should stop. - virtual bool StopDecodeOnDone(); - - // Decode buffer |original| until we run out of input, or kDecodeDone is - // returned by the decoder AND StopDecodeOnDone() returns true. Segments - // (i.e. cuts up) the original DecodeBuffer into (potentially) smaller buffers - // by calling |select_size| to decide how large each buffer should be. - // We do this to test the ability to deal with arbitrary boundaries, as might - // happen in transport. - // Returns the final DecodeStatus. - DecodeStatus DecodeSegments(DecodeBuffer* original, - const SelectSize& select_size); - - // Decode buffer |original| until we run out of input, or kDecodeDone is - // returned by the decoder AND StopDecodeOnDone() returns true. Segments - // (i.e. cuts up) the original DecodeBuffer into (potentially) smaller buffers - // by calling |select_size| to decide how large each buffer should be. - // We do this to test the ability to deal with arbitrary boundaries, as might - // happen in transport. - // Invokes |validator| with the final decode status and the original decode - // buffer, with the cursor advanced as far as has been consumed by the decoder - // and returns validator's result. - ::testing::AssertionResult DecodeSegmentsAndValidate( - DecodeBuffer* original, - const SelectSize& select_size, - const Validator& validator) { - DecodeStatus status = DecodeSegments(original, select_size); - VERIFY_AND_RETURN_SUCCESS(validator(*original, status)); - } - - // Returns a SelectSize function for fast decoding, i.e. passing all that - // is available to the decoder. - static SelectSize SelectRemaining() { - return [](bool first, size_t offset, size_t remaining) -> size_t { - return remaining; - }; - } - - // Returns a SelectSize function for decoding a single byte at a time. - static SelectSize SelectOne() { - return - [](bool first, size_t offset, size_t remaining) -> size_t { return 1; }; - } - - // Returns a SelectSize function for decoding a single byte at a time, where - // zero byte buffers are also allowed. Alternates between zero and one. - static SelectSize SelectZeroAndOne(bool return_non_zero_on_first); - - // Returns a SelectSize function for decoding random sized segments. - SelectSize SelectRandom(bool return_non_zero_on_first); - - // Decode |original| multiple times, with different segmentations of the - // decode buffer, validating after each decode, and confirming that they - // each decode the same amount. Returns on the first failure, else returns - // success. - AssertionResult DecodeAndValidateSeveralWays(DecodeBuffer* original, - bool return_non_zero_on_first, - const Validator& validator); - - static Validator ToValidator(std::nullptr_t) { - return [](const DecodeBuffer& input, DecodeStatus status) { - return ::testing::AssertionSuccess(); - }; - } - - static Validator ToValidator(const Validator& validator) { - if (validator == nullptr) { - return ToValidator(nullptr); - } - return validator; - } - - static Validator ToValidator(const NoArgValidator& validator) { - if (validator == nullptr) { - return ToValidator(nullptr); - } - return [validator](const DecodeBuffer& input, DecodeStatus status) { - return validator(); - }; - } - - // Wraps a validator with another validator - // that first checks that the DecodeStatus is kDecodeDone and - // that the DecodeBuffer is empty. - // TODO(jamessynge): Replace this overload with the next, as using this method - // usually means that the wrapped function doesn't need to be passed the - // DecodeBuffer nor the DecodeStatus. - static Validator ValidateDoneAndEmpty(const Validator& wrapped) { - return [wrapped](const DecodeBuffer& input, - DecodeStatus status) -> AssertionResult { - VERIFY_EQ(status, DecodeStatus::kDecodeDone); - VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset(); - if (wrapped) { - return wrapped(input, status); - } - return ::testing::AssertionSuccess(); - }; - } - static Validator ValidateDoneAndEmpty(NoArgValidator wrapped) { - return [wrapped](const DecodeBuffer& input, - DecodeStatus status) -> AssertionResult { - VERIFY_EQ(status, DecodeStatus::kDecodeDone); - VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset(); - if (wrapped) { - return wrapped(); - } - return ::testing::AssertionSuccess(); - }; - } - static Validator ValidateDoneAndEmpty() { - NoArgValidator validator; - return ValidateDoneAndEmpty(validator); - } - - // Wraps a validator with another validator - // that first checks that the DecodeStatus is kDecodeDone and - // that the DecodeBuffer has the expected offset. - // TODO(jamessynge): Replace this overload with the next, as using this method - // usually means that the wrapped function doesn't need to be passed the - // DecodeBuffer nor the DecodeStatus. - static Validator ValidateDoneAndOffset(uint32_t offset, - const Validator& wrapped) { - return [wrapped, offset](const DecodeBuffer& input, - DecodeStatus status) -> AssertionResult { - VERIFY_EQ(status, DecodeStatus::kDecodeDone); - VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining(); - if (wrapped) { - return wrapped(input, status); - } - return ::testing::AssertionSuccess(); - }; - } - static Validator ValidateDoneAndOffset(uint32_t offset, - NoArgValidator wrapped) { - return [wrapped, offset](const DecodeBuffer& input, - DecodeStatus status) -> AssertionResult { - VERIFY_EQ(status, DecodeStatus::kDecodeDone); - VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining(); - if (wrapped) { - return wrapped(); - } - return ::testing::AssertionSuccess(); - }; - } - static Validator ValidateDoneAndOffset(uint32_t offset) { - NoArgValidator validator; - return ValidateDoneAndOffset(offset, validator); - } - - // Expose |random_| as Http2Random so callers don't have to care about which - // sub-class of Http2Random is used, nor can they rely on the specific - // sub-class that RandomDecoderTest uses. - Http2Random& Random() { return random_; } - Http2Random* RandomPtr() { return &random_; } - - uint32_t RandStreamId(); - - bool stop_decode_on_done_ = true; - - private: - Http2Random random_; -}; - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_TOOLS_RANDOM_DECODER_TEST_H_
diff --git a/net/third_party/http2/tools/random_util.cc b/net/third_party/http2/tools/random_util.cc deleted file mode 100644 index 6449b6b..0000000 --- a/net/third_party/http2/tools/random_util.cc +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2016 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 "net/third_party/http2/tools/random_util.h" - -#include <cmath> - -namespace http2 { -namespace test { - -// Here "word" means something that starts with a lower-case letter, and has -// zero or more additional characters that are numbers or lower-case letters. -Http2String GenerateHttp2HeaderName(size_t len, Http2Random* rng) { - Http2StringPiece alpha_lc = "abcdefghijklmnopqrstuvwxyz"; - // If the name is short, just make it one word. - if (len < 8) { - return rng->RandStringWithAlphabet(len, alpha_lc); - } - // If the name is longer, ensure it starts with a word, and after that may - // have any character in alphanumdash_lc. 4 is arbitrary, could be as low - // as 1. - Http2StringPiece alphanumdash_lc = "abcdefghijklmnopqrstuvwxyz0123456789-"; - return rng->RandStringWithAlphabet(4, alpha_lc) + - rng->RandStringWithAlphabet(len - 4, alphanumdash_lc); -} - -Http2String GenerateWebSafeString(size_t len, Http2Random* rng) { - static const char* kWebsafe64 = - "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"; - return rng->RandStringWithAlphabet(len, kWebsafe64); -} - -Http2String GenerateWebSafeString(size_t lo, size_t hi, Http2Random* rng) { - return GenerateWebSafeString(rng->UniformInRange(lo, hi), rng); -} - -} // namespace test -} // namespace http2
diff --git a/net/third_party/http2/tools/random_util.h b/net/third_party/http2/tools/random_util.h deleted file mode 100644 index 90bb6ed..0000000 --- a/net/third_party/http2/tools/random_util.h +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2016 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 NET_THIRD_PARTY_HTTP2_TOOLS_RANDOM_UTIL_H_ -#define NET_THIRD_PARTY_HTTP2_TOOLS_RANDOM_UTIL_H_ - -#include <stddef.h> - -#include "net/third_party/http2/platform/api/http2_string.h" -#include "net/third_party/http2/test_tools/http2_random.h" - -namespace http2 { -namespace test { - -// Generate a string with the allowed character set for HTTP/2 / HPACK header -// names. -Http2String GenerateHttp2HeaderName(size_t len, Http2Random* rng); - -// Generate a string with the web-safe string character set of specified len. -Http2String GenerateWebSafeString(size_t len, Http2Random* rng); - -// Generate a string with the web-safe string character set of length [lo, hi). -Http2String GenerateWebSafeString(size_t lo, size_t hi, Http2Random* rng); - -} // namespace test -} // namespace http2 - -#endif // NET_THIRD_PARTY_HTTP2_TOOLS_RANDOM_UTIL_H_
diff --git a/net/third_party/quic/core/qpack/qpack_decoder.cc b/net/third_party/quic/core/qpack/qpack_decoder.cc index 284ac35..3e94dd7e 100644 --- a/net/third_party/quic/core/qpack/qpack_decoder.cc +++ b/net/third_party/quic/core/qpack/qpack_decoder.cc
@@ -5,9 +5,9 @@ #include "net/third_party/quic/core/qpack/qpack_decoder.h" #include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" #include "net/third_party/quic/core/qpack/qpack_constants.h" +#include "net/third_party/quiche/src/http2/decoder/decode_buffer.h" +#include "net/third_party/quiche/src/http2/decoder/decode_status.h" namespace quic {
diff --git a/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.cc b/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.cc index 45a3b8d..7e8dd04 100644 --- a/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.cc +++ b/net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.cc
@@ -4,9 +4,9 @@ #include "net/third_party/quic/core/qpack/qpack_encoder_stream_receiver.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" #include "net/third_party/quic/core/qpack/qpack_constants.h" +#include "net/third_party/quiche/src/http2/decoder/decode_buffer.h" +#include "net/third_party/quiche/src/http2/decoder/decode_status.h" namespace quic {
diff --git a/net/third_party/quic/core/qpack/qpack_instruction_decoder.h b/net/third_party/quic/core/qpack/qpack_instruction_decoder.h index 69c4d85e..e462710 100644 --- a/net/third_party/quic/core/qpack/qpack_instruction_decoder.h +++ b/net/third_party/quic/core/qpack/qpack_instruction_decoder.h
@@ -7,12 +7,12 @@ #include <cstddef> -#include "net/third_party/http2/hpack/huffman/hpack_huffman_decoder.h" -#include "net/third_party/http2/hpack/varint/hpack_varint_decoder.h" #include "net/third_party/quic/core/qpack/qpack_constants.h" #include "net/third_party/quic/platform/api/quic_export.h" #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_string_piece.h" +#include "net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder.h" +#include "net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.h" namespace quic {
diff --git a/net/third_party/quic/core/qpack/qpack_instruction_encoder.cc b/net/third_party/quic/core/qpack/qpack_instruction_encoder.cc index 9446c53..44bbeb86 100644 --- a/net/third_party/quic/core/qpack/qpack_instruction_encoder.cc +++ b/net/third_party/quic/core/qpack/qpack_instruction_encoder.cc
@@ -5,8 +5,8 @@ #include "net/third_party/quic/core/qpack/qpack_instruction_encoder.h" #include "base/logging.h" -#include "net/third_party/http2/hpack/huffman/hpack_huffman_encoder.h" #include "net/third_party/quic/platform/api/quic_string_utils.h" +#include "net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder.h" namespace quic {
diff --git a/net/third_party/quic/core/qpack/qpack_instruction_encoder.h b/net/third_party/quic/core/qpack/qpack_instruction_encoder.h index f9f6eeb..39dc4f8 100644 --- a/net/third_party/quic/core/qpack/qpack_instruction_encoder.h +++ b/net/third_party/quic/core/qpack/qpack_instruction_encoder.h
@@ -7,11 +7,11 @@ #include <cstddef> -#include "net/third_party/http2/hpack/varint/hpack_varint_encoder.h" #include "net/third_party/quic/core/qpack/qpack_constants.h" #include "net/third_party/quic/platform/api/quic_export.h" #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/api/quic_string_piece.h" +#include "net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder.h" namespace quic {
diff --git a/net/third_party/quic/core/quic_connection.cc b/net/third_party/quic/core/quic_connection.cc index 8d8c11e..c40d34d 100644 --- a/net/third_party/quic/core/quic_connection.cc +++ b/net/third_party/quic/core/quic_connection.cc
@@ -1182,6 +1182,7 @@ } bool QuicConnection::OnPathResponseFrame(const QuicPathResponseFrame& frame) { + should_last_packet_instigate_acks_ = true; if (!transmitted_connectivity_probe_payload_ || *transmitted_connectivity_probe_payload_ != frame.data_buffer) { // Is not for the probe we sent, ignore it. @@ -1190,7 +1191,6 @@ // Have received the matching PATH RESPONSE, saved payload no longer valid. transmitted_connectivity_probe_payload_ = nullptr; UpdatePacketContent(FIRST_FRAME_IS_PING); - should_last_packet_instigate_acks_ = true; return true; }
diff --git a/net/third_party/spdy/core/hpack/hpack_decoder_adapter.cc b/net/third_party/spdy/core/hpack/hpack_decoder_adapter.cc index f91de28..bce4b36 100644 --- a/net/third_party/spdy/core/hpack/hpack_decoder_adapter.cc +++ b/net/third_party/spdy/core/hpack/hpack_decoder_adapter.cc
@@ -5,8 +5,8 @@ #include "net/third_party/spdy/core/hpack/hpack_decoder_adapter.h" #include "base/logging.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" +#include "net/third_party/quiche/src/http2/decoder/decode_buffer.h" +#include "net/third_party/quiche/src/http2/decoder/decode_status.h" #include "net/third_party/spdy/platform/api/spdy_estimate_memory_usage.h" using ::http2::DecodeBuffer;
diff --git a/net/third_party/spdy/core/hpack/hpack_decoder_adapter.h b/net/third_party/spdy/core/hpack/hpack_decoder_adapter.h index 5048b46..9cbd7828 100644 --- a/net/third_party/spdy/core/hpack/hpack_decoder_adapter.h +++ b/net/third_party/spdy/core/hpack/hpack_decoder_adapter.h
@@ -14,11 +14,11 @@ #include <memory> #include "base/macros.h" -#include "net/third_party/http2/hpack/decoder/hpack_decoder.h" -#include "net/third_party/http2/hpack/decoder/hpack_decoder_listener.h" -#include "net/third_party/http2/hpack/decoder/hpack_decoder_tables.h" -#include "net/third_party/http2/hpack/hpack_string.h" -#include "net/third_party/http2/hpack/http2_hpack_constants.h" +#include "net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h" +#include "net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_listener.h" +#include "net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.h" +#include "net/third_party/quiche/src/http2/hpack/hpack_string.h" +#include "net/third_party/quiche/src/http2/hpack/http2_hpack_constants.h" #include "net/third_party/spdy/core/hpack/hpack_header_table.h" #include "net/third_party/spdy/core/spdy_header_block.h" #include "net/third_party/spdy/core/spdy_headers_handler_interface.h"
diff --git a/net/third_party/spdy/core/hpack/hpack_decoder_adapter_test.cc b/net/third_party/spdy/core/hpack/hpack_decoder_adapter_test.cc index 67a47324..b749748 100644 --- a/net/third_party/spdy/core/hpack/hpack_decoder_adapter_test.cc +++ b/net/third_party/spdy/core/hpack/hpack_decoder_adapter_test.cc
@@ -14,10 +14,10 @@ #include "base/logging.h" #include "base/strings/string_number_conversions.h" -#include "net/third_party/http2/hpack/decoder/hpack_decoder_state.h" -#include "net/third_party/http2/hpack/decoder/hpack_decoder_tables.h" -#include "net/third_party/http2/hpack/tools/hpack_block_builder.h" -#include "net/third_party/http2/test_tools/http2_random.h" +#include "net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h" +#include "net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.h" +#include "net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder.h" +#include "net/third_party/quiche/src/http2/test_tools/http2_random.h" #include "net/third_party/spdy/core/hpack/hpack_constants.h" #include "net/third_party/spdy/core/hpack/hpack_encoder.h" #include "net/third_party/spdy/core/hpack/hpack_output_stream.h" @@ -701,9 +701,10 @@ // RFC 7541, Section C.4: Request Examples with Huffman Coding // http://httpwg.org/specs/rfc7541.html#rfc.section.C.4 TEST_P(HpackDecoderAdapterTest, SectionC4RequestHuffmanExamples) { - // TODO(jamessynge): Use net/third_party/http2/hpack/tools/hpack_example.h to - // parse the example directly, instead of having it as a comment. - // 82 | == Indexed - Add == + // TODO(jamessynge): Use + // net/third_party/quiche/src/http2/hpack/tools/hpack_example.h to parse the + // example directly, instead of having it as a comment. 82 | == Indexed - Add + // == // | idx = 2 // | -> :method: GET // 86 | == Indexed - Add ==
diff --git a/net/third_party/spdy/core/hpack/hpack_huffman_table_test.cc b/net/third_party/spdy/core/hpack/hpack_huffman_table_test.cc index de13d2a8..35757546 100644 --- a/net/third_party/spdy/core/hpack/hpack_huffman_table_test.cc +++ b/net/third_party/spdy/core/hpack/hpack_huffman_table_test.cc
@@ -7,7 +7,7 @@ #include <utility> #include "base/macros.h" -#include "net/third_party/http2/hpack/huffman/hpack_huffman_decoder.h" +#include "net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder.h" #include "net/third_party/spdy/core/hpack/hpack_constants.h" #include "net/third_party/spdy/core/hpack/hpack_output_stream.h" #include "net/third_party/spdy/platform/api/spdy_arraysize.h"
diff --git a/net/third_party/spdy/core/http2_frame_decoder_adapter.cc b/net/third_party/spdy/core/http2_frame_decoder_adapter.cc index 7d9c3a9..e1faaf0 100644 --- a/net/third_party/spdy/core/http2_frame_decoder_adapter.cc +++ b/net/third_party/spdy/core/http2_frame_decoder_adapter.cc
@@ -18,13 +18,13 @@ #include "base/logging.h" #include "base/sys_byteorder.h" #include "build/build_config.h" -#include "net/third_party/http2/decoder/decode_buffer.h" -#include "net/third_party/http2/decoder/decode_status.h" -#include "net/third_party/http2/decoder/http2_frame_decoder.h" -#include "net/third_party/http2/decoder/http2_frame_decoder_listener.h" -#include "net/third_party/http2/http2_constants.h" -#include "net/third_party/http2/http2_structures.h" -#include "net/third_party/http2/platform/api/http2_string.h" +#include "net/third_party/quiche/src/http2/decoder/decode_buffer.h" +#include "net/third_party/quiche/src/http2/decoder/decode_status.h" +#include "net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h" +#include "net/third_party/quiche/src/http2/decoder/http2_frame_decoder_listener.h" +#include "net/third_party/quiche/src/http2/http2_constants.h" +#include "net/third_party/quiche/src/http2/http2_structures.h" +#include "net/third_party/quiche/src/http2/platform/api/http2_string.h" #include "net/third_party/spdy/core/hpack/hpack_decoder_adapter.h" #include "net/third_party/spdy/core/hpack/hpack_header_table.h" #include "net/third_party/spdy/core/spdy_alt_svc_wire_format.h"
diff --git a/net/third_party/spdy/core/http2_frame_decoder_adapter.h b/net/third_party/spdy/core/http2_frame_decoder_adapter.h index fcdada9a..10a5a4e 100644 --- a/net/third_party/spdy/core/http2_frame_decoder_adapter.h +++ b/net/third_party/spdy/core/http2_frame_decoder_adapter.h
@@ -11,7 +11,7 @@ #include <memory> #include "base/optional.h" -#include "net/third_party/http2/decoder/http2_frame_decoder.h" +#include "net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h" #include "net/third_party/spdy/core/hpack/hpack_decoder_adapter.h" #include "net/third_party/spdy/core/hpack/hpack_header_table.h" #include "net/third_party/spdy/core/spdy_alt_svc_wire_format.h"
diff --git a/net/third_party/spdy/core/spdy_deframer_visitor.cc b/net/third_party/spdy/core/spdy_deframer_visitor.cc index 2ebb805..2545b3b 100644 --- a/net/third_party/spdy/core/spdy_deframer_visitor.cc +++ b/net/third_party/spdy/core/spdy_deframer_visitor.cc
@@ -32,8 +32,8 @@ enum class HeaderDirection { REQUEST, RESPONSE }; // Types of HTTP/2 frames, per RFC 7540. -// TODO(jamessynge): Switch to using //net/third_party/http2/http2_constants.h -// when ready. +// TODO(jamessynge): Switch to using +// //net/third_party/quiche/src/http2/http2_constants.h when ready. enum Http2FrameType { DATA = 0, HEADERS = 1, @@ -52,8 +52,8 @@ UNKNOWN = -2, }; -// TODO(jamessynge): Switch to using //net/third_party/http2/http2_constants.h -// when ready. +// TODO(jamessynge): Switch to using +// //net/third_party/quiche/src/http2/http2_constants.h when ready. const char* Http2FrameTypeToString(Http2FrameType v) { switch (v) { case DATA: @@ -87,8 +87,8 @@ } } -// TODO(jamessynge): Switch to using //net/third_party/http2/http2_constants.h -// when ready. +// TODO(jamessynge): Switch to using +// //net/third_party/quiche/src/http2/http2_constants.h when ready. inline std::ostream& operator<<(std::ostream& out, Http2FrameType v) { return out << Http2FrameTypeToString(v); } @@ -97,8 +97,8 @@ // (see https://httpwg.github.io/specs/rfc7540.html#FrameHeader for details on // the fixed 9-octet header structure shared by all frames). // Flag bits are only valid for specified frame types. -// TODO(jamessynge): Switch to using //net/third_party/http2/http2_constants.h -// when ready. +// TODO(jamessynge): Switch to using +// //net/third_party/quiche/src/http2/http2_constants.h when ready. enum Http2HeaderFlag { NO_FLAGS = 0, @@ -110,8 +110,8 @@ }; // Returns name of frame type. -// TODO(jamessynge): Switch to using //net/third_party/http2/http2_constants.h -// when ready. +// TODO(jamessynge): Switch to using +// //net/third_party/quiche/src/http2/http2_constants.h when ready. const char* Http2FrameTypeToString(Http2FrameType v); void SpdyDeframerVisitorInterface::OnPingAck(
diff --git a/net/third_party/spdy/core/spdy_test_utils.h b/net/third_party/spdy/core/spdy_test_utils.h index 7de9ec8e..d0b2346 100644 --- a/net/third_party/spdy/core/spdy_test_utils.h +++ b/net/third_party/spdy/core/spdy_test_utils.h
@@ -12,7 +12,7 @@ #include <memory> #include "net/test/gtest_util.h" -#include "net/third_party/http2/platform/api/http2_test_helpers.h" +#include "net/third_party/quiche/src/http2/platform/api/http2_test_helpers.h" #include "net/third_party/spdy/core/spdy_bug_tracker.h" #include "net/third_party/spdy/core/spdy_header_block.h" #include "net/third_party/spdy/core/spdy_headers_handler_interface.h"
diff --git a/net/url_request/redirect_info.cc b/net/url_request/redirect_info.cc index f7075073..258f642 100644 --- a/net/url_request/redirect_info.cc +++ b/net/url_request/redirect_info.cc
@@ -117,6 +117,7 @@ const std::string& original_method, const GURL& original_url, const GURL& original_site_for_cookies, + const base::Optional<url::Origin>& original_top_frame_origin, URLRequest::FirstPartyURLPolicy original_first_party_url_policy, URLRequest::ReferrerPolicy original_referrer_policy, const std::string& original_referrer, @@ -156,8 +157,13 @@ if (original_first_party_url_policy == URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT) { redirect_info.new_site_for_cookies = redirect_info.new_url; + if (original_top_frame_origin) { + redirect_info.new_top_frame_origin = + url::Origin::Create(redirect_info.new_url); + } } else { redirect_info.new_site_for_cookies = original_site_for_cookies; + redirect_info.new_top_frame_origin = original_top_frame_origin; } redirect_info.new_referrer_policy = ProcessReferrerPolicyHeaderOnRedirect(
diff --git a/net/url_request/redirect_info.h b/net/url_request/redirect_info.h index d461115..c8ce8e5c 100644 --- a/net/url_request/redirect_info.h +++ b/net/url_request/redirect_info.h
@@ -28,6 +28,7 @@ const std::string& original_method, const GURL& original_url, const GURL& original_site_for_cookies, + const base::Optional<url::Origin>& original_top_frame_origin, URLRequest::FirstPartyURLPolicy original_first_party_url_policy, URLRequest::ReferrerPolicy original_referrer_policy, const std::string& original_referrer, @@ -63,6 +64,8 @@ // The new first-party URL for cookies. GURL new_site_for_cookies; + base::Optional<url::Origin> new_top_frame_origin; + // The new HTTP referrer header. std::string new_referrer;
diff --git a/net/url_request/redirect_info_unittest.cc b/net/url_request/redirect_info_unittest.cc index 01a307e6..cefc3a7b 100644 --- a/net/url_request/redirect_info_unittest.cc +++ b/net/url_request/redirect_info_unittest.cc
@@ -30,6 +30,7 @@ const GURL kOriginalUrl = GURL("https://foo.test/original"); const GURL kOriginalSiteForCookies = GURL("https://foo.test/"); + const url::Origin kOriginalTopFrameOrigin = url::Origin::Create(kOriginalUrl); const URLRequest::FirstPartyURLPolicy kOriginalFirstPartyUrlPolicy = net::URLRequest::NEVER_CHANGE_FIRST_PARTY_URL; const URLRequest::ReferrerPolicy kOriginalReferrerPolicy = @@ -46,10 +47,10 @@ RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo( test.original_method, kOriginalUrl, kOriginalSiteForCookies, - kOriginalFirstPartyUrlPolicy, kOriginalReferrerPolicy, - kOriginalReferrer, nullptr /* response_headers */, - test.http_status_code, kNewLocation, kInsecureSchemeWasUpgraded, - kCopyFragment); + kOriginalTopFrameOrigin, kOriginalFirstPartyUrlPolicy, + kOriginalReferrerPolicy, kOriginalReferrer, + nullptr /* response_headers */, test.http_status_code, kNewLocation, + kInsecureSchemeWasUpgraded, kCopyFragment); EXPECT_EQ(test.expected_new_method, redirect_info.new_method); EXPECT_EQ(test.http_status_code, redirect_info.status_code); @@ -97,12 +98,15 @@ RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo( KOriginalMethod, GURL(test.original_url), kOriginalSiteForCookies, + url::Origin::Create(GURL(test.original_url)), kOriginalFirstPartyUrlPolicy, kOriginalReferrerPolicy, kOriginalReferrer, nullptr /* response_headers */, kHttpStatusCode, GURL(test.new_location), kInsecureSchemeWasUpgraded, test.copy_fragment); EXPECT_EQ(GURL(test.expected_new_url), redirect_info.new_url); + EXPECT_EQ(url::Origin::Create(GURL(test.original_url)), + redirect_info.new_top_frame_origin); } } @@ -135,12 +139,19 @@ RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo( KOriginalMethod, kOriginalUrl, kOriginalSiteForCookies, - test.original_first_party_url_policy, kOriginalReferrerPolicy, - kOriginalReferrer, nullptr /* response_headers */, kHttpStatusCode, - kNewLocation, kInsecureSchemeWasUpgraded, kCopyFragment); + url::Origin::Create(kOriginalUrl), test.original_first_party_url_policy, + kOriginalReferrerPolicy, kOriginalReferrer, + nullptr /* response_headers */, kHttpStatusCode, kNewLocation, + kInsecureSchemeWasUpgraded, kCopyFragment); EXPECT_EQ(GURL(test.expected_new_site_for_cookies), redirect_info.new_site_for_cookies); + url::Origin expected_top_frame_origin = + test.original_first_party_url_policy == + URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT + ? url::Origin::Create(GURL(test.expected_new_site_for_cookies)) + : url::Origin::Create(kOriginalUrl); + EXPECT_EQ(expected_top_frame_origin, redirect_info.new_top_frame_origin); } } @@ -448,9 +459,9 @@ RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo( KOriginalMethod, original_url, kOriginalSiteForCookies, - kOriginalFirstPartyUrlPolicy, test.original_referrer_policy, - test.original_referrer, response_headers.get(), - response_headers->response_code(), new_location, + url::Origin::Create(original_url), kOriginalFirstPartyUrlPolicy, + test.original_referrer_policy, test.original_referrer, + response_headers.get(), response_headers->response_code(), new_location, kInsecureSchemeWasUpgraded, kCopyFragment); EXPECT_EQ(test.expected_new_referrer_policy,
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index c37e8c2..75b075e 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc
@@ -971,6 +971,7 @@ referrer_ = redirect_info.new_referrer; referrer_policy_ = redirect_info.new_referrer_policy; site_for_cookies_ = redirect_info.new_site_for_cookies; + top_frame_origin_ = redirect_info.new_top_frame_origin; url_chain_.push_back(redirect_info.new_url); --redirect_limit_;
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h index 12ce9b6..64fcb0c 100644 --- a/net/url_request/url_request.h +++ b/net/url_request/url_request.h
@@ -287,6 +287,15 @@ // This method may only be called before Start(). void set_site_for_cookies(const GURL& site_for_cookies); + // The origin of the top frame of the page making the request (where + // applicable). Note that this is experimental and may not always be set. + const base::Optional<url::Origin>& top_frame_origin() const { + return top_frame_origin_; + } + void set_top_frame_origin(const base::Optional<url::Origin>& origin) { + top_frame_origin_ = origin; + } + // Indicate whether SameSite cookies should be attached even though the // request is cross-site. bool attach_same_site_cookies() const { return attach_same_site_cookies_; } @@ -855,6 +864,8 @@ std::vector<GURL> url_chain_; GURL site_for_cookies_; + base::Optional<url::Origin> top_frame_origin_; + bool attach_same_site_cookies_; base::Optional<url::Origin> initiator_; GURL delegate_redirect_url_;
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc index fddd0be..2422a0b 100644 --- a/net/url_request/url_request_job.cc +++ b/net/url_request/url_request_job.cc
@@ -427,10 +427,10 @@ RedirectInfo redirect_info = RedirectInfo::ComputeRedirectInfo( request_->method(), request_->url(), request_->site_for_cookies(), - request_->first_party_url_policy(), request_->referrer_policy(), - request_->referrer(), request_->response_headers(), http_status_code, - new_location, insecure_scheme_was_upgraded, - CopyFragmentOnRedirect(new_location)); + request_->top_frame_origin(), request_->first_party_url_policy(), + request_->referrer_policy(), request_->referrer(), + request_->response_headers(), http_status_code, new_location, + insecure_scheme_was_upgraded, CopyFragmentOnRedirect(new_location)); bool defer_redirect = false; request_->NotifyReceivedRedirect(redirect_info, &defer_redirect);
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 5f63524..817ea50 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -8003,18 +8003,16 @@ GURL expected_url(http_test_server()->GetURL("/echo#fragment")); TestDelegate d; - { - std::unique_ptr<URLRequest> r(default_context().CreateRequest( - original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); + std::unique_ptr<URLRequest> r(default_context().CreateRequest( + original_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); - r->Start(); - d.RunUntilComplete(); + r->Start(); + d.RunUntilComplete(); - EXPECT_EQ(2U, r->url_chain().size()); - EXPECT_EQ(OK, d.request_status()); - EXPECT_EQ(original_url, r->original_url()); - EXPECT_EQ(expected_url, r->url()); - } + EXPECT_EQ(2U, r->url_chain().size()); + EXPECT_EQ(OK, d.request_status()); + EXPECT_EQ(original_url, r->original_url()); + EXPECT_EQ(expected_url, r->url()); } TEST_F(URLRequestTestHTTP, RedirectPreserveFirstPartyURL) { @@ -8024,18 +8022,54 @@ GURL first_party_url("http://example.com"); TestDelegate d; - { - std::unique_ptr<URLRequest> r(default_context().CreateRequest( - url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); - r->set_site_for_cookies(first_party_url); + std::unique_ptr<URLRequest> r(default_context().CreateRequest( + url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); + r->set_site_for_cookies(first_party_url); - r->Start(); - d.RunUntilComplete(); + r->Start(); + d.RunUntilComplete(); - EXPECT_EQ(2U, r->url_chain().size()); - EXPECT_EQ(OK, d.request_status()); - EXPECT_EQ(first_party_url, r->site_for_cookies()); - } + EXPECT_EQ(2U, r->url_chain().size()); + EXPECT_EQ(OK, d.request_status()); + EXPECT_EQ(first_party_url, r->site_for_cookies()); +} + +TEST_F(URLRequestTestHTTP, RedirectPreserveTopFrameOrigin) { + ASSERT_TRUE(http_test_server()->Start()); + + GURL url(http_test_server()->GetURL("/redirect302-to-echo")); + url::Origin top_frame_origin = + url::Origin::Create(GURL("http://example.com")); + TestDelegate d; + + std::unique_ptr<URLRequest> r(default_context().CreateRequest( + url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); + r->set_top_frame_origin(top_frame_origin); + + r->Start(); + d.RunUntilComplete(); + + EXPECT_EQ(2U, r->url_chain().size()); + EXPECT_EQ(OK, d.request_status()); + EXPECT_EQ(top_frame_origin, *r->top_frame_origin()); +} + +TEST_F(URLRequestTestHTTP, RedirectPreserveUnsetTopFrameOrigin) { + ASSERT_TRUE(http_test_server()->Start()); + + GURL url(http_test_server()->GetURL("/redirect302-to-echo")); + TestDelegate d; + + std::unique_ptr<URLRequest> r(default_context().CreateRequest( + url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); + // Since we're not setting a top frame origin, we wouldn't expect one after + // the redirect. + r->Start(); + d.RunUntilComplete(); + + EXPECT_EQ(2U, r->url_chain().size()); + EXPECT_EQ(OK, d.request_status()); + EXPECT_FALSE(r->top_frame_origin()); } TEST_F(URLRequestTestHTTP, RedirectUpdateFirstPartyURL) { @@ -8046,7 +8080,7 @@ GURL expected_first_party_url(http_test_server()->GetURL("/echo")); TestDelegate d; - { + std::unique_ptr<URLRequest> r(default_context().CreateRequest( url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); r->set_site_for_cookies(original_first_party_url); @@ -8059,7 +8093,50 @@ EXPECT_EQ(2U, r->url_chain().size()); EXPECT_EQ(OK, d.request_status()); EXPECT_EQ(expected_first_party_url, r->site_for_cookies()); - } +} + +TEST_F(URLRequestTestHTTP, RedirectUpdateTopFrameOrigin) { + ASSERT_TRUE(http_test_server()->Start()); + + GURL url(http_test_server()->GetURL("/redirect302-to-echo")); + url::Origin original_top_frame_origin = + url::Origin::Create(GURL("http://example.com")); + url::Origin expected_top_frame_origin = + url::Origin::Create(GURL(http_test_server()->GetURL("/echo"))); + + TestDelegate d; + + std::unique_ptr<URLRequest> r(default_context().CreateRequest( + url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); + r->set_top_frame_origin(original_top_frame_origin); + r->set_first_party_url_policy(URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT); + + r->Start(); + d.RunUntilComplete(); + + EXPECT_EQ(2U, r->url_chain().size()); + EXPECT_EQ(OK, d.request_status()); + EXPECT_EQ(expected_top_frame_origin, *r->top_frame_origin()); +} + +TEST_F(URLRequestTestHTTP, RedirectIgnoreUnsetTopFrameOrigin) { + ASSERT_TRUE(http_test_server()->Start()); + + GURL url(http_test_server()->GetURL("/redirect302-to-echo")); + TestDelegate d; + + std::unique_ptr<URLRequest> r(default_context().CreateRequest( + url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS)); + // Since we're not setting a top frame origin, we wouldn't expect one after + // the redirect. + r->set_first_party_url_policy(URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT); + + r->Start(); + d.RunUntilComplete(); + + EXPECT_EQ(2U, r->url_chain().size()); + EXPECT_EQ(OK, d.request_status()); + EXPECT_FALSE(r->top_frame_origin()); } TEST_F(URLRequestTestHTTP, InterceptPost302RedirectGet) {
diff --git a/net/websockets/websocket_channel.cc b/net/websockets/websocket_channel.cc index 95dddd1..7b435771 100644 --- a/net/websockets/websocket_channel.cc +++ b/net/websockets/websocket_channel.cc
@@ -34,7 +34,6 @@ #include "net/websockets/websocket_frame.h" #include "net/websockets/websocket_handshake_request_info.h" #include "net/websockets/websocket_handshake_response_info.h" -#include "net/websockets/websocket_handshake_stream_create_helper.h" #include "net/websockets/websocket_stream.h" #include "url/origin.h" @@ -544,10 +543,8 @@ } socket_url_ = socket_url; auto connect_delegate = std::make_unique<ConnectDelegate>(this); - auto create_helper = std::make_unique<WebSocketHandshakeStreamCreateHelper>( - connect_delegate.get(), requested_subprotocols); stream_request_ = - callback.Run(socket_url_, std::move(create_helper), origin, + callback.Run(socket_url_, requested_subprotocols, origin, site_for_cookies, additional_headers, url_request_context_, NetLogWithSource(), std::move(connect_delegate)); SetState(CONNECTING);
diff --git a/net/websockets/websocket_channel.h b/net/websockets/websocket_channel.h index bf1d0c9..24a4426 100644 --- a/net/websockets/websocket_channel.h +++ b/net/websockets/websocket_channel.h
@@ -38,7 +38,6 @@ class URLRequestContext; struct WebSocketHandshakeRequestInfo; struct WebSocketHandshakeResponseInfo; -class WebSocketHandshakeStreamCreateHelper; // Transport-independent implementation of WebSockets. Implements protocol // semantics that do not depend on the underlying transport. Provides the @@ -51,7 +50,7 @@ // WebSocketStream::CreateAndConnectStream(). typedef base::Callback<std::unique_ptr<WebSocketStreamRequest>( const GURL&, - std::unique_ptr<WebSocketHandshakeStreamCreateHelper>, + const std::vector<std::string>&, const url::Origin&, const GURL&, const HttpRequestHeaders&,
diff --git a/net/websockets/websocket_channel_test.cc b/net/websockets/websocket_channel_test.cc index 90259e3..48500572 100644 --- a/net/websockets/websocket_channel_test.cc +++ b/net/websockets/websocket_channel_test.cc
@@ -38,7 +38,6 @@ #include "net/websockets/websocket_event_interface.h" #include "net/websockets/websocket_handshake_request_info.h" #include "net/websockets/websocket_handshake_response_info.h" -#include "net/websockets/websocket_handshake_stream_create_helper.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -743,7 +742,7 @@ struct WebSocketStreamCreationCallbackArgumentSaver { std::unique_ptr<WebSocketStreamRequest> Create( const GURL& socket_url, - std::unique_ptr<WebSocketHandshakeStreamCreateHelper> create_helper, + const std::vector<std::string>& requested_subprotocols, const url::Origin& origin, const GURL& site_for_cookies, const HttpRequestHeaders& additional_headers, @@ -751,21 +750,17 @@ const NetLogWithSource& net_log, std::unique_ptr<WebSocketStream::ConnectDelegate> connect_delegate) { this->socket_url = socket_url; - this->create_helper = std::move(create_helper); this->origin = origin; this->site_for_cookies = site_for_cookies; this->url_request_context = url_request_context; - this->net_log = net_log; this->connect_delegate = std::move(connect_delegate); return std::make_unique<MockWebSocketStreamRequest>(); } GURL socket_url; - std::unique_ptr<WebSocketHandshakeStreamCreateHelper> create_helper; url::Origin origin; GURL site_for_cookies; URLRequestContext* url_request_context; - NetLogWithSource net_log; std::unique_ptr<WebSocketStream::ConnectDelegate> connect_delegate; };
diff --git a/net/websockets/websocket_handshake_stream_create_helper.cc b/net/websockets/websocket_handshake_stream_create_helper.cc index 6a09c212..5c25a0b 100644 --- a/net/websockets/websocket_handshake_stream_create_helper.cc +++ b/net/websockets/websocket_handshake_stream_create_helper.cc
@@ -16,11 +16,13 @@ WebSocketHandshakeStreamCreateHelper::WebSocketHandshakeStreamCreateHelper( WebSocketStream::ConnectDelegate* connect_delegate, - const std::vector<std::string>& requested_subprotocols) - : requested_subprotocols_(requested_subprotocols), - connect_delegate_(connect_delegate), - request_(nullptr) { + const std::vector<std::string>& requested_subprotocols, + WebSocketStreamRequestAPI* request) + : connect_delegate_(connect_delegate), + requested_subprotocols_(requested_subprotocols), + request_(request) { DCHECK(connect_delegate_); + DCHECK(request_); } WebSocketHandshakeStreamCreateHelper::~WebSocketHandshakeStreamCreateHelper() = @@ -31,8 +33,6 @@ std::unique_ptr<ClientSocketHandle> connection, bool using_proxy, WebSocketEndpointLockManager* websocket_endpoint_lock_manager) { - DCHECK(request_) << "set_request() must be called"; - // The list of supported extensions and parameters is hard-coded. // TODO(ricea): If more extensions are added, consider a more flexible // method. @@ -43,14 +43,12 @@ requested_subprotocols_, extensions, request_, websocket_endpoint_lock_manager); request_->OnBasicHandshakeStreamCreated(stream.get()); - return std::move(stream); + return stream; } std::unique_ptr<WebSocketHandshakeStreamBase> WebSocketHandshakeStreamCreateHelper::CreateHttp2Stream( base::WeakPtr<SpdySession> session) { - DCHECK(request_) << "set_request() must be called"; - std::vector<std::string> extensions( 1, "permessage-deflate; client_max_window_bits"); auto stream = std::make_unique<WebSocketHttp2HandshakeStream>(
diff --git a/net/websockets/websocket_handshake_stream_create_helper.h b/net/websockets/websocket_handshake_stream_create_helper.h index 74403399..eda441b0 100644 --- a/net/websockets/websocket_handshake_stream_create_helper.h +++ b/net/websockets/websocket_handshake_stream_create_helper.h
@@ -30,10 +30,11 @@ class NET_EXPORT_PRIVATE WebSocketHandshakeStreamCreateHelper : public WebSocketHandshakeStreamBase::CreateHelper { public: - // |connect_delegate| must out-live this object. - explicit WebSocketHandshakeStreamCreateHelper( + // |*connect_delegate| and |*request| must out-live this object. + WebSocketHandshakeStreamCreateHelper( WebSocketStream::ConnectDelegate* connect_delegate, - const std::vector<std::string>& requested_subprotocols); + const std::vector<std::string>& requested_subprotocols, + WebSocketStreamRequestAPI* request); ~WebSocketHandshakeStreamCreateHelper() override; @@ -49,21 +50,10 @@ std::unique_ptr<WebSocketHandshakeStreamBase> CreateHttp2Stream( base::WeakPtr<SpdySession> session) override; - // WebSocketHandshakeStreamCreateHelper methods - - // This method must be called before calling CreateBasicStream() - // or CreateHttp2Stream(). - // The |request| pointer must remain valid as long as this object exists. - void set_stream_request(WebSocketStreamRequestAPI* request) { - request_ = request; - } - private: + WebSocketStream::ConnectDelegate* const connect_delegate_; const std::vector<std::string> requested_subprotocols_; - - WebSocketStream::ConnectDelegate* connect_delegate_; - - WebSocketStreamRequestAPI* request_; + WebSocketStreamRequestAPI* const request_; DISALLOW_COPY_AND_ASSIGN(WebSocketHandshakeStreamCreateHelper); };
diff --git a/net/websockets/websocket_handshake_stream_create_helper_test.cc b/net/websockets/websocket_handshake_stream_create_helper_test.cc index 40f68bf7..3f985be 100644 --- a/net/websockets/websocket_handshake_stream_create_helper_test.cc +++ b/net/websockets/websocket_handshake_stream_create_helper_test.cc
@@ -131,9 +131,8 @@ const GURL url("wss://www.example.org/"); NetLogWithSource net_log; - WebSocketHandshakeStreamCreateHelper create_helper(&connect_delegate_, - sub_protocols); - create_helper.set_stream_request(&stream_request_); + WebSocketHandshakeStreamCreateHelper create_helper( + &connect_delegate_, sub_protocols, &stream_request_); switch (GetParam()) { case BASIC_HANDSHAKE_STREAM:
diff --git a/net/websockets/websocket_stream.cc b/net/websockets/websocket_stream.cc index 4334032..46e7a954 100644 --- a/net/websockets/websocket_stream.cc +++ b/net/websockets/websocket_stream.cc
@@ -106,12 +106,12 @@ public: WebSocketStreamRequestImpl( const GURL& url, + const std::vector<std::string>& requested_subprotocols, const URLRequestContext* context, const url::Origin& origin, const GURL& site_for_cookies, const HttpRequestHeaders& additional_headers, std::unique_ptr<WebSocketStream::ConnectDelegate> connect_delegate, - std::unique_ptr<WebSocketHandshakeStreamCreateHelper> create_helper, std::unique_ptr<WebSocketStreamRequestAPI> api_delegate) : delegate_(this), url_request_(context->CreateRequest(url, @@ -122,7 +122,6 @@ handshake_stream_(nullptr), perform_upgrade_has_been_called_(false), api_delegate_(std::move(api_delegate)) { - create_helper->set_stream_request(this); HttpRequestHeaders headers = additional_headers; headers.SetHeader(websockets::kUpgrade, websockets::kWebSocketLowercase); headers.SetHeader(HttpRequestHeaders::kConnection, websockets::kUpgrade); @@ -140,6 +139,8 @@ url_request_->set_initiator(origin); url_request_->set_site_for_cookies(site_for_cookies); + auto create_helper = std::make_unique<WebSocketHandshakeStreamCreateHelper>( + connect_delegate_.get(), requested_subprotocols, this); url_request_->SetUserData(kWebSocketHandshakeUserDataKey, std::move(create_helper)); url_request_->SetLoadFlags(LOAD_DISABLE_CACHE | LOAD_BYPASS_CACHE); @@ -468,7 +469,7 @@ std::unique_ptr<WebSocketStreamRequest> WebSocketStream::CreateAndConnectStream( const GURL& socket_url, - std::unique_ptr<WebSocketHandshakeStreamCreateHelper> create_helper, + const std::vector<std::string>& requested_subprotocols, const url::Origin& origin, const GURL& site_for_cookies, const HttpRequestHeaders& additional_headers, @@ -476,8 +477,8 @@ const NetLogWithSource& net_log, std::unique_ptr<ConnectDelegate> connect_delegate) { auto request = std::make_unique<WebSocketStreamRequestImpl>( - socket_url, url_request_context, origin, site_for_cookies, - additional_headers, std::move(connect_delegate), std::move(create_helper), + socket_url, requested_subprotocols, url_request_context, origin, + site_for_cookies, additional_headers, std::move(connect_delegate), nullptr); request->Start(std::make_unique<base::OneShotTimer>()); return std::move(request); @@ -486,7 +487,7 @@ std::unique_ptr<WebSocketStreamRequest> WebSocketStream::CreateAndConnectStreamForTesting( const GURL& socket_url, - std::unique_ptr<WebSocketHandshakeStreamCreateHelper> create_helper, + const std::vector<std::string>& requested_subprotocols, const url::Origin& origin, const GURL& site_for_cookies, const HttpRequestHeaders& additional_headers, @@ -496,8 +497,8 @@ std::unique_ptr<base::OneShotTimer> timer, std::unique_ptr<WebSocketStreamRequestAPI> api_delegate) { auto request = std::make_unique<WebSocketStreamRequestImpl>( - socket_url, url_request_context, origin, site_for_cookies, - additional_headers, std::move(connect_delegate), std::move(create_helper), + socket_url, requested_subprotocols, url_request_context, origin, + site_for_cookies, additional_headers, std::move(connect_delegate), std::move(api_delegate)); request->Start(std::move(timer)); return std::move(request);
diff --git a/net/websockets/websocket_stream.h b/net/websockets/websocket_stream.h index aa7585e8..51ebac9b 100644 --- a/net/websockets/websocket_stream.h +++ b/net/websockets/websocket_stream.h
@@ -43,7 +43,6 @@ struct WebSocketFrame; class WebSocketBasicHandshakeStream; class WebSocketHttp2HandshakeStream; -class WebSocketHandshakeStreamCreateHelper; // WebSocketStreamRequest is the caller's handle to the process of creation of a // WebSocketStream. Deleting the object before the ConnectDelegate OnSuccess or @@ -151,7 +150,7 @@ // it is safe to delete. static std::unique_ptr<WebSocketStreamRequest> CreateAndConnectStream( const GURL& socket_url, - std::unique_ptr<WebSocketHandshakeStreamCreateHelper> create_helper, + const std::vector<std::string>& requested_subprotocols, const url::Origin& origin, const GURL& site_for_cookies, const HttpRequestHeaders& additional_headers, @@ -166,7 +165,7 @@ static std::unique_ptr<WebSocketStreamRequest> CreateAndConnectStreamForTesting( const GURL& socket_url, - std::unique_ptr<WebSocketHandshakeStreamCreateHelper> create_helper, + const std::vector<std::string>& requested_subprotocols, const url::Origin& origin, const GURL& site_for_cookies, const HttpRequestHeaders& additional_headers,
diff --git a/net/websockets/websocket_stream_create_test_base.cc b/net/websockets/websocket_stream_create_test_base.cc index 10fcc9a..2a62ffd 100644 --- a/net/websockets/websocket_stream_create_test_base.cc +++ b/net/websockets/websocket_stream_create_test_base.cc
@@ -14,7 +14,6 @@ #include "net/websockets/websocket_basic_handshake_stream.h" #include "net/websockets/websocket_handshake_request_info.h" #include "net/websockets/websocket_handshake_response_info.h" -#include "net/websockets/websocket_handshake_stream_create_helper.h" #include "net/websockets/websocket_stream.h" #include "url/gurl.h" #include "url/origin.h" @@ -101,13 +100,11 @@ std::unique_ptr<base::OneShotTimer> timer) { auto connect_delegate = std::make_unique<TestConnectDelegate>( this, connect_run_loop_.QuitClosure()); - auto create_helper = std::make_unique<WebSocketHandshakeStreamCreateHelper>( - connect_delegate.get(), sub_protocols); auto api_delegate = std::make_unique<TestWebSocketStreamRequestAPI>(); stream_request_ = WebSocketStream::CreateAndConnectStreamForTesting( - socket_url, std::move(create_helper), origin, site_for_cookies, - additional_headers, url_request_context_host_.GetURLRequestContext(), - NetLogWithSource(), std::move(connect_delegate), + socket_url, sub_protocols, origin, site_for_cookies, additional_headers, + url_request_context_host_.GetURLRequestContext(), NetLogWithSource(), + std::move(connect_delegate), timer ? std::move(timer) : std::make_unique<base::OneShotTimer>(), std::move(api_delegate)); }
diff --git a/net/websockets/websocket_test_util.h b/net/websockets/websocket_test_util.h index 6328ad2..ef42219 100644 --- a/net/websockets/websocket_test_util.h +++ b/net/websockets/websocket_test_util.h
@@ -222,11 +222,9 @@ public: // Constructor for using dummy ConnectDelegate and WebSocketStreamRequestAPI. TestWebSocketHandshakeStreamCreateHelper() - : WebSocketHandshakeStreamCreateHelper( - &connect_delegate_, - std::vector<std::string>() /* requested_subprotocols */) { - WebSocketHandshakeStreamCreateHelper::set_stream_request(&request_); - } + : WebSocketHandshakeStreamCreateHelper(&connect_delegate_, + /* requested_subprotocols = */ {}, + &request_) {} ~TestWebSocketHandshakeStreamCreateHelper() override = default;
diff --git a/remoting/host/file_transfer/BUILD.gn b/remoting/host/file_transfer/BUILD.gn index 01d9206..1ce9896 100644 --- a/remoting/host/file_transfer/BUILD.gn +++ b/remoting/host/file_transfer/BUILD.gn
@@ -11,6 +11,8 @@ ] sources = [ + "buffered_file_writer.cc", + "buffered_file_writer.h", "local_file_operations.cc", ] @@ -24,6 +26,9 @@ testonly = true sources = [ + "buffered_file_writer_unittest.cc", + "fake_file_operations.cc", + "fake_file_operations.h", "local_file_operations_unittest.cc", ]
diff --git a/remoting/host/file_transfer/buffered_file_writer.cc b/remoting/host/file_transfer/buffered_file_writer.cc new file mode 100644 index 0000000..5021665 --- /dev/null +++ b/remoting/host/file_transfer/buffered_file_writer.cc
@@ -0,0 +1,143 @@ +// 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 "remoting/host/file_transfer/buffered_file_writer.h" +#include "base/bind.h" + +#include <utility> + +namespace remoting { + +BufferedFileWriter::BufferedFileWriter( + base::OnceClosure on_complete, + base::OnceCallback<void(protocol::FileTransfer_Error)> on_error) + : on_complete_(std::move(on_complete)), + on_error_(std::move(on_error)), + weak_ptr_factory_(this) {} + +BufferedFileWriter::~BufferedFileWriter() = default; + +void BufferedFileWriter::Start(FileOperations* file_operations, + const base::FilePath& filename) { + DCHECK_EQ(kNotStarted, state_); + SetState(kWorking); + file_operations->WriteFile( + filename, base::BindOnce(&BufferedFileWriter::OnWriteFileResult, + weak_ptr_factory_.GetWeakPtr())); +} + +void BufferedFileWriter::Write(std::string data) { + if (state_ == kFailed) { + return; + } + DCHECK(state_ == kWorking || state_ == kWaiting); + chunks_.push(std::move(data)); + + if (state_ == kWaiting) { + SetState(kWorking); + WriteNextChunk(); + } +} + +void BufferedFileWriter::Close() { + if (state_ == kFailed) { + return; + } + DCHECK(state_ == kWorking || state_ == kWaiting); + + State old_state = state_; + SetState(kClosing); + if (old_state != kWorking) { + DoClose(); + } +} + +void BufferedFileWriter::Cancel() { + SetState(kFailed); + // Will implicitly cancel if still in progress. + writer_.reset(); +} + +void BufferedFileWriter::OnWriteFileResult( + base::Optional<protocol::FileTransfer_Error> error, + std::unique_ptr<FileOperations::Writer> writer) { + writer_ = std::move(writer); + OnWriteResult(std::move(error)); +} + +void BufferedFileWriter::WriteNextChunk() { + DCHECK(!chunks_.empty()); + DCHECK(state_ == kWorking || state_ == kClosing); + std::string data = std::move(chunks_.front()); + chunks_.pop(); + writer_->WriteChunk(std::move(data), + base::BindOnce(&BufferedFileWriter::OnWriteResult, + weak_ptr_factory_.GetWeakPtr())); +} + +// Handles the result from both WriteFile and WriteChunk. For the former, it is +// called by OnWriteFileResult after setting writer_. +void BufferedFileWriter::OnWriteResult( + base::Optional<protocol::FileTransfer_Error> error) { + if (error) { + SetState(kFailed); + std::move(on_error_).Run(std::move(*error)); + return; + } + + if (!chunks_.empty()) { + WriteNextChunk(); + } else if (state_ == kClosing) { + DoClose(); + } else { + SetState(kWaiting); + } +} + +void BufferedFileWriter::DoClose() { + DCHECK(chunks_.empty()); + DCHECK_EQ(kClosing, state_); + writer_->Close(base::BindOnce(&BufferedFileWriter::OnCloseResult, + weak_ptr_factory_.GetWeakPtr())); +} + +void BufferedFileWriter::OnCloseResult( + base::Optional<protocol::FileTransfer_Error> error) { + if (error) { + SetState(kFailed); + std::move(on_error_).Run(std::move(*error)); + return; + } + + SetState(kClosed); + std::move(on_complete_).Run(); +} + +void BufferedFileWriter::SetState(BufferedFileWriter::State state) { + switch (state) { + case kNotStarted: + // This is the initial state, but should never be reached again. + NOTREACHED(); + break; + case kWorking: + DCHECK(state_ == kNotStarted || state_ == kWaiting); + break; + case kWaiting: + DCHECK(state_ == kWorking); + break; + case kClosing: + DCHECK(state_ == kWorking || state_ == kWaiting); + break; + case kClosed: + DCHECK(state_ == kClosing); + break; + case kFailed: + // Any state can change to kFailed. + break; + } + + state_ = state; +} + +} // namespace remoting
diff --git a/remoting/host/file_transfer/buffered_file_writer.h b/remoting/host/file_transfer/buffered_file_writer.h new file mode 100644 index 0000000..88ecd219 --- /dev/null +++ b/remoting/host/file_transfer/buffered_file_writer.h
@@ -0,0 +1,96 @@ +// 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 REMOTING_HOST_FILE_TRANSFER_BUFFERED_FILE_WRITER_H_ +#define REMOTING_HOST_FILE_TRANSFER_BUFFERED_FILE_WRITER_H_ + +#include "base/bind.h" +#include "base/callback_forward.h" +#include "base/containers/queue.h" +#include "base/files/file_path.h" +#include "remoting/host/file_transfer/file_operations.h" +#include "remoting/proto/file_transfer.pb.h" + +namespace remoting { + +// Wrapper around FileOperations::WriteFile that automatically handles queuing +// operations. Write can be called immediately after start, can be called +// multiple times in sequence, and close can be called at any time. Internally, +// BufferedFileWriter will maintain a queue of written chunks and feed them to +// the Writer as the latter is ready for them. +class BufferedFileWriter { + public: + // Constructor. + // |on_error| may be called an any time if any operation fails. If no error + // occurs, |on_complete| will be called after Close() has been called and all + // chunks have been successfully written. + BufferedFileWriter( + base::OnceClosure on_complete, + base::OnceCallback<void(protocol::FileTransfer_Error)> on_error); + ~BufferedFileWriter(); + + // Start writing a new file using the provided FileOperations implementation. + // Must be called exactly once before any other methods. + void Start(FileOperations* file_operations, const base::FilePath& filename); + + // Enqueue the provided chunk to be written to the file. + void Write(std::string data); + + // Close the file. If any chunks are currently queued, they will be written + // before the file is closed. + void Close(); + + // Cancels the underlying Writer. If Close has already been called, this will + // either do nothing (if writing the file has already completed) or cancel + // writing out the file (if there are still chunks waiting te be written). + void Cancel(); + + private: + enum State { + // Initial state. + kNotStarted, + // A file operation is in progress. + kWorking, + // Waiting for data. + kWaiting, + // Close called, but file operations still pending. + kClosing, + // End states + // File successfully written. + kClosed, + // An error occured or the transfer was canceled. + kFailed, + }; + + void OnWriteFileResult(base::Optional<protocol::FileTransfer_Error> error, + std::unique_ptr<FileOperations::Writer> writer); + void WriteNextChunk(); + void OnWriteResult(base::Optional<protocol::FileTransfer_Error> error); + void DoClose(); + void OnCloseResult(base::Optional<protocol::FileTransfer_Error> error); + void SetState(State state); + + // Tracks internal state. + State state_ = kNotStarted; + + // Underlying Writer instance. + std::unique_ptr<FileOperations::Writer> writer_; + + // Called once all writes are completed and the file is closed. + base::OnceClosure on_complete_; + + // Called if there is an error at any stage. If this is called, on_complete_ + // won't be. + base::OnceCallback<void(protocol::FileTransfer_Error)> on_error_; + + // Chunks that have been provided to Write but have not yet been passed to the + // Writer instance. + base::queue<std::string> chunks_; + + base::WeakPtrFactory<BufferedFileWriter> weak_ptr_factory_; +}; + +} // namespace remoting + +#endif // REMOTING_HOST_FILE_TRANSFER_BUFFERED_FILE_WRITER_H_
diff --git a/remoting/host/file_transfer/buffered_file_writer_unittest.cc b/remoting/host/file_transfer/buffered_file_writer_unittest.cc new file mode 100644 index 0000000..1b93846 --- /dev/null +++ b/remoting/host/file_transfer/buffered_file_writer_unittest.cc
@@ -0,0 +1,175 @@ +// 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 "remoting/host/file_transfer/buffered_file_writer.h" + +#include "base/test/scoped_task_environment.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "remoting/host/file_transfer/fake_file_operations.h" +#include "remoting/protocol/file_transfer_helpers.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace remoting { + +class BufferedFileWriterTest : public testing::Test { + public: + BufferedFileWriterTest(); + ~BufferedFileWriterTest() override; + + // testing::Test implementation. + void SetUp() override; + void TearDown() override; + + protected: + const base::FilePath kTestFilename{FILE_PATH_LITERAL("test-file.txt")}; + const std::string kTestDataOne = "this is the first test string"; + const std::string kTestDataTwo = "this is the second test string"; + const std::string kTestDataThree = "this is the third test string"; + + void OnCompleted(); + void OnError(protocol::FileTransfer_Error error); + + bool complete_called_ = false; + base::Optional<protocol::FileTransfer_Error> error_ = base::nullopt; + + base::test::ScopedTaskEnvironment scoped_task_environment_; +}; + +BufferedFileWriterTest::BufferedFileWriterTest() = default; + +BufferedFileWriterTest::~BufferedFileWriterTest() = default; + +void BufferedFileWriterTest::SetUp() {} + +void BufferedFileWriterTest::TearDown() {} + +void BufferedFileWriterTest::OnCompleted() { + ASSERT_TRUE(!complete_called_ && !error_); + complete_called_ = true; +} + +void BufferedFileWriterTest::OnError(protocol::FileTransfer_Error error) { + ASSERT_TRUE(!complete_called_ && !error_); + error_ = std::move(error); +} + +// Verifies BufferedFileWriter creates, writes to, and closes a Writer +// without errors. +TEST_F(BufferedFileWriterTest, WritesThreeChunks) { + FakeFileOperations::TestIo test_io; + auto file_operations = std::make_unique<FakeFileOperations>(&test_io); + BufferedFileWriter writer( + base::BindOnce( + &BufferedFileWriterTest_WritesThreeChunks_Test::OnCompleted, + base::Unretained(this)), + base::BindOnce(&BufferedFileWriterTest_WritesThreeChunks_Test::OnError, + base::Unretained(this))); + + writer.Start(file_operations.get(), kTestFilename); + scoped_task_environment_.RunUntilIdle(); + writer.Write(kTestDataOne); + scoped_task_environment_.RunUntilIdle(); + writer.Write(kTestDataTwo); + scoped_task_environment_.RunUntilIdle(); + writer.Write(kTestDataThree); + scoped_task_environment_.RunUntilIdle(); + writer.Close(); + ASSERT_EQ(false, complete_called_); + scoped_task_environment_.RunUntilIdle(); + ASSERT_EQ(true, complete_called_); + + ASSERT_EQ(1ul, test_io.files_written.size()); + ASSERT_EQ(false, test_io.files_written[0].failed); + std::vector<std::string> expected_chunks = {kTestDataOne, kTestDataTwo, + kTestDataThree}; + ASSERT_EQ(expected_chunks, test_io.files_written[0].chunks); +} + +// Verifies BufferedFileWriter properly queues up file operations. +TEST_F(BufferedFileWriterTest, QueuesOperations) { + FakeFileOperations::TestIo test_io; + auto file_operations = std::make_unique<FakeFileOperations>(&test_io); + BufferedFileWriter writer( + base::BindOnce(&BufferedFileWriterTest_QueuesOperations_Test::OnCompleted, + base::Unretained(this)), + base::BindOnce(&BufferedFileWriterTest_QueuesOperations_Test::OnError, + base::Unretained(this))); + + // FakeFileWriter will CHECK that BufferedFileWriter properly serializes + // file operations. + writer.Start(file_operations.get(), kTestFilename); + writer.Write(kTestDataOne); + writer.Write(kTestDataTwo); + writer.Write(kTestDataThree); + writer.Close(); + ASSERT_EQ(false, complete_called_); + scoped_task_environment_.RunUntilIdle(); + ASSERT_EQ(true, complete_called_); + + ASSERT_EQ(1ul, test_io.files_written.size()); + ASSERT_EQ(false, test_io.files_written[0].failed); + std::vector<std::string> expected_chunks = {kTestDataOne, kTestDataTwo, + kTestDataThree}; + ASSERT_EQ(expected_chunks, test_io.files_written[0].chunks); +} + +// Verifies BufferedFileWriter calls the error callback in the event of an +// error. +TEST_F(BufferedFileWriterTest, HandlesWriteError) { + FakeFileOperations::TestIo test_io; + auto file_operations = std::make_unique<FakeFileOperations>(&test_io); + BufferedFileWriter writer( + base::BindOnce( + &BufferedFileWriterTest_HandlesWriteError_Test::OnCompleted, + base::Unretained(this)), + base::BindOnce(&BufferedFileWriterTest_HandlesWriteError_Test::OnError, + base::Unretained(this))); + protocol::FileTransfer_Error fake_error = protocol::MakeFileTransferError( + FROM_HERE, protocol::FileTransfer_Error_Type_IO_ERROR); + + writer.Start(file_operations.get(), kTestFilename); + writer.Write(kTestDataOne); + writer.Write(kTestDataTwo); + scoped_task_environment_.RunUntilIdle(); + test_io.io_error = fake_error; + writer.Write(kTestDataThree); + writer.Close(); + scoped_task_environment_.RunUntilIdle(); + ASSERT_TRUE(error_); + ASSERT_EQ(fake_error.SerializeAsString(), error_->SerializeAsString()); + + ASSERT_EQ(1ul, test_io.files_written.size()); + ASSERT_EQ(true, test_io.files_written[0].failed); + std::vector<std::string> expected_chunks = {kTestDataOne, kTestDataTwo}; + ASSERT_EQ(expected_chunks, test_io.files_written[0].chunks); +} + +// Verifies canceling BufferedFileWriter cancels the underlying writer. +TEST_F(BufferedFileWriterTest, CancelsWriter) { + FakeFileOperations::TestIo test_io; + auto file_operations = std::make_unique<FakeFileOperations>(&test_io); + BufferedFileWriter writer( + base::BindOnce(&BufferedFileWriterTest_CancelsWriter_Test::OnCompleted, + base::Unretained(this)), + base::BindOnce(&BufferedFileWriterTest_CancelsWriter_Test::OnError, + base::Unretained(this))); + protocol::FileTransfer_Error fake_error = protocol::MakeFileTransferError( + FROM_HERE, protocol::FileTransfer_Error_Type_IO_ERROR); + + writer.Start(file_operations.get(), kTestFilename); + writer.Write(kTestDataOne); + writer.Write(kTestDataTwo); + scoped_task_environment_.RunUntilIdle(); + writer.Write(kTestDataThree); + writer.Cancel(); + scoped_task_environment_.RunUntilIdle(); + ASSERT_TRUE(!complete_called_ && !error_); + + ASSERT_EQ(1ul, test_io.files_written.size()); + ASSERT_EQ(true, test_io.files_written[0].failed); + std::vector<std::string> expected_chunks = {kTestDataOne, kTestDataTwo}; + ASSERT_EQ(expected_chunks, test_io.files_written[0].chunks); +} + +} // namespace remoting
diff --git a/remoting/host/file_transfer/fake_file_operations.cc b/remoting/host/file_transfer/fake_file_operations.cc new file mode 100644 index 0000000..f51b1c9 --- /dev/null +++ b/remoting/host/file_transfer/fake_file_operations.cc
@@ -0,0 +1,149 @@ +// 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 "remoting/host/file_transfer/fake_file_operations.h" + +#include "base/bind.h" +#include "base/memory/weak_ptr.h" +#include "base/threading/sequenced_task_runner_handle.h" + +namespace remoting { + +class FakeFileOperations::FakeFileWriter : public FileOperations::Writer { + public: + FakeFileWriter(TestIo* test_io, const base::FilePath& filename); + ~FakeFileWriter() override; + + void WriteChunk(std::string data, Callback callback) override; + void Close(Callback callback) override; + void Cancel() override; + FileOperations::State state() override; + + private: + void DoWrite(std::string data, Callback callback); + void DoClose(Callback callback); + FileOperations::State state_ = FileOperations::kReady; + TestIo* test_io_; + base::FilePath filename_; + std::vector<std::string> chunks_; + base::WeakPtrFactory<FakeFileWriter> weak_ptr_factory_; +}; + +void FakeFileOperations::WriteFile(const base::FilePath& filename, + WriteFileCallback callback) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&FakeFileOperations::DoWriteFile, base::Unretained(this), + filename, std::move(callback))); +} + +void FakeFileOperations::ReadFile(ReadFileCallback) { + NOTIMPLEMENTED(); +} + +FakeFileOperations::FakeFileOperations(FakeFileOperations::TestIo* test_io) + : test_io_(test_io) {} + +FakeFileOperations::~FakeFileOperations() = default; + +void FakeFileOperations::DoWriteFile(const base::FilePath& filename, + WriteFileCallback callback) { + if (!test_io_->io_error) { + std::move(callback).Run( + base::nullopt, std::make_unique<FakeFileWriter>(test_io_, filename)); + } else { + std::move(callback).Run(test_io_->io_error, nullptr); + } +} + +FakeFileOperations::OutputFile::OutputFile(base::FilePath filename, + bool failed, + std::vector<std::string> chunks) + : filename(std::move(filename)), + failed(failed), + chunks(std::move(chunks)) {} + +FakeFileOperations::OutputFile::OutputFile(const OutputFile& other) = default; +FakeFileOperations::OutputFile::~OutputFile() = default; +FakeFileOperations::TestIo::TestIo() = default; +FakeFileOperations::TestIo::TestIo(const TestIo& other) = default; +FakeFileOperations::TestIo::~TestIo() = default; + +FakeFileOperations::FakeFileWriter::FakeFileWriter( + TestIo* test_io, + const base::FilePath& filename) + : test_io_(test_io), filename_(filename), weak_ptr_factory_(this) {} + +FakeFileOperations::FakeFileWriter::~FakeFileWriter() { + Cancel(); +}; + +void FakeFileOperations::FakeFileWriter::WriteChunk(std::string data, + Callback callback) { + CHECK_EQ(kReady, state_) << "WriteChunk called when writer not ready"; + state_ = kBusy; + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&FakeFileWriter::DoWrite, weak_ptr_factory_.GetWeakPtr(), + std::move(data), std::move(callback))); +} + +void FakeFileOperations::FakeFileWriter::Close(Callback callback) { + CHECK_EQ(kReady, state_) << "Close called when writer not ready"; + state_ = kBusy; + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&FakeFileWriter::DoClose, weak_ptr_factory_.GetWeakPtr(), + std::move(callback))); +} + +void FakeFileOperations::FakeFileWriter::Cancel() { + if (state_ == FileOperations::kClosed || state_ == FileOperations::kFailed) { + return; + } + + state_ = kFailed; + test_io_->files_written.push_back( + OutputFile(filename_, true /* failed */, std::move(chunks_))); +} + +FileOperations::State FakeFileOperations::FakeFileWriter::state() { + return state_; +} + +void FakeFileOperations::FakeFileWriter::DoWrite(std::string data, + Callback callback) { + if (state_ == kFailed) { + return; + } + if (!test_io_->io_error) { + chunks_.push_back(std::move(data)); + state_ = kReady; + std::move(callback).Run(base::nullopt); + } else { + state_ = kFailed; + test_io_->files_written.push_back( + OutputFile(filename_, true /* failed */, std::move(chunks_))); + std::move(callback).Run(test_io_->io_error); + } +} + +void FakeFileOperations::FakeFileWriter::DoClose(Callback callback) { + if (state_ == kFailed) { + return; + } + if (!test_io_->io_error) { + test_io_->files_written.push_back( + OutputFile(filename_, false /* failed */, std::move(chunks_))); + state_ = kClosed; + std::move(callback).Run(base::nullopt); + } else { + state_ = kFailed; + test_io_->files_written.push_back( + OutputFile(filename_, true /* failed */, std::move(chunks_))); + std::move(callback).Run(test_io_->io_error); + } +} + +} // namespace remoting
diff --git a/remoting/host/file_transfer/fake_file_operations.h b/remoting/host/file_transfer/fake_file_operations.h new file mode 100644 index 0000000..0d574a2 --- /dev/null +++ b/remoting/host/file_transfer/fake_file_operations.h
@@ -0,0 +1,72 @@ +// 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 REMOTING_HOST_FILE_TRANSFER_FAKE_FILE_OPERATIONS_H_ +#define REMOTING_HOST_FILE_TRANSFER_FAKE_FILE_OPERATIONS_H_ + +#include <string> +#include <vector> + +#include "base/files/file_path.h" +#include "base/optional.h" +#include "remoting/host/file_transfer/file_operations.h" +#include "remoting/proto/file_transfer.pb.h" + +namespace remoting { + +// Fake FileOperations implementation for testing. Outputs written files to a +// vector. +class FakeFileOperations : public FileOperations { + public: + struct OutputFile { + OutputFile(base::FilePath filename, + bool failed, + std::vector<std::string> chunks); + OutputFile(const OutputFile& other); + ~OutputFile(); + + // The filename provided to WriteFile. + base::FilePath filename; + + // True if the file was canceled or returned an error due to io_error being + // set. False if the file was written and closed successfully. + bool failed; + + // All of the chunks successfully written before close/cancel/error. + std::vector<std::string> chunks; + }; + + // Used to interact with FakeFileOperations after ownership is passed + // elsewhere. + struct TestIo { + TestIo(); + TestIo(const TestIo& other); + ~TestIo(); + + // An element will be added for each file written in full or in part. + std::vector<OutputFile> files_written; + + // If set, file operations will return this error. + base::Optional<protocol::FileTransfer_Error> io_error = base::nullopt; + }; + + explicit FakeFileOperations(TestIo* test_io); + ~FakeFileOperations() override; + + // FileOperations implementation. + void WriteFile(const base::FilePath& filename, + WriteFileCallback callback) override; + void ReadFile(ReadFileCallback) override; + + private: + class FakeFileWriter; + + void DoWriteFile(const base::FilePath& filename, WriteFileCallback callback); + + TestIo* test_io_; +}; + +} // namespace remoting + +#endif // REMOTING_HOST_FILE_TRANSFER_FAKE_FILE_OPERATIONS_H_
diff --git a/remoting/host/host_main.cc b/remoting/host/host_main.cc index f23dcef8..4c6261f1 100644 --- a/remoting/host/host_main.cc +++ b/remoting/host/host_main.cc
@@ -150,6 +150,15 @@ base::CommandLine::Init(argc, argv); +#if !defined(NDEBUG) + // Always enable Webrtc logging for debug builds. + // Without this switch, Webrtc errors will still be logged but + // RTC_LOG(LS_INFO) lines will not. + // See https://webrtc.org/native-code/logging + auto* cl = base::CommandLine::ForCurrentProcess(); + cl->AppendSwitch("vmodule=*/webrtc/*=1"); +#endif + // Parse the command line. const base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
diff --git a/remoting/protocol/webrtc_data_stream_adapter.cc b/remoting/protocol/webrtc_data_stream_adapter.cc index b92f2d37..e391a2d 100644 --- a/remoting/protocol/webrtc_data_stream_adapter.cc +++ b/remoting/protocol/webrtc_data_stream_adapter.cc
@@ -33,9 +33,8 @@ channel_->Close(); // Destroy |channel_| asynchronously as it may be on stack. - channel_->AddRef(); - base::ThreadTaskRunnerHandle::Get()->ReleaseSoon(FROM_HERE, channel_.get()); - channel_ = nullptr; + base::ThreadTaskRunnerHandle::Get()->ReleaseSoon( + FROM_HERE, base::WrapRefCounted(channel_.release())); } }
diff --git a/remoting/protocol/webrtc_dummy_video_encoder.cc b/remoting/protocol/webrtc_dummy_video_encoder.cc index 13356d21..562fa3eb 100644 --- a/remoting/protocol/webrtc_dummy_video_encoder.cc +++ b/remoting/protocol/webrtc_dummy_video_encoder.cc
@@ -217,6 +217,16 @@ &header); } +webrtc::VideoEncoder::EncoderInfo WebrtcDummyVideoEncoder::GetEncoderInfo() + const { + EncoderInfo info; + // TODO(mirtad): Set this flag correctly per encoder. + info.is_hardware_accelerated = true; + // Set internal source to true to directly provide encoded frames to webrtc. + info.has_internal_source = true; + return info; +} + WebrtcDummyVideoEncoderFactory::WebrtcDummyVideoEncoderFactory() : main_task_runner_(base::ThreadTaskRunnerHandle::Get()) { formats_.push_back(webrtc::SdpVideoFormat("VP8"));
diff --git a/remoting/protocol/webrtc_dummy_video_encoder.h b/remoting/protocol/webrtc_dummy_video_encoder.h index 75b5a0f..3aba911 100644 --- a/remoting/protocol/webrtc_dummy_video_encoder.h +++ b/remoting/protocol/webrtc_dummy_video_encoder.h
@@ -51,6 +51,7 @@ const webrtc::CodecSpecificInfo* codec_specific_info, const std::vector<webrtc::FrameType>* frame_types) override; int32_t SetRates(uint32_t bitrate, uint32_t framerate) override; + webrtc::VideoEncoder::EncoderInfo GetEncoderInfo() const override; webrtc::EncodedImageCallback::Result SendEncodedFrame( const WebrtcVideoEncoder::EncodedFrame& frame,
diff --git a/services/audio/owning_audio_manager_accessor.cc b/services/audio/owning_audio_manager_accessor.cc index 063a7705..c2998c3 100644 --- a/services/audio/owning_audio_manager_accessor.cc +++ b/services/audio/owning_audio_manager_accessor.cc
@@ -7,12 +7,17 @@ #include <memory> #include <utility> +#include "base/feature_list.h" #include "base/macros.h" #include "base/metrics/histogram_macros.h" +#include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread.h" +#include "base/time/default_tick_clock.h" +#include "media/audio/audio_features.h" #include "media/audio/audio_manager.h" #include "media/audio/audio_thread.h" +#include "media/audio/audio_thread_hang_monitor.h" namespace audio { @@ -21,15 +26,16 @@ // Thread class for hosting owned AudioManager on the main thread of the // service, with a separate worker thread (started on-demand) for running things // that shouldn't be blocked by main-thread tasks. -class MainThread : public media::AudioThread { +class MainThread final : public media::AudioThread { public: MainThread(); - ~MainThread() override; + ~MainThread() final; // AudioThread implementation. - void Stop() override; - base::SingleThreadTaskRunner* GetTaskRunner() override; - base::SingleThreadTaskRunner* GetWorkerTaskRunner() override; + void Stop() final; + bool IsHung() const final; + base::SingleThreadTaskRunner* GetTaskRunner() final; + base::SingleThreadTaskRunner* GetWorkerTaskRunner() final; private: scoped_refptr<base::SingleThreadTaskRunner> task_runner_; @@ -38,12 +44,18 @@ base::Thread worker_thread_; scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner_; + media::AudioThreadHangMonitor::Ptr hang_monitor_; + DISALLOW_COPY_AND_ASSIGN(MainThread); }; MainThread::MainThread() : task_runner_(base::ThreadTaskRunnerHandle::Get()), - worker_thread_("AudioWorkerThread") {} + worker_thread_("AudioWorkerThread"), + hang_monitor_(media::AudioThreadHangMonitor::Create( + base::FeatureList::IsEnabled(features::kDumpOnAudioServiceHang), + base::DefaultTickClock::GetInstance(), + task_runner_)) {} MainThread::~MainThread() { DCHECK(task_runner_->BelongsToCurrentThread()); @@ -51,12 +63,19 @@ void MainThread::Stop() { DCHECK(task_runner_->BelongsToCurrentThread()); + + hang_monitor_.reset(); + if (worker_task_runner_) { worker_task_runner_ = nullptr; worker_thread_.Stop(); } } +bool MainThread::IsHung() const { + return hang_monitor_->IsAudioThreadHung(); +} + base::SingleThreadTaskRunner* MainThread::GetTaskRunner() { return task_runner_.get(); }
diff --git a/services/device/hid/hid_connection.cc b/services/device/hid/hid_connection.cc index ff0e9b16..0d5be49 100644 --- a/services/device/hid/hid_connection.cc +++ b/services/device/hid/hid_connection.cc
@@ -70,12 +70,12 @@ } HidConnection::~HidConnection() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(closed_); } void HidConnection::Close() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!closed_); PlatformClose(); @@ -83,7 +83,7 @@ } void HidConnection::Read(ReadCallback callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (device_info_->max_input_report_size() == 0) { HID_LOG(USER) << "This device does not support input reports."; std::move(callback).Run(false, NULL, 0); @@ -96,7 +96,7 @@ void HidConnection::Write(scoped_refptr<base::RefCountedBytes> buffer, WriteCallback callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (device_info_->max_output_report_size() == 0) { HID_LOG(USER) << "This device does not support output reports."; std::move(callback).Run(false); @@ -126,7 +126,7 @@ } void HidConnection::GetFeatureReport(uint8_t report_id, ReadCallback callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (device_info_->max_feature_report_size() == 0) { HID_LOG(USER) << "This device does not support feature reports."; std::move(callback).Run(false, NULL, 0); @@ -149,7 +149,7 @@ void HidConnection::SendFeatureReport( scoped_refptr<base::RefCountedBytes> buffer, WriteCallback callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (device_info_->max_feature_report_size() == 0) { HID_LOG(USER) << "This device does not support feature reports."; std::move(callback).Run(false); @@ -184,7 +184,7 @@ void HidConnection::ProcessInputReport( scoped_refptr<base::RefCountedBytes> buffer, size_t size) { - DCHECK(thread_checker().CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_GE(size, 1u); uint8_t report_id = buffer->data()[0]; @@ -196,7 +196,7 @@ } void HidConnection::ProcessReadQueue() { - DCHECK(thread_checker().CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Hold a reference to |this| to prevent a callback from freeing this object // during the loop.
diff --git a/services/device/hid/hid_connection.h b/services/device/hid/hid_connection.h index 69dc947..7471cce 100644 --- a/services/device/hid/hid_connection.h +++ b/services/device/hid/hid_connection.h
@@ -13,7 +13,7 @@ #include "base/containers/queue.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/threading/thread_checker.h" +#include "base/sequence_checker.h" #include "services/device/hid/hid_device_info.h" namespace base { @@ -38,7 +38,6 @@ scoped_refptr<HidDeviceInfo> device_info() const { return device_info_; } bool has_protected_collection() const { return has_protected_collection_; } - const base::ThreadChecker& thread_checker() const { return thread_checker_; } bool closed() const { return closed_; } // Closes the connection. This must be called before the object is freed. @@ -86,13 +85,14 @@ private: scoped_refptr<HidDeviceInfo> device_info_; bool has_protected_collection_; - base::ThreadChecker thread_checker_; bool closed_; base::queue<std::tuple<scoped_refptr<base::RefCountedBytes>, size_t>> pending_reports_; base::queue<ReadCallback> pending_reads_; + SEQUENCE_CHECKER(sequence_checker_); + DISALLOW_COPY_AND_ASSIGN(HidConnection); };
diff --git a/services/device/hid/hid_connection_linux.cc b/services/device/hid/hid_connection_linux.cc index 9080a06..b7f23ac 100644 --- a/services/device/hid/hid_connection_linux.cc +++ b/services/device/hid/hid_connection_linux.cc
@@ -18,7 +18,7 @@ #include "base/memory/ref_counted_memory.h" #include "base/posix/eintr_wrapper.h" #include "base/threading/scoped_blocking_call.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "components/device_event_log/device_event_log.h" #include "services/device/hid/hid_service.h" @@ -39,7 +39,7 @@ base::WeakPtr<HidConnectionLinux> connection) : fd_(std::move(fd)), connection_(connection), - origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) { + origin_task_runner_(base::SequencedTaskRunnerHandle::Get()) { DETACH_FROM_SEQUENCE(sequence_checker_); // Report buffers must always have room for the report ID. report_buffer_size_ = device_info->max_input_report_size() + 1; @@ -192,9 +192,7 @@ base::Unretained(helper_.get()))); } -HidConnectionLinux::~HidConnectionLinux() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -} +HidConnectionLinux::~HidConnectionLinux() {} void HidConnectionLinux::PlatformClose() { // By closing the device on the blocking task runner 1) the requirement that
diff --git a/services/device/hid/hid_connection_linux.h b/services/device/hid/hid_connection_linux.h index 97ae5c8..274128c 100644 --- a/services/device/hid/hid_connection_linux.h +++ b/services/device/hid/hid_connection_linux.h
@@ -11,7 +11,6 @@ #include "base/files/scoped_file.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "base/sequence_checker.h" #include "services/device/hid/hid_connection.h" namespace base { @@ -49,8 +48,6 @@ const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; - SEQUENCE_CHECKER(sequence_checker_); - base::WeakPtrFactory<HidConnectionLinux> weak_factory_; DISALLOW_COPY_AND_ASSIGN(HidConnectionLinux);
diff --git a/services/device/hid/hid_service.cc b/services/device/hid/hid_service.cc index 5a4ad95e..95465f4 100644 --- a/services/device/hid/hid_service.cc +++ b/services/device/hid/hid_service.cc
@@ -10,7 +10,7 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/stl_util.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "build/build_config.h" #include "components/device_event_log/device_event_log.h" @@ -46,12 +46,12 @@ } void HidService::GetDevices(GetDevicesCallback callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); bool was_empty = pending_enumerations_.empty(); pending_enumerations_.push_back(std::move(callback)); if (enumeration_ready_ && was_empty) { - base::ThreadTaskRunnerHandle::Get()->PostTask( + base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&HidService::RunPendingEnumerations, GetWeakPtr())); } @@ -68,11 +68,11 @@ HidService::HidService() = default; HidService::~HidService() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } void HidService::AddDevice(scoped_refptr<HidDeviceInfo> device_info) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::string device_guid = FindDeviceIdByPlatformDeviceId(device_info->platform_device_id()); @@ -95,7 +95,7 @@ } void HidService::RemoveDevice(const HidPlatformDeviceId& platform_device_id) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::string device_guid = FindDeviceIdByPlatformDeviceId(platform_device_id); if (!device_guid.empty()) {
diff --git a/services/device/hid/hid_service.h b/services/device/hid/hid_service.h index e45d7ec..b1af0ac 100644 --- a/services/device/hid/hid_service.h +++ b/services/device/hid/hid_service.h
@@ -16,9 +16,8 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" -#include "base/single_thread_task_runner.h" +#include "base/sequence_checker.h" #include "base/task/task_traits.h" -#include "base/threading/thread_checker.h" #include "services/device/hid/hid_device_info.h" #include "services/device/public/mojom/hid.mojom.h" @@ -83,7 +82,7 @@ const DeviceMap& devices() const { return devices_; } - base::ThreadChecker thread_checker_; + SEQUENCE_CHECKER(sequence_checker_); private: void RunPendingEnumerations();
diff --git a/services/device/hid/hid_service_linux.cc b/services/device/hid/hid_service_linux.cc index 65b5595..e96f3f4 100644 --- a/services/device/hid/hid_service_linux.cc +++ b/services/device/hid/hid_service_linux.cc
@@ -25,7 +25,7 @@ #include "base/strings/string_split.h" #include "base/task/post_task.h" #include "base/threading/scoped_blocking_call.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "build/build_config.h" #include "components/device_event_log/device_event_log.h" #include "device/udev_linux/scoped_udev.h" @@ -55,7 +55,7 @@ const ConnectCallback& callback) : device_info(std::move(device_info)), callback(callback), - task_runner(base::ThreadTaskRunnerHandle::Get()), + task_runner(base::SequencedTaskRunnerHandle::Get()), blocking_task_runner( base::CreateSequencedTaskRunnerWithTraits(kBlockingTaskTraits)) {} ~ConnectParams() {} @@ -71,7 +71,7 @@ public: BlockingTaskHelper(base::WeakPtr<HidServiceLinux> service) : service_(std::move(service)), - task_runner_(base::ThreadTaskRunnerHandle::Get()) { + task_runner_(base::SequencedTaskRunnerHandle::Get()) { DETACH_FROM_SEQUENCE(sequence_checker_); } @@ -211,11 +211,11 @@ void HidServiceLinux::Connect(const std::string& device_guid, const ConnectCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); const auto& map_entry = devices().find(device_guid); if (map_entry == devices().end()) { - base::ThreadTaskRunnerHandle::Get()->PostTask( + base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(callback, nullptr)); return; } @@ -248,12 +248,8 @@ // static void HidServiceLinux::OnPathOpenComplete(std::unique_ptr<ConnectParams> params, base::ScopedFD fd) { - scoped_refptr<base::SequencedTaskRunner> blocking_task_runner = - params->blocking_task_runner; params->fd = std::move(fd); - blocking_task_runner->PostTask( - FROM_HERE, - base::BindOnce(&HidServiceLinux::FinishOpen, std::move(params))); + FinishOpen(std::move(params)); } // static @@ -297,32 +293,27 @@ return; } params->fd.reset(device_file.TakePlatformFile()); - FinishOpen(std::move(params)); + + task_runner->PostTask(FROM_HERE, base::BindOnce(&HidServiceLinux::FinishOpen, + std::move(params))); } #endif // defined(OS_CHROMEOS) // static void HidServiceLinux::FinishOpen(std::unique_ptr<ConnectParams> params) { - scoped_refptr<base::SequencedTaskRunner> task_runner = params->task_runner; + DCHECK(params->fd.is_valid()); if (!base::SetNonBlocking(params->fd.get())) { HID_PLOG(ERROR) << "Failed to set the non-blocking flag on the device fd"; - task_runner->PostTask(FROM_HERE, base::BindOnce(params->callback, nullptr)); + std::move(params->callback).Run(nullptr); return; } - task_runner->PostTask( - FROM_HERE, - base::BindOnce(&HidServiceLinux::CreateConnection, std::move(params))); -} - -// static -void HidServiceLinux::CreateConnection(std::unique_ptr<ConnectParams> params) { - DCHECK(params->fd.is_valid()); - params->callback.Run(base::MakeRefCounted<HidConnectionLinux>( - std::move(params->device_info), std::move(params->fd), - std::move(params->blocking_task_runner))); + std::move(params->callback) + .Run(base::MakeRefCounted<HidConnectionLinux>( + std::move(params->device_info), std::move(params->fd), + std::move(params->blocking_task_runner))); } } // namespace device
diff --git a/services/device/hid/hid_service_linux.h b/services/device/hid/hid_service_linux.h index 88e9c9e..b2749db 100644 --- a/services/device/hid/hid_service_linux.h +++ b/services/device/hid/hid_service_linux.h
@@ -46,7 +46,6 @@ static void OpenOnBlockingThread(std::unique_ptr<ConnectParams> params); #endif static void FinishOpen(std::unique_ptr<ConnectParams> params); - static void CreateConnection(std::unique_ptr<ConnectParams> params); const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
diff --git a/services/device/hid/hid_service_mac.cc b/services/device/hid/hid_service_mac.cc index b7385aa..b81d0f66 100644 --- a/services/device/hid/hid_service_mac.cc +++ b/services/device/hid/hid_service_mac.cc
@@ -15,13 +15,11 @@ #include "base/location.h" #include "base/logging.h" #include "base/mac/foundation_util.h" -#include "base/single_thread_task_runner.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/strings/sys_string_conversions.h" #include "base/task/post_task.h" -#include "base/threading/thread_restrictions.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "components/device_event_log/device_event_log.h" #include "services/device/hid/hid_connection_mac.h" @@ -129,11 +127,11 @@ void HidServiceMac::Connect(const std::string& device_guid, const ConnectCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); const auto& map_entry = devices().find(device_guid); if (map_entry == devices().end()) { - base::ThreadTaskRunnerHandle::Get()->PostTask( + base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(callback, nullptr)); return; } @@ -215,7 +213,7 @@ } void HidServiceMac::AddDevices() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::mac::ScopedIOObject<io_service_t> device; while (device.reset(IOIteratorNext(devices_added_iterator_)), device) { @@ -227,7 +225,7 @@ } void HidServiceMac::RemoveDevices() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::mac::ScopedIOObject<io_service_t> device; while (device.reset(IOIteratorNext(devices_removed_iterator_)), device) {
diff --git a/services/device/hid/hid_service_win.cc b/services/device/hid/hid_service_win.cc index c07087a..c8d8f4c0 100644 --- a/services/device/hid/hid_service_win.cc +++ b/services/device/hid/hid_service_win.cc
@@ -50,7 +50,7 @@ void HidServiceWin::Connect(const std::string& device_guid, const ConnectCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); const auto& map_entry = devices().find(device_guid); if (map_entry == devices().end()) { task_runner_->PostTask(FROM_HERE, base::BindOnce(callback, nullptr));
diff --git a/services/identity/public/cpp/DEPS b/services/identity/public/cpp/DEPS index e45e9ef..5634299 100644 --- a/services/identity/public/cpp/DEPS +++ b/services/identity/public/cpp/DEPS
@@ -4,6 +4,7 @@ "+components/signin/core/browser/fake_gaia_cookie_manager_service.h", "+components/signin/core/browser/gaia_cookie_manager_service.h", "+components/signin/core/browser/account_consistency_method.h", + "+components/signin/core/browser/signin_internals_util.h", "+components/signin/core/browser/signin_metrics.h", "+components/signin/core/browser/signin_switches.h", "+google_apis/gaia/gaia_auth_util.h",
diff --git a/services/identity/public/cpp/identity_manager.cc b/services/identity/public/cpp/identity_manager.cc index 738a8f8..b7dfa452 100644 --- a/services/identity/public/cpp/identity_manager.cc +++ b/services/identity/public/cpp/identity_manager.cc
@@ -326,4 +326,13 @@ } } +void IdentityManager::NotifySigninValueChanged( + const signin_internals_util::TimedSigninStatusField& field, + const std::string& value) { + // TODO(843510): Consider notifying observers asynchronously once there + // are no direct clients of ProfileOAuth2TokenService. + for (auto& observer : diagnostics_observer_list_) + observer.NotifySigninValueChanged(field, value); +} + } // namespace identity
diff --git a/services/identity/public/cpp/identity_manager.h b/services/identity/public/cpp/identity_manager.h index f655debc..421819d 100644 --- a/services/identity/public/cpp/identity_manager.h +++ b/services/identity/public/cpp/identity_manager.h
@@ -10,6 +10,7 @@ #include "components/signin/core/browser/account_tracker_service.h" #include "components/signin/core/browser/gaia_cookie_manager_service.h" #include "components/signin/core/browser/profile_oauth2_token_service.h" +#include "components/signin/core/browser/signin_internals_util.h" #include "components/signin/core/browser/signin_manager_base.h" #include "components/signin/core/browser/signin_metrics.h" #include "services/identity/public/cpp/access_token_fetcher.h" @@ -54,6 +55,7 @@ class IdentityManager : public SigninManagerBase::Observer, public OAuth2TokenService::DiagnosticsObserver, public OAuth2TokenService::Observer, + public signin_internals_util::SigninDiagnosticsObserver, public GaiaCookieManagerService::Observer { public: class Observer { @@ -141,6 +143,11 @@ virtual void OnAccessTokenRequested(const std::string& account_id, const std::string& consumer_id, const identity::ScopeSet& scopes) {} + + // Called on credentials and signin related changes. + virtual void NotifySigninValueChanged( + const signin_internals_util::TimedSigninStatusField& field, + const std::string& value) {} }; IdentityManager( @@ -349,10 +356,14 @@ const std::string& consumer_id, const OAuth2TokenService::ScopeSet& scopes) override; + void NotifySigninValueChanged( + const signin_internals_util::TimedSigninStatusField& field, + const std::string& value) override; + // Backing signin classes. NOTE: We strive to limit synchronous access to // these classes in the IdentityManager implementation, as all such - // synchronous access will become impossible when IdentityManager is backed by - // the Identity Service. + // synchronous access will become impossible when IdentityManager is + // backed by the Identity Service. SigninManagerBase* signin_manager_; ProfileOAuth2TokenService* token_service_; AccountTrackerService* account_tracker_service_;
diff --git a/services/metrics/ukm_api.md b/services/metrics/ukm_api.md index 49669eb..8a4a8394 100644 --- a/services/metrics/ukm_api.md +++ b/services/metrics/ukm_api.md
@@ -16,7 +16,7 @@ ### Example ``` -<event name="GoatTeleported"> +<event name="Goat.Teleported"> <owner>teleporter@chromium.org</owner> <summary> Recorded when a page teleports a goat. @@ -42,11 +42,11 @@ 1) Use ukm::UkmRecorder::Get(). This currently only works from the Browser process. -2) Use a service connector and get a MojoUkmRecorder. +2) Use a service connector and get a UkmRecorder. ``` -std::unique_ptr<ukm::MojoUkmRecorder> ukm_recorder = - ukm::MojoUkmRecorder::Create(context()->connector()); +std::unique_ptr<ukm::UkmRecorder> ukm_recorder = + ukm::UkmRecorder::Create(context()->connector()); ukm::builders::MyEvent(source_id) .SetMyMetric(metric_value) .Record(ukm_recorder.get()); @@ -54,7 +54,7 @@ ## Get a ukm::SourceId -UKM identifies navigations by thier source ID and you'll need to associate and ID with your event in order to tie it to a main frame URL. Preferrably, get an existing ID for the navigation from another object. +UKM identifies navigations by their source ID and you'll need to associate and ID with your event in order to tie it to a main frame URL. Preferrably, get an existing ID for the navigation from another object. The main methods for doing this are using one of the following methods: @@ -68,10 +68,12 @@ Example: ``` -ukm::SourceId source_id = ukm::UkmRecorder::GetNewSourceId(); -recorder->UpdateSourceUrl(source_id, main_frame_url); +ukm::SourceId source_id = ukm::UkmRecorder::GetNewSourceID(); +ukm_recorder->UpdateSourceURL(source_id, main_frame_url); ``` +You will also need to add your class as a friend of UkmRecorder in order to use this private API. + ## Create some events Helper objects for recording your event are generated from the descriptions in ukm.xml. You can use them like so: @@ -81,13 +83,15 @@ void OnGoatTeleported() { ... - ukm::builders::GoatTeleported(source_id) + ukm::builders::Goat_Teleported(source_id) .SetDuration(duration.InNanoseconds()) .SetMass(RoundedToMultiple(mass_kg, 10)) .Record(ukm_recorder); } ``` +If the event name in the XML contains a period (`.`), it is replaced with an underscore (`_`) in the method name. + ## Check that it works Build chromium and run it with '--force-enable-metrics-reporting'. Trigger your event and check chrome://ukm to make sure the data was recorded correctly.
diff --git a/services/network/cookie_manager.cc b/services/network/cookie_manager.cc index 0021c4c..3e66d18 100644 --- a/services/network/cookie_manager.cc +++ b/services/network/cookie_manager.cc
@@ -76,6 +76,8 @@ params->secure_origin_cookies_allowed_schemes); cookie_settings_.set_matching_scheme_cookies_allowed_schemes( params->matching_scheme_cookies_allowed_schemes); + cookie_settings_.set_third_party_cookies_allowed_schemes( + params->third_party_cookies_allowed_schemes); } }
diff --git a/services/network/cookie_settings.cc b/services/network/cookie_settings.cc index e0e93a3..82fc269 100644 --- a/services/network/cookie_settings.cc +++ b/services/network/cookie_settings.cc
@@ -47,7 +47,9 @@ // Default to allowing cookies. *cookie_setting = CONTENT_SETTING_ALLOW; - bool block_third = block_third_party_cookies_; + bool block_third = block_third_party_cookies_ && + !base::ContainsKey(third_party_cookies_allowed_schemes_, + first_party_url.scheme()); for (const auto& entry : content_settings_) { if (entry.primary_pattern.Matches(url) && entry.secondary_pattern.Matches(first_party_url)) {
diff --git a/services/network/cookie_settings.h b/services/network/cookie_settings.h index 9f76b6b..578af6b3 100644 --- a/services/network/cookie_settings.h +++ b/services/network/cookie_settings.h
@@ -45,6 +45,14 @@ matching_scheme_cookies_allowed_schemes.end()); } + void set_third_party_cookies_allowed_schemes( + const std::vector<std::string>& third_party_cookies_allowed_schemes) { + third_party_cookies_allowed_schemes_.clear(); + third_party_cookies_allowed_schemes_.insert( + third_party_cookies_allowed_schemes.begin(), + third_party_cookies_allowed_schemes.end()); + } + // Returns a predicate that takes the domain of a cookie and a bool whether // the cookie is secure and returns true if the cookie should be deleted on // exit. @@ -65,6 +73,7 @@ bool block_third_party_cookies_ = false; std::set<std::string> secure_origin_cookies_allowed_schemes_; std::set<std::string> matching_scheme_cookies_allowed_schemes_; + std::set<std::string> third_party_cookies_allowed_schemes_; DISALLOW_COPY_AND_ASSIGN(CookieSettings); };
diff --git a/services/network/cookie_settings_unittest.cc b/services/network/cookie_settings_unittest.cc index 48cb1a9..d2e131ea 100644 --- a/services/network/cookie_settings_unittest.cc +++ b/services/network/cookie_settings_unittest.cc
@@ -123,16 +123,42 @@ settings.set_block_third_party_cookies(true); ContentSetting setting; - settings.GetCookieSetting(GURL("https://foo.com"), GURL("chrome://foo"), - nullptr, &setting); + settings.GetCookieSetting(GURL("https://foo.com") /* url */, + GURL("chrome://foo") /* first_party_url */, + nullptr /* source */, &setting); EXPECT_EQ(setting, CONTENT_SETTING_ALLOW); - settings.GetCookieSetting(GURL("chrome://foo"), GURL("https://foo.com"), - nullptr, &setting); + settings.GetCookieSetting(GURL("chrome://foo") /* url */, + GURL("https://foo.com") /* first_party_url */, + nullptr /* source */, &setting); EXPECT_EQ(setting, CONTENT_SETTING_BLOCK); - settings.GetCookieSetting(GURL("http://foo.com"), GURL("chrome://foo"), - nullptr, &setting); + settings.GetCookieSetting(GURL("http://foo.com") /* url */, + GURL("chrome://foo") /* first_party_url */, + nullptr /* source */, &setting); + EXPECT_EQ(setting, CONTENT_SETTING_BLOCK); +} + +TEST(CookieSettingsTest, GetCookieSettingWithThirdPartyCookiesAllowedScheme) { + CookieSettings settings; + settings.set_third_party_cookies_allowed_schemes({"chrome-extension"}); + settings.set_block_third_party_cookies(true); + + ContentSetting setting; + settings.GetCookieSetting( + GURL("http://foo.com") /* url */, + GURL("chrome-extension://foo") /* first_party_url */, + nullptr /* source */, &setting); + EXPECT_EQ(setting, CONTENT_SETTING_ALLOW); + + settings.GetCookieSetting(GURL("http://foo.com") /* url */, + GURL("other-scheme://foo") /* first_party_url */, + nullptr /* source */, &setting); + EXPECT_EQ(setting, CONTENT_SETTING_BLOCK); + + settings.GetCookieSetting(GURL("chrome-extension://foo") /* url */, + GURL("http://foo.com") /* first_party_url */, + nullptr /* source */, &setting); EXPECT_EQ(setting, CONTENT_SETTING_BLOCK); } @@ -142,16 +168,21 @@ settings.set_block_third_party_cookies(true); ContentSetting setting; - settings.GetCookieSetting(GURL("chrome-extension://bar"), - GURL("chrome-extension://foo"), nullptr, &setting); + settings.GetCookieSetting( + GURL("chrome-extension://bar") /* url */, + GURL("chrome-extension://foo") /* first_party_url */, + nullptr /* source */, &setting); EXPECT_EQ(setting, CONTENT_SETTING_ALLOW); - settings.GetCookieSetting(GURL("http://foo.com"), - GURL("chrome-extension://foo"), nullptr, &setting); + settings.GetCookieSetting( + GURL("http://foo.com") /* url */, + GURL("chrome-extension://foo") /* first_party_url */, + nullptr /* source */, &setting); EXPECT_EQ(setting, CONTENT_SETTING_BLOCK); - settings.GetCookieSetting(GURL("chrome-extension://foo"), - GURL("http://foo.com"), nullptr, &setting); + settings.GetCookieSetting(GURL("chrome-extension://foo") /* url */, + GURL("http://foo.com") /* first_party_url */, + nullptr /* source */, &setting); EXPECT_EQ(setting, CONTENT_SETTING_BLOCK); }
diff --git a/services/network/network_service_proxy_delegate.cc b/services/network/network_service_proxy_delegate.cc index 3c3e0a7..94d61a9 100644 --- a/services/network/network_service_proxy_delegate.cc +++ b/services/network/network_service_proxy_delegate.cc
@@ -52,7 +52,7 @@ rules.Apply(url, proxy_info); proxy_info->DeprioritizeBadProxies(proxy_retry_info); - return !proxy_info->proxy_server().is_direct(); + return !proxy_info->is_empty() && !proxy_info->proxy_server().is_direct(); } // Checks if |target_proxy| is in |proxy_list|.
diff --git a/services/network/network_service_proxy_delegate_unittest.cc b/services/network/network_service_proxy_delegate_unittest.cc index 4815f44f..f0397b6 100644 --- a/services/network/network_service_proxy_delegate_unittest.cc +++ b/services/network/network_service_proxy_delegate_unittest.cc
@@ -386,6 +386,22 @@ EXPECT_TRUE(result.proxy_list().Equals(expected_proxy_list)); } +TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyAllProxiesBad) { + auto config = mojom::CustomProxyConfig::New(); + config->rules.ParseFromString("http=foo"); + auto delegate = CreateDelegate(std::move(config)); + + net::ProxyInfo result; + result.UseDirect(); + net::ProxyRetryInfoMap retry_map; + net::ProxyRetryInfo& info = retry_map["foo:80"]; + info.try_while_bad = false; + info.bad_until = base::TimeTicks::Now() + base::TimeDelta::FromDays(2); + delegate->OnResolveProxy(GURL(kHttpUrl), "GET", retry_map, &result); + + EXPECT_TRUE(result.is_direct()); +} + TEST_F(NetworkServiceProxyDelegateTest, InitialConfigUsedForProxy) { auto config = mojom::CustomProxyConfig::New(); config->rules.ParseFromString("http=foo");
diff --git a/services/network/public/cpp/net_ipc_param_traits.h b/services/network/public/cpp/net_ipc_param_traits.h index 9ae1082f..9bfa614 100644 --- a/services/network/public/cpp/net_ipc_param_traits.h +++ b/services/network/public/cpp/net_ipc_param_traits.h
@@ -253,6 +253,7 @@ IPC_STRUCT_TRAITS_MEMBER(new_method) IPC_STRUCT_TRAITS_MEMBER(new_url) IPC_STRUCT_TRAITS_MEMBER(new_site_for_cookies) + IPC_STRUCT_TRAITS_MEMBER(new_top_frame_origin) IPC_STRUCT_TRAITS_MEMBER(new_referrer) IPC_STRUCT_TRAITS_MEMBER(insecure_scheme_was_upgraded) IPC_STRUCT_TRAITS_MEMBER(new_referrer_policy)
diff --git a/services/network/public/cpp/network_ipc_param_traits.h b/services/network/public/cpp/network_ipc_param_traits.h index 053601c..8e672fb 100644 --- a/services/network/public/cpp/network_ipc_param_traits.h +++ b/services/network/public/cpp/network_ipc_param_traits.h
@@ -139,6 +139,7 @@ IPC_STRUCT_TRAITS_MEMBER(method) IPC_STRUCT_TRAITS_MEMBER(url) IPC_STRUCT_TRAITS_MEMBER(site_for_cookies) + IPC_STRUCT_TRAITS_MEMBER(top_frame_origin) IPC_STRUCT_TRAITS_MEMBER(attach_same_site_cookies) IPC_STRUCT_TRAITS_MEMBER(update_first_party_url_on_redirect) IPC_STRUCT_TRAITS_MEMBER(request_initiator)
diff --git a/services/network/public/cpp/resource_request.h b/services/network/public/cpp/resource_request.h index fbadf62..cd8ba727 100644 --- a/services/network/public/cpp/resource_request.h +++ b/services/network/public/cpp/resource_request.h
@@ -43,6 +43,12 @@ // done if there really is no way to determine the correct value. GURL site_for_cookies; + // If the optional is valid, contains the origin of the top frame of the page + // making the request. Note that this is experimental and is only set for + // navigation and document subresource requests but not other cases such as + // workers. + base::Optional<url::Origin> top_frame_origin; + // Boolean indicating whether SameSite cookies are allowed to be attached // to the request. It should be used as additional input to network side // checks.
diff --git a/services/network/public/mojom/cookie_manager.mojom b/services/network/public/mojom/cookie_manager.mojom index 82d8ae8f..d991ce8 100644 --- a/services/network/public/mojom/cookie_manager.mojom +++ b/services/network/public/mojom/cookie_manager.mojom
@@ -21,6 +21,9 @@ // Schemes that unconditionally allow cookies from the same scheme. array<string> matching_scheme_cookies_allowed_schemes; + + // Schemes that unconditionally allow third party cookies. + array<string> third_party_cookies_allowed_schemes; }; enum CookiePriority {
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom index 0f431c33c..2402e05 100644 --- a/services/network/public/mojom/network_context.mojom +++ b/services/network/public/mojom/network_context.mojom
@@ -373,6 +373,13 @@ // Set to kBrowserProcessId to indicate the browser process. uint32 process_id = kInvalidProcessId; + // If specified, then |request_initiator_site_lock| locks + // |ResourceRequest::request_initiator| to the specified origin. + // TODO(lukasza): https://crbug.com/891872: Make this non-optional. + // TODO(lukasza, nasko): https://crbug.com/888079: Make this an *origin* lock + // (rather than just a site lock). + url.mojom.Origin? request_initiator_site_lock; + // Cross-origin read blocking (CORB) configuration. bool is_corb_enabled = true; // TODO(lukasza): The field below in practice is always set to
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc index 7e9be16..89f21f5 100644 --- a/services/network/url_loader.cc +++ b/services/network/url_loader.cc
@@ -13,14 +13,17 @@ #include "base/debug/alias.h" #include "base/debug/dump_without_crashing.h" #include "base/files/file.h" +#include "base/logging.h" #include "base/memory/weak_ptr.h" #include "base/metrics/histogram_macros.h" +#include "base/optional.h" #include "base/task/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "mojo/public/cpp/system/simple_watcher.h" #include "net/base/elements_upload_data_stream.h" #include "net/base/mime_sniffer.h" +#include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/base/upload_bytes_element_reader.h" #include "net/base/upload_file_element_reader.h" #include "net/cert/symantec_certs.h" @@ -43,6 +46,8 @@ #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/network/resource_scheduler_client.h" #include "services/network/throttling/scoped_throttling_token.h" +#include "url/origin.h" +#include "url/url_constants.h" namespace network { @@ -299,6 +304,53 @@ DISALLOW_COPY_AND_ASSIGN(SSLPrivateKeyInternal); }; +using InitiatorOriginLockCompatibility = + URLLoader::RequestInitiatorOriginLockCompatibility; +InitiatorOriginLockCompatibility VerifyRequestInitiatorOriginLock( + const mojom::URLLoaderFactoryParams& factory_params, + const ResourceRequest& request) { + if (factory_params.process_id == mojom::kBrowserProcessId) + return InitiatorOriginLockCompatibility::kBrowserProcess; + + if (!factory_params.request_initiator_site_lock.has_value()) + return InitiatorOriginLockCompatibility::kNoLock; + const url::Origin& lock = factory_params.request_initiator_site_lock.value(); + + if (!request.request_initiator.has_value()) { + NOTREACHED(); // Should only happen for the browser process. + return InitiatorOriginLockCompatibility::kNoInitiator; + } + const url::Origin& initiator = request.request_initiator.value(); + + if (initiator.opaque() || (initiator == lock)) + return InitiatorOriginLockCompatibility::kCompatibleLock; + + // TODO(lukasza, nasko): https://crbug.com/888079: Return kIncorrectLock if + // the origins do not match exactly in the previous if statement. Once we + // have precursor origins, there should be no need to fall back to + // site-url-safe comparisons. + // + // It is only safe to compare sites if no other site can reuse the process. + // For some schemes (e.g. chrome-extension) the comparison is not safe. + if (initiator.GetURL().SchemeIsHTTPOrHTTPS()) { + // Only keep the scheme and registered domain of |initiator|. + std::string domain = net::registry_controlled_domains::GetDomainAndRegistry( + initiator.host(), + net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); + std::string site = initiator.scheme(); + site += url::kStandardSchemeSeparator; + site += domain.empty() ? initiator.host() : domain; + + // Compare just the site URLs. + return GURL(site) == lock.GetURL() + ? InitiatorOriginLockCompatibility::kCompatibleLock + : InitiatorOriginLockCompatibility::kIncorrectLock; + } + return initiator.scheme() == lock.scheme() + ? InitiatorOriginLockCompatibility::kCompatibleLock + : InitiatorOriginLockCompatibility::kIncorrectLock; +} + } // namespace URLLoader::URLLoader( @@ -369,6 +421,7 @@ GURL(request.url), request.priority, this, traffic_annotation); url_request_->set_method(request.method); url_request_->set_site_for_cookies(request.site_for_cookies); + url_request_->set_top_frame_origin(request.top_frame_origin); url_request_->set_attach_same_site_cookies(request.attach_same_site_cookies); url_request_->SetReferrer(ComputeReferrer(request.referrer)); url_request_->set_referrer_policy(request.referrer_policy); @@ -398,6 +451,14 @@ throttling_token_ = network::ScopedThrottlingToken::MaybeCreate( url_request_->net_log().source().id, request.throttling_profile_id); + UMA_HISTOGRAM_ENUMERATION( + "NetworkService.URLLoader.RequestInitiatorOriginLockCompatibility", + VerifyRequestInitiatorOriginLock(*factory_params_, request)); + // TODO(lukasza): https://crbug.com/871827: Enforce the origin lock. In the + // long-term kIncorrectLock should trigger a renderer kill, but in the + // short-term we should at least fallback to using an opaque origin instead of + // a lock-incorrect |request.request_initiator| - using an opaque should be + // safe and hopefully also compatible with HTML Imports and SVG images. url_request_->set_initiator(request.request_initiator); if (request.update_first_party_url_on_redirect) {
diff --git a/services/network/url_loader.h b/services/network/url_loader.h index aedaec52..61e5054 100644 --- a/services/network/url_loader.h +++ b/services/network/url_loader.h
@@ -138,6 +138,37 @@ static const void* const kUserDataKey; + // These values are logged to UMA. Entries should not be renumbered and + // numeric values should never be reused. Please keep in sync with + // "RequestInitiatorOriginLockCompatibility" in + // tools/metrics/histograms/enums.xml. + enum class RequestInitiatorOriginLockCompatibility { + // Request came from a browser process and so the + // |request_initiator_site_lock| doesn't apply. + kBrowserProcess = 0, + + // |request_initiator_site_lock| is missing - see https://crbug.com/891872 + // and RenderProcessHostImpl::CreateURLLoaderFactoryWithOptionalOrigin. + kNoLock = 1, + + // |request_initiator| is missing. + kNoInitiator = 2, + + // |request.request_initiator| is compatible with + // |factory_params_.request_initiator_site_lock| - either + // |request.request_initiator| is opaque or it is equal to + // |request_initiator_site_lock|. + kCompatibleLock = 3, + + // |request.request_initiator| is incompatible with + // |factory_params_.request_initiator_site_lock|. Cases known so far where + // this can occur: + // - HTML Imports (see https://crbug.com/871827#c9). + kIncorrectLock = 4, + + kMaxValue = kIncorrectLock, + }; + private: // This class is used to set the URLLoader as user data on a URLRequest. This // is used instead of URLLoader directly because SetUserData requires a
diff --git a/services/resource_coordinator/coordination_unit/coordination_unit_test_harness.h b/services/resource_coordinator/coordination_unit/coordination_unit_test_harness.h index daf358d..ece34575 100644 --- a/services/resource_coordinator/coordination_unit/coordination_unit_test_harness.h +++ b/services/resource_coordinator/coordination_unit/coordination_unit_test_harness.h
@@ -35,7 +35,7 @@ TestCoordinationUnitWrapper(CoordinationUnitClass* impl) : impl_(impl) { DCHECK(impl); } - ~TestCoordinationUnitWrapper() { impl_->Destruct(); } + ~TestCoordinationUnitWrapper() { reset(); } CoordinationUnitClass* operator->() const { return impl_; } @@ -44,6 +44,13 @@ CoordinationUnitClass* get() const { return impl_; } + void reset() { + if (impl_) { + impl_->Destruct(); + impl_ = nullptr; + } + } + private: CoordinationUnitClass* impl_;
diff --git a/services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.cc b/services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.cc index 50eaa9af..dbc08fe 100644 --- a/services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.cc +++ b/services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.cc
@@ -18,7 +18,10 @@ : CoordinationUnitInterface(id, graph, std::move(keepalive_ref)), parent_frame_coordination_unit_(nullptr), page_coordination_unit_(nullptr), - process_coordination_unit_(nullptr) {} + process_coordination_unit_(nullptr) { + for (size_t i = 0; i < base::size(intervention_policy_); ++i) + intervention_policy_[i] = mojom::InterventionPolicy::kUnknown; +} FrameCoordinationUnitImpl::~FrameCoordinationUnitImpl() { if (parent_frame_coordination_unit_) @@ -98,6 +101,32 @@ has_nonempty_beforeunload_ = has_nonempty_beforeunload; } +void FrameCoordinationUnitImpl::SetInterventionPolicy( + mojom::PolicyControlledIntervention intervention, + mojom::InterventionPolicy policy) { + size_t i = static_cast<size_t>(intervention); + DCHECK_LT(i, base::size(intervention_policy_)); + + // This can only be called to set a policy, but not to revert a policy to the + // unset state. + DCHECK_NE(mojom::InterventionPolicy::kUnknown, policy); + + // We expect intervention policies to be initially set in order, and rely on + // that as a synchronization primitive. Ensure this is the case. + DCHECK(i == 0 || + intervention_policy_[i - 1] != mojom::InterventionPolicy::kUnknown); + + if (policy == intervention_policy_[i]) + return; + // Only notify of actual changes. + mojom::InterventionPolicy old_policy = intervention_policy_[i]; + intervention_policy_[i] = policy; + if (auto* page_cu = GetPageCoordinationUnit()) { + page_cu->OnFrameInterventionPolicyChanged(this, intervention, old_policy, + policy); + } +} + void FrameCoordinationUnitImpl::OnAlertFired() { SendEvent(mojom::Event::kAlertFired); } @@ -125,6 +154,36 @@ return !parent_frame_coordination_unit_; } +bool FrameCoordinationUnitImpl::AreAllInterventionPoliciesSet() const { + // The convention is that policies are first set en masse, in order. So if + // the last policy is set then they are all considered to be set. Check this + // in DEBUG builds. +#if DCHECK_IS_ON() + bool seen_unset_policy = false; + for (size_t i = 0; i < base::size(intervention_policy_); ++i) { + if (!seen_unset_policy) { + seen_unset_policy = + intervention_policy_[i] != mojom::InterventionPolicy::kUnknown; + } else { + // Once a first unset policy is seen, all subsequent policies must be + // unset. + DCHECK_NE(mojom::InterventionPolicy::kUnknown, intervention_policy_[i]); + } + } +#endif + + return intervention_policy_[base::size(intervention_policy_) - 1] != + mojom::InterventionPolicy::kUnknown; +} // namespace resource_coordinator + +void FrameCoordinationUnitImpl::SetAllInterventionPoliciesForTesting( + mojom::InterventionPolicy policy) { + for (size_t i = 0; i < base::size(intervention_policy_); ++i) { + SetInterventionPolicy(static_cast<mojom::PolicyControlledIntervention>(i), + policy); + } +} + void FrameCoordinationUnitImpl::OnEventReceived(mojom::Event event) { for (auto& observer : observers()) observer.OnFrameEventReceived(this, event);
diff --git a/services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h b/services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h index ebb59c9..e7696a12 100644 --- a/services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h +++ b/services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h
@@ -37,6 +37,8 @@ void SetNetworkAlmostIdle(bool idle) override; void SetLifecycleState(mojom::LifecycleState state) override; void SetHasNonEmptyBeforeUnload(bool has_nonempty_beforeunload) override; + void SetInterventionPolicy(mojom::PolicyControlledIntervention intervention, + mojom::InterventionPolicy policy) override; void OnAlertFired() override; void OnNonPersistentNotificationCreated() override; @@ -49,11 +51,18 @@ base::TimeTicks last_audible_time() const { return last_audible_time_; } bool has_nonempty_beforeunload() const { return has_nonempty_beforeunload_; } + // Returns true if all intervention policies have been set for this frame. + bool AreAllInterventionPoliciesSet() const; + const std::set<FrameCoordinationUnitImpl*>& child_frame_coordination_units_for_testing() const { return child_frame_coordination_units_; } + // Sets the same policy for all intervention types in this frame. Causes + // Page::OnFrameInterventionPolicyChanged to be invoked. + void SetAllInterventionPoliciesForTesting(mojom::InterventionPolicy policy); + private: friend class PageCoordinationUnitImpl; friend class ProcessCoordinationUnitImpl; @@ -89,6 +98,11 @@ bool has_nonempty_beforeunload_ = false; base::TimeTicks last_audible_time_; + // Intervention policy for this frame. These are communicated from the + // renderer process and are controlled by origin trials. + mojom::InterventionPolicy intervention_policy_ + [static_cast<size_t>(mojom::PolicyControlledIntervention::kMaxValue) + 1]; + DISALLOW_COPY_AND_ASSIGN(FrameCoordinationUnitImpl); };
diff --git a/services/resource_coordinator/coordination_unit/mock_coordination_unit_graphs.cc b/services/resource_coordinator/coordination_unit/mock_coordination_unit_graphs.cc index 3ef4d65e..10c775a 100644 --- a/services/resource_coordinator/coordination_unit/mock_coordination_unit_graphs.cc +++ b/services/resource_coordinator/coordination_unit/mock_coordination_unit_graphs.cc
@@ -27,6 +27,8 @@ graph)), page(TestCoordinationUnitWrapper<PageCoordinationUnitImpl>::Create( graph)) { + frame->SetAllInterventionPoliciesForTesting( + mojom::InterventionPolicy::kDefault); page->AddFrame(frame->id()); frame->SetProcess(process->id()); process->SetPID(1); @@ -44,6 +46,8 @@ graph)), other_page(TestCoordinationUnitWrapper<PageCoordinationUnitImpl>::Create( graph)) { + other_frame->SetAllInterventionPoliciesForTesting( + mojom::InterventionPolicy::kDefault); other_page->AddFrame(other_frame->id()); other_frame->SetProcess(process->id()); } @@ -61,6 +65,8 @@ other_process( TestCoordinationUnitWrapper<ProcessCoordinationUnitImpl>::Create( graph)) { + child_frame->SetAllInterventionPoliciesForTesting( + mojom::InterventionPolicy::kDefault); frame->AddChildFrame(child_frame->id()); page->AddFrame(child_frame->id()); child_frame->SetProcess(other_process->id()); @@ -80,6 +86,8 @@ other_process( TestCoordinationUnitWrapper<ProcessCoordinationUnitImpl>::Create( graph)) { + child_frame->SetAllInterventionPoliciesForTesting( + mojom::InterventionPolicy::kDefault); other_frame->AddChildFrame(child_frame->id()); other_page->AddFrame(child_frame->id()); child_frame->SetProcess(other_process->id());
diff --git a/services/resource_coordinator/coordination_unit/page_coordination_unit_impl.cc b/services/resource_coordinator/coordination_unit/page_coordination_unit_impl.cc index cb8f43b..25bdd8f 100644 --- a/services/resource_coordinator/coordination_unit/page_coordination_unit_impl.cc +++ b/services/resource_coordinator/coordination_unit/page_coordination_unit_impl.cc
@@ -13,11 +13,26 @@ namespace resource_coordinator { +namespace { + +constexpr size_t kMaxInterventionIndex = + static_cast<size_t>(mojom::PolicyControlledIntervention::kMaxValue); + +size_t ToIndex(mojom::PolicyControlledIntervention intervention) { + const size_t kIndex = static_cast<size_t>(intervention); + DCHECK(kIndex <= kMaxInterventionIndex); + return kIndex; +} + +} // namespace + PageCoordinationUnitImpl::PageCoordinationUnitImpl( const CoordinationUnitID& id, CoordinationUnitGraph* graph, std::unique_ptr<service_manager::ServiceKeepaliveRef> keepalive_ref) - : CoordinationUnitInterface(id, graph, std::move(keepalive_ref)) {} + : CoordinationUnitInterface(id, graph, std::move(keepalive_ref)) { + InvalidateAllInterventionPolicies(); +} PageCoordinationUnitImpl::~PageCoordinationUnitImpl() { for (auto* child_frame : frame_coordination_units_) @@ -160,6 +175,50 @@ OnNumFrozenFramesStateChange(delta); } +void PageCoordinationUnitImpl::OnFrameInterventionPolicyChanged( + FrameCoordinationUnitImpl* frame, + mojom::PolicyControlledIntervention intervention, + mojom::InterventionPolicy old_policy, + mojom::InterventionPolicy new_policy) { + const size_t kIndex = ToIndex(intervention); + + // Invalidate the local policy aggregation for this intervention. It will be + // recomputed on the next query to GetInterventionPolicy. + intervention_policy_[kIndex] = mojom::InterventionPolicy::kUnknown; + + // The first time a frame transitions away from kUnknown for the last policy, + // then that frame is considered to have checked in. Frames always provide + // initial policy values in order, ensuring this works. + if (old_policy == mojom::InterventionPolicy::kUnknown && + new_policy != mojom::InterventionPolicy::kUnknown && + intervention == mojom::PolicyControlledIntervention::kMaxValue) { + ++intervention_policy_frames_reported_; + DCHECK_LE(intervention_policy_frames_reported_, + frame_coordination_units_.size()); + } +} + +mojom::InterventionPolicy PageCoordinationUnitImpl::GetInterventionPolicy( + mojom::PolicyControlledIntervention intervention) { + // If there are no frames, or they've not all reported, then return kUnknown. + if (frame_coordination_units_.empty() || + intervention_policy_frames_reported_ != + frame_coordination_units_.size()) { + return mojom::InterventionPolicy::kUnknown; + } + + // Recompute the policy if it is currently invalid. + const size_t kIndex = ToIndex(intervention); + DCHECK_LE(kIndex, kMaxInterventionIndex); + if (intervention_policy_[kIndex] == mojom::InterventionPolicy::kUnknown) { + RecomputeInterventionPolicy(intervention); + DCHECK_NE(mojom::InterventionPolicy::kUnknown, + intervention_policy_[kIndex]); + } + + return intervention_policy_[kIndex]; +} + void PageCoordinationUnitImpl::OnEventReceived(mojom::Event event) { for (auto& observer : observers()) observer.OnPageEventReceived(this, event); @@ -179,6 +238,7 @@ if (inserted) { OnNumFrozenFramesStateChange( frame_cu->lifecycle_state() == mojom::LifecycleState::kFrozen ? 1 : 0); + MaybeInvalidateInterventionPolicies(frame_cu, true /* adding_frame */); } return inserted; } @@ -189,14 +249,15 @@ if (removed) { OnNumFrozenFramesStateChange( frame_cu->lifecycle_state() == mojom::LifecycleState::kFrozen ? -1 : 0); + MaybeInvalidateInterventionPolicies(frame_cu, false /* adding_frame */); } + return removed; } void PageCoordinationUnitImpl::OnNumFrozenFramesStateChange( int num_frozen_frames_delta) { num_frozen_frames_ += num_frozen_frames_delta; - DCHECK_GE(num_frozen_frames_, 0u); DCHECK_LE(num_frozen_frames_, frame_coordination_units_.size()); const int64_t kRunning = @@ -233,4 +294,71 @@ is_fully_frozen ? kFrozen : kRunning); } +void PageCoordinationUnitImpl::InvalidateAllInterventionPolicies() { + for (size_t i = 0; i <= kMaxInterventionIndex; ++i) + intervention_policy_[i] = mojom::InterventionPolicy::kUnknown; +} + +void PageCoordinationUnitImpl::MaybeInvalidateInterventionPolicies( + FrameCoordinationUnitImpl* frame_cu, + bool adding_frame) { + // Ensure that the frame was already added or removed as expected. + DCHECK(adding_frame == frame_coordination_units_.count(frame_cu)); + + // Determine whether or not the frames had all reported prior to this change. + const size_t prior_frame_count = + frame_coordination_units_.size() + (adding_frame ? -1 : 1); + const bool frames_all_reported_prior = + prior_frame_count > 0 && + intervention_policy_frames_reported_ == prior_frame_count; + + // If the previous state was considered fully reported, then aggregation may + // have occurred. Adding or removing a frame (even one that is fully reported) + // needs to invalidate that aggregation. Invalidation could happen on every + // single frame addition and removal, but only doing this when the previous + // state was fully reported reduces unnecessary invalidations. + if (frames_all_reported_prior) + InvalidateAllInterventionPolicies(); + + // Update the reporting frame count. + const bool frame_reported = frame_cu->AreAllInterventionPoliciesSet(); + if (frame_reported) + intervention_policy_frames_reported_ += adding_frame ? 1 : -1; + + DCHECK_LE(intervention_policy_frames_reported_, + frame_coordination_units_.size()); +} + +void PageCoordinationUnitImpl::RecomputeInterventionPolicy( + mojom::PolicyControlledIntervention intervention) { + const size_t kIndex = ToIndex(intervention); + + // This should never be called with an empty frame tree. + DCHECK(!frame_coordination_units_.empty()); + + mojom::InterventionPolicy policy = mojom::InterventionPolicy::kDefault; + for (auto* frame : frame_coordination_units_) { + // No frame should have an unknown policy, as aggregation should only be + // invoked after all frames have checked in. + DCHECK_NE(mojom::InterventionPolicy::kUnknown, + frame->intervention_policy_[kIndex]); + + // If any frame opts out then the whole frame tree opts out, even if other + // frames have opted in. + if (frame->intervention_policy_[kIndex] == + mojom::InterventionPolicy::kOptOut) { + intervention_policy_[kIndex] = mojom::InterventionPolicy::kOptOut; + return; + } + + // If any frame opts in and none opt out, then the whole tree opts in. + if (frame->intervention_policy_[kIndex] == + mojom::InterventionPolicy::kOptIn) { + policy = mojom::InterventionPolicy::kOptIn; + } + } + + intervention_policy_[kIndex] = policy; +} + } // namespace resource_coordinator
diff --git a/services/resource_coordinator/coordination_unit/page_coordination_unit_impl.h b/services/resource_coordinator/coordination_unit/page_coordination_unit_impl.h index ef4d8a7..3202166 100644 --- a/services/resource_coordinator/coordination_unit/page_coordination_unit_impl.h +++ b/services/resource_coordinator/coordination_unit/page_coordination_unit_impl.h
@@ -97,6 +97,29 @@ void OnFrameLifecycleStateChanged(FrameCoordinationUnitImpl* frame_cu, mojom::LifecycleState old_state); + void OnFrameInterventionPolicyChanged( + FrameCoordinationUnitImpl* frame, + mojom::PolicyControlledIntervention intervention, + mojom::InterventionPolicy old_policy, + mojom::InterventionPolicy new_policy); + + // Gets the current policy for the specified |intervention|, recomputing it + // from individual frame policies if necessary. Returns kUnknown until there + // are 1 or more frames, and they have all computed their local policy + // settings. + mojom::InterventionPolicy GetInterventionPolicy( + mojom::PolicyControlledIntervention intervention); + + // Similar to GetInterventionPolicy, but doesn't trigger recomputes. + mojom::InterventionPolicy GetRawInterventionPolicyForTesting( + mojom::PolicyControlledIntervention intervention) const { + return intervention_policy_[static_cast<size_t>(intervention)]; + } + + size_t GetInterventionPolicyFramesReportedForTesting() const { + return intervention_policy_frames_reported_; + } + private: friend class FrameCoordinationUnitImpl; @@ -115,6 +138,22 @@ // number of frames itself has changed. void OnNumFrozenFramesStateChange(int num_frozen_frames_delta); + // Invalidates all currently aggregated intervention policies. + void InvalidateAllInterventionPolicies(); + + // Invoked when adding or removing a frame. This will update + // |intervention_policy_frames_reported_| if necessary and potentially + // invalidate the aggregated intervention policies. This should be called + // after the frame has already been added or removed from + // |frame_coordination_units_|. + void MaybeInvalidateInterventionPolicies(FrameCoordinationUnitImpl* frame_cu, + bool adding_frame); + + // Recomputes intervention policy aggregation. This is invoked on demand when + // a policy is queried. + void RecomputeInterventionPolicy( + mojom::PolicyControlledIntervention intervention); + std::set<FrameCoordinationUnitImpl*> frame_coordination_units_; base::TimeTicks visibility_change_time_; @@ -148,6 +187,20 @@ std::string main_frame_url_; int64_t navigation_id_ = 0; + // The aggregate intervention policy states for this page. These are + // aggregated from the corresponding per-frame values. If an individual value + // is kUnknown then a frame in the frame tree has changed values and + // a new aggregation is required. + mojom::InterventionPolicy intervention_policy_ + [static_cast<size_t>(mojom::PolicyControlledIntervention::kMaxValue) + 1]; + + // The number of child frames that have checked in with initial intervention + // policy values. If this doesn't match the number of known child frames, then + // aggregation isn't possible. Child frames check in with all properties once + // immediately after document parsing, and the *last* value being set + // is used as a signal that the frame has reported. + size_t intervention_policy_frames_reported_ = 0; + DISALLOW_COPY_AND_ASSIGN(PageCoordinationUnitImpl); };
diff --git a/services/resource_coordinator/coordination_unit/page_coordination_unit_impl_unittest.cc b/services/resource_coordinator/coordination_unit/page_coordination_unit_impl_unittest.cc index 140d7a2..fc1a4be 100644 --- a/services/resource_coordinator/coordination_unit/page_coordination_unit_impl_unittest.cc +++ b/services/resource_coordinator/coordination_unit/page_coordination_unit_impl_unittest.cc
@@ -249,4 +249,178 @@ mojom::PropertyType::kLifecycleState, kRunning)); } +namespace { + +const size_t kInterventionCount = + static_cast<size_t>(mojom::PolicyControlledIntervention::kMaxValue) + 1; + +void ExpectRawInterventionPolicy(mojom::InterventionPolicy policy, + const PageCoordinationUnitImpl* page_cu) { + for (size_t i = 0; i < kInterventionCount; ++i) { + EXPECT_EQ(policy, page_cu->GetRawInterventionPolicyForTesting( + static_cast<mojom::PolicyControlledIntervention>(i))); + } +} + +void ExpectInterventionPolicy(mojom::InterventionPolicy policy, + PageCoordinationUnitImpl* page_cu) { + for (size_t i = 0; i < kInterventionCount; ++i) { + EXPECT_EQ(policy, page_cu->GetInterventionPolicy( + static_cast<mojom::PolicyControlledIntervention>(i))); + } +} + +void ExpectInitialInterventionPolicyAggregationWorks( + CoordinationUnitGraph* cu_graph, + mojom::InterventionPolicy f0_policy, + mojom::InterventionPolicy f1_policy, + mojom::InterventionPolicy f0_policy_aggregated, + mojom::InterventionPolicy f0f1_policy_aggregated) { + // Create two frames not tied to any page. + TestCoordinationUnitWrapper<FrameCoordinationUnitImpl> f0 = + TestCoordinationUnitWrapper<FrameCoordinationUnitImpl>::Create(cu_graph); + TestCoordinationUnitWrapper<FrameCoordinationUnitImpl> f1 = + TestCoordinationUnitWrapper<FrameCoordinationUnitImpl>::Create(cu_graph); + + // Set frame policies before attaching to a page CU. + f0->SetAllInterventionPoliciesForTesting(f0_policy); + f1->SetAllInterventionPoliciesForTesting(f1_policy); + + // Check the initial values before any frames are added. + TestCoordinationUnitWrapper<PageCoordinationUnitImpl> page = + TestCoordinationUnitWrapper<PageCoordinationUnitImpl>::Create(cu_graph); + EXPECT_EQ(0u, page->GetInterventionPolicyFramesReportedForTesting()); + ExpectRawInterventionPolicy(mojom::InterventionPolicy::kUnknown, page.get()); + ExpectInterventionPolicy(mojom::InterventionPolicy::kUnknown, page.get()); + + // Add a frame and expect the values to be invalidated. Reaggregate and + // ensure the appropriate value results. + page->AddFrame(f0->id()); + EXPECT_EQ(1u, page->GetInterventionPolicyFramesReportedForTesting()); + ExpectRawInterventionPolicy(mojom::InterventionPolicy::kUnknown, page.get()); + ExpectInterventionPolicy(f0_policy_aggregated, page.get()); + + // Do it again. This time the raw values should be the same as the + // aggregated values above. + page->AddFrame(f1->id()); + EXPECT_EQ(2u, page->GetInterventionPolicyFramesReportedForTesting()); + ExpectRawInterventionPolicy(mojom::InterventionPolicy::kUnknown, page.get()); + ExpectInterventionPolicy(f0f1_policy_aggregated, page.get()); + + // Remove a frame and expect the values to be invalidated again. + f1.reset(); + EXPECT_EQ(1u, page->GetInterventionPolicyFramesReportedForTesting()); + ExpectRawInterventionPolicy(mojom::InterventionPolicy::kUnknown, page.get()); + ExpectInterventionPolicy(f0_policy_aggregated, page.get()); +} + +} // namespace + +TEST_F(PageCoordinationUnitImplTest, InitialInterventionPolicy) { + auto* cu_graph = coordination_unit_graph(); + + // Tests all possible transitions where the frame CU has its policy values + // set before being attached to the page CU. This affectively tests the + // aggregation logic in isolation. + + // Default x [Default, OptIn, OptOut] + + ExpectInitialInterventionPolicyAggregationWorks( + cu_graph, mojom::InterventionPolicy::kDefault /* f0_policy */, + mojom::InterventionPolicy::kDefault /* f1_policy */, + mojom::InterventionPolicy::kDefault /* f0_policy_aggregated */, + mojom::InterventionPolicy::kDefault /* f0f1_policy_aggregated */); + + ExpectInitialInterventionPolicyAggregationWorks( + cu_graph, mojom::InterventionPolicy::kDefault /* f0_policy */, + mojom::InterventionPolicy::kOptIn /* f1_policy */, + mojom::InterventionPolicy::kDefault /* f0_policy_aggregated */, + mojom::InterventionPolicy::kOptIn /* f0f1_policy_aggregated */); + + ExpectInitialInterventionPolicyAggregationWorks( + cu_graph, mojom::InterventionPolicy::kDefault /* f0_policy */, + mojom::InterventionPolicy::kOptOut /* f1_policy */, + mojom::InterventionPolicy::kDefault /* f0_policy_aggregated */, + mojom::InterventionPolicy::kOptOut /* f0f1_policy_aggregated */); + + // OptIn x [Default, OptIn, OptOut] + + ExpectInitialInterventionPolicyAggregationWorks( + cu_graph, mojom::InterventionPolicy::kOptIn /* f0_policy */, + mojom::InterventionPolicy::kDefault /* f1_policy */, + mojom::InterventionPolicy::kOptIn /* f0_policy_aggregated */, + mojom::InterventionPolicy::kOptIn /* f0f1_policy_aggregated */); + + ExpectInitialInterventionPolicyAggregationWorks( + cu_graph, mojom::InterventionPolicy::kOptIn /* f0_policy */, + mojom::InterventionPolicy::kOptIn /* f1_policy */, + mojom::InterventionPolicy::kOptIn /* f0_policy_aggregated */, + mojom::InterventionPolicy::kOptIn /* f0f1_policy_aggregated */); + + ExpectInitialInterventionPolicyAggregationWorks( + cu_graph, mojom::InterventionPolicy::kOptIn /* f0_policy */, + mojom::InterventionPolicy::kOptOut /* f1_policy */, + mojom::InterventionPolicy::kOptIn /* f0_policy_aggregated */, + mojom::InterventionPolicy::kOptOut /* f0f1_policy_aggregated */); + + // OptOut x [Default, OptIn, OptOut] + + ExpectInitialInterventionPolicyAggregationWorks( + cu_graph, mojom::InterventionPolicy::kOptOut /* f0_policy */, + mojom::InterventionPolicy::kDefault /* f1_policy */, + mojom::InterventionPolicy::kOptOut /* f0_policy_aggregated */, + mojom::InterventionPolicy::kOptOut /* f0f1_policy_aggregated */); + + ExpectInitialInterventionPolicyAggregationWorks( + cu_graph, mojom::InterventionPolicy::kOptOut /* f0_policy */, + mojom::InterventionPolicy::kOptIn /* f1_policy */, + mojom::InterventionPolicy::kOptOut /* f0_policy_aggregated */, + mojom::InterventionPolicy::kOptOut /* f0f1_policy_aggregated */); + + ExpectInitialInterventionPolicyAggregationWorks( + cu_graph, mojom::InterventionPolicy::kOptOut /* f0_policy */, + mojom::InterventionPolicy::kOptOut /* f1_policy */, + mojom::InterventionPolicy::kOptOut /* f0_policy_aggregated */, + mojom::InterventionPolicy::kOptOut /* f0f1_policy_aggregated */); +} + +TEST_F(PageCoordinationUnitImplTest, IncrementalInterventionPolicy) { + auto* cu_graph = coordination_unit_graph(); + + TestCoordinationUnitWrapper<PageCoordinationUnitImpl> page = + TestCoordinationUnitWrapper<PageCoordinationUnitImpl>::Create(cu_graph); + + // Create two frames and immediately attach them to the page. + TestCoordinationUnitWrapper<FrameCoordinationUnitImpl> f0 = + TestCoordinationUnitWrapper<FrameCoordinationUnitImpl>::Create(cu_graph); + TestCoordinationUnitWrapper<FrameCoordinationUnitImpl> f1 = + TestCoordinationUnitWrapper<FrameCoordinationUnitImpl>::Create(cu_graph); + EXPECT_EQ(0u, page->GetInterventionPolicyFramesReportedForTesting()); + page->AddFrame(f0->id()); + EXPECT_EQ(0u, page->GetInterventionPolicyFramesReportedForTesting()); + page->AddFrame(f1->id()); + EXPECT_EQ(0u, page->GetInterventionPolicyFramesReportedForTesting()); + + // Set the policies on the first frame. This should be observed by the page + // CU, but aggregation should still not be possible. + f0->SetAllInterventionPoliciesForTesting(mojom::InterventionPolicy::kDefault); + EXPECT_EQ(1u, page->GetInterventionPolicyFramesReportedForTesting()); + ExpectRawInterventionPolicy(mojom::InterventionPolicy::kUnknown, page.get()); + ExpectInterventionPolicy(mojom::InterventionPolicy::kUnknown, page.get()); + + // Now set the policy on the second frame. This should be observed and an + // aggregated page policy value should now be available. + f1->SetAllInterventionPoliciesForTesting(mojom::InterventionPolicy::kDefault); + EXPECT_EQ(2u, page->GetInterventionPolicyFramesReportedForTesting()); + ExpectRawInterventionPolicy(mojom::InterventionPolicy::kUnknown, page.get()); + ExpectInterventionPolicy(mojom::InterventionPolicy::kDefault, page.get()); + + // Change the policy value on a frame and expect a new aggregation to be + // required. + f1->SetAllInterventionPoliciesForTesting(mojom::InterventionPolicy::kOptIn); + EXPECT_EQ(2u, page->GetInterventionPolicyFramesReportedForTesting()); + ExpectRawInterventionPolicy(mojom::InterventionPolicy::kUnknown, page.get()); + ExpectInterventionPolicy(mojom::InterventionPolicy::kOptIn, page.get()); +} + } // namespace resource_coordinator
diff --git a/services/resource_coordinator/public/mojom/coordination_unit.mojom b/services/resource_coordinator/public/mojom/coordination_unit.mojom index 62e4a47..52cf9d0 100644 --- a/services/resource_coordinator/public/mojom/coordination_unit.mojom +++ b/services/resource_coordinator/public/mojom/coordination_unit.mojom
@@ -19,6 +19,33 @@ kSystem, }; +// Intervention policy status. This mirrors the definitions used by the +// InterventionPolicyDatabase defined in +// chrome/browser/resource_coordinator/intervention_policy_database.proto +enum InterventionPolicy { + // The frame/page policy is yet unknown. This is the state while a frame is + // still loading. + kUnknown, + // The frame/page has explicitly opted-in to an intervention. + kOptIn, + // The frame/page has explicitly opted-out from an intervention. + kOptOut, + // The frame/page has neither opted-in or opted-out. The intervention will be + // applied usings its own heuristics. + kDefault, +}; + +// A list of interventions for which policy is communicated from individual +// frames and propagated through the frame tree. As each frame loads it will +// communicate the policy state to the associated FrameCoordinationUnit, and +// these will eventually be aggregated to the parent PageCoordinationUnit and +// applied to an entire frame tree. +enum PolicyControlledIntervention { + // Page lifecycles is a feature that causes pages to transition through + // lifecycle states in an attempt to save/reclaim resources. + kPageLifecycleTransitions, +}; + struct CoordinationUnitID { CoordinationUnitType type; int64 id; @@ -67,6 +94,8 @@ SetNetworkAlmostIdle(bool idle); SetLifecycleState(LifecycleState state); SetHasNonEmptyBeforeUnload(bool has_nonempty_beforeunload); + SetInterventionPolicy(PolicyControlledIntervention intervention, + InterventionPolicy policy); // Event signals. OnAlertFired();
diff --git a/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc b/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc index cb76f42..31ecd0b 100644 --- a/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc +++ b/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc
@@ -29,22 +29,64 @@ namespace service_manager { namespace { -constexpr const char* const kRendererServices[] = { - fuchsia::fonts::Provider::Name_, fuchsia::mediacodec::CodecFactory::Name_}; +enum SandboxFeature { + // Clones the job. This is required to start new processes (to make it useful + // the process will also need access to the fuchsia.process.Launcher service). + kCloneJob = 1 << 0, -constexpr const char* const kGpuServices[] = { - fuchsia::ui::scenic::Scenic::Name_}; + // Provides access to resources required by Vulkan. + kProvideVulkanResources = 1 << 1, -base::span<const char* const> GetServicesListForSandboxType( - service_manager::SandboxType type) { - switch (type) { - case service_manager::SANDBOX_TYPE_RENDERER: - return base::make_span(kRendererServices); - case service_manager::SANDBOX_TYPE_GPU: - return base::make_span(kGpuServices); - default: - return base::span<const char* const>(); + // Read only access to /config/ssl, which contains root certs info. + kProvideSslConfig = 1 << 2, +}; + +struct SandboxConfig { + SandboxType type; + base::span<const char* const> services; + uint32_t features; +}; + +constexpr SandboxConfig kSandboxConfigs[] = { + { + SANDBOX_TYPE_WEB_CONTEXT, + + // Services directory is passed by calling SetServiceDirectory(). + base::span<const char* const>(), + + // kCloneJob: context process needs to be able to spawn child processes. + // kProvideVulkanResources: Vulkan access is required to delegate to the + // GPU process. kProvideSslConfig: Context process is responsible for + // cert verification. + kCloneJob | kProvideVulkanResources | kProvideSslConfig, + }, + { + SANDBOX_TYPE_RENDERER, + base::make_span( + (const char* const[]){fuchsia::fonts::Provider::Name_, + fuchsia::mediacodec::CodecFactory::Name_}), + 0, + }, + { + SANDBOX_TYPE_GPU, + base::make_span( + (const char* const[]){fuchsia::ui::scenic::Scenic::Name_}), + kProvideVulkanResources, + }, +}; + +constexpr SandboxConfig kDefaultConfig = { + SANDBOX_TYPE_INVALID, + base::span<const char* const>(), + 0, +}; + +const SandboxConfig& GetConfigForSandboxType(SandboxType type) { + for (auto& config : kSandboxConfigs) { + if (config.type == type) + return config; } + return kDefaultConfig; } } // namespace @@ -73,13 +115,13 @@ // |sandbox_directory_| and initialize it with the corresponding list of // services. FilteredServiceDirectory must be initialized on a thread that has // async_dispatcher. - auto services_list = GetServicesListForSandboxType(type_); - if (!services_list.empty()) { + const SandboxConfig& config = GetConfigForSandboxType(type_); + if (!config.services.empty()) { service_directory_task_runner_ = base::ThreadTaskRunnerHandle::Get(); service_directory_ = std::make_unique<base::fuchsia::FilteredServiceDirectory>( base::fuchsia::ComponentContext::GetDefault()); - for (const char* service_name : services_list) + for (const char* service_name : config.services) service_directory_->AddService(service_name); // Bind the service directory and store the client channel for @@ -89,12 +131,22 @@ } } +void SandboxPolicyFuchsia::SetServiceDirectory( + zx::channel service_directory_client_channel) { + DCHECK_EQ(type_, SANDBOX_TYPE_WEB_CONTEXT); + DCHECK(!service_directory_client_channel_); + + service_directory_client_channel_ = + std::move(service_directory_client_channel); +} + void SandboxPolicyFuchsia::UpdateLaunchOptionsForSandbox( base::LaunchOptions* options) { DCHECK_NE(type_, service_manager::SANDBOX_TYPE_INVALID); // Always clone stderr to get logs output. options->fds_to_remap.push_back(std::make_pair(STDERR_FILENO, STDERR_FILENO)); + options->fds_to_remap.push_back(std::make_pair(STDOUT_FILENO, STDOUT_FILENO)); if (type_ == service_manager::SANDBOX_TYPE_NO_SANDBOX) { options->spawn_flags = FDIO_SPAWN_CLONE_NAMESPACE | FDIO_SPAWN_CLONE_JOB; @@ -105,7 +157,7 @@ // Map /pkg (read-only files deployed from the package) into the child's // namespace. base::FilePath package_root; - base::PathService::Get(base::DIR_SOURCE_ROOT, &package_root); + base::PathService::Get(base::DIR_ASSETS, &package_root); options->paths_to_clone.push_back(package_root); // Clear environmental variables to better isolate the child from @@ -115,7 +167,23 @@ // Don't clone anything by default. options->spawn_flags = 0; - if (service_directory_) { + const SandboxConfig& config = GetConfigForSandboxType(type_); + + if (config.features & kCloneJob) + options->spawn_flags |= FDIO_SPAWN_CLONE_JOB; + + if (config.features & kProvideSslConfig) + options->paths_to_clone.push_back(base::FilePath("/config/ssl")); + + if (config.features & kProvideVulkanResources) { + // /system/lib is used to load Vilkan libraries. /dev/class/gpu and + // /config/vulkan/icd.d are to used configure and access the GPU. + options->paths_to_clone.push_back(base::FilePath("/system/lib")); + options->paths_to_clone.push_back(base::FilePath("/dev/class/gpu")); + options->paths_to_clone.push_back(base::FilePath("/config/vulkan/icd.d")); + } + + if (service_directory_client_channel_) { // Provide the child process with a restricted set of services. options->paths_to_transfer.push_back(base::PathToTransfer{ base::FilePath("/svc"), service_directory_client_channel_.release()});
diff --git a/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.h b/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.h index 8dd65c2..d6607529 100644 --- a/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.h +++ b/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.h
@@ -32,6 +32,10 @@ // IO thread. void Initialize(service_manager::SandboxType type); + // Sets the service directory that's passed to the child process as /svc. Must + // be used only for the web context process. + void SetServiceDirectory(zx::channel service_directory_client_channel); + // Modifies the process launch |options| to achieve the level of // isolation appropriate for current the sandbox type. The caller may then add // any descriptors or handles afterward to grant additional capabilities
diff --git a/services/service_manager/sandbox/sandbox_type.h b/services/service_manager/sandbox/sandbox_type.h index f0c04da8..23211a5 100644 --- a/services/service_manager/sandbox/sandbox_type.h +++ b/services/service_manager/sandbox/sandbox_type.h
@@ -31,6 +31,12 @@ SANDBOX_TYPE_XRCOMPOSITING, #endif +#if defined(OS_FUCHSIA) + // Sandbox type for the web::Context process on Fuchsia. Functionally it's an + // equivalent of the browser process on other platforms. + SANDBOX_TYPE_WEB_CONTEXT, +#endif + // Renderer or worker process. Most common case. SANDBOX_TYPE_RENDERER,
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc index 3bc5009..c2181d1 100644 --- a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc +++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
@@ -4,6 +4,7 @@ #include "services/tracing/public/cpp/perfetto/trace_event_data_source.h" +#include <atomic> #include <map> #include <utility> @@ -11,7 +12,9 @@ #include "base/memory/ref_counted_memory.h" #include "base/no_destructor.h" #include "base/process/process_handle.h" +#include "base/trace_event/trace_buffer.h" #include "base/trace_event/trace_event.h" +#include "build/build_config.h" #include "services/tracing/public/cpp/perfetto/traced_value_proto_writer.h" #include "services/tracing/public/mojom/constants.mojom.h" #include "third_party/perfetto/include/perfetto/tracing/core/shared_memory_arbiter.h" @@ -25,6 +28,14 @@ namespace { static const size_t kMaxEventsPerMessage = 100; +static const size_t kMaxCompleteEventDepth = 20; + +// To mark TraceEvent handles that have been added by Perfetto, +// we use the chunk index so high that TraceLog would've asserted +// at this point anyway. +static const uint32_t kMagicChunkIndex = + base::trace_event::TraceBufferChunk::kMaxChunkIndex; + } // namespace namespace tracing { @@ -108,7 +119,12 @@ ThreadLocalEventSink(std::unique_ptr<perfetto::TraceWriter> trace_writer, bool thread_will_flush) : trace_writer_(std::move(trace_writer)), - thread_will_flush_(thread_will_flush) {} + thread_will_flush_(thread_will_flush) { +#if DCHECK_IS_ON() + static std::atomic<int32_t> id_counter(1); + sink_id_ = id_counter.fetch_add(1, std::memory_order_relaxed); +#endif // DCHECK_IS_ON() + } ~ThreadLocalEventSink() { // Finalize the current message before posting the |trace_writer_| for @@ -171,7 +187,8 @@ arg->set_json_value(json.c_str()); } - void AddTraceEvent(TraceEvent* trace_event) { + void AddTraceEvent(TraceEvent* trace_event, + base::trace_event::TraceEventHandle* handle) { // TODO(oysteine): Adding trace events to Perfetto will // stall in some situations, specifically when we overflow // the buffer and need to make a sync call to flush it, and we're @@ -186,11 +203,36 @@ return; } + if (handle && trace_event->phase() == TRACE_EVENT_PHASE_COMPLETE) { + // 'X' phase events are added through a scoped object and + // will have its duration updated when said object drops off + // the stack; keep a copy of the event around instead of + // writing it into SHM, until we have the duration. + // We can't keep the TraceEvent around in the scoped object + // itself as that causes a lot more codegen in the callsites + // and bloats the binary size too much (due to the increased + // sizeof() of the scoped object itself). + DCHECK_LT(current_stack_depth_, kMaxCompleteEventDepth); + if (current_stack_depth_ >= kMaxCompleteEventDepth) { + return; + } + +#if DCHECK_IS_ON() + handle->chunk_seq = sink_id_; +#endif // DCHECK_IS_ON() + + complete_event_stack_[current_stack_depth_] = std::move(*trace_event); + handle->event_index = ++current_stack_depth_; + handle->chunk_index = kMagicChunkIndex; + return; + } + EnsureValidHandles(); - int name_index = 0; - int category_name_index = 0; - int arg_name_indices[base::trace_event::kTraceMaxNumArgs] = {0}; + uint32_t name_index = 0; + uint32_t category_name_index = 0; + const size_t kMaxSize = base::trace_event::TraceArguments::kMaxSize; + uint32_t arg_name_indices[kMaxSize] = {0}; // Populate any new string table parts first; has to be done before // the add_trace_events() call (as the string table is part of the outer @@ -206,9 +248,8 @@ GetStringTableIndexForString(TraceLog::GetCategoryGroupName( trace_event->category_group_enabled())); - for (int i = 0; - i < base::trace_event::kTraceMaxNumArgs && trace_event->arg_name(i); - ++i) { + for (size_t i = 0; + i < trace_event->arg_size() && trace_event->arg_name(i); ++i) { arg_name_indices[i] = GetStringTableIndexForString(trace_event->arg_name(i)); } @@ -252,8 +293,7 @@ char phase = trace_event->phase(); new_trace_event->set_phase(phase); - for (int i = 0; - i < base::trace_event::kTraceMaxNumArgs && trace_event->arg_name(i); + for (size_t i = 0; i < trace_event->arg_size() && trace_event->arg_name(i); ++i) { auto type = trace_event->arg_type(i); auto* new_arg = new_trace_event->add_args(); @@ -299,15 +339,7 @@ } if (phase == TRACE_EVENT_PHASE_COMPLETE) { - int64_t duration = trace_event->duration().InMicroseconds(); - if (duration != -1) { - new_trace_event->set_duration(duration); - } else { - // TODO(oysteine): Workaround until TRACE_EVENT_PHASE_COMPLETE can be - // split into begin/end pairs. If the duration is -1 and the - // trace-viewer will spend forever generating a warning for each event. - new_trace_event->set_duration(0); - } + new_trace_event->set_duration(trace_event->duration().InMicroseconds()); if (!trace_event->thread_timestamp().is_null()) { int64_t thread_duration = @@ -350,7 +382,37 @@ } } + void UpdateDuration(base::trace_event::TraceEventHandle handle, + const base::TimeTicks& now, + const base::ThreadTicks& thread_now) { + if (!handle.event_index || handle.chunk_index != kMagicChunkIndex) { + return; + } + +#if DCHECK_IS_ON() + DCHECK_EQ(handle.chunk_seq, sink_id_); +#endif // DCHECK_IS_ON() + + DCHECK_EQ(handle.event_index, current_stack_depth_); + DCHECK_GE(current_stack_depth_, 1u); + current_stack_depth_--; + complete_event_stack_[current_stack_depth_].UpdateDuration(now, thread_now); + AddTraceEvent(&complete_event_stack_[current_stack_depth_], nullptr); + +#if defined(OS_ANDROID) + complete_event_stack_[current_stack_depth_].SendToATrace(); +#endif + } + void Flush() { + // TODO(oysteine): This will break events if we flush + // while recording. This can't be done on destruction + // as this can trigger PostTasks which may not be possible + // if the thread is being shut down. + while (current_stack_depth_--) { + AddTraceEvent(&complete_event_stack_[current_stack_depth_], nullptr); + } + event_bundle_ = ChromeEventBundleHandle(); trace_packet_handle_ = perfetto::TraceWriter::TracePacketHandle(); trace_writer_->Flush(); @@ -364,6 +426,11 @@ std::map<intptr_t, int> string_table_; int next_string_table_index_ = 0; size_t current_eventcount_for_message_ = 0; + TraceEvent complete_event_stack_[kMaxCompleteEventDepth]; + uint32_t current_stack_depth_ = 0; +#if DCHECK_IS_ON() + uint32_t sink_id_; +#endif // DCHECK_IS_ON() }; namespace { @@ -405,9 +472,10 @@ RegisterTracedValueProtoWriter(true); - TraceLog::GetInstance()->SetAddTraceEventOverride( + TraceLog::GetInstance()->SetAddTraceEventOverrides( &TraceEventDataSource::OnAddTraceEvent, - &TraceEventDataSource::FlushCurrentThread); + &TraceEventDataSource::FlushCurrentThread, + &TraceEventDataSource::OnUpdateDuration); TraceLog::GetInstance()->SetEnabled( TraceConfig(data_source_config.trace_config), TraceLog::RECORDING_MODE); @@ -425,7 +493,8 @@ } RegisterTracedValueProtoWriter(false); - TraceLog::GetInstance()->SetAddTraceEventOverride(nullptr, nullptr); + TraceLog::GetInstance()->SetAddTraceEventOverrides(nullptr, nullptr, + nullptr); if (data_source->stop_complete_callback_) { std::move(data_source->stop_complete_callback_).Run(); @@ -455,7 +524,7 @@ // unreturned chunks so technically this can go away at some point, but // seems needed for now. FlushCurrentThread(); - + // Flush the remaining threads via TraceLog. We call CancelTracing because // we don't want/need TraceLog to do any of its own JSON serialization. TraceLog::GetInstance()->CancelTracing(base::BindRepeating( @@ -494,8 +563,10 @@ } // static -void TraceEventDataSource::OnAddTraceEvent(TraceEvent* trace_event, - bool thread_will_flush) { +void TraceEventDataSource::OnAddTraceEvent( + TraceEvent* trace_event, + bool thread_will_flush, + base::trace_event::TraceEventHandle* handle) { auto* thread_local_event_sink = static_cast<ThreadLocalEventSink*>(ThreadLocalEventSinkSlot()->Get()); @@ -506,7 +577,19 @@ } if (thread_local_event_sink) { - thread_local_event_sink->AddTraceEvent(trace_event); + thread_local_event_sink->AddTraceEvent(trace_event, handle); + } +} + +// static +void TraceEventDataSource::OnUpdateDuration( + base::trace_event::TraceEventHandle handle, + const base::TimeTicks& now, + const base::ThreadTicks& thread_now) { + auto* thread_local_event_sink = + static_cast<ThreadLocalEventSink*>(ThreadLocalEventSinkSlot()->Get()); + if (thread_local_event_sink) { + thread_local_event_sink->UpdateDuration(handle, now, thread_now); } } @@ -516,6 +599,9 @@ static_cast<ThreadLocalEventSink*>(ThreadLocalEventSinkSlot()->Get()); if (thread_local_event_sink) { thread_local_event_sink->Flush(); + // TODO(oysteine): To support flushing while still recording, this needs to + // be changed to not destruct the TLS object as that will emit any + // uncompleted _COMPLETE events on the stack. delete thread_local_event_sink; ThreadLocalEventSinkSlot()->Set(nullptr); }
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source.h b/services/tracing/public/cpp/perfetto/trace_event_data_source.h index 955ed206..ce00e28 100644 --- a/services/tracing/public/cpp/perfetto/trace_event_data_source.h +++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.h
@@ -85,7 +85,11 @@ // Callback from TraceLog, can be called from any thread. static void OnAddTraceEvent(base::trace_event::TraceEvent* trace_event, - bool thread_will_flush); + bool thread_will_flush, + base::trace_event::TraceEventHandle* handle); + static void OnUpdateDuration(base::trace_event::TraceEventHandle handle, + const base::TimeTicks& now, + const base::ThreadTicks& thread_now); base::Lock lock_; uint32_t target_buffer_ = 0;
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc index bea01e4f..09d5839 100644 --- a/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc +++ b/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
@@ -548,7 +548,7 @@ EXPECT_EQ(kArgValue2, trace_args[1].json_value()); } -TEST_F(TraceEventDataSourceTest, CompleteTraceEventsIntoSeparateBeginAndEnd) { +TEST_F(TraceEventDataSourceTest, UpdateDurationOfCompleteEvent) { static const char kEventName[] = "bar"; CreateTraceEventDataSource(); @@ -569,23 +569,31 @@ base::trace_event::TraceLog::GetInstance()->UpdateTraceEventDurationExplicit( category_group_enabled, kEventName, handle, - base::TimeTicks() + base::TimeDelta::FromMicroseconds(20), + base::TimeTicks() + base::TimeDelta::FromMicroseconds(30), base::ThreadTicks() + base::TimeDelta::FromMicroseconds(50)); - // TRACE_EVENT_PHASE_COMPLETE events should internally emit a - // TRACE_EVENT_PHASE_BEGIN event first, and then a TRACE_EVENT_PHASE_END event - // when the duration is attempted set on the first event. + // The call to UpdateTraceEventDurationExplicit should have successfully + // updated the duration of the event which was added in the + // AddTraceEventWithThreadIdAndTimestamp call. auto events = producer_client()->GetChromeTraceEvents(0); - EXPECT_EQ(events.size(), 2); + EXPECT_EQ(events.size(), 1); - auto begin_trace_event = events[0]; - EXPECT_EQ(TRACE_EVENT_PHASE_BEGIN, begin_trace_event.phase()); - EXPECT_EQ(10, begin_trace_event.timestamp()); + auto trace_event = events[0]; + EXPECT_EQ(TRACE_EVENT_PHASE_COMPLETE, trace_event.phase()); + EXPECT_EQ(10, trace_event.timestamp()); + EXPECT_EQ(20, trace_event.duration()); - auto end_trace_event = events[1]; - EXPECT_EQ(TRACE_EVENT_PHASE_END, end_trace_event.phase()); - EXPECT_EQ(20, end_trace_event.timestamp()); - EXPECT_EQ(50, end_trace_event.thread_timestamp()); + // Updating the duration of an invalid event should cause no further events to + // be emitted. + handle.event_index = 0; + + base::trace_event::TraceLog::GetInstance()->UpdateTraceEventDurationExplicit( + category_group_enabled, kEventName, handle, + base::TimeTicks() + base::TimeDelta::FromMicroseconds(30), + base::ThreadTicks() + base::TimeDelta::FromMicroseconds(50)); + + auto new_events = producer_client()->GetChromeTraceEvents(0); + EXPECT_EQ(new_events.size(), 1); } } // namespace
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index 2787161..11b8dd3 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -179,6 +179,4 @@ #define SK_ATTR_DEPRECATED SK_NOTHING_ARG1 #define GR_GL_CUSTOM_SETUP_HEADER "GrGLConfig_chrome.h" -#define SK_USE_LEGACY_CONIC_CURVATURE_SLOP // temporary for crbug.com/843966 - #endif
diff --git a/skia/ext/benchmarking_canvas.cc b/skia/ext/benchmarking_canvas.cc index f50b6fc..e6f0cc0e 100644 --- a/skia/ext/benchmarking_canvas.cc +++ b/skia/ext/benchmarking_canvas.cc
@@ -654,41 +654,6 @@ INHERITED::onDrawBitmapNine(bitmap, center, dst, op.paint()); } -void BenchmarkingCanvas::onDrawText(const void* text, size_t byteLength, - SkScalar x, SkScalar y, - const SkPaint& paint) { - AutoOp op(this, "DrawText", &paint); - op.addParam("count", AsValue(SkIntToScalar(paint.countText(text, byteLength)))); - op.addParam("x", AsValue(x)); - op.addParam("y", AsValue(y)); - - INHERITED::onDrawText(text, byteLength, x, y, *op.paint()); -} - -void BenchmarkingCanvas::onDrawPosText(const void* text, size_t byteLength, - const SkPoint pos[], const SkPaint& paint) { - AutoOp op(this, "DrawPosText", &paint); - - int count = paint.countText(text, byteLength); - op.addParam("count", AsValue(SkIntToScalar(count))); - op.addParam("pos", AsListValue(pos, count)); - - INHERITED::onDrawPosText(text, byteLength, pos, *op.paint()); -} - -void BenchmarkingCanvas::onDrawPosTextH(const void* text, size_t byteLength, - const SkScalar xpos[], SkScalar constY, - const SkPaint& paint) { - AutoOp op(this, "DrawPosTextH", &paint); - op.addParam("constY", AsValue(constY)); - - int count = paint.countText(text, byteLength); - op.addParam("count", AsValue(SkIntToScalar(count))); - op.addParam("pos", AsListValue(xpos, count)); - - INHERITED::onDrawPosTextH(text, byteLength, xpos, constY, *op.paint()); -} - void BenchmarkingCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) { DCHECK(blob);
diff --git a/skia/ext/benchmarking_canvas.h b/skia/ext/benchmarking_canvas.h index f9858929..67bfa93 100644 --- a/skia/ext/benchmarking_canvas.h +++ b/skia/ext/benchmarking_canvas.h
@@ -60,12 +60,6 @@ void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst, const SkPaint*) override; - void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, - const SkPaint&) override; - void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[], - const SkPaint&) override; - void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], - SkScalar constY, const SkPaint&) override; void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) override;
diff --git a/sql/database.cc b/sql/database.cc index 96689675..adf3b2c 100644 --- a/sql/database.cc +++ b/sql/database.cc
@@ -1490,23 +1490,15 @@ bool Database::DoesColumnExist(const char* table_name, const char* column_name) const { - std::string sql("PRAGMA TABLE_INFO("); - sql.append(table_name); - sql.append(")"); - - Statement statement(GetUntrackedStatement(sql.c_str())); - - // This can happen if the database is corrupt and the error is a test - // expectation. - if (!statement.is_valid()) - return false; - - while (statement.Step()) { - if (base::EqualsCaseInsensitiveASCII(statement.ColumnString(1), - column_name)) - return true; - } - return false; + // sqlite3_table_column_metadata uses out-params to return column definition + // details, such as the column type and whether it allows NULL values. These + // aren't needed to compute the current method's result, so we pass in nullptr + // for all the out-params. + int error = sqlite3_table_column_metadata( + db_, "main", table_name, column_name, /* pzDataType= */ nullptr, + /* pzCollSeq= */ nullptr, /* pNotNull= */ nullptr, + /* pPrimaryKey= */ nullptr, /* pAutoinc= */ nullptr); + return error == SQLITE_OK; } int64_t Database::GetLastInsertRowId() const {
diff --git a/sql/database.h b/sql/database.h index fecead7..e4f38ab 100644 --- a/sql/database.h +++ b/sql/database.h
@@ -420,6 +420,12 @@ bool DoesViewExist(const char* table_name) const; // Returns true if a column with the given name exists in the given table. + // + // Calling this method on a VIEW returns an unspecified result. + // + // This should only be used by migration code for legacy features that do not + // use MetaTable, and need an alternative way of figuring out the database's + // current version. bool DoesColumnExist(const char* table_name, const char* column_name) const; // Returns sqlite's internal ID for the last inserted row. Valid only
diff --git a/storage/browser/blob/blob_data_handle.cc b/storage/browser/blob/blob_data_handle.cc index ab13572..36d19d37 100644 --- a/storage/browser/blob/blob_data_handle.cc +++ b/storage/browser/blob/blob_data_handle.cc
@@ -70,10 +70,7 @@ BlobDataHandle::~BlobDataHandle() { if (!io_task_runner_->RunsTasksInCurrentSequence()) { - BlobDataHandleShared* raw = shared_.get(); - raw->AddRef(); - shared_ = nullptr; - io_task_runner_->ReleaseSoon(FROM_HERE, raw); + io_task_runner_->ReleaseSoon(FROM_HERE, std::move(shared_)); } }
diff --git a/storage/browser/database/database_quota_client.cc b/storage/browser/database/database_quota_client.cc index 84bb06c..1fe1a66f 100644 --- a/storage/browser/database/database_quota_client.cc +++ b/storage/browser/database/database_quota_client.cc
@@ -94,11 +94,7 @@ DatabaseQuotaClient::~DatabaseQuotaClient() { if (!db_tracker_->task_runner()->RunsTasksInCurrentSequence()) { - DatabaseTracker* tracker = db_tracker_.get(); - tracker->AddRef(); - db_tracker_ = nullptr; - if (!tracker->task_runner()->ReleaseSoon(FROM_HERE, tracker)) - tracker->Release(); + db_tracker_->task_runner()->ReleaseSoon(FROM_HERE, std::move(db_tracker_)); } }
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index aad5c59..2726f68 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -1376,6 +1376,55 @@ }, { "args": [ + "--enable-features=NetworkService", + "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_chrome_public_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_chrome_public_test_apk", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "NRD91N", + "device_type": "bullhead", + "os": "Android" + } + ], + "expiration": 10800, + "hard_timeout": 960, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 20 + }, + "test": "chrome_public_test_apk" + }, + { + "args": [ "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json", "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk", "--gs-results-bucket=chromium-result-details", @@ -1655,6 +1704,54 @@ }, { "args": [ + "--enable-features=NetworkService", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_content_shell_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_content_shell_test_apk", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "NRD91N", + "device_type": "bullhead", + "os": "Android" + } + ], + "expiration": 10800, + "hard_timeout": 960, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 5 + }, + "test": "content_shell_test_apk" + }, + { + "args": [ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], @@ -3241,6 +3338,51 @@ "--bucket", "chromium-result-details", "--test-name", + "vr_android_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "NRD91N", + "device_type": "bullhead", + "os": "Android" + } + ], + "expiration": 10800, + "hard_timeout": 960, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "vr_android_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "vr_common_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" @@ -3791,6 +3933,35 @@ }, { "args": [ + "--enable-features=NetworkService", + "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_chrome_public_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_chrome_public_test_apk", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_type": "coho", + "os": "Android" + } + ], + "shards": 20 + }, + "test": "chrome_public_test_apk" + }, + { + "args": [ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], @@ -3922,6 +4093,34 @@ }, { "args": [ + "--enable-features=NetworkService", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_content_shell_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_content_shell_test_apk", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_type": "coho", + "os": "Android" + } + ], + "shards": 5 + }, + "test": "content_shell_test_apk" + }, + { + "args": [ "--gs-results-bucket=chromium-result-details", "--recover-devices" ],
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index 92e20cf..2797721 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -2990,6 +2990,49 @@ "--bucket", "chromium-result-details", "--test-name", + "vr_android_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "vr_android_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "vr_common_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" @@ -3160,6 +3203,7 @@ "--num-retries=3", "--debug", "--android", + "--disable-breakpad", "--additional-driver-flag=--use-gpu-in-tests" ], "isolate_name": "webkit_layout_tests_exparchive", @@ -5599,6 +5643,50 @@ "--bucket", "chromium-result-details", "--test-name", + "vr_android_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84Z", + "device_type": "flo", + "os": "Android" + } + ], + "expiration": 10800, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "vr_android_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "vr_common_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" @@ -6404,6 +6492,55 @@ }, { "args": [ + "--enable-features=NetworkService", + "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_chrome_public_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_chrome_public_test_apk", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "LMY48I", + "device_type": "hammerhead", + "os": "Android" + } + ], + "expiration": 10800, + "hard_timeout": 960, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 20 + }, + "test": "chrome_public_test_apk" + }, + { + "args": [ "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json", "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk", "--gs-results-bucket=chromium-result-details", @@ -6683,6 +6820,54 @@ }, { "args": [ + "--enable-features=NetworkService", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_content_shell_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_content_shell_test_apk", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "LMY48I", + "device_type": "hammerhead", + "os": "Android" + } + ], + "expiration": 10800, + "hard_timeout": 960, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 5 + }, + "test": "content_shell_test_apk" + }, + { + "args": [ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], @@ -8269,6 +8454,51 @@ "--bucket", "chromium-result-details", "--test-name", + "vr_android_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "LMY48I", + "device_type": "hammerhead", + "os": "Android" + } + ], + "expiration": 10800, + "hard_timeout": 960, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "vr_android_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "vr_common_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" @@ -10941,6 +11171,51 @@ "--bucket", "chromium-result-details", "--test-name", + "vr_android_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "LMY49B", + "device_type": "flo", + "os": "Android" + } + ], + "expiration": 10800, + "hard_timeout": 120, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "vr_android_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "vr_common_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" @@ -11769,6 +12044,54 @@ }, { "args": [ + "--enable-features=NetworkService", + "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "experiment_percentage": 100, + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_chrome_public_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_chrome_public_test_apk", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 20 + }, + "test": "chrome_public_test_apk" + }, + { + "args": [ "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json", "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk", "--gs-results-bucket=chromium-result-details", @@ -12036,6 +12359,52 @@ }, { "args": [ + "--enable-features=NetworkService", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_content_shell_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_content_shell_test_apk", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 5 + }, + "test": "content_shell_test_apk" + }, + { + "args": [ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], @@ -13552,6 +13921,49 @@ "--bucket", "chromium-result-details", "--test-name", + "vr_android_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "vr_android_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "vr_common_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" @@ -16161,6 +16573,50 @@ "--bucket", "chromium-result-details", "--test-name", + "vr_android_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MRA58Z", + "device_type": "flo", + "os": "Android" + } + ], + "expiration": 10800, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "vr_android_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "vr_common_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" @@ -16501,7 +16957,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], - "experiment_percentage": 100, + "experiment_percentage": 0, "merge": { "args": [ "--bucket", @@ -16778,7 +17234,7 @@ "--gs-results-bucket=chromium-result-details", "--recover-devices" ], - "experiment_percentage": 100, + "experiment_percentage": 0, "merge": { "args": [ "--bucket", @@ -20307,6 +20763,49 @@ "--bucket", "chromium-result-details", "--test-name", + "vr_android_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "vr_android_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "vr_common_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" @@ -22942,6 +23441,49 @@ "--bucket", "chromium-result-details", "--test-name", + "vr_android_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "vr_android_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "vr_common_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 178b146..fee0454 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -92,23 +92,6 @@ "test": "chrome_all_tast_tests" }, { - "args": [ - "--dbus-stub", - "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.chromeos_unittests.filter" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "kvm": "1", - "os": "Ubuntu-14.04", - "pool": "Chrome-CrOS-VM" - } - ] - }, - "test": "chromeos_unittests" - }, - { "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json index 211095d..a635461 100644 --- a/testing/buildbot/chromium.clang.json +++ b/testing/buildbot/chromium.clang.json
@@ -6470,6 +6470,49 @@ "--bucket", "chromium-result-details", "--test-name", + "vr_android_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "vr_android_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "vr_common_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" @@ -9079,6 +9122,49 @@ "--bucket", "chromium-result-details", "--test-name", + "vr_android_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "vr_android_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "vr_common_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 976ae30b..12eefd8 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -1361,6 +1361,54 @@ }, { "args": [ + "--enable-features=NetworkService,NetworkServiceInProcess", + "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_in_process_chrome_public_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_in_process_chrome_public_test_apk", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "hard_timeout": 3600, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 20 + }, + "test": "chrome_public_test_apk" + }, + { + "args": [ "--enable-features=NetworkService", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -1407,6 +1455,52 @@ }, { "args": [ + "--enable-features=NetworkService,NetworkServiceInProcess", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_in_process_components_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_in_process_components_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "hard_timeout": 3600, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "components_browsertests" + }, + { + "args": [ "--enable-features=NetworkService", "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter", "--gs-results-bucket=chromium-result-details", @@ -1455,6 +1549,54 @@ }, { "args": [ + "--enable-features=NetworkService,NetworkServiceInProcess", + "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_in_process_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_in_process_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "hard_timeout": 3600, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 5 + }, + "test": "content_browsertests" + }, + { + "args": [ "--disable-features=VizDisplayCompositor", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -1597,6 +1739,53 @@ { "args": [ "--enable-features=NetworkService,NetworkServiceInProcess", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_in_process_content_shell_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_in_process_content_shell_test_apk", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "hard_timeout": 3600, + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 5 + }, + "test": "content_shell_test_apk" + }, + { + "args": [ + "--enable-features=NetworkService,NetworkServiceInProcess", "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -1837,6 +2026,19 @@ }, { "args": [ + "--enable-features=NetworkService,NetworkServiceInProcess", + "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_browser_tests.filter" + ], + "name": "network_service_in_process_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "priority_adjustment": 30, + "shards": 15 + }, + "test": "browser_tests" + }, + { + "args": [ "--enable-features=NetworkService" ], "name": "network_service_components_browsertests", @@ -1861,6 +2063,19 @@ }, { "args": [ + "--enable-features=NetworkService,NetworkServiceInProcess", + "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter" + ], + "name": "network_service_in_process_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "priority_adjustment": 30, + "shards": 2 + }, + "test": "content_browsertests" + }, + { + "args": [ "--enable-features=NetworkService" ], "name": "network_service_extensions_browsertests", @@ -1925,6 +2140,18 @@ }, { "args": [ + "--enable-features=NetworkService,NetworkServiceInProcess", + "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_browser_tests.filter" + ], + "name": "network_service_in_process_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 15 + }, + "test": "browser_tests" + }, + { + "args": [ "--disable-features=VizDisplayCompositor" ], "name": "non_viz_browser_tests", @@ -1958,6 +2185,18 @@ }, { "args": [ + "--enable-features=NetworkService,NetworkServiceInProcess", + "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter" + ], + "name": "network_service_in_process_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "shards": 2 + }, + "test": "content_browsertests" + }, + { + "args": [ "--disable-features=VizDisplayCompositor" ], "name": "non_viz_content_browsertests", @@ -2054,25 +2293,6 @@ "args": [ "--site-per-process" ], - "name": "site_per_process_browser_tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "device_os": "MMB29Q", - "device_type": "bullhead", - "os": "Android" - } - ], - "hard_timeout": 960, - "shards": 10 - }, - "test": "browser_tests" - }, - { - "args": [ - "--site-per-process" - ], "name": "site_per_process_components_browsertests", "swarming": { "can_use_on_swarming_builders": true, @@ -2108,7 +2328,8 @@ }, { "args": [ - "--site-per-process" + "--site-per-process", + "--test-launcher-filter-file=../../testing/buildbot/filters/site_isolation_android.content_browsertests.filter" ], "name": "site_per_process_content_browsertests", "swarming": { @@ -2177,6 +2398,36 @@ } ] }, + "WebKit Linux composite_after_paint Dummy Builder": { + "isolated_scripts": [ + { + "args": [ + "--num-retries=3", + "--additional-driver-flag=--enable-blink-features=CompositeAfterPaint" + ], + "isolate_name": "webkit_layout_tests_exparchive", + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "webkit_layout_tests", + "results_handler": "layout tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-14.04" + } + ], + "hard_timeout": 900, + "priority_adjustment": 30, + "shards": 12 + } + } + ] + }, "WebKit Linux layout_ng Dummy Builder": { "gtest_tests": [ { @@ -2253,36 +2504,6 @@ } ] }, - "WebKit Linux slimming_paint_v2 Dummy Builder": { - "isolated_scripts": [ - { - "args": [ - "--num-retries=3", - "--additional-driver-flag=--enable-blink-features=CompositeAfterPaint" - ], - "isolate_name": "webkit_layout_tests_exparchive", - "merge": { - "args": [ - "--verbose" - ], - "script": "//third_party/blink/tools/merge_web_test_results.py" - }, - "name": "webkit_layout_tests", - "results_handler": "layout tests", - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Ubuntu-14.04" - } - ], - "hard_timeout": 900, - "priority_adjustment": 30, - "shards": 12 - } - } - ] - }, "Win 10 Fast Ring": { "gtest_tests": [ { @@ -3097,6 +3318,53 @@ }, { "args": [ + "--enable-features=NetworkService,NetworkServiceInProcess", + "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_in_process_chrome_public_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_in_process_chrome_public_test_apk", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 20 + }, + "test": "chrome_public_test_apk" + }, + { + "args": [ "--enable-features=NetworkService", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -3142,6 +3410,51 @@ }, { "args": [ + "--enable-features=NetworkService,NetworkServiceInProcess", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_in_process_components_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_in_process_components_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "components_browsertests" + }, + { + "args": [ "--enable-features=NetworkService", "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter", "--gs-results-bucket=chromium-result-details", @@ -3189,6 +3502,53 @@ }, { "args": [ + "--enable-features=NetworkService,NetworkServiceInProcess", + "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_in_process_content_browsertests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_in_process_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 5 + }, + "test": "content_browsertests" + }, + { + "args": [ "--disable-features=VizDisplayCompositor", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -3328,6 +3688,52 @@ { "args": [ "--enable-features=NetworkService,NetworkServiceInProcess", + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "network_service_in_process_content_shell_test_apk" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "network_service_in_process_content_shell_test_apk", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "shards": 5 + }, + "test": "content_shell_test_apk" + }, + { + "args": [ + "--enable-features=NetworkService,NetworkServiceInProcess", "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -3415,25 +3821,6 @@ "test": "chrome_login_tast_tests" }, { - "args": [ - "--dbus-stub", - "--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.chromeos_unittests.filter" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "kvm": "1", - "os": "Ubuntu-14.04", - "pool": "Chrome-CrOS-VM" - } - ], - "hard_timeout": 3600, - "io_timeout": 3600 - }, - "test": "chromeos_unittests" - }, - { "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -3918,8 +4305,7 @@ }, { "args": [ - "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.net_unittests.filter", - "--test-launcher-batch-limit=200" + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.net_unittests.filter" ], "swarming": { "can_use_on_swarming_builders": true, @@ -4010,6 +4396,24 @@ } ] }, + "linux-autofill-captured-sites-rel": { + "gtest_tests": [ + { + "args": [ + "--gtest_filter=\"AutofillCapturedSitesInteractiveTest.Recipe/*\"", + "--enable-pixel-output-in-tests", + "--ui-test-action-max-timeout=1000000", + "--test-launcher-timeout=1000000", + "--vmodule=captured_sites_test_utils=1,autofill_captured_sites_interactive_uitest=1" + ], + "name": "autofill_captured_sites_interactive_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "captured_sites_interactive_tests" + } + ] + }, "linux-blink-animation-use-time-delta": { "additional_compile_targets": [ "all" @@ -7483,6 +7887,29 @@ } ] }, + "mac-autofill-captured-sites-rel": { + "gtest_tests": [ + { + "args": [ + "--gtest_filter=\"AutofillCapturedSitesInteractiveTest.Recipe/*\"", + "--enable-pixel-output-in-tests", + "--ui-test-action-max-timeout=1000000", + "--test-launcher-timeout=1000000", + "--vmodule=captured_sites_test_utils=1,autofill_captured_sites_interactive_uitest=1" + ], + "name": "autofill_captured_sites_interactive_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "captured_sites_interactive_tests" + } + ] + }, + "mac-hermetic-upgrade-rel": { + "additional_compile_targets": [ + "all" + ] + }, "mac-mojo-rel": { "gtest_tests": [ { @@ -9875,6 +10302,24 @@ } ] }, + "win-autofill-captured-sites-rel": { + "gtest_tests": [ + { + "args": [ + "--gtest_filter=\"AutofillCapturedSitesInteractiveTest.Recipe/*\"", + "--enable-pixel-output-in-tests", + "--ui-test-action-max-timeout=1000000", + "--test-launcher-timeout=1000000", + "--vmodule=captured_sites_test_utils=1,autofill_captured_sites_interactive_uitest=1" + ], + "name": "autofill_captured_sites_interactive_tests", + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "captured_sites_interactive_tests" + } + ] + }, "win10-blink-rel-dummy": { "isolated_scripts": [ {
diff --git a/testing/buildbot/chromium.goma.json b/testing/buildbot/chromium.goma.json index 3c23463..7fddcb85 100644 --- a/testing/buildbot/chromium.goma.json +++ b/testing/buildbot/chromium.goma.json
@@ -134,9 +134,47 @@ } ] }, + "Chromium Mac Goma RBE Staging": { + "additional_compile_targets": [ + "chrome" + ], + "gtest_tests": [ + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_unittests" + } + ] + }, "Chromium Mac Goma RBE Staging (clobber)": { "additional_compile_targets": [ - "all" + "chrome" + ], + "gtest_tests": [ + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "base_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "content_unittests" + } + ] + }, + "Chromium Mac Goma RBE Staging (dbg)": { + "additional_compile_targets": [ + "chrome" ], "gtest_tests": [ {
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index 67d8d299..67f7926 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -730,6 +730,20 @@ }, { "args": [ + "--qemu-require-kvm" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "kvm": "1" + } + ] + }, + "test": "http_service_tests" + }, + { + "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.ipc_tests.filter", "--qemu-require-kvm" ],
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index 8407e11..a6f190f9 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -2392,6 +2392,49 @@ "--bucket", "chromium-result-details", "--test-name", + "vr_android_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "MMB29Q", + "device_type": "bullhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "vr_android_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", "vr_common_unittests" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json index 320799b8..ceceb0f3 100644 --- a/testing/buildbot/chromium.perf.fyi.json +++ b/testing/buildbot/chromium.perf.fyi.json
@@ -270,37 +270,6 @@ "isolated_scripts": [ { "args": [ - "--benchmarks=blink_perf.layout_ng,blink_perf.paint_layout_ng,loading.desktop_layout_ng", - "-v", - "--upload-results", - "--output-format=histograms", - "--browser=release" - ], - "isolate_name": "performance_test_suite", - "merge": { - "script": "//tools/perf/process_perf_results.py" - }, - "name": "blink_perf.layout_ng", - "override_compile_targets": [ - "performance_test_suite" - ], - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "id": "build186-b7", - "pool": "chrome.tests.perf-fyi" - } - ], - "expiration": 36000, - "hard_timeout": 14400, - "ignore_task_failure": false, - "io_timeout": 3600 - } - }, - { - "args": [ "--benchmarks=loading.desktop.network_service", "-v", "--upload-results", @@ -319,9 +288,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "gpu": "10de:1cb3", - "id": "build186-b7", - "pool": "chrome.tests.perf-fyi" + "id": "build186-b7" } ], "expiration": 36000,
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn index b603e62..fe6c59e 100644 --- a/testing/buildbot/filters/BUILD.gn +++ b/testing/buildbot/filters/BUILD.gn
@@ -40,7 +40,6 @@ source_set("chromeos_filters") { data = [ - "//testing/buildbot/filters/chromeos.chromeos_unittests.filter", "//testing/buildbot/filters/chromeos.media_unittests.filter", "//testing/buildbot/filters/chromeos.services_unittests.filter", ]
diff --git a/testing/buildbot/filters/chromeos.chromeos_unittests.filter b/testing/buildbot/filters/chromeos.chromeos_unittests.filter deleted file mode 100644 index 956c0d3b1..0000000 --- a/testing/buildbot/filters/chromeos.chromeos_unittests.filter +++ /dev/null
@@ -1,2 +0,0 @@ -# TODO(crbug.com/865693): Fix this. --NetworkConnectionHandlerImplTest.ConnectWithCertificateSuccess
diff --git a/testing/buildbot/filters/chromeos.mash.fyi.browser_tests.filter b/testing/buildbot/filters/chromeos.mash.fyi.browser_tests.filter index e84c41c..ca91556 100644 --- a/testing/buildbot/filters/chromeos.mash.fyi.browser_tests.filter +++ b/testing/buildbot/filters/chromeos.mash.fyi.browser_tests.filter
@@ -228,21 +228,37 @@ # ash::Shell access in test. -TrayAccessibilityTestInstance/TrayAccessibilityTest.* -# Virtual keyboard not supported. --AccessibilityManagerLoginTest.ResumeSavedPref --DefaultKeyboardExtensionBrowserTest.* --KeyboardControllerAppWindowTest.* --KeyboardControllerStateTest.* --KeyboardControllerWebContentTest.* +# Changing the Chrome keyboard window size does not change the Ash keyboard +# window size. These tests may require a test mojo interface for Mash. +# https://crbug.com/843332. +-KeyboardControllerAppWindowTest.DisableOverscrollForImeWindow +-KeyboardEndToEndOverscrollTest.ToggleKeyboardOnMaximizedWindowAffectsViewport + +# Keyboard window does not move browser windows. https://crbug.com/906888. +-KeyboardEndToEndOverscrollTest.ToggleKeyboardOnShortOverlappingWindowMovesWindowUpwards +-KeyboardEndToEndOverscrollTest.ToggleKeyboardOnTallOverlappingWindowMovesWindowUpwardsAndAffectsViewport + +# Mouse move events are not handled correctly in tests. +# TODO(stevenjb): Determine why this works in practice but fails in the test. +-KeyboardControllerWebContentTest.CanDragFloatingKeyboardWithMouse + +# RemoteTextInputClient is not forwarding focus requests to show/hide the +# virtual keyboard: https://crbug.com/631527 +-KeyboardEndToEndFormTest.ChangeInputModeToNoneHidesKeyboard +-KeyboardEndToEndFocusTest.TriggerAsyncInputFocusFromUserGestureAfterBlurShowsKeyboard + +# These tests succeed in SingleProcessMash but time out in Mash. They rely on +# focusing an input element to show the virtual keyboard. +# https://crbug.com/912233 -KeyboardEndToEndFocusTest.* -KeyboardEndToEndFormTest.* -KeyboardEndToEndOverscrollTest.* --KioskVirtualKeyboardTest.* --PolicyTest.VirtualKeyboardEnabled - -# Also depends on keyboard. Test crashes in Mash. https://crbug.com/897012 -SelectFileDialogExtensionBrowserTest.SelectFileVirtualKeyboard_TabletMode +# Chrome keyboard window -> root -> host -> input method is null in Mash. +# https://crbug.com/756059 +-KeyboardControllerWebContentTest.EnableIMEInDifferentExtension + # Uses ash::LockWindow. https://crbug.com/899862 -ShutdownPolicyLockerTest.*
diff --git a/testing/buildbot/filters/chromeos.single_process_mash.browser_tests.filter b/testing/buildbot/filters/chromeos.single_process_mash.browser_tests.filter index c5a9027c..aa97d4a 100644 --- a/testing/buildbot/filters/chromeos.single_process_mash.browser_tests.filter +++ b/testing/buildbot/filters/chromeos.single_process_mash.browser_tests.filter
@@ -23,10 +23,6 @@ # Crash in media::AudioOutputController::Create() -KioskVirtualKeyboardTest.RestrictFeatures -# Crash in Window::AddChild(), https://crbug.com/899862 --ShutdownPolicyLockerTest.PolicyChange --ShutdownPolicyLockerTest.TestBasic - # AutomationManagerAura::Enable() uses ash to get active window. More generally, # chrome a11y code directly accesses ash system UI widgets and views. # https://crbug.com/888145
diff --git a/testing/buildbot/filters/chromeos.single_process_mash.fyi.unit_tests.filter b/testing/buildbot/filters/chromeos.single_process_mash.fyi.unit_tests.filter index 43629bf..3ce6a427 100644 --- a/testing/buildbot/filters/chromeos.single_process_mash.fyi.unit_tests.filter +++ b/testing/buildbot/filters/chromeos.single_process_mash.fyi.unit_tests.filter
@@ -1,6 +1,7 @@ # Multi profile: https://crbug.com/910241 -MultiUserWindowManagerChromeOSTest.* -MultiUserWindowManagerChromeOSMashTest.* +-MultiUserWindowManagerClientImpl* -MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest.* -MultiUserContextMenuChromeOSTest.* -BrowserFinderChromeOSTest.FindBrowserOwnedByAnotherProfile @@ -12,6 +13,12 @@ -ImmersiveModeControllerAshTest.RegularToLockedFullscreenDisablesImmersive -ImmersiveModeControllerAshTest.TabAndBrowserFullscreen +# https://crbug.com/912700 +-ChromeKeyboardUITest.ChromeKeyboardContentsDelegate + +# https://crbug.com/910240 +-ArcInputMethodManagerServiceTest.DisableFallbackVirtualKeyboard + # Fails because a MusClient is needed. Blocked on folding views_mus_test_suite # into views_test_suite. -OmniboxViewViewsSteadyStateElisionsTest.GestureTaps
diff --git a/testing/buildbot/filters/fuchsia.net_unittests.filter b/testing/buildbot/filters/fuchsia.net_unittests.filter index 39f7027..293b51f7 100644 --- a/testing/buildbot/filters/fuchsia.net_unittests.filter +++ b/testing/buildbot/filters/fuchsia.net_unittests.filter
@@ -27,6 +27,17 @@ # Flaky, https://crbug.com/814811. -URLRequestTest.NetworkDelegateProxyError +# Flaky hangs, https://crbug.com/913037. +-URLRequestTestHTTP.Redirect301Tests +-URLRequestTestHTTP.Redirect302Tests + +# Flaky hangs, https://crbug.com/913155. +-NetworkErrorLoggingEndToEndTest.ReportNetworkError +-NetworkErrorLoggingEndToEndTest.UploadAtShutdown + +# Flaky test server spawning, https://crbug.com/913156. +-SSLClientSocketReadTest.* + # SocketPosix::IsConnected has a different behavior on Fuchsia. # https://crbug.com/887587. -TCPSocketTest.BeforeConnectCallback
diff --git a/testing/buildbot/filters/site_isolation_android.content_browsertests.filter b/testing/buildbot/filters/site_isolation_android.content_browsertests.filter new file mode 100644 index 0000000..c5f11ac --- /dev/null +++ b/testing/buildbot/filters/site_isolation_android.content_browsertests.filter
@@ -0,0 +1,7 @@ +# https://crbug.com/906247 +-RenderFrameHostManagerTest.ForegroundNavigationIsNeverBackgroundedWithSpareProcess + +# https://crbug.com/906256 +-BlockedSchemeNavigationBrowserTest.PDF_NavigationFromFrame_TopFrameHasBlockedScheme_Block/1 +-BlockedSchemeNavigationBrowserTest.PDF_NavigationFromFrame_Block/1 +
diff --git a/testing/buildbot/filters/webui_polymer2_browser_tests.filter b/testing/buildbot/filters/webui_polymer2_browser_tests.filter index 3a4f5fe..79950d3 100644 --- a/testing/buildbot/filters/webui_polymer2_browser_tests.filter +++ b/testing/buildbot/filters/webui_polymer2_browser_tests.filter
@@ -279,7 +279,6 @@ SettingsA11ySignOut.* SettingsAccessibilityTest.* SettingsAdvancedPageBrowserTest.* -SettingsAnimationBrowserTest.* SettingsAutofillSectionBrowserTest.* SettingsBasicPageBrowserTest.* SettingsEasyUnlockBrowserTest.*
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py index d6c0f30..b7cb9bf 100755 --- a/testing/buildbot/generate_buildbot_json.py +++ b/testing/buildbot/generate_buildbot_json.py
@@ -859,7 +859,8 @@ for c in milo_configs: for l in self.read_file(c).splitlines(): if (not 'name: "buildbucket/luci.chromium.' in l and - not 'name: "buildbot/chromium.' in l): + not 'name: "buildbot/chromium.' in l and + not 'name: "buildbot/tryserver.chromium.' in l): continue # l looks like # `name: "buildbucket/luci.chromium.try/win_chromium_dbg_ng"` @@ -900,9 +901,9 @@ 'win7-blink-rel-dummy', 'win10-blink-rel-dummy', 'Dummy WebKit Mac10.13', + 'WebKit Linux composite_after_paint Dummy Builder', 'WebKit Linux layout_ng Dummy Builder', 'WebKit Linux root_layer_scrolls Dummy Builder', - 'WebKit Linux slimming_paint_v2 Dummy Builder', # chromium, due to https://crbug.com/878915 'win-dbg', 'win32-dbg',
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index cfcc3be..3c422106 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -229,6 +229,10 @@ "label": "//media/capture:capture_unittests", "type": "windowed_test_launcher", }, + "captured_sites_interactive_tests": { + "label": "//chrome/test:captured_sites_interactive_tests", + "type": "console_test_launcher", + }, "cast_audio_backend_unittests": { "label": "//chromecast/media/cma/backend:cast_audio_backend_unittests", "type": "console_test_launcher", @@ -706,7 +710,7 @@ "label": "//ios/chrome/test/earl_grey:ios_chrome_manual_fill_egtests", "type": "raw", "args": [ - "--enable-features=AutofillManualFallback,WebFrameMessaging", + "--enable-features=AutofillManualFallback,AutofillManualFallbackPhaseTwo,WebFrameMessaging", ], }, "ios_chrome_reading_list_egtests": { @@ -1336,6 +1340,10 @@ "label": "//components/viz:viz_unittests", "type": "windowed_test_launcher", }, + 'vr_android_unittests': { + "label": "//chrome/browser/android/vr:vr_android_unittests", + "type": "console_test_launcher", + }, "vr_common_unittests": { "label": "//chrome/browser/vr:vr_common_unittests", "type": "console_test_launcher",
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index d655306..1d25fa9 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -220,6 +220,8 @@ 'mac-rel', ], }, + # Note: keep experiment percentages the same as + # network_service_chrome_public_test_apk. 'chrome_public_test_apk': { 'modifications': { # chromium.android @@ -247,7 +249,9 @@ }, }, 'Oreo Phone Tester': { - 'experiment_percentage': 100, + # TODO(https://crbug.com/884413): Re-enable this once the tests are + # either passing or there is more capacity. + 'experiment_percentage': 0, }, # chromium.swarm 'Android N5X Swarm': { @@ -604,12 +608,6 @@ 'Linux ASan LSan Tests (1)', # https://crbug.com/843732 ], }, - 'http_service_tests': { - 'remove_from': [ - # chromium.linux - 'Fuchsia x64', # https://crbug.com/896884 - ], - }, 'info_collection_tests': { 'remove_from': [ # chromium.gpu.fyi @@ -770,6 +768,37 @@ }, }, }, + # Note: keep experiment percentages the same as chrome_public_test_apk. + 'network_service_chrome_public_test_apk': { + # Only run these on the phone testers for now due to capacity. + 'remove_from': [ + # chromium.android + 'android-kitkat-arm-rel', + 'android-marshmallow-arm64-rel', + 'KitKat Tablet Tester', + 'Lollipop Tablet Tester', + 'Marshmallow Tablet Tester', + 'KitKat Phone Tester (dbg)', + # chromium.android.fyi + 'x86 Cloud Tester', + # chromium.memory + 'Android CFI', + # chromium.clang + 'ToTAndroid', + 'ToTAndroidCFI', + ], + 'modifications': { + # chromium.android + 'Marshmallow 64 bit Tester': { + # TODO(crbug.com/731759): Enable this once we're confident that it + # passes. + 'experiment_percentage': 100, + }, + 'Oreo Phone Tester': { + 'experiment_percentage': 100, + }, + }, + }, 'network_service_components_browsertests': { 'remove_from': [ # chromium.memory @@ -810,6 +839,25 @@ 'ToTMacASan', ], }, + 'network_service_content_shell_test_apk': { + # Only run these on the phone testers for now due to capacity. + 'remove_from': [ + # chromium.android + 'android-kitkat-arm-rel', + 'android-marshmallow-arm64-rel', + 'KitKat Tablet Tester', + 'Lollipop Tablet Tester', + 'Marshmallow Tablet Tester', + 'KitKat Phone Tester (dbg)', + # chromium.android.fyi + 'x86 Cloud Tester', + # chromium.memory + 'Android CFI', + # chromium.clang + 'ToTAndroid', + 'ToTAndroidCFI', + ], + }, 'network_service_extensions_browsertests': { 'remove_from': [ # chromium.memory @@ -1225,6 +1273,13 @@ 'Win10 Tests x64', ], }, + 'vr_android_unittests': { + 'remove_from': [ + # chromium.android.fyi + 'x64 Device Tester', + 'x86 Cloud Tester', + ], + }, 'vr_pixeltests': { 'remove_from': [ # chromium.fyi @@ -1298,6 +1353,10 @@ 'args': [ '--debug', '--android', + # TODO(crbug.com/912120): Breakpad was entirely disabled on + # Android. Remove this when it no longer affects Android crash + # log handling. + '--disable-breakpad', # TODO(crbug.com/875172): run on the real GPU since the # software fallback, SwiftShader, isn't yet for 32-bit ARM. '--additional-driver-flag=--use-gpu-in-tests', @@ -1370,6 +1429,11 @@ 'shards': 12, }, }, + 'WebKit Linux composite_after_paint Dummy Builder': { + 'args': [ + '--additional-driver-flag=--enable-blink-features=CompositeAfterPaint', + ], + }, 'WebKit Linux layout_ng Dummy Builder': { 'args': [ '--additional-driver-flag=--enable-blink-features=LayoutNG', @@ -1380,11 +1444,6 @@ '--additional-driver-flag=--root-layer-scrolls', ], }, - 'WebKit Linux slimming_paint_v2 Dummy Builder': { - 'args': [ - '--additional-driver-flag=--enable-blink-features=CompositeAfterPaint', - ], - }, # chromium.linux 'Linux Tests': { 'swarming': { @@ -1568,6 +1627,20 @@ 'Debug_x64', ], }, + # tryserver.chromium.android + 'android_blink_rel': { + 'args': [ + '--release', + '--android', + # TODO(crbug.com/912120): Breakpad was entirely disabled on + # Android. Remove this when it no longer affects Android crash + # log handling. + '--disable-breakpad', + # TODO(crbug.com/875172): run on the real GPU since the + # software fallback, SwiftShader, isn't yet for 32-bit ARM. + '--additional-driver-flag=--use-gpu-in-tests', + ], + }, }, }, 'webkit_unit_tests': { @@ -1620,7 +1693,9 @@ 'modifications': { 'Oreo Phone Tester': { # TODO(crbug.com/863089): Enable this once it's passing. - 'experiment_percentage': 100, + # TODO(https://crbug.com/884413): Re-enable this once the tests are + # either passing or there is more capacity. + 'experiment_percentage': 0, }, }, },
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 6b33de0..ba38fa9 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -308,6 +308,7 @@ }, 'mojo_test_apk': {}, 'ui_android_unittests': {}, + 'vr_android_unittests': {}, 'webview_instrumentation_test_apk': { 'swarming': { 'shards': 7, @@ -331,6 +332,19 @@ 'wm_unittests': {}, }, + 'autofill_captured_sites_gtests': { + 'autofill_captured_sites_interactive_tests': { + 'test': 'captured_sites_interactive_tests', + 'args': [ + '--gtest_filter="AutofillCapturedSitesInteractiveTest.Recipe/*"', + '--enable-pixel-output-in-tests', + '--ui-test-action-max-timeout=1000000', + '--test-launcher-timeout=1000000', + '--vmodule=captured_sites_test_utils=1,autofill_captured_sites_interactive_uitest=1' + ], + }, + }, + 'cast_audio_specific_chromium_gtests': { 'cast_audio_backend_unittests': {}, 'cast_base_unittests': {}, @@ -370,7 +384,11 @@ 'chromedriver_replay_unittests': {}, }, - 'chromeos_gtests': { + # Tests that run in Chrome OS VMs. + # NOTE: We only want a small subset of test suites here, because most + # suites assume that they stub out the underlying device hardware. + # https://crbug.com/865693 + 'chromeos_device_friendly_gtests': { 'aura_unittests': { 'args': [ '--ozone-platform=headless', @@ -388,13 +406,6 @@ }, 'cc_unittests': {}, 'chrome_all_tast_tests': {}, - 'chromeos_unittests': { - 'args': [ - # TODO(crbug.com/865693): Don't stub out dbus clients. - '--dbus-stub', - '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.chromeos_unittests.filter', - ], - }, 'cros_vm_sanity_test': {}, 'crypto_unittests': {}, 'display_unittests': {}, @@ -440,16 +451,9 @@ 'url_unittests': {}, }, - 'chromeos_gtests_experimental': { + 'chromeos_device_friendly_gtests_experimental': { 'base_unittests': {}, 'chrome_login_tast_tests': {}, - 'chromeos_unittests': { - 'args': [ - # TODO(crbug.com/865693): Don't stub out dbus clients. - '--dbus-stub', - '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.chromeos_unittests.filter', - ], - }, 'cros_vm_sanity_test': {}, 'services_unittests': { 'args': [ @@ -543,6 +547,11 @@ 'base_junit_tests': {}, }, + 'chromium_android_webkit_gtests': { + 'blink_heap_unittests': {}, + 'webkit_unit_tests': {}, + }, + 'chromium_browser_tests': { 'browser_tests': { 'swarming': { @@ -1026,7 +1035,6 @@ 'net_unittests': { 'args': [ '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.net_unittests.filter', - '--test-launcher-batch-limit=200', ], }, 'service_manager_unittests': {}, @@ -1997,7 +2005,7 @@ 'monochrome_apk_checker': {}, }, - 'network_service_android_gtests': { + 'network_service_android_fyi_gtests': { 'network_service_content_browsertests': { 'args': [ '--enable-features=NetworkService', @@ -2014,13 +2022,63 @@ ], 'test': 'components_browsertests', }, + 'network_service_webview_instrumentation_test_apk': { + 'swarming': { + 'shards': 20, + }, + 'args': [ + # TODO(crbug.com/882650): WebView currently does not support running network + # service OOP. + '--enable-features=NetworkService,NetworkServiceInProcess', + '--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter', + ], + 'test': 'webview_instrumentation_test_apk', + }, + 'network_service_in_process_content_browsertests': { + 'args': [ + '--enable-features=NetworkService,NetworkServiceInProcess', + '--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter', + ], + 'swarming': { + 'shards': 5, + }, + 'test': 'content_browsertests', + }, + 'network_service_in_process_components_browsertests': { + 'args': [ + '--enable-features=NetworkService,NetworkServiceInProcess', + ], + 'test': 'components_browsertests', + }, + 'network_service_in_process_chrome_public_test_apk': { + 'swarming': { + 'shards': 20, + }, + 'args': [ + '--enable-features=NetworkService,NetworkServiceInProcess', + '--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter', + ], + 'test': 'chrome_public_test_apk', + }, + 'network_service_in_process_content_shell_test_apk': { + 'swarming': { + 'shards': 5, + }, + 'args': [ + '--enable-features=NetworkService,NetworkServiceInProcess', + ], + 'test': 'content_shell_test_apk', + }, + }, + + # These tests will be run on the main waterfall in addition to the Mojo + # Android bot. + 'network_service_android_gtests': { 'network_service_chrome_public_test_apk': { 'swarming': { 'shards': 20, }, 'args': [ - # TODO(crbug.com/881572): Fix crash when running network service OOP on - # Android. '--enable-features=NetworkService', '--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_chrome_public_test_apk.filter', ], @@ -2035,18 +2093,6 @@ ], 'test': 'content_shell_test_apk', }, - 'network_service_webview_instrumentation_test_apk': { - 'swarming': { - 'shards': 20, - }, - 'args': [ - # TODO(crbug.com/882650): WebView currently does not support running network - # service OOP. - '--enable-features=NetworkService,NetworkServiceInProcess', - '--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter', - ], - 'test': 'webview_instrumentation_test_apk', - }, }, 'network_service_chromeos_fyi_gtests': { @@ -2138,6 +2184,29 @@ }, }, + 'network_service_in_process_gtests': { + 'network_service_in_process_browser_tests': { + 'args': [ + '--enable-features=NetworkService,NetworkServiceInProcess', + '--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_browser_tests.filter', + ], + 'swarming': { + 'shards': 15, + }, + 'test': 'browser_tests', + }, + 'network_service_in_process_content_browsertests': { + 'args': [ + '--enable-features=NetworkService,NetworkServiceInProcess', + '--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter', + ], + 'swarming': { + 'shards': 2, + }, + 'test': 'content_browsertests', + }, + }, + 'non_android_and_cast_and_chromeos_chromium_gtests': { 'cronet_tests': {}, 'cronet_unittests': {}, @@ -2265,15 +2334,6 @@ }, 'site_isolation_android_fyi_gtests': { - 'site_per_process_browser_tests': { - 'args': [ - '--site-per-process' - ], - 'swarming': { - 'shards': 10, - }, - 'test': 'browser_tests', - }, 'site_per_process_components_browsertests': { 'args': [ '--site-per-process', @@ -2291,7 +2351,9 @@ }, 'site_per_process_content_browsertests': { 'args': [ - '--site-per-process' + '--site-per-process', + '--test-launcher-filter-file=../../testing/buildbot/filters/site_isolation_android.content_browsertests.filter', + ], 'swarming': { 'shards': 10, @@ -2575,6 +2637,7 @@ 'chromium_gtests_for_devices_with_graphical_output', 'linux_flavor_specific_chromium_gtests', 'vr_platform_specific_chromium_gtests', + 'network_service_android_gtests', ], 'chromium_dbg_isolated_scripts': [ @@ -3023,6 +3086,7 @@ ], 'mojo_android_gtests': [ + 'network_service_android_fyi_gtests', 'network_service_android_gtests', 'non_viz_fyi_chromium_gtests', 'viz_gtests', @@ -3039,9 +3103,15 @@ 'viz_non_android_fyi_gtests', ], + 'mojo_linux_gtests': [ + 'network_service_gtests', + 'network_service_in_process_gtests', + ], + 'mojo_windows_gtests': [ 'mojo_windows_specific_gtests', 'network_service_gtests', + 'network_service_in_process_gtests', 'non_viz_fyi_chromium_gtests', 'non_viz_non_android_fyi_chromium_gtests', 'viz_gtests',
diff --git a/testing/buildbot/tryserver.chromium.android.json b/testing/buildbot/tryserver.chromium.android.json new file mode 100644 index 0000000..30ab9b5 --- /dev/null +++ b/testing/buildbot/tryserver.chromium.android.json
@@ -0,0 +1,125 @@ +{ + "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, + "AAAAA2 See generate_buildbot_json.py to make changes": {}, + "android_blink_rel": { + "gtest_tests": [ + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "blink_heap_unittests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "blink_heap_unittests" + }, + { + "args": [ + "--gs-results-bucket=chromium-result-details", + "--recover-devices" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "webkit_unit_tests" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ] + }, + "test": "webkit_unit_tests" + } + ], + "isolated_scripts": [ + { + "args": [ + "--num-retries=3", + "--release", + "--android", + "--disable-breakpad", + "--additional-driver-flag=--use-gpu-in-tests" + ], + "isolate_name": "webkit_layout_tests_exparchive", + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "webkit_layout_tests", + "results_handler": "layout tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "device_os": "KTU84P", + "device_type": "hammerhead", + "os": "Android" + } + ], + "shards": 12 + } + } + ] + } +}
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 8fe3087f..8f654e0 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -666,7 +666,7 @@ 'chromiumos_preflight', ], 'test_suites': { - 'gtest_tests': 'chromeos_gtests', + 'gtest_tests': 'chromeos_device_friendly_gtests', 'isolated_scripts': 'chromeos_isolated_scripts', }, 'swarming': { @@ -1204,7 +1204,7 @@ 'priority_adjustment': 30, }, 'test_suites': { - 'gtest_tests': 'network_service_gtests', + 'gtest_tests': 'mojo_linux_gtests', 'isolated_scripts': 'mojo_network_isolated_scripts', }, }, @@ -1241,6 +1241,24 @@ 'gtest_tests': 'vr_platform_specific_chromium_gtests', }, }, + 'WebKit Linux composite_after_paint Dummy Builder': { + # Normally, FYI tests run with a lower priority than main CI tests. + # However, some optional CQ bots mirror FYI bots, so their tests need + # to run at the same priority as other non-optional CQ bots to avoid + # getting starved out. + 'swarming': { + 'dimension_sets': [ + { + 'os': 'Ubuntu-14.04', + }, + ], + 'hard_timeout': 900, + 'priority_adjustment': 30, + }, + 'test_suites': { + 'isolated_scripts': 'chromium_webkit_isolated_scripts', + }, + }, 'WebKit Linux layout_ng Dummy Builder': { 'swarming': { 'dimension_sets': [ @@ -1268,24 +1286,6 @@ 'isolated_scripts': 'chromium_webkit_isolated_scripts', }, }, - 'WebKit Linux slimming_paint_v2 Dummy Builder': { - # Normally, FYI tests run with a lower priority than main CI tests. - # However, some optional CQ bots mirror FYI bots, so their tests need - # to run at the same priority as other non-optional CQ bots to avoid - # getting starved out. - 'swarming': { - 'dimension_sets': [ - { - 'os': 'Ubuntu-14.04', - }, - ], - 'hard_timeout': 900, - 'priority_adjustment': 30, - }, - 'test_suites': { - 'isolated_scripts': 'chromium_webkit_isolated_scripts', - }, - }, 'Win 10 Fast Ring': { 'test_suites': { 'gtest_tests': 'chromium_win_gtests', @@ -1371,7 +1371,7 @@ 'chromiumos_preflight', ], 'test_suites': { - 'gtest_tests': 'chromeos_gtests_experimental', + 'gtest_tests': 'chromeos_device_friendly_gtests_experimental', }, 'swarming': { 'dimension_sets': [ @@ -1433,6 +1433,11 @@ 'scripts': 'test_traffic_annotation_auditor_script', } }, + 'linux-autofill-captured-sites-rel': { + 'test_suites': { + 'gtest_tests': 'autofill_captured_sites_gtests', + }, + }, 'linux-blink-animation-use-time-delta': { 'additional_compile_targets': [ 'all', @@ -1511,6 +1516,16 @@ 'scripts': 'chromium_linux_scripts', }, }, + 'mac-autofill-captured-sites-rel': { + 'test_suites': { + 'gtest_tests': 'autofill_captured_sites_gtests', + }, + }, + 'mac-hermetic-upgrade-rel': { + 'additional_compile_targets': [ + 'all' + ], + }, 'mac-mojo-rel': { 'mixins': [ 'mac_10.13', @@ -1615,6 +1630,11 @@ 'scripts': 'test_traffic_annotation_auditor_script', } }, + 'win-autofill-captured-sites-rel': { + 'test_suites': { + 'gtest_tests': 'autofill_captured_sites_gtests', + }, + }, 'win10-blink-rel-dummy': { 'swarming': { 'dimension_sets': [ @@ -1704,9 +1724,31 @@ 'gtest_tests': 'goma_gtests', }, }, + 'Chromium Mac Goma RBE Staging': { + 'additional_compile_targets': [ + # Due to disk shortage, we build 'chrome' instead of 'all'. + # See crbug.com/899425 + 'chrome', + ], + 'test_suites': { + 'gtest_tests': 'goma_gtests', + }, + }, 'Chromium Mac Goma RBE Staging (clobber)': { 'additional_compile_targets': [ - 'all', + # Due to disk shortage, we build 'chrome' instead of 'all'. + # See crbug.com/899425 + 'chrome', + ], + 'test_suites': { + 'gtest_tests': 'goma_gtests', + }, + }, + 'Chromium Mac Goma RBE Staging (dbg)': { + 'additional_compile_targets': [ + # Due to disk shortage, we build 'chrome' instead of 'all'. + # See crbug.com/899425 + 'chrome', ], 'test_suites': { 'gtest_tests': 'goma_gtests', @@ -3722,11 +3764,32 @@ }, }, { + 'name': 'tryserver.chromium.android', + 'machines': { + 'android_blink_rel': { + 'test_suites': { + 'gtest_tests': 'chromium_android_webkit_gtests', + 'isolated_scripts': 'chromium_webkit_isolated_scripts', + }, + 'swarming': { + 'dimension_sets': [ + { + 'device_os': 'KTU84P', + 'device_type': 'hammerhead', + 'os': 'Android', + }, + ], + }, + 'os_type': 'android', + }, + }, + }, + { 'name': 'tryserver.chromium.linux', 'machines': { 'linux-coverage-rel': { 'mixins': [ - 'code-coverage', + 'code-coverage', ], 'test_suites': { 'gtest_tests': 'chromium_linux_coverage_gtests',
diff --git a/testing/test.gni b/testing/test.gni index d849552b1..4436bab7 100644 --- a/testing/test.gni +++ b/testing/test.gni
@@ -8,15 +8,15 @@ if (is_android) { import("//build/config/android/config.gni") + import("//build/config/android/extract_unwind_tables.gni") import("//build/config/android/rules.gni") import("//build/config/sanitizers/sanitizers.gni") - import("//build/config/android/extract_unwind_tables.gni") } if (is_fuchsia) { import("//build/config/chromecast_build.gni") - import("//build/config/fuchsia/rules.gni") import("//build/config/fuchsia/package.gni") + import("//build/config/fuchsia/rules.gni") } if (is_chromeos) { @@ -322,7 +322,7 @@ } bundle_deps += [ ":$_resources_bundle_data" ] } - } else if (is_chromeos && is_chromeos_chrome) { + } else if (is_chromeos && is_cros_chrome_sdk) { # Building for a cros board (ie: not linux-chromeos). _gen_runner_target = "${target_name}__runner"
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 007389b..1660feea 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -921,6 +921,24 @@ ] } ], + "AutofillUpstreamEditableExpirationDate": [ + { + "platforms": [ + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AutofillUpstreamEditableExpirationDate" + ] + } + ] + } + ], "AutofillUpstreamUseGooglePayOnAndroidBranding": [ { "platforms": [ @@ -2751,8 +2769,7 @@ "enable_features": [ "NewTabPageBackgrounds", "NewTabPageCustomLinks", - "NewTabPageIcons", - "NewTabPageUIMd" + "NewTabPageIcons" ] } ] @@ -5441,7 +5458,8 @@ "mac", "chromeos", "linux", - "ios" + "ios", + "android_webview" ], "experiments": [ {
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 07ddae7..48096f1d 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -146,5 +146,10 @@ const char kMixedContentAutoupgradeModeOptionallyBlockable[] = "optionally-blockable"; +// Decodes lossy WebP images to YUV instead of RGBX and stores in this format +// in the image decode cache. See crbug.com/900264 for details on the feature. +const base::Feature kDecodeLossyWebPImagesToYUV{ + "DecodeLossyWebPImagesToYUV", base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace features } // namespace blink
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn index f258cf51..d87bd76 100644 --- a/third_party/blink/public/BUILD.gn +++ b/third_party/blink/public/BUILD.gn
@@ -488,8 +488,6 @@ "web/web_settings.h", "web/web_shared_worker.h", "web/web_shared_worker_client.h", - "web/web_shared_worker_connect_listener.h", - "web/web_shared_worker_repository_client.h", "web/web_storage_event_dispatcher.h", "web/web_surrounding_text.h", "web/web_testing_support.h", @@ -659,7 +657,6 @@ "platform/ukm.mojom", "web/commit_result.mojom", "web/console_message.mojom", - "web/devtools_agent.mojom", "web/devtools_frontend.mojom", "web/selection_menu_behavior.mojom", "web/window_features.mojom",
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 8e586469..05f70bf 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -51,6 +51,8 @@ BLINK_COMMON_EXPORT extern const char kMixedContentAutoupgradeModeOptionallyBlockable[]; +BLINK_COMMON_EXPORT extern const base::Feature kDecodeLossyWebPImagesToYUV; + } // namespace features } // namespace blink
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index 1d408981..348778b4 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn
@@ -24,6 +24,7 @@ "cookie_store/cookie_store.mojom", "crash/crash_memory_metrics_reporter.mojom", "csp/content_security_policy.mojom", + "devtools/devtools_agent.mojom", "dom_storage/session_storage_namespace.mojom", "dom_storage/storage_area.mojom", "dom_storage/storage_partition_service.mojom", @@ -68,10 +69,14 @@ "speech/speech_recognition_result.mojom", "speech/speech_recognizer.mojom", "use_counter/css_property_id.mojom", + "wake_lock/wake_lock.mojom", "webaudio/audio_context_manager.mojom", "worker/dedicated_worker_factory.mojom", + "worker/shared_worker.mojom", "worker/shared_worker_client.mojom", + "worker/shared_worker_connector.mojom", "worker/shared_worker_creation_context_type.mojom", + "worker/shared_worker_host.mojom", "worker/shared_worker_info.mojom", "worker/worker_main_script_load_params.mojom", ]
diff --git a/third_party/blink/public/mojom/devtools/OWNERS b/third_party/blink/public/mojom/devtools/OWNERS new file mode 100644 index 0000000..43016bc0 --- /dev/null +++ b/third_party/blink/public/mojom/devtools/OWNERS
@@ -0,0 +1,7 @@ +file://third_party/blink/renderer/core/inspector/OWNERS + +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS + +# TEAM: devtools-dev@chromium.org +# COMPONENT: Platform>DevTools
diff --git a/third_party/blink/public/mojom/devtools/README.md b/third_party/blink/public/mojom/devtools/README.md new file mode 100644 index 0000000..999c7e2 --- /dev/null +++ b/third_party/blink/public/mojom/devtools/README.md
@@ -0,0 +1 @@ +Public mojom files that are referenced both from browser-side and renderer-side for DevTools.
diff --git a/third_party/blink/public/web/devtools_agent.mojom b/third_party/blink/public/mojom/devtools/devtools_agent.mojom similarity index 100% rename from third_party/blink/public/web/devtools_agent.mojom rename to third_party/blink/public/mojom/devtools/devtools_agent.mojom
diff --git a/third_party/blink/public/mojom/wake_lock/OWNERS b/third_party/blink/public/mojom/wake_lock/OWNERS new file mode 100644 index 0000000..08850f4 --- /dev/null +++ b/third_party/blink/public/mojom/wake_lock/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/mojom/wake_lock/wake_lock.mojom b/third_party/blink/public/mojom/wake_lock/wake_lock.mojom new file mode 100644 index 0000000..f12ad67 --- /dev/null +++ b/third_party/blink/public/mojom/wake_lock/wake_lock.mojom
@@ -0,0 +1,18 @@ +// 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. + +module blink.mojom; + +import "services/device/public/mojom/wake_lock.mojom"; + +// The Blink WakeLock service allows the creation of WakeLocks without using a +// WakeLockContext or a WakeLockProvider, instead using the associated frame's +// context. This allows Blink to create WakeLocks using the context id +// associated with the window the frame is running in. +interface WakeLockService { + GetWakeLock(device.mojom.WakeLockType type, + device.mojom.WakeLockReason reason, + string description, + device.mojom.WakeLock& wake_lock); +};
diff --git a/third_party/blink/public/mojom/worker/shared_worker.mojom b/third_party/blink/public/mojom/worker/shared_worker.mojom new file mode 100644 index 0000000..8a2a20c --- /dev/null +++ b/third_party/blink/public/mojom/worker/shared_worker.mojom
@@ -0,0 +1,24 @@ +// Copyright 2017 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. + +module blink.mojom; + +import "third_party/blink/public/mojom/devtools/devtools_agent.mojom"; + +// Interface used by the host to control the shared worker. +interface SharedWorker { + // Called to establish a new client connection to the shared worker. The + // |connection_id| parameter will be echoed back to the host via the + // OnConnected method. + Connect(int32 connection_id, handle<message_pipe> message_port); + + // Called to terminate the shared worker. This results in the shared worker + // closing its end of the mojo connection. + Terminate(); + + // Binds a DevToolsAgent interface for this shared worker, used for + // remote debugging. See DevToolsAgent for details. + BindDevToolsAgent(associated DevToolsAgentHost agent_host, + associated DevToolsAgent& agent); +};
diff --git a/third_party/blink/public/mojom/worker/shared_worker_client.mojom b/third_party/blink/public/mojom/worker/shared_worker_client.mojom index f94d1453..709ddeb 100644 --- a/third_party/blink/public/mojom/worker/shared_worker_client.mojom +++ b/third_party/blink/public/mojom/worker/shared_worker_client.mojom
@@ -13,15 +13,15 @@ // Indicates that the shared worker process has started (or may have already // been started). The shared worker script is not necessarily loaded yet. // This event will be followed by either OnConnected or OnScriptLoadFailed. - OnCreated(blink.mojom.SharedWorkerCreationContextType creation_context_type); + OnCreated(SharedWorkerCreationContextType creation_context_type); // Indicates that the shared worker process is up and running, script loaded. - OnConnected(array<blink.mojom.WebFeature> features_used); + OnConnected(array<WebFeature> features_used); // Indicates that the shared worker script failed to load. OnScriptLoadFailed(); // Indicates that the shared worker used a feature. This is intended to be // logged by the client-side feature logging infrastructure. - OnFeatureUsed(blink.mojom.WebFeature feature); + OnFeatureUsed(WebFeature feature); };
diff --git a/third_party/blink/public/mojom/worker/shared_worker_connector.mojom b/third_party/blink/public/mojom/worker/shared_worker_connector.mojom new file mode 100644 index 0000000..8feca4f --- /dev/null +++ b/third_party/blink/public/mojom/worker/shared_worker_connector.mojom
@@ -0,0 +1,26 @@ +// Copyright 2017 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. + +module blink.mojom; + +import "third_party/blink/public/mojom/blob/blob_url_store.mojom"; +import "third_party/blink/public/mojom/worker/shared_worker_client.mojom"; +import "third_party/blink/public/mojom/worker/shared_worker_creation_context_type.mojom"; +import "third_party/blink/public/mojom/worker/shared_worker_info.mojom"; + +// This interface is exposed to enable a client to create and connect to a +// shared worker. +interface SharedWorkerConnector { + // Connect to (and create if necessary) a SharedWorker specified by |info|. + // The SharedWorker will be terminated if all clients go away. + // |blob_url_token| should be non-null when the worker is loaded from a blob: + // URL. The token will then be used to look up the blob associated with the + // blob URL. Without this by the time the worker code starts fetching + // the URL the blob URL might no longer be valid. + Connect(SharedWorkerInfo info, + SharedWorkerClient client, + SharedWorkerCreationContextType creation_context_type, + handle<message_pipe> message_port, + BlobURLToken? blob_url_token); +};
diff --git a/third_party/blink/public/mojom/worker/shared_worker_host.mojom b/third_party/blink/public/mojom/worker/shared_worker_host.mojom new file mode 100644 index 0000000..3227be0 --- /dev/null +++ b/third_party/blink/public/mojom/worker/shared_worker_host.mojom
@@ -0,0 +1,33 @@ +// Copyright 2017 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. + +module blink.mojom; + +import "third_party/blink/public/platform/web_feature.mojom"; + +// Each shared worker has a corresponding host. The host controls the lifetime +// of the shared worker. This interface is used by the shared worker to talk to +// its host. +interface SharedWorkerHost { + // Called in response to SharedWorker's Connect method. The |connection_id| + // parameter is the same value passed to the Connect method. + OnConnected(int32 connection_id); + + // Indicates that the shared worker self-closed. This should trigger the host + // to terminate the shared worker. + OnContextClosed(); + + // Indicates that the shared worker is ready for inspection. + OnReadyForInspection(); + + // Indicates that the script successfully loaded. + OnScriptLoaded(); + + // Indicates that the script failed to load. + OnScriptLoadFailed(); + + // Indicates that the shared worker used a feature. This is intended to be + // logged by the client-side feature logging infrastructure. + OnFeatureUsed(WebFeature feature); +};
diff --git a/third_party/blink/public/platform/web_feature.mojom b/third_party/blink/public/platform/web_feature.mojom index 3e5f158..96b7b3c 100644 --- a/third_party/blink/public/platform/web_feature.mojom +++ b/third_party/blink/public/platform/web_feature.mojom
@@ -155,8 +155,6 @@ kFormAssociationByParser = 248, kSVGSVGElementInDocument = 250, kSVGDocumentRootElement = 251, - kWorkerSubjectToCSP = 257, - kWorkerAllowedByChildBlockedByScript = 258, kDeprecatedWebKitGradient = 260, kDeprecatedWebKitLinearGradient = 261, kDeprecatedWebKitRepeatingLinearGradient = 262,
diff --git a/third_party/blink/public/platform/web_url_loader_client.h b/third_party/blink/public/platform/web_url_loader_client.h index 96991bd..61c9a17 100644 --- a/third_party/blink/public/platform/web_url_loader_client.h +++ b/third_party/blink/public/platform/web_url_loader_client.h
@@ -58,6 +58,7 @@ virtual bool WillFollowRedirect( const WebURL& new_url, const WebURL& new_site_for_cookies, + const base::Optional<WebSecurityOrigin>& new_top_frame_origin, const WebString& new_referrer, network::mojom::ReferrerPolicy new_referrer_policy, const WebString& new_method,
diff --git a/third_party/blink/public/platform/web_url_request.h b/third_party/blink/public/platform/web_url_request.h index 9d9542d..5e61452 100644 --- a/third_party/blink/public/platform/web_url_request.h +++ b/third_party/blink/public/platform/web_url_request.h
@@ -130,6 +130,10 @@ BLINK_PLATFORM_EXPORT WebURL SiteForCookies() const; BLINK_PLATFORM_EXPORT void SetSiteForCookies(const WebURL&); + BLINK_PLATFORM_EXPORT base::Optional<WebSecurityOrigin> TopFrameOrigin() + const; + BLINK_PLATFORM_EXPORT void SetTopFrameOrigin(const WebSecurityOrigin&); + // https://fetch.spec.whatwg.org/#concept-request-origin BLINK_PLATFORM_EXPORT WebSecurityOrigin RequestorOrigin() const; BLINK_PLATFORM_EXPORT void SetRequestorOrigin(const WebSecurityOrigin&);
diff --git a/third_party/blink/public/platform/web_url_response.h b/third_party/blink/public/platform/web_url_response.h index 48e54a4..e438ae62 100644 --- a/third_party/blink/public/platform/web_url_response.h +++ b/third_party/blink/public/platform/web_url_response.h
@@ -256,6 +256,8 @@ // for details. BLINK_PLATFORM_EXPORT void SetURLListViaServiceWorker( const WebVector<WebURL>&); + // Returns true if the URL list is not empty. + BLINK_PLATFORM_EXPORT bool HasUrlListViaServiceWorker() const; // The boundary of the response. Set only when this is a multipart response. BLINK_PLATFORM_EXPORT void SetMultipartBoundary(const char* bytes,
diff --git a/third_party/blink/public/web/blink.h b/third_party/blink/public/web/blink.h index d255161..a15ea06 100644 --- a/third_party/blink/public/web/blink.h +++ b/third_party/blink/public/web/blink.h
@@ -65,14 +65,14 @@ BLINK_EXPORT v8::Isolate* MainThreadIsolate(); // Alters the rendering of content to conform to a fixed set of rules. -BLINK_EXPORT void SetLayoutTestMode(bool); -BLINK_EXPORT bool LayoutTestMode(); +BLINK_EXPORT void SetWebTestMode(bool); +BLINK_EXPORT bool WebTestMode(); -// Enables or disables the use of the mock theme for layout tests. This function -// must be called only if setLayoutTestMode(true). +// Enables or disables the use of the mock theme for web tests. This function +// must be called only if SetWebTestMode(true). BLINK_EXPORT void SetMockThemeEnabledForTest(bool); -// Alters the rendering of fonts for layout tests. +// Alters the rendering of fonts for web tests. BLINK_EXPORT void SetFontAntialiasingEnabledForTest(bool); BLINK_EXPORT bool FontAntialiasingEnabledForTest();
diff --git a/third_party/blink/public/web/web_document.h b/third_party/blink/public/web/web_document.h index b92d57a..6ab2d5c4 100644 --- a/third_party/blink/public/web/web_document.h +++ b/third_party/blink/public/web/web_document.h
@@ -95,13 +95,7 @@ BLINK_EXPORT WebElement Body() const; BLINK_EXPORT WebElement Head(); BLINK_EXPORT WebString Title() const; - - // |use_inner_text| controls which implementation to use for text dump, - // spec-conformant Element.innerText or legacy, to help progressive - // rebaseline of layout test text dumps. - // TODO(xiaochengh): Remove this flag when rebaseline is complete. - BLINK_EXPORT WebString ContentAsTextForTesting(bool use_inner_text) const; - + BLINK_EXPORT WebString ContentAsTextForTesting() const; BLINK_EXPORT WebElementCollection All(); BLINK_EXPORT void Forms(WebVector<WebFormElement>&) const; BLINK_EXPORT WebURL CompleteURL(const WebString&) const;
diff --git a/third_party/blink/public/web/web_document_loader.h b/third_party/blink/public/web/web_document_loader.h index b45799f..9db3041 100644 --- a/third_party/blink/public/web/web_document_loader.h +++ b/third_party/blink/public/web/web_document_loader.h
@@ -134,6 +134,9 @@ // Whether this load was started with a user gesture. virtual bool HadUserGesture() const = 0; + // Returns true when the document is a FTP directory. + virtual bool IsListingFtpDirectory() const = 0; + protected: ~WebDocumentLoader() = default; };
diff --git a/third_party/blink/public/web/web_frame_widget.h b/third_party/blink/public/web/web_frame_widget.h index a9134e9c..9cd623e 100644 --- a/third_party/blink/public/web/web_frame_widget.h +++ b/third_party/blink/public/web/web_frame_widget.h
@@ -146,6 +146,10 @@ // inside) this widget into view. The scrolling might end with a final zooming // into the editable region which is performed in the main frame process. virtual bool ScrollFocusedEditableElementIntoView() = 0; + + // This function provides zooming for find in page results when browsing with + // page autosize. + virtual void ZoomToFindInPageRect(const WebRect& rect_in_root_frame) = 0; }; } // namespace blink
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h index b37009f..eec8cd4 100644 --- a/third_party/blink/public/web/web_local_frame.h +++ b/third_party/blink/public/web/web_local_frame.h
@@ -28,6 +28,10 @@ #include "third_party/blink/public/web/web_text_direction.h" #include "v8/include/v8.h" +namespace service_manager { +class InterfaceProvider; +} // namespace service_manager + namespace blink { class FrameScheduler; @@ -45,7 +49,6 @@ class WebRange; class WebSecurityOrigin; class WebScriptExecutionCallback; -class WebSharedWorkerRepositoryClient; class WebSpellCheckPanelHostClient; class WebString; class WebTextCheckClient; @@ -132,8 +135,8 @@ virtual void SetAutofillClient(WebAutofillClient*) = 0; virtual WebAutofillClient* AutofillClient() = 0; - virtual void SetSharedWorkerRepositoryClient( - WebSharedWorkerRepositoryClient*) = 0; + virtual void InitializeSharedWorkerRepositoryClient( + service_manager::InterfaceProvider*) = 0; // Closing -------------------------------------------------------------
diff --git a/third_party/blink/public/web/web_shared_worker_connect_listener.h b/third_party/blink/public/web/web_shared_worker_connect_listener.h deleted file mode 100644 index df3c92a..0000000 --- a/third_party/blink/public/web/web_shared_worker_connect_listener.h +++ /dev/null
@@ -1,60 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_SHARED_WORKER_CONNECT_LISTENER_H_ -#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_SHARED_WORKER_CONNECT_LISTENER_H_ - -#include "third_party/blink/public/mojom/worker/shared_worker_creation_context_type.mojom-shared.h" -#include "third_party/blink/public/platform/web_feature.mojom-shared.h" - -namespace blink { - -// This is the callback interface passed from blink to the embedder. -class WebSharedWorkerConnectListener { - public: - virtual ~WebSharedWorkerConnectListener() = default; - - // Called when a worker is created. - virtual void WorkerCreated(mojom::SharedWorkerCreationContextType) = 0; - - // Called when worker script load fails. - virtual void ScriptLoadFailed() = 0; - - // Called when a connection is established. - virtual void Connected() = 0; - - // Called when some API to be recorded in UseCounter is called on the worker - // global scope. - virtual void CountFeature(mojom::WebFeature) = 0; -}; - -} // namespace blink - -#endif
diff --git a/third_party/blink/public/web/web_shared_worker_repository_client.h b/third_party/blink/public/web/web_shared_worker_repository_client.h deleted file mode 100644 index ccdb7599..0000000 --- a/third_party/blink/public/web/web_shared_worker_repository_client.h +++ /dev/null
@@ -1,71 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_SHARED_WORKER_REPOSITORY_CLIENT_H_ -#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_SHARED_WORKER_REPOSITORY_CLIENT_H_ - -#include <memory> -#include "third_party/blink/public/mojom/net/ip_address_space.mojom-shared.h" -#include "third_party/blink/public/mojom/worker/shared_worker_creation_context_type.mojom-shared.h" - -namespace blink { - -class MessagePortChannel; -class WebSharedWorkerConnectListener; -class WebString; -class WebURL; - -class WebSharedWorkerRepositoryClient { - public: - // Unique identifier for the parent document of a worker (unique within a - // given process). - using DocumentID = unsigned long long; - - // Connects to a shared worker. - virtual void Connect( - const WebURL&, - const WebString& name, - DocumentID, - const WebString& content_security_policy, - mojom::ContentSecurityPolicyType, - mojom::IPAddressSpace, - mojom::SharedWorkerCreationContextType, - MessagePortChannel, - mojo::ScopedMessagePipeHandle blob_url_token, - std::unique_ptr<blink::WebSharedWorkerConnectListener>) = 0; - - // Invoked when a document has been detached. DocumentID can be re-used after - // documentDetached() is invoked. - virtual void DocumentDetached(DocumentID) {} -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_SHARED_WORKER_REPOSITORY_CLIENT_H_
diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h index 2b22734..6b8eb3f 100644 --- a/third_party/blink/public/web/web_view.h +++ b/third_party/blink/public/web/web_view.h
@@ -274,8 +274,8 @@ virtual float ZoomFactorForDeviceScaleFactor() = 0; // Resize the view at the same time as changing the state of the top - // controls. If |browserControlsShrinkLayout| is true, the embedder shrunk the - // WebView size by the browser controls height. + // controls. If |browser_controls_shrink_layout| is true, the embedder shrunk + // the WebView size by the browser controls height. virtual void ResizeWithBrowserControls( const WebSize&, float top_controls_height,
diff --git a/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.cc b/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.cc index 3822dd5..5dcf3a4 100644 --- a/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.cc +++ b/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.cc
@@ -78,16 +78,17 @@ // difference but the advantage that we can use listener's |ScriptState| // after it get compiled. // https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-value - v8::Local<v8::Value> listener = GetListenerObject(*event->target()); + v8::Local<v8::Value> listener = GetListenerObject(*event->currentTarget()); if (listener.IsEmpty() || !listener->IsObject()) return; } - ScriptState* script_state_of_listener = GetScriptState(); - DCHECK(script_state_of_listener); + ScriptState* script_state_of_listener = GetScriptStateOrReportError("invoke"); + if (!script_state_of_listener) + return; // The error is already reported. if (!script_state_of_listener->ContextIsValid()) - return; + return; // Silently fail. ScriptState::Scope listener_script_state_scope(script_state_of_listener);
diff --git a/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.h b/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.h index 11b430b1..20ef9237 100644 --- a/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.h +++ b/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.h
@@ -73,7 +73,15 @@ protected: explicit JSBasedEventListener(ListenerType); virtual v8::Isolate* GetIsolate() const = 0; + // Returns the ScriptState of the relevant realm of the callback object. + // Must be used only when it's sure that the callback object is the same + // origin-domain. virtual ScriptState* GetScriptState() const = 0; + // Returns the ScriptState of the relevant realm of the callback object iff + // the callback is the same origin-domain. Otherwise, reports the error and + // returns nullptr. + virtual ScriptState* GetScriptStateOrReportError( + const char* operation) const = 0; virtual DOMWrapperWorld& GetWorld() const = 0; private:
diff --git a/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc b/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc index 1f6b5cc..39c41dc8 100644 --- a/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc +++ b/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc
@@ -50,7 +50,8 @@ // Step 1. Let callback be the result of getting the current value of the // event handler given eventTarget and name. // Step 2. If callback is null, then return. - v8::Local<v8::Value> listener_value = GetListenerObject(event_target); + v8::Local<v8::Value> listener_value = + GetListenerObject(*event.currentTarget()); if (listener_value.IsEmpty() || listener_value->IsNull()) return; DCHECK(HasCompiledHandler()); @@ -106,8 +107,12 @@ const bool is_beforeunload_event = event.IsBeforeUnloadEvent() && event.type() == event_type_names::kBeforeunload; + const bool is_print_event = + // TODO(yukishiino): Should check event.Is{Before,After}PrintEvent. + event.type() == event_type_names::kBeforeprint || + event.type() == event_type_names::kAfterprint; if (!event_handler_->IsRunnableOrThrowException( - is_beforeunload_event + (is_beforeunload_event || is_print_event) ? V8EventHandlerNonNull::IgnorePause::kIgnore : V8EventHandlerNonNull::IgnorePause::kDontIgnore)) { return;
diff --git a/third_party/blink/renderer/bindings/core/v8/js_event_handler.h b/third_party/blink/renderer/bindings/core/v8/js_event_handler.h index 65214a8..0013fd3 100644 --- a/third_party/blink/renderer/bindings/core/v8/js_event_handler.h +++ b/third_party/blink/renderer/bindings/core/v8/js_event_handler.h
@@ -71,8 +71,13 @@ ScriptState* GetScriptState() const override { return event_handler_->CallbackRelevantScriptState(); } + ScriptState* GetScriptStateOrReportError( + const char* operation) const override { + return event_handler_->CallbackRelevantScriptStateOrReportError( + "EventHandler", operation); + } DOMWrapperWorld& GetWorld() const override { - return event_handler_->CallbackRelevantScriptState()->World(); + return event_handler_->GetWorld(); } // Initializes |event_handler_| with |listener|. This method must be used only
diff --git a/third_party/blink/renderer/bindings/core/v8/js_event_listener.cc b/third_party/blink/renderer/bindings/core/v8/js_event_listener.cc index 558a038..d6e2dfc 100644 --- a/third_party/blink/renderer/bindings/core/v8/js_event_listener.cc +++ b/third_party/blink/renderer/bindings/core/v8/js_event_listener.cc
@@ -50,9 +50,14 @@ const bool is_beforeunload_event = event.IsBeforeUnloadEvent() && event.type() == event_type_names::kBeforeunload; + const bool is_print_event = + // TODO(yukishiino): Should check event.Is{Before,After}PrintEvent. + event.type() == event_type_names::kBeforeprint || + event.type() == event_type_names::kAfterprint; if (!event_listener_->IsRunnableOrThrowException( - is_beforeunload_event ? V8EventListener::IgnorePause::kIgnore - : V8EventListener::IgnorePause::kDontIgnore)) { + (is_beforeunload_event || is_print_event) + ? V8EventListener::IgnorePause::kIgnore + : V8EventListener::IgnorePause::kDontIgnore)) { return; } v8::Maybe<void> maybe_result = event_listener_->InvokeWithoutRunnabilityCheck(
diff --git a/third_party/blink/renderer/bindings/core/v8/js_event_listener.h b/third_party/blink/renderer/bindings/core/v8/js_event_listener.h index a31902f4..dead4b4 100644 --- a/third_party/blink/renderer/bindings/core/v8/js_event_listener.h +++ b/third_party/blink/renderer/bindings/core/v8/js_event_listener.h
@@ -63,8 +63,13 @@ ScriptState* GetScriptState() const override { return event_listener_->CallbackRelevantScriptState(); } + ScriptState* GetScriptStateOrReportError( + const char* operation) const override { + return event_listener_->CallbackRelevantScriptStateOrReportError( + "EventListener", operation); + } DOMWrapperWorld& GetWorld() const override { - return event_listener_->CallbackRelevantScriptState()->World(); + return event_listener_->GetWorld(); } private:
diff --git a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc index b43ca24..e6fec931 100644 --- a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc +++ b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
@@ -74,7 +74,8 @@ void LocalWindowProxy::DisposeContext(Lifecycle next_status, FrameReuseStatus frame_reuse_status) { DCHECK(next_status == Lifecycle::kGlobalObjectIsDetached || - next_status == Lifecycle::kFrameIsDetached); + next_status == Lifecycle::kFrameIsDetached || + next_status == Lifecycle::kForciblyPurgeV8Memory); if (lifecycle_ != Lifecycle::kContextIsInitialized) return; @@ -86,8 +87,8 @@ // it returns. GetFrame()->Client()->WillReleaseScriptContext(context, world_->GetWorldId()); MainThreadDebugger::Instance()->ContextWillBeDestroyed(script_state_); - - if (next_status == Lifecycle::kGlobalObjectIsDetached) { + if (next_status == Lifecycle::kGlobalObjectIsDetached || + next_status == Lifecycle::kForciblyPurgeV8Memory) { // Clean up state on the global proxy, which will be reused. if (!global_proxy_.IsEmpty()) { CHECK(global_proxy_ == context->Global());
diff --git a/third_party/blink/renderer/bindings/core/v8/remote_window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/remote_window_proxy.cc index dcf2acf..c4f2187 100644 --- a/third_party/blink/renderer/bindings/core/v8/remote_window_proxy.cc +++ b/third_party/blink/renderer/bindings/core/v8/remote_window_proxy.cc
@@ -52,12 +52,14 @@ void RemoteWindowProxy::DisposeContext(Lifecycle next_status, FrameReuseStatus) { DCHECK(next_status == Lifecycle::kGlobalObjectIsDetached || - next_status == Lifecycle::kFrameIsDetached); + next_status == Lifecycle::kFrameIsDetached || + next_status == Lifecycle::kForciblyPurgeV8Memory); if (lifecycle_ != Lifecycle::kContextIsInitialized) return; - if (next_status == Lifecycle::kGlobalObjectIsDetached && + if ((next_status == Lifecycle::kGlobalObjectIsDetached || + next_status == Lifecycle::kForciblyPurgeV8Memory) && !global_proxy_.IsEmpty()) { global_proxy_.Get().SetWrapperClassId(0); V8DOMWrapper::ClearNativeInfo(GetIsolate(),
diff --git a/third_party/blink/renderer/bindings/core/v8/script_event_listener.cc b/third_party/blink/renderer/bindings/core/v8/script_event_listener.cc index 5703b2a5..15576be 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_event_listener.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_event_listener.cc
@@ -55,7 +55,7 @@ OrdinalNumber::First()); String source_url; - v8::Isolate* isolate = node->GetDocument().GetIsolate(); + v8::Isolate* isolate = ToIsolate(&node->GetDocument()); v8::HandleScope scope(isolate); if (LocalFrame* frame = node->GetDocument().GetFrame()) {
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_property_base.cc b/third_party/blink/renderer/bindings/core/v8/script_promise_property_base.cc index 472f8da..fa1fb64 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_promise_property_base.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_promise_property_base.cc
@@ -16,7 +16,7 @@ ExecutionContext* execution_context, Name name) : ContextClient(execution_context), - isolate_(execution_context->GetIsolate()), + isolate_(ToIsolate(execution_context)), name_(name), state_(kPending) {}
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc b/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc index 78cce798..627e808f0 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
@@ -112,7 +112,7 @@ virtual ~ScriptPromisePropertyTestBase() { DestroyContext(); } Document& GetDocument() { return page_->GetDocument(); } - v8::Isolate* GetIsolate() { return GetDocument().GetIsolate(); } + v8::Isolate* GetIsolate() { return ToIsolate(&GetDocument()); } ScriptState* MainScriptState() { return ToScriptStateForMainWorld(GetDocument().GetFrame()); }
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h index d9f7ca9..0702f58f 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h +++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h
@@ -74,7 +74,7 @@ using SharedArrayBufferContentsArray = Vector<WTF::ArrayBufferContents, 1>; using ImageBitmapContentsArray = Vector<scoped_refptr<StaticBitmapImage>, 1>; using TransferredWasmModulesArray = - WTF::Vector<v8::WasmCompiledModule::TransferrableModule>; + WTF::Vector<v8::WasmModuleObject::TransferrableModule>; using MessagePortChannelArray = Vector<MessagePortChannel>; // Increment this for each incompatible change to the wire format.
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc index 6de2a68..4c6ec62 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc +++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc
@@ -678,15 +678,15 @@ return wrapper.As<v8::Object>(); } -v8::MaybeLocal<v8::WasmCompiledModule> +v8::MaybeLocal<v8::WasmModuleObject> V8ScriptValueDeserializer::GetWasmModuleFromId(v8::Isolate* isolate, uint32_t id) { if (id < serialized_script_value_->WasmModules().size()) { - return v8::WasmCompiledModule::FromTransferrableModule( + return v8::WasmModuleObject::FromTransferrableModule( isolate, serialized_script_value_->WasmModules()[id]); } CHECK(serialized_script_value_->WasmModules().IsEmpty()); - return v8::MaybeLocal<v8::WasmCompiledModule>(); + return v8::MaybeLocal<v8::WasmModuleObject>(); } v8::MaybeLocal<v8::SharedArrayBuffer>
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h index 665dcfe..78511fe 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h +++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h
@@ -100,8 +100,8 @@ // v8::ValueDeserializer::Delegate v8::MaybeLocal<v8::Object> ReadHostObject(v8::Isolate*) override; - v8::MaybeLocal<v8::WasmCompiledModule> GetWasmModuleFromId(v8::Isolate*, - uint32_t) override; + v8::MaybeLocal<v8::WasmModuleObject> GetWasmModuleFromId(v8::Isolate*, + uint32_t) override; v8::MaybeLocal<v8::SharedArrayBuffer> GetSharedArrayBufferFromId( v8::Isolate*, uint32_t) override;
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc index 8e52ecc..19b2d96 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc +++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc
@@ -679,7 +679,7 @@ v8::Maybe<uint32_t> V8ScriptValueSerializer::GetWasmModuleTransferId( v8::Isolate* isolate, - v8::Local<v8::WasmCompiledModule> module) { + v8::Local<v8::WasmModuleObject> module) { if (for_storage_) { DCHECK(exception_state_); DCHECK_EQ(isolate, script_state_->GetIsolate());
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.h b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.h index 7d8031f..e159a1e 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.h +++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.h
@@ -92,7 +92,7 @@ v8::Maybe<uint32_t> GetWasmModuleTransferId( v8::Isolate*, - v8::Local<v8::WasmCompiledModule>) override; + v8::Local<v8::WasmModuleObject>) override; // Reallocates memory at |ptr| to the new size and returns the new pointer or // nullptr on failure. |actual_size| will hold the actual size of allocation // requested.
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.cc b/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.cc index 88d5483..31129d4 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.cc
@@ -872,6 +872,22 @@ return iterator_getter->IsFunction(); } +v8::Isolate* ToIsolate(const ExecutionContext* context) { + if (!context) + return nullptr; + +#if DCHECK_IS_ON() + v8::Isolate* isolate; + if (context && context->IsDocument()) + isolate = V8PerIsolateData::MainThreadIsolate(); + else + isolate = v8::Isolate::GetCurrent(); + DCHECK(context->GetIsolate() == isolate); +#endif + + return context->GetIsolate(); +} + v8::Isolate* ToIsolate(const LocalFrame* frame) { DCHECK(frame); return frame->GetWindowProxyManager()->GetIsolate();
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h b/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h index 3504d75..8fcde322 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h +++ b/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h
@@ -436,6 +436,7 @@ v8::Local<v8::Value>, ExceptionState&); +CORE_EXPORT v8::Isolate* ToIsolate(const ExecutionContext*); CORE_EXPORT v8::Isolate* ToIsolate(const LocalFrame*); CORE_EXPORT DOMWindow* ToDOMWindow(v8::Isolate*, v8::Local<v8::Value>);
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc index 41a4e10..6db0013 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
@@ -552,8 +552,8 @@ if (!source->IsWebAssemblyCompiledModule()) return false; - v8::Local<v8::WasmCompiledModule> module = - v8::Local<v8::WasmCompiledModule>::Cast(source); + v8::Local<v8::WasmModuleObject> module = + v8::Local<v8::WasmModuleObject>::Cast(source); if (module->GetWasmWireBytesRef().size > kWasmWireBytesLimit) { ThrowRangeException( args.GetIsolate(),
diff --git a/third_party/blink/renderer/bindings/core/v8/window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/window_proxy.cc index b4b0f69..6602caf 100644 --- a/third_party/blink/renderer/bindings/core/v8/window_proxy.cc +++ b/third_party/blink/renderer/bindings/core/v8/window_proxy.cc
@@ -74,6 +74,10 @@ DisposeContext(Lifecycle::kGlobalObjectIsDetached, kFrameWillNotBeReused); } +void WindowProxy::ClearForMummification() { + DisposeContext(Lifecycle::kForciblyPurgeV8Memory, kFrameWillNotBeReused); +} + v8::Local<v8::Object> WindowProxy::GlobalProxyIfNotDetached() { if (lifecycle_ == Lifecycle::kContextIsInitialized) { DLOG_IF(FATAL, !is_global_object_attached_)
diff --git a/third_party/blink/renderer/bindings/core/v8/window_proxy.h b/third_party/blink/renderer/bindings/core/v8/window_proxy.h index c2f135f7..04dc4ed 100644 --- a/third_party/blink/renderer/bindings/core/v8/window_proxy.h +++ b/third_party/blink/renderer/bindings/core/v8/window_proxy.h
@@ -153,6 +153,7 @@ void ClearForClose(); void ClearForNavigation(); void ClearForSwap(); + void ClearForMummification(); CORE_EXPORT v8::Local<v8::Object> GlobalProxyIfNotDetached(); v8::Local<v8::Object> ReleaseGlobalProxy(); @@ -176,18 +177,19 @@ // - Possible next states: kContextIsInitialized // It's possible to detach the context's frame from the DOM or navigate to a // new page without initializing the WindowProxy, however, there is no - // transition to |kFrameIsDetached| or |kGlobalObjectIsDetached| - // because |DisposeContext| does not change the state if the state is - // |kContextIsUninitialized|. In either case of a) the browsing context - // container is detached from the DOM or b) the page is navigated away, there - // must be no way for author script to access the context of - // |kContextIsUninitialized| because |kContextIsUninitialized| means that - // author script has never accessed the context, hence there must exist no - // reference to the context. + // transition to |kFrameIsDetached| or |kGlobalObjectIsDetached| or + // |kForciblyPurgeV8Memory| because |DisposeContext| does not change the state + // if the state is |kContextIsUninitialized|. In either case of a) the + // browsing context container is detached from the DOM or b) the page is + // navigated away, there must be no way for author script to access the + // context of |kContextIsUninitialized| because |kContextIsUninitialized| + // means that author script has never accessed the context, hence there must + // exist no reference to the context. // // * kContextIsInitialized // The context is initialized and its frame is still attached to the DOM. - // - Possible next states: kFrameIsDetached, kGlobalObjectIsDetached + // - Possible next states: kFrameIsDetached, kGlobalObjectIsDetached, + // kForciblyPurgeV8Memory // // * kGlobalObjectIsDetached // The context is initialized and its frame is still attached to the DOM, but @@ -215,6 +217,15 @@ // weak reference so that it's collectable when author script has no // reference. // - Possible next states: n/a + // + // * kForciblyPurgeV8Memory + // The context is initialized and its frame is still attached to the DOM, but + // the global object is detached from the global proxy in order to drop all + // references to v8, hopefully causing all JS objects to be collected for + // memory reduction. + // There is no possible next state and the renderer process is going to be + // shut down soon. + // - Possible next states: n/a enum class Lifecycle { // v8::Context is not yet initialized. kContextIsUninitialized, @@ -225,6 +236,9 @@ kGlobalObjectIsDetached, // The context's frame is detached from the DOM. kFrameIsDetached, + // The global object (inner global) is detached from the global proxy (outer + // global), and there is no next state after this. + kForciblyPurgeV8Memory, }; WindowProxy(v8::Isolate*, Frame&, scoped_refptr<DOMWrapperWorld>);
diff --git a/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc b/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc index 35096d4..4365c73a 100644 --- a/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc +++ b/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc
@@ -33,6 +33,12 @@ entry.value->ClearForSwap(); } +void WindowProxyManager::ClearForMummification() { + window_proxy_->ClearForMummification(); + for (auto& entry : isolated_worlds_) + entry.value->ClearForMummification(); +} + void WindowProxyManager::ReleaseGlobalProxies( GlobalProxyVector& global_proxies) { DCHECK(global_proxies.IsEmpty());
diff --git a/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h b/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h index 8cbe4da..f0515f29 100644 --- a/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h +++ b/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h
@@ -29,6 +29,7 @@ void ClearForClose(); void CORE_EXPORT ClearForNavigation(); void ClearForSwap(); + void ClearForMummification(); // Global proxies are passed in a vector to maintain their order: global proxy // object for the main world is always first. This is needed to prevent bugs
diff --git a/third_party/blink/renderer/bindings/modules/v8/generated.gni b/third_party/blink/renderer/bindings/modules/v8/generated.gni index b2cf023..4bee75f 100644 --- a/third_party/blink/renderer/bindings/modules/v8/generated.gni +++ b/third_party/blink/renderer/bindings/modules/v8/generated.gni
@@ -48,6 +48,8 @@ "$bindings_modules_v8_output_dir/idb_object_store_or_idb_index.h", "$bindings_modules_v8_output_dir/idb_object_store_or_idb_index_or_idb_cursor.cc", "$bindings_modules_v8_output_dir/idb_object_store_or_idb_index_or_idb_cursor.h", + "$bindings_modules_v8_output_dir/int32_array_or_long_sequence.cc", + "$bindings_modules_v8_output_dir/int32_array_or_long_sequence.h", "$bindings_modules_v8_output_dir/long_or_constrain_long_range.cc", "$bindings_modules_v8_output_dir/long_or_constrain_long_range.h", "$bindings_modules_v8_output_dir/media_stream_track_or_string.cc",
diff --git a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc index d2b25387..40dc159 100644 --- a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc +++ b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc
@@ -40,7 +40,6 @@ #include "third_party/blink/renderer/modules/indexeddb/idb_key.h" #include "third_party/blink/renderer/modules/indexeddb/idb_key_path.h" #include "third_party/blink/renderer/modules/indexeddb/idb_value.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_key_path.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_value.h" #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" @@ -182,7 +181,7 @@ const WebString& key_path) { WebData web_data(SharedBuffer::AdoptVector(wire_bytes)); WebIDBValue web_idb_value(web_data, Vector<WebBlobInfo>()); - web_idb_value.SetInjectedPrimaryKey(WebIDBKey::CreateNumber(primary_key), + web_idb_value.SetInjectedPrimaryKey(IDBKey::CreateNumber(primary_key), WebIDBKeyPath(key_path)); std::unique_ptr<IDBValue> idb_value = web_idb_value.ReleaseIdbValue();
diff --git a/third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl b/third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl index 9331774..c4e1ea8b 100644 --- a/third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl +++ b/third_party/blink/renderer/bindings/templates/callback_function.cc.tmpl
@@ -51,22 +51,22 @@ {% if callback_function_name == 'EventHandlerNonNull' %} bool {{cpp_class}}::IsRunnableOrThrowException(IgnorePause ignore_pause) { + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptState(); + bool is_runnable = ignore_pause == IgnorePause::kIgnore ? IsCallbackFunctionRunnableIgnoringPause( - CallbackRelevantScriptState(), IncumbentScriptState()) : + callback_relevant_script_state, IncumbentScriptState()) : IsCallbackFunctionRunnable( - CallbackRelevantScriptState(), IncumbentScriptState()); + callback_relevant_script_state, IncumbentScriptState()); if (is_runnable) return true; // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context // of the callback function here. - v8::HandleScope handle_scope(GetIsolate()); - v8::Local<v8::Object> callback_object = CallbackObject(); - CHECK(!callback_object.IsEmpty()); - v8::Context::Scope context_scope(callback_object->CreationContext()); + ScriptState::Scope scope(callback_relevant_script_state); V8ThrowException::ThrowError( GetIsolate(), ExceptionMessages::FailedToExecute(
diff --git a/third_party/blink/renderer/bindings/templates/callback_interface.cc.tmpl b/third_party/blink/renderer/bindings/templates/callback_interface.cc.tmpl index 9915e883..fd7c045f 100644 --- a/third_party/blink/renderer/bindings/templates/callback_interface.cc.tmpl +++ b/third_party/blink/renderer/bindings/templates/callback_interface.cc.tmpl
@@ -111,22 +111,22 @@ {% if interface_name == 'EventListener' %} bool {{v8_class}}::IsRunnableOrThrowException(IgnorePause ignore_pause) { + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptState(); + bool is_runnable = ignore_pause == IgnorePause::kIgnore ? IsCallbackFunctionRunnableIgnoringPause( - CallbackRelevantScriptState(), IncumbentScriptState()) : + callback_relevant_script_state, IncumbentScriptState()) : IsCallbackFunctionRunnable( - CallbackRelevantScriptState(), IncumbentScriptState()); + callback_relevant_script_state, IncumbentScriptState()); if (is_runnable) return true; // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context // of the callback function here. - v8::HandleScope handle_scope(GetIsolate()); - v8::Local<v8::Object> callback_object = CallbackObject(); - CHECK(!callback_object.IsEmpty()); - v8::Context::Scope context_scope(callback_object->CreationContext()); + ScriptState::Scope scope(callback_relevant_script_state); V8ThrowException::ThrowError( GetIsolate(), ExceptionMessages::FailedToExecute(
diff --git a/third_party/blink/renderer/bindings/templates/callback_invoke.cc.tmpl b/third_party/blink/renderer/bindings/templates/callback_invoke.cc.tmpl index 647fd8a..6c5ae31b 100644 --- a/third_party/blink/renderer/bindings/templates/callback_invoke.cc.tmpl +++ b/third_party/blink/renderer/bindings/templates/callback_invoke.cc.tmpl
@@ -21,8 +21,16 @@ return_cpp_type, return_native_value_traits_tag, arguments, is_treat_non_object_as_null, bypass_runnability_check, interface_name, operation_name) %} + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "{{interface_name}}", + "{{operation_name}}"); + if (!callback_relevant_script_state) { + return v8::Nothing<{{return_cpp_type}}>(); + } + {% if not bypass_runnability_check %} - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -43,7 +51,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -109,7 +117,7 @@ // step 9.2.2. If getResult is an abrupt completion, set completion to // getResult and jump to the step labeled return. v8::Local<v8::Value> value; - if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), + if (!CallbackObject()->Get(callback_relevant_script_state->GetContext(), V8String(GetIsolate(), "{{operation_name}}")) .ToLocal(&value)) { return v8::Nothing<{{return_cpp_type}}>(); @@ -135,7 +143,7 @@ {% endif %} {# Fill |this_arg|. #} {% if invoke_or_construct == 'invoke' %} - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); {% elif interface_or_function == 'callback interface' %} if (!IsCallbackObjectCallable()) { // step 11. If value's interface is not a single operation callback @@ -146,7 +154,7 @@ // step 2. If thisArg was not given, let thisArg be undefined. this_arg = v8::Undefined(GetIsolate()); } else { - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); } {% endif %} @@ -174,7 +182,7 @@ // labeled return. {% if arguments %} v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); {% set has_variadic_argument = arguments[-1].is_variadic %} {% set non_variadic_arguments = arguments | rejectattr('is_variadic') | list %} @@ -209,7 +217,7 @@ if (!V8ScriptRunner::CallAsConstructor( GetIsolate(), function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), argc, argv).ToLocal(&call_result)) { // step 11. If callResult is an abrupt completion, set completion to @@ -220,7 +228,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv,
diff --git a/third_party/blink/renderer/bindings/tests/idls/core/test_interface.idl b/third_party/blink/renderer/bindings/tests/idls/core/test_interface.idl index 3984e133..ef4a5e46 100644 --- a/third_party/blink/renderer/bindings/tests/idls/core/test_interface.idl +++ b/third_party/blink/renderer/bindings/tests/idls/core/test_interface.idl
@@ -114,9 +114,9 @@ void voidMethodPartialOverload(double doubleArg); static void staticVoidMethodPartialOverload(); - Promise promiseMethodPartialOverload(); - Promise promiseMethodPartialOverload(Window window); - static Promise staticPromiseMethodPartialOverload(); + Promise<any> promiseMethodPartialOverload(); + Promise<any> promiseMethodPartialOverload(Window window); + static Promise<any> staticPromiseMethodPartialOverload(); void overloadMethodWithUnionTypeWithStringMember((double or DOMString) unionArg); void overloadMethodWithUnionTypeWithStringMember(boolean boolArg);
diff --git a/third_party/blink/renderer/bindings/tests/idls/core/test_object.idl b/third_party/blink/renderer/bindings/tests/idls/core/test_object.idl index 00f82f4196..d583b3c 100644 --- a/third_party/blink/renderer/bindings/tests/idls/core/test_object.idl +++ b/third_party/blink/renderer/bindings/tests/idls/core/test_object.idl
@@ -84,7 +84,7 @@ attribute SerializedScriptValue serializedScriptValueAttribute; attribute any anyAttribute; // Custom type conversions - attribute Promise promiseAttribute; + attribute Promise<any> promiseAttribute; attribute Window windowAttribute; // DOM Node types attribute Document documentAttribute; @@ -347,12 +347,12 @@ void passPermissiveDictionaryMethod([PermissiveDictionaryConversion] optional TestDictionary arg); NodeFilter nodeFilterMethod(); Promise<void> promiseMethod(long arg1, Dictionary arg2, DOMString arg3, DOMString... variadic); - Promise promiseMethodWithoutExceptionState(Dictionary arg1); + Promise<any> promiseMethodWithoutExceptionState(Dictionary arg1); SerializedScriptValue serializedScriptValueMethod(); XPathNSResolver xPathNSResolverMethod(); void voidMethodDictionaryArg(Dictionary dictionaryArg); void voidMethodNodeFilterArg(NodeFilter nodeFilterArg); - void voidMethodPromiseArg(Promise promiseArg); + void voidMethodPromiseArg(Promise<any> promiseArg); void voidMethodSerializedScriptValueArg(SerializedScriptValue serializedScriptValueArg); void voidMethodXPathNSResolverArg(XPathNSResolver xPathNSResolverArg); void voidMethodDictionarySequenceArg(sequence<Dictionary> dictionarySequenceArg); @@ -425,9 +425,9 @@ void overloadedMethodN(TestInterface testInterfaceArg); void overloadedMethodN(TestCallbackInterface testCallbackInterfaceArg); - Promise promiseOverloadMethod(); - Promise promiseOverloadMethod(Window arg1, double arg2); - Promise promiseOverloadMethod(Document arg1, double arg2); + Promise<any> promiseOverloadMethod(); + Promise<any> promiseOverloadMethod(Window arg1, double arg2); + Promise<any> promiseOverloadMethod(Document arg1, double arg2); [PerWorldBindings] void overloadedPerWorldBindingsMethod(); [PerWorldBindings] void overloadedPerWorldBindingsMethod(long longArg);
diff --git a/third_party/blink/renderer/bindings/tests/idls/modules/test_interface_partial_3.idl b/third_party/blink/renderer/bindings/tests/idls/modules/test_interface_partial_3.idl index a6507dc..9f4f19e 100644 --- a/third_party/blink/renderer/bindings/tests/idls/modules/test_interface_partial_3.idl +++ b/third_party/blink/renderer/bindings/tests/idls/modules/test_interface_partial_3.idl
@@ -36,8 +36,8 @@ void voidMethodPartialOverload(DOMString value); static void staticVoidMethodPartialOverload(DOMString value); - Promise promiseMethodPartialOverload(Document document); - static Promise staticPromiseMethodPartialOverload(DOMString value); + Promise<any> promiseMethodPartialOverload(Document document); + static Promise<any> staticPromiseMethodPartialOverload(DOMString value); void partial2VoidMethod(DOMString value); void partial2VoidMethod(Node node);
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.cc index c3e866dc..fa60843 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_any_callback_function_optional_any_arg.cc
@@ -28,7 +28,15 @@ } v8::Maybe<ScriptValue> V8AnyCallbackFunctionOptionalAnyArg::Invoke(ScriptWrappable* callback_this_value, ScriptValue optionalAnyArg) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "AnyCallbackFunctionOptionalAnyArg", + "invoke"); + if (!callback_relevant_script_state) { + return v8::Nothing<ScriptValue>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -48,7 +56,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -62,14 +70,14 @@ function = CallbackFunction(); v8::Local<v8::Value> this_arg; - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); // step: Let esArgs be the result of converting args to an ECMAScript // arguments list. If this throws an exception, set completion to the // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_optionalAnyArg = optionalAnyArg.V8Value(); constexpr int argc = 1; @@ -80,7 +88,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv, @@ -108,7 +116,15 @@ } v8::Maybe<ScriptValue> V8AnyCallbackFunctionOptionalAnyArg::Construct(ScriptValue optionalAnyArg) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "AnyCallbackFunctionOptionalAnyArg", + "construct"); + if (!callback_relevant_script_state) { + return v8::Nothing<ScriptValue>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -128,7 +144,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -161,7 +177,7 @@ // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_optionalAnyArg = optionalAnyArg.V8Value(); constexpr int argc = 1; @@ -172,7 +188,7 @@ if (!V8ScriptRunner::CallAsConstructor( GetIsolate(), function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), argc, argv).ToLocal(&call_result)) { // step 11. If callResult is an abrupt completion, set completion to
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_any_callback_function_variadic_any_args.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_any_callback_function_variadic_any_args.cc index a50c7e13..0155e9e 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_any_callback_function_variadic_any_args.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_any_callback_function_variadic_any_args.cc
@@ -28,7 +28,15 @@ } v8::Maybe<ScriptValue> V8AnyCallbackFunctionVariadicAnyArgs::Invoke(ScriptWrappable* callback_this_value, const Vector<ScriptValue>& arguments) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "AnyCallbackFunctionVariadicAnyArgs", + "invoke"); + if (!callback_relevant_script_state) { + return v8::Nothing<ScriptValue>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -48,7 +56,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -62,14 +70,14 @@ function = CallbackFunction(); v8::Local<v8::Value> this_arg; - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); // step: Let esArgs be the result of converting args to an ECMAScript // arguments list. If this throws an exception, set completion to the // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); const int argc = 0 + arguments.size(); v8::Local<v8::Value> argv[argc]; @@ -81,7 +89,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv, @@ -109,7 +117,15 @@ } v8::Maybe<ScriptValue> V8AnyCallbackFunctionVariadicAnyArgs::Construct(const Vector<ScriptValue>& arguments) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "AnyCallbackFunctionVariadicAnyArgs", + "construct"); + if (!callback_relevant_script_state) { + return v8::Nothing<ScriptValue>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -129,7 +145,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -162,7 +178,7 @@ // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); const int argc = 0 + arguments.size(); v8::Local<v8::Value> argv[argc]; @@ -174,7 +190,7 @@ if (!V8ScriptRunner::CallAsConstructor( GetIsolate(), function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), argc, argv).ToLocal(&call_result)) { // step 11. If callResult is an abrupt completion, set completion to
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_long_callback_function.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_long_callback_function.cc index b277f5582..bb50b29 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_long_callback_function.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_long_callback_function.cc
@@ -28,7 +28,15 @@ } v8::Maybe<int32_t> V8LongCallbackFunction::Invoke(ScriptWrappable* callback_this_value, int32_t num1, int32_t num2) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "LongCallbackFunction", + "invoke"); + if (!callback_relevant_script_state) { + return v8::Nothing<int32_t>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -48,7 +56,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -62,14 +70,14 @@ function = CallbackFunction(); v8::Local<v8::Value> this_arg; - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); // step: Let esArgs be the result of converting args to an ECMAScript // arguments list. If this throws an exception, set completion to the // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_num1 = v8::Integer::New(GetIsolate(), num1); v8::Local<v8::Value> v8_num2 = v8::Integer::New(GetIsolate(), num2); @@ -81,7 +89,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv,
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.cc index 57d6334..9f791d90 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_string_sequence_callback_function_long_sequence_arg.cc
@@ -28,7 +28,15 @@ } v8::Maybe<Vector<String>> V8StringSequenceCallbackFunctionLongSequenceArg::Invoke(ScriptWrappable* callback_this_value, const Vector<int32_t>& arg) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "StringSequenceCallbackFunctionLongSequenceArg", + "invoke"); + if (!callback_relevant_script_state) { + return v8::Nothing<Vector<String>>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -48,7 +56,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -62,14 +70,14 @@ function = CallbackFunction(); v8::Local<v8::Value> this_arg; - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); // step: Let esArgs be the result of converting args to an ECMAScript // arguments list. If this throws an exception, set completion to the // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_arg = ToV8(arg, argument_creation_context, GetIsolate()); constexpr int argc = 1; @@ -80,7 +88,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv,
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_callback_interface.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_callback_interface.cc index 9b5ccee..0ddc03a1a 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_callback_interface.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_callback_interface.cc
@@ -39,7 +39,15 @@ } v8::Maybe<void> V8TestCallbackInterface::voidMethod(ScriptWrappable* callback_this_value) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "TestCallbackInterface", + "voidMethod"); + if (!callback_relevant_script_state) { + return v8::Nothing<void>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -59,7 +67,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -74,7 +82,7 @@ // step 9.2.2. If getResult is an abrupt completion, set completion to // getResult and jump to the step labeled return. v8::Local<v8::Value> value; - if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), + if (!CallbackObject()->Get(callback_relevant_script_state->GetContext(), V8String(GetIsolate(), "voidMethod")) .ToLocal(&value)) { return v8::Nothing<void>(); @@ -104,7 +112,7 @@ // step 2. If thisArg was not given, let thisArg be undefined. this_arg = v8::Undefined(GetIsolate()); } else { - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); } // step: Let esArgs be the result of converting args to an ECMAScript @@ -118,7 +126,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv, @@ -134,7 +142,15 @@ } v8::Maybe<bool> V8TestCallbackInterface::booleanMethod(ScriptWrappable* callback_this_value) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "TestCallbackInterface", + "booleanMethod"); + if (!callback_relevant_script_state) { + return v8::Nothing<bool>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -154,7 +170,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -169,7 +185,7 @@ // step 9.2.2. If getResult is an abrupt completion, set completion to // getResult and jump to the step labeled return. v8::Local<v8::Value> value; - if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), + if (!CallbackObject()->Get(callback_relevant_script_state->GetContext(), V8String(GetIsolate(), "booleanMethod")) .ToLocal(&value)) { return v8::Nothing<bool>(); @@ -199,7 +215,7 @@ // step 2. If thisArg was not given, let thisArg be undefined. this_arg = v8::Undefined(GetIsolate()); } else { - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); } // step: Let esArgs be the result of converting args to an ECMAScript @@ -213,7 +229,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv, @@ -241,7 +257,15 @@ } v8::Maybe<void> V8TestCallbackInterface::voidMethodBooleanArg(ScriptWrappable* callback_this_value, bool boolArg) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "TestCallbackInterface", + "voidMethodBooleanArg"); + if (!callback_relevant_script_state) { + return v8::Nothing<void>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -261,7 +285,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -276,7 +300,7 @@ // step 9.2.2. If getResult is an abrupt completion, set completion to // getResult and jump to the step labeled return. v8::Local<v8::Value> value; - if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), + if (!CallbackObject()->Get(callback_relevant_script_state->GetContext(), V8String(GetIsolate(), "voidMethodBooleanArg")) .ToLocal(&value)) { return v8::Nothing<void>(); @@ -306,7 +330,7 @@ // step 2. If thisArg was not given, let thisArg be undefined. this_arg = v8::Undefined(GetIsolate()); } else { - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); } // step: Let esArgs be the result of converting args to an ECMAScript @@ -314,7 +338,7 @@ // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_boolArg = v8::Boolean::New(GetIsolate(), boolArg); constexpr int argc = 1; @@ -325,7 +349,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv, @@ -341,7 +365,15 @@ } v8::Maybe<void> V8TestCallbackInterface::voidMethodSequenceArg(ScriptWrappable* callback_this_value, const HeapVector<Member<TestInterfaceEmpty>>& sequenceArg) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "TestCallbackInterface", + "voidMethodSequenceArg"); + if (!callback_relevant_script_state) { + return v8::Nothing<void>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -361,7 +393,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -376,7 +408,7 @@ // step 9.2.2. If getResult is an abrupt completion, set completion to // getResult and jump to the step labeled return. v8::Local<v8::Value> value; - if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), + if (!CallbackObject()->Get(callback_relevant_script_state->GetContext(), V8String(GetIsolate(), "voidMethodSequenceArg")) .ToLocal(&value)) { return v8::Nothing<void>(); @@ -406,7 +438,7 @@ // step 2. If thisArg was not given, let thisArg be undefined. this_arg = v8::Undefined(GetIsolate()); } else { - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); } // step: Let esArgs be the result of converting args to an ECMAScript @@ -414,7 +446,7 @@ // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_sequenceArg = ToV8(sequenceArg, argument_creation_context, GetIsolate()); constexpr int argc = 1; @@ -425,7 +457,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv, @@ -441,7 +473,15 @@ } v8::Maybe<void> V8TestCallbackInterface::voidMethodFloatArg(ScriptWrappable* callback_this_value, float floatArg) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "TestCallbackInterface", + "voidMethodFloatArg"); + if (!callback_relevant_script_state) { + return v8::Nothing<void>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -461,7 +501,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -476,7 +516,7 @@ // step 9.2.2. If getResult is an abrupt completion, set completion to // getResult and jump to the step labeled return. v8::Local<v8::Value> value; - if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), + if (!CallbackObject()->Get(callback_relevant_script_state->GetContext(), V8String(GetIsolate(), "voidMethodFloatArg")) .ToLocal(&value)) { return v8::Nothing<void>(); @@ -506,7 +546,7 @@ // step 2. If thisArg was not given, let thisArg be undefined. this_arg = v8::Undefined(GetIsolate()); } else { - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); } // step: Let esArgs be the result of converting args to an ECMAScript @@ -514,7 +554,7 @@ // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_floatArg = v8::Number::New(GetIsolate(), floatArg); constexpr int argc = 1; @@ -525,7 +565,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv, @@ -541,7 +581,15 @@ } v8::Maybe<void> V8TestCallbackInterface::voidMethodTestInterfaceEmptyArg(ScriptWrappable* callback_this_value, TestInterfaceEmpty* testInterfaceEmptyArg) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "TestCallbackInterface", + "voidMethodTestInterfaceEmptyArg"); + if (!callback_relevant_script_state) { + return v8::Nothing<void>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -561,7 +609,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -576,7 +624,7 @@ // step 9.2.2. If getResult is an abrupt completion, set completion to // getResult and jump to the step labeled return. v8::Local<v8::Value> value; - if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), + if (!CallbackObject()->Get(callback_relevant_script_state->GetContext(), V8String(GetIsolate(), "voidMethodTestInterfaceEmptyArg")) .ToLocal(&value)) { return v8::Nothing<void>(); @@ -606,7 +654,7 @@ // step 2. If thisArg was not given, let thisArg be undefined. this_arg = v8::Undefined(GetIsolate()); } else { - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); } // step: Let esArgs be the result of converting args to an ECMAScript @@ -614,7 +662,7 @@ // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_testInterfaceEmptyArg = ToV8(testInterfaceEmptyArg, argument_creation_context, GetIsolate()); constexpr int argc = 1; @@ -625,7 +673,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv, @@ -641,7 +689,15 @@ } v8::Maybe<void> V8TestCallbackInterface::voidMethodTestInterfaceEmptyStringArg(ScriptWrappable* callback_this_value, TestInterfaceEmpty* testInterfaceEmptyArg, const String& stringArg) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "TestCallbackInterface", + "voidMethodTestInterfaceEmptyStringArg"); + if (!callback_relevant_script_state) { + return v8::Nothing<void>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -661,7 +717,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -676,7 +732,7 @@ // step 9.2.2. If getResult is an abrupt completion, set completion to // getResult and jump to the step labeled return. v8::Local<v8::Value> value; - if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), + if (!CallbackObject()->Get(callback_relevant_script_state->GetContext(), V8String(GetIsolate(), "voidMethodTestInterfaceEmptyStringArg")) .ToLocal(&value)) { return v8::Nothing<void>(); @@ -706,7 +762,7 @@ // step 2. If thisArg was not given, let thisArg be undefined. this_arg = v8::Undefined(GetIsolate()); } else { - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); } // step: Let esArgs be the result of converting args to an ECMAScript @@ -714,7 +770,7 @@ // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_testInterfaceEmptyArg = ToV8(testInterfaceEmptyArg, argument_creation_context, GetIsolate()); v8::Local<v8::Value> v8_stringArg = V8String(GetIsolate(), stringArg); @@ -726,7 +782,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv, @@ -742,7 +798,15 @@ } v8::Maybe<void> V8TestCallbackInterface::callbackWithThisValueVoidMethodStringArg(ScriptWrappable* callback_this_value, const String& stringArg) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "TestCallbackInterface", + "callbackWithThisValueVoidMethodStringArg"); + if (!callback_relevant_script_state) { + return v8::Nothing<void>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -762,7 +826,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -777,7 +841,7 @@ // step 9.2.2. If getResult is an abrupt completion, set completion to // getResult and jump to the step labeled return. v8::Local<v8::Value> value; - if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), + if (!CallbackObject()->Get(callback_relevant_script_state->GetContext(), V8String(GetIsolate(), "callbackWithThisValueVoidMethodStringArg")) .ToLocal(&value)) { return v8::Nothing<void>(); @@ -807,7 +871,7 @@ // step 2. If thisArg was not given, let thisArg be undefined. this_arg = v8::Undefined(GetIsolate()); } else { - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); } // step: Let esArgs be the result of converting args to an ECMAScript @@ -815,7 +879,7 @@ // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_stringArg = V8String(GetIsolate(), stringArg); constexpr int argc = 1; @@ -826,7 +890,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv, @@ -842,7 +906,15 @@ } v8::Maybe<void> V8TestCallbackInterface::customVoidMethodTestInterfaceEmptyArg(ScriptWrappable* callback_this_value, TestInterfaceEmpty* testInterfaceEmptyArg) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "TestCallbackInterface", + "customVoidMethodTestInterfaceEmptyArg"); + if (!callback_relevant_script_state) { + return v8::Nothing<void>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -862,7 +934,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -877,7 +949,7 @@ // step 9.2.2. If getResult is an abrupt completion, set completion to // getResult and jump to the step labeled return. v8::Local<v8::Value> value; - if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), + if (!CallbackObject()->Get(callback_relevant_script_state->GetContext(), V8String(GetIsolate(), "customVoidMethodTestInterfaceEmptyArg")) .ToLocal(&value)) { return v8::Nothing<void>(); @@ -907,7 +979,7 @@ // step 2. If thisArg was not given, let thisArg be undefined. this_arg = v8::Undefined(GetIsolate()); } else { - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); } // step: Let esArgs be the result of converting args to an ECMAScript @@ -915,7 +987,7 @@ // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_testInterfaceEmptyArg = ToV8(testInterfaceEmptyArg, argument_creation_context, GetIsolate()); constexpr int argc = 1; @@ -926,7 +998,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv,
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_legacy_callback_interface.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_legacy_callback_interface.cc index 954b5f45..572cfc6 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_legacy_callback_interface.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_legacy_callback_interface.cc
@@ -97,7 +97,15 @@ } v8::Maybe<uint16_t> V8TestLegacyCallbackInterface::acceptNode(ScriptWrappable* callback_this_value, Node* node) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "TestLegacyCallbackInterface", + "acceptNode"); + if (!callback_relevant_script_state) { + return v8::Nothing<uint16_t>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -117,7 +125,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -132,7 +140,7 @@ // step 9.2.2. If getResult is an abrupt completion, set completion to // getResult and jump to the step labeled return. v8::Local<v8::Value> value; - if (!CallbackObject()->Get(CallbackRelevantScriptState()->GetContext(), + if (!CallbackObject()->Get(callback_relevant_script_state->GetContext(), V8String(GetIsolate(), "acceptNode")) .ToLocal(&value)) { return v8::Nothing<uint16_t>(); @@ -162,7 +170,7 @@ // step 2. If thisArg was not given, let thisArg be undefined. this_arg = v8::Undefined(GetIsolate()); } else { - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); } // step: Let esArgs be the result of converting args to an ECMAScript @@ -170,7 +178,7 @@ // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_node = ToV8(node, argument_creation_context, GetIsolate()); constexpr int argc = 1; @@ -181,7 +189,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv,
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_treat_non_object_as_null_boolean_function.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_treat_non_object_as_null_boolean_function.cc index f5d5dee..ac079eff 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_treat_non_object_as_null_boolean_function.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_treat_non_object_as_null_boolean_function.cc
@@ -27,7 +27,15 @@ } v8::Maybe<bool> V8TreatNonObjectAsNullBooleanFunction::Invoke(ScriptWrappable* callback_this_value) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "TreatNonObjectAsNullBooleanFunction", + "invoke"); + if (!callback_relevant_script_state) { + return v8::Nothing<bool>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -47,7 +55,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -75,7 +83,7 @@ function = CallbackFunction(); v8::Local<v8::Value> this_arg; - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); // step: Let esArgs be the result of converting args to an ECMAScript // arguments list. If this throws an exception, set completion to the @@ -88,7 +96,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv,
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_treat_non_object_as_null_void_function.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_treat_non_object_as_null_void_function.cc index 110a615f..004aecc 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_treat_non_object_as_null_void_function.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_treat_non_object_as_null_void_function.cc
@@ -27,7 +27,15 @@ } v8::Maybe<void> V8TreatNonObjectAsNullVoidFunction::Invoke(ScriptWrappable* callback_this_value) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "TreatNonObjectAsNullVoidFunction", + "invoke"); + if (!callback_relevant_script_state) { + return v8::Nothing<void>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -47,7 +55,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -64,7 +72,7 @@ function = CallbackFunction(); v8::Local<v8::Value> this_arg; - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); // step: Let esArgs be the result of converting args to an ECMAScript // arguments list. If this throws an exception, set completion to the @@ -77,7 +85,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv,
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function.cc index 135cbec..b7de3e0b 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function.cc
@@ -27,7 +27,15 @@ } v8::Maybe<void> V8VoidCallbackFunction::Invoke(ScriptWrappable* callback_this_value) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "VoidCallbackFunction", + "invoke"); + if (!callback_relevant_script_state) { + return v8::Nothing<void>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -47,7 +55,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -61,7 +69,7 @@ function = CallbackFunction(); v8::Local<v8::Value> this_arg; - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); // step: Let esArgs be the result of converting args to an ECMAScript // arguments list. If this throws an exception, set completion to the @@ -74,7 +82,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv,
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.cc index b47f3dc3..6b20056 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_dictionary_arg.cc
@@ -28,7 +28,15 @@ } v8::Maybe<void> V8VoidCallbackFunctionDictionaryArg::Invoke(ScriptWrappable* callback_this_value, const TestDictionary*& arg) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "VoidCallbackFunctionDictionaryArg", + "invoke"); + if (!callback_relevant_script_state) { + return v8::Nothing<void>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -48,7 +56,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -62,14 +70,14 @@ function = CallbackFunction(); v8::Local<v8::Value> this_arg; - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); // step: Let esArgs be the result of converting args to an ECMAScript // arguments list. If this throws an exception, set completion to the // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_arg = ToV8(arg, argument_creation_context, GetIsolate()); constexpr int argc = 1; @@ -80,7 +88,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv,
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_enum_arg.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_enum_arg.cc index a9093680..be15904e 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_enum_arg.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_enum_arg.cc
@@ -28,7 +28,15 @@ } v8::Maybe<void> V8VoidCallbackFunctionEnumArg::Invoke(ScriptWrappable* callback_this_value, const String& arg) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "VoidCallbackFunctionEnumArg", + "invoke"); + if (!callback_relevant_script_state) { + return v8::Nothing<void>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -48,7 +56,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -62,7 +70,7 @@ function = CallbackFunction(); v8::Local<v8::Value> this_arg; - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); // Enum values provided by Blink must be valid, otherwise typo. #if DCHECK_IS_ON() @@ -89,7 +97,7 @@ // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_arg = V8String(GetIsolate(), arg); constexpr int argc = 1; @@ -100,7 +108,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv,
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_interface_arg.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_interface_arg.cc index f8f4e486..e58423e 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_interface_arg.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_interface_arg.cc
@@ -28,7 +28,15 @@ } v8::Maybe<void> V8VoidCallbackFunctionInterfaceArg::Invoke(ScriptWrappable* callback_this_value, HTMLDivElement* divElement) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "VoidCallbackFunctionInterfaceArg", + "invoke"); + if (!callback_relevant_script_state) { + return v8::Nothing<void>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -48,7 +56,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -62,14 +70,14 @@ function = CallbackFunction(); v8::Local<v8::Value> this_arg; - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); // step: Let esArgs be the result of converting args to an ECMAScript // arguments list. If this throws an exception, set completion to the // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_divElement = ToV8(divElement, argument_creation_context, GetIsolate()); constexpr int argc = 1; @@ -80,7 +88,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv,
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.cc index ffb2273..3a3562b 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_test_interface_sequence_arg.cc
@@ -29,7 +29,15 @@ } v8::Maybe<void> V8VoidCallbackFunctionTestInterfaceSequenceArg::Invoke(ScriptWrappable* callback_this_value, const HeapVector<Member<TestInterfaceImplementation>>& arg) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "VoidCallbackFunctionTestInterfaceSequenceArg", + "invoke"); + if (!callback_relevant_script_state) { + return v8::Nothing<void>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -49,7 +57,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -63,14 +71,14 @@ function = CallbackFunction(); v8::Local<v8::Value> this_arg; - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); // step: Let esArgs be the result of converting args to an ECMAScript // arguments list. If this throws an exception, set completion to the // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_arg = ToV8(arg, argument_creation_context, GetIsolate()); constexpr int argc = 1; @@ -81,7 +89,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv,
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_typedef.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_typedef.cc index cc01356..64d2a5d1 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_typedef.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_void_callback_function_typedef.cc
@@ -28,7 +28,15 @@ } v8::Maybe<void> V8VoidCallbackFunctionTypedef::Invoke(ScriptWrappable* callback_this_value, const String& arg) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "VoidCallbackFunctionTypedef", + "invoke"); + if (!callback_relevant_script_state) { + return v8::Nothing<void>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -48,7 +56,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -62,14 +70,14 @@ function = CallbackFunction(); v8::Local<v8::Value> this_arg; - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); // step: Let esArgs be the result of converting args to an ECMAScript // arguments list. If this throws an exception, set completion to the // completion value representing the thrown exception and jump to the step // labeled return. v8::Local<v8::Object> argument_creation_context = - CallbackRelevantScriptState()->GetContext()->Global(); + callback_relevant_script_state->GetContext()->Global(); ALLOW_UNUSED_LOCAL(argument_creation_context); v8::Local<v8::Value> v8_arg = V8String(GetIsolate(), arg); constexpr int argc = 1; @@ -80,7 +88,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv,
diff --git a/third_party/blink/renderer/bindings/tests/results/modules/v8_void_callback_function_modules.cc b/third_party/blink/renderer/bindings/tests/results/modules/v8_void_callback_function_modules.cc index 8cd929d..a0260ea 100644 --- a/third_party/blink/renderer/bindings/tests/results/modules/v8_void_callback_function_modules.cc +++ b/third_party/blink/renderer/bindings/tests/results/modules/v8_void_callback_function_modules.cc
@@ -27,7 +27,15 @@ } v8::Maybe<void> V8VoidCallbackFunctionModules::Invoke(ScriptWrappable* callback_this_value) { - if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(), + ScriptState* callback_relevant_script_state = + CallbackRelevantScriptStateOrThrowException( + "VoidCallbackFunctionModules", + "invoke"); + if (!callback_relevant_script_state) { + return v8::Nothing<void>(); + } + + if (!IsCallbackFunctionRunnable(callback_relevant_script_state, IncumbentScriptState())) { // Wrapper-tracing for the callback function makes the function object and // its creation context alive. Thus it's safe to use the creation context @@ -47,7 +55,7 @@ // step: Prepare to run script with relevant settings. ScriptState::Scope callback_relevant_context_scope( - CallbackRelevantScriptState()); + callback_relevant_script_state); // step: Prepare to run a callback with stored settings. v8::Context::BackupIncumbentScope backup_incumbent_scope( IncumbentScriptState()->GetContext()); @@ -61,7 +69,7 @@ function = CallbackFunction(); v8::Local<v8::Value> this_arg; - this_arg = ToV8(callback_this_value, CallbackRelevantScriptState()); + this_arg = ToV8(callback_this_value, callback_relevant_script_state); // step: Let esArgs be the result of converting args to an ECMAScript // arguments list. If this throws an exception, set completion to the @@ -74,7 +82,7 @@ // step: Let callResult be Call(X, thisArg, esArgs). if (!V8ScriptRunner::CallFunction( function, - ExecutionContext::From(CallbackRelevantScriptState()), + ExecutionContext::From(callback_relevant_script_state), this_arg, argc, argv,
diff --git a/third_party/blink/renderer/build/scripts/core/css/make_css_primitive_value_unit_trie.py b/third_party/blink/renderer/build/scripts/core/css/make_css_primitive_value_unit_trie.py index 316284c..318d113 100755 --- a/third_party/blink/renderer/build/scripts/core/css/make_css_primitive_value_unit_trie.py +++ b/third_party/blink/renderer/build/scripts/core/css/make_css_primitive_value_unit_trie.py
@@ -3,10 +3,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import os -import sys -sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) - import json5_generator import trie_builder import template_expander
diff --git a/third_party/blink/renderer/build/scripts/core/css/make_css_property_names.py b/third_party/blink/renderer/build/scripts/core/css/make_css_property_names.py index 5cb3e20..665487db 100755 --- a/third_party/blink/renderer/build/scripts/core/css/make_css_property_names.py +++ b/third_party/blink/renderer/build/scripts/core/css/make_css_property_names.py
@@ -1,9 +1,5 @@ #!/usr/bin/env python -import os -import sys -sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) - from core.css import css_properties import gperf import json5_generator
diff --git a/third_party/blink/renderer/build/scripts/core/css/make_css_tokenizer_codepoints.py b/third_party/blink/renderer/build/scripts/core/css/make_css_tokenizer_codepoints.py index c48d23a..a51c5917 100755 --- a/third_party/blink/renderer/build/scripts/core/css/make_css_tokenizer_codepoints.py +++ b/third_party/blink/renderer/build/scripts/core/css/make_css_tokenizer_codepoints.py
@@ -6,7 +6,6 @@ import os import sys -sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) import in_generator
diff --git a/third_party/blink/renderer/build/scripts/core/css/make_css_value_id_mappings.py b/third_party/blink/renderer/build/scripts/core/css/make_css_value_id_mappings.py index b0cdb89..f929b78 100755 --- a/third_party/blink/renderer/build/scripts/core/css/make_css_value_id_mappings.py +++ b/third_party/blink/renderer/build/scripts/core/css/make_css_value_id_mappings.py
@@ -3,10 +3,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import os -import sys -sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) - from blinkbuild.name_style_converter import NameStyleConverter import json5_generator import template_expander
diff --git a/third_party/blink/renderer/build/scripts/core/css/make_css_value_keywords.py b/third_party/blink/renderer/build/scripts/core/css/make_css_value_keywords.py index 7c08560..3110d0f 100755 --- a/third_party/blink/renderer/build/scripts/core/css/make_css_value_keywords.py +++ b/third_party/blink/renderer/build/scripts/core/css/make_css_value_keywords.py
@@ -1,10 +1,5 @@ #!/usr/bin/env python -import os -import sys -sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) - -import os.path import subprocess from name_utilities import enum_for_css_keyword import json5_generator
diff --git a/third_party/blink/renderer/build/scripts/core/css/make_cssom_types.py b/third_party/blink/renderer/build/scripts/core/css/make_cssom_types.py index 6c44db01..93e0afe1 100755 --- a/third_party/blink/renderer/build/scripts/core/css/make_cssom_types.py +++ b/third_party/blink/renderer/build/scripts/core/css/make_cssom_types.py
@@ -3,10 +3,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import os -import sys -sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) - from core.css import css_properties import json5_generator from name_utilities import enum_for_css_keyword
diff --git a/third_party/blink/renderer/build/scripts/core/css/make_media_feature_names.py b/third_party/blink/renderer/build/scripts/core/css/make_media_feature_names.py index 5f1ad9c..e58585b9 100755 --- a/third_party/blink/renderer/build/scripts/core/css/make_media_feature_names.py +++ b/third_party/blink/renderer/build/scripts/core/css/make_media_feature_names.py
@@ -4,10 +4,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import os -import sys -sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) - import json5_generator import make_names import media_feature_symbol
diff --git a/third_party/blink/renderer/build/scripts/core/css/make_media_features.py b/third_party/blink/renderer/build/scripts/core/css/make_media_features.py index fcf89d7d..8d3d09c0 100755 --- a/third_party/blink/renderer/build/scripts/core/css/make_media_features.py +++ b/third_party/blink/renderer/build/scripts/core/css/make_media_features.py
@@ -4,10 +4,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import os -import sys -sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) - from blinkbuild.name_style_converter import NameStyleConverter import media_feature_symbol import json5_generator
diff --git a/third_party/blink/renderer/build/scripts/core/css/make_style_shorthands.py b/third_party/blink/renderer/build/scripts/core/css/make_style_shorthands.py index 060d2f3..a166b36 100755 --- a/third_party/blink/renderer/build/scripts/core/css/make_style_shorthands.py +++ b/third_party/blink/renderer/build/scripts/core/css/make_style_shorthands.py
@@ -27,10 +27,6 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import os -import sys -sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) - from core.css import css_properties from collections import defaultdict import json5_generator
diff --git a/third_party/blink/renderer/build/scripts/core/css/parser/make_atrule_names.py b/third_party/blink/renderer/build/scripts/core/css/parser/make_atrule_names.py index 2715f4d..2a7d6365 100755 --- a/third_party/blink/renderer/build/scripts/core/css/parser/make_atrule_names.py +++ b/third_party/blink/renderer/build/scripts/core/css/parser/make_atrule_names.py
@@ -3,10 +3,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import os -import sys -sys.path.append(os.path.join(os.path.dirname(__file__), '../../..')) - import gperf import json5_generator import template_expander
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_base.py b/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_base.py index 8399000b..637bc3a 100755 --- a/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_base.py +++ b/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_base.py
@@ -3,10 +3,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import os -import sys -sys.path.append(os.path.join(os.path.dirname(__file__), '../../..')) - import json5_generator import template_expander
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_subclasses.py b/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_subclasses.py index 6f8788f..3899bd6 100755 --- a/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_subclasses.py +++ b/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_subclasses.py
@@ -3,9 +3,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import os import sys -sys.path.append(os.path.join(os.path.dirname(__file__), '../../..')) import json5_generator import template_expander
diff --git a/third_party/blink/renderer/build/scripts/core/style/make_computed_style_base.py b/third_party/blink/renderer/build/scripts/core/style/make_computed_style_base.py index 21dbfa4c..1f248f9 100755 --- a/third_party/blink/renderer/build/scripts/core/style/make_computed_style_base.py +++ b/third_party/blink/renderer/build/scripts/core/style/make_computed_style_base.py
@@ -3,10 +3,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import os -import sys -sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) - import math import json5_generator
diff --git a/third_party/blink/renderer/build/scripts/core/style/make_computed_style_initial_values.py b/third_party/blink/renderer/build/scripts/core/style/make_computed_style_initial_values.py index c2627b20..c596a09e 100755 --- a/third_party/blink/renderer/build/scripts/core/style/make_computed_style_initial_values.py +++ b/third_party/blink/renderer/build/scripts/core/style/make_computed_style_initial_values.py
@@ -3,10 +3,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import os -import sys -sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) - import json5_generator import template_expander
diff --git a/third_party/blink/renderer/build/scripts/run_with_pythonpath.py b/third_party/blink/renderer/build/scripts/run_with_pythonpath.py new file mode 100755 index 0000000..9da708d0 --- /dev/null +++ b/third_party/blink/renderer/build/scripts/run_with_pythonpath.py
@@ -0,0 +1,27 @@ +#!/usr/bin/env python +# 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. + +import os +import subprocess +import sys + + +# python run_with_pythonpath.py -I path1 ... -I pathN foo/bar/baz.py args... +# ==> Run "python foo/bar/baz.py args..." with PYTHONPATH=path1:..:pathN +def main(): + python_paths = [] + args = sys.argv[1:] + while len(args) >= 2 and args[0] == '-I': + python_paths.append(args[1]) + args = args[2:] + + env = os.environ.copy() + if len(python_paths) > 0: + existing_pp = (os.pathsep + env['PYTHONPATH']) if 'PYTHONPATH' in env else '' + env['PYTHONPATH'] = os.pathsep.join(python_paths) + existing_pp + sys.exit(subprocess.call([sys.executable] + args, env=env)) + +if __name__ == '__main__': + main()
diff --git a/third_party/blink/renderer/build/scripts/scripts.gni b/third_party/blink/renderer/build/scripts/scripts.gni index eac21781..f5b360f 100644 --- a/third_party/blink/renderer/build/scripts/scripts.gni +++ b/third_party/blink/renderer/build/scripts/scripts.gni
@@ -82,6 +82,34 @@ "//third_party/blink/renderer/core:core_event_interfaces", ] +# A wrapper for python scripts. This adds the following paths to PYTHONPATH, +# then run invoker.script. +# - //third_party/blink/renderer/build/scripts +# - //third_party +template("blink_python_runner") { + action(target_name) { + script = "$_scripts_dir/run_with_pythonpath.py" + inputs = [ + invoker.script, + ] + if (defined(invoker.inputs)) { + inputs += invoker.inputs + } + outputs = invoker.outputs + args = [ + "-I", + rebase_path(_scripts_dir, root_build_dir), + "-I", + rebase_path("//third_party", root_build_dir), + rebase_path(invoker.script, root_build_dir), + ] + invoker.args + if (defined(invoker.deps)) { + deps = invoker.deps + } + forward_variables_from(invoker, [ "visibility" ]) + } +} + # TODO(crbug.com/732657): Remove this once everything that uses this switches over to # the 'code_generator' template instead. # Template to run most of scripts that process "*.json5" files. @@ -97,7 +125,7 @@ # deps [optional]: # Depenendencies. If unspecified defaults to make_core_generated_deps. template("process_json5_files") { - action(target_name) { + blink_python_runner(target_name) { script = invoker.script inputs = invoker.in_files @@ -146,7 +174,7 @@ # deps [optional]: # Depenendencies. If unspecified defaults to make_core_generated_deps. template("code_generator") { - action(target_name) { + blink_python_runner(target_name) { script = invoker.script inputs = invoker.json_inputs + invoker.templates + scripts_for_json5_files if (defined(invoker.other_inputs)) {
diff --git a/third_party/blink/renderer/build/scripts/template_expander.py b/third_party/blink/renderer/build/scripts/template_expander.py index 339e2ab3..2cf3ad6a 100644 --- a/third_party/blink/renderer/build/scripts/template_expander.py +++ b/third_party/blink/renderer/build/scripts/template_expander.py
@@ -29,10 +29,6 @@ import os import sys -_current_dir = os.path.dirname(os.path.realpath(__file__)) -# jinja2 is in chromium's third_party directory -# Insert at front to override system libraries, and after path[0] == script dir -sys.path.insert(1, os.path.join(_current_dir, *([os.pardir] * 4))) import jinja2 @@ -43,8 +39,9 @@ template = template_cache.get(template_path, None) if template is None: + current_dir = os.path.dirname(os.path.realpath(__file__)) jinja_env = jinja2.Environment( - loader=jinja2.FileSystemLoader(_current_dir), + loader=jinja2.FileSystemLoader(current_dir), keep_trailing_newline=True, # newline-terminate generated files lstrip_blocks=True, # so can indent control flow tags trim_blocks=True) # so don't need {%- -%} everywhere
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index 3988dd7..072a710d 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -383,7 +383,7 @@ ] } -action("generated_settings_macros") { +blink_python_runner("generated_settings_macros") { script = "../build/scripts/make_settings.py" inputs = scripts_for_json5_files + [ @@ -402,7 +402,7 @@ ] } -action("generated_testing_idls_settings") { +blink_python_runner("generated_testing_idls_settings") { script = "../build/scripts/make_internal_settings.py" inputs = scripts_for_json5_files + [ @@ -426,7 +426,7 @@ ] } -action("generated_testing_idls_internal_runtime_flags") { +blink_python_runner("generated_testing_idls_internal_runtime_flags") { script = "../build/scripts/make_internal_runtime_flags.py" inputs = scripts_for_json5_files + [ @@ -1416,7 +1416,7 @@ deps = make_core_generated_deps } -action("make_core_generated_css_tokenizer_codepoints") { +blink_python_runner("make_core_generated_css_tokenizer_codepoints") { visibility = [] # Allow re-assignment of list. visibility = [ ":*" ] script = "../build/scripts/core/css/make_css_tokenizer_codepoints.py" @@ -1439,7 +1439,7 @@ deps = make_core_generated_deps } -action("make_core_generated_css_primitive_value_unit_trie") { +blink_python_runner("make_core_generated_css_primitive_value_unit_trie") { visibility = [] # Allow re-assignment of list. visibility = [ ":*" ] script = "../build/scripts/core/css/make_css_primitive_value_unit_trie.py" @@ -1468,7 +1468,7 @@ deps = make_core_generated_deps } -action("make_core_generated_html_element_lookup_trie") { +blink_python_runner("make_core_generated_html_element_lookup_trie") { visibility = [] # Allow re-assignment of list. visibility = [ ":*" ] script = "../build/scripts/make_element_lookup_trie.py" @@ -1499,7 +1499,7 @@ deps = make_core_generated_deps } -action("make_core_generated_origin_trials") { +blink_python_runner("make_core_generated_origin_trials") { script = "../build/scripts/make_origin_trials.py" inputs = scripts_for_json5_files + [ @@ -1525,7 +1525,7 @@ ] } } -action("make_core_generated_web_origin_trials") { +blink_python_runner("make_core_generated_web_origin_trials") { script = "../build/scripts/make_web_origin_trials.py" inputs = scripts_for_json5_files + [
diff --git a/third_party/blink/renderer/core/DEPS b/third_party/blink/renderer/core/DEPS index fb8bd8e..bfc6022 100644 --- a/third_party/blink/renderer/core/DEPS +++ b/third_party/blink/renderer/core/DEPS
@@ -39,6 +39,7 @@ "+services/network/public/cpp/features.h", "+services/network/public/cpp/shared_url_loader_factory.h", "+services/resource_coordinator/public/cpp/resource_coordinator_features.h", + "+services/resource_coordinator/public/mojom/coordination_unit.mojom-blink.h", "+services/service_manager/public", "+services/ws/public/mojom/ime/ime.mojom-shared.h", "+skia/public/interfaces/bitmap_skbitmap_struct_traits.h",
diff --git a/third_party/blink/renderer/core/OWNERS b/third_party/blink/renderer/core/OWNERS index 50bd98e..7337f28e 100644 --- a/third_party/blink/renderer/core/OWNERS +++ b/third_party/blink/renderer/core/OWNERS
@@ -13,7 +13,6 @@ # dtapuska reviews input-related changes dtapuska@chromium.org dgozman@chromium.org -dominicc@chromium.org # drott reviews font specific changes. drott@chromium.org dsinclair@chromium.org
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc index 9b78c1b..d27d062c 100644 --- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc +++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -464,7 +464,8 @@ LocalFrame* GetFrame() const { return helper_.LocalMainFrame()->GetFrame(); } void BeginFrame() { - helper_.GetWebView()->BeginFrame(WTF::CurrentTimeTicks()); + helper_.GetWebView()->MainFrameWidget()->BeginFrame( + WTF::CurrentTimeTicks()); } void ForceFullCompositingUpdate() {
diff --git a/third_party/blink/renderer/core/aom/computed_accessible_node.idl b/third_party/blink/renderer/core/aom/computed_accessible_node.idl index e8b62928..803e1c5 100644 --- a/third_party/blink/renderer/core/aom/computed_accessible_node.idl +++ b/third_party/blink/renderer/core/aom/computed_accessible_node.idl
@@ -49,5 +49,5 @@ readonly attribute ComputedAccessibleNode? previousSibling; readonly attribute ComputedAccessibleNode? nextSibling; - [CallWith=ScriptState] Promise ensureUpToDate(); + [CallWith=ScriptState] Promise<any> ensureUpToDate(); };
diff --git a/third_party/blink/renderer/core/clipboard/data_transfer.cc b/third_party/blink/renderer/core/clipboard/data_transfer.cc index d020720..9f2e9745 100644 --- a/third_party/blink/renderer/core/clipboard/data_transfer.cc +++ b/third_party/blink/renderer/core/clipboard/data_transfer.cc
@@ -349,12 +349,7 @@ } void DataTransfer::ClearDragImage() { - if (!CanSetDragImage()) - return; - - drag_image_ = nullptr; - drag_loc_ = IntPoint(); - drag_image_element_ = nullptr; + setDragImage(nullptr, nullptr, IntPoint()); } void DataTransfer::SetDragImageResource(ImageResourceContent* img,
diff --git a/third_party/blink/renderer/core/clipboard/system_clipboard.cc b/third_party/blink/renderer/core/clipboard/system_clipboard.cc index e35c5269..038e828 100644 --- a/third_party/blink/renderer/core/clipboard/system_clipboard.cc +++ b/third_party/blink/renderer/core/clipboard/system_clipboard.cc
@@ -223,9 +223,7 @@ HashMap<String, String> custom_data; WebDragData data = data_object->ToWebDragData(); - const WebVector<WebDragData::Item>& item_list = data.Items(); - for (size_t i = 0; i < item_list.size(); ++i) { - const WebDragData::Item& item = item_list[i]; + for (const WebDragData::Item& item : data.Items()) { if (item.storage_type == WebDragData::Item::kStorageTypeString) { if (item.string_type == blink::kMimeTypeTextPlain) { clipboard_->WriteText(mojom::ClipboardBuffer::kStandard, @@ -254,7 +252,7 @@ return true; #else // Chrome OS and non-X11 unix builds do not support - // the X selection clipboad. + // the X selection clipboard. // TODO: remove the need for this case, see http://crbug.com/361753 return false; #endif
diff --git a/third_party/blink/renderer/core/css/css_property_name.h b/third_party/blink/renderer/core/css/css_property_name.h index 9a23041..e7c2433c 100644 --- a/third_party/blink/renderer/core/css/css_property_name.h +++ b/third_party/blink/renderer/core/css/css_property_name.h
@@ -5,8 +5,10 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_NAME_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_NAME_H_ +#include "base/optional.h" #include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" +#include "third_party/blink/renderer/platform/wtf/vector_traits.h" namespace blink { @@ -28,6 +30,15 @@ DCHECK(!custom_property_name.IsNull()); } + static base::Optional<CSSPropertyName> From(const String& value) { + const CSSPropertyID property_id = cssPropertyID(value); + if (property_id == CSSPropertyInvalid) + return base::nullopt; + if (property_id == CSSPropertyVariable) + return base::make_optional(CSSPropertyName(AtomicString(value))); + return base::make_optional(CSSPropertyName(property_id)); + } + bool operator==(const CSSPropertyName&) const; bool operator!=(const CSSPropertyName& other) const { return !(*this == other); @@ -46,4 +57,6 @@ } // namespace blink +WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::CSSPropertyName); + #endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PROPERTY_NAME_H_
diff --git a/third_party/blink/renderer/core/css/css_property_name_test.cc b/third_party/blink/renderer/core/css/css_property_name_test.cc index a2885e1..763e88b 100644 --- a/third_party/blink/renderer/core/css/css_property_name_test.cc +++ b/third_party/blink/renderer/core/css/css_property_name_test.cc
@@ -37,4 +37,14 @@ CSSPropertyName(CSSPropertyBackgroundColor)); } +TEST(CSSPropertyNameTest, From) { + EXPECT_TRUE(CSSPropertyName::From("color")); + EXPECT_TRUE(CSSPropertyName::From("--x")); + EXPECT_FALSE(CSSPropertyName::From("notaproperty")); + EXPECT_FALSE(CSSPropertyName::From("-not-a-property")); + + EXPECT_EQ(*CSSPropertyName::From("color"), CSSPropertyName(CSSPropertyColor)); + EXPECT_EQ(*CSSPropertyName::From("--x"), CSSPropertyName("--x")); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc b/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc index e7c767f..303d6d78 100644 --- a/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc +++ b/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc
@@ -175,8 +175,11 @@ .size(); } -bool ComputedStylePropertyMap::ComparePropertyNames(const String& a, - const String& b) { +bool ComputedStylePropertyMap::ComparePropertyNames( + const CSSPropertyName& name_a, + const CSSPropertyName& name_b) { + AtomicString a = name_a.ToAtomicString(); + AtomicString b = name_b.ToAtomicString(); if (a.StartsWith("--")) return b.StartsWith("--") && WTF::CodePointCompareLessThan(a, b); if (a.StartsWith("-")) { @@ -259,7 +262,7 @@ // Have to sort by all properties by code point, so we have to store // them in a buffer first. - HeapVector<std::pair<AtomicString, Member<const CSSValue>>> values; + HeapVector<std::pair<CSSPropertyName, Member<const CSSValue>>> values; for (const CSSProperty* property : CSSComputedStyleDeclaration::ComputableProperties()) { DCHECK(property); @@ -267,7 +270,7 @@ const CSSValue* value = property->CSSValueFromComputedStyle( *style, nullptr /* layout_object */, StyledNode(), false); if (value) - values.emplace_back(property->GetPropertyNameAtomicString(), value); + values.emplace_back(CSSPropertyName(property->PropertyID()), value); } PropertyRegistry* registry = @@ -275,7 +278,7 @@ for (const auto& name_value : ComputedStyleCSSValueMapping::GetVariables(*style, registry)) { - values.emplace_back(name_value.key, name_value.value); + values.emplace_back(CSSPropertyName(name_value.key), name_value.value); } std::sort(values.begin(), values.end(), [](const auto& a, const auto& b) {
diff --git a/third_party/blink/renderer/core/css/cssom/computed_style_property_map.h b/third_party/blink/renderer/core/css/cssom/computed_style_property_map.h index 4c4a4cd1..0bcd9f97 100644 --- a/third_party/blink/renderer/core/css/cssom/computed_style_property_map.h +++ b/third_party/blink/renderer/core/css/cssom/computed_style_property_map.h
@@ -44,7 +44,8 @@ // ComputedStylePropertyMap needs to be sorted. This puts CSS properties // first, then prefixed properties, then custom properties. Everything is // sorted by code point within each category. - static bool ComparePropertyNames(const String&, const String&); + static bool ComparePropertyNames(const CSSPropertyName&, + const CSSPropertyName&); protected: const CSSValue* GetProperty(CSSPropertyID) override;
diff --git a/third_party/blink/renderer/core/css/cssom/declared_style_property_map.cc b/third_party/blink/renderer/core/css/cssom/declared_style_property_map.cc index 1856f7f..7727b70 100644 --- a/third_party/blink/renderer/core/css/cssom/declared_style_property_map.cc +++ b/third_party/blink/renderer/core/css/cssom/declared_style_property_map.cc
@@ -100,15 +100,7 @@ const CSSPropertyValueSet& declared_style_set = GetStyleRule()->Properties(); for (unsigned i = 0; i < declared_style_set.PropertyCount(); i++) { const auto& property_reference = declared_style_set.PropertyAt(i); - if (property_reference.Id() == CSSPropertyVariable) { - const auto& decl = - ToCSSCustomPropertyDeclaration(property_reference.Value()); - callback(decl.GetName(), property_reference.Value()); - } else { - const CSSProperty& property = CSSProperty::Get(property_reference.Id()); - callback(property.GetPropertyNameAtomicString(), - property_reference.Value()); - } + callback(property_reference.Name(), property_reference.Value()); } }
diff --git a/third_party/blink/renderer/core/css/cssom/inline_style_property_map.cc b/third_party/blink/renderer/core/css/cssom/inline_style_property_map.cc index 65e9ed9..048930d 100644 --- a/third_party/blink/renderer/core/css/cssom/inline_style_property_map.cc +++ b/third_party/blink/renderer/core/css/cssom/inline_style_property_map.cc
@@ -74,14 +74,7 @@ owner_element_->EnsureMutableInlineStyle(); for (unsigned i = 0; i < inline_style_set.PropertyCount(); i++) { const auto& property_reference = inline_style_set.PropertyAt(i); - if (property_reference.Id() == CSSPropertyVariable) { - const auto& decl = - ToCSSCustomPropertyDeclaration(property_reference.Value()); - callback(decl.GetName(), property_reference.Value()); - } else { - callback(property_reference.Property().GetPropertyNameAtomicString(), - property_reference.Value()); - } + callback(property_reference.Name(), property_reference.Value()); } }
diff --git a/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc b/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc index 310444d99..375abfb 100644 --- a/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc +++ b/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc
@@ -96,17 +96,16 @@ const IterationCallback& callback) { // Have to sort by all properties by code point, so we have to store // them in a buffer first. - HeapVector<std::pair<AtomicString, Member<const CSSValue>>> values; + HeapVector<std::pair<CSSPropertyName, Member<const CSSValue>>> values; for (const auto& entry : native_values_) { DCHECK(entry.value); - values.emplace_back( - CSSProperty::Get(entry.key).GetPropertyNameAtomicString(), entry.value); + values.emplace_back(CSSPropertyName(entry.key), entry.value); } for (const auto& entry : custom_values_) { DCHECK(entry.value); - values.emplace_back(entry.key, entry.value); + values.emplace_back(CSSPropertyName(entry.key), entry.value); } std::sort(values.begin(), values.end(), [](const auto& a, const auto& b) {
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map.cc b/third_party/blink/renderer/core/css/cssom/style_property_map.cc index 3994c6a..6f86a084 100644 --- a/third_party/blink/renderer/core/css/cssom/style_property_map.cc +++ b/third_party/blink/renderer/core/css/cssom/style_property_map.cc
@@ -5,6 +5,7 @@ #include "third_party/blink/renderer/core/css/cssom/style_property_map.h" #include "third_party/blink/renderer/core/css/css_identifier_value.h" +#include "third_party/blink/renderer/core/css/css_property_name.h" #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/css/css_value_pair.h" #include "third_party/blink/renderer/core/css/cssom/css_style_value.h" @@ -443,7 +444,7 @@ GetCustomProperty(*execution_context, custom_property_name)) { DCHECK(css_value->IsValueList()); style_values = StyleValueFactory::CssValueToStyleValueVector( - property_id, custom_property_name, *css_value); + CSSPropertyName(custom_property_name), *css_value); } // Append incoming CSSStyleValues:
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc index 094400f..7af8d2088 100644 --- a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc +++ b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc
@@ -5,6 +5,7 @@ #include "third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h" #include "third_party/blink/renderer/core/css/css_custom_property_declaration.h" +#include "third_party/blink/renderer/core/css/css_property_name.h" #include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_value_list.h" #include "third_party/blink/renderer/core/css/css_variable_reference_value.h" @@ -61,52 +62,47 @@ const ExecutionContext* execution_context, const String& property_name, ExceptionState& exception_state) { - const CSSPropertyID property_id = cssPropertyID(property_name); - if (property_id == CSSPropertyInvalid) { + base::Optional<CSSPropertyName> name = CSSPropertyName::From(property_name); + + if (!name) { exception_state.ThrowTypeError("Invalid propertyName: " + property_name); return nullptr; } - DCHECK(isValidCSSPropertyID(property_id)); - const CSSProperty& property = CSSProperty::Get(property_id); + const CSSProperty& property = CSSProperty::Get(name->Id()); if (property.IsShorthand()) return GetShorthandProperty(property); - AtomicString custom_property_name = property_id == CSSPropertyVariable - ? AtomicString(property_name) - : g_null_atom; - const CSSValue* value = - (property_id == CSSPropertyVariable) - ? GetCustomProperty(*execution_context, custom_property_name) - : GetProperty(property_id); + (name->IsCustomProperty()) + ? GetCustomProperty(*execution_context, name->ToAtomicString()) + : GetProperty(name->Id()); if (!value) return nullptr; // Custom properties count as repeated whenever we have a CSSValueList. if (property.IsRepeated() || - (property_id == CSSPropertyVariable && value->IsValueList())) { - CSSStyleValueVector values = StyleValueFactory::CssValueToStyleValueVector( - property_id, custom_property_name, *value); + (name->IsCustomProperty() && value->IsValueList())) { + CSSStyleValueVector values = + StyleValueFactory::CssValueToStyleValueVector(*name, *value); return values.IsEmpty() ? nullptr : values[0]; } - return StyleValueFactory::CssValueToStyleValue(property_id, - custom_property_name, *value); + return StyleValueFactory::CssValueToStyleValue(*name, *value); } CSSStyleValueVector StylePropertyMapReadOnlyMainThread::getAll( const ExecutionContext* execution_context, const String& property_name, ExceptionState& exception_state) { - CSSPropertyID property_id = cssPropertyID(property_name); - if (property_id == CSSPropertyInvalid) { + base::Optional<CSSPropertyName> name = CSSPropertyName::From(property_name); + + if (!name) { exception_state.ThrowTypeError("Invalid propertyName: " + property_name); return CSSStyleValueVector(); } - DCHECK(isValidCSSPropertyID(property_id)); - const CSSProperty& property = CSSProperty::Get(property_id); + const CSSProperty& property = CSSProperty::Get(name->Id()); if (property.IsShorthand()) { CSSStyleValueVector values; if (CSSStyleValue* value = GetShorthandProperty(property)) @@ -114,19 +110,14 @@ return values; } - AtomicString custom_property_name = property_id == CSSPropertyVariable - ? AtomicString(property_name) - : g_null_atom; - const CSSValue* value = - (property_id == CSSPropertyVariable) - ? GetCustomProperty(*execution_context, custom_property_name) - : GetProperty(property_id); + (name->IsCustomProperty()) + ? GetCustomProperty(*execution_context, name->ToAtomicString()) + : GetProperty(name->Id()); if (!value) return CSSStyleValueVector(); - return StyleValueFactory::CssValueToStyleValueVector( - property_id, custom_property_name, *value); + return StyleValueFactory::CssValueToStyleValueVector(*name, *value); } bool StylePropertyMapReadOnlyMainThread::has( @@ -156,26 +147,22 @@ const ExecutionContext& execution_context = *ExecutionContext::From(script_state); - ForEachProperty([&result, &execution_context](const String& property_name, + ForEachProperty([&result, &execution_context](const CSSPropertyName& name, const CSSValue& css_value) { - const auto property_id = cssPropertyID(property_name); - const CSSValue* value = &css_value; - AtomicString custom_property_name = g_null_atom; - if (property_id == CSSPropertyVariable) { - custom_property_name = AtomicString(property_name); - + // TODO(andruud): Refactor this. ForEachProperty should yield the correct, + // already-parsed value in the first place. + if (name.IsCustomProperty()) { const auto* document = DynamicTo<Document>(execution_context); if (document) { value = PropertyRegistry::ParseIfRegistered( - *document, custom_property_name, value); + *document, name.ToAtomicString(), value); } } - auto values = StyleValueFactory::CssValueToStyleValueVector( - property_id, custom_property_name, *value); - result.emplace_back(property_name, std::move(values)); + auto values = StyleValueFactory::CssValueToStyleValueVector(name, *value); + result.emplace_back(name.ToAtomicString(), std::move(values)); }); return MakeGarbageCollected<StylePropertyMapIterationSource>(result);
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h index dab11e66..0acda91 100644 --- a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h +++ b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h
@@ -10,6 +10,7 @@ namespace blink { class CSSProperty; +class CSSPropertyName; class CORE_EXPORT StylePropertyMapReadOnlyMainThread : public StylePropertyMapReadOnly { @@ -37,7 +38,7 @@ virtual const CSSValue* GetCustomProperty(AtomicString) = 0; using IterationCallback = - std::function<void(const AtomicString&, const CSSValue&)>; + std::function<void(const CSSPropertyName&, const CSSValue&)>; virtual void ForEachProperty(const IterationCallback&) = 0; virtual String SerializationForShorthand(const CSSProperty&) = 0;
diff --git a/third_party/blink/renderer/core/css/cssom/style_value_factory.cc b/third_party/blink/renderer/core/css/cssom/style_value_factory.cc index 0ac70dd..73d9f24f 100644 --- a/third_party/blink/renderer/core/css/cssom/style_value_factory.cc +++ b/third_party/blink/renderer/core/css/cssom/style_value_factory.cc
@@ -229,15 +229,9 @@ return CreateStyleValue(value); } -CSSStyleValueVector UnsupportedCSSValue( - CSSPropertyID property_id, - const AtomicString& custom_property_name, - const CSSValue& value) { - DCHECK_EQ(property_id == CSSPropertyVariable, !custom_property_name.IsNull()); +CSSStyleValueVector UnsupportedCSSValue(const CSSPropertyName& name, + const CSSValue& value) { CSSStyleValueVector style_value_vector; - auto name = (property_id == CSSPropertyVariable) - ? CSSPropertyName(custom_property_name) - : CSSPropertyName(property_id); style_value_vector.push_back(CSSUnsupportedStyleValue::Create(name, value)); return style_value_vector; } @@ -263,7 +257,7 @@ StyleRule::RuleType::kStyle)) { if (parsed_properties.size() == 1) { const auto result = StyleValueFactory::CssValueToStyleValueVector( - parsed_properties[0].Id(), g_null_atom, + CSSPropertyName(parsed_properties[0].Id()), *parsed_properties[0].Value()); // TODO(801935): Handle list-valued properties. if (result.size() == 1U) @@ -287,7 +281,7 @@ return CSSStyleValueVector(); return StyleValueFactory::CssValueToStyleValueVector( - property_id, custom_property_name, *value); + CSSPropertyName(custom_property_name), *value); } if ((property_id == CSSPropertyVariable && !tokens.IsEmpty()) || @@ -305,19 +299,13 @@ } CSSStyleValue* StyleValueFactory::CssValueToStyleValue( - CSSPropertyID property_id, - const AtomicString& custom_property_name, + const CSSPropertyName& name, const CSSValue& css_value) { - DCHECK(!CSSProperty::Get(property_id).IsRepeated()); - DCHECK_EQ(property_id == CSSPropertyVariable, !custom_property_name.IsNull()); + DCHECK(!CSSProperty::Get(name.Id()).IsRepeated()); CSSStyleValue* style_value = - CreateStyleValueWithProperty(property_id, css_value); - if (!style_value) { - auto name = (property_id == CSSPropertyVariable) - ? CSSPropertyName(custom_property_name) - : CSSPropertyName(property_id); + CreateStyleValueWithProperty(name.Id(), css_value); + if (!style_value) return CSSUnsupportedStyleValue::Create(name, css_value); - } return style_value; } @@ -354,12 +342,11 @@ } CSSStyleValueVector StyleValueFactory::CssValueToStyleValueVector( - CSSPropertyID property_id, - const AtomicString& custom_property_name, + const CSSPropertyName& name, const CSSValue& css_value) { - DCHECK_EQ(property_id == CSSPropertyVariable, !custom_property_name.IsNull()); CSSStyleValueVector style_value_vector; + CSSPropertyID property_id = name.Id(); CSSStyleValue* style_value = CreateStyleValueWithProperty(property_id, css_value); if (style_value) { @@ -380,7 +367,7 @@ // https://github.com/w3c/css-houdini-drafts/issues/290 (property_id == CSSPropertyVariable && CSSTransformComponent::FromCSSValue(css_value))) { - return UnsupportedCSSValue(property_id, custom_property_name, css_value); + return UnsupportedCSSValue(name, css_value); } // We assume list-valued properties are always stored as a list. @@ -388,7 +375,7 @@ for (const CSSValue* inner_value : css_value_list) { style_value = CreateStyleValueWithProperty(property_id, *inner_value); if (!style_value) - return UnsupportedCSSValue(property_id, custom_property_name, css_value); + return UnsupportedCSSValue(name, css_value); style_value_vector.push_back(style_value); } return style_value_vector;
diff --git a/third_party/blink/renderer/core/css/cssom/style_value_factory.h b/third_party/blink/renderer/core/css/cssom/style_value_factory.h index 87f70fb..97e73500 100644 --- a/third_party/blink/renderer/core/css/cssom/style_value_factory.h +++ b/third_party/blink/renderer/core/css/cssom/style_value_factory.h
@@ -14,6 +14,7 @@ class CSSParserContext; class CSSProperty; +class CSSPropertyName; class CSSValue; class ExecutionContext; class PropertyRegistration; @@ -28,14 +29,10 @@ const PropertyRegistration*, const String&, const CSSParserContext*); - static CSSStyleValue* CssValueToStyleValue( - CSSPropertyID, - const AtomicString& custom_property_name, - const CSSValue&); - static CSSStyleValueVector CssValueToStyleValueVector( - CSSPropertyID, - const AtomicString& custom_property_name, - const CSSValue&); + static CSSStyleValue* CssValueToStyleValue(const CSSPropertyName&, + const CSSValue&); + static CSSStyleValueVector CssValueToStyleValueVector(const CSSPropertyName&, + const CSSValue&); // Returns an empty vector on error conditions. static CSSStyleValueVector CoerceStyleValuesOrStrings( const CSSProperty& property,
diff --git a/third_party/blink/renderer/core/css/media_values_dynamic.cc b/third_party/blink/renderer/core/css/media_values_dynamic.cc index 6d8ad635..512f184 100644 --- a/third_party/blink/renderer/core/css/media_values_dynamic.cc +++ b/third_party/blink/renderer/core/css/media_values_dynamic.cc
@@ -52,17 +52,17 @@ bool MediaValuesDynamic::ComputeLength(double value, CSSPrimitiveValue::UnitType type, int& result) const { - return MediaValues::ComputeLength( - value, type, CalculateDefaultFontSize(frame_), - CalculateViewportWidth(frame_), CalculateViewportHeight(frame_), result); + return MediaValues::ComputeLength(value, type, + CalculateDefaultFontSize(frame_), + ViewportWidth(), ViewportHeight(), result); } bool MediaValuesDynamic::ComputeLength(double value, CSSPrimitiveValue::UnitType type, double& result) const { - return MediaValues::ComputeLength( - value, type, CalculateDefaultFontSize(frame_), - CalculateViewportWidth(frame_), CalculateViewportHeight(frame_), result); + return MediaValues::ComputeLength(value, type, + CalculateDefaultFontSize(frame_), + ViewportWidth(), ViewportHeight(), result); } double MediaValuesDynamic::ViewportWidth() const {
diff --git a/third_party/blink/renderer/core/css/style_sheet_contents.cc b/third_party/blink/renderer/core/css/style_sheet_contents.cc index bd88bfa..28a2e179 100644 --- a/third_party/blink/renderer/core/css/style_sheet_contents.cc +++ b/third_party/blink/renderer/core/css/style_sheet_contents.cc
@@ -337,29 +337,15 @@ inspector_parse_author_style_sheet_event::Data(cached_style_sheet)); TimeTicks start_time = CurrentTimeTicks(); - bool is_same_origin_request = - security_origin && security_origin->CanRequest(BaseURL()); - - // When the response was fetched via the Service Worker, the response URL may - // not be same as the base URL. - // TODO(horo): When we will use the response URL as the base URL, we can - // remove this check. crbug.com/553535 - if (is_same_origin_request && - cached_style_sheet->GetResponse().WasFetchedViaServiceWorker()) { - const KURL response_url(cached_style_sheet->GetResponse().ResponseUrl()); - // |response_url| is empty when the response is created in the SW. - if (!response_url.IsEmpty() && !security_origin->CanRequest(response_url)) - is_same_origin_request = false; - } - + const ResourceResponse& response = cached_style_sheet->GetResponse(); CSSStyleSheetResource::MIMETypeCheck mime_type_check = - IsQuirksModeBehavior(parser_context_->Mode()) && is_same_origin_request + (IsQuirksModeBehavior(parser_context_->Mode()) && + response.IsCorsSameOrigin()) ? CSSStyleSheetResource::MIMETypeCheck::kLax : CSSStyleSheetResource::MIMETypeCheck::kStrict; String sheet_text = cached_style_sheet->SheetText(parser_context_, mime_type_check); - const ResourceResponse& response = cached_style_sheet->GetResponse(); source_map_url_ = response.HttpHeaderField(http_names::kSourceMap); if (source_map_url_.IsEmpty()) { // Try to get deprecated header.
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc index 1a0c446..a5cb97d 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -11,6 +11,7 @@ #include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/inspector/inspector_trace_events.h" +#include "third_party/blink/renderer/core/layout/layout_box.h" #include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/platform/bindings/microtask.h" @@ -195,6 +196,20 @@ // continue the work. process_queue_task_scheduled_ = false; + // This is the first operation we do on a locked subtree, and a guaranteed + // operation before we try to use it, so save off the locked_frame_rect_ here + // if we don't have one yet. + // TODO(vmpstr): In mode 1, we should add an explicit states for lock pending + // and lock acquired. + if (!locked_frame_rect_) { + auto* layout_object = GetElement()->GetLayoutObject(); + if (layout_object && layout_object->IsBox()) { + locked_frame_rect_ = ToLayoutBox(layout_object)->FrameRect(); + } else { + locked_frame_rect_ = LayoutRect(); + } + } + // If we're not in callbacks pending, then we shouldn't run anything at the // moment. if (state_ != kCallbacksPending) @@ -245,6 +260,7 @@ resolver_ = nullptr; } callbacks_.clear(); + locked_frame_rect_.reset(); // We may have a dirty subtree and have not propagated the dirty bit up the // ancestor tree. Since we're now rejecting the promise and unlocking the @@ -417,10 +433,58 @@ RejectAndCleanUp(); } +DisplayLockContext::ScopedPendingFrameRect +DisplayLockContext::GetScopedPendingFrameRect() { + SCOPED_LOGGER(__PRETTY_FUNCTION__); + if (IsResolved()) + return ScopedPendingFrameRect(nullptr); + DCHECK(GetElement()->GetLayoutObject() && GetElement()->GetLayoutBox()); + GetElement()->GetLayoutBox()->SetFrameRectForDisplayLock(pending_frame_rect_); + return ScopedPendingFrameRect(this); +} + +void DisplayLockContext::NotifyPendingFrameRectScopeEnded() { + SCOPED_LOGGER(__PRETTY_FUNCTION__); + DCHECK(GetElement()->GetLayoutObject() && GetElement()->GetLayoutBox()); + DCHECK(locked_frame_rect_); + pending_frame_rect_ = GetElement()->GetLayoutBox()->FrameRect(); + GetElement()->GetLayoutBox()->SetFrameRectForDisplayLock(*locked_frame_rect_); +} + void DisplayLockContext::FinishResolution() { SCOPED_LOGGER(__PRETTY_FUNCTION__); if (state_ == kResolving) state_ = kResolved; + locked_frame_rect_.reset(); + + // Update the pending frame rect if we still have a layout object. + + // First, if the element is gone, then there's nothing to do. + if (!weak_element_handle_) + return; + auto* layout_object = GetElement()->GetLayoutObject(); + // The resolution could have disconnected us, which would destroy the layout + // object. + if (!layout_object || !layout_object->IsBox()) + return; + bool frame_rect_changed = + ToLayoutBox(layout_object)->FrameRect() != pending_frame_rect_; + // If the frame rect hasn't actually changed then we don't need to do + // anything. + // TODO(vmpstr): Is this true? What about things like paint? This also needs + // to be updated if there are more "stashed" things. + if (!frame_rect_changed) + return; + + // Set the pending frame rect as the new one, and ensure to schedule a layout + // for just the box itself. Note that we use the non-display locked version to + // ensure all the hooks are property invoked. + ToLayoutBox(layout_object)->SetFrameRect(pending_frame_rect_); + layout_object->SetNeedsLayout( + layout_invalidation_reason::kDisplayLockCommitting); + // Schedule an animation to perform the lifecycle phases. + GetElement()->GetDocument().GetPage()->Animator().ScheduleVisualUpdate( + GetElement()->GetDocument().GetFrame()); } void DisplayLockContext::StartCommit() { @@ -468,4 +532,19 @@ element_ = nullptr; } +DisplayLockContext::ScopedPendingFrameRect::ScopedPendingFrameRect( + DisplayLockContext* context) + : context_(context) {} + +DisplayLockContext::ScopedPendingFrameRect::ScopedPendingFrameRect( + ScopedPendingFrameRect&& other) + : context_(other.context_) { + other.context_ = nullptr; +} + +DisplayLockContext::ScopedPendingFrameRect::~ScopedPendingFrameRect() { + if (context_) + context_->NotifyPendingFrameRectScopeEnded(); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.h b/third_party/blink/renderer/core/display_lock/display_lock_context.h index 33ba17f..d5ae697 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.h +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -46,6 +46,19 @@ kDone }; + class ScopedPendingFrameRect { + public: + ScopedPendingFrameRect(ScopedPendingFrameRect&&); + ~ScopedPendingFrameRect(); + + private: + friend class DisplayLockContext; + + ScopedPendingFrameRect(DisplayLockContext*); + + UntracedMember<DisplayLockContext> context_ = nullptr; + }; + DisplayLockContext(Element*, ExecutionContext*); ~DisplayLockContext() override; @@ -101,6 +114,13 @@ void DidAttachLayoutTree(); + // Returns a ScopedPendingFrameRect object which exposes the pending layout + // frame rect to LayoutBox. This is used to ensure that children of the locked + // element use the pending layout frame to update the size of the element. + // After the scoped object is destroyed, the previous frame rect is restored + // and the pending one is stored in the context until it is needed. + ScopedPendingFrameRect GetScopedPendingFrameRect(); + private: friend class DisplayLockContextTest; friend class DisplayLockSuspendedHandle; @@ -153,6 +173,10 @@ return weak_element_handle_; } + // When ScopedPendingFrameRect is destroyed, it calls this function. See + // GetScopedPendingFrameRect() for more information. + void NotifyPendingFrameRectScopeEnded(); + HeapVector<Member<V8DisplayLockCallback>> callbacks_; Member<ScriptPromiseResolver> resolver_; @@ -185,6 +209,8 @@ unsigned suspended_count_ = 0; State state_ = kUninitialized; LifecycleUpdateState lifecycle_update_state_ = kNeedsStyle; + LayoutRect pending_frame_rect_; + base::Optional<LayoutRect> locked_frame_rect_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 6fc8bef2..bf77ab1 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -32,11 +32,13 @@ #include <memory> #include "base/auto_reset.h" +#include "base/macros.h" #include "base/optional.h" #include "services/metrics/public/cpp/mojo_ukm_recorder.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_source_id.h" #include "services/metrics/public/mojom/ukm_interface.mojom-shared.h" +#include "services/resource_coordinator/public/mojom/coordination_unit.mojom-blink.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/mojom/net/ip_address_space.mojom-blink.h" @@ -269,6 +271,7 @@ #include "third_party/blink/renderer/platform/geometry/length_functions.h" #include "third_party/blink/renderer/platform/histogram.h" #include "third_party/blink/renderer/platform/instance_counters.h" +#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/blink/renderer/platform/language.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" @@ -748,8 +751,8 @@ lifecycle_.AdvanceTo(DocumentLifecycle::kInactive); // Since CSSFontSelector requires Document::fetcher_ and StyleEngine owns - // CSSFontSelector, need to initialize style_engine_ after initializing - // fetcher_. + // CSSFontSelector, need to initialize |style_engine_| after initializing + // |fetcher_|. style_engine_ = StyleEngine::Create(*this); // The parent's parser should be suspended together with all the other @@ -4066,7 +4069,8 @@ // DOM 3 Core: When the Document supports the feature "HTML" [DOM Level 2 // HTML], the base URI is computed using first the value of the href attribute // of the HTML BASE element if any, and the value of the documentURI attribute - // from the Document interface otherwise (which we store, preparsed, in url_). + // from the Document interface otherwise (which we store, preparsed, in + // |url_|). if (!base_element_url_.IsEmpty()) base_url_ = base_element_url_; else if (!base_url_override_.IsEmpty()) @@ -5551,6 +5555,13 @@ date.Minute(), date.Second()); } +scoped_refptr<const SecurityOrigin> Document::TopFrameOrigin() const { + if (!GetFrame()) + return scoped_refptr<const SecurityOrigin>(); + + return GetFrame()->Tree().Top().GetSecurityContext()->GetSecurityOrigin(); +} + const KURL Document::SiteForCookies() const { // TODO(mkwst): This doesn't properly handle HTML Import documents. @@ -6079,6 +6090,51 @@ return frame_ ? dom_window_ : nullptr; } +namespace { + +using resource_coordinator::mojom::InterventionPolicy; +using resource_coordinator::mojom::PolicyControlledIntervention; + +typedef bool (*InterventionPolicyGetter)(const ExecutionContext*); +struct InterventionPolicyGetters { + InterventionPolicyGetter opt_in_getter; + InterventionPolicyGetter opt_out_getter; +}; + +constexpr InterventionPolicyGetters kInterventionPolicyGetters[] = { + {&origin_trials::PageLifecycleTransitionsOptInEnabled, + &origin_trials::PageLifecycleTransitionsOptOutEnabled}}; + +static_assert(base::size(kInterventionPolicyGetters) == + static_cast<size_t>(PolicyControlledIntervention::kMaxValue) + + 1, + "kInterventionPolicyGetters array must be kept in sync with " + "mojom::PolicyControlledIntervention enum."); + +// A helper function for setting intervention policy values on a frame en masse. +void SetInitialInterventionPolicies(FrameResourceCoordinator* frame_coordinator, + const ExecutionContext* context) { + // Note that these must be emitted in order, as the *last* policy being set + // is used as a sentinel in the browser-side logic to infer that the frame has + // transmitted all of its policy data. + for (size_t i = 0; i < base::size(kInterventionPolicyGetters); ++i) { + bool opt_in = (*kInterventionPolicyGetters[i].opt_in_getter)(context); + bool opt_out = (*kInterventionPolicyGetters[i].opt_out_getter)(context); + + // An explicit opt-out overrides an explicit opt-in if both are present. + InterventionPolicy policy = InterventionPolicy::kDefault; + if (opt_out) + policy = InterventionPolicy::kOptOut; + else if (opt_in) + policy = InterventionPolicy::kOptIn; + + frame_coordinator->SetInterventionPolicy( + static_cast<PolicyControlledIntervention>(i), policy); + } +} + +} // namespace + void Document::FinishedParsing() { DCHECK(!GetScriptableDocumentParser() || !parser_->IsParsing()); DCHECK(!GetScriptableDocumentParser() || ready_state_ != kLoading); @@ -6136,6 +6192,13 @@ inspector_mark_load_event::Data(frame)); probe::domContentLoadedEventFired(frame); frame->GetIdlenessDetector()->DomContentLoadedEventFired(); + + // Forward intervention policy state to the corresponding frame object + // in the resource coordinator. + // TODO(chrisha): Plumb in dynamic policy changes driven from Javascript. + if (auto* frame_coordinator = frame->GetFrameResourceCoordinator()) { + SetInitialInterventionPolicies(frame_coordinator, this); + } } // Schedule dropping of the ElementDataCache. We keep it alive for a while
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index 7d5ec6f..089ee7c 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -958,6 +958,8 @@ const KURL& CookieURL() const { return cookie_url_; } void SetCookieURL(const KURL& url) { cookie_url_ = url; } + scoped_refptr<const SecurityOrigin> TopFrameOrigin() const; + const KURL SiteForCookies() const; // The following implements the rule from HTML 4 for what valid names are. @@ -1680,9 +1682,8 @@ // Document URLs. KURL url_; // Document.URL: The URL from which this document was retrieved. KURL base_url_; // Node.baseURI: The URL to use when resolving relative URLs. - // An alternative base URL that takes precedence over base_url_ (but - // not base_element_url_). - KURL base_url_override_; + KURL base_url_override_; // An alternative base URL that takes precedence + // over base_url_ (but not base_element_url_). KURL base_element_url_; // The URL set by the <base> element. KURL cookie_url_; // The URL to use for cookie access. std::unique_ptr<OriginAccessEntry> access_entry_from_url_;
diff --git a/third_party/blink/renderer/core/dom/element.idl b/third_party/blink/renderer/core/dom/element.idl index c6a0e7c..8ef4a7e 100644 --- a/third_party/blink/renderer/core/dom/element.idl +++ b/third_party/blink/renderer/core/dom/element.idl
@@ -141,7 +141,7 @@ attribute EventHandler onsearch; // Display locking. - [RuntimeEnabled=DisplayLocking, CallWith=ScriptState] Promise acquireDisplayLock(DisplayLockCallback callback); + [RuntimeEnabled=DisplayLocking, CallWith=ScriptState] Promise<any> acquireDisplayLock(DisplayLockCallback callback); }; Element implements ParentNode;
diff --git a/third_party/blink/renderer/core/editing/finder/text_finder.cc b/third_party/blink/renderer/core/editing/finder/text_finder.cc index 7398b74..119c4ab 100644 --- a/third_party/blink/renderer/core/editing/finder/text_finder.cc +++ b/third_party/blink/renderer/core/editing/finder/text_finder.cc
@@ -33,6 +33,7 @@ #include "third_party/blink/public/platform/web_float_rect.h" #include "third_party/blink/public/platform/web_scroll_into_view_params.h" #include "third_party/blink/public/platform/web_vector.h" +#include "third_party/blink/public/web/web_frame_widget.h" #include "third_party/blink/public/web/web_local_frame_client.h" #include "third_party/blink/public/web/web_view_client.h" #include "third_party/blink/renderer/core/accessibility/ax_object_cache_base.h" @@ -154,7 +155,7 @@ ->GetDocument() ->GetTextAutosizer() ->PageNeedsAutosizing()) { - OwnerFrame().ViewImpl()->ZoomToFindInPageRect( + OwnerFrame().LocalRoot()->FrameWidget()->ZoomToFindInPageRect( OwnerFrame().GetFrameView()->ConvertToRootFrame( EnclosingIntRect(LayoutObject::AbsoluteBoundingBoxRectForRange( EphemeralRange(active_match_.Get()))))); @@ -635,7 +636,8 @@ // Zoom to the active match. active_match_rect = OwnerFrame().GetFrameView()->ConvertToRootFrame( active_match_bounding_box); - OwnerFrame().ViewImpl()->ZoomToFindInPageRect(active_match_rect); + OwnerFrame().LocalRoot()->FrameWidget()->ZoomToFindInPageRect( + active_match_rect); } if (selection_rect)
diff --git a/third_party/blink/renderer/core/editing/finder/text_finder_test.cc b/third_party/blink/renderer/core/editing/finder/text_finder_test.cc index 824e310..8a2b8f7 100644 --- a/third_party/blink/renderer/core/editing/finder/text_finder_test.cc +++ b/third_party/blink/renderer/core/editing/finder/text_finder_test.cc
@@ -34,7 +34,7 @@ TextFinderTest() { web_view_helper_.Initialize(); WebLocalFrameImpl& frame_impl = *web_view_helper_.LocalMainFrame(); - frame_impl.ViewImpl()->Resize(WebSize(640, 480)); + frame_impl.ViewImpl()->MainFrameWidget()->Resize(WebSize(640, 480)); frame_impl.ViewImpl()->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); document_ = static_cast<Document*>(frame_impl.GetDocument());
diff --git a/third_party/blink/renderer/core/editing/link_selection_test.cc b/third_party/blink/renderer/core/editing/link_selection_test.cc index 9c0d13e..067208a 100644 --- a/third_party/blink/renderer/core/editing/link_selection_test.cc +++ b/third_party/blink/renderer/core/editing/link_selection_test.cc
@@ -62,7 +62,8 @@ const auto& down_event = frame_test_helpers::CreateMouseEvent( WebMouseEvent::kMouseDown, WebMouseEvent::Button::kLeft, down_point, modifiers); - web_view_->HandleInputEvent(WebCoalescedInputEvent(down_event)); + web_view_->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(down_event)); } const int kMoveEventsNumber = 10; @@ -74,14 +75,16 @@ const auto& move_event = frame_test_helpers::CreateMouseEvent( WebMouseEvent::kMouseMove, WebMouseEvent::Button::kLeft, move_point, modifiers); - web_view_->HandleInputEvent(WebCoalescedInputEvent(move_event)); + web_view_->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(move_event)); } if (drag_flags & kSendUpEvent) { const auto& up_event = frame_test_helpers::CreateMouseEvent( WebMouseEvent::kMouseUp, WebMouseEvent::Button::kLeft, up_point, modifiers); - web_view_->HandleInputEvent(WebCoalescedInputEvent(up_event)); + web_view_->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(up_event)); } } @@ -92,9 +95,9 @@ auto event = frame_test_helpers::CreateMouseEvent( WebMouseEvent::kMouseDown, button, click_point, modifiers); event.click_count = count; - web_view_->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view_->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); event.SetType(WebMouseEvent::kMouseUp); - web_view_->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view_->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); } void LinkSelectionTestBase::EmulateMouseDown(const IntPoint& click_point, @@ -104,7 +107,7 @@ auto event = frame_test_helpers::CreateMouseEvent( WebMouseEvent::kMouseDown, button, click_point, modifiers); event.click_count = count; - web_view_->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view_->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); } String LinkSelectionTestBase::GetSelectionText() { @@ -137,7 +140,7 @@ frame_test_helpers::LoadHTMLString( main_frame_, kHTMLString, url_test_helpers::ToKURL("http://foobar.com")); - web_view_->Resize(WebSize(800, 600)); + web_view_->MainFrameWidget()->Resize(WebSize(800, 600)); web_view_->GetPage()->GetFocusController().SetActive(true); auto* document = main_frame_->GetFrame()->GetDocument(); @@ -290,7 +293,7 @@ frame_test_helpers::LoadHTMLString( main_frame_, kHTMLString, url_test_helpers::ToKURL("http://foobar.com")); - web_view_->Resize(WebSize(800, 600)); + web_view_->MainFrameWidget()->Resize(WebSize(800, 600)); web_view_->GetPage()->GetFocusController().SetActive(true); auto* document = main_frame_->GetFrame()->GetDocument();
diff --git a/third_party/blink/renderer/core/editing/local_caret_rect.cc b/third_party/blink/renderer/core/editing/local_caret_rect.cc index 04834d9..d5d92a3 100644 --- a/third_party/blink/renderer/core/editing/local_caret_rect.cc +++ b/third_party/blink/renderer/core/editing/local_caret_rect.cc
@@ -111,10 +111,7 @@ return LocalCaretRect(); if (NGInlineFormattingContextOf(adjusted.GetPosition())) { - // TODO(editing-dev): Use selection height instead of caret height, or - // decide if we need to keep the distinction between caret height and - // selection height in NG. - return ComputeNGLocalCaretRect(adjusted); + return ComputeNGLocalSelectionRect(adjusted); } // TODO(editing-dev): This DCHECK is for ensuring the correctness of
diff --git a/third_party/blink/renderer/core/editing/ng_flat_tree_shorthands.cc b/third_party/blink/renderer/core/editing/ng_flat_tree_shorthands.cc index 8f696f4..77e7ff4f6 100644 --- a/third_party/blink/renderer/core/editing/ng_flat_tree_shorthands.cc +++ b/third_party/blink/renderer/core/editing/ng_flat_tree_shorthands.cc
@@ -29,6 +29,11 @@ return ComputeNGLocalCaretRect(ToPositionInDOMTreeWithAffinity(position)); } +LocalCaretRect ComputeNGLocalSelectionRect( + const PositionInFlatTreeWithAffinity& position) { + return ComputeNGLocalSelectionRect(ToPositionInDOMTreeWithAffinity(position)); +} + bool InSameNGLineBox(const PositionInFlatTreeWithAffinity& position1, const PositionInFlatTreeWithAffinity& position2) { return InSameNGLineBox(ToPositionInDOMTreeWithAffinity(position1),
diff --git a/third_party/blink/renderer/core/editing/ng_flat_tree_shorthands.h b/third_party/blink/renderer/core/editing/ng_flat_tree_shorthands.h index 0497f1b..fb866a5 100644 --- a/third_party/blink/renderer/core/editing/ng_flat_tree_shorthands.h +++ b/third_party/blink/renderer/core/editing/ng_flat_tree_shorthands.h
@@ -22,6 +22,8 @@ NGCaretPosition ComputeNGCaretPosition(const PositionInFlatTreeWithAffinity&); LocalCaretRect ComputeNGLocalCaretRect(const PositionInFlatTreeWithAffinity&); +LocalCaretRect ComputeNGLocalSelectionRect( + const PositionInFlatTreeWithAffinity&); bool InSameNGLineBox(const PositionInFlatTreeWithAffinity&, const PositionInFlatTreeWithAffinity&);
diff --git a/third_party/blink/renderer/core/events/error_event.idl b/third_party/blink/renderer/core/events/error_event.idl index d6298b1..89d3b0c 100644 --- a/third_party/blink/renderer/core/events/error_event.idl +++ b/third_party/blink/renderer/core/events/error_event.idl
@@ -32,8 +32,8 @@ [ Constructor(DOMString type, optional ErrorEventInit eventInitDict), - ConstructorCallWith=ScriptState - // TODO(foolip): Exposed=(Window,Worker) + ConstructorCallWith=ScriptState, + Exposed=(Window,Worker) ] interface ErrorEvent : Event { readonly attribute DOMString message; readonly attribute DOMString filename;
diff --git a/third_party/blink/renderer/core/events/web_input_event_conversion_test.cc b/third_party/blink/renderer/core/events/web_input_event_conversion_test.cc index ae1d84d..9763585 100644 --- a/third_party/blink/renderer/core/events/web_input_event_conversion_test.cc +++ b/third_party/blink/renderer/core/events/web_input_event_conversion_test.cc
@@ -123,7 +123,7 @@ web_view->GetSettings()->SetViewportEnabled(true); int page_width = 640; int page_height = 480; - web_view->Resize(WebSize(page_width, page_height)); + web_view->MainFrameWidget()->Resize(WebSize(page_width, page_height)); web_view->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); @@ -337,7 +337,7 @@ web_view->GetSettings()->SetViewportEnabled(true); int page_width = 640; int page_height = 480; - web_view->Resize(WebSize(page_width, page_height)); + web_view->MainFrameWidget()->Resize(WebSize(page_width, page_height)); web_view->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); @@ -594,7 +594,7 @@ web_view_helper.InitializeAndLoad(base_url + file_name); int page_width = 640; int page_height = 480; - web_view->Resize(WebSize(page_width, page_height)); + web_view->MainFrameWidget()->Resize(WebSize(page_width, page_height)); web_view->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); @@ -632,7 +632,7 @@ web_view_helper.InitializeAndLoad(base_url + file_name); int page_width = 640; int page_height = 480; - web_view->Resize(WebSize(page_width, page_height)); + web_view->MainFrameWidget()->Resize(WebSize(page_width, page_height)); web_view->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); @@ -731,14 +731,14 @@ web_view_helper.InitializeAndLoad(base_url + file_name); int page_width = 640; int page_height = 480; - web_view->Resize(WebSize(page_width, page_height)); + web_view->MainFrameWidget()->Resize(WebSize(page_width, page_height)); web_view->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); LocalFrameView* view = ToLocalFrame(web_view->GetPage()->MainFrame())->View(); gfx::Vector2dF elastic_overscroll(10, -20); - web_view->ApplyViewportChanges( + web_view->MainFrameWidget()->ApplyViewportChanges( {gfx::ScrollOffset(), elastic_overscroll, 1.0f, 0.0f}); // Just elastic overscroll. @@ -807,12 +807,12 @@ web_view_helper.InitializeAndLoad(base_url + file_name); int page_width = 640; int page_height = 480; - web_view->Resize(WebSize(page_width, page_height)); + web_view->MainFrameWidget()->Resize(WebSize(page_width, page_height)); web_view->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); gfx::Vector2dF elastic_overscroll(10, -20); - web_view->ApplyViewportChanges( + web_view->MainFrameWidget()->ApplyViewportChanges( {gfx::ScrollOffset(), elastic_overscroll, 1.0f, 0.0f}); frame_test_helpers::ReloadFrame( web_view_helper.GetWebView()->MainFrameImpl());
diff --git a/third_party/blink/renderer/core/execution_context/execution_context.cc b/third_party/blink/renderer/core/execution_context/execution_context.cc index 15ad0d9..7fe16fa 100644 --- a/third_party/blink/renderer/core/execution_context/execution_context.cc +++ b/third_party/blink/renderer/core/execution_context/execution_context.cc
@@ -37,6 +37,7 @@ #include "third_party/blink/renderer/core/frame/use_counter.h" #include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/core/probe/core_probes.h" +#include "third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h" #include "third_party/blink/renderer/core/workers/worker_global_scope.h" #include "third_party/blink/renderer/core/workers/worker_thread.h" #include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h"
diff --git a/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.cc b/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.cc index fe3347c..3b3b7eb 100644 --- a/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.cc +++ b/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.cc
@@ -32,13 +32,13 @@ #include <memory> #include <utility> +#include "services/service_manager/public/cpp/interface_provider.h" +#include "third_party/blink/public/mojom/worker/shared_worker_info.mojom-blink.h" #include "third_party/blink/public/platform/web_content_security_policy.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/platform/web_url.h" #include "third_party/blink/public/web/blink.h" #include "third_party/blink/public/web/web_shared_worker.h" -#include "third_party/blink/public/web/web_shared_worker_connect_listener.h" -#include "third_party/blink/public/web/web_shared_worker_repository_client.h" #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h" @@ -58,10 +58,12 @@ } // namespace -// Implementation of the callback interface passed to the embedder. This will be -// destructed when a connection to a shared worker is established. +// This is the client implementation to ServiceWorkerConnectorImpl in the +// browser process. This will be destructed when the owner document is +// destroyed. +// TODO(nhiroki): Move this class into its own file. class SharedWorkerConnectListener final - : public WebSharedWorkerConnectListener { + : public mojom::blink::SharedWorkerClient { public: explicit SharedWorkerConnectListener(SharedWorker* worker) : worker_(worker) {} @@ -72,13 +74,12 @@ // going away. } - // WebSharedWorkerConnectListener overrides. - - void WorkerCreated( + // mojom::blink::SharedWorkerClient overrides. + void OnCreated( mojom::SharedWorkerCreationContextType creation_context_type) override { worker_->SetIsBeingConnected(true); - // No nested workers (for now) - connect() should only be called from + // No nested workers (for now) - connect() can only be called from a // document context. DCHECK(worker_->GetExecutionContext()->IsDocument()); DCHECK_EQ(creation_context_type, @@ -86,71 +87,95 @@ worker_->GetExecutionContext()->IsSecureContext())); } - void ScriptLoadFailed() override { + void OnConnected(const Vector<mojom::WebFeature>& features_used) override { + worker_->SetIsBeingConnected(false); + for (auto feature : features_used) + OnFeatureUsed(feature); + } + + void OnScriptLoadFailed() override { worker_->DispatchEvent(*Event::CreateCancelable(event_type_names::kError)); worker_->SetIsBeingConnected(false); } - void Connected() override { worker_->SetIsBeingConnected(false); } - - void CountFeature(WebFeature feature) override { + void OnFeatureUsed(mojom::WebFeature feature) override { UseCounter::Count(worker_->GetExecutionContext(), feature); } Persistent<SharedWorker> worker_; }; -static WebSharedWorkerRepositoryClient::DocumentID GetId(void* document) { - DCHECK(document); - return reinterpret_cast<WebSharedWorkerRepositoryClient::DocumentID>( - document); -} - void SharedWorkerRepositoryClientImpl::Connect( SharedWorker* worker, MessagePortChannel port, const KURL& url, mojom::blink::BlobURLTokenPtr blob_url_token, const String& name) { - DCHECK(client_); + DCHECK(!name.IsNull()); - // No nested workers (for now) - connect() should only be called from document - // context. - Document* document = To<Document>(worker->GetExecutionContext()); + // Lazily bind the connector. + if (!connector_) + interface_provider_->GetInterface(mojo::MakeRequest(&connector_)); // TODO(estark): this is broken, as it only uses the first header // when multiple might have been sent. Fix by making the - // SharedWorkerConnectListener interface take a map that can contain - // multiple headers. + // mojom::blink::SharedWorkerInfo take a map that can contain multiple + // headers. Vector<CSPHeaderAndType> headers = worker->GetExecutionContext()->GetContentSecurityPolicy()->Headers(); - WebString header; - mojom::ContentSecurityPolicyType header_type = - mojom::ContentSecurityPolicyType::kReport; - + WebString header = ""; + auto header_type = mojom::ContentSecurityPolicyType::kReport; if (headers.size() > 0) { header = headers[0].first; header_type = static_cast<mojom::ContentSecurityPolicyType>(headers[0].second); } - bool is_secure_context = worker->GetExecutionContext()->IsSecureContext(); - std::unique_ptr<WebSharedWorkerConnectListener> listener = - std::make_unique<SharedWorkerConnectListener>(worker); - client_->Connect( - url, name, GetId(document), header, header_type, - worker->GetExecutionContext()->GetSecurityContext().AddressSpace(), - ToCreationContextType(is_secure_context), std::move(port), - blob_url_token.PassInterface().PassHandle(), std::move(listener)); + mojom::blink::SharedWorkerInfoPtr info(mojom::blink::SharedWorkerInfo::New( + url, name, header, header_type, + worker->GetExecutionContext()->GetSecurityContext().AddressSpace())); + + // No nested workers (for now) - connect() can only be called from a document + // context. + Document* document = To<Document>(worker->GetExecutionContext()); + mojom::blink::SharedWorkerClientPtr client_ptr; + AddWorker(document, std::make_unique<SharedWorkerConnectListener>(worker), + mojo::MakeRequest(&client_ptr)); + + connector_->Connect( + std::move(info), std::move(client_ptr), + ToCreationContextType(worker->GetExecutionContext()->IsSecureContext()), + port.ReleaseHandle(), + mojom::blink::BlobURLTokenPtr(mojom::blink::BlobURLTokenPtrInfo( + blob_url_token.PassInterface().PassHandle(), + mojom::blink::BlobURLToken::Version_))); } void SharedWorkerRepositoryClientImpl::DocumentDetached(Document* document) { - DCHECK(client_); - client_->DocumentDetached(GetId(document)); + // Delete any associated SharedWorkerConnectListeners, which will signal, via + // the dropped mojo connection, disinterest in the associated shared worker. + client_map_.erase(GetId(document)); } SharedWorkerRepositoryClientImpl::SharedWorkerRepositoryClientImpl( - WebSharedWorkerRepositoryClient* client) - : client_(client) {} + service_manager::InterfaceProvider* interface_provider) + : interface_provider_(interface_provider) {} + +void SharedWorkerRepositoryClientImpl::AddWorker( + Document* document, + std::unique_ptr<mojom::blink::SharedWorkerClient> client, + mojom::blink::SharedWorkerClientRequest request) { + const auto& result = client_map_.insert(GetId(document), nullptr); + std::unique_ptr<ClientSet>& clients = result.stored_value->value; + if (!clients) + clients = std::make_unique<ClientSet>(); + clients->AddBinding(std::move(client), std::move(request)); +} + +SharedWorkerRepositoryClientImpl::DocumentID +SharedWorkerRepositoryClientImpl::GetId(Document* document) { + DCHECK(document); + return reinterpret_cast<DocumentID>(document); +} } // namespace blink
diff --git a/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.h b/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.h index 3b0b0461..2763aaa 100644 --- a/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.h +++ b/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.h
@@ -36,21 +36,29 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/scoped_refptr.h" +#include "mojo/public/cpp/bindings/strong_binding_set.h" +#include "third_party/blink/public/mojom/worker/shared_worker_client.mojom-blink.h" +#include "third_party/blink/public/mojom/worker/shared_worker_connector.mojom-blink.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/workers/shared_worker_repository_client.h" +namespace service_manager { +class InterfaceProvider; +} // namespace service_manager + namespace blink { -class WebSharedWorkerRepositoryClient; - +// TODO(nhiroki): Merge this file into +// core/workers/shared_worker_repository_client.h. class CORE_EXPORT SharedWorkerRepositoryClientImpl final : public SharedWorkerRepositoryClient { USING_FAST_MALLOC(SharedWorkerRepositoryClientImpl); public: static std::unique_ptr<SharedWorkerRepositoryClientImpl> Create( - WebSharedWorkerRepositoryClient* client) { - return base::WrapUnique(new SharedWorkerRepositoryClientImpl(client)); + service_manager::InterfaceProvider* interface_provider) { + return base::WrapUnique( + new SharedWorkerRepositoryClientImpl(interface_provider)); } ~SharedWorkerRepositoryClientImpl() override = default; @@ -63,9 +71,24 @@ void DocumentDetached(Document*) override; private: - explicit SharedWorkerRepositoryClientImpl(WebSharedWorkerRepositoryClient*); + explicit SharedWorkerRepositoryClientImpl( + service_manager::InterfaceProvider*); - WebSharedWorkerRepositoryClient* client_; + void AddWorker(Document* document, + std::unique_ptr<mojom::blink::SharedWorkerClient> client, + mojom::blink::SharedWorkerClientRequest request); + + // Unique identifier for the parent document of a worker (unique within a + // given process). + using DocumentID = unsigned long long; + static DocumentID GetId(Document*); + + service_manager::InterfaceProvider* interface_provider_; + mojom::blink::SharedWorkerConnectorPtr connector_; + + using ClientSet = mojo::StrongBindingSet<mojom::blink::SharedWorkerClient>; + using ClientMap = HashMap<DocumentID, std::unique_ptr<ClientSet>>; + ClientMap client_map_; DISALLOW_COPY_AND_ASSIGN(SharedWorkerRepositoryClientImpl); };
diff --git a/third_party/blink/renderer/core/exported/web_document.cc b/third_party/blink/renderer/core/exported/web_document.cc index 1c09baa..49a6ac70 100644 --- a/third_party/blink/renderer/core/exported/web_document.cc +++ b/third_party/blink/renderer/core/exported/web_document.cc
@@ -154,21 +154,11 @@ return WebString(ConstUnwrap<Document>()->title()); } -WebString WebDocument::ContentAsTextForTesting(bool use_inner_text) const { +WebString WebDocument::ContentAsTextForTesting() const { Element* document_element = ConstUnwrap<Document>()->documentElement(); if (!document_element) return WebString(); - if (use_inner_text) - return document_element->innerText(); - - // TODO(editing-dev): We should use |Element::innerText()|. - const_cast<Document*>(ConstUnwrap<Document>()) - ->UpdateStyleAndLayoutIgnorePendingStylesheetsForNode(document_element); - if (!document_element->GetLayoutObject()) - return document_element->textContent(true); - return WebString( - PlainText(EphemeralRange::RangeOfContents(*document_element), - TextIteratorBehavior::Builder().SetForInnerText(true).Build())); + return document_element->innerText(); } WebElementCollection WebDocument::All() {
diff --git a/third_party/blink/renderer/core/exported/web_document_loader_impl.cc b/third_party/blink/renderer/core/exported/web_document_loader_impl.cc index c2a427a..7e1154e6 100644 --- a/third_party/blink/renderer/core/exported/web_document_loader_impl.cc +++ b/third_party/blink/renderer/core/exported/web_document_loader_impl.cc
@@ -165,6 +165,10 @@ return DocumentLoader::had_transient_activation(); } +bool WebDocumentLoaderImpl::IsListingFtpDirectory() const { + return DocumentLoader::IsListingFtpDirectory(); +} + void WebDocumentLoaderImpl::Trace(blink::Visitor* visitor) { DocumentLoader::Trace(visitor); }
diff --git a/third_party/blink/renderer/core/exported/web_document_loader_impl.h b/third_party/blink/renderer/core/exported/web_document_loader_impl.h index b4b27c73..10a54af 100644 --- a/third_party/blink/renderer/core/exported/web_document_loader_impl.h +++ b/third_party/blink/renderer/core/exported/web_document_loader_impl.h
@@ -84,6 +84,7 @@ bool IsArchive() const override; WebArchiveInfo GetArchiveInfo() const override; bool HadUserGesture() const override; + bool IsListingFtpDirectory() const override; void Trace(blink::Visitor*) override;
diff --git a/third_party/blink/renderer/core/exported/web_document_test.cc b/third_party/blink/renderer/core/exported/web_document_test.cc index 0f691ce..9d982f03 100644 --- a/third_party/blink/renderer/core/exported/web_document_test.cc +++ b/third_party/blink/renderer/core/exported/web_document_test.cc
@@ -338,10 +338,17 @@ ->GetDocument(); } +bool OriginsEqual(const char* path, + scoped_refptr<const SecurityOrigin> origin) { + return SecurityOrigin::Create(ToOriginA(path)) + ->IsSameSchemeHostPort(origin.get()); +} + TEST_F(WebDocumentFirstPartyTest, Empty) { Load(g_empty_file); ASSERT_EQ(ToOriginA(g_empty_file), TopDocument()->SiteForCookies()); + ASSERT_TRUE(OriginsEqual(g_empty_file, TopDocument()->TopFrameOrigin())); } TEST_F(WebDocumentFirstPartyTest, NestedOriginA) { @@ -349,6 +356,10 @@ ASSERT_EQ(ToOriginA(g_nested_origin_a), TopDocument()->SiteForCookies()); ASSERT_EQ(ToOriginA(g_nested_origin_a), NestedDocument()->SiteForCookies()); + + ASSERT_TRUE(OriginsEqual(g_nested_origin_a, TopDocument()->TopFrameOrigin())); + ASSERT_TRUE( + OriginsEqual(g_nested_origin_a, NestedDocument()->TopFrameOrigin())); } TEST_F(WebDocumentFirstPartyTest, NestedOriginSubA) { @@ -357,6 +368,11 @@ ASSERT_EQ(ToOriginA(g_nested_origin_sub_a), TopDocument()->SiteForCookies()); ASSERT_EQ(ToOriginA(g_nested_origin_sub_a), NestedDocument()->SiteForCookies()); + + ASSERT_TRUE( + OriginsEqual(g_nested_origin_sub_a, TopDocument()->TopFrameOrigin())); + ASSERT_TRUE( + OriginsEqual(g_nested_origin_sub_a, NestedDocument()->TopFrameOrigin())); } TEST_F(WebDocumentFirstPartyTest, NestedOriginSecureA) { @@ -366,6 +382,11 @@ TopDocument()->SiteForCookies()); ASSERT_EQ(ToOriginA(g_nested_origin_secure_a), NestedDocument()->SiteForCookies()); + + ASSERT_TRUE( + OriginsEqual(g_nested_origin_secure_a, TopDocument()->TopFrameOrigin())); + ASSERT_TRUE(OriginsEqual(g_nested_origin_secure_a, + NestedDocument()->TopFrameOrigin())); } TEST_F(WebDocumentFirstPartyTest, NestedOriginAInOriginA) { @@ -377,6 +398,11 @@ NestedDocument()->SiteForCookies()); ASSERT_EQ(ToOriginA(g_nested_origin_a_in_origin_a), NestedNestedDocument()->SiteForCookies()); + + ASSERT_TRUE(OriginsEqual(g_nested_origin_a_in_origin_a, + TopDocument()->TopFrameOrigin())); + ASSERT_TRUE(OriginsEqual(g_nested_origin_a_in_origin_a, + NestedDocument()->TopFrameOrigin())); } TEST_F(WebDocumentFirstPartyTest, NestedOriginAInOriginB) { @@ -386,6 +412,13 @@ TopDocument()->SiteForCookies()); ASSERT_EQ(NullURL(), NestedDocument()->SiteForCookies()); ASSERT_EQ(NullURL(), NestedNestedDocument()->SiteForCookies()); + + ASSERT_TRUE(OriginsEqual(g_nested_origin_a_in_origin_b, + TopDocument()->TopFrameOrigin())); + ASSERT_TRUE(OriginsEqual(g_nested_origin_a_in_origin_b, + NestedDocument()->TopFrameOrigin())); + ASSERT_TRUE(OriginsEqual(g_nested_origin_a_in_origin_b, + NestedNestedDocument()->TopFrameOrigin())); } TEST_F(WebDocumentFirstPartyTest, NestedOriginB) { @@ -393,6 +426,10 @@ ASSERT_EQ(ToOriginA(g_nested_origin_b), TopDocument()->SiteForCookies()); ASSERT_EQ(NullURL(), NestedDocument()->SiteForCookies()); + + ASSERT_TRUE(OriginsEqual(g_nested_origin_b, TopDocument()->TopFrameOrigin())); + ASSERT_TRUE( + OriginsEqual(g_nested_origin_b, NestedDocument()->TopFrameOrigin())); } TEST_F(WebDocumentFirstPartyTest, NestedOriginBInOriginA) { @@ -403,6 +440,13 @@ ASSERT_EQ(ToOriginA(g_nested_origin_b_in_origin_a), NestedDocument()->SiteForCookies()); ASSERT_EQ(NullURL(), NestedNestedDocument()->SiteForCookies()); + + ASSERT_TRUE(OriginsEqual(g_nested_origin_b_in_origin_a, + TopDocument()->TopFrameOrigin())); + ASSERT_TRUE(OriginsEqual(g_nested_origin_b_in_origin_a, + NestedDocument()->TopFrameOrigin())); + ASSERT_TRUE(OriginsEqual(g_nested_origin_b_in_origin_a, + NestedNestedDocument()->TopFrameOrigin())); } TEST_F(WebDocumentFirstPartyTest, NestedOriginBInOriginB) { @@ -412,6 +456,13 @@ TopDocument()->SiteForCookies()); ASSERT_EQ(NullURL(), NestedDocument()->SiteForCookies()); ASSERT_EQ(NullURL(), NestedNestedDocument()->SiteForCookies()); + + ASSERT_TRUE(OriginsEqual(g_nested_origin_b_in_origin_b, + TopDocument()->TopFrameOrigin())); + ASSERT_TRUE(OriginsEqual(g_nested_origin_b_in_origin_b, + NestedDocument()->TopFrameOrigin())); + ASSERT_TRUE(OriginsEqual(g_nested_origin_b_in_origin_b, + NestedNestedDocument()->TopFrameOrigin())); } TEST_F(WebDocumentFirstPartyTest, NestedSrcdoc) { @@ -419,6 +470,10 @@ ASSERT_EQ(ToOriginA(g_nested_src_doc), TopDocument()->SiteForCookies()); ASSERT_EQ(ToOriginA(g_nested_src_doc), NestedDocument()->SiteForCookies()); + + ASSERT_TRUE(OriginsEqual(g_nested_src_doc, TopDocument()->TopFrameOrigin())); + ASSERT_TRUE( + OriginsEqual(g_nested_src_doc, NestedDocument()->TopFrameOrigin())); } TEST_F(WebDocumentFirstPartyTest, NestedData) { @@ -426,6 +481,9 @@ ASSERT_EQ(ToOriginA(g_nested_data), TopDocument()->SiteForCookies()); ASSERT_EQ(NullURL(), NestedDocument()->SiteForCookies()); + + ASSERT_TRUE(OriginsEqual(g_nested_data, TopDocument()->TopFrameOrigin())); + ASSERT_TRUE(OriginsEqual(g_nested_data, NestedDocument()->TopFrameOrigin())); } TEST_F(WebDocumentFirstPartyTest, @@ -440,6 +498,13 @@ NestedDocument()->SiteForCookies()); ASSERT_EQ(ToOriginA(g_nested_origin_a_in_origin_b), NestedNestedDocument()->SiteForCookies()); + + ASSERT_TRUE(OriginsEqual(g_nested_origin_a_in_origin_b, + TopDocument()->TopFrameOrigin())); + ASSERT_TRUE(OriginsEqual(g_nested_origin_a_in_origin_b, + NestedDocument()->TopFrameOrigin())); + ASSERT_TRUE(OriginsEqual(g_nested_origin_a_in_origin_b, + NestedNestedDocument()->TopFrameOrigin())); } } // namespace blink
diff --git a/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc b/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc index 22f4dfe..47b6e810 100644 --- a/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc +++ b/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc
@@ -321,7 +321,7 @@ } TEST_F(WebFrameSerializerSanitizationTest, RemovePopupOverlayIfRequested) { - WebView()->Resize(WebSize(500, 500)); + WebView()->MainFrameWidget()->Resize(WebSize(500, 500)); SetRemovePopupOverlay(true); String mhtml = GenerateMHTMLFromHtml("http://www.test.com", "popup.html"); EXPECT_EQ(WTF::kNotFound, mhtml.Find("class=3D\"overlay")); @@ -331,7 +331,7 @@ } TEST_F(WebFrameSerializerSanitizationTest, PopupOverlayNotFound) { - WebView()->Resize(WebSize(500, 500)); + WebView()->MainFrameWidget()->Resize(WebSize(500, 500)); SetRemovePopupOverlay(true); String mhtml = GenerateMHTMLFromHtml("http://www.test.com", "text_only_page.html"); @@ -340,7 +340,7 @@ } TEST_F(WebFrameSerializerSanitizationTest, KeepPopupOverlayIfNotRequested) { - WebView()->Resize(WebSize(500, 500)); + WebView()->MainFrameWidget()->Resize(WebSize(500, 500)); SetRemovePopupOverlay(false); String mhtml = GenerateMHTMLFromHtml("http://www.test.com", "popup.html"); EXPECT_NE(WTF::kNotFound, mhtml.Find("class=3D\"overlay"));
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc index 07a14d1..3f73458 100644 --- a/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -347,7 +347,8 @@ IntRect& caret_bounds) { Element* element = helper.GetWebView()->FocusedElement(); WebRect caret_in_viewport, unused; - helper.GetWebView()->SelectionBounds(caret_in_viewport, unused); + helper.GetWebView()->MainFrameWidget()->SelectionBounds(caret_in_viewport, + unused); caret_bounds = helper.GetWebView()->GetPage()->GetVisualViewport().ViewportToRootFrame( caret_in_viewport); @@ -3233,7 +3234,8 @@ WebSize(viewport_size.width, viewport_size.height)); web_view_helper.GetWebView()->SetPageScaleFactor( initial_page_scale_factor); - ASSERT_EQ(viewport_size, web_view_helper.GetWebView()->Size()); + ASSERT_EQ(viewport_size, + web_view_helper.GetWebView()->MainFrameWidget()->Size()); ASSERT_EQ(initial_page_scale_factor, web_view_helper.GetWebView()->PageScaleFactor()); web_view_helper.Resize( @@ -3437,9 +3439,9 @@ float scale_delta = web_view_impl->FakePageScaleAnimationPageScaleForTesting() / web_view_impl->PageScaleFactor(); - web_view_impl->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), - scale_delta, 0, - cc::BrowserControlsState::kBoth}); + web_view_impl->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), scale_delta, 0, + cc::BrowserControlsState::kBoth}); scale = web_view_impl->PageScaleFactor(); } @@ -3636,7 +3638,7 @@ // back to the div. SimulateDoubleTap(web_view_helper.GetWebView(), top_point, scale); EXPECT_FLOAT_EQ(1, scale); - web_view_helper.GetWebView()->ApplyViewportChanges( + web_view_helper.GetWebView()->MainFrameWidget()->ApplyViewportChanges( {gfx::ScrollOffset(), gfx::Vector2dF(), 0.6f, 0, cc::BrowserControlsState::kBoth}); SimulateDoubleTap(web_view_helper.GetWebView(), bottom_point, scale); @@ -3647,7 +3649,7 @@ // If we didn't yet get an auto-zoom update and a second double-tap arrives, // should go back to minimum scale. - web_view_helper.GetWebView()->ApplyViewportChanges( + web_view_helper.GetWebView()->MainFrameWidget()->ApplyViewportChanges( {gfx::ScrollOffset(), gfx::Vector2dF(), 1.1f, 0, cc::BrowserControlsState::kBoth}); @@ -3703,7 +3705,7 @@ EXPECT_FLOAT_EQ(1, scale); // Zoom in to reset double_tap_zoom_in_effect flag. - web_view_helper.GetWebView()->ApplyViewportChanges( + web_view_helper.GetWebView()->MainFrameWidget()->ApplyViewportChanges( {gfx::ScrollOffset(), gfx::Vector2dF(), 1.1f, 0, cc::BrowserControlsState::kBoth}); // 1 < minimumPageScale < doubleTapZoomAlreadyLegibleScale @@ -3725,7 +3727,7 @@ EXPECT_FLOAT_EQ(double_tap_zoom_already_legible_scale, scale); // Zoom in to reset double_tap_zoom_in_effect flag. - web_view_helper.GetWebView()->ApplyViewportChanges( + web_view_helper.GetWebView()->MainFrameWidget()->ApplyViewportChanges( {gfx::ScrollOffset(), gfx::Vector2dF(), 1.1f, 0, cc::BrowserControlsState::kBoth}); // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale @@ -3795,7 +3797,7 @@ EXPECT_FLOAT_EQ(legible_scale, scale); // Zoom in to reset double_tap_zoom_in_effect flag. - web_view_helper.GetWebView()->ApplyViewportChanges( + web_view_helper.GetWebView()->MainFrameWidget()->ApplyViewportChanges( {gfx::ScrollOffset(), gfx::Vector2dF(), 1.1f, 0, cc::BrowserControlsState::kBoth}); // 1 < maximumLegibleScaleFactor < minimumPageScale < @@ -3818,7 +3820,7 @@ EXPECT_FLOAT_EQ(double_tap_zoom_already_legible_scale, scale); // Zoom in to reset double_tap_zoom_in_effect flag. - web_view_helper.GetWebView()->ApplyViewportChanges( + web_view_helper.GetWebView()->MainFrameWidget()->ApplyViewportChanges( {gfx::ScrollOffset(), gfx::Vector2dF(), 1.1f, 0, cc::BrowserControlsState::kBoth}); // minimumPageScale < 1 < maximumLegibleScaleFactor < @@ -3841,7 +3843,7 @@ EXPECT_FLOAT_EQ(double_tap_zoom_already_legible_scale, scale); // Zoom in to reset double_tap_zoom_in_effect flag. - web_view_helper.GetWebView()->ApplyViewportChanges( + web_view_helper.GetWebView()->MainFrameWidget()->ApplyViewportChanges( {gfx::ScrollOffset(), gfx::Vector2dF(), 1.1f, 0, cc::BrowserControlsState::kBoth}); // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale < @@ -3915,7 +3917,7 @@ EXPECT_FLOAT_EQ(legible_scale, scale); // Zoom in to reset double_tap_zoom_in_effect flag. - web_view_helper.GetWebView()->ApplyViewportChanges( + web_view_helper.GetWebView()->MainFrameWidget()->ApplyViewportChanges( {gfx::ScrollOffset(), gfx::Vector2dF(), 1.1f, 0, cc::BrowserControlsState::kBoth}); // 1 < accessibilityFontScaleFactor < minimumPageScale < @@ -3938,7 +3940,7 @@ EXPECT_FLOAT_EQ(double_tap_zoom_already_legible_scale, scale); // Zoom in to reset double_tap_zoom_in_effect flag. - web_view_helper.GetWebView()->ApplyViewportChanges( + web_view_helper.GetWebView()->MainFrameWidget()->ApplyViewportChanges( {gfx::ScrollOffset(), gfx::Vector2dF(), 1.1f, 0, cc::BrowserControlsState::kBoth}); // minimumPageScale < 1 < accessibilityFontScaleFactor < @@ -3961,7 +3963,7 @@ EXPECT_FLOAT_EQ(double_tap_zoom_already_legible_scale, scale); // Zoom in to reset double_tap_zoom_in_effect flag. - web_view_helper.GetWebView()->ApplyViewportChanges( + web_view_helper.GetWebView()->MainFrameWidget()->ApplyViewportChanges( {gfx::ScrollOffset(), gfx::Vector2dF(), 1.1f, 0, cc::BrowserControlsState::kBoth}); // minimumPageScale < 1 < doubleTapZoomAlreadyLegibleScale < @@ -4645,28 +4647,33 @@ // Move to the next text-field: 1 cursor change. counter.Reset(); - web_view->HandleInputEvent(WebCoalescedInputEvent(tab_down)); - web_view->HandleInputEvent(WebCoalescedInputEvent(tab_up)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(tab_down)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(tab_up)); EXPECT_EQ(1, counter.Count()); // Move to another text-field: 1 cursor change. - web_view->HandleInputEvent(WebCoalescedInputEvent(tab_down)); - web_view->HandleInputEvent(WebCoalescedInputEvent(tab_up)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(tab_down)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(tab_up)); EXPECT_EQ(2, counter.Count()); // Move to a number-field: 1 cursor change. - web_view->HandleInputEvent(WebCoalescedInputEvent(tab_down)); - web_view->HandleInputEvent(WebCoalescedInputEvent(tab_up)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(tab_down)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(tab_up)); EXPECT_EQ(3, counter.Count()); // Move to an editable element: 1 cursor change. - web_view->HandleInputEvent(WebCoalescedInputEvent(tab_down)); - web_view->HandleInputEvent(WebCoalescedInputEvent(tab_up)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(tab_down)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(tab_up)); EXPECT_EQ(4, counter.Count()); // Move to a non-editable element: 0 cursor changes. - web_view->HandleInputEvent(WebCoalescedInputEvent(tab_down)); - web_view->HandleInputEvent(WebCoalescedInputEvent(tab_up)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(tab_down)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(tab_up)); EXPECT_EQ(4, counter.Count()); } @@ -5196,7 +5203,7 @@ frame_test_helpers::WebViewHelper web_view_helper; web_view_helper.InitializeAndLoad(base_url_ + "find_match_count.html", &frame_client); - web_view_helper.GetWebView()->Resize(WebSize(640, 480)); + web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480)); RunPendingTasks(); const char* kFindString = "a"; @@ -5578,7 +5585,7 @@ frame_test_helpers::LoadHTMLString(frame, html, url_test_helpers::ToKURL(base_url_)); web_view_helper.Resize(WebSize(640, 480)); - web_view_helper.GetWebView()->SetFocus(true); + web_view_helper.GetWebView()->MainFrameWidget()->SetFocus(true); RunPendingTasks(); TestFindInPageClient find_in_page_client; @@ -5657,7 +5664,7 @@ frame_test_helpers::LoadHTMLString(frame, html, url_test_helpers::ToKURL(base_url_)); web_view_helper.Resize(WebSize(640, 480)); - web_view_helper.GetWebView()->SetFocus(true); + web_view_helper.GetWebView()->MainFrameWidget()->SetFocus(true); RunPendingTasks(); TestFindInPageClient find_in_page_client; @@ -5734,7 +5741,8 @@ &web_view_helper); frame = web_view_helper.LocalMainFrame(); EXPECT_EQ("Some test text for testing.", SelectionAsString(frame)); - web_view_helper.GetWebView()->SelectionBounds(start_web_rect, end_web_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds( + start_web_rect, end_web_rect); frame->ExecuteCommand(WebString::FromUTF8("Unselect")); EXPECT_EQ("", SelectionAsString(frame)); frame->SelectRange(TopLeft(start_web_rect), @@ -5749,7 +5757,8 @@ &web_view_helper); frame = web_view_helper.LocalMainFrame(); EXPECT_EQ("Some offscreen test text for testing.", SelectionAsString(frame)); - web_view_helper.GetWebView()->SelectionBounds(start_web_rect, end_web_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds( + start_web_rect, end_web_rect); frame->ExecuteCommand(WebString::FromUTF8("Unselect")); EXPECT_EQ("", SelectionAsString(frame)); frame->SelectRange(TopLeft(start_web_rect), @@ -5846,7 +5855,8 @@ frame = web_view_helper.GetWebView()->MainFrame(); WebLocalFrame* subframe = frame->FirstChild()->ToWebLocalFrame(); EXPECT_EQ("Some test text for testing.", SelectionAsString(subframe)); - web_view_helper.GetWebView()->SelectionBounds(start_web_rect, end_web_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds( + start_web_rect, end_web_rect); subframe->ExecuteCommand(WebString::FromUTF8("Unselect")); EXPECT_EQ("", SelectionAsString(subframe)); subframe->SelectRange(TopLeft(start_web_rect), @@ -5873,7 +5883,8 @@ &web_view_helper); frame = web_view_helper.LocalMainFrame(); EXPECT_EQ("This text is initially selected.", SelectionAsString(frame)); - web_view_helper.GetWebView()->SelectionBounds(start_web_rect, end_web_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds( + start_web_rect, end_web_rect); frame->SelectRange(BottomRightMinusOne(end_web_rect), WebPoint(0, 0)); EXPECT_EQ("16-char header. This text is initially selected.", @@ -5884,13 +5895,16 @@ &web_view_helper); frame = web_view_helper.LocalMainFrame(); - web_view_helper.GetWebView()->SelectionBounds(start_web_rect, end_web_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds( + start_web_rect, end_web_rect); frame->SelectRange(TopLeft(start_web_rect), BottomRightMinusOne(end_web_rect)); EXPECT_EQ("This text is initially selected.", SelectionAsString(frame)); - web_view_helper.GetWebView()->SelectionBounds(start_web_rect, end_web_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds( + start_web_rect, end_web_rect); - web_view_helper.GetWebView()->SelectionBounds(start_web_rect, end_web_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds( + start_web_rect, end_web_rect); frame->SelectRange(TopLeft(start_web_rect), WebPoint(640, 480)); EXPECT_EQ("This text is initially selected. 16-char footer.", SelectionAsString(frame)); @@ -5914,7 +5928,8 @@ &web_view_helper); frame = web_view_helper.LocalMainFrame(); EXPECT_EQ("This text is initially selected.", SelectionAsString(frame)); - web_view_helper.GetWebView()->SelectionBounds(start_web_rect, end_web_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds( + start_web_rect, end_web_rect); frame->SelectRange(BottomRightMinusOne(end_web_rect), WebPoint(0, 0)); EXPECT_EQ("16-char header. This text is initially selected.", @@ -5925,14 +5940,17 @@ &web_view_helper); frame = web_view_helper.LocalMainFrame(); - web_view_helper.GetWebView()->SelectionBounds(start_web_rect, end_web_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds( + start_web_rect, end_web_rect); frame->SelectRange(TopLeft(start_web_rect), BottomRightMinusOne(end_web_rect)); EXPECT_EQ("This text is initially selected.", SelectionAsString(frame)); - web_view_helper.GetWebView()->SelectionBounds(start_web_rect, end_web_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds( + start_web_rect, end_web_rect); EXPECT_EQ("This text is initially selected.", SelectionAsString(frame)); - web_view_helper.GetWebView()->SelectionBounds(start_web_rect, end_web_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds( + start_web_rect, end_web_rect); frame->SelectRange(TopLeft(start_web_rect), WebPoint(640, 480)); EXPECT_EQ("This text is initially selected. 16-char footer.", SelectionAsString(frame)); @@ -6058,7 +6076,8 @@ &web_view_helper); frame = web_view_helper.LocalMainFrame(); EXPECT_EQ("This text is initially selected.", SelectionAsString(frame)); - web_view_helper.GetWebView()->SelectionBounds(start_web_rect, end_web_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds( + start_web_rect, end_web_rect); frame->MoveRangeSelectionExtent(WebPoint(640, 480)); EXPECT_EQ("This text is initially selected. 16-char footer.", @@ -6095,7 +6114,8 @@ &web_view_helper); frame = web_view_helper.LocalMainFrame(); EXPECT_EQ("This text is initially selected.", SelectionAsString(frame)); - web_view_helper.GetWebView()->SelectionBounds(start_web_rect, end_web_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds( + start_web_rect, end_web_rect); frame->MoveRangeSelectionExtent(BottomRightMinusOne(start_web_rect)); EXPECT_EQ("This text is initially selected.", SelectionAsString(frame)); @@ -6122,7 +6142,8 @@ &web_view_helper); frame = web_view_helper.LocalMainFrame(); EXPECT_EQ("Length", SelectionAsString(frame)); - web_view_helper.GetWebView()->SelectionBounds(start_web_rect, end_web_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds( + start_web_rect, end_web_rect); EXPECT_EQ(0, frame->GetFrame() ->Selection() @@ -6303,19 +6324,21 @@ WebRect end_rect; frame->ExecuteScript(WebScriptSource("selectRange();")); - web_view_helper.GetWebView()->SelectionBounds(initial_start_rect, - initial_end_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds( + initial_start_rect, initial_end_rect); WebPoint moved_start(TopLeft(initial_start_rect)); moved_start.y += 40; frame->SelectRange(moved_start, BottomRightMinusOne(initial_end_rect)); - web_view_helper.GetWebView()->SelectionBounds(start_rect, end_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds(start_rect, + end_rect); EXPECT_EQ(start_rect, initial_start_rect); EXPECT_EQ(end_rect, initial_end_rect); moved_start.y -= 80; frame->SelectRange(moved_start, BottomRightMinusOne(initial_end_rect)); - web_view_helper.GetWebView()->SelectionBounds(start_rect, end_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds(start_rect, + end_rect); EXPECT_EQ(start_rect, initial_start_rect); EXPECT_EQ(end_rect, initial_end_rect); @@ -6323,13 +6346,15 @@ moved_end.y += 40; frame->SelectRange(TopLeft(initial_start_rect), moved_end); - web_view_helper.GetWebView()->SelectionBounds(start_rect, end_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds(start_rect, + end_rect); EXPECT_EQ(start_rect, initial_start_rect); EXPECT_EQ(end_rect, initial_end_rect); moved_end.y -= 80; frame->SelectRange(TopLeft(initial_start_rect), moved_end); - web_view_helper.GetWebView()->SelectionBounds(start_rect, end_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds(start_rect, + end_rect); EXPECT_EQ(start_rect, initial_start_rect); EXPECT_EQ(end_rect, initial_end_rect); } @@ -6349,19 +6374,21 @@ WebRect end_rect; frame->ExecuteScript(WebScriptSource("selectCaret();")); - web_view_helper.GetWebView()->SelectionBounds(initial_start_rect, - initial_end_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds( + initial_start_rect, initial_end_rect); WebPoint move_to(TopLeft(initial_start_rect)); move_to.y += 40; frame->MoveCaretSelection(move_to); - web_view_helper.GetWebView()->SelectionBounds(start_rect, end_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds(start_rect, + end_rect); EXPECT_EQ(start_rect, initial_start_rect); EXPECT_EQ(end_rect, initial_end_rect); move_to.y -= 80; frame->MoveCaretSelection(move_to); - web_view_helper.GetWebView()->SelectionBounds(start_rect, end_rect); + web_view_helper.GetWebView()->MainFrameWidget()->SelectionBounds(start_rect, + end_rect); EXPECT_EQ(start_rect, initial_start_rect); EXPECT_EQ(end_rect, initial_end_rect); } @@ -6383,7 +6410,7 @@ void RunTestWithNoSelection(const char* test_file) { RegisterMockedHttpURLLoad(test_file); - web_view_helper_.GetWebView()->SetFocus(true); + web_view_helper_.GetWebView()->MainFrameWidget()->SetFocus(true); frame_test_helpers::LoadFrame( web_view_helper_.GetWebView()->MainFrameImpl(), base_url_ + test_file); UpdateAllLifecyclePhases(web_view_helper_.GetWebView()); @@ -6399,7 +6426,7 @@ void RunTest(const char* test_file) { RegisterMockedHttpURLLoad(test_file); - web_view_helper_.GetWebView()->SetFocus(true); + web_view_helper_.GetWebView()->MainFrameWidget()->SetFocus(true); frame_test_helpers::LoadFrame( web_view_helper_.GetWebView()->MainFrameImpl(), base_url_ + test_file); UpdateAllLifecyclePhases(web_view_helper_.GetWebView()); @@ -7275,7 +7302,7 @@ // Do a compositor scroll, verify that this is counted as a user scroll. scrollable_area->DidScroll(FloatPoint(0, 1)); - web_view_helper.GetWebView()->ApplyViewportChanges( + web_view_helper.GetWebView()->MainFrameWidget()->ApplyViewportChanges( {gfx::ScrollOffset(), gfx::Vector2dF(), 1.7f, 0, cc::BrowserControlsState::kBoth}); EXPECT_TRUE(client.WasFrameScrolled()); @@ -7286,7 +7313,7 @@ // The page scale 1.0f and scroll. scrollable_area->DidScroll(FloatPoint(0, 2)); - web_view_helper.GetWebView()->ApplyViewportChanges( + web_view_helper.GetWebView()->MainFrameWidget()->ApplyViewportChanges( {gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, 0, cc::BrowserControlsState::kBoth}); EXPECT_TRUE(client.WasFrameScrolled()); @@ -7296,7 +7323,7 @@ // No scroll event if there is no scroll delta. scrollable_area->DidScroll(FloatPoint(0, 2)); - web_view_helper.GetWebView()->ApplyViewportChanges( + web_view_helper.GetWebView()->MainFrameWidget()->ApplyViewportChanges( {gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, 0, cc::BrowserControlsState::kBoth}); EXPECT_FALSE(client.WasFrameScrolled()); @@ -7305,7 +7332,7 @@ // Non zero page scale and scroll. scrollable_area->DidScroll(FloatPoint(9, 15)); - web_view_helper.GetWebView()->ApplyViewportChanges( + web_view_helper.GetWebView()->MainFrameWidget()->ApplyViewportChanges( {gfx::ScrollOffset(), gfx::Vector2dF(), 0.6f, 0, cc::BrowserControlsState::kBoth}); EXPECT_TRUE(client.WasFrameScrolled()); @@ -8126,50 +8153,50 @@ // Simulate the browser controls showing by 20px, thus shrinking the viewport // and allowing it to scroll an additional 20px. - web_view->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, - 20.0f / browser_controls_height, - cc::BrowserControlsState::kBoth}); + web_view->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, + 20.0f / browser_controls_height, cc::BrowserControlsState::kBoth}); EXPECT_EQ(ScrollOffset(0, 1920), frame_view->LayoutViewport()->MaximumScrollOffset()); // Show more, make sure the scroll actually gets clamped. - web_view->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, - 20.0f / browser_controls_height, - cc::BrowserControlsState::kBoth}); + web_view->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, + 20.0f / browser_controls_height, cc::BrowserControlsState::kBoth}); web_view->MainFrameImpl()->SetScrollOffset(WebSize(0, 2000)); EXPECT_EQ(ScrollOffset(0, 1940), frame_view->LayoutViewport()->GetScrollOffset()); // Hide until there's 10px showing. - web_view->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, - -30.0f / browser_controls_height, - cc::BrowserControlsState::kBoth}); + web_view->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, + -30.0f / browser_controls_height, cc::BrowserControlsState::kBoth}); EXPECT_EQ(ScrollOffset(0, 1910), frame_view->LayoutViewport()->MaximumScrollOffset()); // Simulate a LayoutEmbeddedContent::resize. The frame is resized to // accomodate the browser controls and Blink's view of the browser controls // matches that of the CC - web_view->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, - 30.0f / browser_controls_height, - cc::BrowserControlsState::kBoth}); + web_view->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, + 30.0f / browser_controls_height, cc::BrowserControlsState::kBoth}); web_view->ResizeWithBrowserControls(WebSize(100, 60), 40.0f, 0, true); UpdateAllLifecyclePhases(web_view_helper.GetWebView()); EXPECT_EQ(ScrollOffset(0, 1940), frame_view->LayoutViewport()->MaximumScrollOffset()); // Now simulate hiding. - web_view->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, - -10.0f / browser_controls_height, - cc::BrowserControlsState::kBoth}); + web_view->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, + -10.0f / browser_controls_height, cc::BrowserControlsState::kBoth}); EXPECT_EQ(ScrollOffset(0, 1930), frame_view->LayoutViewport()->MaximumScrollOffset()); // Reset to original state: 100px widget height, browser controls fully // hidden. - web_view->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, - -30.0f / browser_controls_height, - cc::BrowserControlsState::kBoth}); + web_view->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, + -30.0f / browser_controls_height, cc::BrowserControlsState::kBoth}); web_view->ResizeWithBrowserControls(WebSize(100, 100), browser_controls_height, 0, false); UpdateAllLifecyclePhases(web_view_helper.GetWebView()); @@ -8180,15 +8207,15 @@ // should allow an extra 0.5px of scrolling in the visual viewport. Make // sure we're not losing any pixels when applying the adjustment on the // main frame. - web_view->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, - 1.0f / browser_controls_height, - cc::BrowserControlsState::kBoth}); + web_view->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, + 1.0f / browser_controls_height, cc::BrowserControlsState::kBoth}); EXPECT_EQ(ScrollOffset(0, 1901), frame_view->LayoutViewport()->MaximumScrollOffset()); - web_view->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, - 2.0f / browser_controls_height, - cc::BrowserControlsState::kBoth}); + web_view->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 1.0f, + 2.0f / browser_controls_height, cc::BrowserControlsState::kBoth}); EXPECT_EQ(ScrollOffset(0, 1903), frame_view->LayoutViewport()->MaximumScrollOffset()); } @@ -8239,7 +8266,7 @@ Element* div_fullscreen = document->getElementById("div1"); Fullscreen::RequestFullscreen(*div_fullscreen); EXPECT_EQ(nullptr, Fullscreen::FullscreenElementFrom(*document)); - web_view_impl->DidEnterFullscreen(); + web_view_impl->MainFrameWidget()->DidEnterFullscreen(); EXPECT_EQ(div_fullscreen, Fullscreen::FullscreenElementFrom(*document)); UpdateAllLifecyclePhases(web_view_impl); EXPECT_EQ(div_fullscreen, Fullscreen::FullscreenElementFrom(*document)); @@ -8278,7 +8305,7 @@ Element* div_fullscreen = document->getElementById("div1"); Fullscreen::RequestFullscreen(*div_fullscreen); EXPECT_EQ(nullptr, Fullscreen::FullscreenElementFrom(*document)); - web_view_impl->DidEnterFullscreen(); + web_view_impl->MainFrameWidget()->DidEnterFullscreen(); EXPECT_EQ(div_fullscreen, Fullscreen::FullscreenElementFrom(*document)); UpdateAllLifecyclePhases(web_view_impl); EXPECT_EQ(div_fullscreen, Fullscreen::FullscreenElementFrom(*document)); @@ -8301,7 +8328,7 @@ // Verify that the viewports are scrollable upon exiting fullscreen. EXPECT_EQ(div_fullscreen, Fullscreen::FullscreenElementFrom(*document)); - web_view_impl->DidExitFullscreen(); + web_view_impl->MainFrameWidget()->DidExitFullscreen(); EXPECT_EQ(nullptr, Fullscreen::FullscreenElementFrom(*document)); UpdateAllLifecyclePhases(web_view_impl); EXPECT_EQ(nullptr, Fullscreen::FullscreenElementFrom(*document)); @@ -8346,7 +8373,7 @@ LocalFrame::NotifyUserActivation(frame); Fullscreen::RequestFullscreen(*document->documentElement()); EXPECT_EQ(nullptr, Fullscreen::FullscreenElementFrom(*document)); - web_view_impl->DidEnterFullscreen(); + web_view_impl->MainFrameWidget()->DidEnterFullscreen(); EXPECT_EQ(document->documentElement(), Fullscreen::FullscreenElementFrom(*document)); @@ -8396,7 +8423,7 @@ LocalFrame::NotifyUserActivation(frame); Element* div_fullscreen = document->getElementById("div1"); Fullscreen::RequestFullscreen(*div_fullscreen); - web_view_impl->DidEnterFullscreen(); + web_view_impl->MainFrameWidget()->DidEnterFullscreen(); UpdateAllLifecyclePhases(web_view_impl); // Verify that the element is sized to the viewport. @@ -8438,7 +8465,7 @@ LocalFrame::NotifyUserActivation(top_doc->GetFrame()); Fullscreen::RequestFullscreen(*top_body); } - web_view_impl->DidEnterFullscreen(); + web_view_impl->MainFrameWidget()->DidEnterFullscreen(); UpdateAllLifecyclePhases(web_view_impl); { @@ -8446,7 +8473,7 @@ LocalFrame::NotifyUserActivation(iframe_doc->GetFrame()); Fullscreen::RequestFullscreen(*iframe_body); } - web_view_impl->DidEnterFullscreen(); + web_view_impl->MainFrameWidget()->DidEnterFullscreen(); Microtask::PerformCheckpoint(V8PerIsolateData::MainThreadIsolate()); UpdateAllLifecyclePhases(web_view_impl); @@ -8455,7 +8482,7 @@ EXPECT_EQ(iframe, Fullscreen::FullscreenElementFrom(*top_doc)); EXPECT_EQ(iframe_body, Fullscreen::FullscreenElementFrom(*iframe_doc)); - web_view_impl->DidExitFullscreen(); + web_view_impl->MainFrameWidget()->DidExitFullscreen(); UpdateAllLifecyclePhases(web_view_impl); // We should now have fully exited fullscreen. @@ -8491,7 +8518,7 @@ std::unique_ptr<UserGestureIndicator> gesture = LocalFrame::NotifyUserActivation(frame); Fullscreen::RequestFullscreen(*frame->GetDocument()->documentElement()); - web_view_impl->DidEnterFullscreen(); + web_view_impl->MainFrameWidget()->DidEnterFullscreen(); UpdateAllLifecyclePhases(web_view_impl); EXPECT_EQ(384, layout_view->LogicalWidth().Floor()); EXPECT_EQ(640, layout_view->LogicalHeight().Floor()); @@ -8499,7 +8526,7 @@ EXPECT_FLOAT_EQ(1.0, web_view_impl->MinimumPageScaleFactor()); EXPECT_FLOAT_EQ(1.0, web_view_impl->MaximumPageScaleFactor()); - web_view_impl->DidExitFullscreen(); + web_view_impl->MainFrameWidget()->DidExitFullscreen(); UpdateAllLifecyclePhases(web_view_impl); EXPECT_EQ(320, layout_view->LogicalWidth().Floor()); EXPECT_EQ(533, layout_view->LogicalHeight().Floor()); @@ -8530,7 +8557,7 @@ std::unique_ptr<UserGestureIndicator> gesture = LocalFrame::NotifyUserActivation(frame); Fullscreen::RequestFullscreen(*frame->GetDocument()->documentElement()); - web_view_impl->DidEnterFullscreen(); + web_view_impl->MainFrameWidget()->DidEnterFullscreen(); UpdateAllLifecyclePhases(web_view_impl); EXPECT_EQ(384, layout_view->LogicalWidth().Floor()); EXPECT_EQ(640, layout_view->LogicalHeight().Floor()); @@ -8550,7 +8577,7 @@ EXPECT_FLOAT_EQ(1.0, web_view_impl->MinimumPageScaleFactor()); EXPECT_FLOAT_EQ(1.0, web_view_impl->MaximumPageScaleFactor()); - web_view_impl->DidExitFullscreen(); + web_view_impl->MainFrameWidget()->DidExitFullscreen(); UpdateAllLifecyclePhases(web_view_impl); EXPECT_EQ(320, layout_view->LogicalWidth().Floor()); EXPECT_EQ(192, layout_view->LogicalHeight().Floor()); @@ -8598,7 +8625,7 @@ Fullscreen::RequestFullscreen(*frame->GetDocument()->body()); } - web_view_impl->DidEnterFullscreen(); + web_view_impl->MainFrameWidget()->DidEnterFullscreen(); UpdateAllLifecyclePhases(web_view_impl); client.screen_info_.rect.width = screen_size_minus_status_bars.width; client.screen_info_.rect.height = screen_size_minus_status_bars.height; @@ -8612,7 +8639,7 @@ EXPECT_FLOAT_EQ(1.0, web_view_impl->MinimumPageScaleFactor()); EXPECT_FLOAT_EQ(1.0, web_view_impl->MaximumPageScaleFactor()); - web_view_impl->DidExitFullscreen(); + web_view_impl->MainFrameWidget()->DidExitFullscreen(); UpdateAllLifecyclePhases(web_view_impl); client.screen_info_.rect.width = screen_size_minus_status_bars.width; client.screen_info_.rect.height = screen_size_minus_status_bars.height; @@ -8659,7 +8686,7 @@ std::unique_ptr<UserGestureIndicator> gesture = LocalFrame::NotifyUserActivation(frame, UserGestureToken::kNewGesture); Fullscreen::RequestFullscreen(*frame->GetDocument()->documentElement()); - web_view_impl->DidEnterFullscreen(); + web_view_impl->MainFrameWidget()->DidEnterFullscreen(); UpdateAllLifecyclePhases(web_view_impl); // Entering fullscreen causes layout size and page scale limits to be @@ -8676,7 +8703,7 @@ KURL test_url = ToKURL("about:blank"); WebLocalFrame* web_frame = web_view_helper.LocalMainFrame(); frame_test_helpers::LoadHTMLString(web_frame, kSource, test_url); - web_view_impl->DidExitFullscreen(); + web_view_impl->MainFrameWidget()->DidExitFullscreen(); UpdateAllLifecyclePhases(web_view_impl); // Make sure the new page's layout size and scale factor limits aren't @@ -8709,12 +8736,12 @@ EXPECT_EQ(SkColorGetA(layer_tree_host->background_color()), SK_AlphaOPAQUE); video->webkitEnterFullscreen(); - web_view_impl->DidEnterFullscreen(); + web_view_impl->MainFrameWidget()->DidEnterFullscreen(); UpdateAllLifecyclePhases(web_view_impl); EXPECT_TRUE(video->IsFullscreen()); EXPECT_LT(SkColorGetA(layer_tree_host->background_color()), SK_AlphaOPAQUE); - web_view_impl->DidExitFullscreen(); + web_view_impl->MainFrameWidget()->DidExitFullscreen(); UpdateAllLifecyclePhases(web_view_impl); EXPECT_FALSE(video->IsFullscreen()); EXPECT_EQ(SkColorGetA(layer_tree_host->background_color()), SK_AlphaOPAQUE); @@ -9860,7 +9887,7 @@ *helper.RemoteMainFrame(), WebString(), WebFrameOwnerProperties(), nullptr, nullptr, &child_widget_client); - helper.GetWebView()->Resize(WebSize(1000, 1000)); + helper.GetWebView()->MainFrameWidget()->Resize(WebSize(1000, 1000)); WebGestureEvent event(WebInputEvent::kGestureTap, WebInputEvent::kNoModifiers, WebInputEvent::GetStaticTimeStampForTests(), @@ -10214,19 +10241,20 @@ void ScrollBegin(frame_test_helpers::WebViewHelper* web_view_helper, float delta_x_hint, float delta_y_hint) { - web_view_helper->GetWebView()->HandleInputEvent(GenerateEvent( - WebInputEvent::kGestureScrollBegin, delta_x_hint, delta_y_hint)); + web_view_helper->GetWebView()->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollBegin, delta_x_hint, + delta_y_hint)); } void ScrollUpdate(frame_test_helpers::WebViewHelper* web_view_helper, float delta_x, float delta_y) { - web_view_helper->GetWebView()->HandleInputEvent( + web_view_helper->GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, delta_x, delta_y)); } void ScrollEnd(frame_test_helpers::WebViewHelper* web_view_helper) { - web_view_helper->GetWebView()->HandleInputEvent( + web_view_helper->GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollEnd)); } }; @@ -10906,7 +10934,7 @@ frame_test_helpers::WebViewHelper helper; SaveImageFromDataURLWebFrameClient client; WebViewImpl* web_view = helper.InitializeAndLoad(url, &client); - web_view->Resize(WebSize(400, 400)); + web_view->MainFrameWidget()->Resize(WebSize(400, 400)); UpdateAllLifecyclePhases(web_view); WebLocalFrame* local_frame = web_view->MainFrameImpl(); @@ -10943,7 +10971,7 @@ frame_test_helpers::WebViewHelper helper; SaveImageFromDataURLWebFrameClient client; WebViewImpl* web_view = helper.InitializeAndLoad(url, &client); - web_view->Resize(WebSize(400, 400)); + web_view->MainFrameWidget()->Resize(WebSize(400, 400)); WebLocalFrame* local_frame = web_view->MainFrameImpl(); @@ -10977,7 +11005,7 @@ frame_test_helpers::WebViewHelper helper; WebViewImpl* web_view = helper.InitializeAndLoad(url, &client); - web_view->Resize(WebSize(400, 400)); + web_view->MainFrameWidget()->Resize(WebSize(400, 400)); client.Reset(); WebLocalFrame* local_frame = web_view->MainFrameImpl(); @@ -11251,17 +11279,17 @@ // Try GestureScrollEnd and GestureScrollUpdate first to make sure that not // seeing a Begin first doesn't break anything. (This currently happens). - web_view_helper.GetWebView()->HandleInputEvent( + web_view_helper.GetWebView()->MainFrameWidget()->HandleInputEvent( WebCoalescedInputEvent(end_event)); - web_view_helper.GetWebView()->HandleInputEvent( + web_view_helper.GetWebView()->MainFrameWidget()->HandleInputEvent( WebCoalescedInputEvent(update_event)); // Try a full Begin/Update/End cycle. - web_view_helper.GetWebView()->HandleInputEvent( + web_view_helper.GetWebView()->MainFrameWidget()->HandleInputEvent( WebCoalescedInputEvent(begin_event)); - web_view_helper.GetWebView()->HandleInputEvent( + web_view_helper.GetWebView()->MainFrameWidget()->HandleInputEvent( WebCoalescedInputEvent(update_event)); - web_view_helper.GetWebView()->HandleInputEvent( + web_view_helper.GetWebView()->MainFrameWidget()->HandleInputEvent( WebCoalescedInputEvent(end_event)); } @@ -11358,7 +11386,7 @@ }; TEST_F(WebFrameSimTest, HitTestWithIgnoreClippingAtNegativeOffset) { - WebView().Resize(WebSize(500, 300)); + WebView().MainFrameWidget()->Resize(WebSize(500, 300)); WebView().GetPage()->GetSettings().SetTextAutosizingEnabled(false); SimRequest r("https://example.com/test.html", "text/html"); @@ -11410,7 +11438,7 @@ } TEST_F(WebFrameSimTest, TickmarksDocumentRelative) { - WebView().Resize(WebSize(500, 300)); + WebView().MainFrameWidget()->Resize(WebSize(500, 300)); WebView().GetPage()->GetSettings().SetTextAutosizingEnabled(false); SimRequest request("https://example.com/test.html", "text/html"); @@ -11460,7 +11488,7 @@ } TEST_F(WebFrameSimTest, FindInPageSelectNextMatch) { - WebView().Resize(WebSize(500, 300)); + WebView().MainFrameWidget()->Resize(WebSize(500, 300)); WebView().GetPage()->GetSettings().SetTextAutosizingEnabled(false); SimRequest request("https://example.com/test.html", "text/html"); @@ -11538,7 +11566,7 @@ // Test bubbling a document (End key) scroll from an inner iframe. This test // passes if it does not crash. https://crbug.com/904247. TEST_F(WebFrameSimTest, ScrollToEndBubblingCrash) { - WebView().Resize(WebSize(500, 300)); + WebView().MainFrameWidget()->Resize(WebSize(500, 300)); WebView().GetPage()->GetSettings().SetScrollAnimatorEnabled(false); SimRequest request("https://example.com/test.html", "text/html"); @@ -11576,22 +11604,26 @@ // Scroll the iframe to the end. key_event.SetType(WebInputEvent::kRawKeyDown); - WebView().HandleInputEvent(WebCoalescedInputEvent(key_event)); + WebView().MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); key_event.SetType(WebInputEvent::kKeyUp); - WebView().HandleInputEvent(WebCoalescedInputEvent(key_event)); + WebView().MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); Compositor().BeginFrame(); // End key should now bubble from the iframe up to the main viewport. key_event.SetType(WebInputEvent::kRawKeyDown); - WebView().HandleInputEvent(WebCoalescedInputEvent(key_event)); + WebView().MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); key_event.SetType(WebInputEvent::kKeyUp); - WebView().HandleInputEvent(WebCoalescedInputEvent(key_event)); + WebView().MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); } // Basic smoke test of the paint path used by the Android disambiguation popup. TEST_F(WebFrameSimTest, DisambiguationPopupPixelTest) { - WebView().Resize(WebSize(400, 600)); + WebView().MainFrameWidget()->Resize(WebSize(400, 600)); WebView().GetPage()->GetSettings().SetTextAutosizingEnabled(false); UseAndroidSettings(); @@ -11641,7 +11673,8 @@ WebView().MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); - WebView().PaintContentIgnoringCompositing(&canvas, zoom_rect); + WebView().MainFrameWidget()->PaintContentIgnoringCompositing(&canvas, + zoom_rect); // All the pixels in the canvas should be the <div> color. for (int x = 0; x < canvas_size.width(); ++x) { @@ -11653,7 +11686,7 @@ } TEST_F(WebFrameSimTest, TestScrollFocusedEditableElementIntoView) { - WebView().Resize(WebSize(500, 300)); + WebView().MainFrameWidget()->Resize(WebSize(500, 300)); WebView().SetDefaultPageScaleLimits(1.f, 4); WebView().EnableFakePageScaleAnimationForTesting(true); WebView().GetPage()->GetSettings().SetTextAutosizingEnabled(false); @@ -11734,7 +11767,7 @@ // Now resize the visual viewport so that the input box is no longer in view // (e.g. a keyboard is overlayed). - WebView().ResizeVisualViewport(IntSize(200, 100)); + WebView().MainFrameWidget()->ResizeVisualViewport(IntSize(200, 100)); ASSERT_FALSE(visual_viewport.VisibleRectInDocument().Contains(inputRect)); WebView() @@ -11761,7 +11794,7 @@ // input visible, we need to also scroll those clip/scroller elements This // test ensures we do so. https://crbug.com/270018. UseAndroidSettings(); - WebView().Resize(WebSize(400, 600)); + WebView().MainFrameWidget()->Resize(WebSize(400, 600)); WebView().EnableFakePageScaleAnimationForTesting(true); WebView().GetPage()->GetSettings().SetTextAutosizingEnabled(false); @@ -11814,7 +11847,7 @@ // Simulate the keyboard being shown and resizing the widget. Cause a scroll // into view after. - WebView().Resize(WebSize(400, 300)); + WebView().MainFrameWidget()->Resize(WebSize(400, 300)); float scale_before = visual_viewport.Scale(); WebView() @@ -11851,7 +11884,7 @@ TEST_F(WebFrameSimTest, DoubleTapZoomWhileScrolled) { UseAndroidSettings(); - WebView().Resize(WebSize(490, 500)); + WebView().MainFrameWidget()->Resize(WebSize(490, 500)); WebView().EnableFakePageScaleAnimationForTesting(true); WebView().GetSettings()->SetTextAutosizingEnabled(false); WebView().SetDefaultPageScaleLimits(0.5f, 4); @@ -11960,7 +11993,7 @@ // Ensure we don't crash if we try to scroll into view the focused editable // element which doesn't have a LayoutObject. TEST_F(WebFrameSimTest, ScrollFocusedEditableIntoViewNoLayoutObject) { - WebView().Resize(WebSize(500, 600)); + WebView().MainFrameWidget()->Resize(WebSize(500, 600)); WebView().GetPage()->GetSettings().SetTextAutosizingEnabled(false); SimRequest r("https://example.com/test.html", "text/html"); @@ -11998,7 +12031,7 @@ // The resize should cause the focused element to lose its LayoutObject. If // this resize came from the Android on-screen keyboard, this would be // followed by a ScrollFocusedEditableElementIntoView. Ensure we don't crash. - WebView().Resize(WebSize(500, 300)); + WebView().MainFrameWidget()->Resize(WebSize(500, 300)); ASSERT_FALSE(input->GetLayoutObject()); ASSERT_EQ(input, WebView().FocusedElement()); @@ -12098,7 +12131,7 @@ TEST_F(WebFrameSimTest, RtlInitialScrollOffsetWithViewport) { UseAndroidSettings(); - WebView().Resize(WebSize(400, 400)); + WebView().MainFrameWidget()->Resize(WebSize(400, 400)); WebView().SetDefaultPageScaleLimits(0.25f, 2); SimRequest main_resource("https://example.com/test.html", "text/html"); @@ -12144,7 +12177,7 @@ TEST_F(WebFrameSimTest, LayoutViewLocalVisualRect) { UseAndroidSettings(); - WebView().Resize(WebSize(600, 400)); + WebView().MainFrameWidget()->Resize(WebSize(600, 400)); WebView().SetDefaultPageScaleLimits(0.5f, 2); SimRequest main_resource("https://example.com/test.html", "text/html"); @@ -12352,7 +12385,7 @@ WebViewImpl* web_view = web_view_helper.Initialize(&frame); frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(), html, ToKURL("about:blank")); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); web_view->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); RunPendingTasks(); @@ -12366,7 +12399,8 @@ mouse_event.button = WebMouseEvent::Button::kRight; mouse_event.SetPositionInWidget(8, 8); mouse_event.click_count = 1; - web_view->HandleInputEvent(WebCoalescedInputEvent(mouse_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(mouse_event)); RunPendingTasks(); web_view_helper.Reset(); return frame.GetMenuData().edit_flags & WebContextMenuData::kCanSelectAll; @@ -12389,7 +12423,7 @@ const std::string& html = "<input value=' '>"; frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(), html, ToKURL("about:blank")); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(web_view); RunPendingTasks(); web_view->SetInitialFocus(false); @@ -12404,7 +12438,8 @@ mouse_event.button = WebMouseEvent::Button::kRight; mouse_event.SetPositionInWidget(8, 8); mouse_event.click_count = 1; - web_view->HandleInputEvent(WebCoalescedInputEvent(mouse_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(mouse_event)); RunPendingTasks(); web_view_helper.Reset(); EXPECT_EQ(frame.GetMenuData().selected_text, " "); @@ -12417,7 +12452,7 @@ const std::string& html = "<input type='password' value='password'>"; frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(), html, ToKURL("about:blank")); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(web_view); RunPendingTasks(); web_view->SetInitialFocus(false); @@ -12432,7 +12467,8 @@ mouse_event.button = WebMouseEvent::Button::kRight; mouse_event.SetPositionInWidget(8, 8); mouse_event.click_count = 1; - web_view->HandleInputEvent(WebCoalescedInputEvent(mouse_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(mouse_event)); RunPendingTasks(); web_view_helper.Reset(); @@ -12450,7 +12486,7 @@ "Next line</div>"; frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(), html, ToKURL("about:blank")); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(web_view); RunPendingTasks(); web_view->SetInitialFocus(false); @@ -12463,9 +12499,10 @@ mouse_event.button = WebMouseEvent::Button::kLeft; mouse_event.SetPositionInWidget(0, 0); mouse_event.click_count = 2; - web_view->HandleInputEvent(WebCoalescedInputEvent(mouse_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(mouse_event)); - web_view->ShowContextMenu(kMenuSourceTouch); + web_view->MainFrameWidget()->ShowContextMenu(kMenuSourceTouch); RunPendingTasks(); web_view_helper.Reset(); @@ -12787,7 +12824,7 @@ TEST_F(WebFrameSimTest, EnterFullscreenResetScrollAndScaleState) { UseAndroidSettings(); - WebView().Resize(WebSize(490, 500)); + WebView().MainFrameWidget()->Resize(WebSize(490, 500)); WebView().EnableFakePageScaleAnimationForTesting(true); WebView().GetSettings()->SetTextAutosizingEnabled(false); WebView().SetDefaultPageScaleLimits(0.5f, 4); @@ -12823,14 +12860,14 @@ std::unique_ptr<UserGestureIndicator> gesture = LocalFrame::NotifyUserActivation(frame); Fullscreen::RequestFullscreen(*element); - WebView().DidEnterFullscreen(); + WebView().MainFrameWidget()->DidEnterFullscreen(); // Page scale factor must be 1.0 during fullscreen for elements to be sized // properly. EXPECT_EQ(1.0f, WebView().PageScaleFactor()); // Confirm that exiting fullscreen restores back to default values. - WebView().DidExitFullscreen(); + WebView().MainFrameWidget()->DidExitFullscreen(); WebView().MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest);
diff --git a/third_party/blink/renderer/core/exported/web_layer_test.cc b/third_party/blink/renderer/core/exported/web_layer_test.cc index 20a1d46c..6e9ff4f 100644 --- a/third_party/blink/renderer/core/exported/web_layer_test.cc +++ b/third_party/blink/renderer/core/exported/web_layer_test.cc
@@ -218,7 +218,7 @@ class WebLayerListSimTest : public PaintTestConfigurations, public SimTest { public: void InitializeWithHTML(const String& html) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html");
diff --git a/third_party/blink/renderer/core/exported/web_node_test.cc b/third_party/blink/renderer/core/exported/web_node_test.cc index d16be0d..90573e49 100644 --- a/third_party/blink/renderer/core/exported/web_node_test.cc +++ b/third_party/blink/renderer/core/exported/web_node_test.cc
@@ -65,7 +65,7 @@ SimRequest css_resource("https://example.com/style.css", "text/css"); LoadURL("https://example.com/test.html"); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); main_resource.Start(); main_resource.Write(R"HTML(
diff --git a/third_party/blink/renderer/core/exported/web_plugin_container_test.cc b/third_party/blink/renderer/core/exported/web_plugin_container_test.cc index 6c1fffac..22785242 100644 --- a/third_party/blink/renderer/core/exported/web_plugin_container_test.cc +++ b/third_party/blink/renderer/core/exported/web_plugin_container_test.cc
@@ -286,7 +286,7 @@ WebPoint(30, 30), 0); event.click_count = 1; - web_view->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); EXPECT_TRUE( web_view->MainFrame()->ToWebLocalFrame()->ExecuteCommand(command_name)); } @@ -491,7 +491,7 @@ // Now, let's try a more complex scenario: // 1) open the context menu. This will focus the plugin. - web_view->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); // 2) document blurs the plugin, because it can. web_view->ClearFocusedElement(); // 3) Copy should still operate on the context node, even though the focus had @@ -794,7 +794,7 @@ // plugin doesn't receive it. event.SetPositionInWidget(WebFloatPoint(0, 0)); - web_view->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); RunPendingTasks(); EXPECT_EQ(WebInputEvent::kUndefined, test_plugin->GetLastInputEventType()); @@ -805,7 +805,7 @@ event.SetPositionInWidget( WebFloatPoint(rect.x + rect.width / 2, rect.y + rect.height / 2)); - web_view->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); RunPendingTasks(); EXPECT_EQ(WebInputEvent::kGestureLongPress, @@ -837,7 +837,7 @@ WebRect rect = plugin_container_one_element.BoundsInViewport(); event.SetPositionInWidget(rect.x + rect.width / 2, rect.y + rect.height / 2); - web_view->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); RunPendingTasks(); EXPECT_EQ(WebInputEvent::kMouseMove, test_plugin->GetLastInputEventType()); @@ -869,7 +869,7 @@ WebRect rect = plugin_container_one_element.BoundsInViewport(); event.SetPositionInWidget(rect.x + rect.width / 2, rect.y + rect.height / 2); - web_view->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); RunPendingTasks(); EXPECT_EQ(WebInputEvent::kMouseWheel, test_plugin->GetLastInputEventType()); @@ -909,8 +909,8 @@ WebFloatPoint(rect.x + rect.width / 2, rect.y + rect.height / 2)), 1.0f, 1.0f); - web_view->HandleInputEvent(WebCoalescedInputEvent(event)); - web_view->DispatchBufferedTouchEvents(); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view->MainFrameWidget()->DispatchBufferedTouchEvents(); RunPendingTasks(); EXPECT_EQ(WebInputEvent::kTouchStart, test_plugin->GetLastInputEventType()); @@ -953,8 +953,8 @@ WebCoalescedInputEvent coalesced_event(event); - web_view->HandleInputEvent(coalesced_event); - web_view->DispatchBufferedTouchEvents(); + web_view->MainFrameWidget()->HandleInputEvent(coalesced_event); + web_view->MainFrameWidget()->DispatchBufferedTouchEvents(); RunPendingTasks(); EXPECT_EQ(static_cast<const size_t>(1), @@ -1000,8 +1000,8 @@ coalesced_event.AddCoalescedEvent(event2); coalesced_event.AddCoalescedEvent(event3); - web_view->HandleInputEvent(coalesced_event); - web_view->DispatchBufferedTouchEvents(); + web_view->MainFrameWidget()->HandleInputEvent(coalesced_event); + web_view->MainFrameWidget()->DispatchBufferedTouchEvents(); RunPendingTasks(); EXPECT_EQ(static_cast<const size_t>(3), @@ -1041,7 +1041,7 @@ WebRect rect = plugin_container_one_element.BoundsInViewport(); event.SetPositionInWidget(rect.x + rect.width / 2, rect.y + rect.height / 2); - web_view->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); RunPendingTasks(); EXPECT_EQ(WebInputEvent::kMouseWheel, test_plugin->GetLastInputEventType()); @@ -1077,7 +1077,7 @@ WebRect rect = plugin_container_one_element.BoundsInViewport(); event.SetPositionInWidget(rect.x + rect.width / 2, rect.y + rect.height / 2); - web_view->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); RunPendingTasks(); EXPECT_EQ(WebInputEvent::kMouseMove, test_plugin->GetLastInputEventType()); @@ -1116,7 +1116,7 @@ WebRect rect = plugin_container_one_element.BoundsInViewport(); event.SetPositionInWidget(rect.x + rect.width / 2, rect.y + rect.height / 2); - web_view->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); RunPendingTasks(); // rect.width/height divided by 4 because the rect is in viewport bounds and @@ -1158,7 +1158,7 @@ WebRect rect = plugin_container_one_element.BoundsInViewport(); event.SetPositionInWidget(rect.x + rect.width / 2, rect.y + rect.height / 2); - web_view->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); RunPendingTasks(); // rect.width/height divided by 4 because the rect is in viewport bounds and @@ -1177,7 +1177,7 @@ base_url_ + "plugin_scroll.html", &plugin_web_frame_client); DCHECK(web_view); web_view->GetSettings()->SetPluginsEnabled(true); - web_view->Resize(WebSize(300, 300)); + web_view->MainFrameWidget()->Resize(WebSize(300, 300)); web_view->SetPageScaleFactor(2); web_view->SmoothScroll(0, 300, 0); UpdateAllLifecyclePhases(web_view); @@ -1203,8 +1203,8 @@ WebFloatPoint(rect.x + rect.width / 2, rect.y + rect.height / 2)), 1.0f, 1.0f); - web_view->HandleInputEvent(WebCoalescedInputEvent(event)); - web_view->DispatchBufferedTouchEvents(); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view->MainFrameWidget()->DispatchBufferedTouchEvents(); RunPendingTasks(); // rect.width/height divided by 4 because the rect is in viewport bounds and
diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc index e797c90..6a581e3 100644 --- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc +++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
@@ -33,6 +33,7 @@ #include <memory> #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/mojom/fetch_api.mojom-blink.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom-blink.h" #include "third_party/blink/public/mojom/script/script_type.mojom-blink.h" #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h" #include "third_party/blink/public/platform/task_type.h" @@ -41,7 +42,6 @@ #include "third_party/blink/public/platform/web_url.h" #include "third_party/blink/public/platform/web_url_request.h" #include "third_party/blink/public/platform/web_worker_fetch_context.h" -#include "third_party/blink/public/web/devtools_agent.mojom-blink.h" #include "third_party/blink/public/web/web_settings.h" #include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h" #include "third_party/blink/renderer/core/core_initializer.h" @@ -131,7 +131,7 @@ script_request_url_, mojom::RequestContextType::SHARED_WORKER, network::mojom::FetchRequestMode::kSameOrigin, network::mojom::FetchCredentialsMode::kSameOrigin, - creation_address_space_, false /* is_nested_worker */, + creation_address_space_, Bind(&WebSharedWorkerImpl::DidReceiveScriptLoaderResponse, WTF::Unretained(this)), Bind(&WebSharedWorkerImpl::OnScriptLoaderFinished,
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 6483d2d..b261cd6ba 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -1144,9 +1144,7 @@ } void WebViewImpl::ZoomToFindInPageRect(const WebRect& rect_in_root_frame) { - // TODO(lukasza): https://crbug.com/734209: Add OOPIF support. - if (!MainFrameImpl()) - return; + DCHECK(MainFrameImpl()); WebRect block_bounds = MainFrameImpl()->FrameWidgetImpl()->ComputeBlockBound( gfx::Point(rect_in_root_frame.x + rect_in_root_frame.width / 2,
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h index 71fa608..650fad4 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -111,47 +111,8 @@ static bool UseExternalPopupMenus(); // WebWidget methods: - void SetLayerTreeView(WebLayerTreeView*) override; - void Close() override; - WebSize Size() override; - void Resize(const WebSize&) override; - void ResizeVisualViewport(const WebSize&) override; - void DidEnterFullscreen() override; - void DidExitFullscreen() override; - - void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) override; - void BeginFrame(base::TimeTicks last_frame_time) override; - void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override; - void UpdateLifecycle(LifecycleUpdate requested_update, - LifecycleUpdateReason reason) override; - void UpdateAllLifecyclePhasesAndCompositeForTesting(bool do_raster) override; - void RequestPresentationCallbackForTesting( - base::OnceClosure callback) override; - void PaintContent(cc::PaintCanvas*, const WebRect&) override; - void PaintContentIgnoringCompositing(cc::PaintCanvas*, - const WebRect&) override; - void LayoutAndPaintAsync(base::OnceClosure callback) override; - void CompositeAndReadbackAsync( - base::OnceCallback<void(const SkBitmap&)> callback) override; - void ThemeChanged() override; - WebInputEventResult HandleInputEvent(const WebCoalescedInputEvent&) override; - WebInputEventResult DispatchBufferedTouchEvents() override; - void SetCursorVisibilityState(bool is_visible) override; - void ApplyViewportChanges(const ApplyViewportChangesArgs& args) override; - void RecordWheelAndTouchScrollingCount(bool has_scrolled_by_wheel, - bool has_scrolled_by_touch) override; - void MouseCaptureLost() override; - void SetFocus(bool enable) override; - SkColor BackgroundColor() const override; + // TODO(danakj): Make private or move to WebView API. WebPagePopupImpl* GetPagePopup() const override; - bool SelectionBounds(WebRect& anchor, WebRect& focus) const override; - bool IsAcceleratedCompositingActive() const override; - void WillCloseLayerTreeView() override; - void DidAcquirePointerLock() override; - void DidNotAcquirePointerLock() override; - void DidLosePointerLock() override; - void ShowContextMenu(WebMenuSourceType) override; - WebURL GetURLForDebugTrace() override; // WebView methods: bool IsWebView() const override { return true; } @@ -460,6 +421,48 @@ FRIEND_TEST_ALL_PREFIXES(WebFrameTest, DivScrollIntoEditableTestWithDeviceScaleFactor); + // WebWidget methods: + void SetLayerTreeView(WebLayerTreeView*) override; + void Close() override; + WebSize Size() override; + void Resize(const WebSize&) override; + void ResizeVisualViewport(const WebSize&) override; + void DidEnterFullscreen() override; + void DidExitFullscreen() override; + + void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) override; + void BeginFrame(base::TimeTicks last_frame_time) override; + void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override; + void UpdateLifecycle(LifecycleUpdate requested_update, + LifecycleUpdateReason reason) override; + void UpdateAllLifecyclePhasesAndCompositeForTesting(bool do_raster) override; + void RequestPresentationCallbackForTesting( + base::OnceClosure callback) override; + void PaintContent(cc::PaintCanvas*, const WebRect&) override; + void PaintContentIgnoringCompositing(cc::PaintCanvas*, + const WebRect&) override; + void LayoutAndPaintAsync(base::OnceClosure callback) override; + void CompositeAndReadbackAsync( + base::OnceCallback<void(const SkBitmap&)> callback) override; + void ThemeChanged() override; + WebInputEventResult HandleInputEvent(const WebCoalescedInputEvent&) override; + WebInputEventResult DispatchBufferedTouchEvents() override; + void SetCursorVisibilityState(bool is_visible) override; + void ApplyViewportChanges(const ApplyViewportChangesArgs& args) override; + void RecordWheelAndTouchScrollingCount(bool has_scrolled_by_wheel, + bool has_scrolled_by_touch) override; + void MouseCaptureLost() override; + void SetFocus(bool enable) override; + SkColor BackgroundColor() const override; + bool SelectionBounds(WebRect& anchor, WebRect& focus) const override; + bool IsAcceleratedCompositingActive() const override; + void WillCloseLayerTreeView() override; + void DidAcquirePointerLock() override; + void DidNotAcquirePointerLock() override; + void DidLosePointerLock() override; + void ShowContextMenu(WebMenuSourceType) override; + WebURL GetURLForDebugTrace() override; + void SetPageScaleFactorAndLocation(float, const FloatPoint&); void PropagateZoomFactorToLocalFrameRoots(Frame*, float);
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc index 03cbc57..9d707da7 100644 --- a/third_party/blink/renderer/core/exported/web_view_test.cc +++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -400,7 +400,7 @@ WebViewImpl* web_view = web_view_helper_.Initialize(); web_view->GetSettings()->SetLoadsImagesAutomatically(true); LoadFrame(web_view->MainFrameImpl(), url); - web_view->Resize(WebSize(400, 400)); + web_view->MainFrameWidget()->Resize(WebSize(400, 400)); std::string image_url = "http://www.test.com/non_existent.png"; @@ -417,7 +417,7 @@ WebViewImpl* web_view = web_view_helper_.Initialize(); web_view->GetSettings()->SetLoadsImagesAutomatically(true); LoadFrame(web_view->MainFrameImpl(), url); - web_view->Resize(WebSize(400, 400)); + web_view->MainFrameWidget()->Resize(WebSize(400, 400)); std::string image_url = "http://www.test.com/non_existent.png"; @@ -431,10 +431,10 @@ const SkColor kTranslucentPutty = SkColorSetARGB(0x80, 0xBF, 0xB1, 0x96); WebViewImpl* web_view = web_view_helper_.Initialize(); - EXPECT_EQ(SK_ColorWHITE, web_view->BackgroundColor()); + EXPECT_EQ(SK_ColorWHITE, web_view->MainFrameWidget()->BackgroundColor()); web_view->SetBaseBackgroundColor(SK_ColorBLUE); - EXPECT_EQ(SK_ColorBLUE, web_view->BackgroundColor()); + EXPECT_EQ(SK_ColorBLUE, web_view->MainFrameWidget()->BackgroundColor()); WebURL base_url = url_test_helpers::ToKURL("http://example.com/"); frame_test_helpers::LoadHTMLString( @@ -443,7 +443,7 @@ "{background-color:#227788}</style></head></" "html>", base_url); - EXPECT_EQ(kDarkCyan, web_view->BackgroundColor()); + EXPECT_EQ(kDarkCyan, web_view->MainFrameWidget()->BackgroundColor()); frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(), "<html><head><style>body " @@ -451,11 +451,11 @@ "style></head></html>", base_url); // Expected: red (50% alpha) blended atop base of SK_ColorBLUE. - EXPECT_EQ(0xFF80007F, web_view->BackgroundColor()); + EXPECT_EQ(0xFF80007F, web_view->MainFrameWidget()->BackgroundColor()); web_view->SetBaseBackgroundColor(kTranslucentPutty); // Expected: red (50% alpha) blended atop kTranslucentPutty. Note the alpha. - EXPECT_EQ(0xBFE93A31, web_view->BackgroundColor()); + EXPECT_EQ(0xBFE93A31, web_view->MainFrameWidget()->BackgroundColor()); web_view->SetBaseBackgroundColor(SK_ColorTRANSPARENT); frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(), @@ -464,7 +464,8 @@ "head></html>", base_url); // Expected: transparent on top of transparent will still be transparent. - EXPECT_EQ(SK_ColorTRANSPARENT, web_view->BackgroundColor()); + EXPECT_EQ(SK_ColorTRANSPARENT, + web_view->MainFrameWidget()->BackgroundColor()); LocalFrame* frame = web_view->MainFrameImpl()->GetFrame(); // The shutdown() calls are a hack to prevent this test @@ -490,16 +491,17 @@ WebView::Create(&web_view_client, &web_view_client, /*is_hidden=*/false, /*compositing_enabled=*/true, nullptr)); - EXPECT_NE(SK_ColorBLUE, web_view->BackgroundColor()); + EXPECT_NE(SK_ColorBLUE, web_view->MainFrameWidget()->BackgroundColor()); // webView does not have a frame yet, but we should still be able to set the // background color. web_view->SetBaseBackgroundColor(SK_ColorBLUE); - EXPECT_EQ(SK_ColorBLUE, web_view->BackgroundColor()); + EXPECT_EQ(SK_ColorBLUE, web_view->MainFrameWidget()->BackgroundColor()); frame_test_helpers::TestWebFrameClient web_frame_client; WebLocalFrame* frame = WebLocalFrame::CreateMainFrame( web_view, &web_frame_client, nullptr, nullptr); web_frame_client.Bind(frame); - web_view->Close(); + // This closes the WebView also. + web_view->MainFrameWidget()->Close(); } TEST_F(WebViewTest, SetBaseBackgroundColorAndBlendWithExistingContent) { @@ -513,7 +515,7 @@ // Set WebView background to green with alpha. web_view->SetBaseBackgroundColor(kAlphaGreen); web_view->GetSettings()->SetShouldClearDocumentBackground(false); - web_view->Resize(WebSize(kWidth, kHeight)); + web_view->MainFrameWidget()->Resize(WebSize(kWidth, kHeight)); UpdateAllLifecyclePhases(); // Set canvas background to red with alpha. @@ -552,36 +554,36 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + "visible_iframe.html"); - web_view->SetFocus(true); + web_view->MainFrameWidget()->SetFocus(true); web_view->SetIsActive(true); WebLocalFrameImpl* frame = web_view->MainFrameImpl(); EXPECT_TRUE(frame->GetFrame()->GetDocument()->IsHTMLDocument()); Document* document = frame->GetFrame()->GetDocument(); EXPECT_TRUE(document->hasFocus()); - web_view->SetFocus(false); + web_view->MainFrameWidget()->SetFocus(false); web_view->SetIsActive(false); EXPECT_FALSE(document->hasFocus()); - web_view->SetFocus(true); + web_view->MainFrameWidget()->SetFocus(true); web_view->SetIsActive(true); EXPECT_TRUE(document->hasFocus()); - web_view->SetFocus(true); + web_view->MainFrameWidget()->SetFocus(true); web_view->SetIsActive(false); EXPECT_FALSE(document->hasFocus()); - web_view->SetFocus(false); + web_view->MainFrameWidget()->SetFocus(false); web_view->SetIsActive(true); EXPECT_FALSE(document->hasFocus()); web_view->SetIsActive(false); - web_view->SetFocus(true); + web_view->MainFrameWidget()->SetFocus(true); EXPECT_TRUE(document->hasFocus()); web_view->SetIsActive(true); - web_view->SetFocus(false); + web_view->MainFrameWidget()->SetFocus(false); EXPECT_FALSE(document->hasFocus()); } TEST_F(WebViewTest, DocumentHasFocus) { WebViewImpl* web_view = web_view_helper_.Initialize(); - web_view->SetFocus(true); + web_view->MainFrameWidget()->SetFocus(true); WebURL base_url = url_test_helpers::ToKURL("http://example.com/"); frame_test_helpers::LoadHTMLString( @@ -608,11 +610,11 @@ log_element.TextContent().Utf8().data()); web_view->SetIsActive(false); - web_view->SetFocus(false); + web_view->MainFrameWidget()->SetFocus(false); EXPECT_FALSE(document->hasFocus()); EXPECT_TRUE(log_element.TextContent().IsEmpty()); - web_view->SetFocus(true); + web_view->MainFrameWidget()->SetFocus(true); EXPECT_TRUE(document->hasFocus()); EXPECT_STREQ("document.hasFocus(): true", log_element.TextContent().Utf8().data()); @@ -664,7 +666,7 @@ ToKURL(url), test::CoreTestDataPath("specify_size.html")); WebViewImpl* web_view = web_view_helper_.Initialize(); LoadFrame(web_view->MainFrameImpl(), url); - web_view->Resize(WebSize(100, 100)); + web_view->MainFrameWidget()->Resize(WebSize(100, 100)); gfx::Point hit_point(75, 75); // Image is at top left quandrant, so should not hit it. @@ -720,7 +722,7 @@ std::string url = RegisterMockedHttpURLLoad("hit_test.html"); WebViewImpl* web_view = web_view_helper_.Initialize(); LoadFrame(web_view->MainFrameImpl(), url); - web_view->Resize(WebSize(100, 100)); + web_view->MainFrameWidget()->Resize(WebSize(100, 100)); gfx::Point hit_point(55, 55); // Image is at top left quandrant, so should not hit it. @@ -1047,7 +1049,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + "input_placeholder.html"); web_view->SetInitialFocus(false); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -1063,7 +1065,8 @@ kWebGestureDeviceTouchscreen); event.SetPositionInWidget(WebFloatPoint(100, 150)); EXPECT_EQ(WebInputEventResult::kHandledSystem, - web_view->HandleInputEvent(WebCoalescedInputEvent(event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(event))); EXPECT_TRUE(web_view->MainFrameImpl()->SelectionAsText().IsEmpty()); } @@ -1424,7 +1427,7 @@ RegisterMockedHttpURLLoad("form_with_input.html"); WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + "form_with_input.html"); - web_view->Resize(WebSize(800, 600)); + web_view->MainFrameWidget()->Resize(WebSize(800, 600)); web_view->SetInitialFocus(false); EXPECT_EQ(0, web_view->MainFrameImpl()->GetScrollOffset().width); EXPECT_EQ(0, web_view->MainFrameImpl()->GetScrollOffset().height); @@ -1727,7 +1730,7 @@ EXPECT_TRUE(frame->IsSelectionAnchorFirst()); WebRect anchor; WebRect focus; - web_view->SelectionBounds(anchor, focus); + web_view->MainFrameWidget()->SelectionBounds(anchor, focus); frame->SelectRange(WebPoint(focus.x, focus.y), WebPoint(anchor.x, anchor.y)); EXPECT_FALSE(frame->IsSelectionAnchorFirst()); } @@ -2232,7 +2235,7 @@ RegisterMockedHttpURLLoad("200-by-300.html"); WebViewImpl* web_view_impl = web_view_helper_.InitializeAndLoad(base_url_ + "200-by-300.html"); - web_view_impl->Resize(WebSize(200, 300)); + web_view_impl->MainFrameWidget()->Resize(WebSize(200, 300)); float page_scale_expected = web_view_impl->PageScaleFactor(); @@ -2254,7 +2257,7 @@ RegisterMockedHttpURLLoad("200-by-300.html"); WebViewImpl* web_view_impl = web_view_helper_.InitializeAndLoad(base_url_ + "200-by-300.html"); - web_view_impl->Resize(WebSize(100, 150)); + web_view_impl->MainFrameWidget()->Resize(WebSize(100, 150)); UpdateAllLifecyclePhases(); EXPECT_EQ(0, web_view_impl->MainFrameImpl()->GetScrollOffset().width); EXPECT_EQ(0, web_view_impl->MainFrameImpl()->GetScrollOffset().height); @@ -2299,7 +2302,7 @@ RegisterMockedHttpURLLoad("back_forward_restore_scroll.html"); WebViewImpl* web_view_impl = web_view_helper_.InitializeAndLoad( base_url_ + "back_forward_restore_scroll.html"); - web_view_impl->Resize(WebSize(640, 480)); + web_view_impl->MainFrameWidget()->Resize(WebSize(640, 480)); web_view_impl->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); @@ -2353,7 +2356,7 @@ RegisterMockedHttpURLLoad("fullscreen_style.html"); WebViewImpl* web_view_impl = web_view_helper_.InitializeAndLoad(base_url_ + "fullscreen_style.html"); - web_view_impl->Resize(WebSize(800, 600)); + web_view_impl->MainFrameWidget()->Resize(WebSize(800, 600)); UpdateAllLifecyclePhases(); // Scroll the page down. @@ -2366,7 +2369,7 @@ std::unique_ptr<UserGestureIndicator> gesture = LocalFrame::NotifyUserActivation(frame); Fullscreen::RequestFullscreen(*element); - web_view_impl->DidEnterFullscreen(); + web_view_impl->MainFrameWidget()->DidEnterFullscreen(); UpdateAllLifecyclePhases(); // Assert the scroll position on the document element doesn't change. @@ -2374,7 +2377,7 @@ web_view_impl->MainFrameImpl()->SetScrollOffset(WebSize(0, 2100)); - web_view_impl->DidExitFullscreen(); + web_view_impl->MainFrameWidget()->DidExitFullscreen(); UpdateAllLifecyclePhases(); EXPECT_EQ(2100, web_view_impl->MainFrameImpl()->GetScrollOffset().height); @@ -2385,9 +2388,9 @@ RegisterMockedHttpURLLoad("fullscreen_style.html"); WebViewImpl* web_view_impl = web_view_helper_.InitializeAndLoad(base_url_ + "fullscreen_style.html"); - web_view_impl->Resize(WebSize(800, 600)); + web_view_impl->MainFrameWidget()->Resize(WebSize(800, 600)); UpdateAllLifecyclePhases(); - EXPECT_EQ(SK_ColorWHITE, web_view_impl->BackgroundColor()); + EXPECT_EQ(SK_ColorWHITE, web_view_impl->MainFrameWidget()->BackgroundColor()); // Enter fullscreen. LocalFrame* frame = web_view_impl->MainFrameImpl()->GetFrame(); @@ -2396,10 +2399,11 @@ std::unique_ptr<UserGestureIndicator> gesture = LocalFrame::NotifyUserActivation(frame); Fullscreen::RequestFullscreen(*element); - web_view_impl->DidEnterFullscreen(); + web_view_impl->MainFrameWidget()->DidEnterFullscreen(); UpdateAllLifecyclePhases(); - EXPECT_EQ(SK_ColorYELLOW, web_view_impl->BackgroundColor()); + EXPECT_EQ(SK_ColorYELLOW, + web_view_impl->MainFrameWidget()->BackgroundColor()); } class PrintWebViewClient : public frame_test_helpers::TestWebViewClient { @@ -2500,7 +2504,7 @@ kWebGestureDeviceTouchscreen); event.SetPositionInWidget(center); - web_view_helper_.GetWebView()->HandleInputEvent( + web_view_helper_.GetWebView()->MainFrameWidget()->HandleInputEvent( WebCoalescedInputEvent(event)); RunPendingTasks(); return true; @@ -2567,8 +2571,10 @@ kWebGestureDeviceTouchscreen); event.SetPositionInWidget(WebFloatPoint(3, 8)); EXPECT_EQ(WebInputEventResult::kNotHandled, - web_view->HandleInputEvent(WebCoalescedInputEvent(event))); - web_view->Close(); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(event))); + // This also closes the WebView. + web_view->MainFrameWidget()->Close(); } TEST_F(WebViewTest, LongPressEmptyDiv) { @@ -2577,7 +2583,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "long_press_empty_div.html"); web_view->SettingsImpl()->SetAlwaysShowContextMenuOnTouch(false); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -2588,7 +2594,8 @@ event.SetPositionInWidget(WebFloatPoint(250, 150)); EXPECT_EQ(WebInputEventResult::kNotHandled, - web_view->HandleInputEvent(WebCoalescedInputEvent(event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(event))); } TEST_F(WebViewTest, LongPressEmptyDivAlwaysShow) { @@ -2597,7 +2604,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "long_press_empty_div.html"); web_view->SettingsImpl()->SetAlwaysShowContextMenuOnTouch(true); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -2608,7 +2615,8 @@ event.SetPositionInWidget(WebFloatPoint(250, 150)); EXPECT_EQ(WebInputEventResult::kHandledSystem, - web_view->HandleInputEvent(WebCoalescedInputEvent(event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(event))); } TEST_F(WebViewTest, LongPressObject) { @@ -2617,7 +2625,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + "long_press_object.html"); web_view->SettingsImpl()->SetAlwaysShowContextMenuOnTouch(true); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -2628,7 +2636,8 @@ event.SetPositionInWidget(WebFloatPoint(10, 10)); EXPECT_NE(WebInputEventResult::kHandledSystem, - web_view->HandleInputEvent(WebCoalescedInputEvent(event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(event))); HTMLElement* element = ToHTMLElement( web_view->MainFrameImpl()->GetDocument().GetElementById("obj")); @@ -2641,7 +2650,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "long_press_object_fallback.html"); web_view->SettingsImpl()->SetAlwaysShowContextMenuOnTouch(true); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -2652,7 +2661,8 @@ event.SetPositionInWidget(WebFloatPoint(10, 10)); EXPECT_EQ(WebInputEventResult::kHandledSystem, - web_view->HandleInputEvent(WebCoalescedInputEvent(event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(event))); HTMLElement* element = ToHTMLElement( web_view->MainFrameImpl()->GetDocument().GetElementById("obj")); @@ -2665,7 +2675,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + "long_press_image.html"); web_view->SettingsImpl()->SetAlwaysShowContextMenuOnTouch(false); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -2676,7 +2686,8 @@ event.SetPositionInWidget(WebFloatPoint(10, 10)); EXPECT_EQ(WebInputEventResult::kHandledSystem, - web_view->HandleInputEvent(WebCoalescedInputEvent(event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(event))); } TEST_F(WebViewTest, LongPressVideo) { @@ -2685,7 +2696,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + "long_press_video.html"); web_view->SettingsImpl()->SetAlwaysShowContextMenuOnTouch(false); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -2696,7 +2707,8 @@ event.SetPositionInWidget(WebFloatPoint(10, 10)); EXPECT_EQ(WebInputEventResult::kHandledSystem, - web_view->HandleInputEvent(WebCoalescedInputEvent(event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(event))); } TEST_F(WebViewTest, LongPressLink) { @@ -2705,7 +2717,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + "long_press_link.html"); web_view->SettingsImpl()->SetAlwaysShowContextMenuOnTouch(false); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -2716,7 +2728,8 @@ event.SetPositionInWidget(WebFloatPoint(500, 300)); EXPECT_EQ(WebInputEventResult::kHandledSystem, - web_view->HandleInputEvent(WebCoalescedInputEvent(event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(event))); } // Tests that we send touchcancel when drag start by long press. @@ -2730,7 +2743,7 @@ base_url_ + "long_press_draggable_div.html"); web_view->SettingsImpl()->SetTouchDragDropEnabled(true); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -2738,8 +2751,9 @@ WebInputEvent::kPointerDown, WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5); pointer_down.SetPositionInWidget(250, 8); - web_view->HandleInputEvent(WebCoalescedInputEvent(pointer_down)); - web_view->DispatchBufferedTouchEvents(); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(pointer_down)); + web_view->MainFrameWidget()->DispatchBufferedTouchEvents(); WebString target_id = WebString::FromUTF8("target"); @@ -2754,8 +2768,9 @@ WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5); pointer_cancel.SetPositionInWidget(250, 8); EXPECT_NE(WebInputEventResult::kHandledSuppressed, - web_view->HandleInputEvent(WebCoalescedInputEvent(pointer_cancel))); - web_view->DispatchBufferedTouchEvents(); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(pointer_cancel))); + web_view->MainFrameWidget()->DispatchBufferedTouchEvents(); EXPECT_STREQ("touchcancel", web_view->MainFrameImpl()->GetDocument().Title().Utf8().data()); } @@ -2770,7 +2785,7 @@ base_url_ + "long_press_links_and_images.html"); web_view->SettingsImpl()->SetTouchDragDropEnabled(true); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -2792,7 +2807,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "long_press_empty_editable_selection.html"); web_view->SettingsImpl()->SetAlwaysShowContextMenuOnTouch(false); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -2803,7 +2818,8 @@ event.SetPositionInWidget(WebFloatPoint(10, 10)); EXPECT_EQ(WebInputEventResult::kHandledSystem, - web_view->HandleInputEvent(WebCoalescedInputEvent(event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(event))); } TEST_F(WebViewTest, LongPressEmptyNonEditableSelection) { @@ -2811,7 +2827,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + "long_press_image.html"); - web_view->Resize(WebSize(500, 500)); + web_view->MainFrameWidget()->Resize(WebSize(500, 500)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -2823,7 +2839,8 @@ WebLocalFrameImpl* frame = web_view->MainFrameImpl(); EXPECT_EQ(WebInputEventResult::kHandledSystem, - web_view->HandleInputEvent(WebCoalescedInputEvent(event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(event))); EXPECT_TRUE(frame->SelectionAsText().IsEmpty()); } @@ -2832,7 +2849,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "longpress_selection.html"); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -2852,7 +2869,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "longpress_selection.html"); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -2888,7 +2905,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + "longpress_textarea.html"); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -2907,7 +2924,7 @@ event.SetPositionInWidget(WebFloatPoint(100, 25)); event.data.tap.tap_count = 2; - web_view->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); EXPECT_TRUE(frame->SelectionAsText().IsEmpty()); HTMLTextAreaElement* text_area_element = ToHTMLTextAreaElement( @@ -2921,7 +2938,7 @@ EXPECT_TRUE(frame->SelectionAsText().IsEmpty()); // Double-tap past last word of textbox. - web_view->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view->MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent(event)); EXPECT_TRUE(frame->SelectionAsText().IsEmpty()); } #endif @@ -2931,7 +2948,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "longpress_image_contenteditable.html"); - web_view->Resize(WebSize(500, 300)); + web_view->MainFrameWidget()->Resize(WebSize(500, 300)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -2951,7 +2968,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "blink_caret_on_typing_after_long_press.html"); - web_view->Resize(WebSize(640, 480)); + web_view->MainFrameWidget()->Resize(WebSize(640, 480)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -2980,7 +2997,8 @@ mouse_event.button = WebMouseEvent::Button::kRight; mouse_event.SetPositionInWidget(1, 1); mouse_event.click_count = 1; - web_view->HandleInputEvent(WebCoalescedInputEvent(mouse_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(mouse_event)); RunPendingTasks(); WebLocalFrameImpl* main_frame = web_view->MainFrameImpl(); @@ -3000,7 +3018,7 @@ RegisterMockedHttpURLLoad("selection_readonly.html"); WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + "selection_readonly.html"); - web_view->Resize(WebSize(640, 480)); + web_view->MainFrameWidget()->Resize(WebSize(640, 480)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -3022,7 +3040,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + "content-width-1000.html"); - web_view->Resize(WebSize(100, 100)); + web_view->MainFrameWidget()->Resize(WebSize(100, 100)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -3033,60 +3051,74 @@ // RawKeyDown pagedown should be handled. key_event.windows_key_code = VKEY_NEXT; EXPECT_EQ(WebInputEventResult::kHandledSystem, - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event))); key_event.SetType(WebInputEvent::kKeyUp); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); // Coalesced KeyDown arrow-down should be handled. key_event.windows_key_code = VKEY_DOWN; key_event.SetType(WebInputEvent::kKeyDown); EXPECT_EQ(WebInputEventResult::kHandledSystem, - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event))); key_event.SetType(WebInputEvent::kKeyUp); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); // Ctrl-Home should be handled... key_event.windows_key_code = VKEY_HOME; key_event.SetModifiers(WebInputEvent::kControlKey); key_event.SetType(WebInputEvent::kRawKeyDown); EXPECT_EQ(WebInputEventResult::kNotHandled, - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event))); key_event.SetType(WebInputEvent::kKeyUp); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); // But Ctrl-Down should not. key_event.windows_key_code = VKEY_DOWN; key_event.SetModifiers(WebInputEvent::kControlKey); key_event.SetType(WebInputEvent::kRawKeyDown); EXPECT_EQ(WebInputEventResult::kNotHandled, - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event))); key_event.SetType(WebInputEvent::kKeyUp); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); // Shift, meta, and alt should not be handled. key_event.windows_key_code = VKEY_NEXT; key_event.SetModifiers(WebInputEvent::kShiftKey); key_event.SetType(WebInputEvent::kRawKeyDown); EXPECT_EQ(WebInputEventResult::kNotHandled, - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event))); key_event.SetType(WebInputEvent::kKeyUp); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); key_event.windows_key_code = VKEY_NEXT; key_event.SetModifiers(WebInputEvent::kMetaKey); key_event.SetType(WebInputEvent::kRawKeyDown); EXPECT_EQ(WebInputEventResult::kNotHandled, - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event))); key_event.SetType(WebInputEvent::kKeyUp); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); key_event.windows_key_code = VKEY_NEXT; key_event.SetModifiers(WebInputEvent::kAltKey); key_event.SetType(WebInputEvent::kRawKeyDown); EXPECT_EQ(WebInputEventResult::kNotHandled, - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event))); key_event.SetType(WebInputEvent::kKeyUp); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); // System-key labeled Alt-Down (as in Windows) should do nothing, // but non-system-key labeled Alt-Down (as in Mac) should be handled @@ -3096,18 +3128,22 @@ key_event.is_system_key = true; key_event.SetType(WebInputEvent::kRawKeyDown); EXPECT_EQ(WebInputEventResult::kNotHandled, - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event))); key_event.SetType(WebInputEvent::kKeyUp); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); key_event.windows_key_code = VKEY_DOWN; key_event.SetModifiers(WebInputEvent::kAltKey); key_event.is_system_key = false; key_event.SetType(WebInputEvent::kRawKeyDown); EXPECT_EQ(WebInputEventResult::kHandledSystem, - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event))); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event))); key_event.SetType(WebInputEvent::kKeyUp); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); } class MiddleClickAutoscrollWebWidgetClient @@ -3132,7 +3168,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "content-width-1000.html", nullptr, nullptr, &client); - web_view->Resize(WebSize(100, 100)); + web_view->MainFrameWidget()->Resize(WebSize(100, 100)); UpdateAllLifecyclePhases(); RunPendingTasks(); @@ -3144,9 +3180,11 @@ mouse_event.click_count = 1; // Start middle-click autoscroll. - web_view->HandleInputEvent(WebCoalescedInputEvent(mouse_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(mouse_event)); mouse_event.SetType(WebInputEvent::kMouseUp); - web_view->HandleInputEvent(WebCoalescedInputEvent(mouse_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(mouse_event)); EXPECT_EQ(MiddlePanningCursor().GetType(), client.GetLastCursorType()); @@ -3161,9 +3199,11 @@ // End middle-click autoscroll. mouse_event.SetType(WebInputEvent::kMouseDown); - web_view->HandleInputEvent(WebCoalescedInputEvent(mouse_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(mouse_event)); mouse_event.SetType(WebInputEvent::kMouseUp); - web_view->HandleInputEvent(WebCoalescedInputEvent(mouse_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(mouse_event)); web_view->GetChromeClient().SetCursorForPlugin(WebCursorInfo(IBeamCursor()), local_frame); @@ -3181,7 +3221,7 @@ int page_width = 640; int page_height = 480; - web_view_impl->Resize(WebSize(page_width, page_height)); + web_view_impl->MainFrameWidget()->Resize(WebSize(page_width, page_height)); WebURL base_url = url_test_helpers::ToKURL("http://example.com/"); frame_test_helpers::LoadHTMLString( @@ -3198,7 +3238,8 @@ event.SetPositionInWidget(WebFloatPoint(20, 20)); // Just make sure we don't hit any asserts. - web_view_impl->HandleInputEvent(WebCoalescedInputEvent(event)); + web_view_impl->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(event)); } class MockAutofillClient : public WebAutofillClient { @@ -3254,7 +3295,7 @@ // Clear the focus and track that the subsequent composition commit does not // trigger a text changed notification for autofill. client.ClearChangeCounts(); - web_view->SetFocus(false); + web_view->MainFrameWidget()->SetFocus(false); EXPECT_EQ(0, client.TextChanges()); frame->SetAutofillClient(nullptr); @@ -3302,7 +3343,8 @@ WebInputEvent::GetStaticTimeStampForTests()); key_event.dom_key = Platform::Current()->DomKeyEnumFromString("\b"); key_event.windows_key_code = VKEY_BACK; - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); frame->SetEditableSelectionOffsets(6, 6); EXPECT_TRUE(active_input_method_controller->SetComposition( @@ -3312,7 +3354,8 @@ "after pressing Backspace"); key_event.SetType(WebInputEvent::kKeyUp); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); web_view->AdvanceFocus(false); } @@ -3479,9 +3522,9 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "focusout_focusin_events.html"); - web_view->SetFocus(true); - web_view->SetFocus(false); - web_view->SetFocus(true); + web_view->MainFrameWidget()->SetFocus(true); + web_view->MainFrameWidget()->SetFocus(false); + web_view->MainFrameWidget()->SetFocus(true); WebElement element = web_view->MainFrameImpl()->GetDocument().GetElementById("message"); @@ -3493,9 +3536,9 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "domfocusout_domfocusin_events.html"); - web_view->SetFocus(true); - web_view->SetFocus(false); - web_view->SetFocus(true); + web_view->MainFrameWidget()->SetFocus(true); + web_view->MainFrameWidget()->SetFocus(false); + web_view->MainFrameWidget()->SetFocus(true); WebElement element = web_view->MainFrameImpl()->GetDocument().GetElementById("message"); @@ -3606,9 +3649,9 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + "focus_blur_events.html"); - web_view->SetFocus(true); - web_view->SetFocus(false); - web_view->SetFocus(true); + web_view->MainFrameWidget()->SetFocus(true); + web_view->MainFrameWidget()->SetFocus(false); + web_view->MainFrameWidget()->SetFocus(true); WebElement element = web_view->MainFrameImpl()->GetDocument().GetElementById("message"); @@ -3909,7 +3952,7 @@ document->SetFocusedElement( input_element, FocusParams(SelectionBehaviorOnFocus::kNone, kWebFocusTypeNone, nullptr)); - web_view_impl->SetFocus(true); + web_view_impl->MainFrameWidget()->SetFocus(true); WebTextInputInfo info1 = active_input_method_controller->TextInputInfo(); EXPECT_EQ(kWebTextInputFlagAutocompleteOff | kWebTextInputFlagAutocorrectOff | kWebTextInputFlagSpellcheckOff | @@ -3922,7 +3965,7 @@ document->SetFocusedElement( input_element, FocusParams(SelectionBehaviorOnFocus::kNone, kWebFocusTypeNone, nullptr)); - web_view_impl->SetFocus(true); + web_view_impl->MainFrameWidget()->SetFocus(true); WebTextInputInfo info2 = active_input_method_controller->TextInputInfo(); EXPECT_EQ(kWebTextInputFlagAutocompleteOn | kWebTextInputFlagAutocorrectOn | kWebTextInputFlagSpellcheckOn | @@ -3936,7 +3979,7 @@ document->SetFocusedElement( text_area_element, FocusParams(SelectionBehaviorOnFocus::kNone, kWebFocusTypeNone, nullptr)); - web_view_impl->SetFocus(true); + web_view_impl->MainFrameWidget()->SetFocus(true); WebTextInputInfo info3 = active_input_method_controller->TextInputInfo(); EXPECT_EQ(kWebTextInputFlagAutocapitalizeSentences, info3.flags); @@ -3966,9 +4009,11 @@ WebInputEvent::GetStaticTimeStampForTests()); key_event.dom_key = Platform::Current()->DomKeyEnumFromString(" "); key_event.windows_key_code = VKEY_SPACE; - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); key_event.SetType(WebInputEvent::kKeyUp); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); EXPECT_EQ(2, client.GetUserGestureNotificationsCount()); frame->SetAutofillClient(nullptr); @@ -3991,9 +4036,11 @@ mouse_event.button = WebMouseEvent::Button::kLeft; mouse_event.SetPositionInWidget(1, 1); mouse_event.click_count = 1; - web_view->HandleInputEvent(WebCoalescedInputEvent(mouse_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(mouse_event)); mouse_event.SetType(WebInputEvent::kMouseUp); - web_view->HandleInputEvent(WebCoalescedInputEvent(mouse_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(mouse_event)); EXPECT_EQ(1, client.GetUserGestureNotificationsCount()); frame->SetAutofillClient(nullptr); @@ -4096,7 +4143,7 @@ TEST_F(WebViewTest, PreferredMinimumSizeQuirksMode) { WebViewImpl* web_view = web_view_helper_.Initialize(); - web_view->Resize(WebSize(800, 600)); + web_view->MainFrameWidget()->Resize(WebSize(800, 600)); frame_test_helpers::LoadHTMLString( web_view->MainFrameImpl(), R"HTML(<html> @@ -4255,7 +4302,7 @@ WebString::FromUTF8(base_url_ + test_file), web_view_helper_)); web_view_ = mojo_test_helper_->WebView(); - web_view_->Resize(WebSize(500, 300)); + web_view_->MainFrameWidget()->Resize(WebSize(500, 300)); web_view_->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); RunPendingTasks(); @@ -4405,7 +4452,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "content_editable_populated.html"); web_view->GetSettings()->SetDefaultFontSize(12); - web_view->Resize(WebSize(400, 400)); + web_view->MainFrameWidget()->Resize(WebSize(400, 400)); WebLocalFrameImpl* frame = web_view->MainFrameImpl(); WebPoint baseline_point; @@ -4435,7 +4482,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "content_editable_multiline.html"); web_view->GetSettings()->SetDefaultFontSize(12); - web_view->Resize(WebSize(400, 400)); + web_view->MainFrameWidget()->Resize(WebSize(400, 400)); WebLocalFrameImpl* frame = web_view->MainFrameImpl(); WebPoint old_point; @@ -4453,7 +4500,7 @@ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( base_url_ + "content_editable_populated.html"); web_view->GetSettings()->SetDefaultFontSize(12); - web_view->Resize(WebSize(400, 400)); + web_view->MainFrameWidget()->Resize(WebSize(400, 400)); WebLocalFrameImpl* frame = web_view->MainFrameImpl(); NSAttributedString* result = nil; @@ -4482,7 +4529,7 @@ web_view_helper_.InitializeAndLoad(base_url_ + "single_iframe.html"); web_view->GetSettings()->SetDefaultFontSize(12); web_view->GetSettings()->SetJavaScriptEnabled(true); - web_view->Resize(WebSize(400, 400)); + web_view->MainFrameWidget()->Resize(WebSize(400, 400)); WebLocalFrameImpl* main_frame = web_view->MainFrameImpl(); WebLocalFrameImpl* child_frame = WebLocalFrameImpl::FromFrame( ToLocalFrame(main_frame->GetFrame()->Tree().FirstChild())); @@ -4639,7 +4686,7 @@ RegisterMockedHttpURLLoad("200-by-300.html"); WebViewImpl* web_view_impl = web_view_helper_.InitializeAndLoad(base_url_ + "200-by-300.html"); - web_view_impl->Resize(WebSize(100, 150)); + web_view_impl->MainFrameWidget()->Resize(WebSize(100, 150)); SetViewportSize(WebSize(100, 150)); VisualViewport* visual_viewport = &web_view_impl->GetPage()->GetVisualViewport(); @@ -4685,7 +4732,7 @@ RegisterMockedHttpURLLoad("200-by-300.html"); WebViewImpl* web_view_impl = web_view_helper_.InitializeAndLoad(base_url_ + "200-by-300.html"); - web_view_impl->Resize(WebSize(100, 150)); + web_view_impl->MainFrameWidget()->Resize(WebSize(100, 150)); TransformationMatrix expected_matrix; expected_matrix.MakeIdentity(); @@ -4714,7 +4761,7 @@ RegisterMockedHttpURLLoad("200-by-300.html"); WebViewImpl* web_view_impl = web_view_helper_.InitializeAndLoad(base_url_ + "200-by-300.html"); - web_view_impl->Resize(WebSize(100, 150)); + web_view_impl->MainFrameWidget()->Resize(WebSize(100, 150)); SetViewportSize(WebSize(100, 150)); LocalFrameView* frame_view = web_view_impl->MainFrameImpl()->GetFrame()->View(); @@ -4772,7 +4819,7 @@ TEST_F(WebViewTest, ResizeForPrintingViewportUnits) { WebViewImpl* web_view = web_view_helper_.Initialize(); - web_view->Resize(WebSize(800, 600)); + web_view->MainFrameWidget()->Resize(WebSize(800, 600)); WebURL base_url = url_test_helpers::ToKURL("http://example.com/"); frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(), @@ -4802,12 +4849,12 @@ EXPECT_EQ(expected_size.Width(), vw_element->OffsetWidth()); EXPECT_EQ(expected_size.Height(), vw_element->OffsetHeight()); - web_view->Resize(FlooredIntSize(page_size)); + web_view->MainFrameWidget()->Resize(FlooredIntSize(page_size)); EXPECT_EQ(expected_size.Width(), vw_element->OffsetWidth()); EXPECT_EQ(expected_size.Height(), vw_element->OffsetHeight()); - web_view->Resize(WebSize(800, 600)); + web_view->MainFrameWidget()->Resize(WebSize(800, 600)); frame->PrintEnd(); EXPECT_EQ(800, vw_element->OffsetWidth()); @@ -4815,7 +4862,7 @@ TEST_F(WebViewTest, WidthMediaQueryWithPageZoomAfterPrinting) { WebViewImpl* web_view = web_view_helper_.Initialize(); - web_view->Resize(WebSize(800, 600)); + web_view->MainFrameWidget()->Resize(WebSize(800, 600)); web_view->SetZoomLevel(WebView::ZoomFactorToZoomLevel(2.0)); WebURL base_url = url_test_helpers::ToKURL("http://example.com/"); @@ -4850,7 +4897,7 @@ TEST_F(WebViewTest, ViewportUnitsPrintingWithPageZoom) { WebViewImpl* web_view = web_view_helper_.Initialize(); - web_view->Resize(WebSize(800, 600)); + web_view->MainFrameWidget()->Resize(WebSize(800, 600)); web_view->SetZoomLevel(WebView::ZoomFactorToZoomLevel(2.0)); WebURL base_url = url_test_helpers::ToKURL("http://example.com/"); @@ -4889,7 +4936,7 @@ TEST_F(WebViewTest, DeviceEmulationResetScrollbars) { WebViewImpl* web_view = web_view_helper_.Initialize(); - web_view->Resize(WebSize(800, 600)); + web_view->MainFrameWidget()->Resize(WebSize(800, 600)); WebURL base_url = url_test_helpers::ToKURL("http://example.com/"); frame_test_helpers::LoadHTMLString(web_view->MainFrameImpl(), @@ -5051,7 +5098,8 @@ key_event1.windows_key_code = VKEY_SPACE; key_event1.SetTimeStamp(CurrentTimeTicks()); clock.Advance(TimeDelta::FromMilliseconds(50)); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event1)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event1)); EXPECT_NEAR(50, interactive_detector->GetFirstInputDelay().InMillisecondsF(), 0.01); @@ -5067,7 +5115,8 @@ key_event2.windows_key_code = VKEY_SPACE; clock.Advance(TimeDelta::FromMilliseconds(60)); key_event2.SetTimeStamp(CurrentTimeTicks()); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event2)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event2)); EXPECT_NEAR(50, interactive_detector->GetFirstInputDelay().InMillisecondsF(), 0.01); @@ -5105,7 +5154,8 @@ key_event1.windows_key_code = VKEY_SPACE; key_event1.SetTimeStamp(CurrentTimeTicks()); clock.Advance(TimeDelta::FromMilliseconds(50)); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event1)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event1)); TimeTicks longest_input_timestamp = CurrentTimeTicks(); @@ -5116,7 +5166,8 @@ key_event2.windows_key_code = VKEY_SPACE; key_event2.SetTimeStamp(longest_input_timestamp); clock.Advance(TimeDelta::FromMilliseconds(100)); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event2)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event2)); WebKeyboardEvent key_event3(WebInputEvent::kRawKeyDown, WebInputEvent::kNoModifiers, @@ -5125,7 +5176,8 @@ key_event3.windows_key_code = VKEY_SPACE; key_event3.SetTimeStamp(CurrentTimeTicks()); clock.Advance(TimeDelta::FromMilliseconds(70)); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event3)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event3)); EXPECT_NEAR(100, interactive_detector->GetLongestInputDelay().InMillisecondsF(), @@ -5154,7 +5206,8 @@ key_event1.windows_key_code = VKEY_SPACE; key_event1.SetTimeStamp(CurrentTimeTicks()); clock.Advance(TimeDelta::FromMilliseconds(50)); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event1)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event1)); WebKeyboardEvent key_event2(WebInputEvent::kRawKeyDown, WebInputEvent::kNoModifiers, @@ -5163,7 +5216,8 @@ key_event2.windows_key_code = VKEY_SPACE; key_event2.SetTimeStamp(CurrentTimeTicks()); clock.Advance(TimeDelta::FromMilliseconds(50)); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event2)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event2)); WebKeyboardEvent key_event3(WebInputEvent::kRawKeyDown, WebInputEvent::kNoModifiers, @@ -5172,7 +5226,8 @@ key_event3.windows_key_code = VKEY_SPACE; key_event3.SetTimeStamp(CurrentTimeTicks()); clock.Advance(TimeDelta::FromMilliseconds(70)); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event3)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event3)); histogram_tester.ExpectTotalCount("PageLoad.InteractiveTiming.InputDelay", 3); histogram_tester.ExpectBucketCount("PageLoad.InteractiveTiming.InputDelay", 50, 2); @@ -5215,7 +5270,8 @@ TimeTicks key_event1_time = CurrentTimeTicks(); key_event1.SetTimeStamp(key_event1_time); clock.Advance(TimeDelta::FromMilliseconds(50)); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event1)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event1)); WebKeyboardEvent key_event2(WebInputEvent::kRawKeyDown, WebInputEvent::kNoModifiers, @@ -5229,7 +5285,8 @@ web_view->SetIsHidden(/*is_hidden=*/false, /*initial_state=*/false); clock.Advance(TimeDelta::FromMilliseconds(100)); // Total input delay is >300ms. - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event2)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event2)); EXPECT_NEAR( 50, interactive_detector->GetLongestInputDelay().InMillisecondsF(), 0.01); @@ -5267,7 +5324,8 @@ key_event.SetTimeStamp(CurrentTimeTicks()); clock.Advance(TimeDelta::FromMilliseconds(100)); web_view->SetIsHidden(/*is_hidden=*/false, /*initial_state=*/false); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); EXPECT_TRUE(interactive_detector->GetLongestInputDelay().is_zero()); } @@ -5308,7 +5366,8 @@ TimeTicks key_event_time = CurrentTimeTicks(); key_event.SetTimeStamp(key_event_time); clock.Advance(TimeDelta::FromMilliseconds(50)); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); EXPECT_NEAR( 50, interactive_detector->GetLongestInputDelay().InMillisecondsF(), 0.01); @@ -5341,7 +5400,8 @@ WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5); pointer_down.SetTimeStamp(CurrentTimeTicks()); clock.Advance(TimeDelta::FromMilliseconds(50)); - web_view->HandleInputEvent(WebCoalescedInputEvent(pointer_down)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(pointer_down)); // We don't know if this pointer event will result in a scroll or not, so we // can't report its delay. We don't consider a scroll to be meaningful input. @@ -5353,7 +5413,8 @@ WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5); clock.Advance(TimeDelta::FromMilliseconds(60)); pointer_up.SetTimeStamp(CurrentTimeTicks()); - web_view->HandleInputEvent(WebCoalescedInputEvent(pointer_up)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(pointer_up)); EXPECT_NEAR(50, interactive_detector->GetFirstInputDelay().InMillisecondsF(), 0.01); @@ -5387,7 +5448,8 @@ WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5); pointer_down.SetTimeStamp(CurrentTimeTicks()); clock.Advance(TimeDelta::FromMilliseconds(50)); - web_view->HandleInputEvent(WebCoalescedInputEvent(pointer_down)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(pointer_down)); // We don't know if this pointer event will result in a scroll or not, so we // can't report its delay. We don't consider a scroll to be meaningful input. @@ -5399,7 +5461,8 @@ WebPointerProperties(1, WebPointerProperties::PointerType::kTouch), 5, 5); clock.Advance(TimeDelta::FromMilliseconds(60)); pointer_cancel.SetTimeStamp(CurrentTimeTicks()); - web_view->HandleInputEvent(WebCoalescedInputEvent(pointer_cancel)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(pointer_cancel)); // We received a pointer cancel, so this is a scroll gesture. No meaningful // input has occurred yet. @@ -5465,7 +5528,8 @@ clock.Advance(TimeDelta::FromMilliseconds(5000)); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); TimeDelta first_input_delay = interactive_detector->GetFirstInputDelay(); EXPECT_EQ(5000, first_input_delay.InMillisecondsF()); @@ -5510,7 +5574,8 @@ clock.Advance(TimeDelta::FromMilliseconds(5000)); - web_view->HandleInputEvent(WebCoalescedInputEvent(key_event)); + web_view->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(key_event)); TimeDelta longest_input_delay = interactive_detector->GetLongestInputDelay(); EXPECT_EQ(5000, longest_input_delay.InMillisecondsF());
diff --git a/third_party/blink/renderer/core/frame/browser_controls_test.cc b/third_party/blink/renderer/core/frame/browser_controls_test.cc index 87ff69a..5cc681e8 100644 --- a/third_party/blink/renderer/core/frame/browser_controls_test.cc +++ b/third_party/blink/renderer/core/frame/browser_controls_test.cc
@@ -84,7 +84,7 @@ helper_.InitializeAndLoad(base_url_ + page_name, nullptr, nullptr, nullptr, &ConfigureSettings); - GetWebView()->Resize(IntSize(400, 400)); + GetWebView()->MainFrameWidget()->Resize(IntSize(400, 400)); return GetWebView(); } @@ -122,11 +122,11 @@ } void VerticalScroll(float delta_y) { - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollBegin, 0, delta_y)); - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, delta_y)); - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollEnd)); } @@ -191,11 +191,12 @@ } void VerticalScroll(float delta_y) { - WebView().HandleInputEvent( + WebView().MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollBegin, 0, delta_y)); - WebView().HandleInputEvent( + WebView().MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, delta_y)); - WebView().HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollEnd)); + WebView().MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollEnd)); } }; @@ -212,14 +213,16 @@ TEST_F(BrowserControlsTest, MAYBE(HideOnScrollDown)) { WebViewImpl* web_view = Initialize(); // initialize browser controls to be shown. - web_view->ResizeWithBrowserControls(web_view->Size(), 50.f, 0, true); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 50.f, + 0, true); web_view->GetBrowserControls().SetShownRatio(1); - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollBegin)); + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollBegin)); EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset()); // Browser controls should be scrolled partially and page should not scroll. - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -25.f)); EXPECT_FLOAT_EQ(25.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 0), @@ -228,14 +231,14 @@ // Browser controls should consume 25px and become hidden. Excess scroll // should be // consumed by the page. - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -40.f)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 15), GetFrame()->View()->LayoutViewport()->GetScrollOffset()); // Only page should consume scroll - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -20.f)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 35), @@ -246,15 +249,17 @@ TEST_F(BrowserControlsTest, MAYBE(HideBottomControlsOnScrollDown)) { WebViewImpl* web_view = Initialize(); // initialize browser controls to be shown. - web_view->ResizeWithBrowserControls(web_view->Size(), 0, 50.f, true); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 0, + 50.f, true); web_view->GetBrowserControls().SetShownRatio(1); - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollBegin)); + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollBegin)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); // Bottom controls and page content should both scroll and there should be // no content offset. - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -25.f)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_FLOAT_EQ(0.5f, web_view->GetBrowserControls().ShownRatio()); @@ -262,10 +267,12 @@ GetFrame()->View()->LayoutViewport()->GetScrollOffset()); // Browser controls should become completely hidden. - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollBegin)); - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollBegin)); + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -40.f)); - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollEnd)); + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollEnd)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ShownRatio()); EXPECT_EQ(ScrollOffset(0, 65.f), @@ -276,19 +283,21 @@ TEST_F(BrowserControlsTest, MAYBE(ShowOnScrollUp)) { WebViewImpl* web_view = Initialize(); // initialize browser controls to be hidden. - web_view->ResizeWithBrowserControls(web_view->Size(), 50.f, 0, false); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 50.f, + 0, false); web_view->GetBrowserControls().SetShownRatio(0); - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollBegin)); + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollBegin)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 10.f)); EXPECT_FLOAT_EQ(10.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 0), GetFrame()->View()->LayoutViewport()->GetScrollOffset()); - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 50.f)); EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 0), @@ -299,22 +308,28 @@ TEST_F(BrowserControlsTest, MAYBE(ShowBottomControlsOnScrollUp)) { WebViewImpl* web_view = Initialize(); // initialize browser controls to be hidden. - web_view->ResizeWithBrowserControls(web_view->Size(), 0, 50.f, false); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 0, + 50.f, false); web_view->GetBrowserControls().SetShownRatio(0); - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollBegin)); + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollBegin)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); // Allow some space to scroll up. - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollBegin)); - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollBegin)); + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -50.f)); - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollEnd)); + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollEnd)); - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollBegin)); - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollBegin)); + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 25.f)); - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollEnd)); + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollEnd)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_FLOAT_EQ(0.5f, web_view->GetBrowserControls().ShownRatio()); EXPECT_EQ(ScrollOffset(0, 25), @@ -326,17 +341,19 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollDownThenUp)) { WebViewImpl* web_view = Initialize(); // initialize browser controls to be shown and position page at 100px. - web_view->ResizeWithBrowserControls(web_view->Size(), 50.f, 0, true); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 50.f, + 0, true); web_view->GetBrowserControls().SetShownRatio(1); GetFrame()->View()->GetScrollableArea()->SetScrollOffset(ScrollOffset(0, 100), kProgrammaticScroll); - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollBegin)); + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollBegin)); EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset()); // Scroll down to completely hide browser controls. Excess deltaY (100px) // should be consumed by the page. - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -150.f)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 200), @@ -344,13 +361,13 @@ // Scroll up and ensure the browser controls does not move until we recover // 100px previously scrolled. - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 40.f)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 160), GetFrame()->View()->LayoutViewport()->GetScrollOffset()); - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 60.f)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 100), @@ -358,14 +375,14 @@ // Now we have hit the threshold so further scroll up should be consumed by // browser controls. - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 30.f)); EXPECT_FLOAT_EQ(30.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 100), GetFrame()->View()->LayoutViewport()->GetScrollOffset()); // Once top control is fully shown then page should consume any excess scroll. - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 70.f)); EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 50), @@ -377,30 +394,32 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollUpThenDown)) { WebViewImpl* web_view = Initialize(); // initialize browser controls to be hidden and position page at 100px. - web_view->ResizeWithBrowserControls(web_view->Size(), 50.f, 0, false); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 50.f, + 0, false); web_view->GetBrowserControls().SetShownRatio(0); GetFrame()->View()->GetScrollableArea()->SetScrollOffset(ScrollOffset(0, 100), kProgrammaticScroll); - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollBegin)); + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollBegin)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); // Scroll up to completely show browser controls. Excess deltaY (50px) should // be consumed by the page. - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 100.f)); EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 50), GetFrame()->View()->LayoutViewport()->GetScrollOffset()); // Scroll down and ensure only browser controls is scrolled - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -40.f)); EXPECT_FLOAT_EQ(10.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 50), GetFrame()->View()->LayoutViewport()->GetScrollOffset()); - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -60.f)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 100), @@ -411,20 +430,22 @@ TEST_F(BrowserControlsTest, MAYBE(HorizontalScroll)) { WebViewImpl* web_view = Initialize(); // initialize browser controls to be shown. - web_view->ResizeWithBrowserControls(web_view->Size(), 50.f, 0, true); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 50.f, + 0, true); web_view->GetBrowserControls().SetShownRatio(1); - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollBegin)); + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollBegin)); EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset()); // Browser controls should not consume horizontal scroll. - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, -110.f, -100.f)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(110, 50), GetFrame()->View()->LayoutViewport()->GetScrollOffset()); - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, -40.f, 0)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(150, 50), @@ -438,14 +459,16 @@ web_view->SetPageScaleFactor(2.0); // Initialize browser controls to be shown. - web_view->ResizeWithBrowserControls(web_view->Size(), 50.f, 0, true); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 50.f, + 0, true); web_view->GetBrowserControls().SetShownRatio(1); - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollBegin)); + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollBegin)); EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset()); // Browser controls should be scrolled partially and page should not scroll. - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -20.f)); EXPECT_FLOAT_EQ(30.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 0), @@ -453,30 +476,32 @@ // Browser controls should consume 30px and become hidden. Excess scroll // should be consumed by the page at 2x scale. - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -70.f)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 20), GetFrame()->View()->GetScrollableArea()->GetScrollOffset()); - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollEnd)); + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollEnd)); // Change page scale and test. web_view->SetPageScaleFactor(0.5); - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollBegin)); + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollBegin)); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 20), GetFrame()->View()->GetScrollableArea()->GetScrollOffset()); - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 50.f)); EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 20), GetFrame()->View()->GetScrollableArea()->GetScrollOffset()); // At 0.5x scale scrolling 10px should take us to the top of the page. - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 10.f)); EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(ScrollOffset(0, 0), @@ -493,7 +518,8 @@ web_view->SetPageScaleFactor(2.0); // Initialize browser controls to be shown. - web_view->ResizeWithBrowserControls(web_view->Size(), 50.f, 0, true); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 50.f, + 0, true); web_view->GetBrowserControls().SetShownRatio(1); web_view->GetBrowserControls().ScrollBegin(); @@ -510,7 +536,8 @@ // Scrollable subregions should scroll before browser controls TEST_F(BrowserControlsTest, MAYBE(ScrollableSubregionScrollFirst)) { WebViewImpl* web_view = Initialize("overflow-scrolling.html"); - web_view->ResizeWithBrowserControls(web_view->Size(), 50.f, 0, true); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 50.f, + 0, true); web_view->GetBrowserControls().SetShownRatio(1); GetFrame()->View()->GetScrollableArea()->SetScrollOffset(ScrollOffset(0, 50), kProgrammaticScroll); @@ -560,7 +587,8 @@ // Scrollable iframes should scroll before browser controls TEST_F(BrowserControlsTest, MAYBE(ScrollableIframeScrollFirst)) { WebViewImpl* web_view = Initialize("iframe-scrolling.html"); - web_view->ResizeWithBrowserControls(web_view->Size(), 50.f, 0, true); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 50.f, + 0, true); web_view->GetBrowserControls().SetShownRatio(1); GetFrame()->View()->GetScrollableArea()->SetScrollOffset(ScrollOffset(0, 50), kProgrammaticScroll); @@ -610,13 +638,16 @@ // Browser controls visibility should remain consistent when height is changed. TEST_F(BrowserControlsTest, MAYBE(HeightChangeMaintainsVisibility)) { WebViewImpl* web_view = Initialize(); - web_view->ResizeWithBrowserControls(web_view->Size(), 20.f, 0, false); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 20.f, + 0, false); web_view->GetBrowserControls().SetShownRatio(0); - web_view->ResizeWithBrowserControls(web_view->Size(), 20.f, 0, false); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 20.f, + 0, false); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); - web_view->ResizeWithBrowserControls(web_view->Size(), 40.f, 0, false); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 40.f, + 0, false); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); // Scroll up to show browser controls. @@ -625,14 +656,16 @@ // Changing height of a fully shown browser controls should correctly adjust // content offset - web_view->ResizeWithBrowserControls(web_view->Size(), 30.f, 0, false); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 30.f, + 0, false); EXPECT_FLOAT_EQ(30.f, web_view->GetBrowserControls().ContentOffset()); } // Zero delta should not have any effect on browser controls. TEST_F(BrowserControlsTest, MAYBE(ZeroHeightMeansNoEffect)) { WebViewImpl* web_view = Initialize(); - web_view->ResizeWithBrowserControls(web_view->Size(), 0, 0, false); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 0, 0, + false); web_view->GetBrowserControls().SetShownRatio(0); GetFrame()->View()->GetScrollableArea()->SetScrollOffset(ScrollOffset(0, 100), kProgrammaticScroll); @@ -657,7 +690,8 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollUpPastLimitDoesNotHide)) { WebViewImpl* web_view = Initialize(); // Initialize browser controls to be shown - web_view->ResizeWithBrowserControls(web_view->Size(), 50.f, 0, true); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 50.f, + 0, true); web_view->GetBrowserControls().SetShownRatio(1); // Use 2x scale so that both visual viewport and frameview are scrollable web_view->SetPageScaleFactor(2.0); @@ -1087,9 +1121,9 @@ // Zoom in to 2X and fully scroll both viewports. web_view->SetPageScaleFactor(page_scale); { - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollBegin)); - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -10000)); ASSERT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); @@ -1100,7 +1134,8 @@ view->LayoutViewport()->GetScrollOffset().Height()); EXPECT_EQ(expected_root_offset, root_viewport->GetScrollOffset().Height()); - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollEnd)); + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollEnd)); } // Commit the browser controls resize so that the browser controls do not @@ -1122,9 +1157,9 @@ // account for this and keep the visual viewport at the same location relative // to the document (i.e. the user shouldn't see a movement). { - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollBegin)); - web_view->HandleInputEvent( + web_view->MainFrameWidget()->HandleInputEvent( GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 80)); GetVisualViewport().ClampToBoundaries(); @@ -1134,7 +1169,8 @@ ASSERT_EQ(80.f, web_view->GetBrowserControls().ContentOffset()); EXPECT_EQ(expected_root_offset, root_viewport->GetScrollOffset().Height()); - web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollEnd)); + web_view->MainFrameWidget()->HandleInputEvent( + GenerateEvent(WebInputEvent::kGestureScrollEnd)); } } @@ -1231,7 +1267,8 @@ // Test the size adjustment sent to the viewport when top controls exist. TEST_F(BrowserControlsTest, MAYBE(TopControlsSizeAdjustment)) { WebViewImpl* web_view = Initialize(); - web_view->ResizeWithBrowserControls(web_view->Size(), 50.f, 0, false); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 50.f, + 0, false); web_view->GetBrowserControls().SetShownRatio(1); EXPECT_FLOAT_EQ(-50.f, web_view->GetBrowserControls().UnreportedSizeAdjustment()); @@ -1250,7 +1287,8 @@ // the content offset. TEST_F(BrowserControlsTest, MAYBE(BottomControlsSizeAdjustment)) { WebViewImpl* web_view = Initialize(); - web_view->ResizeWithBrowserControls(web_view->Size(), 0, 50.f, false); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 0, + 50.f, false); web_view->GetBrowserControls().SetShownRatio(1); EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().UnreportedSizeAdjustment()); @@ -1267,8 +1305,8 @@ TEST_F(BrowserControlsTest, MAYBE(GrowingHeightKeepsTopControlsHidden)) { WebViewImpl* web_view = Initialize(); float bottom_height = web_view->GetBrowserControls().BottomHeight(); - web_view->ResizeWithBrowserControls(web_view->Size(), 1.f, bottom_height, - false); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 1.f, + bottom_height, false); web_view->GetBrowserControls().UpdateConstraintsAndState( cc::BrowserControlsState::kHidden, cc::BrowserControlsState::kHidden, @@ -1278,12 +1316,12 @@ // shouln't change. EXPECT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); - web_view->ResizeWithBrowserControls(web_view->Size(), 50.f, bottom_height, - false); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), 50.f, + bottom_height, false); EXPECT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); - web_view->ResizeWithBrowserControls(web_view->Size(), 100.f, bottom_height, - false); + web_view->ResizeWithBrowserControls(web_view->MainFrameWidget()->Size(), + 100.f, bottom_height, false); EXPECT_EQ(0.f, web_view->GetBrowserControls().ContentOffset()); }
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc index edf6220..2242204 100644 --- a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc +++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
@@ -1038,41 +1038,6 @@ RedirectStatus redirect_status, SecurityViolationReportingPolicy reporting_policy, CheckHeaderType check_header_type) const { - // CSP 1.1 moves workers from 'script-src' to the new 'child-src'. Measure the - // impact of this backwards-incompatible change. - // TODO(mkwst): We reverted this. - if (Document* document = this->GetDocument()) { - UseCounter::Count(*document, WebFeature::kWorkerSubjectToCSP); - bool is_allowed_worker = true; - if (!ShouldBypassContentSecurityPolicy(url, execution_context_)) { - for (const auto& policy : policies_) { - if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType())) - continue; - is_allowed_worker &= policy->AllowWorkerFromSource( - url, redirect_status, - SecurityViolationReportingPolicy::kSuppressReporting); - } - } - - bool is_allowed_script = true; - - if (!ShouldBypassContentSecurityPolicy(url, execution_context_)) { - for (const auto& policy : policies_) { - if (!CheckHeaderTypeMatches(check_header_type, policy->HeaderType())) - continue; - is_allowed_script &= policy->AllowScriptFromSource( - url, AtomicString(), IntegrityMetadataSet(), kNotParserInserted, - redirect_status, - SecurityViolationReportingPolicy::kSuppressReporting); - } - } - - if (is_allowed_worker && !is_allowed_script) { - UseCounter::Count(*document, - WebFeature::kWorkerAllowedByChildBlockedByScript); - } - } - if (ShouldBypassContentSecurityPolicy(url, execution_context_)) return true; @@ -1684,7 +1649,7 @@ if (!context) return false; - v8::Isolate* isolate = context->GetIsolate(); + v8::Isolate* isolate = ToIsolate(context); v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> v8_context = isolate->GetCurrentContext(); if (v8_context.IsEmpty())
diff --git a/third_party/blink/renderer/core/frame/document_loading_rendering_test.cc b/third_party/blink/renderer/core/frame/document_loading_rendering_test.cc index f6de9474..e2ad997 100644 --- a/third_party/blink/renderer/core/frame/document_loading_rendering_test.cc +++ b/third_party/blink/renderer/core/frame/document_loading_rendering_test.cc
@@ -232,7 +232,7 @@ LoadURL("https://example.com/test.html"); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); main_resource.Complete(R"HTML( <!DOCTYPE html> @@ -317,7 +317,7 @@ LoadURL("https://example.com/main.html"); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); main_resource.Complete(R"HTML( <!DOCTYPE html> @@ -403,7 +403,7 @@ LoadURL("https://example.com/test.html"); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); main_resource.Start();
diff --git a/third_party/blink/renderer/core/frame/frame_overlay_test.cc b/third_party/blink/renderer/core/frame/frame_overlay_test.cc index e89fd981..3452ec07 100644 --- a/third_party/blink/renderer/core/frame/frame_overlay_test.cc +++ b/third_party/blink/renderer/core/frame/frame_overlay_test.cc
@@ -64,7 +64,8 @@ helper_.Initialize(nullptr /* web_frame_client */, nullptr /* web_view_client */, nullptr /* web_widget_client */); - GetWebView()->Resize(WebSize(kViewportWidth, kViewportHeight)); + GetWebView()->MainFrameWidget()->Resize( + WebSize(kViewportWidth, kViewportHeight)); GetWebView()->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); }
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc index f582426..b668cad 100644 --- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc +++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -378,7 +378,8 @@ void WebViewHelper::Reset() { if (web_view_) { DCHECK(!TestWebFrameClient::IsLoading()); - web_view_->Close(); + // This closes the WebView also. + web_view_->MainFrameWidget()->Close(); web_view_ = nullptr; } } @@ -393,7 +394,7 @@ void WebViewHelper::Resize(WebSize size) { test_web_view_client_->ClearAnimationScheduled(); - GetWebView()->Resize(size); + GetWebView()->MainFrameWidget()->Resize(size); EXPECT_FALSE(test_web_view_client_->AnimationScheduled()); test_web_view_client_->ClearAnimationScheduled(); } @@ -415,7 +416,8 @@ // Consequently, all external image resources must be mocked. web_view_->GetSettings()->SetLoadsImagesAutomatically(true); - web_view_->SetLayerTreeView(web_view_client->layer_tree_view()); + web_view_->MainFrameWidget()->SetLayerTreeView( + web_view_client->layer_tree_view()); web_view_->SetDeviceScaleFactor( web_view_client->GetScreenInfo().device_scale_factor); web_view_->SetDefaultPageScaleLimits(1, 4);
diff --git a/third_party/blink/renderer/core/frame/fullscreen_controller.cc b/third_party/blink/renderer/core/frame/fullscreen_controller.cc index 2e6d3604..3c0cb04 100644 --- a/third_party/blink/renderer/core/frame/fullscreen_controller.cc +++ b/third_party/blink/renderer/core/frame/fullscreen_controller.cc
@@ -256,7 +256,8 @@ web_view_base_->GetPageScaleConstraintsSet().SetNeedsReset(true); } else { fullscreen_constraints = PageScaleConstraints(1.0, 1.0, 1.0); - fullscreen_constraints.layout_size = FloatSize(web_view_base_->Size()); + fullscreen_constraints.layout_size = + FloatSize(web_view_base_->MainFrameWidget()->Size()); } web_view_base_->GetPageScaleConstraintsSet().SetFullscreenConstraints( fullscreen_constraints);
diff --git a/third_party/blink/renderer/core/frame/location.cc b/third_party/blink/renderer/core/frame/location.cc index 3306af7..27bc9a1 100644 --- a/third_party/blink/renderer/core/frame/location.cc +++ b/third_party/blink/renderer/core/frame/location.cc
@@ -31,6 +31,7 @@ #include "third_party/blink/renderer/bindings/core/v8/binding_security.h" #include "third_party/blink/renderer/bindings/core/v8/usv_string_or_trusted_url.h" #include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h" #include "third_party/blink/renderer/core/frame/dom_window.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" @@ -294,6 +295,21 @@ if (dom_window_->IsInsecureScriptAccess(*current_window, completed_url)) return; + // Check the source browsing context's CSP to fulfill the CSP check + // requirement of https://html.spec.whatwg.org/#navigate for javascript URLs. + // Although the spec states we should perform this check on task execution, + // we do this prior to dispatch since the parent frame's CSP may be + // inaccessible if the target frame is out of process. + Document* current_document = current_window->document(); + if (current_document && completed_url.ProtocolIsJavaScript() && + !ContentSecurityPolicy::ShouldBypassMainWorld(current_document)) { + String script_source = DecodeURLEscapeSequences(completed_url.GetString()); + if (!current_document->GetContentSecurityPolicy()->AllowJavaScriptURLs( + nullptr, script_source, current_document->Url(), OrdinalNumber())) { + return; + } + } + V8DOMActivityLogger* activity_logger = V8DOMActivityLogger::CurrentActivityLoggerIfIsolatedWorld(); if (activity_logger) {
diff --git a/third_party/blink/renderer/core/frame/rotation_viewport_anchor_test.cc b/third_party/blink/renderer/core/frame/rotation_viewport_anchor_test.cc index 0bc00725..b9fd355 100644 --- a/third_party/blink/renderer/core/frame/rotation_viewport_anchor_test.cc +++ b/third_party/blink/renderer/core/frame/rotation_viewport_anchor_test.cc
@@ -26,7 +26,7 @@ }; TEST_F(RotationViewportAnchorTest, SimpleAbsolutePosition) { - WebView().Resize(WebSize(400, 600)); + WebView().MainFrameWidget()->Resize(WebSize(400, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -58,7 +58,7 @@ layout_viewport->SetScrollOffset(ScrollOffset(3050 - 200, 4050), kProgrammaticScroll); - WebView().Resize(WebSize(600, 400)); + WebView().MainFrameWidget()->Resize(WebSize(600, 400)); Compositor().BeginFrame(); EXPECT_EQ(3050 - 200, layout_viewport->GetScrollOffset().Width()); @@ -66,7 +66,7 @@ } TEST_F(RotationViewportAnchorTest, PositionRelativeToViewportSize) { - WebView().Resize(WebSize(100, 600)); + WebView().MainFrameWidget()->Resize(WebSize(100, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -93,24 +93,25 @@ Document& document = GetDocument(); ScrollableArea* layout_viewport = document.View()->LayoutViewport(); - IntPoint target_position(5 * WebView().Size().width, - 5 * WebView().Size().height); + IntPoint target_position(5 * WebView().MainFrameWidget()->Size().width, + 5 * WebView().MainFrameWidget()->Size().height); // Place the target at the top-center of the viewport. This is where the // rotation anchor finds the node to anchor to. layout_viewport->SetScrollOffset( - ScrollOffset(target_position.X() - WebView().Size().width / 2 + 25, + ScrollOffset(target_position.X() - + WebView().MainFrameWidget()->Size().width / 2 + 25, target_position.Y()), kProgrammaticScroll); - WebView().Resize(WebSize(600, 100)); + WebView().MainFrameWidget()->Resize(WebSize(600, 100)); Compositor().BeginFrame(); - target_position = - IntPoint(5 * WebView().Size().width, 5 * WebView().Size().height); + target_position = IntPoint(5 * WebView().MainFrameWidget()->Size().width, + 5 * WebView().MainFrameWidget()->Size().height); IntPoint expected_offset( - target_position.X() - WebView().Size().width / 2 + 25, + target_position.X() - WebView().MainFrameWidget()->Size().width / 2 + 25, target_position.Y()); EXPECT_EQ(expected_offset.X(), layout_viewport->GetScrollOffset().Width());
diff --git a/third_party/blink/renderer/core/frame/visual_viewport_test.cc b/third_party/blink/renderer/core/frame/visual_viewport_test.cc index d808666e..d17d1c7 100644 --- a/third_party/blink/renderer/core/frame/visual_viewport_test.cc +++ b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
@@ -218,28 +218,28 @@ // WebView resizes the VisualViewport. TEST_P(VisualViewportTest, TestResize) { InitializeWithDesktopSettings(); - WebView()->Resize(IntSize(320, 240)); + WebView()->MainFrameWidget()->Resize(IntSize(320, 240)); NavigateTo("about:blank"); ForceFullCompositingUpdate(); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); - IntSize web_view_size = WebView()->Size(); + IntSize web_view_size = WebView()->MainFrameWidget()->Size(); // Make sure the visual viewport was initialized. EXPECT_EQ(web_view_size, visual_viewport.Size()); // Resizing the WebView should change the VisualViewport. web_view_size = IntSize(640, 480); - WebView()->Resize(web_view_size); - EXPECT_EQ(web_view_size, IntSize(WebView()->Size())); + WebView()->MainFrameWidget()->Resize(web_view_size); + EXPECT_EQ(web_view_size, IntSize(WebView()->MainFrameWidget()->Size())); EXPECT_EQ(web_view_size, visual_viewport.Size()); // Resizing the visual viewport shouldn't affect the WebView. IntSize new_viewport_size = IntSize(320, 200); visual_viewport.SetSize(new_viewport_size); - EXPECT_EQ(web_view_size, IntSize(WebView()->Size())); + EXPECT_EQ(web_view_size, IntSize(WebView()->MainFrameWidget()->Size())); EXPECT_EQ(new_viewport_size, visual_viewport.Size()); } @@ -256,7 +256,7 @@ // Vertical scrollbar width and horizontal scrollbar height. IntSize scrollbar_size = IntSize(15, 15); - WebView()->Resize(size); + WebView()->MainFrameWidget()->Resize(size); // Scroll layout viewport and verify visibleContentRect. WebView()->MainFrameImpl()->SetScrollOffset(WebSize(0, 50)); @@ -286,7 +286,7 @@ // make it appear to stay still). This caused bugs like crbug.com/453859. TEST_P(VisualViewportTest, TestResizeAtFullyScrolledPreservesViewportLocation) { InitializeWithDesktopSettings(); - WebView()->Resize(IntSize(800, 600)); + WebView()->MainFrameWidget()->Resize(IntSize(800, 600)); RegisterMockedHttpURLLoad("content-width-1000.html"); NavigateTo(base_url_ + "content-width-1000.html"); @@ -312,12 +312,12 @@ // Shrink the WebView, this should cause both viewports to shrink and // WebView should do whatever it needs to do to preserve the visible // location. - WebView()->Resize(IntSize(700, 550)); + WebView()->MainFrameWidget()->Resize(IntSize(700, 550)); EXPECT_EQ(expected_location, frame_view.GetScrollableArea()->VisibleContentRect().Location()); - WebView()->Resize(IntSize(800, 600)); + WebView()->MainFrameWidget()->Resize(IntSize(800, 600)); EXPECT_EQ(expected_location, frame_view.GetScrollableArea()->VisibleContentRect().Location()); @@ -355,7 +355,7 @@ RegisterMockedHttpURLLoad("200-by-800-viewport.html"); NavigateTo(base_url_ + "200-by-800-viewport.html"); - WebView()->Resize(IntSize(100, 200)); + WebView()->MainFrameWidget()->Resize(IntSize(100, 200)); // Scroll main frame to the bottom of the document WebView()->MainFrameImpl()->SetScrollOffset(WebSize(0, 400)); @@ -388,7 +388,7 @@ } // Perform the resizing - WebView()->Resize(IntSize(200, 100)); + WebView()->MainFrameWidget()->Resize(IntSize(200, 100)); // After resizing the scale changes 2.0 -> 4.0 EXPECT_FLOAT_SIZE_EQ(FloatSize(50, 25), visual_viewport.VisibleRect().Size()); @@ -446,7 +446,7 @@ RegisterMockedHttpURLLoad("200-by-800-viewport.html"); NavigateTo(base_url_ + "200-by-800-viewport.html"); - WebView()->Resize(IntSize(100, 200)); + WebView()->MainFrameWidget()->Resize(IntSize(100, 200)); // Outer viewport takes the whole width of the document. @@ -475,7 +475,7 @@ &TransformPaintPropertyNode::Root())); } - WebView()->Resize(IntSize(200, 100)); + WebView()->MainFrameWidget()->Resize(IntSize(200, 100)); // After resizing the scale changes 2.0 -> 4.0 EXPECT_FLOAT_SIZE_EQ(FloatSize(50, 25), visual_viewport.VisibleRect().Size()); @@ -513,7 +513,7 @@ WebFrameWidgetBase* main_frame_widget = WebView()->MainFrameImpl()->FrameWidgetImpl(); main_frame_widget->SetRootGraphicsLayer(nullptr); - WebView()->Resize(IntSize(320, 240)); + WebView()->MainFrameWidget()->Resize(IntSize(320, 240)); NavigateTo("about:blank"); UpdateAllLifecyclePhases(); @@ -534,7 +534,7 @@ // location of the viewport. TEST_P(VisualViewportTest, TestVisibleRect) { InitializeWithDesktopSettings(); - WebView()->Resize(IntSize(320, 240)); + WebView()->MainFrameWidget()->Resize(IntSize(320, 240)); NavigateTo("about:blank"); ForceFullCompositingUpdate(); @@ -542,11 +542,12 @@ VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); // Initial visible rect should be the whole frame. - EXPECT_EQ(IntSize(WebView()->Size()), visual_viewport.Size()); + EXPECT_EQ(IntSize(WebView()->MainFrameWidget()->Size()), + visual_viewport.Size()); // Viewport is whole frame. IntSize size = IntSize(400, 200); - WebView()->Resize(size); + WebView()->MainFrameWidget()->Resize(size); UpdateAllLifecyclePhases(); visual_viewport.SetSize(size); @@ -584,7 +585,7 @@ // and scroll location of the viewport relative to the document. TEST_P(VisualViewportTest, TestVisibleRectInDocument) { InitializeWithDesktopSettings(); - WebView()->Resize(IntSize(100, 400)); + WebView()->MainFrameWidget()->Resize(IntSize(100, 400)); RegisterMockedHttpURLLoad("200-by-800-viewport.html"); NavigateTo(base_url_ + "200-by-800-viewport.html"); @@ -609,7 +610,7 @@ TEST_P(VisualViewportTest, TestFractionalScrollOffsetIsNotOverwritten) { ScopedFractionalScrollOffsetsForTest fractional_scroll_offsets(true); InitializeWithAndroidSettings(); - WebView()->Resize(IntSize(200, 250)); + WebView()->MainFrameWidget()->Resize(IntSize(200, 250)); RegisterMockedHttpURLLoad("200-by-800-viewport.html"); NavigateTo(base_url_ + "200-by-800-viewport.html"); @@ -627,7 +628,7 @@ // that the visual viewport always stays within the bounds of the main frame. TEST_P(VisualViewportTest, TestOffsetClamping) { InitializeWithAndroidSettings(); - WebView()->Resize(IntSize(320, 240)); + WebView()->MainFrameWidget()->Resize(IntSize(320, 240)); WebURL base_url = url_test_helpers::ToKURL("http://example.com/"); frame_test_helpers::LoadHTMLString( @@ -688,7 +689,7 @@ // keyboard came up. TEST_P(VisualViewportTest, TestOffsetClampingWithResize) { InitializeWithDesktopSettings(); - WebView()->Resize(IntSize(320, 240)); + WebView()->MainFrameWidget()->Resize(IntSize(320, 240)); NavigateTo("about:blank"); ForceFullCompositingUpdate(); @@ -756,7 +757,7 @@ // main frame when we apply both scaling and resizes. TEST_P(VisualViewportTest, TestOffsetClampingWithResizeAndScale) { InitializeWithDesktopSettings(); - WebView()->Resize(IntSize(320, 240)); + WebView()->MainFrameWidget()->Resize(IntSize(320, 240)); NavigateTo("about:blank"); ForceFullCompositingUpdate(); @@ -787,10 +788,12 @@ EXPECT_EQ(IntSize(330, 250), visual_viewport.Size()); // Resize both the viewport and the frame to be larger. - WebView()->Resize(IntSize(640, 480)); + WebView()->MainFrameWidget()->Resize(IntSize(640, 480)); UpdateAllLifecyclePhases(); - EXPECT_EQ(IntSize(WebView()->Size()), visual_viewport.Size()); - EXPECT_EQ(IntSize(WebView()->Size()), GetFrame()->View()->FrameRect().Size()); + EXPECT_EQ(IntSize(WebView()->MainFrameWidget()->Size()), + visual_viewport.Size()); + EXPECT_EQ(IntSize(WebView()->MainFrameWidget()->Size()), + GetFrame()->View()->FrameRect().Size()); visual_viewport.SetLocation(FloatPoint(1000, 1000)); EXPECT_FLOAT_POINT_EQ(FloatPoint(320, 240), visual_viewport.VisibleRect().Location()); @@ -809,12 +812,12 @@ // the aspect ratio. TEST_P(VisualViewportTest, TestFrameViewSizedToContent) { InitializeWithAndroidSettings(); - WebView()->Resize(IntSize(320, 240)); + WebView()->MainFrameWidget()->Resize(IntSize(320, 240)); RegisterMockedHttpURLLoad("200-by-300-viewport.html"); NavigateTo(base_url_ + "200-by-300-viewport.html"); - WebView()->Resize(IntSize(600, 800)); + WebView()->MainFrameWidget()->Resize(IntSize(600, 800)); UpdateAllLifecyclePhases(); // Note: the size is ceiled and should match the behavior in CC's @@ -828,12 +831,12 @@ // so make sure the LocalFrameView is sized to the viewport. TEST_P(VisualViewportTest, TestFrameViewSizedToMinimumScale) { InitializeWithDesktopSettings(); - WebView()->Resize(IntSize(320, 240)); + WebView()->MainFrameWidget()->Resize(IntSize(320, 240)); RegisterMockedHttpURLLoad("200-by-300.html"); NavigateTo(base_url_ + "200-by-300.html"); - WebView()->Resize(IntSize(100, 160)); + WebView()->MainFrameWidget()->Resize(IntSize(100, 160)); UpdateAllLifecyclePhases(); EXPECT_EQ(IntSize(100, 160), @@ -844,7 +847,7 @@ // scroll layer. crbug.com/423189. TEST_P(VisualViewportTest, TestAttachingNewFrameSetsInnerScrollLayerSize) { InitializeWithAndroidSettings(); - WebView()->Resize(IntSize(320, 240)); + WebView()->MainFrameWidget()->Resize(IntSize(320, 240)); // Load a wider page first, the navigation should resize the scroll layer to // the smaller size on the second navigation. @@ -882,7 +885,7 @@ // appropriately sized in the presence of a viewport <meta> tag. TEST_P(VisualViewportTest, TestFrameViewSizedToViewportMetaMinimumScale) { InitializeWithAndroidSettings(); - WebView()->Resize(IntSize(320, 240)); + WebView()->MainFrameWidget()->Resize(IntSize(320, 240)); RegisterMockedHttpURLLoad("200-by-300-min-scale-2.html"); NavigateTo(base_url_ + "200-by-300-min-scale-2.html"); @@ -898,7 +901,7 @@ TEST_P(VisualViewportTest, TestVisualViewportGetsSizeInAutoSizeMode) { InitializeWithDesktopSettings(); - EXPECT_EQ(IntSize(0, 0), IntSize(WebView()->Size())); + EXPECT_EQ(IntSize(0, 0), IntSize(WebView()->MainFrameWidget()->Size())); EXPECT_EQ(IntSize(0, 0), GetFrame()->GetPage()->GetVisualViewport().Size()); WebView()->EnableAutoResizeMode(WebSize(10, 10), WebSize(1000, 1000)); @@ -914,7 +917,7 @@ // viewport. TEST_P(VisualViewportTest, TestTextSelectionHandles) { InitializeWithDesktopSettings(); - WebView()->Resize(IntSize(500, 800)); + WebView()->MainFrameWidget()->Resize(IntSize(500, 800)); RegisterMockedHttpURLLoad("pinch-viewport-input-field.html"); NavigateTo(base_url_ + "pinch-viewport-input-field.html"); @@ -924,14 +927,15 @@ WebRect original_anchor; WebRect original_focus; - WebView()->SelectionBounds(original_anchor, original_focus); + WebView()->MainFrameWidget()->SelectionBounds(original_anchor, + original_focus); WebView()->SetPageScaleFactor(2); visual_viewport.SetLocation(FloatPoint(100, 400)); WebRect anchor; WebRect focus; - WebView()->SelectionBounds(anchor, focus); + WebView()->MainFrameWidget()->SelectionBounds(anchor, focus); IntPoint expected(IntRect(original_anchor).Location()); expected.MoveBy(-FlooredIntPoint(visual_viewport.VisibleRect().Location())); @@ -984,7 +988,7 @@ // Test restoring a HistoryItem properly restores the visual viewport's state. TEST_P(VisualViewportTest, TestRestoredFromHistoryItem) { InitializeWithDesktopSettings(); - WebView()->Resize(IntSize(200, 300)); + WebView()->MainFrameWidget()->Resize(IntSize(200, 300)); RegisterMockedHttpURLLoad("200-by-300.html"); @@ -1011,7 +1015,7 @@ // viewport. TEST_P(VisualViewportTest, TestRestoredFromLegacyHistoryItem) { InitializeWithDesktopSettings(); - WebView()->Resize(IntSize(100, 150)); + WebView()->MainFrameWidget()->Resize(IntSize(100, 150)); RegisterMockedHttpURLLoad("200-by-300-viewport.html"); @@ -1088,7 +1092,7 @@ DISABLED_TestWebFrameRangeAccountsForVisualViewportScroll) { InitializeWithDesktopSettings(); WebView()->GetSettings()->SetDefaultFontSize(12); - WebView()->Resize(WebSize(640, 480)); + WebView()->MainFrameWidget()->Resize(WebSize(640, 480)); RegisterMockedHttpURLLoad("move_range.html"); NavigateTo(base_url_ + "move_range.html"); @@ -1104,7 +1108,7 @@ mainFrame->ExecuteScript(WebScriptSource("selectRange();")); EXPECT_EQ("ir", mainFrame->SelectionAsText().Utf8()); - WebView()->SelectionBounds(base_rect, extent_rect); + WebView()->MainFrameWidget()->SelectionBounds(base_rect, extent_rect); WebPoint initialPoint(base_rect.x, base_rect.y); WebPoint endPoint(extent_rect.x, extent_rect.y); @@ -1121,7 +1125,7 @@ // relayout. TEST_P(VisualViewportTest, TestWebViewResizeCausesViewportConstrainedLayout) { InitializeWithDesktopSettings(); - WebView()->Resize(IntSize(500, 300)); + WebView()->MainFrameWidget()->Resize(IntSize(500, 300)); RegisterMockedHttpURLLoad("pinch-viewport-fixed-pos.html"); NavigateTo(base_url_ + "pinch-viewport-fixed-pos.html"); @@ -1155,7 +1159,7 @@ // viewport offset. TEST_P(VisualViewportTest, TestContextMenuShownInCorrectLocation) { InitializeWithDesktopSettings(); - WebView()->Resize(IntSize(200, 300)); + WebView()->MainFrameWidget()->Resize(IntSize(200, 300)); RegisterMockedHttpURLLoad("200-by-300.html"); NavigateTo(base_url_ + "200-by-300.html"); @@ -1181,12 +1185,15 @@ // Do a sanity check with no scale applied. WebView()->MainFrameImpl()->SetClient(&mock_web_frame_client); - WebView()->HandleInputEvent(WebCoalescedInputEvent(mouse_down_event)); - WebView()->HandleInputEvent(WebCoalescedInputEvent(mouse_up_event)); + WebView()->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(mouse_down_event)); + WebView()->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(mouse_up_event)); Mock::VerifyAndClearExpectations(&mock_web_frame_client); mouse_down_event.button = WebMouseEvent::Button::kLeft; - WebView()->HandleInputEvent(WebCoalescedInputEvent(mouse_down_event)); + WebView()->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(mouse_down_event)); // Now pinch zoom into the page and move the visual viewport. The context menu // should still appear at the location of the event, relative to the WebView. @@ -1200,8 +1207,10 @@ mouse_down_event.PositionInWidget().y))); mouse_down_event.button = WebMouseEvent::Button::kRight; - WebView()->HandleInputEvent(WebCoalescedInputEvent(mouse_down_event)); - WebView()->HandleInputEvent(WebCoalescedInputEvent(mouse_up_event)); + WebView()->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(mouse_down_event)); + WebView()->MainFrameWidget()->HandleInputEvent( + WebCoalescedInputEvent(mouse_up_event)); // Reset the old client so destruction can occur naturally. WebView()->MainFrameImpl()->SetClient(old_client); @@ -1210,7 +1219,7 @@ // Test that the client is notified if page scroll events. TEST_P(VisualViewportTest, TestClientNotifiedOfScrollEvents) { InitializeWithAndroidSettings(); - WebView()->Resize(IntSize(200, 300)); + WebView()->MainFrameWidget()->Resize(IntSize(200, 300)); RegisterMockedHttpURLLoad("200-by-300.html"); NavigateTo(base_url_ + "200-by-300.html"); @@ -1244,7 +1253,7 @@ TEST_P(VisualViewportTest, ScrollIntoViewFractionalOffset) { InitializeWithAndroidSettings(); - WebView()->Resize(IntSize(1000, 1000)); + WebView()->MainFrameWidget()->Resize(IntSize(1000, 1000)); RegisterMockedHttpURLLoad("scroll-into-view.html"); NavigateTo(base_url_ + "scroll-into-view.html"); @@ -1333,8 +1342,9 @@ EXPECT_EQ(IntSize(1000, 900), frame_view.FrameRect().Size()); // Simulate bringing down the browser controls by 20px. - WebView()->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 1, 1, - cc::BrowserControlsState::kBoth}); + WebView()->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 1, 1, + cc::BrowserControlsState::kBoth}); EXPECT_EQ(FloatSize(500, 430), visual_viewport.VisibleRect().Size()); // Test that the scroll bounds are adjusted appropriately: the visual viewport @@ -1351,9 +1361,9 @@ frame_view.LayoutViewport()->GetScrollOffset()); // Simulate bringing up the browser controls by 10.5px. - WebView()->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 1, - -10.5f / 20, - cc::BrowserControlsState::kBoth}); + WebView()->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 1, -10.5f / 20, + cc::BrowserControlsState::kBoth}); EXPECT_FLOAT_SIZE_EQ(FloatSize(500, 440.5f), visual_viewport.VisibleRect().Size()); @@ -1387,8 +1397,9 @@ // Simulate bringing down the browser controls by 20px. Since we're zoomed in, // the browser controls take up half as much space (in document-space) than // they do at an unzoomed level. - WebView()->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 1, 1, - cc::BrowserControlsState::kBoth}); + WebView()->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 1, 1, + cc::BrowserControlsState::kBoth}); EXPECT_EQ(FloatSize(250, 215), visual_viewport.VisibleRect().Size()); // Test that the scroll bounds are adjusted appropriately. @@ -1404,8 +1415,9 @@ // Scale back out, LocalFrameView max scroll shouldn't have changed. Visual // viewport should be moved up to accomodate larger view. - WebView()->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 0.5f, - 0, cc::BrowserControlsState::kBoth}); + WebView()->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 0.5f, 0, + cc::BrowserControlsState::kBoth}); EXPECT_EQ(1, visual_viewport.Scale()); EXPECT_EQ(expected, frame_view.LayoutViewport()->GetScrollOffset()); frame_view.LayoutViewport()->ScrollBy(ScrollOffset(10000, 10000), @@ -1417,13 +1429,15 @@ EXPECT_EQ(FloatSize(500, 860 - 430), visual_viewport.GetScrollOffset()); // Scale out, use a scale that causes fractional rects. - WebView()->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 0.8f, - -1, cc::BrowserControlsState::kBoth}); + WebView()->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 0.8f, -1, + cc::BrowserControlsState::kBoth}); EXPECT_EQ(FloatSize(625, 562.5), visual_viewport.VisibleRect().Size()); // Bring out the browser controls by 11 - WebView()->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 1, - 11 / 20.f, cc::BrowserControlsState::kBoth}); + WebView()->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 1, 11 / 20.f, + cc::BrowserControlsState::kBoth}); EXPECT_EQ(FloatSize(625, 548.75), visual_viewport.VisibleRect().Size()); // Ensure max scroll offsets are updated properly. @@ -1588,9 +1602,11 @@ // the main frame's scroll offset. crbug.com/428193. TEST_P(VisualViewportTest, TestTopControlHidingResizeDoesntClampMainFrame) { InitializeWithAndroidSettings(); - WebView()->ResizeWithBrowserControls(WebView()->Size(), 500, 0, false); - WebView()->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 1, 1, - cc::BrowserControlsState::kBoth}); + WebView()->ResizeWithBrowserControls(WebView()->MainFrameWidget()->Size(), + 500, 0, false); + WebView()->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 1, 1, + cc::BrowserControlsState::kBoth}); WebView()->ResizeWithBrowserControls(WebSize(1000, 1000), 500, 0, true); RegisterMockedHttpURLLoad("content-width-1000.html"); @@ -1600,8 +1616,9 @@ // Scroll the LocalFrameView to the bottom of the page but "hide" the browser // controls on the compositor side so the max scroll position should account // for the full viewport height. - WebView()->ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 1, -1, - cc::BrowserControlsState::kBoth}); + WebView()->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 1, -1, + cc::BrowserControlsState::kBoth}); LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView(); frame_view.LayoutViewport()->SetScrollOffset(ScrollOffset(0, 10000), kProgrammaticScroll); @@ -1622,7 +1639,7 @@ TEST_P(VisualViewportTest, TestScrollbarsNotAttachedWhenHideScrollbarsSettingIsTrue) { InitializeWithAndroidSettings(configureHiddenScrollbarsSettings); - WebView()->Resize(IntSize(100, 150)); + WebView()->MainFrameWidget()->Resize(IntSize(100, 150)); NavigateTo("about:blank"); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); @@ -1635,7 +1652,7 @@ TEST_P(VisualViewportTest, TestScrollbarsAttachedWhenHideScrollbarsSettingIsFalse) { InitializeWithAndroidSettings(); - WebView()->Resize(IntSize(100, 150)); + WebView()->MainFrameWidget()->Resize(IntSize(100, 150)); NavigateTo("about:blank"); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); @@ -1652,7 +1669,7 @@ return; InitializeWithAndroidSettings(); - WebView()->Resize(IntSize(100, 150)); + WebView()->MainFrameWidget()->Resize(IntSize(100, 150)); RegisterMockedHttpURLLoad("content-width-1000.html"); NavigateTo(base_url_ + "content-width-1000.html"); @@ -1688,14 +1705,14 @@ NavigateTo("about:blank"); UpdateAllLifecyclePhases(); - WebView()->ResizeVisualViewport(IntSize(100, 100)); + WebView()->MainFrameWidget()->ResizeVisualViewport(IntSize(100, 100)); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); visual_viewport.Move(ScrollOffset(0, 100)); EXPECT_EQ(100, visual_viewport.GetScrollOffset().Height()); - WebView()->ResizeVisualViewport(IntSize(100, 200)); + WebView()->MainFrameWidget()->ResizeVisualViewport(IntSize(100, 200)); EXPECT_EQ(0, visual_viewport.GetScrollOffset().Height()); } @@ -1703,7 +1720,7 @@ TEST_P(VisualViewportTest, ElementBoundsInViewportSpaceAccountsForViewport) { InitializeWithAndroidSettings(); - WebView()->Resize(IntSize(500, 800)); + WebView()->MainFrameWidget()->Resize(IntSize(500, 800)); RegisterMockedHttpURLLoad("pinch-viewport-input-field.html"); NavigateTo(base_url_ + "pinch-viewport-input-field.html"); @@ -1732,7 +1749,7 @@ TEST_P(VisualViewportTest, ElementVisibleBoundsInVisualViewport) { InitializeWithAndroidSettings(); - WebView()->Resize(IntSize(640, 1080)); + WebView()->MainFrameWidget()->Resize(IntSize(640, 1080)); RegisterMockedHttpURLLoad("viewport-select.html"); NavigateTo(base_url_ + "viewport-select.html"); @@ -1830,7 +1847,7 @@ TEST_P(VisualViewportTest, TestMainFrameInitializationSizing) { InitializeWithAndroidSettings(); - WebView()->Resize(IntSize(100, 200)); + WebView()->MainFrameWidget()->Resize(IntSize(100, 200)); RegisterMockedHttpURLLoad("content-width-1000-min-scale.html"); NavigateTo(base_url_ + "content-width-1000-min-scale.html"); @@ -1849,7 +1866,7 @@ // Tests that the maximum scroll offset of the viewport can be fractional. TEST_P(VisualViewportTest, FractionalMaxScrollOffset) { InitializeWithDesktopSettings(); - WebView()->Resize(IntSize(101, 201)); + WebView()->MainFrameWidget()->Resize(IntSize(101, 201)); NavigateTo("about:blank"); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); @@ -1868,15 +1885,15 @@ // ScrollAnimatorBase class. TEST_P(VisualViewportTest, SlowScrollAfterImplScroll) { InitializeWithDesktopSettings(); - WebView()->Resize(IntSize(800, 600)); + WebView()->MainFrameWidget()->Resize(IntSize(800, 600)); NavigateTo("about:blank"); VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport(); // Apply some scroll and scale from the impl-side. - WebView()->ApplyViewportChanges({gfx::ScrollOffset(300, 200), - gfx::Vector2dF(0, 0), 2, 0, - cc::BrowserControlsState::kBoth}); + WebView()->MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(300, 200), gfx::Vector2dF(0, 0), 2, 0, + cc::BrowserControlsState::kBoth}); EXPECT_EQ(FloatSize(300, 200), visual_viewport.GetScrollOffset()); @@ -1941,7 +1958,7 @@ // Tests that the maximum scroll offset of the viewport can be fractional. TEST_P(VisualViewportTest, TestCoordinateTransforms) { InitializeWithAndroidSettings(); - WebView()->Resize(IntSize(800, 600)); + WebView()->MainFrameWidget()->Resize(IntSize(800, 600)); RegisterMockedHttpURLLoad("content-width-1000.html"); NavigateTo(base_url_ + "content-width-1000.html"); @@ -1998,7 +2015,7 @@ TEST_P(VisualViewportTest, WindowDimensionsOnLoad) { InitializeWithAndroidSettings(); RegisterMockedHttpURLLoad("window_dimensions.html"); - WebView()->Resize(IntSize(800, 600)); + WebView()->MainFrameWidget()->Resize(IntSize(800, 600)); NavigateTo(base_url_ + "window_dimensions.html"); Element* output = GetFrame()->GetDocument()->getElementById("output"); @@ -2014,7 +2031,7 @@ TEST_P(VisualViewportTest, WindowDimensionsOnLoadWideContent) { InitializeWithAndroidSettings(); RegisterMockedHttpURLLoad("window_dimensions_wide_div.html"); - WebView()->Resize(IntSize(800, 600)); + WebView()->MainFrameWidget()->Resize(IntSize(800, 600)); NavigateTo(base_url_ + "window_dimensions_wide_div.html"); Element* output = GetFrame()->GetDocument()->getElementById("output"); @@ -2035,7 +2052,7 @@ kProgrammaticScroll); UpdateAllLifecyclePhases(); - WebView()->Resize(IntSize(800, 300)); + WebView()->MainFrameWidget()->Resize(IntSize(800, 300)); EXPECT_EQ(ScrollOffset(700, 200), frame_view.LayoutViewport()->GetScrollOffset()); } @@ -2046,7 +2063,7 @@ ScopedSetRootScrollerForTest root_scroller(true); InitializeWithAndroidSettings(); - WebView()->Resize(IntSize(800, 600)); + WebView()->MainFrameWidget()->Resize(IntSize(800, 600)); RegisterMockedHttpURLLoad("root-scroller-div.html"); NavigateTo(base_url_ + "root-scroller-div.html"); @@ -2064,7 +2081,7 @@ VisualViewport& visual_viewport = WebView()->GetPage()->GetVisualViewport(); visual_viewport.SetScrollOffset(ScrollOffset(0, 400), kProgrammaticScroll); - WebView()->Resize(IntSize(800, 500)); + WebView()->MainFrameWidget()->Resize(IntSize(800, 500)); EXPECT_EQ(ScrollOffset(), frame_view.LayoutViewport()->GetScrollOffset()); } @@ -2089,7 +2106,7 @@ scroller->setScrollTop(800); - WebView()->Resize(IntSize(600, 800)); + WebView()->MainFrameWidget()->Resize(IntSize(600, 800)); EXPECT_EQ(ScrollOffset(), frame_view.LayoutViewport()->GetScrollOffset()); EXPECT_EQ(600, scroller->scrollTop()); @@ -2465,7 +2482,7 @@ // Test that we correcty size the visual viewport's scrolling contents layer // when the layout viewport is smaller. TEST_F(VisualViewportSimTest, ScrollingContentsSmallerThanContainer) { - WebView().Resize(WebSize(400, 600)); + WebView().MainFrameWidget()->Resize(WebSize(400, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -2496,8 +2513,9 @@ visual_viewport.GetScrollNode()->ContentsSize()); } - WebView().ApplyViewportChanges({gfx::ScrollOffset(1, 1), gfx::Vector2dF(), 2, - 1, cc::BrowserControlsState::kBoth}); + WebView().MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(1, 1), gfx::Vector2dF(), 2, 1, + cc::BrowserControlsState::kBoth}); EXPECT_EQ(gfx::Size(400, 600), visual_viewport.ContainerLayer()->Size()); EXPECT_EQ(gfx::Size(400, 600), visual_viewport.ContainerLayer()->CcLayer()->bounds());
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc index fb82051..036997d0 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -257,7 +257,7 @@ // both the WebViewImpl size and the Page's VisualViewport. If there are // multiple OOPIFs on a page, this will currently be set redundantly by // each of them. See https://crbug.com/599688. - View()->Resize(new_size); + View()->MainFrameWidget()->Resize(new_size); View()->DidUpdateFullscreenSize(); } @@ -276,11 +276,11 @@ } void WebFrameWidgetImpl::DidEnterFullscreen() { - View()->DidEnterFullscreen(); + View()->MainFrameWidget()->DidEnterFullscreen(); } void WebFrameWidgetImpl::DidExitFullscreen() { - View()->DidExitFullscreen(); + View()->MainFrameWidget()->DidExitFullscreen(); } void WebFrameWidgetImpl::SetSuppressFrameRequestsWorkaroundFor704763Only( @@ -1165,6 +1165,13 @@ return HitTestResultForRootFramePos(point_in_root_frame); } +void WebFrameWidgetImpl::ZoomToFindInPageRect( + const WebRect& rect_in_root_frame) { + // TODO(wjmaclean): add plumbing to send IPC to browser to request + // this zoom operation on the main frame's renderer. + // https://crbug.com/734209: Add OOPIF support. +} + HitTestResult WebFrameWidgetImpl::HitTestResultForRootFramePos( const LayoutPoint& pos_in_root_frame) { LayoutPoint doc_point(
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h index 53ea023..dc907a4 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h +++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
@@ -147,6 +147,7 @@ WebLayerTreeView* GetLayerTreeView() const override; CompositorAnimationHost* AnimationHost() const override; HitTestResult CoreHitTestResultAt(const gfx::Point&) override; + void ZoomToFindInPageRect(const WebRect& rect_in_root_frame) override; // Exposed for the purpose of overriding device metrics. void SendResizeEventAndRepaint();
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc index da22f459..81f3b170d 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -578,10 +578,10 @@ content_settings_client_ = client; } -void WebLocalFrameImpl::SetSharedWorkerRepositoryClient( - WebSharedWorkerRepositoryClient* client) { +void WebLocalFrameImpl::InitializeSharedWorkerRepositoryClient( + service_manager::InterfaceProvider* interface_provider) { shared_worker_repository_client_ = - SharedWorkerRepositoryClientImpl::Create(client); + SharedWorkerRepositoryClientImpl::Create(interface_provider); } ScrollableArea* WebLocalFrameImpl::LayoutViewport() const {
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h index 3f046d8..700bf5a8 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -36,9 +36,9 @@ #include "base/single_thread_task_runner.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom-blink.h" #include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink.h" #include "third_party/blink/public/platform/web_file_system_type.h" -#include "third_party/blink/public/web/devtools_agent.mojom-blink.h" #include "third_party/blink/public/web/web_history_commit_type.h" #include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_navigation_control.h" @@ -92,8 +92,8 @@ WebString AssignedName() const override; void SetName(const WebString&) override; WebVector<WebIconURL> IconURLs(int icon_types_mask) const override; - void SetSharedWorkerRepositoryClient( - WebSharedWorkerRepositoryClient*) override; + void InitializeSharedWorkerRepositoryClient( + service_manager::InterfaceProvider*) override; WebSize GetScrollOffset() const override; void SetScrollOffset(const WebSize&) override; WebSize DocumentSize() const override;
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc index f3c9e23..5f68cec 100644 --- a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc +++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
@@ -216,6 +216,11 @@ return web_view_->CoreHitTestResultAt(point); } +void WebViewFrameWidget::ZoomToFindInPageRect( + const WebRect& rect_in_root_frame) { + web_view_->ZoomToFindInPageRect(rect_in_root_frame); +} + void WebViewFrameWidget::Trace(blink::Visitor* visitor) { WebFrameWidgetBase::Trace(visitor); }
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.h b/third_party/blink/renderer/core/frame/web_view_frame_widget.h index e9217a0d..31d009a 100644 --- a/third_party/blink/renderer/core/frame/web_view_frame_widget.h +++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.h
@@ -98,6 +98,7 @@ WebLayerTreeView* GetLayerTreeView() const override; CompositorAnimationHost* AnimationHost() const override; HitTestResult CoreHitTestResultAt(const gfx::Point&) override; + void ZoomToFindInPageRect(const WebRect& rect_in_root_frame) override; void Trace(blink::Visitor*) override;
diff --git a/third_party/blink/renderer/core/frame/window_or_worker_global_scope.idl b/third_party/blink/renderer/core/frame/window_or_worker_global_scope.idl index 1b78426e..e5cd3c3 100644 --- a/third_party/blink/renderer/core/frame/window_or_worker_global_scope.idl +++ b/third_party/blink/renderer/core/frame/window_or_worker_global_scope.idl
@@ -58,8 +58,8 @@ void clearInterval(optional long handle = 0); // ImageBitmap - [CallWith=ScriptState] Promise createImageBitmap( + [CallWith=ScriptState] Promise<ImageBitmap> createImageBitmap( ImageBitmapSource imageBitmap, optional ImageBitmapOptions options); - [CallWith=ScriptState] Promise createImageBitmap( + [CallWith=ScriptState] Promise<ImageBitmap> createImageBitmap( ImageBitmapSource imageBitmap, long sx, long sy, long sw, long sh, optional ImageBitmapOptions options); };
diff --git a/third_party/blink/renderer/core/geometry/OWNERS b/third_party/blink/renderer/core/geometry/OWNERS index 0262a7d..204a655 100644 --- a/third_party/blink/renderer/core/geometry/OWNERS +++ b/third_party/blink/renderer/core/geometry/OWNERS
@@ -1,3 +1,2 @@ -dominicc@chromium.org fserb@chromium.org jinho.bang@samsung.com
diff --git a/third_party/blink/renderer/core/html/anchor_element_metrics_test.cc b/third_party/blink/renderer/core/html/anchor_element_metrics_test.cc index f318644..2f9e521 100644 --- a/third_party/blink/renderer/core/html/anchor_element_metrics_test.cc +++ b/third_party/blink/renderer/core/html/anchor_element_metrics_test.cc
@@ -45,7 +45,8 @@ void SetUp() override { SimTest::SetUp(); - WebView().Resize(WebSize(kViewportWidth, kViewportHeight)); + WebView().MainFrameWidget()->Resize( + WebSize(kViewportWidth, kViewportHeight)); feature_list_.InitAndEnableFeature(features::kRecordAnchorMetricsClicked); }
diff --git a/third_party/blink/renderer/core/html/custom/element_internals.cc b/third_party/blink/renderer/core/html/custom/element_internals.cc index ff75c8f..f20c50b7b 100644 --- a/third_party/blink/renderer/core/html/custom/element_internals.cc +++ b/third_party/blink/renderer/core/html/custom/element_internals.cc
@@ -16,6 +16,19 @@ namespace blink { +namespace { +bool IsValidityStateFlagsValid(const ValidityStateFlags* flags) { + if (!flags) + return true; + if (flags->badInput() || flags->customError() || flags->patternMismatch() || + flags->rangeOverflow() || flags->rangeUnderflow() || + flags->stepMismatch() || flags->tooLong() || flags->tooShort() || + flags->typeMismatch() || flags->valueMissing()) + return false; + return true; +} +} // anonymous namespace + ElementInternals::ElementInternals(HTMLElement& target) : target_(target) { value_.SetUSVString(String()); } @@ -78,11 +91,7 @@ } // Custom element authors should provide a message. They can omit the message // argument only if nothing if | flags| is true. - if ((flags->badInput() || flags->customError() || flags->patternMismatch() || - flags->rangeOverflow() || flags->rangeUnderflow() || - flags->stepMismatch() || flags->tooLong() || flags->tooShort() || - flags->typeMismatch() || flags->valueMissing()) && - message.IsEmpty()) { + if (!IsValidityStateFlagsValid(flags) && message.IsEmpty()) { exception_state.ThrowDOMException( DOMExceptionCode::kTypeMismatchError, "The second argument should not be empty if one or more flags in the " @@ -122,11 +131,21 @@ "The target element is not a form-associated custom element."); return String(); } - if (ListedElement::validity()->valid()) + return validationMessage(); +} + +String ElementInternals::validationMessage() const { + if (IsValidityStateFlagsValid(validity_flags_)) return String(); return CustomValidationMessage(); } +String ElementInternals::ValidationSubMessage() const { + if (PatternMismatch()) + return Target().FastGetAttribute(html_names::kTitleAttr).GetString(); + return String(); +} + bool ElementInternals::checkValidity(ExceptionState& exception_state) { if (!IsTargetFormAssociated()) { exception_state.ThrowDOMException(
diff --git a/third_party/blink/renderer/core/html/custom/element_internals.h b/third_party/blink/renderer/core/html/custom/element_internals.h index 7eb3572..77d233b 100644 --- a/third_party/blink/renderer/core/html/custom/element_internals.h +++ b/third_party/blink/renderer/core/html/custom/element_internals.h
@@ -64,6 +64,8 @@ bool TypeMismatch() const override; bool ValueMissing() const override; bool CustomError() const override; + String validationMessage() const override; + String ValidationSubMessage() const override; void DisabledStateMightBeChanged() override; Member<HTMLElement> target_;
diff --git a/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc b/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc index a6888218..4b3b9b8 100644 --- a/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc +++ b/third_party/blink/renderer/core/html/forms/external_popup_menu_test.cc
@@ -114,7 +114,7 @@ void LoadFrame(const std::string& file_name) { frame_test_helpers::LoadFrame(MainFrame(), base_url_ + file_name); - WebView()->Resize(WebSize(800, 600)); + WebView()->MainFrameWidget()->Resize(WebSize(800, 600)); WebView()->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); } @@ -135,7 +135,7 @@ RegisterMockedURLLoad("select_mid_screen.html"); LoadFrame("select_mid_screen.html"); - WebView()->Resize(WebSize(100, 100)); + WebView()->MainFrameWidget()->Resize(WebSize(100, 100)); WebView()->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest);
diff --git a/third_party/blink/renderer/core/html/forms/html_field_set_element.cc b/third_party/blink/renderer/core/html/forms/html_field_set_element.cc index b641d95..e8225573 100644 --- a/third_party/blink/renderer/core/html/forms/html_field_set_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_field_set_element.cc
@@ -54,13 +54,11 @@ bool HTMLFieldSetElement::IsValidElement() { for (Element* element : *elements()) { if (element->IsFormControlElement()) { - if (!ToHTMLFormControlElement(element)->checkValidity( - nullptr, kCheckValidityDispatchNoEvent)) + if (!ToHTMLFormControlElement(element)->IsNotCandidateOrValid()) return false; } else if (element->IsHTMLElement() && ToHTMLElement(element)->IsFormAssociatedCustomElement()) { - if (!element->EnsureElementInternals().ListedElement::checkValidity( - nullptr, kCheckValidityDispatchNoEvent)) + if (!element->EnsureElementInternals().IsNotCandidateOrValid()) return false; } }
diff --git a/third_party/blink/renderer/core/html/forms/html_form_element.cc b/third_party/blink/renderer/core/html/forms/html_form_element.cc index 652b6fb..10acde0 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_form_element.cc
@@ -101,8 +101,11 @@ } bool HTMLFormElement::IsValidElement() { - return !CheckInvalidControlsAndCollectUnhandled( - nullptr, kCheckValidityDispatchNoEvent); + for (const auto& element : ListedElements()) { + if (!element->IsNotCandidateOrValid()) + return false; + } + return true; } Node::InsertionNotificationRequest HTMLFormElement::InsertedInto( @@ -211,8 +214,7 @@ element->HideVisibleValidationMessage(); ListedElement::List unhandled_invalid_controls; - if (!CheckInvalidControlsAndCollectUnhandled( - &unhandled_invalid_controls, kCheckValidityDispatchInvalidEvent)) + if (!CheckInvalidControlsAndCollectUnhandled(&unhandled_invalid_controls)) return true; UseCounter::Count(GetDocument(), WebFeature::kFormValidationAbortedSubmission); @@ -718,15 +720,13 @@ } bool HTMLFormElement::checkValidity() { - return !CheckInvalidControlsAndCollectUnhandled( - nullptr, kCheckValidityDispatchInvalidEvent); + return !CheckInvalidControlsAndCollectUnhandled(nullptr); } bool HTMLFormElement::CheckInvalidControlsAndCollectUnhandled( - ListedElement::List* unhandled_invalid_controls, - CheckValidityEventBehavior event_behavior) { + ListedElement::List* unhandled_invalid_controls) { // Copy listedElements because event handlers called from - // HTMLFormControlElement::checkValidity() might change listedElements. + // ListedElement::checkValidity() might change listed_elements. const ListedElement::List& listed_elements = ListedElements(); HeapVector<Member<ListedElement>> elements; elements.ReserveCapacity(listed_elements.size()); @@ -745,12 +745,9 @@ should_check_validity = true; } if (should_check_validity && - !element->checkValidity(unhandled_invalid_controls, event_behavior) && + !element->checkValidity(unhandled_invalid_controls) && element->Form() == this) { ++invalid_controls_count; - if (!unhandled_invalid_controls && - event_behavior == kCheckValidityDispatchNoEvent) - return true; } } return invalid_controls_count;
diff --git a/third_party/blink/renderer/core/html/forms/html_form_element.h b/third_party/blink/renderer/core/html/forms/html_form_element.h index 86a39c5..816b11e 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_element.h +++ b/third_party/blink/renderer/core/html/forms/html_form_element.h
@@ -144,8 +144,7 @@ // Validates each of the controls, and stores controls of which 'invalid' // event was not canceled to the specified vector. Returns true if there // are any invalid controls in this form. - bool CheckInvalidControlsAndCollectUnhandled(ListedElement::List*, - CheckValidityEventBehavior); + bool CheckInvalidControlsAndCollectUnhandled(ListedElement::List*); Element* ElementFromPastNamesMap(const AtomicString&); void AddToPastNamesMap(Element*, const AtomicString& past_name);
diff --git a/third_party/blink/renderer/core/html/forms/listed_element.cc b/third_party/blink/renderer/core/html/forms/listed_element.cc index 09c26a5..1d46391a 100644 --- a/third_party/blink/renderer/core/html/forms/listed_element.cc +++ b/third_party/blink/renderer/core/html/forms/listed_element.cc
@@ -429,14 +429,9 @@ return nullptr; } -bool ListedElement::checkValidity(List* unhandled_invalid_controls, - CheckValidityEventBehavior event_behavior) { - if (!WillValidate()) +bool ListedElement::checkValidity(List* unhandled_invalid_controls) { + if (IsNotCandidateOrValid()) return true; - if (IsValidElement()) - return true; - if (event_behavior != kCheckValidityDispatchInvalidEvent) - return false; HTMLElement& element = ToHTMLElement(*this); Document* original_document = &element.GetDocument(); DispatchEventResult dispatch_result = element.DispatchEvent( @@ -457,8 +452,7 @@ bool ListedElement::reportValidity() { List unhandled_invalid_controls; - bool is_valid = checkValidity(&unhandled_invalid_controls, - kCheckValidityDispatchInvalidEvent); + bool is_valid = checkValidity(&unhandled_invalid_controls); if (is_valid || unhandled_invalid_controls.IsEmpty()) return is_valid; DCHECK_EQ(unhandled_invalid_controls.size(), 1u); @@ -493,6 +487,12 @@ return is_valid_; } +bool ListedElement::IsNotCandidateOrValid() { + // Apply Element::willValidate(), not ListedElement::WillValidate(), because + // some elements override willValidate(). + return !ToHTMLElement(this)->willValidate() || IsValidElement(); +} + void ListedElement::SetNeedsValidityCheck() { HTMLElement& element = ToHTMLElement(*this); if (!validity_is_dirty_) {
diff --git a/third_party/blink/renderer/core/html/forms/listed_element.h b/third_party/blink/renderer/core/html/forms/listed_element.h index af47337..5d19ccfd 100644 --- a/third_party/blink/renderer/core/html/forms/listed_element.h +++ b/third_party/blink/renderer/core/html/forms/listed_element.h
@@ -42,11 +42,6 @@ class ValidationMessageClient; class ValidityState; -enum CheckValidityEventBehavior { - kCheckValidityDispatchNoEvent, - kCheckValidityDispatchInvalidEvent -}; - // https://html.spec.whatwg.org/multipage/forms.html#category-listed class CORE_EXPORT ListedElement : public GarbageCollectedMixin { public: @@ -103,9 +98,7 @@ virtual void setCustomValidity(const String&); void UpdateVisibleValidationMessage(); void HideVisibleValidationMessage(); - bool checkValidity( - List* unhandled_invalid_controls = nullptr, - CheckValidityEventBehavior = kCheckValidityDispatchInvalidEvent); + bool checkValidity(List* unhandled_invalid_controls = nullptr); bool reportValidity(); // This must be called only after the caller check the element is focusable. void ShowValidationMessage(); @@ -117,6 +110,12 @@ // For Element::IsValidElement(), which is for :valid :invalid selectors. bool IsValidElement(); + // Returns true if + // - this is not a candidate for constraint validation, or + // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#candidate-for-constraint-validation + // - this satisfies its constraints + // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#concept-fv-valid + bool IsNotCandidateOrValid(); // This must be called when a validation constraint or control value is // changed.
diff --git a/third_party/blink/renderer/core/html/forms/resources/listPicker.js b/third_party/blink/renderer/core/html/forms/resources/listPicker.js index 2ed7603e..59af8767 100644 --- a/third_party/blink/renderer/core/html/forms/resources/listPicker.js +++ b/third_party/blink/renderer/core/html/forms/resources/listPicker.js
@@ -50,6 +50,7 @@ this._selectElement.addEventListener('change', this._handleChange.bind(this), false); window.addEventListener('message', this._handleWindowMessage.bind(this), false); window.addEventListener('mousemove', this._handleWindowMouseMove.bind(this), false); + window.addEventListener('mouseover', this._handleWindowMouseOver.bind(this), false); this._handleWindowTouchMoveBound = this._handleWindowTouchMove.bind(this); this._handleWindowTouchEndBound = this._handleWindowTouchEnd.bind(this); this._handleTouchSelectModeScrollBound = this._handleTouchSelectModeScroll.bind(this); @@ -115,12 +116,15 @@ } this.lastMousePositionX = event.clientX; this.lastMousePositionY = event.clientY; - this._highlightOption(event.target); this._selectionSetByMouseHover = true; // Prevent the select element from firing change events for mouse input. event.preventDefault(); }; +ListPicker.prototype._handleWindowMouseOver = function(event) { + this._highlightOption(event.target); +}; + ListPicker.prototype._handleMouseUp = function(event) { if (event.target.tagName !== 'OPTION') return;
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc index 251bde0..a4574f3 100644 --- a/third_party/blink/renderer/core/html/html_element.cc +++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -1516,6 +1516,12 @@ return IsFormAssociatedCustomElement(); } +bool HTMLElement::willValidate() const { + return IsFormAssociatedCustomElement() && const_cast<HTMLElement*>(this) + ->EnsureElementInternals() + .WillValidate(); +} + bool HTMLElement::IsValidElement() { return IsFormAssociatedCustomElement() && EnsureElementInternals().IsValidElement();
diff --git a/third_party/blink/renderer/core/html/html_element.h b/third_party/blink/renderer/core/html/html_element.h index 7401953..2d9f2e3d 100644 --- a/third_party/blink/renderer/core/html/html_element.h +++ b/third_party/blink/renderer/core/html/html_element.h
@@ -127,6 +127,7 @@ bool MatchesReadOnlyPseudoClass() const override; bool MatchesReadWritePseudoClass() const override; bool MatchesValidityPseudoClasses() const override; + bool willValidate() const override; bool IsValidElement() override; static const AtomicString& EventParameterName();
diff --git a/third_party/blink/renderer/core/html/html_frame_element_base.cc b/third_party/blink/renderer/core/html/html_frame_element_base.cc index 14734c34..466ad257 100644 --- a/third_party/blink/renderer/core/html/html_frame_element_base.cc +++ b/third_party/blink/renderer/core/html/html_frame_element_base.cc
@@ -63,7 +63,7 @@ // frame. NB: This check can be invoked without any JS on the stack for some // parser operations. In such case, we use the origin of the frame element's // containing document as the caller context. - v8::Isolate* isolate = GetDocument().GetIsolate(); + v8::Isolate* isolate = ToIsolate(&GetDocument()); LocalDOMWindow* accessing_window = isolate->InContext() ? CurrentDOMWindow(isolate) : GetDocument().domWindow();
diff --git a/third_party/blink/renderer/core/html/html_image_element.idl b/third_party/blink/renderer/core/html/html_image_element.idl index b752807..e65d65b0 100644 --- a/third_party/blink/renderer/core/html/html_image_element.idl +++ b/third_party/blink/renderer/core/html/html_image_element.idl
@@ -61,5 +61,5 @@ [MeasureAs=HTMLImageElementX] readonly attribute long x; [MeasureAs=HTMLImageElementY] readonly attribute long y; - [CallWith=ScriptState, RaisesException] Promise decode(); + [CallWith=ScriptState, RaisesException] Promise<void> decode(); };
diff --git a/third_party/blink/renderer/core/html/image_document_test.cc b/third_party/blink/renderer/core/html/image_document_test.cc index 4caa6312..e88d48f 100644 --- a/third_party/blink/renderer/core/html/image_document_test.cc +++ b/third_party/blink/renderer/core/html/image_document_test.cc
@@ -326,7 +326,7 @@ HTMLImageElement* img = GetDocument().ImageElement(); // no zoom - WebView().Resize(IntSize(100, 100)); + WebView().MainFrameWidget()->Resize(IntSize(100, 100)); WebView().SetZoomFactorForDeviceScaleFactor(1.f); Compositor().BeginFrame(); EXPECT_EQ(50u, img->width()); @@ -340,7 +340,7 @@ // visual viewport should be same in CSS pixel, as no dsf applied. // This simulates running on two phones with different screen densities but // same (physical) screen size, image document should displayed the same. - WebView().Resize(IntSize(400, 400)); + WebView().MainFrameWidget()->Resize(IntSize(400, 400)); WebView().SetZoomFactorForDeviceScaleFactor(4.f); Compositor().BeginFrame(); EXPECT_EQ(50u, img->width()); @@ -369,7 +369,7 @@ // Image smaller then webview size, visual viewport is not zoomed, and image // will be centered in the viewport. - WebView().Resize(IntSize(200, 200)); + WebView().MainFrameWidget()->Resize(IntSize(200, 200)); Compositor().BeginFrame(); EXPECT_EQ(50u, img->width()); EXPECT_EQ(50u, img->height()); @@ -383,7 +383,7 @@ // Image wider than webview size, image should fill the visual viewport, and // visual viewport zoom out to 0.5. - WebView().Resize(IntSize(50, 50)); + WebView().MainFrameWidget()->Resize(IntSize(50, 50)); Compositor().BeginFrame(); EXPECT_EQ(50u, img->width()); EXPECT_EQ(50u, img->height()); @@ -394,7 +394,7 @@ // When image is more than 10X wider than webview, shrink the image to fit the // width of the screen. - WebView().Resize(IntSize(4, 20)); + WebView().MainFrameWidget()->Resize(IntSize(4, 20)); Compositor().BeginFrame(); EXPECT_EQ(20u, img->width()); EXPECT_EQ(20u, img->height());
diff --git a/third_party/blink/renderer/core/html/imports/html_import_sheets_test.cc b/third_party/blink/renderer/core/html/imports/html_import_sheets_test.cc index 5bddf38..3f20a86d 100644 --- a/third_party/blink/renderer/core/html/imports/html_import_sheets_test.cc +++ b/third_party/blink/renderer/core/html/imports/html_import_sheets_test.cc
@@ -16,7 +16,7 @@ void SetUp() override { SimTest::SetUp(); - WebView().Resize(WebSize(640, 480)); + WebView().MainFrameWidget()->Resize(WebSize(640, 480)); } };
diff --git a/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc b/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc index 2a1da7a..b46efa70 100644 --- a/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc +++ b/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc
@@ -102,7 +102,8 @@ std::get<WebEffectiveConnectionType>(GetParam())); SimTest::SetUp(); - WebView().Resize(WebSize(kViewportWidth, kViewportHeight)); + WebView().MainFrameWidget()->Resize( + WebSize(kViewportWidth, kViewportHeight)); Settings& settings = WebView().GetPage()->GetSettings(); @@ -1109,7 +1110,8 @@ WebEffectiveConnectionType::kTypeUnknown); SimTest::SetUp(); - WebView().Resize(WebSize(kViewportWidth, kViewportHeight)); + WebView().MainFrameWidget()->Resize( + WebSize(kViewportWidth, kViewportHeight)); Settings& settings = WebView().GetPage()->GetSettings(); settings.SetLazyFrameLoadingDistanceThresholdPxUnknown(
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc index 5cb60c4..0617edd 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -609,6 +609,7 @@ } bool HTMLMediaElement::SupportsFocus() const { + // TODO(https://crbug.com/911882): Depending on result of discussion, remove. if (ownerDocument()->IsMediaDocument()) return false; @@ -618,7 +619,7 @@ } bool HTMLMediaElement::IsMouseFocusable() const { - return false; + return !IsFullscreen(); } void HTMLMediaElement::ParseAttribute(
diff --git a/third_party/blink/renderer/core/html/media_element_filling_viewport_test.cc b/third_party/blink/renderer/core/html/media_element_filling_viewport_test.cc index e8dda256..31c4298 100644 --- a/third_party/blink/renderer/core/html/media_element_filling_viewport_test.cc +++ b/third_party/blink/renderer/core/html/media_element_filling_viewport_test.cc
@@ -20,7 +20,7 @@ void SetUp() override { SimTest::SetUp(); - WebView().Resize(WebSize(640, 480)); + WebView().MainFrameWidget()->Resize(WebSize(640, 480)); } bool IsMostlyFillingViewport(HTMLMediaElement* element) {
diff --git a/third_party/blink/renderer/core/input/event_handler_test.cc b/third_party/blink/renderer/core/input/event_handler_test.cc index 6a9e9886..7556894 100644 --- a/third_party/blink/renderer/core/input/event_handler_test.cc +++ b/third_party/blink/renderer/core/input/event_handler_test.cc
@@ -1085,7 +1085,7 @@ // Test that leaving an iframe sets the mouse position to unknown on that // iframe. TEST_F(EventHandlerSimTest, MouseLeaveIFrameResets) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest main_resource("https://example.com/test.html", "text/html"); SimRequest frame_resource("https://example.com/frame.html", "text/html"); @@ -1152,7 +1152,7 @@ // Test that mouse down and move a small distance on a draggable element will // not change cursor style. TEST_F(EventHandlerSimTest, CursorStyleBeforeStartDragging) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1194,7 +1194,7 @@ // Ensure that tap on element in iframe should apply active state. TEST_F(EventHandlerSimTest, TapActiveInFrame) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest main_resource("https://example.com/test.html", "text/html"); SimRequest frame_resource("https://example.com/iframe.html", "text/html");
diff --git a/third_party/blink/renderer/core/input/ime_on_focus_test.cc b/third_party/blink/renderer/core/input/ime_on_focus_test.cc index a334dbd7..67b6913d 100644 --- a/third_party/blink/renderer/core/input/ime_on_focus_test.cc +++ b/third_party/blink/renderer/core/input/ime_on_focus_test.cc
@@ -98,7 +98,7 @@ WebString::FromUTF8(file_name)); WebViewImpl* web_view = web_view_helper_.Initialize(nullptr, nullptr, &client); - web_view->Resize(WebSize(800, 1200)); + web_view->MainFrameWidget()->Resize(WebSize(800, 1200)); LoadFrame(web_view->MainFrameImpl(), base_url_ + file_name); document_ = web_view_helper_.GetWebView() ->MainFrameImpl()
diff --git a/third_party/blink/renderer/core/input/overscroll_behavior_test.cc b/third_party/blink/renderer/core/input/overscroll_behavior_test.cc index 4e35a02..c642b37 100644 --- a/third_party/blink/renderer/core/input/overscroll_behavior_test.cc +++ b/third_party/blink/renderer/core/input/overscroll_behavior_test.cc
@@ -29,7 +29,7 @@ void OverscrollBehaviorTest::SetUp() { SimTest::SetUp(); v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(400, 400)); + WebView().MainFrameWidget()->Resize(WebSize(400, 400)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML(
diff --git a/third_party/blink/renderer/core/input/pointer_event_manager_test.cc b/third_party/blink/renderer/core/input/pointer_event_manager_test.cc index f5618bb5..9af61ef 100644 --- a/third_party/blink/renderer/core/input/pointer_event_manager_test.cc +++ b/third_party/blink/renderer/core/input/pointer_event_manager_test.cc
@@ -121,7 +121,7 @@ }; TEST_F(PointerEventManagerTest, PointerCancelsOfAllTypes) { - WebView().Resize(WebSize(400, 400)); + WebView().MainFrameWidget()->Resize(WebSize(400, 400)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete( @@ -133,12 +133,12 @@ GetDocument().body()->addEventListener(event_type_names::kPointercancel, callback); - WebView().HandleInputEvent(WebCoalescedInputEvent( + WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent( CreateTestPointerEvent(WebInputEvent::kPointerDown, WebPointerProperties::PointerType::kTouch), std::vector<WebPointerEvent>(), std::vector<WebPointerEvent>())); - WebView().HandleInputEvent(WebCoalescedInputEvent( + WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent( CreateTestPointerEvent(WebInputEvent::kPointerDown, WebPointerProperties::PointerType::kPen), std::vector<WebPointerEvent>(), std::vector<WebPointerEvent>())); @@ -150,7 +150,7 @@ ASSERT_EQ(callback->touchEventCount(), 0); ASSERT_EQ(callback->penEventCount(), 0); - WebView().HandleInputEvent(WebCoalescedInputEvent( + WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent( CreateTestPointerEvent(WebInputEvent::kPointerCausedUaAction, WebPointerProperties::PointerType::kPen), std::vector<WebPointerEvent>(), std::vector<WebPointerEvent>())); @@ -158,7 +158,7 @@ ASSERT_EQ(callback->touchEventCount(), 1); ASSERT_EQ(callback->penEventCount(), 1); - WebView().HandleInputEvent(WebCoalescedInputEvent( + WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent( CreateTestPointerEvent(WebInputEvent::kPointerCausedUaAction, WebPointerProperties::PointerType::kTouch), std::vector<WebPointerEvent>(), std::vector<WebPointerEvent>())); @@ -176,7 +176,7 @@ } TEST_F(PointerEventManagerTest, PointerEventCoordinates) { - WebView().Resize(WebSize(400, 400)); + WebView().MainFrameWidget()->Resize(WebSize(400, 400)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete( @@ -188,7 +188,7 @@ GetDocument().body()->addEventListener(event_type_names::kPointerdown, callback); - WebView().HandleInputEvent(WebCoalescedInputEvent( + WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent( CreateTestPointerEvent(WebInputEvent::kPointerDown, WebPointerProperties::PointerType::kTouch, WebFloatPoint(150, 200), WebFloatPoint(100, 50), @@ -208,7 +208,7 @@ } TEST_F(PointerEventManagerTest, PointerEventMovements) { - WebView().Resize(WebSize(400, 400)); + WebView().MainFrameWidget()->Resize(WebSize(400, 400)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete( @@ -222,7 +222,7 @@ // Turn on the flag for test. RuntimeEnabledFeatures::SetMovementXYInBlinkEnabled(true); - WebView().HandleInputEvent(WebCoalescedInputEvent( + WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent( CreateTestPointerEvent(WebInputEvent::kPointerMove, WebPointerProperties::PointerType::kMouse, WebFloatPoint(150, 210), WebFloatPoint(100, 50), @@ -234,7 +234,7 @@ ASSERT_EQ(callback->last_movement_x_, 0); ASSERT_EQ(callback->last_movement_y_, 0); - WebView().HandleInputEvent(WebCoalescedInputEvent( + WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent( CreateTestPointerEvent(WebInputEvent::kPointerMove, WebPointerProperties::PointerType::kMouse, WebFloatPoint(150, 200), WebFloatPoint(132, 29), @@ -246,7 +246,7 @@ ASSERT_EQ(callback->last_movement_x_, 32); ASSERT_EQ(callback->last_movement_y_, -21); - WebView().HandleInputEvent(WebCoalescedInputEvent( + WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent( CreateTestPointerEvent(WebInputEvent::kPointerMove, WebPointerProperties::PointerType::kMouse, WebFloatPoint(150, 210), @@ -262,7 +262,7 @@ // When flag is off, movementX/Y follows the value in WebPointerProperties. RuntimeEnabledFeatures::SetMovementXYInBlinkEnabled(false); - WebView().HandleInputEvent(WebCoalescedInputEvent( + WebView().MainFrameWidget()->HandleInputEvent(WebCoalescedInputEvent( CreateTestPointerEvent(WebInputEvent::kPointerMove, WebPointerProperties::PointerType::kMouse, WebFloatPoint(150, 210), WebFloatPoint(100, 16.25),
diff --git a/third_party/blink/renderer/core/input/scroll_snap_test.cc b/third_party/blink/renderer/core/input/scroll_snap_test.cc index 4ad31292..d8d162a 100644 --- a/third_party/blink/renderer/core/input/scroll_snap_test.cc +++ b/third_party/blink/renderer/core/input/scroll_snap_test.cc
@@ -33,7 +33,7 @@ void ScrollSnapTest::SetUpForDiv() { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(400, 400)); + WebView().MainFrameWidget()->Resize(WebSize(400, 400)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -204,7 +204,7 @@ TEST_F(ScrollSnapTest, SnapWhenBodyViewportDefining) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(300, 300)); + WebView().MainFrameWidget()->Resize(WebSize(300, 300)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -251,7 +251,7 @@ TEST_F(ScrollSnapTest, SnapWhenHtmlViewportDefining) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(300, 300)); + WebView().MainFrameWidget()->Resize(WebSize(300, 300)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -301,7 +301,7 @@ TEST_F(ScrollSnapTest, SnapWhenBodyOverflowHtmlViewportDefining) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(300, 300)); + WebView().MainFrameWidget()->Resize(WebSize(300, 300)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML(
diff --git a/third_party/blink/renderer/core/input/touch_action_test.cc b/third_party/blink/renderer/core/input/touch_action_test.cc index 4e3e1f4..453e18d8e 100644 --- a/third_party/blink/renderer/core/input/touch_action_test.cc +++ b/third_party/blink/renderer/core/input/touch_action_test.cc
@@ -206,7 +206,7 @@ // Set size to enable hit testing, and avoid line wrapping for consistency // with browser. - web_view->Resize(WebSize(900, 1600)); + web_view->MainFrameWidget()->Resize(WebSize(900, 1600)); // Scroll to verify the code properly transforms windows to client co-ords. const int kScrollOffset = 100;
diff --git a/third_party/blink/renderer/core/input/touch_event_manager_test.cc b/third_party/blink/renderer/core/input/touch_event_manager_test.cc index 2760a137..3f57bd3 100644 --- a/third_party/blink/renderer/core/input/touch_event_manager_test.cc +++ b/third_party/blink/renderer/core/input/touch_event_manager_test.cc
@@ -58,7 +58,7 @@ }; TEST_F(TouchEventManagerTest, LostTouchDueToInnerIframeRemove) { - WebView().Resize(WebSize(400, 400)); + WebView().MainFrameWidget()->Resize(WebSize(400, 400)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML(
diff --git a/third_party/blink/renderer/core/inspector/devtools_agent.h b/third_party/blink/renderer/core/inspector/devtools_agent.h index 270834b..1c4b9dfc 100644 --- a/third_party/blink/renderer/core/inspector/devtools_agent.h +++ b/third_party/blink/renderer/core/inspector/devtools_agent.h
@@ -11,7 +11,7 @@ #include "base/unguessable_token.h" #include "mojo/public/cpp/bindings/associated_binding.h" #include "mojo/public/cpp/bindings/binding.h" -#include "third_party/blink/public/web/devtools_agent.mojom-blink.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom-blink.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/wtf/forward.h"
diff --git a/third_party/blink/renderer/core/inspector/devtools_session.h b/third_party/blink/renderer/core/inspector/devtools_session.h index b187664e..78f42b6 100644 --- a/third_party/blink/renderer/core/inspector/devtools_session.h +++ b/third_party/blink/renderer/core/inspector/devtools_session.h
@@ -7,7 +7,7 @@ #include "base/macros.h" #include "mojo/public/cpp/bindings/associated_binding.h" -#include "third_party/blink/public/web/devtools_agent.mojom-blink.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom-blink.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/inspector/inspector_session_state.h" #include "third_party/blink/renderer/core/inspector/protocol/Forward.h"
diff --git a/third_party/blink/renderer/core/inspector/inspector_session_state.h b/third_party/blink/renderer/core/inspector/inspector_session_state.h index 3c5c8c6..0c7fabe 100644 --- a/third_party/blink/renderer/core/inspector/inspector_session_state.h +++ b/third_party/blink/renderer/core/inspector/inspector_session_state.h
@@ -8,7 +8,7 @@ #include <memory> #include <type_traits> #include <vector> -#include "third_party/blink/public/web/devtools_agent.mojom-blink.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom-blink.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/third_party/blink/renderer/core/inspector/worker_devtools_params.h b/third_party/blink/renderer/core/inspector/worker_devtools_params.h index f42f4655..f80f402 100644 --- a/third_party/blink/renderer/core/inspector/worker_devtools_params.h +++ b/third_party/blink/renderer/core/inspector/worker_devtools_params.h
@@ -6,7 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_WORKER_DEVTOOLS_PARAMS_H_ #include "base/unguessable_token.h" -#include "third_party/blink/public/web/devtools_agent.mojom-blink.h" +#include "third_party/blink/public/mojom/devtools/devtools_agent.mojom-blink.h" namespace blink {
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc index b003ea3b..ebe67a8 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc
@@ -145,7 +145,7 @@ } TEST_F(IntersectionObserverTest, ResumePostsTask) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest main_resource("https://example.com/", "text/html"); LoadURL("https://example.com/"); main_resource.Complete(R"HTML( @@ -205,7 +205,7 @@ } TEST_F(IntersectionObserverTest, HitTestAfterMutation) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest main_resource("https://example.com/", "text/html"); LoadURL("https://example.com/"); main_resource.Complete(R"HTML( @@ -252,7 +252,7 @@ } TEST_F(IntersectionObserverTest, DisconnectClearsNotifications) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest main_resource("https://example.com/", "text/html"); LoadURL("https://example.com/"); main_resource.Complete(R"HTML( @@ -289,7 +289,7 @@ TEST_F(IntersectionObserverTest, RootIntersectionWithForceZeroLayoutHeight) { WebView().GetSettings()->SetForceZeroLayoutHeight(true); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest main_resource("https://example.com/", "text/html"); LoadURL("https://example.com/"); main_resource.Complete(R"HTML( @@ -378,7 +378,7 @@ } TEST_F(IntersectionObserverV2Test, BasicOcclusion) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest main_resource("https://example.com/", "text/html"); LoadURL("https://example.com/"); main_resource.Complete(R"HTML( @@ -437,7 +437,7 @@ } TEST_F(IntersectionObserverV2Test, BasicOpacity) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest main_resource("https://example.com/", "text/html"); LoadURL("https://example.com/"); main_resource.Complete(R"HTML( @@ -486,7 +486,7 @@ } TEST_F(IntersectionObserverV2Test, BasicTransform) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest main_resource("https://example.com/", "text/html"); LoadURL("https://example.com/"); main_resource.Complete(R"HTML(
diff --git a/third_party/blink/renderer/core/layout/BUILD.gn b/third_party/blink/renderer/core/layout/BUILD.gn index c3d109d..75287430 100644 --- a/third_party/blink/renderer/core/layout/BUILD.gn +++ b/third_party/blink/renderer/core/layout/BUILD.gn
@@ -351,6 +351,8 @@ "ng/inline/ng_inline_item.h", "ng/inline/ng_inline_item_result.cc", "ng/inline/ng_inline_item_result.h", + "ng/inline/ng_inline_item_segment.cc", + "ng/inline/ng_inline_item_segment.h", "ng/inline/ng_inline_items.h", "ng/inline/ng_inline_items_builder.cc", "ng/inline/ng_inline_items_builder.h",
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc index e7a05e4c9..63757a68 100644 --- a/third_party/blink/renderer/core/layout/layout_block.cc +++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -434,8 +434,21 @@ LayoutAnalyzer::Scope analyzer(*this); - if (LayoutBlockedByDisplayLock()) - return; + base::Optional<DisplayLockContext::ScopedPendingFrameRect> + scoped_pending_frame_rect; + if (auto* context = GetDisplayLockContext()) { + // In a display locked element, we might be prevented from doing layout in + // which case we should abort. + if (LayoutBlockedByDisplayLock()) + return; + // If we're display locked, then our layout should go into a pending frame + // rect without updating the frame rect visible to the ancestors. The + // following scoped object provides this functionality: it puts in place the + // (previously updated) pending frame rect. When the object is destroyed, it + // saves the pending frame rect in the DisplayLockContext and restores the + // frame rect that was in place at the time the lock was acquired. + scoped_pending_frame_rect.emplace(context->GetScopedPendingFrameRect()); + } bool needs_scroll_anchoring = HasOverflowClip() && GetScrollableArea()->ShouldPerformScrollAnchoring(); @@ -879,11 +892,24 @@ // know this up-front, to correctly evaluate if we need to mark for // relayout, and, if our estimate is correct, we'll even be able to insert // correct pagination struts on the first attempt. - LogicalExtentComputedValues computed_values; - positioned_object->ComputeLogicalHeight(positioned_object->LogicalHeight(), - positioned_object->LogicalTop(), - computed_values); - logical_top_estimate = computed_values.position_; + const ComputedStyle& style = positioned_object->StyleRef(); + if (!style.LogicalBottom().IsAuto() && style.LogicalTop().IsAuto() && + style.LogicalHeight().IsAuto()) { + // This child is bottom-aligned with auto block size. We cannot make a + // decent estimate before layout. Just estimate something as far above a + // fragmentainer break as possible. This is a way to try our best to avoid + // hitting fragmentainer breaks, as that could impact the block size of + // the child (increase it if contents need to be pushed to the next + // fragmentainer, or decrease it if a descendant margin collides into a + // fragmentainer boundary), and thus give us a bad block-start offset. + logical_top_estimate = -OffsetFromLogicalTopOfFirstPage(); + } else { + LogicalExtentComputedValues computed_values; + positioned_object->ComputeLogicalHeight( + positioned_object->LogicalHeight(), positioned_object->LogicalTop(), + computed_values); + logical_top_estimate = computed_values.position_; + } positioned_object->SetLogicalTop(logical_top_estimate); }
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h index cb77e5f..f72f027 100644 --- a/third_party/blink/renderer/core/layout/layout_box.h +++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -389,6 +389,14 @@ SetLocation(rect.Location()); SetSize(rect.Size()); } + // Similar to SetFrameRect(), except it avoids notifying other code about size + // and location changes. This should only be used from a DisplayLockContext to + // temporarily put in place a pending frame rect which is restored at the end + // of layout. Code outside of layout should not observe location or size + // changes. + void SetFrameRectForDisplayLock(const LayoutRect& rect) { + frame_rect_ = rect; + } // Note that those functions have their origin at this box's CSS border box. // As such their location doesn't account for 'top'/'left'. About its
diff --git a/third_party/blink/renderer/core/layout/layout_image_resource.cc b/third_party/blink/renderer/core/layout/layout_image_resource.cc index 62ebf5c..ad5af39 100644 --- a/third_party/blink/renderer/core/layout/layout_image_resource.cc +++ b/third_party/blink/renderer/core/layout/layout_image_resource.cc
@@ -143,7 +143,12 @@ } scoped_refptr<Image> LayoutImageResource::GetImage( - const LayoutSize& container_size) const { + const IntSize& container_size) const { + return GetImage(FloatSize(container_size)); +} + +scoped_refptr<Image> LayoutImageResource::GetImage( + const FloatSize& container_size) const { if (!cached_image_) return Image::NullImage(); @@ -164,7 +169,7 @@ url = node->GetDocument().CompleteURL(url_string); } return SVGImageForContainer::Create( - ToSVGImage(image), FloatSize(container_size), + ToSVGImage(image), container_size, layout_object_->StyleRef().EffectiveZoom(), url); }
diff --git a/third_party/blink/renderer/core/layout/layout_image_resource.h b/third_party/blink/renderer/core/layout/layout_image_resource.h index ffd214d..27ce0cc 100644 --- a/third_party/blink/renderer/core/layout/layout_image_resource.h +++ b/third_party/blink/renderer/core/layout/layout_image_resource.h
@@ -56,7 +56,8 @@ void ResetAnimation(); bool MaybeAnimated() const; - virtual scoped_refptr<Image> GetImage(const LayoutSize&) const; + virtual scoped_refptr<Image> GetImage(const FloatSize&) const; + scoped_refptr<Image> GetImage(const IntSize&) const; virtual bool ErrorOccurred() const { return cached_image_ && cached_image_->ErrorOccurred(); }
diff --git a/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc b/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc index d713f05..9d633fe 100644 --- a/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc +++ b/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc
@@ -59,13 +59,13 @@ } scoped_refptr<Image> LayoutImageResourceStyleImage::GetImage( - const LayoutSize& size) const { + const FloatSize& size) const { // Generated content may trigger calls to image() while we're still pending, // don't assert but gracefully exit. if (style_image_->IsPendingImage()) return nullptr; return style_image_->GetImage(*layout_object_, layout_object_->GetDocument(), - layout_object_->StyleRef(), FloatSize(size)); + layout_object_->StyleRef(), size); } FloatSize LayoutImageResourceStyleImage::ImageSize(float multiplier) const {
diff --git a/third_party/blink/renderer/core/layout/layout_image_resource_style_image.h b/third_party/blink/renderer/core/layout/layout_image_resource_style_image.h index bdc4d0d..6cfd1bf9 100644 --- a/third_party/blink/renderer/core/layout/layout_image_resource_style_image.h +++ b/third_party/blink/renderer/core/layout/layout_image_resource_style_image.h
@@ -47,7 +47,7 @@ void Shutdown() override; bool HasImage() const override { return true; } - scoped_refptr<Image> GetImage(const LayoutSize&) const override; + scoped_refptr<Image> GetImage(const FloatSize&) const override; bool ErrorOccurred() const override { return style_image_->ErrorOccurred(); } bool ImageHasRelativeSize() const override {
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index ad1f25c..81c899f 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -2386,6 +2386,14 @@ context->DidLayout(); } + DisplayLockContext* GetDisplayLockContext() const { + if (!RuntimeEnabledFeatures::DisplayLockingEnabled()) + return nullptr; + if (!GetNode() || !GetNode()->IsElementNode()) + return nullptr; + return ToElement(GetNode())->GetDisplayLockContext(); + } + private: // Used only by applyFirstLineChanges to get a first line style based off of a // given new style, without accessing the cache. @@ -2469,14 +2477,6 @@ } LayoutRect AdjustVisualRectForInlineBox(const LayoutRect&) const; - DisplayLockContext* GetDisplayLockContext() const { - if (!RuntimeEnabledFeatures::DisplayLockingEnabled()) - return nullptr; - if (!GetNode() || !GetNode()->IsElementNode()) - return nullptr; - return ToElement(GetNode())->GetDisplayLockContext(); - } - // This is set by Set[Subtree]ShouldDoFullPaintInvalidation, and cleared // during PrePaint in this object's InvalidatePaint(). It's different from // DisplayItemClient::GetPaintInvalidationReason() which is set during
diff --git a/third_party/blink/renderer/core/layout/ng/geometry/ng_logical_offset.cc b/third_party/blink/renderer/core/layout/ng/geometry/ng_logical_offset.cc index c5ec508..8fead03 100644 --- a/third_party/blink/renderer/core/layout/ng/geometry/ng_logical_offset.cc +++ b/third_party/blink/renderer/core/layout/ng/geometry/ng_logical_offset.cc
@@ -77,6 +77,11 @@ return *this; } +NGLogicalOffset& NGLogicalOffset::operator+=(const NGLogicalSize& size) { + *this = *this + size; + return *this; +} + bool NGLogicalOffset::operator>(const NGLogicalOffset& other) const { return inline_offset > other.inline_offset && block_offset > other.block_offset;
diff --git a/third_party/blink/renderer/core/layout/ng/geometry/ng_logical_offset.h b/third_party/blink/renderer/core/layout/ng/geometry/ng_logical_offset.h index 00d51ca..1f3b38a 100644 --- a/third_party/blink/renderer/core/layout/ng/geometry/ng_logical_offset.h +++ b/third_party/blink/renderer/core/layout/ng/geometry/ng_logical_offset.h
@@ -45,6 +45,7 @@ NGLogicalOffset operator+(const NGLogicalOffset& other) const; NGLogicalOffset operator+(const NGLogicalSize& size) const; NGLogicalOffset& operator+=(const NGLogicalOffset& other); + NGLogicalOffset& operator+=(const NGLogicalSize& size); NGLogicalDelta operator-(const NGLogicalOffset& other) const; NGLogicalOffset& operator-=(const NGLogicalOffset& other);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc index 9d6fa0a..97038f8 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc
@@ -153,10 +153,49 @@ return {layout_object, LayoutRect()}; } +LocalCaretRect ComputeLocalSelectionRect( + const NGCaretPosition& caret_position) { + const LocalCaretRect caret_rect = ComputeLocalCaretRect(caret_position); + if (!caret_rect.layout_object) + return caret_rect; + + const LayoutObject* layout_object = caret_rect.layout_object; + const LayoutRect rect = caret_rect.rect; + + const NGPaintFragment& fragment = *caret_position.fragment; + const NGPaintFragment* line_box = fragment.ContainerLineBox(); + // TODO(xiaochengh): We'll hit this DCHECK for caret in empty block if we + // enable LayoutNG in contenteditable. + DCHECK(line_box); + + if (fragment.Style().IsHorizontalWritingMode()) { + const LayoutUnit line_top = line_box->InlineOffsetToContainerBox().top; + const LayoutUnit line_height = line_box->Size().height; + return LocalCaretRect(layout_object, LayoutRect(rect.X(), line_top, + rect.Width(), line_height)); + } + + const LayoutUnit line_top = line_box->InlineOffsetToContainerBox().left; + const LayoutUnit line_height = line_box->Size().width; + LayoutRect layout_rect(line_top, rect.Y(), line_height, rect.Height()); + // For vertical-rl, convert to "flipped block-flow" coordinates space. + // See core/layout/README.md#coordinate-spaces for details. + if (fragment.Style().IsFlippedBlocksWritingMode()) { + const LayoutBlockFlow* container = layout_object->ContainingNGBlockFlow(); + container->FlipForWritingMode(layout_rect); + } + return LocalCaretRect(layout_object, layout_rect); +} + } // namespace LocalCaretRect ComputeNGLocalCaretRect(const PositionWithAffinity& position) { return ComputeLocalCaretRect(ComputeNGCaretPosition(position)); } +LocalCaretRect ComputeNGLocalSelectionRect( + const PositionWithAffinity& position) { + return ComputeLocalSelectionRect(ComputeNGCaretPosition(position)); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.h b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.h index 4215ef0d..d7a1a029 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.h
@@ -20,6 +20,11 @@ // formatting context. CORE_EXPORT LocalCaretRect ComputeNGLocalCaretRect(const PositionWithAffinity&); +// Almost the same as ComputeNGLocalCaretRect, except that the returned rect +// is adjusted to span the containing line box in the block direction. +CORE_EXPORT LocalCaretRect +ComputeNGLocalSelectionRect(const PositionWithAffinity&); + } // namespace blink #endif // NGCaretRect_h
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc index 19a1adf2..fef96d5 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
@@ -101,20 +101,6 @@ return false; } -LayoutObject* -NGInlineLayoutStateStack::ContainingLayoutObjectForAbsolutePositionObjects() - const { - for (unsigned i = stack_.size(); i-- > 1;) { - const NGInlineBoxState& box = stack_[i]; - DCHECK(box.style); - if (box.style->CanContainAbsolutePositionObjects()) { - DCHECK(box.item->GetLayoutObject()); - return box.item->GetLayoutObject(); - } - } - return nullptr; -} - NGInlineBoxState* NGInlineLayoutStateStack::OnBeginPlaceItems( const ComputedStyle* line_style, FontBaseline baseline_type, @@ -608,10 +594,19 @@ child.layout_result.reset(); } else if (child.fragment) { box.AddChild(std::move(child.fragment), child.offset - offset); + } else if (child.out_of_flow_positioned_box) { + DCHECK(item->GetLayoutObject()->IsLayoutInline()); + NGBlockNode oof_box(ToLayoutBox(child.out_of_flow_positioned_box)); + + // child.offset is the static position wrt. the linebox. As we are adding + // this as a child of an inline level fragment, we adjust the static + // position to be relative to this fragment. + NGLogicalOffset static_offset = child.offset - offset; + + box.AddOutOfFlowChildCandidate(oof_box, static_offset, + child.container_direction); + child.out_of_flow_positioned_box = nullptr; } - // Leave out-of-flow fragments. They need to be at the top level so that - // NGInlineLayoutAlgorithm can handle them later. - DCHECK(!child.HasInFlowFragment()); } box.MoveOutOfFlowDescendantCandidatesToDescendants();
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h index 80d9eb3..32d8ae46 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
@@ -15,7 +15,6 @@ namespace blink { -class LayoutObject; class NGInlineItem; struct NGInlineItemResult; class ShapeResultView; @@ -135,8 +134,6 @@ // Compute all the pending positioning at the end of a line. void OnEndPlaceItems(NGLineBoxFragmentBuilder::ChildList*, FontBaseline); - LayoutObject* ContainingLayoutObjectForAbsolutePositionObjects() const; - bool HasBoxFragments() const { return !box_data_list_.IsEmpty(); } // This class keeps indexes to fragments in the line box, and that only
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc index 00946fc..a22d01eb 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc
@@ -67,9 +67,7 @@ style_(style), layout_object_(layout_object), type_(type), - script_(0), - font_fallback_priority_(0), - render_orientation_(0), + segment_data_(0), bidi_level_(UBIDI_LTR), shape_options_(kPreContext | kPostContext), is_empty_item_(false), @@ -92,9 +90,7 @@ style_(other.style_), layout_object_(other.layout_object_), type_(other.type_), - script_(other.script_), - font_fallback_priority_(other.font_fallback_priority_), - render_orientation_(other.render_orientation_), + segment_data_(other.segment_data_), bidi_level_(other.bidi_level_), shape_options_(other.shape_options_), is_empty_item_(other.is_empty_item_), @@ -151,94 +147,27 @@ return kNGInlineItemTypeStrings[val]; } -UScriptCode NGInlineItem::Script() const { - return script_ != kInvalidScript ? static_cast<UScriptCode>(script_) - : USCRIPT_INVALID_CODE; -} - -FontFallbackPriority NGInlineItem::GetFontFallbackPriority() const { - return static_cast<enum FontFallbackPriority>(font_fallback_priority_); -} - -OrientationIterator::RenderOrientation NGInlineItem::RenderOrientation() const { - return static_cast<OrientationIterator::RenderOrientation>( - render_orientation_); -} - RunSegmenter::RunSegmenterRange NGInlineItem::CreateRunSegmenterRange() const { - return {start_offset_, end_offset_, Script(), RenderOrientation(), - GetFontFallbackPriority()}; + return NGInlineItemSegment::UnpackSegmentData(start_offset_, end_offset_, + segment_data_); } bool NGInlineItem::EqualsRunSegment(const NGInlineItem& other) const { - return script_ == other.script_ && - font_fallback_priority_ == other.font_fallback_priority_ && - render_orientation_ == other.render_orientation_; + return segment_data_ == other.segment_data_; } -void NGInlineItem::SetRunSegment(const RunSegmenter::RunSegmenterRange& range) { +void NGInlineItem::SetSegmentData(unsigned segment_data) { DCHECK_EQ(Type(), NGInlineItem::kText); - - // Orientation should be set in a separate pass. See - // NGInlineNode::SegmentScriptRuns(). - DCHECK_EQ(range.render_orientation, OrientationIterator::kOrientationKeep); - - script_ = static_cast<unsigned>(range.script); - font_fallback_priority_ = static_cast<unsigned>(range.font_fallback_priority); - - // Ensure our bit fields are large enough by reading them back. - DCHECK_EQ(range.script, Script()); - DCHECK_EQ(range.font_fallback_priority, GetFontFallbackPriority()); + segment_data_ = segment_data; } -void NGInlineItem::SetFontOrientation( - OrientationIterator::RenderOrientation orientation) { - DCHECK_EQ(Type(), NGInlineItem::kText); - - // Ensure the value can fit in the bit field. - DCHECK_LT(static_cast<unsigned>(orientation), 1u << 1); - - render_orientation_ = orientation != 0; -} - -unsigned NGInlineItem::PopulateItemsFromRun( - Vector<NGInlineItem>& items, - unsigned index, - const RunSegmenter::RunSegmenterRange& range) { - DCHECK_GE(range.end, items[index].start_offset_); - - for (;; index++) { - NGInlineItem& item = items[index]; - DCHECK_LE(item.start_offset_, range.end); - +void NGInlineItem::SetSegmentData(const RunSegmenter::RunSegmenterRange& range, + Vector<NGInlineItem>* items) { + unsigned segment_data = NGInlineItemSegment::PackSegmentData(range); + for (NGInlineItem& item : *items) { if (item.Type() == NGInlineItem::kText) - item.SetRunSegment(range); - - if (range.end == item.end_offset_) - break; - if (range.end < item.end_offset_) { - Split(items, index, range.end); - break; - } + item.segment_data_ = segment_data; } - return index + 1; -} - -unsigned NGInlineItem::PopulateItemsFromFontOrientation( - Vector<NGInlineItem>& items, - unsigned index, - unsigned end_offset, - OrientationIterator::RenderOrientation orientation) { - // FontOrientaiton is set per item, end_offset should be within this item. - NGInlineItem& item = items[index]; - DCHECK_GE(end_offset, item.start_offset_); - DCHECK_LE(end_offset, item.end_offset_); - - item.SetFontOrientation(orientation); - - if (end_offset < item.end_offset_) - Split(items, index, end_offset); - return index + 1; } void NGInlineItem::SetBidiLevel(UBiDiLevel level) {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h index 8becfc6..7604cd2 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h
@@ -6,6 +6,7 @@ #define NGInlineItem_h #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h" #include "third_party/blink/renderer/core/layout/ng/ng_style_variant.h" #include "third_party/blink/renderer/core/style/computed_style.h" @@ -142,24 +143,14 @@ static void Split(Vector<NGInlineItem>&, unsigned index, unsigned offset); - // Get RunSegmenter properties. - UScriptCode Script() const; - FontFallbackPriority GetFontFallbackPriority() const; - OrientationIterator::RenderOrientation RenderOrientation() const; + // RunSegmenter properties. + unsigned SegmentData() const { return segment_data_; } + void SetSegmentData(unsigned segment_data); + static void SetSegmentData(const RunSegmenter::RunSegmenterRange& range, + Vector<NGInlineItem>* items); RunSegmenter::RunSegmenterRange CreateRunSegmenterRange() const; // Whether the other item has the same RunSegmenter properties or not. bool EqualsRunSegment(const NGInlineItem&) const; - // Set RunSegmenter properties. - static unsigned PopulateItemsFromRun(Vector<NGInlineItem>&, - unsigned index, - const RunSegmenter::RunSegmenterRange&); - void SetRunSegment(const RunSegmenter::RunSegmenterRange&); - static unsigned PopulateItemsFromFontOrientation( - Vector<NGInlineItem>&, - unsigned index, - unsigned end_offset, - OrientationIterator::RenderOrientation); - void SetFontOrientation(OrientationIterator::RenderOrientation); void SetBidiLevel(UBiDiLevel); static unsigned SetBidiLevel(Vector<NGInlineItem>&, @@ -184,15 +175,8 @@ scoped_refptr<const ComputedStyle> style_; LayoutObject* layout_object_; - // UScriptCode is -1 (USCRIPT_INVALID_CODE) to 177 as of ICU 60. - // This can be packed to 8 bits, by handling -1 separately. - static constexpr unsigned kScriptBits = 8; - static constexpr unsigned kInvalidScript = (1 << kScriptBits) - 1; - unsigned type_ : 4; - unsigned script_ : kScriptBits; - unsigned font_fallback_priority_ : 2; // FontFallbackPriority. - unsigned render_orientation_ : 1; // RenderOrientation (excl. kInvalid.) + unsigned segment_data_ : NGInlineItemSegment::kSegmentDataBits; unsigned bidi_level_ : 8; // UBiDiLevel is defined as uint8_t. unsigned shape_options_ : 2; unsigned is_empty_item_ : 1; @@ -225,6 +209,12 @@ String text_content; Vector<NGInlineItem> items; + // Cache RunSegmenter segments when at least one item has multiple runs. + // Set to nullptr when all items has only single run, which is common case for + // most writing systems. However, in multi-script writing systems such as + // Japanese, almost every item has multiple runs. + std::unique_ptr<NGInlineItemSegments> segments; + // The DOM to text content offset mapping of this inline node. std::unique_ptr<NGOffsetMapping> offset_mapping;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc new file mode 100644 index 0000000..b8aa6f02 --- /dev/null +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.cc
@@ -0,0 +1,256 @@ +// 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 "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.h" + +#include "third_party/blink/renderer/core/layout/layout_inline.h" +#include "third_party/blink/renderer/core/layout/layout_object.h" +#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h" +#include "third_party/blink/renderer/core/style/computed_style.h" +#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h" +#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h" + +namespace blink { + +namespace { + +// Constants for PackSegmentData() and UnpackSegmentData(). +// +// UScriptCode is -1 (USCRIPT_INVALID_CODE) to 177 as of ICU 60. +// This can be packed to 8 bits, by handling -1 separately. +static constexpr unsigned kScriptBits = 8; +static constexpr unsigned kFontFallbackPriorityBits = 2; +static constexpr unsigned kRenderOrientationBits = 1; + +static constexpr unsigned kScriptMask = (1 << kScriptBits) - 1; +static constexpr unsigned kFontFallbackPriorityMask = + (1 << kFontFallbackPriorityBits) - 1; +static constexpr unsigned kRenderOrientationMask = + (1 << kRenderOrientationBits) - 1; + +static_assert(NGInlineItemSegment::kSegmentDataBits == + kScriptBits + kRenderOrientationBits + + kFontFallbackPriorityBits, + "kSegmentDataBits must be the sum of these bits"); + +unsigned SetRenderOrientation( + unsigned value, + OrientationIterator::RenderOrientation render_orientation) { + DCHECK_NE(render_orientation, + OrientationIterator::RenderOrientation::kOrientationInvalid); + return (value & ~kRenderOrientationMask) | + (render_orientation != + OrientationIterator::RenderOrientation::kOrientationKeep); +} + +} // namespace + +NGInlineItemSegment::NGInlineItemSegment( + const RunSegmenter::RunSegmenterRange& range) + : end_offset_(range.end), segment_data_(PackSegmentData(range)) {} + +NGInlineItemSegment::NGInlineItemSegment(unsigned end_offset, + const NGInlineItem& item) + : end_offset_(end_offset), segment_data_(item.SegmentData()) {} + +unsigned NGInlineItemSegment::PackSegmentData( + const RunSegmenter::RunSegmenterRange& range) { + DCHECK(range.script == USCRIPT_INVALID_CODE || + static_cast<unsigned>(range.script) <= kScriptMask); + DCHECK_LE(static_cast<unsigned>(range.font_fallback_priority), + kFontFallbackPriorityMask); + DCHECK_LE(static_cast<unsigned>(range.render_orientation), + kRenderOrientationMask); + + unsigned value = + range.script != USCRIPT_INVALID_CODE ? range.script : kScriptMask; + value <<= kFontFallbackPriorityBits; + value |= static_cast<unsigned>(range.font_fallback_priority); + value <<= kRenderOrientationBits; + value |= range.render_orientation; + return value; +} + +RunSegmenter::RunSegmenterRange NGInlineItemSegment::UnpackSegmentData( + unsigned start_offset, + unsigned end_offset, + unsigned value) { + unsigned render_orientation = value & kRenderOrientationMask; + value >>= kRenderOrientationBits; + unsigned font_fallback_priority = value & kFontFallbackPriorityMask; + value >>= kFontFallbackPriorityBits; + unsigned script = value & kScriptMask; + return RunSegmenter::RunSegmenterRange{ + start_offset, end_offset, + script != kScriptMask ? static_cast<UScriptCode>(script) + : USCRIPT_INVALID_CODE, + static_cast<OrientationIterator::RenderOrientation>(render_orientation), + static_cast<FontFallbackPriority>(font_fallback_priority)}; +} + +RunSegmenter::RunSegmenterRange NGInlineItemSegment::ToRunSegmenterRange( + unsigned start_offset, + unsigned end_offset) const { + DCHECK_LT(start_offset, end_offset); + DCHECK_LT(start_offset, end_offset_); + return UnpackSegmentData(start_offset, std::min(end_offset, end_offset_), + segment_data_); +} + +unsigned NGInlineItemSegments::OffsetForSegment( + const NGInlineItemSegment& segment) const { + return &segment == segments_.begin() ? 0 : std::prev(&segment)->EndOffset(); +} + +#if DCHECK_IS_ON() +void NGInlineItemSegments::CheckOffset( + unsigned offset, + const NGInlineItemSegment* segment) const { + DCHECK(segment >= segments_.begin() && segment < segments_.end()); + DCHECK_GE(offset, OffsetForSegment(*segment)); + DCHECK_LT(offset, segment->EndOffset()); +} +#endif + +NGInlineItemSegments::Iterator NGInlineItemSegments::Ranges( + unsigned start_offset, + unsigned end_offset, + unsigned item_index) const { + DCHECK_LT(start_offset, end_offset); + DCHECK_LE(end_offset, EndOffset()); + + // Find the first segment for |item_index|. + unsigned segment_index = items_to_segments_[item_index]; + const NGInlineItemSegment* segment = &segments_[segment_index]; + DCHECK_GE(start_offset, OffsetForSegment(*segment)); + if (start_offset < segment->EndOffset()) + return Iterator(start_offset, end_offset, segment); + + // The item has multiple segments. Find the segments for |start_offset|. + unsigned end_segment_index = item_index + 1 < items_to_segments_.size() + ? items_to_segments_[item_index + 1] + : segments_.size(); + CHECK_GT(end_segment_index, segment_index); + CHECK_LE(end_segment_index, segments_.size()); + segment = std::upper_bound( + segment, segment + (end_segment_index - segment_index), start_offset, + [](unsigned offset, const NGInlineItemSegment& segment) { + return offset < segment.EndOffset(); + }); + CheckOffset(start_offset, segment); + return Iterator(start_offset, end_offset, segment); +} + +void NGInlineItemSegments::ComputeSegments( + RunSegmenter* segmenter, + RunSegmenter::RunSegmenterRange* range) { + segments_.Shrink(0); + do { + segments_.emplace_back(*range); + } while (segmenter->Consume(range)); +} + +unsigned NGInlineItemSegments::AppendMixedFontOrientation( + const String& text_content, + unsigned start_offset, + unsigned end_offset, + unsigned segment_index) { + DCHECK_LT(start_offset, end_offset); + OrientationIterator iterator(text_content.Characters16() + start_offset, + end_offset - start_offset, + FontOrientation::kVerticalMixed); + unsigned original_start_offset = start_offset; + OrientationIterator::RenderOrientation orientation; + for (; iterator.Consume(&end_offset, &orientation); + start_offset = end_offset) { + end_offset += original_start_offset; + segment_index = PopulateItemsFromFontOrientation( + start_offset, end_offset, orientation, segment_index); + } + return segment_index; +} + +unsigned NGInlineItemSegments::PopulateItemsFromFontOrientation( + unsigned start_offset, + unsigned end_offset, + OrientationIterator::RenderOrientation render_orientation, + unsigned segment_index) { + DCHECK_LT(start_offset, end_offset); + DCHECK_LE(end_offset, segments_.back().EndOffset()); + + while (start_offset >= segments_[segment_index].EndOffset()) + ++segment_index; + if (start_offset != + (segment_index ? segments_[segment_index - 1].EndOffset() : 0u)) { + Split(segment_index, start_offset); + ++segment_index; + } + + for (;; ++segment_index) { + NGInlineItemSegment& segment = segments_[segment_index]; + segment.segment_data_ = + SetRenderOrientation(segment.segment_data_, render_orientation); + if (end_offset == segment.EndOffset()) { + ++segment_index; + break; + } + if (end_offset < segment.EndOffset()) { + Split(segment_index, end_offset); + ++segment_index; + break; + } + } + + return segment_index; +} + +void NGInlineItemSegments::Split(unsigned index, unsigned offset) { + NGInlineItemSegment& segment = segments_[index]; + DCHECK_LT(offset, segment.EndOffset()); + unsigned end_offset = segment.EndOffset(); + segment.end_offset_ = offset; + segments_.insert(index + 1, + NGInlineItemSegment(end_offset, segment.segment_data_)); +} + +void NGInlineItemSegments::ComputeItemIndex(const Vector<NGInlineItem>& items) { + DCHECK_EQ(items.back().EndOffset(), EndOffset()); + unsigned segment_index = 0; + const NGInlineItemSegment* segment = segments_.begin(); + unsigned item_index = 0; + items_to_segments_.resize(items.size()); + for (const NGInlineItem& item : items) { + while (segment_index < segments_.size() && + item.StartOffset() >= segment->EndOffset()) { + ++segment_index; + ++segment; + } + items_to_segments_[item_index++] = segment_index; + } +} + +scoped_refptr<ShapeResult> NGInlineItemSegments::ShapeText( + HarfBuzzShaper* shaper, + const Font* font, + TextDirection direction, + unsigned start_offset, + unsigned end_offset, + unsigned item_index) const { + scoped_refptr<ShapeResult> shape_result; + for (const RunSegmenter::RunSegmenterRange& range : + Ranges(start_offset, end_offset, item_index)) { + scoped_refptr<ShapeResult> segment_shape_result = + shaper->Shape(font, direction, range.start, range.end, &range); + if (!shape_result) + shape_result = std::move(segment_shape_result); + else + segment_shape_result->CopyRange(0, end_offset, shape_result.get()); + } + DCHECK(shape_result); + DCHECK_EQ(shape_result->StartIndex(), start_offset); + DCHECK_EQ(shape_result->EndIndex(), end_offset); + return shape_result; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.h new file mode 100644 index 0000000..c9510b5 --- /dev/null +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_segment.h
@@ -0,0 +1,186 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_ITEM_SEGMENT_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_ITEM_SEGMENT_H_ + +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h" +#include "third_party/blink/renderer/core/layout/ng/ng_style_variant.h" +#include "third_party/blink/renderer/core/style/computed_style.h" +#include "third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h" +#include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h" +#include "third_party/blink/renderer/platform/text/text_direction.h" + +#include <unicode/ubidi.h> +#include <unicode/uscript.h> + +namespace blink { + +class HarfBuzzShaper; +class NGInlineItem; + +// Represents a segment produced by |RunSegmenter|. +// +// |RunSegmenter| is forward-only that this class provides random access to the +// result by keeping in memory. This class packs the data in a compact form to +// minimize the memory impact. +class CORE_EXPORT NGInlineItemSegment { + DISALLOW_NEW(); + + public: + NGInlineItemSegment(unsigned end_offset, unsigned segment_data) + : end_offset_(end_offset), segment_data_(segment_data) {} + NGInlineItemSegment(const RunSegmenter::RunSegmenterRange& range); + NGInlineItemSegment(unsigned end_offset, const NGInlineItem& item); + + RunSegmenter::RunSegmenterRange ToRunSegmenterRange( + unsigned start_offset, + unsigned end_offset) const; + + unsigned EndOffset() const { return end_offset_; } + + // Pack/unpack utility functions to store in bit fields. + static constexpr unsigned kSegmentDataBits = 11; + + static unsigned PackSegmentData(const RunSegmenter::RunSegmenterRange& range); + static RunSegmenter::RunSegmenterRange + UnpackSegmentData(unsigned start_offset, unsigned end_offset, unsigned value); + + private: + unsigned end_offset_; + unsigned segment_data_ : kSegmentDataBits; + + friend class NGInlineItemSegments; +}; + +// Represents a set of |NGInlineItemSegment| for an inline formatting context +// represented by |NGInlineItemsData|. +// +// The segments/block ratio for Latin is 1.0 to 1.01 in average, while it +// increases to 1.01 to 1.05 for most other writing systems because it is common +// to have some Latin words within paragraphs. +// +// For writing systems that has multiple native scripts such as Japanese, the +// ratio jumps to 10-30, or sometimes 300 depends on the length of the block, +// because the average characters/segment ratio in Japanese is 2-5. This class +// builds internal indexes for faster access in such cases. +class CORE_EXPORT NGInlineItemSegments { + USING_FAST_MALLOC(NGInlineItemSegments); + + public: + unsigned size() const { return segments_.size(); } + bool IsEmpty() const { return segments_.IsEmpty(); } + + // Start/end offset of each segment/entire segments. + unsigned OffsetForSegment(const NGInlineItemSegment& segment) const; + unsigned EndOffset() const { return segments_.back().EndOffset(); } + + void ReserveCapacity(unsigned capacity) { + segments_.ReserveCapacity(capacity); + } + + // Append a |NGInlineItemSegment| using one of its constructors. + template <class... Args> + void Append(Args&&... args) { + segments_.emplace_back(std::forward<Args>(args)...); + } + + // Compute segments from the given |RunSegmenter|. + void ComputeSegments(RunSegmenter* segmenter, + RunSegmenter::RunSegmenterRange* range); + + // Append mixed-vertical font orientation segments for the specified range. + // This is separated from |ComputeSegments| because this result depends on + // fonts. + unsigned AppendMixedFontOrientation(const String& text_content, + unsigned start_offset, + unsigned end_offset, + unsigned segment_index); + + // Compute an internal items-to-segments index for faster access. + void ComputeItemIndex(const Vector<NGInlineItem>& items); + + // Iterates |RunSegmenterRange| for the given offsets. + class Iterator { + public: + Iterator(unsigned start_offset, + unsigned end_offset, + const NGInlineItemSegment* segment); + + bool IsDone() const { return range_.start == end_offset_; } + + // This class provides both iterator and range for the simplicity. + const Iterator& begin() const { return *this; } + const Iterator& end() const { return *this; } + + bool operator!=(const Iterator& other) const { return !IsDone(); } + const RunSegmenter::RunSegmenterRange& operator*() const { return range_; } + void operator++(); + + private: + RunSegmenter::RunSegmenterRange range_; + const NGInlineItemSegment* segment_; + unsigned start_offset_; + unsigned end_offset_; + }; + using const_iterator = Iterator; + + // Returns an iterator for the given offsets. + // + // |item_index| is the index of |NGInlineItem| for the |start_offset|. + const_iterator Ranges(unsigned start_offset, + unsigned end_offset, + unsigned item_index) const; + + // Shape runs in the range and return the concatenated |ShapeResult|. + scoped_refptr<ShapeResult> ShapeText(HarfBuzzShaper* shaper, + const Font* font, + TextDirection direction, + unsigned start_offset, + unsigned end_offset, + unsigned item_index) const; + + private: + unsigned PopulateItemsFromFontOrientation( + unsigned start_offset, + unsigned end_offset, + OrientationIterator::RenderOrientation, + unsigned segment_index); + void Split(unsigned index, unsigned offset); + +#if DCHECK_IS_ON() + void CheckOffset(unsigned offset, const NGInlineItemSegment* segment) const; +#else + void CheckOffset(unsigned offset, const NGInlineItemSegment* segment) const {} +#endif + + Vector<NGInlineItemSegment> segments_; + Vector<unsigned> items_to_segments_; +}; + +inline NGInlineItemSegments::Iterator::Iterator( + unsigned start_offset, + unsigned end_offset, + const NGInlineItemSegment* segment) + : segment_(segment), start_offset_(start_offset), end_offset_(end_offset) { + DCHECK_LT(start_offset, end_offset); + DCHECK_LT(start_offset, segment->EndOffset()); + range_ = segment->ToRunSegmenterRange(start_offset_, end_offset_); +} + +inline void NGInlineItemSegments::Iterator::operator++() { + DCHECK_LE(range_.end, end_offset_); + if (range_.end == end_offset_) { + range_.start = end_offset_; + return; + } + start_offset_ = range_.end; + ++segment_; + range_ = segment_->ToRunSegmenterRange(start_offset_, end_offset_); +} + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_INLINE_ITEM_SEGMENT_H_
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc index 2fe5b2fd..5888f14b 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc
@@ -302,6 +302,14 @@ return false; } + if (bidi_context_.size() && new_style.PreserveNewline()) { + // We exit and then re-enter all bidi contexts around a forced breaks. We + // must go through the full pipeline to ensure that we exit and enter the + // contexts in the same in the re-layout. + if (layout_text->GetText().Contains(kNewlineCharacter)) + return false; + } + for (const NGInlineItem* item : items) { // Collapsed space item at the start will not be restored, and that not // needed to add.
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc index 87358fff..ce3dce9a 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -247,6 +247,8 @@ CheckBoxStates(*line_info, BreakToken()); #endif + bool has_out_of_flow_positioned_items = false; + // In order to match other browsers when list-style-type: none, pretend // there's an invisible marker here. if (line_style.Display() == EDisplay::kListItem && @@ -293,10 +295,16 @@ } else if (item.Type() == NGInlineItem::kListMarker) { PlaceListMarker(item, &item_result, *line_info); } else if (item.Type() == NGInlineItem::kOutOfFlowPositioned) { - line_box_.AddChild( - item.GetLayoutObject(), - box_states_->ContainingLayoutObjectForAbsolutePositionObjects(), - item.BidiLevel()); + // An inline-level OOF child positions itself based on its direction, a + // block-level OOF child positions itself based on the direction of its + // block-level container. + TextDirection direction = + item.GetLayoutObject()->StyleRef().IsOriginalDisplayInlineType() + ? item.Direction() + : ConstraintSpace().Direction(); + + line_box_.AddChild(item.GetLayoutObject(), item.BidiLevel(), direction); + has_out_of_flow_positioned_items = true; } else if (item.Type() == NGInlineItem::kBidiControl) { line_box_.AddChild(item.BidiLevel()); } @@ -329,18 +337,6 @@ // always positive or 0. inline_size = inline_size.ClampNegativeToZero(); - // Create box fragmetns if needed. After this point forward, |line_box_| is a - // tree structure. - if (box_states_->HasBoxFragments()) - box_states_->CreateBoxFragments(&line_box_); - - // Update item index of the box states in the context. - context_->SetItemIndex(line_info->ItemsData().items, - line_info->EndItemIndex()); - - const NGLineHeightMetrics& line_box_metrics = - box_states_->LineBoxState().metrics; - // Other 'text-align' values than 'justify' move line boxes as a whole, but // indivisual items do not change their relative position to the line box. LayoutUnit bfc_line_offset = line_info->BfcOffset().line_offset; @@ -352,14 +348,32 @@ container_builder_.SetBfcLineOffset(bfc_line_offset); - // Handle out-of-flow positioned objects. They need inline offsets for their - // static positions. - PlaceOutOfFlowObjects(*line_info, line_box_metrics, inline_size); + const NGLineHeightMetrics& line_box_metrics = + box_states_->LineBoxState().metrics; + + // Place out-of-flow positioned objects. + // This adjusts the NGLineBoxFragmentBuilder::Child::offset member to contain + // the static position of the OOF positioned children relative to the linebox. + if (has_out_of_flow_positioned_items) + PlaceOutOfFlowObjects(*line_info, line_box_metrics); + + // Create box fragments if needed. After this point forward, |line_box_| is a + // tree structure. + // The individual children don't move position within the |line_box_|, rather + // the children have their layout_result, fragment, (or similar) set to null, + // creating a "hole" in the array. + if (box_states_->HasBoxFragments()) + box_states_->CreateBoxFragments(&line_box_); + + // Update item index of the box states in the context. + context_->SetItemIndex(line_info->ItemsData().items, + line_info->EndItemIndex()); // Even if we have something in-flow, it may just be empty items that // shouldn't trigger creation of a line. Exit now if that's the case. if (line_info->IsEmptyLine()) { container_builder_.SetIsEmptyLineBox(); + container_builder_.SetBaseDirection(line_info->BaseDirection()); container_builder_.AddChildren(line_box_); return; } @@ -373,9 +387,9 @@ if (line_info->UseFirstLineStyle()) container_builder_.SetStyleVariant(NGStyleVariant::kFirstLine); + container_builder_.SetBaseDirection(line_info->BaseDirection()); container_builder_.AddChildren(line_box_); container_builder_.SetInlineSize(inline_size); - container_builder_.SetBaseDirection(line_info->BaseDirection()); container_builder_.SetMetrics(line_box_metrics); container_builder_.SetBfcBlockOffset(line_info->BfcOffset().block_offset); } @@ -490,56 +504,66 @@ item_result->inline_size, item.BidiLevel()); } -// Place all out-of-flow objects in |line_box_| and clear them. -// @return whether |line_box_| has any in-flow fragments. +// Place all out-of-flow objects in |line_box_|. void NGInlineLayoutAlgorithm::PlaceOutOfFlowObjects( const NGLineInfo& line_info, - const NGLineHeightMetrics& line_box_metrics, - LayoutUnit inline_size) { - TextDirection line_direction = line_info.BaseDirection(); + const NGLineHeightMetrics& line_box_metrics) { + DCHECK(line_info.IsEmptyLine() || !line_box_metrics.IsEmpty()) + << "Non-empty lines must have a valid set of linebox metrics."; + + LayoutUnit line_height = + line_info.IsEmptyLine() ? LayoutUnit() : line_box_metrics.LineHeight(); + + // All children within the linebox are positioned relative to the baseline, + // then shifted later using NGLineBoxFragmentBuilder::MoveInBlockDirection. + LayoutUnit baseline_adjustment = + line_info.IsEmptyLine() ? LayoutUnit() : -line_box_metrics.ascent; + + // The location of the "next" line. + // + // This uses NGConstraintSpace::Direction rather than + // NGLineInfo::BaseDirection as this is for a block-level object rather than + // an inline-level object. + // + // Similarly this uses the available size to determine which edge to align + // to, and *does not* avoid floats. + LayoutUnit block_level_line_location = + IsLtr(ConstraintSpace().Direction()) + ? LayoutUnit() + : ConstraintSpace().AvailableSize().inline_size; + + // This offset represents the position of the "next" line, relative to the + // line we are currently creating, (this takes into account text-indent, etc). + LayoutUnit block_level_inline_offset = + block_level_line_location - (container_builder_.BfcLineOffset() - + ConstraintSpace().BfcOffset().line_offset); + + // To correctly determine which "line" block-level out-of-flow positioned + // object is placed on, we need to keep track of if there is any inline-level + // content preceeding it. + bool has_preceeding_inline_level_content = false; for (NGLineBoxFragmentBuilder::Child& child : line_box_) { + has_preceeding_inline_level_content |= child.HasInFlowFragment(); + LayoutObject* box = child.out_of_flow_positioned_box; if (!box) continue; - // The static position is at the line-top. Ignore the block_offset. - NGLogicalOffset static_offset(child.offset.inline_offset, LayoutUnit()); - - // If a block-level box appears in the middle of a line, move the static - // position to where the next block will be placed. - if (!box->StyleRef().IsOriginalDisplayInlineType()) { - LayoutUnit inline_offset = container_builder_.BfcLineOffset() - - ConstraintSpace().BfcOffset().line_offset; - - // Flip the inline_offset if we are in RTL. - if (IsRtl(line_direction)) { - LayoutUnit container_inline_size = - ConstraintSpace().AvailableSize().inline_size; - inline_offset = container_inline_size - inline_offset + inline_size; - } - - inline_offset += line_info.TextIndent(); - - // We need to subtract the line offset, in order to ignore floats and - // text-indent. - static_offset.inline_offset = -inline_offset; - - if (child.offset.inline_offset && !line_box_metrics.IsEmpty()) - static_offset.block_offset = line_box_metrics.LineHeight(); - } else if (IsRtl(line_direction)) { - // Our child offset is line-relative, but the static offset is - // flow-relative, using the direction we give to - // |AddInlineOutOfFlowChildCandidate|. - static_offset.inline_offset = inline_size - static_offset.inline_offset; + NGLogicalOffset static_offset(LayoutUnit(), baseline_adjustment); + if (box->StyleRef().IsOriginalDisplayInlineType()) { + // An inline-level OOF element positions itself within the line, at the + // position it would have been if it was in-flow. + static_offset.inline_offset = child.offset.inline_offset; + } else { + // A block-level OOF element positions itself on the "next" line. However + // only shifts down if there is inline-level content. + static_offset.inline_offset = block_level_inline_offset; + if (has_preceeding_inline_level_content) + static_offset.block_offset += line_height; } - container_builder_.AddInlineOutOfFlowChildCandidate( - NGBlockNode(ToLayoutBox(box)), static_offset, line_direction, - child.out_of_flow_containing_box); - - child.out_of_flow_positioned_box = nullptr; - child.out_of_flow_containing_box = nullptr; + child.offset = static_offset; } } @@ -559,6 +583,10 @@ // Justify the line. This changes the size of items by adding spacing. // Returns false if justification failed and should fall back to start-aligned. bool NGInlineLayoutAlgorithm::ApplyJustify(NGLineInfo* line_info) { + // Empty lines should align to start. + if (line_info->IsEmptyLine()) + return false; + NGLineAlign align(*line_info); if (align.space <= 0) return false; // no expansion is needed. @@ -572,6 +600,7 @@ // Append a hyphen if the last word is hyphenated. The hyphen is in // |ShapeResult|, but not in text. |ShapeResultSpacing| needs the text that // matches to the |ShapeResult|. + DCHECK(!line_info->Results().IsEmpty()); const NGInlineItemResult& last_item_result = line_info->Results().back(); if (last_item_result.text_end_effect == NGTextEndEffect::kHyphen) line_text.append(last_item_result.item->Style()->HyphenString());
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h index a65f542..f3d878a 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h
@@ -88,9 +88,7 @@ void PlaceLayoutResult(NGInlineItemResult*, NGInlineBoxState*, LayoutUnit inline_offset = LayoutUnit()); - void PlaceOutOfFlowObjects(const NGLineInfo&, - const NGLineHeightMetrics&, - LayoutUnit inline_size); + void PlaceOutOfFlowObjects(const NGLineInfo&, const NGLineHeightMetrics&); void PlaceListMarker(const NGInlineItem&, NGInlineItemResult*, const NGLineInfo&);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc index 3823d70..2c1633d 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
@@ -385,32 +385,48 @@ SegmentBidiRuns(data); SegmentScriptRuns(data); SegmentFontOrientation(data); + if (data->segments) + data->segments->ComputeItemIndex(data->items); } // Segment NGInlineItem by script, Emoji, and orientation using RunSegmenter. void NGInlineNode::SegmentScriptRuns(NGInlineNodeData* data) { - if (data->text_content.Is8Bit() && !data->is_bidi_enabled_) { + String& text_content = data->text_content; + if (text_content.IsEmpty()) { + data->segments = nullptr; + return; + } + + if (text_content.Is8Bit() && !data->is_bidi_enabled_) { if (data->items.size()) { RunSegmenter::RunSegmenterRange range = { 0u, data->text_content.length(), USCRIPT_LATIN, OrientationIterator::kOrientationKeep, FontFallbackPriority::kText}; - NGInlineItem::PopulateItemsFromRun(data->items, 0, range); + NGInlineItem::SetSegmentData(range, &data->items); } + data->segments = nullptr; return; } // Segment by script and Emoji. // Orientation is segmented separately, because it may vary by items. - Vector<NGInlineItem>& items = data->items; - String& text_content = data->text_content; text_content.Ensure16Bit(); RunSegmenter segmenter(text_content.Characters16(), text_content.length(), FontOrientation::kHorizontal); RunSegmenter::RunSegmenterRange range = RunSegmenter::NullRange(); - for (unsigned item_index = 0; segmenter.Consume(&range);) { - DCHECK_EQ(items[item_index].start_offset_, range.start); - item_index = NGInlineItem::PopulateItemsFromRun(items, item_index, range); + bool consumed = segmenter.Consume(&range); + DCHECK(consumed); + if (range.end == text_content.length()) { + NGInlineItem::SetSegmentData(range, &data->items); + data->segments = nullptr; + return; } + + // This node has multiple segments. + if (!data->segments) + data->segments = std::make_unique<NGInlineItemSegments>(); + data->segments->ComputeSegments(&segmenter, &range); + DCHECK_EQ(range.end, text_content.length()); } void NGInlineNode::SegmentFontOrientation(NGInlineNodeData* data) { @@ -420,26 +436,31 @@ return; Vector<NGInlineItem>& items = data->items; + if (items.IsEmpty()) + return; String& text_content = data->text_content; text_content.Ensure16Bit(); - for (unsigned item_index = 0; item_index < items.size();) { - NGInlineItem& item = items[item_index]; - if (item.Type() != NGInlineItem::kText || - item.Style()->GetFont().GetFontDescription().Orientation() != + // If we don't have |NGInlineItemSegments| yet, create a segment for the + // entire content. + const unsigned capacity = items.size() + text_content.length() / 10; + if (!data->segments) { + data->segments = std::make_unique<NGInlineItemSegments>(); + data->segments->ReserveCapacity(capacity); + data->segments->Append(text_content.length(), items.front()); + } else { + DCHECK(!data->segments->IsEmpty()); + data->segments->ReserveCapacity(capacity); + } + DCHECK_EQ(text_content.length(), data->segments->EndOffset()); + unsigned segment_index = 0; + + for (const NGInlineItem& item : items) { + if (item.Type() == NGInlineItem::kText && + item.Style()->GetFont().GetFontDescription().Orientation() == FontOrientation::kVerticalMixed) { - item_index++; - continue; - } - unsigned start_offset = item.StartOffset(); - OrientationIterator iterator(text_content.Characters16() + start_offset, - item.Length(), - FontOrientation::kVerticalMixed); - unsigned end_offset; - OrientationIterator::RenderOrientation orientation; - while (iterator.Consume(&end_offset, &orientation)) { - item_index = NGInlineItem::PopulateItemsFromFontOrientation( - items, item_index, end_offset + start_offset, orientation); + segment_index = data->segments->AppendMixedFontOrientation( + text_content, item.StartOffset(), item.EndOffset(), segment_index); } } } @@ -491,17 +512,18 @@ void NGInlineNode::ShapeText(NGInlineItemsData* data, NGInlineItemsData* previous_data) { - ShapeText(data->text_content, &data->items, - previous_data ? &previous_data->text_content : nullptr); -} + const String& text_content = data->text_content; + Vector<NGInlineItem>* items = &data->items; + const String* previous_text = + previous_data ? &previous_data->text_content : nullptr; -void NGInlineNode::ShapeText(const String& text_content, - Vector<NGInlineItem>* items, - const String* previous_text) { // Provide full context of the entire node to the shaper. HarfBuzzShaper shaper(text_content); ShapeResultSpacing<String> spacing(text_content); + DCHECK(!data->segments || + data->segments->EndOffset() == text_content.length()); + for (unsigned index = 0; index < items->size();) { NGInlineItem& start_item = (*items)[index]; if (start_item.Type() != NGInlineItem::kText) { @@ -580,11 +602,19 @@ } // Shape each item with the full context of the entire node. - RunSegmenter::RunSegmenterRange range = - start_item.CreateRunSegmenterRange(); - range.end = end_offset; - scoped_refptr<ShapeResult> shape_result = shaper.Shape( - &font, direction, start_item.StartOffset(), end_offset, &range); + scoped_refptr<ShapeResult> shape_result; + if (!data->segments) { + RunSegmenter::RunSegmenterRange range = + start_item.CreateRunSegmenterRange(); + range.end = end_offset; + shape_result = shaper.Shape(&font, direction, start_item.StartOffset(), + end_offset, &range); + } else { + shape_result = data->segments->ShapeText( + &shaper, &font, direction, start_item.StartOffset(), end_offset, + &start_item - items->begin()); + } + if (UNLIKELY(spacing.SetSpacing(font.GetFontDescription()))) shape_result->ApplySpacing(spacing); @@ -849,7 +879,6 @@ ClearInlineFragment(layout_object); layout_object = next; } - block_flow->ClearNeedsLayout(); return true; }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h index 1e38711..147c861 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h
@@ -16,7 +16,6 @@ class NGConstraintSpace; class NGInlineBreakToken; class NGInlineChildLayoutContext; -class NGInlineItem; class NGLayoutResult; class NGOffsetMapping; class NGInlineNodeLegacy; @@ -112,9 +111,6 @@ void SegmentBidiRuns(NGInlineNodeData*); void ShapeText(NGInlineItemsData*, NGInlineItemsData* previous_data = nullptr); - void ShapeText(const String& text, - Vector<NGInlineItem>*, - const String* previous_text); void ShapeTextForFirstLineIfNeeded(NGInlineNodeData*); void AssociateItemsWithInlines(NGInlineNodeData*);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc index 52e6aa7..22b84a0 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/core/dom/text.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_child_layout_context.h" @@ -21,6 +22,8 @@ namespace blink { +using ::testing::ElementsAre; + class NGInlineNodeForTest : public NGInlineNode { public: using NGInlineNode::NGInlineNode; @@ -158,6 +161,14 @@ void ForceLayout() { GetDocument().body()->OffsetTop(); } + Vector<unsigned> ToEndOffsetList( + NGInlineItemSegments::const_iterator segments) { + Vector<unsigned> end_offsets; + for (const NGInlineItemSegment& segment : segments) + end_offsets.push_back(segment.EndOffset()); + return end_offsets; + } + scoped_refptr<const ComputedStyle> style_; LayoutNGBlockFlow* layout_block_flow_ = nullptr; LayoutObject* layout_object_ = nullptr; @@ -393,7 +404,7 @@ NGInlineNodeForTest node = CreateInlineNode(); node = CreateBidiIsolateNode(node, style_.get(), layout_object_); Vector<NGInlineItem>& items = node.Items(); - ASSERT_EQ(10u, items.size()); + EXPECT_EQ(9u, items.size()); TEST_ITEM_OFFSET_DIR(items[0], 0u, 6u, TextDirection::kLtr); TEST_ITEM_OFFSET_DIR(items[1], 6u, 7u, TextDirection::kLtr); TEST_ITEM_OFFSET_DIR(items[2], 7u, 13u, TextDirection::kRtl); @@ -402,8 +413,7 @@ TEST_ITEM_OFFSET_DIR(items[5], 15u, 16u, TextDirection::kRtl); TEST_ITEM_OFFSET_DIR(items[6], 16u, 21u, TextDirection::kRtl); TEST_ITEM_OFFSET_DIR(items[7], 21u, 22u, TextDirection::kLtr); - TEST_ITEM_OFFSET_DIR(items[8], 22u, 23u, TextDirection::kLtr); - TEST_ITEM_OFFSET_DIR(items[9], 23u, 28u, TextDirection::kLtr); + TEST_ITEM_OFFSET_DIR(items[8], 22u, 28u, TextDirection::kLtr); } #define TEST_TEXT_FRAGMENT(fragment, start_offset, end_offset) \ @@ -420,13 +430,12 @@ node.ShapeText(); Vector<scoped_refptr<const NGPhysicalTextFragment>> fragments; CreateLine(node, &fragments); - ASSERT_EQ(6u, fragments.size()); + EXPECT_EQ(5u, fragments.size()); TEST_TEXT_FRAGMENT(fragments[0], 0u, 6u); TEST_TEXT_FRAGMENT(fragments[1], 16u, 21u); TEST_TEXT_FRAGMENT(fragments[2], 14u, 15u); TEST_TEXT_FRAGMENT(fragments[3], 7u, 13u); - TEST_TEXT_FRAGMENT(fragments[4], 22u, 23u); - TEST_TEXT_FRAGMENT(fragments[5], 23u, 28u); + TEST_TEXT_FRAGMENT(fragments[4], 22u, 28u); } TEST_F(NGInlineNodeTest, MinMaxSize) { @@ -897,4 +906,63 @@ EXPECT_FALSE(layout_block_flow_->HasNGInlineNodeData()); } +// https://crbug.com/911220 +TEST_F(NGInlineNodeTest, PreservedNewlineWithBidiAndRelayout) { + SetupHtml("container", + "<style>span{unicode-bidi:isolate}</style>" + "<pre id=container>foo<span>\n</span>bar<br></pre>"); + EXPECT_EQ(String(u"foo\u2066\u2069\n\u2066\u2069bar\n"), GetText()); + + Node* new_text = Text::Create(GetDocument(), "baz"); + GetElementById("container")->appendChild(new_text); + UpdateAllLifecyclePhasesForTest(); + + // The bidi context popping and re-entering should be preserved around '\n'. + EXPECT_EQ(String(u"foo\u2066\u2069\n\u2066\u2069bar\nbaz"), GetText()); +} + +TEST_F(NGInlineNodeTest, SegmentRanges) { + SetupHtml("container", + "<div id=container>" + u"\u306Forange\u304C" + "<span>text</span>" + "</div>"); + + NGInlineItemsData* items_data = layout_block_flow_->GetNGInlineNodeData(); + ASSERT_TRUE(items_data); + NGInlineItemSegments* segments = items_data->segments.get(); + ASSERT_TRUE(segments); + + // Test EndOffset for the full text. All segment boundaries including the end + // of the text content should be returned. + Vector<unsigned> expect_0_12 = {1u, 7u, 8u, 12u}; + EXPECT_EQ(ToEndOffsetList(segments->Ranges(0, 12, 0)), expect_0_12); + + // Test ranges for each segment that start with 1st item. + Vector<unsigned> expect_0_1 = {1u}; + EXPECT_EQ(ToEndOffsetList(segments->Ranges(0, 1, 0)), expect_0_1); + Vector<unsigned> expect_2_3 = {3u}; + EXPECT_EQ(ToEndOffsetList(segments->Ranges(2, 3, 0)), expect_2_3); + Vector<unsigned> expect_7_8 = {8u}; + EXPECT_EQ(ToEndOffsetList(segments->Ranges(7, 8, 0)), expect_7_8); + + // Test ranges that acrosses multiple segments. + Vector<unsigned> expect_0_8 = {1u, 7u, 8u}; + EXPECT_EQ(ToEndOffsetList(segments->Ranges(0, 8, 0)), expect_0_8); + Vector<unsigned> expect_2_8 = {7u, 8u}; + EXPECT_EQ(ToEndOffsetList(segments->Ranges(2, 8, 0)), expect_2_8); + Vector<unsigned> expect_2_10 = {7u, 8u, 10u}; + EXPECT_EQ(ToEndOffsetList(segments->Ranges(2, 10, 0)), expect_2_10); + Vector<unsigned> expect_7_10 = {8u, 10u}; + EXPECT_EQ(ToEndOffsetList(segments->Ranges(7, 10, 0)), expect_7_10); + + // Test ranges that starts with 2nd item. + Vector<unsigned> expect_8_9 = {9u}; + EXPECT_EQ(ToEndOffsetList(segments->Ranges(8, 9, 1)), expect_8_9); + Vector<unsigned> expect_8_10 = {10u}; + EXPECT_EQ(ToEndOffsetList(segments->Ranges(8, 10, 1)), expect_8_10); + Vector<unsigned> expect_9_12 = {12u}; + EXPECT_EQ(ToEndOffsetList(segments->Ranges(9, 12, 1)), expect_9_12); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.cc index d70c22a1..cb562a2 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.cc
@@ -78,6 +78,11 @@ } else if (child.fragment) { AddChild(std::move(child.fragment), child.offset); DCHECK(!child.fragment); + } else if (child.out_of_flow_positioned_box) { + AddOutOfFlowChildCandidate( + NGBlockNode(ToLayoutBox(child.out_of_flow_positioned_box)), + child.offset, child.container_direction); + child.out_of_flow_positioned_box = nullptr; } } }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h index 4e2cd3e..e1e5e6f5 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h
@@ -70,7 +70,6 @@ scoped_refptr<NGLayoutResult> layout_result; scoped_refptr<const NGPhysicalFragment> fragment; LayoutObject* out_of_flow_positioned_box = nullptr; - LayoutObject* out_of_flow_containing_box = nullptr; // The offset of the border box, initially in this child coordinate system. // |ComputeInlinePositions()| converts it to the offset within the line box. NGLogicalOffset offset; @@ -81,6 +80,8 @@ // |UpdateAfterReorder()| to track children of boxes across BiDi reorder. unsigned box_data_index = 0; UBiDiLevel bidi_level = 0xff; + // The current text direction for OOF positioned items. + TextDirection container_direction = TextDirection::kLtr; // Empty constructor needed for |resize()|. Child() = default; @@ -118,11 +119,11 @@ bidi_level(bidi_level) {} // Create an out-of-flow positioned object. Child(LayoutObject* out_of_flow_positioned_box, - LayoutObject* out_of_flow_containing_box, - UBiDiLevel bidi_level) + UBiDiLevel bidi_level, + TextDirection container_direction) : out_of_flow_positioned_box(out_of_flow_positioned_box), - out_of_flow_containing_box(out_of_flow_containing_box), - bidi_level(bidi_level) {} + bidi_level(bidi_level), + container_direction(container_direction) {} bool HasInFlowFragment() const { return layout_result || fragment; } bool HasOutOfFlowFragment() const { return out_of_flow_positioned_box; }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc index fdf31c4d..319802a58 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
@@ -424,11 +424,22 @@ // expensive? DCHECK_EQ(item.TextShapeResult()->StartIndex(), item.StartOffset()); DCHECK_EQ(item.TextShapeResult()->EndIndex(), item.EndOffset()); - RunSegmenter::RunSegmenterRange segment_range = - item.CreateRunSegmenterRange(); - ShapingLineBreaker breaker(&shaper_, &item.Style()->GetFont(), - item.TextShapeResult(), &break_iterator_, - &segment_range, &spacing_, hyphenation_); + struct ShapeCallbackContext { + STACK_ALLOCATED(); + + public: + NGLineBreaker* line_breaker; + const NGInlineItem& item; + } shape_callback_context{this, item}; + const ShapingLineBreaker::ShapeCallback shape_callback = + [](void* untyped_context, unsigned start, unsigned end) { + ShapeCallbackContext* context = + static_cast<ShapeCallbackContext*>(untyped_context); + return context->line_breaker->ShapeText(context->item, start, end); + }; + ShapingLineBreaker breaker(item.TextShapeResult(), &break_iterator_, + hyphenation_, shape_callback, + &shape_callback_context); if (!enable_soft_hyphen_) breaker.DisableSoftHyphen(); available_width = std::max(LayoutUnit(0), available_width); @@ -492,14 +503,21 @@ scoped_refptr<ShapeResult> NGLineBreaker::ShapeText(const NGInlineItem& item, unsigned start, unsigned end) { - RunSegmenter::RunSegmenterRange segment_range = - item.CreateRunSegmenterRange(); - scoped_refptr<ShapeResult> result = shaper_.Shape( - &item.Style()->GetFont(), item.TextShapeResult()->Direction(), start, end, - &segment_range); + scoped_refptr<ShapeResult> shape_result; + if (!items_data_.segments) { + RunSegmenter::RunSegmenterRange segment_range = + item.CreateRunSegmenterRange(); + shape_result = shaper_.Shape(&item.Style()->GetFont(), + item.TextShapeResult()->Direction(), start, + end, &segment_range); + } else { + shape_result = items_data_.segments->ShapeText( + &shaper_, &item.Style()->GetFont(), item.TextShapeResult()->Direction(), + start, end, &item - items_data_.items.begin()); + } if (UNLIKELY(spacing_.HasSpacing())) - result->ApplySpacing(spacing_); - return result; + shape_result->ApplySpacing(spacing_); + return shape_result; } // Compute a new ShapeResult for the specified end offset.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc index 85cd2d0..e6ef30f 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
@@ -207,13 +207,11 @@ // inline containing blocks are required. // Not finding a required block is an unexpected behavior (DCHECK). void NGBoxFragmentBuilder::ComputeInlineContainerFragments( - HashMap<const LayoutObject*, FragmentPair>* inline_container_fragments, - NGLogicalSize* container_size) { + HashMap<const LayoutObject*, FragmentPair>* inline_container_fragments) { // This function has detailed knowledge of inline fragment tree structure, // and will break if this changes. DCHECK_GE(InlineSize(), LayoutUnit()); DCHECK_GE(BlockSize(), LayoutUnit()); - *container_size = Size(); for (wtf_size_t i = 0; i < children_.size(); i++) { if (children_[i]->IsLineBox()) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h index a506bffe..c4f55b3d 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h +++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
@@ -225,8 +225,7 @@ }; void ComputeInlineContainerFragments( - HashMap<const LayoutObject*, FragmentPair>* inline_container_fragments, - NGLogicalSize* container_size); + HashMap<const LayoutObject*, FragmentPair>* inline_container_fragments); private: scoped_refptr<NGLayoutResult> ToBoxFragment(WritingMode);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc index 5a75ed3..60fa9fbc 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
@@ -52,24 +52,8 @@ } for (const NGOutOfFlowPositionedDescendant& descendant : out_of_flow_descendants) { - // If we are inside the inline algorithm, (and creating a fragment for a - // <span> or similar), we may add a child (e.g. an atomic-inline) which - // has OOF descandants. - // - // This checks if the object creating this box will be the container for - // the given descendant. - if (layout_object_ && layout_object_->IsLayoutInline() && - layout_object_->CanContainOutOfFlowPositionedElement( - descendant.node.Style().GetPosition()) && - !descendant.inline_container) { - NGOutOfFlowPositionedDescendant descendant_copy(descendant); - descendant_copy.inline_container = layout_object_; - oof_positioned_candidates_.push_back( - NGOutOfFlowPositionedCandidate(descendant_copy, top_left_offset)); - } else { - oof_positioned_candidates_.push_back( - NGOutOfFlowPositionedCandidate{descendant, top_left_offset}); - } + oof_positioned_candidates_.push_back( + NGOutOfFlowPositionedCandidate(descendant, top_left_offset)); } } @@ -121,34 +105,23 @@ NGContainerFragmentBuilder& NGContainerFragmentBuilder::AddOutOfFlowChildCandidate( NGBlockNode child, - const NGLogicalOffset& child_offset) { - DCHECK(child); - oof_positioned_candidates_.push_back(NGOutOfFlowPositionedCandidate( - NGOutOfFlowPositionedDescendant{ - child, NGStaticPosition::Create(GetWritingMode(), Direction(), - NGPhysicalOffset())}, - child_offset)); - - return *this; -} - -NGContainerFragmentBuilder& -NGContainerFragmentBuilder::AddInlineOutOfFlowChildCandidate( - NGBlockNode child, const NGLogicalOffset& child_offset, - TextDirection line_direction, - LayoutObject* inline_container) { + base::Optional<TextDirection> container_direction) { DCHECK(child); - // Fixed positioned children are never placed inside inline container. - if (child.Style().GetPosition() == EPosition::kFixed) - inline_container = nullptr; + DCHECK(layout_object_ && !layout_object_->IsLayoutInline() || + container_direction) + << "container_direction must only be set for inline-level OOF children."; + + // As all inline-level fragments are built in the line-logical coordinate + // system (Direction() is kLtr), we need to know the direction of the + // parent element to correctly determine an OOF childs static position. + TextDirection direction = container_direction.value_or(Direction()); + oof_positioned_candidates_.push_back(NGOutOfFlowPositionedCandidate( NGOutOfFlowPositionedDescendant( - child, - NGStaticPosition::Create(GetWritingMode(), line_direction, - NGPhysicalOffset()), - inline_container), - child_offset, line_direction)); + child, NGStaticPosition::Create(GetWritingMode(), direction, + NGPhysicalOffset())), + child_offset)); return *this; } @@ -175,19 +148,31 @@ ToNGPhysicalSize(Size(), GetWritingMode()); for (NGOutOfFlowPositionedCandidate& candidate : oof_positioned_candidates_) { - TextDirection direction = - candidate.is_line_relative ? candidate.line_direction : Direction(); NGPhysicalOffset child_offset = candidate.child_offset.ConvertToPhysical( - GetWritingMode(), direction, builder_physical_size, NGPhysicalSize()); + GetWritingMode(), Direction(), builder_physical_size, NGPhysicalSize()); NGStaticPosition builder_relative_position; builder_relative_position.type = candidate.descendant.static_position.type; builder_relative_position.offset = child_offset + candidate.descendant.static_position.offset; + // If we are inside the inline algorithm, (and creating a fragment for a + // <span> or similar), we may add a child (e.g. an atomic-inline) which has + // OOF descandants. + // + // This checks if the object creating this box will be the container for + // the given descendant. + const LayoutObject* inline_container = + candidate.descendant.inline_container; + if (!inline_container && layout_object_ && + layout_object_->IsLayoutInline() && + layout_object_->CanContainOutOfFlowPositionedElement( + candidate.descendant.node.Style().GetPosition())) + inline_container = layout_object_; + descendant_candidates->push_back(NGOutOfFlowPositionedDescendant( candidate.descendant.node, builder_relative_position, - candidate.descendant.inline_container)); + inline_container)); NGLogicalOffset container_offset = builder_relative_position.offset.ConvertToLogical( GetWritingMode(), Direction(), builder_physical_size,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h index 2c2a2cc..31ab431 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h +++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
@@ -116,14 +116,8 @@ // Pass in direction if candidates direction does not match. NGContainerFragmentBuilder& AddOutOfFlowChildCandidate( NGBlockNode, - const NGLogicalOffset& child_offset); - - // Inline candidates are laid out line-relative, not fragment-relative. - NGContainerFragmentBuilder& AddInlineOutOfFlowChildCandidate( - NGBlockNode, - const NGLogicalOffset& child_line_offset, - TextDirection line_direction, - LayoutObject* inline_container); + const NGLogicalOffset& child_offset, + base::Optional<TextDirection> container_direction = base::nullopt); NGContainerFragmentBuilder& AddOutOfFlowDescendant( NGOutOfFlowPositionedDescendant descendant); @@ -184,24 +178,10 @@ struct NGOutOfFlowPositionedCandidate { NGOutOfFlowPositionedDescendant descendant; NGLogicalOffset child_offset; // Logical offset of child's top left vertex. - bool is_line_relative; // True if offset is relative to line, not fragment. - TextDirection line_direction; - NGOutOfFlowPositionedCandidate( - NGOutOfFlowPositionedDescendant descendant_arg, - NGLogicalOffset child_offset_arg) - : descendant(descendant_arg), - child_offset(child_offset_arg), - is_line_relative(false) {} - - NGOutOfFlowPositionedCandidate( - NGOutOfFlowPositionedDescendant descendant_arg, - NGLogicalOffset child_offset_arg, - TextDirection line_direction_arg) - : descendant(descendant_arg), - child_offset(child_offset_arg), - is_line_relative(true), - line_direction(line_direction_arg) {} + NGOutOfFlowPositionedCandidate(NGOutOfFlowPositionedDescendant descendant, + NGLogicalOffset child_offset) + : descendant(descendant), child_offset(child_offset) {} }; NGContainerFragmentBuilder(scoped_refptr<const ComputedStyle> style,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc index 6a777bb..3dfb6f81 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -25,7 +25,7 @@ NGBoxFragmentBuilder* container_builder, bool contains_absolute, bool contains_fixed, - const NGBoxStrut& borders_and_scrollers, + const NGBoxStrut& border_scrollbar, const NGConstraintSpace& container_space, const ComputedStyle& container_style, base::Optional<NGLogicalSize> initial_containing_block_fixed_size) @@ -34,28 +34,30 @@ contains_fixed_(contains_fixed) { if (!container_builder->HasOutOfFlowDescendantCandidates()) return; - NGPhysicalBoxStrut physical_borders = borders_and_scrollers.ConvertToPhysical( - container_style.GetWritingMode(), container_style.Direction()); + NGPhysicalBoxStrut physical_border_scrollbar = + border_scrollbar.ConvertToPhysical(container_style.GetWritingMode(), + container_style.Direction()); default_containing_block_.style = &container_style; default_containing_block_.content_size_for_absolute = container_builder_->Size(); default_containing_block_.content_size_for_absolute.inline_size = std::max(default_containing_block_.content_size_for_absolute.inline_size - - borders_and_scrollers.InlineSum(), + border_scrollbar.InlineSum(), LayoutUnit()); default_containing_block_.content_size_for_absolute.block_size = std::max(default_containing_block_.content_size_for_absolute.block_size - - borders_and_scrollers.BlockSum(), + border_scrollbar.BlockSum(), LayoutUnit()); default_containing_block_.content_size_for_fixed = initial_containing_block_fixed_size ? initial_containing_block_fixed_size.value() : default_containing_block_.content_size_for_absolute; - default_containing_block_.content_offset = NGLogicalOffset{ - borders_and_scrollers.inline_start, borders_and_scrollers.block_start}; - default_containing_block_.content_physical_offset = - NGPhysicalOffset(physical_borders.left, physical_borders.top); + + default_containing_block_.container_offset = NGLogicalOffset( + border_scrollbar.inline_start, border_scrollbar.block_start); + default_containing_block_.physical_container_offset = NGPhysicalOffset( + physical_border_scrollbar.left, physical_border_scrollbar.top); } void NGOutOfFlowLayoutPart::Run(LayoutBox* only_layout) { @@ -112,157 +114,153 @@ } } // Fetch start/end fragment info. - NGLogicalSize container_builder_size; container_builder_->ComputeInlineContainerFragments( - &inline_container_fragments, &container_builder_size); + &inline_container_fragments); + NGLogicalSize container_builder_size = container_builder_->Size(); NGPhysicalSize container_builder_physical_size = ToNGPhysicalSize(container_builder_size, default_containing_block_.style->GetWritingMode()); // Translate start/end fragments into ContainingBlockInfo. for (auto& block_info : inline_container_fragments) { // Variables needed to describe ContainingBlockInfo - const ComputedStyle* inline_cb_style; + const ComputedStyle* inline_cb_style = block_info.key->Style(); NGLogicalSize inline_cb_size; - NGLogicalOffset inline_content_offset; - NGPhysicalOffset inline_content_physical_offset; - NGLogicalOffset default_container_offset; + NGLogicalOffset container_offset; + NGPhysicalOffset physical_container_offset; + if (!block_info.value.start_fragment) { // This happens when Legacy block is the default container. // In this case, container builder does not have any fragments because // ng layout algorithm did not run. DCHECK(block_info.key->IsLayoutInline()); - inline_cb_style = block_info.key->Style(); NOTIMPLEMENTED() << "Inline containing block might need geometry information"; // TODO(atotic) ContainingBlockInfo geometry // must be computed from Legacy algorithm } else { - inline_cb_style = &block_info.value.start_fragment->Style(); + DCHECK(inline_cb_style); + + // TODO Creating dummy constraint space just to get borders feels wrong. NGConstraintSpace dummy_constraint_space = NGConstraintSpaceBuilder(inline_cb_style->GetWritingMode(), inline_cb_style->GetWritingMode(), /* is_new_fc */ false) .ToConstraintSpace(); - - // TODO Creating dummy constraint space just to get borders feels wrong. NGBoxStrut inline_cb_borders = ComputeBorders(dummy_constraint_space, *inline_cb_style); - NGPhysicalBoxStrut physical_borders = inline_cb_borders.ConvertToPhysical( - inline_cb_style->GetWritingMode(), inline_cb_style->Direction()); - // Warning: lots of non-obvious coordinate manipulation ahead. + // The calculation below determines the size of the inline containing + // block rect. // - // High level goal is: - // - Find logical topleft of start fragment, and logical bottomright - // of end fragment. - // - Use these to compute inline-cb geometry: - // - inline-cb size (content_size) - // - inline-cb offset from containing block (default_container_offset) + // To perform this calculation we: + // 1. Determine the start_offset "^", this is at the logical-start (wrt. + // default containing block), of the start fragment rect. + // 2. Determine the end_offset "$", this is at the logical-end (wrt. + // default containing block), of the end fragment rect. + // 3. Determine the logical rectangle defined by these two offsets. // - // We start with: - // start_fragment, which has physical offset from start_linebox_fragment, - // end_fragment, also with physical offset. - // start_linebox_fragment, which has logical offset from containing box. - // end_linebox_fragment, which also has logical offset from containing - // box. + // Case 1a: Same direction, overlapping fragments. + // +--------------- + // ---> |^*****--------> + // +*----*--------- + // * * + // ------*----*+ + // ----> *****$| ---> + // ------------+ // - // Then magic happens.^H^H^H^H^H^H^H + // Case 1b: Different direction, overlapping fragments. + // +--------------- + // ---> ^******* <-----| + // *------*-------- + // * * + // -----*------* + // |<-- *******$ ---> + // ------------+ // - // Then we do the following: - // 1. Find start fragment physical topleft wrt containing box. - // - convert start_fragment offset to logical. - // - convert start fragment inline/block start to physical. - // - convert linebox topleft to physical. - // - add start fragment to linebox topleft - // 2. Find end fragment bottom right wrt containing box - // - convert end fragment offset to logical. - // - convert end fragment inline/block end to physical - // - convert linebox topleft to physical - // - add end fragment bottomLeft to linebox topleft - // 3. Convert both topleft/bottomright to logical, so that we can - // 4. Enforce logical topLeft < bottomRight - // 5. Compute size, physical offset - const NGPhysicalLineBoxFragment* start_linebox_fragment = - block_info.value.start_linebox_fragment; + // Case 2a: Same direction, non-overlapping fragments. + // +-------- + // ---------> |^ -----> + // +*------- + // * + // --------+ * + // ------->| $ ---> + // --------+ + // + // Case 2b: Same direction, non-overlapping fragments. + // +-------- + // ---------> ^ <-----| + // *-------- + // * + // --------+ * + // | <------ $ ---> + // --------+ + // + // Note in cases [1a, 2a] we need to account for the inline borders of + // the rectangles, where-as in [1b, 2b] we do not. This is handled by the + // is_same_direction check(s). + // + // Note in cases [2a, 2b] we don't allow a "negative" containing block + // size, we clamp negative sizes to zero. WritingMode container_writing_mode = default_containing_block_.style->GetWritingMode(); TextDirection container_direction = default_containing_block_.style->Direction(); - // Step 1 - NGLogicalOffset start_fragment_logical_offset = - block_info.value.start_fragment_union_rect.offset.ConvertToLogical( - container_writing_mode, container_direction, - start_linebox_fragment->Size(), - block_info.value.start_fragment_union_rect.size); - NGPhysicalOffset start_fragment_physical_offset = - start_fragment_logical_offset.ConvertToPhysical( - container_writing_mode, container_direction, - start_linebox_fragment->Size(), NGPhysicalSize()); - // Step 2 - const NGPhysicalLineBoxFragment* end_linebox_fragment = - block_info.value.end_linebox_fragment; - NGLogicalOffset end_fragment_logical_offset = - block_info.value.end_fragment_union_rect.offset.ConvertToLogical( - container_writing_mode, container_direction, - end_linebox_fragment->Size(), - block_info.value.end_fragment_union_rect.size); - NGLogicalOffset end_fragment_bottom_right = - end_fragment_logical_offset + - block_info.value.end_fragment_union_rect.size.ConvertToLogical( - container_writing_mode); - NGPhysicalOffset end_fragment_physical_offset = - end_fragment_bottom_right.ConvertToPhysical( - container_writing_mode, container_direction, - end_linebox_fragment->Size(), NGPhysicalSize()); - // Step 3 - NGLogicalOffset start_fragment_logical_offset_wrt_box = - start_fragment_physical_offset.ConvertToLogical( - inline_cb_style->GetWritingMode(), inline_cb_style->Direction(), - container_builder_physical_size, NGPhysicalSize()); - NGLogicalOffset end_fragment_logical_offset_wrt_box = - end_fragment_physical_offset.ConvertToLogical( - inline_cb_style->GetWritingMode(), inline_cb_style->Direction(), - container_builder_physical_size, NGPhysicalSize()); - // Step 4 - end_fragment_logical_offset_wrt_box.inline_offset = - std::max(end_fragment_logical_offset_wrt_box.inline_offset, - start_fragment_logical_offset_wrt_box.inline_offset + - inline_cb_borders.InlineSum()); - end_fragment_logical_offset_wrt_box.block_offset = - std::max(end_fragment_logical_offset_wrt_box.block_offset, - start_fragment_logical_offset_wrt_box.block_offset + - inline_cb_borders.BlockSum()); + bool is_same_direction = + container_direction == inline_cb_style->Direction(); - // Step 5 - inline_cb_size.inline_size = - end_fragment_logical_offset_wrt_box.inline_offset - - start_fragment_logical_offset_wrt_box.inline_offset - - inline_cb_borders.InlineSum(); - inline_cb_size.block_size = - end_fragment_logical_offset_wrt_box.block_offset - - start_fragment_logical_offset_wrt_box.block_offset - - inline_cb_borders.BlockSum(); + // Step 1 - determine the start_offset. + const NGPhysicalOffsetRect& start_rect = + block_info.value.start_fragment_union_rect; + NGLogicalOffset start_offset = start_rect.offset.ConvertToLogical( + container_writing_mode, container_direction, + container_builder_physical_size, start_rect.size); + // Make sure we add the inline borders, we don't need to do this in the + // inline direction if the blocks are in opposite directions. + start_offset.block_offset += inline_cb_borders.block_start; + if (is_same_direction) + start_offset.inline_offset += inline_cb_borders.inline_start; + + // Step 2 - determine the end_offset. + const NGPhysicalOffsetRect& end_rect = + block_info.value.end_fragment_union_rect; + NGLogicalOffset end_offset = end_rect.offset.ConvertToLogical( + container_writing_mode, container_direction, + container_builder_physical_size, end_rect.size); + + // Add in the size of the fragment to get the logical end of the fragment. + end_offset += end_rect.size.ConvertToLogical(container_writing_mode); + + // Make sure we substract the inline borders, we don't need to do this in + // the inline direction if the blocks are in opposite directions. + end_offset.block_offset -= inline_cb_borders.block_end; + if (is_same_direction) + end_offset.inline_offset -= inline_cb_borders.inline_end; + + // Make sure we don't end up with a rectangle with "negative" size. + end_offset.inline_offset = + std::max(end_offset.inline_offset, start_offset.inline_offset); + + // Step 3 - determine the logical rectange. + + // Determine the logical size of the containing block. + inline_cb_size = {end_offset.inline_offset - start_offset.inline_offset, + end_offset.block_offset - start_offset.block_offset}; DCHECK_GE(inline_cb_size.inline_size, LayoutUnit()); DCHECK_GE(inline_cb_size.block_size, LayoutUnit()); - inline_content_offset = NGLogicalOffset{inline_cb_borders.inline_start, - inline_cb_borders.block_start}; - inline_content_physical_offset = - NGPhysicalOffset(physical_borders.left, physical_borders.top); - - // NGPaint offset is wrt parent fragment. - default_container_offset = start_fragment_logical_offset_wrt_box - - default_containing_block_.content_offset; - default_container_offset += inline_cb_borders.StartOffset(); + // Determine the container offsets. + container_offset = start_offset; + physical_container_offset = container_offset.ConvertToPhysical( + container_writing_mode, container_direction, + container_builder_physical_size, + ToNGPhysicalSize(inline_cb_size, container_writing_mode)); } containing_blocks_map_.insert( block_info.key, ContainingBlockInfo{inline_cb_style, inline_cb_size, inline_cb_size, - inline_content_offset, - inline_content_physical_offset, - default_container_offset}); + container_offset, physical_container_offset}); } } @@ -274,32 +272,15 @@ WritingMode container_writing_mode(container_info.style->GetWritingMode()); WritingMode descendant_writing_mode(descendant.node.Style().GetWritingMode()); - // Adjust the static_position origin. - // The static_position coordinate origin is relative to default_container's - // border box. - // ng_absolute_utils expects static position to be relative to - // the container's padding box. - // Adjust static position by offset of container from default container, - // and default_container border width. + // Adjust the static_position (which is currently relative to the default + // container's border-box). ng_absolute_utils expects the static position to + // be relative to the container's padding-box. NGStaticPosition static_position(descendant.static_position); - NGPhysicalSize default_containing_block_physical_size = - ToNGPhysicalSize(default_containing_block_.ContentSize( - descendant.node.Style().GetPosition()), - default_containing_block_.style->GetWritingMode()); - NGPhysicalOffset default_container_physical_offset = - container_info.default_container_offset.ConvertToPhysical( - default_containing_block_.style->GetWritingMode(), - default_containing_block_.style->Direction(), - default_containing_block_physical_size, - default_containing_block_physical_size); - - static_position.offset = static_position.offset - - default_containing_block_.content_physical_offset - - default_container_physical_offset; + static_position.offset -= container_info.physical_container_offset; NGLogicalSize container_content_size = container_info.ContentSize(descendant.node.Style().GetPosition()); - // The block estimate is in the descendant's writing mode. + NGConstraintSpace descendant_constraint_space = NGConstraintSpaceBuilder(container_writing_mode, descendant_writing_mode, /* is_new_fc */ true) @@ -307,8 +288,10 @@ .SetAvailableSize(container_content_size) .SetPercentageResolutionSize(container_content_size) .ToConstraintSpace(); - base::Optional<MinMaxSize> min_max_size; + + // The block_estimate is in the descendant's writing mode. base::Optional<LayoutUnit> block_estimate; + base::Optional<MinMaxSize> min_max_size; scoped_refptr<NGLayoutResult> layout_result = nullptr; @@ -372,19 +355,16 @@ ToLayoutBlock(node.GetLayoutBox()) ->SetIsLegacyInitiatedOutOfFlowLayout(false); } - // Compute logical offset, NGAbsolutePhysicalPosition is calculated relative - // to the padding box so add back the container's borders. - NGBoxStrut inset = node_position.inset.ConvertToLogical( - container_writing_mode, container_info.style->Direction()); - offset->inline_offset = - inset.inline_start + - default_containing_block_.content_offset.inline_offset; - offset->block_offset = - inset.block_start + default_containing_block_.content_offset.block_offset; - offset->inline_offset += - container_info.default_container_offset.inline_offset; - offset->block_offset += container_info.default_container_offset.block_offset; + NGBoxStrut inset = node_position.inset.ConvertToLogical( + container_writing_mode, default_containing_block_.style->Direction()); + + // inset is relative to the container's padding-box. Convert this to being + // relative to the default container's border-box. + offset->inline_offset = + inset.inline_start + container_info.container_offset.inline_offset; + offset->block_offset = + inset.block_start + container_info.container_offset.block_offset; base::Optional<LayoutUnit> y = ComputeAbsoluteDialogYPosition( *descendant.node.GetLayoutBox(), @@ -406,6 +386,11 @@ // Descendants whose containing block is inline are always positioned // inside closest parent block flow. if (descendant.inline_container) { + DCHECK( + descendant.node.Style().GetPosition() == EPosition::kAbsolute && + descendant.inline_container->CanContainAbsolutePositionObjects() || + (descendant.node.Style().GetPosition() == EPosition::kFixed && + descendant.inline_container->CanContainFixedPositionObjects())); return true; } return (contains_absolute_ && position == EPosition::kAbsolute) ||
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h index caa03905..78d1e9c 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h +++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h
@@ -75,15 +75,13 @@ const ComputedStyle* style; // Logical in containing block coordinates. NGLogicalSize content_size_for_absolute; - // Content size for fixed is different for icb + // Content size for fixed is different for the ICB. NGLogicalSize content_size_for_fixed; - // Content offset wrt border box. - NGLogicalOffset content_offset; - // Physical content offset wrt border box. - NGPhysicalOffset content_physical_offset; - // Logical offset of container padding box - // wrt default containing block padding box. - NGLogicalOffset default_container_offset; + + // Offsets (both logical and physical) of the container's padding-box, wrt. + // the default container's border-box. + NGLogicalOffset container_offset; + NGPhysicalOffset physical_container_offset; NGLogicalSize ContentSize(EPosition position) const { return position == EPosition::kAbsolute ? content_size_for_absolute
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_descendant.h b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_descendant.h index 2f38cb50..69b0ff6 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_descendant.h +++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_descendant.h
@@ -27,12 +27,12 @@ NGStaticPosition static_position; const LayoutObject* inline_container; NGOutOfFlowPositionedDescendant( - NGBlockNode node_param, - NGStaticPosition static_position_param, - const LayoutObject* inline_container_param = nullptr) - : node(node_param), - static_position(static_position_param), - inline_container(inline_container_param) {} + NGBlockNode node, + NGStaticPosition static_position, + const LayoutObject* inline_container = nullptr) + : node(node), + static_position(static_position), + inline_container(inline_container) {} }; } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/scrollbars_test.cc b/third_party/blink/renderer/core/layout/scrollbars_test.cc index e26fe4b..2d23ebb 100644 --- a/third_party/blink/renderer/core/layout/scrollbars_test.cc +++ b/third_party/blink/renderer/core/layout/scrollbars_test.cc
@@ -158,7 +158,7 @@ TEST_F(ScrollbarsTest, DocumentStyleRecalcPreservesScrollbars) { v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -206,7 +206,7 @@ // Needed so visual viewport supplies its own scrollbars. web_view_impl->GetSettings()->SetViewportEnabled(true); - web_view_impl->Resize(IntSize(800, 600)); + web_view_impl->MainFrameWidget()->Resize(IntSize(800, 600)); WebURL base_url = url_test_helpers::ToKURL("http://example.com/"); frame_test_helpers::LoadHTMLString(web_view_impl->MainFrameImpl(), @@ -234,7 +234,7 @@ const float device_scale = 3.5f; client.set_device_scale_factor(device_scale); - web_view_impl->Resize(IntSize(400, 300)); + web_view_impl->MainFrameWidget()->Resize(IntSize(400, 300)); EXPECT_EQ( clampTo<int>(std::floor(horizontal_scrollbar * device_scale)), @@ -245,7 +245,7 @@ visual_viewport.LayerForVerticalScrollbar()->Size().width()))); client.set_device_scale_factor(1.f); - web_view_impl->Resize(IntSize(800, 600)); + web_view_impl->MainFrameWidget()->Resize(IntSize(800, 600)); EXPECT_EQ( horizontal_scrollbar, @@ -262,7 +262,7 @@ // checking whether the scrollbars should be custom - which do take up layout // space. https://crbug.com/668387. TEST_F(ScrollbarsTest, CustomScrollbarsCauseLayoutOnExistenceChange) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -313,7 +313,7 @@ } TEST_F(ScrollbarsTest, TransparentBackgroundUsesDarkOverlayColorTheme) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); WebView().SetBaseBackgroundColorOverride(SK_ColorTRANSPARENT); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -339,7 +339,7 @@ TEST_F(ScrollbarsTest, BodyBackgroundChangesOverlayColorTheme) { v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -367,7 +367,7 @@ // Ensure overlay scrollbar change to display:none correctly. TEST_F(ScrollbarsTest, OverlayScrollbarChangeToDisplayNoneDynamically) { - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -435,7 +435,7 @@ } TEST_F(ScrollbarsTest, scrollbarIsNotHandlingTouchpadScroll) { - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -476,7 +476,7 @@ } TEST_F(ScrollbarsTest, HidingScrollbarsOnScrollableAreaDisablesScrollbars) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -544,7 +544,7 @@ // Ensure mouse cursor should be pointer when hovering over the scrollbar. TEST_F(ScrollbarsTest, MouseOverScrollbarInCustomCursorElement) { - WebView().Resize(WebSize(250, 250)); + WebView().MainFrameWidget()->Resize(WebSize(250, 250)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -588,7 +588,7 @@ // Ensure mouse cursor should be override when hovering over the custom // scrollbar. TEST_F(ScrollbarsTest, MouseOverCustomScrollbarInCustomCursorElement) { - WebView().Resize(WebSize(250, 250)); + WebView().MainFrameWidget()->Resize(WebSize(250, 250)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -641,7 +641,7 @@ // elements below(except the Element that owns the scrollbar) unless the // scrollbar is faded out. TEST_F(ScrollbarsTest, MouseOverLinkAndOverlayScrollbar) { - WebView().Resize(WebSize(20, 20)); + WebView().MainFrameWidget()->Resize(WebSize(20, 20)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -723,7 +723,7 @@ // Makes sure that mouse hover over an custom scrollbar doesn't change the // activate elements. TEST_F(ScrollbarsTest, MouseOverCustomScrollbar) { - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -790,7 +790,7 @@ // Makes sure that mouse hover over an overlay scrollbar doesn't hover iframe // below. TEST_F(ScrollbarsTest, MouseOverScrollbarAndIFrame) { - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest main_resource("https://example.com/", "text/html"); SimRequest frame_resource("https://example.com/iframe.html", "text/html"); @@ -874,7 +874,7 @@ // scrollbar. TEST_F(ScrollbarsTest, MouseOverScrollbarAndParentElement) { ScopedOverlayScrollbarsForTest overlay_scrollbars(false); - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -962,7 +962,7 @@ TEST_F(ScrollbarsTest, MouseOverRootScrollbar) { ScopedOverlayScrollbarsForTest overlay_scrollbars(false); - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -994,7 +994,7 @@ } TEST_F(ScrollbarsTest, MouseReleaseUpdatesScrollbarHoveredPart) { - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -1059,7 +1059,7 @@ } TEST_F(ScrollbarsTest, ContextMenuUpdatesScrollbarPressedPart) { - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -1112,7 +1112,7 @@ TEST_F(ScrollbarsTest, CustomScrollbarInOverlayScrollbarThemeWillNotCauseDCHECKFails) { - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -1140,7 +1140,7 @@ // Make sure root custom scrollbar can change by Emulator but div custom // scrollbar not. TEST_F(ScrollbarsTest, CustomScrollbarChangeToMobileByEmulator) { - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -1223,7 +1223,7 @@ // Ensure custom scrollbar recreate when style owner change, TEST_F(ScrollbarsTest, CustomScrollbarWhenStyleOwnerChange) { - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -1295,7 +1295,7 @@ (ScrollbarThemeOverlayMock&)theme; mock_overlay_theme.SetOverlayScrollbarFadeOutDelay(kMockOverlayFadeOutDelay); - WebView().Resize(WebSize(640, 480)); + WebView().MainFrameWidget()->Resize(WebSize(640, 480)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); RunTasksForPeriod(kMockOverlayFadeOutDelay); @@ -1432,7 +1432,7 @@ ScopedTestingPlatformSupport<ScrollbarTestingPlatformSupport> platform; bool use_overlay_scrollbar = GetParam(); - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -1526,7 +1526,7 @@ ScopedTestingPlatformSupport<ScrollbarTestingPlatformSupport> platform; v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1551,7 +1551,7 @@ ScopedTestingPlatformSupport<ScrollbarTestingPlatformSupport> platform; v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(1000, 1000)); + WebView().MainFrameWidget()->Resize(WebSize(1000, 1000)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1572,8 +1572,8 @@ Scrollbar* scrollbar = scrollable_area->VerticalScrollbar(); ASSERT_TRUE(scrollbar); - int maximumThumbPosition = - WebView().Size().height - StubWebThemeEngine::kMinimumVerticalLength; + int maximumThumbPosition = WebView().MainFrameWidget()->Size().height - + StubWebThemeEngine::kMinimumVerticalLength; // TODO(bokan): it seems that the scrollbar margin is cached in the static // ScrollbarTheme, so if another test runs first without our mocked @@ -1592,7 +1592,7 @@ // This test requires that scrollbars take up space. ScopedOverlayScrollbarsForTest overlay_scrollbars(false); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1616,7 +1616,7 @@ // This test requires that scrollbars take up space. ScopedOverlayScrollbarsForTest overlay_scrollbars(false); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1641,7 +1641,7 @@ // This test requires that scrollbars take up space. ScopedOverlayScrollbarsForTest overlay_scrollbars(false); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1666,7 +1666,7 @@ // This test requires that scrollbars take up space. ScopedOverlayScrollbarsForTest overlay_scrollbars(false); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1691,7 +1691,7 @@ // This test requires that scrollbars take up space. ScopedOverlayScrollbarsForTest overlay_scrollbars(false); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1717,7 +1717,7 @@ // This test requires that scrollbars take up space. ScopedOverlayScrollbarsForTest overlay_scrollbars(false); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1743,7 +1743,7 @@ // This test requires that scrollbars take up space. ScopedOverlayScrollbarsForTest overlay_scrollbars(false); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1769,7 +1769,7 @@ // This test requires that scrollbars take up space. ScopedOverlayScrollbarsForTest overlay_scrollbars(false); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1795,7 +1795,7 @@ // This test requires that scrollbars take up space. ScopedOverlayScrollbarsForTest overlay_scrollbars(false); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1817,7 +1817,7 @@ TEST_F(ScrollbarsTest, MouseOverIFrameScrollbar) { ScopedOverlayScrollbarsForTest overlay_scrollbars(false); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest main_resource("https://example.com/test.html", "text/html"); SimRequest frame_resource("https://example.com/iframe.html", "text/html"); @@ -1869,7 +1869,7 @@ // This test requires that scrollbars take up space. ScopedOverlayScrollbarsForTest overlay_scrollbars(false); - WebView().Resize(WebSize(0, 0)); + WebView().MainFrameWidget()->Resize(WebSize(0, 0)); SimRequest resource("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); resource.Complete(R"HTML( @@ -1970,7 +1970,7 @@ TEST_F(ScrollbarsTest, HideTheOverlayScrollbarNotCrashAfterPLSADisposedPaintLayer) { - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -2013,7 +2013,7 @@ TEST_F(ScrollbarsTest, PLSADisposeShouldClearPointerInLayers) { GetDocument().GetFrame()->GetSettings()->SetPreferCompositingToLCDTextEnabled( true); - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -2053,7 +2053,7 @@ } TEST_F(ScrollbarsTest, OverlayScrollbarHitTest) { - WebView().Resize(WebSize(300, 300)); + WebView().MainFrameWidget()->Resize(WebSize(300, 300)); SimRequest main_resource("https://example.com/", "text/html"); SimRequest frame_resource("https://example.com/iframe.html", "text/html"); @@ -2108,7 +2108,7 @@ TEST_F(ScrollbarsTest, AllowMiddleButtonPressOnScrollbar) { ScopedOverlayScrollbarsForTest overlay_scrollbars(false); - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -2140,7 +2140,7 @@ // Ensure Scrollbar not release press by middle button down. TEST_F(ScrollbarsTest, MiddleDownShouldNotAffectScrollbarPress) { ScopedOverlayScrollbarsForTest overlay_scrollbars(false); - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -2202,7 +2202,7 @@ #endif TimeAdvance(); GetDocument().GetFrame()->GetSettings()->SetScrollAnimatorEnabled(false); - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -2269,7 +2269,7 @@ class ScrollbarTrackMarginsTest : public ScrollbarsTest { public: void PrepareTest(const String& track_style) { - WebView().Resize(WebSize(200, 200)); + WebView().MainFrameWidget()->Resize(WebSize(200, 200)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html");
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.cc b/third_party/blink/renderer/core/loader/base_fetch_context.cc index ceac85e..86c5eb0 100644 --- a/third_party/blink/renderer/core/loader/base_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -135,11 +135,11 @@ referrer_policy_to_use, request.Url(), referrer_to_use)); request.SetHTTPOriginIfNeeded(GetSecurityOrigin()); } else { - DCHECK_EQ(SecurityPolicy::GenerateReferrer(request.GetReferrerPolicy(), - request.Url(), - request.HttpReferrer()) - .referrer, - request.HttpReferrer()); + CHECK_EQ(SecurityPolicy::GenerateReferrer(request.GetReferrerPolicy(), + request.Url(), + request.HttpReferrer()) + .referrer, + request.HttpReferrer()); request.SetHTTPOriginToMatchReferrerIfNeeded(); } }
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index 88578af..ba85f5e 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -31,6 +31,8 @@ #include <memory> #include "base/auto_reset.h" +#include "services/metrics/public/cpp/ukm_builders.h" +#include "services/metrics/public/cpp/ukm_recorder.h" #include "third_party/blink/public/common/origin_policy/origin_policy.h" #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h" #include "third_party/blink/public/platform/platform.h" @@ -87,6 +89,7 @@ #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h" +#include "third_party/blink/renderer/platform/loader/ftp_directory_listing.h" #include "third_party/blink/renderer/platform/mhtml/archive_resource.h" #include "third_party/blink/renderer/platform/mhtml/mhtml_archive.h" #include "third_party/blink/renderer/platform/network/content_security_policy_response_headers.h" @@ -510,6 +513,13 @@ !frame_->GetPage()->Paused() || MainThreadDebugger::Instance()->IsPaused()); + if (listing_ftp_directory_) { + scoped_refptr<SharedBuffer> buffer = GenerateFtpDirectoryListingHtml( + response_.CurrentRequestUrl(), data_buffer_.get()); + for (const auto& span : *buffer) + ProcessData(span.data(), span.size()); + } + TimeTicks response_end_time = finish_time; if (response_end_time.is_null()) response_end_time = time_of_last_data_received_; @@ -725,6 +735,18 @@ response_ = response; + if (response.CurrentRequestUrl().ProtocolIs("ftp") && + response.MimeType() == "text/vnd.chromium.ftp-dir") { + if (response.CurrentRequestUrl().Query() == "raw") { + // Interpret the FTP LIST command result as text. + response_.SetMimeType("text/plain"); + } else { + // FTP directory listing: Make up an HTML for the entries. + listing_ftp_directory_ = true; + response_.SetMimeType("text/html"); + } + } + if (IsArchiveMIMEType(response_.MimeType()) && resource->GetDataBufferingPolicy() != kBufferData) resource->SetDataBufferingPolicy(kBufferData); @@ -827,6 +849,11 @@ DCHECK(!response_.IsNull()); DCHECK(!frame_->GetPage()->Paused()); + if (listing_ftp_directory_) { + data_buffer_->Append(data, length); + return; + } + if (in_data_received_) { // If this function is reentered, defer processing of the additional data to // the top-level invocation. Reentrant calls can occur because of web @@ -1123,6 +1150,10 @@ ? WebFeature::kLegacyTLSVersionInSubframeMainResource : WebFeature::kLegacyTLSVersionInMainFrameResource); GetLocalFrameClient().ReportLegacyTLSVersion(response_.CurrentRequestUrl()); + if (!frame_->Tree().Parent()) { + ukm::builders::Net_LegacyTLSVersion(document->UkmSourceID()) + .Record(document->UkmRecorder()); + } } }
diff --git a/third_party/blink/renderer/core/loader/document_loader.h b/third_party/blink/renderer/core/loader/document_loader.h index 501d94a..cb776590 100644 --- a/third_party/blink/renderer/core/loader/document_loader.h +++ b/third_party/blink/renderer/core/loader/document_loader.h
@@ -262,6 +262,8 @@ return content_security_policy_.Get(); } + bool IsListingFtpDirectory() const { return listing_ftp_directory_; } + UseCounter& GetUseCounter() { return use_counter_; } protected: @@ -419,6 +421,8 @@ // Whether this load request had a user activation when created. bool had_transient_activation_; + bool listing_ftp_directory_ = false; + // This UseCounter tracks feature usage associated with the lifetime of the // document load. Features recorded prior to commit will be recorded locally. // Once commited, feature usage will be piped to the browser side page load
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc index 2e6381b..ca3287c 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -232,6 +232,7 @@ const base::Optional<mojom::IPAddressSpace>& address_space, const ContentSecurityPolicy* content_security_policy, KURL site_for_cookies, + scoped_refptr<const SecurityOrigin> top_frame_origin, const ClientHintsPreferences& client_hints_preferences, float device_pixel_ratio, const String& user_agent, @@ -242,6 +243,7 @@ address_space(address_space), content_security_policy(content_security_policy), site_for_cookies(site_for_cookies), + top_frame_origin(std::move(top_frame_origin)), client_hints_preferences(client_hints_preferences), device_pixel_ratio(device_pixel_ratio), user_agent(user_agent), @@ -253,6 +255,7 @@ const base::Optional<mojom::IPAddressSpace> address_space; const Member<const ContentSecurityPolicy> content_security_policy; const KURL site_for_cookies; + const scoped_refptr<const SecurityOrigin> top_frame_origin; const ClientHintsPreferences client_hints_preferences; const float device_pixel_ratio; const String user_agent; @@ -520,6 +523,7 @@ void FrameFetchContext::PrepareRequest(ResourceRequest& request, RedirectType redirect_type) { SetFirstPartyCookie(request); + request.SetTopFrameOrigin(GetTopFrameOrigin()); String user_agent = GetUserAgent(); request.SetHTTPUserAgent(AtomicString(user_agent)); @@ -1123,6 +1127,15 @@ ->IsSameSchemeHostPort(SecurityOrigin::Create(url).get()); } +scoped_refptr<const SecurityOrigin> FrameFetchContext::GetTopFrameOrigin() + const { + if (IsDetached()) + return frozen_state_->top_frame_origin; + + Document* document = document_ ? document_.Get() : GetFrame()->GetDocument(); + return document->TopFrameOrigin(); +} + bool FrameFetchContext::ShouldBlockRequestByInspector(const KURL& url) const { if (IsDetached()) return false; @@ -1434,7 +1447,7 @@ if (document_) { frozen_state_ = MakeGarbageCollected<FrozenState>( Url(), GetParentSecurityOrigin(), GetAddressSpace(), - GetContentSecurityPolicy(), GetSiteForCookies(), + GetContentSecurityPolicy(), GetSiteForCookies(), GetTopFrameOrigin(), GetClientHintsPreferences(), GetDevicePixelRatio(), GetUserAgent(), IsMainFrame(), IsSVGImageChromeClient()); SetFetchClientSettingsObject( @@ -1444,13 +1457,14 @@ // Some getters are unavailable in this case. frozen_state_ = MakeGarbageCollected<FrozenState>( NullURL(), GetParentSecurityOrigin(), GetAddressSpace(), - GetContentSecurityPolicy(), GetSiteForCookies(), + GetContentSecurityPolicy(), GetSiteForCookies(), GetTopFrameOrigin(), GetClientHintsPreferences(), GetDevicePixelRatio(), GetUserAgent(), IsMainFrame(), IsSVGImageChromeClient()); SetFetchClientSettingsObject( MakeGarbageCollected<FetchClientSettingsObjectSnapshot>( NullURL(), nullptr, network::mojom::ReferrerPolicy::kDefault, - String(), HttpsState::kNone)); + String(), HttpsState::kNone, + AllowedByNosniff::MimeTypeCheck::kStrict)); } // This is needed to break a reference cycle in which off-heap @@ -1467,10 +1481,6 @@ BaseFetchContext::Trace(visitor); } -void FrameFetchContext::RecordDataUriWithOctothorpe() { - UseCounter::Count(GetFrame(), WebFeature::kDataUriHasOctothorpe); -} - ResourceLoadPriority FrameFetchContext::ModifyPriorityForExperiments( ResourceLoadPriority priority) const { if (!GetSettings())
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.h b/third_party/blink/renderer/core/loader/frame_fetch_context.h index 156a2c6..973b4a0d 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context.h +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.h
@@ -79,8 +79,6 @@ bool IsFrameFetchContext() override { return true; } - void RecordDataUriWithOctothorpe() override; - void AddAdditionalRequestHeaders(ResourceRequest&, FetchResourceType) override; base::Optional<ResourceRequestBlockedReason> CanRequest( @@ -265,6 +263,9 @@ // frame's main resource. bool IsFirstPartyOrigin(const KURL& url) const; + // Returns the origin of the top frame in the document. + scoped_refptr<const SecurityOrigin> GetTopFrameOrigin() const; + Member<DocumentLoader> document_loader_; Member<Document> document_;
diff --git a/third_party/blink/renderer/core/loader/link_loader.cc b/third_party/blink/renderer/core/loader/link_loader.cc index 3894ca37..89e90d4 100644 --- a/third_party/blink/renderer/core/loader/link_loader.cc +++ b/third_party/blink/renderer/core/loader/link_loader.cc
@@ -41,6 +41,7 @@ #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/frame/use_counter.h" +#include "third_party/blink/renderer/core/frame/viewport_data.h" #include "third_party/blink/renderer/core/html/cross_origin_attribute.h" #include "third_party/blink/renderer/core/html/link_rel_attribute.h" #include "third_party/blink/renderer/core/html/parser/html_preload_scanner.h" @@ -331,9 +332,12 @@ MediaValues* media_values = MediaValues::CreateDynamicIfFrameExists(document.GetFrame()); if (viewport_description) { - media_values->OverrideViewportDimensions( - viewport_description->max_width.GetFloatValue(), - viewport_description->max_height.GetFloatValue()); + FloatSize initial_viewport(media_values->DeviceWidth(), + media_values->DeviceHeight()); + PageScaleConstraints constraints = viewport_description->Resolve( + initial_viewport, document.GetViewportData().ViewportDefaultMinWidth()); + media_values->OverrideViewportDimensions(constraints.layout_size.Width(), + constraints.layout_size.Height()); } return media_values; }
diff --git a/third_party/blink/renderer/core/loader/mixed_content_checker.cc b/third_party/blink/renderer/core/loader/mixed_content_checker.cc index 43a77bb..1c148e0d 100644 --- a/third_party/blink/renderer/core/loader/mixed_content_checker.cc +++ b/third_party/blink/renderer/core/loader/mixed_content_checker.cc
@@ -725,21 +725,6 @@ !effective_frame) return; - // There should not be certificate errors for non-HTTPS responses. - DCHECK(response.CurrentRequestUrl().ProtocolIs("https")); - - // Avoid logging in cases where the page URL is HTTP and the response - // URL is HTTPS. - if (MainResourceUrlForFrame(effective_frame).ProtocolIs("https")) { - String message = String::Format( - "Mixed Content: The page at '%s' attempted to load subresource " - "at '%s' over broken HTTPS.", - MainResourceUrlForFrame(effective_frame).ElidedString().Utf8().data(), - response.CurrentRequestUrl().ElidedString().Utf8().data()); - frame->GetDocument()->AddConsoleMessage(ConsoleMessage::Create( - kSecurityMessageSource, kErrorMessageLevel, message)); - } - // Use the current local frame's client; the embedder doesn't distinguish // mixed content signals from different frames on the same page. LocalFrameClient* client = frame->Client();
diff --git a/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc b/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc index be0ecb6b..229a829 100644 --- a/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc +++ b/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc
@@ -52,7 +52,7 @@ frame_test_helpers::WebViewHelper web_view_helper; WebViewImpl* web_view = web_view_helper.InitializeAndLoad(base_url_ + "long_scroll.html"); - web_view->Resize(WebSize(1000, 1000)); + web_view->MainFrameWidget()->Resize(WebSize(1000, 1000)); web_view->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); @@ -85,7 +85,7 @@ frame_test_helpers::WebViewHelper web_view_helper; WebViewImpl* web_view = web_view_helper.InitializeAndLoad(base_url_ + "long_scroll.html"); - web_view->Resize(WebSize(1000, 1000)); + web_view->MainFrameWidget()->Resize(WebSize(1000, 1000)); web_view->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); @@ -115,7 +115,7 @@ frame_test_helpers::WebViewHelper web_view_helper; WebViewImpl* web_view = web_view_helper.InitializeAndLoad(base_url_ + "long_scroll.html"); - web_view->Resize(WebSize(1000, 1000)); + web_view->MainFrameWidget()->Resize(WebSize(1000, 1000)); web_view->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); @@ -141,7 +141,7 @@ class ProgrammaticScrollSimTest : public SimTest {}; TEST_F(ProgrammaticScrollSimTest, NavigateToHash) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest main_resource("https://example.com/test.html#target", "text/html"); SimRequest css_resource("https://example.com/test.css", "text/css");
diff --git a/third_party/blink/renderer/core/messaging/message_port.cc b/third_party/blink/renderer/core/messaging/message_port.cc index a296a04f..196ab5f 100644 --- a/third_party/blink/renderer/core/messaging/message_port.cc +++ b/third_party/blink/renderer/core/messaging/message_port.cc
@@ -313,7 +313,7 @@ evt = MessageEvent::CreateError(); } - v8::Isolate* isolate = GetExecutionContext()->GetIsolate(); + v8::Isolate* isolate = ToIsolate(GetExecutionContext()); ThreadDebugger* debugger = ThreadDebugger::From(isolate); if (debugger) debugger->ExternalAsyncTaskStarted(message.sender_stack_trace_id);
diff --git a/third_party/blink/renderer/core/page/autoscroll_controller_test.cc b/third_party/blink/renderer/core/page/autoscroll_controller_test.cc index e3ef9b4..cc8cea6 100644 --- a/third_party/blink/renderer/core/page/autoscroll_controller_test.cc +++ b/third_party/blink/renderer/core/page/autoscroll_controller_test.cc
@@ -22,7 +22,7 @@ // Ensure Autoscroll not crash by layout called in UpdateSelectionForMouseDrag. TEST_F(AutoscrollControllerTest, CrashWhenLayoutStopAnimationBeforeScheduleAnimation) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); WebView().SetBaseBackgroundColorOverride(SK_ColorTRANSPARENT); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html");
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc index dca59fc..322f977 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl.cc +++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -188,8 +188,8 @@ // These numbers will be fairly wrong. The window's x/y coordinates will // be the top left corner of the screen and the size will be the content // size instead of the window size. - rect.width = web_view_->Size().width; - rect.height = web_view_->Size().height; + rect.width = web_view_->MainFrameWidget()->Size().width; + rect.height = web_view_->MainFrameWidget()->Size().height; } return IntRect(rect); } @@ -823,7 +823,7 @@ void ChromeClientImpl::SetBrowserControlsState(float top_height, float bottom_height, bool shrinks_layout) { - WebSize size = web_view_->Size(); + WebSize size = web_view_->MainFrameWidget()->Size(); if (shrinks_layout) size.height -= top_height + bottom_height;
diff --git a/third_party/blink/renderer/core/page/drag_controller_test.cc b/third_party/blink/renderer/core/page/drag_controller_test.cc index 0d717e2..111b2481 100644 --- a/third_party/blink/renderer/core/page/drag_controller_test.cc +++ b/third_party/blink/renderer/core/page/drag_controller_test.cc
@@ -84,7 +84,7 @@ // https://crbug.com/733996. TEST_F(DragControllerSimTest, DropURLOnNonNavigatingClearsState) { WebView().GetPage()->GetSettings().SetNavigateOnDragDrop(false); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest main_resource("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -124,7 +124,7 @@ // Regression test for https://crbug.com/685030 TEST_F(DragControllerSimTest, ThrottledDocumentHandled) { WebView().GetPage()->GetSettings().SetNavigateOnDragDrop(false); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest main_resource("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html");
diff --git a/third_party/blink/renderer/core/page/focus_controller.cc b/third_party/blink/renderer/core/page/focus_controller.cc index d325516b..3125d9c0 100644 --- a/third_party/blink/renderer/core/page/focus_controller.cc +++ b/third_party/blink/renderer/core/page/focus_controller.cc
@@ -1461,20 +1461,34 @@ Document* focused_document = current_frame->GetDocument(); if (!focused_document) return false; + focused_document->UpdateStyleAndLayoutIgnorePendingStylesheets(); - Element* focused_element = focused_document->FocusedElement(); + Node* focused_element = focused_document->FocusedElement(); + if (!focused_element) // An iframe's document is focused. + focused_element = focused_document; + Node* container = focused_document; - if (auto* document = DynamicTo<Document>(container)) - document->UpdateStyleAndLayoutIgnorePendingStylesheets(); if (focused_element) container = ScrollableAreaOrDocumentOf(focused_element); const LayoutRect visible_rect = RootViewport(current_frame); const LayoutRect start_box = SearchOrigin(visible_rect, focused_element, direction); - bool consumed = false; Node* pruned_sub_tree_root = nullptr; + + if (IsScrollableAreaOrDocument(focused_element) && + !IsOffscreen(focused_element)) { + // A visible scroller is focused. Search inside of it from one of its edges. + LayoutRect edge = OppositeEdge(direction, start_box); + consumed = AdvanceFocusDirectionallyInContainer(focused_element, edge, + direction, nullptr); + if (consumed) + return true; + // The scroller had nothing. Let's search outside of it. + pruned_sub_tree_root = focused_element; + } + while (container) { consumed = AdvanceFocusDirectionallyInContainer( container, start_box, direction, pruned_sub_tree_root);
diff --git a/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.cc b/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.cc index 20099b81..b7704eb 100644 --- a/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.cc +++ b/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.cc
@@ -310,10 +310,8 @@ PaintLayerScrollableArea* area = ancestor->GetScrollableArea(); DCHECK(area); - if ((style->ScrollsOverflowX() && area->HasHorizontalOverflow()) || - (style->ScrollsOverflowY() && area->HasVerticalOverflow())) { + if (style->ScrollsOverflowY() && area->HasVerticalOverflow()) return false; - } } else { if (ancestor->ShouldClipOverflow() || ancestor->HasMask() || ancestor->HasClip() || ancestor->HasClipPath()) {
diff --git a/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc b/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc index 8585499..8a36b16e 100644 --- a/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc +++ b/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
@@ -260,14 +260,14 @@ // makes it 400x450 so max scroll is 550px. double maximum_scroll = 550; - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateTouchGestureEvent(WebInputEvent::kGestureScrollBegin)); { // Scrolling over the #container DIV should cause the browser controls to // hide. EXPECT_FLOAT_EQ(1, GetBrowserControls().ShownRatio()); - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateTouchGestureEvent(WebInputEvent::kGestureScrollUpdate, 0, -GetBrowserControls().TopHeight())); EXPECT_FLOAT_EQ(0, GetBrowserControls().ShownRatio()); @@ -275,7 +275,7 @@ { // Make sure we're actually scrolling the DIV and not the LocalFrameView. - GetWebView()->HandleInputEvent(GenerateTouchGestureEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent( WebInputEvent::kGestureScrollUpdate, 0, -100)); EXPECT_FLOAT_EQ(100, container->scrollTop()); EXPECT_FLOAT_EQ( @@ -288,7 +288,7 @@ EXPECT_CALL(client, DidOverscroll(WebFloatSize(0, 50), WebFloatSize(0, 50), WebFloatPoint(100, 100), WebFloatSize(), cc::OverscrollBehavior())); - GetWebView()->HandleInputEvent(GenerateTouchGestureEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent( WebInputEvent::kGestureScrollUpdate, 0, -500)); EXPECT_FLOAT_EQ(maximum_scroll, container->scrollTop()); EXPECT_FLOAT_EQ( @@ -301,7 +301,7 @@ EXPECT_CALL(client, DidOverscroll(WebFloatSize(0, 20), WebFloatSize(0, 70), WebFloatPoint(100, 100), WebFloatSize(), cc::OverscrollBehavior())); - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateTouchGestureEvent(WebInputEvent::kGestureScrollUpdate, 0, -20)); EXPECT_FLOAT_EQ(maximum_scroll, container->scrollTop()); EXPECT_FLOAT_EQ( @@ -309,40 +309,40 @@ Mock::VerifyAndClearExpectations(&client); } - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateTouchGestureEvent(WebInputEvent::kGestureScrollEnd)); { // Make sure a new gesture scroll still won't scroll the frameview and // overscrolls. - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateTouchGestureEvent(WebInputEvent::kGestureScrollBegin)); EXPECT_CALL(client, DidOverscroll(WebFloatSize(0, 30), WebFloatSize(0, 30), WebFloatPoint(100, 100), WebFloatSize(), cc::OverscrollBehavior())); - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateTouchGestureEvent(WebInputEvent::kGestureScrollUpdate, 0, -30)); EXPECT_FLOAT_EQ(maximum_scroll, container->scrollTop()); EXPECT_FLOAT_EQ( 0, MainFrameView()->LayoutViewport()->GetScrollOffset().Height()); Mock::VerifyAndClearExpectations(&client); - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateTouchGestureEvent(WebInputEvent::kGestureScrollEnd)); } { // Scrolling up should show the browser controls. - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateTouchGestureEvent(WebInputEvent::kGestureScrollBegin)); EXPECT_FLOAT_EQ(0, GetBrowserControls().ShownRatio()); - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateTouchGestureEvent(WebInputEvent::kGestureScrollUpdate, 0, 30)); EXPECT_FLOAT_EQ(0.6, GetBrowserControls().ShownRatio()); - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateTouchGestureEvent(WebInputEvent::kGestureScrollEnd)); } @@ -1033,20 +1033,20 @@ // scroll offset should shrink. ASSERT_EQ(1000 - 400, container_scroller->MaximumScrollOffset().Height()); - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateTouchGestureEvent(WebInputEvent::kGestureScrollBegin)); ASSERT_EQ(1, GetBrowserControls().ShownRatio()); - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateTouchGestureEvent(WebInputEvent::kGestureScrollUpdate, 0, -GetBrowserControls().TopHeight())); ASSERT_EQ(0, GetBrowserControls().ShownRatio()); EXPECT_EQ(1000 - 450, container_scroller->MaximumScrollOffset().Height()); - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateTouchGestureEvent(WebInputEvent::kGestureScrollUpdate, 0, -3000)); EXPECT_EQ(1000 - 450, container_scroller->GetScrollOffset().Height()); - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateTouchGestureEvent(WebInputEvent::kGestureScrollEnd)); GetWebView()->ResizeWithBrowserControls(IntSize(400, 450), 50, 0, false); EXPECT_EQ(1000 - 450, container_scroller->MaximumScrollOffset().Height()); @@ -1079,11 +1079,11 @@ int scroll_y = 1000 * 4; GetWebView()->SetPageScaleFactor(2); - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateTouchGestureEvent(WebInputEvent::kGestureScrollBegin)); - GetWebView()->HandleInputEvent(GenerateTouchGestureEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent(GenerateTouchGestureEvent( WebInputEvent::kGestureScrollUpdate, -scroll_x, -scroll_y)); - GetWebView()->HandleInputEvent( + GetWebView()->MainFrameWidget()->HandleInputEvent( GenerateTouchGestureEvent(WebInputEvent::kGestureScrollEnd)); // The visual viewport should be 1.5 screens scrolled so that the target @@ -1240,7 +1240,7 @@ // However, until a frame is produced, the effective root scroller should // not change. TEST_F(RootScrollerSimTest, SetCausesNeedsBeginFrame) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1281,7 +1281,7 @@ // correctly when the Document is the effective root scroller. It becomes the // root scroller before Document has a LayoutView. TEST_F(RootScrollerSimTest, DocumentEffectiveSetsCachedBit) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1295,7 +1295,7 @@ // Test that layout from outside a lifecycle wont select a new effective root // scroller. TEST_F(RootScrollerSimTest, NonLifecycleLayoutDoesntCauseReselection) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1347,7 +1347,7 @@ // the current one is valid in all ways except that it no longer has a content // frame. This test passes if it doesn't crash. https://crbug.com/805317. TEST_F(RootScrollerSimTest, RecomputeEffectiveWithNoContentFrame) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); SimRequest first_request("https://example.com/first.html", "text/html"); SimRequest second_request("https://example.com/second.html", "text/html"); @@ -1415,7 +1415,7 @@ // Test that the element is considered to be viewport filling only if its // padding box fills the viewport. That means it must have no border. TEST_F(RootScrollerSimTest, UsePaddingBoxForViewportFillingCondition) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1453,7 +1453,7 @@ // Tests that the root scroller doesn't affect visualViewport pageLeft and // pageTop. TEST_F(RootScrollerSimTest, RootScrollerDoesntAffectVisualViewport) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Start(); @@ -1515,7 +1515,7 @@ WebView().GetSettings()->SetShrinksViewportContentToFit(true); WebView().SetDefaultPageScaleLimits(0.25f, 5); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Start(); @@ -1579,7 +1579,7 @@ // Tests basic implicit root scroller mode with a <div>. TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScroller) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1688,7 +1688,7 @@ // Test that adding overflow to an element that would otherwise be eligable to // be implicitly pomoted causes promotion. TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScrollerAddOverflow) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1734,7 +1734,7 @@ // Tests that we don't crash if an implicit candidate is no longer a box. This // test passes if it doesn't crash. TEST_F(ImplicitRootScrollerSimTest, CandidateLosesLayoutBoxDontCrash) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1775,7 +1775,7 @@ // Ensure that a plugin view being considered for implicit promotion doesn't // cause a crash. https://crbug.com/903440. TEST_F(ImplicitRootScrollerSimTest, ConsiderEmbedCrash) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1795,7 +1795,7 @@ // the main document has overflow. TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScrollerDocumentScrollsOverflow) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1850,7 +1850,7 @@ // Test that we'll only implicitly promote an element if its visible. TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScrollerVisibilityCondition) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1923,7 +1923,7 @@ // Tests implicit root scroller mode for iframes. TEST_F(ImplicitRootScrollerSimTest, ImplicitRootScrollerIframe) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -1967,7 +1967,7 @@ // Tests use counter for implicit root scroller. Ensure it's not counted on a // page without an implicit root scroller. TEST_F(ImplicitRootScrollerSimTest, UseCounterNegative) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -2009,7 +2009,7 @@ // Tests use counter for implicit root scroller. Ensure it's counted on a // page that loads with an implicit root scroller. TEST_F(ImplicitRootScrollerSimTest, UseCounterPositive) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -2060,7 +2060,7 @@ // Tests use counter for implicit root scroller. Ensure it's counted on a // page that loads without an implicit root scroller but later gets one. TEST_F(ImplicitRootScrollerSimTest, UseCounterPositiveAfterLoad) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -2111,7 +2111,7 @@ // Tests that if we have multiple valid candidates for implicit promotion, we // don't promote either. TEST_F(ImplicitRootScrollerSimTest, DontPromoteWhenMultipleAreValid) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -2165,7 +2165,7 @@ // Test that when a valid iframe becomes loaded and thus should be promoted, it // becomes the root scroller, without needing an intervening layout. TEST_F(ImplicitRootScrollerSimTest, IframeLoadedWithoutLayout) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest main_request("https://example.com/test.html", "text/html"); SimRequest child_request("https://example.com/child.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -2216,7 +2216,7 @@ // causes it to remain the effective root scroller after the navigation (to a // page where it remains valid) is finished. TEST_F(ImplicitRootScrollerSimTest, NavigateToValidRemainsRootScroller) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest main_request("https://example.com/test.html", "text/html"); SimRequest child_request("https://example.com/child.html", "text/html"); LoadURL("https://example.com/test.html"); @@ -2374,7 +2374,7 @@ // Tests that implicit is continually reevaluating whether to promote or demote // a scroller. TEST_F(ImplicitRootScrollerSimTest, ContinuallyReevaluateImplicitPromotion) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -2457,7 +2457,7 @@ // Tests that implicit mode correctly recognizes when an iframe becomes // scrollable. TEST_F(ImplicitRootScrollerSimTest, IframeScrollingAffectsPromotion) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -2557,8 +2557,8 @@ << "Once loaded, the iframe should be promoted."; } -// Test that we don't promote any elements implicitly if the main document have -// vertical overflow. +// Test that we don't promote any elements implicitly if the main document has +// vertical scrolling. TEST_F(ImplicitRootScrollerSimTest, OverflowInMainDocumentRestrictsImplicit) { WebView().ResizeWithBrowserControls(IntSize(800, 600), 50, 0, true); SimRequest main_request("https://example.com/test.html", "text/html"); @@ -2612,15 +2612,6 @@ ASSERT_NO_EXCEPTION); Compositor().BeginFrame(); - EXPECT_EQ(GetDocument(), - GetDocument().GetRootScrollerController().EffectiveRootScroller()) - << "iframe still shouldn't be promoted due to horizontal overflow in " - << "the main document."; - - spacer->style()->setProperty(&GetDocument(), "width", "100%", String(), - ASSERT_NO_EXCEPTION); - Compositor().BeginFrame(); - EXPECT_EQ(GetDocument().getElementById("container"), GetDocument().GetRootScrollerController().EffectiveRootScroller()) << "Once vertical overflow is removed, the iframe should be promoted."; @@ -2886,8 +2877,9 @@ // Do a scroll gesture that hides the top controls and scrolls all the way // to the bottom. ASSERT_EQ(1, GetBrowserControls().ShownRatio()); - WebView().ApplyViewportChanges({gfx::ScrollOffset(), gfx::Vector2dF(), 1, - -1, cc::BrowserControlsState::kBoth}); + WebView().MainFrameWidget()->ApplyViewportChanges( + {gfx::ScrollOffset(), gfx::Vector2dF(), 1, -1, + cc::BrowserControlsState::kBoth}); ASSERT_EQ(0, GetBrowserControls().ShownRatio()); Node* scroller = GetDocument()
diff --git a/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc b/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc index c866ff5..078b0ee 100644 --- a/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc +++ b/third_party/blink/renderer/core/page/scrolling/scroll_into_view_test.cc
@@ -25,7 +25,7 @@ TEST_F(ScrollIntoViewTest, InstantScroll) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete( @@ -46,7 +46,7 @@ TEST_F(ScrollIntoViewTest, ScrollPaddingOnBodyViewportDefining) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(300, 300)); + WebView().MainFrameWidget()->Resize(WebSize(300, 300)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -75,7 +75,7 @@ TEST_F(ScrollIntoViewTest, ScrollPaddingOnHtmlViewportDefining) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(300, 300)); + WebView().MainFrameWidget()->Resize(WebSize(300, 300)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -104,7 +104,7 @@ TEST_F(ScrollIntoViewTest, ScrollPaddingBodyOverflowHtmlViewportDefining) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(300, 300)); + WebView().MainFrameWidget()->Resize(WebSize(300, 300)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -144,7 +144,7 @@ TEST_F(ScrollIntoViewTest, SmoothScroll) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete( @@ -174,7 +174,7 @@ TEST_F(ScrollIntoViewTest, NestedContainer) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -222,7 +222,7 @@ TEST_F(ScrollIntoViewTest, NewScrollIntoViewAbortsCurrentAnimation) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -287,7 +287,7 @@ TEST_F(ScrollIntoViewTest, ScrollWindowAbortsCurrentAnimation) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -334,7 +334,7 @@ TEST_F(ScrollIntoViewTest, BlockAndInlineSettings) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -391,7 +391,7 @@ TEST_F(ScrollIntoViewTest, SmoothAndInstantInChain) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -442,7 +442,7 @@ TEST_F(ScrollIntoViewTest, SmoothScrollAnchor) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -476,7 +476,7 @@ TEST_F(ScrollIntoViewTest, FindDoesNotScrollOverflowHidden) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML( @@ -498,7 +498,7 @@ TEST_F(ScrollIntoViewTest, ApplyRootElementScrollBehaviorToViewport) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete( @@ -529,7 +529,7 @@ // This test passes if it doesn't crash/hit an ASAN check. TEST_F(ScrollIntoViewTest, RemoveSequencedScrollableArea) { v8::HandleScope HandleScope(v8::Isolate::GetCurrent()); - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(R"HTML(
diff --git a/third_party/blink/renderer/core/page/scrolling/scroll_metrics_test.cc b/third_party/blink/renderer/core/page/scrolling/scroll_metrics_test.cc index 0285f32..010f14c7 100644 --- a/third_party/blink/renderer/core/page/scrolling/scroll_metrics_test.cc +++ b/third_party/blink/renderer/core/page/scrolling/scroll_metrics_test.cc
@@ -118,7 +118,7 @@ } void ScrollMetricsTest::SetUpHtml(const char* html_content) { - WebView().Resize(WebSize(800, 600)); + WebView().MainFrameWidget()->Resize(WebSize(800, 600)); SimRequest request("https://example.com/test.html", "text/html"); LoadURL("https://example.com/test.html"); request.Complete(html_content);
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc index 4483e294..220adff 100644 --- a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc +++ b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
@@ -73,7 +73,7 @@ : ScopedPaintTouchActionRectsForTest(GetParam()), base_url_("http://www.test.com/") { helper_.Initialize(nullptr, nullptr, nullptr, &ConfigureSettings); - GetWebView()->Resize(IntSize(320, 240)); + GetWebView()->MainFrameWidget()->Resize(IntSize(320, 240)); // macOS attaches main frame scrollbars to the VisualViewport so the // VisualViewport layers need to be initialized. @@ -145,7 +145,7 @@ INSTANTIATE_TEST_CASE_P(All, ScrollingCoordinatorTest, ::testing::Bool()); TEST_P(ScrollingCoordinatorTest, fastScrollingByDefault) { - GetWebView()->Resize(WebSize(800, 600)); + GetWebView()->MainFrameWidget()->Resize(WebSize(800, 600)); LoadHTML("<div id='spacer' style='height: 1000px'></div>"); ForceFullCompositingUpdate(); @@ -175,7 +175,7 @@ } TEST_P(ScrollingCoordinatorTest, fastScrollingCanBeDisabledWithSetting) { - GetWebView()->Resize(WebSize(800, 600)); + GetWebView()->MainFrameWidget()->Resize(WebSize(800, 600)); LoadHTML("<div id='spacer' style='height: 1000px'></div>"); GetWebView()->GetSettings()->SetThreadedScrollingEnabled(false); ForceFullCompositingUpdate(); @@ -1707,6 +1707,10 @@ } }; +INSTANTIATE_TEST_CASE_P(All, + NonCompositedMainThreadScrollingReasonTest, + ::testing::Bool()); + TEST_P(NonCompositedMainThreadScrollingReasonTest, TransparentTest) { TestNonCompositedReasons("transparent", MainThreadScrollingReason::kHasOpacityAndLCDText);
diff --git a/third_party/blink/renderer/core/page/validation_message_client_impl.cc b/third_party/blink/renderer/core/page/validation_message_client_impl.cc index 0bc6df7..f01feb3c 100644 --- a/third_party/blink/renderer/core/page/validation_message_client_impl.cc +++ b/third_party/blink/renderer/core/page/validation_message_client_impl.cc
@@ -63,7 +63,7 @@ HideValidationMessage(anchor); return; } - if (!anchor.GetLayoutBox()) + if (!anchor.GetLayoutObject()) return; if (current_anchor_) HideValidationMessageImmediately(*current_anchor_);
diff --git a/third_party/blink/renderer/core/page/viewport_test.cc b/third_party/blink/renderer/core/page/viewport_test.cc index 66afb24..5049147 100644 --- a/third_party/blink/renderer/core/page/viewport_test.cc +++ b/third_party/blink/renderer/core/page/viewport_test.cc
@@ -2958,7 +2958,7 @@ base_url_ + "viewport/viewport-gpu-rasterization-disabled-without-viewport.html", nullptr, nullptr, nullptr, SetViewportSettings); - web_view_helper.GetWebView()->Resize(WebSize(640, 480)); + web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480)); EXPECT_FALSE(web_view_helper.GetWebView() ->MatchesHeuristicsForGpuRasterizationForTesting()); // Also test that setting enableViewport to false (as on desktop Chrome) @@ -2966,7 +2966,7 @@ web_view_helper.InitializeAndLoad( base_url_ + "viewport/viewport-gpu-rasterization-disabled-without-viewport.html"); - web_view_helper.GetWebView()->Resize(WebSize(640, 480)); + web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480)); EXPECT_TRUE(web_view_helper.GetWebView() ->MatchesHeuristicsForGpuRasterizationForTesting()); @@ -2974,7 +2974,7 @@ web_view_helper.InitializeAndLoad( base_url_ + "viewport/viewport-gpu-rasterization.html", nullptr, nullptr, nullptr, SetViewportSettings); - web_view_helper.GetWebView()->Resize(WebSize(640, 480)); + web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480)); EXPECT_TRUE(web_view_helper.GetWebView() ->MatchesHeuristicsForGpuRasterizationForTesting()); @@ -2984,7 +2984,7 @@ base_url_ + "viewport/viewport-gpu-rasterization-expanded-heuristics.html", nullptr, nullptr, nullptr, SetViewportSettings); - web_view_helper.GetWebView()->Resize(WebSize(640, 480)); + web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480)); EXPECT_TRUE(web_view_helper.GetWebView() ->MatchesHeuristicsForGpuRasterizationForTesting()); @@ -2992,7 +2992,7 @@ web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-1.html", nullptr, nullptr, nullptr, SetViewportSettings); - web_view_helper.GetWebView()->Resize(WebSize(640, 480)); + web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480)); EXPECT_TRUE(web_view_helper.GetWebView() ->MatchesHeuristicsForGpuRasterizationForTesting()); @@ -3000,7 +3000,7 @@ web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-15.html", nullptr, nullptr, nullptr, SetViewportSettings); - web_view_helper.GetWebView()->Resize(WebSize(640, 480)); + web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480)); EXPECT_TRUE(web_view_helper.GetWebView() ->MatchesHeuristicsForGpuRasterizationForTesting()); @@ -3008,7 +3008,7 @@ web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-130.html", nullptr, nullptr, nullptr, SetViewportSettings); - web_view_helper.GetWebView()->Resize(WebSize(640, 480)); + web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480)); EXPECT_TRUE(web_view_helper.GetWebView() ->MatchesHeuristicsForGpuRasterizationForTesting()); @@ -3016,7 +3016,7 @@ web_view_helper.InitializeAndLoad( base_url_ + "viewport/viewport-legacy-handheldfriendly.html", nullptr, nullptr, nullptr, SetViewportSettings); - web_view_helper.GetWebView()->Resize(WebSize(640, 480)); + web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480)); EXPECT_TRUE(web_view_helper.GetWebView() ->MatchesHeuristicsForGpuRasterizationForTesting()); @@ -3024,7 +3024,7 @@ web_view_helper.InitializeAndLoad( base_url_ + "viewport/viewport-legacy-handheldfriendly.html", nullptr, nullptr, nullptr, SetViewportSettings); - web_view_helper.GetWebView()->Resize(WebSize(640, 480)); + web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480)); EXPECT_TRUE(web_view_helper.GetWebView() ->MatchesHeuristicsForGpuRasterizationForTesting()); } @@ -3375,7 +3375,7 @@ WebView().GetSettings()->SetViewportEnabled(true); WebView().GetSettings()->SetViewportMetaEnabled(true); - WebView().Resize(WebSize(500, 600)); + WebView().MainFrameWidget()->Resize(WebSize(500, 600)); } void UseMetaTag(const String& metaTag) {
diff --git a/third_party/blink/renderer/core/paint/image_painter.cc b/third_party/blink/renderer/core/paint/image_painter.cc index bc9c41e..43d7804 100644 --- a/third_party/blink/renderer/core/paint/image_painter.cc +++ b/third_party/blink/renderer/core/paint/image_painter.cc
@@ -155,8 +155,8 @@ if (pixel_snapped_dest_rect.IsEmpty()) return; - scoped_refptr<Image> image = layout_image_.ImageResource()->GetImage( - LayoutSize(pixel_snapped_dest_rect.Size())); + scoped_refptr<Image> image = + layout_image_.ImageResource()->GetImage(pixel_snapped_dest_rect.Size()); if (!image || image->IsNull()) return;
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc b/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc index cef75c0e..414f1c7 100644 --- a/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc +++ b/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc
@@ -121,7 +121,7 @@ WebViewImpl* web_view_impl = web_view_helper_.GetWebView(); int page_width = 640; int page_height = 480; - web_view_impl->Resize(WebSize(page_width, page_height)); + web_view_impl->MainFrameWidget()->Resize(WebSize(page_width, page_height)); UpdateAllLifecyclePhases(); WebGestureEvent touch_event(WebInputEvent::kGestureShowPress, @@ -175,7 +175,7 @@ int page_width = 640; int page_height = 480; - web_view_impl->Resize(WebSize(page_width, page_height)); + web_view_impl->MainFrameWidget()->Resize(WebSize(page_width, page_height)); UpdateAllLifecyclePhases(); WebGestureEvent touch_event(WebInputEvent::kGestureShowPress, @@ -222,7 +222,7 @@ int page_width = 640; int page_height = 480; - web_view_impl->Resize(WebSize(page_width, page_height)); + web_view_impl->MainFrameWidget()->Resize(WebSize(page_width, page_height)); UpdateAllLifecyclePhases(); WebGestureEvent touch_event(WebInputEvent::kGestureShowPress, @@ -257,7 +257,7 @@ int page_width = 640; int page_height = 480; WebViewImpl* web_view_impl = web_view_helper_.GetWebView(); - web_view_impl->Resize(WebSize(page_width, page_height)); + web_view_impl->MainFrameWidget()->Resize(WebSize(page_width, page_height)); paint_artifact_compositor()->EnableExtraDataForTesting(); UpdateAllLifecyclePhases(); @@ -312,7 +312,7 @@ int page_width = 640; int page_height = 480; WebViewImpl* web_view_impl = web_view_helper_.GetWebView(); - web_view_impl->Resize(WebSize(page_width, page_height)); + web_view_impl->MainFrameWidget()->Resize(WebSize(page_width, page_height)); UpdateAllLifecyclePhases(); paint_artifact_compositor()->EnableExtraDataForTesting();
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index 7b088b7..33b721d 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -652,30 +652,6 @@ ->SquashingOffsetFromTransformedAncestor()); } -void PaintLayer::MapRectToPaintInvalidationBacking( - const LayoutObject& layout_object, - const LayoutBoxModelObject& paint_invalidation_container, - LayoutRect& rect) { - if (!paint_invalidation_container.Layer()->GroupedMapping()) { - layout_object.MapToVisualRectInAncestorSpace(&paint_invalidation_container, - rect); - return; - } - - // This code adjusts the visual rect to be in the space of the transformed - // ancestor of the grouped (i.e. squashed) layer. This is because all layers - // that squash together need to issue paint invalidations w.r.t. a single - // container that is an ancestor of all of them, in order to properly take - // into account any local transforms etc. - // FIXME: remove this special-case code that works around the paint - // invalidation code structure. - layout_object.MapToVisualRectInAncestorSpace(&paint_invalidation_container, - rect); - - MapRectInPaintInvalidationContainerToBacking(paint_invalidation_container, - rect); -} - void PaintLayer::DirtyVisibleContentStatus() { MarkAncestorChainForDescendantDependentFlagsUpdate(); // Non-self-painting layers paint into their ancestor layer, and count as part
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h index 8f39ceee..feed9f4 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.h +++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -567,15 +567,6 @@ const LayoutBoxModelObject& paint_invalidation_container, LayoutRect&); - // Adjusts the given rect (in the coordinate space of the LayoutObject) to the - // coordinate space of |paintInvalidationContainer|'s GraphicsLayer backing. - // Should use PaintInvalidatorContext::MapRectToPaintInvalidationBacking() - // instead if PaintInvalidatorContext. - static void MapRectToPaintInvalidationBacking( - const LayoutObject&, - const LayoutBoxModelObject& paint_invalidation_container, - LayoutRect&); - bool PaintsWithTransparency(GlobalPaintFlags global_paint_flags) const { return IsTransparent() && !PaintsIntoOwnBacking(global_paint_flags); }
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc index 6bf5cfe6..286fd73 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -809,7 +809,7 @@ } LayoutBox* PaintLayerScrollableArea::GetLayoutBox() const { - return layer_->GetLayoutBox(); + return layer_ ? layer_->GetLayoutBox() : nullptr; } PaintLayer* PaintLayerScrollableArea::Layer() const {
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index 90459804..e7540283 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -1547,8 +1547,8 @@ LayoutRect layout_replaced_rect = layout_image.ReplacedContentRect(); layout_replaced_rect.MoveBy(context_.current.paint_offset); IntRect replaced_rect = PixelSnappedIntRect(layout_replaced_rect); - scoped_refptr<Image> image = layout_image.ImageResource()->GetImage( - LayoutSize(replaced_rect.Size())); + scoped_refptr<Image> image = + layout_image.ImageResource()->GetImage(replaced_rect.Size()); if (image && !image->IsNull()) { IntRect src_rect = image->Rect(); if (ImageWasTransposed(layout_image, *image))
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc b/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc index f47ef22..d236377a 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
@@ -1409,4 +1409,31 @@ svg2_properties->PaintOffsetTranslation())); } +TEST_P(PaintPropertyTreeUpdateTest, ChangingClipPath) { + GetDocument().GetSettings()->SetPreferCompositingToLCDTextEnabled(false); + SetBodyInnerHTML(R"HTML( + <style> + #content { + height: 500px; + width: 200px; + overflow: scroll; + } + .aclippath { clip-path: circle(115px at 20px 20px); } + .bclippath { clip-path: circle(135px at 22px 20px); } + </style> + <div id="content"></div> + )HTML"); + auto* content = GetDocument().getElementById("content"); + content->setAttribute(html_names::kClassAttr, "aclippath"); + UpdateAllLifecyclePhasesForTest(); + + content->setAttribute(html_names::kClassAttr, "bclippath"); + UpdateAllLifecyclePhasesForTest(); + // Pass if no crash. + + content->removeAttribute(html_names::kClassAttr); + UpdateAllLifecyclePhasesForTest(); + // Pass if no crash. +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/svg_image_painter.cc b/third_party/blink/renderer/core/paint/svg_image_painter.cc index d077d2e6..0d47ef4 100644 --- a/third_party/blink/renderer/core/paint/svg_image_painter.cc +++ b/third_party/blink/renderer/core/paint/svg_image_painter.cc
@@ -56,16 +56,12 @@ void SVGImagePainter::PaintForeground(const PaintInfo& paint_info) { const LayoutImageResource* image_resource = layout_svg_image_.ImageResource(); - // TODO(fs): Reduce the number of conversions. - // (FloatSize -> IntSize -> LayoutSize currently.) - FloatSize float_image_viewport_size = ComputeImageViewportSize(); - float_image_viewport_size.Scale(layout_svg_image_.StyleRef().EffectiveZoom()); - IntSize image_viewport_size = ExpandedIntSize(float_image_viewport_size); + FloatSize image_viewport_size = ComputeImageViewportSize(); + image_viewport_size.Scale(layout_svg_image_.StyleRef().EffectiveZoom()); if (image_viewport_size.IsEmpty()) return; - scoped_refptr<Image> image = - image_resource->GetImage(LayoutSize(image_viewport_size)); + scoped_refptr<Image> image = image_resource->GetImage(image_viewport_size); FloatRect dest_rect = layout_svg_image_.ObjectBoundingBox(); FloatRect src_rect(0, 0, image->width(), image->height());
diff --git a/third_party/blink/renderer/core/probe/core_probes.cc b/third_party/blink/renderer/core/probe/core_probes.cc index 262caa13fb..e559212 100644 --- a/third_party/blink/renderer/core/probe/core_probes.cc +++ b/third_party/blink/renderer/core/probe/core_probes.cc
@@ -51,8 +51,7 @@ void* task, const char* step, bool enabled) - : debugger_(enabled && context ? ThreadDebugger::From(context->GetIsolate()) - : nullptr), + : debugger_(enabled ? ThreadDebugger::From(ToIsolate(context)) : nullptr), task_(AsyncId(task)), recurring_(step) { if (recurring_) { @@ -81,10 +80,8 @@ TRACE_EVENT_FLOW_BEGIN1("devtools.timeline.async", "AsyncTask", TRACE_ID_LOCAL(reinterpret_cast<uintptr_t>(task)), "data", inspector_async_task::Data(name)); - if (context) { - if (ThreadDebugger* debugger = ThreadDebugger::From(context->GetIsolate())) - debugger->AsyncTaskScheduled(name, AsyncId(task), true); - } + if (ThreadDebugger* debugger = ThreadDebugger::From(ToIsolate(context))) + debugger->AsyncTaskScheduled(name, AsyncId(task), true); } void AsyncTaskScheduledBreakable(ExecutionContext* context, @@ -95,7 +92,7 @@ } void AsyncTaskCanceled(ExecutionContext* context, void* task) { - AsyncTaskCanceled(context->GetIsolate(), task); + AsyncTaskCanceled(ToIsolate(context), task); } void AsyncTaskCanceled(v8::Isolate* isolate, void* task) { @@ -113,7 +110,7 @@ } void AllAsyncTasksCanceled(ExecutionContext* context) { - if (ThreadDebugger* debugger = ThreadDebugger::From(context->GetIsolate())) + if (ThreadDebugger* debugger = ThreadDebugger::From(ToIsolate(context))) debugger->AllAsyncTasksCanceled(); }
diff --git a/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc b/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc index 49bcf72..1b3c09f 100644 --- a/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc +++ b/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc
@@ -43,7 +43,7 @@ protected: void SetUp() override { SimTest::SetUp(); - WebView().Resize(WebSize(640, 480)); + WebView().MainFrameWidget()->Resize(WebSize(640, 480)); } SimCanvas::Commands CompositeFrame() {
diff --git a/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.cc b/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.cc index 15af66c..461d9172 100644 --- a/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.cc +++ b/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.cc
@@ -40,6 +40,27 @@ return execution_context_->GetHttpsState(); } +AllowedByNosniff::MimeTypeCheck +FetchClientSettingsObjectImpl::MimeTypeCheckForClassicWorkerScript() const { + if (execution_context_->IsDocument()) { + // For worker creation on a document, don't impose strict MIME-type checks + // on the top-level worker script for backward compatibility. Note that + // there is a plan to deprecate legacy mime types for workers. See + // https://crbug.com/794548. + // + // For worker creation on a document with off-the-main-thread top-level + // worker classic script loading, this value is propagated to + // outsideSettings FCSO. + return AllowedByNosniff::MimeTypeCheck::kLax; + } + + // For importScripts() and nested worker top-level scripts impose the strict + // MIME-type checks. + // Nested workers is a new feature (enabled by default in M69) and there is no + // backward compatibility issue. + return AllowedByNosniff::MimeTypeCheck::kStrict; +} + void FetchClientSettingsObjectImpl::Trace(Visitor* visitor) { visitor->Trace(execution_context_); FetchClientSettingsObject::Trace(visitor);
diff --git a/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h b/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h index 8ea794e2..d79ee30 100644 --- a/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h +++ b/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h
@@ -38,6 +38,9 @@ HttpsState GetHttpsState() const override; + AllowedByNosniff::MimeTypeCheck MimeTypeCheckForClassicWorkerScript() + const override; + void Trace(Visitor* visitor) override; private:
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index b921a3d9..63263e8 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2120,10 +2120,8 @@ // CanContainFixedPositionObjects. We currently never use this value // directly, always OR'ing it with CanContainFixedPositionObjects. bool CanContainAbsolutePositionObjects() const { - return GetPosition() != EPosition::kStatic || - WillChangeProperties().Contains(CSSPropertyPosition); + return GetPosition() != EPosition::kStatic; } - bool CanContainFixedPositionObjects(bool is_document_element) const { return HasTransformRelatedProperty() || // Filter establishes containing block for non-document elements:
diff --git a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 index 4cae09bf..0b8ef22 100644 --- a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 +++ b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
@@ -309,6 +309,12 @@ method: "Resize()", field_dependencies: ["resize"] }, + ], + predicates_to_test: [ + { + predicate: "a.ClipPathDataEquivalent(b)", + field_dependencies: ["clip-path"] + } ] }, {
diff --git a/third_party/blink/renderer/core/svg/svg_image_element.idl b/third_party/blink/renderer/core/svg/svg_image_element.idl index 771e482..b4339886 100644 --- a/third_party/blink/renderer/core/svg/svg_image_element.idl +++ b/third_party/blink/renderer/core/svg/svg_image_element.idl
@@ -37,7 +37,8 @@ // https://github.com/ojanvafai/intrinsicsize-attribute/blob/master/README.md [RuntimeEnabled=ExperimentalProductivityFeatures, CEReactions, Reflect] attribute DOMString intrinsicSize; - [CallWith=ScriptState, RaisesException] Promise decode(); + // Follow HTMLImageElement's spec + [CallWith=ScriptState, RaisesException] Promise<void> decode(); }; SVGImageElement implements SVGURIReference;
diff --git a/third_party/blink/renderer/core/testing/internals.idl b/third_party/blink/renderer/core/testing/internals.idl index 6a78ab8..255e98d 100644 --- a/third_party/blink/renderer/core/testing/internals.idl +++ b/third_party/blink/renderer/core/testing/internals.idl
@@ -309,15 +309,15 @@ [RaisesException] void setShouldRevealPassword(Element element, boolean reveal); - [CallWith=ScriptState] Promise createResolvedPromise(any value); - [CallWith=ScriptState] Promise createRejectedPromise(any reason); - [CallWith=ScriptState] Promise addOneToPromise(Promise promise); - [CallWith=ScriptState, RaisesException] Promise promiseCheck(long arg1, boolean arg2, object arg3, DOMString arg4, sequence<DOMString> arg5); - [CallWith=ScriptState] Promise promiseCheckWithoutExceptionState(object arg1, DOMString arg2, DOMString... variadic); - [CallWith=ScriptState] Promise promiseCheckRange([EnforceRange] octet arg1); - [CallWith=ScriptState] Promise promiseCheckOverload(Location arg1); - [CallWith=ScriptState] Promise promiseCheckOverload(Document arg1); - [CallWith=ScriptState] Promise promiseCheckOverload(Location arg1, long arg2, long arg3); + [CallWith=ScriptState] Promise<any> createResolvedPromise(any value); + [CallWith=ScriptState] Promise<any> createRejectedPromise(any reason); + [CallWith=ScriptState] Promise<any> addOneToPromise(Promise<any> promise); + [CallWith=ScriptState, RaisesException] Promise<any> promiseCheck(long arg1, boolean arg2, object arg3, DOMString arg4, sequence<DOMString> arg5); + [CallWith=ScriptState] Promise<any> promiseCheckWithoutExceptionState(object arg1, DOMString arg2, DOMString... variadic); + [CallWith=ScriptState] Promise<any> promiseCheckRange([EnforceRange] octet arg1); + [CallWith=ScriptState] Promise<any> promiseCheckOverload(Location arg1); + [CallWith=ScriptState] Promise<any> promiseCheckOverload(Document arg1); + [CallWith=ScriptState] Promise<any> promiseCheckOverload(Location arg1, long arg2, long arg3); void setValueForUser(HTMLInputElement element, DOMString value);
diff --git a/third_party/blink/renderer/core/testing/sim/sim_canvas.cc b/third_party/blink/renderer/core/testing/sim/sim_canvas.cc index 8ea1b96..29217bb 100644 --- a/third_party/blink/renderer/core/testing/sim/sim_canvas.cc +++ b/third_party/blink/renderer/core/testing/sim/sim_canvas.cc
@@ -87,35 +87,6 @@ SkCanvas::onDrawImageRect(image, src, dst, paint, constraint); } -void SimCanvas::onDrawText(const void* text, - size_t byte_length, - SkScalar x, - SkScalar y, - const SkPaint& paint) { - DrawScope scope; - AddCommand(CommandType::kText, paint.getColor()); - SkCanvas::onDrawText(text, byte_length, x, y, paint); -} - -void SimCanvas::onDrawPosText(const void* text, - size_t byte_length, - const SkPoint pos[], - const SkPaint& paint) { - DrawScope scope; - AddCommand(CommandType::kText, paint.getColor()); - SkCanvas::onDrawPosText(text, byte_length, pos, paint); -} - -void SimCanvas::onDrawPosTextH(const void* text, - size_t byte_length, - const SkScalar xpos[], - SkScalar const_y, - const SkPaint& paint) { - DrawScope scope; - AddCommand(CommandType::kText, paint.getColor()); - SkCanvas::onDrawPosTextH(text, byte_length, xpos, const_y, paint); -} - void SimCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
diff --git a/third_party/blink/renderer/core/testing/sim/sim_canvas.h b/third_party/blink/renderer/core/testing/sim/sim_canvas.h index 4c40108a..cf086d5 100644 --- a/third_party/blink/renderer/core/testing/sim/sim_canvas.h +++ b/third_party/blink/renderer/core/testing/sim/sim_canvas.h
@@ -62,20 +62,6 @@ SrcRectConstraint) override; // Text - void onDrawText(const void* text, - size_t byte_length, - SkScalar x, - SkScalar y, - const SkPaint&) override; - void onDrawPosText(const void* text, - size_t byte_length, - const SkPoint pos[], - const SkPaint&) override; - void onDrawPosTextH(const void* text, - size_t byte_length, - const SkScalar xpos[], - SkScalar const_y, - const SkPaint&) override; void onDrawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y,
diff --git a/third_party/blink/renderer/core/testing/sim/sim_compositor.cc b/third_party/blink/renderer/core/testing/sim/sim_compositor.cc index becc31a0..7881ce55a 100644 --- a/third_party/blink/renderer/core/testing/sim/sim_compositor.cc +++ b/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
@@ -76,7 +76,7 @@ } void SimCompositor::ApplyViewportChanges(const ApplyViewportChangesArgs& args) { - web_view_->ApplyViewportChanges(args); + web_view_->MainFrameWidget()->ApplyViewportChanges(args); } void SimCompositor::RequestNewLayerTreeFrameSink( @@ -89,7 +89,7 @@ void SimCompositor::BeginMainFrame(base::TimeTicks frame_time) { // There is no WebWidget like RenderWidget would have..? So go right to the // WebViewImpl. - web_view_->BeginFrame(last_frame_time_); + web_view_->MainFrameWidget()->BeginFrame(last_frame_time_); web_view_->MainFrameWidget()->UpdateAllLifecyclePhases( WebWidget::LifecycleUpdateReason::kTest); *paint_commands_ = PaintFrame();
diff --git a/third_party/blink/renderer/core/timing/performance_event_timing.idl b/third_party/blink/renderer/core/timing/performance_event_timing.idl index 6bc00fb6..5713e2d4 100644 --- a/third_party/blink/renderer/core/timing/performance_event_timing.idl +++ b/third_party/blink/renderer/core/timing/performance_event_timing.idl
@@ -4,6 +4,7 @@ // https://github.com/wicg/event-timing [ + Exposed=Window, OriginTrialEnabled=EventTiming ] interface PerformanceEventTiming : PerformanceEntry { readonly attribute DOMHighResTimeStamp processingStart;
diff --git a/third_party/blink/renderer/core/timing/performance_resource_timing.cc b/third_party/blink/renderer/core/timing/performance_resource_timing.cc index b80b062..746382b 100644 --- a/third_party/blink/renderer/core/timing/performance_resource_timing.cc +++ b/third_party/blink/renderer/core/timing/performance_resource_timing.cc
@@ -258,6 +258,10 @@ if (!AllowTimingDetails()) return 0.0; ResourceLoadTiming* timing = GetResourceLoadTiming(); + // Step 1 of + // https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-secureconnectionstart. + if (DidReuseConnection()) + return fetchStart(); // SslStart will be zero when a secure connection is not negotiated. if (!timing || timing->SslStart().is_null()) return 0.0;
diff --git a/third_party/blink/renderer/core/timing/performance_user_timing.cc b/third_party/blink/renderer/core/timing/performance_user_timing.cc index 82e9b3a..558ecf82 100644 --- a/third_party/blink/renderer/core/timing/performance_user_timing.cc +++ b/third_party/blink/renderer/core/timing/performance_user_timing.cc
@@ -226,14 +226,15 @@ double start_time_monotonic = performance_->GetTimeOrigin() + start_time / 1000.0; double end_time_monotonic = performance_->GetTimeOrigin() + end_time / 1000.0; + unsigned hash = WTF::StringHash::GetHash(measure_name); + WTF::AddFloatToHash(hash, start_time); + WTF::AddFloatToHash(hash, end_time); TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( - "blink.user_timing", measure_name.Utf8().data(), - WTF::StringHash::GetHash(measure_name), + "blink.user_timing", measure_name.Utf8().data(), hash, trace_event::ToTraceTimestamp(start_time_monotonic)); TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TIMESTAMP0( - "blink.user_timing", measure_name.Utf8().data(), - WTF::StringHash::GetHash(measure_name), + "blink.user_timing", measure_name.Utf8().data(), hash, trace_event::ToTraceTimestamp(end_time_monotonic)); PerformanceMeasure* measure = PerformanceMeasure::Create(
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc b/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc index 83cbee3..068d0750e 100644 --- a/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc +++ b/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc
@@ -90,7 +90,7 @@ } TrustedHTML* result = default_policy->CreateHTML( - doc->GetIsolate(), string_or_trusted_html.GetAsString(), exception_state); + ToIsolate(doc), string_or_trusted_html.GetAsString(), exception_state); if (exception_state.HadException()) { exception_state.ClearException(); exception_state.ThrowTypeError( @@ -146,7 +146,7 @@ ? g_empty_string : string_or_trusted_script.GetAsString(); TrustedScript* result = default_policy->CreateScript( - doc->GetIsolate(), string_value_or_empty, exception_state); + ToIsolate(doc), string_value_or_empty, exception_state); DCHECK_EQ(!result, exception_state.HadException()); if (exception_state.HadException()) { exception_state.ClearException(); @@ -186,7 +186,7 @@ } TrustedScriptURL* result = default_policy->CreateScriptURL( - doc->GetIsolate(), string_or_trusted_script_url.GetAsString(), + ToIsolate(doc), string_or_trusted_script_url.GetAsString(), exception_state); if (exception_state.HadException()) { @@ -226,8 +226,7 @@ } TrustedURL* result = default_policy->CreateURL( - doc->GetIsolate(), string_or_trusted_url.GetAsUSVString(), - exception_state); + ToIsolate(doc), string_or_trusted_url.GetAsUSVString(), exception_state); if (exception_state.HadException()) { exception_state.ClearException(); exception_state.ThrowTypeError(
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.cc b/third_party/blink/renderer/core/workers/dedicated_worker.cc index 83787cdb..80101c65 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker.cc
@@ -164,7 +164,7 @@ DCHECK(GetExecutionContext()->IsContextThread()); v8_inspector::V8StackTraceId stack_id = - ThreadDebugger::From(GetExecutionContext()->GetIsolate()) + ThreadDebugger::From(ToIsolate(GetExecutionContext())) ->StoreCurrentStackTrace("Worker Created"); if (auto* scope = DynamicTo<WorkerGlobalScope>(*GetExecutionContext())) @@ -197,7 +197,6 @@ network::mojom::FetchRequestMode::kSameOrigin, network::mojom::FetchCredentialsMode::kSameOrigin, GetExecutionContext()->GetSecurityContext().AddressSpace(), - GetExecutionContext()->IsWorkerGlobalScope(), WTF::Bind(&DedicatedWorker::OnResponse, WrapPersistent(this)), WTF::Bind(&DedicatedWorker::OnFinished, WrapPersistent(this), stack_id));
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc index 08de75ba..4d8ccaa9 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
@@ -65,10 +65,6 @@ return event_target_names::kDedicatedWorkerGlobalScope; } -bool DedicatedWorkerGlobalScope::IsNestedWorker() const { - return static_cast<DedicatedWorkerThread*>(GetThread())->IsNestedWorker(); -} - // https://html.spec.whatwg.org/multipage/workers.html#worker-processing-model void DedicatedWorkerGlobalScope::ImportModuleScript( const KURL& module_url_record,
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h index c73d796..10687a3 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h +++ b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h
@@ -62,7 +62,6 @@ const AtomicString& InterfaceName() const override; // WorkerGlobalScope - bool IsNestedWorker() const override; void ImportModuleScript( const KURL& module_url_record, FetchClientSettingsObjectSnapshot* outside_settings_object,
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc index 7734b5cb..f849cba 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc
@@ -53,7 +53,7 @@ InitializeWorkerThread( std::move(creation_params), - CreateBackingThreadStartupData(GetExecutionContext()->GetIsolate())); + CreateBackingThreadStartupData(ToIsolate(GetExecutionContext()))); // Step 13: "Obtain script by switching on the value of options's type // member:" @@ -140,7 +140,7 @@ return; ThreadDebugger* debugger = - ThreadDebugger::From(GetExecutionContext()->GetIsolate()); + ThreadDebugger::From(ToIsolate(GetExecutionContext())); MessagePortArray* ports = MessagePort::EntanglePorts( *GetExecutionContext(), std::move(message.ports)); debugger->ExternalAsyncTaskStarted(message.sender_stack_trace_id);
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_thread.cc b/third_party/blink/renderer/core/workers/dedicated_worker_thread.cc index 273c6da1..9d0ce47 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_thread.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker_thread.cc
@@ -59,8 +59,7 @@ DedicatedWorkerObjectProxy& worker_object_proxy) : WorkerThread(worker_object_proxy), name_(name.IsolatedCopy()), - worker_object_proxy_(worker_object_proxy), - is_nested_worker_(parent_execution_context->IsWorkerGlobalScope()) { + worker_object_proxy_(worker_object_proxy) { FrameOrWorkerScheduler* scheduler = parent_execution_context ? parent_execution_context->GetScheduler() : nullptr;
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_thread.h b/third_party/blink/renderer/core/workers/dedicated_worker_thread.h index b506d3f68..01466db 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_thread.h +++ b/third_party/blink/renderer/core/workers/dedicated_worker_thread.h
@@ -54,8 +54,6 @@ return worker_object_proxy_; } - bool IsNestedWorker() const { return is_nested_worker_; } - private: friend class DedicatedWorkerThreadForTest; @@ -72,7 +70,6 @@ std::unique_ptr<WorkerBackingThread> worker_backing_thread_; const String name_; DedicatedWorkerObjectProxy& worker_object_proxy_; - const bool is_nested_worker_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/workers/experimental/task.cc b/third_party/blink/renderer/core/workers/experimental/task.cc index 01a57b7..4626c59 100644 --- a/third_party/blink/renderer/core/workers/experimental/task.cc +++ b/third_party/blink/renderer/core/workers/experimental/task.cc
@@ -170,7 +170,7 @@ DCHECK(v8_result_); ScriptState::Scope scope( worker_thread_->GlobalScope()->ScriptController()->GetScriptState()); - v8::Isolate* isolate = worker_thread_->GlobalScope()->GetIsolate(); + v8::Isolate* isolate = ToIsolate(worker_thread_->GlobalScope()); serialized_result_ = SerializedScriptValue::SerializeAndSwallowExceptions( isolate, v8_result_->GetResult(isolate)); } @@ -250,7 +250,7 @@ State state) { DCHECK(worker_thread_->IsCurrentThread()); v8_result_ = MakeGarbageCollected<V8ResultHolder>( - worker_thread_->GlobalScope()->GetIsolate(), v8_result); + ToIsolate(worker_thread_->GlobalScope()), v8_result); function_ = nullptr; arguments_.clear(); @@ -278,7 +278,7 @@ // so no mutex needed while actually running the task. WorkerOrWorkletGlobalScope* global_scope = worker_thread_->GlobalScope(); ScriptState::Scope scope(global_scope->ScriptController()->GetScriptState()); - v8::Isolate* isolate = global_scope->GetIsolate(); + v8::Isolate* isolate = ToIsolate(global_scope); v8::Local<v8::Context> context = isolate->GetCurrentContext(); v8::Local<v8::Function> script_function; @@ -401,7 +401,7 @@ DCHECK(worker_thread_->IsCurrentThread()); if (!WillStartTaskOnWorkerThread()) { WorkerOrWorkletGlobalScope* global_scope = worker_thread_->GlobalScope(); - v8::Isolate* isolate = global_scope->GetIsolate(); + v8::Isolate* isolate = ToIsolate(global_scope); ScriptState::Scope scope( global_scope->ScriptController()->GetScriptState()); TaskCompletedOnWorkerThread(V8String(isolate, "Task aborted"),
diff --git a/third_party/blink/renderer/core/workers/shared_worker.cc b/third_party/blink/renderer/core/workers/shared_worker.cc index 4433a999..46dcdca 100644 --- a/third_party/blink/renderer/core/workers/shared_worker.cc +++ b/third_party/blink/renderer/core/workers/shared_worker.cc
@@ -88,9 +88,18 @@ } if (document->GetFrame()->Client()->GetSharedWorkerRepositoryClient()) { + // |name| should not be null according to the HTML spec, but the current + // impl wrongly allows it when |name| is omitted. See TODO comment in + // shared_worker.idl. + // TODO(nhiroki): Stop assigning null to |name| as a default value, and + // remove this hack. + String worker_name = ""; + if (!name.IsNull()) + worker_name = name; + document->GetFrame()->Client()->GetSharedWorkerRepositoryClient()->Connect( worker, std::move(remote_port), script_url, std::move(blob_url_token), - name); + worker_name); } return worker;
diff --git a/third_party/blink/renderer/core/workers/shared_worker.idl b/third_party/blink/renderer/core/workers/shared_worker.idl index e5b88eb..c5b5399 100644 --- a/third_party/blink/renderer/core/workers/shared_worker.idl +++ b/third_party/blink/renderer/core/workers/shared_worker.idl
@@ -33,7 +33,8 @@ [ ActiveScriptWrappable, - // TODO(foolip): The name argument should not have a default null value. + // TODO(nhiroki): The second argument should be |optional (DOMString or + // WorkerOptions) options)|. Constructor(DOMString scriptURL, optional DOMString name = null), ConstructorCallWith=ExecutionContext, // TODO(foolip): Exposed=(Window,Worker),
diff --git a/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc b/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc index 37cb55d8..5dc426c 100644 --- a/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc +++ b/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc
@@ -36,6 +36,7 @@ #include "third_party/blink/renderer/core/loader/resource/script_resource.h" #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h" #include "third_party/blink/renderer/core/workers/worker_global_scope.h" +#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h" @@ -49,8 +50,7 @@ namespace blink { WorkerClassicScriptLoader::WorkerClassicScriptLoader() - : response_address_space_(mojom::IPAddressSpace::kPublic), - mime_type_check_mode_(AllowedByNosniff::MimeTypeCheck::kStrict) {} + : response_address_space_(mojom::IPAddressSpace::kPublic) {} void WorkerClassicScriptLoader::LoadSynchronously( ExecutionContext& execution_context, @@ -62,10 +62,6 @@ url_ = url; fetch_client_settings_object_fetcher_ = fetch_client_settings_object_fetcher; - // Impose strict MIME-type checks on importScripts(). See - // https://crbug.com/794548. - mime_type_check_mode_ = AllowedByNosniff::MimeTypeCheck::kStrict; - ResourceRequest request(url); request.SetHTTPMethod(http_names::kGET); request.SetExternalRequestStateFromRequestorAddressSpace( @@ -93,7 +89,6 @@ network::mojom::FetchRequestMode fetch_request_mode, network::mojom::FetchCredentialsMode fetch_credentials_mode, mojom::IPAddressSpace creation_address_space, - bool is_nested_worker, base::OnceClosure response_callback, base::OnceClosure finished_callback) { DCHECK(fetch_client_settings_object_fetcher); @@ -104,30 +99,7 @@ fetch_client_settings_object_fetcher_ = fetch_client_settings_object_fetcher; forbid_cross_origin_redirects_ = true; - if (execution_context.IsDocument()) { - // For worker creation on a document, don't impose strict MIME-type checks - // on the top-level worker script for backward compatibility. Note that - // there is a plan to deprecate legacy mime types for workers. See - // https://crbug.com/794548. - mime_type_check_mode_ = AllowedByNosniff::MimeTypeCheck::kLax; - } else { - DCHECK(execution_context.IsWorkerGlobalScope()); - is_worker_global_scope_ = true; - if (is_nested_worker) { - // For nested workers, impose the strict MIME-type checks because the - // feature is new (enabled by default in M69) and there is no backward - // compatibility issue. - mime_type_check_mode_ = AllowedByNosniff::MimeTypeCheck::kStrict; - } else { - // For worker creation on a document with off-the-main-thread top-level - // worker classic script loading, don't impose strict MIME-type checks for - // backward compatibility. - // TODO(nhiroki): Always impose strict MIME-type checks on all web - // workers (https://crbug.com/794548). - DCHECK(RuntimeEnabledFeatures::OffMainThreadWorkerScriptFetchEnabled()); - mime_type_check_mode_ = AllowedByNosniff::MimeTypeCheck::kLax; - } - } + is_worker_global_scope_ = execution_context.IsWorkerGlobalScope(); ResourceRequest request(url); request.SetHTTPMethod(http_names::kGET); @@ -162,7 +134,10 @@ } if (!AllowedByNosniff::MimeTypeAsScript( fetch_client_settings_object_fetcher_->Context(), response, - mime_type_check_mode_, is_worker_global_scope_)) { + fetch_client_settings_object_fetcher_->Context() + .GetFetchClientSettingsObject() + ->MimeTypeCheckForClassicWorkerScript(), + is_worker_global_scope_)) { NotifyError(); return; } @@ -181,13 +156,6 @@ identifier_ = identifier; response_url_ = response.ResponseUrl(); - // The response URL may be empty if a service worker did respondWith(new - // Response()) to generate a response. - // TODO(falken): Change this to an empty URL if that is indeed spec - // conformant. - if (response_url_.IsEmpty()) - response_url_ = response.CurrentRequestUrl(); - response_encoding_ = response.TextEncodingName(); app_cache_id_ = response.AppCacheID();
diff --git a/third_party/blink/renderer/core/workers/worker_classic_script_loader.h b/third_party/blink/renderer/core/workers/worker_classic_script_loader.h index 7462543..c0aeb0dd 100644 --- a/third_party/blink/renderer/core/workers/worker_classic_script_loader.h +++ b/third_party/blink/renderer/core/workers/worker_classic_script_loader.h
@@ -80,7 +80,6 @@ network::mojom::FetchRequestMode, network::mojom::FetchCredentialsMode, mojom::IPAddressSpace, - bool is_nested_worker, base::OnceClosure response_callback, base::OnceClosure finished_callback); @@ -160,9 +159,6 @@ bool is_worker_global_scope_ = false; Member<ResourceFetcher> fetch_client_settings_object_fetcher_; - - // TODO(nhiroki): Move this to FetchClientSettingsObject. - AllowedByNosniff::MimeTypeCheck mime_type_check_mode_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc index f4cfdcb..a05010a 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -345,6 +345,16 @@ void WorkerGlobalScope::TasksWereUnpaused() { WorkerOrWorkletGlobalScope::TasksWereUnpaused(); + // We cannot run the paused tasks right away, as there might be some other + // code that still needs to be run synchronously. + GetTaskRunner(TaskType::kInternalWorker) + ->PostTask(FROM_HERE, WTF::Bind(&WorkerGlobalScope::MaybeRunPausedTasks, + WrapWeakPersistent(this))); +} + +void WorkerGlobalScope::MaybeRunPausedTasks() { + if (IsContextPaused()) + return; Vector<base::OnceClosure> calls; paused_calls_.swap(calls); for (auto& call : calls) @@ -402,7 +412,7 @@ script_url, mojom::RequestContextType::WORKER, network::mojom::FetchRequestMode::kSameOrigin, network::mojom::FetchCredentialsMode::kSameOrigin, - GetSecurityContext().AddressSpace(), IsNestedWorker(), + GetSecurityContext().AddressSpace(), WTF::Bind(&WorkerGlobalScope::DidReceiveResponseForClassicScript, WrapWeakPersistent(this), WrapPersistent(classic_script_loader)),
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.h b/third_party/blink/renderer/core/workers/worker_global_scope.h index eee519b..65f082f 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.h +++ b/third_party/blink/renderer/core/workers/worker_global_scope.h
@@ -177,9 +177,6 @@ return animation_frame_provider_; } - // Returns true when this is a nested worker. - virtual bool IsNestedWorker() const { return false; } - TrustedTypePolicyFactory* trustedTypes(); protected: @@ -207,6 +204,8 @@ void AddPausedCall(base::OnceClosure closure); + void MaybeRunPausedTasks(); + mojom::ScriptType GetScriptType() const { return script_type_; } private:
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc index 28f5fa4d..af557b1 100644 --- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc +++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -273,7 +273,7 @@ } XMLHttpRequest* XMLHttpRequest::Create(ExecutionContext* context) { - v8::Isolate* isolate = context->GetIsolate(); + v8::Isolate* isolate = ToIsolate(context); CHECK(isolate); XMLHttpRequest* xml_http_request =
diff --git a/third_party/blink/renderer/devtools/BUILD.gn b/third_party/blink/renderer/devtools/BUILD.gn index df89928..12ffdeb1 100644 --- a/third_party/blink/renderer/devtools/BUILD.gn +++ b/third_party/blink/renderer/devtools/BUILD.gn
@@ -875,6 +875,71 @@ "front_end/workspace_diff/module.json", ] +devtools_test_files = [ + "front_end/accessibility_test_runner/AccessibilityPaneTestRunner.js", + "front_end/accessibility_test_runner/module.json", + "front_end/application_test_runner/AppcacheTestRunner.js", + "front_end/application_test_runner/CacheStorageTestRunner.js", + "front_end/application_test_runner/IndexedDBTestRunner.js", + "front_end/application_test_runner/module.json", + "front_end/application_test_runner/ResourcesTestRunner.js", + "front_end/application_test_runner/ResourceTreeTestRunner.js", + "front_end/application_test_runner/ServiceWorkersTestRunner.js", + "front_end/audits2_test_runner/Audits2TestRunner.js", + "front_end/audits2_test_runner/module.json", + "front_end/bindings_test_runner/AutomappingTestRunner.js", + "front_end/bindings_test_runner/BindingsTestRunner.js", + "front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js", + "front_end/bindings_test_runner/module.json", + "front_end/bindings_test_runner/OverridesTestRunner.js", + "front_end/bindings_test_runner/PersistenceTestRunner.js", + "front_end/console_test_runner/ConsoleTestRunner.js", + "front_end/console_test_runner/module.json", + "front_end/coverage_test_runner/CoverageTestRunner.js", + "front_end/coverage_test_runner/module.json", + "front_end/cpu_profiler_test_runner/module.json", + "front_end/cpu_profiler_test_runner/ProfilerTestRunner.js", + "front_end/data_grid_test_runner/DataGridTestRunner.js", + "front_end/data_grid_test_runner/module.json", + "front_end/device_mode_test_runner/DeviceModeTestRunner.js", + "front_end/device_mode_test_runner/module.json", + "front_end/elements_test_runner/EditDOMTestRunner.js", + "front_end/elements_test_runner/ElementsPanelShadowSelectionOnRefreshTestRunner.js", + "front_end/elements_test_runner/ElementsTestRunner.js", + "front_end/elements_test_runner/module.json", + "front_end/elements_test_runner/SetOuterHTMLTestRunner.js", + "front_end/elements_test_runner/StylesUpdateLinksTestRunner.js", + "front_end/extensions_test_runner/ExtensionsNetworkTestRunner.js", + "front_end/extensions_test_runner/ExtensionsTestRunner.js", + "front_end/extensions_test_runner/module.json", + "front_end/heap_profiler_test_runner/HeapProfilerTestRunner.js", + "front_end/heap_profiler_test_runner/module.json", + "front_end/integration_test_runner.html", + "front_end/integration_test_runner.js", + "front_end/integration_test_runner.json", + "front_end/layers_test_runner/LayersTestRunner.js", + "front_end/layers_test_runner/module.json", + "front_end/network_test_runner/module.json", + "front_end/network_test_runner/NetworkTestRunner.js", + "front_end/network_test_runner/ProductRegistryTestRunner.js", + "front_end/performance_test_runner/module.json", + "front_end/performance_test_runner/TimelineDataTestRunner.js", + "front_end/performance_test_runner/TimelineTestRunner.js", + "front_end/sdk_test_runner/module.json", + "front_end/sdk_test_runner/PageMockTestRunner.js", + "front_end/security_test_runner/module.json", + "front_end/security_test_runner/SecurityTestRunner.js", + "front_end/sources_test_runner/AutocompleteTestRunner.js", + "front_end/sources_test_runner/DebuggerTestRunner.js", + "front_end/sources_test_runner/EditorTestRunner.js", + "front_end/sources_test_runner/LiveEditTestRunner.js", + "front_end/sources_test_runner/module.json", + "front_end/sources_test_runner/SearchTestRunner.js", + "front_end/sources_test_runner/SourcesTestRunner.js", + "front_end/test_runner/module.json", + "front_end/test_runner/TestRunner.js", +] + devtools_embedder_scripts = [ "front_end/devtools_compatibility.js", "front_end/Tests.js", @@ -1076,6 +1141,30 @@ "$resources_out_dir/product_registry_impl/product_registry_impl_module.js", ] +generated_test_modules = [ + "$resources_out_dir/accessibility_test_runner/accessibility_test_runner_module.js", + "$resources_out_dir/application_test_runner/application_test_runner_module.js", + "$resources_out_dir/audits2_test_runner/audits2_test_runner_module.js", + "$resources_out_dir/bindings_test_runner/bindings_test_runner_module.js", + "$resources_out_dir/console_test_runner/console_test_runner_module.js", + "$resources_out_dir/coverage_test_runner/coverage_test_runner_module.js", + "$resources_out_dir/cpu_profiler_test_runner/cpu_profiler_test_runner_module.js", + "$resources_out_dir/data_grid_test_runner/data_grid_test_runner_module.js", + "$resources_out_dir/device_mode_test_runner/device_mode_test_runner_module.js", + "$resources_out_dir/elements_test_runner/elements_test_runner_module.js", + "$resources_out_dir/extensions_test_runner/extensions_test_runner_module.js", + "$resources_out_dir/heap_profiler_test_runner/heap_profiler_test_runner_module.js", + "$resources_out_dir/heap_snapshot_worker/heap_snapshot_worker_module.js", + "$resources_out_dir/integration_test_runner.html", + "$resources_out_dir/integration_test_runner.js", + "$resources_out_dir/layers_test_runner/layers_test_runner_module.js", + "$resources_out_dir/network_test_runner/network_test_runner_module.js", + "$resources_out_dir/performance_test_runner/performance_test_runner_module.js", + "$resources_out_dir/sdk_test_runner/sdk_test_runner_module.js", + "$resources_out_dir/security_test_runner/security_test_runner_module.js", + "$resources_out_dir/sources_test_runner/sources_test_runner_module.js", +] + devtools_applications = [ "audits2_worker", "devtools_app", @@ -1124,6 +1213,7 @@ outputs = [ "$resources_out_dir/{{source_file_part}}", ] + data = process_file_template(sources, outputs) } copy("copy_htaccess") { @@ -1133,6 +1223,7 @@ outputs = [ "$resources_out_dir/.htaccess", ] + data = outputs } copy("copy_inspector_images") { @@ -1140,6 +1231,7 @@ outputs = [ "$resources_out_dir/Images/{{source_file_part}}", ] + data = process_file_template(sources, outputs) } copy("copy_emulated_devices_images") { @@ -1147,6 +1239,7 @@ outputs = [ "$resources_out_dir/emulated_devices/{{source_file_part}}", ] + data = process_file_template(sources, outputs) } action("generate_devtools_grd") { @@ -1195,6 +1288,7 @@ outputs = [ "$resources_out_dir/devtools_extension_api.js", ] + data = outputs args = rebase_path(outputs, root_build_dir) + rebase_path(devtools_extension_api_files, root_build_dir) @@ -1210,6 +1304,7 @@ outputs = [ "$resources_out_dir/SupportedCSSProperties.js", ] + data = outputs args = rebase_path(inputs, root_build_dir) + rebase_path(outputs, root_build_dir) @@ -1225,6 +1320,7 @@ outputs = [ "$resources_out_dir/accessibility/ARIAProperties.js", ] + data = outputs args = rebase_path(inputs, root_build_dir) + rebase_path(outputs, root_build_dir) @@ -1241,6 +1337,7 @@ outputs = [ "$resources_out_dir/InspectorBackendCommands.js", ] + data = outputs args = rebase_path(inputs, root_build_dir) + [ "--output_js_dir", @@ -1262,11 +1359,12 @@ "scripts/build/rjsmin.py", ] - inputs = helper_scripts + all_devtools_files + generated_scripts + - generated_aria_properties + application_templates + inputs = helper_scripts + all_devtools_files + devtools_test_files + + generated_scripts + generated_aria_properties + application_templates outputs = generated_applications + generated_non_autostart_non_remote_modules + - generated_remote_modules + generated_remote_modules + generated_test_modules + data = outputs args = devtools_applications + [ "--input_path", @@ -1297,6 +1395,7 @@ "$resources_out_debug_dir/toolbox.html", "$resources_out_debug_dir/worker_app.html", ] + data = outputs args = devtools_applications + [ "--input_path", @@ -1315,6 +1414,7 @@ outputs = [ "$resources_out_debug_dir/{{source_file_part}}", ] + data = process_file_template(sources, outputs) } copy("copy_aria_properties") { @@ -1328,6 +1428,7 @@ outputs = [ "$resources_out_debug_dir/accessibility/{{source_file_part}}", ] + data = process_file_template(sources, outputs) } }
diff --git a/third_party/blink/renderer/devtools/front_end/browser_sdk/LogManager.js b/third_party/blink/renderer/devtools/front_end/browser_sdk/LogManager.js index 8fa6c8b..faf4032 100644 --- a/third_party/blink/renderer/devtools/front_end/browser_sdk/LogManager.js +++ b/third_party/blink/renderer/devtools/front_end/browser_sdk/LogManager.js
@@ -42,7 +42,22 @@ if (data.entry.networkRequestId) SDK.networkLog.associateConsoleMessageWithRequest(consoleMessage, data.entry.networkRequestId); - SDK.consoleModel.addMessage(consoleMessage); + + if (consoleMessage.source === SDK.ConsoleMessage.MessageSource.Worker) { + const workerId = consoleMessage.workerId || ''; + // We have a copy of worker messages reported through the page, so that + // user can see messages from the worker which has been already destroyed. + // When opening DevTools, give us some time to connect to the worker and + // not report the message twice if the worker is still alive. + if (SDK.targetManager.targetById(workerId)) + return; + setTimeout(() => { + if (!SDK.targetManager.targetById(workerId)) + SDK.consoleModel.addMessage(consoleMessage); + }, 1000); + } else { + SDK.consoleModel.addMessage(consoleMessage); + } } };
diff --git a/third_party/blink/renderer/devtools/front_end/devtools_compatibility.js b/third_party/blink/renderer/devtools/front_end/devtools_compatibility.js index 1319616..788ebe82 100644 --- a/third_party/blink/renderer/devtools/front_end/devtools_compatibility.js +++ b/third_party/blink/renderer/devtools/front_end/devtools_compatibility.js
@@ -1172,6 +1172,52 @@ /** @type {!Array<string>} */ const styleRules = []; + // Shadow DOM V0 polyfill + if (majorVersion <= 73 && !Element.prototype.createShadowRoot) { + Element.prototype.createShadowRoot = function() { + try { + return this.attachShadow({mode: 'open'}); + } catch (e) { + // some elements we use to add shadow roots can no + // longer have shadow roots. + const fakeShadowHost = document.createElement('span'); + this.appendChild(fakeShadowHost); + fakeShadowHost.className = 'fake-shadow-host'; + return fakeShadowHost.createShadowRoot(); + } + }; + + const origAdd = DOMTokenList.prototype.add; + DOMTokenList.prototype.add = function(...tokens) { + if (tokens[0].startsWith('insertion-point') || tokens[0].startsWith('tabbed-pane-header')) + this._myElement.slot = '.' + tokens[0]; + return origAdd.apply(this, tokens); + }; + + const origCreateElement = Document.prototype.createElement; + Document.prototype.createElement = function(tagName, ...rest) { + if (tagName === 'content') + tagName = 'slot'; + const element = origCreateElement.call(this, tagName, ...rest); + element.classList._myElement = element; + return element; + }; + + Object.defineProperty(HTMLSlotElement.prototype, 'select', { + async set(selector) { + this.name = selector; + } + }); + const origCreateElementWithClass = Document.prototype.createElementWithClass; + Document.prototype.createElementWithClass = function(tagName, className, ...rest) { + if (tagName !== 'button' || (className !== 'soft-dropdown' && className !== 'dropdown-button')) + return origCreateElementWithClass.call(this, tagName, className, ...rest); + const element = origCreateElementWithClass.call(this, 'div', className, ...rest); + element.tabIndex = 0; + element.role = 'button'; + return element; + }; + } if (majorVersion <= 66) { /** @type {(!function(number, number):Element|undefined)} */
diff --git a/third_party/blink/renderer/devtools/front_end/main/Main.js b/third_party/blink/renderer/devtools/front_end/main/Main.js index ac199417..655128e 100644 --- a/third_party/blink/renderer/devtools/front_end/main/Main.js +++ b/third_party/blink/renderer/devtools/front_end/main/Main.js
@@ -152,7 +152,7 @@ Runtime.experiments.setDefaultExperiments([ 'colorContrastRatio', 'stepIntoAsync', 'oopifInlineDOM', 'consoleBelowPrompt', 'timelineTracingJSProfile', - 'pinnedExpressions' + 'pinnedExpressions', 'consoleKeyboardNavigation' ]); }
diff --git a/third_party/blink/renderer/devtools/front_end/performance_test_runner/TimelineTestRunner.js b/third_party/blink/renderer/devtools/front_end/performance_test_runner/TimelineTestRunner.js index c6efc2d..34dd193 100644 --- a/third_party/blink/renderer/devtools/front_end/performance_test_runner/TimelineTestRunner.js +++ b/third_party/blink/renderer/devtools/front_end/performance_test_runner/TimelineTestRunner.js
@@ -82,8 +82,8 @@ }; PerformanceTestRunner.invokeWithTracing = function(functionName, callback, additionalCategories, enableJSSampling) { - let categories = - '-*,disabled-by-default-devtools.timeline*,devtools.timeline,' + SDK.TracingModel.TopLevelEventCategory; + let categories = '-*,disabled-by-default-devtools.timeline*,devtools.timeline,blink.user_timing,' + + SDK.TracingModel.TopLevelEventCategory; if (additionalCategories) categories += ',' + additionalCategories;
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/ProfilesPanel.js b/third_party/blink/renderer/devtools/front_end/profiler/ProfilesPanel.js index eb7ffe8..d3383a05 100644 --- a/third_party/blink/renderer/devtools/front_end/profiler/ProfilesPanel.js +++ b/third_party/blink/renderer/devtools/front_end/profiler/ProfilesPanel.js
@@ -98,6 +98,8 @@ this.contentElement.addEventListener('keydown', this._onKeyDown.bind(this), false); SDK.targetManager.addEventListener(SDK.TargetManager.Events.SuspendStateChanged, this._onSuspendStateChanged, this); + UI.context.addFlavorChangeListener(SDK.CPUProfilerModel, this._updateProfileTypeSpecificUI, this); + UI.context.addFlavorChangeListener(SDK.HeapProfilerModel, this._updateProfileTypeSpecificUI, this); } /** @@ -189,7 +191,8 @@ * @param {boolean} toggled */ _updateToggleRecordAction(toggled) { - const enable = toggled || !SDK.targetManager.allTargetsSuspended(); + const hasSelectedTarget = !!(UI.context.flavor(SDK.CPUProfilerModel) || UI.context.flavor(SDK.HeapProfilerModel)); + const enable = toggled || (!SDK.targetManager.allTargetsSuspended() && hasSelectedTarget); this._toggleRecordAction.setEnabled(enable); this._toggleRecordAction.setToggled(toggled); if (enable)
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/ConsoleModel.js b/third_party/blink/renderer/devtools/front_end/sdk/ConsoleModel.js index edddf469..90c3892 100644 --- a/third_party/blink/renderer/devtools/front_end/sdk/ConsoleModel.js +++ b/third_party/blink/renderer/devtools/front_end/sdk/ConsoleModel.js
@@ -159,9 +159,6 @@ * @param {!SDK.ConsoleMessage} msg */ addMessage(msg) { - if (msg.source === SDK.ConsoleMessage.MessageSource.Worker && SDK.targetManager.targetById(msg.workerId)) - return; - msg._pageLoadSequenceNumber = this._pageLoadSequenceNumber; if (msg.source === SDK.ConsoleMessage.MessageSource.ConsoleAPI && msg.type === SDK.ConsoleMessage.MessageType.Clear) this._clearIfNecessary();
diff --git a/third_party/blink/renderer/devtools/front_end/sources/BreakpointEditDialog.js b/third_party/blink/renderer/devtools/front_end/sources/BreakpointEditDialog.js index 101eb22..c98cc69 100644 --- a/third_party/blink/renderer/devtools/front_end/sources/BreakpointEditDialog.js +++ b/third_party/blink/renderer/devtools/front_end/sources/BreakpointEditDialog.js
@@ -18,6 +18,7 @@ this._finished = false; /** @type {?UI.TextEditor} */ this._editor = null; + const isNewBreakpointsEnabled = Runtime.experiments.isEnabled('sourcesLogpoints'); const logpointPrefix = Sources.BreakpointEditDialog._LogpointPrefix; const logpointSuffix = Sources.BreakpointEditDialog._LogpointSuffix; @@ -26,25 +27,46 @@ oldCondition = oldCondition.substring(logpointPrefix.length, oldCondition.length - logpointSuffix.length); this._isLogpoint = this._isLogpoint || preferLogpoint; - const labelElement = this.contentElement.createChild('label', 'source-frame-breakpoint-message'); - labelElement.htmlFor = 'source-frame-breakpoint-condition'; - const labelText = this._isLogpoint ? ls`On line ${editorLineNumber + 1}, log to the Console:` : ls - `The breakpoint on line ${editorLineNumber + 1} will stop only if this expression is true:`; - labelElement.createTextChild(labelText); + if (isNewBreakpointsEnabled) { + this.element.classList.add('sources-edit-breakpoint-dialog'); + const toolbar = new UI.Toolbar('source-frame-breakpoint-toolbar', this.contentElement); + toolbar.appendText(`Line ${editorLineNumber + 1}:`); + + this._typeSelector = new UI.ToolbarComboBox(this._onTypeChanged.bind(this)); + this._typeSelector.createOption(ls`Breakpoint`, '', Sources.BreakpointEditDialog.BreakpointType.Breakpoint); + const conditionalOption = this._typeSelector.createOption( + ls`Conditional breakpoint`, '', Sources.BreakpointEditDialog.BreakpointType.Conditional); + const logpointOption = + this._typeSelector.createOption(ls`Logpoint`, '', Sources.BreakpointEditDialog.BreakpointType.Logpoint); + this._typeSelector.select(this._isLogpoint ? logpointOption : conditionalOption); + toolbar.appendToolbarItem(this._typeSelector); + + } else { + const labelElement = this.contentElement.createChild('label', 'source-frame-breakpoint-message'); + labelElement.htmlFor = 'source-frame-breakpoint-condition'; + const labelText = this._isLogpoint ? ls`On line ${editorLineNumber + 1}, log to the Console:` : ls + `The breakpoint on line ${editorLineNumber + 1} will stop only if this expression is true:`; + labelElement.createTextChild(labelText); + } self.runtime.extension(UI.TextEditorFactory).instance().then(factory => { - this._editor = - factory.createEditor({lineNumbers: false, lineWrapping: true, mimeType: 'javascript', autoHeight: true}); + const editorOptions = {lineNumbers: false, lineWrapping: true, mimeType: 'javascript', autoHeight: true}; + this._editor = factory.createEditor(editorOptions); + if (isNewBreakpointsEnabled) { + this._updatePlaceholder(); + this._editor.widget().element.classList.add('condition-editor'); + } else { + this._editor.widget().element.id = 'source-frame-breakpoint-condition'; + } this._editor.configureAutocomplete(ObjectUI.JavaScriptAutocompleteConfig.createConfigForEditor(this._editor)); if (oldCondition) this._editor.setText(oldCondition); this._editor.widget().show(this.contentElement); - this._editor.widget().element.id = 'source-frame-breakpoint-condition'; this._editor.setSelection(this._editor.fullRange()); this._editor.widget().focus(); this._editor.widget().element.addEventListener('keydown', this._onKeyDown.bind(this), true); - this._editor.widget().element.addEventListener('blur', event => { - if (event.relatedTarget && !event.relatedTarget.isSelfOrDescendant(this._editor.widget().element)) + this.contentElement.addEventListener('blur', event => { + if (event.relatedTarget && !event.relatedTarget.isSelfOrDescendant(this.element)) this._finishEditing(true); }, true); }); @@ -58,6 +80,27 @@ return `${Sources.BreakpointEditDialog._LogpointPrefix}${condition}${Sources.BreakpointEditDialog._LogpointSuffix}`; } + _onTypeChanged() { + const value = this._typeSelector.selectedOption().value; + this._isLogpoint = value === Sources.BreakpointEditDialog.BreakpointType.Logpoint; + this._updatePlaceholder(); + if (value === Sources.BreakpointEditDialog.BreakpointType.Breakpoint) { + this._editor.setText(''); + this._finishEditing(true); + } + } + + _updatePlaceholder() { + const selectedValue = this._typeSelector.selectedOption().value; + if (selectedValue === Sources.BreakpointEditDialog.BreakpointType.Conditional) { + this._editor.setPlaceholder(ls`Expression to check before pausing, e.g. x > 5`); + this._typeSelector.element.title = ls`Pause only when the condition is true`; + } else if (selectedValue === Sources.BreakpointEditDialog.BreakpointType.Logpoint) { + this._editor.setPlaceholder(ls`Log message, e.g. 'x is', x`); + this._typeSelector.element.title = ls`Log a message to Console, do not break`; + } + } + /** * @param {boolean} committed */ @@ -91,3 +134,9 @@ Sources.BreakpointEditDialog._LogpointPrefix = '/** DEVTOOLS_LOGPOINT */ console.log('; Sources.BreakpointEditDialog._LogpointSuffix = ')'; + +Sources.BreakpointEditDialog.BreakpointType = { + Breakpoint: 'Breakpoint', + Conditional: 'Conditional', + Logpoint: 'Logpoint', +};
diff --git a/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js b/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js index 40ad095..a28b947 100644 --- a/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js +++ b/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js
@@ -767,7 +767,7 @@ _appendUISourceCodeFrameItems(event, contextMenu, target) { if (!(target instanceof Sources.UISourceCodeFrame)) return; - if (target.uiSourceCode().contentType().isFromSourceMap()) + if (target.uiSourceCode().contentType().isFromSourceMap() || target.textEditor.selection().isEmpty()) return; contextMenu.debugSection().appendAction('debugger.evaluate-selection'); }
diff --git a/third_party/blink/renderer/devtools/front_end/sources/breakpointEditDialog.css b/third_party/blink/renderer/devtools/front_end/sources/breakpointEditDialog.css index 4555060..e2ec0db 100644 --- a/third_party/blink/renderer/devtools/front_end/sources/breakpointEditDialog.css +++ b/third_party/blink/renderer/devtools/front_end/sources/breakpointEditDialog.css
@@ -32,3 +32,31 @@ outline: none !important; background: white; } + +:host(.sources-edit-breakpoint-dialog) { + border: none; + border-radius: 0; + z-index: 30; + background-color: var(--toolbar-bg-color); + width: 100%; + max-width: 600px; + pointer-events: auto; + margin-bottom: 5px; + padding: 0 10px 10px 5px; + border-left: 3px solid var(--divider-color); +} + +:host-context(.sources-edit-breakpoint-dialog) .condition-editor { + background-color: #fff; + margin-left: 3px; +} + +:host-context(.sources-edit-breakpoint-dialog) .source-frame-breakpoint-toolbar { + font-family: sans-serif; + font-size: 12px; +} + +:host-context(.sources-edit-breakpoint-dialog) .source-frame-breakpoint-editor:hover, +:host-context(.sources-edit-breakpoint-dialog) .source-frame-breakpoint-editor:focus-within { + box-shadow: var(--focus-ring-inactive-shadow); +}
diff --git a/third_party/blink/renderer/devtools/front_end/sources/module.json b/third_party/blink/renderer/devtools/front_end/sources/module.json index aa91d7d..79fa5e19 100644 --- a/third_party/blink/renderer/devtools/front_end/sources/module.json +++ b/third_party/blink/renderer/devtools/front_end/sources/module.json
@@ -222,7 +222,7 @@ "type": "action", "actionId": "debugger.evaluate-selection", "className": "Sources.SourcesPanel.DebuggingActionDelegate", - "title": "Evaluate in console", + "title": "Evaluate selected text in console", "contextTypes": [ "Sources.UISourceCodeFrame" ],
diff --git a/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js b/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js index 65317dd..64670ab 100644 --- a/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js +++ b/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js
@@ -374,6 +374,19 @@ } /** + * @override + * @param {string} placeholder + */ + setPlaceholder(placeholder) { + if (!this._placeholderElement) { + this._placeholderElement = createElement('pre'); + this._placeholderElement.classList.add('placeholder-text'); + } + this._placeholderElement.textContent = placeholder || ''; + this._updatePlaceholder(); + } + + /** * @param {number} lineNumber * @param {number} lineLength * @param {number} charNumber
diff --git a/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js b/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js index a06fa96..2c2597bd 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js +++ b/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js
@@ -90,7 +90,12 @@ * @param {number} columnNumber * @return {?{startColumn: number, endColumn: number, type: string}} */ - tokenAtTextPosition(lineNumber, columnNumber) {} + tokenAtTextPosition(lineNumber, columnNumber) {}, + + /** + * @param {string} placeholder + */ + setPlaceholder(placeholder) {} }; /** @enum {symbol} */
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc index 6e567d1..af2e0d3ae 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -1422,11 +1422,8 @@ if (GetNode() && GetNode()->IsElementNode() && ToElement(GetNode())->IsFormControlElement()) { HTMLFormControlElement* element = ToHTMLFormControlElement(GetNode()); - ListedElement::List invalid_controls; - bool is_invalid = !element->checkValidity(&invalid_controls, - kCheckValidityDispatchNoEvent); - return is_invalid ? ax::mojom::InvalidState::kTrue - : ax::mojom::InvalidState::kFalse; + return element->IsNotCandidateOrValid() ? ax::mojom::InvalidState::kFalse + : ax::mojom::InvalidState::kTrue; } return AXObject::GetInvalidState();
diff --git a/third_party/blink/renderer/modules/battery/navigator_battery.idl b/third_party/blink/renderer/modules/battery/navigator_battery.idl index 579ee18..ce0f399 100644 --- a/third_party/blink/renderer/modules/battery/navigator_battery.idl +++ b/third_party/blink/renderer/modules/battery/navigator_battery.idl
@@ -6,5 +6,5 @@ [ ImplementedAs=NavigatorBattery ] partial interface Navigator { - [CallWith=ScriptState, MeasureAs=BatteryStatusGetBattery] Promise getBattery(); + [CallWith=ScriptState, MeasureAs=BatteryStatusGetBattery] Promise<BatteryManager> getBattery(); };
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.h b/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.h index 2159e69..7a3d3da 100644 --- a/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.h +++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.h
@@ -51,4 +51,4 @@ } // namespace blink -#endif // GamepadButton_h +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_CHARACTERISTIC_PROPERTIES_H_
diff --git a/third_party/blink/renderer/modules/cache_storage/OWNERS b/third_party/blink/renderer/modules/cache_storage/OWNERS index 9ba85db..6df3d341 100644 --- a/third_party/blink/renderer/modules/cache_storage/OWNERS +++ b/third_party/blink/renderer/modules/cache_storage/OWNERS
@@ -1,6 +1,5 @@ kinuko@chromium.org jsbell@chromium.org -dominicc@chromium.org falken@chromium.org horo@chromium.org nhiroki@chromium.org
diff --git a/third_party/blink/renderer/modules/credentialmanager/credentials_container.idl b/third_party/blink/renderer/modules/credentialmanager/credentials_container.idl index 075f8ee3..1ff690c2 100644 --- a/third_party/blink/renderer/modules/credentialmanager/credentials_container.idl +++ b/third_party/blink/renderer/modules/credentialmanager/credentials_container.idl
@@ -6,8 +6,8 @@ [Exposed=Window, SecureContext] interface CredentialsContainer { - [CallWith=ScriptState, MeasureAs=CredentialManagerGet] Promise get(optional CredentialRequestOptions options); - [CallWith=ScriptState, MeasureAs=CredentialManagerStore] Promise store(Credential credential); - [CallWith=ScriptState, RaisesException, MeasureAs=CredentialManagerCreate] Promise create(optional CredentialCreationOptions options); - [CallWith=ScriptState, MeasureAs=CredentialManagerPreventSilentAccess] Promise preventSilentAccess(); + [CallWith=ScriptState, MeasureAs=CredentialManagerGet] Promise<Credential?> get(optional CredentialRequestOptions options); + [CallWith=ScriptState, MeasureAs=CredentialManagerStore] Promise<Credential> store(Credential credential); + [CallWith=ScriptState, RaisesException, MeasureAs=CredentialManagerCreate] Promise<Credential?> create(optional CredentialCreationOptions options); + [CallWith=ScriptState, MeasureAs=CredentialManagerPreventSilentAccess] Promise<void> preventSilentAccess(); };
diff --git a/third_party/blink/renderer/modules/credentialmanager/public_key_credential.idl b/third_party/blink/renderer/modules/credentialmanager/public_key_credential.idl index cb5b091..76bcc33 100644 --- a/third_party/blink/renderer/modules/credentialmanager/public_key_credential.idl +++ b/third_party/blink/renderer/modules/credentialmanager/public_key_credential.idl
@@ -11,6 +11,6 @@ ] interface PublicKeyCredential : Credential { [SameObject] readonly attribute ArrayBuffer rawId; [SameObject] readonly attribute AuthenticatorResponse response; - [CallWith=ScriptState] static Promise <boolean> isUserVerifyingPlatformAuthenticatorAvailable(); + [CallWith=ScriptState] static Promise<boolean> isUserVerifyingPlatformAuthenticatorAvailable(); AuthenticationExtensionsClientOutputs getClientExtensionResults(); };
diff --git a/third_party/blink/renderer/modules/crypto/subtle_crypto.idl b/third_party/blink/renderer/modules/crypto/subtle_crypto.idl index c5c75b01..e7287cb 100644 --- a/third_party/blink/renderer/modules/crypto/subtle_crypto.idl +++ b/third_party/blink/renderer/modules/crypto/subtle_crypto.idl
@@ -37,16 +37,19 @@ [ Exposed=(Window,Worker) ] interface SubtleCrypto { - [CallWith=ScriptState, MeasureAs=SubtleCryptoEncrypt] Promise encrypt(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource data); - [CallWith=ScriptState, MeasureAs=SubtleCryptoDecrypt] Promise decrypt(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource data); - [CallWith=ScriptState, MeasureAs=SubtleCryptoSign] Promise sign(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource data); - [CallWith=ScriptState, ImplementedAs=verifySignature, MeasureAs=SubtleCryptoVerify] Promise verify(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource signature, BufferSource data); - [CallWith=ScriptState, MeasureAs=SubtleCryptoDigest] Promise digest(AlgorithmIdentifier algorithm, BufferSource data); - [CallWith=ScriptState, MeasureAs=SubtleCryptoGenerateKey] Promise generateKey(AlgorithmIdentifier algorithm, boolean extractable, sequence<KeyUsage> keyUsages); - [CallWith=ScriptState, MeasureAs=SubtleCryptoImportKey] Promise importKey(KeyFormat format, (ArrayBuffer or ArrayBufferView or Dictionary) keyData, AlgorithmIdentifier algorithm, boolean extractable, sequence<KeyUsage> keyUsages); - [CallWith=ScriptState, MeasureAs=SubtleCryptoExportKey] Promise exportKey(KeyFormat format, CryptoKey key); - [CallWith=ScriptState, MeasureAs=SubtleCryptoDeriveBits] Promise deriveBits(AlgorithmIdentifier algorithm, CryptoKey baseKey, unsigned long length); - [CallWith=ScriptState, MeasureAs=SubtleCryptoDeriveKey] Promise deriveKey(AlgorithmIdentifier algorithm, CryptoKey baseKey, AlgorithmIdentifier derivedKeyType, boolean extractable, sequence<KeyUsage> keyUsages); - [CallWith=ScriptState, MeasureAs=SubtleCryptoWrapKey] Promise wrapKey(KeyFormat format, CryptoKey key, CryptoKey wrappingKey, AlgorithmIdentifier wrapAlgorithm); - [CallWith=ScriptState, MeasureAs=SubtleCryptoUnwrapKey] Promise unwrapKey(KeyFormat format, BufferSource wrappedKey, CryptoKey unwrappingKey, AlgorithmIdentifier unwrapAlgorithm, AlgorithmIdentifier unwrappedKeyAlgorithm, boolean extractable, sequence<KeyUsage> keyUsages); + [CallWith=ScriptState, MeasureAs=SubtleCryptoEncrypt] Promise<any> encrypt(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource data); + [CallWith=ScriptState, MeasureAs=SubtleCryptoDecrypt] Promise<any> decrypt(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource data); + [CallWith=ScriptState, MeasureAs=SubtleCryptoSign] Promise<any> sign(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource data); + [CallWith=ScriptState, ImplementedAs=verifySignature, MeasureAs=SubtleCryptoVerify] Promise<any> verify(AlgorithmIdentifier algorithm, CryptoKey key, BufferSource signature, BufferSource data); + [CallWith=ScriptState, MeasureAs=SubtleCryptoDigest] Promise<any> digest(AlgorithmIdentifier algorithm, BufferSource data); + + [CallWith=ScriptState, MeasureAs=SubtleCryptoGenerateKey] Promise<any> generateKey(AlgorithmIdentifier algorithm, boolean extractable, sequence<KeyUsage> keyUsages); + [CallWith=ScriptState, MeasureAs=SubtleCryptoDeriveKey] Promise<any> deriveKey(AlgorithmIdentifier algorithm, CryptoKey baseKey, AlgorithmIdentifier derivedKeyType, boolean extractable, sequence<KeyUsage> keyUsages); + [CallWith=ScriptState, MeasureAs=SubtleCryptoDeriveBits] Promise<ArrayBuffer> deriveBits(AlgorithmIdentifier algorithm, CryptoKey baseKey, unsigned long length); + + [CallWith=ScriptState, MeasureAs=SubtleCryptoImportKey] Promise<CryptoKey> importKey(KeyFormat format, (ArrayBuffer or ArrayBufferView or Dictionary) keyData, AlgorithmIdentifier algorithm, boolean extractable, sequence<KeyUsage> keyUsages); + [CallWith=ScriptState, MeasureAs=SubtleCryptoExportKey] Promise<any> exportKey(KeyFormat format, CryptoKey key); + + [CallWith=ScriptState, MeasureAs=SubtleCryptoWrapKey] Promise<any> wrapKey(KeyFormat format, CryptoKey key, CryptoKey wrappingKey, AlgorithmIdentifier wrapAlgorithm); + [CallWith=ScriptState, MeasureAs=SubtleCryptoUnwrapKey] Promise<CryptoKey> unwrapKey(KeyFormat format, BufferSource wrappedKey, CryptoKey unwrappingKey, AlgorithmIdentifier unwrapAlgorithm, AlgorithmIdentifier unwrappedKeyAlgorithm, boolean extractable, sequence<KeyUsage> keyUsages); };
diff --git a/third_party/blink/renderer/modules/encoding/text_decoder_stream.idl b/third_party/blink/renderer/modules/encoding/text_decoder_stream.idl index 9fe58423..286489d 100644 --- a/third_party/blink/renderer/modules/encoding/text_decoder_stream.idl +++ b/third_party/blink/renderer/modules/encoding/text_decoder_stream.idl
@@ -8,8 +8,7 @@ Constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options), ConstructorCallWith=ScriptState, RaisesException=Constructor, - MeasureAs=TextDecoderStreamConstructor, - RuntimeEnabled=EncodingStreams + MeasureAs=TextDecoderStreamConstructor ] interface TextDecoderStream { readonly attribute DOMString encoding; readonly attribute boolean fatal;
diff --git a/third_party/blink/renderer/modules/encoding/text_encoder_stream.idl b/third_party/blink/renderer/modules/encoding/text_encoder_stream.idl index 73f60a8..b28dd76 100644 --- a/third_party/blink/renderer/modules/encoding/text_encoder_stream.idl +++ b/third_party/blink/renderer/modules/encoding/text_encoder_stream.idl
@@ -8,8 +8,7 @@ Constructor(), ConstructorCallWith=ScriptState, RaisesException=Constructor, - MeasureAs=TextEncoderStreamConstructor, - RuntimeEnabled=EncodingStreams + MeasureAs=TextEncoderStreamConstructor ] interface TextEncoderStream { readonly attribute DOMString encoding; readonly attribute ReadableStream readable;
diff --git a/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.idl b/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.idl index c8e54ea9..8c1a025 100644 --- a/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.idl +++ b/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.idl
@@ -1,11 +1,13 @@ // Copyright 2014 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. + +// https://w3c.github.io/encrypted-media/#htmlmediaelement-extensions [ ImplementedAs=HTMLMediaElementEncryptedMedia ] partial interface HTMLMediaElement { [SecureContext] readonly attribute MediaKeys mediaKeys; - [SecureContext, CallWith=ScriptState] Promise setMediaKeys(MediaKeys? mediaKeys); + [SecureContext, CallWith=ScriptState] Promise<void> setMediaKeys(MediaKeys? mediaKeys); attribute EventHandler onencrypted; attribute EventHandler onwaitingforkey; };
diff --git a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc index dd1ca87..6047bd6b 100644 --- a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc +++ b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
@@ -326,8 +326,7 @@ worker_start_data_.script_url, mojom::RequestContextType::SERVICE_WORKER, network::mojom::FetchRequestMode::kSameOrigin, network::mojom::FetchCredentialsMode::kSameOrigin, - worker_start_data_.address_space, false /* is_nested_worker */, - base::OnceClosure(), + worker_start_data_.address_space, base::OnceClosure(), Bind(&WebEmbeddedWorkerImpl::OnScriptLoaderFinished, WTF::Unretained(this))); // Do nothing here since OnScriptLoaderFinished() might have been already
diff --git a/third_party/blink/renderer/modules/filesystem/file_system_directory_iterator.idl b/third_party/blink/renderer/modules/filesystem/file_system_directory_iterator.idl index bb376bb..85c7bfd 100644 --- a/third_party/blink/renderer/modules/filesystem/file_system_directory_iterator.idl +++ b/third_party/blink/renderer/modules/filesystem/file_system_directory_iterator.idl
@@ -9,6 +9,6 @@ NoInterfaceObject, RuntimeEnabled=WritableFiles ] interface FileSystemDirectoryIterator { - [CallWith=ScriptState] Promise next(); + [CallWith=ScriptState] Promise<any> next(); [ImplementedAs=IteratorReturn] void return(); };
diff --git a/third_party/blink/renderer/modules/indexeddb/BUILD.gn b/third_party/blink/renderer/modules/indexeddb/BUILD.gn index 4e3f0311..11973200 100644 --- a/third_party/blink/renderer/modules/indexeddb/BUILD.gn +++ b/third_party/blink/renderer/modules/indexeddb/BUILD.gn
@@ -88,11 +88,7 @@ "web_idb_factory.h", "web_idb_factory_impl.cc", "web_idb_factory_impl.h", - "web_idb_key.cc", - "web_idb_key.h", "web_idb_key_path.h", - "web_idb_key_range.cc", - "web_idb_key_range.h", "web_idb_name_and_version.h", "web_idb_observation.h", "web_idb_value.cc",
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc b/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc index 8c9da201..9d68a61 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc
@@ -37,7 +37,6 @@ #include "third_party/blink/renderer/modules/indexeddb/idb_tracing.h" #include "third_party/blink/renderer/modules/indexeddb/idb_transaction.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key_range.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/bindings/v8_private_property.h" @@ -281,7 +280,10 @@ const IDBKey* current_primary_key = IdbPrimaryKey(); - if (key) { + if (!key) + key = IDBKey::CreateNull(); + + if (key->GetType() != mojom::IDBKeyType::Null) { DCHECK(key_); if (direction_ == mojom::IDBCursorDirection::Next || direction_ == mojom::IDBCursorDirection::NextNoDuplicate) { @@ -308,14 +310,16 @@ } } + if (!primary_key) + primary_key = IDBKey::CreateNull(); + // FIXME: We're not using the context from when continue was called, which // means the callback will be on the original context openCursor was called // on. Is this right? request_->SetPendingCursor(this); request_->AssignNewMetrics(std::move(metrics)); got_value_ = false; - backend_->CursorContinue(WebIDBKeyView(key.get()), - WebIDBKeyView(primary_key.get()), + backend_->CursorContinue(key.get(), primary_key.get(), request_->CreateWebCallbacks().release()); } @@ -359,8 +363,8 @@ IDBRequest* request = IDBRequest::Create( script_state, this, transaction_.Get(), std::move(metrics)); transaction_->BackendDB()->Delete( - transaction_->Id(), EffectiveObjectStore()->Id(), - WebIDBKeyView(IdbPrimaryKey()), request->CreateWebCallbacks().release()); + transaction_->Id(), EffectiveObjectStore()->Id(), IdbPrimaryKey(), + request->CreateWebCallbacks().release()); return request; }
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_factory.cc b/third_party/blink/renderer/modules/indexeddb/idb_factory.cc index 6a48a4c..3c573a4 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_factory.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
@@ -128,8 +128,8 @@ void OnSuccess(const WebVector<WebString>&) override { NOTREACHED(); } void OnSuccess(WebIDBCursor* cursor, - WebIDBKey key, - WebIDBKey primary_key, + std::unique_ptr<IDBKey> key, + std::unique_ptr<IDBKey> primary_key, WebIDBValue value) override { NOTREACHED(); } @@ -139,7 +139,7 @@ NOTREACHED(); } - void OnSuccess(WebIDBKey key) override { NOTREACHED(); } + void OnSuccess(std::unique_ptr<IDBKey> key) override { NOTREACHED(); } void OnSuccess(WebIDBValue value) override { NOTREACHED(); } @@ -149,8 +149,8 @@ void OnSuccess() override { NOTREACHED(); } - void OnSuccess(WebIDBKey key, - WebIDBKey primary_key, + void OnSuccess(std::unique_ptr<IDBKey> key, + std::unique_ptr<IDBKey> primary_key, WebIDBValue value) override { NOTREACHED(); }
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_index.cc b/third_party/blink/renderer/modules/indexeddb/idb_index.cc index 9b972998..d4076ea 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_index.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_index.cc
@@ -36,7 +36,6 @@ #include "third_party/blink/renderer/modules/indexeddb/idb_object_store.h" #include "third_party/blink/renderer/modules/indexeddb/idb_tracing.h" #include "third_party/blink/renderer/modules/indexeddb/idb_transaction.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key_range.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" using blink::WebIDBCallbacks;
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_key.cc b/third_party/blink/renderer/modules/indexeddb/idb_key.cc index a2353210..7ea4e82 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_key.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_key.cc
@@ -29,13 +29,15 @@ #include <memory> #include "third_party/blink/public/common/indexeddb/web_idb_types.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key.h" #include "third_party/blink/renderer/platform/wtf/assertions.h" namespace blink { namespace { +// Very rough estimate of minimum key size overhead. +const size_t kIDBKeyOverheadSize = 16; + size_t CalculateIDBKeyArraySize(const IDBKey::KeyArray& keys) { size_t size(0); for (const auto& key : keys) @@ -45,13 +47,57 @@ } // namespace +// static +std::unique_ptr<IDBKey> IDBKey::Clone(const IDBKey* rkey) { + if (!rkey) + return IDBKey::CreateNull(); + + switch (rkey->GetType()) { + case mojom::IDBKeyType::Invalid: + return IDBKey::CreateInvalid(); + case mojom::IDBKeyType::Null: + return IDBKey::CreateNull(); + case mojom::IDBKeyType::Array: { + IDBKey::KeyArray lkey_array; + const auto& rkey_array = rkey->Array(); + for (const auto& rkey_item : rkey_array) + lkey_array.push_back(IDBKey::Clone(rkey_item)); + return IDBKey::CreateArray(std::move(lkey_array)); + } + case mojom::IDBKeyType::Binary: + return IDBKey::CreateBinary(rkey->Binary()); + case mojom::IDBKeyType::String: + return IDBKey::CreateString(rkey->GetString()); + case mojom::IDBKeyType::Date: + return IDBKey::CreateDate(rkey->Date()); + case mojom::IDBKeyType::Number: + return IDBKey::CreateNumber(rkey->Number()); + + case mojom::IDBKeyType::Min: + break; // Not used, NOTREACHED. + } + NOTREACHED(); + return nullptr; +} + IDBKey::IDBKey() : type_(mojom::IDBKeyType::Invalid), size_estimate_(kIDBKeyOverheadSize) {} +// Must be Invalid or Null. +IDBKey::IDBKey(mojom::IDBKeyType type) + : type_(type), size_estimate_(kIDBKeyOverheadSize) { + DCHECK(type_ == mojom::IDBKeyType::Invalid || + type_ == mojom::IDBKeyType::Null); +} + +// Must be Number or Date. IDBKey::IDBKey(mojom::IDBKeyType type, double number) : type_(type), number_(number), - size_estimate_(kIDBKeyOverheadSize + sizeof(number_)) {} + size_estimate_(kIDBKeyOverheadSize + sizeof(number_)) { + DCHECK(type_ == mojom::IDBKeyType::Number || + type_ == mojom::IDBKeyType::Date); +} IDBKey::IDBKey(const String& value) : type_(mojom::IDBKeyType::String), @@ -145,11 +191,11 @@ } // static -WebVector<WebIDBKey> IDBKey::ToMultiEntryArray( +Vector<std::unique_ptr<IDBKey>> IDBKey::ToMultiEntryArray( std::unique_ptr<IDBKey> array_key) { DCHECK_EQ(array_key->type_, mojom::IDBKeyType::Array); - WebVector<WebIDBKey> result; - result.reserve(array_key->array_.size()); + Vector<std::unique_ptr<IDBKey>> result; + result.ReserveInitialCapacity(array_key->array_.size()); for (std::unique_ptr<IDBKey>& key : array_key->array_) { if (key->IsValid()) result.emplace_back(std::move(key)); @@ -158,10 +204,11 @@ // Remove duplicates using std::sort/std::unique rather than a hashtable to // avoid the complexity of implementing DefaultHash<IDBKey>. std::sort( - result.begin(), result.end(), [](const WebIDBKey& a, const WebIDBKey& b) { - return static_cast<IDBKey*>(a)->IsLessThan(static_cast<IDBKey*>(b)); + result.begin(), result.end(), + [](const std::unique_ptr<IDBKey>& a, const std::unique_ptr<IDBKey>& b) { + return (a)->IsLessThan(b.get()); }); - const auto end = std::unique(result.begin(), result.end()); + std::unique_ptr<IDBKey>* end = std::unique(result.begin(), result.end()); DCHECK_LE(static_cast<wtf_size_t>(end - result.begin()), result.size()); result.resize(end - result.begin());
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_key.h b/third_party/blink/renderer/modules/indexeddb/idb_key.h index b60ce04..3575caf7 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_key.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_key.h
@@ -32,8 +32,8 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/scoped_refptr.h" +#include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-shared.h" #include "third_party/blink/public/platform/web_vector.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/shared_buffer.h" #include "third_party/blink/renderer/platform/wtf/forward.h" @@ -57,6 +57,10 @@ return base::WrapUnique(new IDBKey()); } + static std::unique_ptr<IDBKey> CreateNull() { + return base::WrapUnique(new IDBKey(mojom::IDBKeyType::Null)); + } + static std::unique_ptr<IDBKey> CreateNumber(double number) { return base::WrapUnique(new IDBKey(mojom::IDBKeyType::Number, number)); } @@ -78,50 +82,13 @@ return base::WrapUnique(new IDBKey(std::move(array))); } - // TODO(cmp): This |Clone| function is necessary for WebIDBKey's ctor - // functions. It needs to be available in this header file so - // web_idb_key.cc can use it. When the IDB Blink variant typemap - // moves to the renderer/modules/indexeddb/ types and off of the - // WebIDB* types, this |Clone| function should be removed. static std::unique_ptr<IDBKey> Clone(const std::unique_ptr<IDBKey>& rkey_in) { - IDBKey* rkey = rkey_in.get(); - if (!rkey_in.get()) - return nullptr; - - switch (rkey->GetType()) { - case mojom::IDBKeyType::Invalid: - return IDBKey::CreateInvalid(); - case mojom::IDBKeyType::Array: { - IDBKey::KeyArray lkey_array; - const auto& rkey_array = rkey->Array(); - for (const auto& rkey_item : rkey_array) - lkey_array.push_back(IDBKey::Clone(rkey_item)); - return IDBKey::CreateArray(std::move(lkey_array)); - } - case mojom::IDBKeyType::Binary: - return IDBKey::CreateBinary(rkey->Binary()); - case mojom::IDBKeyType::String: - return IDBKey::CreateString(rkey->GetString()); - case mojom::IDBKeyType::Date: - return IDBKey::CreateDate(rkey->Date()); - case mojom::IDBKeyType::Number: - return IDBKey::CreateNumber(rkey->Number()); - - case mojom::IDBKeyType::Null: - case mojom::IDBKeyType::Min: - break; // Not used, NOTREACHED. - } - NOTREACHED(); - return nullptr; + return IDBKey::Clone(rkey_in.get()); } - ~IDBKey(); + static std::unique_ptr<IDBKey> Clone(const IDBKey* rkey); - // Very rough estimate of minimum key size overhead. - // - // TODO(cmp): When the reference to this in web_idb_key.cc goes away, move - // this variable back to idb_key.cc's anonymous namespace. - static const size_t kIDBKeyOverheadSize = 16; + ~IDBKey(); mojom::IDBKeyType GetType() const { return type_; } bool IsValid() const; @@ -165,13 +132,14 @@ // The return value will be pasesd to the backing store, which requires // Web types. Returning the correct types directly avoids copying later on // (wasted CPU cycles and code size). - static WebVector<WebIDBKey> ToMultiEntryArray( + static Vector<std::unique_ptr<IDBKey>> ToMultiEntryArray( std::unique_ptr<IDBKey> array_key); private: DISALLOW_COPY_AND_ASSIGN(IDBKey); IDBKey(); + IDBKey(mojom::IDBKeyType type); IDBKey(mojom::IDBKeyType type, double number); explicit IDBKey(const String& value); explicit IDBKey(scoped_refptr<SharedBuffer> value); @@ -189,6 +157,8 @@ size_t size_estimate_; }; +using IDBIndexKeys = std::pair<int64_t, Vector<std::unique_ptr<IDBKey>>>; + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_KEY_H_
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_key_range.cc b/third_party/blink/renderer/modules/indexeddb/idb_key_range.cc index f9af248..193c0cf 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_key_range.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_key_range.cc
@@ -40,13 +40,13 @@ if (value.IsUndefined() || value.IsNull()) return nullptr; - IDBKeyRange* const range = ScriptValue::To<IDBKeyRange*>( - context->GetIsolate(), value, exception_state); + IDBKeyRange* const range = + ScriptValue::To<IDBKeyRange*>(ToIsolate(context), value, exception_state); if (range) return range; std::unique_ptr<IDBKey> key = ScriptValue::To<std::unique_ptr<IDBKey>>( - context->GetIsolate(), value, exception_state); + ToIsolate(context), value, exception_state); if (exception_state.HadException()) return nullptr; if (!key || !key->IsValid()) { @@ -105,7 +105,8 @@ const ScriptValue& key_value, ExceptionState& exception_state) { std::unique_ptr<IDBKey> key = ScriptValue::To<std::unique_ptr<IDBKey>>( - script_state->GetIsolate(), key_value, exception_state); + ToIsolate(ExecutionContext::From(script_state)), key_value, + exception_state); if (exception_state.HadException()) return nullptr; if (!key || !key->IsValid()) { @@ -125,7 +126,7 @@ bool open, ExceptionState& exception_state) { std::unique_ptr<IDBKey> bound = ScriptValue::To<std::unique_ptr<IDBKey>>( - ExecutionContext::From(script_state)->GetIsolate(), bound_value, + ToIsolate(ExecutionContext::From(script_state)), bound_value, exception_state); if (exception_state.HadException()) return nullptr; @@ -145,7 +146,7 @@ bool open, ExceptionState& exception_state) { std::unique_ptr<IDBKey> bound = ScriptValue::To<std::unique_ptr<IDBKey>>( - ExecutionContext::From(script_state)->GetIsolate(), bound_value, + ToIsolate(ExecutionContext::From(script_state)), bound_value, exception_state); if (exception_state.HadException()) return nullptr; @@ -166,7 +167,7 @@ bool upper_open, ExceptionState& exception_state) { std::unique_ptr<IDBKey> lower = ScriptValue::To<std::unique_ptr<IDBKey>>( - ExecutionContext::From(script_state)->GetIsolate(), lower_value, + ToIsolate(ExecutionContext::From(script_state)), lower_value, exception_state); if (exception_state.HadException()) return nullptr; @@ -177,7 +178,7 @@ } std::unique_ptr<IDBKey> upper = ScriptValue::To<std::unique_ptr<IDBKey>>( - ExecutionContext::From(script_state)->GetIsolate(), upper_value, + ToIsolate(ExecutionContext::From(script_state)), upper_value, exception_state); if (exception_state.HadException()) @@ -213,7 +214,7 @@ const ScriptValue& key_value, ExceptionState& exception_state) { std::unique_ptr<IDBKey> key = ScriptValue::To<std::unique_ptr<IDBKey>>( - ExecutionContext::From(script_state)->GetIsolate(), key_value, + ToIsolate(ExecutionContext::From(script_state)), key_value, exception_state); if (exception_state.HadException()) return false;
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_key_range.h b/third_party/blink/renderer/modules/indexeddb/idb_key_range.h index fb8132b9..9df0a6d 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_key_range.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_key_range.h
@@ -48,6 +48,9 @@ std::unique_ptr<IDBKey> upper, LowerBoundType lower_type, UpperBoundType upper_type) { + if ((!lower || !lower->IsValid()) && (!upper || !upper->IsValid())) + return nullptr; + IDBKey* upper_compressed = upper.get(); return MakeGarbageCollected<IDBKeyRange>(std::move(lower), upper_compressed, std::move(upper), lower_type,
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc index c554f0eb..4b945c8 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
@@ -47,8 +47,6 @@ #include "third_party/blink/renderer/modules/indexeddb/idb_tracing.h" #include "third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key_range.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/histogram.h" @@ -306,7 +304,7 @@ return request; } -static WebVector<WebIDBKey> GenerateIndexKeysForValue( +static Vector<std::unique_ptr<IDBKey>> GenerateIndexKeysForValue( v8::Isolate* isolate, const IDBIndexMetadata& index_metadata, const ScriptValue& object_value) { @@ -314,7 +312,7 @@ std::unique_ptr<IDBKey> index_key = ScriptValue::To<std::unique_ptr<IDBKey>>( isolate, object_value, exception_state, index_metadata.key_path); if (!index_key) - return WebVector<WebIDBKey>(); + return Vector<std::unique_ptr<IDBKey>>(); DEFINE_THREAD_SAFE_STATIC_LOCAL( EnumerationHistogram, key_type_histogram, @@ -324,20 +322,20 @@ if (!index_metadata.multi_entry || index_key->GetType() != mojom::IDBKeyType::Array) { if (!index_key->IsValid()) - return WebVector<WebIDBKey>(); + return Vector<std::unique_ptr<IDBKey>>(); - WebVector<WebIDBKey> index_keys; - index_keys.reserve(1); + Vector<std::unique_ptr<IDBKey>> index_keys; + index_keys.ReserveInitialCapacity(1); index_keys.emplace_back(std::move(index_key)); - key_type_histogram.Count(static_cast<int>(index_keys[0].View().KeyType())); - return WebVector<WebIDBKey>(std::move(index_keys)); + key_type_histogram.Count(static_cast<int>(index_keys[0]->GetType())); + return index_keys; } else { DCHECK(index_metadata.multi_entry); DCHECK_EQ(index_key->GetType(), mojom::IDBKeyType::Array); - WebVector<WebIDBKey> index_keys = + Vector<std::unique_ptr<IDBKey>> index_keys = IDBKey::ToMultiEntryArray(std::move(index_key)); - for (const WebIDBKey& key : index_keys) - key_type_histogram.Count(static_cast<int>(key.View().KeyType())); + for (std::unique_ptr<IDBKey>& key : index_keys) + key_type_histogram.Count(static_cast<int>(key->GetType())); return index_keys; } } @@ -558,7 +556,7 @@ key_type_histogram.Count(static_cast<int>(key->GetType())); } - Vector<WebIDBIndexKeys> index_keys; + Vector<IDBIndexKeys> index_keys; index_keys.ReserveInitialCapacity(Metadata().indexes.size()); for (const auto& it : Metadata().indexes) { if (clone.IsEmpty()) @@ -584,7 +582,7 @@ request->transit_blob_handles() = value_wrapper.TakeBlobDataHandles(); BackendDB()->Put( transaction_->Id(), Id(), WebData(value_wrapper.TakeWireBytes()), - value_wrapper.TakeBlobInfo(), WebIDBKeyView(key), put_mode, + value_wrapper.TakeBlobInfo(), IDBKey::Clone(key), put_mode, request->CreateWebCallbacks().release(), std::move(index_keys)); return request; @@ -754,7 +752,7 @@ const IDBKey* primary_key = cursor->IdbPrimaryKey(); ScriptValue value = cursor->value(script_state_); - Vector<WebIDBIndexKeys> index_keys; + Vector<IDBIndexKeys> index_keys; index_keys.ReserveInitialCapacity(1); index_keys.emplace_back( IndexMetadata().id, @@ -762,7 +760,7 @@ IndexMetadata(), value)); database_->Backend()->SetIndexKeys(transaction_id_, object_store_id_, - WebIDBKeyView(primary_key), + IDBKey::Clone(primary_key), std::move(index_keys)); } else { // Now that we are done indexing, tell the backend to go
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_value.cc b/third_party/blink/renderer/modules/indexeddb/idb_value.cc index 5d9fb39a..7703fe06 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_value.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_value.cc
@@ -10,6 +10,7 @@ #include "base/memory/ptr_util.h" #include "base/memory/scoped_refptr.h" #include "third_party/blink/public/platform/web_blob_info.h" +#include "third_party/blink/public/platform/web_data.h" #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_value.h" #include "third_party/blink/renderer/platform/blob/blob_data.h"
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_value.h b/third_party/blink/renderer/modules/indexeddb/idb_value.h index fd54d85..28fedb1 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_value.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_value.h
@@ -19,6 +19,7 @@ class BlobDataHandle; class SerializedScriptValue; +class WebData; class WebBlobInfo; class WebIDBValue; @@ -60,6 +61,9 @@ // Injects a primary key into a value coming from the backend. void SetInjectedPrimaryKey(std::unique_ptr<IDBKey> primary_key, IDBKeyPath primary_key_path) { + // If the given key is type Null, ignore it. + if (primary_key && primary_key->GetType() == mojom::IDBKeyType::Null) + primary_key.reset(); primary_key_ = std::move(primary_key); key_path_ = std::move(primary_key_path); }
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink.typemap b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink.typemap index 3e509b3..2e98b32 100644 --- a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink.typemap +++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink.typemap
@@ -5,9 +5,7 @@ mojom = "//third_party/blink/public/mojom/indexeddb/indexeddb.mojom" public_headers = [ "//third_party/blink/public/common/indexeddb/web_idb_types.h", - "//third_party/blink/renderer/modules/indexeddb/web_idb_key.h", "//third_party/blink/renderer/modules/indexeddb/web_idb_key_path.h", - "//third_party/blink/renderer/modules/indexeddb/web_idb_key_range.h", "//third_party/blink/renderer/modules/indexeddb/web_idb_name_and_version.h", "//third_party/blink/renderer/modules/indexeddb/idb_key_range.h", "//third_party/blink/renderer/modules/indexeddb/idb_metadata.h", @@ -26,10 +24,9 @@ ] type_mappings = [ "blink.mojom.IDBDatabaseMetadata=::blink::IDBDatabaseMetadata", - "blink.mojom.IDBIndexKeys=::blink::WebIDBIndexKeys", + "blink.mojom.IDBIndexKeys=::blink::IDBIndexKeys[move_only]", "blink.mojom.IDBIndexMetadata=scoped_refptr<::blink::IDBIndexMetadata>", - "blink.mojom.IDBKey=::blink::WebIDBKey[move_only]", + "blink.mojom.IDBKey=std::unique_ptr<::blink::IDBKey>[move_only]", "blink.mojom.IDBKeyPath=::blink::IDBKeyPath", - "blink.mojom.IDBKeyRange=::blink::WebIDBKeyRange", "blink.mojom.IDBObjectStoreMetadata=scoped_refptr<::blink::IDBObjectStoreMetadata>", ]
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc index fd80cc8..1000785 100644 --- a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc +++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc
@@ -10,6 +10,7 @@ #include "third_party/blink/public/common/indexeddb/indexed_db_default_mojom_traits.h" #include "third_party/blink/public/common/indexeddb/indexeddb_key.h" #include "third_party/blink/public/common/indexeddb/indexeddb_key_range.h" +#include "third_party/blink/public/platform/web_data.h" #include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h" #include "third_party/blink/renderer/platform/mojo/string16_mojom_traits.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" @@ -51,8 +52,8 @@ } // static -bool StructTraits<blink::mojom::IDBIndexKeysDataView, blink::WebIDBIndexKeys>:: - Read(blink::mojom::IDBIndexKeysDataView data, blink::WebIDBIndexKeys* out) { +bool StructTraits<blink::mojom::IDBIndexKeysDataView, blink::IDBIndexKeys>:: + Read(blink::mojom::IDBIndexKeysDataView data, blink::IDBIndexKeys* out) { out->first = data.index_id(); if (!data.ReadIndexKeys(&out->second)) return false; @@ -81,9 +82,10 @@ // static blink::mojom::IDBKeyDataDataView::Tag -UnionTraits<blink::mojom::IDBKeyDataDataView, blink::WebIDBKey>::GetTag( - const blink::WebIDBKey& key) { - switch (key.View().KeyType()) { +UnionTraits<blink::mojom::IDBKeyDataDataView, std::unique_ptr<blink::IDBKey>>:: + GetTag(const std::unique_ptr<blink::IDBKey>& key) { + DCHECK(key.get()); + switch (key->GetType()) { case blink::mojom::IDBKeyType::Invalid: return blink::mojom::IDBKeyDataDataView::Tag::OTHER_INVALID; case blink::mojom::IDBKeyType::Array: @@ -107,26 +109,22 @@ } // static -bool UnionTraits<blink::mojom::IDBKeyDataDataView, blink::WebIDBKey>::Read( - blink::mojom::IDBKeyDataDataView data, - blink::WebIDBKey* out) { +bool UnionTraits< + blink::mojom::IDBKeyDataDataView, + std::unique_ptr<blink::IDBKey>>::Read(blink::mojom::IDBKeyDataDataView data, + std::unique_ptr<blink::IDBKey>* out) { switch (data.tag()) { case blink::mojom::IDBKeyDataDataView::Tag::KEY_ARRAY: { - Vector<blink::WebIDBKey> array; + Vector<std::unique_ptr<blink::IDBKey>> array; if (!data.ReadKeyArray(&array)) return false; - blink::WebVector<blink::WebIDBKey> webvector_array; - for (const auto& item : array) { - webvector_array.emplace_back( - blink::WebIDBKeyBuilder::Build(item.View())); - } - *out = blink::WebIDBKey::CreateArray(std::move(webvector_array)); + *out = blink::IDBKey::CreateArray(std::move(array)); return true; } case blink::mojom::IDBKeyDataDataView::Tag::BINARY: { ArrayDataView<uint8_t> bytes; data.GetBinaryDataView(&bytes); - *out = blink::WebIDBKey::CreateBinary(blink::WebData( + *out = blink::IDBKey::CreateBinary(blink::WebData( reinterpret_cast<const char*>(bytes.data()), bytes.size())); return true; } @@ -134,20 +132,20 @@ String string; if (!data.ReadString(&string)) return false; - *out = blink::WebIDBKey::CreateString(blink::WebString(string)); + *out = blink::IDBKey::CreateString(blink::WebString(string)); return true; } case blink::mojom::IDBKeyDataDataView::Tag::DATE: - *out = blink::WebIDBKey::CreateDate(data.date()); + *out = blink::IDBKey::CreateDate(data.date()); return true; case blink::mojom::IDBKeyDataDataView::Tag::NUMBER: - *out = blink::WebIDBKey::CreateNumber(data.number()); + *out = blink::IDBKey::CreateNumber(data.number()); return true; case blink::mojom::IDBKeyDataDataView::Tag::OTHER_INVALID: - *out = blink::WebIDBKey::CreateInvalid(); + *out = blink::IDBKey::CreateInvalid(); return true; case blink::mojom::IDBKeyDataDataView::Tag::OTHER_NULL: - *out = blink::WebIDBKey::CreateNull(); + *out = blink::IDBKey::CreateNull(); return true; } @@ -155,26 +153,17 @@ } // static -const blink::WebVector<blink::WebIDBKey> -UnionTraits<blink::mojom::IDBKeyDataDataView, blink::WebIDBKey>::key_array( - const blink::WebIDBKey& key) { - const auto& array_view = key.View().ArrayView(); - const size_t array_size = array_view.size(); - Vector<blink::WebIDBKey> result; - result.ReserveInitialCapacity(SafeCast<wtf_size_t>(array_view.size())); - // |array_view| is of type WebIDBKeyArrayView which only implements size() - // and operator[]. Since it doesn't have other typical array functions, we - // must use an iterator-style for loop. - for (size_t i = 0; i < array_size; ++i) - result.emplace_back(blink::WebIDBKeyBuilder::Build(array_view[i])); - return result; +const Vector<std::unique_ptr<blink::IDBKey>>& +UnionTraits<blink::mojom::IDBKeyDataDataView, std::unique_ptr<blink::IDBKey>>:: + key_array(const std::unique_ptr<blink::IDBKey>& key) { + return key->Array(); } // static -const Vector<uint8_t> -UnionTraits<blink::mojom::IDBKeyDataDataView, blink::WebIDBKey>::binary( - const blink::WebIDBKey& key) { - const auto& data = key.View().Binary(); +Vector<uint8_t> +UnionTraits<blink::mojom::IDBKeyDataDataView, std::unique_ptr<blink::IDBKey>>:: + binary(const std::unique_ptr<blink::IDBKey>& key) { + const blink::WebData& data = key->Binary(); Vector<uint8_t> result; result.ReserveInitialCapacity(SafeCast<wtf_size_t>(data.size())); data.ForEachSegment([&result](const char* segment, size_t segment_size, @@ -187,16 +176,17 @@ } // static -const blink::WebIDBKey& -StructTraits<blink::mojom::IDBKeyDataView, blink::WebIDBKey>::data( - const blink::WebIDBKey& key) { +const std::unique_ptr<blink::IDBKey>& +StructTraits<blink::mojom::IDBKeyDataView, std::unique_ptr<blink::IDBKey>>:: + data(const std::unique_ptr<blink::IDBKey>& key) { return key; } // static -bool StructTraits<blink::mojom::IDBKeyDataView, blink::WebIDBKey>::Read( - blink::mojom::IDBKeyDataView data, - blink::WebIDBKey* out) { +bool StructTraits< + blink::mojom::IDBKeyDataView, + std::unique_ptr<blink::IDBKey>>::Read(blink::mojom::IDBKeyDataView data, + std::unique_ptr<blink::IDBKey>* out) { return data.ReadData(out); } @@ -266,21 +256,6 @@ } // static -bool StructTraits<blink::mojom::IDBKeyRangeDataView, blink::WebIDBKeyRange>:: - Read(blink::mojom::IDBKeyRangeDataView data, blink::WebIDBKeyRange* out) { - // TODO(cmp): Use WebIDBKey and WebIDBKeyRange directly. - blink::IndexedDBKey lower; - blink::IndexedDBKey upper; - if (!data.ReadLower(&lower) || !data.ReadUpper(&upper)) - return false; - - blink::IndexedDBKeyRange temp(lower, upper, data.lower_open(), - data.upper_open()); - *out = blink::WebIDBKeyRangeBuilder::Build(temp); - return true; -} - -// static bool StructTraits<blink::mojom::IDBObjectStoreMetadataDataView, scoped_refptr<blink::IDBObjectStoreMetadata>>:: Read(blink::mojom::IDBObjectStoreMetadataDataView data, @@ -311,4 +286,61 @@ return true; } +// static +blink::mojom::blink::IDBKeyRangePtr TypeConverter< + blink::mojom::blink::IDBKeyRangePtr, + const blink::IDBKeyRange*>::Convert(const blink::IDBKeyRange* input) { + if (!input) { + std::unique_ptr<blink::IDBKey> lower = blink::IDBKey::CreateNull(); + std::unique_ptr<blink::IDBKey> upper = blink::IDBKey::CreateNull(); + return blink::mojom::blink::IDBKeyRange::New( + std::move(lower), std::move(upper), false /* lower_open */, + false /* upper_open */); + } + + return blink::mojom::blink::IDBKeyRange::New( + blink::IDBKey::Clone(input->Lower()), + blink::IDBKey::Clone(input->Upper()), input->lowerOpen(), + input->upperOpen()); +} + +// static +blink::mojom::blink::IDBKeyRangePtr +TypeConverter<blink::mojom::blink::IDBKeyRangePtr, + blink::IDBKeyRange*>::Convert(blink::IDBKeyRange* input) { + if (!input) { + std::unique_ptr<blink::IDBKey> lower = blink::IDBKey::CreateNull(); + std::unique_ptr<blink::IDBKey> upper = blink::IDBKey::CreateNull(); + return blink::mojom::blink::IDBKeyRange::New( + std::move(lower), std::move(upper), false /* lower_open */, + false /* upper_open */); + } + + return blink::mojom::blink::IDBKeyRange::New( + blink::IDBKey::Clone(input->Lower()), + blink::IDBKey::Clone(input->Upper()), input->lowerOpen(), + input->upperOpen()); +} + +// static +blink::IDBKeyRange* +TypeConverter<blink::IDBKeyRange*, blink::mojom::blink::IDBKeyRangePtr>:: + Convert(const blink::mojom::blink::IDBKeyRangePtr& input) { + if (!input) + return nullptr; + + blink::IDBKeyRange::LowerBoundType lower_type = + blink::IDBKeyRange::kLowerBoundClosed; + if (input->lower_open) + lower_type = blink::IDBKeyRange::kLowerBoundOpen; + + blink::IDBKeyRange::UpperBoundType upper_type = + blink::IDBKeyRange::kUpperBoundClosed; + if (input->upper_open) + upper_type = blink::IDBKeyRange::kUpperBoundOpen; + + return blink::IDBKeyRange::Create( + std::move(input->lower), std::move(input->upper), lower_type, upper_type); +} + } // namespace mojo
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.h b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.h index ee5073c..ac32fb0 100644 --- a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.h +++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.h
@@ -14,9 +14,6 @@ #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h" #include "third_party/blink/public/platform/web_vector.h" #include "third_party/blink/renderer/modules/indexeddb/idb_metadata.h" -#include "third_party/blink/renderer/modules/indexeddb/indexed_db_key_builder.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key_range.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -50,16 +47,16 @@ template <> struct MODULES_EXPORT - StructTraits<blink::mojom::IDBIndexKeysDataView, blink::WebIDBIndexKeys> { - static int64_t index_id(const blink::WebIDBIndexKeys& index_keys) { + StructTraits<blink::mojom::IDBIndexKeysDataView, blink::IDBIndexKeys> { + static int64_t index_id(const blink::IDBIndexKeys& index_keys) { return index_keys.first; } - static const blink::WebVector<blink::WebIDBKey>& index_keys( - const blink::WebIDBIndexKeys& index_keys) { + static const Vector<std::unique_ptr<blink::IDBKey>>& index_keys( + const blink::IDBIndexKeys& index_keys) { return index_keys.second; } static bool Read(blink::mojom::IDBIndexKeysDataView data, - blink::WebIDBIndexKeys* out); + blink::IDBIndexKeys* out); }; template <> @@ -90,38 +87,42 @@ }; template <> -struct MODULES_EXPORT - UnionTraits<blink::mojom::IDBKeyDataDataView, blink::WebIDBKey> { +struct MODULES_EXPORT UnionTraits<blink::mojom::IDBKeyDataDataView, + std::unique_ptr<blink::IDBKey>> { static blink::mojom::IDBKeyDataDataView::Tag GetTag( - const blink::WebIDBKey& key); + const std::unique_ptr<blink::IDBKey>& key); static bool Read(blink::mojom::IDBKeyDataDataView data, - blink::WebIDBKey* out); - static const blink::WebVector<blink::WebIDBKey> key_array( - const blink::WebIDBKey& key); - static const Vector<uint8_t> binary(const blink::WebIDBKey& key); - static const WTF::String string(const blink::WebIDBKey& key) { - String key_string = key.View().String(); + std::unique_ptr<blink::IDBKey>* out); + static const Vector<std::unique_ptr<blink::IDBKey>>& key_array( + const std::unique_ptr<blink::IDBKey>& key); + static Vector<uint8_t> binary(const std::unique_ptr<blink::IDBKey>& key); + static const WTF::String string(const std::unique_ptr<blink::IDBKey>& key) { + String key_string = key->GetString(); if (key_string.IsNull()) key_string = g_empty_string; return key_string; } - static double date(const blink::WebIDBKey& key) { return key.View().Date(); } - static double number(const blink::WebIDBKey& key) { - return key.View().Number(); + static double date(const std::unique_ptr<blink::IDBKey>& key) { + return key->Date(); } - static bool other_invalid(const blink::WebIDBKey& key) { - return key.View().KeyType() == blink::mojom::IDBKeyType::Invalid; + static double number(const std::unique_ptr<blink::IDBKey>& key) { + return key->Number(); } - static bool other_null(const blink::WebIDBKey& key) { - return key.View().KeyType() == blink::mojom::IDBKeyType::Null; + static bool other_invalid(const std::unique_ptr<blink::IDBKey>& key) { + return key->GetType() == blink::mojom::IDBKeyType::Invalid; + } + static bool other_null(const std::unique_ptr<blink::IDBKey>& key) { + return key->GetType() == blink::mojom::IDBKeyType::Null; } }; template <> struct MODULES_EXPORT - StructTraits<blink::mojom::IDBKeyDataView, blink::WebIDBKey> { - static const blink::WebIDBKey& data(const blink::WebIDBKey& key); - static bool Read(blink::mojom::IDBKeyDataView data, blink::WebIDBKey* out); + StructTraits<blink::mojom::IDBKeyDataView, std::unique_ptr<blink::IDBKey>> { + static const std::unique_ptr<blink::IDBKey>& data( + const std::unique_ptr<blink::IDBKey>& key); + static bool Read(blink::mojom::IDBKeyDataView data, + std::unique_ptr<blink::IDBKey>* out); }; template <> @@ -135,25 +136,6 @@ template <> struct MODULES_EXPORT - StructTraits<blink::mojom::IDBKeyRangeDataView, blink::WebIDBKeyRange> { - static blink::WebIDBKey lower(const blink::WebIDBKeyRange& key_range) { - return blink::WebIDBKeyBuilder::Build(key_range.Lower()); - } - static blink::WebIDBKey upper(const blink::WebIDBKeyRange& key_range) { - return blink::WebIDBKeyBuilder::Build(key_range.Upper()); - } - static bool lower_open(const blink::WebIDBKeyRange& key_range) { - return key_range.LowerOpen(); - } - static bool upper_open(const blink::WebIDBKeyRange& key_range) { - return key_range.UpperOpen(); - } - static bool Read(blink::mojom::IDBKeyRangeDataView data, - blink::WebIDBKeyRange* out); -}; - -template <> -struct MODULES_EXPORT StructTraits<blink::mojom::IDBObjectStoreMetadataDataView, scoped_refptr<blink::IDBObjectStoreMetadata>> { static int64_t id( @@ -186,6 +168,24 @@ scoped_refptr<blink::IDBObjectStoreMetadata>* out); }; +template <> +struct TypeConverter<blink::mojom::blink::IDBKeyRangePtr, + const blink::IDBKeyRange*> { + static blink::mojom::blink::IDBKeyRangePtr Convert( + const blink::IDBKeyRange* input); +}; + +template <> +struct TypeConverter<blink::mojom::blink::IDBKeyRangePtr, blink::IDBKeyRange*> { + static blink::mojom::blink::IDBKeyRangePtr Convert(blink::IDBKeyRange* input); +}; + +template <> +struct TypeConverter<blink::IDBKeyRange*, blink::mojom::blink::IDBKeyRangePtr> { + static blink::IDBKeyRange* Convert( + const blink::mojom::blink::IDBKeyRangePtr& input); +}; + } // namespace mojo #endif // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_INDEXED_DB_BLINK_MOJOM_TRAITS_H_
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.cc b/third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.cc index 61b1d5bd..1cecf195f 100644 --- a/third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.cc +++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.cc
@@ -5,9 +5,9 @@ #include "third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h" #include "third_party/blink/public/platform/file_path_conversion.h" +#include "third_party/blink/public/platform/web_data.h" #include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h" #include "third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h" -#include "third_party/blink/renderer/modules/indexeddb/indexed_db_key_builder.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_database_error.h" @@ -17,7 +17,6 @@ using blink::IndexedDBDatabaseMetadata; using blink::WebBlobInfo; -using blink::WebData; using blink::WebIDBCallbacks; using blink::WebIDBDatabase; using blink::WebIDBNameAndVersion; @@ -35,7 +34,8 @@ return WebIDBValue(WebData(), WebVector<WebBlobInfo>()); WebIDBValue web_value = IndexedDBCallbacksImpl::ConvertValue(value->value); - web_value.SetInjectedPrimaryKey(value->primary_key, value->key_path); + web_value.SetInjectedPrimaryKey(std::move(value->primary_key), + value->key_path); return web_value; } @@ -144,8 +144,8 @@ void IndexedDBCallbacksImpl::SuccessCursor( mojom::blink::IDBCursorAssociatedPtrInfo cursor_info, - WebIDBKey key, - WebIDBKey primary_key, + std::unique_ptr<IDBKey> key, + std::unique_ptr<IDBKey> primary_key, mojom::blink::IDBValuePtr value) { WebIDBCursorImpl* cursor = new WebIDBCursorImpl(std::move(cursor_info), transaction_id_); @@ -161,8 +161,8 @@ } void IndexedDBCallbacksImpl::SuccessCursorContinue( - WebIDBKey key, - WebIDBKey primary_key, + std::unique_ptr<IDBKey> key, + std::unique_ptr<IDBKey> primary_key, mojom::blink::IDBValuePtr value) { callbacks_->OnSuccess(std::move(key), std::move(primary_key), ConvertValue(value)); @@ -170,8 +170,8 @@ } void IndexedDBCallbacksImpl::SuccessCursorPrefetch( - Vector<WebIDBKey> keys, - Vector<WebIDBKey> primary_keys, + Vector<std::unique_ptr<IDBKey>> keys, + Vector<std::unique_ptr<IDBKey>> primary_keys, Vector<mojom::blink::IDBValuePtr> values) { Vector<WebIDBValue> web_values; web_values.ReserveInitialCapacity(values.size()); @@ -196,7 +196,7 @@ callbacks_.reset(); } -void IndexedDBCallbacksImpl::SuccessKey(WebIDBKey key) { +void IndexedDBCallbacksImpl::SuccessKey(std::unique_ptr<IDBKey> key) { callbacks_->OnSuccess(std::move(key)); callbacks_.reset(); }
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h b/third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h index a454698..6717737 100644 --- a/third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h +++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h
@@ -53,18 +53,18 @@ void SuccessDatabase(mojom::blink::IDBDatabaseAssociatedPtrInfo database_info, const IDBDatabaseMetadata& metadata) override; void SuccessCursor(mojom::blink::IDBCursorAssociatedPtrInfo cursor, - WebIDBKey key, - WebIDBKey primary_key, + std::unique_ptr<IDBKey> key, + std::unique_ptr<IDBKey> primary_key, mojom::blink::IDBValuePtr value) override; void SuccessValue(mojom::blink::IDBReturnValuePtr value) override; - void SuccessCursorContinue(WebIDBKey key, - WebIDBKey primary_key, + void SuccessCursorContinue(std::unique_ptr<IDBKey> key, + std::unique_ptr<IDBKey> primary_key, mojom::blink::IDBValuePtr value) override; - void SuccessCursorPrefetch(Vector<WebIDBKey> keys, - Vector<WebIDBKey> primary_keys, + void SuccessCursorPrefetch(Vector<std::unique_ptr<IDBKey>> keys, + Vector<std::unique_ptr<IDBKey>> primary_keys, Vector<mojom::blink::IDBValuePtr> values) override; void SuccessArray(Vector<mojom::blink::IDBReturnValuePtr> values) override; - void SuccessKey(WebIDBKey key) override; + void SuccessKey(std::unique_ptr<IDBKey> key) override; void SuccessInteger(int64_t value) override; void Success() override;
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.cc b/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.cc index 8312c3c..db0cd91 100644 --- a/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.cc +++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.cc
@@ -8,8 +8,8 @@ #include <utility> #include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h" +#include "third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.h" #include "third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h" -#include "third_party/blink/renderer/modules/indexeddb/indexed_db_key_builder.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_database_callbacks.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_database_error.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_observation.h" @@ -51,8 +51,9 @@ WebVector<WebIDBObservation> web_observations; web_observations.reserve(changes->observations.size()); for (const auto& observation : changes->observations) { + IDBKeyRange* key_range = observation->key_range.To<IDBKeyRange*>(); web_observations.emplace_back( - observation->object_store_id, observation->type, observation->key_range, + observation->object_store_id, observation->type, key_range, IndexedDBCallbacksImpl::ConvertValue(observation->value)); }
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_key_builder.cc b/third_party/blink/renderer/modules/indexeddb/indexed_db_key_builder.cc index bf02c787..2347651 100644 --- a/third_party/blink/renderer/modules/indexeddb/indexed_db_key_builder.cc +++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_key_builder.cc
@@ -4,198 +4,17 @@ #include "third_party/blink/renderer/modules/indexeddb/indexed_db_key_builder.h" -#include <stddef.h> - -#include <algorithm> -#include <string> -#include <utility> -#include <vector> - -#include "third_party/blink/public/common/indexeddb/indexeddb_key_range.h" -#include "third_party/blink/public/common/indexeddb/web_idb_types.h" -#include "third_party/blink/public/platform/web_string.h" -#include "third_party/blink/public/platform/web_vector.h" #include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key_path.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key_range.h" namespace blink { -namespace { - -IndexedDBKey::KeyArray CopyKeyArray(WebIDBKeyArrayView array) { - IndexedDBKey::KeyArray result; - const size_t array_size = array.size(); - result.reserve(array_size); - for (size_t i = 0; i < array_size; ++i) - result.emplace_back(IndexedDBKeyBuilder::Build(array[i])); - return result; -} - -std::vector<base::string16> CopyArray(const WebVector<WebString>& array) { - std::vector<base::string16> result; - result.reserve(array.size()); - for (const WebString& element : array) - result.emplace_back(element.Utf16()); - return result; -} - -} // anonymous namespace - // static -IndexedDBKey IndexedDBKeyBuilder::Build(WebIDBKeyView key) { - switch (key.KeyType()) { - case mojom::IDBKeyType::Array: - return IndexedDBKey(CopyKeyArray(key.ArrayView())); - case mojom::IDBKeyType::Binary: { - const WebData data = key.Binary(); - std::string key_string; - key_string.reserve(data.size()); - - data.ForEachSegment([&key_string](const char* segment, - size_t segment_size, - size_t segment_offset) { - key_string.append(segment, segment_size); - return true; - }); - return IndexedDBKey(std::move(key_string)); - } - case mojom::IDBKeyType::String: - return IndexedDBKey(key.String().Utf16()); - case mojom::IDBKeyType::Date: - return IndexedDBKey(key.Date(), blink::mojom::IDBKeyType::Date); - case mojom::IDBKeyType::Number: - return IndexedDBKey(key.Number(), blink::mojom::IDBKeyType::Number); - case mojom::IDBKeyType::Null: - case mojom::IDBKeyType::Invalid: - return IndexedDBKey(key.KeyType()); - case mojom::IDBKeyType::Min: - NOTREACHED(); - return IndexedDBKey(); - } -} - -// static -WebIDBKey WebIDBKeyBuilder::Build(const WebIDBKeyView& key) { - switch (key.KeyType()) { - case mojom::IDBKeyType::Array: { - const WebIDBKeyArrayView& array = key.ArrayView(); - WebVector<WebIDBKey> web_idb_keys; - const size_t array_size = array.size(); - web_idb_keys.reserve(array_size); - for (size_t i = 0; i < array_size; ++i) - web_idb_keys.emplace_back(Build(array[i])); - return WebIDBKey::CreateArray(std::move(web_idb_keys)); - } - case mojom::IDBKeyType::Binary: { - const WebData data = key.Binary(); - return WebIDBKey::CreateBinary(data); - } - case mojom::IDBKeyType::String: - return WebIDBKey::CreateString(key.String()); - case mojom::IDBKeyType::Date: - return WebIDBKey::CreateDate(key.Date()); - case mojom::IDBKeyType::Number: - return WebIDBKey::CreateNumber(key.Number()); - case mojom::IDBKeyType::Invalid: - return WebIDBKey::CreateInvalid(); - case mojom::IDBKeyType::Null: - return WebIDBKey::CreateNull(); - case mojom::IDBKeyType::Min: - NOTREACHED(); - return WebIDBKey::CreateInvalid(); - } -} - -// static -WebIDBKey WebIDBKeyBuilder::Build(const IndexedDBKey& key) { - switch (key.type()) { - case mojom::IDBKeyType::Array: { - const IndexedDBKey::KeyArray& array = key.array(); - WebVector<WebIDBKey> web_idb_keys; - web_idb_keys.reserve(array.size()); - for (const IndexedDBKey& array_element : array) - web_idb_keys.emplace_back(Build(array_element)); - return WebIDBKey::CreateArray(std::move(web_idb_keys)); - } - case blink::mojom::IDBKeyType::Binary: { - const std::string& str = key.binary(); - const WebData& data = WebData(str.c_str(), str.length()); - return WebIDBKey::CreateBinary(data); - } - case mojom::IDBKeyType::String: - return WebIDBKey::CreateString(WebString::FromUTF16(key.string())); - case blink::mojom::IDBKeyType::Date: - return WebIDBKey::CreateDate(key.date()); - case blink::mojom::IDBKeyType::Number: - return WebIDBKey::CreateNumber(key.number()); - case mojom::IDBKeyType::Invalid: - return WebIDBKey::CreateInvalid(); - case mojom::IDBKeyType::Null: - return WebIDBKey::CreateNull(); - case mojom::IDBKeyType::Min: - NOTREACHED(); - return WebIDBKey::CreateInvalid(); - } -} - -// static -IndexedDBKeyRange IndexedDBKeyRangeBuilder::Build( - const WebIDBKeyRange& key_range) { - return IndexedDBKeyRange(IndexedDBKeyBuilder::Build(key_range.Lower()), - IndexedDBKeyBuilder::Build(key_range.Upper()), - key_range.LowerOpen(), key_range.UpperOpen()); -} - -// static -IndexedDBKeyRange IndexedDBKeyRangeBuilder::Build(WebIDBKeyView key) { - return IndexedDBKeyRange(IndexedDBKeyBuilder::Build(key), - IndexedDBKeyBuilder::Build(key), - false /* lower_open */, false /* upper_open */); -} - -// static -WebIDBKeyRange WebIDBKeyRangeBuilder::Build(WebIDBKeyView key) { - return WebIDBKeyRange(WebIDBKeyBuilder::Build(key), - WebIDBKeyBuilder::Build(key), false /* lower_open */, - false /* upper_open */); -} - -// static -WebIDBKeyRange WebIDBKeyRangeBuilder::Build( - const IndexedDBKeyRange& key_range) { - return WebIDBKeyRange(WebIDBKeyBuilder::Build(key_range.lower()), - WebIDBKeyBuilder::Build(key_range.upper()), - key_range.lower_open(), key_range.upper_open()); -} - -// static -IndexedDBKeyPath IndexedDBKeyPathBuilder::Build(const WebIDBKeyPath& key_path) { - switch (key_path.KeyPathType()) { - case mojom::IDBKeyPathType::String: - return IndexedDBKeyPath(key_path.String().Utf16()); - case mojom::IDBKeyPathType::Array: - return IndexedDBKeyPath(CopyArray(key_path.Array())); - case mojom::IDBKeyPathType::Null: - return IndexedDBKeyPath(); - } -} - -// static -WebIDBKeyPath WebIDBKeyPathBuilder::Build(const IndexedDBKeyPath& key_path) { - switch (key_path.type()) { - case mojom::IDBKeyPathType::String: - return WebIDBKeyPath::Create(WebString::FromUTF16(key_path.string())); - case mojom::IDBKeyPathType::Array: { - WebVector<WebString> key_path_vector(key_path.array().size()); - for (const auto& item : key_path.array()) - key_path_vector.emplace_back(WebString::FromUTF16(item)); - return WebIDBKeyPath::Create(key_path_vector); - } - case mojom::IDBKeyPathType::Null: - return WebIDBKeyPath::CreateNull(); - } +IDBKeyRange* IDBKeyRangeBuilder::Build(const IDBKey* key) { + std::unique_ptr<IDBKey> lower_key = IDBKey::Clone(key); + std::unique_ptr<IDBKey> upper_key = IDBKey::Clone(key); + return IDBKeyRange::Create(std::move(lower_key), std::move(upper_key), + IDBKeyRange::kLowerBoundClosed, + IDBKeyRange::kUpperBoundClosed); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_key_builder.h b/third_party/blink/renderer/modules/indexeddb/indexed_db_key_builder.h index f3c39508..e1987723 100644 --- a/third_party/blink/renderer/modules/indexeddb/indexed_db_key_builder.h +++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_key_builder.h
@@ -5,70 +5,21 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_INDEXED_DB_KEY_BUILDER_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_INDEXED_DB_KEY_BUILDER_H_ -#include "third_party/blink/public/common/indexeddb/indexeddb_key.h" -#include "third_party/blink/public/common/indexeddb/indexeddb_key_path.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key.h" +#include "base/macros.h" #include "third_party/blink/renderer/modules/modules_export.h" namespace blink { -class IndexedDBKeyRange; -class WebIDBKeyPath; -class WebIDBKeyRange; +class IDBKey; +class IDBKeyRange; -class MODULES_EXPORT IndexedDBKeyBuilder { +class MODULES_EXPORT IDBKeyRangeBuilder { public: - static IndexedDBKey Build(WebIDBKeyView key); - - private: - DISALLOW_COPY_AND_ASSIGN(IndexedDBKeyBuilder); -}; - -class MODULES_EXPORT WebIDBKeyBuilder { - public: - static WebIDBKey Build(const IndexedDBKey& key); - static WebIDBKey Build(const WebIDBKeyView& key); - - private: - DISALLOW_COPY_AND_ASSIGN(WebIDBKeyBuilder); -}; - -class MODULES_EXPORT IndexedDBKeyRangeBuilder { - public: - static IndexedDBKeyRange Build(const WebIDBKeyRange& key_range); - // Builds a point range (containing a single key). - static IndexedDBKeyRange Build(WebIDBKeyView key); + static IDBKeyRange* Build(const IDBKey* key); private: - DISALLOW_COPY_AND_ASSIGN(IndexedDBKeyRangeBuilder); -}; - -class MODULES_EXPORT WebIDBKeyRangeBuilder { - public: - static WebIDBKeyRange Build(const IndexedDBKeyRange& key); - - // Builds a point range (containing a single key). - static WebIDBKeyRange Build(WebIDBKeyView key); - - private: - DISALLOW_COPY_AND_ASSIGN(WebIDBKeyRangeBuilder); -}; - -class MODULES_EXPORT IndexedDBKeyPathBuilder { - public: - static IndexedDBKeyPath Build(const WebIDBKeyPath& key_path); - - private: - DISALLOW_COPY_AND_ASSIGN(IndexedDBKeyPathBuilder); -}; - -class MODULES_EXPORT WebIDBKeyPathBuilder { - public: - static WebIDBKeyPath Build(const IndexedDBKeyPath& key_path); - - private: - DISALLOW_COPY_AND_ASSIGN(WebIDBKeyPathBuilder); + DISALLOW_COPY_AND_ASSIGN(IDBKeyRangeBuilder); }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.cc b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.cc index 1f783952..5f88eff 100644 --- a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.cc +++ b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.cc
@@ -4,35 +4,36 @@ #include "third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h" +#include "third_party/blink/renderer/modules/indexeddb/idb_key.h" + namespace blink { MockWebIDBCallbacks::MockWebIDBCallbacks() {} MockWebIDBCallbacks::~MockWebIDBCallbacks() {} -void MockWebIDBCallbacks::OnSuccess(blink::WebIDBKey key, - blink::WebIDBKey primaryKey, - blink::WebIDBValue value) { +void MockWebIDBCallbacks::OnSuccess(std::unique_ptr<IDBKey> key, + std::unique_ptr<IDBKey> primaryKey, + WebIDBValue value) { DoOnSuccess(key, primaryKey, value); } -void MockWebIDBCallbacks::OnSuccess(blink::WebIDBCursor* cursor, - blink::WebIDBKey key, - blink::WebIDBKey primaryKey, - blink::WebIDBValue value) { +void MockWebIDBCallbacks::OnSuccess(WebIDBCursor* cursor, + std::unique_ptr<IDBKey> key, + std::unique_ptr<IDBKey> primaryKey, + WebIDBValue value) { DoOnSuccess(cursor, key, primaryKey, value); } -void MockWebIDBCallbacks::OnSuccess(blink::WebIDBKey key) { +void MockWebIDBCallbacks::OnSuccess(std::unique_ptr<IDBKey> key) { DoOnSuccess(key); } -void MockWebIDBCallbacks::OnSuccess(blink::WebIDBValue value) { +void MockWebIDBCallbacks::OnSuccess(WebIDBValue value) { DoOnSuccess(value); } -void MockWebIDBCallbacks::OnSuccess( - blink::WebVector<blink::WebIDBValue> values) { +void MockWebIDBCallbacks::OnSuccess(WebVector<WebIDBValue> values) { DoOnSuccess(values); }
diff --git a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h index f4dd6efd..875b5c2 100644 --- a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h +++ b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h
@@ -17,54 +17,52 @@ namespace blink { -class MockWebIDBCallbacks : public blink::WebIDBCallbacks { +class MockWebIDBCallbacks : public WebIDBCallbacks { public: MockWebIDBCallbacks(); ~MockWebIDBCallbacks() override; - MOCK_METHOD1(OnError, void(const blink::WebIDBDatabaseError&)); + MOCK_METHOD1(OnError, void(const WebIDBDatabaseError&)); - void OnSuccess(blink::WebIDBKey, - blink::WebIDBKey primaryKey, - blink::WebIDBValue) override; + void OnSuccess(std::unique_ptr<IDBKey>, + std::unique_ptr<IDBKey> primaryKey, + WebIDBValue) override; MOCK_METHOD3(DoOnSuccess, - void(const blink::WebIDBKey& key, - const blink::WebIDBKey& primaryKey, - const blink::WebIDBValue& value)); + void(const std::unique_ptr<IDBKey>& key, + const std::unique_ptr<IDBKey>& primaryKey, + const WebIDBValue& value)); - MOCK_METHOD1(OnSuccess, - void(const blink::WebVector<blink::WebIDBNameAndVersion>&)); - MOCK_METHOD1(OnSuccess, void(const blink::WebVector<blink::WebString>&)); + MOCK_METHOD1(OnSuccess, void(const WebVector<WebIDBNameAndVersion>&)); + MOCK_METHOD1(OnSuccess, void(const WebVector<WebString>&)); - void OnSuccess(blink::WebIDBCursor* cursor, - blink::WebIDBKey key, - blink::WebIDBKey primaryKey, - blink::WebIDBValue value) override; + void OnSuccess(WebIDBCursor* cursor, + std::unique_ptr<IDBKey> key, + std::unique_ptr<IDBKey> primaryKey, + WebIDBValue value) override; MOCK_METHOD4(DoOnSuccess, - void(blink::WebIDBCursor*, - const blink::WebIDBKey&, - const blink::WebIDBKey& primaryKey, - const blink::WebIDBValue&)); + void(WebIDBCursor*, + const std::unique_ptr<IDBKey>&, + const std::unique_ptr<IDBKey>& primaryKey, + const WebIDBValue&)); - MOCK_METHOD2(OnSuccess, - void(blink::WebIDBDatabase*, const blink::IDBDatabaseMetadata&)); - void OnSuccess(blink::WebIDBKey) override; - MOCK_METHOD1(DoOnSuccess, void(const blink::WebIDBKey&)); + MOCK_METHOD2(OnSuccess, void(WebIDBDatabase*, const IDBDatabaseMetadata&)); + void OnSuccess(std::unique_ptr<IDBKey>) override; + MOCK_METHOD1(DoOnSuccess, void(const std::unique_ptr<IDBKey>&)); - void OnSuccess(blink::WebIDBValue) override; - MOCK_METHOD1(DoOnSuccess, void(const blink::WebIDBValue&)); + void OnSuccess(WebIDBValue) override; + MOCK_METHOD1(DoOnSuccess, void(const WebIDBValue&)); - void OnSuccess(blink::WebVector<blink::WebIDBValue>) override; - MOCK_METHOD1(DoOnSuccess, void(const blink::WebVector<blink::WebIDBValue>&)); + void OnSuccess(WebVector<WebIDBValue>) override; + MOCK_METHOD1(DoOnSuccess, void(const WebVector<WebIDBValue>&)); MOCK_METHOD1(OnSuccess, void(long long)); MOCK_METHOD0(OnSuccess, void()); MOCK_METHOD1(OnBlocked, void(long long oldVersion)); MOCK_METHOD5(OnUpgradeNeeded, void(long long oldVersion, - blink::WebIDBDatabase*, - const blink::IDBDatabaseMetadata&, + WebIDBDatabase*, + const IDBDatabaseMetadata&, mojom::IDBDataLoss dataLoss, - blink::WebString dataLossMessage)); + WebString dataLossMessage)); MOCK_METHOD0(Detach, void()); private:
diff --git a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.cc b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.cc index 3b66f4b..d05a1488 100644 --- a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.cc +++ b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.cc
@@ -7,6 +7,7 @@ #include <memory> #include "base/memory/ptr_util.h" +#include "third_party/blink/public/platform/web_data.h" namespace blink {
diff --git a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h index f8572f7..736fad7 100644 --- a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h +++ b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h
@@ -10,7 +10,6 @@ #include "third_party/blink/renderer/modules/indexeddb/idb_key.h" #include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key_range.h" namespace blink { @@ -72,14 +71,14 @@ void(long long transaction_id, long long object_store_id, long long index_id, - const WebIDBKeyRange&, + const IDBKeyRange*, bool key_only, WebIDBCallbacks*)); MOCK_METHOD7(GetAll, void(long long transaction_id, long long object_store_id, long long index_id, - const WebIDBKeyRange&, + const IDBKeyRange*, long long max_count, bool key_only, WebIDBCallbacks*)); @@ -89,16 +88,16 @@ long long object_store_id, const WebData& value, const Vector<WebBlobInfo>&, - WebIDBKeyView primary_key, + std::unique_ptr<IDBKey> primary_key, mojom::IDBPutMode, WebIDBCallbacks*, - const Vector<WebIDBIndexKeys>&)); + Vector<IDBIndexKeys>)); MOCK_METHOD4(SetIndexKeys, void(long long transaction_id, long long object_store_id, - WebIDBKeyView primary_key, - const Vector<WebIDBIndexKeys>&)); + std::unique_ptr<IDBKey> primary_key, + Vector<IDBIndexKeys>)); MOCK_METHOD3(SetIndexesReady, void(long long transaction_id, long long object_store_id, @@ -107,7 +106,7 @@ void(long long transaction_id, long long object_store_id, long long index_id, - const WebIDBKeyRange&, + const IDBKeyRange*, mojom::IDBCursorDirection, bool key_only, mojom::IDBTaskType, @@ -116,17 +115,17 @@ void(long long transaction_id, long long object_store_id, long long index_id, - const WebIDBKeyRange&, + const IDBKeyRange*, WebIDBCallbacks*)); MOCK_METHOD4(Delete, void(long long transaction_id, long long object_store_id, - WebIDBKeyView primary_key, + const IDBKey* primary_key, WebIDBCallbacks*)); MOCK_METHOD4(DeleteRange, void(long long transaction_id, long long object_store_id, - const WebIDBKeyRange&, + const IDBKeyRange*, WebIDBCallbacks*)); MOCK_METHOD3(Clear, void(long long transaction_id,
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h b/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h index 240205b..b86a2a1 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h
@@ -34,10 +34,10 @@ namespace blink { struct IDBDatabaseMetadata; +class IDBKey; class WebIDBCursor; class WebIDBDatabase; class WebIDBDatabaseError; -class WebIDBKey; struct WebIDBNameAndVersion; class WebIDBValue; @@ -50,16 +50,18 @@ virtual void OnSuccess(const WebVector<WebIDBNameAndVersion>&) = 0; virtual void OnSuccess(const WebVector<WebString>&) = 0; virtual void OnSuccess(WebIDBCursor*, - WebIDBKey, - WebIDBKey primary_key, + std::unique_ptr<IDBKey>, + std::unique_ptr<IDBKey> primary_key, WebIDBValue) = 0; virtual void OnSuccess(WebIDBDatabase*, const IDBDatabaseMetadata&) = 0; - virtual void OnSuccess(WebIDBKey) = 0; + virtual void OnSuccess(std::unique_ptr<IDBKey>) = 0; virtual void OnSuccess(WebIDBValue) = 0; virtual void OnSuccess(WebVector<WebIDBValue>) = 0; virtual void OnSuccess(long long) = 0; virtual void OnSuccess() = 0; - virtual void OnSuccess(WebIDBKey, WebIDBKey primary_key, WebIDBValue) = 0; + virtual void OnSuccess(std::unique_ptr<IDBKey>, + std::unique_ptr<IDBKey> primary_key, + WebIDBValue) = 0; virtual void OnBlocked(long long old_version) = 0; virtual void OnUpgradeNeeded(long long old_version, WebIDBDatabase*,
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc index 07b31bb..57198a1 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc
@@ -40,7 +40,6 @@ #include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_database_error.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_name_and_version.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_value.h" #include "third_party/blink/renderer/platform/shared_buffer.h" @@ -49,7 +48,6 @@ using blink::WebIDBCursor; using blink::WebIDBDatabase; using blink::WebIDBDatabaseError; -using blink::WebIDBKey; using blink::WebIDBKeyPath; using blink::WebIDBNameAndVersion; using blink::WebIDBValue; @@ -110,8 +108,8 @@ } void WebIDBCallbacksImpl::OnSuccess(WebIDBCursor* cursor, - WebIDBKey key, - WebIDBKey primary_key, + std::unique_ptr<IDBKey> key, + std::unique_ptr<IDBKey> primary_key, WebIDBValue value) { if (!request_) return; @@ -119,8 +117,8 @@ probe::AsyncTask async_task(request_->GetExecutionContext(), this, "success"); std::unique_ptr<IDBValue> idb_value = value.ReleaseIdbValue(); idb_value->SetIsolate(request_->GetIsolate()); - request_->HandleResponse(base::WrapUnique(cursor), key.ReleaseIdbKey(), - primary_key.ReleaseIdbKey(), std::move(idb_value)); + request_->HandleResponse(base::WrapUnique(cursor), std::move(key), + std::move(primary_key), std::move(idb_value)); } void WebIDBCallbacksImpl::OnSuccess(WebIDBDatabase* backend, @@ -138,12 +136,12 @@ } } -void WebIDBCallbacksImpl::OnSuccess(WebIDBKey key) { +void WebIDBCallbacksImpl::OnSuccess(std::unique_ptr<IDBKey> key) { if (!request_) return; probe::AsyncTask async_task(request_->GetExecutionContext(), this, "success"); - request_->HandleResponse(key.ReleaseIdbKey()); + request_->HandleResponse(std::move(key)); } void WebIDBCallbacksImpl::OnSuccess(WebIDBValue value) { @@ -187,8 +185,8 @@ request_->HandleResponse(); } -void WebIDBCallbacksImpl::OnSuccess(WebIDBKey key, - WebIDBKey primary_key, +void WebIDBCallbacksImpl::OnSuccess(std::unique_ptr<IDBKey> key, + std::unique_ptr<IDBKey> primary_key, WebIDBValue value) { if (!request_) return; @@ -196,7 +194,7 @@ probe::AsyncTask async_task(request_->GetExecutionContext(), this, "success"); std::unique_ptr<IDBValue> idb_value = value.ReleaseIdbValue(); idb_value->SetIsolate(request_->GetIsolate()); - request_->HandleResponse(key.ReleaseIdbKey(), primary_key.ReleaseIdbKey(), + request_->HandleResponse(std::move(key), std::move(primary_key), std::move(idb_value)); }
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h b/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h index 0ed7e46..e8ae25f 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h
@@ -37,11 +37,11 @@ namespace blink { +class IDBKey; class IDBRequest; class WebIDBCursor; class WebIDBDatabase; class WebIDBDatabaseError; -class WebIDBKey; struct IDBDatabaseMetadata; struct WebIDBNameAndVersion; class WebIDBValue; @@ -59,16 +59,18 @@ void OnSuccess(const WebVector<WebIDBNameAndVersion>&) override; void OnSuccess(const WebVector<WebString>&) override; void OnSuccess(WebIDBCursor*, - WebIDBKey, - WebIDBKey primary_key, + std::unique_ptr<IDBKey>, + std::unique_ptr<IDBKey> primary_key, WebIDBValue) override; void OnSuccess(WebIDBDatabase*, const IDBDatabaseMetadata&) override; - void OnSuccess(WebIDBKey) override; + void OnSuccess(std::unique_ptr<IDBKey>) override; void OnSuccess(WebIDBValue) override; void OnSuccess(WebVector<WebIDBValue>) override; void OnSuccess(long long) override; void OnSuccess() override; - void OnSuccess(WebIDBKey, WebIDBKey primary_key, WebIDBValue) override; + void OnSuccess(std::unique_ptr<IDBKey>, + std::unique_ptr<IDBKey> primary_key, + WebIDBValue) override; void OnBlocked(long long old_version) override; void OnUpgradeNeeded(long long old_version, WebIDBDatabase*,
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h index ae9dab7..5d486f7 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h
@@ -29,7 +29,6 @@ #include "third_party/blink/public/common/indexeddb/web_idb_types.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key.h" #include "third_party/blink/renderer/modules/modules_export.h" namespace blink { @@ -47,10 +46,10 @@ // application. When both arguments are null, the cursor advances by one // entry. // - // The keys pointed to by WebIDBKeyView are only guaranteed to be alive for + // The keys pointed to by IDBKey* are only guaranteed to be alive for // the duration of the call. - virtual void CursorContinue(WebIDBKeyView, - WebIDBKeyView primary_key, + virtual void CursorContinue(const IDBKey*, + const IDBKey* primary_key, WebIDBCallbacks*) = 0; // Called after a cursor request's success handler is executed.
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.cc index 28d0d6f4..8ba79b7 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.cc +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.cc
@@ -13,14 +13,11 @@ #include "mojo/public/cpp/bindings/strong_associated_binding.h" #include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h" #include "third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h" -#include "third_party/blink/renderer/modules/indexeddb/indexed_db_key_builder.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_value.h" using blink::WebBlobInfo; using blink::WebData; using blink::WebIDBCallbacks; -using blink::WebIDBKey; -using blink::WebIDBKeyView; using blink::WebIDBValue; using blink::mojom::blink::IDBCallbacksAssociatedPtrInfo; using blink::mojom::blink::IDBCursorAssociatedPtrInfo; @@ -64,13 +61,14 @@ cursor_->Advance(count, GetCallbacksProxy(std::move(callbacks_impl))); } -void WebIDBCursorImpl::CursorContinue(WebIDBKeyView key, - WebIDBKeyView primary_key, +void WebIDBCursorImpl::CursorContinue(const IDBKey* key, + const IDBKey* primary_key, WebIDBCallbacks* callbacks_ptr) { + DCHECK(key && primary_key); std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); - if (key.KeyType() == mojom::IDBKeyType::Null && - primary_key.KeyType() == mojom::IDBKeyType::Null) { + if (key->GetType() == mojom::IDBKeyType::Null && + primary_key->GetType() == mojom::IDBKeyType::Null) { // No key(s), so this would qualify for a prefetch. ++continue_count_; @@ -106,8 +104,7 @@ auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( std::move(callbacks), transaction_id_, weak_factory_.GetWeakPtr()); - cursor_->CursorContinue(WebIDBKeyBuilder::Build(key), - WebIDBKeyBuilder::Build(primary_key), + cursor_->CursorContinue(IDBKey::Clone(key), IDBKey::Clone(primary_key), GetCallbacksProxy(std::move(callbacks_impl))); } @@ -124,9 +121,10 @@ ResetPrefetchCache(); } -void WebIDBCursorImpl::SetPrefetchData(Vector<WebIDBKey> keys, - Vector<WebIDBKey> primary_keys, - Vector<WebIDBValue> values) { +void WebIDBCursorImpl::SetPrefetchData( + Vector<std::unique_ptr<IDBKey>> keys, + Vector<std::unique_ptr<IDBKey>> primary_keys, + Vector<WebIDBValue> values) { // Keys and values are stored in reverse order so that a cache'd continue can // pop a value off of the back and prevent new memory allocations. prefetch_keys_.AppendRange(std::make_move_iterator(keys.rbegin()), @@ -165,8 +163,9 @@ // Keys and values are stored in reverse order so that a cache'd continue can // pop a value off of the back and prevent new memory allocations. - WebIDBKey key = std::move(prefetch_keys_.back()); - WebIDBKey primary_key = std::move(prefetch_primary_keys_.back()); + std::unique_ptr<IDBKey> key = std::move(prefetch_keys_.back()); + std::unique_ptr<IDBKey> primary_key = + std::move(prefetch_primary_keys_.back()); WebIDBValue value = std::move(prefetch_values_.back()); prefetch_keys_.pop_back();
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h index 96a21375..bb4bcd74 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl.h
@@ -14,7 +14,6 @@ #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_cursor.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_value.h" #include "third_party/blink/renderer/modules/modules_export.h" @@ -29,13 +28,13 @@ ~WebIDBCursorImpl() override; void Advance(uint32_t count, WebIDBCallbacks* callback) override; - void CursorContinue(WebIDBKeyView key, - WebIDBKeyView primary_key, + void CursorContinue(const IDBKey* key, + const IDBKey* primary_key, WebIDBCallbacks* callback) override; void PostSuccessHandlerCallback() override; - void SetPrefetchData(Vector<WebIDBKey> keys, - Vector<WebIDBKey> primary_keys, + void SetPrefetchData(Vector<std::unique_ptr<IDBKey>> keys, + Vector<std::unique_ptr<IDBKey>> primary_keys, Vector<WebIDBValue> values); void CachedAdvance(unsigned long count, WebIDBCallbacks* callbacks); @@ -67,8 +66,8 @@ // Prefetch cache. Keys and values are stored in reverse order so that a // cache'd continue can pop a value off of the back and prevent new memory // allocations. - Vector<WebIDBKey> prefetch_keys_; - Vector<WebIDBKey> prefetch_primary_keys_; + Vector<std::unique_ptr<IDBKey>> prefetch_keys_; + Vector<std::unique_ptr<IDBKey>> prefetch_primary_keys_; Vector<WebIDBValue> prefetch_values_; // Number of continue calls that would qualify for a pre-fetch.
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc index 11b6664..1d1f7d46 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_cursor_impl_unittest.cc
@@ -15,7 +15,6 @@ #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" #include "third_party/blink/public/platform/web_data.h" #include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h" -#include "third_party/blink/renderer/modules/indexeddb/indexed_db_key_builder.h" #include "third_party/blink/renderer/modules/indexeddb/mock_web_idb_callbacks.h" #include "third_party/blink/renderer/platform/testing/testing_platform_support.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" @@ -51,8 +50,8 @@ } void CursorContinue( - WebIDBKey key, - WebIDBKey primary_key, + std::unique_ptr<IDBKey> key, + std::unique_ptr<IDBKey> primary_key, mojom::blink::IDBCallbacksAssociatedPtrInfo callbacks) override { ++continue_calls_; } @@ -81,21 +80,21 @@ class MockContinueCallbacks : public testing::StrictMock<MockWebIDBCallbacks> { public: - MockContinueCallbacks(IndexedDBKey* key = nullptr, + MockContinueCallbacks(std::unique_ptr<IDBKey>* key = nullptr, WebVector<WebBlobInfo>* blobs = nullptr) : key_(key), blobs_(blobs) {} - void OnSuccess(WebIDBKey key, - WebIDBKey primaryKey, + void OnSuccess(std::unique_ptr<IDBKey> key, + std::unique_ptr<IDBKey> primaryKey, WebIDBValue value) override { if (key_) - *key_ = IndexedDBKeyBuilder::Build(key.View()); + *key_ = IDBKey::Clone(key); if (blobs_) *blobs_ = value.BlobInfoForTesting(); } private: - IndexedDBKey* key_; + std::unique_ptr<IDBKey>* key_; WebVector<WebBlobInfo>* blobs_; }; @@ -103,7 +102,7 @@ class WebIDBCursorImplTest : public testing::Test { public: - WebIDBCursorImplTest() : null_key_(WebIDBKey::CreateNull()) { + WebIDBCursorImplTest() : null_key_(IDBKey::CreateNull()) { mojom::blink::IDBCursorAssociatedPtr ptr; mock_cursor_ = std::make_unique<MockCursorImpl>( mojo::MakeRequestAssociatedWithDedicatedPipe(&ptr)); @@ -112,7 +111,7 @@ protected: ScopedTestingPlatformSupport<TestingPlatformSupport> platform_; - WebIDBKey null_key_; + std::unique_ptr<IDBKey> null_key_; std::unique_ptr<WebIDBCursorImpl> cursor_; std::unique_ptr<MockCursorImpl> mock_cursor_; @@ -125,7 +124,7 @@ int continue_calls = 0; EXPECT_EQ(mock_cursor_->continue_calls(), 0); for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) { - cursor_->CursorContinue(null_key_.View(), null_key_.View(), + cursor_->CursorContinue(null_key_.get(), null_key_.get(), new MockContinueCallbacks()); platform_->RunUntilIdle(); EXPECT_EQ(++continue_calls, mock_cursor_->continue_calls()); @@ -140,7 +139,7 @@ int last_prefetch_count = 0; for (int repetitions = 0; repetitions < kPrefetchRepetitions; ++repetitions) { // Initiate the prefetch - cursor_->CursorContinue(null_key_.View(), null_key_.View(), + cursor_->CursorContinue(null_key_.get(), null_key_.get(), new MockContinueCallbacks()); platform_->RunUntilIdle(); EXPECT_EQ(continue_calls, mock_cursor_->continue_calls()); @@ -152,12 +151,12 @@ last_prefetch_count = prefetch_count; // Fill the prefetch cache as requested. - Vector<WebIDBKey> keys; - Vector<WebIDBKey> primary_keys; + Vector<std::unique_ptr<IDBKey>> keys; + Vector<std::unique_ptr<IDBKey>> primary_keys; Vector<WebIDBValue> values; size_t expected_size = 0; for (int i = 0; i < prefetch_count; ++i) { - WebIDBKey key = WebIDBKey::CreateNumber(expected_key + i); + std::unique_ptr<IDBKey> key = IDBKey::CreateNumber(expected_key + i); keys.emplace_back(std::move(key)); primary_keys.emplace_back(); expected_size++; @@ -180,17 +179,17 @@ // Verify that the cache is used for subsequent continue() calls. for (int i = 0; i < prefetch_count; ++i) { - IndexedDBKey key; + std::unique_ptr<IDBKey> key; WebVector<WebBlobInfo> blobs; - cursor_->CursorContinue(null_key_.View(), null_key_.View(), + cursor_->CursorContinue(null_key_.get(), null_key_.get(), new MockContinueCallbacks(&key, &blobs)); platform_->RunUntilIdle(); EXPECT_EQ(continue_calls, mock_cursor_->continue_calls()); EXPECT_EQ(repetitions + 1, mock_cursor_->prefetch_calls()); - EXPECT_EQ(mojom::IDBKeyType::Number, key.type()); + EXPECT_EQ(mojom::IDBKeyType::Number, key->GetType()); EXPECT_EQ(expected_key, static_cast<int>(blobs.size())); - EXPECT_EQ(expected_key++, key.number()); + EXPECT_EQ(expected_key++, key->Number()); } } @@ -203,14 +202,14 @@ // Call continue() until prefetching should kick in. EXPECT_EQ(0, mock_cursor_->continue_calls()); for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) { - cursor_->CursorContinue(null_key_.View(), null_key_.View(), + cursor_->CursorContinue(null_key_.get(), null_key_.get(), new MockContinueCallbacks()); } platform_->RunUntilIdle(); EXPECT_EQ(0, mock_cursor_->prefetch_calls()); // Initiate the prefetch - cursor_->CursorContinue(null_key_.View(), null_key_.View(), + cursor_->CursorContinue(null_key_.get(), null_key_.get(), new MockContinueCallbacks()); platform_->RunUntilIdle(); @@ -223,12 +222,12 @@ // Fill the prefetch cache as requested. int expected_key = 0; - Vector<WebIDBKey> keys; - Vector<WebIDBKey> primary_keys; + Vector<std::unique_ptr<IDBKey>> keys; + Vector<std::unique_ptr<IDBKey>> primary_keys; Vector<WebIDBValue> values; size_t expected_size = 0; for (int i = 0; i < prefetch_count; ++i) { - WebIDBKey key = WebIDBKey::CreateNumber(expected_key + i); + std::unique_ptr<IDBKey> key = IDBKey::CreateNumber(expected_key + i); keys.emplace_back(std::move(key)); primary_keys.emplace_back(); expected_size++; @@ -253,27 +252,27 @@ ASSERT_GE(prefetch_count, 5); // IDBCursor.continue() - IndexedDBKey key; - cursor_->CursorContinue(null_key_.View(), null_key_.View(), + std::unique_ptr<IDBKey> key; + cursor_->CursorContinue(null_key_.get(), null_key_.get(), new MockContinueCallbacks(&key)); platform_->RunUntilIdle(); - EXPECT_EQ(0, key.number()); + EXPECT_EQ(0, key->Number()); // IDBCursor.advance(1) cursor_->Advance(1, new MockContinueCallbacks(&key)); platform_->RunUntilIdle(); - EXPECT_EQ(1, key.number()); + EXPECT_EQ(1, key->Number()); // IDBCursor.continue() - cursor_->CursorContinue(null_key_.View(), null_key_.View(), + cursor_->CursorContinue(null_key_.get(), null_key_.get(), new MockContinueCallbacks(&key)); platform_->RunUntilIdle(); - EXPECT_EQ(2, key.number()); + EXPECT_EQ(2, key->Number()); // IDBCursor.advance(2) cursor_->Advance(2, new MockContinueCallbacks(&key)); platform_->RunUntilIdle(); - EXPECT_EQ(4, key.number()); + EXPECT_EQ(4, key->Number()); EXPECT_EQ(0, mock_cursor_->advance_calls()); @@ -296,7 +295,7 @@ int continue_calls = 0; EXPECT_EQ(mock_cursor_->continue_calls(), 0); for (int i = 0; i < WebIDBCursorImpl::kPrefetchContinueThreshold; ++i) { - cursor_->CursorContinue(null_key_.View(), null_key_.View(), + cursor_->CursorContinue(null_key_.get(), null_key_.get(), new MockContinueCallbacks()); platform_->RunUntilIdle(); EXPECT_EQ(++continue_calls, mock_cursor_->continue_calls()); @@ -304,7 +303,7 @@ } // Initiate the prefetch - cursor_->CursorContinue(null_key_.View(), null_key_.View(), + cursor_->CursorContinue(null_key_.get(), null_key_.get(), new MockContinueCallbacks()); platform_->RunUntilIdle(); EXPECT_EQ(continue_calls, mock_cursor_->continue_calls()); @@ -320,8 +319,8 @@ // Fill the prefetch cache as requested. int prefetch_count = mock_cursor_->last_prefetch_count(); - Vector<WebIDBKey> keys(prefetch_count); - Vector<WebIDBKey> primary_keys(prefetch_count); + Vector<std::unique_ptr<IDBKey>> keys(prefetch_count); + Vector<std::unique_ptr<IDBKey>> primary_keys(prefetch_count); Vector<WebIDBValue> values; for (int i = 0; i < prefetch_count; ++i) values.emplace_back(WebData(), WebVector<WebBlobInfo>());
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_database.h b/third_party/blink/renderer/modules/indexeddb/web_idb_database.h index d97f44c..88e3f262da 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_database.h +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_database.h
@@ -37,10 +37,10 @@ namespace blink { +class IDBKeyRange; class WebData; class WebIDBCallbacks; class WebIDBKeyPath; -class WebIDBKeyRange; class MODULES_EXPORT WebIDBDatabase { public: @@ -94,13 +94,13 @@ virtual void Get(long long transaction_id, long long object_store_id, long long index_id, - const WebIDBKeyRange&, + const IDBKeyRange*, bool key_only, WebIDBCallbacks*) = 0; virtual void GetAll(long long transaction_id, long long object_store_id, long long index_id, - const WebIDBKeyRange&, + const IDBKeyRange*, long long max_count, bool key_only, WebIDBCallbacks*) = 0; @@ -108,21 +108,21 @@ long long object_store_id, const WebData& value, const Vector<WebBlobInfo>&, - WebIDBKeyView primary_key, + std::unique_ptr<IDBKey> primary_key, mojom::IDBPutMode, WebIDBCallbacks*, - const Vector<WebIDBIndexKeys>&) = 0; + Vector<IDBIndexKeys>) = 0; virtual void SetIndexKeys(long long transaction_id, long long object_store_id, - WebIDBKeyView primary_key, - const Vector<WebIDBIndexKeys>&) = 0; + std::unique_ptr<IDBKey> primary_key, + Vector<IDBIndexKeys>) = 0; virtual void SetIndexesReady(long long transaction_id, long long object_store_id, const Vector<int64_t>& index_ids) = 0; virtual void OpenCursor(long long transaction_id, long long object_store_id, long long index_id, - const WebIDBKeyRange&, + const IDBKeyRange*, mojom::IDBCursorDirection, bool key_only, mojom::IDBTaskType, @@ -130,15 +130,15 @@ virtual void Count(long long transaction_id, long long object_store_id, long long index_id, - const WebIDBKeyRange&, + const IDBKeyRange*, WebIDBCallbacks*) = 0; virtual void Delete(long long transaction_id, long long object_store_id, - WebIDBKeyView primary_key, + const IDBKey* primary_key, WebIDBCallbacks*) = 0; virtual void DeleteRange(long long transaction_id, long long object_store_id, - const WebIDBKeyRange&, + const IDBKeyRange*, WebIDBCallbacks*) = 0; virtual void Clear(long long transaction_id, long long object_store_id,
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.cc index fa94672..f925ead 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.cc +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.cc
@@ -16,9 +16,11 @@ #include "third_party/blink/public/platform/file_path_conversion.h" #include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h" #include "third_party/blink/public/platform/web_blob_info.h" +#include "third_party/blink/public/platform/web_data.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/platform/web_vector.h" #include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h" +#include "third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.h" #include "third_party/blink/renderer/modules/indexeddb/indexed_db_callbacks_impl.h" #include "third_party/blink/renderer/modules/indexeddb/indexed_db_dispatcher.h" #include "third_party/blink/renderer/modules/indexeddb/indexed_db_key_builder.h" @@ -89,30 +91,35 @@ void WebIDBDatabaseImpl::Get(long long transaction_id, long long object_store_id, long long index_id, - const WebIDBKeyRange& key_range, + const IDBKeyRange* key_range, bool key_only, WebIDBCallbacks* callbacks) { IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr); + mojom::blink::IDBKeyRangePtr key_range_ptr = + mojom::blink::IDBKeyRange::From(key_range); auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( base::WrapUnique(callbacks), transaction_id, nullptr); - database_->Get(transaction_id, object_store_id, index_id, key_range, key_only, + database_->Get(transaction_id, object_store_id, index_id, + std::move(key_range_ptr), key_only, GetCallbacksProxy(std::move(callbacks_impl))); } void WebIDBDatabaseImpl::GetAll(long long transaction_id, long long object_store_id, long long index_id, - const WebIDBKeyRange& key_range, + const IDBKeyRange* key_range, long long max_count, bool key_only, WebIDBCallbacks* callbacks) { IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr); + mojom::blink::IDBKeyRangePtr key_range_ptr = + mojom::blink::IDBKeyRange::From(key_range); auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( base::WrapUnique(callbacks), transaction_id, nullptr); - database_->GetAll(transaction_id, object_store_id, index_id, key_range, - key_only, max_count, + database_->GetAll(transaction_id, object_store_id, index_id, + std::move(key_range_ptr), key_only, max_count, GetCallbacksProxy(std::move(callbacks_impl))); } @@ -120,12 +127,10 @@ long long object_store_id, const WebData& value, const Vector<WebBlobInfo>& web_blob_info, - WebIDBKeyView web_primary_key, + std::unique_ptr<IDBKey> primary_key, mojom::IDBPutMode put_mode, WebIDBCallbacks* callbacks, - const Vector<WebIDBIndexKeys>& index_keys) { - WebIDBKey primary_key = WebIDBKeyBuilder::Build(web_primary_key); - + Vector<IDBIndexKeys> index_keys) { IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr); auto mojo_value = mojom::blink::IDBValue::New(); @@ -168,12 +173,12 @@ for (const auto& index_key : index_keys) { index_keys_size++; // Account for index_key.first (int64_t). for (const auto& key : index_key.second) { - index_keys_size += key.SizeEstimate(); + index_keys_size += key->SizeEstimate(); } } size_t arg_size = - mojo_value->bits.size() + primary_key.SizeEstimate() + index_keys_size; + mojo_value->bits.size() + primary_key->SizeEstimate() + index_keys_size; if (arg_size >= max_put_value_size_) { callbacks->OnError(blink::WebIDBDatabaseError( blink::kWebIDBDatabaseExceptionUnknownError, @@ -187,18 +192,16 @@ auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( base::WrapUnique(callbacks), transaction_id, nullptr); database_->Put(transaction_id, object_store_id, std::move(mojo_value), - std::move(primary_key), put_mode, index_keys, + std::move(primary_key), put_mode, std::move(index_keys), GetCallbacksProxy(std::move(callbacks_impl))); } -void WebIDBDatabaseImpl::SetIndexKeys( - long long transaction_id, - long long object_store_id, - WebIDBKeyView primary_key, - const Vector<WebIDBIndexKeys>& index_keys) { - IndexedDBKey temp(IndexedDBKeyBuilder::Build(primary_key)); +void WebIDBDatabaseImpl::SetIndexKeys(long long transaction_id, + long long object_store_id, + std::unique_ptr<IDBKey> primary_key, + Vector<IDBIndexKeys> index_keys) { database_->SetIndexKeys(transaction_id, object_store_id, - WebIDBKeyBuilder::Build(temp), std::move(index_keys)); + std::move(primary_key), std::move(index_keys)); } void WebIDBDatabaseImpl::SetIndexesReady(long long transaction_id, @@ -211,55 +214,66 @@ void WebIDBDatabaseImpl::OpenCursor(long long transaction_id, long long object_store_id, long long index_id, - const WebIDBKeyRange& key_range, + const IDBKeyRange* key_range, mojom::IDBCursorDirection direction, bool key_only, mojom::IDBTaskType task_type, WebIDBCallbacks* callbacks) { IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr); + mojom::blink::IDBKeyRangePtr key_range_ptr = + mojom::blink::IDBKeyRange::From(key_range); auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( base::WrapUnique(callbacks), transaction_id, nullptr); - database_->OpenCursor(transaction_id, object_store_id, index_id, key_range, - direction, key_only, task_type, + database_->OpenCursor(transaction_id, object_store_id, index_id, + std::move(key_range_ptr), direction, key_only, + task_type, GetCallbacksProxy(std::move(callbacks_impl))); } void WebIDBDatabaseImpl::Count(long long transaction_id, long long object_store_id, long long index_id, - const WebIDBKeyRange& key_range, + const IDBKeyRange* key_range, WebIDBCallbacks* callbacks) { IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr); + mojom::blink::IDBKeyRangePtr key_range_ptr = + mojom::blink::IDBKeyRange::From(key_range); auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( base::WrapUnique(callbacks), transaction_id, nullptr); - database_->Count(transaction_id, object_store_id, index_id, key_range, + database_->Count(transaction_id, object_store_id, index_id, + std::move(key_range_ptr), GetCallbacksProxy(std::move(callbacks_impl))); } void WebIDBDatabaseImpl::Delete(long long transaction_id, long long object_store_id, - WebIDBKeyView primary_key, + const IDBKey* primary_key, WebIDBCallbacks* callbacks) { IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr); + mojom::blink::IDBKeyRangePtr key_range_ptr = + mojom::blink::IDBKeyRange::From(IDBKeyRangeBuilder::Build(primary_key)); auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( base::WrapUnique(callbacks), transaction_id, nullptr); database_->DeleteRange(transaction_id, object_store_id, - WebIDBKeyRangeBuilder::Build(primary_key), + std::move(key_range_ptr), GetCallbacksProxy(std::move(callbacks_impl))); } void WebIDBDatabaseImpl::DeleteRange(long long transaction_id, long long object_store_id, - const WebIDBKeyRange& key_range, + const IDBKeyRange* key_range, WebIDBCallbacks* callbacks) { IndexedDBDispatcher::ResetCursorPrefetchCaches(transaction_id, nullptr); + mojom::blink::IDBKeyRangePtr key_range_ptr = + mojom::blink::IDBKeyRange::From(key_range); auto callbacks_impl = std::make_unique<IndexedDBCallbacksImpl>( base::WrapUnique(callbacks), transaction_id, nullptr); - database_->DeleteRange(transaction_id, object_store_id, key_range, + database_->DeleteRange(transaction_id, object_store_id, + std::move(key_range_ptr), GetCallbacksProxy(std::move(callbacks_impl))); }
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h b/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h index b4df30e..e35c6d8 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h
@@ -21,16 +21,16 @@ class WebBlobInfo; class WebIDBCallbacks; -class MODULES_EXPORT WebIDBDatabaseImpl : public blink::WebIDBDatabase { +class MODULES_EXPORT WebIDBDatabaseImpl : public WebIDBDatabase { public: WebIDBDatabaseImpl(mojom::blink::IDBDatabaseAssociatedPtrInfo database); ~WebIDBDatabaseImpl() override; - // blink::WebIDBDatabase + // WebIDBDatabase void CreateObjectStore(long long transaction_id, long long objectstore_id, const String& name, - const blink::WebIDBKeyPath&, + const WebIDBKeyPath&, bool auto_increment) override; void DeleteObjectStore(long long transaction_id, long long object_store_id) override; @@ -50,66 +50,66 @@ bool include_transaction, bool no_records, bool values, - std::bitset<blink::kIDBOperationTypeCount> operation_types) override; + std::bitset<kIDBOperationTypeCount> operation_types) override; void RemoveObservers(const Vector<int32_t>& observer_ids) override; void Get(long long transaction_id, long long object_store_id, long long index_id, - const blink::WebIDBKeyRange&, + const IDBKeyRange*, bool key_only, - blink::WebIDBCallbacks*) override; + WebIDBCallbacks*) override; void GetAll(long long transaction_id, long long object_store_id, long long index_id, - const blink::WebIDBKeyRange&, + const IDBKeyRange*, long long max_count, bool key_only, - blink::WebIDBCallbacks*) override; + WebIDBCallbacks*) override; void Put(long long transaction_id, long long object_store_id, - const blink::WebData& value, - const Vector<blink::WebBlobInfo>&, - blink::WebIDBKeyView primary_key, + const WebData& value, + const Vector<WebBlobInfo>&, + std::unique_ptr<IDBKey> primary_key, mojom::IDBPutMode, - blink::WebIDBCallbacks*, - const Vector<blink::WebIDBIndexKeys>&) override; + WebIDBCallbacks*, + Vector<IDBIndexKeys>) override; void SetIndexKeys(long long transaction_id, long long object_store_id, - blink::WebIDBKeyView primary_key, - const Vector<blink::WebIDBIndexKeys>&) override; + std::unique_ptr<IDBKey> primary_key, + Vector<IDBIndexKeys>) override; void SetIndexesReady(long long transaction_id, long long object_store_id, const Vector<int64_t>& index_ids) override; void OpenCursor(long long transaction_id, long long object_store_id, long long index_id, - const blink::WebIDBKeyRange&, + const IDBKeyRange*, mojom::IDBCursorDirection direction, bool key_only, mojom::IDBTaskType, - blink::WebIDBCallbacks*) override; + WebIDBCallbacks*) override; void Count(long long transaction_id, long long object_store_id, long long index_id, - const blink::WebIDBKeyRange&, - blink::WebIDBCallbacks*) override; + const IDBKeyRange*, + WebIDBCallbacks*) override; void Delete(long long transaction_id, long long object_store_id, - blink::WebIDBKeyView primary_key, - blink::WebIDBCallbacks*) override; + const IDBKey* primary_key, + WebIDBCallbacks*) override; void DeleteRange(long long transaction_id, long long object_store_id, - const blink::WebIDBKeyRange&, - blink::WebIDBCallbacks*) override; + const IDBKeyRange*, + WebIDBCallbacks*) override; void Clear(long long transaction_id, long long object_store_id, - blink::WebIDBCallbacks*) override; + WebIDBCallbacks*) override; void CreateIndex(long long transaction_id, long long object_store_id, long long index_id, const String& name, - const blink::WebIDBKeyPath&, + const WebIDBKeyPath&, bool unique, bool multi_entry) override; void DeleteIndex(long long transaction_id,
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl_unittest.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl_unittest.cc index 42f4342..f8dd4525 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl_unittest.cc +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl_unittest.cc
@@ -35,20 +35,20 @@ const std::vector<char> data(kMaxValueSizeForTesting + 1); const WebData value(&data.front(), data.size()); const Vector<WebBlobInfo> blob_info; - const WebIDBKey key = WebIDBKey::CreateNumber(0); + std::unique_ptr<IDBKey> key = IDBKey::CreateNumber(0); const int64_t transaction_id = 1; const int64_t object_store_id = 2; StrictMock<MockWebIDBCallbacks> callbacks; - ASSERT_GT(value.size() + key.SizeEstimate(), kMaxValueSizeForTesting); + ASSERT_GT(value.size() + key->SizeEstimate(), kMaxValueSizeForTesting); ThreadState::Current()->CollectAllGarbage(); EXPECT_CALL(callbacks, OnError(_)).Times(1); WebIDBDatabaseImpl database_impl(nullptr); database_impl.max_put_value_size_ = kMaxValueSizeForTesting; database_impl.Put(transaction_id, object_store_id, value, blob_info, - key.View(), mojom::IDBPutMode::AddOrUpdate, &callbacks, - Vector<blink::WebIDBIndexKeys>()); + std::move(key), mojom::IDBPutMode::AddOrUpdate, &callbacks, + Vector<IDBIndexKeys>()); } TEST_F(WebIDBDatabaseImplTest, KeyAndValueSizeTest) { @@ -75,10 +75,10 @@ String key_string(key_string_vector); DCHECK_EQ(key_string.length(), number_of_chars); - WebIDBKey key = WebIDBKey::CreateString(key_string); + std::unique_ptr<IDBKey> key = IDBKey::CreateString(key_string); DCHECK_EQ(value.size(), kMaxValueSizeForTesting - kKeySize); - DCHECK_GT(key.SizeEstimate() - kKeySize, static_cast<unsigned long>(0)); - DCHECK_GT(value.size() + key.SizeEstimate(), kMaxValueSizeForTesting); + DCHECK_GT(key->SizeEstimate() - kKeySize, static_cast<unsigned long>(0)); + DCHECK_GT(value.size() + key->SizeEstimate(), kMaxValueSizeForTesting); ThreadState::Current()->CollectAllGarbage(); EXPECT_CALL(callbacks, OnError(_)).Times(1); @@ -86,8 +86,8 @@ WebIDBDatabaseImpl database_impl(nullptr); database_impl.max_put_value_size_ = kMaxValueSizeForTesting; database_impl.Put(transaction_id, object_store_id, value, blob_info, - key.View(), mojom::IDBPutMode::AddOrUpdate, &callbacks, - Vector<blink::WebIDBIndexKeys>()); + std::move(key), mojom::IDBPutMode::AddOrUpdate, &callbacks, + Vector<IDBIndexKeys>()); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_key.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_key.cc deleted file mode 100644 index bb84b91d..0000000 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_key.cc +++ /dev/null
@@ -1,143 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key.h" - -#include "third_party/blink/renderer/modules/indexeddb/idb_key.h" -#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" - -namespace blink { - -size_t WebIDBKeyArrayView::size() const { - return private_->Array().size(); -} - -WebIDBKeyView WebIDBKeyArrayView::operator[](size_t index) const { - return WebIDBKeyView(private_->Array()[SafeCast<wtf_size_t>(index)].get()); -} - -mojom::IDBKeyType WebIDBKeyView::KeyType() const { - if (!private_) - return blink::mojom::IDBKeyType::Null; - return static_cast<mojom::IDBKeyType>(private_->GetType()); -} - -bool WebIDBKeyView::IsValid() const { - if (!private_) - return false; - return private_->IsValid(); -} - -WebData WebIDBKeyView::Binary() const { - return private_->Binary(); -} - -WebString WebIDBKeyView::String() const { - return private_->GetString(); -} - -double WebIDBKeyView::Date() const { - return private_->Date(); -} - -double WebIDBKeyView::Number() const { - return private_->Number(); -} - -size_t WebIDBKeyView::SizeEstimate() const { - // TODO(cmp): Ensure |private_| can never be null. - // - // SizeEstimate() can be called when |private_| is null. That happens if and - // only if the |WebIDBKey| instance is created using WebIDBKey::CreateNull(). - // - // Eventually, WebIDBKey::CreateNull() will change so that case will lead to - // a non-null |private_|. At that time, this null check can change to a - // DCHECK that |private_| is not null and the special null case handling can - // be removed. - if (this->IsNull()) { - return IDBKey::kIDBKeyOverheadSize; - } - - return private_->SizeEstimate(); -} - -WebIDBKey WebIDBKey::CreateArray(WebVector<WebIDBKey> array) { - IDBKey::KeyArray keys; - keys.ReserveCapacity(SafeCast<wtf_size_t>(array.size())); - for (WebIDBKey& key : array) { - DCHECK(key.View().KeyType() != mojom::IDBKeyType::Null); - keys.emplace_back(key.ReleaseIdbKey()); - } - return WebIDBKey(IDBKey::CreateArray(std::move(keys))); -} - -WebIDBKey WebIDBKey::CreateBinary(const WebData& binary) { - return WebIDBKey(IDBKey::CreateBinary(binary)); -} - -WebIDBKey WebIDBKey::CreateString(const WebString& string) { - return WebIDBKey(IDBKey::CreateString(string)); -} - -WebIDBKey WebIDBKey::CreateDate(double date) { - return WebIDBKey(IDBKey::CreateDate(date)); -} - -WebIDBKey WebIDBKey::CreateNumber(double number) { - return WebIDBKey(IDBKey::CreateNumber(number)); -} - -WebIDBKey WebIDBKey::CreateInvalid() { - return WebIDBKey(IDBKey::CreateInvalid()); -} - -WebIDBKey::WebIDBKey() noexcept = default; - -WebIDBKey::WebIDBKey(WebIDBKey&&) noexcept = default; -WebIDBKey& WebIDBKey::operator=(WebIDBKey&&) noexcept = default; - -WebIDBKey::~WebIDBKey() noexcept = default; - -std::unique_ptr<IDBKey> WebIDBKey::ReleaseIdbKey() noexcept { - return std::move(private_); -} - -WebIDBKey::WebIDBKey(std::unique_ptr<IDBKey> idb_key) noexcept - : private_(std::move(idb_key)) {} -WebIDBKey& WebIDBKey::operator=(std::unique_ptr<IDBKey> idb_key) noexcept { - private_ = std::move(idb_key); - return *this; -} - -WebIDBKey::WebIDBKey(const WebIDBKey& rkey) - : private_(IDBKey::Clone(rkey.private_)) {} -WebIDBKey& WebIDBKey::operator=(const WebIDBKey& rkey) { - private_ = IDBKey::Clone(rkey.private_); - return *this; -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_key.h b/third_party/blink/renderer/modules/indexeddb/web_idb_key.h deleted file mode 100644 index eac96067..0000000 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_key.h +++ /dev/null
@@ -1,175 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_KEY_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_KEY_H_ - -#include <memory> - -#include "third_party/blink/public/common/indexeddb/web_idb_types.h" -#include "third_party/blink/public/platform/web_data.h" -#include "third_party/blink/public/platform/web_private_ptr.h" -#include "third_party/blink/public/platform/web_string.h" -#include "third_party/blink/public/platform/web_vector.h" -#include "third_party/blink/renderer/modules/modules_export.h" - -namespace blink { - -class IDBKey; -class WebIDBKeyView; - -// Minimal interface for iterating over an IndexedDB array key. -// -// See WebIDBKeyView for the rationale behind this class' existence. -class WebIDBKeyArrayView { - public: - MODULES_EXPORT size_t size() const; - - MODULES_EXPORT WebIDBKeyView operator[](size_t index) const; - - private: - // Only WebIDBKeyView can vend WebIDBArrayKeyView instances. - friend class WebIDBKeyView; - explicit WebIDBKeyArrayView(const IDBKey* idb_key) : private_(idb_key) {} - - const IDBKey* const private_; -}; - -// Non-owning reference to an IndexedDB key. -// -// The Blink object wrapped by WebIDBKey is immutable, so WebIDBKeyView -// instances are implicitly const references. -// -// Having both WebIDBKeyView and WebIDBKey is extra complexity, and we pay this -// price to avoid unnecessary memory copying. Specifically, WebIDBKeyView is -// used to issue requests to the IndexedDB backing store. -// -// For example, IDBCursor.update() must send the cursor's primary key to the -// backing store. IDBCursor cannot give up the ownership of its primary key, -// because it might need to satisfy further update() or delete() calls. -class WebIDBKeyView { - public: - WebIDBKeyView(const WebIDBKeyView&) noexcept = default; - - explicit WebIDBKeyView(const IDBKey* idb_key) noexcept : private_(idb_key) {} - - MODULES_EXPORT mojom::IDBKeyType KeyType() const; - - MODULES_EXPORT bool IsValid() const; - - // Only valid for ArrayType. - // - // The caller is responsible for ensuring that the WebIDBKeyView is valid for - // the lifetime of the returned WeIDBKeyArrayView. - MODULES_EXPORT const WebIDBKeyArrayView ArrayView() const { - return WebIDBKeyArrayView(private_); - } - - // Only valid for BinaryType. - MODULES_EXPORT WebData Binary() const; - - // Only valid for StringType. - MODULES_EXPORT WebString String() const; - - // Only valid for DateType. - MODULES_EXPORT double Date() const; - - // Only valid for NumberType. - MODULES_EXPORT double Number() const; - - MODULES_EXPORT size_t SizeEstimate() const; - - // TODO(cmp): Ensure |private_| can never be null. - // - // SizeEstimate() can be called when |private_| is null. That happens if and - // only if the |WebIDBKey| instance is created using WebIDBKey::CreateNull(). - // - // Eventually, WebIDBKey::CreateNull() will change so that case will lead to - // a non-null |private_|. At that time, this null check can change to a - // DCHECK that |private_| is not null and the special null case handling can - // be removed. - MODULES_EXPORT bool IsNull() const { return !private_; } - - private: - const IDBKey* const private_; -}; - -// Move-only handler that owns an IndexedDB key. -// -// The wrapped Blink object wrapped is immutable while it is owned by the -// WebIDBKey. -// -// Having both WebIDBKeyView and WebIDBKeyArrayView is extra complexity, and we -// pay this price to avoid unnecessary memory copying. Specifically, WebIDBKey -// is used to receive data from the IndexedDB backing store. Once constructed, a -// WebIDBKey is moved through the layer cake until the underlying Blink object -// ends up at its final destination. -class WebIDBKey { - public: - MODULES_EXPORT static WebIDBKey CreateArray(WebVector<WebIDBKey>); - MODULES_EXPORT static WebIDBKey CreateBinary(const WebData&); - MODULES_EXPORT static WebIDBKey CreateString(const WebString&); - MODULES_EXPORT static WebIDBKey CreateDate(double); - MODULES_EXPORT static WebIDBKey CreateNumber(double); - MODULES_EXPORT static WebIDBKey CreateInvalid(); - MODULES_EXPORT static WebIDBKey CreateNull() noexcept { return WebIDBKey(); } - - // The default constructor must not be used explicitly. - // It is only provided for WebVector and Mojo's use. - MODULES_EXPORT WebIDBKey() noexcept; - - MODULES_EXPORT WebIDBKey(WebIDBKey&&) noexcept; - MODULES_EXPORT WebIDBKey& operator=(WebIDBKey&&) noexcept; - - // TODO(cmp): Remove copy and assignment constructors when Vector<->WebVector - // conversions are no longer needed. - MODULES_EXPORT WebIDBKey(const WebIDBKey& rkey); - MODULES_EXPORT WebIDBKey& operator=(const WebIDBKey& rkey); - - MODULES_EXPORT ~WebIDBKey(); - - MODULES_EXPORT WebIDBKeyView View() const { - return WebIDBKeyView(private_.get()); - } - - MODULES_EXPORT size_t SizeEstimate() const { return View().SizeEstimate(); } - -#if INSIDE_BLINK - explicit WebIDBKey(std::unique_ptr<IDBKey>) noexcept; - WebIDBKey& operator=(std::unique_ptr<IDBKey>) noexcept; - operator IDBKey*() const noexcept { return private_.get(); } - - std::unique_ptr<IDBKey> ReleaseIdbKey() noexcept; -#endif // INSIDE_BLINK - - private: - std::unique_ptr<IDBKey> private_; -}; - -using WebIDBIndexKeys = std::pair<int64_t, WebVector<WebIDBKey>>; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_KEY_H_
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_key_range.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_key_range.cc deleted file mode 100644 index dc09503..0000000 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_key_range.cc +++ /dev/null
@@ -1,77 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key_range.h" - -#include "third_party/blink/renderer/modules/indexeddb/idb_key.h" -#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key.h" - -namespace blink { - -void WebIDBKeyRange::Assign(const WebIDBKeyRange& other) { - private_ = other.private_; -} - -void WebIDBKeyRange::Assign(WebIDBKey lower, - WebIDBKey upper, - bool lower_open, - bool upper_open) { - if (!lower.View().IsValid() && !upper.View().IsValid()) { - private_.Reset(); - } else { - private_ = IDBKeyRange::Create(lower.ReleaseIdbKey(), upper.ReleaseIdbKey(), - lower_open ? IDBKeyRange::kLowerBoundOpen - : IDBKeyRange::kLowerBoundClosed, - upper_open ? IDBKeyRange::kUpperBoundOpen - : IDBKeyRange::kUpperBoundClosed); - } -} - -void WebIDBKeyRange::Reset() { - private_.Reset(); -} - -WebIDBKeyView WebIDBKeyRange::Lower() const { - if (!private_.Get()) - return WebIDBKeyView(nullptr); - return WebIDBKeyView(private_->Lower()); -} - -WebIDBKeyView WebIDBKeyRange::Upper() const { - if (!private_.Get()) - return WebIDBKeyView(nullptr); - return WebIDBKeyView(private_->Upper()); -} - -bool WebIDBKeyRange::LowerOpen() const { - return private_.Get() && private_->lowerOpen(); -} - -bool WebIDBKeyRange::UpperOpen() const { - return private_.Get() && private_->upperOpen(); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_key_range.h b/third_party/blink/renderer/modules/indexeddb/web_idb_key_range.h deleted file mode 100644 index 43d49823..0000000 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_key_range.h +++ /dev/null
@@ -1,83 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_KEY_RANGE_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_KEY_RANGE_H_ - -#include "third_party/blink/public/platform/web_private_ptr.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key.h" -#include "third_party/blink/renderer/modules/modules_export.h" - -namespace blink { - -class IDBKeyRange; - -class WebIDBKeyRange { - public: - ~WebIDBKeyRange() { Reset(); } - - WebIDBKeyRange() = default; - WebIDBKeyRange(const WebIDBKeyRange& key_range) { Assign(key_range); } - WebIDBKeyRange(WebIDBKey lower, - WebIDBKey upper, - bool lower_open, - bool upper_open) { - Assign(std::move(lower), std::move(upper), lower_open, upper_open); - } - - MODULES_EXPORT WebIDBKeyView Lower() const; - MODULES_EXPORT WebIDBKeyView Upper() const; - MODULES_EXPORT bool LowerOpen() const; - MODULES_EXPORT bool UpperOpen() const; - - MODULES_EXPORT void Assign(const WebIDBKeyRange&); - MODULES_EXPORT void Assign(WebIDBKey lower, - WebIDBKey upper, - bool lower_open, - bool upper_open); - - WebIDBKeyRange& operator=(const WebIDBKeyRange& e) { - Assign(e); - return *this; - } - - MODULES_EXPORT void Reset(); - -#if INSIDE_BLINK - WebIDBKeyRange(IDBKeyRange* value) : private_(value) {} - WebIDBKeyRange& operator=(IDBKeyRange* value) { - private_ = value; - return *this; - } - operator IDBKeyRange*() const { return private_.Get(); } -#endif - - private: - WebPrivatePtr<IDBKeyRange> private_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_WEB_IDB_KEY_RANGE_H_
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_observation.h b/third_party/blink/renderer/modules/indexeddb/web_idb_observation.h index 00aff73..31da4200 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_observation.h +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_observation.h
@@ -7,7 +7,7 @@ #include "third_party/blink/public/common/indexeddb/web_idb_types.h" #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-shared.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key_range.h" +#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_value.h" namespace blink { @@ -15,12 +15,12 @@ struct WebIDBObservation { int64_t object_store_id; mojom::IDBOperationType type; - WebIDBKeyRange key_range; + Persistent<IDBKeyRange> key_range; WebIDBValue value; WebIDBObservation(int64_t object_store_id, mojom::IDBOperationType type, - WebIDBKeyRange key_range, + IDBKeyRange* key_range, WebIDBValue value) : object_store_id(object_store_id), type(type),
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_value.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_value.cc index 546f29f6..1ffed78 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_value.cc +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_value.cc
@@ -10,7 +10,6 @@ #include "third_party/blink/renderer/modules/indexeddb/idb_key.h" #include "third_party/blink/renderer/modules/indexeddb/idb_key_path.h" #include "third_party/blink/renderer/modules/indexeddb/idb_value.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key.h" #include "third_party/blink/renderer/modules/indexeddb/web_idb_key_path.h" namespace blink { @@ -28,9 +27,9 @@ WebIDBValue::~WebIDBValue() noexcept = default; -void WebIDBValue::SetInjectedPrimaryKey(WebIDBKey primary_key, +void WebIDBValue::SetInjectedPrimaryKey(std::unique_ptr<IDBKey> primary_key, const WebIDBKeyPath& primary_key_path) { - private_->SetInjectedPrimaryKey(primary_key.ReleaseIdbKey(), + private_->SetInjectedPrimaryKey(std::move(primary_key), IDBKeyPath(primary_key_path)); }
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_value.h b/third_party/blink/renderer/modules/indexeddb/web_idb_value.h index f653fe60..c6611d2 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_value.h +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_value.h
@@ -10,11 +10,11 @@ #include "third_party/blink/public/platform/web_blob_info.h" #include "third_party/blink/public/platform/web_vector.h" -#include "third_party/blink/renderer/modules/indexeddb/web_idb_key.h" #include "third_party/blink/renderer/modules/modules_export.h" namespace blink { +class IDBKey; class IDBValue; class WebData; class WebIDBKeyPath; @@ -31,7 +31,7 @@ // Used by object stores that store primary keys separately from wire data. MODULES_EXPORT void SetInjectedPrimaryKey( - WebIDBKey primary_key, + std::unique_ptr<IDBKey> primary_key, const WebIDBKeyPath& primary_key_path); // Returns the Blobs associated with this value. Should only be used for
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.cc index 6e6749e..2c7aebd 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.cc +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.cc
@@ -20,7 +20,7 @@ namespace { // The default size of an overflow button in pixels. -constexpr int kDefaultButtonSize = 36; +constexpr int kDefaultButtonSize = 48; const char kOverflowContainerWithSubtitleCSSClass[] = "with-subtitle"; const char kOverflowSubtitleCSSClass[] = "subtitle";
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_remaining_time_display_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_remaining_time_display_element.cc index 0ef8bb5..4f7db11 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_remaining_time_display_element.cc +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_remaining_time_display_element.cc
@@ -6,6 +6,14 @@ #include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h" +namespace { + +// The during element has extra '/ ' in the text which takes approximately +// 9 pixels. +constexpr int kTimeDisplayExtraCharacterWidth = 9; + +} // namespace + namespace blink { MediaControlRemainingTimeDisplayElement:: @@ -16,6 +24,12 @@ AtomicString("-webkit-media-controls-time-remaining-display")); } +int MediaControlRemainingTimeDisplayElement::EstimateElementWidth() const { + // Add extra pixel width for during display since we have an extra "/ ". + return kTimeDisplayExtraCharacterWidth + + MediaControlTimeDisplayElement::EstimateElementWidth(); +} + String MediaControlRemainingTimeDisplayElement::FormatTime() const { // For the duration display, we prepend a "/ " to deliminate the current time // from the duration, e.g. "0:12 / 3:45".
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_remaining_time_display_element.h b/third_party/blink/renderer/modules/media_controls/elements/media_control_remaining_time_display_element.h index 241b8507e..bcec717 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_remaining_time_display_element.h +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_remaining_time_display_element.h
@@ -17,6 +17,8 @@ explicit MediaControlRemainingTimeDisplayElement(MediaControlsImpl&); private: + int EstimateElementWidth() const override; + String FormatTime() const override; };
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc index 2b72e374..9000462 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc
@@ -4,9 +4,21 @@ #include "third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.h" +#include "third_party/blink/public/platform/web_size.h" +#include "third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.h" #include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" +namespace { + +// These constants are used to estimate the size of time display element +// when the time display is hidden. +constexpr int kDefaultTimeDisplayDigitWidth = 8; +constexpr int kDefaultTimeDisplayColonWidth = 3; +constexpr int kDefaultTimeDisplayHeight = 48; + +} // namespace + namespace blink { MediaControlTimeDisplayElement::MediaControlTimeDisplayElement( @@ -23,6 +35,18 @@ return current_value_; } +WebSize MediaControlTimeDisplayElement::GetSizeOrDefault() const { + return MediaControlElementsHelper::GetSizeOrDefault( + *this, WebSize(EstimateElementWidth(), kDefaultTimeDisplayHeight)); +} + +int MediaControlTimeDisplayElement::EstimateElementWidth() const { + String formatted_time = MediaControlTimeDisplayElement::FormatTime(); + int colons = formatted_time.length() > 5 ? 2 : 1; + return kDefaultTimeDisplayColonWidth * colons + + kDefaultTimeDisplayDigitWidth * (formatted_time.length() - colons); +} + String MediaControlTimeDisplayElement::FormatTime() const { double time = std::isfinite(current_value_) ? current_value_ : 0;
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.h b/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.h index 28ce2852..b3c1395 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.h +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.h
@@ -19,9 +19,13 @@ // Exported to be used by modules/accessibility. MODULES_EXPORT double CurrentValue() const; + WebSize GetSizeOrDefault() const override; + protected: MediaControlTimeDisplayElement(MediaControlsImpl&, MediaControlElementType); + virtual int EstimateElementWidth() const; + virtual String FormatTime() const; private:
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc b/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc index cbeaf85..48708da4 100644 --- a/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc +++ b/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc
@@ -1076,8 +1076,10 @@ return false; // Don't hide if the mouse is over the controls. + // Touch focus shouldn't affect controls visibility. const bool ignore_controls_hover = behavior_flags & kIgnoreControlsHover; - if (!ignore_controls_hover && AreVideoControlsHovered()) + if (!ignore_controls_hover && AreVideoControlsHovered() && + !is_touch_interaction_) return false; // Don't hide if the mouse is over the video area. @@ -1484,7 +1486,8 @@ MakeTransparent(); } else { MakeOpaque(); - if (ShouldHideMediaControls(kIgnoreWaitForTimer)) { + // Touch focus shouldn't affect controls visibility. + if (ShouldHideMediaControls(kIgnoreWaitForTimer | kIgnoreFocus)) { keep_showing_until_timer_fires_ = true; StartHideMediaControlsTimer(); } @@ -1836,7 +1839,8 @@ } void MediaControlsImpl::OnFocusIn() { - if (!MediaElement().ShouldShowControls()) + // Touch focus shouldn't affect controls visibility. + if (!MediaElement().ShouldShowControls() || is_touch_interaction_) return; ResetHideMediaControlsTimer(); @@ -2265,10 +2269,15 @@ void MediaControlsImpl::OpenVolumeSliderIfNecessary() { if (ShouldOpenVolumeSlider()) { - volume_slider_wanted_timer_.StartOneShot(WebTestSupport::IsRunningWebTest() - ? kTimeToShowVolumeSliderTest - : kTimeToShowVolumeSlider, - FROM_HERE); + if (volume_slider_->IsFocused() || mute_button_->IsFocused()) { + // When we're focusing with the keyboard, we don't need the delay. + volume_slider_->OpenSlider(); + } else { + volume_slider_wanted_timer_.StartOneShot( + WebTestSupport::IsRunningWebTest() ? kTimeToShowVolumeSliderTest + : kTimeToShowVolumeSlider, + FROM_HERE); + } } } @@ -2292,7 +2301,8 @@ if (!volume_slider_ || !IsModern()) return false; - return !(volume_slider_->IsHovered() || mute_button_->IsHovered()); + return !(volume_slider_->IsHovered() || mute_button_->IsHovered() || + volume_slider_->IsFocused() || mute_button_->IsFocused()); } const MediaControlDownloadButtonElement& MediaControlsImpl::DownloadButton()
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc b/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc index 60a132a..bb79039 100644 --- a/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc +++ b/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc
@@ -1376,6 +1376,32 @@ EXPECT_TRUE(volume_slider->classList().contains("closed")); } +TEST_F(MediaControlsImplTestWithMockScheduler, + VolumeSliderBehaviorWhenFocused) { + MediaControls().MediaElement().SetSrc("https://example.com/foo.mp4"); + platform()->RunForPeriodSeconds(1); + SetHasAudio(true); + + WebTestSupport::SetIsRunningWebTest(false); + + Element* volume_slider = GetElementByShadowPseudoId( + MediaControls(), "-webkit-media-controls-volume-slider"); + + ASSERT_NE(nullptr, volume_slider); + + // Volume slider starts out hidden + EXPECT_TRUE(volume_slider->classList().contains("closed")); + + // Tab focus should open volume slider immediately. + volume_slider->SetFocused(true, WebFocusType::kWebFocusTypeNone); + volume_slider->DispatchEvent(*Event::Create("focus")); + EXPECT_FALSE(volume_slider->classList().contains("closed")); + + // Unhover slider while focused should not close slider. + volume_slider->DispatchEvent(*Event::Create("mouseout")); + EXPECT_FALSE(volume_slider->classList().contains("closed")); +} + TEST_F(MediaControlsImplTest, CastOverlayDefaultHidesOnTimer) { MediaControls().MediaElement().SetBooleanAttribute(html_names::kControlsAttr, false);
diff --git a/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc b/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc index e09ad43..01b79e3 100644 --- a/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc +++ b/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc
@@ -17,6 +17,7 @@ #include "third_party/blink/renderer/modules/mediarecorder/blob_event.h" #include "third_party/blink/renderer/platform/blob/blob_data.h" #include "third_party/blink/renderer/platform/network/mime/content_type.h" +#include "third_party/blink/renderer/platform/wtf/functional.h" #include "third_party/blink/renderer/platform/wtf/time.h" namespace blink { @@ -139,48 +140,35 @@ MediaRecorder* MediaRecorder::Create(ExecutionContext* context, MediaStream* stream, ExceptionState& exception_state) { - MediaRecorder* recorder = MakeGarbageCollected<MediaRecorder>( + return MakeGarbageCollected<MediaRecorder>( context, stream, MediaRecorderOptions::Create(), exception_state); - recorder->PauseIfNeeded(); - - return recorder; } MediaRecorder* MediaRecorder::Create(ExecutionContext* context, MediaStream* stream, const MediaRecorderOptions* options, ExceptionState& exception_state) { - MediaRecorder* recorder = MakeGarbageCollected<MediaRecorder>( - context, stream, options, exception_state); - recorder->PauseIfNeeded(); - - return recorder; + return MakeGarbageCollected<MediaRecorder>(context, stream, options, + exception_state); } MediaRecorder::MediaRecorder(ExecutionContext* context, MediaStream* stream, const MediaRecorderOptions* options, ExceptionState& exception_state) - : PausableObject(context), + : ContextLifecycleObserver(context), stream_(stream), mime_type_(options->hasMimeType() ? options->mimeType() : kDefaultMimeType), stopped_(true), audio_bits_per_second_(0), video_bits_per_second_(0), - state_(State::kInactive), - // MediaStream recording should use DOM manipulation task source. - // https://www.w3.org/TR/mediastream-recording/ - dispatch_scheduled_event_runner_(AsyncMethodRunner<MediaRecorder>::Create( - this, - &MediaRecorder::DispatchScheduledEvent, - context->GetTaskRunner(TaskType::kDOMManipulation))) { + state_(State::kInactive) { if (context->IsContextDestroyed()) { exception_state.ThrowDOMException(DOMExceptionCode::kNotAllowedError, "Execution context is detached."); return; } - DCHECK(stream_->getTracks().size()); recorder_handler_ = Platform::Current()->CreateMediaRecorderHandler( context->GetTaskRunner(TaskType::kInternalMediaRealTime)); @@ -324,15 +312,7 @@ } ExecutionContext* MediaRecorder::GetExecutionContext() const { - return PausableObject::GetExecutionContext(); -} - -void MediaRecorder::Pause() { - dispatch_scheduled_event_runner_->Pause(); -} - -void MediaRecorder::Unpause() { - dispatch_scheduled_event_runner_->Unpause(); + return ContextLifecycleObserver::GetExecutionContext(); } void MediaRecorder::ContextDestroyed(ExecutionContext*) { @@ -394,8 +374,17 @@ void MediaRecorder::ScheduleDispatchEvent(Event* event) { scheduled_events_.push_back(event); - - dispatch_scheduled_event_runner_->RunAsync(); + // Only schedule a post if we are placing the first item in the queue. + if (scheduled_events_.size() == 1) { + if (auto* context = GetExecutionContext()) { + // MediaStream recording should use DOM manipulation task source. + // https://www.w3.org/TR/mediastream-recording/ + context->GetTaskRunner(TaskType::kDOMManipulation) + ->PostTask(FROM_HERE, + WTF::Bind(&MediaRecorder::DispatchScheduledEvent, + WrapPersistent(this))); + } + } } void MediaRecorder::DispatchScheduledEvent() { @@ -408,10 +397,9 @@ void MediaRecorder::Trace(blink::Visitor* visitor) { visitor->Trace(stream_); - visitor->Trace(dispatch_scheduled_event_runner_); visitor->Trace(scheduled_events_); EventTargetWithInlineData::Trace(visitor); - PausableObject::Trace(visitor); + ContextLifecycleObserver::Trace(visitor); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/mediarecorder/media_recorder.h b/third_party/blink/renderer/modules/mediarecorder/media_recorder.h index aaf3ab16c..e9aca43e 100644 --- a/third_party/blink/renderer/modules/mediarecorder/media_recorder.h +++ b/third_party/blink/renderer/modules/mediarecorder/media_recorder.h
@@ -15,7 +15,6 @@ #include "third_party/blink/renderer/modules/mediarecorder/media_recorder_options.h" #include "third_party/blink/renderer/modules/mediastream/media_stream.h" #include "third_party/blink/renderer/modules/modules_export.h" -#include "third_party/blink/renderer/platform/async_method_runner.h" namespace blink { @@ -27,7 +26,7 @@ : public EventTargetWithInlineData, public WebMediaRecorderHandlerClient, public ActiveScriptWrappable<MediaRecorder>, - public PausableObject { + public ContextLifecycleObserver { USING_GARBAGE_COLLECTED_MIXIN(MediaRecorder); DEFINE_WRAPPERTYPEINFO(); @@ -74,9 +73,7 @@ const AtomicString& InterfaceName() const override; ExecutionContext* GetExecutionContext() const override; - // PausableObject - void Pause() override; - void Unpause() override; + // ContextLifecycleObserver void ContextDestroyed(ExecutionContext* context) override; // ScriptWrappable @@ -110,7 +107,6 @@ std::unique_ptr<WebMediaRecorderHandler> recorder_handler_; - Member<AsyncMethodRunner<MediaRecorder>> dispatch_scheduled_event_runner_; HeapVector<Member<Event>> scheduled_events_; };
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni index ce6f8931..e348d15 100644 --- a/third_party/blink/renderer/modules/modules_idl_files.gni +++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -403,6 +403,8 @@ "webgl/webgl_draw_buffers.idl", "webgl/webgl_framebuffer.idl", "webgl/webgl_lose_context.idl", + "webgl/webgl_multi_draw_instanced.idl", + "webgl/webgl_multi_draw.idl", "webgl/webgl_multiview.idl", "webgl/webgl_program.idl", "webgl/webgl_query.idl",
diff --git a/third_party/blink/renderer/modules/nfc/nfc.cc b/third_party/blink/renderer/modules/nfc/nfc.cc index f5996e9..0de8637 100644 --- a/third_party/blink/renderer/modules/nfc/nfc.cc +++ b/third_party/blink/renderer/modules/nfc/nfc.cc
@@ -858,8 +858,10 @@ auto it = callbacks_.find(id); if (it != callbacks_.end()) { V8MessageCallback* callback = it->value; - ScriptState* script_state = callback->CallbackRelevantScriptState(); - DCHECK(script_state); + ScriptState* script_state = + callback->CallbackRelevantScriptStateOrReportError("NFC", "watch"); + if (!script_state) + continue; ScriptState::Scope scope(script_state); const NFCMessage* nfc_message = ToNFCMessage(script_state, message); callback->InvokeAndReportException(nullptr, nfc_message);
diff --git a/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.idl b/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.idl index 587cb1f4..d40f95d 100644 --- a/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.idl +++ b/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.idl
@@ -9,6 +9,6 @@ ImplementedAs=ServiceWorkerRegistrationNotifications, RuntimeEnabled=Notifications ] partial interface ServiceWorkerRegistration { - [CallWith=ScriptState, RaisesException] Promise showNotification(DOMString title, optional NotificationOptions options); + [CallWith=ScriptState, RaisesException] Promise<void> showNotification(DOMString title, optional NotificationOptions options); [CallWith=ScriptState] Promise<sequence<Notification>> getNotifications(optional GetNotificationOptions filter); };
diff --git a/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.cc b/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.cc index 3d86413..55992d19 100644 --- a/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.cc +++ b/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.cc
@@ -38,8 +38,8 @@ DCHECK(GetExecutionContext()); ExceptionState exception_state(value.GetIsolate(), context_type, interface_name, property_name); - bool response = - ToBoolean(value.GetIsolate(), value.V8Value(), exception_state); + bool response = ToBoolean(ToIsolate(GetExecutionContext()), value.V8Value(), + exception_state); if (exception_state.HadException()) { exception_state.ClearException(); OnResponseRejected(blink::mojom::ServiceWorkerResponseError::kNoV8Instance);
diff --git a/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.cc b/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.cc index 0a61048..41e87e2 100644 --- a/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.cc +++ b/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.cc
@@ -38,8 +38,8 @@ DCHECK(GetExecutionContext()); ExceptionState exception_state(value.GetIsolate(), context_type, interface_name, property_name); - bool response = - ToBoolean(value.GetIsolate(), value.V8Value(), exception_state); + bool response = ToBoolean(ToIsolate(GetExecutionContext()), value.V8Value(), + exception_state); if (exception_state.HadException()) { exception_state.ClearException(); OnResponseRejected(blink::mojom::ServiceWorkerResponseError::kNoV8Instance);
diff --git a/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.cc b/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.cc index cfdcd13..c8e5ee19 100644 --- a/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.cc +++ b/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.cc
@@ -47,7 +47,7 @@ interface_name, property_name); PaymentHandlerResponse* response = NativeValueTraits<PaymentHandlerResponse>::NativeValue( - value.GetIsolate(), value.V8Value(), exception_state); + ToIsolate(GetExecutionContext()), value.V8Value(), exception_state); if (exception_state.HadException()) { exception_state.ClearException(); OnResponseRejected(mojom::ServiceWorkerResponseError::kNoV8Instance);
diff --git a/third_party/blink/renderer/modules/push_messaging/push_manager.idl b/third_party/blink/renderer/modules/push_messaging/push_manager.idl index 14411230..d9ace9fa 100644 --- a/third_party/blink/renderer/modules/push_messaging/push_manager.idl +++ b/third_party/blink/renderer/modules/push_messaging/push_manager.idl
@@ -13,5 +13,5 @@ [CallWith=ScriptState, RaisesException] Promise<PushSubscription> subscribe(optional PushSubscriptionOptionsInit options); [CallWith=ScriptState] Promise<PushSubscription?> getSubscription(); - [CallWith=ScriptState, RaisesException] Promise permissionState(optional PushSubscriptionOptionsInit options); + [CallWith=ScriptState, RaisesException] Promise<PushPermissionState> permissionState(optional PushSubscriptionOptionsInit options); };
diff --git a/third_party/blink/renderer/modules/screen_orientation/screen_orientation.idl b/third_party/blink/renderer/modules/screen_orientation/screen_orientation.idl index f46ee29..3343e61 100644 --- a/third_party/blink/renderer/modules/screen_orientation/screen_orientation.idl +++ b/third_party/blink/renderer/modules/screen_orientation/screen_orientation.idl
@@ -26,7 +26,7 @@ [MeasureAs=ScreenOrientationAngle] readonly attribute unsigned short angle; [MeasureAs=ScreenOrientationType] readonly attribute DOMString type; - [CallWith=ScriptState, MeasureAs=ScreenOrientationLock] Promise lock(OrientationLockType orientation); + [CallWith=ScriptState, MeasureAs=ScreenOrientationLock] Promise<void> lock(OrientationLockType orientation); [MeasureAs=ScreenOrientationUnlock] void unlock(); attribute EventHandler onchange;
diff --git a/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc b/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc index c21c0f7..d8cd91c6 100644 --- a/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc +++ b/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc
@@ -233,12 +233,13 @@ const char* interface_name, const char* property_name) { DCHECK(GetExecutionContext()); - if (!V8Response::HasInstance(value.V8Value(), value.GetIsolate())) { + if (!V8Response::HasInstance(value.V8Value(), + ToIsolate(GetExecutionContext()))) { OnResponseRejected(ServiceWorkerResponseError::kNoV8Instance); return; } - Response* response = - V8Response::ToImplWithTypeCheck(value.GetIsolate(), value.V8Value()); + Response* response = V8Response::ToImplWithTypeCheck( + ToIsolate(GetExecutionContext()), value.V8Value()); // "If one of the following conditions is true, return a network error: // - |response|'s type is |error|. // - |request|'s mode is |same-origin| and |response|'s type is |cors|.
diff --git a/third_party/blink/renderer/modules/time_zone_monitor/time_zone_monitor_client.cc b/third_party/blink/renderer/modules/time_zone_monitor/time_zone_monitor_client.cc index 8367c44..7438528 100644 --- a/third_party/blink/renderer/modules/time_zone_monitor/time_zone_monitor_client.cc +++ b/third_party/blink/renderer/modules/time_zone_monitor/time_zone_monitor_client.cc
@@ -30,7 +30,7 @@ void NotifyTimezoneChangeOnWorkerThread(WorkerThread* worker_thread) { DCHECK(worker_thread->IsCurrentThread()); - NotifyTimezoneChangeToV8(worker_thread->GlobalScope()->GetIsolate()); + NotifyTimezoneChangeToV8(ToIsolate(worker_thread->GlobalScope())); } } // namespace
diff --git a/third_party/blink/renderer/modules/vr/navigator_vr.idl b/third_party/blink/renderer/modules/vr/navigator_vr.idl index 7e7fc582..86ae2c92 100644 --- a/third_party/blink/renderer/modules/vr/navigator_vr.idl +++ b/third_party/blink/renderer/modules/vr/navigator_vr.idl
@@ -10,5 +10,5 @@ [SecureContext, OriginTrialEnabled=WebXR, MeasureAs=NavigatorXR] readonly attribute XR xr; // Legacy API - [OriginTrialEnabled=WebVR, CallWith=ScriptState] Promise getVRDisplays(); + [OriginTrialEnabled=WebVR, CallWith=ScriptState] Promise<sequence<VRDisplay>> getVRDisplays(); };
diff --git a/third_party/blink/renderer/modules/vr/vr_display.idl b/third_party/blink/renderer/modules/vr/vr_display.idl index 026d6ce..5f8be46 100644 --- a/third_party/blink/renderer/modules/vr/vr_display.idl +++ b/third_party/blink/renderer/modules/vr/vr_display.idl
@@ -38,10 +38,10 @@ // Begin presenting to the VRDisplay. Must be called in response to a user // gesture. Repeat calls while already presenting will update the layer // being displayed. - [CallWith=ScriptState] Promise requestPresent(sequence<VRLayerInit> layers); + [CallWith=ScriptState] Promise<void> requestPresent(sequence<VRLayerInit> layers); // Stops presenting to the VRDisplay. - [CallWith=ScriptState] Promise exitPresent(); + [CallWith=ScriptState] Promise<void> exitPresent(); // Get the sources currently being presented. sequence<VRLayerInit> getLayers();
diff --git a/third_party/blink/renderer/modules/wake_lock/DEPS b/third_party/blink/renderer/modules/wake_lock/DEPS index 5f009fc2..23424fb8 100644 --- a/third_party/blink/renderer/modules/wake_lock/DEPS +++ b/third_party/blink/renderer/modules/wake_lock/DEPS
@@ -3,6 +3,5 @@ "+services/device/public/mojom", "+services/device/public/interfaces/constants.mojom-blink.h", "+services/device/public/mojom/wake_lock.mojom-blink.h", - "+services/device/public/mojom/wake_lock_provider.mojom-blink.h", "+third_party/blink/renderer/modules/event_target_modules.h", ]
diff --git a/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.idl b/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.idl index 609ac6e8..3e14fe2 100644 --- a/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.idl +++ b/third_party/blink/renderer/modules/wake_lock/navigator_wake_lock.idl
@@ -9,5 +9,5 @@ ImplementedAs=NavigatorWakeLock, RuntimeEnabled=WakeLockNavigator ] partial interface Navigator { - [CallWith=ScriptState] Promise getWakeLock(WakeLockType type); -}; \ No newline at end of file + [CallWith=ScriptState] Promise<WakeLock> getWakeLock(WakeLockType type); +};
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock.cc index 0c317e5..a7d14d0 100644 --- a/third_party/blink/renderer/modules/wake_lock/wake_lock.cc +++ b/third_party/blink/renderer/modules/wake_lock/wake_lock.cc
@@ -5,10 +5,10 @@ #include "third_party/blink/renderer/modules/wake_lock/wake_lock.h" #include "services/device/public/mojom/constants.mojom-blink.h" -#include "services/device/public/mojom/wake_lock_provider.mojom-blink.h" +#include "services/device/public/mojom/wake_lock.mojom-blink.h" #include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/interface_provider.h" -#include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/public/mojom/wake_lock/wake_lock.mojom-blink.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/dom/events/event.h" @@ -94,17 +94,23 @@ break; } - device::mojom::blink::WakeLockProviderPtr provider; - Platform::Current()->GetConnector()->BindInterface( - device::mojom::blink::kServiceName, mojo::MakeRequest(&provider)); - provider->GetWakeLockWithoutContext( - type, device::mojom::blink::WakeLockReason::kOther, "Blink Wake Lock", - mojo::MakeRequest(&wake_lock_service_)); + if (!GetDocument() || !GetDocument()->GetFrame()) + return; + blink::mojom::blink::WakeLockServicePtr service; + GetDocument()->GetFrame()->GetInterfaceProvider().GetInterface( + mojo::MakeRequest(&service)); + service->GetWakeLock(type, device::mojom::blink::WakeLockReason::kOther, + "Blink Wake Lock", + mojo::MakeRequest(&wake_lock_service_)); wake_lock_service_.set_connection_error_handler( WTF::Bind(&WakeLock::OnConnectionError, WrapWeakPersistent(this))); } +Document* WakeLock::GetDocument() { + return To<Document>(GetExecutionContext()); +} + WakeLockRequest* WakeLock::createRequest() { if (!active_ && request_counter_ == 0) ChangeActiveStatus(true);
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock.h b/third_party/blink/renderer/modules/wake_lock/wake_lock.h index 0355ec6..709c2860 100644 --- a/third_party/blink/renderer/modules/wake_lock/wake_lock.h +++ b/third_party/blink/renderer/modules/wake_lock/wake_lock.h
@@ -16,6 +16,7 @@ namespace blink { +class Document; class WakeLockRequest; class WakeLock final : public EventTargetWithInlineData, @@ -73,6 +74,9 @@ // Binds to the Wake Lock mojo service void BindToServiceIfNeeded(); + // Returns the document associated with the object. nullptr if there is none. + Document* GetDocument(); + device::mojom::blink::WakeLockPtr wake_lock_service_; int request_counter_ = 0;
diff --git a/third_party/blink/renderer/modules/webaudio/BUILD.gn b/third_party/blink/renderer/modules/webaudio/BUILD.gn index 52ec0bf..7ca12c1 100644 --- a/third_party/blink/renderer/modules/webaudio/BUILD.gn +++ b/third_party/blink/renderer/modules/webaudio/BUILD.gn
@@ -30,6 +30,8 @@ "audio_node_input.h", "audio_node_output.cc", "audio_node_output.h", + "audio_node_wiring.cc", + "audio_node_wiring.h", "audio_param.cc", "audio_param.h", "audio_param_map.cc",
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context.cc b/third_party/blink/renderer/modules/webaudio/audio_context.cc index bbbb92b..3ff688d 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_context.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_context.cc
@@ -49,7 +49,6 @@ const AudioContextOptions* context_options, ExceptionState& exception_state) { DCHECK(IsMainThread()); - LOG(ERROR) << __func__; UseCounter::CountCrossOriginIframe( document, WebFeature::kAudioContextCrossOriginIframe); @@ -91,7 +90,6 @@ audio_context->MaybeAllowAutoplayWithUnlockType( AutoplayUnlockType::kContextConstructor); if (audio_context->IsAllowedToStart()) { - LOG(ERROR) << "starting"; audio_context->StartRendering(); audio_context->SetContextState(kRunning); } @@ -128,15 +126,12 @@ : BaseAudioContext(&document, kRealtimeContext), context_id_(g_context_id++) { destination_node_ = DefaultAudioDestinationNode::Create(this, latency_hint); - LOG(ERROR) << __func__; switch (GetAutoplayPolicy()) { case AutoplayPolicy::Type::kNoUserGestureRequired: - LOG(ERROR) << "no user gesture"; break; case AutoplayPolicy::Type::kUserGestureRequired: case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin: - LOG(ERROR) << "user gesture"; if (document.GetFrame() && document.GetFrame()->IsCrossOriginSubframe()) { autoplay_status_ = AutoplayStatus::kAutoplayStatusFailed; @@ -144,7 +139,6 @@ } break; case AutoplayPolicy::Type::kDocumentUserActivationRequired: - LOG(ERROR) << "document user activation"; autoplay_status_ = AutoplayStatus::kAutoplayStatusFailed; user_gesture_required_ = true; break; @@ -204,7 +198,6 @@ ScriptPromise AudioContext::resumeContext(ScriptState* script_state) { DCHECK(IsMainThread()); - LOG(ERROR) << __func__; if (IsContextClosed()) { return ScriptPromise::RejectWithDOMException( @@ -434,7 +427,6 @@ } bool AudioContext::IsAllowedToStart() const { - LOG(ERROR) << __func__; if (!user_gesture_required_) return true;
diff --git a/third_party/blink/renderer/modules/webaudio/audio_node.cc b/third_party/blink/renderer/modules/webaudio/audio_node.cc index b2e018d1..55a3610b 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_node.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_node.cc
@@ -27,6 +27,7 @@ #include "third_party/blink/renderer/modules/webaudio/audio_node_input.h" #include "third_party/blink/renderer/modules/webaudio/audio_node_options.h" #include "third_party/blink/renderer/modules/webaudio/audio_node_output.h" +#include "third_party/blink/renderer/modules/webaudio/audio_node_wiring.h" #include "third_party/blink/renderer/modules/webaudio/audio_param.h" #include "third_party/blink/renderer/modules/webaudio/base_audio_context.h" #include "third_party/blink/renderer/platform/bindings/exception_messages.h" @@ -729,9 +730,8 @@ return nullptr; } - destination->Handler() - .Input(input_index) - .Connect(Handler().Output(output_index)); + AudioNodeWiring::Connect(Handler().Output(output_index), + destination->Handler().Input(input_index)); if (!connected_nodes_[output_index]) { connected_nodes_[output_index] = MakeGarbageCollected<HeapHashSet<Member<AudioNode>>>(); @@ -779,7 +779,7 @@ return; } - param->Handler().Connect(Handler().Output(output_index)); + AudioNodeWiring::Connect(Handler().Output(output_index), param->Handler()); if (!connected_params_[output_index]) { connected_params_[output_index] = MakeGarbageCollected<HeapHashSet<Member<AudioParam>>>(); @@ -802,9 +802,9 @@ AudioNodeOutput& output = Handler().Output(output_index); AudioNodeInput& input = destination.Handler().Input(input_index_of_destination); - if (!output.IsConnectedToInput(input)) + if (!AudioNodeWiring::IsConnected(output, input)) return false; - output.DisconnectInput(input); + AudioNodeWiring::Disconnect(output, input); connected_nodes_[output_index]->erase(&destination); return true; } @@ -812,9 +812,9 @@ bool AudioNode::DisconnectFromOutputIfConnected(unsigned output_index, AudioParam& param) { AudioNodeOutput& output = Handler().Output(output_index); - if (!output.IsConnectedToAudioParam(param.Handler())) + if (!AudioNodeWiring::IsConnected(output, param.Handler())) return false; - output.DisconnectAudioParam(param.Handler()); + AudioNodeWiring::Disconnect(output, param.Handler()); connected_params_[output_index]->erase(¶m); return true; }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_node_input.cc b/third_party/blink/renderer/modules/webaudio/audio_node_input.cc index 390f660..10ee03a 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_node_input.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_node_input.cc
@@ -30,6 +30,7 @@ #include "base/memory/ptr_util.h" #include "third_party/blink/renderer/modules/webaudio/audio_node_output.h" +#include "third_party/blink/renderer/modules/webaudio/audio_node_wiring.h" namespace blink { @@ -42,85 +43,13 @@ } AudioNodeInput::~AudioNodeInput() { - GetDeferredTaskHandler().AssertGraphOwner(); - - for (AudioNodeOutput* output : outputs_) - output->RemoveInput(*this); - for (AudioNodeOutput* output : disabled_outputs_) - output->RemoveInput(*this); - outputs_.clear(); - disabled_outputs_.clear(); - ChangedOutputs(); + AudioNodeWiring::WillBeDestroyed(*this); } std::unique_ptr<AudioNodeInput> AudioNodeInput::Create(AudioHandler& handler) { return base::WrapUnique(new AudioNodeInput(handler)); } -void AudioNodeInput::Connect(AudioNodeOutput& output) { - GetDeferredTaskHandler().AssertGraphOwner(); - - // Check if we're already connected to this output. - if (outputs_.Contains(&output)) - return; - - output.AddInput(*this); - outputs_.insert(&output); - ChangedOutputs(); -} - -void AudioNodeInput::Disconnect(AudioNodeOutput& output) { - GetDeferredTaskHandler().AssertGraphOwner(); - - // First try to disconnect from "active" connections. - if (outputs_.Contains(&output)) { - outputs_.erase(&output); - ChangedOutputs(); - output.RemoveInput(*this); - // Note: it's important to return immediately after removeInput() calls - // since the node may be deleted. - return; - } - - // Otherwise, try to disconnect from disabled connections. - if (disabled_outputs_.Contains(&output)) { - disabled_outputs_.erase(&output); - output.RemoveInput(*this); - // Note: it's important to return immediately after all removeInput() calls - // since the node may be deleted. - return; - } - - NOTREACHED(); -} - -void AudioNodeInput::Disable(AudioNodeOutput& output) { - GetDeferredTaskHandler().AssertGraphOwner(); - DCHECK(outputs_.Contains(&output)); - - disabled_outputs_.insert(&output); - outputs_.erase(&output); - ChangedOutputs(); - - // Propagate disabled state to outputs. - Handler().DisableOutputsIfNecessary(); -} - -void AudioNodeInput::Enable(AudioNodeOutput& output) { - GetDeferredTaskHandler().AssertGraphOwner(); - - // Move output from disabled list to active list. - outputs_.insert(&output); - if (disabled_outputs_.size() > 0) { - DCHECK(disabled_outputs_.Contains(&output)); - disabled_outputs_.erase(&output); - } - ChangedOutputs(); - - // Propagate enabled state to outputs. - Handler().EnableOutputsIfNecessary(); -} - void AudioNodeInput::DidUpdate() { Handler().CheckNumberOfChannelsForInput(this); }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_node_input.h b/third_party/blink/renderer/modules/webaudio/audio_node_input.h index 77033ce..3245e4d 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_node_input.h +++ b/third_party/blink/renderer/modules/webaudio/audio_node_input.h
@@ -43,7 +43,9 @@ // input will act as a unity-gain summing junction, mixing all the outputs. The // number of channels of the input's bus is the maximum of the number of // channels of all its connections. - +// +// Use AudioNodeWiring to connect the AudioNodeOutput of another node to this, +// and to disconnect, enable or disable that connection afterward. class MODULES_EXPORT AudioNodeInput final : public AudioSummingJunction { USING_FAST_MALLOC(AudioNodeInput); @@ -57,17 +59,6 @@ // Can be called from any thread. AudioHandler& Handler() const { return handler_; } - // Must be called with the context's graph lock. - void Connect(AudioNodeOutput&); - void Disconnect(AudioNodeOutput&); - - // disable() will take the output out of the active connections list and set - // aside in a disabled list. - // enable() will put the output back into the active connections list. - // Must be called with the context's graph lock. - void Enable(AudioNodeOutput&); - void Disable(AudioNodeOutput&); - // pull() processes all of the AudioNodes connected to us. // In the case of multiple connections it sums the result into an internal // summing bus. In the single connection case, it allows in-place processing @@ -112,6 +103,9 @@ void SumAllConnections(AudioBus* summing_bus, uint32_t frames_to_process); scoped_refptr<AudioBus> internal_summing_bus_; + + // Used to connect inputs and outputs together. + friend class AudioNodeWiring; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/audio_node_input_test.cc b/third_party/blink/renderer/modules/webaudio/audio_node_input_test.cc index 072bf6f5..3d00fb4 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_node_input_test.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_node_input_test.cc
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/core/testing/dummy_page_holder.h" #include "third_party/blink/renderer/modules/webaudio/audio_node_input.h" #include "third_party/blink/renderer/modules/webaudio/audio_node_output.h" +#include "third_party/blink/renderer/modules/webaudio/audio_node_wiring.h" #include "third_party/blink/renderer/modules/webaudio/delay_node.h" #include "third_party/blink/renderer/modules/webaudio/offline_audio_context.h" @@ -28,7 +29,7 @@ { BaseAudioContext::GraphAutoLocker graph_lock(context); - input->Connect(*output); + AudioNodeWiring::Connect(*output, *input); ASSERT_TRUE(output->IsConnected()); // This should not crash. @@ -52,7 +53,7 @@ { BaseAudioContext::GraphAutoLocker graph_lock(context); - input->Connect(*output); + AudioNodeWiring::Connect(*output, *input); ASSERT_TRUE(output->IsConnected()); // This should not crash.
diff --git a/third_party/blink/renderer/modules/webaudio/audio_node_output.cc b/third_party/blink/renderer/modules/webaudio/audio_node_output.cc index def68ddf..71019c0 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_node_output.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_node_output.cc
@@ -29,6 +29,7 @@ #include "base/memory/ptr_util.h" #include "third_party/blink/renderer/modules/webaudio/audio_node_input.h" +#include "third_party/blink/renderer/modules/webaudio/audio_node_wiring.h" #include "third_party/blink/renderer/modules/webaudio/base_audio_context.h" #include "third_party/blink/renderer/platform/wtf/threading.h" @@ -162,54 +163,26 @@ return rendering_fan_out_count_; } -void AudioNodeOutput::AddInput(AudioNodeInput& input) { - GetDeferredTaskHandler().AssertGraphOwner(); - inputs_.insert(&input); - input.Handler().MakeConnection(); -} - -void AudioNodeOutput::RemoveInput(AudioNodeInput& input) { - GetDeferredTaskHandler().AssertGraphOwner(); - input.Handler().BreakConnectionWithLock(); - inputs_.erase(&input); -} - void AudioNodeOutput::DisconnectAllInputs() { GetDeferredTaskHandler().AssertGraphOwner(); - // AudioNodeInput::disconnect() changes m_inputs by calling removeInput(). - while (!inputs_.IsEmpty()) - (*inputs_.begin())->Disconnect(*this); -} - -void AudioNodeOutput::DisconnectInput(AudioNodeInput& input) { - GetDeferredTaskHandler().AssertGraphOwner(); - DCHECK(IsConnectedToInput(input)); - input.Disconnect(*this); -} - -void AudioNodeOutput::DisconnectAudioParam(AudioParamHandler& param) { - GetDeferredTaskHandler().AssertGraphOwner(); - DCHECK(IsConnectedToAudioParam(param)); - param.Disconnect(*this); -} - -void AudioNodeOutput::AddParam(AudioParamHandler& param) { - GetDeferredTaskHandler().AssertGraphOwner(); - params_.insert(¶m); -} - -void AudioNodeOutput::RemoveParam(AudioParamHandler& param) { - GetDeferredTaskHandler().AssertGraphOwner(); - params_.erase(¶m); + // Disconnect changes inputs_, so we can't iterate directly over the hash set. + Vector<AudioNodeInput*, 4> inputs; + CopyToVector(inputs_, inputs); + for (AudioNodeInput* input : inputs) + AudioNodeWiring::Disconnect(*this, *input); + DCHECK(inputs_.IsEmpty()); } void AudioNodeOutput::DisconnectAllParams() { GetDeferredTaskHandler().AssertGraphOwner(); - // AudioParam::disconnect() changes m_params by calling removeParam(). - while (!params_.IsEmpty()) - (*params_.begin())->Disconnect(*this); + // Disconnect changes params_, so we can't iterate directly over the hash set. + Vector<AudioParamHandler*, 4> params; + CopyToVector(params_, params); + for (AudioParamHandler* param : params) + AudioNodeWiring::Disconnect(*this, *param); + DCHECK(params_.IsEmpty()); } void AudioNodeOutput::DisconnectAll() { @@ -217,23 +190,13 @@ DisconnectAllParams(); } -bool AudioNodeOutput::IsConnectedToInput(AudioNodeInput& input) { - GetDeferredTaskHandler().AssertGraphOwner(); - return inputs_.Contains(&input); -} - -bool AudioNodeOutput::IsConnectedToAudioParam(AudioParamHandler& param) { - GetDeferredTaskHandler().AssertGraphOwner(); - return params_.Contains(¶m); -} - void AudioNodeOutput::Disable() { GetDeferredTaskHandler().AssertGraphOwner(); if (is_enabled_) { is_enabled_ = false; - for (AudioNodeInput* i : inputs_) - i->Disable(*this); + for (AudioNodeInput* input : inputs_) + AudioNodeWiring::Disable(*this, *input); } } @@ -242,8 +205,8 @@ if (!is_enabled_) { is_enabled_ = true; - for (AudioNodeInput* i : inputs_) - i->Enable(*this); + for (AudioNodeInput* input : inputs_) + AudioNodeWiring::Enable(*this, *input); } }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_node_output.h b/third_party/blink/renderer/modules/webaudio/audio_node_output.h index 2f136c2..dd84388 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_node_output.h +++ b/third_party/blink/renderer/modules/webaudio/audio_node_output.h
@@ -70,7 +70,6 @@ void DisconnectAll(); // Disconnect a specific input or AudioParam. - void DisconnectInput(AudioNodeInput&); void DisconnectAudioParam(AudioParamHandler&); void SetNumberOfChannels(unsigned); @@ -79,10 +78,6 @@ bool IsConnected() { return FanOutCount() > 0 || ParamFanOutCount() > 0; } - // Probe if the output node is connected with a certain input or AudioParam - bool IsConnectedToInput(AudioNodeInput&); - bool IsConnectedToAudioParam(AudioParamHandler&); - // Disable/Enable happens when there are still JavaScript references to a // node, but it has otherwise "finished" its work. For example, when a note // has finished playing. It is kept around, because it may be played again at @@ -107,16 +102,6 @@ // object. AudioHandler& handler_; - friend class AudioNodeInput; - friend class AudioParamHandler; - - // These are called from AudioNodeInput. - // They must be called with the context's graph lock. - void AddInput(AudioNodeInput&); - void RemoveInput(AudioNodeInput&); - void AddParam(AudioParamHandler&); - void RemoveParam(AudioParamHandler&); - // fanOutCount() is the number of AudioNodeInputs that we're connected to. // This method should not be called in audio thread rendering code, instead // renderingFanOutCount() should be used. @@ -180,6 +165,8 @@ // This collection of raw pointers is safe because they are retained by // AudioParam objects retained by m_connectedParams of the owner AudioNode. HashSet<AudioParamHandler*> params_; + + friend class AudioNodeWiring; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/audio_node_wiring.cc b/third_party/blink/renderer/modules/webaudio/audio_node_wiring.cc new file mode 100644 index 0000000..3cbe48a6 --- /dev/null +++ b/third_party/blink/renderer/modules/webaudio/audio_node_wiring.cc
@@ -0,0 +1,228 @@ +// 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 "third_party/blink/renderer/modules/webaudio/audio_node_wiring.h" + +#include "third_party/blink/renderer/modules/webaudio/audio_node_input.h" +#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h" +#include "third_party/blink/renderer/modules/webaudio/deferred_task_handler.h" +#include "third_party/blink/renderer/platform/wtf/hash_set.h" + +namespace blink { + +namespace { + +using AudioNodeOutputSet = HashSet<AudioNodeOutput*>; + +struct FindOutputResult { + AudioNodeOutputSet& output_set; + AudioNodeOutputSet::const_iterator iterator; + bool is_disabled; +}; + +// Given a connected output, finds it in the "active" or "disabled" set (e.g. +// of the outputs connected to an input). Produces the set in which it was +// found, an iterator into that set (so that it can be erased), and whether or +// not the set it was found in was the disabled set. +// +// It is an error to pass an output which is *not* connected (i.e. is neither +// active nor disabled). +FindOutputResult FindOutput(AudioNodeOutput& output, + AudioNodeOutputSet& outputs, + AudioNodeOutputSet& disabled_outputs) { + auto it = outputs.find(&output); + if (it != outputs.end()) + return {outputs, it, false}; + + it = disabled_outputs.find(&output); + if (it != disabled_outputs.end()) + return {disabled_outputs, it, true}; + + NOTREACHED() << "The output must be connected to the input."; + return {outputs, {}, false}; +} + +} // namespace + +void AudioNodeWiring::Connect(AudioNodeOutput& output, AudioNodeInput& input) { + input.GetDeferredTaskHandler().AssertGraphOwner(); + + const bool input_connected_to_output = + input.outputs_.Contains(&output) || + input.disabled_outputs_.Contains(&output); + const bool output_connected_to_input = output.inputs_.Contains(&input); + DCHECK_EQ(input_connected_to_output, output_connected_to_input); + + // Do nothing if already connected. + if (input_connected_to_output) + return; + + (output.is_enabled_ ? input.outputs_ : input.disabled_outputs_) + .insert(&output); + output.inputs_.insert(&input); + + // If it has gained an active connection, the input may need to have its + // rendering state updated. + if (output.is_enabled_) + input.ChangedOutputs(); + + // The input node's handler needs to know about this connection. This may + // cause it to re-enable itself. + input.Handler().MakeConnection(); +} + +void AudioNodeWiring::Connect(AudioNodeOutput& output, + AudioParamHandler& param) { + param.GetDeferredTaskHandler().AssertGraphOwner(); + + const bool param_connected_to_output = param.outputs_.Contains(&output); + const bool output_connected_to_param = output.params_.Contains(¶m); + DCHECK_EQ(param_connected_to_output, output_connected_to_param); + + // Do nothing if already connected. + if (param_connected_to_output) + return; + + param.outputs_.insert(&output); + output.params_.insert(¶m); + + // The param may need to have its rendering state updated. + param.ChangedOutputs(); +} + +void AudioNodeWiring::Disconnect(AudioNodeOutput& output, + AudioNodeInput& input) { + input.GetDeferredTaskHandler().AssertGraphOwner(); + + // These must be connected. + DCHECK(output.inputs_.Contains(&input)); + DCHECK(input.outputs_.Contains(&output) || + input.disabled_outputs_.Contains(&output)); + + // Find the output in the appropriate place. + auto result = FindOutput(output, input.outputs_, input.disabled_outputs_); + + // Erase the pointers from both sets. + result.output_set.erase(result.iterator); + output.inputs_.erase(&input); + + // If an active connection was disconnected, the input may need to have its + // rendering state updated. + if (!result.is_disabled) + input.ChangedOutputs(); + + // The input node's handler may try to disable itself if this was the last + // connection. This must happen after the set erasures above, or the disabling + // logic would observe an inconsistent state. + input.Handler().BreakConnectionWithLock(); +} + +void AudioNodeWiring::Disconnect(AudioNodeOutput& output, + AudioParamHandler& param) { + param.GetDeferredTaskHandler().AssertGraphOwner(); + + DCHECK(param.outputs_.Contains(&output)); + DCHECK(output.params_.Contains(¶m)); + + // Erase the pointers from both sets. + param.outputs_.erase(&output); + output.params_.erase(¶m); + + // The param may need to have its rendering state updated. + param.ChangedOutputs(); +} + +void AudioNodeWiring::Disable(AudioNodeOutput& output, AudioNodeInput& input) { + input.GetDeferredTaskHandler().AssertGraphOwner(); + + // These must be connected. + DCHECK(output.inputs_.Contains(&input)); + DCHECK(input.outputs_.Contains(&output) || + input.disabled_outputs_.Contains(&output)); + + // The output should have been marked as disabled. + DCHECK(!output.is_enabled_); + + // Move from the active list to the disabled list. + // Do nothing if this is the current state. + if (!input.disabled_outputs_.insert(&output).is_new_entry) + return; + input.outputs_.erase(&output); + + // Since it has lost an active connection, the input may need to have its + // rendering state updated. + input.ChangedOutputs(); + + // Propagate disabled state downstream. This must happen after the set + // manipulations above, or the disabling logic could observe an inconsistent + // state. + input.Handler().DisableOutputsIfNecessary(); +} + +void AudioNodeWiring::Enable(AudioNodeOutput& output, AudioNodeInput& input) { + input.GetDeferredTaskHandler().AssertGraphOwner(); + + // These must be connected. + DCHECK(output.inputs_.Contains(&input)); + DCHECK(input.outputs_.Contains(&output) || + input.disabled_outputs_.Contains(&output)); + + // The output should have been marked as enabled. + DCHECK(output.is_enabled_); + + // Move from the disabled list to the active list. + // Do nothing if this is the current state. + if (!input.outputs_.insert(&output).is_new_entry) + return; + input.disabled_outputs_.erase(&output); + + // Since it has gained an active connection, the input may need to have its + // rendering state updated. + input.ChangedOutputs(); + + // Propagate enabled state downstream. This must happen after the set + // manipulations above, or the disabling logic could observe an inconsistent + // state. + input.Handler().EnableOutputsIfNecessary(); +} + +bool AudioNodeWiring::IsConnected(AudioNodeOutput& output, + AudioNodeInput& input) { + input.GetDeferredTaskHandler().AssertGraphOwner(); + + bool is_connected = output.inputs_.Contains(&input); + DCHECK_EQ(is_connected, input.outputs_.Contains(&output) || + input.disabled_outputs_.Contains(&output)); + return is_connected; +} + +bool AudioNodeWiring::IsConnected(AudioNodeOutput& output, + AudioParamHandler& param) { + param.GetDeferredTaskHandler().AssertGraphOwner(); + + bool is_connected = output.params_.Contains(¶m); + DCHECK_EQ(is_connected, param.outputs_.Contains(&output)); + return is_connected; +} + +void AudioNodeWiring::WillBeDestroyed(AudioNodeInput& input) { + // This is more or less a streamlined version of calling Disconnect + // repeatedly. In particular it cannot happen while the input's handler is + // being destroyed, and so does not require any information about these final + // changes to its connections. + // + // What does matter, however, is ensuring that no AudioNodeOutput holds a + // dangling pointer to |input|. + + input.GetDeferredTaskHandler().AssertGraphOwner(); + + for (AudioNodeOutput* output : input.outputs_) + output->inputs_.erase(&input); + for (AudioNodeOutput* output : input.disabled_outputs_) + output->inputs_.erase(&input); + input.outputs_.clear(); + input.disabled_outputs_.clear(); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/audio_node_wiring.h b/third_party/blink/renderer/modules/webaudio/audio_node_wiring.h new file mode 100644 index 0000000..239e8d83 --- /dev/null +++ b/third_party/blink/renderer/modules/webaudio/audio_node_wiring.h
@@ -0,0 +1,51 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_AUDIO_NODE_WIRING_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_AUDIO_NODE_WIRING_H_ + +#include "third_party/blink/renderer/modules/modules_export.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" + +namespace blink { + +class AudioNodeInput; +class AudioNodeOutput; +class AudioParamHandler; + +// Utilities for connecting AudioHandlers to one another, via AudioNodeInput and +// AudioNodeOutput. Gathered into one place that can see the internals of both, +// to avoid both needing to call one another back and forth. +// +// An AudioNodeOutput can also be connected to an AudioParamHandler. +// +// All functions require the graph lock. +class MODULES_EXPORT AudioNodeWiring { + STATIC_ONLY(AudioNodeWiring); + + public: + // Make or break a connection from an output of one audio node to an input of + // another. + static void Connect(AudioNodeOutput&, AudioNodeInput&); + static void Connect(AudioNodeOutput&, AudioParamHandler&); + static void Disconnect(AudioNodeOutput&, AudioNodeInput&); + static void Disconnect(AudioNodeOutput&, AudioParamHandler&); + + // Disable the connection from an output to an input, setting it aside in + // a separate list of disabled connections. Enabling does the reverse. + // Should be called only from AudioNodeOutput, when its state has changed. + static void Disable(AudioNodeOutput&, AudioNodeInput&); + static void Enable(AudioNodeOutput&, AudioNodeInput&); + + // Queries whether a connection exists, disabled or not. + static bool IsConnected(AudioNodeOutput&, AudioNodeInput&); + static bool IsConnected(AudioNodeOutput&, AudioParamHandler&); + + // Called before complete destruction to remove any remaining connections. + static void WillBeDestroyed(AudioNodeInput&); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_AUDIO_NODE_WIRING_H_
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param.cc b/third_party/blink/renderer/modules/webaudio/audio_param.cc index 307273b5..7fead11f 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_param.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_param.cc
@@ -167,7 +167,7 @@ void AudioParamHandler::SetIntrinsicValue(float new_value) { new_value = clampTo(new_value, min_value_, max_value_); - NoBarrierStore(&intrinsic_value_, new_value); + intrinsic_value_.store(new_value, std::memory_order_relaxed); } void AudioParamHandler::SetValue(float value) { @@ -298,27 +298,6 @@ sample_rate, sample_rate, MinValue(), MaxValue())); } -void AudioParamHandler::Connect(AudioNodeOutput& output) { - GetDeferredTaskHandler().AssertGraphOwner(); - - if (outputs_.Contains(&output)) - return; - - output.AddParam(*this); - outputs_.insert(&output); - ChangedOutputs(); -} - -void AudioParamHandler::Disconnect(AudioNodeOutput& output) { - GetDeferredTaskHandler().AssertGraphOwner(); - - if (outputs_.Contains(&output)) { - outputs_.erase(&output); - ChangedOutputs(); - output.RemoveParam(*this); - } -} - int AudioParamHandler::ComputeQHistogramValue(float new_value) const { // For the Q value, assume a useful range is [0, 25] and that 0.25 dB // resolution is good enough. Then, we can map the floating point Q value (in
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param.h b/third_party/blink/renderer/modules/webaudio/audio_param.h index 6339400..b9cbdeb 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_param.h +++ b/third_party/blink/renderer/modules/webaudio/audio_param.h
@@ -30,6 +30,7 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_AUDIO_PARAM_H_ #include <sys/types.h> +#include <atomic> #include "base/memory/scoped_refptr.h" #include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h" #include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h" @@ -91,6 +92,8 @@ // processing classes have additional references. An AudioParamHandler can // outlive the owner AudioParam, and it never dies before the owner AudioParam // dies. +// +// Connected to AudioNodeOutput using AudioNodeWiring. class AudioParamHandler final : public ThreadSafeRefCounted<AudioParamHandler>, public AudioSummingJunction { public: @@ -193,11 +196,9 @@ // Must be called in the context's render thread. void CalculateSampleAccurateValues(float* values, unsigned number_of_values); - // Connect an audio-rate signal to control this parameter. - void Connect(AudioNodeOutput&); - void Disconnect(AudioNodeOutput&); - - float IntrinsicValue() const { return NoBarrierLoad(&intrinsic_value_); } + float IntrinsicValue() const { + return intrinsic_value_.load(std::memory_order_relaxed); + } private: AudioParamHandler(BaseAudioContext&, @@ -228,7 +229,7 @@ String custom_param_name_; // Intrinsic value - float intrinsic_value_; + std::atomic<float> intrinsic_value_; void SetIntrinsicValue(float new_value); float default_value_; @@ -251,6 +252,8 @@ // Audio bus to sum in any connections to the AudioParam. scoped_refptr<AudioBus> summing_bus_; + + friend class AudioNodeWiring; }; // AudioParam class represents web-exposed AudioParam interface.
diff --git a/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.cc b/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.cc index 099e5ce..0e8c1bf 100644 --- a/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.cc +++ b/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.cc
@@ -101,7 +101,7 @@ float reduction = dynamics_compressor_->ParameterValue(DynamicsCompressor::kParamReduction); - NoBarrierStore(&reduction_, reduction); + reduction_.store(reduction, std::memory_order_relaxed); } void DynamicsCompressorHandler::ProcessOnlyAudioParams(
diff --git a/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.h b/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.h index a4f681a..452b320 100644 --- a/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.h +++ b/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.h
@@ -26,6 +26,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_DYNAMICS_COMPRESSOR_NODE_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_DYNAMICS_COMPRESSOR_NODE_H_ +#include <atomic> #include <memory> #include "base/gtest_prod_util.h" #include "third_party/blink/renderer/modules/modules_export.h" @@ -56,7 +57,9 @@ void ProcessOnlyAudioParams(uint32_t frames_to_process) override; void Initialize() override; - float ReductionValue() const { return NoBarrierLoad(&reduction_); } + float ReductionValue() const { + return reduction_.load(std::memory_order_relaxed); + } void SetChannelCount(unsigned, ExceptionState&) final; void SetChannelCountMode(const String&, ExceptionState&) final; @@ -77,7 +80,7 @@ scoped_refptr<AudioParamHandler> threshold_; scoped_refptr<AudioParamHandler> knee_; scoped_refptr<AudioParamHandler> ratio_; - float reduction_; + std::atomic<float> reduction_; scoped_refptr<AudioParamHandler> attack_; scoped_refptr<AudioParamHandler> release_;
diff --git a/third_party/blink/renderer/modules/webdatabase/database.cc b/third_party/blink/renderer/modules/webdatabase/database.cc index dc8fcd38..aefb6b1 100644 --- a/third_party/blink/renderer/modules/webdatabase/database.cc +++ b/third_party/blink/renderer/modules/webdatabase/database.cc
@@ -225,7 +225,7 @@ display_name_(display_name.IsolatedCopy()), estimated_size_(estimated_size), guid_(0), - opened_(0), + opened_(false), new_(false), transaction_in_progress_(false), is_transaction_queue_enabled_(true) { @@ -266,7 +266,7 @@ // DatabaseContext::stopDatabases()). By the time we get here, the SQLite // database should have already been closed. - DCHECK(!opened_); + DCHECK(!Opened()); } void Database::Trace(blink::Visitor* visitor) { @@ -411,10 +411,10 @@ } void Database::CloseDatabase() { - if (!opened_) + if (!opened_.load(std::memory_order_relaxed)) return; - ReleaseStore(&opened_, 0); + opened_.store(false, std::memory_order_release); sqlite_database_.Close(); // See comment at the top this file regarding calling removeOpenDatabase(). DatabaseTracker::Tracker().RemoveOpenDatabase(this); @@ -590,7 +590,7 @@ // See comment at the top this file regarding calling addOpenDatabase(). DatabaseTracker::Tracker().AddOpenDatabase(this); - opened_ = 1; + opened_.store(true, std::memory_order_release); // Declare success: error = DatabaseError::kNone; // Clear the presumed error from above. @@ -924,10 +924,6 @@ return nullptr; } -bool Database::Opened() { - return static_cast<bool>(AcquireLoad(&opened_)); -} - base::SingleThreadTaskRunner* Database::GetDatabaseTaskRunner() const { return database_task_runner_.get(); }
diff --git a/third_party/blink/renderer/modules/webdatabase/database.h b/third_party/blink/renderer/modules/webdatabase/database.h index f01a685..48841e0 100644 --- a/third_party/blink/renderer/modules/webdatabase/database.h +++ b/third_party/blink/renderer/modules/webdatabase/database.h
@@ -26,6 +26,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBDATABASE_DATABASE_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBDATABASE_DATABASE_H_ +#include <atomic> #include "base/single_thread_task_runner.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_database_callback.h" #include "third_party/blink/renderer/modules/webdatabase/database_basic_types.h" @@ -94,7 +95,7 @@ SQLTransaction::OnErrorCallback*, SQLTransaction::OnSuccessCallback*); - bool Opened(); + bool Opened() { return opened_.load(std::memory_order_acquire); } bool IsNew() const { return new_; } const SecurityOrigin* GetSecurityOrigin() const; @@ -181,7 +182,11 @@ String filename_; DatabaseGuid guid_; - int opened_; + + // Atomically written from the database thread only, but read from multiple + // threads. + std::atomic_bool opened_; + bool new_; SQLiteDatabase sqlite_database_;
diff --git a/third_party/blink/renderer/modules/webgl/BUILD.gn b/third_party/blink/renderer/modules/webgl/BUILD.gn index db785e2..24619b53 100644 --- a/third_party/blink/renderer/modules/webgl/BUILD.gn +++ b/third_party/blink/renderer/modules/webgl/BUILD.gn
@@ -89,6 +89,12 @@ "webgl_framebuffer.h", "webgl_lose_context.cc", "webgl_lose_context.h", + "webgl_multi_draw.cc", + "webgl_multi_draw.h", + "webgl_multi_draw_common.cc", + "webgl_multi_draw_common.h", + "webgl_multi_draw_instanced.cc", + "webgl_multi_draw_instanced.h", "webgl_multiview.cc", "webgl_multiview.h", "webgl_object.cc",
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc index 198f039..5c581a17 100644 --- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc +++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc
@@ -30,6 +30,8 @@ #include "third_party/blink/renderer/modules/webgl/webgl_debug_renderer_info.h" #include "third_party/blink/renderer/modules/webgl/webgl_debug_shaders.h" #include "third_party/blink/renderer/modules/webgl/webgl_lose_context.h" +#include "third_party/blink/renderer/modules/webgl/webgl_multi_draw.h" +#include "third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.h" #include "third_party/blink/renderer/modules/webgl/webgl_multiview.h" #include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h" @@ -138,6 +140,9 @@ RegisterExtension<WebGLDebugRendererInfo>(webgl_debug_renderer_info_); RegisterExtension<WebGLDebugShaders>(webgl_debug_shaders_); RegisterExtension<WebGLLoseContext>(webgl_lose_context_); + RegisterExtension<WebGLMultiDraw>(webgl_multi_draw_, kDraftExtension); + RegisterExtension<WebGLMultiDrawInstanced>(webgl_multi_draw_instanced_, + kDraftExtension); RegisterExtension<WebGLMultiview>(webgl_multiview_, kDraftExtension); } @@ -156,6 +161,8 @@ visitor->Trace(webgl_debug_renderer_info_); visitor->Trace(webgl_debug_shaders_); visitor->Trace(webgl_lose_context_); + visitor->Trace(webgl_multi_draw_); + visitor->Trace(webgl_multi_draw_instanced_); visitor->Trace(webgl_multiview_); WebGL2RenderingContextBase::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h index 18a4af6..da68105c 100644 --- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h +++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h
@@ -17,6 +17,8 @@ class OESTextureFloatLinear; class WebGLDebugRendererInfo; class WebGLLoseContext; +class WebGLMultiDraw; +class WebGLMultiDrawInstanced; class WebGLMultiview; class KHRParallelShaderCompile; @@ -72,6 +74,8 @@ Member<WebGLDebugRendererInfo> webgl_debug_renderer_info_; Member<WebGLDebugShaders> webgl_debug_shaders_; Member<WebGLLoseContext> webgl_lose_context_; + Member<WebGLMultiDraw> webgl_multi_draw_; + Member<WebGLMultiDrawInstanced> webgl_multi_draw_instanced_; Member<WebGLMultiview> webgl_multiview_; };
diff --git a/third_party/blink/renderer/modules/webgl/webgl_extension_name.h b/third_party/blink/renderer/modules/webgl/webgl_extension_name.h index 786b9e1..2c0d7044 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_extension_name.h +++ b/third_party/blink/renderer/modules/webgl/webgl_extension_name.h
@@ -40,6 +40,8 @@ kWebGLDrawBuffersName, kWebGLGetBufferSubDataAsyncName, kWebGLLoseContextName, + kWebGLMultiDrawName, + kWebGLMultiDrawInstancedName, kWebGLMultiviewName, kWebGLExtensionNameCount, // Must be the last entry };
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw.cc b/third_party/blink/renderer/modules/webgl/webgl_multi_draw.cc new file mode 100644 index 0000000..cd2a88e4 --- /dev/null +++ b/third_party/blink/renderer/modules/webgl/webgl_multi_draw.cc
@@ -0,0 +1,81 @@ +// 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 "third_party/blink/renderer/modules/webgl/webgl_multi_draw.h" + +#include "gpu/command_buffer/client/gles2_interface.h" + +namespace blink { + +WebGLMultiDraw::WebGLMultiDraw(WebGLRenderingContextBase* context) + : WebGLExtension(context) { + context->ExtensionsUtil()->EnsureExtensionEnabled("GL_WEBGL_multi_draw"); + context->ExtensionsUtil()->EnsureExtensionEnabled("GL_ANGLE_multi_draw"); +} + +WebGLMultiDraw* WebGLMultiDraw::Create(WebGLRenderingContextBase* context) { + return MakeGarbageCollected<WebGLMultiDraw>(context); +} + +WebGLExtensionName WebGLMultiDraw::GetName() const { + return kWebGLMultiDrawName; +} + +bool WebGLMultiDraw::Supported(WebGLRenderingContextBase* context) { + return context->ExtensionsUtil()->SupportsExtension("GL_WEBGL_multi_draw") || + context->ExtensionsUtil()->SupportsExtension("GL_ANGLE_multi_draw"); +} + +const char* WebGLMultiDraw::ExtensionName() { + return "WEBGL_multi_draw"; +} + +void WebGLMultiDraw::multiDrawArraysImpl( + GLenum mode, + const base::span<const int32_t>& firsts, + GLuint firstsOffset, + const base::span<const int32_t>& counts, + GLuint countsOffset, + GLsizei drawcount) { + WebGLExtensionScopedContext scoped(this); + if (scoped.IsLost() || + !ValidateDrawcount(&scoped, "glMultiDrawArraysWEBGL", drawcount) || + !ValidateArray(&scoped, "glMultiDrawArraysWEBGL", + "firstsOffset out of bounds", firsts.size(), firstsOffset, + drawcount) || + !ValidateArray(&scoped, "glMultiDrawArraysWEBGL", + "countsOffset out of bounds", counts.size(), countsOffset, + drawcount)) { + return; + } + + scoped.Context()->ContextGL()->MultiDrawArraysWEBGL( + mode, &firsts[firstsOffset], &counts[countsOffset], drawcount); +} + +void WebGLMultiDraw::multiDrawElementsImpl( + GLenum mode, + const base::span<const int32_t>& counts, + GLuint countsOffset, + GLenum type, + const base::span<const int32_t>& offsets, + GLuint offsetsOffset, + GLsizei drawcount) { + WebGLExtensionScopedContext scoped(this); + if (scoped.IsLost() || + !ValidateDrawcount(&scoped, "glMultiDrawElementsWEBGL", drawcount) || + !ValidateArray(&scoped, "glMultiDrawElementsWEBGL", + "countsOffset out of bounds", counts.size(), countsOffset, + drawcount) || + !ValidateArray(&scoped, "glMultiDrawElementsWEBGL", + "offsetsOffset out of bounds", offsets.size(), + offsetsOffset, drawcount)) { + return; + } + + scoped.Context()->ContextGL()->MultiDrawElementsWEBGL( + mode, &counts[countsOffset], type, &offsets[offsetsOffset], drawcount); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw.h b/third_party/blink/renderer/modules/webgl/webgl_multi_draw.h new file mode 100644 index 0000000..06d6bf3 --- /dev/null +++ b/third_party/blink/renderer/modules/webgl/webgl_multi_draw.h
@@ -0,0 +1,67 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_H_ + +#include "third_party/blink/renderer/bindings/modules/v8/int32_array_or_long_sequence.h" +#include "third_party/blink/renderer/modules/webgl/webgl_extension.h" +#include "third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" + +namespace blink { + +class WebGLMultiDraw final : public WebGLExtension, + public WebGLMultiDrawCommon { + DEFINE_WRAPPERTYPEINFO(); + + public: + static WebGLMultiDraw* Create(WebGLRenderingContextBase*); + static bool Supported(WebGLRenderingContextBase*); + static const char* ExtensionName(); + + explicit WebGLMultiDraw(WebGLRenderingContextBase*); + WebGLExtensionName GetName() const override; + + void multiDrawArraysWEBGL(GLenum mode, + Int32ArrayOrLongSequence firstsList, + GLuint firstsOffset, + Int32ArrayOrLongSequence countsList, + GLuint countsOffset, + GLsizei drawcount) { + multiDrawArraysImpl(mode, MakeSpan(firstsList), firstsOffset, + MakeSpan(countsList), countsOffset, drawcount); + } + + void multiDrawElementsWEBGL(GLenum mode, + Int32ArrayOrLongSequence countsList, + GLuint countsOffset, + GLenum type, + Int32ArrayOrLongSequence offsetsList, + GLuint offsetsOffset, + GLsizei drawcount) { + multiDrawElementsImpl(mode, MakeSpan(countsList), countsOffset, type, + MakeSpan(offsetsList), offsetsOffset, drawcount); + } + + private: + void multiDrawArraysImpl(GLenum mode, + const base::span<const int32_t>& firsts, + GLuint firstsOffset, + const base::span<const int32_t>& counts, + GLuint countsOffset, + GLsizei drawcount); + + void multiDrawElementsImpl(GLenum mode, + const base::span<const int32_t>& counts, + GLuint countsOffset, + GLenum type, + const base::span<const int32_t>& offsets, + GLuint offsetsOffset, + GLsizei drawcount); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_H_
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw.idl b/third_party/blink/renderer/modules/webgl/webgl_multi_draw.idl new file mode 100644 index 0000000..37ea035 --- /dev/null +++ b/third_party/blink/renderer/modules/webgl/webgl_multi_draw.idl
@@ -0,0 +1,23 @@ +// 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. + +// https://www.khronos.org/registry/webgl/extensions/WEBGL_multi_draw/ + +[NoInterfaceObject] +interface WebGLMultiDraw { + void multiDrawArraysWEBGL(GLenum mode, + (Int32Array or sequence<long>) firstsList, + GLuint firstsOffset, + (Int32Array or sequence<long>) countsList, + GLuint countsOffset, + GLsizei drawcount); + + void multiDrawElementsWEBGL(GLenum mode, + (Int32Array or sequence<long>) countsList, + GLuint countsOffset, + GLenum type, + (Int32Array or sequence<long>) offsetsList, + GLuint offsetsOffset, + GLsizei drawcount); +};
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc new file mode 100644 index 0000000..93dca19 --- /dev/null +++ b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.cc
@@ -0,0 +1,50 @@ +// 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 "third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.h" + +namespace blink { + +bool WebGLMultiDrawCommon::ValidateDrawcount( + WebGLExtensionScopedContext* scoped, + const char* function_name, + GLsizei drawcount) { + if (drawcount < 0) { + scoped->Context()->SynthesizeGLError(GL_INVALID_VALUE, function_name, + "negative drawcount"); + return false; + } + return true; +} + +bool WebGLMultiDrawCommon::ValidateArray(WebGLExtensionScopedContext* scoped, + const char* function_name, + const char* outOfBoundsDescription, + size_t size, + GLuint offset, + GLsizei drawcount) { + if (static_cast<uint32_t>(drawcount) > size) { + scoped->Context()->SynthesizeGLError(GL_INVALID_OPERATION, function_name, + "drawcount out of bounds"); + return false; + } + if (offset >= size) { + scoped->Context()->SynthesizeGLError(GL_INVALID_OPERATION, function_name, + outOfBoundsDescription); + return false; + } + return true; +} + +base::span<const int32_t> WebGLMultiDrawCommon::MakeSpan( + const Int32ArrayOrLongSequence& array) { + if (array.IsInt32Array()) { + return base::span<const int32_t>(array.GetAsInt32Array().View()->Data(), + array.GetAsInt32Array().View()->length()); + } + return base::span<const int32_t>(array.GetAsLongSequence().data(), + array.GetAsLongSequence().size()); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.h b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.h new file mode 100644 index 0000000..d9c3a843 --- /dev/null +++ b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.h
@@ -0,0 +1,34 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_COMMON_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_COMMON_H_ + +#include "base/containers/span.h" +#include "third_party/blink/renderer/bindings/modules/v8/int32_array_or_long_sequence.h" +#include "third_party/blink/renderer/modules/webgl/webgl_extension.h" + +namespace blink { + +class WebGLExtensionScopedContext; +class WebGLMultiDrawCommon { + protected: + bool ValidateDrawcount(WebGLExtensionScopedContext* scoped, + const char* function_name, + GLsizei drawcount); + + bool ValidateArray(WebGLExtensionScopedContext* scoped, + const char* function_name, + const char* outOfBoundsDescription, + size_t size, + GLuint offset, + GLsizei drawcount); + + static base::span<const int32_t> MakeSpan( + const Int32ArrayOrLongSequence& array); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_COMMON_H_
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.cc b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.cc new file mode 100644 index 0000000..4b914c1 --- /dev/null +++ b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.cc
@@ -0,0 +1,99 @@ +// 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 "third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.h" + +#include "gpu/command_buffer/client/gles2_interface.h" + +namespace blink { + +WebGLMultiDrawInstanced::WebGLMultiDrawInstanced( + WebGLRenderingContextBase* context) + : WebGLExtension(context) { + context->ExtensionsUtil()->EnsureExtensionEnabled( + "GL_WEBGL_multi_draw_instanced"); + context->ExtensionsUtil()->EnsureExtensionEnabled("GL_ANGLE_multi_draw"); +} + +WebGLMultiDrawInstanced* WebGLMultiDrawInstanced::Create( + WebGLRenderingContextBase* context) { + return MakeGarbageCollected<WebGLMultiDrawInstanced>(context); +} + +WebGLExtensionName WebGLMultiDrawInstanced::GetName() const { + return kWebGLMultiDrawInstancedName; +} + +bool WebGLMultiDrawInstanced::Supported(WebGLRenderingContextBase* context) { + return context->ExtensionsUtil()->SupportsExtension( + "GL_WEBGL_multi_draw_instanced") || + (context->ExtensionsUtil()->SupportsExtension("GL_ANGLE_multi_draw") && + context->ExtensionsUtil()->SupportsExtension( + "GL_ANGLE_instanced_arrays")); +} + +const char* WebGLMultiDrawInstanced::ExtensionName() { + return "WEBGL_multi_draw_instanced"; +} + +void WebGLMultiDrawInstanced::multiDrawArraysInstancedImpl( + GLenum mode, + const base::span<const int32_t>& firsts, + GLuint firstsOffset, + const base::span<const int32_t>& counts, + GLuint countsOffset, + const base::span<const int32_t>& instanceCounts, + GLuint instanceCountsOffset, + GLsizei drawcount) { + WebGLExtensionScopedContext scoped(this); + if (scoped.IsLost() || + !ValidateDrawcount(&scoped, "glMultiDrawArraysWEBGL", drawcount) || + !ValidateArray(&scoped, "glMultiDrawArraysWEBGL", + "firstsOffset out of bounds", firsts.size(), firstsOffset, + drawcount) || + !ValidateArray(&scoped, "glMultiDrawArraysWEBGL", + "countsOffset out of bounds", counts.size(), countsOffset, + drawcount) || + !ValidateArray(&scoped, "glMultiDrawElementsWEBGL", + "instanceCountsOffset out of bounds", + instanceCounts.size(), instanceCountsOffset, drawcount)) { + return; + } + + scoped.Context()->ContextGL()->MultiDrawArraysInstancedWEBGL( + mode, &firsts[firstsOffset], &counts[countsOffset], + &instanceCounts[instanceCountsOffset], drawcount); +} + +void WebGLMultiDrawInstanced::multiDrawElementsInstancedImpl( + GLenum mode, + const base::span<const int32_t>& counts, + GLuint countsOffset, + GLenum type, + const base::span<const int32_t>& offsets, + GLuint offsetsOffset, + const base::span<const int32_t>& instanceCounts, + GLuint instanceCountsOffset, + GLsizei drawcount) { + WebGLExtensionScopedContext scoped(this); + if (scoped.IsLost() || + !ValidateDrawcount(&scoped, "glMultiDrawElementsWEBGL", drawcount) || + !ValidateArray(&scoped, "glMultiDrawElementsWEBGL", + "countsOffset out of bounds", counts.size(), countsOffset, + drawcount) || + !ValidateArray(&scoped, "glMultiDrawElementsWEBGL", + "offsetsOffset out of bounds", offsets.size(), + offsetsOffset, drawcount) || + !ValidateArray(&scoped, "glMultiDrawElementsWEBGL", + "instanceCountsOffset out of bounds", + instanceCounts.size(), instanceCountsOffset, drawcount)) { + return; + } + + scoped.Context()->ContextGL()->MultiDrawElementsInstancedWEBGL( + mode, &counts[countsOffset], type, &offsets[offsetsOffset], + &instanceCounts[instanceCountsOffset], drawcount); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.h b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.h new file mode 100644 index 0000000..540a4d7 --- /dev/null +++ b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.h
@@ -0,0 +1,82 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_INSTANCED_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_INSTANCED_H_ + +#include "third_party/blink/renderer/bindings/modules/v8/int32_array_or_long_sequence.h" +#include "third_party/blink/renderer/modules/webgl/webgl_extension.h" +#include "third_party/blink/renderer/modules/webgl/webgl_multi_draw_common.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" + +namespace blink { +class WebGLMultiDrawInstanced final : public WebGLExtension, + public WebGLMultiDrawCommon { + DEFINE_WRAPPERTYPEINFO(); + + public: + static WebGLMultiDrawInstanced* Create(WebGLRenderingContextBase*); + static bool Supported(WebGLRenderingContextBase*); + static const char* ExtensionName(); + + explicit WebGLMultiDrawInstanced(WebGLRenderingContextBase*); + WebGLExtensionName GetName() const override; + + void multiDrawArraysInstancedWEBGL( + GLenum mode, + Int32ArrayOrLongSequence firstsList, + GLuint firstsOffset, + Int32ArrayOrLongSequence countsList, + GLuint countsOffset, + Int32ArrayOrLongSequence instanceCountsList, + GLuint instanceCountsOffset, + GLsizei drawcount) { + multiDrawArraysInstancedImpl(mode, MakeSpan(firstsList), firstsOffset, + MakeSpan(countsList), countsOffset, + MakeSpan(instanceCountsList), + instanceCountsOffset, drawcount); + } + + void multiDrawElementsInstancedWEBGL( + GLenum mode, + Int32ArrayOrLongSequence countsList, + GLuint countsOffset, + GLenum type, + Int32ArrayOrLongSequence offsetsList, + GLuint offsetsOffset, + Int32ArrayOrLongSequence instanceCountsList, + GLuint instanceCountsOffset, + GLsizei drawcount) { + multiDrawElementsInstancedImpl(mode, MakeSpan(countsList), countsOffset, + type, MakeSpan(offsetsList), offsetsOffset, + MakeSpan(instanceCountsList), + instanceCountsOffset, drawcount); + } + + private: + void multiDrawArraysInstancedImpl( + GLenum mode, + const base::span<const int32_t>& firsts, + GLuint firstsOffset, + const base::span<const int32_t>& counts, + GLuint countsOffset, + const base::span<const int32_t>& instanceCounts, + GLuint instanceCountsOffset, + GLsizei drawcount); + + void multiDrawElementsInstancedImpl( + GLenum mode, + const base::span<const int32_t>& counts, + GLuint countsOffset, + GLenum type, + const base::span<const int32_t>& offsets, + GLuint offsetsOffset, + const base::span<const int32_t>& instanceCounts, + GLuint instanceCountsOffset, + GLsizei drawcount); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_MULTI_DRAW_INSTANCED_H_
diff --git a/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.idl b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.idl new file mode 100644 index 0000000..b117010 --- /dev/null +++ b/third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.idl
@@ -0,0 +1,27 @@ +// 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. + +// https://www.khronos.org/registry/webgl/extensions/WEBGL_multi_draw_instanced/ + +[NoInterfaceObject] +interface WebGLMultiDrawInstanced { + void multiDrawArraysInstancedWEBGL(GLenum mode, + (Int32Array or sequence<long>) firstsList, + GLuint firstsOffset, + (Int32Array or sequence<long>) countsList, + GLuint countsOffset, + (Int32Array or sequence<long>) instanceCountsList, + GLuint instanceCountsOffset, + GLsizei drawcount); + + void multiDrawElementsInstancedWEBGL(GLenum mode, + (Int32Array or sequence<long>) countsList, + GLuint countsOffset, + GLenum type, + (Int32Array or sequence<long>) offsetsList, + GLuint offsetsOffset, + (Int32Array or sequence<long>) instanceCountsList, + GLuint instanceCountsOffset, + GLsizei drawcount); +};
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc index 452ad89..d6322372 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc
@@ -65,6 +65,8 @@ #include "third_party/blink/renderer/modules/webgl/webgl_depth_texture.h" #include "third_party/blink/renderer/modules/webgl/webgl_draw_buffers.h" #include "third_party/blink/renderer/modules/webgl/webgl_lose_context.h" +#include "third_party/blink/renderer/modules/webgl/webgl_multi_draw.h" +#include "third_party/blink/renderer/modules/webgl/webgl_multi_draw_instanced.h" #include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h" namespace blink { @@ -187,6 +189,9 @@ RegisterExtension<WebGLDrawBuffers>(webgl_draw_buffers_); RegisterExtension<WebGLLoseContext>(webgl_lose_context_, kApprovedExtension, kBothPrefixes); + RegisterExtension<WebGLMultiDraw>(webgl_multi_draw_, kDraftExtension); + RegisterExtension<WebGLMultiDrawInstanced>(webgl_multi_draw_instanced_, + kDraftExtension); } void WebGLRenderingContext::Trace(blink::Visitor* visitor) { @@ -218,6 +223,8 @@ visitor->Trace(webgl_depth_texture_); visitor->Trace(webgl_draw_buffers_); visitor->Trace(webgl_lose_context_); + visitor->Trace(webgl_multi_draw_); + visitor->Trace(webgl_multi_draw_instanced_); WebGLRenderingContextBase::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h index 9c71981..610461cd 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h
@@ -51,6 +51,8 @@ class WebGLDebugRendererInfo; class WebGLDepthTexture; class WebGLLoseContext; +class WebGLMultiDraw; +class WebGLMultiDrawInstanced; class WebGLRenderingContext final : public WebGLRenderingContextBase { DEFINE_WRAPPERTYPEINFO(); @@ -119,6 +121,8 @@ Member<WebGLDepthTexture> webgl_depth_texture_; Member<WebGLDrawBuffers> webgl_draw_buffers_; Member<WebGLLoseContext> webgl_lose_context_; + Member<WebGLMultiDraw> webgl_multi_draw_; + Member<WebGLMultiDrawInstanced> webgl_multi_draw_instanced_; }; DEFINE_TYPE_CASTS(WebGLRenderingContext,
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h index ed1a145ec..6c2b734d 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
@@ -632,6 +632,9 @@ friend class WebGLCompressedTexturePVRTC; friend class WebGLCompressedTextureS3TC; friend class WebGLCompressedTextureS3TCsRGB; + friend class WebGLMultiDraw; + friend class WebGLMultiDrawCommon; + friend class WebGLMultiDrawInstanced; friend class WebGLMultiview; friend class WebGLRenderingContextErrorMessageCallback; friend class WebGLVertexArrayObjectBase;
diff --git a/third_party/blink/renderer/modules/webmidi/midi_port.idl b/third_party/blink/renderer/modules/webmidi/midi_port.idl index 7699de27..eddf0f0 100644 --- a/third_party/blink/renderer/modules/webmidi/midi_port.idl +++ b/third_party/blink/renderer/modules/webmidi/midi_port.idl
@@ -65,6 +65,6 @@ attribute EventHandler onstatechange; - [CallWith=ScriptState] Promise open(); - [CallWith=ScriptState] Promise close(); + [CallWith=ScriptState] Promise<MIDIPort> open(); + [CallWith=ScriptState] Promise<MIDIPort> close(); };
diff --git a/third_party/blink/renderer/modules/webmidi/navigator_web_midi.idl b/third_party/blink/renderer/modules/webmidi/navigator_web_midi.idl index da51aec..fbc72c1 100644 --- a/third_party/blink/renderer/modules/webmidi/navigator_web_midi.idl +++ b/third_party/blink/renderer/modules/webmidi/navigator_web_midi.idl
@@ -33,8 +33,5 @@ [ ImplementedAs=NavigatorWebMIDI ] partial interface Navigator { - [ - CallWith = ScriptState, MeasureAs = RequestMIDIAccess_ObscuredByFootprinting - ] Promise - requestMIDIAccess(optional MIDIOptions options); + [CallWith=ScriptState, MeasureAs=RequestMIDIAccess_ObscuredByFootprinting] Promise<MIDIAccess> requestMIDIAccess(optional MIDIOptions options); };
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index b14d749..a14d15f0 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -27,7 +27,7 @@ output_dir = blink_platform_output_dir } -action("runtime_enabled_features") { +blink_python_runner("runtime_enabled_features") { script = "../build/scripts/make_runtime_features.py" runtime_enabled_features_json5 = "runtime_enabled_features.json5" @@ -51,7 +51,7 @@ ] } -action("color_data") { +blink_python_runner("color_data") { script = "../build/scripts/gperf.py" color_data_gperf = "color_data.gperf"
diff --git a/third_party/blink/renderer/platform/bindings/callback_function_base.cc b/third_party/blink/renderer/platform/bindings/callback_function_base.cc index 07c8a4c..12ba1af 100644 --- a/third_party/blink/renderer/platform/bindings/callback_function_base.cc +++ b/third_party/blink/renderer/platform/bindings/callback_function_base.cc
@@ -4,18 +4,30 @@ #include "third_party/blink/renderer/platform/bindings/callback_function_base.h" +#include "third_party/blink/renderer/platform/bindings/binding_security_for_platform.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" + namespace blink { CallbackFunctionBase::CallbackFunctionBase( v8::Local<v8::Object> callback_function) { DCHECK(!callback_function.IsEmpty()); - callback_relevant_script_state_ = - ScriptState::From(callback_function->CreationContext()); - v8::Isolate* isolate = callback_relevant_script_state_->GetIsolate(); - + v8::Isolate* isolate = callback_function->GetIsolate(); callback_function_.Set(isolate, callback_function); + incumbent_script_state_ = ScriptState::From(isolate->GetIncumbentContext()); + + // Set |callback_relevant_script_state_| iff the creation context and the + // incumbent context are the same origin-domain. Otherwise, leave it as + // nullptr. + v8::Local<v8::Context> creation_context = + callback_function->CreationContext(); + if (BindingSecurityForPlatform::ShouldAllowAccessToV8Context( + incumbent_script_state_->GetContext(), creation_context, + BindingSecurityForPlatform::ErrorReportOption::kDoNotReport)) { + callback_relevant_script_state_ = ScriptState::From(creation_context); + } } void CallbackFunctionBase::Trace(Visitor* visitor) { @@ -24,6 +36,40 @@ visitor->Trace(incumbent_script_state_); } +ScriptState* CallbackFunctionBase::CallbackRelevantScriptStateOrReportError( + const char* interface, + const char* operation) { + if (callback_relevant_script_state_) + return callback_relevant_script_state_; + + // Report a SecurityError due to a cross origin callback object. + v8::TryCatch try_catch(GetIsolate()); + try_catch.SetVerbose(true); + ExceptionState exception_state( + GetIsolate(), ExceptionState::kExecutionContext, interface, operation); + ScriptState::Scope incumbent_scope(incumbent_script_state_); + exception_state.ThrowSecurityError( + "An invocation of the provided callback failed due to cross origin " + "access."); + return nullptr; +} + +ScriptState* CallbackFunctionBase::CallbackRelevantScriptStateOrThrowException( + const char* interface, + const char* operation) { + if (callback_relevant_script_state_) + return callback_relevant_script_state_; + + // Throw a SecurityError due to a cross origin callback object. + ExceptionState exception_state( + GetIsolate(), ExceptionState::kExecutionContext, interface, operation); + ScriptState::Scope incumbent_scope(incumbent_script_state_); + exception_state.ThrowSecurityError( + "An invocation of the provided callback failed due to cross origin " + "access."); + return nullptr; +} + V8PersistentCallbackFunctionBase::V8PersistentCallbackFunctionBase( CallbackFunctionBase* callback_function) : callback_function_(callback_function) {
diff --git a/third_party/blink/renderer/platform/bindings/callback_function_base.h b/third_party/blink/renderer/platform/bindings/callback_function_base.h index f7da224c..c5f6569 100644 --- a/third_party/blink/renderer/platform/bindings/callback_function_base.h +++ b/third_party/blink/renderer/platform/bindings/callback_function_base.h
@@ -36,13 +36,35 @@ } v8::Isolate* GetIsolate() const { - return callback_relevant_script_state_->GetIsolate(); + return incumbent_script_state_->GetIsolate(); } + // Returns the ScriptState of the relevant realm of the callback object. + // + // NOTE: This function must be used only when it's pretty sure that the + // callcack object is the same origin-domain. Otherwise, + // |CallbackRelevantScriptStateOrReportError| or + // |CallbackRelevantScriptStateOrThrowException| must be used instead. ScriptState* CallbackRelevantScriptState() { + DCHECK(callback_relevant_script_state_); return callback_relevant_script_state_; } + // Returns the ScriptState of the relevant realm of the callback object iff + // the callback is the same origin-domain. Otherwise, reports an error and + // returns nullptr. + ScriptState* CallbackRelevantScriptStateOrReportError(const char* interface, + const char* operation); + + // Returns the ScriptState of the relevant realm of the callback object iff + // the callback is the same origin-domain. Otherwise, throws an exception and + // returns nullptr. + ScriptState* CallbackRelevantScriptStateOrThrowException( + const char* interface, + const char* operation); + + DOMWrapperWorld& GetWorld() const { return incumbent_script_state_->World(); } + // Returns true if the ES function has a [[Construct]] internal method. bool IsConstructor() const { return CallbackFunction()->IsConstructor(); } @@ -52,6 +74,7 @@ v8::Local<v8::Function> CallbackFunction() const { return callback_function_.NewLocal(GetIsolate()).As<v8::Function>(); } + ScriptState* IncumbentScriptState() { return incumbent_script_state_; } private: @@ -59,7 +82,8 @@ // Use v8::Object instead of v8::Function in order to handle // [TreatNonObjectAsNull]. TraceWrapperV8Reference<v8::Object> callback_function_; - // The associated Realm of the callback function type value. + // The associated Realm of the callback function type value iff it's the same + // origin-domain. Otherwise, nullptr. Member<ScriptState> callback_relevant_script_state_; // The callback context, i.e. the incumbent Realm when an ECMAScript value is // converted to an IDL value.
diff --git a/third_party/blink/renderer/platform/bindings/callback_interface_base.cc b/third_party/blink/renderer/platform/bindings/callback_interface_base.cc index 6523b79..73b57c5 100644 --- a/third_party/blink/renderer/platform/bindings/callback_interface_base.cc +++ b/third_party/blink/renderer/platform/bindings/callback_interface_base.cc
@@ -31,6 +31,20 @@ visitor->Trace(incumbent_script_state_); } +ScriptState* CallbackInterfaceBase::CallbackRelevantScriptStateOrReportError( + const char* interface, + const char* operation) { + // TODO(yukishiino): Implement this function. + return callback_relevant_script_state_; +} + +ScriptState* CallbackInterfaceBase::CallbackRelevantScriptStateOrThrowException( + const char* interface, + const char* operation) { + // TODO(yukishiino): Implement this function. + return callback_relevant_script_state_; +} + V8PersistentCallbackInterfaceBase::V8PersistentCallbackInterfaceBase( CallbackInterfaceBase* callback_interface) : callback_interface_(callback_interface) {
diff --git a/third_party/blink/renderer/platform/bindings/callback_interface_base.h b/third_party/blink/renderer/platform/bindings/callback_interface_base.h index de706f72..0108ac45 100644 --- a/third_party/blink/renderer/platform/bindings/callback_interface_base.h +++ b/third_party/blink/renderer/platform/bindings/callback_interface_base.h
@@ -49,14 +49,34 @@ return callback_object_.NewLocal(GetIsolate()); } - v8::Isolate* GetIsolate() { - return callback_relevant_script_state_->GetIsolate(); - } + v8::Isolate* GetIsolate() { return incumbent_script_state_->GetIsolate(); } + // Returns the ScriptState of the relevant realm of the callback object. + // + // NOTE: This function must be used only when it's pretty sure that the + // callcack object is the same origin-domain. Otherwise, + // |CallbackRelevantScriptStateOrReportError| or + // |CallbackRelevantScriptStateOrThrowException| must be used instead. ScriptState* CallbackRelevantScriptState() { + DCHECK(callback_relevant_script_state_); return callback_relevant_script_state_; } + // Returns the ScriptState of the relevant realm of the callback object iff + // the callback is the same origin-domain. Otherwise, reports an error and + // returns nullptr. + ScriptState* CallbackRelevantScriptStateOrReportError(const char* interface, + const char* operation); + + // Returns the ScriptState of the relevant realm of the callback object iff + // the callback is the same origin-domain. Otherwise, throws an exception and + // returns nullptr. + ScriptState* CallbackRelevantScriptStateOrThrowException( + const char* interface, + const char* operation); + + DOMWrapperWorld& GetWorld() const { return incumbent_script_state_->World(); } + // NodeIteratorBase counts the invocation of those which are callable and // those which are not. bool IsCallbackObjectCallableForNodeIteratorBase() const {
diff --git a/third_party/blink/renderer/platform/bindings/to_v8.h b/third_party/blink/renderer/platform/bindings/to_v8.h index 75478328..be64af69 100644 --- a/third_party/blink/renderer/platform/bindings/to_v8.h +++ b/third_party/blink/renderer/platform/bindings/to_v8.h
@@ -47,10 +47,11 @@ v8::Isolate* isolate) { // |creation_context| is intentionally ignored. Callback functions are not // wrappers nor clonable. ToV8 on a callback function must be used only when - // it's the same origin-domain in the same world. - DCHECK(!callback || (callback->CallbackRelevantScriptState()->GetContext() == - creation_context->CreationContext())); - return callback ? callback->CallbackFunction().As<v8::Value>() + // it's in the same world. + DCHECK(!callback || + (&callback->GetWorld() == + &ScriptState::From(creation_context->CreationContext())->World())); + return callback ? callback->CallbackObject().As<v8::Value>() : v8::Null(isolate).As<v8::Value>(); }
diff --git a/third_party/blink/renderer/platform/exported/web_url_request.cc b/third_party/blink/renderer/platform/exported/web_url_request.cc index c387c5d..51f57324 100644 --- a/third_party/blink/renderer/platform/exported/web_url_request.cc +++ b/third_party/blink/renderer/platform/exported/web_url_request.cc
@@ -101,6 +101,16 @@ resource_request_->SetSiteForCookies(site_for_cookies); } +base::Optional<WebSecurityOrigin> WebURLRequest::TopFrameOrigin() const { + const SecurityOrigin* origin = resource_request_->TopFrameOrigin(); + return origin ? base::Optional<WebSecurityOrigin>(origin) + : base::Optional<WebSecurityOrigin>(); +} + +void WebURLRequest::SetTopFrameOrigin(const WebSecurityOrigin& origin) { + resource_request_->SetTopFrameOrigin(origin); +} + WebSecurityOrigin WebURLRequest::RequestorOrigin() const { return resource_request_->RequestorOrigin(); }
diff --git a/third_party/blink/renderer/platform/exported/web_url_response.cc b/third_party/blink/renderer/platform/exported/web_url_response.cc index 58ca5135..1b65b50f 100644 --- a/third_party/blink/renderer/platform/exported/web_url_response.cc +++ b/third_party/blink/renderer/platform/exported/web_url_response.cc
@@ -360,6 +360,12 @@ resource_response_->SetURLListViaServiceWorker(url_list); } +bool WebURLResponse::HasUrlListViaServiceWorker() const { + DCHECK(resource_response_->UrlListViaServiceWorker().size() == 0 || + WasFetchedViaServiceWorker()); + return resource_response_->UrlListViaServiceWorker().size() > 0; +} + void WebURLResponse::SetMultipartBoundary(const char* bytes, size_t size) { resource_response_->SetMultipartBoundary(bytes, size); }
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc b/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc index 2219806..d6864da 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc
@@ -4,35 +4,24 @@ #include "third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h" -#include "third_party/blink/renderer/platform/fonts/font.h" -#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h" #include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h" -#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h" #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h" #include "third_party/blink/renderer/platform/text/text_break_iterator.h" namespace blink { ShapingLineBreaker::ShapingLineBreaker( - const HarfBuzzShaper* shaper, - const Font* font, scoped_refptr<const ShapeResult> result, const LazyLineBreakIterator* break_iterator, - const RunSegmenter::RunSegmenterRange* pre_segmented, - ShapeResultSpacing<String>* spacing, - const Hyphenation* hyphenation) - : shaper_(shaper), - font_(font), + const Hyphenation* hyphenation, + ShapeCallback shape_callback, + void* shape_callback_context) + : shape_callback_(shape_callback), + shape_callback_context_(shape_callback_context), result_(result), - pre_segmented_(pre_segmented), break_iterator_(break_iterator), - spacing_(spacing), hyphenation_(hyphenation), is_soft_hyphen_enabled_(true) { - // ShapeResultSpacing is stateful when it has expansions. We may use it in - // arbitrary order that it cannot have expansions. - DCHECK(!spacing_ || !spacing_->HasExpansion()); - // Line breaking performance relies on high-performance x-position to // character offset lookup. Ensure that the desired cache has been computed. DCHECK(result_); @@ -175,18 +164,6 @@ return {break_iterator_->NextBreakOpportunity(offset, len), false}; } -inline scoped_refptr<ShapeResult> ShapingLineBreaker::Shape(TextDirection direction, - unsigned start, - unsigned end) { - if (!spacing_ || !spacing_->HasSpacing()) - return shaper_->Shape(font_, direction, start, end, pre_segmented_); - - scoped_refptr<ShapeResult> result = - shaper_->Shape(font_, direction, start, end, pre_segmented_); - result->ApplySpacing(*spacing_); - return result; -} - // Shapes a line of text by finding a valid and appropriate break opportunity // based on the shaping results for the entire paragraph. Re-shapes the start // and end of the line as needed. @@ -289,14 +266,14 @@ // There is no safe-to-break, reshape the whole range. result_out->break_offset = break_opportunity.offset; return ShapeResultView::Create( - Shape(direction, start, break_opportunity.offset).get()); + Shape(start, break_opportunity.offset).get()); } LayoutUnit original_width = FlipRtl( SnapEnd(result_->CachedPositionForOffset(first_safe - range_start), direction) - start_position, direction); - line_start_result = Shape(direction, start, first_safe); + line_start_result = Shape(start, first_safe); available_space += line_start_result->SnappedWidth() - original_width; } DCHECK_GE(first_safe, start); @@ -320,12 +297,12 @@ break; DCHECK_LE(break_opportunity.offset, range_end); if (is_overflow) { - line_end_result = Shape(direction, last_safe, break_opportunity.offset); + line_end_result = Shape(last_safe, break_opportunity.offset); break; } LayoutUnit safe_position = SnapStart( result_->CachedPositionForOffset(last_safe - range_start), direction); - line_end_result = Shape(direction, last_safe, break_opportunity.offset); + line_end_result = Shape(last_safe, break_opportunity.offset); if (line_end_result->SnappedWidth() <= FlipRtl(end_position - safe_position, direction)) break; @@ -402,14 +379,13 @@ return ShapeResultView::Create(result_.get(), start, range_end); // If no safe-to-break offset is found in range, reshape the entire range. - TextDirection direction = result_->Direction(); if (first_safe >= range_end) { - scoped_refptr<ShapeResult> line_result = Shape(direction, start, range_end); + scoped_refptr<ShapeResult> line_result = Shape(start, range_end); return ShapeResultView::Create(line_result.get()); } // Otherwise reshape to |first_safe|, then copy the rest. - scoped_refptr<ShapeResult> line_start = Shape(direction, start, first_safe); + scoped_refptr<ShapeResult> line_start = Shape(start, first_safe); ShapeResultView::Segment segments[2] = { {line_start.get(), 0, std::numeric_limits<unsigned>::max()}, {result_.get(), first_safe, range_end}};
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h b/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h index 159cd3e4..14ed9828 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h +++ b/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h
@@ -13,15 +13,11 @@ namespace blink { -class Font; class ShapeResult; class ShapeResultView; -class HarfBuzzShaper; class Hyphenation; class LazyLineBreakIterator; enum class LineBreakType; -template <typename TextContainerType> -class ShapeResultSpacing; // Shapes a line of text by finding the ideal break position as indicated by the // available space and the shape results for the entire paragraph. Once an ideal @@ -37,18 +33,20 @@ STACK_ALLOCATED(); public: - // Construct a ShapingLineBreaker. + // Callback function to reshape line edges. // - // When the ShapeResult is from a RunSegmenterRange, giving it can skip - // running RunSegmenter for much better performance. - ShapingLineBreaker(const HarfBuzzShaper*, - const Font*, - scoped_refptr<const ShapeResult>, - const LazyLineBreakIterator*, - const RunSegmenter::RunSegmenterRange* = nullptr, - ShapeResultSpacing<String>* = nullptr, - const Hyphenation* = nullptr); - ~ShapingLineBreaker() = default; + // std::function is forbidden in Chromium and base::Callback is way too + // expensive so we resort to a good old function pointer instead. + using ShapeCallback = scoped_refptr<ShapeResult> (*)(void* context, + unsigned start, + unsigned end); + + // Construct a ShapingLineBreaker. + ShapingLineBreaker(scoped_refptr<const ShapeResult> result, + const LazyLineBreakIterator* break_iterator, + const Hyphenation* hyphenation, + ShapeCallback shape_callback, + void* shape_callback_context); // Represents details of the result of |ShapeLine()|. struct Result { @@ -116,20 +114,18 @@ unsigned word_end, bool backwards) const; - scoped_refptr<ShapeResult> Shape(TextDirection, unsigned start, unsigned end); + scoped_refptr<ShapeResult> Shape(unsigned start, unsigned end) { + return (*shape_callback_)(shape_callback_context_, start, end); + } scoped_refptr<const ShapeResultView> ShapeToEnd(unsigned start, unsigned first_safe, unsigned range_start, unsigned range_end); - const HarfBuzzShaper* shaper_; - const Font* font_; + const ShapeCallback shape_callback_; + void* shape_callback_context_; scoped_refptr<const ShapeResult> result_; - const RunSegmenter::RunSegmenterRange* pre_segmented_; const LazyLineBreakIterator* break_iterator_; - // TODO(kojii): ShapeResultSpacing is not const because it's stateful when it - // has expansions. Split spacing and expansions to make this const. - ShapeResultSpacing<String>* spacing_; const Hyphenation* hyphenation_; bool is_soft_hyphen_enabled_;
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc b/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc index 25ba3d14..2e05f33 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc
@@ -20,6 +20,20 @@ namespace { +struct HarfBuzzShaperCallbackContext { + const HarfBuzzShaper* shaper; + const Font* font; + TextDirection direction; +}; + +scoped_refptr<ShapeResult> HarfBuzzShaperCallback(void* untyped_context, + unsigned start, + unsigned end) { + HarfBuzzShaperCallbackContext* context = + static_cast<HarfBuzzShaperCallbackContext*>(untyped_context); + return context->shaper->Shape(context->font, context->direction, start, end); +} + scoped_refptr<const ShapeResultView> ShapeLine(ShapingLineBreaker* breaker, unsigned start_offset, LayoutUnit available_space, @@ -109,7 +123,9 @@ shaper.Shape(&font, direction, 0, 4); ASSERT_LT(first1->SnappedWidth(), first2->SnappedWidth()); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, result->Direction()}; + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); scoped_refptr<const ShapeResultView> line; unsigned break_offset = 0; @@ -168,7 +184,9 @@ scoped_refptr<const ShapeResult> mid_third = shaper.Shape(&font, direction, 0, 16); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, result->Direction()}; + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); unsigned break_offset = 0; ShapeLine(&breaker, 0, result->SnappedWidth() - 1, &break_offset); @@ -195,7 +213,9 @@ scoped_refptr<const ShapeResult> midpoint = shaper.Shape(&font, direction, 0, 16); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, result->Direction()}; + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); scoped_refptr<const ShapeResultView> line; unsigned break_offset = 0; @@ -216,7 +236,9 @@ HarfBuzzShaper shaper(string); scoped_refptr<const ShapeResult> result = shaper.Shape(&font, direction); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, result->Direction()}; + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); scoped_refptr<const ShapeResultView> line; unsigned break_offset = 0; LayoutUnit zero(0); @@ -259,7 +281,9 @@ }); LayoutUnit longest_word_width = (*longest_word)->SnappedWidth(); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, result->Direction()}; + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); scoped_refptr<const ShapeResult> line; unsigned break_offset = 0; @@ -288,7 +312,9 @@ scoped_refptr<const ShapeResult> result = shaper.Shape(&font, direction, 0, 2); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, result->Direction()}; + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); scoped_refptr<const ShapeResultView> line; unsigned break_offset = 0; @@ -325,7 +351,9 @@ scoped_refptr<const ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, result->Direction()}; + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); EXPECT_THAT(BreakPositionsByNext(breaker, string), testing::ElementsAreArray(data.break_positions)); @@ -345,7 +373,9 @@ scoped_refptr<const ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, result->Direction()}; + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); EXPECT_THAT(BreakPositionsByPrevious(breaker, string), testing::ElementsAreArray(data.break_positions));
diff --git a/third_party/blink/renderer/platform/graphics/intercepting_canvas.h b/third_party/blink/renderer/platform/graphics/intercepting_canvas.h index f17b64a..78164e7 100644 --- a/third_party/blink/renderer/platform/graphics/intercepting_canvas.h +++ b/third_party/blink/renderer/platform/graphics/intercepting_canvas.h
@@ -116,20 +116,6 @@ void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint&) override = 0; - void onDrawText(const void* text, - size_t byte_length, - SkScalar x, - SkScalar y, - const SkPaint&) override = 0; - void onDrawPosText(const void* text, - size_t byte_length, - const SkPoint pos[], - const SkPaint&) override = 0; - void onDrawPosTextH(const void* text, - size_t byte_length, - const SkScalar xpos[], - SkScalar const_y, - const SkPaint&) override = 0; void onDrawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y, @@ -258,32 +244,6 @@ this->SkCanvas::onDrawDRRect(outer, inner, paint); } - void onDrawText(const void* text, - size_t byte_length, - SkScalar x, - SkScalar y, - const SkPaint& paint) override { - Interceptor interceptor(this); - this->SkCanvas::onDrawText(text, byte_length, x, y, paint); - } - - void onDrawPosText(const void* text, - size_t byte_length, - const SkPoint pos[], - const SkPaint& paint) override { - Interceptor interceptor(this); - this->SkCanvas::onDrawPosText(text, byte_length, pos, paint); - } - - void onDrawPosTextH(const void* text, - size_t byte_length, - const SkScalar xpos[], - SkScalar const_y, - const SkPaint& paint) override { - Interceptor interceptor(this); - this->SkCanvas::onDrawPosTextH(text, byte_length, xpos, const_y, paint); - } - void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
diff --git a/third_party/blink/renderer/platform/graphics/logging_canvas.cc b/third_party/blink/renderer/platform/graphics/logging_canvas.cc index b5eae59..07dd685 100644 --- a/third_party/blink/renderer/platform/graphics/logging_canvas.cc +++ b/third_party/blink/renderer/platform/graphics/logging_canvas.cc
@@ -472,14 +472,6 @@ return paint_item; } -std::unique_ptr<JSONArray> ArrayForSkScalars(size_t n, - const SkScalar scalars[]) { - std::unique_ptr<JSONArray> scalars_array = JSONArray::Create(); - for (size_t i = 0; i < n; ++i) - scalars_array->PushDouble(scalars[i]); - return scalars_array; -} - String ClipOpName(SkClipOp op) { switch (op) { case SkClipOp::kDifference: @@ -498,51 +490,6 @@ return flags_string; } -String StringForUTF32LEText(const void* text, size_t byte_length) { - icu::UnicodeString utf16; -#if defined(ARCH_CPU_BIG_ENDIAN) - // Swap LE to BE - size_t char_length = length / sizeof(UChar32); - WTF::Vector<UChar32> utf32be(char_length); - const UChar32* utf32le = static_cast<const UChar32*>(text); - for (size_t i = 0; i < char_length; ++i) - utf32be[i] = base::ByteSwap(utf32le[i]); - utf16 = icu::UnicodeString::fromUTF32(utf32be.data(), - static_cast<int32_t>(byte_length)); -#else - utf16 = icu::UnicodeString::fromUTF32(reinterpret_cast<const UChar32*>(text), - static_cast<int32_t>(byte_length)); -#endif - return String(icu::toUCharPtr(utf16.getBuffer()), - static_cast<unsigned>(utf16.length())); -} - -String StringForText(const void* text, - size_t byte_length, - const SkPaint& paint) { - SkTextEncoding encoding = paint.getTextEncoding(); - switch (encoding) { - case kUTF8_SkTextEncoding: - return WTF::TextEncoding("UTF-8").Decode( - reinterpret_cast<const char*>(text), byte_length); - case kUTF16_SkTextEncoding: - return WTF::TextEncoding("UTF-16LE") - .Decode(reinterpret_cast<const char*>(text), byte_length); - case kUTF32_SkTextEncoding: - return StringForUTF32LEText(text, byte_length); - case kGlyphID_SkTextEncoding: { - WTF::Vector<SkUnichar> data_vector(byte_length / 2); - SkUnichar* text_data = data_vector.data(); - paint.glyphsToUnichars(static_cast<const uint16_t*>(text), - byte_length / 2, text_data); - return StringForUTF32LEText(text, byte_length); - } - default: - NOTREACHED(); - return "?"; - } -} - } // namespace class AutoLogger @@ -725,48 +672,6 @@ this->SkCanvas::onDrawDRRect(outer, inner, paint); } -void LoggingCanvas::onDrawText(const void* text, - size_t byte_length, - SkScalar x, - SkScalar y, - const SkPaint& paint) { - AutoLogger logger(this); - JSONObject* params = logger.LogItemWithParams("drawText"); - params->SetString("text", StringForText(text, byte_length, paint)); - params->SetDouble("x", x); - params->SetDouble("y", y); - params->SetObject("paint", ObjectForSkPaint(paint)); - this->SkCanvas::onDrawText(text, byte_length, x, y, paint); -} - -void LoggingCanvas::onDrawPosText(const void* text, - size_t byte_length, - const SkPoint pos[], - const SkPaint& paint) { - AutoLogger logger(this); - JSONObject* params = logger.LogItemWithParams("drawPosText"); - params->SetString("text", StringForText(text, byte_length, paint)); - size_t points_count = paint.countText(text, byte_length); - params->SetArray("pos", ArrayForSkPoints(points_count, pos)); - params->SetObject("paint", ObjectForSkPaint(paint)); - this->SkCanvas::onDrawPosText(text, byte_length, pos, paint); -} - -void LoggingCanvas::onDrawPosTextH(const void* text, - size_t byte_length, - const SkScalar xpos[], - SkScalar const_y, - const SkPaint& paint) { - AutoLogger logger(this); - JSONObject* params = logger.LogItemWithParams("drawPosTextH"); - params->SetString("text", StringForText(text, byte_length, paint)); - size_t points_count = paint.countText(text, byte_length); - params->SetArray("xpos", ArrayForSkScalars(points_count, xpos)); - params->SetDouble("constY", const_y); - params->SetObject("paint", ObjectForSkPaint(paint)); - this->SkCanvas::onDrawPosTextH(text, byte_length, xpos, const_y, paint); -} - void LoggingCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
diff --git a/third_party/blink/renderer/platform/graphics/logging_canvas.h b/third_party/blink/renderer/platform/graphics/logging_canvas.h index eceee7d..3951bbf5 100644 --- a/third_party/blink/renderer/platform/graphics/logging_canvas.h +++ b/third_party/blink/renderer/platform/graphics/logging_canvas.h
@@ -79,20 +79,6 @@ void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint&) override; - void onDrawText(const void* text, - size_t byte_length, - SkScalar x, - SkScalar y, - const SkPaint&) override; - void onDrawPosText(const void* text, - size_t byte_length, - const SkPoint pos[], - const SkPaint&) override; - void onDrawPosTextH(const void* text, - size_t byte_length, - const SkScalar xpos[], - SkScalar const_y, - const SkPaint&) override; void onDrawTextBlob(const SkTextBlob*, SkScalar x, SkScalar y,
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc index 2155008..22747be 100644 --- a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc +++ b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
@@ -143,7 +143,8 @@ // for clearing the property tree changed state at the end of paint instead of // in FinishCycle. See: LocalFrameView::RunPaintLifecyclePhase. bool clear_property_tree_changed = - !RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled(); + !RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() || + RuntimeEnabledFeatures::CompositeAfterPaintEnabled(); for (auto& chunk : chunks_) { chunk.client_is_just_created = false; if (clear_property_tree_changed)
diff --git a/third_party/blink/renderer/platform/heap/BUILD.gn b/third_party/blink/renderer/platform/heap/BUILD.gn index 470d703..650d1f90 100644 --- a/third_party/blink/renderer/platform/heap/BUILD.gn +++ b/third_party/blink/renderer/platform/heap/BUILD.gn
@@ -32,6 +32,7 @@ sources = [ "address_cache.cc", "address_cache.h", + "atomic_entry_flag.h", "blink_gc.h", "blink_gc_memory_dump_provider.cc", "blink_gc_memory_dump_provider.h",
diff --git a/third_party/blink/renderer/platform/heap/atomic_entry_flag.h b/third_party/blink/renderer/platform/heap/atomic_entry_flag.h new file mode 100644 index 0000000..0404e9e --- /dev/null +++ b/third_party/blink/renderer/platform/heap/atomic_entry_flag.h
@@ -0,0 +1,47 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_ATOMIC_ENTRY_FLAG_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_ATOMIC_ENTRY_FLAG_H_ + +#include <atomic> + +namespace blink { + +// A flag which provides a fast check whether a scope may be entered on the +// current thread, without needing to access thread-local storage or mutex. +// +// Can have false positives (i.e., spuriously report that it might be entered), +// so it is expected that this will be used in tandem with a precise check that +// the scope is in fact entered on that thread. +// +// Example: +// g_frobnicating_flag.MightBeEntered() && +// ThreadLocalFrobnicator().IsFrobnicating() +// +// Relaxed atomic operations are sufficient, since: +// - all accesses remain atomic +// - each thread must observe its own operations in order +// - no thread ever exits the flag more times than it enters (if used correctly) +// And so if a thread observes zero, it must be because it has observed an equal +// number of exits as entries. +class AtomicEntryFlag { + public: + inline void Enter() { entries_.fetch_add(1, std::memory_order_relaxed); } + inline void Exit() { entries_.fetch_sub(1, std::memory_order_relaxed); } + + // Returns false only if the current thread is not between a call to Enter and + // a call to Exit. Returns true if this thread or another thread may currently + // be in the scope guarded by this flag. + inline bool MightBeEntered() const { + return entries_.load(std::memory_order_relaxed) != 0; + } + + private: + std::atomic_int entries_{0}; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_ATOMIC_ENTRY_FLAG_H_
diff --git a/third_party/blink/renderer/platform/heap/persistent.h b/third_party/blink/renderer/platform/heap/persistent.h index 52dc689..35ed1d2 100644 --- a/third_party/blink/renderer/platform/heap/persistent.h +++ b/third_party/blink/renderer/platform/heap/persistent.h
@@ -13,7 +13,6 @@ #include "third_party/blink/renderer/platform/heap/persistent_node.h" #include "third_party/blink/renderer/platform/heap/visitor.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" -#include "third_party/blink/renderer/platform/wtf/atomics.h" namespace blink { @@ -26,11 +25,6 @@ \ private: -enum WeaknessPersistentConfiguration { - kNonWeakPersistentConfiguration, - kWeakPersistentConfiguration -}; - enum CrossThreadnessPersistentConfiguration { kSingleThreadPersistentConfiguration, kCrossThreadPersistentConfiguration @@ -172,10 +166,9 @@ // needing to be cleared out before the thread is terminated. PersistentBase* RegisterAsStaticReference() { CHECK_EQ(weaknessConfiguration, kNonWeakPersistentConfiguration); - if (persistent_node_) { + if (PersistentNode* node = persistent_node_.Get()) { DCHECK(ThreadState::Current()); - ThreadState::Current()->RegisterStaticPersistentNode(persistent_node_, - nullptr); + ThreadState::Current()->RegisterStaticPersistentNode(node, nullptr); LEAK_SANITIZER_IGNORE_OBJECT(this); } return this; @@ -190,11 +183,7 @@ ProcessHeap::CrossThreadPersistentMutex().AssertAcquired(); #endif raw_ = nullptr; - CrossThreadPersistentRegion& region = - weaknessConfiguration == kWeakPersistentConfiguration - ? ProcessHeap::GetCrossThreadWeakPersistentRegion() - : ProcessHeap::GetCrossThreadPersistentRegion(); - region.FreePersistentNode(persistent_node_); + persistent_node_.ClearWithLockHeld(); } private: @@ -208,7 +197,7 @@ } CheckPointer(); if (raw_) { - if (!persistent_node_) + if (!persistent_node_.IsInitialized()) Initialize(); return; } @@ -229,64 +218,17 @@ NO_SANITIZE_ADDRESS void Initialize() { - DCHECK(!persistent_node_); + DCHECK(!persistent_node_.IsInitialized()); if (!raw_ || IsHashTableDeletedValue()) return; TraceCallback trace_callback = TraceMethodDelegate<PersistentBase, &PersistentBase::TracePersistent>::Trampoline; - if (crossThreadnessConfiguration == kCrossThreadPersistentConfiguration) { - CrossThreadPersistentRegion& region = - weaknessConfiguration == kWeakPersistentConfiguration - ? ProcessHeap::GetCrossThreadWeakPersistentRegion() - : ProcessHeap::GetCrossThreadPersistentRegion(); - MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex()); - region.AllocatePersistentNode(persistent_node_, this, trace_callback); - return; - } - ThreadState* state = - ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState(); - DCHECK(state->CheckThread()); - PersistentRegion* region = - weaknessConfiguration == kWeakPersistentConfiguration - ? state->GetWeakPersistentRegion() - : state->GetPersistentRegion(); - persistent_node_ = region->AllocatePersistentNode(this, trace_callback); -#if DCHECK_IS_ON() - state_ = state; -#endif + persistent_node_.Initialize(this, trace_callback); } - void Uninitialize() { - if (crossThreadnessConfiguration == kCrossThreadPersistentConfiguration) { - if (AcquireLoad(reinterpret_cast<void* volatile*>(&persistent_node_))) { - CrossThreadPersistentRegion& region = - weaknessConfiguration == kWeakPersistentConfiguration - ? ProcessHeap::GetCrossThreadWeakPersistentRegion() - : ProcessHeap::GetCrossThreadPersistentRegion(); - MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex()); - region.FreePersistentNode(persistent_node_); - } - return; - } - - if (!persistent_node_) - return; - ThreadState* state = - ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState(); - DCHECK(state->CheckThread()); - // Persistent handle must be created and destructed in the same thread. -#if DCHECK_IS_ON() - DCHECK_EQ(state_, state); -#endif - PersistentRegion* region = - weaknessConfiguration == kWeakPersistentConfiguration - ? state->GetWeakPersistentRegion() - : state->GetPersistentRegion(); - state->FreePersistentNode(region, persistent_node_); - persistent_node_ = nullptr; - } + void Uninitialize() { persistent_node_.Uninitialize(); } void CheckPointer() const { #if DCHECK_IS_ON() @@ -353,11 +295,22 @@ NOTREACHED(); } - // m_raw is accessed most, so put it at the first field. + // raw_ is accessed most, so put it at the first field. T* raw_; - PersistentNode* persistent_node_ = nullptr; + + // The pointer to the underlying persistent node. + // + // Since accesses are atomics in the cross-thread case, a different type is + // needed to prevent the compiler producing an error when it encounters + // operations that are legal on raw pointers but not on atomics, or + // vice-versa. + std::conditional_t< + crossThreadnessConfiguration == kCrossThreadPersistentConfiguration, + CrossThreadPersistentNodePtr<weaknessConfiguration>, + PersistentNodePtr<ThreadingTrait<T>::kAffinity, weaknessConfiguration>> + persistent_node_; + #if DCHECK_IS_ON() - ThreadState* state_ = nullptr; const ThreadState* creation_thread_state_; #endif };
diff --git a/third_party/blink/renderer/platform/heap/persistent_node.h b/third_party/blink/renderer/platform/heap/persistent_node.h index 596ce27..31c31cd6f 100644 --- a/third_party/blink/renderer/platform/heap/persistent_node.h +++ b/third_party/blink/renderer/platform/heap/persistent_node.h
@@ -5,18 +5,24 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PERSISTENT_NODE_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PERSISTENT_NODE_H_ +#include <atomic> #include <memory> #include "third_party/blink/renderer/platform/heap/process_heap.h" #include "third_party/blink/renderer/platform/heap/thread_state.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/assertions.h" -#include "third_party/blink/renderer/platform/wtf/atomics.h" #include "third_party/blink/renderer/platform/wtf/threading_primitives.h" namespace blink { class CrossThreadPersistentRegion; +class PersistentRegion; + +enum WeaknessPersistentConfiguration { + kNonWeakPersistentConfiguration, + kWeakPersistentConfiguration +}; class PersistentNode final { DISALLOW_NEW(); @@ -97,6 +103,52 @@ friend class CrossThreadPersistentRegion; }; +// Used by PersistentBase to manage a pointer to a thread heap persistent node. +// This class mostly passes accesses through, but provides an interface +// compatible with CrossThreadPersistentNodePtr. +template <ThreadAffinity affinity, + WeaknessPersistentConfiguration weakness_configuration> +class PersistentNodePtr { + public: + PersistentNode* Get() const { return ptr_; } + bool IsInitialized() const { return ptr_; } + + void Initialize(void* owner, TraceCallback); + void Uninitialize(); + + private: + PersistentNode* ptr_ = nullptr; +#if DCHECK_IS_ON() + ThreadState* state_ = nullptr; +#endif +}; + +// Used by PersistentBase to manage a pointer to a cross-thread persistent node. +// It uses ProcessHeap::CrossThreadPersistentMutex() to protect most accesses, +// but can be polled to see whether it is initialized without the mutex. +template <WeaknessPersistentConfiguration weakness_configuration> +class CrossThreadPersistentNodePtr { + public: + PersistentNode* Get() const { +#if DCHECK_IS_ON() + ProcessHeap::CrossThreadPersistentMutex().AssertAcquired(); +#endif + return ptr_.load(std::memory_order_relaxed); + } + bool IsInitialized() const { return ptr_.load(std::memory_order_acquire); } + + void Initialize(void* owner, TraceCallback); + void Uninitialize(); + + void ClearWithLockHeld(); + + private: + // Access must either be protected by the cross-thread persistent mutex or + // handle the fact that this may be changed concurrently (with a + // release-store). + std::atomic<PersistentNode*> ptr_{nullptr}; +}; + // PersistentRegion provides a region of PersistentNodes. PersistentRegion // holds a linked list of PersistentNodeSlots, each of which stores // a predefined number of PersistentNodes. You can call allocatePersistentNode/ @@ -171,18 +223,14 @@ USING_FAST_MALLOC(CrossThreadPersistentRegion); public: - void AllocatePersistentNode(PersistentNode*& persistent_node, - void* self, - TraceCallback trace) { + PersistentNode* AllocatePersistentNode(void* self, TraceCallback trace) { #if DCHECK_IS_ON() ProcessHeap::CrossThreadPersistentMutex().AssertAcquired(); #endif - PersistentNode* node = - persistent_region_.AllocatePersistentNode(self, trace); - ReleaseStore(reinterpret_cast<void* volatile*>(&persistent_node), node); + return persistent_region_.AllocatePersistentNode(self, trace); } - void FreePersistentNode(PersistentNode*& persistent_node) { + void FreePersistentNode(PersistentNode* node) { #if DCHECK_IS_ON() ProcessHeap::CrossThreadPersistentMutex().AssertAcquired(); #endif @@ -196,10 +244,9 @@ // The lock ensures the updating is ordered, but by the time lock has been // acquired the PersistentNode reference may have been cleared out already; // check for this. - if (!persistent_node) + if (!node) return; - persistent_region_.FreePersistentNode(persistent_node); - ReleaseStore(reinterpret_cast<void* volatile*>(&persistent_node), nullptr); + persistent_region_.FreePersistentNode(node); } void TracePersistentNodes(Visitor* visitor) { @@ -228,6 +275,92 @@ PersistentRegion persistent_region_; }; +template <ThreadAffinity affinity, + WeaknessPersistentConfiguration weakness_configuration> +void PersistentNodePtr<affinity, weakness_configuration>::Initialize( + void* owner, + TraceCallback trace_callback) { + ThreadState* state = ThreadStateFor<affinity>::GetState(); + DCHECK(state->CheckThread()); + PersistentRegion* region = + weakness_configuration == kWeakPersistentConfiguration + ? state->GetWeakPersistentRegion() + : state->GetPersistentRegion(); + ptr_ = region->AllocatePersistentNode(owner, trace_callback); +#if DCHECK_IS_ON() + state_ = state; +#endif +} + +template <ThreadAffinity affinity, + WeaknessPersistentConfiguration weakness_configuration> +void PersistentNodePtr<affinity, weakness_configuration>::Uninitialize() { + if (!ptr_) + return; + ThreadState* state = ThreadStateFor<affinity>::GetState(); + DCHECK(state->CheckThread()); +#if DCHECK_IS_ON() + DCHECK_EQ(state_, state) + << "must be initialized and uninitialized on the same thread"; + state_ = nullptr; +#endif + PersistentRegion* region = + weakness_configuration == kWeakPersistentConfiguration + ? state->GetWeakPersistentRegion() + : state->GetPersistentRegion(); + state->FreePersistentNode(region, ptr_); + ptr_ = nullptr; +} + +template <WeaknessPersistentConfiguration weakness_configuration> +void CrossThreadPersistentNodePtr<weakness_configuration>::Initialize( + void* owner, + TraceCallback trace_callback) { + CrossThreadPersistentRegion& region = + weakness_configuration == kWeakPersistentConfiguration + ? ProcessHeap::GetCrossThreadWeakPersistentRegion() + : ProcessHeap::GetCrossThreadPersistentRegion(); + MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex()); + PersistentNode* node = region.AllocatePersistentNode(owner, trace_callback); + ptr_.store(node, std::memory_order_release); +} + +template <WeaknessPersistentConfiguration weakness_configuration> +void CrossThreadPersistentNodePtr<weakness_configuration>::Uninitialize() { + // As an optimization, skip the mutex acquisition. + // + // Persistent handles are often assigned or destroyed while being + // uninitialized. + // + // Calling code is still expected to synchronize mutations to persistent + // handles, so if this thread can see the node pointer as having been + // cleared and the program does not have a data race, then this pointer would + // still have been blank after waiting for the cross-thread persistent mutex. + if (!ptr_.load(std::memory_order_acquire)) + return; + + CrossThreadPersistentRegion& region = + weakness_configuration == kWeakPersistentConfiguration + ? ProcessHeap::GetCrossThreadWeakPersistentRegion() + : ProcessHeap::GetCrossThreadPersistentRegion(); + MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex()); + region.FreePersistentNode(ptr_.load(std::memory_order_relaxed)); + ptr_.store(nullptr, std::memory_order_release); +} + +template <WeaknessPersistentConfiguration weakness_configuration> +void CrossThreadPersistentNodePtr<weakness_configuration>::ClearWithLockHeld() { +#if DCHECK_IS_ON() + ProcessHeap::CrossThreadPersistentMutex().AssertAcquired(); +#endif + CrossThreadPersistentRegion& region = + weakness_configuration == kWeakPersistentConfiguration + ? ProcessHeap::GetCrossThreadWeakPersistentRegion() + : ProcessHeap::GetCrossThreadPersistentRegion(); + region.FreePersistentNode(ptr_.load(std::memory_order_relaxed)); + ptr_.store(nullptr, std::memory_order_release); +} + } // namespace blink #endif
diff --git a/third_party/blink/renderer/platform/heap/thread_state.cc b/third_party/blink/renderer/platform/heap/thread_state.cc index a88a4ef..82226a9 100644 --- a/third_party/blink/renderer/platform/heap/thread_state.cc +++ b/third_party/blink/renderer/platform/heap/thread_state.cc
@@ -1402,32 +1402,32 @@ } // static -base::subtle::AtomicWord ThreadState::incremental_marking_counter_ = 0; +AtomicEntryFlag ThreadState::incremental_marking_flag_; // static -base::subtle::AtomicWord ThreadState::wrapper_tracing_counter_ = 0; +AtomicEntryFlag ThreadState::wrapper_tracing_flag_; void ThreadState::EnableIncrementalMarkingBarrier() { CHECK(!IsIncrementalMarking()); - base::subtle::Barrier_AtomicIncrement(&incremental_marking_counter_, 1); + incremental_marking_flag_.Enter(); SetIncrementalMarking(true); } void ThreadState::DisableIncrementalMarkingBarrier() { CHECK(IsIncrementalMarking()); - base::subtle::Barrier_AtomicIncrement(&incremental_marking_counter_, -1); + incremental_marking_flag_.Exit(); SetIncrementalMarking(false); } void ThreadState::EnableWrapperTracingBarrier() { CHECK(!IsWrapperTracing()); - base::subtle::Barrier_AtomicIncrement(&wrapper_tracing_counter_, 1); + wrapper_tracing_flag_.Enter(); SetWrapperTracing(true); } void ThreadState::DisableWrapperTracingBarrier() { CHECK(IsWrapperTracing()); - base::subtle::Barrier_AtomicIncrement(&wrapper_tracing_counter_, -1); + wrapper_tracing_flag_.Exit(); SetWrapperTracing(false); }
diff --git a/third_party/blink/renderer/platform/heap/thread_state.h b/third_party/blink/renderer/platform/heap/thread_state.h index cac61a6..7e7a50e6 100644 --- a/third_party/blink/renderer/platform/heap/thread_state.h +++ b/third_party/blink/renderer/platform/heap/thread_state.h
@@ -33,10 +33,10 @@ #include <memory> -#include "base/atomicops.h" #include "base/macros.h" #include "third_party/blink/public/platform/scheduler/web_rail_mode_observer.h" #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h" +#include "third_party/blink/renderer/platform/heap/atomic_entry_flag.h" #include "third_party/blink/renderer/platform/heap/blink_gc.h" #include "third_party/blink/renderer/platform/heap/threading_traits.h" #include "third_party/blink/renderer/platform/platform_export.h" @@ -219,19 +219,23 @@ ThreadState* state_; }; - // Returns true if any thread is currently incremental marking its heap and - // false otherwise. For an exact check use - // ThreadState::IsIncrementalMarking(). + // Returns true if some thread (possibly the current thread) may be doing + // incremental marking. If false is returned, the *current* thread is + // definitely not doing incremental marking. See atomic_entry_flag.h for + // details. + // + // For an exact check, use ThreadState::IsIncrementalMarking. ALWAYS_INLINE static bool IsAnyIncrementalMarking() { - // Stores use full barrier to allow using the simplest relaxed load here. - return base::subtle::NoBarrier_Load(&incremental_marking_counter_) > 0; + return incremental_marking_flag_.MightBeEntered(); } - // Returns true if any thread is currently incremental marking its heap and - // false otherwise. For an exact check use ThreadState::IsWrapperTracing(). + // Returns true if some thread (possibly the current thread) may be doing + // wrapper tracing. If false is returned, the *current* thread is definitely + // not doing wrapper tracing. See atomic_entry_flag.h for details. + // + // For an exact check, use ThreadState::IsWrapperTracing. static bool IsAnyWrapperTracing() { - // Stores use full barrier to allow using the simplest relaxed load here. - return base::subtle::NoBarrier_Load(&wrapper_tracing_counter_) > 0; + return wrapper_tracing_flag_.MightBeEntered(); } static void AttachMainThread(); @@ -569,13 +573,11 @@ } private: - // Number of ThreadState's that are currently in incremental marking. The - // counter is incremented by one when some ThreadState enters incremental - // marking and decremented upon finishing. - static base::subtle::AtomicWord incremental_marking_counter_; + // Stores whether some ThreadState is currently in incremental marking. + static AtomicEntryFlag incremental_marking_flag_; - // Same semantic as |incremental_marking_counter_|. - static base::subtle::AtomicWord wrapper_tracing_counter_; + // Same semantic as |incremental_marking_flag_|. + static AtomicEntryFlag wrapper_tracing_flag_; ThreadState(); ~ThreadState() override;
diff --git a/third_party/blink/renderer/platform/instance_counters.cc b/third_party/blink/renderer/platform/instance_counters.cc index 64734a7d..36251b56 100644 --- a/third_party/blink/renderer/platform/instance_counters.cc +++ b/third_party/blink/renderer/platform/instance_counters.cc
@@ -32,10 +32,14 @@ namespace blink { -int InstanceCounters::counters_[kCounterTypeLength]; +// static +std::atomic_int InstanceCounters::counters_[kCounterTypeLength]; + +// static +int InstanceCounters::node_counter_ = 0; int InstanceCounters::CounterValue(CounterType type) { - return AcquireLoad(&counters_[type]); + return counters_[type].load(std::memory_order_relaxed); } } // namespace blink
diff --git a/third_party/blink/renderer/platform/instance_counters.h b/third_party/blink/renderer/platform/instance_counters.h index b8384c5..f0dc08fa 100644 --- a/third_party/blink/renderer/platform/instance_counters.h +++ b/third_party/blink/renderer/platform/instance_counters.h
@@ -31,9 +31,9 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_INSTANCE_COUNTERS_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_INSTANCE_COUNTERS_H_ +#include <atomic> #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" -#include "third_party/blink/renderer/platform/wtf/atomics.h" #include "third_party/blink/renderer/platform/wtf/wtf.h" namespace blink { @@ -58,6 +58,13 @@ V(AdSubframe) \ V(DetachedScriptState) +// Atomic counters of the number of instances of objects that exist. +// +// Note that while these operations are atomic, they do not imply that other +// changes to memory are visible to the accessing thread. As a result, this +// is primarily useful where either other synchronization exists (e.g. the +// objects are only used on one thread), or an inconsistent answer is +// acceptable. class InstanceCounters { STATIC_ONLY(InstanceCounters); @@ -76,7 +83,7 @@ DCHECK(IsMainThread()); ++counters_[kNodeCounter]; } else { - AtomicIncrement(&counters_[type]); + counters_[type].fetch_add(1, std::memory_order_relaxed); } } @@ -85,14 +92,15 @@ DCHECK(IsMainThread()); --counters_[kNodeCounter]; } else { - AtomicDecrement(&counters_[type]); + counters_[type].fetch_sub(1, std::memory_order_relaxed); } } PLATFORM_EXPORT static int CounterValue(CounterType); private: - PLATFORM_EXPORT static int counters_[]; + PLATFORM_EXPORT static std::atomic_int counters_[]; + PLATFORM_EXPORT static int node_counter_; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.cc b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.cc index aa33be3a..1b5b1d3 100644 --- a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.cc +++ b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.cc
@@ -9,6 +9,13 @@ namespace blink { +namespace { + +using resource_coordinator::mojom::InterventionPolicy; +using resource_coordinator::mojom::PolicyControlledIntervention; + +} // namespace + // static std::unique_ptr<FrameResourceCoordinator> FrameResourceCoordinator::Create( service_manager::InterfaceProvider* interface_provider) { @@ -37,6 +44,12 @@ service_->SetHasNonEmptyBeforeUnload(has_nonempty_beforeunload); } +void FrameResourceCoordinator::SetInterventionPolicy( + PolicyControlledIntervention intervention, + InterventionPolicy policy) { + service_->SetInterventionPolicy(intervention, policy); +} + void FrameResourceCoordinator::OnNonPersistentNotificationCreated() { service_->OnNonPersistentNotificationCreated(); }
diff --git a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.h b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.h index 483cf4f..819625c 100644 --- a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.h +++ b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.h
@@ -26,6 +26,9 @@ void SetNetworkAlmostIdle(bool); void SetLifecycleState(resource_coordinator::mojom::LifecycleState); void SetHasNonEmptyBeforeUnload(bool has_nonempty_beforeunload); + void SetInterventionPolicy( + resource_coordinator::mojom::PolicyControlledIntervention intervention, + resource_coordinator::mojom::InterventionPolicy policy); void OnNonPersistentNotificationCreated(); private:
diff --git a/third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h b/third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h index 97e1475..5d8d61d 100644 --- a/third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h +++ b/third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h
@@ -11,19 +11,14 @@ #include "third_party/blink/renderer/platform/wtf/text/cstring.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" -namespace WTF { - -// CString version of SetTraceValue so that trace arguments can be strings. -static inline void SetTraceValue(const CString& arg, - unsigned char* type, - unsigned long long* value) { - trace_event_internal::TraceValueUnion type_value; - type_value.as_string = arg.data(); - *type = TRACE_VALUE_TYPE_COPY_STRING; - *value = type_value.as_uint; -} - -} // namespace WTF +// Conversion from CString to TraceValue so that trace arguments can be strings. +template <> +struct base::trace_event::TraceValue::Helper<WTF::CString> { + static constexpr unsigned char kType = TRACE_VALUE_TYPE_COPY_STRING; + static inline void SetValue(TraceValue* v, const WTF::CString& value) { + v->as_string = value.data(); + } +}; namespace blink { namespace trace_event {
diff --git a/third_party/blink/renderer/platform/loader/BUILD.gn b/third_party/blink/renderer/platform/loader/BUILD.gn index 347472a7..c9ac86e 100644 --- a/third_party/blink/renderer/platform/loader/BUILD.gn +++ b/third_party/blink/renderer/platform/loader/BUILD.gn
@@ -87,6 +87,8 @@ "fetch/text_resource_decoder_options.h", "fetch/unique_identifier.cc", "fetch/unique_identifier.h", + "ftp_directory_listing.cc", + "ftp_directory_listing.h", "link_header.cc", "link_header.h", "mixed_content_autoupgrade_status.h", @@ -127,6 +129,7 @@ "fetch/resource_response_test.cc", "fetch/resource_test.cc", "fetch/source_keyed_cached_metadata_handler_test.cc", + "ftp_directory_listing_test.cc", "link_header_test.cc", "subresource_integrity_test.cc", ]
diff --git a/third_party/blink/renderer/platform/loader/DEPS b/third_party/blink/renderer/platform/loader/DEPS index edcb279..1620cfa 100644 --- a/third_party/blink/renderer/platform/loader/DEPS +++ b/third_party/blink/renderer/platform/loader/DEPS
@@ -44,5 +44,21 @@ specific_include_rules = { "resource_error\.cc": [ "+net/base/net_errors.h" + ], + "ftp_directory_listing.cc": [ + "+base/i18n/encoding_detection.h", + "+base/i18n/icu_string_conversions.h", + "+base/strings/string_util.h", + "+base/strings/sys_string_conversions.h", + "+base/strings/utf_string_conversions.h", + "+net/base/directory_listing.h", + "+net/base/escape.h", + "+net/base/net_errors.h", + "+net/ftp/ftp_directory_listing_parser.h", + "+net/net_buildflags.h", + ], + "ftp_directory_listing_test.cc": [ + "+net/net_buildflags.h", + "+third_party/icu/source/i18n/unicode/timezone.h" ] }
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h b/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h index 9e6f233..13db292 100644 --- a/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h +++ b/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/platform/cross_thread_copier.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/heap/heap.h" +#include "third_party/blink/renderer/platform/loader/allowed_by_nosniff.h" #include "third_party/blink/renderer/platform/loader/fetch/https_state.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" @@ -51,6 +52,11 @@ // https://html.spec.whatwg.org/multipage/webappapis.html#https-state virtual HttpsState GetHttpsState() const = 0; + // Used for classic top-level scripts and importScripts(). + // TODO(crbug.com/794548): Remove this once we deprecate kLax. + virtual AllowedByNosniff::MimeTypeCheck MimeTypeCheckForClassicWorkerScript() + const = 0; + virtual void Trace(Visitor*) {} };
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.cc b/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.cc index 4b064b3..af21d75 100644 --- a/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.cc +++ b/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.cc
@@ -15,26 +15,32 @@ fetch_client_setting_object.GetSecurityOrigin(), fetch_client_setting_object.GetReferrerPolicy(), fetch_client_setting_object.GetOutgoingReferrer(), - fetch_client_setting_object.GetHttpsState()) {} + fetch_client_setting_object.GetHttpsState(), + fetch_client_setting_object.MimeTypeCheckForClassicWorkerScript()) {} FetchClientSettingsObjectSnapshot::FetchClientSettingsObjectSnapshot( std::unique_ptr<CrossThreadFetchClientSettingsObjectData> data) - : FetchClientSettingsObjectSnapshot(data->base_url, - data->security_origin, - data->referrer_policy, - data->outgoing_referrer, - data->https_state) {} + : FetchClientSettingsObjectSnapshot( + data->base_url, + data->security_origin, + data->referrer_policy, + data->outgoing_referrer, + data->https_state, + data->mime_type_check_for_classic_worker_script) {} FetchClientSettingsObjectSnapshot::FetchClientSettingsObjectSnapshot( const KURL& base_url, const scoped_refptr<const SecurityOrigin> security_origin, network::mojom::ReferrerPolicy referrer_policy, const String& outgoing_referrer, - HttpsState https_state) + HttpsState https_state, + AllowedByNosniff::MimeTypeCheck mime_type_check_for_classic_worker_script) : base_url_(base_url), security_origin_(std::move(security_origin)), referrer_policy_(referrer_policy), outgoing_referrer_(outgoing_referrer), - https_state_(https_state) {} + https_state_(https_state), + mime_type_check_for_classic_worker_script_( + mime_type_check_for_classic_worker_script) {} } // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h b/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h index 78c217d..2ba7402c 100644 --- a/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h +++ b/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h
@@ -32,18 +32,23 @@ scoped_refptr<const SecurityOrigin> security_origin, network::mojom::ReferrerPolicy referrer_policy, String outgoing_referrer, - HttpsState https_state) + HttpsState https_state, + AllowedByNosniff::MimeTypeCheck mime_type_check_for_classic_worker_script) : base_url(std::move(base_url)), security_origin(std::move(security_origin)), referrer_policy(referrer_policy), outgoing_referrer(std::move(outgoing_referrer)), - https_state(https_state) {} + https_state(https_state), + mime_type_check_for_classic_worker_script( + mime_type_check_for_classic_worker_script) {} const KURL base_url; const scoped_refptr<const SecurityOrigin> security_origin; const network::mojom::ReferrerPolicy referrer_policy; const String outgoing_referrer; const HttpsState https_state; + const AllowedByNosniff::MimeTypeCheck + mime_type_check_for_classic_worker_script; }; // This takes a partial snapshot of the execution context's states so that an @@ -67,7 +72,8 @@ const scoped_refptr<const SecurityOrigin> security_origin, network::mojom::ReferrerPolicy referrer_policy, const String& outgoing_referrer, - HttpsState https_state); + HttpsState https_state, + AllowedByNosniff::MimeTypeCheck); ~FetchClientSettingsObjectSnapshot() override = default; @@ -83,11 +89,17 @@ } HttpsState GetHttpsState() const override { return https_state_; } + AllowedByNosniff::MimeTypeCheck MimeTypeCheckForClassicWorkerScript() + const override { + return mime_type_check_for_classic_worker_script_; + } + // Gets a copy of the data suitable for passing to another thread. std::unique_ptr<CrossThreadFetchClientSettingsObjectData> CopyData() const { return std::make_unique<CrossThreadFetchClientSettingsObjectData>( base_url_.Copy(), security_origin_->IsolatedCopy(), referrer_policy_, - outgoing_referrer_.IsolatedCopy(), https_state_); + outgoing_referrer_.IsolatedCopy(), https_state_, + mime_type_check_for_classic_worker_script_); } private: @@ -96,6 +108,8 @@ const network::mojom::ReferrerPolicy referrer_policy_; const String outgoing_referrer_; const HttpsState https_state_; + const AllowedByNosniff::MimeTypeCheck + mime_type_check_for_classic_worker_script_; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc b/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc index 70094ed..a18eac0 100644 --- a/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc +++ b/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
@@ -47,7 +47,7 @@ MakeGarbageCollected<FetchClientSettingsObjectSnapshot>( KURL(), nullptr /* security_origin */, network::mojom::ReferrerPolicy::kDefault, String(), - HttpsState::kNone)); + HttpsState::kNone, AllowedByNosniff::MimeTypeCheck::kStrict)); } void CountUsage(mojom::WebFeature) const override {}
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h index 5663ba61..06619c7 100644 --- a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h +++ b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
@@ -114,13 +114,6 @@ const FetchClientSettingsObject* GetFetchClientSettingsObject() const; - // Called when the ResourceFetcher observes a data: URI load that contains an - // octothorpe ('#') character. This is a temporary method to support an Intent - // to Deprecate for spec incompliant handling of '#' characters in data URIs. - // - // TODO(crbug.com/123004): Remove once we have enough data for the I2D. - virtual void RecordDataUriWithOctothorpe() {} - // Returns the cache policy for the resource. ResourceRequest is not passed as // a const reference as a header needs to be added for doc.write blocking // intervention.
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc index 22eb769..ca0686e 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -822,7 +822,7 @@ if (context_) { const KURL& url = params.Url(); if (url.HasFragmentIdentifier() && url.ProtocolIsData()) { - context_->RecordDataUriWithOctothorpe(); + context_->CountUsage(mojom::WebFeature::kDataUriHasOctothorpe); } }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc index e777fa5f..f8289cc 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -547,6 +547,7 @@ bool ResourceLoader::WillFollowRedirect( const WebURL& new_url, const WebURL& new_site_for_cookies, + const base::Optional<WebSecurityOrigin>& new_top_frame_origin, const WebString& new_referrer, network::mojom::ReferrerPolicy new_referrer_policy, const WebString& new_method, @@ -561,10 +562,15 @@ return false; } + scoped_refptr<const SecurityOrigin> top_frame_origin = + new_top_frame_origin + ? base::WrapRefCounted(new_top_frame_origin.value().Get()) + : scoped_refptr<SecurityOrigin>(); std::unique_ptr<ResourceRequest> new_request = resource_->LastResourceRequest().CreateRedirectRequest( - new_url, new_method, new_site_for_cookies, new_referrer, - new_referrer_policy, + new_url, new_method, new_site_for_cookies, top_frame_origin, + new_referrer, new_referrer_policy, + !passed_redirect_response.WasFetchedViaServiceWorker()); ResourceType resource_type = resource_->GetType(); @@ -851,29 +857,41 @@ return; } - // If the response is fetched via ServiceWorker, the URL of the response - // could be different from the URL of the request. We check the URL not to - // load the resources which are forbidden by the page CSP. + // Run post-request CSP checks. This is the "Should response to request be + // blocked by Content Security Policy?" algorithm in the CSP specification: // https://w3c.github.io/webappsec-csp/#should-block-response + // + // In particular, the connect-src directive's post-request check: + // https://w3c.github.io/webappsec-csp/#connect-src-post-request) + // + // We only run post-request checks when the response was fetched via service + // worker, because that is the only case where the response URL can differ + // from the current request URL, allowing the result of the check to differ + // from the pre-request check. The pre-request check is implemented in + // ResourceFetcher::PrepareRequest() and + // ResourceFetcher::WillFollowRedirect(). + // + // TODO(falken): To align with the CSP specification, implement post-request + // checks as a first-class concept instead of just reusing the functions for + // pre-request checks, and consider running the checks regardless of service + // worker interception. const KURL& response_url = response.ResponseUrl(); - if (!response_url.IsEmpty()) { - // CanRequest() below only checks enforced policies: check report-only - // here to ensure violations are sent. - Context().CheckCSPForRequest( - request_context, response_url, options, - SecurityViolationReportingPolicy::kReport, - ResourceRequest::RedirectStatus::kFollowedRedirect); + // CanRequest() below only checks enforced policies: check report-only + // here to ensure violations are sent. + Context().CheckCSPForRequest( + request_context, response_url, options, + SecurityViolationReportingPolicy::kReport, + ResourceRequest::RedirectStatus::kFollowedRedirect); - base::Optional<ResourceRequestBlockedReason> blocked_reason = - Context().CanRequest( - resource_type, initial_request, response_url, options, - SecurityViolationReportingPolicy::kReport, - ResourceRequest::RedirectStatus::kFollowedRedirect); - if (blocked_reason) { - HandleError(ResourceError::CancelledDueToAccessCheckError( - response_url, blocked_reason.value())); - return; - } + base::Optional<ResourceRequestBlockedReason> blocked_reason = + Context().CanRequest( + resource_type, initial_request, response_url, options, + SecurityViolationReportingPolicy::kReport, + ResourceRequest::RedirectStatus::kFollowedRedirect); + if (blocked_reason) { + HandleError(ResourceError::CancelledDueToAccessCheckError( + response_url, blocked_reason.value())); + return; } }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.h b/third_party/blink/renderer/platform/loader/fetch/resource_loader.h index 2cc7f9c..c70f949 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
@@ -109,13 +109,15 @@ // A failed load is indicated by 1 DidFail(), which can occur at any time // before DidFinishLoading(), including synchronous inside one of the other // callbacks via ResourceLoader::cancel() - bool WillFollowRedirect(const WebURL& new_url, - const WebURL& new_site_for_cookies, - const WebString& new_referrer, - network::mojom::ReferrerPolicy new_referrer_policy, - const WebString& new_method, - const WebURLResponse& passed_redirect_response, - bool& report_raw_headers) override; + bool WillFollowRedirect( + const WebURL& new_url, + const WebURL& new_site_for_cookies, + const base::Optional<WebSecurityOrigin>& new_top_frame_origin, + const WebString& new_referrer, + network::mojom::ReferrerPolicy new_referrer_policy, + const WebString& new_method, + const WebURLResponse& passed_redirect_response, + bool& report_raw_headers) override; void DidSendData(unsigned long long bytes_sent, unsigned long long total_bytes_to_be_sent) override; void DidReceiveResponse(const WebURLResponse&) override;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc index 4e0c30af..0fa7840b 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
@@ -93,6 +93,7 @@ const KURL& new_url, const AtomicString& new_method, const KURL& new_site_for_cookies, + scoped_refptr<const SecurityOrigin> new_top_frame_origin, const String& new_referrer, network::mojom::ReferrerPolicy new_referrer_policy, bool skip_service_worker) const { @@ -101,6 +102,7 @@ request->SetRequestorOrigin(RequestorOrigin()); request->SetHTTPMethod(new_method); request->SetSiteForCookies(new_site_for_cookies); + request->SetTopFrameOrigin(std::move(new_top_frame_origin)); String referrer = new_referrer.IsEmpty() ? Referrer::NoReferrer() : String(new_referrer); // TODO(domfarolino): Stop storing ResourceRequest's generated referrer as a @@ -181,6 +183,15 @@ site_for_cookies_ = site_for_cookies; } +const SecurityOrigin* ResourceRequest::TopFrameOrigin() const { + return top_frame_origin_.get(); +} + +void ResourceRequest::SetTopFrameOrigin( + scoped_refptr<const SecurityOrigin> origin) { + top_frame_origin_ = std::move(origin); +} + const AtomicString& ResourceRequest::HttpMethod() const { return http_method_; }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.h b/third_party/blink/renderer/platform/loader/fetch/resource_request.h index a50a101..518ddf96 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_request.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.h
@@ -84,6 +84,7 @@ const KURL& new_url, const AtomicString& new_method, const KURL& new_site_for_cookies, + scoped_refptr<const SecurityOrigin> new_top_frame_origin, const String& new_referrer, network::mojom::ReferrerPolicy new_referrer_policy, bool skip_service_worker) const; @@ -104,6 +105,9 @@ const KURL& SiteForCookies() const; void SetSiteForCookies(const KURL&); + const SecurityOrigin* TopFrameOrigin() const; + void SetTopFrameOrigin(scoped_refptr<const SecurityOrigin>); + // The origin of the request, specified at // https://fetch.spec.whatwg.org/#concept-request-origin. This origin can be // null upon request, corresponding to the "client" value in the spec. In that @@ -438,6 +442,7 @@ // TimeDelta::Max() represents the default timeout on platforms that have one. base::TimeDelta timeout_interval_; KURL site_for_cookies_; + scoped_refptr<const SecurityOrigin> top_frame_origin_; scoped_refptr<const SecurityOrigin> requestor_origin_;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc index ffb5fbc..188cbd4e 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc
@@ -33,11 +33,28 @@ std::unique_ptr<ResourceRequest> redirect_request = original.CreateRedirectRequest( KURL("https://example.test/redirect"), original.HttpMethod(), - original.SiteForCookies(), original.HttpReferrer(), - original.GetReferrerPolicy(), original.GetSkipServiceWorker()); + original.SiteForCookies(), original.TopFrameOrigin(), + original.HttpReferrer(), original.GetReferrerPolicy(), + original.GetSkipServiceWorker()); EXPECT_TRUE(redirect_request->IsAdResource()); } +TEST(ResourceRequestTest, SetTopFrameURL) { + KURL url("http://example.com"); + scoped_refptr<SecurityOrigin> origin = SecurityOrigin::Create(url); + ResourceRequest original; + original.SetTopFrameOrigin(origin); + + // Should persist across redirects. + std::unique_ptr<ResourceRequest> redirect_request = + original.CreateRedirectRequest( + KURL("https://example.test/redirect"), original.HttpMethod(), + original.SiteForCookies(), original.TopFrameOrigin(), + original.HttpReferrer(), original.GetReferrerPolicy(), + original.GetSkipServiceWorker()); + EXPECT_EQ(origin, redirect_request->TopFrameOrigin()); +} + TEST(ResourceRequestTest, UpgradeIfInsecureAcrossRedirects) { ResourceRequest original; EXPECT_FALSE(original.UpgradeIfInsecure()); @@ -48,8 +65,9 @@ std::unique_ptr<ResourceRequest> redirect_request = original.CreateRedirectRequest( KURL("https://example.test/redirect"), original.HttpMethod(), - original.SiteForCookies(), original.HttpReferrer(), - original.GetReferrerPolicy(), original.GetSkipServiceWorker()); + original.SiteForCookies(), original.TopFrameOrigin(), + original.HttpReferrer(), original.GetReferrerPolicy(), + original.GetSkipServiceWorker()); EXPECT_TRUE(redirect_request->UpgradeIfInsecure()); }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_response.cc b/third_party/blink/renderer/platform/loader/fetch/resource_response.cc index f83311c..388a37f 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_response.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
@@ -101,11 +101,28 @@ } KURL ResourceResponse::ResponseUrl() const { - if (WasFetchedViaServiceWorker()) { - if (url_list_via_service_worker_.IsEmpty()) - return KURL(); + // Ideally ResourceResponse would have a |url_list_| to match Fetch + // specification's URL list concept + // (https://fetch.spec.whatwg.org/#concept-response-url-list), and its + // last element would be returned here. + // + // Instead it has |url_list_via_service_worker_| which is only populated when + // the response came from a service worker, and that response was not created + // through `new Response()`. Use it when available. + if (!url_list_via_service_worker_.IsEmpty()) { + DCHECK(WasFetchedViaServiceWorker()); return url_list_via_service_worker_.back(); } + + // Otherwise, use the current request URL. This is OK because the Fetch + // specification's "main fetch" algorithm[1] sets the response URL list to the + // request's URL list when the list isn't present. That step can't be + // implemented now because there is no |url_list_| memeber, but effectively + // the same thing happens by returning CurrentRequestUrl() here. + // + // [1] "If internalResponse’s URL list is empty, then set it to a clone of + // request’s URL list." at + // https://fetch.spec.whatwg.org/#ref-for-concept-response-url-list%E2%91%A4 return CurrentRequestUrl(); }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_response.h b/third_party/blink/renderer/platform/loader/fetch/resource_response.h index e36402a..6f6c422 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_response.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_response.h
@@ -179,20 +179,6 @@ // The response URL of this resource. Corresponds to: // https://fetch.spec.whatwg.org/#concept-response-url - // - // Beware that this can be the empty URL. Specifically, if a service worker - // responded to a request using a response created with the Response - // constructor, the response URL is empty. Example service worker code: - // - // onfetch = (event => { - // if (event.request.url == 'https://abc.com') - // event.respondWith(new Response('hi')); - // }); - // - // If this service worker responds to an "https://abc.com" request, then - // for the resulting ResourceResponse, CurrentRequestUrl() is - // "https://abc.com", WasFetchedViaServiceWorker() is true, and - // ResponseUrl() is the empty URL. KURL ResponseUrl() const; const AtomicString& MimeType() const;
diff --git a/third_party/blink/renderer/platform/loader/ftp_directory_listing.cc b/third_party/blink/renderer/platform/loader/ftp_directory_listing.cc new file mode 100644 index 0000000..34b8172 --- /dev/null +++ b/third_party/blink/renderer/platform/loader/ftp_directory_listing.cc
@@ -0,0 +1,110 @@ +// 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 "third_party/blink/renderer/platform/loader/ftp_directory_listing.h" + +#include <string> +#include <vector> + +#include "base/i18n/encoding_detection.h" +#include "base/i18n/icu_string_conversions.h" +#include "base/logging.h" +#include "base/strings/string_util.h" +#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "base/time/time.h" +#include "net/base/directory_listing.h" +#include "net/base/escape.h" +#include "net/base/net_errors.h" +#include "net/ftp/ftp_directory_listing_parser.h" +#include "net/net_buildflags.h" +#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h" +#include "third_party/blink/renderer/platform/shared_buffer.h" +#include "third_party/blink/renderer/platform/weborigin/kurl.h" +#include "url/gurl.h" + +namespace blink { + +namespace { + +base::string16 ConvertPathToUTF16(const std::string& path) { + // Per RFC 2640, FTP servers should use UTF-8 or its proper subset ASCII, + // but many old FTP servers use legacy encodings. Try UTF-8 first. + if (base::IsStringUTF8(path)) + return base::UTF8ToUTF16(path); + + // Try detecting the encoding. The sample is rather small though, so it may + // fail. + std::string encoding; + if (base::DetectEncoding(path, &encoding) && encoding != "US-ASCII") { + base::string16 path_utf16; + if (base::CodepageToUTF16(path, encoding.c_str(), + base::OnStringConversionError::SUBSTITUTE, + &path_utf16)) { + return path_utf16; + } + } + + // Use system native encoding as the last resort. + return base::WideToUTF16(base::SysNativeMBToWide(path)); +} + +} // namespace + +scoped_refptr<SharedBuffer> GenerateFtpDirectoryListingHtml( + const KURL& url, + const SharedBuffer* input) { + const GURL gurl = url; + scoped_refptr<SharedBuffer> output = SharedBuffer::Create(); + net::UnescapeRule::Type unescape_rules = + net::UnescapeRule::SPACES | + net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS; + std::string unescaped_path = + net::UnescapeURLComponent(gurl.path(), unescape_rules); + const std::string header = + net::GetDirectoryListingHeader(ConvertPathToUTF16(unescaped_path)); + output->Append(header.c_str(), header.size()); + + // If this isn't top level directory (i.e. the path isn't "/",) + // add a link to the parent directory. + if (gurl.path().length() > 1) { + const std::string link = net::GetParentDirectoryLink(); + output->Append(link.c_str(), link.size()); + } + + std::string flatten; + for (const auto& span : *input) { + flatten.append(span.data(), span.size()); + } + + std::vector<net::FtpDirectoryListingEntry> entries; + int rv = net::ERR_NOT_IMPLEMENTED; +#if !BUILDFLAG(DISABLE_FTP_SUPPORT) + rv = net::ParseFtpDirectoryListing(flatten, base::Time::Now(), &entries); +#endif + if (rv != net::OK) { + const std::string script = "<script>onListingParsingError();</script>\n"; + output->Append(script.c_str(), script.size()); + return output; + } + for (const net::FtpDirectoryListingEntry& entry : entries) { + // Skip the current and parent directory entries in the listing. + // net::GetParentDirectoryLink() takes care of them. + if (base::EqualsASCII(entry.name, ".") || + base::EqualsASCII(entry.name, "..")) + continue; + + bool is_directory = + (entry.type == net::FtpDirectoryListingEntry::DIRECTORY); + int64_t size = + entry.type == net::FtpDirectoryListingEntry::FILE ? entry.size : 0; + std::string entry_string = net::GetDirectoryListingEntry( + entry.name, entry.raw_name, is_directory, size, entry.last_modified); + output->Append(entry_string.c_str(), entry_string.size()); + } + + return output; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/ftp_directory_listing.h b/third_party/blink/renderer/platform/loader/ftp_directory_listing.h new file mode 100644 index 0000000..78473c8 --- /dev/null +++ b/third_party/blink/renderer/platform/loader/ftp_directory_listing.h
@@ -0,0 +1,25 @@ +// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FTP_DIRECTORY_LISTING_H_ +#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FTP_DIRECTORY_LISTING_H_ + +#include "base/memory/scoped_refptr.h" +#include "base/optional.h" +#include "third_party/blink/renderer/platform/platform_export.h" + +namespace blink { + +class KURL; +class SharedBuffer; + +// Translates |input|, an FTP LISTING result, to an HTML and returns it. When +// an error happens that is written in the result HTML. +PLATFORM_EXPORT scoped_refptr<SharedBuffer> GenerateFtpDirectoryListingHtml( + const KURL& url, + const SharedBuffer* input); + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FTP_DIRECTORY_LISTING_H_
diff --git a/third_party/blink/renderer/platform/loader/ftp_directory_listing_test.cc b/third_party/blink/renderer/platform/loader/ftp_directory_listing_test.cc new file mode 100644 index 0000000..c840479 --- /dev/null +++ b/third_party/blink/renderer/platform/loader/ftp_directory_listing_test.cc
@@ -0,0 +1,111 @@ +// 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 "third_party/blink/renderer/platform/loader/ftp_directory_listing.h" + +#include <string> + +#include "base/test/icu_test_util.h" +#include "net/net_buildflags.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h" +#include "third_party/blink/renderer/platform/shared_buffer.h" +#include "third_party/blink/renderer/platform/weborigin/kurl.h" +#include "third_party/icu/source/i18n/unicode/timezone.h" + +namespace blink { +namespace { + +class ScopedRestoreDefaultTimezone { + public: + explicit ScopedRestoreDefaultTimezone(const char* zoneid) { + original_zone_.reset(icu::TimeZone::createDefault()); + icu::TimeZone::adoptDefault(icu::TimeZone::createTimeZone(zoneid)); + } + ~ScopedRestoreDefaultTimezone() { + icu::TimeZone::adoptDefault(original_zone_.release()); + } + + ScopedRestoreDefaultTimezone(const ScopedRestoreDefaultTimezone&) = delete; + ScopedRestoreDefaultTimezone& operator=(const ScopedRestoreDefaultTimezone&) = + delete; + + private: + std::unique_ptr<icu::TimeZone> original_zone_; +}; + +#if !BUILDFLAG(DISABLE_FTP_SUPPORT) +TEST(FtpDirectoryListingTest, Top) { + base::test::ScopedRestoreICUDefaultLocale locale("en_US"); + ScopedRestoreDefaultTimezone timezone("Asia/Tokyo"); + + const KURL url("ftp://ftp.example.com/"); + + const std::string input = "drwxr-xr-x 1 ftp ftp 17 Feb 15 2016 top\r\n"; + // Referring to code in net/base/dir_header.html, but the code itself + // is not included in the expectation due to unittest configuration. + std::string expected = R"JS(<script>start("/");</script> +<script>addRow("top","top",1,0,"0 B",1455494400,"2/15/16, 9:00:00 AM");</script> +)JS"; + auto input_buffer = SharedBuffer::Create(); + input_buffer->Append(input.data(), input.size()); + + auto output = GenerateFtpDirectoryListingHtml(url, input_buffer.get()); + std::string flatten_output; + for (const auto span : *output) { + flatten_output.append(span.data(), span.size()); + } + + EXPECT_EQ(expected, flatten_output); +} +#endif // !BUILDFLAG(DISABLE_FTP_SUPPORT) + +#if !BUILDFLAG(DISABLE_FTP_SUPPORT) +TEST(FtpDirectoryListingTest, NonTop) { + base::test::ScopedRestoreICUDefaultLocale locale("en_US"); + ScopedRestoreDefaultTimezone timezone("Asia/Tokyo"); + const KURL url("ftp://ftp.example.com/foo/"); + + const std::string input = "drwxr-xr-x 1 ftp ftp 17 Feb 15 2016 dir\r\n"; + // Referring to code in net/base/dir_header.html, but the code itself + // is not included in the expectation due to unittest configuration. + std::string expected = R"JS(<script>start("/foo/");</script> +<script>onHasParentDirectory();</script> +<script>addRow("dir","dir",1,0,"0 B",1455494400,"2/15/16, 9:00:00 AM");</script> +)JS"; + + auto input_buffer = SharedBuffer::Create(); + input_buffer->Append(input.data(), input.size()); + + auto output = GenerateFtpDirectoryListingHtml(url, input_buffer.get()); + std::string flatten_output; + for (const auto span : *output) { + flatten_output.append(span.data(), span.size()); + } + + EXPECT_EQ(expected, flatten_output); +} +#endif // !BUILDFLAG(DISABLE_FTP_SUPPORT) + +TEST(FtpDirectoryListingTest, Fail) { + base::test::ScopedRestoreICUDefaultLocale locale("en_US"); + ScopedRestoreDefaultTimezone timezone("Asia/Tokyo"); + const KURL url("ftp://ftp.example.com/"); + auto input = SharedBuffer::Create(); + input->Append("bogus", 5u); + std::string expected = R"JS(<script>start("/");</script> +<script>onListingParsingError();</script> +)JS"; + auto output = GenerateFtpDirectoryListingHtml(url, input.get()); + std::string flatten_output; + for (const auto span : *output) { + flatten_output.append(span.data(), span.size()); + } + + EXPECT_EQ(expected, flatten_output); +} + +} // namespace + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h b/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h index 56551b9..00a92db 100644 --- a/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h +++ b/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
@@ -69,7 +69,7 @@ MakeGarbageCollected<FetchClientSettingsObjectSnapshot>( KURL(), std::move(security_origin), network::mojom::ReferrerPolicy::kDefault, String(), - HttpsState::kNone)); + HttpsState::kNone, AllowedByNosniff::MimeTypeCheck::kStrict)); } // The last ResourceRequest passed to DispatchWillSendRequest.
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 5b1c490..18830b80 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -131,10 +131,11 @@ }, { name: "Badging", - status: "test", + status: "experimental", }, { name: "BlinkGenPropertyTrees", + status: "experimental", }, { name: "BlinkRuntimeCallStats", @@ -418,10 +419,6 @@ status: "test", }, { - name: "EncodingStreams", - status: "stable", - }, - { name: "EncryptedMediaEncryptionSchemeQuery", status: "test", }, @@ -933,10 +930,25 @@ name: "OverscrollCustomization", settable_from_internals: true, }, + // This feature refers to the API that delivers notifications to pages on + // lifecycle state changes. { name: "PageLifecycle", status: "stable", }, + // The following are developer opt-outs and opt-ins for PageLifecycle state + // transitions. If neither is specified then heuristics will be applied to + // determine whether the page is eligible. + { + name: "PageLifecycleTransitionsOptIn", + origin_trial_feature_name: "PageLifecycleTransitionsOptIn", + status: "experimental", + }, + { + name: "PageLifecycleTransitionsOptOut", + origin_trial_feature_name: "PageLifecycleTransitionsOptOut", + status: "experimental", + }, { name: "PagePopup", status: "stable",
diff --git a/third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor.cc b/third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor.cc index 2f0cebae..783b01ab8 100644 --- a/third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor.cc +++ b/third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor.cc
@@ -41,11 +41,10 @@ ordered_actions_.emplace_back(main_thread_manager_->ordered_actions()); ordered_tasks_.emplace_back(main_thread_manager_->ordered_tasks()); - for (auto&& thread : (thread_pool_manager_->threads())) { - DCHECK(thread->thread_manager()); - ordered_actions_.emplace_back( - thread->thread_manager()->ordered_actions()); - ordered_tasks_.emplace_back(thread->thread_manager()->ordered_tasks()); + for (ThreadManager* thread_manager : + thread_pool_manager_->GetAllThreadManagers()) { + ordered_actions_.emplace_back(thread_manager->ordered_actions()); + ordered_tasks_.emplace_back(thread_manager->ordered_tasks()); } } }
diff --git a/third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor_unittest.cc b/third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor_unittest.cc index 04586d06..6759a69 100644 --- a/third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor_unittest.cc +++ b/third_party/blink/renderer/platform/scheduler/test/fuzzer/sequence_manager_fuzzer_processor_unittest.cc
@@ -1478,5 +1478,23 @@ EXPECT_THAT(executed_tasks, ContainerEq(expected_tasks)); } +TEST(SequenceManagerFuzzerProcessorTest, CrossThreadPostFromChildThreads) { + // We do not wait for child threads to start, so their ThreadManager* might + // not be registered by the time we cross post the task + SequenceManagerTestDescription description; + auto* main_thread = + description.add_main_thread_actions()->mutable_create_thread(); + for (int i = 0; i < 100; ++i) { + auto* child_thread = + main_thread->add_initial_thread_actions()->mutable_create_thread(); + + child_thread->add_initial_thread_actions() + ->mutable_cross_thread_post() + ->set_thread_id(i + 1234); + } + + SequenceManagerFuzzerProcessor::ParseAndRun(description); +} + } // namespace sequence_manager } // namespace base
diff --git a/third_party/blink/renderer/platform/scheduler/test/fuzzer/simple_thread_impl.cc b/third_party/blink/renderer/platform/scheduler/test/fuzzer/simple_thread_impl.cc index 85b0132..90414bb 100644 --- a/third_party/blink/renderer/platform/scheduler/test/fuzzer/simple_thread_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/test/fuzzer/simple_thread_impl.cc
@@ -30,9 +30,5 @@ Join(); } -ThreadManager* SimpleThreadImpl::thread_manager() const { - return thread_manager_; -} - } // namespace sequence_manager } // namespace base
diff --git a/third_party/blink/renderer/platform/scheduler/test/fuzzer/simple_thread_impl.h b/third_party/blink/renderer/platform/scheduler/test/fuzzer/simple_thread_impl.h index d1d1f1e..d19ec4c 100644 --- a/third_party/blink/renderer/platform/scheduler/test/fuzzer/simple_thread_impl.h +++ b/third_party/blink/renderer/platform/scheduler/test/fuzzer/simple_thread_impl.h
@@ -29,8 +29,6 @@ ~SimpleThreadImpl() override; - ThreadManager* thread_manager() const; - private: // This doesn't terminate until |this| object is destructed. void Run() override;
diff --git a/third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_pool_manager.cc b/third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_pool_manager.cc index 6c9b6420..bd01bd1 100644 --- a/third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_pool_manager.cc +++ b/third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_pool_manager.cc
@@ -33,7 +33,7 @@ const google::protobuf::RepeatedPtrField< SequenceManagerTestDescription::Action>& initial_thread_actions, TimeTicks time) { - SimpleThreadImpl* thread; + SimpleThread* thread; { AutoLock lock(lock_); threads_.push_back(std::make_unique<SimpleThreadImpl>( @@ -51,6 +51,7 @@ ThreadManager* thread_manager) { { AutoLock lock(lock_); + thread_managers_.push_back(thread_manager); while (!initial_threads_created_) ready_to_execute_threads_.Wait(); } @@ -147,19 +148,21 @@ } } -const std::vector<std::unique_ptr<SimpleThreadImpl>>& -ThreadPoolManager::threads() const { - return threads_; -} - SequenceManagerFuzzerProcessor* ThreadPoolManager::processor() const { return processor_; } ThreadManager* ThreadPoolManager::GetThreadManagerFor(uint64_t thread_id) { AutoLock lock(lock_); - int id = thread_id % threads_.size(); - return threads_[id]->thread_manager(); + if (thread_managers_.empty()) + return nullptr; + int id = thread_id % thread_managers_.size(); + return thread_managers_[id]; +} + +std::vector<ThreadManager*> ThreadPoolManager::GetAllThreadManagers() { + AutoLock lock(lock_); + return thread_managers_; } } // namespace sequence_manager
diff --git a/third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_pool_manager.h b/third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_pool_manager.h index 1aeb27bef..a802c9ac 100644 --- a/third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_pool_manager.h +++ b/third_party/blink/renderer/platform/scheduler/test/fuzzer/thread_pool_manager.h
@@ -10,6 +10,7 @@ #include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" +#include "base/threading/simple_thread.h" #include "base/time/time.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/scheduler/test/fuzzer/proto/sequence_manager_test_description.pb.h" @@ -18,7 +19,6 @@ namespace sequence_manager { class SequenceManagerFuzzerProcessor; -class SimpleThreadImpl; class ThreadManager; // Used by the SequenceManagerFuzzerProcessor to manage threads and synchronize @@ -58,12 +58,17 @@ // the threads are not terminated until |this| gets destructed. void WaitForAllThreads(); + // (Thread Safe) + std::vector<ThreadManager*> GetAllThreadManagers(); + // (Thread Safe) Used to return the thread manager of the |thread_id|'s entry // in |threads_| (modulo the number of entries). + // Note: not all threads created with CreateThread() might have had time to + // register their thread manager by the time this method is called as the + // ThreadManager creation happens on the new thread. This method will return + // nullptr if no ThreadManager was registered yet. ThreadManager* GetThreadManagerFor(uint64_t thread_id); - const std::vector<std::unique_ptr<SimpleThreadImpl>>& threads() const; - SequenceManagerFuzzerProcessor* processor() const; private: @@ -133,7 +138,14 @@ // Threads that are being managed/synchronized. For unit testing purposes, // make sure not to create threads at the same time (if the ordering matters) // since in this case the order will not be deterministic. - std::vector<std::unique_ptr<SimpleThreadImpl>> threads_; + std::vector<std::unique_ptr<SimpleThread>> threads_; + + // ThreadManager instances associated to the managed threads. Values are not + // stored in any particular order and there might not exist a manager for all + // managed threads at any point in time (SimpleThread instances are created + // before their corresponding ThreadManager, as this must happen on the actual + // thread). + std::vector<ThreadManager*> thread_managers_; }; } // namespace sequence_manager
diff --git a/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc b/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc index 15219c4c..9ce98802 100644 --- a/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc +++ b/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc
@@ -25,6 +25,20 @@ static const int kWarmupRuns = 5; static const int kTimeCheckInterval = 10; +struct HarfBuzzShaperCallbackContext { + const HarfBuzzShaper* shaper; + const Font* font; + TextDirection direction; +}; + +scoped_refptr<ShapeResult> HarfBuzzShaperCallback(void* untyped_context, + unsigned start, + unsigned end) { + HarfBuzzShaperCallbackContext* context = + static_cast<HarfBuzzShaperCallbackContext*>(untyped_context); + return context->shaper->Shape(context->font, context->direction, start, end); +} + LayoutUnit ShapeText(ShapingLineBreaker* breaker, LayoutUnit available_space, unsigned string_length) { @@ -127,8 +141,11 @@ HarfBuzzShaper shaper(string); scoped_refptr<const ShapeResult> reference_result = shaper.Shape(&font, direction); - ShapingLineBreaker reference_breaker(&shaper, &font, reference_result.get(), - &break_iterator); + HarfBuzzShaperCallbackContext context{&shaper, &font, + reference_result->Direction()}; + ShapingLineBreaker reference_breaker(reference_result, &break_iterator, + nullptr, HarfBuzzShaperCallback, + &context); scoped_refptr<const ShapeResult> line; LayoutUnit available_width_px(500); @@ -138,7 +155,8 @@ timer_.Reset(); do { scoped_refptr<const ShapeResult> result = shaper.Shape(&font, direction); - ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator); + ShapingLineBreaker breaker(result, &break_iterator, nullptr, + HarfBuzzShaperCallback, &context); LayoutUnit width = ShapeText(&breaker, available_width_px, len); EXPECT_EQ(expected_width, width);
diff --git a/third_party/blink/renderer/platform/testing/weburl_loader_mock.cc b/third_party/blink/renderer/platform/testing/weburl_loader_mock.cc index 93d1e97..3a42fa3 100644 --- a/third_party/blink/renderer/platform/testing/weburl_loader_mock.cc +++ b/third_party/blink/renderer/platform/testing/weburl_loader_mock.cc
@@ -8,6 +8,7 @@ #include "third_party/blink/public/platform/url_conversion.h" #include "third_party/blink/public/platform/web_data.h" +#include "third_party/blink/public/platform/web_security_origin.h" #include "third_party/blink/public/platform/web_url_error.h" #include "third_party/blink/public/platform/web_url_loader_client.h" #include "third_party/blink/renderer/platform/shared_buffer.h" @@ -93,7 +94,8 @@ bool report_raw_headers = false; bool follow = client_->WillFollowRedirect( - redirect_url, redirect_url, WebString(), + redirect_url, redirect_url, + WebSecurityOrigin::Create(WebURL(redirect_url)), WebString(), network::mojom::ReferrerPolicy::kDefault, request.HttpMethod(), redirect_response, report_raw_headers); // |this| might be deleted in willFollowRedirect().
diff --git a/third_party/blink/renderer/platform/web_test_support.cc b/third_party/blink/renderer/platform/web_test_support.cc index 66a26d6c..be87a75 100644 --- a/third_party/blink/renderer/platform/web_test_support.cc +++ b/third_party/blink/renderer/platform/web_test_support.cc
@@ -36,11 +36,11 @@ namespace blink { // Wrapper functions defined in blink.h -void SetLayoutTestMode(bool value) { +void SetWebTestMode(bool value) { WebTestSupport::SetIsRunningWebTest(value); } -bool LayoutTestMode() { +bool WebTestMode() { return WebTestSupport::IsRunningWebTest(); }
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py b/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py index 6a766fd..0d0554a 100644 --- a/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py +++ b/third_party/blink/tools/blinkpy/web_tests/controllers/manager.py
@@ -99,7 +99,7 @@ self._printer.write_update('Collecting tests ...') running_all_tests = False - if not args or any('external' in path for path in args): + if self._options.manifest_update and (not args or any('external' in path for path in args)): self._printer.write_update('Generating MANIFEST.json for web-platform-tests ...') WPTManifest.ensure_manifest(self._port.host) self._printer.write_update('Completed generating manifest.')
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/base.py b/third_party/blink/tools/blinkpy/web_tests/port/base.py index cde939d8..4c559dd 100644 --- a/third_party/blink/tools/blinkpy/web_tests/port/base.py +++ b/third_party/blink/tools/blinkpy/web_tests/port/base.py
@@ -798,7 +798,7 @@ def _wpt_manifest(self): manifest_path = self._filesystem.join(self.layout_tests_dir(), 'external', 'wpt', 'MANIFEST.json') if not self._filesystem.exists(manifest_path): - _log.error('Manifest not found at %s. See http://crbug.com/698294', manifest_path) + _log.error('Manifest not found at %s. Remove the --no-manifest-update argument to generate it.', manifest_path) return WPTManifest('{}') return WPTManifest(self._filesystem.read_text_file(manifest_path))
diff --git a/third_party/blink/tools/blinkpy/web_tests/run_webkit_tests.py b/third_party/blink/tools/blinkpy/web_tests/run_webkit_tests.py index fac537df..a527fbe6 100644 --- a/third_party/blink/tools/blinkpy/web_tests/run_webkit_tests.py +++ b/third_party/blink/tools/blinkpy/web_tests/run_webkit_tests.py
@@ -467,6 +467,16 @@ ' Used on trybots when layout tests are retried without patch.') ])) + option_group_definitions.append( + ('web-platform-tests (WPT) Options', [ + optparse.make_option( + '--no-manifest-update', + dest='manifest_update', + action='store_false', + default=True, + help=('Do not update the web-platform-tests MANIFEST.json.')), + ])) + # FIXME: Move these into json_results_generator.py. option_group_definitions.append( ('Result JSON Options', [
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=BlinkGenPropertyTrees b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=BlinkGenPropertyTrees index ccdaafd6..f8a60d17 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=BlinkGenPropertyTrees +++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=BlinkGenPropertyTrees
@@ -1,6 +1,5 @@ # Expectations for --enable-blink-features=BlinkGenPropertyTrees -# We are focused on scrolling, compositing, animations, threading, and paint -# related tests with all other directories skipped to improve bot cycle time. +# TODO(pdr): Remove these expectations as blink-gen-property-trees is enabled. Bug(none) app_banner/ [ Skip ] Bug(none) battery-status/ [ Skip ] @@ -9,7 +8,6 @@ Bug(none) clipboard/ [ Skip ] Bug(none) crypto/ [ Skip ] Bug(none) css-parser/ [ Skip ] -Bug(none) css-shadow-parts/ [ Skip ] Bug(none) custom-elements/ [ Skip ] Bug(none) custom-properties/ [ Skip ] Bug(none) device_orientation/ [ Skip ] @@ -62,7 +60,6 @@ Bug(none) virtual/custom-user-timing/ [ Skip ] Bug(none) virtual/exotic-color-space/ [ Skip ] Bug(none) virtual/feature-policy-permissions/ [ Skip ] -Bug(none) virtual/feature-policy-vibrate/ [ Skip ] Bug(none) virtual/gpu-rasterization/ [ Skip ] Bug(none) virtual/gpu/ [ Skip ] Bug(none) virtual/high-contrast-mode/ [ Skip ] @@ -76,6 +73,7 @@ Bug(none) virtual/mouseevent_fractional/ [ Skip ] Bug(none) virtual/mse-1mb-buffers/ [ Skip ] Bug(none) virtual/new-remote-playback-pipeline/ [ Skip ] +Bug(none) virtual/not-blink-gen-property-trees/ [ Skip ] Bug(none) virtual/origin-trials-runtimeflags-disabled/ [ Skip ] Bug(none) virtual/outofblink-cors/ [ Skip ] Bug(none) virtual/paint-timing/ [ Skip ] @@ -88,7 +86,6 @@ Bug(none) virtual/scalefactor200withzoom/ [ Skip ] Bug(none) virtual/sharedarraybuffer/ [ Skip ] Bug(none) virtual/single-renderer-process/ [ Skip ] -Bug(none) virtual/composite-after-paint/ [ Skip ] Bug(none) virtual/stable/ [ Skip ] Bug(none) virtual/sxg-with-network-service/ [ Skip ] Bug(none) virtual/sxg/ [ Skip ] @@ -109,9 +106,7 @@ # These tests failed in normal mode but are fixed with BlinkGenPropertyTrees. Bug(none) compositing/overflow/clip-escaping-reverse-order-should-not-crash.html [ Pass ] -Bug(none) compositing/overflow/composited-scroll-with-fractional-translation.html [ Pass ] Bug(none) virtual/prefer_compositing_to_lcd_text/compositing/overflow/clip-escaping-reverse-order-should-not-crash.html [ Pass ] -Bug(none) virtual/prefer_compositing_to_lcd_text/compositing/overflow/composited-scroll-with-fractional-translation.html [ Pass ] crbug.com/865039 compositing/masks/mask-with-added-filters.html [ Pass ] # Link highlights are no longer affected by ancestor effects.
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint index 2831e10..685f64c 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint +++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
@@ -22,6 +22,7 @@ Bug(none) virtual/layout_ng_experimental/ [ Skip ] Bug(none) virtual/mouseevent_fractional/ [ Skip ] Bug(none) virtual/new-remote-playback-pipeline/ [ Skip ] +Bug(none) virtual/not-blink-gen-property-trees/ [ Skip ] Bug(none) virtual/outofblink-cors/ [ Skip ] Bug(none) virtual/prefer_compositing_to_lcd_text/ [ Skip ] Bug(none) virtual/scroll_customization/ [ Skip ] @@ -50,9 +51,10 @@ Bug(none) compositing/change-preferCompositingToLCDText-setting.html [ Failure ] Bug(none) compositing/contents-opaque/hidden-with-visible-child.html [ Failure ] Bug(none) compositing/contents-opaque/layer-opacity.html [ Failure ] +Bug(none) compositing/culling/filter-occlusion-blur-large.html [ Failure ] +Bug(none) compositing/culling/filter-occlusion-blur.html [ Failure ] Bug(none) compositing/draws-content/canvas-background-layer.html [ Failure ] Bug(none) compositing/draws-content/webgl-background-layer.html [ Failure ] -Bug(none) compositing/flat-with-transformed-child.html [ Failure ] Bug(none) compositing/force-compositing-mode/overflow-iframe-enter-compositing.html [ Failure ] Bug(none) compositing/force-compositing-mode/overflow-iframe-layer.html [ Failure ] Bug(none) compositing/geometry/bounds-clipped-composited-child.html [ Failure ] @@ -61,19 +63,14 @@ Bug(none) compositing/geometry/clip-inside.html [ Failure ] Bug(none) compositing/geometry/clip-with-shadow.html [ Failure ] Bug(none) compositing/geometry/clip.html [ Failure ] -Bug(none) compositing/geometry/fixed-position-transform-composited-page-scale.html [ Failure ] Bug(none) compositing/geometry/foreground-layer.html [ Failure ] -Bug(none) compositing/geometry/layer-due-to-layer-children-deep.html [ Failure ] Bug(none) compositing/geometry/layer-due-to-layer-children-deep-switch.html [ Failure ] -Bug(none) compositing/geometry/layer-due-to-layer-children.html [ Failure ] Bug(none) compositing/geometry/limit-layer-bounds-opacity-transition.html [ Failure ] Bug(none) compositing/geometry/limit-layer-bounds-overflow-root.html [ Failure ] Bug(none) compositing/geometry/limit-layer-bounds-positioned-transition.html [ Failure ] Bug(none) compositing/geometry/limit-layer-bounds-positioned.html [ Failure ] Bug(none) compositing/geometry/limit-layer-bounds-transformed.html [ Failure ] Bug(none) compositing/geometry/preserve-3d-switching.html [ Failure ] -Bug(none) compositing/geometry/video-fixed-scrolling.html [ Failure ] -Bug(none) compositing/geometry/video-opacity-overlay.html [ Failure ] Bug(none) compositing/iframes/become-composited-nested-iframes.html [ Failure ] Bug(none) compositing/iframes/become-overlapped-iframe.html [ Failure ] Bug(none) compositing/iframes/iframe-composited-scrolling-hide-and-show.html [ Failure ] @@ -107,7 +104,6 @@ Bug(none) compositing/layer-creation/scroll-partial-update.html [ Failure ] Bug(none) compositing/layer-creation/spanOverlapsCanvas.html [ Failure ] Bug(none) compositing/layer-creation/squashing-into-ancestor-clipping-layer-change.html [ Failure ] -Bug(none) compositing/layers-inside-overflow-scroll.html [ Failure ] Bug(none) compositing/masks/mask-with-removed-filters.html [ Failure ] Bug(none) compositing/overflow/accelerated-overflow-scroll-should-not-affect-perspective.html [ Failure ] Bug(none) compositing/overflow/accelerated-scrolling-with-clip-path.html [ Failure ] @@ -116,10 +112,7 @@ Bug(none) compositing/overflow/clip-descendents.html [ Failure ] Bug(none) compositing/overflow/content-loses-scrollbars.html [ Failure ] Bug(none) compositing/overflow/content-gains-scrollbars.html [ Failure ] -Bug(none) compositing/overflow/mask-with-filter.html [ Failure Crash ] -Bug(none) compositing/overflow/nested-render-surfaces-with-rotation.html [ Failure ] Bug(none) compositing/overflow/opt-in-if-composited.html [ Failure ] -Bug(none) compositing/overflow/overflow-compositing-descendant.html [ Failure ] Bug(none) compositing/overflow/overflow-scroll-background-fractional-offset.html [ Failure ] Bug(none) compositing/overflow/overflow-scroll-background-opaque-to-transparent.html [ Failure ] Bug(none) compositing/overflow/overflow-scroll-background-transparent-to-opaque.html [ Failure ] @@ -131,7 +124,6 @@ Bug(none) compositing/overflow/reparented-scrollbars-non-sc-anc.html [ Failure ] Bug(none) compositing/overflow/resize-painting.html [ Failure ] Bug(none) compositing/overflow/scaled-overflow.html [ Failure ] -Bug(none) compositing/overflow/scroll-ancestor-update.html [ Failure ] Bug(none) compositing/overflow/scroll-parent-absolute-with-backdrop-filter.html [ Failure ] Bug(none) compositing/overflow/scroll-parent-absolute.html [ Failure ] Bug(none) compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor.html [ Failure ] @@ -142,11 +134,8 @@ crbug.com/667946 compositing/overflow/scrolls-with-respect-to-transform.html [ Failure Crash ] crbug.com/667946 compositing/overflow/scrolls-with-respect-to.html [ Failure Crash ] Bug(none) compositing/overflow/textarea-scroll-touch.html [ Failure ] -Bug(none) compositing/overflow/tiled-mask.html [ Failure ] Bug(none) compositing/overflow/universal-accelerated-overflow-scroll.html [ Failure ] -Bug(none) compositing/perpendicular-layer-sorting.html [ Failure ] Bug(none) compositing/reflections/deeply-nested-reflections.html [ Failure Crash ] -Bug(none) compositing/reflections/nested-reflection-anchor-point.html [ Failure Crash ] Bug(none) compositing/reflections/nested-reflection-mask-change.html [ Failure Crash ] Bug(none) compositing/rtl/rtl-absolute-overflow-scrolled.html [ Failure Crash ] Bug(none) compositing/rtl/rtl-absolute-overflow.html [ Failure Crash ] @@ -160,7 +149,6 @@ Bug(none) compositing/rtl/rtl-iframe-fixed.html [ Failure ] Bug(none) compositing/rtl/rtl-iframe-relative.html [ Failure ] Bug(none) compositing/scrollbars/nested-overlay-scrollbars.html [ Failure ] -Bug(none) compositing/self-painting-layers.html [ Failure ] Bug(none) compositing/squashing/add-remove-squashed-layers.html [ Failure ] Bug(none) compositing/squashing/composited-bounds-for-negative-z.html [ Failure ] Bug(none) compositing/squashing/do-not-squash-non-self-painting-layer.html [ Failure ] @@ -189,9 +177,9 @@ Bug(none) compositing/visibility/layer-visible-content.html [ Failure ] Bug(none) compositing/visibility/overlays.html [ Failure Crash ] Bug(none) compositing/visibility/visibility-image-layers-dynamic.html [ Crash Failure ] -Bug(none) compositing/visibility/visibility-simple-video-layer.html [ Failure ] Bug(none) compositing/webgl/webgl-reflection.html [ Failure Pass ] Bug(none) compositing/webgl/webgl-with-accelerated-background-color.html [ Failure Pass ] +Bug(none) custom-elements/form-validation-bubble-appearance.html [ Failure ] Bug(none) fast/canvas/OffscreenCanvas-2d-drawImage-in-worker.html [ Failure ] Bug(none) fast/canvas/OffscreenCanvas-2d-drawImage.html [ Failure ] Bug(none) fast/canvas/OffscreenCanvas-2d-gradients-in-worker.html [ Failure ] @@ -240,7 +228,6 @@ Bug(none) fast/sub-pixel/transformed-iframe-copy-on-scroll.html [ Failure ] Bug(none) fragmentation/outline-crossing-columns.html [ Crash ] Bug(none) fullscreen/compositor-touch-hit-rects-fullscreen-video-controls.html [ Failure ] -Bug(none) http/tests/local/blob/send-data-blob.html [ Crash ] Bug(none) http/tests/misc/scroll-cross-origin-iframes.html [ Timeout ] Bug(none) http/tests/misc/slow-loading-mask.html [ Failure ] Bug(none) http/tests/navigation/same-document-scroll-position-restore.html [ Timeout ] @@ -353,17 +340,11 @@ crbug.com/707444 svg/custom/clip-mask-negative-scale.svg [ Failure ] # Subpixel differences -Bug(none) compositing/overflow/border-radius-styles-with-composited-child.html [ Failure ] -Bug(none) compositing/overflow/overflow-scroll-with-negative-offset-translucent-outline.html [ Failure ] Bug(none) fast/scrolling/fractional-scroll-offset-fixed-position-non-composited.html [ Failure ] Bug(none) svg/custom/grayscale-gradient-mask-2.svg [ Failure ] -Bug(none) svg/custom/grayscale-gradient-mask.svg [ Failure ] Bug(none) svg/wicd/test-rightsizing-b.xhtml [ Crash Failure ] Bug(none) paint/invalidation/scroll/scroll-in-transformed-layer.html [ Failure ] Bug(none) paint/invalidation/scroll/scroll-with-transformed-parent-layer.html [ Failure ] -Bug(none) compositing/reflections/nested-reflection-animated.html [ Failure ] -Bug(none) compositing/transitions/scale-transition-no-start.html [ Failure ] -Bug(none) virtual/threaded/animations/skew-notsequential-compositor.html [ Failure ] crbug.com/644358 fast/block/float/float-overhanging-grandparent-change-self-painting.html [ Crash ] @@ -385,11 +366,6 @@ Bug(none) fast/scroll-snap/snap-scrolls-visual-viewport.html [ Failure ] Bug(none) fast/events/remove-child-onscroll.html [ Timeout ] -Bug(none) compositing/lots-of-img-layers-with-opacity.html [ Failure ] -Bug(none) compositing/lots-of-img-layers.html [ Failure ] - -Bug(none) css3/blending/background-blend-mode-overlapping-accelerated-elements.html [ Failure ] - # Text failures due to layerization differences Bug(none) compositing/overflow/scroller-with-border-radius.html [ Failure ] Bug(none) css3/blending/mix-blend-mode-2nd-stacking-context-composited.html [ Failure ] @@ -400,29 +376,10 @@ Bug(none) css3/blending/mix-blend-mode-isolation-remove.html [ Failure ] Bug(none) fast/borders/overflow-hidden-border-radius-force-backing-store.html [ Failure ] -# Failures due to rounding differences -crbug.com/589265 compositing/culling/filter-occlusion-blur-large.html [ Failure ] -crbug.com/589265 compositing/culling/filter-occlusion-blur.html [ Failure ] -crbug.com/589265 css3/blending/svg-blend-exclusion.html [ Failure ] -crbug.com/589265 css3/blending/svg-blend-screen.html [ Failure ] -crbug.com/589265 fast/forms/text/input-appearance-autocomplete-very-long-value.html [ Failure ] - -# Failures due to effect compositing decision - -# Failures due to CompositeAfterPaint using SkBlendMode::kDstIn to implement -# masks. Some rounding differences is expected but none of them should be -# apparent. Text failures are also expected because of the different layer -# structure. -crbug.com/589265 compositing/masks/mask-layer-size.html [ Failure ] -crbug.com/589265 fast/borders/border-radius-with-composited-child.html [ Failure ] -crbug.com/589265 fast/clip/overflow-border-radius-composited-parent.html [ Failure ] -crbug.com/589265 fast/clip/overflow-border-radius-composited.html [ Failure ] - # Subpixel adjustments due to differences in compositing -crbug.com/589265 animations/svg/animated-filter-svg-element.html [ Failure Crash ] -crbug.com/589265 virtual/threaded/animations/svg/animated-filter-svg-element.html [ Failure Crash ] -crbug.com/589265 compositing/perspective-interest-rect.html [ Failure ] -Bug(none) css3/blending/svg-blend-multiply.html [ Failure ] +crbug.com/589265 fast/forms/text/input-appearance-autocomplete-very-long-value.html [ Failure ] +crbug.com/589265 animations/svg/animated-filter-svg-element.html [ Failure ] +crbug.com/589265 virtual/threaded/animations/svg/animated-filter-svg-element.html [ Failure ] # Some work remains to fully support composited animation and scrolling. crbug.com/702350 virtual/threaded/transitions/opacity-transform-transitions-inside-iframe.html [ Timeout ] @@ -438,11 +395,10 @@ Bug(none) virtual/threaded/compositing/visibility/layer-visible-content.html [ Failure ] Bug(none) virtual/threaded/compositing/visibility/overlays.html [ Failure Crash ] Bug(none) virtual/threaded/compositing/visibility/visibility-image-layers-dynamic.html [ Crash Failure ] -Bug(none) virtual/threaded/compositing/visibility/visibility-simple-video-layer.html [ Failure ] Bug(none) virtual/threaded/compositing/webgl/webgl-reflection.html [ Failure Pass ] Bug(none) virtual/threaded/compositing/webgl/webgl-with-accelerated-background-color.html [ Failure Pass ] Bug(none) virtual/threaded/printing/ [ Skip ] -Bug(none) virtual/threaded/synthetic_gestures/ [ Failure Crash ] +Bug(none) virtual/threaded/synthetic_gestures/ [ Failure Pass Crash ] Bug(none) fast/forms/validation-bubble-appearance-edge.html [ Failure ] Bug(none) fast/forms/validation-bubble-appearance-iframe.html [ Failure ] @@ -544,7 +500,6 @@ Bug(none) compositing/squashing/frame-clip-squashed-scrolled.html [ Failure ] Bug(none) paint/invalidation/selection/japanese-rl-selection-repaint.html [ Failure ] -Bug(none) virtual/threaded/external/wpt/feature-policy/experimental-features/vertical-scroll-touch-action-manual.tentative.html [ Failure ] Bug(none) virtual/threaded/external/wpt/feature-policy/experimental-features/vertical-scroll-touch-block-manual.tentative.html [ Failure ] Bug(none) virtual/threaded/fast/events/pinch/gesture-pinch-fake-mouse-wheel.html [ Pass Failure Crash ] @@ -557,7 +512,6 @@ Bug(none) compositing/overflow/overlap-testing-ancestor-scroller-high-dpi.html [ Failure ] Bug(none) virtual/outofblink-cors-ns/http/tests/navigation/same-document-scroll-position-restore.html [ Timeout ] Bug(none) virtual/threaded/external/wpt/css/css-scroll-snap/snap-at-user-scroll-end-manual.html [ Timeout ] -Bug(none) synthetic_gestures/animated-wheel-tiny-delta.html [ Failure ] # Duplicated display item id of background of scrollable table cell. Bug(none) fast/table/overflowHidden.html [ Crash ] @@ -573,37 +527,4 @@ crbug.com/909749 fast/events/touch/compositor-touch-hit-rects-with-negative-child.html [ Failure ] crbug.com/909749 fast/events/touch/compositor-touch-hit-rects.html [ Failure ] -# These tests have failures that were introduced between enabling BGPT for the -# first time and later disabling it. These are not real failures and can be -# rebaselined. -Bug(none) compositing/overflow/siblings-composited-with-border-radius-ancestor.html [ Failure ] -Bug(none) compositing/composited-translated-child-with-border-radius-parent-clip.html [ Failure ] -Bug(none) compositing/composited-scaled-child-with-border-radius-parent-clip.html [ Failure ] -Bug(none) compositing/overflow/border-radius-on-two-ancestors-composited-grandchild.html [ Failure ] -Bug(none) compositing/overflow/border-radius-on-parent-composited-grandchild.html [ Failure ] -Bug(none) compositing/overflow-trumps-transform-style.html [ Failure ] -Bug(none) compositing/overflow/border-radius-on-grandparent-composited-grandchild.html [ Failure ] -Bug(none) compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped.html [ Failure ] -Bug(none) compositing/overflow/grandchild-with-border-radius-ancestor.html [ Failure ] -Bug(none) compositing/overflow/siblings-with-border-radius-ancestor.html [ Failure ] -Bug(none) compositing/overflow/grandchild-composited-with-border-radius-ancestor.html [ Failure ] -Bug(none) paint/invalidation/float-offscreen.html [ Failure ] -Bug(none) compositing/video/video-controls-squashing.html [ Failure ] - -# These tests just need to be rebaselined. -Bug(none) compositing/masks/mask-with-added-filters.html [ Failure ] -Bug(none) compositing/visibility/visibility-image-layers.html [ Failure ] -Bug(none) virtual/threaded/compositing/visibility/visibility-image-layers.html [ Failure ] -Bug(none) css3/blending/effect-background-blend-mode-stacking.html [ Failure ] -Bug(none) css3/blending/mix-blend-mode-isolated-group-1.html [ Failure ] -Bug(none) css3/blending/mix-blend-mode-isolated-group-2.html [ Failure ] -Bug(none) css3/blending/mix-blend-mode-isolated-group-3.html [ Failure ] -Bug(none) fast/backgrounds/size/contain-and-cover-zoomed.html [ Failure ] -Bug(none) fast/borders/border-inner-bleed.html [ Failure ] -Bug(none) fast/borders/inline-mask-overlay-image-outset-vertical-rl.html [ Failure ] -Bug(none) fast/borders/inline-mask-overlay-image-outset.html [ Failure ] -Bug(none) images/color-profile-layer-filter.html [ Failure ] -Bug(none) images/color-profile-layer.html [ Failure ] -Bug(none) images/color-profile-mask-image-svg.html [ Failure ] -Bug(none) svg/W3C-SVG-1.1/masking-path-04-b.svg [ Failure ] -Bug(none) fast/overflow/overflow-text-hit-testing.html [ Failure ] +Bug(none) synthetic_gestures/animated-wheel-tiny-delta.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG index 9162d71..07bc332 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
@@ -25,7 +25,6 @@ # rightsizing-grid.html is truly flaky, show flakiness on reload # Needs rebaselining. -crbug.com/900015 fast/table/dynamic-caption-add-before-child.xhtml [ Failure Pass ] # Features that do not have active plans to support or turn on. crbug.com/591099 fast/css3-text/css3-text-indent/text-indent-out-of-flow-each-line-hanging.html [ Skip ] @@ -54,29 +53,15 @@ # New failures are appended below by the script. crbug.com/591099 animations/rotate-transform-equivalent.html [ Failure ] -crbug.com/591099 bluetooth/characteristic/notifications/notification-after-disconnection.html [ Failure ] crbug.com/728378 compositing/culling/tile-occlusion-boundaries.html [ Failure ] crbug.com/864398 compositing/iframes/floating-self-painting-frame.html [ Failure ] crbug.com/591099 compositing/overflow/border-radius-above-composited-subframe.html [ Failure ] -crbug.com/591099 compositing/video-frame-size-change.html [ Pass ] +crbug.com/591099 css3/filters/backdrop-filter-plus-filter.html [ Failure Timeout ] +crbug.com/591099 css3/filters/backdrop-filter-rendering.html [ Pass ] crbug.com/591099 css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html [ Failure ] crbug.com/591099 css3/flexbox/intrinsic-width-orthogonal-writing-mode.html [ Failure ] crbug.com/591099 css3/selectors3/xml/css3-modsel-61.xml [ Failure Pass ] -crbug.com/591099 editing/selection/drag-in-iframe.html [ Failure ] crbug.com/591099 editing/selection/paint-hyphen.html [ Pass ] -crbug.com/591099 external/wpt/bluetooth/requestDevice/cross-origin-iframe.sub.https.html [ Timeout ] -crbug.com/591099 external/wpt/bluetooth/requestDevice/request-from-iframe.https.html [ Timeout ] -crbug.com/591099 external/wpt/bluetooth/requestDevice/request-from-sandboxed-iframe.https.html [ Timeout ] -crbug.com/591099 external/wpt/bluetooth/server/disconnect/detach-gc.https.html [ Timeout ] -crbug.com/591099 external/wpt/bluetooth/server/disconnect/gc-detach.https.html [ Timeout ] -crbug.com/591099 external/wpt/bluetooth/server/getPrimaryService/gen-discovery-complete-no-permission-absent-service.https.html [ Failure ] -crbug.com/591099 external/wpt/bluetooth/server/getPrimaryService/gen-discovery-complete-service-not-found.https.html [ Failure ] -crbug.com/591099 external/wpt/bluetooth/server/getPrimaryService/two-iframes-from-same-origin.https.html [ Failure ] -crbug.com/591099 external/wpt/bluetooth/server/getPrimaryServices/gen-discovery-complete-no-permission-absent-service-with-uuid.https.html [ Failure ] -crbug.com/591099 external/wpt/bluetooth/server/getPrimaryServices/gen-discovery-complete-service-not-found-with-uuid.https.html [ Failure ] -crbug.com/591099 external/wpt/bluetooth/service/getCharacteristic/gen-reconnect-during.https.html [ Failure ] -crbug.com/591099 external/wpt/bluetooth/service/getCharacteristics/gen-reconnect-during-with-uuid.https.html [ Failure ] -crbug.com/591099 external/wpt/bluetooth/service/getCharacteristics/gen-reconnect-during.https.html [ Failure ] crbug.com/591099 external/wpt/css/CSS2/abspos/abspos-in-block-in-inline-in-relpos-inline.html [ Failure ] crbug.com/591099 external/wpt/css/CSS2/floats/float-nowrap-3.html [ Pass ] crbug.com/591099 external/wpt/css/CSS2/floats/floats-line-wrap-shifted-001.html [ Pass ] @@ -91,6 +76,15 @@ crbug.com/714962 external/wpt/css/css-fonts/font-features-across-space-1.html [ Pass ] crbug.com/714962 external/wpt/css/css-fonts/font-features-across-space-3.html [ Pass ] crbug.com/591099 external/wpt/css/css-namespaces/syntax-007.xml [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-position/static-position/htb-ltr-rtl.tentative.html [ Pass ] +crbug.com/591099 external/wpt/css/css-position/static-position/htb-rtl-ltr.tentative.html [ Pass ] +crbug.com/591099 external/wpt/css/css-position/static-position/htb-rtl-rtl.html [ Pass ] +crbug.com/591099 external/wpt/css/css-position/static-position/vlr-ltr-rtl.tentative.html [ Pass ] +crbug.com/591099 external/wpt/css/css-position/static-position/vlr-rtl-ltr.tentative.html [ Pass ] +crbug.com/591099 external/wpt/css/css-position/static-position/vlr-rtl-rtl.html [ Pass ] +crbug.com/591099 external/wpt/css/css-position/static-position/vrl-ltr-rtl.tentative.html [ Pass ] +crbug.com/591099 external/wpt/css/css-position/static-position/vrl-rtl-ltr.tentative.html [ Pass ] +crbug.com/591099 external/wpt/css/css-position/static-position/vrl-rtl-rtl.html [ Pass ] crbug.com/591099 external/wpt/css/css-rhythm/ [ Skip ] crbug.com/591099 external/wpt/css/css-shapes/shape-outside/supported-shapes/polygon/shape-outside-polygon-017.html [ Pass ] crbug.com/845902 external/wpt/css/css-sizing/whitespace-and-break.html [ Pass ] @@ -106,8 +100,6 @@ crbug.com/40634 external/wpt/css/css-text/white-space/trailing-space-before-br-001.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/white-space/white-space-pre-wrap-trailing-spaces-001.html [ Pass ] crbug.com/591099 external/wpt/css/css-text/word-break/word-break-break-all-004.html [ Pass ] -crbug.com/591099 external/wpt/css/css-transitions/properties-value-003.html [ Pass ] -crbug.com/591099 external/wpt/css/css-transitions/properties-value-implicit-001.html [ Pass ] crbug.com/591099 external/wpt/css/css-ui/text-overflow-010.html [ Pass ] crbug.com/893550 external/wpt/css/css-ui/text-overflow-015.html [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-icb-vlr-003.xht [ Pass ] @@ -207,8 +199,6 @@ crbug.com/591099 external/wpt/css/cssom-view/elementsFromPoint-inline-vrl-rtl.html [ Pass ] crbug.com/591099 external/wpt/css/cssom-view/offsetTopLeftInline.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-horiz-002.xhtml [ Pass ] -crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-011.html [ Pass ] -crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-writing-mode-012.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/ib-split/emptyspan-1.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/ib-split/emptyspan-4.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/ib-split/remove-from-split-inline-6.html [ Pass ] @@ -229,43 +219,16 @@ crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-margin-box-border-radius-004.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-margin-box-border-radius-008.html [ Pass ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/shapes1/shape-outside-padding-box-border-radius-002.html [ Pass ] -crbug.com/591099 external/wpt/editing/run/bold.html [ Pass ] -crbug.com/591099 external/wpt/editing/run/fontname.html [ Pass ] -crbug.com/591099 external/wpt/editing/run/formatblock.html [ Pass ] -crbug.com/591099 external/wpt/editing/run/insertparagraph.html [ Pass ] -crbug.com/591099 external/wpt/editing/run/justifycenter.html [ Pass ] -crbug.com/591099 external/wpt/editing/run/justifyfull.html [ Pass ] -crbug.com/591099 external/wpt/editing/run/justifyleft.html [ Pass ] -crbug.com/591099 external/wpt/editing/run/justifyright.html [ Pass ] -crbug.com/591099 external/wpt/editing/run/multitest.html [ Pass ] -crbug.com/591099 external/wpt/editing/run/strikethrough.html [ Pass ] -crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-ksc_5601.html [ Timeout ] +crbug.com/591099 external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-ksc_5601.html [ Pass Timeout ] crbug.com/591099 external/wpt/fetch/api/redirect/redirect-count.any.html [ Pass ] crbug.com/591099 external/wpt/fetch/api/redirect/redirect-count.any.worker.html [ Pass ] crbug.com/591099 external/wpt/fetch/api/request/request-keepalive-quota.html?include=slow-2 [ Pass ] -crbug.com/591099 external/wpt/fetch/http-cache/basic-auth-cache-test.html [ Timeout ] -crbug.com/591099 external/wpt/geolocation-API/PositionOptions.https.html [ Failure ] -crbug.com/591099 external/wpt/html/browsers/history/joint-session-history/joint-session-history-remove-iframe.html [ Timeout ] -crbug.com/591099 external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Crash Pass ] -crbug.com/591099 external/wpt/html/browsers/the-window-object/window-open-noopener.html?_parent [ Timeout ] -crbug.com/591099 external/wpt/html/browsers/the-window-object/window-open-noopener.html?_self [ Timeout ] +crbug.com/591099 external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Pass ] crbug.com/591099 external/wpt/html/interaction/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-positive.html [ Timeout ] crbug.com/850504 external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-vertical.html [ Failure ] -crbug.com/591099 external/wpt/html/semantics/scripting-1/the-script-element/async_010.htm [ Pass ] -crbug.com/591099 external/wpt/picture-in-picture/leave-picture-in-picture.html [ Pass ] -crbug.com/591099 external/wpt/picture-in-picture/picture-in-picture-window.html [ Pass ] -crbug.com/591099 external/wpt/picture-in-picture/request-picture-in-picture-twice.html [ Pass ] crbug.com/845902 external/wpt/quirks/line-height-trailing-collapsable-whitespace.html [ Pass ] -crbug.com/591099 external/wpt/requestidlecallback/callback-iframe.html [ Pass ] -crbug.com/591099 external/wpt/service-workers/service-worker/update-after-navigation-redirect.https.html [ Pass ] -crbug.com/591099 external/wpt/svg/rendering/order/clip-path-filter-order.svg [ Pass ] -crbug.com/591099 external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Pass ] -crbug.com/591099 external/wpt/webrtc/RTCPeerConnection-setLocalDescription-answer.html [ Pass ] -crbug.com/591099 external/wpt/workers/Worker_cross_origin_security_err.htm [ Pass ] -crbug.com/591099 external/wpt/workers/constructors/SharedWorker/same-origin.html [ Pass ] -crbug.com/591099 external/wpt/workers/constructors/Worker/same-origin.html [ Pass ] crbug.com/591099 external/wpt/workers/interfaces/WorkerUtils/navigator/language.html [ Pass ] -crbug.com/591099 external/wpt/worklets/audio-worklet-csp.https.html [ Pass Timeout ] +crbug.com/591099 external/wpt/workers/semantics/reporting-errors/002.html [ Pass ] crbug.com/591099 fast/backgrounds/quirks-mode-line-box-backgrounds.html [ Failure ] crbug.com/591099 fast/block/float-avoids-padding-inline-ancestors.html [ Failure ] crbug.com/591099 fast/block/positioning/positioned-child-inside-relative-positioned-anonymous-block.html [ Failure ] @@ -273,10 +236,8 @@ crbug.com/591099 fast/css-intrinsic-dimensions/height-positioned.html [ Pass ] crbug.com/807708 fast/css-intrinsic-dimensions/width-avoid-floats.html [ Failure ] crbug.com/591099 fast/css/absolute-inline-alignment-2.html [ Pass ] -crbug.com/591099 fast/css/css-properties-position-relative-as-parent-fixed.html [ Failure ] crbug.com/835484 fast/css/outline-narrowLine.html [ Failure ] crbug.com/855279 fast/css/text-overflow-ellipsis-vertical-hittest.html [ Pass ] -crbug.com/591099 fast/css/transform-inline-style-remove.html [ Failure Pass ] crbug.com/591099 fast/css3-text/css3-text-decoration/text-underline-position/text-underline-position-under.html [ Failure ] crbug.com/591099 fast/dom/nodesFromRect/nodesFromRect-basic.html [ Failure ] crbug.com/591099 fast/events/touch/compositor-touch-hit-rects-continuation.html [ Failure ] @@ -284,8 +245,6 @@ crbug.com/591099 fast/events/touch/compositor-touch-hit-rects.html [ Failure ] crbug.com/591099 fast/events/wheel/mainthread-touchpad-fling-latching.html [ Pass ] crbug.com/591099 fast/forms/textarea/basic-textareas-quirks.html [ Failure ] -crbug.com/889721 fast/inline/continuation-outlines-with-layers.html [ Failure Pass ] -crbug.com/889721 fast/inline/continuation-outlines.html [ Failure Pass ] crbug.com/889721 fast/inline/outline-continuations.html [ Failure ] crbug.com/591099 fast/overflow/overflow-update-transform.html [ Failure ] crbug.com/591099 fast/replaced/replaced-breaking.html [ Failure Pass ] @@ -303,17 +262,16 @@ crbug.com/591099 fast/writing-mode/percentage-height-orthogonal-writing-modes.html [ Failure ] crbug.com/591099 fast/writing-mode/table-percent-width-quirk.html [ Pass ] crbug.com/591099 http/tests/devtools/elements/highlight/highlight-node.js [ Failure ] +crbug.com/591099 http/tests/fetch/serviceworker/thorough/scheme-blob-base-https-other-https.html [ Pass ] crbug.com/591099 http/tests/images/image-decode-in-frame.html [ Pass ] crbug.com/591099 http/tests/images/restyle-decode-error.html [ Failure ] -crbug.com/591099 http/tests/security/upgrade-insecure-requests/iframe-upgrade.https.html [ Crash ] -crbug.com/591099 idle-callback/test-runner-run-idle-tasks.html [ Crash Pass ] crbug.com/591099 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-pseudo-element.js [ Failure ] crbug.com/591099 inspector-protocol/timeline/page-frames.js [ Failure ] crbug.com/591099 intersection-observer/v2/text-shadow.html [ Failure ] +crbug.com/591099 media/autoplay/webaudio-audio-context-resume.html [ Failure Pass ] crbug.com/591099 media/controls/buttons-after-reset.html [ Failure Pass ] crbug.com/591099 media/controls/lazy-loaded-style.html [ Failure ] crbug.com/591099 paint/float/float-under-inline-self-painting-change.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/repaint-via-layout-offset.html [ Failure Pass ] crbug.com/591099 paint/invalidation/compositing/subpixel-offset-scaled-transform-composited.html [ Failure ] crbug.com/591099 paint/invalidation/flexbox/align-content-change-keeping-geometry.html [ Failure ] crbug.com/591099 paint/invalidation/flexbox/align-self-change-keeping-geometry-grid.html [ Failure ] @@ -322,26 +280,19 @@ crbug.com/591099 paint/invalidation/flexbox/justify-self-change-keeping-geometry.html [ Failure ] crbug.com/591099 paint/invalidation/flexbox/repaint-on-margin-change.html [ Failure ] crbug.com/591099 paint/invalidation/flexbox/scrollbars-changed.html [ Failure ] -crbug.com/591099 paint/invalidation/outline/focus-ring-on-child-move.html [ Failure Pass ] crbug.com/835484 paint/invalidation/outline/inline-focus.html [ Failure ] -crbug.com/591099 paint/invalidation/outline/outline-change-invalidation.html [ Failure Pass ] crbug.com/591099 paint/invalidation/overflow/opacity-change-on-overflow-float.html [ Failure ] -crbug.com/591099 paint/invalidation/position/abspos-shift-image-incorrect-repaint.html [ Failure Pass ] crbug.com/591099 paint/invalidation/position/intermediate-layout-position.html [ Failure ] crbug.com/714962 paint/invalidation/position/relative-positioned-movement-repaint.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/repaint-composited-child-in-scrolled-container.html [ Failure ] -crbug.com/591099 paint/invalidation/selection/japanese-rl-selection-clear.html [ Failure Pass ] crbug.com/591099 paint/invalidation/svg/svg-background-partial-redraw.html [ Failure ] crbug.com/591099 paint/invalidation/svg/text-selection-update.svg [ Failure ] crbug.com/591099 paint/invalidation/svg/transform-focus-ring-repaint.html [ Failure ] crbug.com/591099 paint/invalidation/table/table-extra-bottom-grow.html [ Failure ] crbug.com/591099 paint/invalidation/table/table-two-pass-layout-overpaint.html [ Failure ] -crbug.com/591099 printing/absolute-position-headers-and-footers.html [ Failure ] crbug.com/591099 printing/iframe-svg-in-object-print.html [ Failure ] crbug.com/591099 printing/single-line-must-not-be-split-into-two-pages.html [ Failure ] crbug.com/591099 scrollbars/auto-scrollbar-fit-content.html [ Failure ] -crbug.com/591099 storage/indexeddb/mozilla/test_objectStore_openKeyCursor.html [ Pass ] -crbug.com/591099 storage/indexeddb/objectstore-cursor.html [ Pass ] crbug.com/591099 svg/zoom/page/zoom-img-preserveAspectRatio-support-1.html [ Failure ] crbug.com/591099 svg/zoom/page/zoom-svg-float-border-padding.xml [ Pass ] crbug.com/591099 svg/zoom/page/zoom-svg-through-object-with-absolute-size-2.xhtml [ Failure ] @@ -356,49 +307,36 @@ crbug.com/591099 virtual/android/rootscroller/set-root-scroller.html [ Pass ] crbug.com/591099 virtual/android/rootscroller/set-rootscroller-before-load.html [ Pass ] crbug.com/591099 virtual/android/url-bar/bottom-and-top-fixed-sticks-to-top.html [ Failure ] +crbug.com/591099 virtual/composite-after-paint/paint/background/scrolling-background-with-negative-z-child.html [ Failure ] +crbug.com/591099 virtual/composite-after-paint/paint/invalidation/box/margin.html [ Failure Pass ] +crbug.com/591099 virtual/display-lock/display-lock/lock-before-append/measure-and-remove.html [ Failure ] crbug.com/591099 virtual/exotic-color-space/ [ Skip ] -crbug.com/591099 virtual/feature-policy-vibrate/ [ Skip ] -crbug.com/591099 virtual/fractional_scrolling/fast/scrolling/fractional-scroll-offset-iframe-fixed-position.html [ Failure ] -crbug.com/591099 virtual/fractional_scrolling_threaded/fast/scrolling/fractional-scroll-offset-iframe-fixed-position.html [ Failure ] -crbug.com/591099 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Failure Pass ] -crbug.com/591099 virtual/gpu/fast/canvas/canvas-blending-color-over-image.html [ Pass ] -crbug.com/591099 virtual/gpu/fast/canvas/canvas-blending-gradient-over-pattern.html [ Pass Timeout ] -crbug.com/591099 virtual/gpu/fast/canvas/canvas-with-overflowing-object-fit.html [ Failure ] crbug.com/591099 virtual/intersection-observer-v2/intersection-observer/v2/text-shadow.html [ Failure ] crbug.com/591099 virtual/layout_ng/ [ Skip ] crbug.com/824918 virtual/layout_ng_experimental/ [ Skip ] -crbug.com/591099 virtual/mojo-blob-urls/external/wpt/FileAPI/url/sandboxed-iframe.html [ Pass ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects-continuation.html [ Failure ] -crbug.com/591099 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects.html [ Failure ] -crbug.com/591099 virtual/mouseevent_fractional/fast/events/wheel/mainthread-touchpad-fling-latching.html [ Pass ] crbug.com/591099 virtual/new-remote-playback-pipeline/ [ Skip ] +crbug.com/591099 virtual/not-blink-gen-property-trees/ [ Skip ] +crbug.com/591099 virtual/not-blink-gen-property-trees/compositing/culling/tile-occlusion-boundaries.html [ Failure ] +crbug.com/591099 virtual/not-blink-gen-property-trees/compositing/iframes/floating-self-painting-frame.html [ Failure ] +crbug.com/591099 virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-above-composited-subframe.html [ Failure ] +crbug.com/591099 virtual/not-blink-gen-property-trees/paint/float/float-under-inline-self-painting-change.html [ Failure ] crbug.com/591099 virtual/omt-worker-fetch/external/wpt/workers/interfaces/WorkerUtils/navigator/language.html [ Pass ] crbug.com/591099 virtual/omt-worker-fetch/external/wpt/workers/semantics/multiple-workers/003.html [ Pass ] +crbug.com/591099 virtual/omt-worker-fetch/external/wpt/workers/semantics/reporting-errors/002.html [ Pass ] +crbug.com/591099 virtual/omt-worker-fetch/http/tests/workers/worker-invalid-context.html [ Failure Pass ] crbug.com/591099 virtual/outofblink-cors-ns/external/wpt/fetch/api/redirect/redirect-count.any.html [ Pass ] crbug.com/591099 virtual/outofblink-cors-ns/external/wpt/fetch/api/redirect/redirect-count.any.worker.html [ Pass ] crbug.com/591099 virtual/outofblink-cors-ns/external/wpt/fetch/api/request/request-keepalive-quota.html?include=slow-2 [ Pass ] -crbug.com/591099 virtual/outofblink-cors-ns/http/tests/fetch/chromium/release-handle-crash.html [ Pass ] crbug.com/591099 virtual/outofblink-cors-ns/http/tests/security/cors-rfc1918/addressspace-document-appcache.https.html [ Crash Failure ] crbug.com/591099 virtual/outofblink-cors-ns/http/tests/security/cors-rfc1918/addressspace-document-csp-appcache.https.html [ Crash Failure Pass ] -crbug.com/591099 virtual/outofblink-cors-ns/http/tests/security/setDomainRelaxationForbiddenForURLScheme.html [ Pass ] -crbug.com/591099 virtual/outofblink-cors-ns/http/tests/security/video-poster-cross-origin-crash2.html [ Pass ] crbug.com/591099 virtual/outofblink-cors/ [ Skip ] -crbug.com/591099 virtual/outofblink-cors/http/tests/security/cors-rfc1918/addressspace-document-appcache.https.html [ Crash Failure ] -crbug.com/591099 virtual/outofblink-cors/http/tests/security/cors-rfc1918/addressspace-document-csp-appcache.https.html [ Crash Failure Pass ] -crbug.com/591099 virtual/outofblink-cors/http/tests/security/setDomainRelaxationForbiddenForURLScheme.html [ Pass ] crbug.com/591099 virtual/paint-timing/external/wpt/paint-timing/sibling-painting-first-image.html [ Failure ] crbug.com/591099 virtual/prefer_compositing_to_lcd_text/ [ Skip ] -crbug.com/591099 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-doesnt-send-reports-without-violation.https.sub.html [ Pass ] -crbug.com/591099 virtual/sampling-heap-profiler/inspector-protocol/memory/sampling-native-profile-blink-gc.js [ Failure Pass ] crbug.com/591099 virtual/scroll_customization/ [ Skip ] -crbug.com/591099 virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects.html [ Failure ] -crbug.com/591099 virtual/sharedarraybuffer/external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.html [ Pass ] -crbug.com/591099 virtual/composite-after-paint/paint/invalidation/box/margin.html [ Failure Pass ] crbug.com/591099 virtual/stable/ [ Skip ] crbug.com/591099 virtual/threaded/ [ Skip ] -crbug.com/591099 virtual/user-activation-v2/fast/events/mouse-cursor.html [ Failure Pass ] +crbug.com/591099 virtual/user-activation-v2/fast/events/mouse-cursor.html [ Failure ] crbug.com/591099 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects-continuation.html [ Failure ] -crbug.com/591099 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects.html [ Failure ] crbug.com/591099 virtual/video-surface-layer/media/controls/buttons-after-reset.html [ Failure Pass ] -crbug.com/591099 virtual/video-surface-layer/media/stable/video-object-fit-stable.html [ Failure ] -crbug.com/591099 virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Pass ] +crbug.com/591099 virtual/video-surface-layer/media/stable/video-object-fit-stable.html [ Pass ]
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-features=NetworkService b/third_party/blink/web_tests/FlagExpectations/enable-features=NetworkService index f24256e1..7916242 100644 --- a/third_party/blink/web_tests/FlagExpectations/enable-features=NetworkService +++ b/third_party/blink/web_tests/FlagExpectations/enable-features=NetworkService
@@ -34,3 +34,7 @@ # Skip virtual/outofblink-cors-ns on this bot, since when run normally it # already forces NetworkService on, so there is no need to run it again here. Bug(none) virtual/outofblink-cors-ns [ Skip ] + +# NetworkService needs S13nServiceWorker. Running these test with +# NetworkService doesn't make sense. +Bug(none) virtual/disabled-service-worker-servicification [ Skip ]
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests index 6287c84..0d08fe8 100644 --- a/third_party/blink/web_tests/NeverFixTests +++ b/third_party/blink/web_tests/NeverFixTests
@@ -442,6 +442,7 @@ external/wpt/encrypted-media/clearkey-mp4-waiting-for-a-key.https.html [ WontFix ] external/wpt/encrypted-media/clearkey-events-session-closed-event.https.html [ WontFix ] external/wpt/encrypted-media/clearkey-update-non-ascii-input.https.html [ WontFix ] +external/wpt/media-source/mediasource-invalid-codec.html [ WontFix ] external/wpt/clipboard-apis/async-navigator-clipboard-basics.https.html [ WontFix ] external/wpt/css/CSS2/linebox/inline-formatting-context-010b.xht [ WontFix ] @@ -2122,15 +2123,19 @@ virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-event-is-reload-navigation-manual.https.html [ WontFix ] virtual/outofblink-cors/external/wpt/xhr/send-authentication-existing-session-manual.htm [ WontFix ] virtual/outofblink-cors/external/wpt/xhr/send-authentication-prompt-2-manual.htm [ WontFix ] -virtual/service-worker-servicification/external/wpt/service-workers/service-worker/fetch-event-is-history-backward-navigation-manual.https.html [ WontFix ] -virtual/service-worker-servicification/external/wpt/service-workers/service-worker/fetch-event-is-history-forward-navigation-manual.https.html [ WontFix ] -virtual/service-worker-servicification/external/wpt/service-workers/service-worker/fetch-event-is-reload-navigation-manual.https.html [ WontFix ] +virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/fetch-event-is-history-backward-navigation-manual.https.html [ WontFix ] +virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/fetch-event-is-history-forward-navigation-manual.https.html [ WontFix ] +virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/fetch-event-is-reload-navigation-manual.https.html [ WontFix ] virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechRecognition-abort-manual.https.html [ WontFix ] virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechRecognition-onerror-manual.https.html [ WontFix ] virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechRecognition-onresult-manual.https.html [ WontFix ] virtual/speech-with-unified-autoplay/external/wpt/speech-api/SpeechRecognition-stop-manual.https.html [ WontFix ] [ Retina ] external/wpt/pointerevents/pointerevent_touch-action-table-test_touch-manual.html [ WontFix ] +# See crbug.com/865839. +virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/update-after-navigation-redirect.https.html [ WontFix ] + + # ====== Tests incompatible with the default Site Isolation from here ====== # See also third_party/blink/web_tests/virtual/not-site-per-process/README.md # @@ -2170,3 +2175,4 @@ Bug(none) http/tests/devtools/isolated-code-cache/cross-origin-test.js [ WontFix ] # ====== Tests incompatible with the default Site Isolation until here ====== +external/wpt/css/css-overscroll-behavior/overscrollBehavior-manual.html [ WontFix ]
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests index 3d2aef70..00a1ccd 100644 --- a/third_party/blink/web_tests/SlowTests +++ b/third_party/blink/web_tests/SlowTests
@@ -213,8 +213,6 @@ crbug.com/592183 external/wpt/webusb/usbDevice.https.html [ Slow ] -crbug.com/594189 virtual/composite-after-paint/fast/overflow/lots-of-sibling-inline-boxes.html [ Slow ] - crbug.com/614910 virtual/gpu-rasterization/images/color-profile-filter.html [ Slow ] crbug.com/623798 paint/images/animated-gif-last-frame-crash.html [ Slow ] @@ -361,6 +359,7 @@ crbug.com/842995 external/wpt/html/semantics/scripting-1/the-script-element/execution-timing/078.html [ Slow ] crbug.com/626703 external/wpt/html/semantics/scripting-1/the-script-element/async_007.htm [ Slow ] crbug.com/626703 external/wpt/html/semantics/scripting-1/the-script-element/async_010.htm [ Slow ] +crbug.com/842995 virtual/streaming-preload/external/wpt/html/semantics/scripting-1/the-script-element/execution-timing/078.html [ Slow ] crbug.com/626703 virtual/streaming-preload/external/wpt/html/semantics/scripting-1/the-script-element/async_007.htm [ Slow ] crbug.com/626703 virtual/streaming-preload/external/wpt/html/semantics/scripting-1/the-script-element/async_010.htm [ Slow ] @@ -512,7 +511,7 @@ crbug.com/874695 virtual/outofblink-cors-ns/external/wpt/xhr/xmlhttprequest-timeout-worker-simple.html [ Slow ] crbug.com/874695 virtual/outofblink-cors-ns/external/wpt/xhr/xmlhttprequest-timeout-worker-synconworker.html [ Slow ] crbug.com/874695 virtual/outofblink-cors-ns/external/wpt/xhr/xmlhttprequest-timeout-worker-twice.html [ Slow ] -crbug.com/874695 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/fetch-frame-resource.https.html [ Slow ] +crbug.com/874695 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/fetch-frame-resource.https.html [ Slow ] crbug.com/874695 virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCDTMFSender-ontonechange-long.https.html [ Slow ] # Tests where |3s <= slowest_run < 10s| on flakiness dashboard for site_per_process_webkit_layout_tests @@ -572,7 +571,6 @@ crbug.com/874695 external/wpt/css/css-fonts/variations/font-style-interpolation.html [ Slow ] crbug.com/874695 external/wpt/css/css-layout-api/constraints-data.https.html [ Slow ] crbug.com/874695 external/wpt/css/cssom-view/matchMedia.xht [ Slow ] -crbug.com/874695 external/wpt/css/cssom-view/overscrollBehavior-manual.html [ Slow ] crbug.com/874695 external/wpt/css/cssom-view/scroll-behavior-smooth.html [ Slow ] crbug.com/874695 external/wpt/css/css-transitions/transitions-animatable-properties-01.html [ Slow ] crbug.com/874695 external/wpt/css/css-values/vh_not_refreshing_on_chrome.html [ Slow ] @@ -1392,19 +1390,19 @@ crbug.com/874695 virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-doesnt-send-reports-without-violation.https.sub.html [ Slow ] crbug.com/874695 virtual/sampling-heap-profiler/inspector-protocol/memory/sampling-native-snapshot.js [ Slow ] crbug.com/874695 virtual/scroll_customization/fast/scroll-behavior/overscroll-behavior.html [ Slow ] -crbug.com/874695 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-cache.https.html [ Slow ] -crbug.com/874695 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video.https.html [ Slow ] -crbug.com/874695 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/fetch-event-redirect.https.html [ Slow ] -crbug.com/874695 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/fetch-event-respond-with-body-loaded-in-chunk.https.html [ Slow ] -crbug.com/874695 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/fetch-response-taint.https.html [ Slow ] -crbug.com/874695 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/navigation-redirect.https.html [ Slow ] -crbug.com/874695 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/registration-mime-types.https.html [ Slow ] -crbug.com/874695 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/registration-updateviacache.https.html [ Slow ] -crbug.com/874695 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/skip-waiting-using-registration.https.html [ Slow ] -crbug.com/874695 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/skip-waiting-without-using-registration.https.html [ Slow ] -crbug.com/874695 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/update-after-navigation-fetch-event.https.html [ Slow ] -crbug.com/874695 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/update-after-navigation-redirect.https.html [ Slow ] -crbug.com/874695 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Slow ] +crbug.com/874695 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-cache.https.html [ Slow ] +crbug.com/874695 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video.https.html [ Slow ] +crbug.com/874695 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/fetch-event-redirect.https.html [ Slow ] +crbug.com/874695 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/fetch-event-respond-with-body-loaded-in-chunk.https.html [ Slow ] +crbug.com/874695 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/fetch-response-taint.https.html [ Slow ] +crbug.com/874695 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/navigation-redirect.https.html [ Slow ] +crbug.com/874695 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/registration-mime-types.https.html [ Slow ] +crbug.com/874695 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/registration-updateviacache.https.html [ Slow ] +crbug.com/874695 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/skip-waiting-using-registration.https.html [ Slow ] +crbug.com/874695 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/skip-waiting-without-using-registration.https.html [ Slow ] +crbug.com/874695 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/update-after-navigation-fetch-event.https.html [ Slow ] +crbug.com/874695 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/update-after-navigation-redirect.https.html [ Slow ] +crbug.com/874695 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Slow ] crbug.com/874695 virtual/sharedarraybuffer/external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success-and-failure.html [ Slow ] crbug.com/874695 virtual/sharedarraybuffer/external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success.html [ Slow ] crbug.com/874695 virtual/sharedarraybuffer/external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.html [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 56a94ed6..ccbac6d 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -202,38 +202,43 @@ # display-lock # Some additional bugs that are caused by painting problems are also within this section. -# Failures due to CompositeAfterPaint. DO NOT REBASELINE. -# -# These tests should not be rebaselined automatically, as our goal is to exactly -# match existing tests. We have skipped the entire composite-after-paint -# directory and are adding [ Pass ] lines as we go. Please remove [ Pass ] lines -# instead of rebaselining these tests. -crbug.com/537409 virtual/composite-after-paint/ [ Skip ] -# End whitlelisted paint invalidation tests -crbug.com/596780 virtual/composite-after-paint/compositing/framesets/composited-frame-alignment.html [ Pass ] -crbug.com/596780 [ Mac ] virtual/composite-after-paint/compositing/geometry/outline-change.html [ Pass ] -crbug.com/596780 [ Win ] virtual/composite-after-paint/compositing/geometry/outline-change.html [ Pass ] - -# Re-add this once it rebaselines. -# crbug.com/600618 virtual/composite-after-paint/svg/custom/object-sizing-explicit-height.xhtml [ Pass ] -# SkiaBitLocker should avoid allocating huge offscreen buffer -crbug.com/605812 [ Mac ] virtual/composite-after-paint/fast/overflow/overflow-height-float-not-removed-crash.html [ Skip ] -crbug.com/605812 [ Mac ] virtual/composite-after-paint/fast/overflow/overflow-height-float-not-removed-crash2.html [ Skip ] -crbug.com/619427 [ Mac ] virtual/composite-after-paint/fast/overflow/overflow-height-float-not-removed-crash3.html [ Pass Failure ] -crbug.com/619427 [ Linux ] virtual/composite-after-paint/fast/overflow/overflow-height-float-not-removed-crash3.html [ Pass Failure ] +# --- Begin CompositeAfterPaint Tests -- +# Only whitelisted tests run under the virtual suite. +# More tests run with CompositeAfterPaint on the flag-specific try bot. +Bug(none) virtual/composite-after-paint/ [ Skip ] +Bug(none) virtual/composite-after-paint/compositing/backface-visibility/ [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/backgrounds/ [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/geometry/abs-position-inside-opacity.html [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/geometry/composited-html-size.html [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/geometry/outline-change.html [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/geometry/tall-page-composited.html [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/gestures/gesture-tapHighlight-img.html [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/gestures/gesture-tapHighlight-simple-scaledY.html [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/iframes/iframe-in-composited-layer.html [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/images/direct-image-clip-path.html [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/masks/mask-of-clipped-layer.html [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/overflow/clip-rotate-opacity-fixed.html [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/overlap-blending/children-opacity-huge.html [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/plugins/ [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/reflections/reflection-ordering.html [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/rtl/rtl-overflow-scrolling.html [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/squashing/squash-composited-input.html [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/transitions/opacity-on-inline.html [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/will-change/stacking-context-creation.html [ Pass ] +Bug(none) virtual/composite-after-paint/compositing/z-order/ [ Pass ] +Bug(none) virtual/composite-after-paint/paint/background/ [ Pass ] +Bug(none) virtual/composite-after-paint/paint/filters/ [ Pass ] +Bug(none) virtual/composite-after-paint/paint/frames [ Pass ] # --- End CompositeAfterPaint Tests -- # Subpixel differences crbug.com/771643 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-color-5.html [ Failure ] crbug.com/771643 external/wpt/css/css-backgrounds/background-attachment-local/attachment-local-clipping-image-5.html [ Failure ] -# Difficult ancestor clip mask issue. -crbug.com/771643 compositing/overflow/nested-border-radius-clipping.html [ Failure ] -crbug.com/771643 virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping.html [ Failure ] - # Fails due to flaws in the SPv1 architecture. Can be fixed with composite-after-paint. crbug.com/862483 compositing/overflow/scrollbar-layer-placement-negative-z-index-child.html [ Failure ] crbug.com/862483 virtual/prefer_compositing_to_lcd_text/compositing/overflow/scrollbar-layer-placement-negative-z-index-child.html [ Failure ] +crbug.com/862483 virtual/not-blink-gen-property-trees/compositing/overflow/scrollbar-layer-placement-negative-z-index-child.html [ Failure ] crbug.com/805134 http/tests/devtools/tracing/scroll-invalidations.js [ Failure ] crbug.com/805134 virtual/threaded/http/tests/devtools/tracing/scroll-invalidations.js [ Failure ] @@ -256,6 +261,7 @@ # This is a missing event and increasing the timeout or using run-after-layout-and-paint doesn't # seem to fix it. crbug.com/309675 compositing/gestures/gesture-tapHighlight-simple-longPress.html [ Failure ] +crbug.com/309675 virtual/not-blink-gen-property-trees/compositing/gestures/gesture-tapHighlight-simple-longPress.html [ Failure ] crbug.com/845267 [ Mac ] http/tests/inspector-protocol/page/page-lifecycleEvents.js [ Failure Pass ] @@ -263,6 +269,7 @@ crbug.com/726075 [ Win ] compositing/3d-cube.html [ Failure ] crbug.com/726075 [ Linux ] compositing/3d-cube.html [ Failure ] crbug.com/726075 [ Mac ] compositing/3d-cube.html [ Failure ] +crbug.com/726075 [ Linux ] virtual/not-blink-gen-property-trees/compositing/3d-cube.html [ Failure ] # Looks like a filuare to get a paint on time. Test could be changed to use runAfterLayoutAndPaint # instead of a timeout, which may fix things. @@ -291,6 +298,7 @@ crbug.com/736052 compositing/overflow/composited-scroll-with-fractional-translation.html [ Failure ] crbug.com/736052 virtual/prefer_compositing_to_lcd_text/compositing/overflow/composited-scroll-with-fractional-translation.html [ Failure ] +crbug.com/736052 virtual/not-blink-gen-property-trees/compositing/overflow/composited-scroll-with-fractional-translation.html [ Failure ] # New OffscreenCanvas Tests that are breaking LayoutTest crbug.com/680635 external/wpt/offscreen-canvas/text/2d.text.font.parse.invalid.html [ Skip ] @@ -355,6 +363,48 @@ crbug.com/849459 fragmentation/repeating-thead-under-repeating-thead.html [ Failure ] +# The not-blink-gen-property-trees virtual suite ensures regressions are not introduced as BlinkGenPropertyTrees rolls out. +# To reduce bot resources and rebaseline works, only linux is used. +Bug(none) [ Android ] virtual/not-blink-gen-property-trees [ Skip ] +Bug(none) [ Fuchsia ] virtual/not-blink-gen-property-trees [ Skip ] +Bug(none) [ Mac ] virtual/not-blink-gen-property-trees [ Skip ] +Bug(none) [ Win ] virtual/not-blink-gen-property-trees [ Skip ] + +# Paint invalidation does not change with BlinkGenPropertyTrees. There are many tests +# in the paint/invalidation directory so they are skipped so bot resources are not wasted. +Bug(none) virtual/not-blink-gen-property-trees/paint/invalidation [ Skip ] + +# The following tests are fixed with BlinkGenPropertyTrees and are expected to fail without it. +Bug(none) virtual/not-blink-gen-property-trees/compositing/composited-canvas-with-overflowing-object-fit.html [ Failure ] +Bug(none) virtual/not-blink-gen-property-trees/compositing/gestures/gesture-tapHighlight-with-filter.html [ Failure ] +Bug(none) virtual/not-blink-gen-property-trees/compositing/masks/mask-with-added-filters.html [ Failure ] +Bug(none) virtual/not-blink-gen-property-trees/compositing/overflow/clip-escaping-reverse-order-should-not-crash.html [ Failure ] +Bug(none) virtual/not-blink-gen-property-trees/compositing/overflow/nested-border-radius-clipping.html [ Failure ] + +# These tests are no longer applicable with layer list mode (BGPT). Move to NeverFixTests later. +Bug(none) http/tests/devtools/layers/layer-sticky-position-constraint-get.js [ Skip ] +Bug(none) inspector-protocol/layers/get-layers.js [ Skip ] + +# ==== Regressions introduced by BlinkGenPropertyTrees ===== +# Reflection / mask ordering issue +crbug.com/767318 compositing/reflections/nested-reflection-mask-change.html [ Failure ] +# Incorrect scrollbar invalidation. +crbug.com/887000 virtual/prefer_compositing_to_lcd_text/scrollbars/hidden-scrollbars-invisible.html [ Failure ] +crbug.com/882975 virtual/threaded/fast/events/pinch/gesture-pinch-zoom-prevent-in-handler.html [ Failure Pass ] +crbug.com/882975 virtual/threaded/fast/events/pinch/scroll-visual-viewport-send-boundary-events.html [ Failure Pass ] +### See crbug.com/891427 comment near the top of this file: +###crbug.com/882975 virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-desktop.html [ Failure Pass ] +crbug.com/911664 fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html [ Failure ] +crbug.com/911664 virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html [ Failure ] +crbug.com/911664 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html [ Failure ] +crbug.com/911664 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects-non-composited-scroll.html [ Failure ] +crbug.com/882973 http/tests/devtools/layers/layer-tree-model.js [ Failure ] +crbug.com/884239 virtual/threaded/animations/animationworklet/worklet-animation-local-time-undefined.html [ Failure ] +# Subpixel rounding differences that are incorrect. +crbug.com/836886 virtual/prefer_compositing_to_lcd_text/compositing/overflow/scaled-overflow.html [ Failure ] +crbug.com/836886 compositing/overflow/scaled-overflow.html [ Failure ] +crbug.com/836886 compositing/scrollbars/nested-overlay-scrollbars.html [ Failure ] + # ====== Paint team owned tests to here ====== # ====== Layout team owned tests from here ====== @@ -589,6 +639,15 @@ crbug.com/796943 fast/text/international/shape-across-elements-simple.html [ Failure ] crbug.com/877946 external/wpt/css/CSS2/linebox/anonymous-inline-inherit-001.html [ Failure ] crbug.com/859233 external/wpt/css/css-break/hit-test-inline-fragmentation-with-border-radius.html [ Failure ] +crbug.com/591099 external/wpt/css/css-position/static-position/htb-ltr-rtl.tentative.html [ Failure ] +crbug.com/591099 external/wpt/css/css-position/static-position/htb-rtl-ltr.tentative.html [ Failure ] +crbug.com/591099 external/wpt/css/css-position/static-position/htb-rtl-rtl.html [ Failure ] +crbug.com/591099 external/wpt/css/css-position/static-position/vlr-ltr-rtl.tentative.html [ Failure ] +crbug.com/591099 external/wpt/css/css-position/static-position/vlr-rtl-ltr.tentative.html [ Failure ] +crbug.com/591099 external/wpt/css/css-position/static-position/vlr-rtl-rtl.html [ Failure ] +crbug.com/591099 external/wpt/css/css-position/static-position/vrl-ltr-rtl.tentative.html [ Failure ] +crbug.com/591099 external/wpt/css/css-position/static-position/vrl-rtl-ltr.tentative.html [ Failure ] +crbug.com/591099 external/wpt/css/css-position/static-position/vrl-rtl-rtl.html [ Failure ] crbug.com/845902 external/wpt/css/css-sizing/whitespace-and-break.html [ Failure ] crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-non-replaced-004.html [ Failure ] crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-non-replaced-005.html [ Failure ] @@ -1877,14 +1936,16 @@ crbug.com/497522 css3/filters/backdrop-filter-bleeding.html [ Failure ] crbug.com/497522 css3/filters/backdrop-filter-svg.html [ Failure ] crbug.com/497522 css3/filters/backdrop-filter-plus-filter.html [ Failure ] +crbug.com/497522 css3/filters/backdrop-filter-rendering.html [ Failure ] crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-isolation-isolate.html [ Failure ] crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-border-radius.html [ Failure ] crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-clip-rect.html [ Failure ] -crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-edge-pixels.html [ Failure ] crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-paint-order.html [ Failure ] -crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-basic-opacity.html [ Failure ] -crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-fixed-clip.html [ Failure ] crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-isolation-fixed.html [ Failure ] +crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-edge-pixels.html [ Pass Failure ] +crbug.com/497522 external/wpt/css/filter-effects/backdrop-filter-isolation.html [ Failure ] +# Flaky timeout: https://crbug.com/912748 +crbug.com/912748 external/wpt/css/filter-effects/backdrop-filter-plus-filter.html [ Skip ] # ====== Backdrop-filter related tests END ====== @@ -1904,7 +1965,6 @@ crbug.com/909095 [ Mac ] media/W3C/video/networkState/networkState_during_progress.html [ Failure Pass ] # This is also flaky from findit, see crbug.com/903019: crbug.com/520736 virtual/video-surface-layer/media/W3C/video/networkState/networkState_during_progress.html [ Pass Failure Timeout Crash ] -crbug.com/865839 external/wpt/service-workers/service-worker/update-after-navigation-redirect.https.html [ Timeout ] crbug.com/841922 [ Linux ] virtual/video-surface-layer/media/video-controls-focus-movement-on-hide.html [ Pass Failure ] crbug.com/841922 [ Win ] virtual/video-surface-layer/media/video-controls-focus-movement-on-hide.html [ Pass Failure ] @@ -2343,12 +2403,8 @@ crbug.com/400841 media/video-canvas-draw.html [ Failure ] crbug.com/400841 virtual/video-surface-layer/media/video-canvas-draw.html [ Failure ] -crbug.com/400829 media/video-object-fit.html [ Failure ] -crbug.com/400829 virtual/video-surface-layer/media/video-object-fit.html [ Failure ] crbug.com/400829 virtual/stable/media/stable/video-object-fit-stable.html [ Failure ] crbug.com/400829 virtual/video-surface-layer/media/stable/video-object-fit-stable.html [ Failure ] -crbug.com/400829 compositing/composited-canvas-with-overflowing-object-fit.html [ Failure ] -crbug.com/400829 virtual/gpu/fast/canvas/canvas-with-overflowing-object-fit.html [ Failure ] # We only want to run one of the web-animations-api tests in stable mode. crbug.com/441553 virtual/stable/web-animations-api [ Skip ] @@ -2382,7 +2438,7 @@ crbug.com/574283 [ Mac ] fast/scroll-behavior/smooth-scroll/ongoing-smooth-scroll-anchors.html [ Skip ] crbug.com/574283 [ Mac ] virtual/scroll_customization/fast/scroll-behavior/smooth-scroll/ongoing-smooth-scroll-anchors.html [ Skip ] crbug.com/574283 [ Mac ] virtual/threaded/fast/scroll-behavior/smooth-scroll/fixed-background-in-iframe.html [ Skip ] -crbug.com/574283 [ Mac ] virtual/threaded/fast/scroll-behavior/smooth-scroll/main-thread-scrolling-reason-correctness.html [ Skip ] +crbug.com/574283 virtual/threaded/fast/scroll-behavior/smooth-scroll/main-thread-scrolling-reason-correctness.html [ Skip ] crbug.com/574283 [ Mac ] virtual/threaded/fast/scroll-behavior/smooth-scroll/mousewheel-scroll-interrupted.html [ Skip ] crbug.com/665577 virtual/threaded/fast/scroll-behavior/overflow-scroll-root-frame-animates.html [ Pass Timeout ] @@ -2627,6 +2683,7 @@ # Fails with leak detector. crbug.com/769885 [ Linux ] virtual/android/fullscreen/full-screen-frameset.html [ Skip ] +crbug.com/769885 [ Linux ] virtual/android/fullscreen/video-scrolled-iframe.html [ Skip ] # Temporarily disabled after chromium change crbug.com/492511 [ Mac ] fast/text/atsui-negative-spacing-features.html [ Failure ] @@ -2670,11 +2727,9 @@ crbug.com/591500 [ Win10 ] printing/fixed-positioned-headers-and-footers-absolute-covering-some-pages.html [ Failure ] crbug.com/591500 [ Win10 ] virtual/threaded/printing/fixed-positioned-headers-and-footers-absolute-covering-some-pages.html [ Failure ] crbug.com/591500 [ Win10 ] printing/fixed-positioned-but-static-headers-and-footers.html [ Skip ] -crbug.com/591500 [ Win10 ] printing/absolute-position-headers-and-footers.html [ Skip ] crbug.com/591500 [ Win10 ] printing/fixed-positioned-headers-and-footers-inside-transform.html [ Skip ] crbug.com/591500 [ Win10 ] printing/fixed-positioned-headers-and-footers-larger-than-page.html [ Skip ] crbug.com/591500 [ Win10 ] printing/fixed-positioned-headers-and-footers.html [ Skip ] -crbug.com/591500 [ Win10 ] virtual/threaded/printing/absolute-position-headers-and-footers.html [ Skip ] crbug.com/591500 [ Win10 ] virtual/threaded/printing/fixed-positioned-but-static-headers-and-footers.html [ Skip ] crbug.com/591500 [ Win10 ] virtual/threaded/printing/fixed-positioned-headers-and-footers-clipped.html [ Skip ] crbug.com/591500 [ Win10 ] virtual/threaded/printing/fixed-positioned-headers-and-footers-inside-transform.html [ Skip ] @@ -2901,7 +2956,7 @@ # Failure messages are unstable so we cannot create baselines. crbug.com/832071 external/wpt/service-workers/service-worker/worker-client-id.https.html [ Failure ] -crbug.com/832071 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/worker-client-id.https.html [ Failure ] +crbug.com/832071 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/worker-client-id.https.html [ Failure ] crbug.com/832071 virtual/navigation-mojo-response/external/wpt/service-workers/service-worker/worker-client-id.https.html [ Failure ] crbug.com/832071 virtual/outofblink-cors/external/wpt/service-workers/service-worker/worker-client-id.https.html [ Failure ] crbug.com/832071 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/worker-client-id.https.html [ Failure ] @@ -2914,6 +2969,8 @@ crbug.com/875622 external/wpt/css/css-transitions/AnimationEffect-getComputedTiming.tentative.html [ Pass Failure ] crbug.com/875622 external/wpt/css/css-transitions/CSSTransition-startTime.tentative.html [ Pass Failure Timeout ] +crbug.com/552085 external/wpt/css/css-cascade/important-prop.html [ Failure ] + # Some control characters still not visible crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-001.html [ Failure ] @@ -3088,6 +3145,8 @@ crbug.com/626703 [ Mac10.11 ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-003v.html [ Failure ] crbug.com/626703 external/wpt/wasm/webapi/abort.any.worker.html [ Timeout ] crbug.com/626703 external/wpt/wasm/webapi/abort.any.html [ Timeout ] +crbug.com/626703 external/wpt/css/css-will-change/will-change-abspos-cb-dynamic-001.html [ Failure ] +crbug.com/626703 external/wpt/css/css-will-change/will-change-abspos-cb-001.html [ Failure ] crbug.com/626703 external/wpt/css/css-conditional/at-supports-040.html [ Failure ] ### See crbug.com/891427 comment near the top of this file: ###crbug.com/626703 [ Win7 ] external/wpt/resource-timing/resource_timing_buffer_full_eventually.html [ Timeout ] @@ -3097,7 +3156,7 @@ crbug.com/626703 external/wpt/service-workers/service-worker/update-not-allowed.https.html [ Timeout ] crbug.com/626703 virtual/layout_ng_experimental/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-block-margins-2.html [ Failure ] crbug.com/626703 external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-block-margins-2.html [ Failure ] -crbug.com/626703 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/update-not-allowed.https.html [ Timeout ] +crbug.com/626703 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/update-not-allowed.https.html [ Timeout ] crbug.com/626703 external/wpt/css/css-text/white-space/line-edge-white-space-collapse-002.html [ Failure ] crbug.com/626703 external/wpt/css/css-text/white-space/line-edge-white-space-collapse-001.html [ Failure ] crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/align_center.html [ Failure ] @@ -3659,7 +3718,6 @@ crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-002v.html [ Failure ] crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-intrinsic-ratio-005v.html [ Failure ] crbug.com/626703 external/wpt/css/mediaqueries/viewport-script-dynamic.html [ Failure ] -crbug.com/626703 external/wpt/css/css-cascade/important-prop.html [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/available-size-014.html [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/available-size-013.html [ Failure ] crbug.com/626703 external/wpt/css/css-writing-modes/available-size-016.html [ Failure ] @@ -3800,7 +3858,7 @@ crbug.com/648295 external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ] crbug.com/626703 virtual/outofblink-cors/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ] crbug.com/626703 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ] -crbug.com/648295 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ] +crbug.com/648295 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ] crbug.com/626703 external/wpt/svg/linking/reftests/href-filter-element.html [ Failure ] crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up.html [ Failure ] crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down.html [ Failure ] @@ -4083,6 +4141,10 @@ crbug.com/785940 external/wpt/web-animations/timing-model/timelines/document-timelines.html [ Failure Pass ] +crbug.com/912362 external/wpt/web-animations/timing-model/timelines/timelines.html [ Failure ] + +crbug.com/912574 virtual/threaded/animations/responsive/transform-responsive-neutral-keyframe.html [ Crash ] + # Decoding test timeout on Win7. Marked flaky to get imported in case it's flaky timeout everywhere. crbug.com/862938 external/wpt/encoding/textdecoder-fatal-single-byte.any.worker.html [ Pass Timeout ] @@ -4096,10 +4158,8 @@ crbug.com/655458 external/wpt/workers/constructors/SharedWorker/setting-port-members.html [ Failure ] crbug.com/655458 external/wpt/workers/constructors/SharedWorker/connect-event.html [ Failure ] crbug.com/655458 external/wpt/workers/constructors/Worker/unresolvable-url.html [ Failure ] -crbug.com/655458 external/wpt/workers/semantics/reporting-errors/002.html [ Failure ] crbug.com/655458 external/wpt/workers/semantics/run-a-worker/003.html [ Failure ] crbug.com/655458 external/wpt/workers/Worker_terminate_event_queue.htm [ Pass Timeout ] -crbug.com/655458 external/wpt/workers/interfaces/WorkerUtils/navigator/language.html [ Failure ] crbug.com/655458 external/wpt/workers/constructors/SharedWorker/interface-objects.html [ Failure ] crbug.com/655458 external/wpt/workers/constructors/SharedWorker/unresolvable-url.html [ Failure ] crbug.com/655458 external/wpt/workers/semantics/multiple-workers/007.html [ Timeout ] @@ -4109,10 +4169,8 @@ crbug.com/655458 virtual/omt-worker-fetch/external/wpt/workers/constructors/SharedWorker/setting-port-members.html [ Failure ] crbug.com/655458 virtual/omt-worker-fetch/external/wpt/workers/constructors/SharedWorker/connect-event.html [ Failure ] crbug.com/655458 virtual/omt-worker-fetch/external/wpt/workers/constructors/Worker/unresolvable-url.html [ Failure ] -crbug.com/655458 virtual/omt-worker-fetch/external/wpt/workers/semantics/reporting-errors/002.html [ Failure ] crbug.com/655458 virtual/omt-worker-fetch/external/wpt/workers/semantics/run-a-worker/003.html [ Failure ] crbug.com/655458 virtual/omt-worker-fetch/external/wpt/workers/Worker_terminate_event_queue.htm [ Pass Timeout ] -crbug.com/655458 virtual/omt-worker-fetch/external/wpt/workers/interfaces/WorkerUtils/navigator/language.html [ Failure ] crbug.com/655458 virtual/omt-worker-fetch/external/wpt/workers/constructors/SharedWorker/interface-objects.html [ Failure ] crbug.com/655458 virtual/omt-worker-fetch/external/wpt/workers/constructors/SharedWorker/unresolvable-url.html [ Failure ] crbug.com/655458 virtual/omt-worker-fetch/external/wpt/workers/semantics/multiple-workers/007.html [ Timeout ] @@ -4192,17 +4250,17 @@ # This test requires a special browser flag and seems not suitable for a wpt test, see bug. crbug.com/691944 external/wpt/service-workers/service-worker/update-after-oneday.https.html [ Skip ] -crbug.com/691944 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/update-after-oneday.https.html [ Skip ] +crbug.com/691944 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/update-after-oneday.https.html [ Skip ] crbug.com/691944 virtual/outofblink-cors/external/wpt/service-workers/service-worker/update-after-oneday.https.html [ Skip ] crbug.com/691944 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/update-after-oneday.https.html [ Skip ] # These tests (erroneously) see a platform-specific User-Agent header crbug.com/595993 external/wpt/service-workers/service-worker/fetch-header-visibility.https.html [ Failure ] -crbug.com/595993 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/fetch-header-visibility.https.html [ Failure ] +crbug.com/595993 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/fetch-header-visibility.https.html [ Failure ] crbug.com/595993 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-header-visibility.https.html [ Failure ] crbug.com/595993 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/fetch-header-visibility.https.html [ Failure ] crbug.com/595993 external/wpt/service-workers/service-worker/request-end-to-end.https.html [ Failure ] -crbug.com/595993 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/request-end-to-end.https.html [ Failure ] +crbug.com/595993 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/request-end-to-end.https.html [ Failure ] crbug.com/595993 virtual/outofblink-cors/external/wpt/service-workers/service-worker/request-end-to-end.https.html [ Failure ] crbug.com/595993 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/request-end-to-end.https.html [ Failure ] @@ -4211,7 +4269,7 @@ crbug.com/894682 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/postmessage-to-client-message-queue.https.html [ Skip ] crbug.com/894682 external/wpt/service-workers/service-worker/postmessage-to-client-message-queue.https.html [ Skip ] crbug.com/894682 virtual/outofblink-cors/external/wpt/service-workers/service-worker/postmessage-to-client-message-queue.https.html [ Skip ] -crbug.com/894682 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/postmessage-to-client-message-queue.https.html [ Skip ] +crbug.com/894682 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/postmessage-to-client-message-queue.https.html [ Skip ] crbug.com/619427 [ Mac ] fast/overflow/overflow-height-float-not-removed-crash3.html [ Pass Failure ] crbug.com/619427 [ Linux ] fast/overflow/overflow-height-float-not-removed-crash3.html [ Pass Failure ] @@ -4294,8 +4352,6 @@ crbug.com/709227 external/wpt/console/console-time-label-conversion.any.html [ Failure ] crbug.com/709227 external/wpt/console/console-time-label-conversion.any.worker.html [ Failure ] crbug.com/709227 external/wpt/html/browsers/history/the-location-interface/per-global.window.html [ Failure ] -crbug.com/709227 external/wpt/html/webappapis/scripting/events/event-handler-processing-algorithm-error/synthetic-errorevent-click.worker.html [ Failure ] -crbug.com/709227 external/wpt/html/webappapis/scripting/events/event-handler-processing-algorithm-error/workerglobalscope-synthetic-errorevent.worker.html [ Failure ] crbug.com/709227 external/wpt/offscreen-canvas/path-objects/2d.path.stroke.prune.arc.worker.html [ Failure ] crbug.com/709227 external/wpt/offscreen-canvas/path-objects/2d.path.stroke.prune.closed.worker.html [ Failure ] crbug.com/709227 external/wpt/offscreen-canvas/path-objects/2d.path.stroke.prune.curve.worker.html [ Failure ] @@ -4373,15 +4429,6 @@ crbug.com/820334 virtual/outofblink-cors/external/wpt/fetch/api/request/request-cache-default-conditional.html [ Timeout Pass ] crbug.com/820334 virtual/outofblink-cors-ns/external/wpt/fetch/api/request/request-cache-default-conditional.html [ Timeout Pass ] -# Link highlights currently paint under ancestor affects but this is being -# changed with BlinkGenPropertyTrees. Until that launches, this test will fail. -crbug.com/857501 compositing/gestures/gesture-tapHighlight-with-filter.html [ Failure ] - -# Clip and Clip-path order with filtering is currently incorrect. This is being fixed with BlinkGenPropertyTrees. -crbug.com/907175 external/wpt/css/css-masking/clip/clip-filter-order.html [ Failure ] -crbug.com/907175 external/wpt/css/css-masking/clip-path/clip-path-filter-order.html [ Failure ] -crbug.com/907175 external/wpt/svg/rendering/order/clip-path-filter-order.svg [ Failure ] - crbug.com/716320 external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success-and-failure.html [ Failure Timeout ] crbug.com/716320 external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success.html [ Failure Timeout ] crbug.com/716320 [ Android ] external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-messagechannel-success.html [ Failure Timeout ] @@ -4413,7 +4460,7 @@ crbug.com/831509 external/wpt/service-workers/service-worker/skip-waiting-installed.https.html [ Failure Pass ] crbug.com/831509 virtual/navigation-mojo-response/external/wpt/service-workers/service-worker/skip-waiting-installed.https.html [ Failure Pass ] -crbug.com/831509 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/skip-waiting-installed.https.html [ Failure Pass ] +crbug.com/831509 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/skip-waiting-installed.https.html [ Failure Pass ] crbug.com/831509 virtual/outofblink-cors/external/wpt/service-workers/service-worker/skip-waiting-installed.https.html [ Failure Pass ] crbug.com/831509 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/skip-waiting-installed.https.html [ Failure Pass ] @@ -4454,7 +4501,7 @@ crbug.com/874567 [ Mac ] svg/custom/getscreenctm-in-scrollable-div-area-nested.xhtml [ Pass Failure ] crbug.com/874837 [ Win ] ietestcenter/css3/bordersbackgrounds/background-attachment-local-scrolling.htm [ Pass Failure ] crbug.com/874866 [ Mac ] virtual/new-remote-playback-pipeline/media/controls/modern/doubletap-to-jump-backwards-at-start.html [ Pass Timeout ] -crbug.com/874931 virtual/threaded/fast/scroll-behavior/smooth-scroll/mousewheel-scroll.html [ Pass Failure ] +crbug.com/874931 virtual/threaded/fast/scroll-behavior/smooth-scroll/mousewheel-scroll.html [ Pass Failure Crash ] crbug.com/875003 [ Win ] editing/caret/caret-is-hidden-when-no-focus.html [ Pass Failure ] crbug.com/715718 external/wpt/media-source/mediasource-remove.html [ Failure Pass ] @@ -4562,6 +4609,7 @@ # Tests failing when enabling new modern media controls crbug.com/831942 media/webkit-media-controls-webkit-appearance.html [ Failure Pass ] crbug.com/831957 compositing/video/video-controls-layer-creation-squashing.html [ Failure Pass ] +crbug.com/831957 virtual/not-blink-gen-property-trees/compositing/video/video-controls-layer-creation-squashing.html [ Failure Pass ] crbug.com/832157 external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-added.html [ Skip ] crbug.com/832169 media/media-controls-fit-properly-while-zoomed.html [ Failure Pass ] crbug.com/832169 virtual/video-surface-layer/media/media-controls-fit-properly-while-zoomed.html [ Failure Pass ] @@ -4669,11 +4717,6 @@ # Antialiasing error crbug.com/845973 virtual/display-compositor-pixel-dump/fast/canvas/display-compositor-pixel-dump/OffscreenCanvas-opaque-background-compositing.html [ Pass Failure ] -# Workaround crbug.com/817175 . Very difficult to fix with old-world compositing -# but pass with CompositeAfterPaint. -crbug.com/817175 compositing/overflow/clip-escaping-reverse-order-should-not-crash.html [ Failure ] -crbug.com/817175 virtual/prefer_compositing_to_lcd_text/compositing/overflow/clip-escaping-reverse-order-should-not-crash.html [ Failure ] - # Tests occasionaly timing out (flaky) on WebKit Win7 dbg builder crbug.com/757955 [ Win7 Debug ] http/tests/devtools/sources/debugger-pause/pause-on-elements-panel.js [ Pass Timeout ] crbug.com/757955 [ Win7 Debug ] storage/indexeddb/mozilla/cursors.html [ Pass Timeout ] @@ -4814,7 +4857,6 @@ # Sheriff failures 2017-11-30 crbug.com/789921 [ Win7 ] media/video-controls-overflow-menu-last-button-visible.html [ Pass Failure ] crbug.com/789921 [ Mac ] media/video-controls-overflow-menu-last-button-visible.html [ Pass Failure ] -crbug.com/790025 virtual/gpu-rasterization/images/image-hover-display-alt.html [ Failure Pass ] # Sheriff failures 2017-12-04 crbug.com/667560 http/tests/devtools/elements/styles-4/inline-style-sourcemap.js [ Pass Failure ] @@ -4857,7 +4899,7 @@ crbug.com/802915 css3/blending/isolation-should-include-non-local-background.html [ Failure ] crbug.com/807838 external/wpt/service-workers/service-worker/worker-in-sandboxed-iframe-by-csp-fetch-event.https.html [ Crash Pass ] -crbug.com/807838 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/worker-in-sandboxed-iframe-by-csp-fetch-event.https.html [ Crash Pass ] +crbug.com/807838 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/worker-in-sandboxed-iframe-by-csp-fetch-event.https.html [ Crash Pass ] crbug.com/807838 virtual/outofblink-cors/external/wpt/service-workers/service-worker/worker-in-sandboxed-iframe-by-csp-fetch-event.https.html [ Crash Pass ] crbug.com/807838 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/worker-in-sandboxed-iframe-by-csp-fetch-event.https.html [ Crash Pass ] @@ -5080,7 +5122,7 @@ crbug.com/840881 external/wpt/service-workers/service-worker/resource-timing.https.html [ Failure ] crbug.com/840881 virtual/outofblink-cors/external/wpt/service-workers/service-worker/resource-timing.https.html [ Failure ] crbug.com/840881 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/resource-timing.https.html [ Failure ] -crbug.com/840881 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/resource-timing.https.html [ Failure ] +crbug.com/840881 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/resource-timing.https.html [ Failure ] # Sheriff 2018-04-12 crbug.com/831993 [ Linux ] virtual/gpu-rasterization/images/cross-fade-overflow-position.html [ Pass Timeout ] @@ -5428,11 +5470,11 @@ crbug.com/873873 external/wpt/service-workers/service-worker/fetch-canvas-tainting-video.https.html [ Timeout Pass ] crbug.com/873873 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video.https.html [ Timeout Pass ] crbug.com/873873 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video.https.html [ Timeout Pass ] -crbug.com/873873 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video.https.html [ Timeout Pass ] +crbug.com/873873 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video.https.html [ Timeout Pass ] crbug.com/873873 external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-cache.https.html [ Timeout Pass ] crbug.com/873873 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-cache.https.html [ Timeout Pass ] crbug.com/873873 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-cache.https.html [ Timeout Pass ] -crbug.com/873873 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-cache.https.html [ Timeout Pass ] +crbug.com/873873 virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-cache.https.html [ Timeout Pass ] # IntersectionObserverV2 tests run in a virtual test suite crbug.com/827639 intersection-observer/v2 [ Skip ] @@ -5550,9 +5592,6 @@ crbug.com/902591 [ Linux ] svg/zoom/page/zoom-svg-float-border-padding.xml [ Failure ] crbug.com/902591 [ Linux ] tables/mozilla/bugs/bug2973.html [ Failure ] -# Sheriff 2018-09-13 -crbug.com/883591 [ Android ] fullscreen/full-screen-inline-split-crash.html [ Pass Crash ] - # Sheriff 2018-09-18 crbug.com/884445 virtual/unified-autoplay/external/wpt/feature-policy/feature-policy-nested-header-policy-disallowed-for-all.https.sub.html [ Pass Timeout ] crbug.com/884445 virtual/video-surface-layer/external/wpt/feature-policy/feature-policy-nested-header-policy-disallowed-for-all.https.sub.html [ Pass Timeout ] @@ -5568,7 +5607,6 @@ # Enable AnimationWorklet tests for mainthread crbug.com/785940 [ Release ] animations/animationworklet/worklet-animation-currentTime.html [ Pass Failure ] -crbug.com/887659 virtual/threaded/animations/animationworklet/worklet-animation-local-time-after-duration.html [ Failure ] # Sheriff 2018-09-25 crbug.com/888609 [ Mac ] http/tests/devtools/coverage/gutter-css.js [ Pass Timeout ] @@ -5604,11 +5642,6 @@ crbug.com/895777 external/wpt/css/css-transforms/text-perspective-001.html [ Pass Crash ] crbug.com/895777 external/wpt/infrastructure/assumptions/blank.html [ Failure Crash ] -#Sheriff 2018-10-18 -crbug.com/896765 [ Linux ] http/tests/performance-timing/element-timing/observe-child-element.html [ Failure Pass ] -crbug.com/896765 [ Mac ] http/tests/performance-timing/element-timing/observe-child-element.html [ Failure Pass ] -crbug.com/896765 [ Win ] http/tests/performance-timing/element-timing/observe-child-element.html [ Failure Pass ] - #Sheriff 2018-10-23 crbug.com/898214 [ Mac10.11 ] virtual/outofblink-cors-ns/external/wpt/fetch/api/credentials/authentication-basic.any.html [ Failure ] crbug.com/898050 [ Mac ] fast/workers/taskqueue/basic.html [ Pass Timeout ] @@ -5668,7 +5701,7 @@ crbug.com/904389 http/tests/preload/delaying_onload_link_preload_after_discovery.html [ Failure Pass ] #Sheriff 2018-11-14 -crbug.com/905694 [ Linux ] virtual/threaded/fast/scroll-behavior/smooth-scroll/scroll-during-selection.html [ Failure Pass ] +crbug.com/905694 [ Linux ] virtual/threaded/fast/scroll-behavior/smooth-scroll/scroll-during-selection.html [ Failure Pass Crash ] crbug.com/905772 [ Linux ] virtual/sampling-heap-profiler/inspector-protocol/memory/sampling-native-profile-partition-alloc.js [ Failure Pass ] crbug.com/905827 [ Mac10.13 ] fast/dom/StyleSheet/stylesheet-move-between-documents-crash.html [ Failure Pass ] @@ -5682,7 +5715,6 @@ # See also crbug.com/907150 crbug.com/667560 http/tests/devtools/console-cross-origin-iframe-logging.js [ Pass Failure Timeout ] crbug.com/907412 [ Mac10.13 ] external/wpt/domxpath/xml_xpath_runner.html [ Pass Timeout ] -crbug.com/907481 virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-nomsid.html [ Pass Failure ] #Sheriff 2018-11-22 crbug.com/907736 http/tests/devtools/elements/elements-save-to-temp-var.js [ Timeout Pass ] @@ -5701,10 +5733,29 @@ crbug.com/910139 custom-elements/form-submission-file.html [ Crash Pass ] crbug.com/905772 [ Linux ] inspector-protocol/memory/sampling-native-profile-blink-gc.js [ Failure Pass ] -#Sheriff 2018-12-03 -crbug.com/910846 [ Win ] virtual/streaming-preload/external/wpt/html/semantics/scripting-1/the-script-element/execution-timing/078.html [ Failure Pass Timeout ] - #Sheriff 2018-12-04 crbug.com/911515 [ Mac ] transforms/shadows.html [ Pass Failure ] crbug.com/911634 [ Linux ] fast/events/touch/gesture/touch-gesture-scroll-input-field.html [ Pass Failure ] crbug.com/911782 [ Mac ] paint/invalidation/forms/submit-focus-by-mouse-then-keydown.html [ Pass Failure ] + +#Sheriff 2018-12-06 +crbug.com/912570 [ Linux ] virtual/threaded/compositing/visibility/overlays-persist-on-navigation.html [ Failure Pass ] + +# ssauleau 2018-12-06 +crbug.com/v8/8319 external/wpt/wasm/jsapi/interface.any.html [ Pass Failure ] +crbug.com/v8/8319 external/wpt/wasm/webapi/idlharness.any.worker.html [ Pass Failure ] +crbug.com/v8/8319 external/wpt/wasm/webapi/idlharness.any.html [ Pass Failure ] +crbug.com/v8/8319 external/wpt/wasm/jsapi/idlharness.any.worker.html [ Pass Failure ] +crbug.com/v8/8319 external/wpt/wasm/jsapi/idlharness.any.html [ Pass Failure ] +crbug.com/v8/8319 external/wpt/wasm/jsapi/interface.any.worker.html [ Pass Failure ] + +# Sheriff 2018-12-06 +crbug.com/912793 http/tests/devtools/sources/debugger-breakpoints/restore-locations-for-breakpoint-with-broken-source-map.js [ Pass Failure ] +crbug.com/912793 virtual/android/fullscreen/full-screen-iframe-allowed-video.html [ Pass Failure ] + +# Sheriff 2018-12-07 +crbug.com/912821 [ Mac ] virtual/threaded/http/tests/devtools/tracing/user-timing.js [ Pass Failure ] + +crbug.com/913170 compositing/layer-creation/fixed-position-in-fixed-overflow.html [ Crash Pass ] +crbug.com/913173 fast/backgrounds/background-svg-scaling-zoom.html [ Failure Pass ] +
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 6ec1bcd..6bc096c 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -263,43 +263,18 @@ }, { "prefix": "composite-after-paint", - "base": "fast/block", - "args": ["--enable-blink-features=CompositeAfterPaint"] - }, - { - "prefix": "composite-after-paint", - "base": "fast/borders", - "args": ["--enable-blink-features=CompositeAfterPaint"] - }, - { - "prefix": "composite-after-paint", - "base": "fast/clip", - "args": ["--enable-blink-features=CompositeAfterPaint"] - }, - { - "prefix": "composite-after-paint", - "base": "fast/css", - "args": ["--enable-blink-features=CompositeAfterPaint"] - }, - { - "prefix": "composite-after-paint", - "base": "fast/overflow", - "args": ["--enable-blink-features=CompositeAfterPaint"] - }, - { - "prefix": "composite-after-paint", "base": "paint", "args": ["--enable-blink-features=CompositeAfterPaint"] }, { - "prefix": "composite-after-paint", - "base": "svg", - "args": ["--enable-blink-features=CompositeAfterPaint"] + "prefix": "not-blink-gen-property-trees", + "base": "compositing", + "args": ["--disable-blink-features=BlinkGenPropertyTrees"] }, { - "prefix": "blink-gen-property-trees", - "base": "paint/transparency", - "args": ["--enable-blink-features=BlinkGenPropertyTrees"] + "prefix": "not-blink-gen-property-trees", + "base": "paint", + "args": ["--disable-blink-features=BlinkGenPropertyTrees"] }, { "prefix": "scalefactor200", @@ -683,16 +658,14 @@ "args": ["--enable-features=SignedHTTPExchangeOriginTrial,NetworkService"] }, { - "prefix": "service-worker-servicification", + "prefix": "disabled-service-worker-servicification", "base": "http/tests/serviceworker", - "args": ["--enable-features=ServiceWorkerServicification", - "--disable-features=NetworkService"] + "args": ["--disable-features=ServiceWorkerServicification,NetworkService"] }, { - "prefix": "service-worker-servicification", + "prefix": "disabled-service-worker-servicification", "base": "external/wpt/service-workers/service-worker", - "args": ["--enable-features=ServiceWorkerServicification", - "--disable-features=NetworkService"] + "args": ["--disable-features=ServiceWorkerServicification,NetworkService"] }, { "prefix": "omt-worker-fetch",
diff --git a/third_party/blink/web_tests/animations/animationworklet/worklet-animation-local-time-after-duration.html b/third_party/blink/web_tests/animations/animationworklet/worklet-animation-local-time-after-duration.html index 6a7a8d2..3632015 100644 --- a/third_party/blink/web_tests/animations/animationworklet/worklet-animation-local-time-after-duration.html +++ b/third_party/blink/web_tests/animations/animationworklet/worklet-animation-local-time-after-duration.html
@@ -14,7 +14,7 @@ animate(currentTime, effect) { // If an effect doesn't have fill-mode specified, setting its local time // beyond its duration makes the animation inactive. - effect.localTime = 5000; + effect.localTime = 2000; } }); </script> @@ -36,6 +36,7 @@ { transform: 'translateY(200px)' } ], { duration: 1000, + delay: 1000 } );
diff --git a/third_party/blink/web_tests/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png b/third_party/blink/web_tests/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png index 446aa85..c692dda 100644 --- a/third_party/blink/web_tests/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png +++ b/third_party/blink/web_tests/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png b/third_party/blink/web_tests/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png index 5393c95..5bfd018 100644 --- a/third_party/blink/web_tests/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png +++ b/third_party/blink/web_tests/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/fixed-body-background-positioned-expected.txt b/third_party/blink/web_tests/compositing/fixed-body-background-positioned-expected.txt index a9d5368..3ec78909d 100644 --- a/third_party/blink/web_tests/compositing/fixed-body-background-positioned-expected.txt +++ b/third_party/blink/web_tests/compositing/fixed-body-background-positioned-expected.txt
@@ -10,10 +10,6 @@ "drawsContent": false }, { - "name": "Overscroll Elasticity Layer", - "drawsContent": false - }, - { "name": "Page Scale Layer", "drawsContent": false },
diff --git a/third_party/blink/web_tests/compositing/geometry/clip-expected.txt b/third_party/blink/web_tests/compositing/geometry/clip-expected.txt index 100aca1..25c210da 100644 --- a/third_party/blink/web_tests/compositing/geometry/clip-expected.txt +++ b/third_party/blink/web_tests/compositing/geometry/clip-expected.txt
@@ -26,12 +26,6 @@ "transform": 2 }, { - "name": "Ancestor Clipping Layer", - "position": [215, 15], - "bounds": [110, 110], - "drawsContent": false - }, - { "name": "LayoutBlockFlow (relative positioned) DIV class='composited inner'", "bounds": [120, 120], "backgroundColor": "#00000033", @@ -65,8 +59,7 @@ [0, 1, 0, 0], [0, 0, 1, 0], [210, 10, 0, 1] - ], - "flattenInheritedTransform": false + ] }, { "id": 4, @@ -76,8 +69,7 @@ [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 1, 1] - ], - "flattenInheritedTransform": false + ] } ] }
diff --git a/third_party/blink/web_tests/compositing/geometry/clip-inside-expected.txt b/third_party/blink/web_tests/compositing/geometry/clip-inside-expected.txt index 3566aba2..5f640749 100644 --- a/third_party/blink/web_tests/compositing/geometry/clip-inside-expected.txt +++ b/third_party/blink/web_tests/compositing/geometry/clip-inside-expected.txt
@@ -27,12 +27,6 @@ "transform": 2 }, { - "name": "Ancestor Clipping Layer", - "position": [225, 35], - "bounds": [90, 80], - "drawsContent": false - }, - { "name": "LayoutBlockFlow (relative positioned) DIV class='composited inner'", "bounds": [120, 120], "backgroundColor": "#00000033", @@ -66,8 +60,7 @@ [0, 1, 0, 0], [0, 0, 1, 0], [210, 10, 0, 1] - ], - "flattenInheritedTransform": false + ] }, { "id": 4, @@ -77,8 +70,7 @@ [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 1, 1] - ], - "flattenInheritedTransform": false + ] } ] }
diff --git a/third_party/blink/web_tests/compositing/geometry/clip-with-shadow-expected.txt b/third_party/blink/web_tests/compositing/geometry/clip-with-shadow-expected.txt index 3a44c3e..c0cdeeab 100644 --- a/third_party/blink/web_tests/compositing/geometry/clip-with-shadow-expected.txt +++ b/third_party/blink/web_tests/compositing/geometry/clip-with-shadow-expected.txt
@@ -24,12 +24,6 @@ "transform": 2 }, { - "name": "Ancestor Clipping Layer", - "position": [215, 15], - "bounds": [110, 110], - "drawsContent": false - }, - { "name": "LayoutBlockFlow (relative positioned) DIV class='composited inner'", "bounds": [120, 120], "backgroundColor": "#00000033", @@ -63,8 +57,7 @@ [0, 1, 0, 0], [0, 0, 1, 0], [210, 10, 0, 1] - ], - "flattenInheritedTransform": false + ] }, { "id": 4, @@ -74,8 +67,7 @@ [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 1, 1] - ], - "flattenInheritedTransform": false + ] } ] }
diff --git a/third_party/blink/web_tests/compositing/geometry/foreground-layer-expected.txt b/third_party/blink/web_tests/compositing/geometry/foreground-layer-expected.txt index 1617299..6b6d8611 100644 --- a/third_party/blink/web_tests/compositing/geometry/foreground-layer-expected.txt +++ b/third_party/blink/web_tests/compositing/geometry/foreground-layer-expected.txt
@@ -42,13 +42,6 @@ "transform": 4 }, { - "name": "Child Containment Layer", - "position": [59, 59], - "bounds": [200, 200], - "drawsContent": false, - "transform": 4 - }, - { "name": "LayoutBlockFlow (positioned) DIV class='negative child'", "bounds": [50, 50], "drawsContent": false, @@ -56,8 +49,7 @@ }, { "name": "LayoutBlockFlow (relative positioned) DIV class='main box' (foreground) Layer", - "position": [59, 59], - "bounds": [200, 200], + "bounds": [318, 318], "transform": 4 } ],
diff --git a/third_party/blink/web_tests/compositing/iframes/become-composited-nested-iframes-expected.txt b/third_party/blink/web_tests/compositing/iframes/become-composited-nested-iframes-expected.txt index 2021656..d178b72 100644 --- a/third_party/blink/web_tests/compositing/iframes/become-composited-nested-iframes-expected.txt +++ b/third_party/blink/web_tests/compositing/iframes/become-composited-nested-iframes-expected.txt
@@ -28,12 +28,6 @@ "bounds": [280, 200] }, { - "name": "Child Containment Layer", - "position": [22, 122], - "bounds": [280, 200], - "drawsContent": false - }, - { "name": "LayoutIFrame IFRAME", "position": [30, 130], "bounds": [252, 172] @@ -45,12 +39,6 @@ "backgroundColor": "#C0C0C0" }, { - "name": "Child Containment Layer", - "position": [31, 131], - "bounds": [250, 170], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV id='iframe-content' class='box'", "bounds": [210, 210], "contentsOpaque": true, @@ -68,12 +56,6 @@ "bounds": [280, 200] }, { - "name": "Child Containment Layer", - "position": [22, 346], - "bounds": [280, 200], - "drawsContent": false - }, - { "name": "LayoutIFrame IFRAME", "position": [30, 354], "bounds": [252, 172] @@ -85,12 +67,6 @@ "backgroundColor": "#C0C0C0" }, { - "name": "Child Containment Layer", - "position": [31, 355], - "bounds": [250, 170], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV id='iframe-content' class='box'", "bounds": [210, 210], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/compositing/iframes/invisible-nested-iframe-show-expected.txt b/third_party/blink/web_tests/compositing/iframes/invisible-nested-iframe-show-expected.txt deleted file mode 100644 index feaa11f..0000000 --- a/third_party/blink/web_tests/compositing/iframes/invisible-nested-iframe-show-expected.txt +++ /dev/null
@@ -1,117 +0,0 @@ -{ - "layers": [ - { - "name": "LayoutView #document", - "bounds": [800, 600], - "drawsContent": false, - "backgroundColor": "#FFFFFF" - }, - { - "name": "Scrolling Layer", - "bounds": [800, 600], - "drawsContent": false - }, - { - "name": "Scrolling Contents Layer", - "bounds": [800, 600], - "contentsOpaque": true, - "backgroundColor": "#FFFFFF" - }, - { - "name": "LayoutIFrame IFRAME", - "position": [-11, -11], - "bounds": [368, 218] - }, - { - "name": "LayoutView #document", - "position": [23, 23], - "bounds": [300, 150], - "drawsContent": false - }, - { - "name": "Scrolling Layer", - "position": [23, 23], - "bounds": [285, 150], - "drawsContent": false - }, - { - "name": "Scrolling Contents Layer", - "position": [23, 23], - "bounds": [285, 192] - }, - { - "name": "LayoutIFrame IFRAME", - "position": [31, 31], - "bounds": [252, 172] - }, - { - "name": "LayoutView #document", - "position": [32, 32], - "bounds": [250, 170], - "backgroundColor": "#C0C0C0" - }, - { - "name": "Child Containment Layer", - "position": [32, 32], - "bounds": [250, 170], - "drawsContent": false - }, - { - "name": "LayoutBlockFlow DIV id='iframe-content' class='box'", - "bounds": [210, 210], - "contentsOpaque": true, - "backgroundColor": "#0000FF", - "transform": 1 - }, - { - "name": "Overflow Controls Host Layer", - "position": [23, 23], - "bounds": [300, 150], - "drawsContent": false - }, - { - "name": "Vertical Scrollbar Layer", - "position": [308, 23], - "bounds": [15, 150], - "drawsContent": false - }, - { - "name": "LayoutBlockFlow DIV class='box'", - "bounds": [210, 210], - "contentsOpaque": true, - "backgroundColor": "#0000FF", - "transform": 3 - } - ], - "transforms": [ - { - "id": 1, - "transform": [ - [1, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 1, 0], - [50, 42, 0, 1] - ] - }, - { - "id": 2, - "transform": [ - [1, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 1, 0], - [18, 202, 0, 1] - ] - }, - { - "id": 3, - "parent": 2, - "transform": [ - [1, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 1, 0], - [0, 0, 1, 1] - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/compositing/iframes/overlapped-iframe-iframe-expected.txt b/third_party/blink/web_tests/compositing/iframes/overlapped-iframe-iframe-expected.txt index c3c1d6f8..39fe83cf 100644 --- a/third_party/blink/web_tests/compositing/iframes/overlapped-iframe-iframe-expected.txt +++ b/third_party/blink/web_tests/compositing/iframes/overlapped-iframe-iframe-expected.txt
@@ -28,12 +28,6 @@ "backgroundColor": "#C0C0C0" }, { - "name": "Child Containment Layer", - "position": [2, 2], - "bounds": [300, 300], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV id='iframe-content' class='box'", "bounds": [210, 210], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/compositing/iframes/overlapped-nested-iframes-expected.txt b/third_party/blink/web_tests/compositing/iframes/overlapped-nested-iframes-expected.txt index 368814d..9ba42f2e 100644 --- a/third_party/blink/web_tests/compositing/iframes/overlapped-nested-iframes-expected.txt +++ b/third_party/blink/web_tests/compositing/iframes/overlapped-nested-iframes-expected.txt
@@ -31,13 +31,6 @@ "transform": 1 }, { - "name": "Child Containment Layer", - "position": [22, 152], - "bounds": [280, 200], - "drawsContent": false, - "transform": 1 - }, - { "name": "LayoutIFrame IFRAME", "position": [30, 160], "bounds": [252, 172], @@ -51,13 +44,6 @@ "transform": 1 }, { - "name": "Child Containment Layer", - "position": [31, 161], - "bounds": [250, 170], - "drawsContent": false, - "transform": 1 - }, - { "name": "LayoutBlockFlow DIV id='iframe-content' class='box'", "bounds": [210, 210], "contentsOpaque": true, @@ -77,13 +63,6 @@ "transform": 1 }, { - "name": "Child Containment Layer", - "position": [22, 376], - "bounds": [280, 200], - "drawsContent": false, - "transform": 1 - }, - { "name": "LayoutIFrame IFRAME", "position": [30, 384], "bounds": [252, 172], @@ -97,13 +76,6 @@ "transform": 1 }, { - "name": "Child Containment Layer", - "position": [31, 385], - "bounds": [250, 170], - "drawsContent": false, - "transform": 1 - }, - { "name": "LayoutBlockFlow DIV id='iframe-content' class='box'", "bounds": [210, 210], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overflow-scroll-overlap-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/overflow-scroll-overlap-expected.txt index 0bc9060..dadd6247 100644 --- a/third_party/blink/web_tests/compositing/layer-creation/overflow-scroll-overlap-expected.txt +++ b/third_party/blink/web_tests/compositing/layer-creation/overflow-scroll-overlap-expected.txt
@@ -33,9 +33,7 @@ "bounds": [306, 206] }, { - "name": "Ancestor Clipping Layer", - "position": [23, 23], - "bounds": [285, 200], + "name": "Squashing Containment Layer", "drawsContent": false }, {
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overlap-animation-clipping-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/overlap-animation-clipping-expected.txt index 1d920582..259d5e5 100644 --- a/third_party/blink/web_tests/compositing/layer-creation/overlap-animation-clipping-expected.txt +++ b/third_party/blink/web_tests/compositing/layer-creation/overlap-animation-clipping-expected.txt
@@ -32,12 +32,6 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Child Containment Layer", - "position": [59, 231], - "bounds": [120, 460], - "drawsContent": false - }, - { "name": "LayoutBlockFlow (relative positioned) DIV class='box gray force-layer'", "bounds": [100, 100], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overlap-animation-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/overlap-animation-expected.txt index 0f1c74b..6dba170 100644 --- a/third_party/blink/web_tests/compositing/layer-creation/overlap-animation-expected.txt +++ b/third_party/blink/web_tests/compositing/layer-creation/overlap-animation-expected.txt
@@ -23,12 +23,6 @@ "bounds": [122, 242] }, { - "name": "Child Containment Layer", - "position": [9, 9], - "bounds": [120, 240], - "drawsContent": false - }, - { "name": "LayoutBlockFlow (relative positioned) DIV id='to-animate' class='animating box'", "bounds": [100, 100], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overlap-clipping-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/overlap-clipping-expected.txt index f2c359c09..cddaf922 100644 --- a/third_party/blink/web_tests/compositing/layer-creation/overlap-clipping-expected.txt +++ b/third_party/blink/web_tests/compositing/layer-creation/overlap-clipping-expected.txt
@@ -18,12 +18,6 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Ancestor Clipping Layer", - "position": [50, 50], - "bounds": [100, 100], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV id='child'", "bounds": [500, 100], "contentsOpaque": true, @@ -55,8 +49,7 @@ [0, 1, 0, 0], [0, 0, 1, 0], [50, 50, 0, 1] - ], - "flattenInheritedTransform": false + ] }, { "id": 2,
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt index 7f07d31..789cc60 100644 --- a/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt +++ b/third_party/blink/web_tests/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt
@@ -23,12 +23,6 @@ "transform": 1 }, { - "name": "Child Containment Layer", - "bounds": [100, 100], - "drawsContent": false, - "transform": 1 - }, - { "name": "Squashing Containment Layer", "drawsContent": false, "transform": 1
diff --git a/third_party/blink/web_tests/compositing/layer-creation/overlap-transforms-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/overlap-transforms-expected.txt index 6d2c9d99..7ac25dba 100644 --- a/third_party/blink/web_tests/compositing/layer-creation/overlap-transforms-expected.txt +++ b/third_party/blink/web_tests/compositing/layer-creation/overlap-transforms-expected.txt
@@ -23,12 +23,6 @@ "bounds": [122, 242] }, { - "name": "Child Containment Layer", - "position": [9, 9], - "bounds": [120, 240], - "drawsContent": false - }, - { "name": "LayoutBlockFlow (relative positioned) DIV class='transformed box'", "bounds": [100, 100], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt b/third_party/blink/web_tests/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt index 623ad00..c796e3f 100644 --- a/third_party/blink/web_tests/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt +++ b/third_party/blink/web_tests/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt
@@ -18,9 +18,7 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Ancestor Clipping Layer", - "position": [8, 8], - "bounds": [100, 100], + "name": "Squashing Containment Layer", "drawsContent": false }, {
diff --git a/third_party/blink/web_tests/compositing/layer-tree-expected.txt b/third_party/blink/web_tests/compositing/layer-tree-expected.txt index 18acd2b..e2a0b0b 100644 --- a/third_party/blink/web_tests/compositing/layer-tree-expected.txt +++ b/third_party/blink/web_tests/compositing/layer-tree-expected.txt
@@ -9,40 +9,34 @@ "drawsContent": false, "children": [ { - "name": "Overscroll Elasticity Layer", + "name": "Page Scale Layer", "drawsContent": false, "children": [ { - "name": "Page Scale Layer", + "name": "Inner Viewport Scroll Layer", + "bounds": [800, 600], "drawsContent": false, "children": [ { - "name": "Inner Viewport Scroll Layer", + "name": "LayoutView #document", "bounds": [800, 600], "drawsContent": false, + "backgroundColor": "#FFFFFF", + "shouldFlattenTransform": false, "children": [ { - "name": "LayoutView #document", - "bounds": [800, 600], + "name": "Scrolling Layer", + "bounds": [780, 580], "drawsContent": false, - "backgroundColor": "#FFFFFF", + "flattenInheritedTransform": false, "shouldFlattenTransform": false, "children": [ { - "name": "Scrolling Layer", - "bounds": [780, 580], - "drawsContent": false, - "flattenInheritedTransform": false, - "shouldFlattenTransform": false, - "children": [ - { - "name": "Scrolling Contents Layer", - "bounds": [1200, 900], - "contentsOpaque": true, - "backgroundColor": "#FFFFFF", - "flattenInheritedTransform": false - } - ] + "name": "Scrolling Contents Layer", + "bounds": [1200, 900], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "flattenInheritedTransform": false } ] } @@ -92,10 +86,6 @@ "drawsContent": false }, { - "name": "Overscroll Elasticity Layer", - "drawsContent": false - }, - { "name": "Page Scale Layer", "drawsContent": false },
diff --git a/third_party/blink/web_tests/compositing/opacity-with-mask-expected.png b/third_party/blink/web_tests/compositing/opacity-with-mask-expected.png index b39d0c8..7792efb 100644 --- a/third_party/blink/web_tests/compositing/opacity-with-mask-expected.png +++ b/third_party/blink/web_tests/compositing/opacity-with-mask-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/overflow/border-radius-above-composited-subframe-expected.png b/third_party/blink/web_tests/compositing/overflow/border-radius-above-composited-subframe-expected.png index 3c73dc0..1a941fc1 100644 --- a/third_party/blink/web_tests/compositing/overflow/border-radius-above-composited-subframe-expected.png +++ b/third_party/blink/web_tests/compositing/overflow/border-radius-above-composited-subframe-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/overflow/border-radius-composited-subframe-expected.png b/third_party/blink/web_tests/compositing/overflow/border-radius-composited-subframe-expected.png index 8540490..d0ef886 100644 --- a/third_party/blink/web_tests/compositing/overflow/border-radius-composited-subframe-expected.png +++ b/third_party/blink/web_tests/compositing/overflow/border-radius-composited-subframe-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/overflow/border-radius-on-grandparent-composited-grandchild-expected.png b/third_party/blink/web_tests/compositing/overflow/border-radius-on-grandparent-composited-grandchild-expected.png index f4b4fff8..2cee245 100644 --- a/third_party/blink/web_tests/compositing/overflow/border-radius-on-grandparent-composited-grandchild-expected.png +++ b/third_party/blink/web_tests/compositing/overflow/border-radius-on-grandparent-composited-grandchild-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/overflow/border-radius-on-parent-composited-grandchild-expected.png b/third_party/blink/web_tests/compositing/overflow/border-radius-on-parent-composited-grandchild-expected.png index f380d7a..9e367a68 100644 --- a/third_party/blink/web_tests/compositing/overflow/border-radius-on-parent-composited-grandchild-expected.png +++ b/third_party/blink/web_tests/compositing/overflow/border-radius-on-parent-composited-grandchild-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png b/third_party/blink/web_tests/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png index 61743f1..b9fac482 100644 --- a/third_party/blink/web_tests/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png +++ b/third_party/blink/web_tests/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/overflow/border-radius-styles-with-composited-child-expected.png b/third_party/blink/web_tests/compositing/overflow/border-radius-styles-with-composited-child-expected.png index 969f416..0258aeb 100644 --- a/third_party/blink/web_tests/compositing/overflow/border-radius-styles-with-composited-child-expected.png +++ b/third_party/blink/web_tests/compositing/overflow/border-radius-styles-with-composited-child-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/overflow/clear-scroll-parent-expected.txt b/third_party/blink/web_tests/compositing/overflow/clear-scroll-parent-expected.txt index 9b7a2ba..6ec2d94 100644 --- a/third_party/blink/web_tests/compositing/overflow/clear-scroll-parent-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/clear-scroll-parent-expected.txt
@@ -60,17 +60,11 @@ "backgroundColor": "#008000" }, { - "name": "Ancestor Clipping Layer", - "position": [12, 12], - "bounds": [80, 80], - "drawsContent": false, - "hasScrollParent": true - }, - { "name": "LayoutBlockFlow (relative positioned) DIV class='box red'", "position": [22, 22], "bounds": [100, 100], - "backgroundColor": "#FF000080" + "backgroundColor": "#FF000080", + "hasScrollParent": true }, { "name": "Squashing Containment Layer",
diff --git a/third_party/blink/web_tests/compositing/overflow/clip-descendents-expected.txt b/third_party/blink/web_tests/compositing/overflow/clip-descendents-expected.txt index 048aec8..cbfaa8c 100644 --- a/third_party/blink/web_tests/compositing/overflow/clip-descendents-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/clip-descendents-expected.txt
@@ -18,12 +18,6 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Ancestor Clipping Layer", - "position": [48, 38], - "bounds": [60, 70], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV class='box'", "bounds": [100, 150], "contentsOpaque": true, @@ -31,12 +25,6 @@ "transform": 2 }, { - "name": "Ancestor Clipping Layer", - "position": [240, 38], - "bounds": [60, 70], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV class='box'", "bounds": [100, 150], "contentsOpaque": true, @@ -49,12 +37,6 @@ "bounds": [60, 70] }, { - "name": "Child Containment Layer", - "position": [48, 230], - "bounds": [60, 70], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV class='box'", "bounds": [100, 150], "contentsOpaque": true, @@ -67,12 +49,6 @@ "bounds": [60, 70] }, { - "name": "Child Containment Layer", - "position": [240, 230], - "bounds": [60, 70], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV class='box'", "bounds": [100, 150], "contentsOpaque": true, @@ -88,8 +64,7 @@ [0, 1, 0, 0], [0, 0, 1, 0], [50, 50, 0, 1] - ], - "flattenInheritedTransform": false + ] }, { "id": 2, @@ -99,8 +74,7 @@ [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 1, 1] - ], - "flattenInheritedTransform": false + ] }, { "id": 3, @@ -109,8 +83,7 @@ [0, 1, 0, 0], [0, 0, 1, 0], [242, 50, 0, 1] - ], - "flattenInheritedTransform": false + ] }, { "id": 4, @@ -120,8 +93,7 @@ [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 1, 1] - ], - "flattenInheritedTransform": false + ] }, { "id": 5,
diff --git a/third_party/blink/web_tests/compositing/overflow/content-gains-scrollbars-expected.txt b/third_party/blink/web_tests/compositing/overflow/content-gains-scrollbars-expected.txt index 285f901d..5738063 100644 --- a/third_party/blink/web_tests/compositing/overflow/content-gains-scrollbars-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/content-gains-scrollbars-expected.txt
@@ -144,12 +144,6 @@ "transform": 4 }, { - "name": "Child Containment Layer", - "bounds": [100, 100], - "drawsContent": false, - "transform": 4 - }, - { "name": "LayoutBlockFlow (positioned) DIV class='content'", "bounds": [10, 10], "drawsContent": false,
diff --git a/third_party/blink/web_tests/compositing/overflow/content-loses-scrollbars-expected.txt b/third_party/blink/web_tests/compositing/overflow/content-loses-scrollbars-expected.txt index 28e47b8..ccb3739 100644 --- a/third_party/blink/web_tests/compositing/overflow/content-loses-scrollbars-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/content-loses-scrollbars-expected.txt
@@ -24,12 +24,6 @@ "transform": 1 }, { - "name": "Child Containment Layer", - "bounds": [100, 100], - "drawsContent": false, - "transform": 1 - }, - { "name": "LayoutBlockFlow (positioned) DIV id='vertical' class='content'", "bounds": [10, 10], "drawsContent": false, @@ -42,12 +36,6 @@ "transform": 2 }, { - "name": "Child Containment Layer", - "bounds": [100, 100], - "drawsContent": false, - "transform": 2 - }, - { "name": "LayoutBlockFlow (positioned) DIV id='horizontal' class='content'", "bounds": [10, 10], "drawsContent": false, @@ -60,12 +48,6 @@ "transform": 3 }, { - "name": "Child Containment Layer", - "bounds": [100, 100], - "drawsContent": false, - "transform": 3 - }, - { "name": "LayoutBlockFlow (positioned) DIV id='both' class='content'", "bounds": [10, 10], "drawsContent": false, @@ -78,12 +60,6 @@ "transform": 4 }, { - "name": "Child Containment Layer", - "bounds": [100, 100], - "drawsContent": false, - "transform": 4 - }, - { "name": "LayoutBlockFlow (positioned) DIV class='content'", "bounds": [10, 10], "drawsContent": false,
diff --git a/third_party/blink/web_tests/compositing/overflow/grandchild-composited-with-border-radius-ancestor-expected.png b/third_party/blink/web_tests/compositing/overflow/grandchild-composited-with-border-radius-ancestor-expected.png index b219e48..f38a1b2 100644 --- a/third_party/blink/web_tests/compositing/overflow/grandchild-composited-with-border-radius-ancestor-expected.png +++ b/third_party/blink/web_tests/compositing/overflow/grandchild-composited-with-border-radius-ancestor-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png b/third_party/blink/web_tests/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png index b219e48..f38a1b2 100644 --- a/third_party/blink/web_tests/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png +++ b/third_party/blink/web_tests/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/overflow/no-excessive-clip-parent-if-parent-escaped-expected.txt b/third_party/blink/web_tests/compositing/overflow/no-excessive-clip-parent-if-parent-escaped-expected.txt index cc0d374d..88d5d8a 100644 --- a/third_party/blink/web_tests/compositing/overflow/no-excessive-clip-parent-if-parent-escaped-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/no-excessive-clip-parent-if-parent-escaped-expected.txt
@@ -25,12 +25,6 @@ "backgroundColor": "#FF0000" }, { - "name": "Child Containment Layer", - "position": [8, 8], - "bounds": [100, 100], - "drawsContent": false - }, - { "name": "LayoutBlockFlow (positioned) DIV", "position": [8, 8], "bounds": [50, 50],
diff --git a/third_party/blink/web_tests/compositing/overflow/overflow-scroll-with-negative-offset-translucent-outline-expected.html b/third_party/blink/web_tests/compositing/overflow/overflow-scroll-with-negative-offset-translucent-outline-expected.html index 384b2a1..11eb547 100644 --- a/third_party/blink/web_tests/compositing/overflow/overflow-scroll-with-negative-offset-translucent-outline-expected.html +++ b/third_party/blink/web_tests/compositing/overflow/overflow-scroll-with-negative-offset-translucent-outline-expected.html
@@ -8,7 +8,7 @@ #scroller-outline { will-change: transform; - outline: 5px solid rgba(0, 255, 0, 0.5); + outline: 5px solid rgba(0, 255, 0, 0.504); outline-offset: -4px; position: absolute; width: 200px; @@ -16,6 +16,7 @@ } .spacer { + width: 300px; height: 300px; } </style>
diff --git a/third_party/blink/web_tests/compositing/overflow/overflow-scroll-with-negative-offset-translucent-outline.html b/third_party/blink/web_tests/compositing/overflow/overflow-scroll-with-negative-offset-translucent-outline.html index 3c00c48..3ead2559f 100644 --- a/third_party/blink/web_tests/compositing/overflow/overflow-scroll-with-negative-offset-translucent-outline.html +++ b/third_party/blink/web_tests/compositing/overflow/overflow-scroll-with-negative-offset-translucent-outline.html
@@ -1,6 +1,6 @@ <style> #scroller { - outline: 5px solid rgba(0, 255, 0, 0.5); + outline: 5px solid rgba(0, 255, 0, 0.504); outline-offset: -4px; overflow: scroll; width: 200px; @@ -10,6 +10,7 @@ } .spacer { + width: 300px; height: 300px; } </style>
diff --git a/third_party/blink/web_tests/compositing/overflow/overflow-scrollbar-layers-expected.txt b/third_party/blink/web_tests/compositing/overflow/overflow-scrollbar-layers-expected.txt index f679344..59e20844 100644 --- a/third_party/blink/web_tests/compositing/overflow/overflow-scrollbar-layers-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/overflow-scrollbar-layers-expected.txt
@@ -144,12 +144,6 @@ "transform": 4 }, { - "name": "Child Containment Layer", - "bounds": [100, 100], - "drawsContent": false, - "transform": 4 - }, - { "name": "LayoutBlockFlow (positioned) DIV class='content'", "bounds": [10, 10], "drawsContent": false,
diff --git a/third_party/blink/web_tests/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt b/third_party/blink/web_tests/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt index c8f192a..9bf52b91 100644 --- a/third_party/blink/web_tests/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt
@@ -18,29 +18,11 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Ancestor Clipping Layer", - "position": [8, 8], - "bounds": [1200, 800], - "drawsContent": false - }, - { "name": "LayoutBlockFlow (relative positioned) DIV id='positioned'", "position": [8, 8], "bounds": [1200, 800] }, { - "name": "Child Containment Layer", - "position": [8, 8], - "bounds": [1200, 800], - "drawsContent": false - }, - { - "name": "Ancestor Clipping Layer", - "position": [8, 8], - "bounds": [1200, 1000], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV id='scroller'", "position": [8, 8], "bounds": [1200, 1000] @@ -63,12 +45,6 @@ "drawsContent": false }, { - "name": "Overflow Controls Ancestor Clipping Layer", - "position": [8, 8], - "bounds": [1200, 1000], - "drawsContent": false - }, - { "name": "Overflow Controls Host Layer", "position": [8, 8], "bounds": [1200, 1000],
diff --git a/third_party/blink/web_tests/compositing/overflow/rotate-clip-expected.txt b/third_party/blink/web_tests/compositing/overflow/rotate-clip-expected.txt index 9801d91..101f13c 100644 --- a/third_party/blink/web_tests/compositing/overflow/rotate-clip-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/rotate-clip-expected.txt
@@ -23,13 +23,6 @@ "transform": 2 }, { - "name": "Child Containment Layer", - "position": [20, 20], - "bounds": [200, 200], - "drawsContent": false, - "transform": 2 - }, - { "name": "LayoutBlockFlow DIV", "position": [20, 20], "bounds": [400, 400],
diff --git a/third_party/blink/web_tests/compositing/overflow/rotate-then-clip-effect-interleave-expected.txt b/third_party/blink/web_tests/compositing/overflow/rotate-then-clip-effect-interleave-expected.txt index a390599f..c087562 100644 --- a/third_party/blink/web_tests/compositing/overflow/rotate-then-clip-effect-interleave-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/rotate-then-clip-effect-interleave-expected.txt
@@ -30,13 +30,6 @@ "transform": 2 }, { - "name": "Ancestor Clipping Layer", - "position": [20, 20], - "bounds": [200, 200], - "drawsContent": false, - "transform": 2 - }, - { "name": "LayoutBlockFlow DIV", "position": [20, 20], "bounds": [400, 400], @@ -53,13 +46,6 @@ "transform": 2 }, { - "name": "Ancestor Clipping Layer", - "position": [20, 20], - "bounds": [200, 200], - "drawsContent": false, - "transform": 2 - }, - { "name": "LayoutBlockFlow (relative positioned) DIV", "position": [20, 20], "bounds": [100, 400],
diff --git a/third_party/blink/web_tests/compositing/overflow/rotate-then-clip-expected.txt b/third_party/blink/web_tests/compositing/overflow/rotate-then-clip-expected.txt index fbb4681..101f13c 100644 --- a/third_party/blink/web_tests/compositing/overflow/rotate-then-clip-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/rotate-then-clip-expected.txt
@@ -23,13 +23,6 @@ "transform": 2 }, { - "name": "Ancestor Clipping Layer", - "position": [20, 20], - "bounds": [200, 200], - "drawsContent": false, - "transform": 2 - }, - { "name": "LayoutBlockFlow DIV", "position": [20, 20], "bounds": [400, 400],
diff --git a/third_party/blink/web_tests/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png b/third_party/blink/web_tests/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png index 0edab25..3ade606 100644 --- a/third_party/blink/web_tests/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png +++ b/third_party/blink/web_tests/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/overflow/rotate-then-clip-z-order-interleave-expected.txt b/third_party/blink/web_tests/compositing/overflow/rotate-then-clip-z-order-interleave-expected.txt index f97eb4f..c40716aa 100644 --- a/third_party/blink/web_tests/compositing/overflow/rotate-then-clip-z-order-interleave-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/rotate-then-clip-z-order-interleave-expected.txt
@@ -23,12 +23,6 @@ "transform": 2 }, { - "name": "Ancestor Clipping Layer", - "bounds": [100, 100], - "drawsContent": false, - "transform": 2 - }, - { "name": "LayoutBlockFlow (relative positioned) DIV", "bounds": [200, 100], "contentsOpaque": true, @@ -43,12 +37,6 @@ "transform": 2 }, { - "name": "Ancestor Clipping Layer", - "bounds": [100, 100], - "drawsContent": false, - "transform": 2 - }, - { "name": "LayoutBlockFlow (relative positioned) DIV", "bounds": [50, 200], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt b/third_party/blink/web_tests/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt index 15c58a53..d50ca8f2 100644 --- a/third_party/blink/web_tests/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt
@@ -28,7 +28,8 @@ { "name": "LayoutBlockFlow DIV id='scroller'", "position": [98, 90], - "bounds": [102, 102] + "bounds": [102, 102], + "backfaceVisibility": "hidden" }, { "name": "Scrolling Layer", @@ -40,7 +41,8 @@ "name": "Scrolling Contents Layer", "position": [99, 91], "bounds": [100, 180], - "drawsContent": false + "drawsContent": false, + "backfaceVisibility": "hidden" }, { "name": "LayoutBlockFlow (positioned) DIV id='fixed'", @@ -58,12 +60,14 @@ "position": [103, 95], "bounds": [60, 40], "contentsOpaque": true, + "backfaceVisibility": "hidden", "backgroundColor": "#0000FF" }, { "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV class='scrolled')", "position": [103, 139], - "bounds": [60, 128] + "bounds": [60, 128], + "backfaceVisibility": "hidden" }, { "name": "Overflow Controls Host Layer",
diff --git a/third_party/blink/web_tests/compositing/overflow/scrollbar-layer-placement-expected.txt b/third_party/blink/web_tests/compositing/overflow/scrollbar-layer-placement-expected.txt index 7be354a..b5a628c 100644 --- a/third_party/blink/web_tests/compositing/overflow/scrollbar-layer-placement-expected.txt +++ b/third_party/blink/web_tests/compositing/overflow/scrollbar-layer-placement-expected.txt
@@ -100,12 +100,6 @@ "bounds": [340, 282] }, { - "name": "Ancestor Clipping Layer", - "position": [46, 337], - "bounds": [260, 100], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV class='scroller'", "position": [37, 328], "bounds": [278, 218], @@ -131,12 +125,6 @@ "backgroundColor": "#DDDDDD" }, { - "name": "Overflow Controls Ancestor Clipping Layer", - "position": [46, 337], - "bounds": [260, 100], - "drawsContent": false - }, - { "name": "Overflow Controls Host Layer", "position": [61, 352], "bounds": [230, 170], @@ -159,18 +147,6 @@ "bounds": [292, 200] }, { - "name": "Child Containment Layer", - "position": [389, 331], - "bounds": [272, 180], - "drawsContent": false - }, - { - "name": "Ancestor Clipping Layer", - "position": [395, 337], - "bounds": [260, 100], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV class='scroller'", "position": [386, 328], "bounds": [278, 218], @@ -196,12 +172,6 @@ "backgroundColor": "#DDDDDD" }, { - "name": "Overflow Controls Ancestor Clipping Layer", - "position": [395, 337], - "bounds": [260, 100], - "drawsContent": false - }, - { "name": "Overflow Controls Host Layer", "position": [410, 352], "bounds": [230, 170],
diff --git a/third_party/blink/web_tests/compositing/overflow/siblings-composited-with-border-radius-ancestor-expected.png b/third_party/blink/web_tests/compositing/overflow/siblings-composited-with-border-radius-ancestor-expected.png index b219e48..f38a1b2 100644 --- a/third_party/blink/web_tests/compositing/overflow/siblings-composited-with-border-radius-ancestor-expected.png +++ b/third_party/blink/web_tests/compositing/overflow/siblings-composited-with-border-radius-ancestor-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped-expected.png b/third_party/blink/web_tests/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped-expected.png index ef41de3..00fa2b9 100644 --- a/third_party/blink/web_tests/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped-expected.png +++ b/third_party/blink/web_tests/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/overflow/siblings-with-border-radius-ancestor-expected.png b/third_party/blink/web_tests/compositing/overflow/siblings-with-border-radius-ancestor-expected.png index fa893ed..ff3a0270 100644 --- a/third_party/blink/web_tests/compositing/overflow/siblings-with-border-radius-ancestor-expected.png +++ b/third_party/blink/web_tests/compositing/overflow/siblings-with-border-radius-ancestor-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/overflow/tiled-mask-expected.png b/third_party/blink/web_tests/compositing/overflow/tiled-mask-expected.png index 49e4d2e8..0eac266 100644 --- a/third_party/blink/web_tests/compositing/overflow/tiled-mask-expected.png +++ b/third_party/blink/web_tests/compositing/overflow/tiled-mask-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/perpendicular-layer-sorting-expected.png b/third_party/blink/web_tests/compositing/perpendicular-layer-sorting-expected.png index fa252db..bcf9403 100644 --- a/third_party/blink/web_tests/compositing/perpendicular-layer-sorting-expected.png +++ b/third_party/blink/web_tests/compositing/perpendicular-layer-sorting-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/perspective-interest-rect-expected.png b/third_party/blink/web_tests/compositing/perspective-interest-rect-expected.png index 6beffe78..403b68b 100644 --- a/third_party/blink/web_tests/compositing/perspective-interest-rect-expected.png +++ b/third_party/blink/web_tests/compositing/perspective-interest-rect-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-absolute-expected.txt b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-absolute-expected.txt index 11a5e14..47a25e3 100644 --- a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-absolute-expected.txt +++ b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-absolute-expected.txt
@@ -27,11 +27,6 @@ "backgroundColor": "#FF0000" }, { - "name": "Child Containment Layer", - "bounds": [400, 400], - "drawsContent": false - }, - { "name": "LayoutBlockFlow (positioned) DIV class='positioned layer'", "bounds": [100, 100], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-fixed-expected.txt b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-fixed-expected.txt index 11a5e14..47a25e3 100644 --- a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-fixed-expected.txt +++ b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-fixed-expected.txt
@@ -27,11 +27,6 @@ "backgroundColor": "#FF0000" }, { - "name": "Child Containment Layer", - "bounds": [400, 400], - "drawsContent": false - }, - { "name": "LayoutBlockFlow (positioned) DIV class='positioned layer'", "bounds": [100, 100], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-relative-expected.txt b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-relative-expected.txt index 7d4fc5b..2c64a041 100644 --- a/third_party/blink/web_tests/compositing/rtl/rtl-iframe-relative-expected.txt +++ b/third_party/blink/web_tests/compositing/rtl/rtl-iframe-relative-expected.txt
@@ -26,11 +26,6 @@ "bounds": [400, 400] }, { - "name": "Child Containment Layer", - "bounds": [400, 400], - "drawsContent": false - }, - { "name": "LayoutBlockFlow (relative positioned) DIV id='layer'", "bounds": [100, 100], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/compositing/squashing/clipping-ancestor-expected.txt b/third_party/blink/web_tests/compositing/squashing/clipping-ancestor-expected.txt index 7298b1c..d296aee5 100644 --- a/third_party/blink/web_tests/compositing/squashing/clipping-ancestor-expected.txt +++ b/third_party/blink/web_tests/compositing/squashing/clipping-ancestor-expected.txt
@@ -18,12 +18,6 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Ancestor Clipping Layer", - "position": [8, 8], - "bounds": [200, 10], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV id='inner'", "bounds": [200, 10], "contentsOpaque": true, @@ -46,8 +40,7 @@ [0, 1, 0, 0], [0, 0, 1, 0], [8, 8, 0, 1] - ], - "flattenInheritedTransform": false + ] } ] }
diff --git a/third_party/blink/web_tests/compositing/squashing/no-squashing-into-fixed-position-that-clips-expected.txt b/third_party/blink/web_tests/compositing/squashing/no-squashing-into-fixed-position-that-clips-expected.txt index f13b579..f9ed6c24 100644 --- a/third_party/blink/web_tests/compositing/squashing/no-squashing-into-fixed-position-that-clips-expected.txt +++ b/third_party/blink/web_tests/compositing/squashing/no-squashing-into-fixed-position-that-clips-expected.txt
@@ -25,12 +25,6 @@ "backgroundColor": "#ADD8E6" }, { - "name": "Child Containment Layer", - "position": [0, 50], - "bounds": [800, 550], - "drawsContent": false - }, - { "name": "LayoutBlockFlow (positioned) DIV class='compositedlayer'", "bounds": [24, 100], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/compositing/visibility/layer-visible-content-expected.txt b/third_party/blink/web_tests/compositing/visibility/layer-visible-content-expected.txt index 0b05974b..cf2e1362 100644 --- a/third_party/blink/web_tests/compositing/visibility/layer-visible-content-expected.txt +++ b/third_party/blink/web_tests/compositing/visibility/layer-visible-content-expected.txt
@@ -22,11 +22,6 @@ "bounds": [200, 200] }, { - "name": "Child Containment Layer", - "bounds": [200, 200], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV class='composited box'", "bounds": [10, 10], "drawsContent": false
diff --git a/third_party/blink/web_tests/css-shadow-parts/OWNERS b/third_party/blink/web_tests/css-shadow-parts/OWNERS deleted file mode 100644 index 422c227..0000000 --- a/third_party/blink/web_tests/css-shadow-parts/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -# TEAM: dom-dev@chromium.org
diff --git a/third_party/blink/web_tests/css-shadow-parts/README.md b/third_party/blink/web_tests/css-shadow-parts/README.md deleted file mode 100644 index a72b706..0000000 --- a/third_party/blink/web_tests/css-shadow-parts/README.md +++ /dev/null
@@ -1,5 +0,0 @@ -TODO(crbug/805271): Move these tests to wpt/css/css-shadow-parts. They are -testing an implementation that differs from the draft spec, so they are chromium -only for now. - -The contents of support/ is also forked temporarily.
diff --git a/third_party/blink/web_tests/css-shadow-parts/double-forward.html b/third_party/blink/web_tests/css-shadow-parts/double-forward.html deleted file mode 100644 index c938b12..0000000 --- a/third_party/blink/web_tests/css-shadow-parts/double-forward.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>CSS Shadow Parts - Double forward</title> - <meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly"> - <link href="http://www.google.com/" rel="author" title="Google"> - <link href="https://drafts.csswg.org/css-shadow-parts/" rel="help"> - <script src="../resources/testharness.js"></script> - <script src="../resources/testharnessreport.js"></script> - <script src="support/shadow-helper.js"></script> - </head> - <body> - <style>#c-e-outer::part(part-forwarded2) { color: green; }</style> - <script>installCustomElement("custom-element-inner", "custom-element-inner-template");</script> - <template id="custom-element-inner-template"> - <style>span { color: red; }</style> - <span id="green_part" part="partp">This text</span> - </template> - <script>installCustomElement("custom-element-middle", "custom-element-middle-template");</script> - <template id="custom-element-middle-template"><custom-element-inner id="c-e-inner" exportparts="partp: part-forwarded1"></custom-element-inner></template> - <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> - <template id="custom-element-outer-template"><custom-element-middle id="c-e-middle" exportparts="part-forwarded1: part-forwarded2"></custom-element-middle></template> - The following text should be green: - <custom-element-outer id="c-e-outer"></custom-element-outer> - <script> - "use strict"; - const colorGreen = "rgb(0, 128, 0)"; - test(function() { - const el = getElementByShadowIds(document, ["c-e-outer", "c-e-middle", "c-e-inner", "green_part"]); - assert_equals(window.getComputedStyle(el).color, colorGreen); - }, "Part in inner host is forwarded through the middle host for styling by document style sheet"); - </script> - </body> -</html>
diff --git a/third_party/blink/web_tests/css-shadow-parts/invalidation-change-part-name-forward.html b/third_party/blink/web_tests/css-shadow-parts/invalidation-change-part-name-forward.html deleted file mode 100644 index 87d5952..0000000 --- a/third_party/blink/web_tests/css-shadow-parts/invalidation-change-part-name-forward.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>CSS Shadow Parts - Invalidation change part name forward</title> - <meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly"> - <link href="http://www.google.com/" rel="author" title="Google"> - <link href="https://drafts.csswg.org/css-shadow-parts/" rel="help"> - <script src="../resources/testharness.js"></script> - <script src="../resources/testharnessreport.js"></script> - <script src="support/shadow-helper.js"></script> - </head> - <body> - <style>#c-e-outer::part(part-forwarded) { color: red; }</style> - <script>installCustomElement("custom-element-inner", "custom-element-inner-template");</script> - <template id="custom-element-inner-template"> - <style>span { color: green; }</style> - <span id="part" part="partp">This text</span> - </template> - <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> - <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" exportparts="partp: part-forwarded"></custom-element-inner></template> - The following text should be green: - <custom-element-outer id="c-e-outer"></custom-element-outer> - <script> - "use strict"; - test(function() { - const part = getElementByShadowIds(document, ["c-e-outer", "c-e-inner", "part"]); - const before = window.getComputedStyle(part).color; - part.setAttribute("part", "new-partp"); - const after = window.getComputedStyle(part).color; - assert_not_equals(before, after); - }, "Part in selected host changed color"); - </script> - </body> -</html>
diff --git a/third_party/blink/web_tests/css-shadow-parts/invalidation-changep-forward.html b/third_party/blink/web_tests/css-shadow-parts/invalidation-changep-forward.html deleted file mode 100644 index 9a92abb05..0000000 --- a/third_party/blink/web_tests/css-shadow-parts/invalidation-changep-forward.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>CSS Shadow Parts - Invalidation change exportparts forward</title> - <meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly"> - <link href="http://www.google.com/" rel="author" title="Google"> - <link href="https://drafts.csswg.org/css-shadow-parts/" rel="help"> - <script src="../resources/testharness.js"></script> - <script src="../resources/testharnessreport.js"></script> - <script src="support/shadow-helper.js"></script> - </head> - <body> - <style>#c-e-outer::part(part-forwarded) { color: red; }</style> - <script>installCustomElement("custom-element-inner", "custom-element-inner-template");</script> - <template id="custom-element-inner-template"> - <style>span { color: green; }</style> - <span id="part" part="partp">This text</span> - </template> - <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> - <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" exportparts="partp: part-forwarded"></custom-element-inner></template> - The following text should be green: - <custom-element-outer id="c-e-outer"></custom-element-outer> - <script type="text/javascript"> - "use strict"; - test(function() { - var part = getElementByShadowIds(document, ["c-e-outer", "c-e-inner", "part"]); - var before = window.getComputedStyle(part).color; - getElementByShadowIds(document, ["c-e-outer", "c-e-inner"]).setAttribute("exportparts", "new-exportparts"); - var after = window.getComputedStyle(part).color; - assert_not_equals(before, after); - }, "Part in selected host changed color"); - </script> - </body> -</html>
diff --git a/third_party/blink/web_tests/css-shadow-parts/invalidation-complex-selector-forward.html b/third_party/blink/web_tests/css-shadow-parts/invalidation-complex-selector-forward.html deleted file mode 100644 index cc374239..0000000 --- a/third_party/blink/web_tests/css-shadow-parts/invalidation-complex-selector-forward.html +++ /dev/null
@@ -1,34 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>CSS Shadow Parts - Invalidation complex selector forward</title> - <meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly"> - <link href="http://www.google.com/" rel="author" title="Google"> - <link href="https://drafts.csswg.org/css-shadow-parts/" rel="help"> - <script src="../resources/testharness.js"></script> - <script src="../resources/testharnessreport.js"></script> - <script src="support/shadow-helper.js"></script> - </head> - <body> - <style>#elem #c-e-outer::part(part-forwarded) { color: red; }</style> - <script>installCustomElement("custom-element-inner", "custom-element-inner-template");</script> - <template id="custom-element-inner-template"> - <style>span { color: green; }</style> - <span id="part" part="partp">This text</span> - </template> - <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> - <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" exportparts="partp: part-forwarded"></custom-element-inner></template> - The following text should be green: - <div id="elem"><custom-element-outer id="c-e-outer"></custom-element-outer></div> - <script> - "use strict"; - test(function() { - const part = getElementByShadowIds(document, ["c-e-outer", "c-e-inner", "part"]); - const before = window.getComputedStyle(part).color; - document.getElementById("elem").setAttribute("id", "new-elem"); - const after = window.getComputedStyle(part).color; - assert_not_equals(before, after); - }, "Part in selected host changed color"); - </script> - </body> -</html>
diff --git a/third_party/blink/web_tests/css-shadow-parts/precedence-part-vs-part.html b/third_party/blink/web_tests/css-shadow-parts/precedence-part-vs-part.html deleted file mode 100644 index bb12535..0000000 --- a/third_party/blink/web_tests/css-shadow-parts/precedence-part-vs-part.html +++ /dev/null
@@ -1,35 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>CSS Shadow Parts - Precedence part vs part</title> - <meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly"> - <link href="http://www.google.com/" rel="author" title="Google"> - <link href="https://drafts.csswg.org/css-shadow-parts/" rel="help"> - <script src="../resources/testharness.js"></script> - <script src="../resources/testharnessreport.js"></script> - <script src="support/shadow-helper.js"></script> - </head> - <body> - <style>#c-e-outer::part(part-forwarded) { color: green; }</style> - <script>installCustomElement("custom-element-inner", "custom-element-inner-template");</script> - <template id="custom-element-inner-template"> - <style>span { color: blue; }</style> - <span id="green_part" part="partp">This text</span> - </template> - <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> - <template id="custom-element-outer-template"> - <style>#c-e-inner::part(partp) { color: red; }</style> - <custom-element-inner id="c-e-inner" exportparts="partp: part-forwarded"></custom-element-inner> - </template> - The following text should be green: - <custom-element-outer id="c-e-outer"></custom-element-outer> - <script> - "use strict"; - const colorGreen = "rgb(0, 128, 0)"; - test(function() { - const el = getElementByShadowIds(document, ["c-e-outer", "c-e-inner", "green_part"]); - assert_equals(window.getComputedStyle(el).color, colorGreen); - }, "Style from document overrides style from outer CE"); - </script> - </body> -</html>
diff --git a/third_party/blink/web_tests/css-shadow-parts/simple-forward-shorthand.html b/third_party/blink/web_tests/css-shadow-parts/simple-forward-shorthand.html deleted file mode 100644 index 720bdd0d..0000000 --- a/third_party/blink/web_tests/css-shadow-parts/simple-forward-shorthand.html +++ /dev/null
@@ -1,32 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>CSS Shadow Parts - Simple forward shorthand</title> - <meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly"> - <link href="http://www.google.com/" rel="author" title="Google"> - <link href="https://drafts.csswg.org/css-shadow-parts/" rel="help"> - <script src="../resources/testharness.js"></script> - <script src="../resources/testharnessreport.js"></script> - <script src="support/shadow-helper.js"></script> - </head> - <body> - <style>#c-e-outer::part(partp) { color: green; }</style> - <script>installCustomElement("custom-element-inner", "custom-element-inner-template");</script> - <template id="custom-element-inner-template"> - <style>span { color: red; }</style> - <span id="green_part" part="partp">This text</span> - </template> - <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> - <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" exportparts="partp"></custom-element-inner></template> - The following text should be green: - <custom-element-outer id="c-e-outer"></custom-element-outer> - <script> - "use strict"; - const colorGreen = "rgb(0, 128, 0)"; - test(function() { - const el = getElementByShadowIds(document, ["c-e-outer", "c-e-inner", "green_part"]); - assert_equals(window.getComputedStyle(el).color, colorGreen); - }, "Part in inner host is forwarded, under the same name, for styling by document style sheet"); - </script> - </body> -</html>
diff --git a/third_party/blink/web_tests/css-shadow-parts/simple-forward.html b/third_party/blink/web_tests/css-shadow-parts/simple-forward.html deleted file mode 100644 index a41e0728..0000000 --- a/third_party/blink/web_tests/css-shadow-parts/simple-forward.html +++ /dev/null
@@ -1,32 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>CSS Shadow Parts - Simple forward</title> - <meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly"> - <link href="http://www.google.com/" rel="author" title="Google"> - <link href="https://drafts.csswg.org/css-shadow-parts/" rel="help"> - <script src="../resources/testharness.js"></script> - <script src="../resources/testharnessreport.js"></script> - <script src="support/shadow-helper.js"></script> - </head> - <body> - <style>#c-e-outer::part(part-forwarded) { color: green; }</style> - <script>installCustomElement("custom-element-inner", "custom-element-inner-template");</script> - <template id="custom-element-inner-template"> - <style>span { color: red; }</style> - <span id="green_part" part="partp">This text</span> - </template> - <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> - <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" exportparts="partp: part-forwarded"></custom-element-inner></template> - The following text should be green: - <custom-element-outer id="c-e-outer"></custom-element-outer> - <script> - "use strict"; - const colorGreen = "rgb(0, 128, 0)"; - test(function() { - const el = getElementByShadowIds(document, ["c-e-outer", "c-e-inner", "green_part"]); - assert_equals(window.getComputedStyle(el).color, colorGreen); - }, "Part in inner host is forwarded for styling by document style sheet"); - </script> - </body> -</html>
diff --git a/third_party/blink/web_tests/css-shadow-parts/support/shadow-helper.js b/third_party/blink/web_tests/css-shadow-parts/support/shadow-helper.js deleted file mode 100644 index 10b83c1..0000000 --- a/third_party/blink/web_tests/css-shadow-parts/support/shadow-helper.js +++ /dev/null
@@ -1,29 +0,0 @@ -// Takes a root element and a list of ids of shadow host elements. Each id refers to a shadow host -// inside the previous id's shadow tree. -function getElementByShadowIds(root, ids) { - for (var i = 0; ;i++) { - var host = root.getElementById(ids[i]); - if (host == null) { - throw "No element found: i=" + i + " id=" + ids[i] + ". Root was " + root; - } - if (i == ids.length - 1) { - return host; - } - root = host.shadowRoot; - if (root == null) { - throw "No shadowRoot found: i=" + i + " id=" + ids[i] + ". Host was " + host; - } - } -} - -// Installs a mininal custom element based on this template. -function installCustomElement(element_name, template_id) { - ceClass = class extends HTMLElement { - constructor() { - super(); - var template = document.getElementById(template_id).content; - this.attachShadow({mode: 'open'}).appendChild(template.cloneNode(true)); - } - }; - window.customElements.define(element_name, ceClass); -}
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-basic-blur-expected.png b/third_party/blink/web_tests/css3/filters/backdrop-filter-basic-blur-expected.png index f6dee09b..71307d03 100644 --- a/third_party/blink/web_tests/css3/filters/backdrop-filter-basic-blur-expected.png +++ b/third_party/blink/web_tests/css3/filters/backdrop-filter-basic-blur-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-basic-blur.html b/third_party/blink/web_tests/css3/filters/backdrop-filter-basic-blur.html index 335da2b..2e3a06d 100644 --- a/third_party/blink/web_tests/css3/filters/backdrop-filter-basic-blur.html +++ b/third_party/blink/web_tests/css3/filters/backdrop-filter-basic-blur.html
@@ -33,17 +33,15 @@ } .box1 { top: -50px; - opacity: 0.5; - background: blue; + background: #0000ff7f; } .box2 { top: 150px; - opacity: 1.0; } .box3 { top: 50px; left: -100px; - opacity: 0.5; + opacity: 0.6; } </style>
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-filter-expected.html b/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-filter-expected.html index 9818d73..91129fde 100644 --- a/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-filter-expected.html +++ b/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-filter-expected.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <div class="container"> <div class="orangebox"></div> - <div class="bluebox blur-bd" style="opacity: 0.0;"></div> + <div class="bluebox blur-bd" style="background:transparent;"></div> <div class="bluebox blur"></div> </div> @@ -17,8 +17,8 @@ position:absolute; } .blur { - -webkit-filter: blur(5px); - filter: blur(5px); + -webkit-filter: blur(3px); + filter: blur(3px); } .blur-bd { backdrop-filter: blur(15px); @@ -31,7 +31,6 @@ .bluebox { left: 60px; top: 110px; - background: blue; - opacity: 0.35; + background: #0000ff33; } </style>
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-filter.html b/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-filter.html index 33f572e..602a4a3 100644 --- a/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-filter.html +++ b/third_party/blink/web_tests/css3/filters/backdrop-filter-plus-filter.html
@@ -4,6 +4,7 @@ <div class="bluebox blur blur-bd"></div> </div> + <style> div { width: 100px; @@ -16,8 +17,8 @@ position:absolute; } .blur { - -webkit-filter: blur(5px); - filter: blur(5px); + -webkit-filter: blur(3px); + filter: blur(3px); } .blur-bd { backdrop-filter: blur(15px); @@ -30,7 +31,6 @@ .bluebox { left: 60px; top: 110px; - background: blue; - opacity: 0.35; + background: #0000ff33; } </style>
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-rendering-expected.html b/third_party/blink/web_tests/css3/filters/backdrop-filter-rendering-expected.html index d501199..0ea8694 100644 --- a/third_party/blink/web_tests/css3/filters/backdrop-filter-rendering-expected.html +++ b/third_party/blink/web_tests/css3/filters/backdrop-filter-rendering-expected.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <html> <head> -<style> +<style> div { width: 100px; @@ -29,4 +29,4 @@ <div class="background_object"></div> <div class="grayscale"></div> </body> -</html> \ No newline at end of file +</html>
diff --git a/third_party/blink/web_tests/css3/filters/backdrop-filter-rendering.html b/third_party/blink/web_tests/css3/filters/backdrop-filter-rendering.html index 57e56b08..38e343b0 100644 --- a/third_party/blink/web_tests/css3/filters/backdrop-filter-rendering.html +++ b/third_party/blink/web_tests/css3/filters/backdrop-filter-rendering.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <html> <head> -<style> +<style> div { width: 100px; @@ -18,15 +18,15 @@ .grayscale_backdrop { left: 60px; top: 60px; - background: blue; - opacity: 0.0; + background: #fff0; backdrop-filter: grayscale(100%); } + </style> </head> <body> <div class="background_object"></div> <div class="grayscale_backdrop"></div> </body> -</html> \ No newline at end of file +</html>
diff --git a/third_party/blink/web_tests/custom-elements/form-validation-bubble-appearance-expected.txt b/third_party/blink/web_tests/custom-elements/form-validation-bubble-appearance-expected.txt new file mode 100644 index 0000000..d79b8697 --- /dev/null +++ b/third_party/blink/web_tests/custom-elements/form-validation-bubble-appearance-expected.txt
@@ -0,0 +1,3 @@ +Check if a validation bubble is shown + +🆖
diff --git a/third_party/blink/web_tests/custom-elements/form-validation-bubble-appearance.html b/third_party/blink/web_tests/custom-elements/form-validation-bubble-appearance.html new file mode 100644 index 0000000..0a30a1e --- /dev/null +++ b/third_party/blink/web_tests/custom-elements/form-validation-bubble-appearance.html
@@ -0,0 +1,30 @@ +<!DOCTYPE html> +<body> +<p>Check if a validation bubble is shown</p> +<script> +class MyControl extends HTMLElement { + static get formAssociated() { return true; } + + constructor() { + super(); + this.internals_ = this.attachInternals(); + } + get i() { return this.internals_; } + + // Must provide ‘value’ setter. + set value(v) {} +} + +customElements.define('my-control', MyControl); +</script> +<my-control title="Please specify four digits." tabindex=0>🆖</my-control> +<script> +if (window.testRunner) { + // Layout tree dump doesn't matter. + testRunner.dumpAsTextWithPixelResults(); +} +const myControl = document.querySelector('my-control'); +myControl.i.setValidity({patternMismatch:true}, 'The value does not match to the requested format'); +myControl.i.reportValidity(); +</script> +<body>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/measure-and-remove-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/measure-and-remove-expected.html new file mode 100644 index 0000000..4478d3b --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/measure-and-remove-expected.html
@@ -0,0 +1,11 @@ +<style> +#spacer { + width: 150px; + height: 150px; + background: green; +} +</style> + +<div id="spacer"></div> +<div id="log">0 20 40 8 8</div> +
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/measure-and-remove.html b/third_party/blink/web_tests/display-lock/lock-before-append/measure-and-remove.html new file mode 100644 index 0000000..ce482162 --- /dev/null +++ b/third_party/blink/web_tests/display-lock/lock-before-append/measure-and-remove.html
@@ -0,0 +1,76 @@ +<!doctype HTML> + +<!-- +Runs an acquireDisplayLock which constructs a subtree, and measures it in +the promise resolution. +--> + +<style> +#container { + contain: content; + width: 100px; + height: 100px; + background: lightgreen; +} +.child { + width: 20px; + height: 20%; + background: cyan; +} +#empty { + background: red; + width: max-content; +} +#spacer { + width: 150px; + height: 150px; + background: green; +} +</style> + +<div id="empty"></div> +<div id="spacer"></div> +<div id="log"></div> + +<script> +if (window.testRunner) + window.testRunner.waitUntilDone(); + +function finish() { + if (window.testRunner) + window.testRunner.notifyDone(); +} + +function measureAndRemove() { + let log = document.getElementById("log"); + log.innerHTML += "" + document.getElementById("0").offsetTop; + log.innerHTML += " " + document.getElementById("1").offsetTop; + log.innerHTML += " " + document.getElementById("2").offsetTop; + log.innerHTML += " " + document.getElementById("empty").offsetTop; + log.innerHTML += " " + document.getElementById("spacer").offsetTop; + document.getElementById("container").remove(); +} + +function createChild(id) { + let child = document.createElement("div"); + child.classList = "child"; + child.id = id; + return child; +} + +function construct(context) { + context.lockedElement.appendChild(createChild("0")); + context.lockedElement.appendChild(createChild("1")); + context.lockedElement.appendChild(createChild("2")); +} + +function acquire() { + let container = document.createElement("div"); + container.id = "container"; + container.acquireDisplayLock(construct).then(measureAndRemove).then(finish); + document.getElementById("empty").appendChild(container); +} + +window.onload = acquire; +</script> +
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json index fbc6d1e..9c24a94 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -1669,6 +1669,12 @@ {} ] ], + "css/css-overscroll-behavior/overscrollBehavior-manual.html": [ + [ + "/css/css-overscroll-behavior/overscrollBehavior-manual.html", + {} + ] + ], "css/css-scroll-snap/snap-at-user-scroll-end-manual.html": [ [ "/css/css-scroll-snap/snap-at-user-scroll-end-manual.html", @@ -3583,12 +3589,6 @@ {} ] ], - "css/cssom-view/overscrollBehavior-manual.html": [ - [ - "/css/cssom-view/overscrollBehavior-manual.html", - {} - ] - ], "css/selectors/focus-visible-001-manual.html": [ [ "/css/selectors/focus-visible-001-manual.html", @@ -55243,6 +55243,150 @@ {} ] ], + "css/css-position/static-position/htb-ltr-ltr.html": [ + [ + "/css/css-position/static-position/htb-ltr-ltr.html", + [ + [ + "/css/css-position/static-position/htb-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/static-position/htb-ltr-rtl.tentative.html": [ + [ + "/css/css-position/static-position/htb-ltr-rtl.tentative.html", + [ + [ + "/css/css-position/static-position/htb-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/static-position/htb-rtl-ltr.tentative.html": [ + [ + "/css/css-position/static-position/htb-rtl-ltr.tentative.html", + [ + [ + "/css/css-position/static-position/htb-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/static-position/htb-rtl-rtl.html": [ + [ + "/css/css-position/static-position/htb-rtl-rtl.html", + [ + [ + "/css/css-position/static-position/htb-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/static-position/vlr-ltr-ltr.html": [ + [ + "/css/css-position/static-position/vlr-ltr-ltr.html", + [ + [ + "/css/css-position/static-position/vlr-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/static-position/vlr-ltr-rtl.tentative.html": [ + [ + "/css/css-position/static-position/vlr-ltr-rtl.tentative.html", + [ + [ + "/css/css-position/static-position/vlr-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/static-position/vlr-rtl-ltr.tentative.html": [ + [ + "/css/css-position/static-position/vlr-rtl-ltr.tentative.html", + [ + [ + "/css/css-position/static-position/vlr-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/static-position/vlr-rtl-rtl.html": [ + [ + "/css/css-position/static-position/vlr-rtl-rtl.html", + [ + [ + "/css/css-position/static-position/vlr-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/static-position/vrl-ltr-ltr.html": [ + [ + "/css/css-position/static-position/vrl-ltr-ltr.html", + [ + [ + "/css/css-position/static-position/vrl-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/static-position/vrl-ltr-rtl.tentative.html": [ + [ + "/css/css-position/static-position/vrl-ltr-rtl.tentative.html", + [ + [ + "/css/css-position/static-position/vrl-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/static-position/vrl-rtl-ltr.tentative.html": [ + [ + "/css/css-position/static-position/vrl-rtl-ltr.tentative.html", + [ + [ + "/css/css-position/static-position/vrl-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-position/static-position/vrl-rtl-rtl.html": [ + [ + "/css/css-position/static-position/vrl-rtl-rtl.html", + [ + [ + "/css/css-position/static-position/vrl-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-pseudo/first-letter-001.html": [ [ "/css/css-pseudo/first-letter-001.html", @@ -89083,6 +89227,18 @@ {} ] ], + "css/filter-effects/backdrop-filter-basic-opacity-2.html": [ + [ + "/css/filter-effects/backdrop-filter-basic-opacity-2.html", + [ + [ + "/css/filter-effects/backdrop-filter-basic-opacity-2-ref.html", + "==" + ] + ], + {} + ] + ], "css/filter-effects/backdrop-filter-basic-opacity.html": [ [ "/css/filter-effects/backdrop-filter-basic-opacity.html", @@ -89124,7 +89280,7 @@ "/css/filter-effects/backdrop-filter-clip-rect.html", [ [ - "/css/filter-effects/backdrop-filter-paint-order-ref.html", + "/css/filter-effects/backdrop-filter-clip-rect-ref.html", "==" ] ], @@ -111451,6 +111607,16 @@ {} ] ], + "IndexedDB/idb-explicit-commit.any-expected.txt": [ + [ + {} + ] + ], + "IndexedDB/idb-explicit-commit.any.worker-expected.txt": [ + [ + {} + ] + ], "IndexedDB/idbobjectstore_createIndex15-autoincrement-expected.txt": [ [ {} @@ -112066,11 +112232,6 @@ {} ] ], - "WebIDL/ecmascript-binding/no-regexp-special-casing.any.worker-expected.txt": [ - [ - {} - ] - ], "WebIDL/ecmascript-binding/sequence-conversion-expected.txt": [ [ {} @@ -137146,6 +137307,21 @@ {} ] ], + "css/css-position/static-position/htb-ref.html": [ + [ + {} + ] + ], + "css/css-position/static-position/vlr-ref.html": [ + [ + {} + ] + ], + "css/css-position/static-position/vrl-ref.html": [ + [ + {} + ] + ], "css/css-properties-values-api/META.yml": [ [ {} @@ -148516,6 +148692,11 @@ {} ] ], + "css/filter-effects/backdrop-filter-basic-opacity-2-ref.html": [ + [ + {} + ] + ], "css/filter-effects/backdrop-filter-basic-opacity-ref.html": [ [ {} @@ -154966,21 +155147,6 @@ {} ] ], - "event-timing/idlharness.any.serviceworker-expected.txt": [ - [ - {} - ] - ], - "event-timing/idlharness.any.sharedworker-expected.txt": [ - [ - {} - ] - ], - "event-timing/idlharness.any.worker-expected.txt": [ - [ - {} - ] - ], "event-timing/resources/event-timing-crossiframe-childframe.html": [ [ {} @@ -170526,6 +170692,11 @@ {} ] ], + "media-source/mp4/invalid-codec.mp4": [ + [ + {} + ] + ], "media-source/mp4/test-a-128k-44100Hz-1ch-manifest.json": [ [ {} @@ -170631,6 +170802,11 @@ {} ] ], + "media-source/webm/invalid-codec.webm": [ + [ + {} + ] + ], "media-source/webm/test-a-128k-44100Hz-1ch-manifest.json": [ [ {} @@ -176981,12 +177157,12 @@ {} ] ], - "resources/chromium/mojo_layouttest_test.mojom.js": [ + "resources/chromium/mojo_web_test_helper_test.mojom.js": [ [ {} ] ], - "resources/chromium/mojo_layouttest_test.mojom.js.headers": [ + "resources/chromium/mojo_web_test_helper_test.mojom.js.headers": [ [ {} ] @@ -177271,6 +177447,11 @@ {} ] ], + "scroll-animations/resources/scrolltimeline-utils.js": [ + [ + {} + ] + ], "secure-contexts/META.yml": [ [ {} @@ -178641,6 +178822,11 @@ {} ] ], + "service-workers/service-worker/fetch-request-css-base-url.https-expected.txt": [ + [ + {} + ] + ], "service-workers/service-worker/fetch-request-xhr-sync.https-expected.txt": [ [ {} @@ -181166,6 +181352,16 @@ {} ] ], + "svg/interact/scripted/resources/blank.htm": [ + [ + {} + ] + ], + "svg/interact/scripted/tabindex-focus-flag-expected.txt": [ + [ + {} + ] + ], "svg/linking/reftests/href-a-element-ref.html": [ [ {} @@ -182846,6 +183042,11 @@ {} ] ], + "web-animations/animation-model/keyframe-effects/effect-value-context-filling-expected.txt": [ + [ + {} + ] + ], "web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation-expected.txt": [ [ {} @@ -183106,6 +183307,11 @@ {} ] ], + "web-nfc/idlharness.https.window-expected.txt": [ + [ + {} + ] + ], "web-nfc/nfc_push.https-expected.txt": [ [ {} @@ -200284,6 +200490,12 @@ {} ] ], + "content-security-policy/navigation/to-javascript-parent-initiated-parent-csp-disallow.html": [ + [ + "/content-security-policy/navigation/to-javascript-parent-initiated-parent-csp-disallow.html", + {} + ] + ], "content-security-policy/navigation/to-javascript-parent-initiated-parent-csp.html": [ [ "/content-security-policy/navigation/to-javascript-parent-initiated-parent-csp.html", @@ -244022,6 +244234,12 @@ {} ] ], + "media-source/mediasource-invalid-codec.html": [ + [ + "/media-source/mediasource-invalid-codec.html", + {} + ] + ], "media-source/mediasource-is-type-supported.html": [ [ "/media-source/mediasource-is-type-supported.html", @@ -268950,6 +269168,12 @@ {} ] ], + "scroll-animations/current-time.html": [ + [ + "/scroll-animations/current-time.html", + {} + ] + ], "scroll-animations/idlharness.window.js": [ [ "/scroll-animations/idlharness.window.html", @@ -272942,6 +273166,30 @@ {} ] ], + "svg/interact/scripted/composed.window.svg": [ + [ + "/svg/interact/scripted/composed.window.svg", + {} + ] + ], + "svg/interact/scripted/focus-events.svg": [ + [ + "/svg/interact/scripted/focus-events.svg", + {} + ] + ], + "svg/interact/scripted/focus-tabindex-default-value.svg": [ + [ + "/svg/interact/scripted/focus-tabindex-default-value.svg", + {} + ] + ], + "svg/interact/scripted/tabindex-focus-flag.svg": [ + [ + "/svg/interact/scripted/tabindex-focus-flag.svg", + {} + ] + ], "svg/painting/inheritance.svg": [ [ "/svg/painting/inheritance.svg", @@ -275580,6 +275828,12 @@ {} ] ], + "web-animations/animation-model/keyframe-effects/effect-value-context-filling.html": [ + [ + "/web-animations/animation-model/keyframe-effects/effect-value-context-filling.html", + {} + ] + ], "web-animations/animation-model/keyframe-effects/effect-value-context.html": [ [ "/web-animations/animation-model/keyframe-effects/effect-value-context.html", @@ -278652,6 +278906,14 @@ {} ] ], + "webrtc/legacy/RTCPeerConnection-addStream.https.html": [ + [ + "/webrtc/legacy/RTCPeerConnection-addStream.https.html", + { + "timeout": "long" + } + ] + ], "webrtc/legacy/RTCPeerConnection-createOffer-offerToReceive.html": [ [ "/webrtc/legacy/RTCPeerConnection-createOffer-offerToReceive.html", @@ -283115,7 +283377,9 @@ "worklets/animation-worklet-csp.https.html": [ [ "/worklets/animation-worklet-csp.https.html", - {} + { + "timeout": "long" + } ] ], "worklets/animation-worklet-import.https.html": [ @@ -283145,7 +283409,9 @@ "worklets/audio-worklet-csp.https.html": [ [ "/worklets/audio-worklet-csp.https.html", - {} + { + "timeout": "long" + } ] ], "worklets/audio-worklet-import.https.html": [ @@ -296661,10 +296927,18 @@ "3b8d148d76c1e9cd59486b4b612bfc7641023c37", "testharness" ], + "IndexedDB/idb-explicit-commit.any-expected.txt": [ + "24f8be29db0a1ffd56ec58749d7c4ccfb00b9bf7", + "support" + ], "IndexedDB/idb-explicit-commit.any.js": [ - "b2dec751b1a8f1e82fce2db965b78f26d416073e", + "da4bd8c95269d6f0630d77ba4922a8251f7c18e6", "testharness" ], + "IndexedDB/idb-explicit-commit.any.worker-expected.txt": [ + "24f8be29db0a1ffd56ec58749d7c4ccfb00b9bf7", + "support" + ], "IndexedDB/idb_binary_key_conversion.htm": [ "b55e6324b349987750816d49efb9eb908a845724", "testharness" @@ -298781,10 +299055,6 @@ "4446dbf69c02ab466ad03fd69d6ed3924d8e84a0", "testharness" ], - "WebIDL/ecmascript-binding/no-regexp-special-casing.any.worker-expected.txt": [ - "7bf939bfd151d784084d521cbb8631232d15f8f7", - "support" - ], "WebIDL/ecmascript-binding/put-forwards.html": [ "b004bd008d8ce679009e7ed339775fc253fdd6fa", "testharness" @@ -300390,7 +300660,7 @@ "testharness" ], "bluetooth/resources/bluetooth-helpers.js": [ - "9b23d650baf2a77c105f61df2d8f197812aefce0", + "c4e26077c34283cc6d442cc8bc57f799eadd5a99", "support" ], "bluetooth/resources/health-thermometer-iframe.html": [ @@ -302697,6 +302967,10 @@ "d2289257a888efe0f35e296922948bdbf5f70394", "testharness" ], + "content-security-policy/navigation/to-javascript-parent-initiated-parent-csp-disallow.html": [ + "3a0641170ea26edfd998acc9105ccc3bad8b4f98", + "testharness" + ], "content-security-policy/navigation/to-javascript-parent-initiated-parent-csp.html": [ "4cbb37ee68fb83890d5f4881c4e1a78f013eaa52", "testharness" @@ -345157,6 +345431,10 @@ "e49fa49bc4e26572a68ad947e8e82a63ee46d4e2", "testharness" ], + "css/css-overscroll-behavior/overscrollBehavior-manual.html": [ + "97f52984a51ae4157ec8ed91ddf4b3b8d405bec6", + "manual" + ], "css/css-paint-api/META.yml": [ "082a0977fa8569038eeab3e7595496256f87d725", "support" @@ -346161,6 +346439,66 @@ "969cededcbe658a8d25c0cf9cabb97d86d965a77", "support" ], + "css/css-position/static-position/htb-ltr-ltr.html": [ + "770ce7bd8a3b49291d741e85bed17d8aa0619334", + "reftest" + ], + "css/css-position/static-position/htb-ltr-rtl.tentative.html": [ + "abc8585ab24d4455a3053a75d8518bd6547d2175", + "reftest" + ], + "css/css-position/static-position/htb-ref.html": [ + "bd534b07729131a7e253c8647bf12ce8e04b7fc8", + "support" + ], + "css/css-position/static-position/htb-rtl-ltr.tentative.html": [ + "6a20341cbc6330ddc0e41436597f52d67f147ec3", + "reftest" + ], + "css/css-position/static-position/htb-rtl-rtl.html": [ + "279754ca4ea2102b8fd84b3225495f2a17816a08", + "reftest" + ], + "css/css-position/static-position/vlr-ltr-ltr.html": [ + "1d95b46a0ff039ebd37b5de429ef755029d3cb79", + "reftest" + ], + "css/css-position/static-position/vlr-ltr-rtl.tentative.html": [ + "d3faab1430442454472b0c085cd20903e406fb88", + "reftest" + ], + "css/css-position/static-position/vlr-ref.html": [ + "2dc2012f0466c4cd2fd8f3d98da3a6e52af90070", + "support" + ], + "css/css-position/static-position/vlr-rtl-ltr.tentative.html": [ + "736339ab54e55692780b78f50854b768b09feecd", + "reftest" + ], + "css/css-position/static-position/vlr-rtl-rtl.html": [ + "71f810fc7db38c10a6fe52911303592e77d5c8bd", + "reftest" + ], + "css/css-position/static-position/vrl-ltr-ltr.html": [ + "d9e613a9eade04db2b6f66cc3ff3bf749f78859f", + "reftest" + ], + "css/css-position/static-position/vrl-ltr-rtl.tentative.html": [ + "342d1cadfd1492baaea7080322ff089b025bf22e", + "reftest" + ], + "css/css-position/static-position/vrl-ref.html": [ + "31be2b52cd982bc696b0377b60461870ffcc0b58", + "support" + ], + "css/css-position/static-position/vrl-rtl-ltr.tentative.html": [ + "b0960490cfc20871ca1dce12b5c75d54c80883c3", + "reftest" + ], + "css/css-position/static-position/vrl-rtl-rtl.html": [ + "8bdb06c8271e89cfed18bae3eff5b413fc46f46f", + "reftest" + ], "css/css-properties-values-api/META.yml": [ "38cd166ca8f45769c269039577aac391ad707e75", "support" @@ -372009,10 +372347,6 @@ "772cc34f05bffc5b8445cd23ba13d9357269b84b", "reftest" ], - "css/cssom-view/overscrollBehavior-manual.html": [ - "d66317fe306d264708c3cac725d562c22034a5f6", - "manual" - ], "css/cssom-view/resources/elementsFromPoint.js": [ "ba986ef3f568d4971eb4e84c4faaeae6e276b975", "support" @@ -373010,11 +373344,19 @@ "support" ], "css/filter-effects/backdrop-filter-basic-background-color-ref.html": [ - "44dd8d44d64c1d89d09a2a35b76c86acfff87d51", + "a3dbad0b497d0ab7eaab494178fa87be78cf0d3c", "support" ], "css/filter-effects/backdrop-filter-basic-background-color.html": [ - "39febb17d2df21456b8f8ea4a42407e799a6eb2b", + "c48cadeef67a026d8b63a286da05ce864e1f4604", + "reftest" + ], + "css/filter-effects/backdrop-filter-basic-opacity-2-ref.html": [ + "1027811f261a9c8ed7f33bf9e0efc42b1706aa93", + "support" + ], + "css/filter-effects/backdrop-filter-basic-opacity-2.html": [ + "8d7df67fbedb09dd5980b7db083bca93249157eb", "reftest" ], "css/filter-effects/backdrop-filter-basic-opacity-ref.html": [ @@ -373046,15 +373388,15 @@ "support" ], "css/filter-effects/backdrop-filter-clip-rect.html": [ - "8b5d9f4e34f8f4fd04c988f99f03685c3fbf58c9", + "075b34d513c2959f5dbc40c316d7a13330cfd262", "reftest" ], "css/filter-effects/backdrop-filter-edge-pixels-ref.html": [ - "1960435775c24f7b7464e1f42cd9da15766c2b5e", + "bbd562856f7a0ee305874575935c66e8b4830c1d", "support" ], "css/filter-effects/backdrop-filter-edge-pixels.html": [ - "1e29d725ebcd8d78350ba2a2fcff50b3b239f88a", + "c26e70ce918c4a43609afd2ce61b320bbc782309", "reftest" ], "css/filter-effects/backdrop-filter-fixed-clip-ref.html": [ @@ -373066,19 +373408,19 @@ "reftest" ], "css/filter-effects/backdrop-filter-isolation-fixed.html": [ - "c812d1f67436fd91fbb3ddfc5d3f147d8f265baa", + "a3c3fa25a85077b8297feae745d2ab5cd9e24b23", "reftest" ], "css/filter-effects/backdrop-filter-isolation-isolate.html": [ - "99fa69d03fa6fac067a375a951ccb292183dc8df", + "88dd91ac8fe3c033a999315b342cbe82a482721f", "reftest" ], "css/filter-effects/backdrop-filter-isolation-ref.html": [ - "58f5a7ec1edc11d59c2ef789bf078bace7dceb71", + "470704a688f3883aee6a3fb6be21be1591007f75", "support" ], "css/filter-effects/backdrop-filter-isolation.html": [ - "e41772578e5d2ccea955bb9f65cfa77771a36027", + "500228df08162d4a946058e2252d225209a6d4e1", "reftest" ], "css/filter-effects/backdrop-filter-paint-order-ref.html": [ @@ -386130,25 +386472,13 @@ "testharness" ], "event-timing/idlharness.any-expected.txt": [ - "1167549bddda93e3bc0ee83677044b979b4d17b1", + "db34042579b00300c630d8624ed952187d15b139", "support" ], "event-timing/idlharness.any.js": [ "5ee98548fb6f2209b8c4b5346830c0d723e68170", "testharness" ], - "event-timing/idlharness.any.serviceworker-expected.txt": [ - "d4d084ce5e594430efca9427a3840ab410568375", - "support" - ], - "event-timing/idlharness.any.sharedworker-expected.txt": [ - "d4d084ce5e594430efca9427a3840ab410568375", - "support" - ], - "event-timing/idlharness.any.worker-expected.txt": [ - "d4d084ce5e594430efca9427a3840ab410568375", - "support" - ], "event-timing/resources/event-timing-crossiframe-childframe.html": [ "7491fd88cb3c8cbfa849620e3690e4a42e454b9e", "support" @@ -409842,7 +410172,7 @@ "support" ], "interfaces/event-timing.idl": [ - "0e12737bcc6e75d643abdd0e6bc44d44bcd8e6af", + "cd727beead3741c6cd2b280d180e4913991d7d1c", "support" ], "interfaces/feature-policy.idl": [ @@ -410146,7 +410476,7 @@ "support" ], "interfaces/web-nfc.idl": [ - "d54773be499366806bbd93c7fc119ff7a3a2ff72", + "3dd4817eb0dfb329720b0e6da5097bf2d28cc6b4", "support" ], "interfaces/web-share.idl": [ @@ -410186,7 +410516,7 @@ "support" ], "interfaces/webrtc.idl": [ - "9cfd687c18b7802dd814f9a447dd75bb38c1f694", + "c7529ced356dfa932c403217910d859e69773bea", "support" ], "interfaces/webusb.idl": [ @@ -410945,6 +411275,10 @@ "f92fdbc3c71eb1caeb8c49b40be29d64434687c6", "testharness" ], + "media-source/mediasource-invalid-codec.html": [ + "19aa00c4d5f4966ef8a5de657341141f69c08ea3", + "testharness" + ], "media-source/mediasource-is-type-supported.html": [ "a364693298d9f87b8c29ef1d609986e247667cca", "testharness" @@ -411041,6 +411375,10 @@ "bd202919899c5586a62790a11780649642447066", "support" ], + "media-source/mp4/invalid-codec.mp4": [ + "6fcc7c21a698ab9d9622c4a6fb6685aeafdd6f40", + "support" + ], "media-source/mp4/test-a-128k-44100Hz-1ch-manifest.json": [ "f3caa460e9f078278680c6cdb9e1ce914a8c59ae", "support" @@ -411125,6 +411463,10 @@ "1b0e7b56a6b74b4c1636c80911741cbb565d0397", "support" ], + "media-source/webm/invalid-codec.webm": [ + "f1c8bdd7abba1f6b24dc0a5d44463c3bda770d0d", + "support" + ], "media-source/webm/test-a-128k-44100Hz-1ch-manifest.json": [ "524da8149fe6d36c891501d059f85621f06cde36", "support" @@ -433329,11 +433671,11 @@ "6805c323df5a975231648b830e33ce183c3cbbd3", "support" ], - "resources/chromium/mojo_layouttest_test.mojom.js": [ - "babaeda156fc8c10afcc08c6652576e32a6741e1", + "resources/chromium/mojo_web_test_helper_test.mojom.js": [ + "cfbad086898778b920c2d750890c870e082dc60a", "support" ], - "resources/chromium/mojo_layouttest_test.mojom.js.headers": [ + "resources/chromium/mojo_web_test_helper_test.mojom.js.headers": [ "6805c323df5a975231648b830e33ce183c3cbbd3", "support" ], @@ -433442,7 +433784,7 @@ "support" ], "resources/testharness.js": [ - "2e14c30730d2efaf8fab98328f0a07d270627802", + "b08074b96bd64acdec4b0aaead9cf957aa725e85", "support" ], "resources/testharness.js.headers": [ @@ -433605,6 +433947,10 @@ "a449b32d2be4bfe9e825ff3b3637a5ddb609b93e", "testharness" ], + "scroll-animations/current-time.html": [ + "8c70594612ac758f7934d8f30818cb0150925e5e", + "testharness" + ], "scroll-animations/idlharness-expected.txt": [ "d652f6b264e3e109c69691e461d65caa3a79794a", "support" @@ -433617,6 +433963,10 @@ "90157580ce00716403346f369b1e25bba8db23c2", "testharness" ], + "scroll-animations/resources/scrolltimeline-utils.js": [ + "b0e5ead25c6ecd72bb0afcba572af46b819152aa", + "support" + ], "secure-contexts/META.yml": [ "e6537166280091c062a8894508f3f0ab9a33a8bf", "support" @@ -434894,7 +435244,7 @@ "testharness" ], "service-workers/cache-storage/window/sandboxed-iframes.https-expected.txt": [ - "dc39b9697164090239c471ee6ffe69094cad715b", + "a0a646099cfa729b63cc3bd1f56bfb4dedd94b46", "support" ], "service-workers/cache-storage/window/sandboxed-iframes.https.html": [ @@ -435381,8 +435731,12 @@ "391dc5d2c19ade20e864ab3b276be05a535d2d85", "testharness" ], + "service-workers/service-worker/fetch-request-css-base-url.https-expected.txt": [ + "d59cfa9f4200c3f24288868c82aeff42d03f71c3", + "support" + ], "service-workers/service-worker/fetch-request-css-base-url.https.html": [ - "7feccfb98c56fa29eae0c204791ec90e67e5dd5c", + "a08e0c74881364f7fd29d3e6ac332a7e1d94bf7a", "testharness" ], "service-workers/service-worker/fetch-request-css-cross-origin.https.html": [ @@ -436242,7 +436596,7 @@ "support" ], "service-workers/service-worker/resources/fetch-request-css-base-url-iframe.html": [ - "0edf2e7f9659a5ba2b204c76ec04503eacac14a7", + "504e10435642330fbeb2334855bb9d3966276469", "support" ], "service-workers/service-worker/resources/fetch-request-css-base-url-style.css": [ @@ -436250,7 +436604,7 @@ "support" ], "service-workers/service-worker/resources/fetch-request-css-base-url-worker.js": [ - "91c325998a3b8d6a6106a834903e20559e0f0055", + "e8dbd2725c68f9326c41ae5e7bde65158970a272", "support" ], "service-workers/service-worker/resources/fetch-request-css-cross-origin-mime-check-cross.css": [ @@ -439085,6 +439439,30 @@ "94836f7c0331cb8a1caebacef02a75018b2b4ddb", "testharness" ], + "svg/interact/scripted/composed.window.svg": [ + "b63dcf024439446e0624f98cfa9f7ceb01544524", + "testharness" + ], + "svg/interact/scripted/focus-events.svg": [ + "bf307b79fdf10c578d93332f57d4de2ab844eb34", + "testharness" + ], + "svg/interact/scripted/focus-tabindex-default-value.svg": [ + "3af1acffd8de01618fb1dc9e8a753bcbb0357f1c", + "testharness" + ], + "svg/interact/scripted/resources/blank.htm": [ + "18ecdcb795c33d6ab7bbb43f647947defca5634d", + "support" + ], + "svg/interact/scripted/tabindex-focus-flag-expected.txt": [ + "5ca66db46326fb522bffc84842fe0fd6adae8e5e", + "support" + ], + "svg/interact/scripted/tabindex-focus-flag.svg": [ + "29ba209b2badecaac695a678540cc53e5c4ed3f5", + "testharness" + ], "svg/linking/reftests/href-a-element-attr-change.html": [ "c74b2e015613a09d1cecb5a0c3136d26f07e2a5b", "reftest" @@ -441942,7 +442320,7 @@ "support" ], "wasm/jsapi/memory/constructor.any.js": [ - "a584a23ecf0a582b21b913a780accee38e277927", + "11e309fe654f7a46c95c96dae78da2bef1a109f1", "testharness" ], "wasm/jsapi/memory/constructor.any.worker-expected.txt": [ @@ -442357,6 +442735,14 @@ "78f46c9e4684b4d7a7144ca071451069101c8a55", "testharness" ], + "web-animations/animation-model/keyframe-effects/effect-value-context-filling-expected.txt": [ + "c0b9a11f5fddb67be4329324c72683917757b1d6", + "support" + ], + "web-animations/animation-model/keyframe-effects/effect-value-context-filling.html": [ + "fcb7f131266c47bb225aa78458ba96b043a47e41", + "testharness" + ], "web-animations/animation-model/keyframe-effects/effect-value-context.html": [ "3730a02098ad317ee5bee5018f2a672f81276c3a", "testharness" @@ -442889,6 +443275,10 @@ "2a0e82019549591b88878ca70fc6baf616d34c29", "support" ], + "web-nfc/idlharness.https.window-expected.txt": [ + "4e21915ce19da634ab0e7da170b00e8b98ca04a6", + "support" + ], "web-nfc/idlharness.https.window.js": [ "0b3b099b7721eb3b7efb336d0f3f161bbcb23588", "testharness" @@ -445194,11 +445584,11 @@ "testharness" ], "webrtc/RTCPeerConnection-track-stats.https-expected.txt": [ - "2acdf26e212450f00ce6da121ed495f1e14869b1", + "bd8e8449e00bea6b07050accc890d99e8e61d4b2", "support" ], "webrtc/RTCPeerConnection-track-stats.https.html": [ - "9ad679272b57e4d77ed4d2ceea3c1283e2e0eacd", + "30c368f670d78154fd3ca3c67d20eb67d9a052e7", "testharness" ], "webrtc/RTCPeerConnection-transceivers.https-expected.txt": [ @@ -445238,11 +445628,11 @@ "testharness" ], "webrtc/RTCRtpParameters-encodings-expected.txt": [ - "f94c1df0efc27c3c65d65a9e944305eaf561fbc2", + "155de8602419798f82f8f35e11cbd769dfc7b322", "support" ], "webrtc/RTCRtpParameters-encodings.html": [ - "b446dde230efbbdb197c7f24f16e2490271563c4", + "b8ae4e4c187ce0ccea70421a248c900aae844af6", "testharness" ], "webrtc/RTCRtpParameters-headerExtensions-expected.txt": [ @@ -445254,7 +445644,7 @@ "testharness" ], "webrtc/RTCRtpParameters-helper.js": [ - "c4105decdfcb12286d4b153ab07f7be25baf1aad", + "8f7c85df475f5a5c6cf09cfa08d0b9c45c1e7546", "support" ], "webrtc/RTCRtpParameters-rtcp-expected.txt": [ @@ -445445,6 +445835,10 @@ "8adbf6aa173949718a90bd54cc95361e1a8801ba", "support" ], + "webrtc/legacy/RTCPeerConnection-addStream.https.html": [ + "5a35ebc53b8d7ce3857d4869a476e0e99a9078c8", + "testharness" + ], "webrtc/legacy/RTCPeerConnection-createOffer-offerToReceive-expected.txt": [ "09d40c0ab084ee38a53e27b6b846c27ba4e91268", "support" @@ -445470,7 +445864,7 @@ "testharness" ], "webrtc/no-media-call.html": [ - "0f2e2a33e62b47292085c14ad36a253d800c5982", + "10933fae4c396198ade091894ea8538d1a174eaf", "testharness" ], "webrtc/promises-call.html": [ @@ -451254,7 +451648,7 @@ "testharness" ], "workers/semantics/interface-objects/001.worker-expected.txt": [ - "842154f827110f28609e0073d9aba63a4b50c97b", + "d48b057020eb94b1b0b671ff6bfcc55aae1a2752", "support" ], "workers/semantics/interface-objects/001.worker.js": [ @@ -451266,7 +451660,7 @@ "testharness" ], "workers/semantics/interface-objects/003-expected.txt": [ - "b2b1f993012a6044c3661ea694f1985f20175e99", + "e72a68ecc1b03d21f201b48630cea1a481978c8d", "support" ], "workers/semantics/interface-objects/003.html": [ @@ -451574,7 +451968,7 @@ "testharness" ], "worklets/animation-worklet-csp.https.html": [ - "a2364a4a0cfca87d6dc2faf0fc81938da341a730", + "3950ea20945a5da5b2ab8bd6addfeb9436adb41d", "testharness" ], "worklets/animation-worklet-import.https.html": [ @@ -451598,7 +451992,7 @@ "testharness" ], "worklets/audio-worklet-csp.https.html": [ - "ef148a4a098472b7a76bac9ad99fb52f964b2ace", + "76018705fa984e0c90dc3c9880380853f03209a0", "testharness" ], "worklets/audio-worklet-import.https.html": [
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/idb-explicit-commit.any-expected.txt b/third_party/blink/web_tests/external/wpt/IndexedDB/idb-explicit-commit.any-expected.txt new file mode 100644 index 0000000..24f8be2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/IndexedDB/idb-explicit-commit.any-expected.txt
@@ -0,0 +1,14 @@ +This is a testharness.js-based test. +PASS Explicitly committed data can be read back out. +PASS commit() on a version change transaction does not cause errors. +PASS A committed transaction becomes inactive immediately. +PASS A committed transaction is inactive in future request callbacks. +PASS Puts issued after commit are not fulfilled. +PASS Calling commit on an aborted transaction throws. +PASS Calling commit on a committed transaction throws. +PASS Calling abort on a committed transaction throws and does not prevent persisting the data. +PASS Calling txn.commit() when txn is inactive should throw. +PASS Transactions with same scope should stay in program order, even if one calls commit. +FAIL Transactions that explicitly commit and have errors should abort. assert_unreached: Transaction with invalid "add" call should not be completed. Reached unreachable code +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/idb-explicit-commit.any.js b/third_party/blink/web_tests/external/wpt/IndexedDB/idb-explicit-commit.any.js index b2dec75..da4bd8c 100644 --- a/third_party/blink/web_tests/external/wpt/IndexedDB/idb-explicit-commit.any.js +++ b/third_party/blink/web_tests/external/wpt/IndexedDB/idb-explicit-commit.any.js
@@ -8,8 +8,8 @@ */ promise_test(async testCase => { - const db = await createDatabase(testCase, async db => { - await createBooksStore(testCase, db); + const db = await createDatabase(testCase, db => { + createBooksStore(testCase, db); }); const txn = db.transaction(['books'], 'readwrite'); const objectStore = txn.objectStore('books'); @@ -43,7 +43,7 @@ // Upgrade the versionDB database and explicitly commit its versionchange // transaction. - db = await migrateDatabase(testCase, 2, async (db, txn) => { + db = await migrateDatabase(testCase, 2, (db, txn) => { txn.commit(); }); assert_equals(2, db.version, @@ -55,8 +55,8 @@ promise_test(async testCase => { - const db = await createDatabase(testCase, async db => { - await createBooksStore(testCase, db); + const db = await createDatabase(testCase, db => { + createBooksStore(testCase, db); }); const txn = db.transaction(['books'], 'readwrite'); const objectStore = txn.objectStore('books'); @@ -69,8 +69,8 @@ promise_test(async testCase => { - const db = await createDatabase(testCase, async db => { - await createBooksStore(testCase, db); + const db = await createDatabase(testCase, db => { + createBooksStore(testCase, db); }); const txn = db.transaction(['books'], 'readwrite'); const objectStore = txn.objectStore('books'); @@ -88,8 +88,8 @@ promise_test(async testCase => { - const db = await createDatabase(testCase, async db => { - await createBooksStore(testCase, db); + const db = await createDatabase(testCase, db => { + createBooksStore(testCase, db); }); const txn = db.transaction(['books'], 'readwrite'); const objectStore = txn.objectStore('books'); @@ -110,8 +110,8 @@ promise_test(async testCase => { - const db = await createDatabase(testCase, async db => { - await createBooksStore(testCase, db); + const db = await createDatabase(testCase, db => { + createBooksStore(testCase, db); }); const txn = db.transaction(['books'], 'readwrite'); const objectStore = txn.objectStore('books'); @@ -124,8 +124,8 @@ promise_test(async testCase => { - const db = await createDatabase(testCase, async db => { - await createBooksStore(testCase, db); + const db = await createDatabase(testCase, db => { + createBooksStore(testCase, db); }); const txn = db.transaction(['books'], 'readwrite'); const objectStore = txn.objectStore('books'); @@ -138,8 +138,8 @@ promise_test(async testCase => { - const db = await createDatabase(testCase, async db => { - await createBooksStore(testCase, db); + const db = await createDatabase(testCase, db => { + createBooksStore(testCase, db); }); const txn = db.transaction(['books'], 'readwrite'); const objectStore = txn.objectStore('books'); @@ -162,8 +162,8 @@ promise_test(async testCase => { - const db = await createDatabase(testCase, async db => { - await createBooksStore(testCase, db); + const db = await createDatabase(testCase, db => { + createBooksStore(testCase, db); }); const txn = db.transaction(['books'], 'readwrite'); const objectStore = txn.objectStore('books'); @@ -179,3 +179,79 @@ releaseTxnFunction(); db.close(); }, 'Calling txn.commit() when txn is inactive should throw.'); + + +promise_test(async testCase => { + const db = await createDatabase(testCase, db => { + createBooksStore(testCase, db); + createNotBooksStore(testCase, db); + }); + // Txn1 should commit before txn2, even though txn2 uses commit(). + const txn1 = db.transaction(['books'], 'readwrite'); + const objectStore1 = txn1.objectStore('books'); + const putRequest1 = objectStore1.put({isbn:'one', title:'title1'}); + const releaseTxnFunction = keepAlive(testCase, txn1, 'books'); + + const txn2 = db.transaction(['books'], 'readwrite'); + const objectStore2 = txn2.objectStore('books'); + const putRequest2 = objectStore2.put({isbn:'one', title:'title2'}); + txn2.commit(); + + // Exercise the IndexedDB transaction ordering by executing one with a + // different scope. + const txn3 = db.transaction(['not_books'], 'readwrite'); + const objectStore3 = txn3.objectStore('not_books'); + objectStore3.put({'title': 'not_title'}, 'key'); + txn3.oncomplete = function() { + releaseTxnFunction(); + } + await Promise.all([promiseForTransaction(testCase, txn1), + promiseForTransaction(testCase, txn2)]); + + // Read the data back to verify that txn2 executed last. + const txn4 = db.transaction(['books'], 'readonly'); + const objectStore4 = txn4.objectStore('books'); + const getRequest4 = objectStore4.get('one'); + await promiseForTransaction(testCase, txn4); + assert_equals(getRequest4.result.title, 'title2'); + db.close(); +}, 'Transactions with same scope should stay in program order, even if one ' + + 'calls commit.'); + + +promise_test(async testCase => { + const db = await createDatabase(testCase, db => { + createBooksStore(testCase, db); + }); + // Txn1 creates the book 'one' so the 'add()' below fails. + const txn1 = db.transaction(['books'], 'readwrite'); + const objectStore1 = txn1.objectStore('books'); + const putRequest1 = objectStore1.add({isbn:'one', title:'title1'}); + txn1.commit(); + await promiseForTransaction(testCase, txn1); + + // Txn2 should abort, because the 'add' call is invalid, and commit() was + // called. + const txn2 = db.transaction(['books'], 'readwrite'); + const objectStore2 = txn2.objectStore('books'); + objectStore2.put({isbn:'two', title:'title2'}); + const addRequest2 = objectStore2.add({isbn:'one', title:'title2'}); + txn2.commit(); + txn2.oncomplete = assert_unreached( + 'Transaction with invalid "add" call should not be completed.'); + + var addWatcher = requestWatcher(testCase, addRequest2); + var txnWatcher = transactionWatcher(testCase, txn2); + await Promise.all([addWatcher.wait_for('error'), + txnWatcher.wait_for('error', 'abort')]); + + // Read the data back to verify that txn2 was aborted. + const txn3 = db.transaction(['books'], 'readonly'); + const objectStore3 = txn3.objectStore('books'); + const getRequest1 = objectStore3.get('one'); + const getRequest2 = objectStore3.count('two'); + await promiseForTransaction(testCase, txn3); + assert_equals(getRequest1.result.title, 'title1'); + assert_equals(getRequest2.result, 0); + db.close(); +}, 'Transactions that explicitly commit and have errors should abort.');
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/idb-explicit-commit.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/IndexedDB/idb-explicit-commit.any.worker-expected.txt new file mode 100644 index 0000000..24f8be2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/IndexedDB/idb-explicit-commit.any.worker-expected.txt
@@ -0,0 +1,14 @@ +This is a testharness.js-based test. +PASS Explicitly committed data can be read back out. +PASS commit() on a version change transaction does not cause errors. +PASS A committed transaction becomes inactive immediately. +PASS A committed transaction is inactive in future request callbacks. +PASS Puts issued after commit are not fulfilled. +PASS Calling commit on an aborted transaction throws. +PASS Calling commit on a committed transaction throws. +PASS Calling abort on a committed transaction throws and does not prevent persisting the data. +PASS Calling txn.commit() when txn is inactive should throw. +PASS Transactions with same scope should stay in program order, even if one calls commit. +FAIL Transactions that explicitly commit and have errors should abort. assert_unreached: Transaction with invalid "add" call should not be completed. Reached unreachable code +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/WebIDL/ecmascript-binding/no-regexp-special-casing.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/WebIDL/ecmascript-binding/no-regexp-special-casing.any.worker-expected.txt deleted file mode 100644 index 7bf939b..0000000 --- a/third_party/blink/web_tests/external/wpt/WebIDL/ecmascript-binding/no-regexp-special-casing.any.worker-expected.txt +++ /dev/null
@@ -1,7 +0,0 @@ -This is a testharness.js-based test. -FAIL Conversion to a dictionary works ErrorEvent is not defined -PASS Conversion to a sequence works -PASS Can convert a RegExp to a USVString -PASS Can be used as an object implementing a callback interface -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/bluetooth/resources/bluetooth-helpers.js b/third_party/blink/web_tests/external/wpt/bluetooth/resources/bluetooth-helpers.js index 9b23d65..c4e2607 100644 --- a/third_party/blink/web_tests/external/wpt/bluetooth/resources/bluetooth-helpers.js +++ b/third_party/blink/web_tests/external/wpt/bluetooth/resources/bluetooth-helpers.js
@@ -40,7 +40,7 @@ } return loadScripts([ `${prefix}/mojo_bindings.js`, - `${prefix}/mojo_layouttest_test.mojom.js`, + `${prefix}/mojo_web_test_helper_test.mojom.js`, `${prefix}/uuid.mojom.js`, `${prefix}/fake_bluetooth.mojom.js`, `${prefix}/fake_bluetooth_chooser.mojom.js`,
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/navigation/to-javascript-parent-initiated-parent-csp-disallow.html b/third_party/blink/web_tests/external/wpt/content-security-policy/navigation/to-javascript-parent-initiated-parent-csp-disallow.html new file mode 100644 index 0000000..3a06411 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/content-security-policy/navigation/to-javascript-parent-initiated-parent-csp-disallow.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<head> +<meta http-equiv="content-security-policy" content="script-src 'self' 'nonce-abc'"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<iframe src="support/frame-with-csp.sub.html?csp=script-src%20'self'%20'unsafe-inline'"></iframe> +<script nonce='abc'> + var t = async_test("Should not have executed the javascript url"); + const iframe = document.querySelector("iframe"); + iframe.addEventListener('load', () => { + window.onmessage = t.step_func(function(e) { + if (e.data == "executed") + assert_true(false, "Javascript url executed"); + }); + window.addEventListener('securitypolicyviolation', t.step_func_done(function(e) { + assert_equals(e.blockedURI, 'inline'); + })); + iframe.contentWindow.location.href = 'javascript:parent.postMessage(\'executed\', \'*\')' + }); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/block-end-aligned-abspos-with-overflow-ref.html b/third_party/blink/web_tests/external/wpt/css/css-break/block-end-aligned-abspos-with-overflow-ref.html new file mode 100644 index 0000000..a8470b09 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/block-end-aligned-abspos-with-overflow-ref.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<style> + body { overflow:scroll; } /* Auto scrollbars may hide bugs. */ +</style> +<p>There should be a green square below, and a smaller hotpink square.</p> +<div style="float:left; width:20px; height:20px; margin-top:80px; margin-right:30px; background:hotpink;"></div> +<div style="float:left; width:50px; height:50px; background:green;"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/block-end-aligned-abspos-with-overflow.html b/third_party/blink/web_tests/external/wpt/css/css-break/block-end-aligned-abspos-with-overflow.html new file mode 100644 index 0000000..9000c63 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/block-end-aligned-abspos-with-overflow.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/css-break-3/#transforms"> +<link rel="help" href="https://www.w3.org/TR/CSS22/visudet.html#abs-non-replaced-height"> +<link rel="match" href="block-end-aligned-abspos-with-overflow-ref.html"> +<meta name="assert" content="Check that content that overflows a tall bottom-aligned abspos fragments properly"> +<style> + body { overflow:scroll; } /* Auto scrollbars may hide bugs. */ +</style> +<p>There should be a green square below, and a smaller hotpink square.</p> +<div style="columns:2; width:100px; height:100px; column-fill:auto; column-gap:0; background:white;"> + <div style="position:relative; height:100%;"> + <div style="position:absolute; width:20px; bottom:20px;"> + <div style="height:10px; background:white;"> + <div style="background:hotpink;"> + <div style="height:10px; background:white;"></div> + <div style="break-inside:avoid; width:50px; height:50px; background:green;"></div> + </div> + </div> + </div> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/block-end-aligned-abspos.html b/third_party/blink/web_tests/external/wpt/css/css-break/block-end-aligned-abspos.html new file mode 100644 index 0000000..c7acaa9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/block-end-aligned-abspos.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org"> +<link rel="help" href="https://www.w3.org/TR/css-break-3/#transforms"> +<link rel="help" href="https://www.w3.org/TR/CSS22/visudet.html#abs-non-replaced-height"> +<style> + body { overflow:scroll; } /* Auto scrollbars may hide bugs. */ + #container { columns:2; height:200px; column-fill:auto; background:white; } + #abspos { position:absolute; width:50px; bottom:0; background:blue; } + #abspos > div { height:10px; background:white; } +</style> +<p>There should be two identical blue squares below.</p> +<div id="container"> + <div style="position:relative; height:100%;"> + <div id="abspos" data-offset-y="80" data-expected-height="120"> + <div style="margin:50px 0;" data-offset-y="50"></div> + <div data-offset-y="110"></div> + </div> + </div> +</div> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/check-layout-th.js"></script> +<script> + checkLayout("[data-offset-y]"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overscroll-behavior/overscrollBehavior-manual.html b/third_party/blink/web_tests/external/wpt/css/css-overscroll-behavior/overscrollBehavior-manual.html new file mode 100644 index 0000000..97f52984 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overscroll-behavior/overscrollBehavior-manual.html
@@ -0,0 +1,158 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<link rel="help" href="https://drafts.csswg.org/css-overscroll-behavior"> + +<style> +.outer { + height: 400px; + width: 1000px; + background: white +} +.content { + height: 600px; + width: 1200px; +} +#root { + overflow: scroll; + height: 600px; + width: 800px; + background: white; +} +#container { + overflow: scroll; +} +#non_scrollable { + overflow: none; +} +#green { + background: repeating-linear-gradient(to bottom right, green 15%, white 30%); +} +#blue { + background: repeating-linear-gradient(to bottom right, blue 15%, white 30%); +} +</style> + +<div id='root'> + <div id='non_scrollable' class='outer'> + <div id='green' class='content'></div> + </div> + <div id='container' class='outer'> + <div id='blue' class='content'></div> + </div> +</div> +<input type="button" id="btnDone" value="DONE" style="width: 100px; height: 50px;"/> +<h1>overscroll-behavior</h1> +<h4>Tests that overscroll-behavior prevents scroll-propagation in the area and direction as specified.</h4> +<ol> + <li id="i1">Make two scrolls on <span style="color: blue">BLUE</span>, in this order: scroll UP (or drag down), then scroll LEFT (or drag right). Scroll (or drag) until nothing is scrolling. Then tap on DONE.</li> + <li id="i2">Repeat the same scrolls as in step 1 and then tap on DONE.</li> + <li id="i3">Repeat the same scrolls as in step 1 and then tap on DONE.</li> + <li id="i4">Make two separate scrolls on <span style="color: green">GREEN</span>, in this order: scroll UP (or drag down), then scroll LEFT (or drag right). Scroll (or drag) until nothing is scrolling. Then tap on DONE.</li> +</ol> + + +<script> +setup({explicit_timeout: true}); +const container = document.getElementById('container'); +const non_scrollable = document.getElementById('non_scrollable'); +const root = document.getElementById('root'); +var test = async_test("overscroll-behavior prevents scroll-propagation in the area and direction as specified"); +var instruction1 = document.getElementById("i1"); +var instruction2 = document.getElementById("i2"); +var instruction3 = document.getElementById("i3"); +var instruction4 = document.getElementById("i4"); + +function setUpForRoot(offset) { + root.scrollTop = offset; + root.scrollLeft = offset; +} + +function setUpForContainer(offset) { + container.scrollTop = offset; + container.scrollLeft = offset +} + +function set_boundary_prevents_y() { + instruction1.style.color = 'red'; + instruction1.style.fontWeight = 'bold'; + container.style.overscrollBehaviorX = 'auto'; + container.style.overscrollBehaviorY = 'none'; + setUpForRoot(100); + setUpForContainer(0); + window.scrollTo(0, 0); +} + +function verify_y_prevented_and_set_boundary_prevents_x() { + instruction1.style.fontWeight = 'normal'; + instruction2.style.fontWeight = 'bold'; + test.step(function() { + assert_equals(root.scrollTop, 100); + assert_equals(root.scrollLeft, 0); + window.scrollTo(0, 0); + }, "overscroll-behavior-y: none should only prevent scroll propagation on y axis."); + + container.style.overscrollBehaviorX = 'none'; + container.style.overscrollBehaviorY = 'auto'; + setUpForRoot(100); + setUpForContainer(0); + window.scrollTo(0, 0); +} + +function verify_x_prevented_and_set_boundary_allows_inner() { + instruction2.style.fontWeight = 'normal'; + instruction3.style.fontWeight = 'bold'; + test.step(function() { + assert_equals(root.scrollTop, 0); + assert_equals(root.scrollLeft, 100); + }, "overscroll-behavior-x: none should only prevent scroll propagation on x axis."); + + container.style.overscrollBehaviorX = 'none'; + container.style.overscrollBehaviorY = 'none'; + setUpForRoot(100); + setUpForContainer(100); + window.scrollTo(0, 0); +} + +function verify_inner_allowed_and_set_nonscrollable_allows_propagation() { + instruction1.style.color = 'black'; + instruction4.style.color = 'red'; + instruction3.style.fontWeight = 'normal'; + instruction4.style.fontWeight = 'bold'; + test.step(function() { + assert_equals(container.scrollTop, 0); + assert_equals(container.scrollLeft, 0); + assert_equals(root.scrollTop, 100); + assert_equals(root.scrollLeft, 100); + }, "overscroll-behavior should latch the scroll to the inner container."); + + non_scrollable.style.overscrollBehaviorX = 'none'; + non_scrollable.style.overscrollBehaviorY = 'none'; + setUpForRoot(100); + window.scrollTo(0, 0); +} + +function verify_non_scrollable_allows_propagation() { + test.step(function() { + assert_equals(root.scrollLeft, 0); + assert_equals(root.scrollTop, 0); + }, "overscroll-behavior on non-scrollable area should not affect scroll propagation."); + test.done(); +} + +var verifyAndSetupForNext = [ + set_boundary_prevents_y, + verify_y_prevented_and_set_boundary_prevents_x, + verify_x_prevented_and_set_boundary_allows_inner, + verify_inner_allowed_and_set_nonscrollable_allows_propagation, + verify_non_scrollable_allows_propagation]; + +on_event(document.getElementById("btnDone"), "click", function() { + if (current_test < verifyAndSetupForNext.length) + verifyAndSetupForNext[current_test++](); +}); + +var current_test = 0; +verifyAndSetupForNext[current_test++](); + +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/htb-ltr-ltr.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/htb-ltr-ltr.html new file mode 100644 index 0000000..770ce7b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/htb-ltr-ltr.html
@@ -0,0 +1,73 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" /> +<link rel="match" href="htb-ref.html"> +<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." /> +<style> +.container { + position: relative; + background: green; + color: green; + font: 16px/1 Ahem; + border: solid black 3px; + width: 400px; + margin: 16px 0; +} +.red { color: red; } +.cb { position: relative; } +.rtl { direction: rtl; } +.ltr { direction: ltr; } +.inline { display: inline; } +.abs { position: absolute; } + +.indent { text-indent: 20px; } +* { text-indent: initial; } +</style> + +There should be no red. +<div class="container ltr"> + XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="ltr cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="ltr cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="ltr cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="ltr cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + <span class="cb">XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr indent"> + <span class="cb">XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr"> + <span class="cb">XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr indent"> + <span class="cb">XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/htb-ltr-rtl.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/htb-ltr-rtl.tentative.html new file mode 100644 index 0000000..abc8585a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/htb-ltr-rtl.tentative.html
@@ -0,0 +1,73 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" /> +<link rel="match" href="htb-ref.html"> +<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." /> +<style> +.container { + position: relative; + background: green; + color: green; + font: 16px/1 Ahem; + border: solid black 3px; + width: 400px; + margin: 16px 0; +} +.red { color: red; } +.cb { position: relative; } +.rtl { direction: rtl; } +.ltr { direction: ltr; } +.inline { display: inline; } +.abs { position: absolute; } + +.indent { text-indent: 20px; } +* { text-indent: initial; } +</style> + +There should be no red. +<div class="container ltr"> + XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="rtl cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="rtl cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="rtl cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="rtl cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + <span class="cb">XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr indent"> + <span class="cb">XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr"> + <span class="cb">XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr indent"> + <span class="cb">XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/htb-ref.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/htb-ref.html new file mode 100644 index 0000000..bd534b07 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/htb-ref.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<style> +.container { + background: green; + height: 16px; + border: solid black 3px; + width: 400px; + margin: 16px 0; +} + +.large { height: 32px; } +</style> + +There should be no red. +<div class="container"></div> + +<div class="container"></div> + +<div class="container large"></div> + +<div class="container large"></div> + +<div class="container"></div> + +<div class="container"></div> + +<div class="container large"></div> + +<div class="container large"></div> + +<div class="container"></div> + +<div class="container"></div> + +<div class="container large"></div> + +<div class="container large"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/htb-rtl-ltr.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/htb-rtl-ltr.tentative.html new file mode 100644 index 0000000..6a20341 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/htb-rtl-ltr.tentative.html
@@ -0,0 +1,73 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" /> +<link rel="match" href="htb-ref.html"> +<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." /> +<style> +.container { + position: relative; + background: green; + color: green; + font: 16px/1 Ahem; + border: solid black 3px; + width: 400px; + margin: 16px 0; +} +.red { color: red; } +.cb { position: relative; } +.rtl { direction: rtl; } +.ltr { direction: ltr; } +.inline { display: inline; } +.abs { position: absolute; } + +.indent { text-indent: 20px; } +* { text-indent: initial; } +</style> + +There should be no red. +<div class="container rtl"> + XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="ltr cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="ltr cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="ltr cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="ltr cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + <span class="cb">XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl indent"> + <span class="cb">XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl"> + <span class="cb">XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl indent"> + <span class="cb">XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/htb-rtl-rtl.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/htb-rtl-rtl.html new file mode 100644 index 0000000..279754c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/htb-rtl-rtl.html
@@ -0,0 +1,73 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" /> +<link rel="match" href="htb-ref.html"> +<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." /> +<style> +.container { + position: relative; + background: green; + color: green; + font: 16px/1 Ahem; + border: solid black 3px; + width: 400px; + margin: 16px 0; +} +.red { color: red; } +.cb { position: relative; } +.rtl { direction: rtl; } +.ltr { direction: ltr; } +.inline { display: inline; } +.abs { position: absolute; } + +.indent { text-indent: 20px; } +* { text-indent: initial; } +</style> + +There should be no red. +<div class="container rtl"> + XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="rtl cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="rtl cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="rtl cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="rtl cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + <span class="cb">XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl indent"> + <span class="cb">XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl"> + <span class="cb">XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl indent"> + <span class="cb">XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vlr-ltr-ltr.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vlr-ltr-ltr.html new file mode 100644 index 0000000..1d95b46 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vlr-ltr-ltr.html
@@ -0,0 +1,74 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" /> +<link rel="match" href="vlr-ref.html"> +<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." /> +<style> +body { writing-mode: vertical-lr; } +.container { + position: relative; + background: green; + color: green; + font: 16px/1 Ahem; + border: solid black 3px; + height: 400px; + margin: 0 16px; +} +.red { color: red; } +.cb { position: relative; } +.rtl { direction: rtl; } +.ltr { direction: ltr; } +.inline { display: inline; } +.abs { position: absolute; } + +.indent { text-indent: 20px; } +* { text-indent: initial; } +</style> + +There should be no red. +<div class="container ltr"> + XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="ltr cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="ltr cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="ltr cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="ltr cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + <span class="cb">XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr indent"> + <span class="cb">XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr"> + <span class="cb">XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr indent"> + <span class="cb">XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vlr-ltr-rtl.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vlr-ltr-rtl.tentative.html new file mode 100644 index 0000000..d3faab14 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vlr-ltr-rtl.tentative.html
@@ -0,0 +1,74 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" /> +<link rel="match" href="vlr-ref.html"> +<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." /> +<style> +body { writing-mode: vertical-lr; } +.container { + position: relative; + background: green; + color: green; + font: 16px/1 Ahem; + border: solid black 3px; + height: 400px; + margin: 0 16px; +} +.red { color: red; } +.cb { position: relative; } +.rtl { direction: rtl; } +.ltr { direction: ltr; } +.inline { display: inline; } +.abs { position: absolute; } + +.indent { text-indent: 20px; } +* { text-indent: initial; } +</style> + +There should be no red. +<div class="container ltr"> + XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="rtl cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="rtl cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="rtl cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="rtl cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + <span class="cb">XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr indent"> + <span class="cb">XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr"> + <span class="cb">XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr indent"> + <span class="cb">XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vlr-ref.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vlr-ref.html new file mode 100644 index 0000000..2dc2012 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vlr-ref.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<style> +body { writing-mode: vertical-lr; } +.container { + background: green; + width: 16px; + border: solid black 3px; + height: 400px; + margin: 0 16px; +} + +.large { width: 32px; } +</style> + +There should be no red. +<div class="container"></div> + +<div class="container"></div> + +<div class="container large"></div> + +<div class="container large"></div> + +<div class="container"></div> + +<div class="container"></div> + +<div class="container large"></div> + +<div class="container large"></div> + +<div class="container"></div> + +<div class="container"></div> + +<div class="container large"></div> + +<div class="container large"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vlr-rtl-ltr.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vlr-rtl-ltr.tentative.html new file mode 100644 index 0000000..736339a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vlr-rtl-ltr.tentative.html
@@ -0,0 +1,74 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" /> +<link rel="match" href="vlr-ref.html"> +<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." /> +<style> +body { writing-mode: vertical-lr; } +.container { + position: relative; + background: green; + color: green; + font: 16px/1 Ahem; + border: solid black 3px; + height: 400px; + margin: 0 16px; +} +.red { color: red; } +.cb { position: relative; } +.rtl { direction: rtl; } +.ltr { direction: ltr; } +.inline { display: inline; } +.abs { position: absolute; } + +.indent { text-indent: 20px; } +* { text-indent: initial; } +</style> + +There should be no red. +<div class="container rtl"> + XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="ltr cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="ltr cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="ltr cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="ltr cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + <span class="cb">XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl indent"> + <span class="cb">XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl"> + <span class="cb">XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl indent"> + <span class="cb">XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vlr-rtl-rtl.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vlr-rtl-rtl.html new file mode 100644 index 0000000..71f810f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vlr-rtl-rtl.html
@@ -0,0 +1,74 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" /> +<link rel="match" href="vlr-ref.html"> +<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." /> +<style> +body { writing-mode: vertical-lr; } +.container { + position: relative; + background: green; + color: green; + font: 16px/1 Ahem; + border: solid black 3px; + height: 400px; + margin: 0 16px; +} +.red { color: red; } +.cb { position: relative; } +.rtl { direction: rtl; } +.ltr { direction: ltr; } +.inline { display: inline; } +.abs { position: absolute; } + +.indent { text-indent: 20px; } +* { text-indent: initial; } +</style> + +There should be no red. +<div class="container rtl"> + XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="rtl cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="rtl cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="rtl cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="rtl cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + <span class="cb">XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl indent"> + <span class="cb">XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl"> + <span class="cb">XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl indent"> + <span class="cb">XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vrl-ltr-ltr.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vrl-ltr-ltr.html new file mode 100644 index 0000000..d9e613a9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vrl-ltr-ltr.html
@@ -0,0 +1,74 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" /> +<link rel="match" href="vrl-ref.html"> +<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." /> +<style> +body { writing-mode: vertical-rl; } +.container { + position: relative; + background: green; + color: green; + font: 16px/1 Ahem; + border: solid black 3px; + height: 400px; + margin: 0 16px; +} +.red { color: red; } +.cb { position: relative; } +.rtl { direction: rtl; } +.ltr { direction: ltr; } +.inline { display: inline; } +.abs { position: absolute; } + +.indent { text-indent: 20px; } +* { text-indent: initial; } +</style> + +There should be no red. +<div class="container ltr"> + XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="ltr cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="ltr cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="ltr cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="ltr cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + <span class="cb">XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr indent"> + <span class="cb">XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr"> + <span class="cb">XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr indent"> + <span class="cb">XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vrl-ltr-rtl.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vrl-ltr-rtl.tentative.html new file mode 100644 index 0000000..342d1ca --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vrl-ltr-rtl.tentative.html
@@ -0,0 +1,74 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" /> +<link rel="match" href="vrl-ref.html"> +<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." /> +<style> +body { writing-mode: vertical-rl; } +.container { + position: relative; + background: green; + color: green; + font: 16px/1 Ahem; + border: solid black 3px; + height: 400px; + margin: 0 16px; +} +.red { color: red; } +.cb { position: relative; } +.rtl { direction: rtl; } +.ltr { direction: ltr; } +.inline { display: inline; } +.abs { position: absolute; } + +.indent { text-indent: 20px; } +* { text-indent: initial; } +</style> + +There should be no red. +<div class="container ltr"> + XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="rtl cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="rtl cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + XXX<span class="rtl cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr indent"> + XXX<span class="rtl cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container ltr"> + <span class="cb">XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr indent"> + <span class="cb">XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr"> + <span class="cb">XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div> + +<div class="container ltr indent"> + <span class="cb">XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vrl-ref.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vrl-ref.html new file mode 100644 index 0000000..31be2b5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vrl-ref.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<style> +body { writing-mode: vertical-rl; } +.container { + background: green; + width: 16px; + border: solid black 3px; + height: 400px; + margin: 0 16px; +} + +.large { width: 32px; } +</style> + +There should be no red. +<div class="container"></div> + +<div class="container"></div> + +<div class="container large"></div> + +<div class="container large"></div> + +<div class="container"></div> + +<div class="container"></div> + +<div class="container large"></div> + +<div class="container large"></div> + +<div class="container"></div> + +<div class="container"></div> + +<div class="container large"></div> + +<div class="container large"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vrl-rtl-ltr.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vrl-rtl-ltr.tentative.html new file mode 100644 index 0000000..b096049 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vrl-rtl-ltr.tentative.html
@@ -0,0 +1,74 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" /> +<link rel="match" href="vrl-ref.html"> +<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." /> +<style> +body { writing-mode: vertical-rl; } +.container { + position: relative; + background: green; + color: green; + font: 16px/1 Ahem; + border: solid black 3px; + height: 400px; + margin: 0 16px; +} +.red { color: red; } +.cb { position: relative; } +.rtl { direction: rtl; } +.ltr { direction: ltr; } +.inline { display: inline; } +.abs { position: absolute; } + +.indent { text-indent: 20px; } +* { text-indent: initial; } +</style> + +There should be no red. +<div class="container rtl"> + XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="ltr cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="ltr cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="ltr cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="ltr cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + <span class="cb">XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl indent"> + <span class="cb">XXX<span class="ltr">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl"> + <span class="cb">XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl indent"> + <span class="cb">XXX<span class="ltr">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vrl-rtl-rtl.html b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vrl-rtl-rtl.html new file mode 100644 index 0000000..8bdb06c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/static-position/vrl-rtl-rtl.html
@@ -0,0 +1,74 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width" /> +<link rel="match" href="vrl-ref.html"> +<meta name="assert" content="This test checks the static position of an out of flow absolute positioned element, under various conditions." /> +<style> +body { writing-mode: vertical-rl; } +.container { + position: relative; + background: green; + color: green; + font: 16px/1 Ahem; + border: solid black 3px; + height: 400px; + margin: 0 16px; +} +.red { color: red; } +.cb { position: relative; } +.rtl { direction: rtl; } +.ltr { direction: ltr; } +.inline { display: inline; } +.abs { position: absolute; } + +.indent { text-indent: 20px; } +* { text-indent: initial; } +</style> + +There should be no red. +<div class="container rtl"> + XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="rtl cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="rtl cb">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + XXX<span class="rtl cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl indent"> + XXX<span class="rtl cb">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span> +</div> + +<div class="container rtl"> + <span class="cb">XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl indent"> + <span class="cb">XXX<span class="rtl">XX<div class="abs inline">XXXXX</div><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl"> + <span class="cb">XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div> + +<div class="container rtl indent"> + <span class="cb">XXX<span class="rtl">XX<div class="abs block">XXXXX</div><br><span class="red">XXXXX</span></span></span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/double-forward.html b/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/double-forward.html new file mode 100644 index 0000000..d23ec775 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/double-forward.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> + <head> + <title>CSS Shadow Parts - Double forward</title> + <meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly"> + <link href="http://www.google.com/" rel="author" title="Google"> + <link href="https://drafts.csswg.org/css-shadow-parts/" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="support/shadow-helper.js"></script> + </head> + <body> + <style>#c-e-outer::part(part-forwarded2) { color: green; }</style> + <script>installCustomElement("custom-element-inner", "custom-element-inner-template");</script> + <template id="custom-element-inner-template"> + <style>span { color: red; }</style> + <span id="green_part" part="partp">This text</span> + </template> + <script>installCustomElement("custom-element-middle", "custom-element-middle-template");</script> + <template id="custom-element-middle-template"><custom-element-inner id="c-e-inner" exportparts="partp: part-forwarded1"></custom-element-inner></template> + <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> + <template id="custom-element-outer-template"><custom-element-middle id="c-e-middle" exportparts="part-forwarded1: part-forwarded2"></custom-element-middle></template> + The following text should be green: + <custom-element-outer id="c-e-outer"></custom-element-outer> + <script> + "use strict"; + const colorGreen = "rgb(0, 128, 0)"; + test(function() { + const el = getElementByShadowIds(document, ["c-e-outer", "c-e-middle", "c-e-inner", "green_part"]); + assert_equals(window.getComputedStyle(el).color, colorGreen); + }, "Part in inner host is forwarded through the middle host for styling by document style sheet"); + </script> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/invalidation-change-exportparts-forward.html b/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/invalidation-change-exportparts-forward.html new file mode 100644 index 0000000..1e319deb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/invalidation-change-exportparts-forward.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> + <head> + <title>CSS Shadow Parts - Invalidation change exportparts forward</title> + <meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly"> + <link href="http://www.google.com/" rel="author" title="Google"> + <link href="https://drafts.csswg.org/css-shadow-parts/" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="support/shadow-helper.js"></script> + </head> + <body> + <style>#c-e-outer::part(part-forwarded) { color: red; }</style> + <script>installCustomElement("custom-element-inner", "custom-element-inner-template");</script> + <template id="custom-element-inner-template"> + <style>span { color: green; }</style> + <span id="part" part="partp">This text</span> + </template> + <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> + <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" exportparts="partp: part-forwarded"></custom-element-inner></template> + The following text should be green: + <custom-element-outer id="c-e-outer"></custom-element-outer> + <script> + "use strict"; + test(function() { + const part = getElementByShadowIds(document, ["c-e-outer", "c-e-inner", "part"]); + const before = window.getComputedStyle(part).color; + getElementByShadowIds(document, ["c-e-outer", "c-e-inner"]).setAttribute("exportparts", "new-exportparts"); + const after = window.getComputedStyle(part).color; + assert_not_equals(before, after); + }, "Part in selected host changed color"); + </script> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/invalidation-change-part-name-forward.html b/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/invalidation-change-part-name-forward.html new file mode 100644 index 0000000..f8da6d1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/invalidation-change-part-name-forward.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> + <head> + <title>CSS Shadow Parts - Invalidation change part name forward</title> + <meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly"> + <link href="http://www.google.com/" rel="author" title="Google"> + <link href="https://drafts.csswg.org/css-shadow-parts/" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="support/shadow-helper.js"></script> + </head> + <body> + <style>#c-e-outer::part(part-forwarded) { color: red; }</style> + <script>installCustomElement("custom-element-inner", "custom-element-inner-template");</script> + <template id="custom-element-inner-template"> + <style>span { color: green; }</style> + <span id="part" part="partp">This text</span> + </template> + <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> + <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" exportparts="partp: part-forwarded"></custom-element-inner></template> + The following text should be green: + <custom-element-outer id="c-e-outer"></custom-element-outer> + <script> + "use strict"; + test(function() { + const part = getElementByShadowIds(document, ["c-e-outer", "c-e-inner", "part"]); + const before = window.getComputedStyle(part).color; + part.setAttribute("part", "new-partp"); + const after = window.getComputedStyle(part).color; + assert_not_equals(before, after); + }, "Part in selected host changed color"); + </script> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/invalidation-complex-selector-forward.html b/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/invalidation-complex-selector-forward.html new file mode 100644 index 0000000..7c732b9b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/invalidation-complex-selector-forward.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> + <head> + <title>CSS Shadow Parts - Invalidation complex selector forward</title> + <meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly"> + <link href="http://www.google.com/" rel="author" title="Google"> + <link href="https://drafts.csswg.org/css-shadow-parts/" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="support/shadow-helper.js"></script> + </head> + <body> + <style>#elem #c-e-outer::part(part-forwarded) { color: red; }</style> + <script>installCustomElement("custom-element-inner", "custom-element-inner-template");</script> + <template id="custom-element-inner-template"> + <style>span { color: green; }</style> + <span id="part" part="partp">This text</span> + </template> + <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> + <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" exportparts="partp: part-forwarded"></custom-element-inner></template> + The following text should be green: + <div id="elem"><custom-element-outer id="c-e-outer"></custom-element-outer></div> + <script> + "use strict"; + test(function() { + const part = getElementByShadowIds(document, ["c-e-outer", "c-e-inner", "part"]); + const before = window.getComputedStyle(part).color; + document.getElementById("elem").setAttribute("id", "new-elem"); + const after = window.getComputedStyle(part).color; + assert_not_equals(before, after); + }, "Part in selected host changed color"); + </script> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/precedence-part-vs-part.html b/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/precedence-part-vs-part.html new file mode 100644 index 0000000..9905cf8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/precedence-part-vs-part.html
@@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html> + <head> + <title>CSS Shadow Parts - Precedence part vs part</title> + <meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly"> + <link href="http://www.google.com/" rel="author" title="Google"> + <link href="https://drafts.csswg.org/css-shadow-parts/" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="support/shadow-helper.js"></script> + </head> + <body> + <style>#c-e-outer::part(part-forwarded) { color: green; }</style> + <script>installCustomElement("custom-element-inner", "custom-element-inner-template");</script> + <template id="custom-element-inner-template"> + <style>span { color: blue; }</style> + <span id="green_part" part="partp">This text</span> + </template> + <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> + <template id="custom-element-outer-template"> + <style>#c-e-inner::part(partp) { color: red; }</style> + <custom-element-inner id="c-e-inner" exportparts="partp: part-forwarded"></custom-element-inner> + </template> + The following text should be green: + <custom-element-outer id="c-e-outer"></custom-element-outer> + <script> + "use strict"; + const colorGreen = "rgb(0, 128, 0)"; + test(function() { + const el = getElementByShadowIds(document, ["c-e-outer", "c-e-inner", "green_part"]); + assert_equals(window.getComputedStyle(el).color, colorGreen); + }, "Style from document overrides style from outer CE"); + </script> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/simple-forward-shorthand.html b/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/simple-forward-shorthand.html new file mode 100644 index 0000000..0142967d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/simple-forward-shorthand.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> + <head> + <title>CSS Shadow Parts - Simple forward shorthand</title> + <meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly"> + <link href="http://www.google.com/" rel="author" title="Google"> + <link href="https://drafts.csswg.org/css-shadow-parts/" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="support/shadow-helper.js"></script> + </head> + <body> + <style>#c-e-outer::part(partp) { color: green; }</style> + <script>installCustomElement("custom-element-inner", "custom-element-inner-template");</script> + <template id="custom-element-inner-template"> + <style>span { color: red; }</style> + <span id="green_part" part="partp">This text</span> + </template> + <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> + <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" exportparts="partp"></custom-element-inner></template> + The following text should be green: + <custom-element-outer id="c-e-outer"></custom-element-outer> + <script> + "use strict"; + const colorGreen = "rgb(0, 128, 0)"; + test(function() { + const el = getElementByShadowIds(document, ["c-e-outer", "c-e-inner", "green_part"]); + assert_equals(window.getComputedStyle(el).color, colorGreen); + }, "Part in inner host is forwarded, under the same name, for styling by document style sheet"); + </script> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/simple-forward.html b/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/simple-forward.html new file mode 100644 index 0000000..a1a19ae --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-shadow-parts/simple-forward.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> + <head> + <title>CSS Shadow Parts - Simple forward</title> + <meta href="mailto:fergal@chromium.org" rel="author" title="Fergal Daly"> + <link href="http://www.google.com/" rel="author" title="Google"> + <link href="https://drafts.csswg.org/css-shadow-parts/" rel="help"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="support/shadow-helper.js"></script> + </head> + <body> + <style>#c-e-outer::part(part-forwarded) { color: green; }</style> + <script>installCustomElement("custom-element-inner", "custom-element-inner-template");</script> + <template id="custom-element-inner-template"> + <style>span { color: red; }</style> + <span id="green_part" part="partp">This text</span> + </template> + <script>installCustomElement("custom-element-outer", "custom-element-outer-template");</script> + <template id="custom-element-outer-template"><custom-element-inner id="c-e-inner" exportparts="partp: part-forwarded"></custom-element-inner></template> + The following text should be green: + <custom-element-outer id="c-e-outer"></custom-element-outer> + <script> + "use strict"; + const colorGreen = "rgb(0, 128, 0)"; + test(function() { + const el = getElementByShadowIds(document, ["c-e-outer", "c-e-inner", "green_part"]); + assert_equals(window.getComputedStyle(el).color, colorGreen); + }, "Part in inner host is forwarded for styling by document style sheet"); + </script> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom-view/overscrollBehavior-manual.html b/third_party/blink/web_tests/external/wpt/css/cssom-view/overscrollBehavior-manual.html deleted file mode 100644 index d66317f..0000000 --- a/third_party/blink/web_tests/external/wpt/css/cssom-view/overscrollBehavior-manual.html +++ /dev/null
@@ -1,157 +0,0 @@ -<!doctype html> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> - -<style> -.outer { - height: 400px; - width: 1000px; - background: white -} -.content { - height: 600px; - width: 1200px; -} -#root { - overflow: scroll; - height: 600px; - width: 800px; - background: white; -} -#container { - overflow: scroll; -} -#non_scrollable { - overflow: none; -} -#green { - background: repeating-linear-gradient(to bottom right, green 15%, white 30%); -} -#blue { - background: repeating-linear-gradient(to bottom right, blue 15%, white 30%); -} -</style> - -<div id='root'> - <div id='non_scrollable' class='outer'> - <div id='green' class='content'></div> - </div> - <div id='container' class='outer'> - <div id='blue' class='content'></div> - </div> -</div> -<input type="button" id="btnDone" value="DONE" style="width: 100px; height: 50px;"/> -<h1>overscroll-behavior</h1> -<h4>Tests that overscroll-behavior prevents scroll-propagation in the area and direction as specified.</h4> -<ol> - <li id="i1">Make two scrolls on <span style="color: blue">BLUE</span>, in this order: scroll UP (or drag down), then scroll LEFT (or drag right). Scroll (or drag) until nothing is scrolling. Then tap on DONE.</li> - <li id="i2">Repeat the same scrolls as in step 1 and then tap on DONE.</li> - <li id="i3">Repeat the same scrolls as in step 1 and then tap on DONE.</li> - <li id="i4">Make two separate scrolls on <span style="color: green">GREEN</span>, in this order: scroll UP (or drag down), then scroll LEFT (or drag right). Scroll (or drag) until nothing is scrolling. Then tap on DONE.</li> -</ol> - - -<script> -setup({explicit_timeout: true}); -const container = document.getElementById('container'); -const non_scrollable = document.getElementById('non_scrollable'); -const root = document.getElementById('root'); -var test = async_test("overscroll-behavior prevents scroll-propagation in the area and direction as specified"); -var instruction1 = document.getElementById("i1"); -var instruction2 = document.getElementById("i2"); -var instruction3 = document.getElementById("i3"); -var instruction4 = document.getElementById("i4"); - -function setUpForRoot(offset) { - root.scrollTop = offset; - root.scrollLeft = offset; -} - -function setUpForContainer(offset) { - container.scrollTop = offset; - container.scrollLeft = offset -} - -function set_boundary_prevents_y() { - instruction1.style.color = 'red'; - instruction1.style.fontWeight = 'bold'; - container.style.overscrollBehaviorX = 'auto'; - container.style.overscrollBehaviorY = 'none'; - setUpForRoot(100); - setUpForContainer(0); - window.scrollTo(0, 0); -} - -function verify_y_prevented_and_set_boundary_prevents_x() { - instruction1.style.fontWeight = 'normal'; - instruction2.style.fontWeight = 'bold'; - test.step(function() { - assert_equals(root.scrollTop, 100); - assert_equals(root.scrollLeft, 0); - window.scrollTo(0, 0); - }, "overscroll-behavior-y: none should only prevent scroll propagation on y axis."); - - container.style.overscrollBehaviorX = 'none'; - container.style.overscrollBehaviorY = 'auto'; - setUpForRoot(100); - setUpForContainer(0); - window.scrollTo(0, 0); -} - -function verify_x_prevented_and_set_boundary_allows_inner() { - instruction2.style.fontWeight = 'normal'; - instruction3.style.fontWeight = 'bold'; - test.step(function() { - assert_equals(root.scrollTop, 0); - assert_equals(root.scrollLeft, 100); - }, "overscroll-behavior-x: none should only prevent scroll propagation on x axis."); - - container.style.overscrollBehaviorX = 'none'; - container.style.overscrollBehaviorY = 'none'; - setUpForRoot(100); - setUpForContainer(100); - window.scrollTo(0, 0); -} - -function verify_inner_allowed_and_set_nonscrollable_allows_propagation() { - instruction1.style.color = 'black'; - instruction4.style.color = 'red'; - instruction3.style.fontWeight = 'normal'; - instruction4.style.fontWeight = 'bold'; - test.step(function() { - assert_equals(container.scrollTop, 0); - assert_equals(container.scrollLeft, 0); - assert_equals(root.scrollTop, 100); - assert_equals(root.scrollLeft, 100); - }, "overscroll-behavior should latch the scroll to the inner container."); - - non_scrollable.style.overscrollBehaviorX = 'none'; - non_scrollable.style.overscrollBehaviorY = 'none'; - setUpForRoot(100); - window.scrollTo(0, 0); -} - -function verify_non_scrollable_allows_propagation() { - test.step(function() { - assert_equals(root.scrollLeft, 0); - assert_equals(root.scrollTop, 0); - }, "overscroll-behavior on non-scrollable area should not affect scroll propagation."); - test.done(); -} - -var verifyAndSetupForNext = [ - set_boundary_prevents_y, - verify_y_prevented_and_set_boundary_prevents_x, - verify_x_prevented_and_set_boundary_allows_inner, - verify_inner_allowed_and_set_nonscrollable_allows_propagation, - verify_non_scrollable_allows_propagation]; - -on_event(document.getElementById("btnDone"), "click", function() { - if (current_test < verifyAndSetupForNext.length) - verifyAndSetupForNext[current_test++](); -}); - -var current_test = 0; -verifyAndSetupForNext[current_test++](); - -</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-background-color-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-background-color-ref.html index 44dd8d4..a3dbad0b 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-background-color-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-background-color-ref.html
@@ -23,7 +23,7 @@ top: 100px; } .box2outside { - background: #000080; + background: #000088; position: absolute; width: 100px; height: 100px; @@ -31,7 +31,7 @@ top: 150px; } .box2inside { - background: #8040ff; + background: #773bff; position: absolute; width: 50px; height: 50px;
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-background-color.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-background-color.html index 39febb17..c48cade 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-background-color.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-background-color.html
@@ -29,7 +29,6 @@ left: 50px; top: 50px; backdrop-filter: invert(1); - opacity: 0.5; - background: blue; + background: #00f8; } </style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-2-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-2-ref.html new file mode 100644 index 0000000..1027811f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-2-ref.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>backdrop-filter: Basic operation of filter with opacity</title> +<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> + + + +<div> + <p>Expected: Just a single grey box.</p> +</div> +<div class="colorbox"></div> + + +<style> +.colorbox { + position: absolute; + background: #808080; + width: 100px; + height: 100px; + left: 10px; + top: 100px; +} +</style> +
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-2.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-2.html new file mode 100644 index 0000000..8d7df67 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-basic-opacity-2.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>backdrop-filter: Basic operation of filter with opacity</title> +<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> +<link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> +<link rel="match" href="backdrop-filter-basic-opacity-2-ref.html"> + +<div> + <p>Expected: Just a single grey box.</p> +</div> +<div class="box colorbox"></div> +<div class="box filterbox"></div> + +<style> +.box { + position: absolute; + width: 100px; + height: 100px; + left: 10px; + top: 100px; +} +.colorbox { + background: green; +} +.filterbox { + backdrop-filter: invert(1); + opacity: 0.5; + /* An invert backdrop-filter with opacity 0.5 should always give a grey + result. It will always mix the background color with its inverse, in + equal proportion.*/ +} +</style> +
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clip-rect.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clip-rect.html index 8b5d9f4..075b34d 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clip-rect.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-clip-rect.html
@@ -3,7 +3,7 @@ <title>backdrop-filter: Clip the filter at border box of element</title> <link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org"> <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> -<link rel="match" href="backdrop-filter-paint-order-ref.html"> +<link rel="match" href="backdrop-filter-clip-rect-ref.html"> <div> <p>Expected: A green box, blurred inside the short, wide white box with a<br>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-pixels-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-pixels-ref.html index 1960435..bbd5628 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-pixels-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-pixels-ref.html
@@ -6,7 +6,7 @@ <div class="box"></div> -<div style="position:absolute;top:100px;"> +<div style="position:absolute;top:100px;will-change:transform;"> <p>Expected above: A pure white box with a blue border.<br> No dark/black should be observed within the white box.</p> </div> @@ -20,6 +20,5 @@ left: 0px; border: 1px solid blue; - } </style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-pixels.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-pixels.html index 1e29d72..c26e70c 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-pixels.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-pixels.html
@@ -6,7 +6,7 @@ <link rel="match" href="backdrop-filter-edge-pixels-ref.html"> <div class="box"></div> -<div style="position:absolute;top:100px;"> +<div style="position:absolute;top:100px;will-change:transform;"> <p>Expected above: A pure white box with a blue border.<br> No dark/black should be observed within the white box.</p> </div>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-fixed.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-fixed.html index c812d1f..a3c3fa25 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-fixed.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-fixed.html
@@ -5,28 +5,31 @@ <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-isolation-ref.html"> -<div class="outside"> - <div class="stacking-context"> - <div class="filter"> +<div> + <p>Expected: Two green boxes overlapped by a yellow box. The overlapped region<br> + of the right-hand box ONLY should be inverted (pink).</p> +</div> +<div class="box outside"> + <div class="box stacking-context"> + <div class="box filter"> </div> </div> </div> - <style> -div { +.box { position: absolute; width: 100px; height: 100px; background: green; } .outside { - top: 10px; + top: 110px; left: 10px; } .stacking-context { position: fixed; - top: 10px; + top: 110px; left: 130px; } .filter { @@ -34,9 +37,8 @@ height: 160px; top: 30px; left: -90px; - opacity: 0.3; backdrop-filter: invert(1); - background: yellow; + background: #ff08; } </style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-isolate.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-isolate.html index 99fa69d0..88dd91a 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-isolate.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-isolate.html
@@ -5,23 +5,26 @@ <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-isolation-ref.html"> -<div class="outside"> - <div class="stacking-context"> - <div class="filter"> +<div> + <p>Expected: Two green boxes overlapped by a yellow box. The overlapped region<br> + of the right-hand box ONLY should be inverted (pink).</p> +</div> +<div class="box outside"> + <div class="box stacking-context"> + <div class="box filter"> </div> </div> </div> - <style> -div { +.box { position: absolute; width: 100px; height: 100px; background: green; } .outside { - top: 10px; + top: 110px; left: 10px; } .stacking-context { @@ -34,9 +37,8 @@ height: 160px; top: 30px; left: -90px; - opacity: 0.3; backdrop-filter: invert(1); - background: yellow; + background: #ff08; } </style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-ref.html index 58f5a7e..470704a6 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation-ref.html
@@ -5,23 +5,26 @@ -<div class="outside"> - <div class="stacking-context"> - <div class="filter"> +<div> + <p>Expected: Two green boxes overlapped by a yellow box. The overlapped region<br> + of the right-hand box ONLY should be inverted (pink).</p> +</div> +<div class="box outside"> + <div class="box stacking-context"> + <div class="box filter"> </div> </div> </div> -<div style="background:#ffa5b2;width:70px;height:70px;top:40px;left:130px;"></div> - +<div class="box overlay"></div> <style> -div { +.box { position: absolute; width: 100px; height: 100px; background: green; } .outside { - top: 10px; + top: 110px; left: 10px; } .stacking-context { @@ -34,9 +37,15 @@ height: 160px; top: 30px; left: -90px; - opacity: 0.3; will-change: transform; - background: yellow; + background: #ff08; +} +.overlay { + background:#ffc377; + width:70px; + height:70px; + top:140px; + left:130px; } </style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation.html index e4177257..500228d 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation.html +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-isolation.html
@@ -5,23 +5,26 @@ <link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty"> <link rel="match" href="backdrop-filter-isolation-ref.html"> -<div class="outside"> - <div class="stacking-context"> - <div class="filter"> +<div> + <p>Expected: Two green boxes overlapped by a yellow box. The overlapped region<br> + of the right-hand box ONLY should be inverted (pink).</p> +</div> +<div class="box outside"> + <div class="box stacking-context"> + <div class="box filter"> </div> </div> </div> - <style> -div { +.box { position: absolute; width: 100px; height: 100px; background: green; } .outside { - top: 10px; + top: 110px; left: 10px; } .stacking-context { @@ -34,9 +37,8 @@ height: 160px; top: 30px; left: -90px; - opacity: 0.3; backdrop-filter: invert(1); - background: yellow; + background: #ff08; } </style>
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/idlharness.any-expected.txt b/third_party/blink/web_tests/external/wpt/event-timing/idlharness.any-expected.txt index 1167549..db34042 100644 --- a/third_party/blink/web_tests/external/wpt/event-timing/idlharness.any-expected.txt +++ b/third_party/blink/web_tests/external/wpt/event-timing/idlharness.any-expected.txt
@@ -1,6 +1,7 @@ This is a testharness.js-based test. PASS idl_test setup PASS Partial interface Performance: original interface defined +PASS Partial interface Performance: valid exposure set PASS PerformanceEventTiming interface: existence and properties of interface object PASS PerformanceEventTiming interface object length PASS PerformanceEventTiming interface object name
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/idlharness.any.serviceworker-expected.txt b/third_party/blink/web_tests/external/wpt/event-timing/idlharness.any.serviceworker-expected.txt deleted file mode 100644 index d4d084c..0000000 --- a/third_party/blink/web_tests/external/wpt/event-timing/idlharness.any.serviceworker-expected.txt +++ /dev/null
@@ -1,9 +0,0 @@ -This is a testharness.js-based test. -PASS idl_test setup -PASS Partial interface Performance: original interface defined -PASS PerformanceEventTiming interface: existence and properties of interface object -PASS EventCounts interface: existence and properties of interface object -FAIL Performance interface: attribute eventCounts assert_true: The prototype object must have a property "eventCounts" expected true got false -FAIL Performance interface: performance must inherit property "eventCounts" with the proper type assert_inherits: property "eventCounts" not found in prototype chain -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/idlharness.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/event-timing/idlharness.any.sharedworker-expected.txt deleted file mode 100644 index d4d084c..0000000 --- a/third_party/blink/web_tests/external/wpt/event-timing/idlharness.any.sharedworker-expected.txt +++ /dev/null
@@ -1,9 +0,0 @@ -This is a testharness.js-based test. -PASS idl_test setup -PASS Partial interface Performance: original interface defined -PASS PerformanceEventTiming interface: existence and properties of interface object -PASS EventCounts interface: existence and properties of interface object -FAIL Performance interface: attribute eventCounts assert_true: The prototype object must have a property "eventCounts" expected true got false -FAIL Performance interface: performance must inherit property "eventCounts" with the proper type assert_inherits: property "eventCounts" not found in prototype chain -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/event-timing/idlharness.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/event-timing/idlharness.any.worker-expected.txt deleted file mode 100644 index d4d084c..0000000 --- a/third_party/blink/web_tests/external/wpt/event-timing/idlharness.any.worker-expected.txt +++ /dev/null
@@ -1,9 +0,0 @@ -This is a testharness.js-based test. -PASS idl_test setup -PASS Partial interface Performance: original interface defined -PASS PerformanceEventTiming interface: existence and properties of interface object -PASS EventCounts interface: existence and properties of interface object -FAIL Performance interface: attribute eventCounts assert_true: The prototype object must have a property "eventCounts" expected true got false -FAIL Performance interface: performance must inherit property "eventCounts" with the proper type assert_inherits: property "eventCounts" not found in prototype chain -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/elementPosition.html.ini b/third_party/blink/web_tests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/elementPosition.html.ini index f751532..649c1709 100644 --- a/third_party/blink/web_tests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/elementPosition.html.ini +++ b/third_party/blink/web_tests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/elementPosition.html.ini
@@ -1,3 +1,3 @@ [elementPosition.html] expected: - if product == "chrome" or product == "safari": ERROR + if product == "safari": ERROR
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/event-timing.idl b/third_party/blink/web_tests/external/wpt/interfaces/event-timing.idl index 0e12737b..cd727be 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/event-timing.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/event-timing.idl
@@ -3,16 +3,19 @@ // (https://github.com/tidoust/reffy-reports) // Source: Event Timing API (https://wicg.github.io/event-timing/) +[Exposed=Window] interface PerformanceEventTiming : PerformanceEntry { readonly attribute DOMHighResTimeStamp processingStart; readonly attribute DOMHighResTimeStamp processingEnd; readonly attribute boolean cancelable; }; +[Exposed=Window] interface EventCounts { readonly maplike<DOMString, unsigned long>; }; +[Exposed=Window] partial interface Performance { - readonly attribute EventCounts eventCounts; + [SameObject] readonly attribute EventCounts eventCounts; };
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/web-nfc.idl b/third_party/blink/web_tests/external/wpt/interfaces/web-nfc.idl index d54773be..3dd4817 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/web-nfc.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/web-nfc.idl
@@ -30,9 +30,13 @@ typedef (DOMString or ArrayBuffer or NFCMessage) NFCMessageSource; +[Constructor(), SecureContext, Exposed=Window] +interface NFCWriter { + Promise<void> push(NFCMessageSource message, optional NFCPushOptions options); +}; + [SecureContext] interface NFC { - Promise<void> push(NFCMessageSource message, optional NFCPushOptions options); Promise<void> watch(MessageCallback callback, optional NFCWatchOptions options); };
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/webrtc.idl b/third_party/blink/web_tests/external/wpt/interfaces/webrtc.idl index 9cfd687c..c7529ce 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/webrtc.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/webrtc.idl
@@ -75,22 +75,22 @@ }; enum RTCPeerConnectionState { + "closed", + "failed", + "disconnected", "new", "connecting", - "connected", - "disconnected", - "failed", - "closed" + "connected" }; enum RTCIceConnectionState { + "closed", + "failed", + "disconnected", "new", "checking", - "connected", "completed", - "disconnected", - "failed", - "closed" + "connected" }; [ Constructor(optional RTCConfiguration configuration), Exposed=Window]
diff --git a/third_party/blink/web_tests/external/wpt/media-source/mediasource-invalid-codec.html b/third_party/blink/web_tests/external/wpt/media-source/mediasource-invalid-codec.html new file mode 100644 index 0000000..19aa00c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/media-source/mediasource-invalid-codec.html
@@ -0,0 +1,45 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>SourceBuffer handling of invalid codecs in the initialization segment</title> + <link rel="author" title="Alicia Boya García" href="mailto:aboya@igalia.com"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="mediasource-util.js"></script> +</head> +<body> +<div id="log"></div> +<script> + function testInvalidCodec(test, mediaElement, mediaSource, mediaType, url) { + assert_true(MediaSource.isTypeSupported(mediaType), `Media type not supported in this browser: isTypeSupported('${mediaType}')`); + + MediaSourceUtil.loadBinaryData(test, url, (mediaData) => { + _testInvalidCodecWithData(test, mediaElement, mediaSource, mediaType, mediaData); + }); + } + + function _testInvalidCodecWithData(test, mediaElement, mediaSource, mediaType, mediaData) { + const sourceBuffer = mediaSource.addSourceBuffer(mediaType); + sourceBuffer.appendBuffer(mediaData); + test.expectEvent(sourceBuffer, 'error', 'Append ended with error'); + test.waitForExpectedEvents(() => { + test.done(); + }) + } + + // These test cases provide a typical media MIME type, but the actual files have been mangled to declare a different, + // unsupported, fictitious codec (MP4 fourcc: 'zzzz', WebM codec id 'V_ZZZ'). The browser should report a parsing + // error. + + mediasource_test((test, mediaElement, mediaSource) => { + testInvalidCodec(test, mediaElement, mediaSource, 'video/mp4;codecs="avc1.4D4001"', 'mp4/invalid-codec.mp4'); + }, 'Test an MP4 with an invalid codec results in an error.'); + + mediasource_test((test, mediaElement, mediaSource) => { + testInvalidCodec(test, mediaElement, mediaSource, 'video/webm; codecs="vp8"', 'webm/invalid-codec.webm'); + }, 'Test a WebM with an invalid codec results in an error.'); + +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/media-source/mp4/invalid-codec.mp4 b/third_party/blink/web_tests/external/wpt/media-source/mp4/invalid-codec.mp4 new file mode 100644 index 0000000..6fcc7c2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/media-source/mp4/invalid-codec.mp4 Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/media-source/webm/invalid-codec.webm b/third_party/blink/web_tests/external/wpt/media-source/webm/invalid-codec.webm new file mode 100644 index 0000000..f1c8bdd7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/media-source/webm/invalid-codec.webm Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse.html b/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse.html index d2bcab9..74c7c1082 100644 --- a/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse.html +++ b/third_party/blink/web_tests/external/wpt/resource-timing/resource_connection_reuse.html
@@ -41,6 +41,10 @@ const entry = entries[1]; test_equals(entry.fetchStart, entry.connectStart, 'connectStart and fetchStart should be the same'); test_equals(entry.fetchStart, entry.connectEnd, 'connectEnd and fetchStart should be the same'); + test_equals(entry.fetchStart, entry.secureConnectionStart, 'secureConnectStart and fetchStart should be the same'); + test_equals(entry.fetchStart, entry.domainLookupStart, 'domainLookupStart and fetchStart should be the same') + test_equals(entry.fetchStart, entry.domainLookupEnd, 'domainLookupEnd and fetchStart should be the same') + } done();
diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/mojo_layouttest_test.mojom.js b/third_party/blink/web_tests/external/wpt/resources/chromium/mojo_layouttest_test.mojom.js deleted file mode 100644 index babaeda..0000000 --- a/third_party/blink/web_tests/external/wpt/resources/chromium/mojo_layouttest_test.mojom.js +++ /dev/null
@@ -1,264 +0,0 @@ -// Copyright 2014 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. - -'use strict'; - -(function() { - var mojomId = 'content/test/data/mojo_layouttest_test.mojom'; - if (mojo.internal.isMojomLoaded(mojomId)) { - console.warn('The following mojom is loaded multiple times: ' + mojomId); - return; - } - mojo.internal.markMojomLoaded(mojomId); - - // TODO(yzshen): Define these aliases to minimize the differences between the - // old/new modes. Remove them when the old mode goes away. - var bindings = mojo; - var associatedBindings = mojo; - var codec = mojo.internal; - var validator = mojo.internal; - - var exports = mojo.internal.exposeNamespace('content.mojom'); - - - - function MojoLayoutTestHelper_Reverse_Params(values) { - this.initDefaults_(); - this.initFields_(values); - } - - - MojoLayoutTestHelper_Reverse_Params.prototype.initDefaults_ = function() { - this.message = null; - }; - MojoLayoutTestHelper_Reverse_Params.prototype.initFields_ = function(fields) { - for(var field in fields) { - if (this.hasOwnProperty(field)) - this[field] = fields[field]; - } - }; - - MojoLayoutTestHelper_Reverse_Params.validate = function(messageValidator, offset) { - var err; - err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); - if (err !== validator.validationError.NONE) - return err; - - var kVersionSizes = [ - {version: 0, numBytes: 16} - ]; - err = messageValidator.validateStructVersion(offset, kVersionSizes); - if (err !== validator.validationError.NONE) - return err; - - - // validate MojoLayoutTestHelper_Reverse_Params.message - err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) - if (err !== validator.validationError.NONE) - return err; - - return validator.validationError.NONE; - }; - - MojoLayoutTestHelper_Reverse_Params.encodedSize = codec.kStructHeaderSize + 8; - - MojoLayoutTestHelper_Reverse_Params.decode = function(decoder) { - var packed; - var val = new MojoLayoutTestHelper_Reverse_Params(); - var numberOfBytes = decoder.readUint32(); - var version = decoder.readUint32(); - val.message = decoder.decodeStruct(codec.String); - return val; - }; - - MojoLayoutTestHelper_Reverse_Params.encode = function(encoder, val) { - var packed; - encoder.writeUint32(MojoLayoutTestHelper_Reverse_Params.encodedSize); - encoder.writeUint32(0); - encoder.encodeStruct(codec.String, val.message); - }; - function MojoLayoutTestHelper_Reverse_ResponseParams(values) { - this.initDefaults_(); - this.initFields_(values); - } - - - MojoLayoutTestHelper_Reverse_ResponseParams.prototype.initDefaults_ = function() { - this.reversed = null; - }; - MojoLayoutTestHelper_Reverse_ResponseParams.prototype.initFields_ = function(fields) { - for(var field in fields) { - if (this.hasOwnProperty(field)) - this[field] = fields[field]; - } - }; - - MojoLayoutTestHelper_Reverse_ResponseParams.validate = function(messageValidator, offset) { - var err; - err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); - if (err !== validator.validationError.NONE) - return err; - - var kVersionSizes = [ - {version: 0, numBytes: 16} - ]; - err = messageValidator.validateStructVersion(offset, kVersionSizes); - if (err !== validator.validationError.NONE) - return err; - - - // validate MojoLayoutTestHelper_Reverse_ResponseParams.reversed - err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) - if (err !== validator.validationError.NONE) - return err; - - return validator.validationError.NONE; - }; - - MojoLayoutTestHelper_Reverse_ResponseParams.encodedSize = codec.kStructHeaderSize + 8; - - MojoLayoutTestHelper_Reverse_ResponseParams.decode = function(decoder) { - var packed; - var val = new MojoLayoutTestHelper_Reverse_ResponseParams(); - var numberOfBytes = decoder.readUint32(); - var version = decoder.readUint32(); - val.reversed = decoder.decodeStruct(codec.String); - return val; - }; - - MojoLayoutTestHelper_Reverse_ResponseParams.encode = function(encoder, val) { - var packed; - encoder.writeUint32(MojoLayoutTestHelper_Reverse_ResponseParams.encodedSize); - encoder.writeUint32(0); - encoder.encodeStruct(codec.String, val.reversed); - }; - var kMojoLayoutTestHelper_Reverse_Name = 0; - - function MojoLayoutTestHelperPtr(handleOrPtrInfo) { - this.ptr = new bindings.InterfacePtrController(MojoLayoutTestHelper, - handleOrPtrInfo); - } - - function MojoLayoutTestHelperAssociatedPtr(associatedInterfacePtrInfo) { - this.ptr = new associatedBindings.AssociatedInterfacePtrController( - MojoLayoutTestHelper, associatedInterfacePtrInfo); - } - - MojoLayoutTestHelperAssociatedPtr.prototype = - Object.create(MojoLayoutTestHelperPtr.prototype); - MojoLayoutTestHelperAssociatedPtr.prototype.constructor = - MojoLayoutTestHelperAssociatedPtr; - - function MojoLayoutTestHelperProxy(receiver) { - this.receiver_ = receiver; - } - MojoLayoutTestHelperPtr.prototype.reverse = function() { - return MojoLayoutTestHelperProxy.prototype.reverse - .apply(this.ptr.getProxy(), arguments); - }; - - MojoLayoutTestHelperProxy.prototype.reverse = function(message) { - var params = new MojoLayoutTestHelper_Reverse_Params(); - params.message = message; - return new Promise(function(resolve, reject) { - var builder = new codec.MessageV1Builder( - kMojoLayoutTestHelper_Reverse_Name, - codec.align(MojoLayoutTestHelper_Reverse_Params.encodedSize), - codec.kMessageExpectsResponse, 0); - builder.encodeStruct(MojoLayoutTestHelper_Reverse_Params, params); - var message = builder.finish(); - this.receiver_.acceptAndExpectResponse(message).then(function(message) { - var reader = new codec.MessageReader(message); - var responseParams = - reader.decodeStruct(MojoLayoutTestHelper_Reverse_ResponseParams); - resolve(responseParams); - }).catch(function(result) { - reject(Error("Connection error: " + result)); - }); - }.bind(this)); - }; - - function MojoLayoutTestHelperStub(delegate) { - this.delegate_ = delegate; - } - MojoLayoutTestHelperStub.prototype.reverse = function(message) { - return this.delegate_ && this.delegate_.reverse && this.delegate_.reverse(message); - } - - MojoLayoutTestHelperStub.prototype.accept = function(message) { - var reader = new codec.MessageReader(message); - switch (reader.messageName) { - default: - return false; - } - }; - - MojoLayoutTestHelperStub.prototype.acceptWithResponder = - function(message, responder) { - var reader = new codec.MessageReader(message); - switch (reader.messageName) { - case kMojoLayoutTestHelper_Reverse_Name: - var params = reader.decodeStruct(MojoLayoutTestHelper_Reverse_Params); - this.reverse(params.message).then(function(response) { - var responseParams = - new MojoLayoutTestHelper_Reverse_ResponseParams(); - responseParams.reversed = response.reversed; - var builder = new codec.MessageV1Builder( - kMojoLayoutTestHelper_Reverse_Name, - codec.align(MojoLayoutTestHelper_Reverse_ResponseParams.encodedSize), - codec.kMessageIsResponse, reader.requestID); - builder.encodeStruct(MojoLayoutTestHelper_Reverse_ResponseParams, - responseParams); - var message = builder.finish(); - responder.accept(message); - }); - return true; - default: - return false; - } - }; - - function validateMojoLayoutTestHelperRequest(messageValidator) { - var message = messageValidator.message; - var paramsClass = null; - switch (message.getName()) { - case kMojoLayoutTestHelper_Reverse_Name: - if (message.expectsResponse()) - paramsClass = MojoLayoutTestHelper_Reverse_Params; - break; - } - if (paramsClass === null) - return validator.validationError.NONE; - return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); - } - - function validateMojoLayoutTestHelperResponse(messageValidator) { - var message = messageValidator.message; - var paramsClass = null; - switch (message.getName()) { - case kMojoLayoutTestHelper_Reverse_Name: - if (message.isResponse()) - paramsClass = MojoLayoutTestHelper_Reverse_ResponseParams; - break; - } - if (paramsClass === null) - return validator.validationError.NONE; - return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); - } - - var MojoLayoutTestHelper = { - name: 'content.mojom.MojoLayoutTestHelper', - kVersion: 0, - ptrClass: MojoLayoutTestHelperPtr, - proxyClass: MojoLayoutTestHelperProxy, - stubClass: MojoLayoutTestHelperStub, - validateRequest: validateMojoLayoutTestHelperRequest, - validateResponse: validateMojoLayoutTestHelperResponse, - }; - MojoLayoutTestHelperStub.prototype.validator = validateMojoLayoutTestHelperRequest; - MojoLayoutTestHelperProxy.prototype.validator = validateMojoLayoutTestHelperResponse; - exports.MojoLayoutTestHelper = MojoLayoutTestHelper; - exports.MojoLayoutTestHelperPtr = MojoLayoutTestHelperPtr; - exports.MojoLayoutTestHelperAssociatedPtr = MojoLayoutTestHelperAssociatedPtr; -})();
diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/mojo_web_test_helper_test.mojom.js b/third_party/blink/web_tests/external/wpt/resources/chromium/mojo_web_test_helper_test.mojom.js new file mode 100644 index 0000000..cfbad08 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/resources/chromium/mojo_web_test_helper_test.mojom.js
@@ -0,0 +1,264 @@ +// Copyright 2014 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. + +'use strict'; + +(function() { + var mojomId = 'content/test/data/mojo_web_test_helper_test.mojom'; + if (mojo.internal.isMojomLoaded(mojomId)) { + console.warn('The following mojom is loaded multiple times: ' + mojomId); + return; + } + mojo.internal.markMojomLoaded(mojomId); + + // TODO(yzshen): Define these aliases to minimize the differences between the + // old/new modes. Remove them when the old mode goes away. + var bindings = mojo; + var associatedBindings = mojo; + var codec = mojo.internal; + var validator = mojo.internal; + + var exports = mojo.internal.exposeNamespace('content.mojom'); + + + + function MojoWebTestHelper_Reverse_Params(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + MojoWebTestHelper_Reverse_Params.prototype.initDefaults_ = function() { + this.message = null; + }; + MojoWebTestHelper_Reverse_Params.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + MojoWebTestHelper_Reverse_Params.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 16} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + + // validate MojoWebTestHelper_Reverse_Params.message + err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) + if (err !== validator.validationError.NONE) + return err; + + return validator.validationError.NONE; + }; + + MojoWebTestHelper_Reverse_Params.encodedSize = codec.kStructHeaderSize + 8; + + MojoWebTestHelper_Reverse_Params.decode = function(decoder) { + var packed; + var val = new MojoWebTestHelper_Reverse_Params(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + val.message = decoder.decodeStruct(codec.String); + return val; + }; + + MojoWebTestHelper_Reverse_Params.encode = function(encoder, val) { + var packed; + encoder.writeUint32(MojoWebTestHelper_Reverse_Params.encodedSize); + encoder.writeUint32(0); + encoder.encodeStruct(codec.String, val.message); + }; + function MojoWebTestHelper_Reverse_ResponseParams(values) { + this.initDefaults_(); + this.initFields_(values); + } + + + MojoWebTestHelper_Reverse_ResponseParams.prototype.initDefaults_ = function() { + this.reversed = null; + }; + MojoWebTestHelper_Reverse_ResponseParams.prototype.initFields_ = function(fields) { + for(var field in fields) { + if (this.hasOwnProperty(field)) + this[field] = fields[field]; + } + }; + + MojoWebTestHelper_Reverse_ResponseParams.validate = function(messageValidator, offset) { + var err; + err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); + if (err !== validator.validationError.NONE) + return err; + + var kVersionSizes = [ + {version: 0, numBytes: 16} + ]; + err = messageValidator.validateStructVersion(offset, kVersionSizes); + if (err !== validator.validationError.NONE) + return err; + + + // validate MojoWebTestHelper_Reverse_ResponseParams.reversed + err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) + if (err !== validator.validationError.NONE) + return err; + + return validator.validationError.NONE; + }; + + MojoWebTestHelper_Reverse_ResponseParams.encodedSize = codec.kStructHeaderSize + 8; + + MojoWebTestHelper_Reverse_ResponseParams.decode = function(decoder) { + var packed; + var val = new MojoWebTestHelper_Reverse_ResponseParams(); + var numberOfBytes = decoder.readUint32(); + var version = decoder.readUint32(); + val.reversed = decoder.decodeStruct(codec.String); + return val; + }; + + MojoWebTestHelper_Reverse_ResponseParams.encode = function(encoder, val) { + var packed; + encoder.writeUint32(MojoWebTestHelper_Reverse_ResponseParams.encodedSize); + encoder.writeUint32(0); + encoder.encodeStruct(codec.String, val.reversed); + }; + var kMojoWebTestHelper_Reverse_Name = 0; + + function MojoWebTestHelperPtr(handleOrPtrInfo) { + this.ptr = new bindings.InterfacePtrController(MojoWebTestHelper, + handleOrPtrInfo); + } + + function MojoWebTestHelperAssociatedPtr(associatedInterfacePtrInfo) { + this.ptr = new associatedBindings.AssociatedInterfacePtrController( + MojoWebTestHelper, associatedInterfacePtrInfo); + } + + MojoWebTestHelperAssociatedPtr.prototype = + Object.create(MojoWebTestHelperPtr.prototype); + MojoWebTestHelperAssociatedPtr.prototype.constructor = + MojoWebTestHelperAssociatedPtr; + + function MojoWebTestHelperProxy(receiver) { + this.receiver_ = receiver; + } + MojoWebTestHelperPtr.prototype.reverse = function() { + return MojoWebTestHelperProxy.prototype.reverse + .apply(this.ptr.getProxy(), arguments); + }; + + MojoWebTestHelperProxy.prototype.reverse = function(message) { + var params = new MojoWebTestHelper_Reverse_Params(); + params.message = message; + return new Promise(function(resolve, reject) { + var builder = new codec.MessageV1Builder( + kMojoWebTestHelper_Reverse_Name, + codec.align(MojoWebTestHelper_Reverse_Params.encodedSize), + codec.kMessageExpectsResponse, 0); + builder.encodeStruct(MojoWebTestHelper_Reverse_Params, params); + var message = builder.finish(); + this.receiver_.acceptAndExpectResponse(message).then(function(message) { + var reader = new codec.MessageReader(message); + var responseParams = + reader.decodeStruct(MojoWebTestHelper_Reverse_ResponseParams); + resolve(responseParams); + }).catch(function(result) { + reject(Error("Connection error: " + result)); + }); + }.bind(this)); + }; + + function MojoWebTestHelperStub(delegate) { + this.delegate_ = delegate; + } + MojoWebTestHelperStub.prototype.reverse = function(message) { + return this.delegate_ && this.delegate_.reverse && this.delegate_.reverse(message); + } + + MojoWebTestHelperStub.prototype.accept = function(message) { + var reader = new codec.MessageReader(message); + switch (reader.messageName) { + default: + return false; + } + }; + + MojoWebTestHelperStub.prototype.acceptWithResponder = + function(message, responder) { + var reader = new codec.MessageReader(message); + switch (reader.messageName) { + case kMojoWebTestHelper_Reverse_Name: + var params = reader.decodeStruct(MojoWebTestHelper_Reverse_Params); + this.reverse(params.message).then(function(response) { + var responseParams = + new MojoWebTestHelper_Reverse_ResponseParams(); + responseParams.reversed = response.reversed; + var builder = new codec.MessageV1Builder( + kMojoWebTestHelper_Reverse_Name, + codec.align(MojoWebTestHelper_Reverse_ResponseParams.encodedSize), + codec.kMessageIsResponse, reader.requestID); + builder.encodeStruct(MojoWebTestHelper_Reverse_ResponseParams, + responseParams); + var message = builder.finish(); + responder.accept(message); + }); + return true; + default: + return false; + } + }; + + function validateMojoWebTestHelperRequest(messageValidator) { + var message = messageValidator.message; + var paramsClass = null; + switch (message.getName()) { + case kMojoWebTestHelper_Reverse_Name: + if (message.expectsResponse()) + paramsClass = MojoWebTestHelper_Reverse_Params; + break; + } + if (paramsClass === null) + return validator.validationError.NONE; + return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); + } + + function validateMojoWebTestHelperResponse(messageValidator) { + var message = messageValidator.message; + var paramsClass = null; + switch (message.getName()) { + case kMojoWebTestHelper_Reverse_Name: + if (message.isResponse()) + paramsClass = MojoWebTestHelper_Reverse_ResponseParams; + break; + } + if (paramsClass === null) + return validator.validationError.NONE; + return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); + } + + var MojoWebTestHelper = { + name: 'content.mojom.MojoWebTestHelper', + kVersion: 0, + ptrClass: MojoWebTestHelperPtr, + proxyClass: MojoWebTestHelperProxy, + stubClass: MojoWebTestHelperStub, + validateRequest: validateMojoWebTestHelperRequest, + validateResponse: validateMojoWebTestHelperResponse, + }; + MojoWebTestHelperStub.prototype.validator = validateMojoWebTestHelperRequest; + MojoWebTestHelperProxy.prototype.validator = validateMojoWebTestHelperResponse; + exports.MojoWebTestHelper = MojoWebTestHelper; + exports.MojoWebTestHelperPtr = MojoWebTestHelperPtr; + exports.MojoWebTestHelperAssociatedPtr = MojoWebTestHelperAssociatedPtr; +})();
diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/mojo_layouttest_test.mojom.js.headers b/third_party/blink/web_tests/external/wpt/resources/chromium/mojo_web_test_helper_test.mojom.js.headers similarity index 100% rename from third_party/blink/web_tests/external/wpt/resources/chromium/mojo_layouttest_test.mojom.js.headers rename to third_party/blink/web_tests/external/wpt/resources/chromium/mojo_web_test_helper_test.mojom.js.headers
diff --git a/third_party/blink/web_tests/external/wpt/resources/testharness.js b/third_party/blink/web_tests/external/wpt/resources/testharness.js index 2e14c30..b08074b9 100644 --- a/third_party/blink/web_tests/external/wpt/resources/testharness.js +++ b/third_party/blink/web_tests/external/wpt/resources/testharness.js
@@ -1486,11 +1486,9 @@ this.index = null; this.properties = properties; - var timeout = properties.timeout ? properties.timeout : settings.test_timeout; - if (timeout !== null) { - this.timeout_length = timeout * tests.timeout_multiplier; - } else { - this.timeout_length = null; + this.timeout_length = settings.test_timeout; + if (this.timeout_length !== null) { + this.timeout_length *= tests.timeout_multiplier; } this.message = null;
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/current-time-writing-modes.html b/third_party/blink/web_tests/external/wpt/scroll-animations/current-time-writing-modes.html new file mode 100644 index 0000000..a7e5551 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/current-time-writing-modes.html
@@ -0,0 +1,350 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>ScrollTimeline current time algorithm - interaction with writing modes</title> +<link rel="help" href="https://wicg.github.io/scroll-animations/#current-time-algorithm"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script src="./resources/scrolltimeline-utils.js"></script> + +<body></body> + +<script> +'use strict'; + +test(function() { + const scrollerOverrides = new Map([['direction', 'rtl']]); + const scroller = setupScrollTimelineTest(scrollerOverrides); + + // Set the timeRange such that currentTime maps directly to the value + // scrolled. The contents and scroller are square, so it suffices to compute + // one edge and use it for all the timelines. + const scrollerSize = scroller.scrollHeight - scroller.clientHeight; + + const blockScrollTimeline = new ScrollTimeline( + {scrollSource: scroller, timeRange: scrollerSize, orientation: 'block'}); + const inlineScrollTimeline = new ScrollTimeline( + {scrollSource: scroller, timeRange: scrollerSize, orientation: 'inline'}); + const horizontalScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'horizontal' + }); + const verticalScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'vertical' + }); + + // Unscrolled, all timelines should read a current time of 0 even though the + // X-axis will have started at the right hand side for rtl. + assert_equals( + blockScrollTimeline.currentTime, 0, 'Unscrolled block timeline'); + assert_equals( + inlineScrollTimeline.currentTime, 0, 'Unscrolled inline timeline'); + assert_equals( + horizontalScrollTimeline.currentTime, 0, + 'Unscrolled horizontal timeline'); + assert_equals( + verticalScrollTimeline.currentTime, 0, 'Unscrolled vertical timeline'); + + // The offset in the inline/horizontal direction should be inverted. The + // block/vertical direction should be unaffected. + scroller.scrollTop = 50; + scroller.scrollLeft = 75; + + assert_equals(blockScrollTimeline.currentTime, 50, 'Scrolled block timeline'); + assert_equals( + inlineScrollTimeline.currentTime, scrollerSize - 75, + 'Scrolled inline timeline'); + assert_equals( + horizontalScrollTimeline.currentTime, scrollerSize - 75, + 'Scrolled horizontal timeline'); + assert_equals( + verticalScrollTimeline.currentTime, 50, 'Scrolled vertical timeline'); +}, 'currentTime handles direction: rtl correctly'); + +test(function() { + const scrollerOverrides = new Map([['writing-mode', 'vertical-rl']]); + const scroller = setupScrollTimelineTest(scrollerOverrides); + + // Set the timeRange such that currentTime maps directly to the value + // scrolled. The contents and scroller are square, so it suffices to compute + // one edge and use it for all the timelines. + const scrollerSize = scroller.scrollHeight - scroller.clientHeight; + + const blockScrollTimeline = new ScrollTimeline( + {scrollSource: scroller, timeRange: scrollerSize, orientation: 'block'}); + const inlineScrollTimeline = new ScrollTimeline( + {scrollSource: scroller, timeRange: scrollerSize, orientation: 'inline'}); + const horizontalScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'horizontal' + }); + const verticalScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'vertical' + }); + + // Unscrolled, all timelines should read a current time of 0 even though the + // X-axis will have started at the right hand side for vertical-rl. + assert_equals( + blockScrollTimeline.currentTime, 0, 'Unscrolled block timeline'); + assert_equals( + inlineScrollTimeline.currentTime, 0, 'Unscrolled inline timeline'); + assert_equals( + horizontalScrollTimeline.currentTime, 0, + 'Unscrolled horizontal timeline'); + assert_equals( + verticalScrollTimeline.currentTime, 0, 'Unscrolled vertical timeline'); + + // For vertical-rl, the X-axis starts on the right-hand-side and is the block + // axis. The Y-axis is normal but is the inline axis. For the + // horizontal/vertical cases, horizontal starts on the right-hand-side and + // vertical is normal. + scroller.scrollTop = 50; + scroller.scrollLeft = 75; + + assert_equals( + blockScrollTimeline.currentTime, scrollerSize - 75, + 'Scrolled block timeline'); + assert_equals( + inlineScrollTimeline.currentTime, 50, 'SCrolled inline timeline'); + assert_equals( + horizontalScrollTimeline.currentTime, scrollerSize - 75, + 'Scrolled horizontal timeline'); + assert_equals( + verticalScrollTimeline.currentTime, 50, 'Scrolled vertical timeline'); +}, 'currentTime handles writing-mode: vertical-rl correctly'); + +test(function() { + const scrollerOverrides = new Map([['writing-mode', 'vertical-lr']]); + const scroller = setupScrollTimelineTest(scrollerOverrides); + + // Set the timeRange such that currentTime maps directly to the value + // scrolled. The contents and scroller are square, so it suffices to compute + // one edge and use it for all the timelines. + const scrollerSize = scroller.scrollHeight - scroller.clientHeight; + + const blockScrollTimeline = new ScrollTimeline( + {scrollSource: scroller, timeRange: scrollerSize, orientation: 'block'}); + const inlineScrollTimeline = new ScrollTimeline( + {scrollSource: scroller, timeRange: scrollerSize, orientation: 'inline'}); + const horizontalScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'horizontal' + }); + const verticalScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'vertical' + }); + + // Unscrolled, all timelines should read a current time of 0. + assert_equals( + blockScrollTimeline.currentTime, 0, 'Unscrolled block timeline'); + assert_equals( + inlineScrollTimeline.currentTime, 0, 'Unscrolled inline timeline'); + assert_equals( + horizontalScrollTimeline.currentTime, 0, + 'Unscrolled horizontal timeline'); + assert_equals( + verticalScrollTimeline.currentTime, 0, 'Unscrolled vertical timeline'); + + // For vertical-lr, both axes start at their 'normal' positions but the X-axis + // is the block direction and the Y-axis is the inline direction. This does + // not affect horizontal/vertical. + scroller.scrollTop = 50; + scroller.scrollLeft = 75; + + assert_equals(blockScrollTimeline.currentTime, 75, 'Scrolled block timeline'); + assert_equals( + inlineScrollTimeline.currentTime, 50, 'Scrolled inline timeline'); + assert_equals( + horizontalScrollTimeline.currentTime, 75, 'Scrolled horizontal timeline'); + assert_equals( + verticalScrollTimeline.currentTime, 50, 'Scrolled vertical timeline'); +}, 'currentTime handles writing-mode: vertical-lr correctly'); + +test(function() { + const scrollerOverrides = new Map([['direction', 'rtl']]); + const scroller = setupScrollTimelineTest(scrollerOverrides); + // Set the timeRange such that currentTime maps directly to the value + // scrolled. The contents and scroller are square, so it suffices to compute + // one edge and use it for all the timelines. + const scrollerSize = scroller.scrollHeight - scroller.clientHeight; + + const lengthScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'horizontal', + startScrollOffset: '20px' + }); + const percentageScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'horizontal', + startScrollOffset: '20%' + }); + const calcScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'horizontal', + startScrollOffset: 'calc(20% - 5px)' + }); + + // Unscrolled, all timelines should read a current time of unresolved, since + // the current offset (0) will be less than the startScrollOffset. + assert_equals( + lengthScrollTimeline.currentTime, null, + 'Unscrolled length-based timeline'); + assert_equals( + percentageScrollTimeline.currentTime, null, + 'Unscrolled percentage-based timeline'); + assert_equals( + calcScrollTimeline.currentTime, null, 'Unscrolled calc-based timeline'); + + // With direction rtl offsets are inverted, such that scrollLeft == + // scrollerSize is the 'zero' point for currentTime. However the + // startScrollOffset is an absolute distance along the offset, so doesn't + // need adjusting. + + // Check the length-based ScrollTimeline. + scroller.scrollLeft = scrollerSize; + assert_equals( + lengthScrollTimeline.currentTime, null, + 'Length-based timeline before the startScrollOffset point'); + scroller.scrollLeft = scrollerSize - 20; + assert_equals( + lengthScrollTimeline.currentTime, 0, + 'Length-based timeline at the startScrollOffset point'); + scroller.scrollLeft = scrollerSize - 50; + assert_equals( + lengthScrollTimeline.currentTime, + calculateCurrentTime(50, 20, scrollerSize, scrollerSize), + 'Length-based timeline after the startScrollOffset point'); + + // Check the percentage-based ScrollTimeline. + scroller.scrollLeft = scrollerSize - (0.19 * scrollerSize); + assert_equals( + percentageScrollTimeline.currentTime, null, + 'Percentage-based timeline before the startScrollOffset point'); + scroller.scrollLeft = scrollerSize - (0.20 * scrollerSize); + assert_equals( + percentageScrollTimeline.currentTime, 0, + 'Percentage-based timeline at the startScrollOffset point'); + scroller.scrollLeft = scrollerSize - (0.4 * scrollerSize); + assert_equals( + percentageScrollTimeline.currentTime, + calculateCurrentTime( + 0.4 * scrollerSize, 0.2 * scrollerSize, scrollerSize, scrollerSize), + 'Percentage-based timeline after the startScrollOffset point'); + + // Check the calc-based ScrollTimeline. + scroller.scrollLeft = scrollerSize - (0.2 * scrollerSize - 10); + assert_equals( + calcScrollTimeline.currentTime, null, + 'Calc-based timeline before the startScrollOffset point'); + scroller.scrollLeft = scrollerSize - (0.2 * scrollerSize - 5); + assert_equals( + calcScrollTimeline.currentTime, 0, + 'Calc-based timeline at the startScrollOffset point'); + scroller.scrollLeft = scrollerSize - (0.2 * scrollerSize); + assert_equals( + calcScrollTimeline.currentTime, + calculateCurrentTime( + 0.2 * scrollerSize, 0.2 * scrollerSize - 5, scrollerSize, + scrollerSize), + 'Calc-based timeline after the startScrollOffset point'); +}, 'currentTime handles startScrollOffset with direction: rtl correctly'); + +test(function() { + const scrollerOverrides = new Map([['direction', 'rtl']]); + const scroller = setupScrollTimelineTest(scrollerOverrides); + // Set the timeRange such that currentTime maps directly to the value + // scrolled. The contents and scroller are square, so it suffices to compute + // one edge and use it for all the timelines. + const scrollerSize = scroller.scrollHeight - scroller.clientHeight; + + const lengthScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'horizontal', + endScrollOffset: (scrollerSize - 20) + 'px' + }); + const percentageScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'horizontal', + endScrollOffset: '80%' + }); + const calcScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'horizontal', + endScrollOffset: 'calc(80% + 5px)' + }); + + // With direction rtl offsets are inverted, such that scrollLeft == + // scrollerSize is the 'zero' point for currentTime. However the + // endScrollOffset is an absolute distance along the offset, so doesn't need + // adjusting. + + // Check the length-based ScrollTimeline. + scroller.scrollLeft = 0; + assert_equals( + lengthScrollTimeline.currentTime, null, + 'Length-based timeline after the endScrollOffset point'); + scroller.scrollLeft = 20; + assert_equals( + lengthScrollTimeline.currentTime, + calculateCurrentTime( + scrollerSize - 20, 0, scrollerSize - 20, scrollerSize), + 'Length-based timeline at the endScrollOffset point'); + scroller.scrollLeft = 50; + assert_equals( + lengthScrollTimeline.currentTime, + calculateCurrentTime( + scrollerSize - 50, 0, scrollerSize - 20, scrollerSize), + 'Length-based timeline before the endScrollOffset point'); + + // Check the percentage-based ScrollTimeline. + scroller.scrollLeft = 0.19 * scrollerSize; + assert_equals( + percentageScrollTimeline.currentTime, null, + 'Percentage-based timeline after the endScrollOffset point'); + scroller.scrollLeft = 0.20 * scrollerSize; + assert_equals( + percentageScrollTimeline.currentTime, + calculateCurrentTime( + 0.8 * scrollerSize, 0, 0.8 * scrollerSize, scrollerSize), + 'Percentage-based timeline at the endScrollOffset point'); + scroller.scrollLeft = 0.4 * scrollerSize; + assert_equals( + percentageScrollTimeline.currentTime, + calculateCurrentTime( + 0.6 * scrollerSize, 0, 0.8 * scrollerSize, scrollerSize), + 'Percentage-based timeline before the endScrollOffset point'); + + // Check the calc-based ScrollTimeline. 80% + 5px + scroller.scrollLeft = 0.2 * scrollerSize - 10; + assert_equals( + calcScrollTimeline.currentTime, null, + 'Calc-based timeline after the endScrollOffset point'); + scroller.scrollLeft = 0.2 * scrollerSize - 5; + assert_equals( + calcScrollTimeline.currentTime, + calculateCurrentTime( + 0.8 * scrollerSize + 5, 0, 0.8 * scrollerSize + 5, scrollerSize), + 'Calc-based timeline at the endScrollOffset point'); + scroller.scrollLeft = 0.2 * scrollerSize; + assert_equals( + calcScrollTimeline.currentTime, + calculateCurrentTime( + 0.8 * scrollerSize, 0, 0.8 * scrollerSize + 5, scrollerSize), + 'Calc-based timeline before the endScrollOffset point'); +}, 'currentTime handles endScrollOffset with direction: rtl correctly'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/current-time.html b/third_party/blink/web_tests/external/wpt/scroll-animations/current-time.html new file mode 100644 index 0000000..0dc2a6f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/current-time.html
@@ -0,0 +1,308 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>ScrollTimeline current time algorithm</title> +<link rel="help" href="https://wicg.github.io/scroll-animations/#current-time-algorithm"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script src="./resources/scrolltimeline-utils.js"></script> + +<body></body> + +<script> +'use strict'; + +test(function() { + const scroller = setupScrollTimelineTest(); + // Set the timeRange such that currentTime maps directly to the value + // scrolled. The contents and scroller are square, so it suffices to compute + // one edge and use it for all the timelines. + const scrollerSize = scroller.scrollHeight - scroller.clientHeight; + + const blockScrollTimeline = new ScrollTimeline( + {scrollSource: scroller, timeRange: scrollerSize, orientation: 'block'}); + const inlineScrollTimeline = new ScrollTimeline( + {scrollSource: scroller, timeRange: scrollerSize, orientation: 'inline'}); + const horizontalScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'horizontal' + }); + const verticalScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'vertical' + }); + + // Unscrolled, all timelines should read a currentTime of 0. + assert_equals( + blockScrollTimeline.currentTime, 0, 'Unscrolled block timeline'); + assert_equals( + inlineScrollTimeline.currentTime, 0, 'Unscrolled inline timeline'); + assert_equals( + horizontalScrollTimeline.currentTime, 0, + 'Unscrolled horizontal timeline'); + assert_equals( + verticalScrollTimeline.currentTime, 0, 'Unscrolled vertical timeline'); + + // Do some scrolling and make sure that the ScrollTimelines update. + scroller.scrollTop = 50; + scroller.scrollLeft = 75; + + // As noted above timeRange is mapped such that currentTime should be the + // scroll offset. + assert_equals(blockScrollTimeline.currentTime, 50, 'Scrolled block timeline'); + assert_equals( + inlineScrollTimeline.currentTime, 75, 'Scrolled inline timeline'); + assert_equals( + horizontalScrollTimeline.currentTime, 75, 'Scrolled horizontal timeline'); + assert_equals( + verticalScrollTimeline.currentTime, 50, 'Scrolled vertical timeline'); +}, 'currentTime calculates the correct time based on scrolled amount'); + +test(function() { + // It is difficult to calculate the scroll offset which results in an exact + // currentTime. Scrolling is calculated in integers which allows for the + // possibility of rounding, and scrollbar widths differ between platforms + // which means it is not possible to ensure a divisible scroller size. Instead + // the scroller content is made large enough that rounding differences result + // in negligible deltas in the output value. + const contentOverrides = new Map([['width', '1000px'], ['height', '1000px']]); + const scroller = setupScrollTimelineTest(new Map(), contentOverrides); + const scrollTimeline = new ScrollTimeline( + {scrollSource: scroller, timeRange: 100, orientation: 'block'}); + + // Mapping timeRange to 100 means the output is 'percentage scrolled', so + // calculate where the 50% scroll mark would be. + const halfwayY = (scroller.scrollHeight - scroller.clientHeight) / 2; + scroller.scrollTop = halfwayY; + + assert_approx_equals(scrollTimeline.currentTime, 50, 0.5); +}, 'currentTime adjusts correctly for the timeRange'); + +test(function() { + const scroller = setupScrollTimelineTest(); + // Set the timeRange such that currentTime maps directly to the value + // scrolled. The contents and scroller are square, so it suffices to compute + // one edge and use it for all the timelines. + const scrollerSize = scroller.scrollHeight - scroller.clientHeight; + + const lengthScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'block', + startScrollOffset: '20px' + }); + const percentageScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'block', + startScrollOffset: '20%' + }); + const calcScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'block', + startScrollOffset: 'calc(20% - 5px)' + }); + + // Unscrolled all timelines should read a current time of unresolved, as the + // current offset (0) will be less than the startScrollOffset. + assert_equals( + lengthScrollTimeline.currentTime, null, + 'Unscrolled length-based timeline'); + assert_equals( + percentageScrollTimeline.currentTime, null, + 'Unscrolled percentage-based timeline'); + assert_equals( + calcScrollTimeline.currentTime, null, 'Unscrolled calc-based timeline'); + + // Check the length-based ScrollTimeline. + scroller.scrollTop = 19; + assert_equals( + lengthScrollTimeline.currentTime, null, + 'Length-based timeline before the startScrollOffset point'); + scroller.scrollTop = 20; + assert_equals( + lengthScrollTimeline.currentTime, 0, + 'Length-based timeline at the startScrollOffset point'); + scroller.scrollTop = 50; + assert_equals( + lengthScrollTimeline.currentTime, + calculateCurrentTime(50, 20, scrollerSize, scrollerSize), + 'Length-based timeline after the startScrollOffsetPoint'); + + // Check the percentage-based ScrollTimeline. + scroller.scrollTop = 0.19 * scrollerSize; + assert_equals( + percentageScrollTimeline.currentTime, null, + 'Percentage-based scroller before the startScrollOffset point'); + scroller.scrollTop = 0.20 * scrollerSize; + assert_equals( + percentageScrollTimeline.currentTime, 0, + 'Percentage-based scroller at the startScrollOffset point'); + scroller.scrollTop = 0.50 * scrollerSize; + assert_equals( + percentageScrollTimeline.currentTime, + calculateCurrentTime( + scroller.scrollTop, 0.2 * scrollerSize, scrollerSize, scrollerSize), + 'Percentage-based scroller after the startScrollOffset point'); + + // Check the calc-based ScrollTimeline. + scroller.scrollTop = 0.2 * scrollerSize - 10; + assert_equals( + calcScrollTimeline.currentTime, null, + 'Calc-based scroller before the startScrollOffset point'); + scroller.scrollTop = 0.2 * scrollerSize - 5; + assert_equals( + calcScrollTimeline.currentTime, 0, + 'Calc-based scroller at the startScrollOffset point'); + scroller.scrollTop = 0.2 * scrollerSize; + assert_equals( + calcScrollTimeline.currentTime, + calculateCurrentTime( + scroller.scrollTop, 0.2 * scrollerSize - 5, scrollerSize, + scrollerSize), + 'Calc-based scroller after the startScrollOffset point'); +}, 'currentTime handles startScrollOffset correctly'); + +test(function() { + const scroller = setupScrollTimelineTest(); + // Set the timeRange such that currentTime maps directly to the value + // scrolled. The contents and scroller are square, so it suffices to compute + // one edge and use it for all the timelines. + const scrollerSize = scroller.scrollHeight - scroller.clientHeight; + + const lengthScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'block', + endScrollOffset: (scrollerSize - 20) + 'px' + }); + const percentageScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'block', + endScrollOffset: '80%' + }); + const calcScrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'block', + endScrollOffset: 'calc(80% + 5px)' + }); + + // Check the length-based ScrollTimeline. + scroller.scrollTop = scrollerSize; + assert_equals( + lengthScrollTimeline.currentTime, null, + 'Length-based timeline after the endScrollOffset point'); + scroller.scrollTop = scrollerSize - 20; + assert_equals( + lengthScrollTimeline.currentTime, + calculateCurrentTime( + scrollerSize - 20, 0, scrollerSize - 20, scrollerSize), + 'Length-based timeline at the endScrollOffset point'); + scroller.scrollTop = scrollerSize - 50; + assert_equals( + lengthScrollTimeline.currentTime, + calculateCurrentTime( + scrollerSize - 50, 0, scrollerSize - 20, scrollerSize), + 'Length-based timeline before the endScrollOffset point'); + + // Check the percentage-based ScrollTimeline. + scroller.scrollTop = 0.81 * scrollerSize; + assert_equals( + percentageScrollTimeline.currentTime, null, + 'Percentage-based timeline after the endScrollOffset point'); + scroller.scrollTop = 0.80 * scrollerSize; + assert_equals( + percentageScrollTimeline.currentTime, + calculateCurrentTime( + scroller.scrollTop, 0, 0.8 * scrollerSize, scrollerSize), + 'Percentage-based timeline at the endScrollOffset point'); + scroller.scrollTop = 0.50 * scrollerSize; + assert_equals( + percentageScrollTimeline.currentTime, + calculateCurrentTime( + scroller.scrollTop, 0, 0.8 * scrollerSize, scrollerSize), + 'Percentage-based timeline before the endScrollOffset point'); + + // Check the calc-based ScrollTimeline. + scroller.scrollTop = 0.8 * scrollerSize + 6; + assert_equals( + calcScrollTimeline.currentTime, null, + 'Calc-based timeline after the endScrollOffset point'); + scroller.scrollTop = 0.8 * scrollerSize + 5; + assert_equals( + calcScrollTimeline.currentTime, + calculateCurrentTime( + scroller.scrollTop, 0, 0.8 * scrollerSize + 5, scrollerSize), + 'Calc-based timeline at the endScrollOffset point'); + scroller.scrollTop = 0.5 * scrollerSize; + assert_equals( + calcScrollTimeline.currentTime, + calculateCurrentTime( + scroller.scrollTop, 0, 0.8 * scrollerSize + 5, scrollerSize), + 'Calc-based timeline before the endScrollOffset point'); +}, 'currentTime handles endScrollOffset correctly'); + +test(function() { + const scroller = setupScrollTimelineTest(); + // Set the timeRange such that currentTime maps directly to the value + // scrolled. The contents and scroller are square, so it suffices to compute + // one edge and use it for all the timelines. + const scrollerSize = scroller.scrollHeight - scroller.clientHeight; + + const scrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'block', + startScrollOffset: '20px', + endScrollOffset: (scrollerSize - 50) + 'px' + }); + + scroller.scrollTop = 150; + assert_equals( + scrollTimeline.currentTime, + calculateCurrentTime(150, 20, scrollerSize - 50, scrollerSize)); +}, 'currentTime handles startScrollOffset and endScrollOffset together correctly'); + +test(function() { + const scroller = setupScrollTimelineTest(); + // Set the timeRange such that currentTime maps directly to the value + // scrolled. The contents and scroller are square, so it suffices to compute + // one edge and use it for all the timelines. + const scrollerSize = scroller.scrollHeight - scroller.clientHeight; + + const scrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'block', + startScrollOffset: '20px', + endScrollOffset: '20px', + }); + + scroller.scrollTop = 150; + assert_equals(scrollTimeline.currentTime, null); +}, 'currentTime handles startScrollOffset == endScrollOffset correctly'); + +test(function() { + const scroller = setupScrollTimelineTest(); + // Set the timeRange such that currentTime maps directly to the value + // scrolled. The contents and scroller are square, so it suffices to compute + // one edge and use it for all the timelines. + const scrollerSize = scroller.scrollHeight - scroller.clientHeight; + + const scrollTimeline = new ScrollTimeline({ + scrollSource: scroller, + timeRange: scrollerSize, + orientation: 'block', + startScrollOffset: '50px', + endScrollOffset: '10px', + }); + + scroller.scrollTop = 150; + assert_equals(scrollTimeline.currentTime, null); +}, 'currentTime handles startScrollOffset > endScrollOffset correctly'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/resources/scrolltimeline-utils.js b/third_party/blink/web_tests/external/wpt/scroll-animations/resources/scrolltimeline-utils.js new file mode 100644 index 0000000..b0e5ead2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/resources/scrolltimeline-utils.js
@@ -0,0 +1,44 @@ +'use strict'; + +// Builds a generic structure that looks like: +// +// <div class="scroller"> // 100x100 viewport +// <div class="contents"></div> // 500x500 +// </div> +// +// The |scrollerOverrides| and |contentOverrides| parameters are maps which +// are applied to the scroller and contents style after basic setup. +// +// Appends the outer 'scroller' element to the document body, and returns it. +function setupScrollTimelineTest( + scrollerOverrides = new Map(), contentOverrides = new Map()) { + let scroller = document.createElement('div'); + scroller.style.width = '100px'; + scroller.style.height = '100px'; + scroller.style.overflow = 'scroll'; + for (const [key, value] of scrollerOverrides) { + scroller.style[key] = value; + } + + let contents = document.createElement('div'); + contents.style.width = '500px'; + contents.style.height = '500px'; + for (const [key, value] of contentOverrides) { + contents.style[key] = value; + } + + scroller.appendChild(contents); + document.body.appendChild(scroller); + return scroller; +} + +// Helper method to calculate the current time, implementing only step 5 of +// https://wicg.github.io/scroll-animations/#current-time-algorithm +function calculateCurrentTime( + currentScrollOffset, startScrollOffset, endScrollOffset, + effectiveTimeRange) { + return ((currentScrollOffset - startScrollOffset) / + (endScrollOffset - startScrollOffset)) * + effectiveTimeRange; +} +
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/window/sandboxed-iframes.https-expected.txt b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/window/sandboxed-iframes.https-expected.txt index dc39b96..a0a6460 100644 --- a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/window/sandboxed-iframes.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/window/sandboxed-iframes.https-expected.txt
@@ -1,4 +1,3 @@ - This is a testharness.js-based test. PASS Sandboxed iframe with allow-same-origin is allowed access FAIL Sandboxed iframe without allow-same-origin is denied access assert_equals: Access should be denied if sandbox lacks allow-same-origin expected "denied" but got "unexpecteddenied"
diff --git a/third_party/blink/web_tests/external/wpt/svg/interact/scripted/composed.window.svg b/third_party/blink/web_tests/external/wpt/svg/interact/scripted/composed.window.svg new file mode 100644 index 0000000..b63dcf02 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/interact/scripted/composed.window.svg
@@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml"> + <title>Focus events are composed</title> + <metadata> + <h:link rel="help" href="https://svgwg.org/svg2-draft/interact.html#Focus"/> + </metadata> + <a id="a1" href="#"></a> + <h:script src="/resources/testharness.js"/> + <h:script src="/resources/testharnessreport.js"/> + <script><![CDATA[ + async_test(t => { + const anchor = document.getElementById("a1"); + let happened = false; + anchor.onfocus = t.step_func(e => { + happened = true; + assert_equals(e.type, "focus"); + assert_true(e.composed); + }); + anchor.focus(); + anchor.onblur = t.step_func_done(e => { + assert_true(happened); + assert_equals(e.type, "blur"); + assert_true(e.composed); + }); + anchor.blur(); + }, "Focus events are composed"); + ]]></script> +</svg> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/svg/interact/scripted/focus-events.svg b/third_party/blink/web_tests/external/wpt/svg/interact/scripted/focus-events.svg new file mode 100644 index 0000000..bf307b79 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/interact/scripted/focus-events.svg
@@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml"> + <title>Focus management</title> + <metadata> + <h:link rel="help" href="https://svgwg.org/svg2-draft/interact.html#Focus"/> + </metadata> + <a id="a1" href="#"></a> + <a id="a2" href="#"></a> + <h:script src="/resources/testharness.js"/> + <h:script src="/resources/testharnessreport.js"/> + <script><![CDATA[ + var a1 = document.getElementById('a1'), + a2 = document.getElementById('a2'), + t1 = async_test("focusing on a focusable element fires a focus event at the element"), + t2 = async_test("focusing on a focusable element fires a blur event at the previous focussed element"); + + a2.onfocus = t1.step_func_done(function(e){ + assert_true(e.isTrusted, "focus event is trusted"); + assert_false(e.bubbles, "focus event doesn't bubble"); + assert_false(e.cancelable, "focus event is not cancelable"); + assert_equals(document.activeElement, a2); + }); + + a1.onblur = t2.step_func_done(function(e){ + assert_true(e.isTrusted, "blur event is trusted"); + assert_false(e.bubbles, "blur event doesn't bubble"); + assert_false(e.cancelable, "blur event is not cancelable"); + }); + + a1.focus(); + a2.focus(); + ]]></script> +</svg> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/svg/interact/scripted/focus-tabindex-default-value.svg b/third_party/blink/web_tests/external/wpt/svg/interact/scripted/focus-tabindex-default-value.svg new file mode 100644 index 0000000..3af1acff --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/interact/scripted/focus-tabindex-default-value.svg
@@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml"> + <title>SVG Test: focus - default value of tabindex</title> + <metadata> + <h:link rel="help" href="https://svgwg.org/svg2-draft/interact.html#Focus"/> + </metadata> + <a id="test1" href="#"></a> + <rect id="test2"></rect> + <h:script src="/resources/testharness.js"/> + <h:script src="/resources/testharnessreport.js"/> + <script><![CDATA[ + test(function() { + assert_equals(document.getElementById("test1").tabIndex, 0, "The value of tabIndex attribute should be 0."); + }, "The default value of tabIndex attribute must be 0 for elements that are focusable"); + + test(function() { + assert_equals(document.getElementById("test2").tabIndex, -1, "The value of tabIndex attribute should be -1."); + }, "The default value of tabIndex attribute must be -1 for elements that are not focusable"); + ]]></script> +</svg> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/svg/interact/scripted/resources/blank.htm b/third_party/blink/web_tests/external/wpt/svg/interact/scripted/resources/blank.htm new file mode 100644 index 0000000..18ecdcb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/interact/scripted/resources/blank.htm
@@ -0,0 +1 @@ +<html></html>
diff --git a/third_party/blink/web_tests/external/wpt/svg/interact/scripted/tabindex-focus-flag-expected.txt b/third_party/blink/web_tests/external/wpt/svg/interact/scripted/tabindex-focus-flag-expected.txt new file mode 100644 index 0000000..5ca66db --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/interact/scripted/tabindex-focus-flag-expected.txt
@@ -0,0 +1,46 @@ +This is a testharness.js-based test. +FAIL The document root element should be focusable. assert_equals: expected Element node <svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://w... but got null +PASS rect should not be focusable. +PASS svg should not be focusable. +FAIL rect[focusable=true] should be focusable. assert_equals: expected Element node <rect focusable="true"></rect> but got null +PASS a should not be focusable. +PASS a[href] should be focusable. +FAIL a[focusable=false] should not be focusable. assert_not_equals: got disallowed value Element node <a href="" focusable="false"></a> +FAIL iframe should be focusable. assert_equals: expected Element node <iframe src="resources/blank.htm"></iframe> but got Element node <a href="" focusable="false"></a> +FAIL audio[controls] should be focusable. assert_equals: expected Element node <audio controls="controls"></audio> but got Element node <a href="" focusable="false"></a> +FAIL video[controls] should be focusable. assert_equals: expected Element node <video controls="controls"></video> but got Element node <a href="" focusable="false"></a> +FAIL canvas[tabindex] should be focusable. assert_equals: expected Element node <canvas tabindex="0"></canvas> but got Element node <a href="" focusable="false"></a> +PASS circle[tabindex] should be focusable. +PASS ellipse[tabindex] should be focusable. +PASS foreignObject[tabindex] should be focusable. +PASS g[tabindex] should be focusable. +PASS image[tabindex] should be focusable. +PASS line[tabindex] should be focusable. +FAIL mesh[tabindex] should be focusable. assert_equals: expected Element node <mesh tabindex="0"></mesh> but got Element node <line tabindex="0"></line> +PASS path[tabindex] should be focusable. +PASS polygon[tabindex] should be focusable. +PASS rect[tabindex] should be focusable. +PASS svg[tabindex] should be focusable. +PASS switch[tabindex] should be focusable. +PASS text[tabindex] should be focusable. +PASS textPath[tabindex] should be focusable. +PASS tspan[tabindex] should be focusable. +FAIL unknown[tabindex] should be focusable. assert_equals: expected Element node <unknown tabindex="0"></unknown> but got Element node <tspan tabindex="0"></tspan> +PASS use[tabindex] should be focusable. +PASS clipPath[tabindex] should not be focusable. +PASS defs[tabindex] should not be focusable. +PASS desc[tabindex] should not be focusable. +PASS hatch[tabindex] should not be focusable. +PASS linearGradient[tabindex] should not be focusable. +PASS marker[tabindex] should not be focusable. +PASS mask[tabindex] should not be focusable. +PASS meshgradient[tabindex] should not be focusable. +PASS metadata[tabindex] should not be focusable. +PASS pattern[tabindex] should not be focusable. +PASS radialGradient[tabindex] should not be focusable. +PASS script[tabindex] should not be focusable. +PASS style[tabindex] should not be focusable. +PASS title[tabindex] should not be focusable. +PASS symbol[tabindex] should not be focusable. +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/svg/interact/scripted/tabindex-focus-flag.svg b/third_party/blink/web_tests/external/wpt/svg/interact/scripted/tabindex-focus-flag.svg new file mode 100644 index 0000000..29ba209b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/interact/scripted/tabindex-focus-flag.svg
@@ -0,0 +1,125 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml"> + <metadata> + <h:link rel="help" href="https://svgwg.org/svg2-draft/interact.html#Focus"/> + </metadata> + <g id="default-samples"> + <!-- non-default focusable renderable element --> + <rect></rect> + <svg></svg> + <!-- for compatibility with SVG Tiny 1.2 focusable attribute, user agents should treat an element with a value of true for that attribute as focusable --> + <rect focusable="true"></rect> + <!-- anchors need a href to be focusable --> + <a></a> + <a href=""></a> + <!-- Remove default focus behaviour with focusable="false" (SVG Tiny 1.2 compatibility) --> + <a href="" focusable="false"></a> + <!-- iframe, and audio/video with controls are default focusable --> + <h:iframe src="resources/blank.htm"></h:iframe> + <h:audio controls="controls"></h:audio> + <h:video controls="controls"></h:video> + <!-- non-default focusable renderable element with valid tabindex --> + <h:canvas tabindex="0"></h:canvas> + <circle tabindex="0"></circle> + <ellipse tabindex="0"></ellipse> + <foreignObject tabindex="0"></foreignObject> + <g tabindex="0"></g> + <image tabindex="0"></image> + <line tabindex="0"></line> + <mesh tabindex="0"></mesh> + <path tabindex="0"></path> + <polygon tabindex="0"></polygon> + <rect tabindex="0"></rect> + <svg tabindex="0"></svg> + <switch tabindex="0"></switch> + <text tabindex="0"> + <textPath tabindex="0"></textPath> + <tspan tabindex="0"></tspan> + </text> + <unknown tabindex="0"></unknown> + <use tabindex="0"></use> + <!-- never-rendered element with valid tabindex --> + <clipPath tabindex="0"></clipPath> + <defs tabindex="0"></defs> + <desc tabindex="0"></desc> + <hatch tabindex="0"></hatch> + <linearGradient tabindex="0"></linearGradient> + <marker tabindex="0"></marker> + <mask tabindex="0"></mask> + <meshgradient tabindex="0"></meshgradient> + <metadata tabindex="0"></metadata> + <pattern tabindex="0"></pattern> + <radialGradient tabindex="0"></radialGradient> + <script tabindex="0"></script> + <style tabindex="0"></style> + <title tabindex="0"></title> + <symbol tabindex="0"></symbol> + </g> + <h:script src="/resources/testharness.js"/> + <h:script src="/resources/testharnessreport.js"/> + <script><![CDATA[ + var root = document.querySelector("svg"); + + test(() => { + root.focus(); + assert_equals(document.activeElement, root); + }, 'The document root element should be focusable.'); + + const defaultList = [ + ['rect', false], + ['svg', false], + ['rect[focusable=true]', true], + ['a', false], + ['a[href]', true], + ['a[focusable=false]', false], + ['iframe', true], + ['audio[controls]', true], + ['video[controls]', true], + ['canvas[tabindex]', true], + ['circle[tabindex]', true], + ['ellipse[tabindex]', true], + ['foreignObject[tabindex]', true], + ['g[tabindex]', true], + ['image[tabindex]', true], + ['line[tabindex]', true], + ['mesh[tabindex]', true], + ['path[tabindex]', true], + ['polygon[tabindex]', true], + ['rect[tabindex]', true], + ['svg[tabindex]', true], + ['switch[tabindex]', true], + ['text[tabindex]', true], + ['textPath[tabindex]', true], + ['tspan[tabindex]', true], + ['unknown[tabindex]', true], + ['use[tabindex]', true], + ['clipPath[tabindex]', false], + ['defs[tabindex]', false], + ['desc[tabindex]', false], + ['hatch[tabindex]', false], + ['linearGradient[tabindex]', false], + ['marker[tabindex]', false], + ['mask[tabindex]', false], + ['meshgradient[tabindex]', false], + ['metadata[tabindex]', false], + ['pattern[tabindex]', false], + ['radialGradient[tabindex]', false], + ['script[tabindex]', false], + ['style[tabindex]', false], + ['title[tabindex]', false], + ['symbol[tabindex]', false], + ]; + + for (entry of defaultList) { + test(() => { + var element = document.querySelector('#default-samples ' + entry[0]); + element.focus(); + if (entry[1]) + assert_equals(document.activeElement, element); + else + assert_not_equals(document.activeElement, element); + }, entry[0] + ' should ' + (entry[1] ? '' : 'not ') + 'be focusable.'); + } + ]]></script> +</svg> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/constructor.any.js b/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/constructor.any.js index a584a23e..11e309fe6 100644 --- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/constructor.any.js +++ b/third_party/blink/web_tests/external/wpt/wasm/jsapi/memory/constructor.any.js
@@ -80,7 +80,7 @@ } test(() => { - assert_throws(new RangeError(), () => new WebAssembly.Memory({ "element": "anyfunc", "initial": 10, "maximum": 9 })); + assert_throws(new RangeError(), () => new WebAssembly.Memory({ "initial": 10, "maximum": 9 })); }, "Initial value exceeds maximum"); test(() => {
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-context-filling-expected.txt b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-context-filling-expected.txt new file mode 100644 index 0000000..c0b9a11f5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-context-filling-expected.txt
@@ -0,0 +1,17 @@ +This is a testharness.js-based test. +PASS Filling effect values reflect changes to font-size on element +PASS Filling effect values reflect changes to font-size on parent element +PASS Filling effect values reflect changes to variables on element +PASS Filling effect values reflect changes to variables on parent element +PASS Filling effect values reflect changes to the the animation's keyframes +FAIL Filling effect values reflect changes to the the animation's composite mode assert_equals: Effect value after updating the composite mode expected "300px" but got "200px" +FAIL Filling effect values reflect changes to the the animation's iteration composite mode assert_equals: Effect value after updating the iteration composite mode expected "200px" but got "100px" +PASS Filling effect values reflect changes to the base value when using additive animation +PASS Filling effect values reflect changes to the base value when using additive animation on a single keyframe +PASS Filling effect values reflect changes to the base value when using the fill value is an implicit keyframe +PASS Filling effect values reflect changes to the base value via a parent element +PASS Filling effect values reflect changes to underlying animations +PASS Filling effect values reflect changes to underlying animations via a a parent element +PASS Filling effect values reflect changes to underlying animations made by directly changing the keyframes +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-context-filling.html b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-context-filling.html new file mode 100644 index 0000000..fcb7f131 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/keyframe-effects/effect-value-context-filling.html
@@ -0,0 +1,377 @@ +<!doctype html> +<meta charset=utf-8> +<title>The effect value of a keyframe effect: Forwards-filling animations whose + values depend on their context (target element)</title> +<link rel="help" href="https://drafts.csswg.org/web-animations/#calculating-computed-keyframes"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +'use strict'; + +test(t => { + const div = createDiv(t); + div.style.fontSize = '10px'; + const animation = div.animate( + [{ marginLeft: '10em' }, { marginLeft: '20em' }], + { duration: 1000, fill: 'forwards' } + ); + animation.finish(); + assert_equals( + getComputedStyle(div).marginLeft, + '200px', + 'Effect value before updating font-size' + ); + + div.style.fontSize = '20px'; + + assert_equals( + getComputedStyle(div).marginLeft, + '400px', + 'Effect value after updating font-size' + ); +}, 'Filling effect values reflect changes to font-size on element'); + +test(t => { + const parentDiv = createDiv(t); + const div = createDiv(t); + parentDiv.appendChild(div); + parentDiv.style.fontSize = '10px'; + + const animation = div.animate( + [{ marginLeft: '10em' }, { marginLeft: '20em' }], + { duration: 1000, fill: 'forwards' } + ); + animation.finish(); + assert_equals( + getComputedStyle(div).marginLeft, + '200px', + 'Effect value before updating font-size on parent element' + ); + + parentDiv.style.fontSize = '20px'; + + assert_equals( + getComputedStyle(div).marginLeft, + '400px', + 'Effect value after updating font-size on parent element' + ); +}, 'Filling effect values reflect changes to font-size on parent element'); + +test(t => { + const div = createDiv(t); + div.style.setProperty('--target', '100px'); + const animation = div.animate( + [{ marginLeft: '0px' }, { marginLeft: 'var(--target)' }], + { duration: 1000, fill: 'forwards' } + ); + animation.finish(); + assert_equals( + getComputedStyle(div).marginLeft, + '100px', + 'Effect value before updating variable' + ); + + div.style.setProperty('--target', '200px'); + + assert_equals( + getComputedStyle(div).marginLeft, + '200px', + 'Effect value after updating variable' + ); +}, 'Filling effect values reflect changes to variables on element'); + +test(t => { + const parentDiv = createDiv(t); + const div = createDiv(t); + parentDiv.appendChild(div); + + parentDiv.style.setProperty('--target', '10em'); + parentDiv.style.fontSize = '10px'; + + const animation = div.animate( + [{ marginLeft: '0px' }, { marginLeft: 'calc(var(--target) * 2)' }], + { duration: 1000, fill: 'forwards' } + ); + animation.finish(); + assert_equals( + getComputedStyle(div).marginLeft, + '200px', + 'Effect value before updating variable' + ); + + parentDiv.style.setProperty('--target', '20em'); + + assert_equals( + getComputedStyle(div).marginLeft, + '400px', + 'Effect value after updating variable' + ); +}, 'Filling effect values reflect changes to variables on parent element'); + +test(t => { + const div = createDiv(t); + const animation = div.animate( + [{ marginLeft: '100px' }, { marginLeft: '200px' }], + { duration: 1000, fill: 'forwards' } + ); + animation.finish(); + assert_equals( + getComputedStyle(div).marginLeft, + '200px', + 'Effect value before updating the animation' + ); + + animation.effect.setKeyframes([ + { marginLeft: '100px' }, + { marginLeft: '300px' }, + ]); + + assert_equals( + getComputedStyle(div).marginLeft, + '300px', + 'Effect value after updating the animation' + ); +}, 'Filling effect values reflect changes to the the animation\'s keyframes'); + +test(t => { + const div = createDiv(t); + div.style.marginLeft = '100px'; + const animation = div.animate( + [{ marginLeft: '100px' }, { marginLeft: '200px' }], + { duration: 1000, fill: 'forwards' } + ); + animation.finish(); + assert_equals( + getComputedStyle(div).marginLeft, + '200px', + 'Effect value before updating the animation' + ); + + animation.effect.composite = 'add'; + + assert_equals( + getComputedStyle(div).marginLeft, + '300px', + 'Effect value after updating the composite mode' + ); +}, 'Filling effect values reflect changes to the the animation\'s composite mode'); + +test(t => { + const div = createDiv(t); + const animation = div.animate( + [{ marginLeft: '0px' }, { marginLeft: '100px' }], + { duration: 1000, iterations: 2, fill: 'forwards' } + ); + animation.finish(); + assert_equals( + getComputedStyle(div).marginLeft, + '100px', + 'Effect value before updating the animation' + ); + + animation.effect.iterationComposite = 'accumulate'; + + assert_equals( + getComputedStyle(div).marginLeft, + '200px', + 'Effect value after updating the iteration composite mode' + ); +}, 'Filling effect values reflect changes to the the animation\'s iteration composite mode'); + +test(t => { + const div = createDiv(t); + div.style.marginLeft = '100px'; + const animation = div.animate( + [{ marginLeft: '100px' }, { marginLeft: '200px' }], + { duration: 1000, fill: 'forwards', composite: 'add' } + ); + animation.finish(); + assert_equals( + getComputedStyle(div).marginLeft, + '300px', + 'Effect value before updating underlying value' + ); + + div.style.marginLeft = '200px'; + + assert_equals( + getComputedStyle(div).marginLeft, + '400px', + 'Effect value after updating underlying value' + ); +}, 'Filling effect values reflect changes to the base value when using' + + ' additive animation'); + +test(t => { + const div = createDiv(t); + div.style.marginLeft = '100px'; + const animation = div.animate( + [{ marginLeft: '100px' }, { marginLeft: '200px', composite: 'add' }], + { duration: 1000, fill: 'forwards' } + ); + animation.finish(); + assert_equals( + getComputedStyle(div).marginLeft, + '300px', + 'Effect value before updating underlying value' + ); + + div.style.marginLeft = '200px'; + + assert_equals( + getComputedStyle(div).marginLeft, + '400px', + 'Effect value after updating underlying value' + ); +}, 'Filling effect values reflect changes to the base value when using' + + ' additive animation on a single keyframe'); + +test(t => { + const div = createDiv(t); + div.style.marginLeft = '0px'; + const animation = div.animate([{ marginLeft: '100px', offset: 0 }], { + duration: 1000, + fill: 'forwards', + }); + animation.finish(); + assert_equals( + getComputedStyle(div).marginLeft, + '0px', + 'Effect value before updating underlying value' + ); + + div.style.marginLeft = '200px'; + + assert_equals( + getComputedStyle(div).marginLeft, + '200px', + 'Effect value after updating underlying value' + ); +}, 'Filling effect values reflect changes to the base value when using' + + ' the fill value is an implicit keyframe'); + +test(t => { + const parentDiv = createDiv(t); + const div = createDiv(t); + parentDiv.appendChild(div); + parentDiv.style.fontSize = '10px'; + div.style.marginLeft = '10em'; + // Computed underlying margin-left is 100px + + const animation = div.animate( + [{ marginLeft: '100px' }, { marginLeft: '200px' }], + { duration: 1000, fill: 'forwards', composite: 'add' } + ); + animation.finish(); + assert_equals( + getComputedStyle(div).marginLeft, + '300px', + 'Effect value before updating font-size on parent' + ); + + parentDiv.style.fontSize = '20px'; + // Computed underlying margin-left is now 200px + + assert_equals( + getComputedStyle(div).marginLeft, + '400px', + 'Effect value after updating font-size on parent' + ); +}, 'Filling effect values reflect changes to the base value via a' + + ' parent element'); + +test(t => { + const div = createDiv(t); + const animationA = div.animate( + [{ marginLeft: '0px' }, { marginLeft: '100px' }], + { duration: 2000, fill: 'forwards', easing: 'step-end' } + ); + const animationB = div.animate( + [{ marginLeft: '100px' }, { marginLeft: '200px' }], + { duration: 1000, fill: 'forwards', composite: 'add' } + ); + animationB.finish(); + assert_equals( + getComputedStyle(div).marginLeft, + '200px', + 'Effect value before updating underyling animation' + ); + + // Go to end of the underlying animation so that it jumps to 100px + animationA.finish(); + + assert_equals( + getComputedStyle(div).marginLeft, + '300px', + 'Effect value after updating underlying animation' + ); +}, 'Filling effect values reflect changes to underlying animations'); + +test(t => { + const parentDiv = createDiv(t); + const div = createDiv(t); + parentDiv.appendChild(div); + + parentDiv.style.fontSize = '10px'; + + const animationA = div.animate( + [{ marginLeft: '0px' }, { marginLeft: '10em' }], + { duration: 2000, fill: 'forwards', easing: 'step-start' } + ); + const animationB = div.animate( + [{ marginLeft: '100px' }, { marginLeft: '200px' }], + { duration: 1000, fill: 'forwards', composite: 'add' } + ); + animationB.finish(); + assert_equals( + getComputedStyle(div).marginLeft, + '300px', + 'Effect value before updating parent font-size' + ); + + parentDiv.style.fontSize = '20px'; + // At this point the underlying animation's output should jump to 200px. + + assert_equals( + getComputedStyle(div).marginLeft, + '400px', + 'Effect value after updating parent font-size' + ); +}, 'Filling effect values reflect changes to underlying animations via a' + + ' a parent element'); + +test(t => { + const div = createDiv(t); + const animationA = div.animate( + [{ marginLeft: '0px' }, { marginLeft: '0px' }], + { duration: 2000, fill: 'forwards' } + ); + const animationB = div.animate( + [{ marginLeft: '100px' }, { marginLeft: '200px' }], + { duration: 1000, fill: 'forwards', composite: 'add' } + ); + animationB.finish(); + assert_equals( + getComputedStyle(div).marginLeft, + '200px', + 'Effect value before updating underyling animation' + ); + + animationA.effect.setKeyframes([ + { marginLeft: '100px' }, + { marginLeft: '100px' }, + ]); + + assert_equals( + getComputedStyle(div).marginLeft, + '300px', + 'Effect value after updating underlying animation' + ); +}, 'Filling effect values reflect changes to underlying animations made by' + + ' directly changing the keyframes'); + +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/web-nfc/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/web-nfc/idlharness.https.window-expected.txt new file mode 100644 index 0000000..4e21915c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/web-nfc/idlharness.https.window-expected.txt
@@ -0,0 +1,25 @@ +This is a testharness.js-based test. +PASS idl_test setup +PASS Partial interface Navigator: original interface defined +FAIL NFCWriter interface: existence and properties of interface object assert_own_property: self does not have own property "NFCWriter" expected property "NFCWriter" missing +FAIL NFCWriter interface object length assert_own_property: self does not have own property "NFCWriter" expected property "NFCWriter" missing +FAIL NFCWriter interface object name assert_own_property: self does not have own property "NFCWriter" expected property "NFCWriter" missing +FAIL NFCWriter interface: existence and properties of interface prototype object assert_own_property: self does not have own property "NFCWriter" expected property "NFCWriter" missing +FAIL NFCWriter interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "NFCWriter" expected property "NFCWriter" missing +FAIL NFCWriter interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "NFCWriter" expected property "NFCWriter" missing +FAIL NFCWriter interface: operation push(NFCMessageSource, NFCPushOptions) assert_own_property: self does not have own property "NFCWriter" expected property "NFCWriter" missing +PASS NFC interface: existence and properties of interface object +PASS NFC interface object length +PASS NFC interface object name +PASS NFC interface: existence and properties of interface prototype object +PASS NFC interface: existence and properties of interface prototype object's "constructor" property +PASS NFC interface: existence and properties of interface prototype object's @@unscopables property +PASS NFC interface: operation watch(MessageCallback, NFCWatchOptions) +PASS NFC must be primary interface of navigator.nfc +PASS Stringification of navigator.nfc +PASS NFC interface: navigator.nfc must inherit property "watch(MessageCallback, NFCWatchOptions)" with the proper type +PASS NFC interface: calling watch(MessageCallback, NFCWatchOptions) on navigator.nfc with too few arguments must throw TypeError +PASS Navigator interface: attribute nfc +PASS Navigator interface: navigator must inherit property "nfc" with the proper type +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-track-stats.https-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-track-stats.https-expected.txt index 2acdf26..bd8e8449 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-track-stats.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-track-stats.https-expected.txt
@@ -4,7 +4,7 @@ PASS addTrack() with setLocalDescription() yields track stats PASS addTrack() with setLocalDescription() yields media stream stats PASS addTrack(): Media stream stats references track stats -PASS Legacy addStream(): Media stream stats references track stats +PASS Media stream stats references track stats PASS O/A exchange yields outbound RTP stream stats for sending track PASS O/A exchange yields inbound RTP stream stats for receiving track PASS replaceTrack() before offer: new track attachment stats present
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-track-stats.https.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-track-stats.https.html index 9ad6792..30c368f 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-track-stats.https.html +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-track-stats.https.html
@@ -155,11 +155,6 @@ })); }, 'addTrack(): Media stream stats references track stats'); - // TODO(hbos): addStream() is legacy API not in the spec. Based on discussion - // whether to standardize in legacy section, consider removing this test or - // keeping it until addTrack() has wide support. - // https://github.com/w3c/webrtc-pc/issues/1705 - // https://github.com/w3c/webrtc-pc/issues/1125 async_test(t => { const pc = new RTCPeerConnection(); t.add_cleanup(() => pc.close()); @@ -170,7 +165,8 @@ track = tracks[0]; stream = streams[0]; stream.addTrack(track); - pc.addStream(stream); + for (const track of stream.getTracks()) + pc.addTrack(track, stream); return pc.createOffer(); })) .then(t.step_func(offer => { @@ -193,7 +189,7 @@ .catch(t.step_func(reason => { assert_unreached(reason); })); - }, 'Legacy addStream(): Media stream stats references track stats'); + }, 'Media stream stats references track stats'); async_test(t => { const caller = new RTCPeerConnection();
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/legacy/RTCPeerConnection-addStream.https.html b/third_party/blink/web_tests/external/wpt/webrtc/legacy/RTCPeerConnection-addStream.https.html new file mode 100644 index 0000000..5a35ebc5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webrtc/legacy/RTCPeerConnection-addStream.https.html
@@ -0,0 +1,74 @@ +<!doctype html> +<meta charset=utf-8> +<meta name="timeout" content="long"> +<title>RTCPeerConnection legacy addStream</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../RTCPeerConnection-helper.js"></script> +<script src="../RTCStats-helper.js"></script> +<script src="../dictionary-helper.js"></script> +<script> + 'use strict'; + + // The following helper functions are called from RTCPeerConnection-helper.js: + // getUserMediaTracksAndStreams + + // The following helper functions are called from RTCStats-helper.js + // (depends on dictionary-helper.js): + // validateRtcStats + + // TODO(hbos): addStream() is legacy API not in the spec. Based on discussion + // whether to standardize in legacy section, consider removing this test or + // keeping it until addTrack() has wide support. + // https://github.com/w3c/webrtc-pc/issues/1705 + // https://github.com/w3c/webrtc-pc/issues/1125 + async_test(t => { + const pc = new RTCPeerConnection(); + t.add_cleanup(() => pc.close()); + let track; + let stream; + return getUserMediaTracksAndStreams(1) + .then(t.step_func(([tracks, streams]) => { + track = tracks[0]; + stream = streams[0]; + stream.addTrack(track); + pc.addStream(stream); + return pc.createOffer(); + })) + .then(t.step_func(offer => { + return pc.setLocalDescription(offer); + })) + .then(t.step_func(() => { + return pc.getStats(); + })) + .then(t.step_func(report => { + let trackStats = findStatsByTypeAndId(report, 'track', track.id); + let streamStats = findStatsByTypeAndId(report, 'stream', stream.id); + assert_true(trackStats != null && streamStats != null, + 'Has stats for track and stream'); + assert_array_equals(streamStats.trackIds, [ trackStats.id ], + 'streamStats.trackIds == [ trackStats.id ]'); + validateRtcStats(report, trackStats); + validateRtcStats(report, streamStats); + t.done(); + })) + .catch(t.step_func(reason => { + assert_unreached(reason); + })); + }, 'Legacy addStream(): Media stream stats references track stats'); + + function findStatsByTypeAndId(report, type, identifier) { + return findStats(report, stats => { + return stats.type == type && stats[type + 'Identifier'] == identifier; + }); + } + + function findStats(report, findFunc) { + for (let it = report.values(), n = it.next(); !n.done; n = it.next()) { + if (findFunc(n.value)) + return n.value; + } + return null; + } + +</script>
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/no-media-call.html b/third_party/blink/web_tests/external/wpt/webrtc/no-media-call.html index 0f2e2a33..10933fa 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/no-media-call.html +++ b/third_party/blink/web_tests/external/wpt/webrtc/no-media-call.html
@@ -1,7 +1,4 @@ <!doctype html> -<!-- -This test uses the legacy callback API with no media, and thus does not require fake media devices. ---> <html> <head> @@ -37,7 +34,6 @@ var parsedOffer = new RTCSessionDescription({ type: 'offer', sdp: offerSdp }); - // These functions use the legacy interface extensions to RTCPeerConnection. gSecondConnection.setRemoteDescription(parsedOffer).then( function() { gSecondConnection.createAnswer().then(onAnswerCreated,
diff --git a/third_party/blink/web_tests/external/wpt/workers/semantics/interface-objects/001.worker-expected.txt b/third_party/blink/web_tests/external/wpt/workers/semantics/interface-objects/001.worker-expected.txt index 842154f..d48b0570 100644 --- a/third_party/blink/web_tests/external/wpt/workers/semantics/interface-objects/001.worker-expected.txt +++ b/third_party/blink/web_tests/external/wpt/workers/semantics/interface-objects/001.worker-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 63 tests; 60 PASS, 3 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 63 tests; 61 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS The WorkerGlobalScope interface object should be exposed. PASS The DedicatedWorkerGlobalScope interface object should be exposed. PASS The Worker interface object should be exposed. @@ -44,7 +44,7 @@ PASS The FileReader interface object should be exposed. PASS The FileReaderSync interface object should be exposed. PASS The EventTarget interface object should be exposed. -FAIL The ErrorEvent interface object should be exposed. assert_own_property: expected property "ErrorEvent" missing +PASS The ErrorEvent interface object should be exposed. PASS The Event interface object should be exposed. PASS The CustomEvent interface object should be exposed. PASS The DOMException interface object should be exposed.
diff --git a/third_party/blink/web_tests/external/wpt/workers/semantics/interface-objects/003-expected.txt b/third_party/blink/web_tests/external/wpt/workers/semantics/interface-objects/003-expected.txt index b2b1f993..e72a68e 100644 --- a/third_party/blink/web_tests/external/wpt/workers/semantics/interface-objects/003-expected.txt +++ b/third_party/blink/web_tests/external/wpt/workers/semantics/interface-objects/003-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 64 tests; 59 PASS, 5 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 64 tests; 60 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN. FAIL The ApplicationCache interface object should be exposed assert_true: expected true got false PASS The WorkerGlobalScope interface object should be exposed PASS The SharedWorkerGlobalScope interface object should be exposed @@ -45,7 +45,7 @@ PASS The FileReader interface object should be exposed PASS The FileReaderSync interface object should be exposed PASS The EventTarget interface object should be exposed -FAIL The ErrorEvent interface object should be exposed assert_true: expected true got false +PASS The ErrorEvent interface object should be exposed PASS The Event interface object should be exposed PASS The CustomEvent interface object should be exposed PASS The DOMException interface object should be exposed
diff --git a/third_party/blink/web_tests/external/wpt/worklets/animation-worklet-csp.https.html b/third_party/blink/web_tests/external/wpt/worklets/animation-worklet-csp.https.html index a2364a4a..3950ea20 100644 --- a/third_party/blink/web_tests/external/wpt/worklets/animation-worklet-csp.https.html +++ b/third_party/blink/web_tests/external/wpt/worklets/animation-worklet-csp.https.html
@@ -1,15 +1,11 @@ <!DOCTYPE html> -<html> -<head> - <script src="/common/get-host-info.sub.js"></script> - <script src="/resources/testharness.js"></script> - <script src="/resources/testharnessreport.js"></script> - <script src="resources/worklet-test-utils.js"></script> - <script src="resources/csp-tests.js"></script> -</head> -<body> +<title>ContentSecurityPolicy for Animation Worklets</title> +<meta name="timeout" content="long"> +<script src="/common/get-host-info.sub.js"></script> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/worklet-test-utils.js"></script> +<script src="resources/csp-tests.js"></script> <script> - runContentSecurityPolicyTests("animation"); +runContentSecurityPolicyTests("animation"); </script> -</body> -</html>
diff --git a/third_party/blink/web_tests/external/wpt/worklets/audio-worklet-csp.https.html b/third_party/blink/web_tests/external/wpt/worklets/audio-worklet-csp.https.html index ef148a4..7601870 100644 --- a/third_party/blink/web_tests/external/wpt/worklets/audio-worklet-csp.https.html +++ b/third_party/blink/web_tests/external/wpt/worklets/audio-worklet-csp.https.html
@@ -1,15 +1,11 @@ <!DOCTYPE html> -<html> -<head> - <script src="/common/get-host-info.sub.js"></script> - <script src="/resources/testharness.js"></script> - <script src="/resources/testharnessreport.js"></script> - <script src="resources/worklet-test-utils.js"></script> - <script src="resources/csp-tests.js"></script> -</head> -<body> +<title>ContentSecurityPolicy for Audio Worklets</title> +<meta name="timeout" content="long"> +<script src="/common/get-host-info.sub.js"></script> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/worklet-test-utils.js"></script> +<script src="resources/csp-tests.js"></script> <script> - runContentSecurityPolicyTests("audio"); +runContentSecurityPolicyTests("audio"); </script> -</body> -</html>
diff --git a/third_party/blink/web_tests/fast/animation/scroll-animations/scrolltimeline-creation-no-document.html b/third_party/blink/web_tests/fast/animation/scroll-animations/scrolltimeline-creation-no-document.html deleted file mode 100644 index a3661235..0000000 --- a/third_party/blink/web_tests/fast/animation/scroll-animations/scrolltimeline-creation-no-document.html +++ /dev/null
@@ -1,11 +0,0 @@ -<!DOCTYPE html> -<script src='../../../resources/testharness.js'></script> -<script src='../../../resources/testharnessreport.js'></script> -<script> -test(function() { - document.documentElement.remove(); - const timeline = new ScrollTimeline({timeRange: 100}); - assert_equals(timeline.scrollSource, null); - assert_equals(timeline.currentTime, null); -}, 'The scrollSource can be null, if the document.scrollingElement does not exist'); -</script>
diff --git a/third_party/blink/web_tests/fast/animation/scroll-animations/scrolltimeline-currenttime.html b/third_party/blink/web_tests/fast/animation/scroll-animations/scrolltimeline-currenttime.html deleted file mode 100644 index 61e0b2c..0000000 --- a/third_party/blink/web_tests/fast/animation/scroll-animations/scrolltimeline-currenttime.html +++ /dev/null
@@ -1,616 +0,0 @@ -<!DOCTYPE html> - -<script src='resources/scroll-timeline-util.js'></script> -<script src='../../../resources/testharness.js'></script> -<script src='../../../resources/testharnessreport.js'></script> - -<body></body> - -<script> -// Builds a generic structure that looks like: -// -// <div class="scroller"> // 100x100 viewport -// <div class="contents"></div> // 500x500 -// </div> -// -// The |scrollerOverrides| and |contentOverrides| parameters are maps which -// are applied to the scroller and contents style after basic setup. -// -// Returns the outer 'scroller' element. -function setupScrollTimelineTest( - scrollerOverrides = new Map(), contentOverrides = new Map()) { - let scroller = document.createElement('div'); - scroller.style.width = '100px'; - scroller.style.height = '100px'; - scroller.style.overflow = 'scroll'; - for (const [key, value] of scrollerOverrides) { - scroller.style[key] = value; - } - - let contents = document.createElement('div'); - contents.style.width = '500px'; - contents.style.height = '500px'; - for (const [key, value] of contentOverrides) { - contents.style[key] = value; - } - - scroller.appendChild(contents); - document.body.appendChild(scroller); - return scroller; -} - -// Helper method to calculate the current time, implementing only step 5 of -// https://wicg.github.io/scroll-animations/#current-time-algorithm -function calculateCurrentTime( - currentScrollOffset, startScrollOffset, endScrollOffset, - effectiveTimeRange) { - return ((currentScrollOffset - startScrollOffset) / - (endScrollOffset - startScrollOffset)) * - effectiveTimeRange; -} - -test(function() { - const scroller = setupScrollTimelineTest(); - // For simplicity, we set the timeRange such that currentTime maps directly to - // the value scrolled. We have a square scroller/contents, so can just compute - // one edge and use it for all the timelines; - const scrollerSize = scroller.scrollHeight - scroller.clientHeight; - - const blockScrollTimeline = new ScrollTimeline( - {scrollSource: scroller, timeRange: scrollerSize, orientation: 'block'}); - const inlineScrollTimeline = new ScrollTimeline( - {scrollSource: scroller, timeRange: scrollerSize, orientation: 'inline'}); - const horizontalScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'horizontal' - }); - const verticalScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'vertical' - }); - - // Unscrolled, all timelines should read a currentTime of 0. - assert_equals(blockScrollTimeline.currentTime, 0); - assert_equals(inlineScrollTimeline.currentTime, 0); - assert_equals(horizontalScrollTimeline.currentTime, 0); - assert_equals(verticalScrollTimeline.currentTime, 0); - - // Now do some scrolling and make sure that the ScrollTimelines update. - scroller.scrollTop = 50; - scroller.scrollLeft = 75; - - // As noted above, we have mapped timeRange such that currentTime should just - // be the scroll offset. - assert_equals(blockScrollTimeline.currentTime, 50); - assert_equals(inlineScrollTimeline.currentTime, 75); - assert_equals(horizontalScrollTimeline.currentTime, 75); - assert_equals(verticalScrollTimeline.currentTime, 50); -}, 'currentTime calculates the correct time based on scrolled amount'); - -test(function() { - // It is unfortunately difficult to calculate what scroll offset results in an - // exact currentTime. Scrolling is calculated in integers which allows for the - // possibility of rounding, and scrollbar widths differ between platforms - // which means it is not possible to ensure a divisible scroller size. - // - // Instead we make the scroller content big enough that a 1-pixel rounding - // difference results in a negligible difference in the output value. - const contentOverrides = new Map([['width', '1000px'], ['height', '1000px']]); - const scroller = setupScrollTimelineTest(new Map(), contentOverrides); - const scrollTimeline = new ScrollTimeline( - {scrollSource: scroller, timeRange: 100, orientation: 'block'}); - - // Mapping timeRange to 100 gives a form of 'percentage scrolled', so - // calculate where the 50% scroll mark would be. - const halfwayY = (scroller.scrollHeight - scroller.clientHeight) / 2; - scroller.scrollTop = halfwayY; - - assert_approx_equals(scrollTimeline.currentTime, 50, 0.5); -}, 'currentTime adjusts correctly for the timeRange'); - -test(function() { - const scrollerOverrides = new Map([['direction', 'rtl']]); - const scroller = setupScrollTimelineTest(scrollerOverrides); - - // For simplicity, we set the timeRange such that currentTime maps directly to - // the value scrolled. We have a square scroller/contents, so can just compute - // one edge and use it for all the timelines. - const scrollerSize = scroller.scrollHeight - scroller.clientHeight; - - const blockScrollTimeline = new ScrollTimeline( - {scrollSource: scroller, timeRange: scrollerSize, orientation: 'block'}); - const inlineScrollTimeline = new ScrollTimeline( - {scrollSource: scroller, timeRange: scrollerSize, orientation: 'inline'}); - const horizontalScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'horizontal' - }); - const verticalScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'vertical' - }); - - // Unscrolled, all timelines should read a current time of 0 even though the - // X-axis will have started at the right hand side for rtl. - assert_equals(blockScrollTimeline.currentTime, 0); - assert_equals(inlineScrollTimeline.currentTime, 0); - assert_equals(horizontalScrollTimeline.currentTime, 0); - assert_equals(verticalScrollTimeline.currentTime, 0); - - // The offset in the inline/horizontal direction should be inverted. The - // block/vertical direction should be unaffected. - scroller.scrollTop = 50; - scroller.scrollLeft = 75; - - assert_equals(blockScrollTimeline.currentTime, 50); - assert_equals(inlineScrollTimeline.currentTime, scrollerSize - 75); - assert_equals(horizontalScrollTimeline.currentTime, scrollerSize - 75); - assert_equals(verticalScrollTimeline.currentTime, 50); -}, 'currentTime handles direction: rtl correctly'); - -test(function() { - const scrollerOverrides = new Map([['writing-mode', 'vertical-rl']]); - const scroller = setupScrollTimelineTest(scrollerOverrides); - - // For simplicity, we set the timeRange such that currentTime maps directly to - // the value scrolled. We have a square scroller/contents, so can just compute - // one edge and use it for all the timelines. - const scrollerSize = scroller.scrollHeight - scroller.clientHeight; - - const blockScrollTimeline = new ScrollTimeline( - {scrollSource: scroller, timeRange: scrollerSize, orientation: 'block'}); - const inlineScrollTimeline = new ScrollTimeline( - {scrollSource: scroller, timeRange: scrollerSize, orientation: 'inline'}); - const horizontalScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'horizontal' - }); - const verticalScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'vertical' - }); - - // Unscrolled, all timelines should read a current time of 0 even though the - // X-axis will have started at the right hand side for vertical-rl. - assert_equals(blockScrollTimeline.currentTime, 0); - assert_equals(inlineScrollTimeline.currentTime, 0); - assert_equals(horizontalScrollTimeline.currentTime, 0); - assert_equals(verticalScrollTimeline.currentTime, 0); - - // For vertical-rl, the X-axis starts on the right-hand-side and is the block - // axis. The Y-axis is normal but is the inline axis. For the - // horizontal/vertical cases, horizontal starts on the right-hand-side and - // vertical is normal. - scroller.scrollTop = 50; - scroller.scrollLeft = 75; - - assert_equals(blockScrollTimeline.currentTime, scrollerSize - 75); - assert_equals(inlineScrollTimeline.currentTime, 50); - assert_equals(horizontalScrollTimeline.currentTime, scrollerSize - 75); - assert_equals(verticalScrollTimeline.currentTime, 50); -}, 'currentTime handles writing-mode: vertical-rl correctly'); - -test(function() { - const scrollerOverrides = new Map([['writing-mode', 'vertical-lr']]); - const scroller = setupScrollTimelineTest(scrollerOverrides); - - // For simplicity, we set the timeRange such that currentTime maps directly to - // the value scrolled. We have a square scroller/contents, so can just compute - // one edge and use it for all the timelines. - const scrollerSize = scroller.scrollHeight - scroller.clientHeight; - - const blockScrollTimeline = new ScrollTimeline( - {scrollSource: scroller, timeRange: scrollerSize, orientation: 'block'}); - const inlineScrollTimeline = new ScrollTimeline( - {scrollSource: scroller, timeRange: scrollerSize, orientation: 'inline'}); - const horizontalScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'horizontal' - }); - const verticalScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'vertical' - }); - - // Unscrolled, all timelines should read a current time of 0. - assert_equals(blockScrollTimeline.currentTime, 0); - assert_equals(inlineScrollTimeline.currentTime, 0); - assert_equals(horizontalScrollTimeline.currentTime, 0); - assert_equals(verticalScrollTimeline.currentTime, 0); - - // For vertical-lr, both axes start at their 'normal' positions but the X-axis - // is the block direction and the Y-axis is the inline direction. This does - // not affect horizontal/vertical. - scroller.scrollTop = 50; - scroller.scrollLeft = 75; - - assert_equals(blockScrollTimeline.currentTime, 75); - assert_equals(inlineScrollTimeline.currentTime, 50); - assert_equals(horizontalScrollTimeline.currentTime, 75); - assert_equals(verticalScrollTimeline.currentTime, 50); -}, 'currentTime handles writing-mode: vertical-lr correctly'); - -test(function() { - const scroller = setupScrollTimelineTest(); - // For simplicity, we set the timeRange such that currentTime maps directly to - // the value scrolled. We have a square scroller/contents, so can just compute - // one edge and use it for all the timelines; - const scrollerSize = scroller.scrollHeight - scroller.clientHeight; - - const lengthScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'block', - startScrollOffset: '20px' - }); - const percentageScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'block', - startScrollOffset: '20%' - }); - const calcScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'block', - startScrollOffset: 'calc(20% - 5px)' - }); - - // Unscrolled, all timelines should read a current time of unresolved, since - // the current offset (0) will be less than the startScrollOffset. - assert_equals(lengthScrollTimeline.currentTime, null); - assert_equals(percentageScrollTimeline.currentTime, null); - assert_equals(calcScrollTimeline.currentTime, null); - - // Check the length-based ScrollTimeline. - scroller.scrollTop = 19; - assert_equals(lengthScrollTimeline.currentTime, null); - scroller.scrollTop = 20; - assert_equals(lengthScrollTimeline.currentTime, 0); - scroller.scrollTop = 50; - assert_equals( - lengthScrollTimeline.currentTime, - calculateCurrentTime(50, 20, scrollerSize, scrollerSize)); - scroller.scrollTop = 200; - assert_equals( - lengthScrollTimeline.currentTime, - calculateCurrentTime(200, 20, scrollerSize, scrollerSize)); - - // Check the percentage-based ScrollTimeline. - scroller.scrollTop = 0.19 * scrollerSize; - assert_equals(percentageScrollTimeline.currentTime, null); - scroller.scrollTop = 0.20 * scrollerSize; - assert_equals(percentageScrollTimeline.currentTime, 0); - scroller.scrollTop = 0.50 * scrollerSize; - assert_equals( - percentageScrollTimeline.currentTime, - calculateCurrentTime( - scroller.scrollTop, 0.2 * scrollerSize, scrollerSize, scrollerSize)); - - // Check the calc-based ScrollTimeline. - scroller.scrollTop = 0.2 * scrollerSize - 10; - assert_equals(calcScrollTimeline.currentTime, null); - scroller.scrollTop = 0.2 * scrollerSize - 5; - assert_equals(calcScrollTimeline.currentTime, 0); - scroller.scrollTop = 0.2 * scrollerSize; - assert_equals( - calcScrollTimeline.currentTime, - calculateCurrentTime( - scroller.scrollTop, 0.2 * scrollerSize - 5, scrollerSize, - scrollerSize)); - scroller.scrollTop = 0.5 * scrollerSize; - assert_equals( - calcScrollTimeline.currentTime, - calculateCurrentTime( - scroller.scrollTop, 0.2 * scrollerSize - 5, scrollerSize, - scrollerSize)); -}, 'currentTime handles startScrollOffset correctly'); - -test(function() { - const scrollerOverrides = new Map([['direction', 'rtl']]); - const scroller = setupScrollTimelineTest(scrollerOverrides); - // For simplicity, we set the timeRange such that currentTime maps directly to - // the value scrolled. We have a square scroller/contents, so can just compute - // one edge and use it for all the timelines; - const scrollerSize = scroller.scrollHeight - scroller.clientHeight; - - const lengthScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'horizontal', - startScrollOffset: '20px' - }); - const percentageScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'horizontal', - startScrollOffset: '20%' - }); - const calcScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'horizontal', - startScrollOffset: 'calc(20% - 5px)' - }); - - // Unscrolled, all timelines should read a current time of unresolved, since - // the current offset (0) will be less than the startScrollOffset. - assert_equals(lengthScrollTimeline.currentTime, null); - assert_equals(percentageScrollTimeline.currentTime, null); - assert_equals(calcScrollTimeline.currentTime, null); - - // With direction rtl offsets are inverted, such that scrollLeft == - // scrollerSize is the 'zero' point for currentTime. However the - // startScrollOffset is an absolute distance along the offset, so doesn't - // need adjusting. - - // Check the length-based ScrollTimeline. - scroller.scrollLeft = scrollerSize; - assert_equals(lengthScrollTimeline.currentTime, null); - scroller.scrollLeft = scrollerSize - 20; - assert_equals(lengthScrollTimeline.currentTime, 0); - scroller.scrollLeft = scrollerSize - 50; - assert_equals( - lengthScrollTimeline.currentTime, - calculateCurrentTime(50, 20, scrollerSize, scrollerSize)); - scroller.scrollLeft = scrollerSize - 200; - assert_equals( - lengthScrollTimeline.currentTime, - calculateCurrentTime(200, 20, scrollerSize, scrollerSize)); - - // Check the percentage-based ScrollTimeline. - scroller.scrollLeft = scrollerSize - (0.19 * scrollerSize); - assert_equals(percentageScrollTimeline.currentTime, null); - scroller.scrollLeft = scrollerSize - (0.20 * scrollerSize); - assert_equals(percentageScrollTimeline.currentTime, 0); - scroller.scrollLeft = scrollerSize - (0.4 * scrollerSize); - assert_equals( - percentageScrollTimeline.currentTime, - calculateCurrentTime( - 0.4 * scrollerSize, 0.2 * scrollerSize, scrollerSize, scrollerSize)); - - // Check the calc-based ScrollTimeline. - scroller.scrollLeft = scrollerSize - (0.2 * scrollerSize - 10); - assert_equals(calcScrollTimeline.currentTime, null); - scroller.scrollLeft = scrollerSize - (0.2 * scrollerSize - 5); - assert_equals(calcScrollTimeline.currentTime, 0); - scroller.scrollLeft = scrollerSize - (0.2 * scrollerSize); - assert_equals( - calcScrollTimeline.currentTime, - calculateCurrentTime( - 0.2 * scrollerSize, 0.2 * scrollerSize - 5, scrollerSize, - scrollerSize)); - scroller.scrollLeft = scrollerSize - (0.4 * scrollerSize); - assert_equals( - calcScrollTimeline.currentTime, - calculateCurrentTime( - 0.4 * scrollerSize, 0.2 * scrollerSize - 5, scrollerSize, - scrollerSize)); -}, 'currentTime handles startScrollOffset with direction: rtl correctly'); - -test(function() { - const scroller = setupScrollTimelineTest(); - // For simplicity, we set the timeRange such that currentTime maps directly to - // the value scrolled. We have a square scroller/contents, so can just compute - // one edge and use it for all the timelines; - const scrollerSize = scroller.scrollHeight - scroller.clientHeight; - - const lengthScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'block', - endScrollOffset: (scrollerSize - 20) + 'px' - }); - const percentageScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'block', - endScrollOffset: '80%' - }); - const calcScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'block', - endScrollOffset: 'calc(80% + 5px)' - }); - - // Check the length-based ScrollTimeline. - scroller.scrollTop = scrollerSize; - assert_equals(lengthScrollTimeline.currentTime, null); - scroller.scrollTop = scrollerSize - 20; - assert_equals( - lengthScrollTimeline.currentTime, - calculateCurrentTime( - scrollerSize - 20, 0, scrollerSize - 20, scrollerSize)); - scroller.scrollTop = scrollerSize - 50; - assert_equals( - lengthScrollTimeline.currentTime, - calculateCurrentTime( - scrollerSize - 50, 0, scrollerSize - 20, scrollerSize)); - scroller.scrollTop = scrollerSize - 200; - assert_equals( - lengthScrollTimeline.currentTime, - calculateCurrentTime( - scrollerSize - 200, 0, scrollerSize - 20, scrollerSize)); - - // Check the percentage-based ScrollTimeline. - scroller.scrollTop = 0.81 * scrollerSize; - assert_equals(percentageScrollTimeline.currentTime, null); - scroller.scrollTop = 0.80 * scrollerSize; - assert_equals( - percentageScrollTimeline.currentTime, - calculateCurrentTime( - scroller.scrollTop, 0, 0.8 * scrollerSize, scrollerSize)); - scroller.scrollTop = 0.50 * scrollerSize; - assert_equals( - percentageScrollTimeline.currentTime, - calculateCurrentTime( - scroller.scrollTop, 0, 0.8 * scrollerSize, scrollerSize)); - - // Check the calc-based ScrollTimeline. - scroller.scrollTop = 0.8 * scrollerSize + 6; - assert_equals(calcScrollTimeline.currentTime, null); - scroller.scrollTop = 0.8 * scrollerSize + 5; - assert_equals( - calcScrollTimeline.currentTime, - calculateCurrentTime( - scroller.scrollTop, 0, 0.8 * scrollerSize + 5, scrollerSize)); - scroller.scrollTop = 0.5 * scrollerSize; - assert_equals( - calcScrollTimeline.currentTime, - calculateCurrentTime( - scroller.scrollTop, 0, 0.8 * scrollerSize + 5, scrollerSize)); -}, 'currentTime handles endScrollOffset correctly'); - -test(function() { - const scrollerOverrides = new Map([['direction', 'rtl']]); - const scroller = setupScrollTimelineTest(scrollerOverrides); - // For simplicity, we set the timeRange such that currentTime maps directly to - // the value scrolled. We have a square scroller/contents, so can just compute - // one edge and use it for all the timelines; - const scrollerSize = scroller.scrollHeight - scroller.clientHeight; - - const lengthScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'horizontal', - endScrollOffset: (scrollerSize - 20) + 'px' - }); - const percentageScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'horizontal', - endScrollOffset: '80%' - }); - const calcScrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'horizontal', - endScrollOffset: 'calc(80% + 5px)' - }); - - // With direction rtl offsets are inverted, such that scrollLeft == - // scrollerSize is the 'zero' point for currentTime. However the - // endScrollOffset is an absolute distance along the offset, so doesn't need - // adjusting. - - // Check the length-based ScrollTimeline. - scroller.scrollLeft = 0; - assert_equals(lengthScrollTimeline.currentTime, null); - scroller.scrollLeft = 20; - assert_equals( - lengthScrollTimeline.currentTime, - calculateCurrentTime( - scrollerSize - 20, 0, scrollerSize - 20, scrollerSize)); - scroller.scrollLeft = 50; - assert_equals( - lengthScrollTimeline.currentTime, - calculateCurrentTime( - scrollerSize - 50, 0, scrollerSize - 20, scrollerSize)); - scroller.scrollLeft = 200; - assert_equals( - lengthScrollTimeline.currentTime, - calculateCurrentTime( - scrollerSize - 200, 0, scrollerSize - 20, scrollerSize)); - - // Check the percentage-based ScrollTimeline. - scroller.scrollLeft = 0.19 * scrollerSize; - assert_equals(percentageScrollTimeline.currentTime, null); - scroller.scrollLeft = 0.20 * scrollerSize; - assert_equals( - percentageScrollTimeline.currentTime, - calculateCurrentTime( - 0.8 * scrollerSize, 0, 0.8 * scrollerSize, scrollerSize)); - scroller.scrollLeft = 0.4 * scrollerSize; - assert_equals( - percentageScrollTimeline.currentTime, - calculateCurrentTime( - 0.6 * scrollerSize, 0, 0.8 * scrollerSize, scrollerSize)); - - // Check the calc-based ScrollTimeline. 80% + 5px - scroller.scrollLeft = 0.2 * scrollerSize - 10; - assert_equals(calcScrollTimeline.currentTime, null); - scroller.scrollLeft = 0.2 * scrollerSize - 5; - assert_equals( - calcScrollTimeline.currentTime, - calculateCurrentTime( - 0.8 * scrollerSize + 5, 0, 0.8 * scrollerSize + 5, scrollerSize)); - scroller.scrollLeft = 0.2 * scrollerSize; - assert_equals( - calcScrollTimeline.currentTime, - calculateCurrentTime( - 0.8 * scrollerSize, 0, 0.8 * scrollerSize + 5, scrollerSize)); - scroller.scrollLeft = 0.6 * scrollerSize; - assert_equals( - calcScrollTimeline.currentTime, - calculateCurrentTime( - 0.4 * scrollerSize, 0, 0.8 * scrollerSize + 5, scrollerSize)); -}, 'currentTime handles endScrollOffset with direction: rtl correctly'); - -test(function() { - const scroller = setupScrollTimelineTest(); - // For simplicity, we set the timeRange such that currentTime maps directly to - // the value scrolled. We have a square scroller/contents, so can just compute - // one edge and use it for all the timelines; - const scrollerSize = scroller.scrollHeight - scroller.clientHeight; - - const scrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'block', - startScrollOffset: '20px', - endScrollOffset: (scrollerSize - 50) + 'px' - }); - - scroller.scrollTop = 150; - assert_equals( - scrollTimeline.currentTime, - calculateCurrentTime(150, 20, scrollerSize - 50, scrollerSize)); -}, 'currentTime handles startScrollOffset and endScrollOffset together correctly'); - -test(function() { - const scroller = setupScrollTimelineTest(); - // For simplicity, we set the timeRange such that currentTime maps directly to - // the value scrolled. We have a square scroller/contents, so can just compute - // one edge and use it for all the timelines; - const scrollerSize = scroller.scrollHeight - scroller.clientHeight; - - const scrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'block', - startScrollOffset: '20px', - endScrollOffset: '20px', - }); - - scroller.scrollTop = 150; - assert_equals(scrollTimeline.currentTime, null); -}, 'currentTime handles startScrollOffset == endScrollOffset correctly'); - -test(function() { - const scroller = setupScrollTimelineTest(); - // For simplicity, we set the timeRange such that currentTime maps directly to - // the value scrolled. We have a square scroller/contents, so can just compute - // one edge and use it for all the timelines; - const scrollerSize = scroller.scrollHeight - scroller.clientHeight; - - const scrollTimeline = new ScrollTimeline({ - scrollSource: scroller, - timeRange: scrollerSize, - orientation: 'block', - startScrollOffset: '50px', - endScrollOffset: '10px', - }); - - scroller.scrollTop = 150; - assert_equals(scrollTimeline.currentTime, null); -}, 'currentTime handles startScrollOffset > endScrollOffset correctly'); -</script>
diff --git a/third_party/blink/web_tests/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt b/third_party/blink/web_tests/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt index c5c1822..475ca2d 100644 --- a/third_party/blink/web_tests/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt +++ b/third_party/blink/web_tests/fast/borders/overflow-hidden-border-radius-force-backing-store-expected.txt
@@ -23,24 +23,6 @@ "bounds": [300, 300] }, { - "name": "Child Containment Layer", - "position": [50, 50], - "bounds": [300, 300], - "drawsContent": false, - "maskLayer": [ - { - "name": "Child Clipping Mask Layer", - "bounds": [300, 300] - } - ] - }, - { - "name": "Ancestor Clipping Layer", - "position": [50, 50], - "bounds": [285, 300], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV id='content'", "bounds": [285, 1000], "contentsOpaque": true, @@ -55,8 +37,7 @@ [0, 1, 0, 0], [0, 0, 1, 0], [50, 50, 0, 1] - ], - "flattenInheritedTransform": false + ] } ] }
diff --git a/third_party/blink/web_tests/fast/dom/Window/window-postmessage-user-gesture-expected.txt b/third_party/blink/web_tests/fast/dom/Window/window-postmessage-user-gesture-expected.txt index eaa0e8a..9a165aff 100644 --- a/third_party/blink/web_tests/fast/dom/Window/window-postmessage-user-gesture-expected.txt +++ b/third_party/blink/web_tests/fast/dom/Window/window-postmessage-user-gesture-expected.txt
@@ -1,8 +1,8 @@ -Test that user gesture is available through postMessages to appropriate frames. +Test that user gesture is kept when postMessage() to self or across frames. Click me PASS Stack postMessages on self window and the user gesture is only consumed once PASS Bounce postMessages between self and frame window and the user gesture is consumed only once in self window -PASS Bounce postMessages between self and frame window and the user gesture is consumed 0 times in frame +PASS Bounce postMessages between self and frame window and the user gesture is consumed only once in frame PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/fast/dom/Window/window-postmessage-user-gesture.html b/third_party/blink/web_tests/fast/dom/Window/window-postmessage-user-gesture.html index 5e6d400..eb5b00e8 100644 --- a/third_party/blink/web_tests/fast/dom/Window/window-postmessage-user-gesture.html +++ b/third_party/blink/web_tests/fast/dom/Window/window-postmessage-user-gesture.html
@@ -3,7 +3,7 @@ <script src="../../../resources/js-test.js"></script> </head> <body> -<div id="description">Test that user gesture is available through postMessages to appropriate frames.</div> +<div id="description">Test that user gesture is kept when postMessage() to self or across frames.</div> <div id="div1" onclick="clickHandler()">Click me</div> <iframe id="subframe" src="resources/window-postmessage-user-gesture-frame.html" onload="startTest()"></iframe> <div id="console"></div> @@ -62,9 +62,6 @@ (consumeInFrame ? "in frame" : "in self window"); var consumeCountIsCorrect = (msg.consumeCount == 1); - if (internals.runtimeFlags.userActivationV2Enabled) - consumeCountIsCorrect = (!consumeInFrame && msg.consumeCount == 1) || - (consumeInFrame && msg.consumeCount == 0); if (consumeCountIsCorrect) testPassed(outputStr);
diff --git a/third_party/blink/web_tests/fast/events/open-window-from-another-frame-expected.txt b/third_party/blink/web_tests/fast/events/open-window-from-another-frame-expected.txt index 7a6533d..bd2118e8 100644 --- a/third_party/blink/web_tests/fast/events/open-window-from-another-frame-expected.txt +++ b/third_party/blink/web_tests/fast/events/open-window-from-another-frame-expected.txt
@@ -1,8 +1,8 @@ -This tests that window.open from a subframe doesn't work with main frame activation. +This tests that window.open works across frames. To run manually click the link below. GreenBox or Success page. -Window was not opened! Test succeeded! +Window was opened! Test succeeded! --------
diff --git a/third_party/blink/web_tests/fast/events/open-window-from-another-frame.html b/third_party/blink/web_tests/fast/events/open-window-from-another-frame.html index 882e135..ab8791be 100644 --- a/third_party/blink/web_tests/fast/events/open-window-from-another-frame.html +++ b/third_party/blink/web_tests/fast/events/open-window-from-another-frame.html
@@ -32,7 +32,7 @@ </script> </head> <body onload="test()"> - This tests that window.open from a subframe doesn't work with main frame activation.<br> + This tests that window.open works across frames.<br> To run manually click the link below.<br> <a href="resources/greenbox.png" id="link">GreenBox or Success page.</a><br> <iframe src="resources/open-window-from-another-frame-otherFrame.html" name="otherFrame"></iframe>
diff --git a/third_party/blink/web_tests/fast/events/resources/open-window-from-another-frame-otherFrame.html b/third_party/blink/web_tests/fast/events/resources/open-window-from-another-frame-otherFrame.html index 17f2172..c9b89bb 100644 --- a/third_party/blink/web_tests/fast/events/resources/open-window-from-another-frame-otherFrame.html +++ b/third_party/blink/web_tests/fast/events/resources/open-window-from-another-frame-otherFrame.html
@@ -15,17 +15,9 @@ function handleClick(event) { var newWin = window.open('resources/window-opened.html', 'badName', 'width=100, height=100'); - if (!internals.runtimeFlags.userActivationV2Enabled) { - if (newWin) { - parent.log("Window was opened! Test succeeded!"); - closeWin(newWin); - } - } else { - if (!newWin) { - parent.log("Window was not opened! Test succeeded!"); - if (window.testRunner) - testRunner.notifyDone(); - } + if (newWin) { + parent.log("Window was opened! Test succeeded!"); + closeWin(newWin); } event.preventDefault();
diff --git a/third_party/blink/web_tests/fast/repaint/OWNERS b/third_party/blink/web_tests/fast/repaint/OWNERS deleted file mode 100644 index 6904c86..0000000 --- a/third_party/blink/web_tests/fast/repaint/OWNERS +++ /dev/null
@@ -1,2 +0,0 @@ -# TEAM: paint-dev@chromium.org -# COMPONENT: Blink>Paint
diff --git a/third_party/blink/web_tests/fast/spatial-navigation/resources/snav-testharness.js b/third_party/blink/web_tests/fast/spatial-navigation/resources/snav-testharness.js index b9b02fd4..ab6a841 100644 --- a/third_party/blink/web_tests/fast/spatial-navigation/resources/snav-testharness.js +++ b/third_party/blink/web_tests/fast/spatial-navigation/resources/snav-testharness.js
@@ -2,6 +2,7 @@ "use strict"; let gAsyncTest; + let gPostAssertsFunc; // TODO: Use WebDriver's API instead of eventSender. // Hopefully something like: @@ -60,6 +61,8 @@ function stepAndAssertMoves(expectedMoves) { if (expectedMoves.length == 0) { + if (gPostAssertsFunc) + gAsyncTest.step(gPostAssertsFunc); gAsyncTest.done(); return; } @@ -95,9 +98,11 @@ }, 'window.testRunner is present.'); }, - assertFocusMoves: function(expectedMoves, enableSpatnav=true) { + assertFocusMoves: function(expectedMoves, enableSpatnav=true, postAssertsFunc=null) { if (enableSpatnav) snav.assertSnavEnabledAndTestable(); + if (postAssertsFunc) + gPostAssertsFunc = postAssertsFunc; gAsyncTest = async_test("Focus movements:\n" + JSON.stringify(expectedMoves).replace(/],/g, ']\n') + '\n');
diff --git a/third_party/blink/web_tests/fast/spatial-navigation/snav-div-scrollable-but-without-focusable-content.html b/third_party/blink/web_tests/fast/spatial-navigation/snav-div-scrollable-but-without-focusable-content.html index c93c587..2a479f6 100644 --- a/third_party/blink/web_tests/fast/spatial-navigation/snav-div-scrollable-but-without-focusable-content.html +++ b/third_party/blink/web_tests/fast/spatial-navigation/snav-div-scrollable-but-without-focusable-content.html
@@ -43,6 +43,9 @@ ["Up" , "scrollerB"], ["Up" , "scrollerB"], ["Up" , "scrollerB"], + ["Up" , "scrollerB"], + ["Up" , "scrollerB"], + ["Up" , "scrollerB"], ["Up" , "scrollerA"], ["Up" , "start"], ];
diff --git a/third_party/blink/web_tests/fast/spatial-navigation/snav-dont-search-focused-offscreen-scroller.html b/third_party/blink/web_tests/fast/spatial-navigation/snav-dont-search-focused-offscreen-scroller.html new file mode 100644 index 0000000..d4375e0 --- /dev/null +++ b/third_party/blink/web_tests/fast/spatial-navigation/snav-dont-search-focused-offscreen-scroller.html
@@ -0,0 +1,30 @@ +<!doctype html> +<div id="start" tabindex="0" style="overflow-y: scroll; height: 35px; margin-top: 100%"> + <br><br><br> + <p>Text</p> +</div> + +<p>Don't search inside or scroll the focused scrollable element when it is offscreen.</p> + +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="resources/snav-testharness.js"></script> +<script> + var resultMap = [ + ["Down", "start"], // Scroll performed at Window + ]; + + let start = document.getElementById("start"); + + function postFocusMoveCheck() { + assert_equals(start.scrollTop, 0, "Offscreen scroller shouldn't be scrolled."); + } + + start.focus({preventScroll:true}); + + test(function() { + assert_equals(window.scrollY, 0); + }, "Window shouldn't be scrolled by focus.") + + snav.assertFocusMoves(resultMap, true, postFocusMoveCheck); +</script>
diff --git a/third_party/blink/web_tests/fast/spatial-navigation/snav-search-focused-scroller-first.html b/third_party/blink/web_tests/fast/spatial-navigation/snav-search-focused-scroller-first.html new file mode 100644 index 0000000..6cec3fd --- /dev/null +++ b/third_party/blink/web_tests/fast/spatial-navigation/snav-search-focused-scroller-first.html
@@ -0,0 +1,22 @@ +<!doctype html> +<div id="start" tabindex="0" style="overflow-y: scroll; width: 150px; height: 150px"> + <a id="link" href="#" style="display: inline-block; margin-top: 150px">Link</a> +</div> +<a id="end" href="#">End</a> + +<p>Search inside the focused scrollable element before searching outside of it.</p> + +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="resources/snav-testharness.js"></script> +<script> + var resultMap = [ + ["Down", "start"], // Scrolled + ["Down", "link"], + ["Down", "end"], + ]; + + // Start at a known place. + document.getElementById("start").focus(); + snav.assertFocusMoves(resultMap); +</script>
diff --git a/third_party/blink/web_tests/fast/text/absolute-in-inline-block-change-crash-expected.txt b/third_party/blink/web_tests/fast/text/absolute-in-inline-block-change-crash-expected.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/third_party/blink/web_tests/fast/text/absolute-in-inline-block-change-crash-expected.txt
@@ -0,0 +1 @@ +
diff --git a/third_party/blink/web_tests/fast/text/absolute-in-inline-block-change-crash.html b/third_party/blink/web_tests/fast/text/absolute-in-inline-block-change-crash.html new file mode 100644 index 0000000..dd4d5c9 --- /dev/null +++ b/third_party/blink/web_tests/fast/text/absolute-in-inline-block-change-crash.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<body> + <div style="position: relative"> + <div style="display: inline-block"> + <span id=abs style="position: absolute"></span> + </div> + </div> +<script> +if (window.testRunner) + testRunner.dumpAsText(); + +document.body.offsetTop; +//abs.appendChild(document.createTextNode('abs')); +abs.style.top = '0'; +</script> +</body>
diff --git a/third_party/blink/web_tests/fast/text/justify-empty-line-crash-expected.html b/third_party/blink/web_tests/fast/text/justify-empty-line-crash-expected.html new file mode 100644 index 0000000..918bd31 --- /dev/null +++ b/third_party/blink/web_tests/fast/text/justify-empty-line-crash-expected.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<style> +p { + text-align: justify; +} +</style> +<p>Test pass if it does not crash.</p> +<p></p>
diff --git a/third_party/blink/web_tests/fast/text/justify-empty-line-crash.html b/third_party/blink/web_tests/fast/text/justify-empty-line-crash.html new file mode 100644 index 0000000..9cc8f30 --- /dev/null +++ b/third_party/blink/web_tests/fast/text/justify-empty-line-crash.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<style> +p { + text-align: justify; +} +</style> +<p>Test pass if it does not crash.</p> +<p><span style="position: absolute"></span></p>
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/direct-image-compositing-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/direct-image-compositing-expected.png new file mode 100644 index 0000000..bb3c623 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/direct-image-compositing-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/flat-with-transformed-child-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/flat-with-transformed-child-expected.png new file mode 100644 index 0000000..2b04e99 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/flat-with-transformed-child-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/fixed-position-transform-composited-page-scale-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/fixed-position-transform-composited-page-scale-expected.png new file mode 100644 index 0000000..dba55d6 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/fixed-position-transform-composited-page-scale-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/layer-due-to-layer-children-deep-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/layer-due-to-layer-children-deep-expected.png index b01a0638..53b62c7 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/layer-due-to-layer-children-deep-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/layer-due-to-layer-children-deep-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/layer-due-to-layer-children-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/layer-due-to-layer-children-expected.png new file mode 100644 index 0000000..0cc88ee --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/geometry/layer-due-to-layer-children-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/lots-of-img-layers-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/lots-of-img-layers-expected.png new file mode 100644 index 0000000..922d3110 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/lots-of-img-layers-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/lots-of-img-layers-with-opacity-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/lots-of-img-layers-with-opacity-expected.png new file mode 100644 index 0000000..15a601b --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/lots-of-img-layers-with-opacity-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/masks/mask-layer-size-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/masks/mask-layer-size-expected.txt new file mode 100644 index 0000000..2d856c8 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/masks/mask-layer-size-expected.txt
@@ -0,0 +1,34 @@ +{ + "layers": [ + { + "name": "Scrolling background of LayoutView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow DIV id='masked'", + "bounds": [400, 200], + "contentsOpaque": true, + "backgroundColor": "#000000", + "transform": 1 + }, + { + "name": "LayoutBlockFlow DIV id='masked'", + "bounds": [400, 200], + "transform": 1 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [10, 10, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/masks/mask-with-added-filters-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/masks/mask-with-added-filters-expected.png index 0c9e438..e912d1c9 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/masks/mask-with-added-filters-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/masks/mask-with-added-filters-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/mask-with-filter-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/mask-with-filter-expected.png new file mode 100644 index 0000000..d2e7bbd --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/mask-with-filter-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/nested-render-surfaces-with-rotation-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/nested-render-surfaces-with-rotation-expected.png new file mode 100644 index 0000000..672088db --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/nested-render-surfaces-with-rotation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/reflections/nested-reflection-anchor-point-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/reflections/nested-reflection-anchor-point-expected.png new file mode 100644 index 0000000..4b133a0 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/reflections/nested-reflection-anchor-point-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/reflections/nested-reflection-animated-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/reflections/nested-reflection-animated-expected.png deleted file mode 100644 index ef56548..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/reflections/nested-reflection-animated-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/transitions/scale-transition-no-start-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/transitions/scale-transition-no-start-expected.png deleted file mode 100644 index 6512bdce..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/transitions/scale-transition-no-start-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/video/video-controls-squashing-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/video/video-controls-squashing-expected.png new file mode 100644 index 0000000..200b5da3 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/video/video-controls-squashing-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/visibility/visibility-image-layers-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/visibility/visibility-image-layers-expected.png index ae2e8a6..d515bc0 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/visibility/visibility-image-layers-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/visibility/visibility-image-layers-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png new file mode 100644 index 0000000..1381bae --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/effect-background-blend-mode-stacking-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/effect-background-blend-mode-stacking-expected.png deleted file mode 100644 index f2ef4f51..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/effect-background-blend-mode-stacking-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/mix-blend-mode-isolated-group-1-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/mix-blend-mode-isolated-group-1-expected.png index bb961226..3ea6bcd 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/mix-blend-mode-isolated-group-1-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/mix-blend-mode-isolated-group-1-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/mix-blend-mode-isolated-group-2-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/mix-blend-mode-isolated-group-2-expected.png index 99335e0d..34798702 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/mix-blend-mode-isolated-group-2-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/mix-blend-mode-isolated-group-2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/mix-blend-mode-isolated-group-3-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/mix-blend-mode-isolated-group-3-expected.png index 24252b1..da77527 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/mix-blend-mode-isolated-group-3-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/mix-blend-mode-isolated-group-3-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/svg-blend-exclusion-expected.html b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/svg-blend-exclusion-expected.html new file mode 100644 index 0000000..08743c5 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/svg-blend-exclusion-expected.html
@@ -0,0 +1,36 @@ +<!DOCTYPE HTML> +<html> +<body> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="400px" height="400px"> +<defs> + <g id="patch"> + <rect x="0" y="0" width="10" height="40" fill="rgb(255,0,0)"></rect> + <rect x="10" y="0" width="10" height="40" fill="rgb(0,255,0)"></rect> + <rect x="20" y="0" width="10" height="40" fill="rgb(0,0,255)"></rect> + <rect x="30" y="0" width="10" height="40" fill="rgb(255,255,0)"></rect> + </g> + <rect x="0" y="0" width="10" height="10" fill="rgb(255,0,0)"></rect> +</defs> +<g transform="scale(4 4)"> + <g> + <rect x="0" y="0" width="10" height="10" fill="rgba(0,0,0,1)"></rect> + <rect x="10" y="0" width="10" height="10" fill="rgba(255,255,0,1)"></rect> + <rect x="20" y="0" width="10" height="10" fill="rgba(255,0,255,1)"></rect> + <rect x="30" y="0" width="10" height="10" fill="rgba(128,127,0,1)"></rect> + <rect x="0" y="10" width="10" height="10" fill="rgba(255,255,0,1)"></rect> + <rect x="10" y="10" width="10" height="10" fill="rgba(0,0,0,1)"></rect> + <rect x="20" y="10" width="10" height="10" fill="rgba(0,255,255,1)"></rect> + <rect x="30" y="10" width="10" height="10" fill="rgba(127,128,0,1)"></rect> + <rect x="0" y="20" width="10" height="10" fill="rgba(255,0,255,1)"></rect> + <rect x="10" y="20" width="10" height="10" fill="rgba(0,255,255,1)"></rect> + <rect x="20" y="20" width="10" height="10" fill="rgba(0,0,0,1)"></rect> + <rect x="30" y="20" width="10" height="10" fill="rgba(127,127,255,1)"></rect> + <rect x="0" y="30" width="10" height="10" fill="rgba(128,127,0,1)"></rect> + <rect x="10" y="30" width="10" height="10" fill="rgba(127,128,0,1)"></rect> + <rect x="20" y="30" width="10" height="10" fill="rgba(127,127,255,1)"></rect> + <rect x="30" y="30" width="10" height="10" fill="rgba(127,127,0,1)"></rect> + </g> +</g> +</svg> +</body> +</html>
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/svg-blend-multiply-expected.html b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/svg-blend-multiply-expected.html new file mode 100644 index 0000000..d34d3ec0 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/svg-blend-multiply-expected.html
@@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> +<body> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="400px" height="400px"> +<g transform="scale(4 4)"> + <g> + <rect x="0" y="0" width="10" height="10" fill="rgba(255,0,0,1)"></rect> + <rect x="10" y="0" width="10" height="10" fill="rgba(0,0,0,1)"></rect> + <rect x="20" y="0" width="10" height="10" fill="rgba(0,0,0,1)"></rect> + <rect x="30" y="0" width="10" height="10" fill="rgba(127,0,0,1)"></rect> + <rect x="0" y="10" width="10" height="10" fill="rgba(0,0,0,1)"></rect> + <rect x="10" y="10" width="10" height="10" fill="rgba(0,255,0,1)"></rect> + <rect x="20" y="10" width="10" height="10" fill="rgba(0,0,0,1)"></rect> + <rect x="30" y="10" width="10" height="10" fill="rgba(0,127,0,1)"></rect> + <rect x="0" y="20" width="10" height="10" fill="rgba(0,0,0,1)"></rect> + <rect x="10" y="20" width="10" height="10" fill="rgba(0,0,0,1)"></rect> + <rect x="20" y="20" width="10" height="10" fill="rgba(0,0,255,1)"></rect> + <rect x="30" y="20" width="10" height="10" fill="rgba(0,0,0,1)"></rect> + <rect x="0" y="30" width="10" height="10" fill="rgba(127,0,0,1)"></rect> + <rect x="10" y="30" width="10" height="10" fill="rgba(0,127,0,1)"></rect> + <rect x="20" y="30" width="10" height="10" fill="rgba(0,0,0,1)"></rect> + <rect x="30" y="30" width="10" height="10" fill="rgba(63,63,0,1)"></rect> + </g> +</g> +</svg> +</body> +</html>
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/svg-blend-screen-expected.html b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/svg-blend-screen-expected.html new file mode 100644 index 0000000..dac228a --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/css3/blending/svg-blend-screen-expected.html
@@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> +<body> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="400px" height="400px"> +<g transform="scale(4 4)"> + <g> + <rect x="0" y="0" width="10" height="10" fill="rgba(255,0,0,1)"></rect> + <rect x="10" y="0" width="10" height="10" fill="rgba(255,255,0,1)"></rect> + <rect x="20" y="0" width="10" height="10" fill="rgba(255,0,255,1)"></rect> + <rect x="30" y="0" width="10" height="10" fill="rgba(255,127,0,1)"></rect> + <rect x="0" y="10" width="10" height="10" fill="rgba(255,255,0,1)"></rect> + <rect x="10" y="10" width="10" height="10" fill="rgba(0,255,0,1)"></rect> + <rect x="20" y="10" width="10" height="10" fill="rgba(0,255,255,1)"></rect> + <rect x="30" y="10" width="10" height="10" fill="rgba(127,255,0,1)"></rect> + <rect x="0" y="20" width="10" height="10" fill="rgba(255,0,255,1)"></rect> + <rect x="10" y="20" width="10" height="10" fill="rgba(0,255,255,1)"></rect> + <rect x="20" y="20" width="10" height="10" fill="rgba(0,0,255,1)"></rect> + <rect x="30" y="20" width="10" height="10" fill="rgba(127,127,255,1)"></rect> + <rect x="0" y="30" width="10" height="10" fill="rgba(255,127,0,1)"></rect> + <rect x="10" y="30" width="10" height="10" fill="rgba(127,255,0,1)"></rect> + <rect x="20" y="30" width="10" height="10" fill="rgba(127,127,255,1)"></rect> + <rect x="30" y="30" width="10" height="10" fill="rgba(191,191,0,1)"></rect> + </g> +</g> +</svg> +</body> +</html>
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/backgrounds/size/contain-and-cover-zoomed-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/backgrounds/size/contain-and-cover-zoomed-expected.png index fd5f80a..edb4ba6 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/backgrounds/size/contain-and-cover-zoomed-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/backgrounds/size/contain-and-cover-zoomed-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/border-inner-bleed-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/border-inner-bleed-expected.png index 4777466..d8ca013 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/border-inner-bleed-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/border-inner-bleed-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/border-radius-with-composited-child-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/border-radius-with-composited-child-expected.png new file mode 100644 index 0000000..4ec4fb95 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/border-radius-with-composited-child-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-expected.png index fe5ebf8..450c5e1ce 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png index f1f4f6d8..eda6e52 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/overflow/overflow-text-hit-testing-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/overflow/overflow-text-hit-testing-expected.png index 1d3c3b6..d7bb8b4d 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/overflow/overflow-text-hit-testing-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/overflow/overflow-text-hit-testing-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/images/color-profile-layer-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/images/color-profile-layer-expected.png index 5fc7320..aa8e69b 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/images/color-profile-layer-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/images/color-profile-layer-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/images/color-profile-layer-filter-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/images/color-profile-layer-filter-expected.png index c83056d..9937417 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/images/color-profile-layer-filter-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/images/color-profile-layer-filter-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/images/color-profile-mask-image-svg-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/images/color-profile-mask-image-svg-expected.png index 6229832..956e482 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/images/color-profile-mask-image-svg-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/images/color-profile-mask-image-svg-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/float-offscreen-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/float-offscreen-expected.txt new file mode 100644 index 0000000..2ece251 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/paint/invalidation/float-offscreen-expected.txt
@@ -0,0 +1,36 @@ +{ + "layers": [ + { + "name": "Scrolling background of LayoutView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow DIV id='target'", + "position": [3, 3], + "bounds": [85, 22], + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow DIV id='target'", + "rect": [0, 0, 85, 22], + "reason": "full layer" + } + ], + "transform": 1 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 8, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/W3C-SVG-1.1/masking-path-04-b-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/W3C-SVG-1.1/masking-path-04-b-expected.png index a71a97d..15a42cf 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/W3C-SVG-1.1/masking-path-04-b-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/W3C-SVG-1.1/masking-path-04-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/custom/grayscale-gradient-mask-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/custom/grayscale-gradient-mask-expected.png new file mode 100644 index 0000000..ed499940 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/custom/grayscale-gradient-mask-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/justify-ideograph-complex-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/justify-ideograph-complex-expected.png index d65cd62e..7813dbe7 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/justify-ideograph-complex-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/justify-ideograph-complex-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/justify-ideograph-simple-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/justify-ideograph-simple-expected.png index d65cd62e..7813dbe7 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/justify-ideograph-simple-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/justify-ideograph-simple-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/justify-ideograph-vertical-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/justify-ideograph-vertical-expected.png index 524efb6..41a94b97 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/justify-ideograph-vertical-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/justify-ideograph-vertical-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/selection-multiple-runs-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/selection-multiple-runs-expected.png index 763048a..7d48c5a 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/selection-multiple-runs-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/selection/selection-multiple-runs-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/trailing-white-space-2-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/trailing-white-space-2-expected.png index 127ad257..398f3d61 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/trailing-white-space-2-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/trailing-white-space-2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/trailing-white-space-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/trailing-white-space-expected.png index 92b63b77..1892d08 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/trailing-white-space-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/text/trailing-white-space-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/writing-mode/japanese-lr-selection-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/writing-mode/japanese-lr-selection-expected.png index ac53a29..c60698db 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/writing-mode/japanese-lr-selection-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/writing-mode/japanese-lr-selection-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/writing-mode/japanese-rl-selection-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/writing-mode/japanese-rl-selection-expected.png index 7e47bb5a..e89de57 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/writing-mode/japanese-rl-selection-expected.png +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/writing-mode/japanese-rl-selection-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/appcache/main-resource-hash-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/appcache/main-resource-hash-expected.txt deleted file mode 100644 index 33a0735c..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/appcache/main-resource-hash-expected.txt +++ /dev/null
@@ -1,7 +0,0 @@ -CONSOLE WARNING: line 21: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. -Test that offline applications' main resources are not affected by URL hashes. - -Should say SUCCESS: - -SUCCESS -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/appcache/offline-access-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/appcache/offline-access-expected.txt deleted file mode 100644 index 37b203c..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/appcache/offline-access-expected.txt +++ /dev/null
@@ -1,7 +0,0 @@ -CONSOLE WARNING: line 21: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. -Test that offline applications work when there is no network access (simulated). - -Should say SUCCESS: - -SUCCESS -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/loading/preload-picture-invalid-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/loading/preload-picture-invalid-expected.txt deleted file mode 100644 index f08d61b6..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/loading/preload-picture-invalid-expected.txt +++ /dev/null
@@ -1,45 +0,0 @@ -main frame - didStartProvisionalLoadForFrame -main frame - didCommitLoadForFrame -main frame - didReceiveTitle: -main frame - didFinishDocumentLoadForFrame -main frame - didHandleOnloadEventsForFrame -main frame - didFinishLoadForFrame -PASS internals.isPreloaded('resources/preload-test.jpg?0'); is true -PASS internals.isPreloaded('resources/image2.png'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?1'); is true -PASS internals.isPreloaded('resources/base-image1.png?1'); is false -PASS internals.isPreloaded('resources/base-image2.png?1'); is false -PASS internals.isPreloaded('resources/base-image3.png?1'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?2'); is true -PASS internals.isPreloaded('resources/base-image1.png?2'); is false -PASS internals.isPreloaded('resources/base-image2.png?2'); is false -PASS internals.isPreloaded('resources/base-image3.png?2'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?3'); is false -PASS internals.isPreloaded('resources/base-image1.png?3'); is false -PASS internals.isPreloaded('resources/base-image2.png?3'); is false -PASS internals.isPreloaded('resources/base-image3.png?3'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?4'); is false -PASS internals.isPreloaded('resources/base-image1.png?4'); is false -PASS internals.isPreloaded('resources/base-image2.png?4'); is false -PASS internals.isPreloaded('resources/base-image3.png?4'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?5'); is false -PASS internals.isPreloaded('resources/base-image1.png?5'); is false -PASS internals.isPreloaded('resources/base-image2.png?5'); is false -PASS internals.isPreloaded('resources/base-image3.png?5'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?6'); is true -PASS internals.isPreloaded('resources/base-image1.png?6'); is false -PASS internals.isPreloaded('resources/base-image2.png?6'); is false -PASS internals.isPreloaded('resources/base-image3.png?6'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?7'); is true -PASS internals.isPreloaded('resources/base-image1.png?7'); is false -PASS internals.isPreloaded('resources/base-image2.png?7'); is false -PASS internals.isPreloaded('resources/base-image3.png?7'); is false -PASS successfullyParsed is true - -TEST COMPLETE - - - bla - - -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/loading/preload-picture-nested-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/loading/preload-picture-nested-expected.txt deleted file mode 100644 index e118b571..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/loading/preload-picture-nested-expected.txt +++ /dev/null
@@ -1,48 +0,0 @@ -main frame - didStartProvisionalLoadForFrame -main frame - didCommitLoadForFrame -main frame - didReceiveTitle: -main frame - didFinishDocumentLoadForFrame -main frame - didHandleOnloadEventsForFrame -main frame - didFinishLoadForFrame -PASS internals.isPreloaded('resources/preload-test.jpg?0'); is true -PASS internals.isPreloaded('resources/image2.png'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?1'); is false -PASS internals.isPreloaded('resources/base-image1.png?1'); is false -PASS internals.isPreloaded('resources/base-image2.png?1'); is false -PASS internals.isPreloaded('resources/base-image3.png?1'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?2'); is false -PASS internals.isPreloaded('resources/base-image1.png?2'); is false -PASS internals.isPreloaded('resources/base-image2.png?2'); is false -PASS internals.isPreloaded('resources/base-image3.png?2'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?3'); is true -PASS internals.isPreloaded('resources/base-image1.png?3'); is false -PASS internals.isPreloaded('resources/base-image2.png?3'); is false -PASS internals.isPreloaded('resources/base-image3.png?3'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?4'); is false -PASS internals.isPreloaded('resources/base-image1.png?4'); is false -PASS internals.isPreloaded('resources/base-image2.png?4'); is false -PASS internals.isPreloaded('resources/base-image3.png?4'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?5'); is true -PASS internals.isPreloaded('resources/base-image1.png?5'); is false -PASS internals.isPreloaded('resources/base-image2.png?5'); is false -PASS internals.isPreloaded('resources/base-image3.png?5'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?6'); is false -PASS internals.isPreloaded('resources/base-image1.png?6'); is false -PASS internals.isPreloaded('resources/base-image2.png?6'); is false -PASS internals.isPreloaded('resources/base-image3.png?6'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?7'); is false -PASS internals.isPreloaded('resources/base-image1.png?7'); is false -PASS internals.isPreloaded('resources/base-image2.png?7'); is false -PASS internals.isPreloaded('resources/base-image3.png?7'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?71'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?72'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?8'); is true -PASS successfullyParsed is true - -TEST COMPLETE - - - - - -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/loading/preload-picture-sizes-2x-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/loading/preload-picture-sizes-2x-expected.txt deleted file mode 100644 index 98bbe3a6..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/loading/preload-picture-sizes-2x-expected.txt +++ /dev/null
@@ -1,63 +0,0 @@ -main frame - didStartProvisionalLoadForFrame -main frame - didCommitLoadForFrame -CONSOLE WARNING: <source src> with a <picture> parent is invalid and therefore ignored. Please use <source srcset> instead. -main frame - didReceiveTitle: -main frame - didFinishDocumentLoadForFrame -main frame - didHandleOnloadEventsForFrame -main frame - didFinishLoadForFrame -main frame - didStartProvisionalLoadForFrame -main frame - didCommitLoadForFrame -CONSOLE WARNING: <source src> with a <picture> parent is invalid and therefore ignored. Please use <source srcset> instead. -main frame - didReceiveTitle: -main frame - didFinishDocumentLoadForFrame -main frame - didHandleOnloadEventsForFrame -main frame - didFinishLoadForFrame -PASS internals.isPreloaded('resources/image2.png'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?1'); is false -PASS internals.isPreloaded('resources/base-image1.png?1'); is false -PASS internals.isPreloaded('resources/base-image2.png?1'); is true -PASS internals.isPreloaded('resources/base-image3.png?1'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?2'); is false -PASS internals.isPreloaded('resources/base-image1.png?2'); is false -PASS internals.isPreloaded('resources/base-image2.png?2'); is true -PASS internals.isPreloaded('resources/base-image3.png?2'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?3'); is false -PASS internals.isPreloaded('resources/base-image1.png?3'); is false -PASS internals.isPreloaded('resources/base-image2.png?3'); is true -PASS internals.isPreloaded('resources/base-image3.png?3'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?4'); is false -PASS internals.isPreloaded('resources/base-image1.png?4'); is false -PASS internals.isPreloaded('resources/base-image2.png?4'); is true -PASS internals.isPreloaded('resources/base-image3.png?4'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?5'); is false -PASS internals.isPreloaded('resources/base-image1.png?5'); is false -PASS internals.isPreloaded('resources/base-image2.png?5'); is true -PASS internals.isPreloaded('resources/base-image3.png?5'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?6'); is false -PASS internals.isPreloaded('resources/base-image1.png?6'); is false -PASS internals.isPreloaded('resources/base-image2.png?6'); is true -PASS internals.isPreloaded('resources/base-image3.png?6'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?7'); is false -PASS internals.isPreloaded('resources/base-image1.png?7'); is false -PASS internals.isPreloaded('resources/base-image2.png?7'); is true -PASS internals.isPreloaded('resources/base-image3.png?7'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?8'); is false -PASS internals.isPreloaded('resources/base-image1.png?8'); is false -PASS internals.isPreloaded('resources/base-image2.png?8'); is true -PASS internals.isPreloaded('resources/base-image3.png?8'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?9'); is false -PASS internals.isPreloaded('resources/base-image1.png?9'); is false -PASS internals.isPreloaded('resources/base-image2.png?9'); is true -PASS internals.isPreloaded('resources/base-image3.png?9'); is false -PASS internals.isPreloaded('resources/dup-image1.png?7'); is false -PASS internals.isPreloaded('resources/dup-image1.png?8'); is false -PASS internals.isPreloaded('resources/dup-image2.png?8'); is false -PASS internals.isPreloaded('resources/dup-image3.png?8'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?10'); is false -PASS internals.isPreloaded('resources/base-image1.png?10'); is true -PASS internals.isPreloaded('resources/base-image2.png?10'); is false -PASS internals.isPreloaded('resources/base-image3.png?10'); is false -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/loading/preload-picture-sizes-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/loading/preload-picture-sizes-expected.txt deleted file mode 100644 index 4d7c558..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/loading/preload-picture-sizes-expected.txt +++ /dev/null
@@ -1,64 +0,0 @@ -main frame - didStartProvisionalLoadForFrame -main frame - didCommitLoadForFrame -CONSOLE WARNING: <source src> with a <picture> parent is invalid and therefore ignored. Please use <source srcset> instead. -main frame - didReceiveTitle: -main frame - didFinishDocumentLoadForFrame -main frame - didHandleOnloadEventsForFrame -main frame - didFinishLoadForFrame -PASS internals.isPreloaded('resources/image2.png'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?1'); is false -PASS internals.isPreloaded('resources/base-image1.png?1'); is false -PASS internals.isPreloaded('resources/base-image2.png?1'); is false -PASS internals.isPreloaded('resources/base-image3.png?1'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?2'); is false -PASS internals.isPreloaded('resources/base-image1.png?2'); is false -PASS internals.isPreloaded('resources/base-image2.png?2'); is false -PASS internals.isPreloaded('resources/base-image3.png?2'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?3'); is false -PASS internals.isPreloaded('resources/base-image1.png?3'); is false -PASS internals.isPreloaded('resources/base-image2.png?3'); is false -PASS internals.isPreloaded('resources/base-image3.png?3'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?4'); is false -PASS internals.isPreloaded('resources/base-image1.png?4'); is false -PASS internals.isPreloaded('resources/base-image2.png?4'); is false -PASS internals.isPreloaded('resources/base-image3.png?4'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?5'); is false -PASS internals.isPreloaded('resources/base-image1.png?5'); is false -PASS internals.isPreloaded('resources/base-image2.png?5'); is false -PASS internals.isPreloaded('resources/base-image3.png?5'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?6'); is false -PASS internals.isPreloaded('resources/base-image1.png?6'); is false -PASS internals.isPreloaded('resources/base-image2.png?6'); is false -PASS internals.isPreloaded('resources/base-image3.png?6'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?7'); is false -PASS internals.isPreloaded('resources/base-image1.png?7'); is false -PASS internals.isPreloaded('resources/base-image2.png?7'); is false -PASS internals.isPreloaded('resources/base-image3.png?7'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?8'); is false -PASS internals.isPreloaded('resources/base-image1.png?8'); is false -PASS internals.isPreloaded('resources/base-image2.png?8'); is false -PASS internals.isPreloaded('resources/base-image3.png?8'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?9'); is false -PASS internals.isPreloaded('resources/base-image1.png?9'); is false -PASS internals.isPreloaded('resources/base-image2.png?9'); is false -PASS internals.isPreloaded('resources/base-image3.png?9'); is true -PASS internals.isPreloaded('resources/preload-test.jpg?10'); is false -PASS internals.isPreloaded('resources/base-image1.png?10'); is false -PASS internals.isPreloaded('resources/base-image2.png?10'); is false -PASS internals.isPreloaded('resources/base-image3.png?10'); is true -PASS internals.isPreloaded('resources/dup-image1.png?7'); is false -PASS internals.isPreloaded('resources/dup-image1.png?8'); is false -PASS internals.isPreloaded('resources/dup-image2.png?8'); is false -PASS internals.isPreloaded('resources/dup-image3.png?8'); is false -PASS internals.isPreloaded('resources/base-image1.png?101'); is false -PASS internals.isPreloaded('resources/base-image2.png?101'); is false -PASS internals.isPreloaded('resources/base-image3.png?101'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?10'); is false -PASS internals.isPreloaded('resources/preload-test.jpg?11'); is true -PASS internals.isPreloaded('resources/base-image1.png?11'); is false -PASS internals.isPreloaded('resources/base-image2.png?11'); is false -PASS internals.isPreloaded('resources/base-image3.png?11'); is false -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/misc/dns-prefetch-control-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/misc/dns-prefetch-control-expected.txt deleted file mode 100644 index a41d0927..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/misc/dns-prefetch-control-expected.txt +++ /dev/null
@@ -1,8 +0,0 @@ -This is a test of DNS prefetch control. It's considered a pass if it doesn't crash. It can also be used as a manual test of DNS prefetch using a networking monitoring tool. - -The following frames contain links that are expected to trigger a DNS prefetch. - - -The following frames contain links that are not expected to cause a DNS prefetch. - -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/anchor-basic-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/anchor-basic-expected.txt deleted file mode 100644 index 59d0a5cb..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/anchor-basic-expected.txt +++ /dev/null
@@ -1,39 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/anchor-basic.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html#anchor1 -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/anchor-goback-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/anchor-goback-expected.txt deleted file mode 100644 index 59ad1be..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/anchor-goback-expected.txt +++ /dev/null
@@ -1,40 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/anchor-goback.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html#anchor1 - http://127.0.0.1:8000/navigation/resources/otherpage.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/back-to-slow-frame-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/back-to-slow-frame-expected.txt deleted file mode 100644 index 5c6a622c..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/back-to-slow-frame-expected.txt +++ /dev/null
@@ -1,11 +0,0 @@ - -This test checks that going back and forth across a slow-loading frame doesn't crash. If you got back here without crashing, you win. - -If testing manually click here. - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/back-to-slow-frame.html -curr-> http://127.0.0.1:8000/navigation/resources/back-to-slow-frame-2.html - http://127.0.0.1:8000/navigation/resources/slow-resource-1-sec.pl (in frame "<!--framePath //<!--frame0-->-->") - http://127.0.0.1:8000/navigation/resources/back-to-slow-frame-3.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/form-targets-cross-site-frame-get-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/form-targets-cross-site-frame-get-expected.txt deleted file mode 100644 index 8c86440..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/form-targets-cross-site-frame-get-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -Test field: - - --------- -Frame: 'cross-site-frame' --------- -This page was requested with the HTTP method GET. - -Parameters: - -test-field = test-value -Http headers: - -HTTP_CONNECTION = keep-alive -HTTP_HOST = localhost:8080 -HTTP_REFERER = http://127.0.0.1:8000/navigation/form-targets-cross-site-frame-get.html -HTTP_SEC_METADATA = cause=forced, destination=nested-document, site=cross-site -HTTP_UPGRADE_INSECURE_REQUESTS = 1
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/form-targets-cross-site-frame-no-referrer-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/form-targets-cross-site-frame-no-referrer-expected.txt deleted file mode 100644 index 5bb8877..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/form-targets-cross-site-frame-no-referrer-expected.txt +++ /dev/null
@@ -1,19 +0,0 @@ -Test field: - - --------- -Frame: 'cross-site-frame' --------- -This page was requested with the HTTP method POST. - -Parameters: - -test-field = test-value -Http headers: - -HTTP_CACHE_CONTROL = max-age=0 -HTTP_CONNECTION = keep-alive -HTTP_HOST = localhost:8080 -HTTP_ORIGIN = null -HTTP_SEC_METADATA = cause=forced, destination=nested-document, site=cross-site -HTTP_UPGRADE_INSECURE_REQUESTS = 1
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/form-targets-cross-site-frame-post-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/form-targets-cross-site-frame-post-expected.txt deleted file mode 100644 index 9ad8ab7..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/form-targets-cross-site-frame-post-expected.txt +++ /dev/null
@@ -1,20 +0,0 @@ -Test field: - - --------- -Frame: 'cross-site-frame' --------- -This page was requested with the HTTP method POST. - -Parameters: - -test-field = test-value -Http headers: - -HTTP_CACHE_CONTROL = max-age=0 -HTTP_CONNECTION = keep-alive -HTTP_HOST = localhost:8080 -HTTP_ORIGIN = http://127.0.0.1:8000 -HTTP_REFERER = http://127.0.0.1:8000/navigation/form-targets-cross-site-frame-post.html -HTTP_SEC_METADATA = cause=forced, destination=nested-document, site=cross-site -HTTP_UPGRADE_INSECURE_REQUESTS = 1
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/form-with-enctype-targets-cross-site-frame-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/form-with-enctype-targets-cross-site-frame-expected.txt deleted file mode 100644 index 1a8e236..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/form-with-enctype-targets-cross-site-frame-expected.txt +++ /dev/null
@@ -1,20 +0,0 @@ -Test field: - - --------- -Frame: 'cross-site-frame' --------- -This page was requested with the HTTP method POST. - -Parameters: - -test-field = test-value -Http headers: - -HTTP_CACHE_CONTROL = max-age=0 -HTTP_CONNECTION = keep-alive -HTTP_HOST = localhost:8080 -HTTP_ORIGIN = http://127.0.0.1:8000 -HTTP_REFERER = http://127.0.0.1:8000/navigation/form-with-enctype-targets-cross-site-frame.html -HTTP_SEC_METADATA = cause=forced, destination=nested-document, site=cross-site -HTTP_UPGRADE_INSECURE_REQUESTS = 1
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/javascriptlink-basic-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/javascriptlink-basic-expected.txt deleted file mode 100644 index 706f789..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/javascriptlink-basic-expected.txt +++ /dev/null
@@ -1,40 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/javascriptlink-basic.html - http://127.0.0.1:8000/navigation/resources/javascriptlink.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/javascriptlink-goback-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/javascriptlink-goback-expected.txt deleted file mode 100644 index 6dfd2dac..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/javascriptlink-goback-expected.txt +++ /dev/null
@@ -1,41 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/javascriptlink-goback.html - http://127.0.0.1:8000/navigation/resources/javascriptlink.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html - http://127.0.0.1:8000/navigation/resources/otherpage.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/metaredirect-basic-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/metaredirect-basic-expected.txt deleted file mode 100644 index 0aae04f..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/metaredirect-basic-expected.txt +++ /dev/null
@@ -1,39 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/metaredirect-basic.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/metaredirect-goback-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/metaredirect-goback-expected.txt deleted file mode 100644 index 85af4688c..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/metaredirect-goback-expected.txt +++ /dev/null
@@ -1,40 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/metaredirect-goback.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html - http://127.0.0.1:8000/navigation/resources/otherpage.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/post-goback2-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/post-goback2-expected.txt deleted file mode 100644 index dace1fb..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/post-goback2-expected.txt +++ /dev/null
@@ -1,41 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/post-goback2.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html - http://127.0.0.1:8000/navigation/resources/postresult.pl - http://127.0.0.1:8000/navigation/resources/otherpage.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/postredirect-goback2-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/postredirect-goback2-expected.txt deleted file mode 100644 index 781c51fd..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/postredirect-goback2-expected.txt +++ /dev/null
@@ -1,41 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/postredirect-goback2.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html - http://127.0.0.1:8000/navigation/resources/postresult.pl?submitwithpostredirect=Submit%20with%20POST%20followed%20by%20a%20redirect&textfield1=New%20form%20text%20from%20user&textfield2=&radiogroup1=female&checkbox2=on&selectgroup1=fiat&textarea1=More%20new%20form%20text%20from%20user%2C%20which%20should%20be%20restored%20when%20we%20return%20to%20this%20page.&redirectHappened=true - http://127.0.0.1:8000/navigation/resources/otherpage.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/redirect302-basic-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/redirect302-basic-expected.txt deleted file mode 100644 index 50163628..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/redirect302-basic-expected.txt +++ /dev/null
@@ -1,39 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/redirect302-basic.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/redirect302-goback-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/redirect302-goback-expected.txt deleted file mode 100644 index 87c7511..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/redirect302-goback-expected.txt +++ /dev/null
@@ -1,40 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/redirect302-goback.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html - http://127.0.0.1:8000/navigation/resources/otherpage.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/relativeanchor-basic-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/relativeanchor-basic-expected.txt deleted file mode 100644 index 94144430b..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/relativeanchor-basic-expected.txt +++ /dev/null
@@ -1,40 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/relativeanchor-basic.html - http://127.0.0.1:8000/navigation/resources/success200.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html#anchor1 -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/relativeanchor-goback-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/relativeanchor-goback-expected.txt deleted file mode 100644 index ea63877c..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/relativeanchor-goback-expected.txt +++ /dev/null
@@ -1,41 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/relativeanchor-goback.html - http://127.0.0.1:8000/navigation/resources/success200.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html#anchor1 - http://127.0.0.1:8000/navigation/resources/otherpage.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/restore-form-state-https-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/restore-form-state-https-expected.txt deleted file mode 100644 index 34c23ff..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/restore-form-state-https-expected.txt +++ /dev/null
@@ -1,19 +0,0 @@ -This is test page that has a secure form. It is part of a test to show that form state is restored during back/forward navigations. - -Test Passed - - - - - - - - - - - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/restore-form-state-https.html -curr-> http://127.0.0.1:8000/navigation/resources/restore-form-state-https-1.html - http://127.0.0.1:8000/navigation/resources/otherpage.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/slowmetaredirect-basic-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/slowmetaredirect-basic-expected.txt deleted file mode 100644 index 8192497..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/slowmetaredirect-basic-expected.txt +++ /dev/null
@@ -1,40 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/slowmetaredirect-basic.html - http://127.0.0.1:8000/navigation/resources/slowmetaredirect.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/slowtimerredirect-basic-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/slowtimerredirect-basic-expected.txt deleted file mode 100644 index 003d3c6a..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/slowtimerredirect-basic-expected.txt +++ /dev/null
@@ -1,39 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/slowtimerredirect-basic.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/success200-basic-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/success200-basic-expected.txt deleted file mode 100644 index 6a97a3e..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/success200-basic-expected.txt +++ /dev/null
@@ -1,39 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/success200-basic.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/success200-goback-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/success200-goback-expected.txt deleted file mode 100644 index ba9e3b7..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/success200-goback-expected.txt +++ /dev/null
@@ -1,40 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/success200-goback.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html - http://127.0.0.1:8000/navigation/resources/otherpage.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/success200-loadsame-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/success200-loadsame-expected.txt deleted file mode 100644 index 7a868714..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/success200-loadsame-expected.txt +++ /dev/null
@@ -1,39 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/success200-loadsame.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/success200-reload-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/success200-reload-expected.txt deleted file mode 100644 index 76ee784b..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/success200-reload-expected.txt +++ /dev/null
@@ -1,39 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/success200-reload.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/timerredirect-basic-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/timerredirect-basic-expected.txt deleted file mode 100644 index 2f9ac80..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/timerredirect-basic-expected.txt +++ /dev/null
@@ -1,39 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/timerredirect-basic.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/timerredirect-goback-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/timerredirect-goback-expected.txt deleted file mode 100644 index 5179db87..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/navigation/timerredirect-goback-expected.txt +++ /dev/null
@@ -1,40 +0,0 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. - - - - -Here are some form elements -that we can use for testing - Male - Female - option #1 - option #2 - - -Now - -some - -filler - -so - -the - -doc - -is - -long - -enough - -to scroll. - -This is an anchor point named "anchor1". - -============== Back Forward List ============== - http://127.0.0.1:8000/navigation/timerredirect-goback.html -curr-> http://127.0.0.1:8000/navigation/resources/success200.html - http://127.0.0.1:8000/navigation/resources/otherpage.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/XFrameOptions/x-frame-options-cached-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/XFrameOptions/x-frame-options-cached-expected.txt deleted file mode 100644 index 5549bd28..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/XFrameOptions/x-frame-options-cached-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -ALERT: This must fire twice -ALERT: This must fire twice -Check that an X-Frame-Options header added by a 304 response does not override one from the original request. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - - -Two console messages should be generated, each followed by an alert. -Both frames should point to the expected URL, and not to about:blank. -PASS frame1.src is "http://127.0.0.1:8000/security/XFrameOptions/resources/nph-cached-xfo.pl" -PASS frame2.src is "http://127.0.0.1:8000/security/XFrameOptions/resources/nph-cached-xfo.pl" -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-blank-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-blank-expected.txt deleted file mode 100644 index 44261e4f..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-blank-expected.txt +++ /dev/null
@@ -1,13 +0,0 @@ -CONSOLE MESSAGE: line 15: submit event fired. -CONSOLE ERROR: line 19: Refused to send form data to 'http://127.0.0.1:8000/navigation/resources/form-target.pl' because it violates the following Content Security Policy directive: "form-action 'none'". - -CONSOLE MESSAGE: line 24: securitypolicyviolation event fired. -CONSOLE MESSAGE: line 25: securitypolicyviolation_event.documentURI=http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-blank.html -CONSOLE MESSAGE: line 26: securitypolicyviolation_event.blockedURI=http://127.0.0.1:8000/navigation/resources/form-target.pl -CONSOLE MESSAGE: line 27: securitypolicyviolation_event.violatedDirective=form-action - -Tests that blocking form actions works correctly. If this test passes, you will see a console error, and will not see a page indicating a form was POSTed. - -============== Back Forward List ============== -curr-> http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-blank.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-cross-site-window-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-cross-site-window-expected.txt deleted file mode 100644 index 439aa937..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-cross-site-window-expected.txt +++ /dev/null
@@ -1,9 +0,0 @@ -CONSOLE MESSAGE: line 19: submit event fired. -CONSOLE ERROR: line 23: Refused to send form data to 'http://127.0.0.1:8000/navigation/resources/form-target.pl' because it violates the following Content Security Policy directive: "form-action 'none'". - -CONSOLE MESSAGE: line 28: securitypolicyviolation event fired. -CONSOLE MESSAGE: line 29: securitypolicyviolation_event.documentURI=http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-cross-site-window.html -CONSOLE MESSAGE: line 30: securitypolicyviolation_event.blockedURI=http://127.0.0.1:8000/navigation/resources/form-target.pl -CONSOLE MESSAGE: line 31: securitypolicyviolation_event.violatedDirective=form-action - -Tests that blocking form actions works correctly. If this test passes, you will see a console error, and will not see a page indicating a form was POSTed.
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-src-blocked-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-src-blocked-expected.txt deleted file mode 100644 index fec078c..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-src-blocked-expected.txt +++ /dev/null
@@ -1,13 +0,0 @@ -CONSOLE MESSAGE: line 15: submit event fired. -CONSOLE ERROR: line 19: Refused to send form data to 'http://127.0.0.1:8000/navigation/resources/form-target.pl' because it violates the following Content Security Policy directive: "form-action 'none'". - -CONSOLE MESSAGE: line 24: securitypolicyviolation event fired. -CONSOLE MESSAGE: line 25: securitypolicyviolation_event.documentURI=http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-blocked.html -CONSOLE MESSAGE: line 26: securitypolicyviolation_event.blockedURI=http://127.0.0.1:8000/navigation/resources/form-target.pl -CONSOLE MESSAGE: line 27: securitypolicyviolation_event.violatedDirective=form-action - -Tests that blocking form actions works correctly. If this test passes, you will see a console error, and will not see a page indicating a form was POSTed. - -============== Back Forward List ============== -curr-> http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-blocked.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-expected.txt deleted file mode 100644 index 691d2a60d..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-expected.txt +++ /dev/null
@@ -1,8 +0,0 @@ -CONSOLE ERROR: line 16: Refused to send form data to 'http://127.0.0.1:8000/navigation/resources/form-target.pl' because it violates the following Content Security Policy directive: "form-action 'none'". - - -Tests that blocking form actions works correctly. If this test passes, you will see a console error, and will not see a page indicating a form was POSTed. - -============== Back Forward List ============== -curr-> http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-get-blocked.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-with-redirect-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-with-redirect-expected.txt deleted file mode 100644 index a4a649b..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-with-redirect-expected.txt +++ /dev/null
@@ -1,8 +0,0 @@ -CONSOLE ERROR: Refused to send form data to 'http://localhost:8000/' because it violates the following Content Security Policy directive: "form-action 127.0.0.1:8000". - - -Tests that blocking form actions works with the 'get' method and redirects. If this test passes, you will see a console error, and will not see a page indicating a form was POSTed. - -============== Back Forward List ============== -curr-> http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-with-redirect.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-src-javascript-blocked-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-src-javascript-blocked-expected.txt deleted file mode 100644 index 63be18ed..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-src-javascript-blocked-expected.txt +++ /dev/null
@@ -1,8 +0,0 @@ -CONSOLE ERROR: line 14: Refused to send form data to 'javascript:alert("FAIL!")' because it violates the following Content Security Policy directive: "form-action 'none'". - - -Tests that blocking form actions works correctly. If this test passes, you will see a console error, and will not see a JavaScript alert. - -============== Back Forward List ============== -curr-> http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-javascript-blocked.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-src-redirect-blocked-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-src-redirect-blocked-expected.txt deleted file mode 100644 index 043997f..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/1.1/form-action-src-redirect-blocked-expected.txt +++ /dev/null
@@ -1,8 +0,0 @@ -CONSOLE ERROR: Refused to send form data to 'http://localhost:8000/' because it violates the following Content Security Policy directive: "form-action 127.0.0.1:8000". - - -Tests that blocking form redirect works correctly. If this test passes, you will see a console error, and will not see a page indicating a form was POSTed. - -============== Back Forward List ============== -curr-> http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-redirect-blocked.html -===============================================
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/cached-frame-csp-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/cached-frame-csp-expected.txt deleted file mode 100644 index 605c163..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/cached-frame-csp-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -CONSOLE ERROR: line 5: Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'none'". Either the 'unsafe-inline' keyword, a hash ('sha256-HNo4gm6q1snjil9OgSmpbSnn3Bhbw4R+r+SBLYD3ENc='), or a nonce ('nonce-...') is required to enable inline execution. - -CONSOLE ERROR: line 5: Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'none'". Either the 'unsafe-inline' keyword, a hash ('sha256-HNo4gm6q1snjil9OgSmpbSnn3Bhbw4R+r+SBLYD3ENc='), or a nonce ('nonce-...') is required to enable inline execution. - -Check that a CSP header added by a 304 response does not override one from the original request. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - - -Check that the nonce is the same, meaning that the document was only generated once: -PASS frame1.contentDocument.querySelector("input").value == frame2.contentDocument.querySelector("input").value is true -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/frame-src-cross-origin-load-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/frame-src-cross-origin-load-expected.txt deleted file mode 100644 index 849a79bc..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/contentSecurityPolicy/frame-src-cross-origin-load-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -CONSOLE ERROR: line 24: Refused to frame 'https://localhost:8443/' because it violates the following Content Security Policy directive: "frame-src 'self' http://localhost:8080". - -ALERT: PASS -ALERT: PASS -IFrames blocked by CSP should generate a 'load' event, regardless of blocked state. This means they appear to be normal cross-origin loads, thereby not leaking URL information directly to JS. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - - -PASS IFrame #1 generated a 'load' event. -PASS IFrame #2 generated a 'load' event. -PASS IFrame #3 generated a 'load' event. -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-to-data-url-sub-frame-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-to-data-url-sub-frame-expected.txt deleted file mode 100644 index 36f5306..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-to-data-url-sub-frame-expected.txt +++ /dev/null
@@ -1,17 +0,0 @@ -This tests that a data: URL subframe can't access a sibling data: URL subframe. - - - --------- -Frame: 'firstSubFrame' --------- -Inner iframe. - -Pass: Cross frame access from a sibling data: URL was denied. - --------- -Frame: 'secondSubFrame' --------- -Inner iframe. - -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/feed-urls-from-remote-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/feed-urls-from-remote-expected.txt deleted file mode 100644 index 14103dde..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/feed-urls-from-remote-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -Policy delegate: attempt to load feed://127.0.0.1:8000/security/resources/feed.xml with navigation type 'link clicked' -< rdar://problem/5329440> REGRESSION: Clicking links with the feed:// protocol in Safari 3 does nothing -This test is to see if a feed URL can be followed from a link on a page. - -Test Finished. -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/filesystem-iframe-from-remote-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/filesystem-iframe-from-remote-expected.txt deleted file mode 100644 index fd3c983..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/filesystem-iframe-from-remote-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -CONSOLE MESSAGE: line 9: filesystem:http://localhost:8000/temporary/page.html created. -CONSOLE ERROR: line 8: Not allowed to load local resource: filesystem:http://localhost:8000/temporary/page.html -This test is to see if a remote file can include a local page via a filesystem: URI in an iFrame. - -Test Passed. Local page not remotely loaded into iFrame. -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/frameNavigation/xss-ALLOWED-targeted-subframe-navigation-change-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/frameNavigation/xss-ALLOWED-targeted-subframe-navigation-change-expected.txt deleted file mode 100644 index e0548bfd..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/frameNavigation/xss-ALLOWED-targeted-subframe-navigation-change-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -This tests that documents can navigate the location of any of it's sub-frames regardless of domain. - -127.0.0.1 - Perform Test - --------- -Frame: '<!--framePath //<!--frame0-->-->' --------- -localhost - - --------- -Frame: 'targetFrame' --------- -localhost -PASSED: Navigation succeeded.
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/host-compare-case-insensitive-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/host-compare-case-insensitive-expected.txt deleted file mode 100644 index bc64e6f5..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/host-compare-case-insensitive-expected.txt +++ /dev/null
@@ -1,17 +0,0 @@ -This tests that the comparison of the host for security is done case insensitive. - - - --------- -Frame: 'frameA' --------- -PASS: Host name compare is case insensitive. - -Inner iframe. - --------- -Frame: 'frameB' --------- -Other inner iframe. - -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/local-CSS-from-remote-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/local-CSS-from-remote-expected.txt deleted file mode 100644 index 0c2f18f..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/local-CSS-from-remote-expected.txt +++ /dev/null
@@ -1,7 +0,0 @@ -CONSOLE ERROR: line 19: Not allowed to load local resource: cssStyle.css -This test is to see if a remote file can include a local CSS style. -Currently this test cannot be run manually on Windows because we do not have a function like pathToLocalResource() outside of DRT. - -If the background is yellow then the CSS was loaded. - -Test Passed: Local CSS not remotely loaded.
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/local-JavaScript-from-remote-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/local-JavaScript-from-remote-expected.txt deleted file mode 100644 index a679f87b..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/local-JavaScript-from-remote-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -CONSOLE ERROR: line 35: Not allowed to load local resource: localScript.js -This test is to see if a remote file can run a local script. -Currently this test cannot be run manually on Windows because we do not have a function like pathToLocalResource() outside of DRT. - -Test Passed: Local script not loaded.
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/local-iFrame-from-remote-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/local-iFrame-from-remote-expected.txt deleted file mode 100644 index 6cc8bb2..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/local-iFrame-from-remote-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -CONSOLE ERROR: line 16: Not allowed to load local resource: localPage.html -This test is to see if a remote file can include a local page in an iFrame. -Currently this test cannot be run manually on Windows because we do not have a function like pathToLocalResource() outside of DRT. - -Test Passed. Local page not remotely loaded into iFrame. -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/local-image-from-remote-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/local-image-from-remote-expected.txt deleted file mode 100644 index e7a1dd7..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/local-image-from-remote-expected.txt +++ /dev/null
@@ -1,7 +0,0 @@ -CONSOLE ERROR: Not allowed to load local resource: compass.jpg -This test is to see if a remote file can include a local image. -Currently this test cannot be run manually on Windows because we do not have a function like pathToLocalResource() outside of DRT. - -Test Passed. Local image not loaded remotely. - -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/xssAuditor/block-does-not-leak-location-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/xssAuditor/block-does-not-leak-location-expected.txt deleted file mode 100644 index 616fd5f..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/xssAuditor/block-does-not-leak-location-expected.txt +++ /dev/null
@@ -1,7 +0,0 @@ -CONSOLE ERROR: line 8: The XSS Auditor blocked access to 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl?enable-full-block=1&q=%3Cscript%3Ealert(String.fromCharCode(0x58,0x53,0x53));%3C/script%3E' because the source code of a script was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. -PASS xssed.contentDocument is null -PASS xssed.contentWindow.location.href threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.. -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/xssAuditor/cached-frame-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/xssAuditor/cached-frame-expected.txt deleted file mode 100644 index f344e7e1..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/security/xssAuditor/cached-frame-expected.txt +++ /dev/null
@@ -1,14 +0,0 @@ -CONSOLE ERROR: line 5: The XSS Auditor refused to execute a script in 'http://127.0.0.1:8000/security/xssAuditor/resources/nph-cached.pl?q=%3cscript%3ealert(/XSS/);%3c/script%3e' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. -CONSOLE ERROR: line 5: The XSS Auditor refused to execute a script in 'http://127.0.0.1:8000/security/xssAuditor/resources/nph-cached.pl?q=%3cscript%3ealert(/XSS/);%3c/script%3e' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. -Check that an X-XSS-Protection header added by a 304 response does not override one from the original request. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - - -Two console messages should be generated, noting that JavaScript was blocked. -Check that the nonce is the same, meaning that the document was only generated once: -PASS frame1.contentDocument.querySelector("input").value == frame2.contentDocument.querySelector("input").value is true -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/xmlhttprequest/remember-bad-password-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/xmlhttprequest/remember-bad-password-expected.txt deleted file mode 100644 index 351969a..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/xmlhttprequest/remember-bad-password-expected.txt +++ /dev/null
@@ -1,12 +0,0 @@ -CONSOLE WARNING: line 53: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. -rdar://problem/7062824 A wrong password entered for site or proxy auth remains in WebCore credential storage, and is sent with subsequent requests. - -This test counts the number of failed requests server side. - -PASS - -Sync -With credentials Without credentials -Async -With credentials Without credentials -Status
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt index 34f9fbe5..a1eb1dc 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt
@@ -18,8 +18,8 @@ "backgroundColor": "#FFFFFF", "paintInvalidations": [ { - "object": "NGPhysicalTextFragment 'paragraph 1'", - "rect": [548, 165, 23, 97], + "object": "NGPhysicalTextFragment '\u7B2C\u4E00\u6BB5\u843D paragraph 1'", + "rect": [548, 80, 24, 182], "reason": "selection" } ]
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/japanese-rl-selection-clear-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/japanese-rl-selection-clear-expected.txt index 3ee87af..9810f141 100644 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/japanese-rl-selection-clear-expected.txt +++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/japanese-rl-selection-clear-expected.txt
@@ -18,203 +18,63 @@ "backgroundColor": "#FFFFFF", "paintInvalidations": [ { - "object": "NGPhysicalTextFragment '\u306A\u3089\u30BF\u30A4\u30C8\u30EB\u3068\u30A2\u30C9\u30EC\u30B9\u3060\u3051\u3067\u306A\u304F\u3001'", - "rect": [681, 123, 32, 357], + "object": "NGPhysicalTextFragment '\u305B\u3063\u304B\u304F\u898B\u3064\u3051\u305F\u3059\u3070\u3089\u3057\u3044\u8A18\u4E8B\u304C\u3069\u3053\u306B'", + "rect": [745, 123, 32, 404], "reason": "selection" }, { - "object": "NGPhysicalTextFragment '\u3057\u305F\u30A6\u30A7\u30D6\u30DA\u30FC\u30B8\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u304B\u3089\u3082'", - "rect": [649, 123, 32, 357], + "object": "NGPhysicalTextFragment '\u3042\u3063\u305F\u304B\u5FD8\u308C\u3066\u3057\u307E\u3063\u305F\u7D4C\u9A13\u306F\u3042\u308A\u307E\u3059\u304B'", + "rect": [713, 123, 32, 404], "reason": "selection" }, { - "object": "NGPhysicalTextFragment '\u3057\u305F\u30A6\u30A7\u30D6\u30DA\u30FC\u30B8\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u304B'", - "rect": [457, 207, 32, 320], + "object": "NGPhysicalTextFragment '\u306A\u3089\u30BF\u30A4\u30C8\u30EB\u3068\u30A2\u30C9\u30EC\u30B9\u3060\u3051\u3067\u306A\u304F\u3001\u8A2A\u554F'", + "rect": [681, 123, 32, 404], "reason": "selection" }, { - "object": "NGPhysicalTextFragment '\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\u305B\u3063\u304B\u304F'", - "rect": [617, 123, 32, 294], + "object": "NGPhysicalTextFragment '\u3057\u305F\u30A6\u30A7\u30D6\u30DA\u30FC\u30B8\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u304B\u3089\u3082\u691C\u7D22'", + "rect": [649, 123, 32, 404], "reason": "selection" }, { - "object": "NGPhysicalTextFragment '\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\u305B\u3063\u304B\u304F'", - "rect": [425, 207, 32, 294], + "object": "NGPhysicalTextFragment '\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\u305B\u3063\u304B\u304F\u898B\u3064\u3051\u305F\u3059'", + "rect": [617, 123, 32, 404], "reason": "selection" }, { - "object": "NGPhysicalTextFragment '\u30C9\u30EC\u30B9\u3060\u3051\u3067\u306A\u304F\u3001'", - "rect": [521, 123, 32, 189], + "object": "NGPhysicalTextFragment '\u3070\u3089\u3057\u3044\u8A18\u4E8B\u304C\u3069\u3053\u306B\u3042\u3063\u305F\u304B\u5FD8\u308C\u3066\u3057\u307E'", + "rect": [585, 123, 32, 404], "reason": "selection" }, { - "object": "NGPhysicalTextFragment '\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u304B\u3089\u3082'", - "rect": [489, 123, 32, 189], + "object": "NGPhysicalTextFragment '\u30C9\u30EC\u30B9\u3060\u3051\u3067\u306A\u304F\u3001\u8A2A\u554F\u3057\u305F\u30A6\u30A7\u30D6\u30DA\u30FC\u30B8'", + "rect": [521, 123, 32, 404], "reason": "selection" }, { - "object": "NGPhysicalTextFragment '\u306A\u3089\u30BF\u30A4\u30C8\u30EB\u3068\u30A2'", - "rect": [553, 338, 32, 173], + "object": "NGPhysicalTextFragment '\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u304B\u3089\u3082\u691C\u7D22\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E'", + "rect": [489, 123, 32, 404], "reason": "selection" }, { - "object": "NGPhysicalTextFragment '\u3057\u305F\u30A6\u30A7\u30D6\u30DA\u30FC\u30B8'", - "rect": [521, 354, 32, 173], + "object": "NGPhysicalTextFragment '\u3059\u3002\u8A2A\u554F\u3057\u305F\u30A6\u30A7\u30D6\u30DA\u30FC\u30B8\u306E\u30B3\u30F3\u30C6\u30F3\u30C4\u304B'", + "rect": [457, 123, 32, 404], "reason": "selection" }, { - "object": "NGPhysicalTextFragment '\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E'", - "rect": [489, 354, 32, 173], + "object": "NGPhysicalTextFragment '\u3089\u3082\u691C\u7D22\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\u305B\u3063\u304B\u304F\u898B'", + "rect": [425, 123, 32, 404], "reason": "selection" }, { - "object": "NGPhysicalTextFragment '\u3064\u3051\u305F\u3059\u3070\u3089\u3057\u3044'", - "rect": [745, 228, 32, 168], + "object": "NGPhysicalTextFragment '\u3064\u3051\u305F\u3059\u3070\u3089\u3057\u3044\u8A18\u4E8B\u304C\u3069\u3053\u306B\u3042\u3063\u305F\u304B\u5FD8'", + "rect": [393, 123, 32, 399], "reason": "selection" }, { - "object": "NGPhysicalTextFragment '\u304C\u3069\u3053\u306B\u3042\u3063\u305F\u304B'", - "rect": [585, 249, 32, 168], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u3064\u3051\u305F\u3059\u3070\u3089\u3057\u3044'", - "rect": [393, 123, 32, 168], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u306F\u3042\u308A\u307E\u3059\u304B'", - "rect": [713, 396, 32, 131], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u308C\u3066\u3057\u307E\u3063\u305F'", - "rect": [713, 228, 32, 126], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u306F\u3042\u308A\u307E\u3059\u304B'", - "rect": [553, 207, 32, 126], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u304C\u3069\u3053\u306B'", - "rect": [745, 438, 32, 89], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u3064\u3051\u305F\u3059'", - "rect": [617, 438, 32, 89], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u308C\u3066\u3057\u307E'", - "rect": [585, 438, 32, 89], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u3042\u3063\u305F\u304B'", - "rect": [713, 123, 32, 84], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u3070\u3089\u3057\u3044'", - "rect": [585, 123, 32, 84], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u8A2A\u554F'", - "rect": [681, 480, 32, 47], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u691C\u7D22'", - "rect": [649, 480, 32, 47], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u8A18\u4E8B'", - "rect": [745, 396, 32, 43], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u7D4C\u9A13'", - "rect": [713, 354, 32, 43], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u8A18\u4E8B'", - "rect": [585, 207, 32, 43], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u7D4C\u9A13'", - "rect": [553, 165, 32, 43], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u8A2A\u554F'", - "rect": [521, 312, 32, 43], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u691C\u7D22'", - "rect": [489, 312, 32, 43], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u8A2A\u554F'", - "rect": [457, 165, 32, 43], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u691C\u7D22'", - "rect": [425, 165, 32, 43], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u3063\u305F'", - "rect": [553, 123, 32, 42], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u3059\u3002'", - "rect": [457, 123, 32, 42], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u3089\u3082'", - "rect": [425, 123, 32, 42], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u898B'", - "rect": [425, 501, 32, 26], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u898B'", - "rect": [745, 207, 32, 22], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u898B'", - "rect": [617, 417, 32, 22], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u5FD8'", - "rect": [713, 207, 32, 21], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment '\u5FD8'", - "rect": [585, 417, 32, 21], - "reason": "selection" - }, - { - "object": "NGPhysicalTextFragment ' '", - "rect": [553, 333, 32, 5], + "object": "NGPhysicalTextFragment '\u3063\u305F\u7D4C\u9A13\u306F\u3042\u308A\u307E\u3059\u304B \u306A\u3089\u30BF\u30A4\u30C8\u30EB\u3068\u30A2'", + "rect": [553, 123, 32, 388], "reason": "selection" } ]
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/transforms/3d/hit-testing/coplanar-with-camera-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/transforms/3d/hit-testing/coplanar-with-camera-expected.txt deleted file mode 100644 index b62ceb7..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/transforms/3d/hit-testing/coplanar-with-camera-expected.txt +++ /dev/null
@@ -1,9 +0,0 @@ -The text on this element should be selectable. Hovering on this element should cause a highlight.Element at 98, 200 has id "background": PASS -Element at 302, 200 has id "background": PASS -Element at 200, 98 has id "background": PASS -Element at 200, 302 has id "background": PASS -Element at 101, 200 has id "layer": PASS -Element at 299, 200 has id "layer": PASS -Element at 200, 101 has id "layer": PASS -Element at 200, 299 has id "layer": PASS -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/transforms/scrollIntoView-transformed-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/transforms/scrollIntoView-transformed-expected.txt deleted file mode 100644 index 0d509313..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/transforms/scrollIntoView-transformed-expected.txt +++ /dev/null
@@ -1,25 +0,0 @@ -Testing the scrolling behaviour of elements when in a normal and transformed container. On the left is the normal container. On the right are containers containing transformed elements. To test this manually, click on the two select elements. The menu popup should appear directly over the element - the content should not move. -The third and fourth containers tests that scrollIntoView(false) works properly in the presence of a scaled element. Because the element is at the bottom of the container, scrollIntoView should give the same result regardless of flag. - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - - - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - - - -This text should not be cut off - - -This text should not be cut off - - -PASS - Element a and Element b had different scrollTop -PASS - Element b had scrollTop: 0 -PASS - Element c and Element d had same scrollTop -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/traversal/tree-walker-001-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/traversal/tree-walker-001-expected.txt deleted file mode 100644 index 15c8a24..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/traversal/tree-walker-001-expected.txt +++ /dev/null
@@ -1,20 +0,0 @@ - -Tree Walker: -A - A.1 - A.2 - A.3 -B - B.1 - B.1.1 -C - C.1 - C.1.1 - C.1.1.1 - C.1.1.2 - C.1.1.3 - C.1.2 - C.2.1 -D - -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/traversal/tree-walker-002-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/traversal/tree-walker-002-expected.txt deleted file mode 100644 index 844d25a6..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/traversal/tree-walker-002-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ - -Tree Walker: -B - B.1 - B.1.1 -C - C.1 - C.1.1 - C.1.1.1 - C.1.1.2 - C.1.1.3 - C.1.2 - C.2.1 -D - -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/traversal/tree-walker-003-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/traversal/tree-walker-003-expected.txt deleted file mode 100644 index 0795412..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/traversal/tree-walker-003-expected.txt +++ /dev/null
@@ -1,30 +0,0 @@ - -Tree Walker: -A - A.1 - A.2 - A.3 -B - B.2 - B.2.1 -C - C.1 - C.1.2 - C.2.1 -D - -Tree Walker: -D - C.2.1 - C.1.2 - C.1 -C - B.2.1 - B.2 -B - A.3 - A.2 - A.1 -A - -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/traversal/tree-walker-004-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/traversal/tree-walker-004-expected.txt deleted file mode 100644 index 4b7bd8e..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/traversal/tree-walker-004-expected.txt +++ /dev/null
@@ -1,44 +0,0 @@ - -Tree Walker: -A - A.1 - A.2 - A.3 -B - B.1 - B.1.1 - B.1.2 - B.2 - B.2.1 -C - C.1 - C.1.1 - C.1.1.1 - C.1.1.2 - C.1.1.3 - C.1.2 - C.2.1 -D - -Tree Walker: -D - C.2.1 - C.1.2 - C.1.1.3 - C.1.1.2 - C.1.1.1 - C.1.1 - C.1 -C - B.2.1 - B.2 - B.1.2 - B.1.1 - B.1 -B - A.3 - A.2 - A.1 -A - -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/traversal/tree-walker-005-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/traversal/tree-walker-005-expected.txt deleted file mode 100644 index 731ea17f..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/traversal/tree-walker-005-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ - -Tree Walker: -B - B.2 - B.2.1 -C - C.1 - C.1.1 - C.1.1.1 - C.1.1.2 - C.1.1.3 - C.1.2 - C.2.1 -D - -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/composite-after-paint/fast/overflow/overflow-height-float-not-removed-crash3-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/composite-after-paint/fast/overflow/overflow-height-float-not-removed-crash3-expected.txt deleted file mode 100644 index 01adb9b..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/composite-after-paint/fast/overflow/overflow-height-float-not-removed-crash3-expected.txt +++ /dev/null
@@ -1,3 +0,0 @@ -Test passes if it does not crash. - sometextsometextsometextsometextsometextsometext -
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/outofblink-cors-ns/http/tests/navigation/form-targets-cross-site-frame-get-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/outofblink-cors-ns/http/tests/navigation/form-targets-cross-site-frame-get-expected.txt deleted file mode 100644 index 8c86440..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/outofblink-cors-ns/http/tests/navigation/form-targets-cross-site-frame-get-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -Test field: - - --------- -Frame: 'cross-site-frame' --------- -This page was requested with the HTTP method GET. - -Parameters: - -test-field = test-value -Http headers: - -HTTP_CONNECTION = keep-alive -HTTP_HOST = localhost:8080 -HTTP_REFERER = http://127.0.0.1:8000/navigation/form-targets-cross-site-frame-get.html -HTTP_SEC_METADATA = cause=forced, destination=nested-document, site=cross-site -HTTP_UPGRADE_INSECURE_REQUESTS = 1
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/outofblink-cors-ns/http/tests/navigation/form-targets-cross-site-frame-no-referrer-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/outofblink-cors-ns/http/tests/navigation/form-targets-cross-site-frame-no-referrer-expected.txt deleted file mode 100644 index 5bb8877..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/outofblink-cors-ns/http/tests/navigation/form-targets-cross-site-frame-no-referrer-expected.txt +++ /dev/null
@@ -1,19 +0,0 @@ -Test field: - - --------- -Frame: 'cross-site-frame' --------- -This page was requested with the HTTP method POST. - -Parameters: - -test-field = test-value -Http headers: - -HTTP_CACHE_CONTROL = max-age=0 -HTTP_CONNECTION = keep-alive -HTTP_HOST = localhost:8080 -HTTP_ORIGIN = null -HTTP_SEC_METADATA = cause=forced, destination=nested-document, site=cross-site -HTTP_UPGRADE_INSECURE_REQUESTS = 1
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/outofblink-cors-ns/http/tests/navigation/form-targets-cross-site-frame-post-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/outofblink-cors-ns/http/tests/navigation/form-targets-cross-site-frame-post-expected.txt deleted file mode 100644 index 9ad8ab7..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/outofblink-cors-ns/http/tests/navigation/form-targets-cross-site-frame-post-expected.txt +++ /dev/null
@@ -1,20 +0,0 @@ -Test field: - - --------- -Frame: 'cross-site-frame' --------- -This page was requested with the HTTP method POST. - -Parameters: - -test-field = test-value -Http headers: - -HTTP_CACHE_CONTROL = max-age=0 -HTTP_CONNECTION = keep-alive -HTTP_HOST = localhost:8080 -HTTP_ORIGIN = http://127.0.0.1:8000 -HTTP_REFERER = http://127.0.0.1:8000/navigation/form-targets-cross-site-frame-post.html -HTTP_SEC_METADATA = cause=forced, destination=nested-document, site=cross-site -HTTP_UPGRADE_INSECURE_REQUESTS = 1
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/outofblink-cors-ns/http/tests/navigation/form-with-enctype-targets-cross-site-frame-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/outofblink-cors-ns/http/tests/navigation/form-with-enctype-targets-cross-site-frame-expected.txt deleted file mode 100644 index 1a8e236..0000000 --- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/virtual/outofblink-cors-ns/http/tests/navigation/form-with-enctype-targets-cross-site-frame-expected.txt +++ /dev/null
@@ -1,20 +0,0 @@ -Test field: - - --------- -Frame: 'cross-site-frame' --------- -This page was requested with the HTTP method POST. - -Parameters: - -test-field = test-value -Http headers: - -HTTP_CACHE_CONTROL = max-age=0 -HTTP_CONNECTION = keep-alive -HTTP_HOST = localhost:8080 -HTTP_ORIGIN = http://127.0.0.1:8000 -HTTP_REFERER = http://127.0.0.1:8000/navigation/form-with-enctype-targets-cross-site-frame.html -HTTP_SEC_METADATA = cause=forced, destination=nested-document, site=cross-site -HTTP_UPGRADE_INSECURE_REQUESTS = 1
diff --git a/third_party/blink/web_tests/fullscreen/full-screen-test.js b/third_party/blink/web_tests/fullscreen/full-screen-test.js index 1d6790e..800322b 100644 --- a/third_party/blink/web_tests/fullscreen/full-screen-test.js +++ b/third_party/blink/web_tests/fullscreen/full-screen-test.js
@@ -9,7 +9,7 @@ testRunner.waitUntilDone(); } -function runWithKeyDown(fn) +function runWithKeyDown(fn, key) { function thunk() { document.removeEventListener("keypress", thunk, false); @@ -17,8 +17,10 @@ } document.addEventListener("keypress", thunk, false); - if (window.eventSender) - eventSender.keyDown(" ", []); + if (window.eventSender) { + let character = key || " "; + eventSender.keyDown(character, []); + } } function logConsole()
diff --git a/third_party/blink/web_tests/fullscreen/video-controls-timeline.html b/third_party/blink/web_tests/fullscreen/video-controls-timeline.html index ba197b16..5eab655 100644 --- a/third_party/blink/web_tests/fullscreen/video-controls-timeline.html +++ b/third_party/blink/web_tests/fullscreen/video-controls-timeline.html
@@ -31,7 +31,10 @@ }); waitForEvent(video, 'canplaythrough', function() { - runWithKeyDown(function(){video.webkitRequestFullScreen()}); + // Run with garbage key. User input is needed to go into fullscreen, + // and since the video will be in focus, we cannot use space as it + // will play the video. + runWithKeyDown(function(){video.webkitRequestFullScreen()}, 'a'); }); video.src = '../media/content/test.ogv';
diff --git a/third_party/blink/web_tests/http/tests/accessibility/slow-document-load-expected.txt b/third_party/blink/web_tests/http/tests/accessibility/slow-document-load-expected.txt index 35708ae6..794aad30 100644 --- a/third_party/blink/web_tests/http/tests/accessibility/slow-document-load-expected.txt +++ b/third_party/blink/web_tests/http/tests/accessibility/slow-document-load-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS elapsedTime is >= 900 PASS gotLayoutCompleteBeforeOneSecond is true PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/activedomobject/media-expected.txt b/third_party/blink/web_tests/http/tests/activedomobject/media-expected.txt index 5cc0c2c..36a0816 100644 --- a/third_party/blink/web_tests/http/tests/activedomobject/media-expected.txt +++ b/third_party/blink/web_tests/http/tests/activedomobject/media-expected.txt
@@ -1,6 +1,5 @@ Tests that reparenting media elements also reparents ActiveDOMObject. - Before Reparenting PASS: internals.pausableObjectCount(document) should be '2' and is. PASS: internals.pausableObjectCount(iframe) should be '2' and is.
diff --git a/third_party/blink/web_tests/http/tests/appcache/404-manifest-expected.txt b/third_party/blink/web_tests/http/tests/appcache/404-manifest-expected.txt index 77ead251..20f3066 100644 --- a/third_party/blink/web_tests/http/tests/appcache/404-manifest-expected.txt +++ b/third_party/blink/web_tests/http/tests/appcache/404-manifest-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS gotCheckingEvent is true PASS window.applicationCache.status is applicationCache.UNCACHED PASS event.reason is "manifest"
diff --git a/third_party/blink/web_tests/http/tests/appcache/404-resource-cross-origin-expected.txt b/third_party/blink/web_tests/http/tests/appcache/404-resource-cross-origin-expected.txt index 477e848..cde521f 100644 --- a/third_party/blink/web_tests/http/tests/appcache/404-resource-cross-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/appcache/404-resource-cross-origin-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS applicationCache.status is applicationCache.UNCACHED PASS event.reason is "resource" PASS event.url is "http://127.0.0.1/does-not-exist.txt"
diff --git a/third_party/blink/web_tests/http/tests/appcache/404-resource-expected.txt b/third_party/blink/web_tests/http/tests/appcache/404-resource-expected.txt index 01feeab..5e48eda4 100644 --- a/third_party/blink/web_tests/http/tests/appcache/404-resource-expected.txt +++ b/third_party/blink/web_tests/http/tests/appcache/404-resource-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS applicationCache.status is applicationCache.UNCACHED PASS event.reason is "resource" PASS event.url is "http://127.0.0.1:8000/appcache/resources/does-not-exist.txt"
diff --git a/third_party/blink/web_tests/http/tests/appcache/destroyed-frame-expected.txt b/third_party/blink/web_tests/http/tests/appcache/destroyed-frame-expected.txt index 9ea83e98..b4bb50a 100644 --- a/third_party/blink/web_tests/http/tests/appcache/destroyed-frame-expected.txt +++ b/third_party/blink/web_tests/http/tests/appcache/destroyed-frame-expected.txt
@@ -1,6 +1,8 @@ PASS successfullyParsed is true TEST COMPLETE + + Test for bug 33813: Crash when using DOMApplicationCache from a destroyed frame. PASS if didn't crash.
diff --git a/third_party/blink/web_tests/http/tests/appcache/different-https-origin-resource-main-expected.txt b/third_party/blink/web_tests/http/tests/appcache/different-https-origin-resource-main-expected.txt index 67ee129..e680ea2 100644 --- a/third_party/blink/web_tests/http/tests/appcache/different-https-origin-resource-main-expected.txt +++ b/third_party/blink/web_tests/http/tests/appcache/different-https-origin-resource-main-expected.txt
@@ -1,4 +1,3 @@ Test that a resource from a different https origin is not cached. FAIL: Different https origin resource is getting downloaded to cache. -
diff --git a/third_party/blink/web_tests/http/tests/appcache/exceptions-expected.txt b/third_party/blink/web_tests/http/tests/appcache/exceptions-expected.txt index 65ec8e20..f0b1e6b8 100644 --- a/third_party/blink/web_tests/http/tests/appcache/exceptions-expected.txt +++ b/third_party/blink/web_tests/http/tests/appcache/exceptions-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS cache.update() threw exception InvalidStateError: Failed to execute 'update' on 'ApplicationCache': there is no application cache to update.. PASS cache.swapCache() threw exception InvalidStateError: Failed to execute 'swapCache' on 'ApplicationCache': there is no newer application cache to swap to.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/appcache/foreign-fallback-expected.txt b/third_party/blink/web_tests/http/tests/appcache/foreign-fallback-expected.txt index dded924b..52a7d13 100644 --- a/third_party/blink/web_tests/http/tests/appcache/foreign-fallback-expected.txt +++ b/third_party/blink/web_tests/http/tests/appcache/foreign-fallback-expected.txt
@@ -1,6 +1,5 @@ Test for bug 44406: Application Cache crash when a fallback document has a manifest URL. PASS + The frame below should display a Not Found error - the fallback entry is foreign, so it shouldn't be used for main resource. - -
diff --git a/third_party/blink/web_tests/http/tests/appcache/main-resource-hash-expected.txt b/third_party/blink/web_tests/http/tests/appcache/main-resource-hash-expected.txt index 45dceb4..93a11b10 100644 --- a/third_party/blink/web_tests/http/tests/appcache/main-resource-hash-expected.txt +++ b/third_party/blink/web_tests/http/tests/appcache/main-resource-hash-expected.txt
@@ -4,4 +4,5 @@ Should say SUCCESS: SUCCESS - + +
diff --git a/third_party/blink/web_tests/http/tests/appcache/main-resource-redirect-expected.txt b/third_party/blink/web_tests/http/tests/appcache/main-resource-redirect-expected.txt index 0a727f5..a3c3a553 100644 --- a/third_party/blink/web_tests/http/tests/appcache/main-resource-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/appcache/main-resource-redirect-expected.txt
@@ -1,4 +1,3 @@ Test that application cache is consulted again after a redirect response. PASS -
diff --git a/third_party/blink/web_tests/http/tests/appcache/modified-manifest-expected.txt b/third_party/blink/web_tests/http/tests/appcache/modified-manifest-expected.txt index a71b37c..1bfb2ef 100644 --- a/third_party/blink/web_tests/http/tests/appcache/modified-manifest-expected.txt +++ b/third_party/blink/web_tests/http/tests/appcache/modified-manifest-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS gotCheckingEvent is true PASS gotDownloadingEvent is true PASS window.applicationCache.status is applicationCache.UNCACHED
diff --git a/third_party/blink/web_tests/http/tests/appcache/obsolete-error-events-expected.txt b/third_party/blink/web_tests/http/tests/appcache/obsolete-error-events-expected.txt index a229cf6..dbdca0d51 100644 --- a/third_party/blink/web_tests/http/tests/appcache/obsolete-error-events-expected.txt +++ b/third_party/blink/web_tests/http/tests/appcache/obsolete-error-events-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS eventDetailsFromWindow.type is "obsolete" PASS eventDetailsFromFrame.type is "error" PASS eventDetailsFromFrame.reason is "manifest"
diff --git a/third_party/blink/web_tests/http/tests/appcache/offline-access-expected.txt b/third_party/blink/web_tests/http/tests/appcache/offline-access-expected.txt index 1ef95e00..48452744 100644 --- a/third_party/blink/web_tests/http/tests/appcache/offline-access-expected.txt +++ b/third_party/blink/web_tests/http/tests/appcache/offline-access-expected.txt
@@ -4,4 +4,5 @@ Should say SUCCESS: SUCCESS - + +
diff --git a/third_party/blink/web_tests/http/tests/appcache/remove-cache-expected.txt b/third_party/blink/web_tests/http/tests/appcache/remove-cache-expected.txt index d009b9aa..8d54a3bc 100644 --- a/third_party/blink/web_tests/http/tests/appcache/remove-cache-expected.txt +++ b/third_party/blink/web_tests/http/tests/appcache/remove-cache-expected.txt
@@ -5,6 +5,7 @@ Frame 2: Manifest loading results in 404 response, so the cache group becomes obsolete, and an obsolete event is dispatched (because the document in frame was associated with a cache in the group). Frame 3: Manifest is still 404 - the document is never associated with a cache. Frame 4: Manifest is now available, so the document gets associated with a cache in a newly created group; the obsolete cache group is not affected. + Should say SUCCESS: SUCCESS
diff --git a/third_party/blink/web_tests/http/tests/appcache/resource-redirect-expected.txt b/third_party/blink/web_tests/http/tests/appcache/resource-redirect-expected.txt index b1e9e80..7fa757a 100644 --- a/third_party/blink/web_tests/http/tests/appcache/resource-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/appcache/resource-redirect-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS window.applicationCache.status is window.applicationCache.UNCACHED PASS event.reason is "resource" PASS event.url is "http://127.0.0.1:8000/appcache/resources/resource-redirect.php"
diff --git a/third_party/blink/web_tests/http/tests/appcache/wrong-signature-2-expected.txt b/third_party/blink/web_tests/http/tests/appcache/wrong-signature-2-expected.txt index 535e8bb5..7fb74b47 100644 --- a/third_party/blink/web_tests/http/tests/appcache/wrong-signature-2-expected.txt +++ b/third_party/blink/web_tests/http/tests/appcache/wrong-signature-2-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS window.applicationCache.status is applicationCache.UNCACHED PASS event.reason is "signature" PASS event.url is ""
diff --git a/third_party/blink/web_tests/http/tests/appcache/wrong-signature-expected.txt b/third_party/blink/web_tests/http/tests/appcache/wrong-signature-expected.txt index 535e8bb5..7fb74b47 100644 --- a/third_party/blink/web_tests/http/tests/appcache/wrong-signature-expected.txt +++ b/third_party/blink/web_tests/http/tests/appcache/wrong-signature-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS window.applicationCache.status is applicationCache.UNCACHED PASS event.reason is "signature" PASS event.url is ""
diff --git a/third_party/blink/web_tests/http/tests/cache/cached-main-resource-expected.txt b/third_party/blink/web_tests/http/tests/cache/cached-main-resource-expected.txt index 23985fc9..94e1707 100644 --- a/third_party/blink/web_tests/http/tests/cache/cached-main-resource-expected.txt +++ b/third_party/blink/web_tests/http/tests/cache/cached-main-resource-expected.txt
@@ -1,2 +1 @@ FAIL -
diff --git a/third_party/blink/web_tests/http/tests/cache/content-type-ignored-during-revalidation-expected.txt b/third_party/blink/web_tests/http/tests/cache/content-type-ignored-during-revalidation-expected.txt index f47a974..a222a99 100644 --- a/third_party/blink/web_tests/http/tests/cache/content-type-ignored-during-revalidation-expected.txt +++ b/third_party/blink/web_tests/http/tests/cache/content-type-ignored-during-revalidation-expected.txt
@@ -2,9 +2,9 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS window.getComputedStyle(document.getElementById('test')).backgroundColor is "rgb(0, 255, 0)" PASS successfullyParsed is true TEST COMPLETE + This div should have a green background.
diff --git a/third_party/blink/web_tests/http/tests/cache/history-only-cached-subresource-loads-max-age-https-expected.txt b/third_party/blink/web_tests/http/tests/cache/history-only-cached-subresource-loads-max-age-https-expected.txt index 7a2d6c31..55d449ce 100644 --- a/third_party/blink/web_tests/http/tests/cache/history-only-cached-subresource-loads-max-age-https-expected.txt +++ b/third_party/blink/web_tests/http/tests/cache/history-only-cached-subresource-loads-max-age-https-expected.txt
@@ -1,7 +1,3 @@ -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/cache/resources/max-age-resource.html' attempted to load subresource at 'https://127.0.0.1:8443/cache/resources/random-max-age.cgi' over broken HTTPS. -CONSOLE ERROR: line 1: Mixed Content: The page at 'https://127.0.0.1:8443/cache/resources/max-age-resource.html' attempted to load subresource at 'https://127.0.0.1:8443/cache/resources/random-max-age.cgi' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/cache/resources/max-age-resource.html' attempted to load subresource at 'https://127.0.0.1:8443/cache/resources/random-max-age.cgi' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/cache/resources/max-age-resource-next.html' attempted to load subresource at 'https://127.0.0.1:8443/cache/resources/random-max-age.cgi' over broken HTTPS. This test checks that loading a subresource with "Cache-Control: max-age=0" is cached and reused in back navigation when the page is not in the page cache. We then test that loading the same subresource is refetched when used in non-stale loads such as refreshes or normal navigation.
diff --git a/third_party/blink/web_tests/http/tests/cache/post-redirect-get-expected.txt b/third_party/blink/web_tests/http/tests/cache/post-redirect-get-expected.txt index e91be87e..14055e0 100644 --- a/third_party/blink/web_tests/http/tests/cache/post-redirect-get-expected.txt +++ b/third_party/blink/web_tests/http/tests/cache/post-redirect-get-expected.txt
@@ -1,3 +1,2 @@ CONSOLE WARNING: line 14: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. PASS -
diff --git a/third_party/blink/web_tests/http/tests/cache/post-with-cached-subresources-expected.txt b/third_party/blink/web_tests/http/tests/cache/post-with-cached-subresources-expected.txt index e91be87e..14055e0 100644 --- a/third_party/blink/web_tests/http/tests/cache/post-with-cached-subresources-expected.txt +++ b/third_party/blink/web_tests/http/tests/cache/post-with-cached-subresources-expected.txt
@@ -1,3 +1,2 @@ CONSOLE WARNING: line 14: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. PASS -
diff --git a/third_party/blink/web_tests/http/tests/cache/reload-main-resource-expected.txt b/third_party/blink/web_tests/http/tests/cache/reload-main-resource-expected.txt index 69cfc5a9..7ef22e9 100644 --- a/third_party/blink/web_tests/http/tests/cache/reload-main-resource-expected.txt +++ b/third_party/blink/web_tests/http/tests/cache/reload-main-resource-expected.txt
@@ -1,2 +1 @@ PASS -
diff --git a/third_party/blink/web_tests/http/tests/cache/stopped-revalidation-expected.txt b/third_party/blink/web_tests/http/tests/cache/stopped-revalidation-expected.txt index 58de103f3..e0f90fed 100644 --- a/third_party/blink/web_tests/http/tests/cache/stopped-revalidation-expected.txt +++ b/third_party/blink/web_tests/http/tests/cache/stopped-revalidation-expected.txt
@@ -1,3 +1,2 @@ CONSOLE WARNING: line 11: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. PASS -
diff --git a/third_party/blink/web_tests/http/tests/cache/subresource-fragment-identifier-expected.txt b/third_party/blink/web_tests/http/tests/cache/subresource-fragment-identifier-expected.txt index a301a53..02d26bc 100644 --- a/third_party/blink/web_tests/http/tests/cache/subresource-fragment-identifier-expected.txt +++ b/third_party/blink/web_tests/http/tests/cache/subresource-fragment-identifier-expected.txt
@@ -3,9 +3,9 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Resource Requeset Log: + bg_pattern.jpg PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/cache/subresource-revalidation-referrer-expected.txt b/third_party/blink/web_tests/http/tests/cache/subresource-revalidation-referrer-expected.txt index 25280c7d2..2daf03e 100644 --- a/third_party/blink/web_tests/http/tests/cache/subresource-revalidation-referrer-expected.txt +++ b/third_party/blink/web_tests/http/tests/cache/subresource-revalidation-referrer-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS referrer.indexOf("subresource-revalidation-referrer.html") >= 0 is true PASS referrer.indexOf("subresource-revalidation-referrer-iframe.html") >= 0 is true PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/cache/xhr-vary-header-expected.txt b/third_party/blink/web_tests/http/tests/cache/xhr-vary-header-expected.txt index f7bb3cb4..5d7a84d8 100644 --- a/third_party/blink/web_tests/http/tests/cache/xhr-vary-header-expected.txt +++ b/third_party/blink/web_tests/http/tests/cache/xhr-vary-header-expected.txt
@@ -1,6 +1,6 @@ Test that XMLHttpRequest doesn't return a wrong cached answer when there is a Vary header in response. -Make cross origin request +Make cross origin request PASS responseText is 'Cross origin response' PASS responseText is 'Same origin response'
diff --git a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.drawImage.canvas-expected.txt b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.drawImage.canvas-expected.txt index 13d97762..29e4c13 100644 --- a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.drawImage.canvas-expected.txt +++ b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.drawImage.canvas-expected.txt
@@ -1,10 +1,11 @@ < [index] > security.drawImage.canvas + drawImage of unclean canvas makes the canvas origin-unclean References: security.drawImage.canvas + Actual output: Passed -
diff --git a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.drawImage.image-expected.txt b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.drawImage.image-expected.txt index d5dc00d..de68224 100644 --- a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.drawImage.image-expected.txt +++ b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.drawImage.image-expected.txt
@@ -1,10 +1,11 @@ < [index] > security.drawImage.image + drawImage of different-origin image makes the canvas origin-unclean References: security.drawImage.image security.toDataURL security.getImageData + Actual output: Passed -
diff --git a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.canvas.fillStyle-expected.txt b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.canvas.fillStyle-expected.txt index 61df12d7..6305a780 100644 --- a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.canvas.fillStyle-expected.txt +++ b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.canvas.fillStyle-expected.txt
@@ -1,10 +1,11 @@ < [index] > security.pattern.canvas.fillStyle + Setting fillStyle to a pattern of an unclean canvas makes the canvas origin-unclean References: security.fillStyle.canvas Bugzilla + Actual output: Passed -
diff --git a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.canvas.strokeStyle-expected.txt b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.canvas.strokeStyle-expected.txt index b07b953..adabf2d 100644 --- a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.canvas.strokeStyle-expected.txt +++ b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.canvas.strokeStyle-expected.txt
@@ -1,10 +1,11 @@ < [index] > security.pattern.canvas.strokeStyle + Setting strokeStyle to a pattern of an unclean canvas makes the canvas origin-unclean References: security.strokeStyle.canvas Bugzilla + Actual output: Passed -
diff --git a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.canvas.timing-expected.txt b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.canvas.timing-expected.txt index 95a43eb..51130d8e 100644 --- a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.canvas.timing-expected.txt +++ b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.canvas.timing-expected.txt
@@ -1,12 +1,13 @@ < [index] > security.pattern.canvas.timing + Pattern safety depends on whether the source was origin-clean, not on whether it still is clean References: security.start security.fillStyle.canvas + Disagrees with spec on "is" vs "was" Actual output: Passed -
diff --git a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.create-expected.txt b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.create-expected.txt index 9c2070e..8ebfe6f 100644 --- a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.create-expected.txt +++ b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.create-expected.txt
@@ -1,10 +1,11 @@ < [index] > security.pattern.create + Creating an unclean pattern does not make the canvas origin-unclean References: security.start + Actual output: Passed -
diff --git a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.cross-expected.txt b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.cross-expected.txt index ab097ac..2e5f88bb 100644 --- a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.cross-expected.txt +++ b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.cross-expected.txt
@@ -1,10 +1,11 @@ < [index] > security.pattern.cross + Using an unclean pattern makes the target canvas origin-unclean, not the pattern canvas References: security.start + Actual output: Passed -
diff --git a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.image.fillStyle-expected.txt b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.image.fillStyle-expected.txt index 2f1e835..81b7bc3b 100644 --- a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.image.fillStyle-expected.txt +++ b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.image.fillStyle-expected.txt
@@ -1,10 +1,11 @@ < [index] > security.pattern.image.fillStyle + Setting fillStyle to a pattern of a different-origin image makes the canvas origin-unclean References: security.fillStyle.image + Actual output: Passed -
diff --git a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.image.strokeStyle-expected.txt b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.image.strokeStyle-expected.txt index debab8f..ca5b33d 100644 --- a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.image.strokeStyle-expected.txt +++ b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.pattern.image.strokeStyle-expected.txt
@@ -1,10 +1,11 @@ < [index] > security.pattern.image.strokeStyle + Setting strokeStyle to a pattern of a different-origin image makes the canvas origin-unclean References: security.strokeStyle.image + Actual output: Passed -
diff --git a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.reset-expected.txt b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.reset-expected.txt index 8adf16b..6bd5d500 100644 --- a/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.reset-expected.txt +++ b/third_party/blink/web_tests/http/tests/canvas/philip/tests/security.reset-expected.txt
@@ -1,10 +1,11 @@ < [index] > security.reset + Resetting the canvas state does not reset the origin-clean flag References: initial.reset + Actual output: Failed assertion: should throw exception: canvas.toDataURL() -
diff --git a/third_party/blink/web_tests/http/tests/canvas/webgl/origin-clean-conformance-expected.txt b/third_party/blink/web_tests/http/tests/canvas/webgl/origin-clean-conformance-expected.txt index bfef0a8..6b4d21b 100644 --- a/third_party/blink/web_tests/http/tests/canvas/webgl/origin-clean-conformance-expected.txt +++ b/third_party/blink/web_tests/http/tests/canvas/webgl/origin-clean-conformance-expected.txt
@@ -25,4 +25,5 @@ PASS should not throw exception by toDataURL for WebGL canvas, which should stay origin clean. TEST COMPLETE +
diff --git a/third_party/blink/web_tests/http/tests/cookies/double-quoted-value-with-semi-colon-expected.txt b/third_party/blink/web_tests/http/tests/cookies/double-quoted-value-with-semi-colon-expected.txt index 522d1a2..4ef2dc7 100644 --- a/third_party/blink/web_tests/http/tests/cookies/double-quoted-value-with-semi-colon-expected.txt +++ b/third_party/blink/web_tests/http/tests/cookies/double-quoted-value-with-semi-colon-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Check that setting a cookie with a semi-colon in a duoble-quoted value works FAIL cookie was 'disorder="477beccb'. Expected 'disorder="477beccb;richard"'. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/cookies/http-get-cookie-set-in-js-expected.txt b/third_party/blink/web_tests/http/tests/cookies/http-get-cookie-set-in-js-expected.txt index 5150eb4e..58e1fbb 100644 --- a/third_party/blink/web_tests/http/tests/cookies/http-get-cookie-set-in-js-expected.txt +++ b/third_party/blink/web_tests/http/tests/cookies/http-get-cookie-set-in-js-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - checking that the cookie set in javascript can be read by HTTP server PASS cookie is 'name=value'. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/cookies/js-get-and-set-http-only-cookie-expected.txt b/third_party/blink/web_tests/http/tests/cookies/js-get-and-set-http-only-cookie-expected.txt index df7353c..48e3e3ab 100644 --- a/third_party/blink/web_tests/http/tests/cookies/js-get-and-set-http-only-cookie-expected.txt +++ b/third_party/blink/web_tests/http/tests/cookies/js-get-and-set-http-only-cookie-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Check that we can't get or set httpOnly Cookies by JavaScript. PASS We can't get httpOnly cookies by JavaScript. PASS We can't set httpOnly cookies by JavaScript.
diff --git a/third_party/blink/web_tests/http/tests/cookies/js-set-null-expected.txt b/third_party/blink/web_tests/http/tests/cookies/js-set-null-expected.txt index 216e43c..948ed08 100644 --- a/third_party/blink/web_tests/http/tests/cookies/js-set-null-expected.txt +++ b/third_party/blink/web_tests/http/tests/cookies/js-set-null-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS document.cookie is 'null' PASS cookie is 'null'. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/cookies/multiple-cookies-expected.txt b/third_party/blink/web_tests/http/tests/cookies/multiple-cookies-expected.txt index e8d5ef1d..9abba81 100644 --- a/third_party/blink/web_tests/http/tests/cookies/multiple-cookies-expected.txt +++ b/third_party/blink/web_tests/http/tests/cookies/multiple-cookies-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Check setting several cookies without clearing. PASS cookie is 'test=foobar'. PASS cookie is 'test2=foobar; test=foobar'.
diff --git a/third_party/blink/web_tests/http/tests/cookies/simple-cookies-expired-expected.txt b/third_party/blink/web_tests/http/tests/cookies/simple-cookies-expired-expected.txt index deb8cd8..20c2cb1 100644 --- a/third_party/blink/web_tests/http/tests/cookies/simple-cookies-expired-expected.txt +++ b/third_party/blink/web_tests/http/tests/cookies/simple-cookies-expired-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Check that setting a simple cookie works. PASS cookie is 'test=foobar'. Check setting a cookie that timed out.
diff --git a/third_party/blink/web_tests/http/tests/cookies/simple-cookies-max-age-expected.txt b/third_party/blink/web_tests/http/tests/cookies/simple-cookies-max-age-expected.txt index c48aebc9..4c46e9f 100644 --- a/third_party/blink/web_tests/http/tests/cookies/simple-cookies-max-age-expected.txt +++ b/third_party/blink/web_tests/http/tests/cookies/simple-cookies-max-age-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Check that setting a simple cookie works. PASS cookie is 'test=foobar'. Check setting a cookie that timed out.
diff --git a/third_party/blink/web_tests/http/tests/cookies/single-quoted-value-expected.txt b/third_party/blink/web_tests/http/tests/cookies/single-quoted-value-expected.txt index ab0558f..d65beee 100644 --- a/third_party/blink/web_tests/http/tests/cookies/single-quoted-value-expected.txt +++ b/third_party/blink/web_tests/http/tests/cookies/single-quoted-value-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Check that setting a cookie with a single-quoted value works. PASS cookie is 'singleQuoted="value'. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/css/css-image-valued-shape-expected.txt b/third_party/blink/web_tests/http/tests/css/css-image-valued-shape-expected.txt index 8eb15cd7..5ff6a853 100644 --- a/third_party/blink/web_tests/http/tests/css/css-image-valued-shape-expected.txt +++ b/third_party/blink/web_tests/http/tests/css/css-image-valued-shape-expected.txt
@@ -1,6 +1,7 @@ Verify that a image valued shape-outside layout is updated after the image has been loaded. This test checks that left edge of the "Hello World" text span is defined by the 200px wide float before shape-outside image has been loaded and by the 100px wide image after it's been laoded. Hello World + PASS elementRect("text").left is 200 PASS elementRect("text").left is 100 PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/css/pending-stylesheet-offset-width-expected.txt b/third_party/blink/web_tests/http/tests/css/pending-stylesheet-offset-width-expected.txt index 2e9c8e96..d137b0c 100644 --- a/third_party/blink/web_tests/http/tests/css/pending-stylesheet-offset-width-expected.txt +++ b/third_party/blink/web_tests/http/tests/css/pending-stylesheet-offset-width-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS t.offsetWidth is 200 PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/css/performance-info-with-cached-sheet-expected.txt b/third_party/blink/web_tests/http/tests/css/performance-info-with-cached-sheet-expected.txt index 1bf6754..c05bbbdc 100644 --- a/third_party/blink/web_tests/http/tests/css/performance-info-with-cached-sheet-expected.txt +++ b/third_party/blink/web_tests/http/tests/css/performance-info-with-cached-sheet-expected.txt
@@ -2,10 +2,10 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE + PASS window.performance.getEntriesByName("http://127.0.0.1:8000/css/resources/abe.png") is not [] PASS window.performance.getEntriesByName("http://127.0.0.1:8000/resources/square20.png") is [] PASS window.performance.getEntriesByName("http://127.0.0.1:8000/misc/resources/acid3/font.ttf") is not []
diff --git a/third_party/blink/web_tests/http/tests/css/resource-timing-details-for-revalidation-expected.txt b/third_party/blink/web_tests/http/tests/css/resource-timing-details-for-revalidation-expected.txt index ef439900d..0144ffe 100644 --- a/third_party/blink/web_tests/http/tests/css/resource-timing-details-for-revalidation-expected.txt +++ b/third_party/blink/web_tests/http/tests/css/resource-timing-details-for-revalidation-expected.txt
@@ -1,6 +1,6 @@ PASS successfullyParsed is true TEST COMPLETE + PASS entry.domainLookupStart > 0 is true This fetches ahem font. -
diff --git a/third_party/blink/web_tests/http/tests/css/shared-stylesheet-mutation-expected.txt b/third_party/blink/web_tests/http/tests/css/shared-stylesheet-mutation-expected.txt index 836731e..fc67a1d 100644 --- a/third_party/blink/web_tests/http/tests/css/shared-stylesheet-mutation-expected.txt +++ b/third_party/blink/web_tests/http/tests/css/shared-stylesheet-mutation-expected.txt
@@ -2,11 +2,11 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Test 0 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(255, 0, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: red; } @@ -18,10 +18,12 @@ } @font-face { font-family: Foo; } + Test 1 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: red; } @@ -34,10 +36,12 @@ } @font-face { font-family: Foo; } + Test 2 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @page :right { margin-left: 3cm; } @-webkit-keyframes bounce { @@ -46,10 +50,12 @@ } @font-face { font-family: Foo; } + Test 3 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: red; } @@ -62,10 +68,12 @@ } @font-face { font-family: Foo; } + Test 4 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media all { } @@ -76,10 +84,12 @@ } @font-face { font-family: Foo; } + Test 5 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: green; } @@ -91,10 +101,12 @@ } @font-face { font-family: Foo; } + Test 6 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media all { #testdiv { } @@ -106,10 +118,12 @@ } @font-face { font-family: Foo; } + Test 7 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: green; } @@ -121,10 +135,12 @@ } @font-face { font-family: Foo; } + Test 8 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media all { #dontmatch { background-color: red; } @@ -136,10 +152,12 @@ } @font-face { font-family: Foo; } + Test 9 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media print { #testdiv { background-color: red; } @@ -151,10 +169,12 @@ } @font-face { font-family: Foo; } + Test 10 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media print { #testdiv { background-color: red; } @@ -166,16 +186,20 @@ } @font-face { font-family: Foo; } + Test 11 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } + Test 12 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + @import url("data:text/css;charset=utf-8,%23testdiv%7Bbackground-color%3Agreen%20!important%7D"); #testdiv { background-color: green; } @media all { @@ -188,10 +212,12 @@ } @font-face { font-family: Foo; } + Test 13 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(255, 0, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: red; } @@ -203,10 +229,12 @@ } @font-face { font-family: Foo; } + Test 14 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(255, 0, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: red; } @@ -219,10 +247,12 @@ } @font-face { font-family: Foo; } + Test 15 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(255, 0, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: red; } @@ -233,10 +263,12 @@ } @font-face { font-family: Foo; } + Test 16 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(255, 0, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: red; } @@ -248,6 +280,7 @@ } @font-face { font-family: Bar; } + PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/http/tests/css/shared-stylesheet-mutation-preconstruct-expected.txt b/third_party/blink/web_tests/http/tests/css/shared-stylesheet-mutation-preconstruct-expected.txt index 836731e..fc67a1d 100644 --- a/third_party/blink/web_tests/http/tests/css/shared-stylesheet-mutation-preconstruct-expected.txt +++ b/third_party/blink/web_tests/http/tests/css/shared-stylesheet-mutation-preconstruct-expected.txt
@@ -2,11 +2,11 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Test 0 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(255, 0, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: red; } @@ -18,10 +18,12 @@ } @font-face { font-family: Foo; } + Test 1 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: red; } @@ -34,10 +36,12 @@ } @font-face { font-family: Foo; } + Test 2 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @page :right { margin-left: 3cm; } @-webkit-keyframes bounce { @@ -46,10 +50,12 @@ } @font-face { font-family: Foo; } + Test 3 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: red; } @@ -62,10 +68,12 @@ } @font-face { font-family: Foo; } + Test 4 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media all { } @@ -76,10 +84,12 @@ } @font-face { font-family: Foo; } + Test 5 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: green; } @@ -91,10 +101,12 @@ } @font-face { font-family: Foo; } + Test 6 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media all { #testdiv { } @@ -106,10 +118,12 @@ } @font-face { font-family: Foo; } + Test 7 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: green; } @@ -121,10 +135,12 @@ } @font-face { font-family: Foo; } + Test 8 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media all { #dontmatch { background-color: red; } @@ -136,10 +152,12 @@ } @font-face { font-family: Foo; } + Test 9 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media print { #testdiv { background-color: red; } @@ -151,10 +169,12 @@ } @font-face { font-family: Foo; } + Test 10 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } @media print { #testdiv { background-color: red; } @@ -166,16 +186,20 @@ } @font-face { font-family: Foo; } + Test 11 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + #testdiv { background-color: green; } + Test 12 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(0, 128, 0)' + @import url("data:text/css;charset=utf-8,%23testdiv%7Bbackground-color%3Agreen%20!important%7D"); #testdiv { background-color: green; } @media all { @@ -188,10 +212,12 @@ } @font-face { font-family: Foo; } + Test 13 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(255, 0, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: red; } @@ -203,10 +229,12 @@ } @font-face { font-family: Foo; } + Test 14 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(255, 0, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: red; } @@ -219,10 +247,12 @@ } @font-face { font-family: Foo; } + Test 15 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(255, 0, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: red; } @@ -233,10 +263,12 @@ } @font-face { font-family: Foo; } + Test 16 -------------------------------------- PASS getComputedStyle(testElement, null).getPropertyValue('background-color') is 'rgb(255, 0, 0)' + #testdiv { background-color: green; } @media all { #testdiv { background-color: red; } @@ -248,6 +280,7 @@ } @font-face { font-family: Bar; } + PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/user-timing-expected.txt b/third_party/blink/web_tests/http/tests/devtools/tracing/user-timing-expected.txt new file mode 100644 index 0000000..ad1bbbac --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/tracing/user-timing-expected.txt
@@ -0,0 +1,7 @@ +Tests the instrumentation of a UserTiming events + +Expecting three measures with durations (in this order): 100, 200, 0 +Got Async Event. Duration: 100 +Got Async Event. Duration: 200 +Got Async Event. Duration: 0 +
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/user-timing.js b/third_party/blink/web_tests/http/tests/devtools/tracing/user-timing.js new file mode 100644 index 0000000..47c03f85 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/tracing/user-timing.js
@@ -0,0 +1,56 @@ +// 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. + +(async function() { + TestRunner.addResult(`Tests the instrumentation of a UserTiming events\n`); + await TestRunner.loadModule('performance_test_runner'); + await TestRunner.showPanel('timeline'); + await TestRunner.evaluateInPagePromise(` + function makeUserTimings() + { + let fulfill; + const promise = new Promise(resolve => fulfill = resolve); + + setTimeout(_ => performance.mark('astart'), 0); + setTimeout(_ => performance.mark('aend'), 100); + + setTimeout(_ => performance.mark('bstart'), 20); + setTimeout(_ => performance.mark('bend'), 220); + + setTimeout(_ => performance.mark('cstart'), 40); + setTimeout(_ => performance.mark('cend'), 41); + + setTimeout(_ => { + performance.measure('timespan', 'astart', 'aend'); + performance.measure('timespan', 'bstart', 'bend'); + performance.measure('timespan', 'cstart', 'cend'); + }, 250); + + setTimeout(fulfill, 300); + return promise; + } + `); + + PerformanceTestRunner.invokeWithTracing('makeUserTimings', TestRunner.safeWrap(onTracingComplete)); + TestRunner.addResult(`Expecting three measures with durations (in this order): 100, 200, 0`); + + var userTimingEventCount = 0; + function onTracingComplete() { + + PerformanceTestRunner.tracingModel().sortedProcesses().forEach(process => { + process.sortedThreads().forEach(thread => thread.asyncEvents().forEach(processAsyncEvent)); + }); + + TestRunner.assertEquals(3, userTimingEventCount); + TestRunner.completeTest(); + + function processAsyncEvent(event) { + if (!event._parsedCategories.has('blink.user_timing')) return; + + const roundedDuration = Math.round(event.duration / 100) * 100; + TestRunner.addResult(`Got Async Event. Duration: ${roundedDuration}`); + ++userTimingEventCount; + } + } +})();
diff --git a/third_party/blink/web_tests/http/tests/dom/create-contextual-fragment-from-bodyless-svg-document-range-expected.txt b/third_party/blink/web_tests/http/tests/dom/create-contextual-fragment-from-bodyless-svg-document-range-expected.txt index f12d100..1d9133cf 100644 --- a/third_party/blink/web_tests/http/tests/dom/create-contextual-fragment-from-bodyless-svg-document-range-expected.txt +++ b/third_party/blink/web_tests/http/tests/dom/create-contextual-fragment-from-bodyless-svg-document-range-expected.txt
@@ -1,5 +1,3 @@ Test of createContextualFragment from a Range whose container is an SVG document with no <svg> element. If the test succeeds you will see the word "PASS" below. PASS - -
diff --git a/third_party/blink/web_tests/http/tests/dom/create-contextual-fragment-from-svg-document-range-expected.txt b/third_party/blink/web_tests/http/tests/dom/create-contextual-fragment-from-svg-document-range-expected.txt index 08f40f9..901dfedeb 100644 --- a/third_party/blink/web_tests/http/tests/dom/create-contextual-fragment-from-svg-document-range-expected.txt +++ b/third_party/blink/web_tests/http/tests/dom/create-contextual-fragment-from-svg-document-range-expected.txt
@@ -1,5 +1,3 @@ Test of createContextualFragment from a Range whose container is an SVG document. If the test succeeds you will see the word "PASS" below. PASS - -
diff --git a/third_party/blink/web_tests/http/tests/dom/document-contentType-expected.txt b/third_party/blink/web_tests/http/tests/dom/document-contentType-expected.txt index 5d515879..8b3db68 100644 --- a/third_party/blink/web_tests/http/tests/dom/document-contentType-expected.txt +++ b/third_party/blink/web_tests/http/tests/dom/document-contentType-expected.txt
@@ -1,6 +1,7 @@ PASS successfullyParsed is true TEST COMPLETE + PASS iframes[0].contentDocument.contentType is "text/css" PASS iframes[0].contentDocument.cloneNode(false).contentType is "text/css" PASS iframes[1].contentDocument.contentType is "application/x-javascript" @@ -29,4 +30,5 @@ PASS iframes[12].contentDocument.cloneNode(false).contentType is "image/jpeg" PASS iframes[13].contentDocument.contentType is "image/png" PASS iframes[13].contentDocument.cloneNode(false).contentType is "image/png" +
diff --git a/third_party/blink/web_tests/http/tests/download/basic-ascii-expected.txt b/third_party/blink/web_tests/http/tests/download/basic-ascii-expected.txt index be716cb..ee7ec3d 100644 --- a/third_party/blink/web_tests/http/tests/download/basic-ascii-expected.txt +++ b/third_party/blink/web_tests/http/tests/download/basic-ascii-expected.txt
@@ -1,4 +1,2 @@ Policy delegate: attempt to load http://127.0.0.1:8000/download/resources/basic-ascii.php with navigation type 'other' Download file name should be "test file.txt". - -
diff --git a/third_party/blink/web_tests/http/tests/download/inherited-encoding-form-submission-result-expected.txt b/third_party/blink/web_tests/http/tests/download/inherited-encoding-form-submission-result-expected.txt index edf8ed19..205c1218 100644 --- a/third_party/blink/web_tests/http/tests/download/inherited-encoding-form-submission-result-expected.txt +++ b/third_party/blink/web_tests/http/tests/download/inherited-encoding-form-submission-result-expected.txt
@@ -1,4 +1,2 @@ Policy delegate: attempt to load http://127.0.0.1:8000/download/resources/literal-koi8-r.php? with navigation type 'form submitted' Downloaded file name should be "SUССЕSS.txt" (letters "CCE" are Cyrillic). - -
diff --git a/third_party/blink/web_tests/http/tests/download/literal-utf-8-expected.txt b/third_party/blink/web_tests/http/tests/download/literal-utf-8-expected.txt index 9f4b9f7c..9b3b9016 100644 --- a/third_party/blink/web_tests/http/tests/download/literal-utf-8-expected.txt +++ b/third_party/blink/web_tests/http/tests/download/literal-utf-8-expected.txt
@@ -1,4 +1,2 @@ Policy delegate: attempt to load http://127.0.0.1:8000/download/resources/literal-utf-8.php with navigation type 'other' Downloaded file name should be "SUССЕSS.txt" (letters "CCE" are Cyrillic). - -
diff --git a/third_party/blink/web_tests/http/tests/eventsource/eventsource-bad-mime-type-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/eventsource-bad-mime-type-expected.txt index 742dc74..d694fc5 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/eventsource-bad-mime-type-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/eventsource-bad-mime-type-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS es.readyState is es.CLOSED PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/eventsource/eventsource-content-type-charset-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/eventsource-content-type-charset-expected.txt index 865332c..5c6c8c1 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/eventsource-content-type-charset-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/eventsource-content-type-charset-expected.txt
@@ -4,7 +4,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS es = new EventSource("/eventsource/resources/response-content-type-charset.php?contentType=text/event-stream%3B%20charset%3DUTF-8") did not throw exception. Content type: text/event-stream; charset=UTF-8 PASS !!es.sawError is false
diff --git a/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-basic-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-basic-expected.txt index 58dbd0f..7aa65b1 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-basic-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-basic-expected.txt
@@ -4,7 +4,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS es = new EventSource("http://127.0.0.1:8080/eventsource/resources/es-cors-basic.php?count=1") did not throw exception. PASS es.withCredentials is false PASS es.readyState is es.CLOSED
diff --git a/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-no-server-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-no-server-expected.txt index 82e43c71..d4d20fea2 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-no-server-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-no-server-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS es = new EventSource("http://127.0.0.1:12345/event-stream") did not throw exception. PASS got error event and readyState is CONNECTING PASS es = new EventSource("http://localhost:54321/event-stream") did not throw exception.
diff --git a/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-non-http-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-non-http-expected.txt index e47cb76..bd1a70d 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-non-http-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-non-http-expected.txt
@@ -6,7 +6,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS es.readyState is EventSource.CLOSED PASS es.readyState is EventSource.CLOSED PASS es.readyState is EventSource.CLOSED
diff --git a/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-redirect-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-redirect-expected.txt index d5e89fb..633503ce 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-redirect-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS es = new EventSource("/resources/redirect.php?code=307&url=http://127.0.0.1:8080/eventsource/resources/es-cors-basic.php") did not throw exception. PASS es.readyState is EventSource.CLOSED PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-with-credentials-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-with-credentials-expected.txt index 34a16ba..ce402fe 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-with-credentials-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/eventsource-cors-with-credentials-expected.txt
@@ -5,7 +5,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS es = new EventSource("http://127.0.0.1:8080/eventsource/resources/es-cors-credentials.php?count=1", {'withCredentials': true}) did not throw exception. PASS es.withCredentials is true PASS count != 4 && count != 5 is true
diff --git a/third_party/blink/web_tests/http/tests/eventsource/eventsource-csp-redirect-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/eventsource-csp-redirect-expected.txt index b994f603..a8693a9 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/eventsource-csp-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/eventsource-csp-redirect-expected.txt
@@ -4,7 +4,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS es = new EventSource("http://127.0.0.1:8000/resources/redirect.php?code=307&cors_allow_origin=*&url=http://127.0.0.1:8080/resources/redirect.php") did not throw exception. PASS es.readyState is EventSource.CLOSED PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/eventsource/eventsource-eof-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/eventsource-eof-expected.txt index db8eab93..a00b9f6a 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/eventsource-eof-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/eventsource-eof-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS evt.type is "message" PASS evt.data is "DATA1" PASS evt.lastEventId is "1"
diff --git a/third_party/blink/web_tests/http/tests/eventsource/eventsource-events-after-close-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/eventsource-events-after-close-expected.txt index 381f6626..f99a618 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/eventsource-events-after-close-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/eventsource-events-after-close-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS es = new EventSource("/eventsource/resources/event-stream.php"); did not throw exception. PASS Got message #1 PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/eventsource/eventsource-parse-event-stream-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/eventsource-parse-event-stream-expected.txt index 8a4af08..c9c4e5c3 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/eventsource-parse-event-stream-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/eventsource-parse-event-stream-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS es = new EventSource("resources/event-stream.php"); did not throw exception. PASS got open event PASS evt.data is "\n\n"
diff --git a/third_party/blink/web_tests/http/tests/eventsource/eventsource-reconnect-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/eventsource-reconnect-expected.txt index 9b405cc9e..0fef3bc 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/eventsource-reconnect-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/eventsource-reconnect-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS es.readyState is es.CONNECTING PASS es.readyState is es.OPEN PASS evt.lastEventId is "77☃"
diff --git a/third_party/blink/web_tests/http/tests/eventsource/eventsource-reconnect-on-redirect-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/eventsource-reconnect-on-redirect-expected.txt index 11bf191..de07ec4 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/eventsource-reconnect-on-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/eventsource-reconnect-on-redirect-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS es.readyState is es.CONNECTING PASS es.readyState is es.OPEN got a message: url = /eventsource/resources/echo-url.php?id=, id =
diff --git a/third_party/blink/web_tests/http/tests/eventsource/eventsource-retry-precision-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/eventsource-retry-precision-expected.txt index 1466bd0e..d55696b4 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/eventsource-retry-precision-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/eventsource-retry-precision-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS did not immediately reconnect DONE PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/eventsource/eventsource-status-code-states-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/eventsource-status-code-states-expected.txt index f5fd394..da815804 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/eventsource-status-code-states-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/eventsource-status-code-states-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS arrayCompare(states, tests[count].expectedStates) is true PASS status code 200 resulted in states CONNECTING, OPEN, OPEN, CONNECTING, CLOSED PASS arrayCompare(states, tests[count].expectedStates) is true
diff --git a/third_party/blink/web_tests/http/tests/eventsource/eventsource-url-attribute-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/eventsource-url-attribute-expected.txt index 191b7c1..f6960e4b 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/eventsource-url-attribute-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/eventsource-url-attribute-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS source.url is "http://127.0.0.1:8000/eventsource/resources/event-stream.php" PASS source.URL is undefined. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-bad-mime-type-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-bad-mime-type-expected.txt index 0887232..a6787d4 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-bad-mime-type-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-bad-mime-type-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ../script-tests/eventsource-bad-mime-type.js PASS [Worker] es.readyState is es.CLOSED PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-content-type-charset-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-content-type-charset-expected.txt index 6b85f12..4b2b7fd 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-content-type-charset-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-content-type-charset-expected.txt
@@ -4,7 +4,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ../script-tests/eventsource-content-type-charset.js PASS [Worker] es = new EventSource("/eventsource/resources/response-content-type-charset.php?contentType=text/event-stream%3B%20charset%3DUTF-8") did not throw exception. [Worker] Content type: text/event-stream; charset=UTF-8
diff --git a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-basic-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-basic-expected.txt index d19dcf53..afc5f8f 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-basic-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-basic-expected.txt
@@ -4,7 +4,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ../script-tests/eventsource-cors-basic.js PASS [Worker] es = new EventSource("http://127.0.0.1:8080/eventsource/resources/es-cors-basic.php?count=1") did not throw exception. PASS [Worker] es.withCredentials is false
diff --git a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-no-server-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-no-server-expected.txt index d09caf91..2f97a5e 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-no-server-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-no-server-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ../script-tests/eventsource-cors-no-server.js PASS [Worker] es = new EventSource("http://127.0.0.1:12345/event-stream") did not throw exception. PASS [Worker] got error event and readyState is CONNECTING
diff --git a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-non-http-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-non-http-expected.txt index bbbb437..d4f94b6 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-non-http-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-non-http-expected.txt
@@ -6,7 +6,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ../script-tests/eventsource-cors-non-http.js PASS [Worker] es.readyState is EventSource.CLOSED PASS [Worker] es.readyState is EventSource.CLOSED
diff --git a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-redirect-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-redirect-expected.txt index 7139ecdb..f27584a 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-redirect-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ../script-tests/eventsource-cors-redirect.js PASS [Worker] es = new EventSource("/resources/redirect.php?code=307&url=http://127.0.0.1:8080/eventsource/resources/es-cors-basic.php") did not throw exception. PASS [Worker] es.readyState is EventSource.CLOSED
diff --git a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-with-credentials-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-with-credentials-expected.txt index 74a829f1..078b4fb5 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-with-credentials-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-cors-with-credentials-expected.txt
@@ -5,7 +5,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ../script-tests/eventsource-cors-with-credentials.js PASS [Worker] es = new EventSource("http://127.0.0.1:8080/eventsource/resources/es-cors-credentials.php?count=1", {'withCredentials': true}) did not throw exception. PASS [Worker] es.withCredentials is true
diff --git a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-csp-redirect-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-csp-redirect-expected.txt index 1e4bd84d..651d960 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-csp-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-csp-redirect-expected.txt
@@ -4,7 +4,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ../script-tests/eventsource-csp-redirect.js PASS [Worker] es = new EventSource("http://127.0.0.1:8000/resources/redirect.php?code=307&cors_allow_origin=*&url=http://127.0.0.1:8080/resources/redirect.php") did not throw exception. PASS [Worker] es.readyState is EventSource.CLOSED
diff --git a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-eof-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-eof-expected.txt index 03d71cf..143c698 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-eof-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-eof-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ../script-tests/eventsource-eof.js PASS [Worker] evt.type is "message" PASS [Worker] evt.data is "DATA1"
diff --git a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-events-after-close-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-events-after-close-expected.txt index 4d214ba..0d1b487c 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-events-after-close-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-events-after-close-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ../script-tests/eventsource-events-after-close.js PASS [Worker] es = new EventSource("/eventsource/resources/event-stream.php"); did not throw exception. PASS [Worker] Got message #1
diff --git a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-parse-event-stream-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-parse-event-stream-expected.txt index 7ee9889..16b7afc 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-parse-event-stream-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-parse-event-stream-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ../script-tests/eventsource-parse-event-stream.js PASS [Worker] es = new EventSource("resources/event-stream.php"); did not throw exception. FAIL [Worker] count should be 7. Was -1.
diff --git a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-reconnect-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-reconnect-expected.txt index 0ff2d9a..27e3591 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-reconnect-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-reconnect-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ../script-tests/eventsource-reconnect.js PASS [Worker] es.readyState is es.CONNECTING PASS [Worker] es.readyState is es.OPEN
diff --git a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-retry-precision-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-retry-precision-expected.txt index a92ddcd6..f049df7d 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-retry-precision-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-retry-precision-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ../script-tests/eventsource-retry-precision.js PASS [Worker] did not immediately reconnect [Worker] DONE
diff --git a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-status-code-states-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-status-code-states-expected.txt index 98e86253..873841e 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-status-code-states-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-status-code-states-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ../script-tests/eventsource-status-code-states.js PASS [Worker] arrayCompare(states, tests[count].expectedStates) is true PASS [Worker] status code 200 resulted in states CONNECTING, OPEN, OPEN, CONNECTING, CLOSED
diff --git a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-url-attribute-expected.txt b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-url-attribute-expected.txt index 3cfe1ea..1d295b4 100644 --- a/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-url-attribute-expected.txt +++ b/third_party/blink/web_tests/http/tests/eventsource/workers/eventsource-url-attribute-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ../script-tests/eventsource-url-attribute.js PASS [Worker] source.url is "http://127.0.0.1:8000/eventsource/resources/event-stream.php" PASS [Worker] source.URL is undefined.
diff --git a/third_party/blink/web_tests/http/tests/fetch/serviceworker/thorough/scheme-blob-base-https-other-https-expected.txt b/third_party/blink/web_tests/http/tests/fetch/serviceworker/thorough/scheme-blob-base-https-other-https-expected.txt index 80fc3f0..9a6ca8e7 100644 --- a/third_party/blink/web_tests/http/tests/fetch/serviceworker/thorough/scheme-blob-base-https-other-https-expected.txt +++ b/third_party/blink/web_tests/http/tests/fetch/serviceworker/thorough/scheme-blob-base-https-other-https-expected.txt
@@ -1,10 +1,3 @@ -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/serviceworker/resources/fetch-access-control-login.html' attempted to load subresource at 'https://username1s:password1s@127.0.0.1:8443/serviceworker/resources/fetch-access-control.php?Auth' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://localhost:8443/serviceworker/resources/fetch-access-control-login.html' attempted to load subresource at 'https://username2s:password2s@localhost:8443/serviceworker/resources/fetch-access-control.php?Auth' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/fetch/serviceworker/thorough/scheme-blob-base-https-other-https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharness.js' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/fetch/serviceworker/thorough/scheme-blob-base-https-other-https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharnessreport.js' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/fetch/serviceworker/thorough/scheme-blob-base-https-other-https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/get-host-info.js?pipe=sub' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/fetch/serviceworker/thorough/scheme-blob-base-https-other-https.html' attempted to load subresource at 'https://127.0.0.1:8443/serviceworker/resources/test-helpers.js' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/fetch/serviceworker/thorough/scheme-blob-base-https-other-https.html' attempted to load subresource at 'https://127.0.0.1:8443/fetch/resources/init.js' over broken HTTPS. This is a testharness.js-based test. Harness Error. harness_status.status = 1 , harness_status.message = 1 duplicate test name: "scheme-blob" PASS Startup
diff --git a/third_party/blink/web_tests/http/tests/fetch/serviceworker/thorough/scheme-blob-expected.txt b/third_party/blink/web_tests/http/tests/fetch/serviceworker/thorough/scheme-blob-expected.txt index 289f22b..9a6ca8e7 100644 --- a/third_party/blink/web_tests/http/tests/fetch/serviceworker/thorough/scheme-blob-expected.txt +++ b/third_party/blink/web_tests/http/tests/fetch/serviceworker/thorough/scheme-blob-expected.txt
@@ -1,5 +1,3 @@ -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/serviceworker/resources/fetch-access-control-login.html' attempted to load subresource at 'https://username1s:password1s@127.0.0.1:8443/serviceworker/resources/fetch-access-control.php?Auth' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://localhost:8443/serviceworker/resources/fetch-access-control-login.html' attempted to load subresource at 'https://username2s:password2s@localhost:8443/serviceworker/resources/fetch-access-control.php?Auth' over broken HTTPS. This is a testharness.js-based test. Harness Error. harness_status.status = 1 , harness_status.message = 1 duplicate test name: "scheme-blob" PASS Startup
diff --git a/third_party/blink/web_tests/http/tests/fetch/serviceworker/thorough/scheme-blob-other-https-expected.txt b/third_party/blink/web_tests/http/tests/fetch/serviceworker/thorough/scheme-blob-other-https-expected.txt index 289f22b..9a6ca8e7 100644 --- a/third_party/blink/web_tests/http/tests/fetch/serviceworker/thorough/scheme-blob-other-https-expected.txt +++ b/third_party/blink/web_tests/http/tests/fetch/serviceworker/thorough/scheme-blob-other-https-expected.txt
@@ -1,5 +1,3 @@ -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/serviceworker/resources/fetch-access-control-login.html' attempted to load subresource at 'https://username1s:password1s@127.0.0.1:8443/serviceworker/resources/fetch-access-control.php?Auth' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://localhost:8443/serviceworker/resources/fetch-access-control-login.html' attempted to load subresource at 'https://username2s:password2s@localhost:8443/serviceworker/resources/fetch-access-control.php?Auth' over broken HTTPS. This is a testharness.js-based test. Harness Error. harness_status.status = 1 , harness_status.message = 1 duplicate test name: "scheme-blob" PASS Startup
diff --git a/third_party/blink/web_tests/http/tests/fileapi/blob-url-in-subframe-expected.txt b/third_party/blink/web_tests/http/tests/fileapi/blob-url-in-subframe-expected.txt index 0a0c4a9..31dec61 100644 --- a/third_party/blink/web_tests/http/tests/fileapi/blob-url-in-subframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/fileapi/blob-url-in-subframe-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/http/tests/filesystem/resolve-uri-expected.txt b/third_party/blink/web_tests/http/tests/filesystem/resolve-uri-expected.txt index bdac8b5..1ff077c 100644 --- a/third_party/blink/web_tests/http/tests/filesystem/resolve-uri-expected.txt +++ b/third_party/blink/web_tests/http/tests/filesystem/resolve-uri-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - * Resolving a generated URL. PASS expectedPath is actualPath PASS isFile is true
diff --git a/third_party/blink/web_tests/http/tests/filesystem/workers/resolve-url-expected.txt b/third_party/blink/web_tests/http/tests/filesystem/workers/resolve-url-expected.txt index a8630ca29..13997f1d 100644 --- a/third_party/blink/web_tests/http/tests/filesystem/workers/resolve-url-expected.txt +++ b/third_party/blink/web_tests/http/tests/filesystem/workers/resolve-url-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ../script-tests/resolve-uri.js [Worker] * Resolving a generated URL. PASS [Worker] expectedPath is actualPath
diff --git a/third_party/blink/web_tests/http/tests/filesystem/workers/resolve-url-sync-expected.txt b/third_party/blink/web_tests/http/tests/filesystem/workers/resolve-url-sync-expected.txt index e6fb596..3b8aace 100644 --- a/third_party/blink/web_tests/http/tests/filesystem/workers/resolve-url-sync-expected.txt +++ b/third_party/blink/web_tests/http/tests/filesystem/workers/resolve-url-sync-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: script-tests/resolve-url-sync.js [Worker] * Resolving a generated URL. PASS [Worker] expectedPath is actualPath
diff --git a/third_party/blink/web_tests/http/tests/fullscreen/fullscreenelement-different-origin-expected.txt b/third_party/blink/web_tests/http/tests/fullscreen/fullscreenelement-different-origin-expected.txt index b9c8b744..888f0e3 100644 --- a/third_party/blink/web_tests/http/tests/fullscreen/fullscreenelement-different-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/fullscreen/fullscreenelement-different-origin-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS document.webkitFullscreenElement is targetDiv1 PASS document.webkitCurrentFullScreenElement is targetDiv1 PASS message is "inner-iframe.html document.webkitFullscreenElement = null"
diff --git a/third_party/blink/web_tests/http/tests/fullscreen/fullscreenelement-same-origin-expected.txt b/third_party/blink/web_tests/http/tests/fullscreen/fullscreenelement-same-origin-expected.txt index f582735..e5986c1 100644 --- a/third_party/blink/web_tests/http/tests/fullscreen/fullscreenelement-same-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/fullscreen/fullscreenelement-same-origin-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS document.webkitFullscreenElement is targetDiv1 PASS document.webkitCurrentFullScreenElement is targetDiv1 PASS message is "inner-iframe.html document.webkitFullscreenElement = null"
diff --git a/third_party/blink/web_tests/http/tests/history/back-during-onload-triggered-by-back-expected.txt b/third_party/blink/web_tests/http/tests/history/back-during-onload-triggered-by-back-expected.txt index 2a87bb1..a60488e1 100644 --- a/third_party/blink/web_tests/http/tests/history/back-during-onload-triggered-by-back-expected.txt +++ b/third_party/blink/web_tests/http/tests/history/back-during-onload-triggered-by-back-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/http/tests/history/client-redirect-after-push-state-expected.txt b/third_party/blink/web_tests/http/tests/history/client-redirect-after-push-state-expected.txt index 5002f2c7..2577b4d 100644 --- a/third_party/blink/web_tests/http/tests/history/client-redirect-after-push-state-expected.txt +++ b/third_party/blink/web_tests/http/tests/history/client-redirect-after-push-state-expected.txt
@@ -2,9 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-inline-scripts-expected.txt b/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-inline-scripts-expected.txt index 6bf19179..44cfdce 100644 --- a/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-inline-scripts-expected.txt +++ b/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-inline-scripts-expected.txt
@@ -4,9 +4,9 @@ Created <iframe class="left" src="resources/red.html"></iframe> Created <iframe class="right" src="resources/green.html"></iframe> + Final frame URLs during this page load (should match the list above): URL of left is http://127.0.0.1:8000/history/resources/red.html URL of right is http://127.0.0.1:8000/history/resources/green.html Dynamically created frames: -
diff --git a/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-onload-handler-expected.txt b/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-onload-handler-expected.txt index 42b664b..7343d777 100644 --- a/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-onload-handler-expected.txt +++ b/third_party/blink/web_tests/http/tests/history/dynamic-frame-creation-order-onload-handler-expected.txt
@@ -6,13 +6,14 @@ <iframe class="right" src="resources/green.htm"></iframe> The tricky part is that the order of subframe creation changes at each load (via sessionStorage.pageLoadCount). This can confuse the browser into restoring (after back navigation) green.htm into left frame and red.htm into right frame. + Frame creation order during this page load: Created <iframe class="left" src="resources/red.html"></iframe> Created <iframe class="right" src="resources/green.html"></iframe> + Final frame URLs during this page load (should match the list above): URL of left is http://127.0.0.1:8000/history/resources/red.html URL of right is http://127.0.0.1:8000/history/resources/green.html Dynamically created frames: -
diff --git a/third_party/blink/web_tests/http/tests/history/popstate-fires-with-pending-requests-expected.txt b/third_party/blink/web_tests/http/tests/history/popstate-fires-with-pending-requests-expected.txt index 63ccbbb5..d2b99de 100644 --- a/third_party/blink/web_tests/http/tests/history/popstate-fires-with-pending-requests-expected.txt +++ b/third_party/blink/web_tests/http/tests/history/popstate-fires-with-pending-requests-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting slow image request Pushing newState1 Current search: ?newState1
diff --git a/third_party/blink/web_tests/http/tests/history/popstate-reload-expected.txt b/third_party/blink/web_tests/http/tests/history/popstate-reload-expected.txt index 415866e..6c02b91 100644 --- a/third_party/blink/web_tests/http/tests/history/popstate-reload-expected.txt +++ b/third_party/blink/web_tests/http/tests/history/popstate-reload-expected.txt
@@ -1,2 +1,3 @@ Tests that popstate events do not fire when reloading. + PASS
diff --git a/third_party/blink/web_tests/http/tests/htmlimports/cached-import-expected.txt b/third_party/blink/web_tests/http/tests/htmlimports/cached-import-expected.txt index 859dcdb..d9a6c7a 100644 --- a/third_party/blink/web_tests/http/tests/htmlimports/cached-import-expected.txt +++ b/third_party/blink/web_tests/http/tests/htmlimports/cached-import-expected.txt
@@ -4,7 +4,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/htmlimports/encoding-expected.txt b/third_party/blink/web_tests/http/tests/htmlimports/encoding-expected.txt index 66778ede..ddfc7f4a 100644 --- a/third_party/blink/web_tests/http/tests/htmlimports/encoding-expected.txt +++ b/third_party/blink/web_tests/http/tests/htmlimports/encoding-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Default encoding should be UTF-8... PASS links[0].import.characterSet is "UTF-8" And Content-Type headers should be ignored...
diff --git a/third_party/blink/web_tests/http/tests/htmlimports/import-script-block-crossorigin-dynamic-expected.txt b/third_party/blink/web_tests/http/tests/htmlimports/import-script-block-crossorigin-dynamic-expected.txt index b70b87be..b7f06110 100644 --- a/third_party/blink/web_tests/http/tests/htmlimports/import-script-block-crossorigin-dynamic-expected.txt +++ b/third_party/blink/web_tests/http/tests/htmlimports/import-script-block-crossorigin-dynamic-expected.txt
@@ -5,7 +5,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS document.externalScriptHasRun is undefined PASS document.corsExternalScriptHasRun is undefined PASS document.corsExternalScriptForLocalhostHasRun is true
diff --git a/third_party/blink/web_tests/http/tests/images/image-with-origin-header-expected.txt b/third_party/blink/web_tests/http/tests/images/image-with-origin-header-expected.txt index 3e36137..8073553 100644 --- a/third_party/blink/web_tests/http/tests/images/image-with-origin-header-expected.txt +++ b/third_party/blink/web_tests/http/tests/images/image-with-origin-header-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS srcFirstHasOrigin is true PASS srcLastHasOrigin is true PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/loading/dont-preload-non-img-srcset-expected.txt b/third_party/blink/web_tests/http/tests/loading/dont-preload-non-img-srcset-expected.txt index 857057b..37d19544 100644 --- a/third_party/blink/web_tests/http/tests/loading/dont-preload-non-img-srcset-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/dont-preload-non-img-srcset-expected.txt
@@ -30,5 +30,6 @@ PASS successfullyParsed is true TEST COMPLETE + This test passes if the image is preloaded, but none of the non-img elements with a srcset attribute is.
diff --git a/third_party/blink/web_tests/http/tests/loading/link-preload-image-srcset-2x-expected.txt b/third_party/blink/web_tests/http/tests/loading/link-preload-image-srcset-2x-expected.txt index 8334aa0..1508e941 100644 --- a/third_party/blink/web_tests/http/tests/loading/link-preload-image-srcset-2x-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/link-preload-image-srcset-2x-expected.txt
@@ -18,5 +18,6 @@ PASS successfullyParsed is true TEST COMPLETE + This test passes if the fallback image (defined in the href attribute) is not preloaded, but the 2x version (defined in imagesrcset) is. The second link rel=preload is here to make sure isPreloaded is working properly
diff --git a/third_party/blink/web_tests/http/tests/loading/link-preload-image-srcset-expected.txt b/third_party/blink/web_tests/http/tests/loading/link-preload-image-srcset-expected.txt index 66ae308..93481da 100644 --- a/third_party/blink/web_tests/http/tests/loading/link-preload-image-srcset-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/link-preload-image-srcset-expected.txt
@@ -18,5 +18,6 @@ PASS successfullyParsed is true TEST COMPLETE + This test passes if the fallback image (defined in the href attribute) is not preloaded, but the 1x version (defined in imagesrcset) is. The second link rel=preload is here to make sure isPreloaded is working properly
diff --git a/third_party/blink/web_tests/http/tests/loading/nested_bad_objects-expected.txt b/third_party/blink/web_tests/http/tests/loading/nested_bad_objects-expected.txt index 21b5929..8c50b52 100644 --- a/third_party/blink/web_tests/http/tests/loading/nested_bad_objects-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/nested_bad_objects-expected.txt
@@ -4,4 +4,4 @@ main frame - didFinishDocumentLoadForFrame main frame - didHandleOnloadEventsForFrame main frame - didFinishLoadForFrame - PASS - nested image objects with bad mimetype do not cause a crash. + PASS - nested image objects with bad mimetype do not cause a crash.
diff --git a/third_party/blink/web_tests/http/tests/loading/pending-script-leak-expected.txt b/third_party/blink/web_tests/http/tests/loading/pending-script-leak-expected.txt index 008c1c02..b6bba1e 100644 --- a/third_party/blink/web_tests/http/tests/loading/pending-script-leak-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/pending-script-leak-expected.txt
@@ -11,5 +11,4 @@ main frame - didFinishDocumentLoadForFrame main frame - didHandleOnloadEventsForFrame main frame - didFinishLoadForFrame - There should be no leaks when run with --enable-leak-detection
diff --git a/third_party/blink/web_tests/http/tests/loading/preload-append-scan-expected.txt b/third_party/blink/web_tests/http/tests/loading/preload-append-scan-expected.txt index e94d4a8..fdda6d3e 100644 --- a/third_party/blink/web_tests/http/tests/loading/preload-append-scan-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/preload-append-scan-expected.txt
@@ -7,4 +7,5 @@ This test needs to be run in DRT. Preload scanner should see the image resource. <img src="resources/preload-test.jpg"> + PASS
diff --git a/third_party/blink/web_tests/http/tests/loading/preload-image-sizes-2x-expected.txt b/third_party/blink/web_tests/http/tests/loading/preload-image-sizes-2x-expected.txt index df57f07..8244f69 100644 --- a/third_party/blink/web_tests/http/tests/loading/preload-image-sizes-2x-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/preload-image-sizes-2x-expected.txt
@@ -61,4 +61,5 @@ PASS successfullyParsed is true TEST COMPLETE +
diff --git a/third_party/blink/web_tests/http/tests/loading/preload-image-sizes-expected.txt b/third_party/blink/web_tests/http/tests/loading/preload-image-sizes-expected.txt index 1543f19..d1b1e06 100644 --- a/third_party/blink/web_tests/http/tests/loading/preload-image-sizes-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/preload-image-sizes-expected.txt
@@ -52,4 +52,5 @@ PASS successfullyParsed is true TEST COMPLETE +
diff --git a/third_party/blink/web_tests/http/tests/loading/preload-image-src-expected.txt b/third_party/blink/web_tests/http/tests/loading/preload-image-src-expected.txt index f6158446..2b166a4 100644 --- a/third_party/blink/web_tests/http/tests/loading/preload-image-src-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/preload-image-src-expected.txt
@@ -11,5 +11,6 @@ PASS successfullyParsed is true TEST COMPLETE + This test passes if the image (defined in the src attribute) is preloaded, except for data URI.
diff --git a/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-2x-expected.txt b/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-2x-expected.txt index 605daadc..9cd9db77 100644 --- a/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-2x-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-2x-expected.txt
@@ -18,6 +18,7 @@ PASS successfullyParsed is true TEST COMPLETE + This test passes if the fallback image (defined in the src attribute) is not preloaded, but the 2x version (defined in srcset) is. The second image is here to make sure isPreloaded is working properly
diff --git a/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-duplicate-expected.txt b/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-duplicate-expected.txt index c93c039..c135a4d 100644 --- a/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-duplicate-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-duplicate-expected.txt
@@ -22,6 +22,7 @@ PASS successfullyParsed is true TEST COMPLETE + This test passes if the fallback image (defined in the src attribute) is not preloaded, the 1x version (defined in srcset) is, and none of the duplicate resources is preloaded. The second image is here to make sure isPreloaded is working properly
diff --git a/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-expected.txt b/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-expected.txt index 4a2d7a3..35f1eb6 100644 --- a/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-expected.txt
@@ -18,6 +18,7 @@ PASS successfullyParsed is true TEST COMPLETE + This test passes if the fallback image (defined in the src attribute) is not preloaded, but the 1x version (defined in srcset) is. The second image is here to make sure isPreloaded is working properly
diff --git a/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-reverse-order-expected.txt b/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-reverse-order-expected.txt index 9a0af49..80e4e81 100644 --- a/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-reverse-order-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-reverse-order-expected.txt
@@ -16,6 +16,7 @@ PASS successfullyParsed is true TEST COMPLETE + This test passes if the fallback image (defined in the src attribute) is not preloaded, but the 1x version (defined in srcset) is, even when srcset is defined first. The second image is here to make sure isPreloaded is working properly
diff --git a/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-src-preloaded-expected.txt b/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-src-preloaded-expected.txt index c3c5743..ae9ec54 100644 --- a/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-src-preloaded-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-src-preloaded-expected.txt
@@ -17,6 +17,7 @@ PASS successfullyParsed is true TEST COMPLETE + This test passes if the fallback image (defined in the src attribute) is preloaded, and the 1x versions (defined in srcset) aren't. The second image is here to make sure isPreloaded is working properly
diff --git a/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-src-preloaded-reverse-order-expected.txt b/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-src-preloaded-reverse-order-expected.txt index a4e2e273..8968525 100644 --- a/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-src-preloaded-reverse-order-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/preload-image-srcset-src-preloaded-reverse-order-expected.txt
@@ -17,6 +17,7 @@ PASS successfullyParsed is true TEST COMPLETE + This test passes if the fallback image (defined in the src attribute) is preloaded, and the 1x versions (defined in srcset) aren't, even when srcset is defined first. The second image is here to make sure isPreloaded is working properly
diff --git a/third_party/blink/web_tests/http/tests/loading/preload-picture-invalid-expected.txt b/third_party/blink/web_tests/http/tests/loading/preload-picture-invalid-expected.txt index 48588c5..e7a84ae 100644 --- a/third_party/blink/web_tests/http/tests/loading/preload-picture-invalid-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/preload-picture-invalid-expected.txt
@@ -37,9 +37,7 @@ PASS successfullyParsed is true TEST COMPLETE - - bla + bla -
diff --git a/third_party/blink/web_tests/http/tests/loading/preload-picture-nested-expected.txt b/third_party/blink/web_tests/http/tests/loading/preload-picture-nested-expected.txt index 3a5bc03..1af0247 100644 --- a/third_party/blink/web_tests/http/tests/loading/preload-picture-nested-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/preload-picture-nested-expected.txt
@@ -40,9 +40,6 @@ PASS successfullyParsed is true TEST COMPLETE - - - - - + +
diff --git a/third_party/blink/web_tests/http/tests/loading/preload-picture-sizes-2x-expected.txt b/third_party/blink/web_tests/http/tests/loading/preload-picture-sizes-2x-expected.txt index cb37a6c7..b1d08b9 100644 --- a/third_party/blink/web_tests/http/tests/loading/preload-picture-sizes-2x-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/preload-picture-sizes-2x-expected.txt
@@ -60,4 +60,5 @@ PASS successfullyParsed is true TEST COMPLETE - + +
diff --git a/third_party/blink/web_tests/http/tests/loading/preload-picture-sizes-expected.txt b/third_party/blink/web_tests/http/tests/loading/preload-picture-sizes-expected.txt index 96e747e..7d9fa94 100644 --- a/third_party/blink/web_tests/http/tests/loading/preload-picture-sizes-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/preload-picture-sizes-expected.txt
@@ -61,4 +61,5 @@ PASS successfullyParsed is true TEST COMPLETE - + +
diff --git a/third_party/blink/web_tests/http/tests/loading/preload-video-poster-expected.txt b/third_party/blink/web_tests/http/tests/loading/preload-video-poster-expected.txt index 817a481..35e0b00c 100644 --- a/third_party/blink/web_tests/http/tests/loading/preload-video-poster-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/preload-video-poster-expected.txt
@@ -10,5 +10,6 @@ PASS successfullyParsed is true TEST COMPLETE + This test passes if the image (defined in the src attribute) is preloaded.
diff --git a/third_party/blink/web_tests/http/tests/loading/redirect-methods-expected.txt b/third_party/blink/web_tests/http/tests/loading/redirect-methods-expected.txt index 1dfb926..9bef8ff 100644 --- a/third_party/blink/web_tests/http/tests/loading/redirect-methods-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/redirect-methods-expected.txt
@@ -102,11 +102,8 @@ frame "3" - didFinishLoadForFrame This test checks to see what HTTP method is used to fetch the final resource in the case where the first request results in a redirect. 301, 302, 303, and 307 http redirects are all tested. + 301 redirect - 302 redirect - 303 redirect - 307 redirect -
diff --git a/third_party/blink/web_tests/http/tests/loading/state-object-security-exception-expected.txt b/third_party/blink/web_tests/http/tests/loading/state-object-security-exception-expected.txt index ff7c27f..76a2bea 100644 --- a/third_party/blink/web_tests/http/tests/loading/state-object-security-exception-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/state-object-security-exception-expected.txt
@@ -6,6 +6,8 @@ main frame - didFinishLoadForFrame This test makes sure that calls to pushState() and replaceState() with URLs that violate the security origin check fail as expected. + + Trying to pushState() with url http://localhost/test.html failed with exception SecurityError: Failed to execute 'pushState' on 'History': A history state object with URL 'http://localhost/test.html' cannot be created in a document with origin 'http://127.0.0.1:8000' and URL 'http://127.0.0.1:8000/loading/state-object-security-exception.html'. History length is 1 Trying to replaceState() with url http://localhost/test.html failed with exception SecurityError: Failed to execute 'replaceState' on 'History': A history state object with URL 'http://localhost/test.html' cannot be created in a document with origin 'http://127.0.0.1:8000' and URL 'http://127.0.0.1:8000/loading/state-object-security-exception.html'.
diff --git a/third_party/blink/web_tests/http/tests/loading/text-content-type-with-binary-extension-expected.txt b/third_party/blink/web_tests/http/tests/loading/text-content-type-with-binary-extension-expected.txt index 74c24b9..0dcc4b7 100644 --- a/third_party/blink/web_tests/http/tests/loading/text-content-type-with-binary-extension-expected.txt +++ b/third_party/blink/web_tests/http/tests/loading/text-content-type-with-binary-extension-expected.txt
@@ -10,5 +10,3 @@ Test for https://bugs.webkit.org/show_bug.cgi?id=17360 REGRESSION: mp4 file downloaded from server is downloaded as html. Binary data not loaded as text. Maybe PASS. - -
diff --git a/third_party/blink/web_tests/http/tests/messaging/cross-domain-message-send-expected.txt b/third_party/blink/web_tests/http/tests/messaging/cross-domain-message-send-expected.txt index 12241225..014bdb8 100644 --- a/third_party/blink/web_tests/http/tests/messaging/cross-domain-message-send-expected.txt +++ b/third_party/blink/web_tests/http/tests/messaging/cross-domain-message-send-expected.txt
@@ -1,2 +1 @@ - data: Something origin: http://127.0.0.1:8000
diff --git a/third_party/blink/web_tests/http/tests/misc/DOMContentLoaded-event-expected.txt b/third_party/blink/web_tests/http/tests/misc/DOMContentLoaded-event-expected.txt index 4feb495..cec7d48 100644 --- a/third_party/blink/web_tests/http/tests/misc/DOMContentLoaded-event-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/DOMContentLoaded-event-expected.txt
@@ -4,7 +4,5 @@ ALERT: load event fired! ALERT: PASSED Test case for bug 5122: Equivalent of Mozilla's DOMContentLoaded needed + You should see a note about the DOMContentLoaded event being fired and bubbled, a timer being called, and then the load event being fired. - - -
diff --git a/third_party/blink/web_tests/http/tests/misc/acid2-expected.txt b/third_party/blink/web_tests/http/tests/misc/acid2-expected.txt index 87a60ed..2042436 100644 --- a/third_party/blink/web_tests/http/tests/misc/acid2-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/acid2-expected.txt
@@ -1,8 +1,10 @@ Standards compliant? + Take The Acid2 Test and compare it to the reference rendering. Hello World! + - - + +
diff --git a/third_party/blink/web_tests/http/tests/misc/async-script-expected.txt b/third_party/blink/web_tests/http/tests/misc/async-script-expected.txt index 24f5b8e..f8447e3 100644 --- a/third_party/blink/web_tests/http/tests/misc/async-script-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/async-script-expected.txt
@@ -1,6 +1,8 @@ PASS successfullyParsed is true TEST COMPLETE + + Test that an asynchronous script tag is executed, even if it's removed from the document before it was loaded. This test passes if the word "PASS" is displayed below.
diff --git a/third_party/blink/web_tests/http/tests/misc/bad-charset-alias-expected.txt b/third_party/blink/web_tests/http/tests/misc/bad-charset-alias-expected.txt index 88c213f6..0ef7703 100644 --- a/third_party/blink/web_tests/http/tests/misc/bad-charset-alias-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/bad-charset-alias-expected.txt
@@ -1,5 +1,3 @@ Test that iso-8859-1 aliases that aren't known to Firefox and IE aren't supported (we should fall back to parent frame charset). SUCCESS - -
diff --git a/third_party/blink/web_tests/http/tests/misc/bubble-drag-events-expected.txt b/third_party/blink/web_tests/http/tests/misc/bubble-drag-events-expected.txt index be70297..0bc59ca 100644 --- a/third_party/blink/web_tests/http/tests/misc/bubble-drag-events-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/bubble-drag-events-expected.txt
@@ -1,9 +1,6 @@ CONSOLE ERROR: line 67: Not allowed to load local resource: file: This page tests the drag event bubbling with valid and invalid targets. - - - Drag here. Tests that we don't bubble up the events if we drag something to an iframe that has an invalid source Tests that we don't bubble up the events if we drag something to an iframe that has a valid source
diff --git a/third_party/blink/web_tests/http/tests/misc/cached-scripts-expected.txt b/third_party/blink/web_tests/http/tests/misc/cached-scripts-expected.txt index f508ac59..bb24d88 100644 --- a/third_party/blink/web_tests/http/tests/misc/cached-scripts-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/cached-scripts-expected.txt
@@ -1,3 +1,2 @@ This tests that when script that calls document.write to write out two new script tags while being parsed causes both scripts to be executed, even if the first one is cached. SUCCESS -
diff --git a/third_party/blink/web_tests/http/tests/misc/charset-sniffer-end-sniffing-expected.txt b/third_party/blink/web_tests/http/tests/misc/charset-sniffer-end-sniffing-expected.txt index c664f55..2791de71 100644 --- a/third_party/blink/web_tests/http/tests/misc/charset-sniffer-end-sniffing-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/charset-sniffer-end-sniffing-expected.txt
@@ -2,4 +2,5 @@ Running second script. PASS: First script ran before second script was loaded. + This test is for a bug where the charset sniffer would not stop looking for charset if the body contains no tags. Charset sniffer is supposed to stop looking for charset after 1024 bytes.
diff --git a/third_party/blink/web_tests/http/tests/misc/client-hints-accept-meta-preloader-expected.txt b/third_party/blink/web_tests/http/tests/misc/client-hints-accept-meta-preloader-expected.txt index cf0d081..4c4bd73 100644 --- a/third_party/blink/web_tests/http/tests/misc/client-hints-accept-meta-preloader-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/client-hints-accept-meta-preloader-expected.txt
@@ -1,3 +1,2 @@ This test checks that a meta based Accept-CH is properly parsed by the HTMLPreloadScanner. PASSED -
diff --git a/third_party/blink/web_tests/http/tests/misc/dns-prefetch-control-expected.txt b/third_party/blink/web_tests/http/tests/misc/dns-prefetch-control-expected.txt index f16afa8..fb29a969 100644 --- a/third_party/blink/web_tests/http/tests/misc/dns-prefetch-control-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/dns-prefetch-control-expected.txt
@@ -2,7 +2,8 @@ The following frames contain links that are expected to trigger a DNS prefetch. - + + The following frames contain links that are not expected to cause a DNS prefetch. - +
diff --git a/third_party/blink/web_tests/http/tests/misc/drag-not-loaded-image-expected.txt b/third_party/blink/web_tests/http/tests/misc/drag-not-loaded-image-expected.txt index 74750f3f..29815da 100644 --- a/third_party/blink/web_tests/http/tests/misc/drag-not-loaded-image-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/drag-not-loaded-image-expected.txt
@@ -1,3 +1,2 @@ - Success
diff --git a/third_party/blink/web_tests/http/tests/misc/drag-over-iframe-invalid-source-crash-expected.txt b/third_party/blink/web_tests/http/tests/misc/drag-over-iframe-invalid-source-crash-expected.txt index ec9ec69..c2f4e2af 100644 --- a/third_party/blink/web_tests/http/tests/misc/drag-over-iframe-invalid-source-crash-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/drag-over-iframe-invalid-source-crash-expected.txt
@@ -1,6 +1,4 @@ CONSOLE ERROR: line 22: Not allowed to load local resource: file: This page tests that we don't crash if we drag something to an iframe that has an invalid source. - SUCCESS - didn't crash -
diff --git a/third_party/blink/web_tests/http/tests/misc/embed-image-load-outlives-gc-without-crashing-expected.txt b/third_party/blink/web_tests/http/tests/misc/embed-image-load-outlives-gc-without-crashing-expected.txt index 1e42359..7cce2359d 100644 --- a/third_party/blink/web_tests/http/tests/misc/embed-image-load-outlives-gc-without-crashing-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/embed-image-load-outlives-gc-without-crashing-expected.txt
@@ -1,5 +1,6 @@ PASS successfullyParsed is true TEST COMPLETE + This has an embed element representing an image. That embed element is wrapped in a div. It removes the div, forces garbage collection, and makes sure that the window load event does not fire. It also makes sure there is no crash.
diff --git a/third_party/blink/web_tests/http/tests/misc/empty-urls-expected.txt b/third_party/blink/web_tests/http/tests/misc/empty-urls-expected.txt index 7efef2f..dadcf3e 100644 --- a/third_party/blink/web_tests/http/tests/misc/empty-urls-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/empty-urls-expected.txt
@@ -4,4 +4,5 @@ PASS: video src onerror fired PASS: audio onerror fired PASS: source onerror fired - + +
diff --git a/third_party/blink/web_tests/http/tests/misc/font-face-in-multiple-segmented-faces-expected.txt b/third_party/blink/web_tests/http/tests/misc/font-face-in-multiple-segmented-faces-expected.txt index 8f14932..50f7f48 100644 --- a/third_party/blink/web_tests/http/tests/misc/font-face-in-multiple-segmented-faces-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/font-face-in-multiple-segmented-faces-expected.txt
@@ -1,3 +1 @@ Test for https://bugs.webkit.org/show_bug.cgi?id=22454 REGRESSION (3.2-TOT): Crash below FontFallbackList::fontDataAt on jacobian.org - -
diff --git a/third_party/blink/web_tests/http/tests/misc/form-action-using-replaceChild-expected.txt b/third_party/blink/web_tests/http/tests/misc/form-action-using-replaceChild-expected.txt index 05b659d..4e5f4eca 100644 --- a/third_party/blink/web_tests/http/tests/misc/form-action-using-replaceChild-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/form-action-using-replaceChild-expected.txt
@@ -1,4 +1,5 @@ PASS successfullyParsed is true TEST COMPLETE + Success! The form was rendered correctly. This test is for bug 388664
diff --git a/third_party/blink/web_tests/http/tests/misc/form-target-iframe-inline-expected.txt b/third_party/blink/web_tests/http/tests/misc/form-target-iframe-inline-expected.txt index 17527d5..9ba947d4 100644 --- a/third_party/blink/web_tests/http/tests/misc/form-target-iframe-inline-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/form-target-iframe-inline-expected.txt
@@ -1,2 +1 @@ - This text should be visible.
diff --git a/third_party/blink/web_tests/http/tests/misc/gmail-assert-on-load-expected.txt b/third_party/blink/web_tests/http/tests/misc/gmail-assert-on-load-expected.txt index 74e9eaa..b9ba90c 100644 --- a/third_party/blink/web_tests/http/tests/misc/gmail-assert-on-load-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/gmail-assert-on-load-expected.txt
@@ -1,5 +1,3 @@ This test provokes HTMLTokenizer::timerFired to be called and from within timerFired we want to call WebCore::pageDestroyed. You pass this test if you don't see an ASSERT. This is from http://bugs.webkit.org/show_bug.cgi?id=15765. - -
diff --git a/third_party/blink/web_tests/http/tests/misc/image-blocked-src-change-expected.txt b/third_party/blink/web_tests/http/tests/misc/image-blocked-src-change-expected.txt index 10d02d3f..8d66fc3 100644 --- a/third_party/blink/web_tests/http/tests/misc/image-blocked-src-change-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/image-blocked-src-change-expected.txt
@@ -4,5 +4,3 @@ You should see PASSED once and 250 x 50 green box. The console should also show a blocked attempt to load a local resource. PASSED - -
diff --git a/third_party/blink/web_tests/http/tests/misc/image-blocked-src-no-change-expected.txt b/third_party/blink/web_tests/http/tests/misc/image-blocked-src-no-change-expected.txt index 63d7764..63091c1 100644 --- a/third_party/blink/web_tests/http/tests/misc/image-blocked-src-no-change-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/image-blocked-src-no-change-expected.txt
@@ -5,5 +5,3 @@ This test checks that setting an image url should lead to load even if the image was in error and the url is not changed. For this test to pass, you should see 2 messages in the console - -
diff --git a/third_party/blink/web_tests/http/tests/misc/image-input-type-outlives-gc-without-crashing-expected.txt b/third_party/blink/web_tests/http/tests/misc/image-input-type-outlives-gc-without-crashing-expected.txt index 10eab27..a02f0895 100644 --- a/third_party/blink/web_tests/http/tests/misc/image-input-type-outlives-gc-without-crashing-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/image-input-type-outlives-gc-without-crashing-expected.txt
@@ -1,5 +1,6 @@ PASS successfullyParsed is true TEST COMPLETE + This test has a form with an input type=image element in it. The form is wrapped in a div. It removes the div, forces garbage collection, and makes sure that the window load event does not fire. It also makes sure there is no crash.
diff --git a/third_party/blink/web_tests/http/tests/misc/image-load-outlives-gc-without-crashing-expected.txt b/third_party/blink/web_tests/http/tests/misc/image-load-outlives-gc-without-crashing-expected.txt index 223fdcc9..c94145f 100644 --- a/third_party/blink/web_tests/http/tests/misc/image-load-outlives-gc-without-crashing-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/image-load-outlives-gc-without-crashing-expected.txt
@@ -1,5 +1,6 @@ PASS successfullyParsed is true TEST COMPLETE + This test has an image inside a div. It removes the div, forces garbage collection, and makes sure that the window load event does not fire. It also makes sure there is no crash.
diff --git a/third_party/blink/web_tests/http/tests/misc/image-onerror-no-load-event-expected.txt b/third_party/blink/web_tests/http/tests/misc/image-onerror-no-load-event-expected.txt index da2074b8..82cdcee5e 100644 --- a/third_party/blink/web_tests/http/tests/misc/image-onerror-no-load-event-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/image-onerror-no-load-event-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS Received onerror for non-existent img.src PASS Received onerror for non-existent img.src PASS Received error event repeatedly.
diff --git a/third_party/blink/web_tests/http/tests/misc/javascript-url-stop-loaders-expected.txt b/third_party/blink/web_tests/http/tests/misc/javascript-url-stop-loaders-expected.txt index 6d88936..2a6b550 100644 --- a/third_party/blink/web_tests/http/tests/misc/javascript-url-stop-loaders-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/javascript-url-stop-loaders-expected.txt
@@ -1,6 +1,6 @@ PASS successfullyParsed is true TEST COMPLETE + + This test checks whether loading a JavaScript URL cancels loaders. If it fails, it will give an assertion failure in Debug builds. - -
diff --git a/third_party/blink/web_tests/http/tests/misc/missing-style-sheet-expected.txt b/third_party/blink/web_tests/http/tests/misc/missing-style-sheet-expected.txt index e604a40..871796f 100644 --- a/third_party/blink/web_tests/http/tests/misc/missing-style-sheet-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/missing-style-sheet-expected.txt
@@ -1,2 +1,3 @@ This test passes if it does not ASSERT that the document's pending style sheet count is less than 0, and the load event fires. + PASS: Load event fired.
diff --git a/third_party/blink/web_tests/http/tests/misc/object-image-error-expected.txt b/third_party/blink/web_tests/http/tests/misc/object-image-error-expected.txt index 8a19f14..9d64ba82 100644 --- a/third_party/blink/web_tests/http/tests/misc/object-image-error-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/object-image-error-expected.txt
@@ -1,4 +1,3 @@ Test for http://bugs.webkit.org/show_bug.cgi?id=17471 REGRESSION (r30438): Crash in deleteLineBoxes in cursor-adjusting code browsing Acid3. PASS, no crash. -
diff --git a/third_party/blink/web_tests/http/tests/misc/prefetch-purpose-expected.txt b/third_party/blink/web_tests/http/tests/misc/prefetch-purpose-expected.txt index dc582e7..7e433c7 100644 --- a/third_party/blink/web_tests/http/tests/misc/prefetch-purpose-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/prefetch-purpose-expected.txt
@@ -1,4 +1,5 @@ prefetch-purpose.php has MIME type text/html prefetch-purpose.php has MIME type text/html Purpose: prefetch + This test verifies that prefetches are sent with the HTTP request header Purpose: prefetch. To do this, the root page has a prefetch link targetting this subresource which contains a PHP script (resources/prefetch-purpose.php). The PHP prints the value of the Purpose header into the document. Later, the root page sets window.location to target this script, which should have "Purpose: prefetch" in its output if it's served from cache.
diff --git a/third_party/blink/web_tests/http/tests/misc/redirect-to-about-blank-expected.txt b/third_party/blink/web_tests/http/tests/misc/redirect-to-about-blank-expected.txt index db84807..8db5e55 100644 --- a/third_party/blink/web_tests/http/tests/misc/redirect-to-about-blank-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/redirect-to-about-blank-expected.txt
@@ -1,3 +1,2 @@ - This tests that loading a main resource that redirects to about:blank does not cause a crash (and that the load is done correctly). SUCCESS: Did not crash and loaded about:blank correctly
diff --git a/third_party/blink/web_tests/http/tests/misc/resource-timing-iframe-restored-from-history-expected.txt b/third_party/blink/web_tests/http/tests/misc/resource-timing-iframe-restored-from-history-expected.txt index 2661d6b1..396b12ea 100644 --- a/third_party/blink/web_tests/http/tests/misc/resource-timing-iframe-restored-from-history-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/resource-timing-iframe-restored-from-history-expected.txt
@@ -6,7 +6,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS resources.length is 1 PASS resources[0].name is "http://127.0.0.1:8000/js-test-resources/js-test.js" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/misc/resource-timing-navigation-in-restored-iframe-expected.txt b/third_party/blink/web_tests/http/tests/misc/resource-timing-navigation-in-restored-iframe-expected.txt index b864cded..4aebeaff 100644 --- a/third_party/blink/web_tests/http/tests/misc/resource-timing-navigation-in-restored-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/resource-timing-navigation-in-restored-iframe-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS resources.length is 1 PASS resources[0].name is "http://127.0.0.1:8000/js-test-resources/js-test.js" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/misc/script-defer-expected.txt b/third_party/blink/web_tests/http/tests/misc/script-defer-expected.txt index 27f96c3..1c6bc98e 100644 --- a/third_party/blink/web_tests/http/tests/misc/script-defer-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/script-defer-expected.txt
@@ -7,4 +7,5 @@ PASS successfullyParsed is true TEST COMPLETE + load
diff --git a/third_party/blink/web_tests/http/tests/misc/script-sync-slow-scripts-onerror-expected.txt b/third_party/blink/web_tests/http/tests/misc/script-sync-slow-scripts-onerror-expected.txt index 4328e54..780f4c9 100644 --- a/third_party/blink/web_tests/http/tests/misc/script-sync-slow-scripts-onerror-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/script-sync-slow-scripts-onerror-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS firstOnErrorHandlerCount is 1 PASS secondOnErrorHandlerCount is 1 PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/misc/set-window-opener-to-null-expected.txt b/third_party/blink/web_tests/http/tests/misc/set-window-opener-to-null-expected.txt index 720805c..7ed3d8b 100644 --- a/third_party/blink/web_tests/http/tests/misc/set-window-opener-to-null-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/set-window-opener-to-null-expected.txt
@@ -1,5 +1,7 @@ This tests that following code works in Chrome: var w = window.open(...); w.opener = null; + After new page finishes loading, its opener should stay as null. + PASS
diff --git a/third_party/blink/web_tests/http/tests/misc/stop-loading-on-resource-timing-buffer-full-crash-expected.txt b/third_party/blink/web_tests/http/tests/misc/stop-loading-on-resource-timing-buffer-full-crash-expected.txt index a9efafb..928b902 100644 --- a/third_party/blink/web_tests/http/tests/misc/stop-loading-on-resource-timing-buffer-full-crash-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/stop-loading-on-resource-timing-buffer-full-crash-expected.txt
@@ -1,4 +1,5 @@ PASS successfullyParsed is true TEST COMPLETE + PASS. No crash when stop loading on resource timing buffer full.
diff --git a/third_party/blink/web_tests/http/tests/misc/svg-image-load-outlives-gc-without-crashing-expected.txt b/third_party/blink/web_tests/http/tests/misc/svg-image-load-outlives-gc-without-crashing-expected.txt index 0196e870..d4076d4 100644 --- a/third_party/blink/web_tests/http/tests/misc/svg-image-load-outlives-gc-without-crashing-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/svg-image-load-outlives-gc-without-crashing-expected.txt
@@ -1,5 +1,6 @@ PASS successfullyParsed is true TEST COMPLETE + This has an svg element that contains an svg image element. That svg element is wrapped in a div. It removes the div, forces garbage collection, and makes sure that the window load event does not fire. It also makes sure there is no crash.
diff --git a/third_party/blink/web_tests/http/tests/misc/webtiming-buffer-full-no-event-expected.txt b/third_party/blink/web_tests/http/tests/misc/webtiming-buffer-full-no-event-expected.txt index 423126f..12dfe309 100644 --- a/third_party/blink/web_tests/http/tests/misc/webtiming-buffer-full-no-event-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/webtiming-buffer-full-no-event-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS Performance.prototype.__proto__ is EventTarget.prototype PASS performance.onresourcetimingbufferfull is null PASS performance.onresourcetimingbufferfull is null
diff --git a/third_party/blink/web_tests/http/tests/misc/webtiming-cross-origin-and-back-expected.txt b/third_party/blink/web_tests/http/tests/misc/webtiming-cross-origin-and-back-expected.txt index f0bdf5a9..a7466bc 100644 --- a/third_party/blink/web_tests/http/tests/misc/webtiming-cross-origin-and-back-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/webtiming-cross-origin-and-back-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS timing.connectEnd is non-zero. PASS timing.connectStart is non-zero. PASS timing.domComplete is non-zero.
diff --git a/third_party/blink/web_tests/http/tests/misc/webtiming-cross-origin-redirect-expected.txt b/third_party/blink/web_tests/http/tests/misc/webtiming-cross-origin-redirect-expected.txt index 72444d41..aac41a0 100644 --- a/third_party/blink/web_tests/http/tests/misc/webtiming-cross-origin-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/webtiming-cross-origin-redirect-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS timing.connectEnd is non-zero. PASS timing.connectStart is non-zero. PASS timing.domComplete is non-zero.
diff --git a/third_party/blink/web_tests/http/tests/misc/webtiming-no-origin-expected.txt b/third_party/blink/web_tests/http/tests/misc/webtiming-no-origin-expected.txt index 682aec4..28b7e48 100644 --- a/third_party/blink/web_tests/http/tests/misc/webtiming-no-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/webtiming-no-origin-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS timing.connectEnd is non-zero. PASS timing.connectStart is non-zero. PASS timing.domComplete is non-zero.
diff --git a/third_party/blink/web_tests/http/tests/misc/webtiming-one-redirect-expected.txt b/third_party/blink/web_tests/http/tests/misc/webtiming-one-redirect-expected.txt index 3b21851..a5934df 100644 --- a/third_party/blink/web_tests/http/tests/misc/webtiming-one-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/webtiming-one-redirect-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS timing.redirectStart is >= timing.navigationStart PASS timing.redirectEnd is >= timing.redirectStart PASS navigation.redirectCount is 1
diff --git a/third_party/blink/web_tests/http/tests/misc/webtiming-slow-load-expected.txt b/third_party/blink/web_tests/http/tests/misc/webtiming-slow-load-expected.txt index 349927eb..48f2c420 100644 --- a/third_party/blink/web_tests/http/tests/misc/webtiming-slow-load-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/webtiming-slow-load-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS timing.requestStart is non-zero. PASS timing.responseStart is non-zero. PASS timing.responseEnd is 0
diff --git a/third_party/blink/web_tests/http/tests/misc/webtiming-two-redirects-expected.txt b/third_party/blink/web_tests/http/tests/misc/webtiming-two-redirects-expected.txt index 2d47dc0..6e5712f 100644 --- a/third_party/blink/web_tests/http/tests/misc/webtiming-two-redirects-expected.txt +++ b/third_party/blink/web_tests/http/tests/misc/webtiming-two-redirects-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS timing.redirectStart is >= timing.navigationStart PASS timing.redirectEnd is >= timing.redirectStart PASS navigation.redirectCount is 2
diff --git a/third_party/blink/web_tests/http/tests/mixed-autoupgrade/optionally/image-upgrade-console-message.https-expected.txt b/third_party/blink/web_tests/http/tests/mixed-autoupgrade/optionally/image-upgrade-console-message.https-expected.txt index 2bebfe4..4d9d826 100644 --- a/third_party/blink/web_tests/http/tests/mixed-autoupgrade/optionally/image-upgrade-console-message.https-expected.txt +++ b/third_party/blink/web_tests/http/tests/mixed-autoupgrade/optionally/image-upgrade-console-message.https-expected.txt
@@ -1,3 +1,2 @@ CONSOLE WARNING: line 2: Mixed Content: The page at 'https://127.0.0.1:8443/mixed-autoupgrade/optionally/image-upgrade-console-message.https.html' was loaded over HTTPS, but requested an insecure element 'http://web-platform.test:8443/mixed-autoupgrade/resources/pass.png'. As part of an experiment this request was automatically upgraded to HTTPS, For more information see https://chromium.googlesource.com/chromium/src/+/master/docs/security/autougprade-mixed.md CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/mixed-autoupgrade/optionally/image-upgrade-console-message.https.html' was loaded over HTTPS, but requested an insecure element 'http://web-platform.test:8443/mixed-autoupgrade/resources/pass.png'. As part of an experiment this request was automatically upgraded to HTTPS, For more information see https://chromium.googlesource.com/chromium/src/+/master/docs/security/autougprade-mixed.md -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/mixed-autoupgrade/optionally/image-upgrade-console-message.https.html' attempted to load subresource at 'https://web-platform.test:8443/mixed-autoupgrade/resources/pass.png' over broken HTTPS.
diff --git a/third_party/blink/web_tests/http/tests/multipart/stop-crash-expected.txt b/third_party/blink/web_tests/http/tests/multipart/stop-crash-expected.txt index cbb1e29..473d069 100644 --- a/third_party/blink/web_tests/http/tests/multipart/stop-crash-expected.txt +++ b/third_party/blink/web_tests/http/tests/multipart/stop-crash-expected.txt
@@ -2,5 +2,4 @@ If WebKit does not assert or crash after the test, then it passed. - PASS
diff --git a/third_party/blink/web_tests/http/tests/navigation/anchor-basic-expected.txt b/third_party/blink/web_tests/http/tests/navigation/anchor-basic-expected.txt index 8ea9128..e7735da5 100644 --- a/third_party/blink/web_tests/http/tests/navigation/anchor-basic-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/anchor-basic-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/anchor-frames-cross-origin-expected.txt b/third_party/blink/web_tests/http/tests/navigation/anchor-frames-cross-origin-expected.txt index 5e299801..4f7d2f8 100644 --- a/third_party/blink/web_tests/http/tests/navigation/anchor-frames-cross-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/anchor-frames-cross-origin-expected.txt
@@ -7,7 +7,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS document.documentElement.scrollTop == 0 is true PASS document.documentElement.scrollLeft == 0 is true PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/navigation/anchor-frames-expected.txt b/third_party/blink/web_tests/http/tests/navigation/anchor-frames-expected.txt index e537b10..2140708 100644 --- a/third_party/blink/web_tests/http/tests/navigation/anchor-frames-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/anchor-frames-expected.txt
@@ -7,13 +7,13 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS document.documentElement.offsetHeight > document.documentElement.clientHeight is true PASS document.scrollingElement.scrollTop > 0 is true PASS document.scrollingElement.scrollTop + document.body.clientHeight > 2000 is true PASS successfullyParsed is true TEST COMPLETE + This is an anchor point named "anchor1. --------
diff --git a/third_party/blink/web_tests/http/tests/navigation/anchor-frames-gbk-expected.txt b/third_party/blink/web_tests/http/tests/navigation/anchor-frames-gbk-expected.txt index d65ba7d..eaad7bdd 100644 --- a/third_party/blink/web_tests/http/tests/navigation/anchor-frames-gbk-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/anchor-frames-gbk-expected.txt
@@ -7,13 +7,13 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS document.body.offsetHeight > document.documentElement.clientHeight is true FAIL document.documentElement.scrollTop > 0 should be true. Was false. FAIL document.documentElement.scrollTop + document.documentElement.clientHeight > 2000 should be true. Was false. PASS successfullyParsed is true TEST COMPLETE + This is an anchor point named as the Unicode equivalent of the GBK sequence %a9g (test trailing low byte). --------
diff --git a/third_party/blink/web_tests/http/tests/navigation/anchor-frames-same-origin-expected.txt b/third_party/blink/web_tests/http/tests/navigation/anchor-frames-same-origin-expected.txt index c50353a0..7bfe338 100644 --- a/third_party/blink/web_tests/http/tests/navigation/anchor-frames-same-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/anchor-frames-same-origin-expected.txt
@@ -7,7 +7,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS document.scrollingElement.scrollTop > 0 is true PASS document.scrollingElement.scrollLeft == 0 is true PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/navigation/anchor-goback-expected.txt b/third_party/blink/web_tests/http/tests/navigation/anchor-goback-expected.txt index 39b0871..cd29354 100644 --- a/third_party/blink/web_tests/http/tests/navigation/anchor-goback-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/anchor-goback-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/back-send-referrer-expected.txt b/third_party/blink/web_tests/http/tests/navigation/back-send-referrer-expected.txt index fe786b2..13d7413 100644 --- a/third_party/blink/web_tests/http/tests/navigation/back-send-referrer-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/back-send-referrer-expected.txt
@@ -1,3 +1,2 @@ Referrer: http://127.0.0.1:8000/navigation/back-send-referrer.html window.name: 3 -
diff --git a/third_party/blink/web_tests/http/tests/navigation/back-to-slow-frame-expected.txt b/third_party/blink/web_tests/http/tests/navigation/back-to-slow-frame-expected.txt index e8a7d975..bb9237d 100644 --- a/third_party/blink/web_tests/http/tests/navigation/back-to-slow-frame-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/back-to-slow-frame-expected.txt
@@ -1,4 +1,6 @@ - + + + This test checks that going back and forth across a slow-loading frame doesn't crash. If you got back here without crashing, you win. If testing manually click here.
diff --git a/third_party/blink/web_tests/http/tests/navigation/cross-origin-fragment-navigation-is-async-expected.txt b/third_party/blink/web_tests/http/tests/navigation/cross-origin-fragment-navigation-is-async-expected.txt index a633286..850c549 100644 --- a/third_party/blink/web_tests/http/tests/navigation/cross-origin-fragment-navigation-is-async-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/cross-origin-fragment-navigation-is-async-expected.txt
@@ -2,5 +2,3 @@ ALERT: PASS: scheduled postMessage() before hashchange triggered. ALERT: PASS: hashchange triggered after postMessage(). This tests that cross-origin fragment navigations are asynchronous. It does so by scheduling a postMessage before scheduling the navigation. If the navigation is synchronous, the internals API will be able to report the presence of an url fragment immediately. - -
diff --git a/third_party/blink/web_tests/http/tests/navigation/form-targets-cross-site-frame-get-expected.txt b/third_party/blink/web_tests/http/tests/navigation/form-targets-cross-site-frame-get-expected.txt index f71b4b6..362338b 100644 --- a/third_party/blink/web_tests/http/tests/navigation/form-targets-cross-site-frame-get-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/form-targets-cross-site-frame-get-expected.txt
@@ -1,5 +1,4 @@ -Test field: - +Test field: -------- Frame: 'cross-site-frame' @@ -9,6 +8,7 @@ Parameters: test-field = test-value + Http headers: HTTP_CONNECTION = keep-alive
diff --git a/third_party/blink/web_tests/http/tests/navigation/form-targets-cross-site-frame-no-referrer-expected.txt b/third_party/blink/web_tests/http/tests/navigation/form-targets-cross-site-frame-no-referrer-expected.txt index ff92dd23..aba3bfd 100644 --- a/third_party/blink/web_tests/http/tests/navigation/form-targets-cross-site-frame-no-referrer-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/form-targets-cross-site-frame-no-referrer-expected.txt
@@ -1,5 +1,4 @@ -Test field: - +Test field: -------- Frame: 'cross-site-frame' @@ -9,6 +8,7 @@ Parameters: test-field = test-value + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/http/tests/navigation/form-targets-cross-site-frame-post-expected.txt b/third_party/blink/web_tests/http/tests/navigation/form-targets-cross-site-frame-post-expected.txt index f2931a8..5ae9738 100644 --- a/third_party/blink/web_tests/http/tests/navigation/form-targets-cross-site-frame-post-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/form-targets-cross-site-frame-post-expected.txt
@@ -1,5 +1,4 @@ -Test field: - +Test field: -------- Frame: 'cross-site-frame' @@ -9,6 +8,7 @@ Parameters: test-field = test-value + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/http/tests/navigation/form-with-enctype-targets-cross-site-frame-expected.txt b/third_party/blink/web_tests/http/tests/navigation/form-with-enctype-targets-cross-site-frame-expected.txt index 0c0c453..138b2bd 100644 --- a/third_party/blink/web_tests/http/tests/navigation/form-with-enctype-targets-cross-site-frame-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/form-with-enctype-targets-cross-site-frame-expected.txt
@@ -1,5 +1,4 @@ -Test field: - +Test field: -------- Frame: 'cross-site-frame' @@ -9,6 +8,7 @@ Parameters: test-field = test-value + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/http/tests/navigation/forward-to-fragment-fires-onload-expected.txt b/third_party/blink/web_tests/http/tests/navigation/forward-to-fragment-fires-onload-expected.txt index dbf2218..694a7d0 100644 --- a/third_party/blink/web_tests/http/tests/navigation/forward-to-fragment-fires-onload-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/forward-to-fragment-fires-onload-expected.txt
@@ -8,7 +8,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/http/tests/navigation/history-back-across-form-submission-to-fragment-expected.txt b/third_party/blink/web_tests/http/tests/navigation/history-back-across-form-submission-to-fragment-expected.txt index 6d696a3..7188e96 100644 --- a/third_party/blink/web_tests/http/tests/navigation/history-back-across-form-submission-to-fragment-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/history-back-across-form-submission-to-fragment-expected.txt
@@ -1,5 +1,5 @@ ALERT: stage: 1 ALERT: stage: 2 ALERT: stage: 3 - + PASS
diff --git a/third_party/blink/web_tests/http/tests/navigation/javascriptlink-basic-expected.txt b/third_party/blink/web_tests/http/tests/navigation/javascriptlink-basic-expected.txt index 86df391..6f6c5f5 100644 --- a/third_party/blink/web_tests/http/tests/navigation/javascriptlink-basic-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/javascriptlink-basic-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/javascriptlink-goback-expected.txt b/third_party/blink/web_tests/http/tests/navigation/javascriptlink-goback-expected.txt index eb00e1e1..54f02f9 100644 --- a/third_party/blink/web_tests/http/tests/navigation/javascriptlink-goback-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/javascriptlink-goback-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/lockedhistory-iframe-expected.txt b/third_party/blink/web_tests/http/tests/navigation/lockedhistory-iframe-expected.txt index 74f4ec1..eea8da5 100644 --- a/third_party/blink/web_tests/http/tests/navigation/lockedhistory-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/lockedhistory-iframe-expected.txt
@@ -1,7 +1,5 @@ This test verifies that setting the iframe.src through javascript to # does not add a history item. If the test passes you'll see only one history item. - - ============== Back Forward List ============== curr-> http://127.0.0.1:8000/navigation/lockedhistory-iframe.html about:blank (in frame "<!--framePath //<!--frame0-->-->")
diff --git a/third_party/blink/web_tests/http/tests/navigation/metaredirect-basic-expected.txt b/third_party/blink/web_tests/http/tests/navigation/metaredirect-basic-expected.txt index c25ac1c..ef6d9be5 100644 --- a/third_party/blink/web_tests/http/tests/navigation/metaredirect-basic-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/metaredirect-basic-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/metaredirect-goback-expected.txt b/third_party/blink/web_tests/http/tests/navigation/metaredirect-goback-expected.txt index 9f36cdb..929f414 100644 --- a/third_party/blink/web_tests/http/tests/navigation/metaredirect-goback-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/metaredirect-goback-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/no-referrer-reset-expected.txt b/third_party/blink/web_tests/http/tests/navigation/no-referrer-reset-expected.txt index ada1d16f..2c82186 100644 --- a/third_party/blink/web_tests/http/tests/navigation/no-referrer-reset-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/no-referrer-reset-expected.txt
@@ -1,7 +1,7 @@ This tests whether referrer information gets properly set and reset when "noreferrer" links are present. We do the following: 1. Open a link in a new window: referrer is sent and window.opener is sent. 2. Click a rel="noreferrer" link: referrer is null, but window.opener remains set since the link was not opened with target="_blank". -3. Click a link without rel="noreferrer": referrer is sent, but window.opener is still set. +3. Click a link without rel="noreferrer": referrer is sent, but window.opener is still set. Start reset test Referrer: http://127.0.0.1:8000/navigation/no-referrer-reset.html window.opener: http://127.0.0.1:8000/navigation/no-referrer-reset.html
diff --git a/third_party/blink/web_tests/http/tests/navigation/no-referrer-same-window-expected.txt b/third_party/blink/web_tests/http/tests/navigation/no-referrer-same-window-expected.txt index e547d98..02d140c 100644 --- a/third_party/blink/web_tests/http/tests/navigation/no-referrer-same-window-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/no-referrer-same-window-expected.txt
@@ -1,3 +1,4 @@ The Referrer displayed below should be empty. + Referrer: PASS
diff --git a/third_party/blink/web_tests/http/tests/navigation/no-referrer-target-blank-expected.txt b/third_party/blink/web_tests/http/tests/navigation/no-referrer-target-blank-expected.txt index bc19c71a..d882833 100644 --- a/third_party/blink/web_tests/http/tests/navigation/no-referrer-target-blank-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/no-referrer-target-blank-expected.txt
@@ -1,3 +1,2 @@ This tests the functionality of the "noreferrer" link relation on anchor tags. The link below should not send an http referrer, and the resulting window should have its opener attribute set to null. The values of the referrer and window.opener should be empty below. Start no referrer test -
diff --git a/third_party/blink/web_tests/http/tests/navigation/onload-navigation-iframe-2-expected.txt b/third_party/blink/web_tests/http/tests/navigation/onload-navigation-iframe-2-expected.txt index 6ab5c935..a44b67fa 100644 --- a/third_party/blink/web_tests/http/tests/navigation/onload-navigation-iframe-2-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/onload-navigation-iframe-2-expected.txt
@@ -1,4 +1,4 @@ -In this case, Safari and Firefox don't add a history item. +In this case, Safari and Firefox don't add a history item. ============== Back Forward List ============== curr-> http://127.0.0.1:8000/navigation/onload-navigation-iframe-2.html
diff --git a/third_party/blink/web_tests/http/tests/navigation/onload-navigation-iframe-expected.txt b/third_party/blink/web_tests/http/tests/navigation/onload-navigation-iframe-expected.txt index 0e438302..89697766 100644 --- a/third_party/blink/web_tests/http/tests/navigation/onload-navigation-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/onload-navigation-iframe-expected.txt
@@ -1,6 +1,5 @@ In this case, Safari and Firefox don't add a history item. - ============== Back Forward List ============== curr-> http://127.0.0.1:8000/navigation/onload-navigation-iframe.html http://127.0.0.1:8000/navigation/resources/blank.txt? (in frame "myFrame")
diff --git a/third_party/blink/web_tests/http/tests/navigation/onload-navigation-iframe-timeout-expected.txt b/third_party/blink/web_tests/http/tests/navigation/onload-navigation-iframe-timeout-expected.txt index 65b2af0..dd8578a 100644 --- a/third_party/blink/web_tests/http/tests/navigation/onload-navigation-iframe-timeout-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/onload-navigation-iframe-timeout-expected.txt
@@ -1,6 +1,5 @@ In this case, Safari and Firefox adds a history item but IE doesn't. - ============== Back Forward List ============== curr-> http://127.0.0.1:8000/navigation/onload-navigation-iframe-timeout.html http://127.0.0.1:8000/navigation/resources/blank.txt? (in frame "myFrame")
diff --git a/third_party/blink/web_tests/http/tests/navigation/ping-cross-origin-from-https-expected.txt b/third_party/blink/web_tests/http/tests/navigation/ping-cross-origin-from-https-expected.txt index 960c102..60751e8 100644 --- a/third_party/blink/web_tests/http/tests/navigation/ping-cross-origin-from-https-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/ping-cross-origin-from-https-expected.txt
@@ -1,4 +1,3 @@ -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/navigation/resources/ping-cross-origin-from-https-target.html' attempted to load subresource at 'https://127.0.0.1:8443/navigation/resources/resources/delete-ping.php?test=cross-origin-from-https' over broken HTTPS. PingLoader dispatched to 'http://example.test:8000/navigation/resources/save-Ping.php?test=cross-origin-from-https'. CONSOLE ERROR: line 25: Mixed Content: The page at 'https://127.0.0.1:8443/navigation/resources/ping-cross-origin-from-https-target.html' was loaded over HTTPS, but requested an insecure hyperlink auditing endpoint 'http://example.test:8000/navigation/resources/save-Ping.php?test=cross-origin-from-https'. This request has been blocked; the content must be served over HTTPS. This page calls testRunner.notifyDone().
diff --git a/third_party/blink/web_tests/http/tests/navigation/post-basic-expected.txt b/third_party/blink/web_tests/http/tests/navigation/post-basic-expected.txt index 25297e8f..d160973 100644 --- a/third_party/blink/web_tests/http/tests/navigation/post-basic-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/post-basic-expected.txt
@@ -4,6 +4,7 @@ the-input = input value goes here submitwithpost = Submit with POST + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/http/tests/navigation/post-frames-expected.txt b/third_party/blink/web_tests/http/tests/navigation/post-frames-expected.txt index c59de62..9d4b4c6 100644 --- a/third_party/blink/web_tests/http/tests/navigation/post-frames-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/post-frames-expected.txt
@@ -1,7 +1,5 @@ Tests that a POST request in a frame is handled correctly. If this test passes, you will see a page indicating a form was POSTed. - - -------- Frame: '<!--framePath //<!--frame0-->-->' -------- @@ -11,6 +9,7 @@ the-input = input value goes here submitwithpost = Submit with POST + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/http/tests/navigation/post-frames-goback1-expected.txt b/third_party/blink/web_tests/http/tests/navigation/post-frames-goback1-expected.txt index 68028c8..bec24a3 100644 --- a/third_party/blink/web_tests/http/tests/navigation/post-frames-goback1-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/post-frames-goback1-expected.txt
@@ -1,8 +1,5 @@ Tests that a POST targetted to a frame is handled correctly when navigating away and coming back to the page. - - - -------- Frame: 'target-frame' -------- @@ -11,6 +8,7 @@ Parameters: the-input = input value goes here + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/http/tests/navigation/post-goback-same-url-expected.txt b/third_party/blink/web_tests/http/tests/navigation/post-goback-same-url-expected.txt index 6202b41..bf4a152a 100644 --- a/third_party/blink/web_tests/http/tests/navigation/post-goback-same-url-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/post-goback-same-url-expected.txt
@@ -1,4 +1,4 @@ - + ============== Back Forward List ============== http://127.0.0.1:8000/navigation/post-goback-same-url.html
diff --git a/third_party/blink/web_tests/http/tests/navigation/post-goback1-expected.txt b/third_party/blink/web_tests/http/tests/navigation/post-goback1-expected.txt index 8fbf9db50..6094bb0 100644 --- a/third_party/blink/web_tests/http/tests/navigation/post-goback1-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/post-goback1-expected.txt
@@ -4,6 +4,7 @@ the-input = input value goes here submitwithpost = Submit with POST + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/http/tests/navigation/post-goback2-expected.txt b/third_party/blink/web_tests/http/tests/navigation/post-goback2-expected.txt index ac5f64d..3bdcb9d 100644 --- a/third_party/blink/web_tests/http/tests/navigation/post-goback2-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/post-goback2-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/post-redirect-get-reload-expected.txt b/third_party/blink/web_tests/http/tests/navigation/post-redirect-get-reload-expected.txt index 36c82f2..2ab45dd 100644 --- a/third_party/blink/web_tests/http/tests/navigation/post-redirect-get-reload-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/post-redirect-get-reload-expected.txt
@@ -4,4 +4,3 @@ 2. Reload The reload should not trigger a form resubmission warning. -
diff --git a/third_party/blink/web_tests/http/tests/navigation/postredirect-basic-expected.txt b/third_party/blink/web_tests/http/tests/navigation/postredirect-basic-expected.txt index c3b56f60..97c7b36 100644 --- a/third_party/blink/web_tests/http/tests/navigation/postredirect-basic-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/postredirect-basic-expected.txt
@@ -1,8 +1,8 @@ -This is just a minimal page that we navigate in response to an HTTP POST. +This is just a minimal page that we navigate in response to an HTTP POST. -If the next line is empty after the colon, it probably means that we made a mistake and requested this page with a GET with no query instead of a POST. +If the next line is empty after the colon, it probably means that we made a mistake and requested this page with a GET with no query instead of a POST. -The first text field contained: New form text from user +The first text field contained: New form text from user This page was requested with an HTTP GET ============== Back Forward List ==============
diff --git a/third_party/blink/web_tests/http/tests/navigation/postredirect-frames-expected.txt b/third_party/blink/web_tests/http/tests/navigation/postredirect-frames-expected.txt index 3a19da70..1899af66 100644 --- a/third_party/blink/web_tests/http/tests/navigation/postredirect-frames-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/postredirect-frames-expected.txt
@@ -3,11 +3,11 @@ -------- Frame: 'main' -------- -This is just a minimal page that we navigate in response to an HTTP POST. +This is just a minimal page that we navigate in response to an HTTP POST. -If the next line is empty after the colon, it probably means that we made a mistake and requested this page with a GET with no query instead of a POST. +If the next line is empty after the colon, it probably means that we made a mistake and requested this page with a GET with no query instead of a POST. -The first text field contained: New form text from user +The first text field contained: New form text from user This page was requested with an HTTP GET --------
diff --git a/third_party/blink/web_tests/http/tests/navigation/postredirect-frames-goback1-expected.txt b/third_party/blink/web_tests/http/tests/navigation/postredirect-frames-goback1-expected.txt index a787707..58bedb0d 100644 --- a/third_party/blink/web_tests/http/tests/navigation/postredirect-frames-goback1-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/postredirect-frames-goback1-expected.txt
@@ -4,11 +4,9 @@ Form page does a 302 to a static page (top-go-back.html), still within the frame. Static page does a top-level navigation to another static page (go-back.html) This static page goes back. + We should end up showing the top-level page with the first static page inside the frame. - - - -------- Frame: 'target-frame' --------
diff --git a/third_party/blink/web_tests/http/tests/navigation/postredirect-goback1-expected.txt b/third_party/blink/web_tests/http/tests/navigation/postredirect-goback1-expected.txt index a23b9a7..9653e92c 100644 --- a/third_party/blink/web_tests/http/tests/navigation/postredirect-goback1-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/postredirect-goback1-expected.txt
@@ -1,8 +1,8 @@ -This is just a minimal page that we navigate in response to an HTTP POST. +This is just a minimal page that we navigate in response to an HTTP POST. -If the next line is empty after the colon, it probably means that we made a mistake and requested this page with a GET with no query instead of a POST. +If the next line is empty after the colon, it probably means that we made a mistake and requested this page with a GET with no query instead of a POST. -The first text field contained: New form text from user +The first text field contained: New form text from user This page was requested with an HTTP GET ============== Back Forward List ==============
diff --git a/third_party/blink/web_tests/http/tests/navigation/postredirect-goback2-expected.txt b/third_party/blink/web_tests/http/tests/navigation/postredirect-goback2-expected.txt index b871ccb..aaf0a49 100644 --- a/third_party/blink/web_tests/http/tests/navigation/postredirect-goback2-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/postredirect-goback2-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/redirect302-basic-expected.txt b/third_party/blink/web_tests/http/tests/navigation/redirect302-basic-expected.txt index 974ce09..704a9514 100644 --- a/third_party/blink/web_tests/http/tests/navigation/redirect302-basic-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/redirect302-basic-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/redirect302-goback-expected.txt b/third_party/blink/web_tests/http/tests/navigation/redirect302-goback-expected.txt index e80f7ef..be2ca4a 100644 --- a/third_party/blink/web_tests/http/tests/navigation/redirect302-goback-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/redirect302-goback-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/relativeanchor-basic-expected.txt b/third_party/blink/web_tests/http/tests/navigation/relativeanchor-basic-expected.txt index b2ddf97..6af162b 100644 --- a/third_party/blink/web_tests/http/tests/navigation/relativeanchor-basic-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/relativeanchor-basic-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/relativeanchor-goback-expected.txt b/third_party/blink/web_tests/http/tests/navigation/relativeanchor-goback-expected.txt index 96170f0..505aae1 100644 --- a/third_party/blink/web_tests/http/tests/navigation/relativeanchor-goback-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/relativeanchor-goback-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/rename-subframe-goback-expected.txt b/third_party/blink/web_tests/http/tests/navigation/rename-subframe-goback-expected.txt index 1ca913b3..00d64738 100644 --- a/third_party/blink/web_tests/http/tests/navigation/rename-subframe-goback-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/rename-subframe-goback-expected.txt
@@ -12,6 +12,7 @@ the-input = input value goes here submitwithpost = Submit with POST + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/http/tests/navigation/restore-form-state-https-expected.txt b/third_party/blink/web_tests/http/tests/navigation/restore-form-state-https-expected.txt index 7903bbfa..00d2bb00 100644 --- a/third_party/blink/web_tests/http/tests/navigation/restore-form-state-https-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/restore-form-state-https-expected.txt
@@ -1,4 +1,5 @@ -This is test page that has a secure form. It is part of a test to show that form state is restored during back/forward navigations. +This is test page that has a secure form. It is part of a test to show that form state is restored during back/forward navigations. + Test Passed @@ -9,7 +10,12 @@ - + +Initial Value +foo +Value set by User that should be Restored +bar + ============== Back Forward List ==============
diff --git a/third_party/blink/web_tests/http/tests/navigation/same-and-different-back-expected.txt b/third_party/blink/web_tests/http/tests/navigation/same-and-different-back-expected.txt index 821ca48..596df55 100644 --- a/third_party/blink/web_tests/http/tests/navigation/same-and-different-back-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/same-and-different-back-expected.txt
@@ -1,4 +1,4 @@ -We pass if we don't crash under ASAN. +We pass if we don't crash under ASAN. ============== Back Forward List ============== curr-> http://127.0.0.1:8000/navigation/same-and-different-back.html
diff --git a/third_party/blink/web_tests/http/tests/navigation/same-document-scroll-position-restore-expected.txt b/third_party/blink/web_tests/http/tests/navigation/same-document-scroll-position-restore-expected.txt index 019407a..19f57406 100644 --- a/third_party/blink/web_tests/http/tests/navigation/same-document-scroll-position-restore-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/same-document-scroll-position-restore-expected.txt
@@ -3,5 +3,6 @@ TEST COMPLETE + Link to bottom scrollY should be 800: PASS
diff --git a/third_party/blink/web_tests/http/tests/navigation/same-origin-fragment-navigation-is-sync-expected.txt b/third_party/blink/web_tests/http/tests/navigation/same-origin-fragment-navigation-is-sync-expected.txt index 09078e91..c1c1143 100644 --- a/third_party/blink/web_tests/http/tests/navigation/same-origin-fragment-navigation-is-sync-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/same-origin-fragment-navigation-is-sync-expected.txt
@@ -2,5 +2,3 @@ ALERT: PASS: scheduled postMessage() before hashchange triggered. ALERT: PASS: hashchange triggered after postMessage(). This tests that same-origin fragment navigations are synchronous. It does so by scheduling a postMessage before scheduling the navigation. If the navigation is synchronous, the internals API will be able to report the presence of an url fragment immediately. - -
diff --git a/third_party/blink/web_tests/http/tests/navigation/slowmetaredirect-basic-expected.txt b/third_party/blink/web_tests/http/tests/navigation/slowmetaredirect-basic-expected.txt index 3b30104..0da143e1 100644 --- a/third_party/blink/web_tests/http/tests/navigation/slowmetaredirect-basic-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/slowmetaredirect-basic-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/slowtimerredirect-basic-expected.txt b/third_party/blink/web_tests/http/tests/navigation/slowtimerredirect-basic-expected.txt index 90ca793..0dc2d290 100644 --- a/third_party/blink/web_tests/http/tests/navigation/slowtimerredirect-basic-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/slowtimerredirect-basic-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/success200-basic-expected.txt b/third_party/blink/web_tests/http/tests/navigation/success200-basic-expected.txt index 555fed45..f26e8b90 100644 --- a/third_party/blink/web_tests/http/tests/navigation/success200-basic-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/success200-basic-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/success200-goback-expected.txt b/third_party/blink/web_tests/http/tests/navigation/success200-goback-expected.txt index 6a690a2..a9d7c0a 100644 --- a/third_party/blink/web_tests/http/tests/navigation/success200-goback-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/success200-goback-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/success200-loadsame-expected.txt b/third_party/blink/web_tests/http/tests/navigation/success200-loadsame-expected.txt index 5e91890f..a9d14f84 100644 --- a/third_party/blink/web_tests/http/tests/navigation/success200-loadsame-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/success200-loadsame-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/success200-reload-expected.txt b/third_party/blink/web_tests/http/tests/navigation/success200-reload-expected.txt index 40bfd90d..f7ad9405 100644 --- a/third_party/blink/web_tests/http/tests/navigation/success200-reload-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/success200-reload-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/timerredirect-basic-expected.txt b/third_party/blink/web_tests/http/tests/navigation/timerredirect-basic-expected.txt index 15a80f2..bffd1ad7 100644 --- a/third_party/blink/web_tests/http/tests/navigation/timerredirect-basic-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/timerredirect-basic-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigation/timerredirect-goback-expected.txt b/third_party/blink/web_tests/http/tests/navigation/timerredirect-goback-expected.txt index 72b1d50..1796a86 100644 --- a/third_party/blink/web_tests/http/tests/navigation/timerredirect-goback-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigation/timerredirect-goback-expected.txt
@@ -1,4 +1,5 @@ -This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. +This is test page that we navigate to as part of testing various navigation styles. It includes a form so that we can test saving and restoring of form data, and it needs to be long enough that we can test saving and restoring of scroll position. + @@ -10,6 +11,12 @@ option #1 option #2 +Initial Value +foo +Value set by User that should be Restored +bar + + Now
diff --git a/third_party/blink/web_tests/http/tests/navigatorcontentutils/register-protocol-handler-expected.txt b/third_party/blink/web_tests/http/tests/navigatorcontentutils/register-protocol-handler-expected.txt index af30005e..0578523 100644 --- a/third_party/blink/web_tests/http/tests/navigatorcontentutils/register-protocol-handler-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigatorcontentutils/register-protocol-handler-expected.txt
@@ -42,6 +42,7 @@ PASS URL with origin different than document origin threw SecurityError exception: "Failed to execute 'registerProtocolHandler' on 'Navigator': Can only register custom handler in the document's origin.". PASS Valid call succeeded. + PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/http/tests/navigatorcontentutils/unregister-protocol-handler-expected.txt b/third_party/blink/web_tests/http/tests/navigatorcontentutils/unregister-protocol-handler-expected.txt index 033374d..fb88ce0 100644 --- a/third_party/blink/web_tests/http/tests/navigatorcontentutils/unregister-protocol-handler-expected.txt +++ b/third_party/blink/web_tests/http/tests/navigatorcontentutils/unregister-protocol-handler-expected.txt
@@ -41,6 +41,7 @@ PASS URL with origin different than document origin threw SecurityError exception: "Failed to execute 'unregisterProtocolHandler' on 'Navigator': Can only register custom handler in the document's origin.". PASS Valid call succeeded. + PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/http/tests/notifications/notification-sandbox-permission-expected.txt b/third_party/blink/web_tests/http/tests/notifications/notification-sandbox-permission-expected.txt index 695c02c7..e82f5c0 100644 --- a/third_party/blink/web_tests/http/tests/notifications/notification-sandbox-permission-expected.txt +++ b/third_party/blink/web_tests/http/tests/notifications/notification-sandbox-permission-expected.txt
@@ -1,12 +1,9 @@ Tests that the <iframe sandbox> attribute influences whether notification permissions will be inherit by an iframe. Normal iframe. Should inherit permissions. - Sandboxed iframe with allow-same-origin. Should inherit permissions. - Sandboxed iframe without allow-same-origin. Should not inherit permissions. - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/performance-timing/element-timing/cross-origin-iframe-element.html b/third_party/blink/web_tests/http/tests/performance-timing/element-timing/cross-origin-iframe-element.html index e8922dc..7f73881c 100644 --- a/third_party/blink/web_tests/http/tests/performance-timing/element-timing/cross-origin-iframe-element.html +++ b/third_party/blink/web_tests/http/tests/performance-timing/element-timing/cross-origin-iframe-element.html
@@ -26,7 +26,7 @@ t.step_timeout( () => { // After some wait, assume observer did not receive the entry, so the test passes. t.done(); - }, 100); + }, 300); }, 'Element from cross origin iframe is NOT observable.'); </script>
diff --git a/third_party/blink/web_tests/http/tests/performance-timing/element-timing/observe-child-element.html b/third_party/blink/web_tests/http/tests/performance-timing/element-timing/observe-child-element.html index 15cc001c..5bb82908 100644 --- a/third_party/blink/web_tests/http/tests/performance-timing/element-timing/observe-child-element.html +++ b/third_party/blink/web_tests/http/tests/performance-timing/element-timing/observe-child-element.html
@@ -33,10 +33,6 @@ document.body.appendChild(iframe); beforeRender = performance.now(); }; - t.step_timeout( () => { - // We were idle long enough to wait for PerfomanceObserver callback. - assert_unreached("PerformanceObserver callback should have been fired."); - }, 100); }, 'Element from same-origin iframe is observable.'); </script>
diff --git a/third_party/blink/web_tests/http/tests/permissionclient/image-permissions-expected.txt b/third_party/blink/web_tests/http/tests/permissionclient/image-permissions-expected.txt index fafe617..612ca5b 100644 --- a/third_party/blink/web_tests/http/tests/permissionclient/image-permissions-expected.txt +++ b/third_party/blink/web_tests/http/tests/permissionclient/image-permissions-expected.txt
@@ -5,7 +5,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/http/tests/plugins/cross-frame-object-access-expected.txt b/third_party/blink/web_tests/http/tests/plugins/cross-frame-object-access-expected.txt index a4c1bbe..4cf37cf5a 100644 --- a/third_party/blink/web_tests/http/tests/plugins/cross-frame-object-access-expected.txt +++ b/third_party/blink/web_tests/http/tests/plugins/cross-frame-object-access-expected.txt
@@ -5,7 +5,6 @@ -------- Frame: 'childFrame' -------- - This tests that plugins can access objects in other frames as allowed by the security model enforced in WebCore. Error: Error: Failed conversion between PP_Var and V8 value Error: Uncaught
diff --git a/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-allow-pointer-lock-expected.txt b/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-allow-pointer-lock-expected.txt index c22acc9..a7b4b83 100644 --- a/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-allow-pointer-lock-expected.txt +++ b/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-allow-pointer-lock-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS message is "inner-iframe.html onpointerlockchange, document.pointerLockElement = [object HTMLBodyElement]" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-expected.txt b/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-expected.txt index 4f254efa..cb9f862 100644 --- a/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-expected.txt +++ b/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS message is "inner-iframe.html onpointerlockerror" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-nested-allow-pointer-lock-expected.txt b/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-nested-allow-pointer-lock-expected.txt index a047fc5cb..2d031b2 100644 --- a/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-nested-allow-pointer-lock-expected.txt +++ b/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-nested-allow-pointer-lock-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS message is "inner-iframe.html onpointerlockchange, document.pointerLockElement = [object HTMLBodyElement]" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-nested-disallow-then-allow-pointer-lock-expected.txt b/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-nested-disallow-then-allow-pointer-lock-expected.txt index 997078d4..e0fec51 100644 --- a/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-nested-disallow-then-allow-pointer-lock-expected.txt +++ b/third_party/blink/web_tests/http/tests/pointer-lock/iframe-sandboxed-nested-disallow-then-allow-pointer-lock-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS message is "inner-iframe.html onpointerlockerror" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/pointer-lock/pointerlockelement-different-origin-expected.txt b/third_party/blink/web_tests/http/tests/pointer-lock/pointerlockelement-different-origin-expected.txt index d950246..2a46433 100644 --- a/third_party/blink/web_tests/http/tests/pointer-lock/pointerlockelement-different-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/pointer-lock/pointerlockelement-different-origin-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Lock targetDiv1. PASS onpointerlockchange received after: Lock targetDiv1. PASS document.pointerLockElement is targetDiv1
diff --git a/third_party/blink/web_tests/http/tests/pointer-lock/pointerlockelement-same-origin-expected.txt b/third_party/blink/web_tests/http/tests/pointer-lock/pointerlockelement-same-origin-expected.txt index 4663e9e..3386e93 100644 --- a/third_party/blink/web_tests/http/tests/pointer-lock/pointerlockelement-same-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/pointer-lock/pointerlockelement-same-origin-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Lock targetDiv1. PASS onpointerlockchange received after: Lock targetDiv1. PASS document.pointerLockElement is targetDiv1
diff --git a/third_party/blink/web_tests/http/tests/pointer-lock/requestPointerLock-can-not-transfer-between-documents-expected.txt b/third_party/blink/web_tests/http/tests/pointer-lock/requestPointerLock-can-not-transfer-between-documents-expected.txt index 72f225fc..8b76939 100644 --- a/third_party/blink/web_tests/http/tests/pointer-lock/requestPointerLock-can-not-transfer-between-documents-expected.txt +++ b/third_party/blink/web_tests/http/tests/pointer-lock/requestPointerLock-can-not-transfer-between-documents-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Lock targetDiv1. PASS onpointerlockchange received after: Lock targetDiv1. PASS document.pointerLockElement is targetDiv1
diff --git a/third_party/blink/web_tests/http/tests/preload/meta-viewport-device-width-link-headers.html b/third_party/blink/web_tests/http/tests/preload/meta-viewport-device-width-link-headers.html new file mode 100644 index 0000000..ee170f3 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/preload/meta-viewport-device-width-link-headers.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<script> + if (window.testRunner) { + testRunner.setCanOpenWindows(true); + testRunner.setCloseRemainingWindowsWhenComplete(true); + } +</script> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script> + var t = async_test('Makes sure that media queries in Link headers correctly evaluate viewport width when <meta content=viewport width=device-width> is specified'); + addEventListener("message", t.step_func(function(event) { + if (event.data == "zeroloaded") + assert_unreached("FAIL: media query (width: 0px) matched"); + if (event.data == "nonzeronotloaded") + assert_unreached("FAIL: media query (min-width: 1px) did not match"); + t.done(); + }, false)); + var w = window.open("resources/enable-viewport-and-refresh.html?media-link-headers-device-width.php"); +</script>
diff --git a/third_party/blink/web_tests/http/tests/preload/meta-viewport-link-headers-imagesrcset.html b/third_party/blink/web_tests/http/tests/preload/meta-viewport-link-headers-imagesrcset.html index c5d09895..07f57e8 100644 --- a/third_party/blink/web_tests/http/tests/preload/meta-viewport-link-headers-imagesrcset.html +++ b/third_party/blink/web_tests/http/tests/preload/meta-viewport-link-headers-imagesrcset.html
@@ -15,11 +15,8 @@ <script> var t = async_test('Makes sure that Link headers support the imagesrcset and imagesizes attributes and respond to <meta content=viewport>'); addEventListener("message", t.step_func(function(event) { - if (event.data == "largeloaded") - assert_unreached("FAIL: large resource was loaded"); - if (event.data == "smallnotloaded") - assert_unreached("FAIL: small resource was not loaded"); + assert_array_equals(event.data.sort(), ["300", "small"]) t.done(); - }, false)); + }, false)); window.open("resources/enable-viewport-and-refresh.html?media-link-headers-imagesrcset.php"); </script>
diff --git a/third_party/blink/web_tests/http/tests/preload/resources/media-link-headers-device-width.php b/third_party/blink/web_tests/http/tests/preload/resources/media-link-headers-device-width.php new file mode 100644 index 0000000..b7888bd9 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/preload/resources/media-link-headers-device-width.php
@@ -0,0 +1,23 @@ +<?php + header("Link: <http://127.0.0.1:8000/resources/square.png?nonzero>;rel=preload;as=image;media=\"(min-width: 1px)\"", false); + header("Link: <http://127.0.0.1:8000/resources/square.png?zero>;rel=preload;as=image;media=\"(width: 0px)\"", false); +?> +<!DOCTYPE html> +<meta name="viewport" content="width=device-width"> +<script> + window.addEventListener("load", function() { + var entries = performance.getEntriesByType("resource"); + var nonzeroLoaded = false; + for (var i = 0; i < entries.length; ++i) { + if (entries[i].name.indexOf("?zero") != -1) + window.opener.postMessage("zeroloaded", "*"); + if (entries[i].name.indexOf("?nonzero") != -1) + nonzeroLoaded = true; + } + if (nonzeroLoaded) + window.opener.postMessage("success", "*") + window.opener.postMessage("nonzeronotloaded", "*"); + }); +</script> +<script src="../resources/slow-script.pl?delay=200"></script> +
diff --git a/third_party/blink/web_tests/http/tests/preload/resources/media-link-headers-imagesrcset.php b/third_party/blink/web_tests/http/tests/preload/resources/media-link-headers-imagesrcset.php index 0813e5f4..5c3ed546 100644 --- a/third_party/blink/web_tests/http/tests/preload/resources/media-link-headers-imagesrcset.php +++ b/third_party/blink/web_tests/http/tests/preload/resources/media-link-headers-imagesrcset.php
@@ -1,22 +1,25 @@ <?php - header('Link: <http://127.0.0.1:8000/resources/square.png?large>; rel=preload; as=image; imagesrcset="http://127.0.0.1:8000/resources/square.png?small 150w, http://127.0.0.1:8000/resources/square.png?large 300w"; imagesizes="(min-width: 150px) and (max-width: 150px) 150px, 300px"', false); + header('Link: <http://127.0.0.1:8000/resources/square.png?large>; rel=preload; as=image; imagesrcset="http://127.0.0.1:8000/resources/square.png?small 300w, http://127.0.0.1:8000/resources/square.png?large 600w"; imagesizes="(min-width: 300px) and (max-width: 300px) 300px, 600px"', false); + header('Link: <http://127.0.0.1:8000/resources/square.png?base>; rel=preload; as=image; imagesrcset="http://127.0.0.1:8000/resources/square.png?299 299w, http://127.0.0.1:8000/resources/square.png?300 300w, http://127.0.0.1:8000/resources/square.png?301 301w"; imagesizes="100vw"', false); ?> <!DOCTYPE html> -<meta name="viewport" content="width=150"> +<meta name="viewport" content="width=300"> <script> - window.addEventListener("load", function() { - var entries = performance.getEntriesByType("resource"); - var smallLoaded = false; - for (var i = 0; i < entries.length; ++i) { - if (entries[i].name.indexOf("large") != -1) - window.opener.postMessage("largeloaded", "*"); - if (entries[i].name.indexOf("small") != -1) - smallLoaded = true; + const numPreloads = 2; + + let loaded = []; + function checkPreloads(perf) { + for (let e of perf.getEntriesByType('resource')) { + let q = e.name.indexOf("?"); + if (q >= 0) + loaded.push(e.name.substr(q + 1)); } - if (smallLoaded) - window.opener.postMessage("success", "*") - window.opener.postMessage("smallnotloaded", "*"); - }); + if (loaded.length >= numPreloads) + window.opener.postMessage(loaded, "*"); + } + + let observer = new PerformanceObserver(checkPreloads); + observer.observe({entryTypes: ["resource"]}); + checkPreloads(performance); </script> -<script src="../resources/slow-script.pl?delay=200"></script>
diff --git a/third_party/blink/web_tests/http/tests/security/XFrameOptions/x-frame-options-cached-expected.txt b/third_party/blink/web_tests/http/tests/security/XFrameOptions/x-frame-options-cached-expected.txt index 3e39d2d..8241a92 100644 --- a/third_party/blink/web_tests/http/tests/security/XFrameOptions/x-frame-options-cached-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/XFrameOptions/x-frame-options-cached-expected.txt
@@ -4,7 +4,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Two console messages should be generated, each followed by an alert. Both frames should point to the expected URL, and not to about:blank. PASS frame1.src is "http://127.0.0.1:8000/security/XFrameOptions/resources/nph-cached-xfo.pl" @@ -12,4 +11,5 @@ PASS successfullyParsed is true TEST COMPLETE - + +
diff --git a/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-expected.txt b/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-expected.txt index c761d8f..bc91b1f2 100644 --- a/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-expected.txt
@@ -1,5 +1,6 @@ + --- Test begins --- * "about:blank" document.URL = about:blank
diff --git a/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-grandchildren-expected.txt b/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-grandchildren-expected.txt index 3d6af6f..837ab3e 100644 --- a/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-grandchildren-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-grandchildren-expected.txt
@@ -1,4 +1,3 @@ - --- Test begins --- * "about:blank" document.URL = about:blank
diff --git a/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-grandchildren-lexical-expected.txt b/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-grandchildren-lexical-expected.txt index a06ff80..c89672a 100644 --- a/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-grandchildren-lexical-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-grandchildren-lexical-expected.txt
@@ -1,4 +1,3 @@ - Helpers loaded! --- Test begins --- * "about:blank"
diff --git a/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-grandchildren-write-lexical-expected.txt b/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-grandchildren-write-lexical-expected.txt index 04d05b3..9b554b5 100644 --- a/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-grandchildren-write-lexical-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-grandchildren-write-lexical-expected.txt
@@ -1,4 +1,3 @@ - Helpers loaded! --- Test begins --- * "about:blank"
diff --git a/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-grandchildren-writeln-lexical-expected.txt b/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-grandchildren-writeln-lexical-expected.txt index a1db1c26..c958521 100644 --- a/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-grandchildren-writeln-lexical-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-grandchildren-writeln-lexical-expected.txt
@@ -1,4 +1,3 @@ - Helpers loaded! --- Test begins --- * "about:blank"
diff --git a/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-with-base-tag-expected.txt b/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-with-base-tag-expected.txt index 003bc485..00ab3afe 100644 --- a/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-with-base-tag-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-with-base-tag-expected.txt
@@ -1,5 +1,6 @@ + --- Test begins --- * "about:blank" document.URL = about:blank
diff --git a/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-write-expected.txt b/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-write-expected.txt index 44ffbfd..2558e3a7 100644 --- a/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-write-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-write-expected.txt
@@ -1,5 +1,6 @@ + --- Test begins --- * "about:blank" document.URL = about:blank
diff --git a/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-writeln-expected.txt b/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-writeln-expected.txt index 7b264ada..66d7c91 100644 --- a/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-writeln-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/aboutBlank/security-context-writeln-expected.txt
@@ -1,5 +1,6 @@ + --- Test begins --- * "about:blank" document.URL = about:blank
diff --git a/third_party/blink/web_tests/http/tests/security/aboutBlank/xss-DENIED-navigate-opener-document-write-expected.txt b/third_party/blink/web_tests/http/tests/security/aboutBlank/xss-DENIED-navigate-opener-document-write-expected.txt index 830ca81..d423bef2 100644 --- a/third_party/blink/web_tests/http/tests/security/aboutBlank/xss-DENIED-navigate-opener-document-write-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/aboutBlank/xss-DENIED-navigate-opener-document-write-expected.txt
@@ -2,6 +2,7 @@ This page opens a window to "", injects malicious code, and then navigates its opener to the victim. The opened window then tries to scripts its opener after document.writeing a new document. Code injected into window: <script>document.write('<script>function write(target, message) { target.document.body.innerHTML = message; }setTimeout(function() {write(window.opener, \'FAIL: XSS was allowed.\');}, 100);setTimeout(function() {write(window.opener.top.frames[1], \'SUCCESS: Window remained in original SecurityOrigin.\');}, 200);setTimeout(function() { window.opener.top.postMessage(\'done\', \'*\'); }, 300);<\/script>');</script> + --------
diff --git a/third_party/blink/web_tests/http/tests/security/aboutBlank/xss-DENIED-navigate-opener-javascript-url-expected.txt b/third_party/blink/web_tests/http/tests/security/aboutBlank/xss-DENIED-navigate-opener-javascript-url-expected.txt index e15379de..916427a2a 100644 --- a/third_party/blink/web_tests/http/tests/security/aboutBlank/xss-DENIED-navigate-opener-javascript-url-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/aboutBlank/xss-DENIED-navigate-opener-javascript-url-expected.txt
@@ -2,6 +2,7 @@ This page opens a window to "", injects malicious code, and then navigates its opener to the victim. The opened window then tries to scripts its opener after reloading itself as a javascript URL. Code injected into window: <script>window.location = 'javascript:\'<script>function write(target, message) { target.document.body.innerHTML = message; }setTimeout(function() {write(window.opener, \\\'FAIL: XSS was allowed.\\\');}, 100);setTimeout(function() {write(window.opener.top.frames[1], \\\'SUCCESS: Window remained in original SecurityOrigin.\\\');}, 200);setTimeout(function() { window.opener.top.postMessage(\\\'done\\\', \\\'*\\\'); }, 300);<\\\/script>\''</script> + --------
diff --git a/third_party/blink/web_tests/http/tests/security/aboutBlank/xss-DENIED-set-opener-expected.txt b/third_party/blink/web_tests/http/tests/security/aboutBlank/xss-DENIED-set-opener-expected.txt index 7450a89..fdfacc3 100644 --- a/third_party/blink/web_tests/http/tests/security/aboutBlank/xss-DENIED-set-opener-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/aboutBlank/xss-DENIED-set-opener-expected.txt
@@ -6,6 +6,7 @@ setTimeout(function() {write(window.opener.top.frames[1], 'SUCCESS: Window remained in original SecurityOrigin.');}, 200); setTimeout(function() { window.opener.top.postMessage('done', '*'); }, 300);</script> PASS: 'window.open' called on another frame threw: SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. + --------
diff --git a/third_party/blink/web_tests/http/tests/security/canvas-remote-read-redirect-to-remote-image-expected.txt b/third_party/blink/web_tests/http/tests/security/canvas-remote-read-redirect-to-remote-image-expected.txt index b62a3f3f..17a7132 100644 --- a/third_party/blink/web_tests/http/tests/security/canvas-remote-read-redirect-to-remote-image-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/canvas-remote-read-redirect-to-remote-image-expected.txt
@@ -1,4 +1,5 @@ This tests that drawing an image that redirects to a remote image to a canvas taints the canvas PASS: getImageData failed. Canvas tainted. +
diff --git a/third_party/blink/web_tests/http/tests/security/clipboard/clipboard-file-access-expected.txt b/third_party/blink/web_tests/http/tests/security/clipboard/clipboard-file-access-expected.txt index 417ea2f5..e171c67 100644 --- a/third_party/blink/web_tests/http/tests/security/clipboard/clipboard-file-access-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/clipboard/clipboard-file-access-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Dragging no files should return an empty file list (arbitrary implementation detail): On dragenter: PASS event.dataTransfer.types does not contain Files.
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-blank-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-blank-expected.txt index 7b22df16..d8e8140 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-blank-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-blank-expected.txt
@@ -5,7 +5,8 @@ CONSOLE MESSAGE: line 25: securitypolicyviolation_event.documentURI=http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-blank.html CONSOLE MESSAGE: line 26: securitypolicyviolation_event.blockedURI=http://127.0.0.1:8000/navigation/resources/form-target.pl CONSOLE MESSAGE: line 27: securitypolicyviolation_event.violatedDirective=form-action - + + Tests that blocking form actions works correctly. If this test passes, you will see a console error, and will not see a page indicating a form was POSTed. ============== Back Forward List ==============
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-cross-site-window-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-cross-site-window-expected.txt index 957bce5a..0f2e5512 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-cross-site-window-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-cross-site-window-expected.txt
@@ -5,5 +5,6 @@ CONSOLE MESSAGE: line 29: securitypolicyviolation_event.documentURI=http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-blocked-when-target-cross-site-window.html CONSOLE MESSAGE: line 30: securitypolicyviolation_event.blockedURI=http://127.0.0.1:8000/navigation/resources/form-target.pl CONSOLE MESSAGE: line 31: securitypolicyviolation_event.violatedDirective=form-action - + + Tests that blocking form actions works correctly. If this test passes, you will see a console error, and will not see a page indicating a form was POSTed.
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-allowed-expected.txt index 4adf7c18..34f19a1 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-allowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-allowed-expected.txt
@@ -3,6 +3,7 @@ Parameters: fieldname = fieldvalue + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-blocked-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-blocked-expected.txt index 9e95b5d9..0d6ed22 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-blocked-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-blocked-expected.txt
@@ -5,7 +5,8 @@ CONSOLE MESSAGE: line 25: securitypolicyviolation_event.documentURI=http://127.0.0.1:8000/security/contentSecurityPolicy/1.1/form-action-src-blocked.html CONSOLE MESSAGE: line 26: securitypolicyviolation_event.blockedURI=http://127.0.0.1:8000/navigation/resources/form-target.pl CONSOLE MESSAGE: line 27: securitypolicyviolation_event.violatedDirective=form-action - + + Tests that blocking form actions works correctly. If this test passes, you will see a console error, and will not see a page indicating a form was POSTed. ============== Back Forward List ==============
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-default-ignored-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-default-ignored-expected.txt index 5c321ee6e..e275733 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-default-ignored-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-default-ignored-expected.txt
@@ -3,6 +3,7 @@ Parameters: fieldname = fieldvalue + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-allowed-expected.txt index aab40ae..933c0fb 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-allowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-allowed-expected.txt
@@ -3,6 +3,7 @@ Parameters: fieldname = fieldvalue + Http headers: HTTP_CONNECTION = keep-alive
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-expected.txt index 5f482cf2..639dc10 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-expected.txt
@@ -1,6 +1,7 @@ CONSOLE ERROR: line 16: Refused to send form data to 'http://127.0.0.1:8000/navigation/resources/form-target.pl' because it violates the following Content Security Policy directive: "form-action 'none'". - + + Tests that blocking form actions works correctly. If this test passes, you will see a console error, and will not see a page indicating a form was POSTed. ============== Back Forward List ==============
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-with-redirect-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-with-redirect-expected.txt index dec9eeb..a37a9d3 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-with-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-get-blocked-with-redirect-expected.txt
@@ -1,6 +1,7 @@ CONSOLE ERROR: Refused to send form data to 'http://localhost:8000/' because it violates the following Content Security Policy directive: "form-action 127.0.0.1:8000". - + + Tests that blocking form actions works with the 'get' method and redirects. If this test passes, you will see a console error, and will not see a page indicating a form was POSTed. ============== Back Forward List ==============
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-javascript-blocked-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-javascript-blocked-expected.txt index 372073a..512532c 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-javascript-blocked-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-javascript-blocked-expected.txt
@@ -1,6 +1,7 @@ CONSOLE ERROR: line 14: Refused to send form data to 'javascript:alert("FAIL!")' because it violates the following Content Security Policy directive: "form-action 'none'". - + + Tests that blocking form actions works correctly. If this test passes, you will see a console error, and will not see a JavaScript alert. ============== Back Forward List ==============
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-redirect-blocked-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-redirect-blocked-expected.txt index fe7feb11..e12c940 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-redirect-blocked-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/form-action-src-redirect-blocked-expected.txt
@@ -1,6 +1,7 @@ CONSOLE ERROR: Refused to send form data to 'http://localhost:8000/' because it violates the following Content Security Policy directive: "form-action 127.0.0.1:8000". - + + Tests that blocking form redirect works correctly. If this test passes, you will see a console error, and will not see a page indicating a form was POSTed. ============== Back Forward List ==============
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-child-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-child-expected.txt index 9437597..dbeb430 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-child-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-child-expected.txt
@@ -1,5 +1,3 @@ CONSOLE ERROR: Refused to load 'http://127.0.0.1:8000/plugins/resources/mock-plugin.pl' (MIME type 'application/x-blink-test-plugin') because it violates the following Content Security Policy Directive: 'plugin-types text/plain'. This tests that a plugin-types directive on a top-level page should be inherited by a PluginDocument embedded in the page. This test passes if a console error says that the plugin was blocked. - -
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-cross-site-child-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-cross-site-child-allowed-expected.txt index c8cedc5..784f9aff 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-cross-site-child-allowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-cross-site-child-allowed-expected.txt
@@ -1,4 +1,2 @@ CONSOLE MESSAGE: Blink Test Plugin: initializing This tests a scenario where an iframe element's src attribute points to a cross-site URI that loads a plugin. In this test the plugin is allowed by the plugin-types Content Security Policy directive, therefore the test passes if 1) there is a "Blink Test Plugin: initializing" console message 2) there is no console message indicating CSP violation - -
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-cross-site-child-disallowed-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-cross-site-child-disallowed-expected.txt index f06ab9a..3d0a25f 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-cross-site-child-disallowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-affects-cross-site-child-disallowed-expected.txt
@@ -1,5 +1,3 @@ CONSOLE ERROR: Refused to load 'http://localhost:8000/plugins/resources/mock-plugin.pl' (MIME type 'application/x-blink-test-plugin') because it violates the following Content Security Policy Directive: 'plugin-types text/plain'. This tests a scenario where an iframe element's src attribute points to a cross-site URI that loads a plugin. In this test the plugin is disallowed by the plugin-types Content Security Policy directive, therefore the test passes if 1) there is no "Blink Test Plugin: initializing" console message 2) there is a console message indicating CSP violation - -
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-invalid-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-invalid-expected.txt index 3ac3880c..aba4473 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-invalid-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-invalid-expected.txt
@@ -35,8 +35,6 @@ CONSOLE MESSAGE: Blink Test Plugin: initializing This tests our handling of invalid `plugin-types` CSP directives. Consider this test passing if each of the following frames contains either "PASS" or no text at all. - - -------- Frame: '<!--framePath //<!--frame0-->-->' -------- @@ -80,5 +78,4 @@ -------- Frame: '<!--framePath //<!--frame8-->-->' -------- - PASS.
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-url-01-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-url-01-expected.txt index 735c4b1..330623b 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-url-01-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-url-01-expected.txt
@@ -4,28 +4,22 @@ CONSOLE MESSAGE: Blink Test Plugin: initializing This tests our handling of `data:` URLs, given a `plugin-types` CSP directive. Consider this test passing if each of the following frames contains "PASS" or no text at all, and no console warnings appear above. - - -------- Frame: '<!--framePath //<!--frame0-->-->' -------- - PASS. -------- Frame: '<!--framePath //<!--frame1-->-->' -------- - PASS. -------- Frame: '<!--framePath //<!--frame2-->-->' -------- - PASS. -------- Frame: '<!--framePath //<!--frame3-->-->' -------- - PASS.
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-url-02-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-url-02-expected.txt index 92e893c2..f6b1827 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-url-02-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/1.1/plugintypes-url-02-expected.txt
@@ -6,8 +6,6 @@ This tests our handling of non-`data:` URLs, given a `plugin-types` CSP directive. Consider this test passing if none of the following frames contains "FAIL" and four sets of console logs appear above. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/cached-frame-csp-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/cached-frame-csp-expected.txt index 5b00f861..3b8963e 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/cached-frame-csp-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/cached-frame-csp-expected.txt
@@ -6,10 +6,10 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Check that the nonce is the same, meaning that the document was only generated once: PASS frame1.contentDocument.querySelector("input").value == frame2.contentDocument.querySelector("input").value is true PASS successfullyParsed is true TEST COMPLETE - + +
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-01-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-01-expected.txt index 94d4fc4..781ffb8 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-01-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-01-expected.txt
@@ -3,8 +3,6 @@ This script should not execute even though there are parse errors in the policy. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-02-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-02-expected.txt index 4073a41..4fd91f55 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-02-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-02-expected.txt
@@ -4,8 +4,6 @@ This script should not execute even though there are parse errors in the policy. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-04-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-04-expected.txt index 1ad1ba2..ad3efb1f 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-04-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-04-expected.txt
@@ -2,8 +2,6 @@ A warning should be logged to the console, as `script-src: 'none'` shouldn't contain a colon. Since the directive is invalid, the script should run. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-05-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-05-expected.txt index b68a5fb1..49bd4c99 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-05-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-05-expected.txt
@@ -2,8 +2,6 @@ Directives starting with an invalid character should be logged and ignored. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-multiple-headers-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-multiple-headers-expected.txt index ad88556..cc5171f 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-multiple-headers-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/directive-parsing-multiple-headers-expected.txt
@@ -3,8 +3,6 @@ This script should not execute even through the second CSP header would allow it. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/frame-src-cross-origin-load-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/frame-src-cross-origin-load-expected.txt index 71ce0a1..f1b0e635 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/frame-src-cross-origin-load-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/frame-src-cross-origin-load-expected.txt
@@ -6,11 +6,11 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS IFrame #1 generated a 'load' event. PASS IFrame #2 generated a 'load' event. PASS IFrame #3 generated a 'load' event. PASS successfullyParsed is true TEST COMPLETE - + +
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/nonces/scriptnonce-blocked-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/nonces/scriptnonce-blocked-expected.txt index 169c4c2..2da23698 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/nonces/scriptnonce-blocked-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/nonces/scriptnonce-blocked-expected.txt
@@ -4,8 +4,6 @@ Only the first two of these scripts should execute even though there are parse errors in the policy. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/nonces/scriptnonce-invalidnonce-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/nonces/scriptnonce-invalidnonce-expected.txt index ddd088b..895a1dc 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/nonces/scriptnonce-invalidnonce-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/nonces/scriptnonce-invalidnonce-expected.txt
@@ -32,8 +32,6 @@ None of these scripts should execute, as all the nonces are invalid. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-does-not-affect-child-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-does-not-affect-child-expected.txt index 2359ca44..9b5e5a85 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-does-not-affect-child-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-does-not-affect-child-expected.txt
@@ -1,4 +1,2 @@ CONSOLE MESSAGE: Blink Test Plugin: initializing This tests that an object-src directive on a top-level page is not inherited by a PluginDocument embedded in an iframe on the page. This test passes if the plugin logs a message that it loaded. - -
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-none-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-none-allowed-expected.txt index e2466fa..15b5149 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-none-allowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-none-allowed-expected.txt
@@ -4,5 +4,4 @@ -------- Frame: '<!--framePath //<!--frame0-->-->' -------- - PASS!
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/plugin-in-iframe-with-csp-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/plugin-in-iframe-with-csp-expected.txt index 2f5cd64..5c35b5ef 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/plugin-in-iframe-with-csp-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/plugin-in-iframe-with-csp-expected.txt
@@ -1,5 +1,3 @@ CONSOLE ERROR: Refused to load plugin data from 'http://127.0.0.1:8000/plugins/resources/mock-plugin-with-csp.pl' because it violates the following Content Security Policy directive: "object-src 'none'". This tests that a plugin served with a CSP header will block the plugin from running in an iframe. This test passes if a console error says that the plugin was blocked. - -
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/register-bypassing-scheme-partial-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/register-bypassing-scheme-partial-expected.txt index 8fc832c..66a75252 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/register-bypassing-scheme-partial-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/register-bypassing-scheme-partial-expected.txt
@@ -27,5 +27,3 @@ CONSOLE MESSAGE: line 15: PASS (12/12) This test ensures that registering a scheme as bypassing CSP actually bypasses CSP. This test passes if only PASSes are generated. - -
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/register-bypassing-scheme-script.https-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/register-bypassing-scheme-script.https-expected.txt index 61d51174..28997ad5 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/register-bypassing-scheme-script.https-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/register-bypassing-scheme-script.https-expected.txt
@@ -1,5 +1,3 @@ -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/contentSecurityPolicy/register-bypassing-scheme-script.https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharness.js' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/contentSecurityPolicy/register-bypassing-scheme-script.https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharnessreport.js' over broken HTTPS. CONSOLE ERROR: Refused to load the script 'http://127.0.0.1:8000/security/contentSecurityPolicy/resources/script-set-attribute.js?t1' because it violates the following Content Security Policy directive: "script-src 'nonce-abc'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback. This is a testharness.js-based test.
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/script-src-in-iframe-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/script-src-in-iframe-expected.txt index 12245ff4..b490b2b 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/script-src-in-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/script-src-in-iframe-expected.txt
@@ -1,8 +1,6 @@ CONSOLE ERROR: The 'allow' directive has been replaced with 'default-src'. Please use that directive instead, as 'allow' has no effect. Loads an iframe (a) which loads an iframe (b) which in turns tries to load an external script. The iframe (a) has a content security policy disabling external scripts. As this policy does not apply to (b), the script should be executed. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/script-src-none-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/script-src-none-expected.txt index 3b1fab6..d0cbce3d 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/script-src-none-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/script-src-none-expected.txt
@@ -3,8 +3,6 @@ Loads an iframe which in turns tries to load an external script. The iframe has a content security policy disabling external scripts. So the script should not get executed. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/script-src-none-inline-event-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/script-src-none-inline-event-expected.txt index 3f97004..ad1afff1 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/script-src-none-inline-event-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/script-src-none-inline-event-expected.txt
@@ -1,6 +1,6 @@ CONSOLE ERROR: line 3: Refused to execute inline event handler because it violates the following Content Security Policy directive: "script-src 'none'". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution. - + -------- Frame: '<!--framePath //<!--frame0-->-->'
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/script-src-redirect-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/script-src-redirect-expected.txt index 2d6682f..6ebcccd 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/script-src-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/script-src-redirect-expected.txt
@@ -4,8 +4,6 @@ Loads an iframe which in turns tries to load an external script. The request for the script is redirected to 'localhost'. The iframe has a content security policy disabling external scripts from hosts other than 'localhost'. So the script should be allowed to run. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-01-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-01-expected.txt index 8ba221a..5071fe4 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-01-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-01-expected.txt
@@ -6,8 +6,6 @@ None of these scripts should execute even though there are parse errors in the policy. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-02-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-02-expected.txt index 3b051ae..f06e6c70 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-02-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-02-expected.txt
@@ -1,7 +1,5 @@ These scripts should execute even though there are parse errors in the policy. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-03-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-03-expected.txt index 3b58f52c..3ee3a0e 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-03-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-03-expected.txt
@@ -4,8 +4,6 @@ None of these scripts should execute. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-05-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-05-expected.txt index b445b01..ff723f9 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-05-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-05-expected.txt
@@ -22,8 +22,6 @@ Paths should be ignored when evaluating sources. This test passes if FAIL does not appear in the output, and each of the tests generates a warning about the path component. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-06-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-06-expected.txt index fe57066..7670fe5 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-06-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-06-expected.txt
@@ -22,8 +22,6 @@ Paths should be ignored when evaluating sources. This test passes if FAIL does not appear in the output, and each of the tests generates a warning about the path component. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-07-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-07-expected.txt index d87514f..0d0133c 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-07-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-07-expected.txt
@@ -25,8 +25,6 @@ CONSOLE ERROR: The source list for Content Security Policy directive 'script-src' contains an invalid source: 'https://127.0.0.1:'. It will be ignored. Invalid source expressions should log a console warning, and be ignored. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-08-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-08-expected.txt index ab94e05..e150e8b 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-08-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-08-expected.txt
@@ -4,8 +4,6 @@ Test proper handling of data: URLs. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-09-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-09-expected.txt index 1d01574c..c5243523 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-09-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-09-expected.txt
@@ -1,7 +1,5 @@ Host wildcards should work correctly. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-10-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-10-expected.txt index d790748a..8dea874 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-10-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-10-expected.txt
@@ -1,7 +1,5 @@ None of these scripts should execute even though there are parse errors in the policy. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-deprecated-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-deprecated-expected.txt index 636d988d..f84c2d98 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-deprecated-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-deprecated-expected.txt
@@ -3,8 +3,6 @@ CONSOLE ERROR: The 'policy-uri' directive has been removed from the specification. Please specify a complete policy via the Content-Security-Policy header. Test that directives that predate the CSP 1.0 standard generate proper warnings to set developer expectations correctly. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-malformed-meta-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-malformed-meta-expected.txt index 924548a5..e3b55b5d 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-malformed-meta-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-malformed-meta-expected.txt
@@ -1,4 +1,6 @@ CONSOLE ERROR: line 24: Refused to connect to 'http://127.0.0.1:8000/xmlhttprequest/resources/get.txt' because it violates the following Content Security Policy directive: "connect-src http://localhost:8000". Pass + + This test passes if the malformed meta tag doesn't cause a crash and the resource is blocked.
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-no-semicolon-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-no-semicolon-expected.txt index 8bd4d1e..28ef0d9 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-no-semicolon-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-no-semicolon-expected.txt
@@ -3,8 +3,6 @@ CONSOLE ERROR: The Content Security Policy directive 'script-src' contains 'style-src' as a source expression. Did you mean 'script-src ...; style-src...' (note the semicolon)? If a web author forgets a semicolon, we should do our best to warn them that the policy they've defined is probably not what they intended. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-nonascii-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-nonascii-expected.txt index 029ac1b4..0d8295c 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-nonascii-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-nonascii-expected.txt
@@ -1,8 +1,6 @@ CONSOLE ERROR: The value for Content Security Policy directive 'script-src' contains an invalid character: '127.0.0.1/ßisnotSorB/'. Non-whitespace characters outside ASCII 0x21-0x7E must be percent-encoded, as described in RFC 3986, section 2.1: http://tools.ietf.org/html/rfc3986#section-2.1. Sources containing non-ascii characters should be ignored, and should generate warnings. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-none-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-none-expected.txt index aa20f7d..b4108ea 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-none-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-none-expected.txt
@@ -11,8 +11,6 @@ 'none' should be ignored in source lists, unless it is the only token. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-paths-01-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-paths-01-expected.txt index 1c52e74..dccf3f6 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-paths-01-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-paths-01-expected.txt
@@ -8,8 +8,6 @@ Resources should be rejected unless they match a whitelisted path. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-paths-02-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-paths-02-expected.txt index dce2156..df43c21d 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-paths-02-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/source-list-parsing-paths-02-expected.txt
@@ -12,8 +12,6 @@ Resources should be rejected unless they match a whitelisted path. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/xmlhttprequest-protected-resource-does-not-crash-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/xmlhttprequest-protected-resource-does-not-crash-expected.txt index e14ac1c..ca495cb 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/xmlhttprequest-protected-resource-does-not-crash-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/xmlhttprequest-protected-resource-does-not-crash-expected.txt
@@ -1,2 +1,4 @@ PASS: [object HTMLDocument] + + Loading a frameless document (like those generated via XMLHttpRequest) shouldn't crash the CSP parser.
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/xsl-img-blocked-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/xsl-img-blocked-expected.txt index 9874f45..11bdc28 100644 --- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/xsl-img-blocked-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/xsl-img-blocked-expected.txt
@@ -1,3 +1,3 @@ CONSOLE ERROR: Refused to load the image 'http://127.0.0.1:8000/security/resources/abe.png' because it violates the following Content Security Policy directive: "img-src 'none'". -Here is an image: +Here is an image:
diff --git a/third_party/blink/web_tests/http/tests/security/contentTypeOptions/invalid-content-type-options-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/contentTypeOptions/invalid-content-type-options-allowed-expected.txt index 9c3a3bb..7137a2d 100644 --- a/third_party/blink/web_tests/http/tests/security/contentTypeOptions/invalid-content-type-options-allowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentTypeOptions/invalid-content-type-options-allowed-expected.txt
@@ -7,7 +7,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS window.scriptsSuccessfullyLoaded is unscriptyMimeTypes.length PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/security/contentTypeOptions/nosniff-dynamic-script-blocked-expected.txt b/third_party/blink/web_tests/http/tests/security/contentTypeOptions/nosniff-dynamic-script-blocked-expected.txt index dafdb96..16dbd097 100644 --- a/third_party/blink/web_tests/http/tests/security/contentTypeOptions/nosniff-dynamic-script-blocked-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentTypeOptions/nosniff-dynamic-script-blocked-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS window.scriptsSuccessfullyLoaded is 0 PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/security/contentTypeOptions/nosniff-script-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/contentTypeOptions/nosniff-script-allowed-expected.txt index a1b19901..ccb7333 100644 --- a/third_party/blink/web_tests/http/tests/security/contentTypeOptions/nosniff-script-allowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentTypeOptions/nosniff-script-allowed-expected.txt
@@ -12,7 +12,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS window.scriptsSuccessfullyLoaded is scriptyMimeTypes.length PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/security/contentTypeOptions/nosniff-script-blocked-expected.txt b/third_party/blink/web_tests/http/tests/security/contentTypeOptions/nosniff-script-blocked-expected.txt index f4a4751..ac3db12b 100644 --- a/third_party/blink/web_tests/http/tests/security/contentTypeOptions/nosniff-script-blocked-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentTypeOptions/nosniff-script-blocked-expected.txt
@@ -7,7 +7,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS window.scriptsSuccessfullyLoaded is 0 PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/security/contentTypeOptions/nosniff-script-without-content-type-blocked-expected.txt b/third_party/blink/web_tests/http/tests/security/contentTypeOptions/nosniff-script-without-content-type-blocked-expected.txt index 69b21e2..3a1a4af 100644 --- a/third_party/blink/web_tests/http/tests/security/contentTypeOptions/nosniff-script-without-content-type-blocked-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/contentTypeOptions/nosniff-script-without-content-type-blocked-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS window.scriptsSuccessfullyLoaded is 0 PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/security/cookies/base-tag-expected.txt b/third_party/blink/web_tests/http/tests/security/cookies/base-tag-expected.txt index ac712508..b38b7e4 100644 --- a/third_party/blink/web_tests/http/tests/security/cookies/base-tag-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cookies/base-tag-expected.txt
@@ -1,4 +1,3 @@ - Running test. secret=PASS Test complete.
diff --git a/third_party/blink/web_tests/http/tests/security/cookies/basic-expected.txt b/third_party/blink/web_tests/http/tests/security/cookies/basic-expected.txt index ac712508..b38b7e4 100644 --- a/third_party/blink/web_tests/http/tests/security/cookies/basic-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cookies/basic-expected.txt
@@ -1,4 +1,3 @@ - Running test. secret=PASS Test complete.
diff --git a/third_party/blink/web_tests/http/tests/security/cookies/document-open-expected.txt b/third_party/blink/web_tests/http/tests/security/cookies/document-open-expected.txt index 88504c6..c21e912 100644 --- a/third_party/blink/web_tests/http/tests/security/cookies/document-open-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cookies/document-open-expected.txt
@@ -1,4 +1,3 @@ - Running test. frames[0].document.URL = http://127.0.0.1:8000/security/cookies/document-open.html frames[0].document.baseURI = http://127.0.0.1:8000/security/cookies/document-open.html
diff --git a/third_party/blink/web_tests/http/tests/security/cookies/third-party-cookie-blocking-expected.txt b/third_party/blink/web_tests/http/tests/security/cookies/third-party-cookie-blocking-expected.txt index e2c35fa..50a59de 100644 --- a/third_party/blink/web_tests/http/tests/security/cookies/third-party-cookie-blocking-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cookies/third-party-cookie-blocking-expected.txt
@@ -1,6 +1,5 @@ - -------- Frame: 'iframe' --------
diff --git a/third_party/blink/web_tests/http/tests/security/cookies/third-party-cookie-blocking-user-action-expected.txt b/third_party/blink/web_tests/http/tests/security/cookies/third-party-cookie-blocking-user-action-expected.txt index e2c35fa..50a59de 100644 --- a/third_party/blink/web_tests/http/tests/security/cookies/third-party-cookie-blocking-user-action-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cookies/third-party-cookie-blocking-user-action-expected.txt
@@ -1,6 +1,5 @@ - -------- Frame: 'iframe' --------
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-DOMImplementation-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-DOMImplementation-expected.txt index 221441f..e958790f 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-DOMImplementation-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-DOMImplementation-expected.txt
@@ -1,3 +1,2 @@ - PASS: Setting properties on the DOMImplementation did not leak cross-frame.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-call-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-call-expected.txt index f7d6e36..f001ccb5 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-call-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-call-expected.txt
@@ -1,9 +1,7 @@ - ----- tests for calling methods of another frame using Function.call ----- On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS window.setTimeout.call(targetWindow, 'void(0);', 0) threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.. PASS window.setInterval.call(targetWindow, 'void(0);', 0) threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.. PASS window.open.call(targetWindow, '') threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.. @@ -30,8 +28,10 @@ PASS window.addEventListener.call(targetWindow, 'load', null, false); threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.. PASS window.removeEventListener.call(targetWindow, 'load', null, false); threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.. PASS: window.eval.call(targetWindow, '1+2'); should be '3' and is. + PASS window.location.toString.call(targetWindow.location) threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.. PASS: successfullyParsed should be 'true' and is. + TEST COMPLETE
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-callback-explicit-domain-DENY-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-callback-explicit-domain-DENY-expected.txt index 8747cd9..0a2da1a9 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-callback-explicit-domain-DENY-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-callback-explicit-domain-DENY-expected.txt
@@ -1,7 +1,5 @@ Test that a child frame can't define a function and the use it to access parent properties after document.domain write blocks the access. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-child-explicit-domain-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-child-explicit-domain-expected.txt index 974dddc..76ccc08f 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-child-explicit-domain-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-child-explicit-domain-expected.txt
@@ -1,4 +1,3 @@ - PASS: Cross frame access to frame explicitly setting document.domain was denied.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-custom-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-custom-expected.txt index 921e5ac0..c538340 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-custom-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-custom-expected.txt
@@ -1,5 +1,4 @@ - ----- tests for getting/setting interesting properties ----- PASS: canGet('targetWindow.Object') should be 'false' and is.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-delete-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-delete-expected.txt index 12ab0b38..c5a7912 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-delete-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-delete-expected.txt
@@ -1,4 +1,3 @@ - PASS: deletionThrowsException('targetWindow.existingProperty') should be 'true' and is. PASS: deletionThrowsException('targetWindow[1]') should be 'true' and is. PASS: deletionThrowsException('targetWindow.location.existingProperty') should be 'true' and is.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-dispatchEvent-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-dispatchEvent-expected.txt index 58932629..b02a2b3 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-dispatchEvent-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-dispatchEvent-expected.txt
@@ -1,4 +1,3 @@ - PASS: targetWindow.dispatchEvent(new CustomEvent("click")); should have thrown an exception, and did: SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. PASS: window.dispatchEvent.call(targetWindow, new CustomEvent("click")); should have thrown an exception, and did: SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-document-direct-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-document-direct-expected.txt index 864cf6a..c46963e 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-document-direct-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-document-direct-expected.txt
@@ -1,7 +1,5 @@ Test cross-origin direct document access. - - -------- Frame: 'theFrame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-enumeration-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-enumeration-expected.txt index 1b5abb3..4a4de46 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-enumeration-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-enumeration-expected.txt
@@ -1,6 +1,5 @@ This tests that variable names can't be enumerated cross domain (see http://bugs.webkit.org/show_bug.cgi?id=16387) - PASS: Cross frame access by enumerating the window object was denied. PASS: Cross frame access by getting the keys of the window object was denied. PASS: Cross frame access by getting the property names of the window object was denied.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-first-time-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-first-time-expected.txt index 17e1759e..aa9f4381 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-first-time-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-first-time-expected.txt
@@ -1,6 +1,5 @@ This test checks cross-frame access security for first-time access to the document (rdar://problem/5251309). - Exception thrown trying to get cross-domain document: SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. canGet(frames[0], 'document'): false canGet(frames[0].document, 'cookie'): false
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-frames-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-frames-expected.txt index 482d1ee..cd23c6f 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-frames-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-frames-expected.txt
@@ -1,5 +1,4 @@ - ----- tests for getting/setting the frames array access and the properties associated with it ----- PASS: targetWindow.frames.length should be '1' and is.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-get-custom-property-cached-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-get-custom-property-cached-expected.txt index 52a1704..f1e2cef7 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-get-custom-property-cached-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-get-custom-property-cached-expected.txt
@@ -1,6 +1,5 @@ This test checks that caching of property accesses doesn't allow for illegal cross-frame access of a custom property. It also checks for an assertion failure that once occurred in this situation. - PASS: customPropertyAccessThrowsException(targetWindow) should be 'true' and is. PASS: customPropertyAccessThrowsException(targetWindow) should be 'true' and is. PASS: customPropertyAccessThrowsException(targetWindow) should be 'true' and is.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-get-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-get-expected.txt index 36d88ff..8232af8d 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-get-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-get-expected.txt
@@ -1,7 +1,6 @@ This test checks cross-frame access security (rdar://problem/5251309). - ----- tests for getting of allowed properties -----
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-get-override-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-get-override-expected.txt index 79fde2c..a80192f 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-get-override-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-get-override-expected.txt
@@ -1,4 +1,3 @@ - ----- tests for getting a targetWindow's functions which have custom overrides. The desired behavior is for the targetWindow to return the built-in function, not the override ----- PASS: canGet('targetWindow.focus') should be 'true' and is.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-getOwnPropertyDescriptor-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-getOwnPropertyDescriptor-expected.txt index 3ccaa67..2631850c 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-getOwnPropertyDescriptor-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-getOwnPropertyDescriptor-expected.txt
@@ -1,7 +1,6 @@ This test checks cross-frame access security of getOwnPropertyDescriptor (https://bugs.webkit.org/show_bug.cgi?id=32119). - ----- tests for getting of not allowed properties -----
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-location-get-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-location-get-expected.txt index eefaac7..f694e92347 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-location-get-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-location-get-expected.txt
@@ -1,5 +1,4 @@ - ----- tests for getting window.location's properties ----- PASS: canGet('targetWindow.location') should be 'true' and is.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-location-get-override-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-location-get-override-expected.txt index 8553426..f45a2757 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-location-get-override-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-location-get-override-expected.txt
@@ -1,4 +1,3 @@ - ----- tests for getting a targetWindow's location object's functions which have custom overrides. The desired behavior is for the targetWindow to return the builtin function, not the override ----- PASS: canGet('targetWindow.location.assign') should be 'true' and is.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-location-put-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-location-put-expected.txt index a35480b..7948b17 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-location-put-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-location-put-expected.txt
@@ -1,4 +1,3 @@ - SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-name-getter-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-name-getter-expected.txt index 9035eaf3..e36e51a4 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-name-getter-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-name-getter-expected.txt
@@ -1,5 +1,4 @@ - ----- tests for getting properties by name ----- PASS: canGet('targetWindow.testiframe') should be 'true' and is.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-object-prototype-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-object-prototype-expected.txt index ae364b82..1a3f293b 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-object-prototype-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-object-prototype-expected.txt
@@ -1,4 +1,3 @@ - SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-parent-explicit-domain-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-parent-explicit-domain-expected.txt index 5545c436..f8181dc 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-parent-explicit-domain-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-parent-explicit-domain-expected.txt
@@ -1,4 +1,3 @@ - PASS: Cross frame access from frame explicitly setting document.domain was denied.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-parent-explicit-domain-isolated-world-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-parent-explicit-domain-isolated-world-expected.txt index d05b07e..0239fd7c 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-parent-explicit-domain-isolated-world-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-parent-explicit-domain-isolated-world-expected.txt
@@ -2,10 +2,8 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS Parent document access from isolated world is not allowed. PASS successfullyParsed is true TEST COMPLETE -
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-parent-isolated-world-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-parent-isolated-world-expected.txt index d05b07e..0239fd7c 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-parent-isolated-world-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-parent-isolated-world-expected.txt
@@ -2,10 +2,8 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS Parent document access from isolated world is not allowed. PASS successfullyParsed is true TEST COMPLETE -
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-port-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-port-expected.txt index 6f84a1e..98feeea9 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-port-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-port-expected.txt
@@ -1,4 +1,3 @@ - PASS: Cross frame access to different port was denied!
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-port-explicit-domain-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-port-explicit-domain-expected.txt index a0a4330..c0cf5b4b 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-port-explicit-domain-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-port-explicit-domain-expected.txt
@@ -1,6 +1,5 @@ This test currently fails because we check the port and protocol even if document.domain is explicitly set (rdar://problem/5366437). - PASS: Cross frame access to a different port, after explicitly setting document.domain, was allowed!
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-protocol-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-protocol-expected.txt index decb25e..47908799 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-protocol-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-protocol-expected.txt
@@ -1,4 +1,3 @@ - PASS: Cross frame access to https from http was denied!
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-protocol-explicit-domain-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-protocol-explicit-domain-expected.txt index 0e31236..260b112 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-protocol-explicit-domain-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-protocol-explicit-domain-expected.txt
@@ -1,6 +1,5 @@ This test currently fails because we check the port and protocol even if document.domain is explicitly set (rdar://problem/5366437). - PASS: Cross frame access to https from http, after explicitly setting document.domain, was denied.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-put-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-put-expected.txt index b44e74dc9e..51a58fa2 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-put-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-put-expected.txt
@@ -184,7 +184,6 @@ ALERT: PASS: window.stop should be 'function stop() { [native code] }' and is. This test checks cross-frame access security of window attribute setters (rdar://problem/5326791). - PASS: Unable to set property Attr: SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. PASS: Unable to set property CDATASection: SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame. PASS: Unable to set property CharacterData: SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-frame-access-set-window-properties-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-frame-access-set-window-properties-expected.txt index 2faac1e..dea63605 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-frame-access-set-window-properties-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-frame-access-set-window-properties-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS iWindow.focus = function () {}; threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.. PASS iWindow.blur = function () {}; threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.. PASS iWindow.close = function () {}; threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame..
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-OffscreenCanvas2D-createPattern-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-OffscreenCanvas2D-createPattern-expected.txt index 44996f4..3356d98a 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-origin-OffscreenCanvas2D-createPattern-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-origin-OffscreenCanvas2D-createPattern-expected.txt
@@ -2,8 +2,8 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE + PASS ImageBitmap is tainted. Threw error: SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-OffscreenCanvas2D-transferToImageBitmap-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-OffscreenCanvas2D-transferToImageBitmap-expected.txt index 3df44e17..242485a 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-origin-OffscreenCanvas2D-transferToImageBitmap-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-origin-OffscreenCanvas2D-transferToImageBitmap-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS ImageBitmap is tainted. Threw error: SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-access-over-property-descriptor-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-access-over-property-descriptor-expected.txt index 1f436d64..d144872 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-origin-access-over-property-descriptor-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-origin-access-over-property-descriptor-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS [object HTMLIFrameElement] is non-null. PASS [object Window] is non-null. PASS pathnameDescriptor is non-null.
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-appcache-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-appcache-allowed-expected.txt index ebd91b49..bdddf836 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-origin-appcache-allowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-origin-appcache-allowed-expected.txt
@@ -1,10 +1,7 @@ This iframe should have a cache: - This iframe should have a cache: - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-createImageBitmap-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-createImageBitmap-expected.txt index d6ab0ee7..a9d9ce24 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-origin-createImageBitmap-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-origin-createImageBitmap-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS Resolved as expected: image PASS ImageBitmap is tainted. Threw error: SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data. PASS Resolved as expected: canvas
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-indexeddb-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-indexeddb-allowed-expected.txt index d2501ba8..19716bd 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-origin-indexeddb-allowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-origin-indexeddb-allowed-expected.txt
@@ -1,6 +1,6 @@ Both of these frames should successfully open the database: - + -------- Frame: '<!--framePath //<!--frame0-->-->'
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-local-storage-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-local-storage-allowed-expected.txt index 9946bb4..3861c09 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-origin-local-storage-allowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-origin-local-storage-allowed-expected.txt
@@ -1,10 +1,7 @@ This iframe should not return any errors: - This iframe should not return any errors: - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-session-storage-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-session-storage-allowed-expected.txt index 9946bb4..3861c09 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-origin-session-storage-allowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-origin-session-storage-allowed-expected.txt
@@ -1,10 +1,7 @@ This iframe should not return any errors: - This iframe should not return any errors: - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-shared-worker-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-shared-worker-allowed-expected.txt index bbeb3351..24019b7 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-origin-shared-worker-allowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-origin-shared-worker-allowed-expected.txt
@@ -1,10 +1,7 @@ This iframe should not return any errors: - This iframe should not return any errors: - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-websql-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-websql-allowed-expected.txt index 9946bb4..3861c09 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-origin-websql-allowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-origin-websql-allowed-expected.txt
@@ -1,10 +1,7 @@ This iframe should not return any errors: - This iframe should not return any errors: - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-window-event-exception-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-window-event-exception-expected.txt index 89ea303..fb9f6422 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-origin-window-event-exception-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-origin-window-event-exception-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS frame.contentWindow.event threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.. PASS frame.contentWindow.event = 1; threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-window-open-exception-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-window-open-exception-expected.txt index 20e41810..48b6a0e 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-origin-window-open-exception-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-origin-window-open-exception-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS frame.contentWindow.open() threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.. FAIL frame.contentWindow.opener = 1; should throw SecurityError: Failed to set the 'opener' property on 'Window': Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.. Threw exception SecurityError: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a cross-origin frame.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-worker-indexeddb-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-worker-indexeddb-allowed-expected.txt index 055e1842..ffef155 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-origin-worker-indexeddb-allowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-origin-worker-indexeddb-allowed-expected.txt
@@ -1,6 +1,6 @@ Both of these frames should successfully open the database: - + -------- Frame: '<!--framePath //<!--frame0-->-->'
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-xsl-BLOCKED-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-xsl-BLOCKED-expected.txt index 3a0d099..092df08 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-origin-xsl-BLOCKED-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-origin-xsl-BLOCKED-expected.txt
@@ -2,4 +2,3 @@ This test loads the XML document in an iframe so that it can call dumpAsText(). This test passes if the iframe below does not contain a message starting with "FAIL". -
diff --git a/third_party/blink/web_tests/http/tests/security/cross-origin-xsl-redirect-BLOCKED-expected.txt b/third_party/blink/web_tests/http/tests/security/cross-origin-xsl-redirect-BLOCKED-expected.txt index 45f0869..0f757ac 100644 --- a/third_party/blink/web_tests/http/tests/security/cross-origin-xsl-redirect-BLOCKED-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/cross-origin-xsl-redirect-BLOCKED-expected.txt
@@ -2,4 +2,3 @@ This test loads the XML document in an iframe so that it can call dumpAsText(). This test passes if the iframe below does not contain a message starting with "FAIL". -
diff --git a/third_party/blink/web_tests/http/tests/security/data-url-inline.css-expected.txt b/third_party/blink/web_tests/http/tests/security/data-url-inline.css-expected.txt index bcfaf889..44569f3 100644 --- a/third_party/blink/web_tests/http/tests/security/data-url-inline.css-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/data-url-inline.css-expected.txt
@@ -2,5 +2,3 @@ This test ensures that a data URL can access its own inline style sheets. Sorry for the obscurity of the test case, but it's the repro from Bug 32309, which has an "unobfuscated" version of the code. This test passes if it alerts that it found 1 rule. - -
diff --git a/third_party/blink/web_tests/http/tests/security/data-url-xsl-expected.txt b/third_party/blink/web_tests/http/tests/security/data-url-xsl-expected.txt index f75b1cf0..f95d392 100644 --- a/third_party/blink/web_tests/http/tests/security/data-url-xsl-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/data-url-xsl-expected.txt
@@ -1,6 +1,5 @@ This test loads the XML document in an iframe so that it can call dumpAsText(). This test passes if the iframe below contains a message starting with "PASS". - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-in-foreign-domain-subframe-expected.txt b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-in-foreign-domain-subframe-expected.txt index 04b0eeee..a984dd65 100644 --- a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-in-foreign-domain-subframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-in-foreign-domain-subframe-expected.txt
@@ -3,15 +3,11 @@ Pass: Cross frame access from a data: URL on a different domain was denied. - - -------- Frame: 'aFrame' -------- Inner iframe on a foreign domain. - - -------- Frame: '<!--framePath //aFrame/<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-2-level-expected.txt b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-2-level-expected.txt index df2fbe1..c665bbc 100644 --- a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-2-level-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-2-level-expected.txt
@@ -1,6 +1,5 @@ This tests that a data: URL loaded in an iframe inside another data: URL loaded iframe doesn't have access to the main frame. - PASS: Cross frame access from a data: URL inside another data: URL was denied. -------- @@ -8,8 +7,6 @@ -------- Inner iframe. - - -------- Frame: '<!--framePath //aFrame/<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-expected.txt b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-expected.txt index 15f0538..a05b0345 100644 --- a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-expected.txt
@@ -1,6 +1,5 @@ This tests that a data: URL loaded in an iframe doesn't have access to its parent's frame - PASS: Cross frame access from a data: URL was denied. --------
diff --git a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-to-data-url-sub-frame-expected.txt b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-to-data-url-sub-frame-expected.txt index 060ea802..7a1d728 100644 --- a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-to-data-url-sub-frame-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-to-data-url-sub-frame-expected.txt
@@ -1,6 +1,6 @@ This tests that a data: URL subframe can't access a sibling data: URL subframe. - + -------- Frame: 'firstSubFrame' @@ -13,5 +13,3 @@ Frame: 'secondSubFrame' -------- Inner iframe. - -
diff --git a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-to-data-url-expected.txt b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-to-data-url-expected.txt index 757b863..93defd1 100644 --- a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-to-data-url-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-from-data-url-to-data-url-expected.txt
@@ -1,15 +1,10 @@ This tests that a data: URL subframe can't access a child data: URL subframe of itself. - - -------- Frame: 'aFrame' -------- - Inner iframe. - - -------- Frame: 'inner' --------
diff --git a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-from-data-url-expected.txt b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-from-data-url-expected.txt index 481943a..ab108e6 100644 --- a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-from-data-url-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-from-data-url-expected.txt
@@ -1,7 +1,5 @@ This tests that a data: URL loaded in an iframe inside another data: URL loaded iframe doesn't have access to its parent, the first data: URL loaded iframe. - - -------- Frame: 'aFrame' -------- @@ -9,8 +7,6 @@ Inner iframe. - - -------- Frame: 'innerFrame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-expected.txt b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-expected.txt index 20d84ef..5fc9a794 100644 --- a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-expected.txt
@@ -1,6 +1,5 @@ The scenario for this test is that you have an iframe with content from a foreign domain. In that foreign content is an iframe which loads a data: URL. This tests that this main document does not have access to that data: URL loaded iframe. - PASS: Cross frame access to a data: URL embed in a frame on a foreign domain denied! @@ -9,8 +8,6 @@ -------- Inner iframe on a foreign domain. - - -------- Frame: 'aFrame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-location-change-expected.txt b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-location-change-expected.txt index 0f0cf16..c4e02db 100644 --- a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-location-change-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-location-change-expected.txt
@@ -1,6 +1,5 @@ Opener frame - PASS: Cross frame access to a data: URL embed in a frame on a foreign domain denied!
diff --git a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-2-level-expected.txt b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-2-level-expected.txt index d1cb200..1a55c825 100644 --- a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-2-level-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-2-level-expected.txt
@@ -1,6 +1,5 @@ This tests that the main frame doesn't have access to a data: URL loaded in an iframe inside another data: URL loaded iframe. - PASS: Cross frame access to a data: URL 2 levels deep was denied. @@ -9,8 +8,6 @@ -------- Inner iframe. - - -------- Frame: '<!--framePath //aFrame/<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-expected.txt b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-expected.txt index b941cfc..5ebc11d 100644 --- a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-expected.txt
@@ -1,6 +1,5 @@ This tests that the main frame can't access the contents of an iframe that contains a data: URL loaded page - PASS: Cross frame access to a data: URL was denied.
diff --git a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-uppercase-expected.txt b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-uppercase-expected.txt index fd78c63..ac9811b 100644 --- a/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-uppercase-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-uppercase-expected.txt
@@ -1,6 +1,5 @@ This tests that the main frame can't access the contents of an iframe that contains a data: URL loaded page using the uppercased variant DATA: - PASS: Cross frame access to a DATA: URL was denied.
diff --git a/third_party/blink/web_tests/http/tests/security/detached-sandboxed-frame-access-expected.txt b/third_party/blink/web_tests/http/tests/security/detached-sandboxed-frame-access-expected.txt index b3f1a63c..33e44799 100644 --- a/third_party/blink/web_tests/http/tests/security/detached-sandboxed-frame-access-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/detached-sandboxed-frame-access-expected.txt
@@ -1,4 +1,6 @@ PASS successfullyParsed is true TEST COMPLETE + + PASS
diff --git a/third_party/blink/web_tests/http/tests/security/drag-over-remote-content-iframe-expected.txt b/third_party/blink/web_tests/http/tests/security/drag-over-remote-content-iframe-expected.txt index eb12e04..45847ae95 100644 --- a/third_party/blink/web_tests/http/tests/security/drag-over-remote-content-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/drag-over-remote-content-iframe-expected.txt
@@ -3,6 +3,5 @@ https://bugs.webkit.org/show_bug.cgi?id=25907 | rdar://problem/6910832. To test, drag Abe's image into this light blue div. - PASS: ondragover saw a URL of ''
diff --git a/third_party/blink/web_tests/http/tests/security/feed-urls-from-remote-expected.txt b/third_party/blink/web_tests/http/tests/security/feed-urls-from-remote-expected.txt index b7a9227e..b651008 100644 --- a/third_party/blink/web_tests/http/tests/security/feed-urls-from-remote-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/feed-urls-from-remote-expected.txt
@@ -1,6 +1,6 @@ Policy delegate: attempt to load feed://127.0.0.1:8000/security/resources/feed.xml with navigation type 'link clicked' -< rdar://problem/5329440> REGRESSION: Clicking links with the feed:// protocol in Safari 3 does nothing +< rdar://problem/5329440> REGRESSION: Clicking links with the feed:// protocol in Safari 3 does nothing This test is to see if a feed URL can be followed from a link on a page. -Test Finished. +Test Finished.
diff --git a/third_party/blink/web_tests/http/tests/security/filesystem-iframe-from-remote-expected.txt b/third_party/blink/web_tests/http/tests/security/filesystem-iframe-from-remote-expected.txt index 31009a6..7e6190ec 100644 --- a/third_party/blink/web_tests/http/tests/security/filesystem-iframe-from-remote-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/filesystem-iframe-from-remote-expected.txt
@@ -2,5 +2,6 @@ CONSOLE ERROR: line 8: Not allowed to load local resource: filesystem:http://localhost:8000/temporary/page.html This test is to see if a remote file can include a local page via a filesystem: URI in an iFrame. + Test Passed. Local page not remotely loaded into iFrame. - +
diff --git a/third_party/blink/web_tests/http/tests/security/frame-loading-via-document-write-expected.txt b/third_party/blink/web_tests/http/tests/security/frame-loading-via-document-write-expected.txt index 5ae943f..6bd94c7 100644 --- a/third_party/blink/web_tests/http/tests/security/frame-loading-via-document-write-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/frame-loading-via-document-write-expected.txt
@@ -14,9 +14,7 @@ -------- Image NOT loaded. - -------- Frame: 'bottomRow' -------- Image loaded. -
diff --git a/third_party/blink/web_tests/http/tests/security/frameNavigation/context-for-location-assign-expected.txt b/third_party/blink/web_tests/http/tests/security/frameNavigation/context-for-location-assign-expected.txt index dfda608..bba061b 100644 --- a/third_party/blink/web_tests/http/tests/security/frameNavigation/context-for-location-assign-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/frameNavigation/context-for-location-assign-expected.txt
@@ -1,2 +1 @@ document.referrer = http://127.0.0.1:8000/security/frameNavigation/context-for-location-assign.html -
diff --git a/third_party/blink/web_tests/http/tests/security/frameNavigation/context-for-location-expected.txt b/third_party/blink/web_tests/http/tests/security/frameNavigation/context-for-location-expected.txt index 23b9203..4a21c6d 100644 --- a/third_party/blink/web_tests/http/tests/security/frameNavigation/context-for-location-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/frameNavigation/context-for-location-expected.txt
@@ -1,2 +1 @@ document.referrer = http://127.0.0.1:8000/security/frameNavigation/context-for-location.html -
diff --git a/third_party/blink/web_tests/http/tests/security/frameNavigation/context-for-location-href-expected.txt b/third_party/blink/web_tests/http/tests/security/frameNavigation/context-for-location-href-expected.txt index 66c3857..88cb3e0 100644 --- a/third_party/blink/web_tests/http/tests/security/frameNavigation/context-for-location-href-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/frameNavigation/context-for-location-href-expected.txt
@@ -1,2 +1 @@ document.referrer = http://127.0.0.1:8000/security/frameNavigation/context-for-location-href.html -
diff --git a/third_party/blink/web_tests/http/tests/security/frameNavigation/context-for-window-open-expected.txt b/third_party/blink/web_tests/http/tests/security/frameNavigation/context-for-window-open-expected.txt index b30b9c5..c36d0223 100644 --- a/third_party/blink/web_tests/http/tests/security/frameNavigation/context-for-window-open-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/frameNavigation/context-for-window-open-expected.txt
@@ -1,2 +1 @@ document.referrer = http://127.0.0.1:8000/security/frameNavigation/context-for-window-open.html -
diff --git a/third_party/blink/web_tests/http/tests/security/frameNavigation/sandbox-ALLOWED-top-navigation-with-two-flags-expected.txt b/third_party/blink/web_tests/http/tests/security/frameNavigation/sandbox-ALLOWED-top-navigation-with-two-flags-expected.txt index 4ec5fe0..9968bd11 100644 --- a/third_party/blink/web_tests/http/tests/security/frameNavigation/sandbox-ALLOWED-top-navigation-with-two-flags-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/frameNavigation/sandbox-ALLOWED-top-navigation-with-two-flags-expected.txt
@@ -1,2 +1,3 @@ localhost + PASSED: Navigation succeeded.
diff --git a/third_party/blink/web_tests/http/tests/security/frameNavigation/sandbox-ALLOWED-top-navigation-with-user-gesture-expected.txt b/third_party/blink/web_tests/http/tests/security/frameNavigation/sandbox-ALLOWED-top-navigation-with-user-gesture-expected.txt index 4ec5fe0..9968bd11 100644 --- a/third_party/blink/web_tests/http/tests/security/frameNavigation/sandbox-ALLOWED-top-navigation-with-user-gesture-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/frameNavigation/sandbox-ALLOWED-top-navigation-with-user-gesture-expected.txt
@@ -1,2 +1,3 @@ localhost + PASSED: Navigation succeeded.
diff --git a/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-parent-navigation-change-async-expected.txt b/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-parent-navigation-change-async-expected.txt index 4ec5fe0..9968bd11 100644 --- a/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-parent-navigation-change-async-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-parent-navigation-change-async-expected.txt
@@ -1,2 +1,3 @@ localhost + PASSED: Navigation succeeded.
diff --git a/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-parent-navigation-change-expected.txt b/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-parent-navigation-change-expected.txt index 4ec5fe0..9968bd11 100644 --- a/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-parent-navigation-change-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-parent-navigation-change-expected.txt
@@ -1,2 +1,3 @@ localhost + PASSED: Navigation succeeded.
diff --git a/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-same-etld-plus-1-top-navigation-without-user-gesture-expected.txt b/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-same-etld-plus-1-top-navigation-without-user-gesture-expected.txt index 03d9c82..77b237d 100644 --- a/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-same-etld-plus-1-top-navigation-without-user-gesture-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-same-etld-plus-1-top-navigation-without-user-gesture-expected.txt
@@ -1,2 +1,3 @@ sub2.example.test + PASSED: Navigation succeeded.
diff --git a/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-same-origin-top-navigation-without-user-gesture-expected.txt b/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-same-origin-top-navigation-without-user-gesture-expected.txt index a7d62a5..3c77ad4 100644 --- a/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-same-origin-top-navigation-without-user-gesture-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-same-origin-top-navigation-without-user-gesture-expected.txt
@@ -1,2 +1,3 @@ 127.0.0.1 + PASSED: Navigation succeeded.
diff --git a/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-targeted-subframe-navigation-change-expected.txt b/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-targeted-subframe-navigation-change-expected.txt index d52aca0..21bfbec6 100644 --- a/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-targeted-subframe-navigation-change-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-ALLOWED-targeted-subframe-navigation-change-expected.txt
@@ -1,16 +1,16 @@ This tests that documents can navigate the location of any of it's sub-frames regardless of domain. 127.0.0.1 - Perform Test + Perform Test -------- Frame: '<!--framePath //<!--frame0-->-->' -------- localhost - -------- Frame: 'targetFrame' -------- localhost + PASSED: Navigation succeeded.
diff --git a/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-DENIED-targeted-link-navigation-expected.txt b/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-DENIED-targeted-link-navigation-expected.txt index ec0b3c7..cda7cef9 100644 --- a/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-DENIED-targeted-link-navigation-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/frameNavigation/xss-DENIED-targeted-link-navigation-expected.txt
@@ -6,6 +6,7 @@ Frame-with-link-to-navigate localhost Test PASSED + Click me --------
diff --git a/third_party/blink/web_tests/http/tests/security/host-compare-case-insensitive-expected.txt b/third_party/blink/web_tests/http/tests/security/host-compare-case-insensitive-expected.txt index 0df152e..5a92e7b 100644 --- a/third_party/blink/web_tests/http/tests/security/host-compare-case-insensitive-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/host-compare-case-insensitive-expected.txt
@@ -1,6 +1,6 @@ This tests that the comparison of the host for security is done case insensitive. - + -------- Frame: 'frameA' @@ -13,5 +13,3 @@ Frame: 'frameB' -------- Other inner iframe. - -
diff --git a/third_party/blink/web_tests/http/tests/security/img-crossorigin-redirect-anonymous-expected.txt b/third_party/blink/web_tests/http/tests/security/img-crossorigin-redirect-anonymous-expected.txt index 00adcb5..01dd20e 100644 --- a/third_party/blink/web_tests/http/tests/security/img-crossorigin-redirect-anonymous-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/img-crossorigin-redirect-anonymous-expected.txt
@@ -5,9 +5,9 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS/FAIL descriptions are of the form, 'CORS request type': 'redirect CORS type' => 'resource' + PASS: Anonymous request: anonymous => no-CORS image resource. PASS: Anonymous request: anonymous => anonymous-CORS image resource. PASS: Credentialled request: anonymous => credentialled image resource (same origin.)
diff --git a/third_party/blink/web_tests/http/tests/security/img-crossorigin-redirect-no-cors-expected.txt b/third_party/blink/web_tests/http/tests/security/img-crossorigin-redirect-no-cors-expected.txt index 842d6daa..a06fd286 100644 --- a/third_party/blink/web_tests/http/tests/security/img-crossorigin-redirect-no-cors-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/img-crossorigin-redirect-no-cors-expected.txt
@@ -6,9 +6,9 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS/FAIL descriptions are of the form, 'CORS request type': 'redirect CORS type' => 'resource' + PASS: Anonymous request: no-CORS => no-CORS image resource. PASS: Anonymous request: no-CORS => anonymous-CORS image resource. PASS: Credentialled request: no-CORS => credential-CORS image resource (same origin.)
diff --git a/third_party/blink/web_tests/http/tests/security/isolatedWorld/bypass-main-world-csp-for-inline-script-expected.txt b/third_party/blink/web_tests/http/tests/security/isolatedWorld/bypass-main-world-csp-for-inline-script-expected.txt index 697ffd3..cb824dc 100644 --- a/third_party/blink/web_tests/http/tests/security/isolatedWorld/bypass-main-world-csp-for-inline-script-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/isolatedWorld/bypass-main-world-csp-for-inline-script-expected.txt
@@ -10,5 +10,3 @@ CONSOLE ERROR: line 21: Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-eval'". Either the 'unsafe-inline' keyword, a hash ('sha256-09Et/dqtUwF1zPoVDKo5ZDj2NUXqkLUxcQfh9UtQQt0='), or a nonce ('nonce-...') is required to enable inline execution. This test ensures that scripts run in isolated worlds marked with their own Content Security Policy aren't affected by the page's content security policy. Extensions, for example, should be able to inject inline JavaScript (even though it's probably a bad idea to do so). - -
diff --git a/third_party/blink/web_tests/http/tests/security/isolatedWorld/bypass-main-world-csp-javascript-urls-expected.txt b/third_party/blink/web_tests/http/tests/security/isolatedWorld/bypass-main-world-csp-javascript-urls-expected.txt index 00f91bdb..52e7a4b 100644 --- a/third_party/blink/web_tests/http/tests/security/isolatedWorld/bypass-main-world-csp-javascript-urls-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/isolatedWorld/bypass-main-world-csp-javascript-urls-expected.txt
@@ -5,5 +5,4 @@ ALERT: iframe loaded ALERT: Running test #0 - This test ensures that scripts run in isolated worlds marked with their own Content Security Policy can bypass javascript: URL restrictions.
diff --git a/third_party/blink/web_tests/http/tests/security/isolatedWorld/cross-origin-xhr-expected.txt b/third_party/blink/web_tests/http/tests/security/isolatedWorld/cross-origin-xhr-expected.txt index a3bbeda..f1d894e 100644 --- a/third_party/blink/web_tests/http/tests/security/isolatedWorld/cross-origin-xhr-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/isolatedWorld/cross-origin-xhr-expected.txt
@@ -5,7 +5,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - XHR from main world XHR completed with status 0 XHR from isolated world with unchanged security origin
diff --git a/third_party/blink/web_tests/http/tests/security/isolatedWorld/no-bypass-main-world-csp-for-delayed-execution-expected.txt b/third_party/blink/web_tests/http/tests/security/isolatedWorld/no-bypass-main-world-csp-for-delayed-execution-expected.txt index 0381f0a..9813f0e 100644 --- a/third_party/blink/web_tests/http/tests/security/isolatedWorld/no-bypass-main-world-csp-for-delayed-execution-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/isolatedWorld/no-bypass-main-world-csp-for-delayed-execution-expected.txt
@@ -5,5 +5,3 @@ ALERT: PASS: Case 1 was not evaluated in main world. ALERT: PASS: Case 1 was evaluated in isolated world. Test a script that bypasses the main world's CSP to see if its *content* bypasses the main world as well (it should not). - -
diff --git a/third_party/blink/web_tests/http/tests/security/isolatedWorld/sandboxed-iframe-expected.txt b/third_party/blink/web_tests/http/tests/security/isolatedWorld/sandboxed-iframe-expected.txt index ab13db3..9d0de7c0 100644 --- a/third_party/blink/web_tests/http/tests/security/isolatedWorld/sandboxed-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/isolatedWorld/sandboxed-iframe-expected.txt
@@ -1,5 +1,3 @@ CONSOLE ERROR: Blocked script execution in 'http://127.0.0.1:8000/security/isolatedWorld/resources/fail.html' because the document's frame is sandboxed and the 'allow-scripts' permission is not set. CONSOLE MESSAGE: PASS Test that executing scripts in an isolated world works even inside sandboxed iframes. The test passes, if an alert with the text "PASS" is shown. - -
diff --git a/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-getAttribute-value-expected.txt b/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-getAttribute-value-expected.txt index 901ac8fd..3945d86 100644 --- a/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-getAttribute-value-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-getAttribute-value-expected.txt
@@ -3,8 +3,6 @@ CONSOLE ERROR: line 7: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match. This test passes as long as the word 'FAIL' and an accompanying message do not appear in the subframe. - - -------- Frame: 'aFrame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-htmldom-expected.txt b/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-htmldom-expected.txt index 901ac8fd..3945d86 100644 --- a/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-htmldom-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-htmldom-expected.txt
@@ -3,8 +3,6 @@ CONSOLE ERROR: line 7: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match. This test passes as long as the word 'FAIL' and an accompanying message do not appear in the subframe. - - -------- Frame: 'aFrame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-setAttribute-expected.txt b/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-setAttribute-expected.txt index 901ac8fd..3945d86 100644 --- a/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-setAttribute-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-setAttribute-expected.txt
@@ -3,8 +3,6 @@ CONSOLE ERROR: line 7: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match. This test passes as long as the word 'FAIL' and an accompanying message do not appear in the subframe. - - -------- Frame: 'aFrame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-setAttributeNS-expected.txt b/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-setAttributeNS-expected.txt index 901ac8fd..3945d86 100644 --- a/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-setAttributeNS-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-setAttributeNS-expected.txt
@@ -3,8 +3,6 @@ CONSOLE ERROR: line 7: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match. This test passes as long as the word 'FAIL' and an accompanying message do not appear in the subframe. - - -------- Frame: 'aFrame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-setAttributeNode-expected.txt b/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-setAttributeNode-expected.txt index 7162b39..a7d6c26d 100644 --- a/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-setAttributeNode-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/javascriptURL/javascriptURL-execution-context-iframe-src-setAttributeNode-expected.txt
@@ -3,8 +3,6 @@ CONSOLE ERROR: line 9: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match. This test passes as long as the word 'FAIL' and an accompanying message do not appear in the subframe. - - -------- Frame: 'aFrame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-from-javascript-url-sub-frame-2-level-expected.txt b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-from-javascript-url-sub-frame-2-level-expected.txt index 53761282..a2b15fb9b 100644 --- a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-from-javascript-url-sub-frame-2-level-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-from-javascript-url-sub-frame-2-level-expected.txt
@@ -1,12 +1,10 @@ This tests that a javascript: URL loaded in an iframe inside another javascript: URL loaded iframe has access to the main frame. - PASS: Cross frame access from a javascript: URL inside another javascript: URL was allowed! -------- Frame: 'aFrame' -------- - Inner iframe. --------
diff --git a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-from-javascript-url-sub-frame-expected.txt b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-from-javascript-url-sub-frame-expected.txt index 63b49b1..41b3284a 100644 --- a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-from-javascript-url-sub-frame-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-from-javascript-url-sub-frame-expected.txt
@@ -1,6 +1,5 @@ This tests that a javascript: URL loaded in an iframe has access to its parent's frame - PASS: Cross frame access from a javascript: URL was allowed! --------
diff --git a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-from-javascript-url-sub-frame-to-javascript-url-sub-frame-expected.txt b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-from-javascript-url-sub-frame-to-javascript-url-sub-frame-expected.txt index 4220e1e8..df6793d2 100644 --- a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-from-javascript-url-sub-frame-to-javascript-url-sub-frame-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-from-javascript-url-sub-frame-to-javascript-url-sub-frame-expected.txt
@@ -1,6 +1,6 @@ This tests that a javascript: URL subframe can access a sibling javascript: URL subframe. - + -------- Frame: 'firstSubFrame'
diff --git a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-from-javascript-url-to-javscript-url-expected.txt b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-from-javascript-url-to-javscript-url-expected.txt index 7fb33d2..b3e0748b 100644 --- a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-from-javascript-url-to-javscript-url-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-from-javascript-url-to-javscript-url-expected.txt
@@ -1,11 +1,8 @@ This tests that a javascript: URL subframe can access a child javascript: URL subframe of itself. - - -------- Frame: 'aFrame' -------- - Inner iframe. --------
diff --git a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-to-javascript-url-from-javscript-url-expected.txt b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-to-javascript-url-from-javscript-url-expected.txt index a6b46b8..ae52424c 100644 --- a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-to-javascript-url-from-javscript-url-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-to-javascript-url-from-javscript-url-expected.txt
@@ -1,13 +1,10 @@ This tests that a javascript: URL loaded in an iframe inside another javascript: URL loaded iframe has access to it's parent, the first javascript: URL loaded iframe. - - -------- Frame: 'aFrame' -------- PASS: Cross frame access from a javascript: URL was allowed! - Inner iframe. --------
diff --git a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-to-javascript-url-sub-frame-2-level-expected.txt b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-to-javascript-url-sub-frame-2-level-expected.txt index 5516ed2..eafc9306 100644 --- a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-to-javascript-url-sub-frame-2-level-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-to-javascript-url-sub-frame-2-level-expected.txt
@@ -1,13 +1,11 @@ This tests that the main frame has access to a javascript: URL loaded in an iframe inside another javascript: URL loaded iframe. - PASS: Cross frame access to a javascript: URL 2 levels deep was allowed! -------- Frame: 'aFrame' -------- - Inner iframe. --------
diff --git a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-to-javascript-url-sub-frame-expected.txt b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-to-javascript-url-sub-frame-expected.txt index 83beb8b7..9624790 100644 --- a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-to-javascript-url-sub-frame-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-ALLOWED-to-javascript-url-sub-frame-expected.txt
@@ -1,6 +1,5 @@ This tests that the main frame can access the contents of an iframe that contains a javascript: URL loaded page - PASS: Cross frame access to a javascript: URL was allowed!
diff --git a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-DENIED-from-javascript-url-in-foreign-domain-subframe-expected.txt b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-DENIED-from-javascript-url-in-foreign-domain-subframe-expected.txt index 4dbbfe3..91d1f9a 100644 --- a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-DENIED-from-javascript-url-in-foreign-domain-subframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-DENIED-from-javascript-url-in-foreign-domain-subframe-expected.txt
@@ -1,6 +1,5 @@ The scenario for this test is that you have an iframe with content from a foreign domain. In that foreign content is an iframe which loads a javascript: URL. This tests that the javascript: URL loaded iframe does not have access to the main frame using top.document. - Pass: Cross frame access from a javascript: URL on a different domain was denied. -------- @@ -8,8 +7,6 @@ -------- Inner iframe on a foreign domain. - - -------- Frame: 'aFrame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-DENIED-from-javascript-url-in-foreign-domain-window-open-expected.txt b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-DENIED-from-javascript-url-in-foreign-domain-window-open-expected.txt index 684cff3..1a274a5 100644 --- a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-DENIED-from-javascript-url-in-foreign-domain-window-open-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-DENIED-from-javascript-url-in-foreign-domain-window-open-expected.txt
@@ -1,5 +1,3 @@ Opener Frame Pass: Cross frame access from a javascript: URL on a different domain was denied. - -
diff --git a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-DENIED-to-javascript-url-in-foreign-domain-subframe-expected.txt b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-DENIED-to-javascript-url-in-foreign-domain-subframe-expected.txt index 4c10f77..ed4a9ce 100644 --- a/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-DENIED-to-javascript-url-in-foreign-domain-subframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/javascriptURL/xss-DENIED-to-javascript-url-in-foreign-domain-subframe-expected.txt
@@ -1,6 +1,5 @@ The scenario for this test is that you have an iframe with content from a foreign domain. In that foreign content is an iframe which loads a javascript: URL. This tests that this main document does not have access to that javascript: URL loaded iframe. - PASS: Cross frame access to a javascript: URL embed in a frame on a foreign domain denied! @@ -9,8 +8,6 @@ -------- Inner iframe on a foreign domain. - - -------- Frame: 'aFrame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-anonymous-expected.txt b/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-anonymous-expected.txt index 3080dfd..230e806 100644 --- a/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-anonymous-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-anonymous-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS PASS PASS
diff --git a/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-import-anonymous-expected.txt b/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-import-anonymous-expected.txt index 37f53d01..4818c43 100644 --- a/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-import-anonymous-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-import-anonymous-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS PASS PASS
diff --git a/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-import-credentials-expected.txt b/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-import-credentials-expected.txt index 2185fd0..e2c4da89 100644 --- a/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-import-credentials-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-import-credentials-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS PASS PASS
diff --git a/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-reinserted-expected.txt b/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-reinserted-expected.txt index 3fa6837..b542537 100644 --- a/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-reinserted-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-reinserted-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS non-CORS stylesheet loaded with error(no assert) PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-use-credentials-expected.txt b/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-use-credentials-expected.txt index 00ab067..7548c4b 100644 --- a/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-use-credentials-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/link-crossorigin-stylesheet-use-credentials-expected.txt
@@ -4,7 +4,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS PASS PASS
diff --git a/third_party/blink/web_tests/http/tests/security/listener/xss-JSTargetNode-onclick-addEventListener-expected.txt b/third_party/blink/web_tests/http/tests/security/listener/xss-JSTargetNode-onclick-addEventListener-expected.txt index e89d15c..d4a1aa9 100644 --- a/third_party/blink/web_tests/http/tests/security/listener/xss-JSTargetNode-onclick-addEventListener-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/listener/xss-JSTargetNode-onclick-addEventListener-expected.txt
@@ -1,3 +1,3 @@ This tests that frame used when setting eventListeners on an EventTarget using addEventListener is the target nodes frame. (rdar://problem/5426142). This test passes if you don't see an alert dialog with the domain of "localhost" in it and an "Unsafe JavaScript" warning is logged to the console. - +
diff --git a/third_party/blink/web_tests/http/tests/security/listener/xss-JSTargetNode-onclick-shortcut-expected.txt b/third_party/blink/web_tests/http/tests/security/listener/xss-JSTargetNode-onclick-shortcut-expected.txt index 80fd6ab..497fca0c 100644 --- a/third_party/blink/web_tests/http/tests/security/listener/xss-JSTargetNode-onclick-shortcut-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/listener/xss-JSTargetNode-onclick-shortcut-expected.txt
@@ -1,3 +1,3 @@ This tests that frame used when setting eventListeners on an EventTarget with the shortcut (onclick, etc), is the target nodes frame. (rdar://problem/5426142). This test passes if you don't see an alert dialog with the domain of "localhost" in it and an "Unsafe JavaScript" warning is logged to the console. - +
diff --git a/third_party/blink/web_tests/http/tests/security/listener/xss-XMLHttpRequest-addEventListener-expected.txt b/third_party/blink/web_tests/http/tests/security/listener/xss-XMLHttpRequest-addEventListener-expected.txt index c019249..1eeb432 100644 --- a/third_party/blink/web_tests/http/tests/security/listener/xss-XMLHttpRequest-addEventListener-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/listener/xss-XMLHttpRequest-addEventListener-expected.txt
@@ -1,4 +1,4 @@ CONSOLE WARNING: line 18: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. This tests that frame used when setting eventListeners on an XMLHttpRequest using addEventListener, is the requests frame. (rdar://problem/5426142). This test passes if you don't see an alert dialog with the domain of "localhost" in it and an "Unsafe JavaScript" warning is logged to the console. - +
diff --git a/third_party/blink/web_tests/http/tests/security/listener/xss-XMLHttpRequest-shortcut-expected.txt b/third_party/blink/web_tests/http/tests/security/listener/xss-XMLHttpRequest-shortcut-expected.txt index 1b4bab0..1a79aa8 100644 --- a/third_party/blink/web_tests/http/tests/security/listener/xss-XMLHttpRequest-shortcut-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/listener/xss-XMLHttpRequest-shortcut-expected.txt
@@ -1,3 +1,3 @@ This tests that frame used when setting eventListeners on an XMLHttpRequest with the shortcut (onreadystatechange), is the requests frame. (rdar://problem/5426142). This test passes if you don't see an alert dialog with the domain of "localhost" in it and an "Unsafe JavaScript" warning is logged to the console. - +
diff --git a/third_party/blink/web_tests/http/tests/security/listener/xss-inactive-closure-expected.txt b/third_party/blink/web_tests/http/tests/security/listener/xss-inactive-closure-expected.txt index 6269c61..cfbcc0fc 100644 --- a/third_party/blink/web_tests/http/tests/security/listener/xss-inactive-closure-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/listener/xss-inactive-closure-expected.txt
@@ -3,4 +3,4 @@ You should see PASSED at the end of page if the test passes. PASSED - +
diff --git a/third_party/blink/web_tests/http/tests/security/listener/xss-window-onclick-addEventListener-expected.txt b/third_party/blink/web_tests/http/tests/security/listener/xss-window-onclick-addEventListener-expected.txt index c394cfae..cc2b495 100644 --- a/third_party/blink/web_tests/http/tests/security/listener/xss-window-onclick-addEventListener-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/listener/xss-window-onclick-addEventListener-expected.txt
@@ -1,3 +1,3 @@ This tests that frame used when setting eventListeners on the window using addEventListener is the window's frame. (rdar://problem/5426142). This test passes if you don't see an alert dialog with the domain of "localhost" in it and an "Unsafe JavaScript" warning is logged to the console. - +
diff --git a/third_party/blink/web_tests/http/tests/security/listener/xss-window-onclick-shortcut-expected.txt b/third_party/blink/web_tests/http/tests/security/listener/xss-window-onclick-shortcut-expected.txt index c1ba636..3ceee05 100644 --- a/third_party/blink/web_tests/http/tests/security/listener/xss-window-onclick-shortcut-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/listener/xss-window-onclick-shortcut-expected.txt
@@ -1,3 +1,3 @@ This tests that frame used when setting eventListeners on the window with the shortcut (onclick, etc), is the window's frame. (rdar://problem/5426142). This test passes if you don't see an alert dialog with the domain of "localhost" in it and an "Unsafe JavaScript" warning is logged to the console. - +
diff --git a/third_party/blink/web_tests/http/tests/security/local-CSS-from-remote-expected.txt b/third_party/blink/web_tests/http/tests/security/local-CSS-from-remote-expected.txt index 34cc6594..952398b 100644 --- a/third_party/blink/web_tests/http/tests/security/local-CSS-from-remote-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/local-CSS-from-remote-expected.txt
@@ -1,7 +1,8 @@ CONSOLE ERROR: line 19: Not allowed to load local resource: cssStyle.css -This test is to see if a remote file can include a local CSS style. -Currently this test cannot be run manually on Windows because we do not have a function like pathToLocalResource() outside of DRT. +This test is to see if a remote file can include a local CSS style. +Currently this test cannot be run manually on Windows because we do not have a function like pathToLocalResource() outside of DRT. If the background is yellow then the CSS was loaded. + Test Passed: Local CSS not remotely loaded.
diff --git a/third_party/blink/web_tests/http/tests/security/local-JavaScript-from-remote-expected.txt b/third_party/blink/web_tests/http/tests/security/local-JavaScript-from-remote-expected.txt index 7f11df0e..f7fbe85 100644 --- a/third_party/blink/web_tests/http/tests/security/local-JavaScript-from-remote-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/local-JavaScript-from-remote-expected.txt
@@ -1,5 +1,7 @@ CONSOLE ERROR: line 35: Not allowed to load local resource: localScript.js -This test is to see if a remote file can run a local script. -Currently this test cannot be run manually on Windows because we do not have a function like pathToLocalResource() outside of DRT. +This test is to see if a remote file can run a local script. +Currently this test cannot be run manually on Windows because we do not have a function like pathToLocalResource() outside of DRT. + + Test Passed: Local script not loaded.
diff --git a/third_party/blink/web_tests/http/tests/security/local-iFrame-from-remote-expected.txt b/third_party/blink/web_tests/http/tests/security/local-iFrame-from-remote-expected.txt index 929dc54..51fcbc1 100644 --- a/third_party/blink/web_tests/http/tests/security/local-iFrame-from-remote-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/local-iFrame-from-remote-expected.txt
@@ -1,6 +1,7 @@ CONSOLE ERROR: line 16: Not allowed to load local resource: localPage.html -This test is to see if a remote file can include a local page in an iFrame. -Currently this test cannot be run manually on Windows because we do not have a function like pathToLocalResource() outside of DRT. +This test is to see if a remote file can include a local page in an iFrame. +Currently this test cannot be run manually on Windows because we do not have a function like pathToLocalResource() outside of DRT. + + Test Passed. Local page not remotely loaded into iFrame. -
diff --git a/third_party/blink/web_tests/http/tests/security/local-image-from-remote-expected.txt b/third_party/blink/web_tests/http/tests/security/local-image-from-remote-expected.txt index b9c1a26..8b472b5 100644 --- a/third_party/blink/web_tests/http/tests/security/local-image-from-remote-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/local-image-from-remote-expected.txt
@@ -1,6 +1,8 @@ CONSOLE ERROR: Not allowed to load local resource: compass.jpg -This test is to see if a remote file can include a local image. -Currently this test cannot be run manually on Windows because we do not have a function like pathToLocalResource() outside of DRT. +This test is to see if a remote file can include a local image. +Currently this test cannot be run manually on Windows because we do not have a function like pathToLocalResource() outside of DRT. + + Test Passed. Local image not loaded remotely.
diff --git a/third_party/blink/web_tests/http/tests/security/local-image-from-remote-whitelisted-expected.txt b/third_party/blink/web_tests/http/tests/security/local-image-from-remote-whitelisted-expected.txt index f7ed06a..34c2c36 100644 --- a/third_party/blink/web_tests/http/tests/security/local-image-from-remote-whitelisted-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/local-image-from-remote-whitelisted-expected.txt
@@ -1,4 +1,3 @@ - This test is to see if a remote file can include a local image when the access has been white listed using addOriginAccessAllowListEntry. Test Passed. Local image loaded remotely.
diff --git a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-01-expected.txt b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-01-expected.txt index dacfa09..8bd78a4 100644 --- a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-01-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-01-expected.txt
@@ -1,7 +1,5 @@ This test verifies that resources served with a mime type of 'application/atom+xml' is not rendered as HTML. It passes if no "FAIL: ..." alert is present, and if the textual content of the frame is visible below. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-02-expected.txt b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-02-expected.txt index 8a4761a..6b0d1f2a 100644 --- a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-02-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-02-expected.txt
@@ -1,7 +1,5 @@ This test verifies that resources served with a mime type of 'application/json' is not rendered as HTML. It passes if no "FAIL: ..." alert is present, and if the textual content of the frame is visible below. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-03-expected.txt b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-03-expected.txt index b8b6bff0..9b6742d 100644 --- a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-03-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-03-expected.txt
@@ -1,7 +1,5 @@ This test verifies that resources served with a mime type of 'application/javascript' is not rendered as HTML. It passes if no "FAIL: ..." alert is present, and if the textual content of the frame is visible below. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-04-expected.txt b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-04-expected.txt index 6649d59..b821f488 100644 --- a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-04-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-04-expected.txt
@@ -1,7 +1,5 @@ This test verifies that resources served with a mime type of 'application/rss+xml' is not rendered as HTML. It passes if no "FAIL: ..." alert is present, and if the textual content of the frame is visible below. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-05-expected.txt b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-05-expected.txt index b844760..ea8cfca 100644 --- a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-05-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-05-expected.txt
@@ -1,7 +1,5 @@ This test verifies that resources served with a mime type of 'text/' is not rendered as HTML. It passes if no "FAIL: ..." alert is present, and if the textual content of the frame is visible below. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-06-expected.txt b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-06-expected.txt index 2bbea21..5156ba0 100644 --- a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-06-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-06-expected.txt
@@ -1,7 +1,5 @@ This test verifies that resources served with a mime type of 'text/cache-manifest' is not rendered as HTML. It passes if no "FAIL: ..." alert is present, and if the textual content of the frame is visible below. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-07-expected.txt b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-07-expected.txt index e6abf45b1..cf0ece9 100644 --- a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-07-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-07-expected.txt
@@ -1,7 +1,5 @@ This test verifies that resources served with a mime type of 'text/css' is not rendered as HTML. It passes if no "FAIL: ..." alert is present, and if the textual content of the frame is visible below. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-08-expected.txt b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-08-expected.txt index 96a6015..642053b 100644 --- a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-08-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-08-expected.txt
@@ -1,7 +1,5 @@ This test verifies that resources served with a mime type of 'text/ecmascript' is not rendered as HTML. It passes if no "FAIL: ..." alert is present, and if the textual content of the frame is visible below. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-09-expected.txt b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-09-expected.txt index eb83ca9..fc9a0687 100644 --- a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-09-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-09-expected.txt
@@ -1,7 +1,5 @@ This test verifies that resources served with a mime type of 'text/javascript' is not rendered as HTML. It passes if no "FAIL: ..." alert is present, and if the textual content of the frame is visible below. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-10-expected.txt b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-10-expected.txt index 081cb5c..4ca51bf 100644 --- a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-10-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-10-expected.txt
@@ -1,7 +1,5 @@ This test verifies that resources served with a mime type of 'text/javascript1.1' is not rendered as HTML. It passes if no "FAIL: ..." alert is present, and if the textual content of the frame is visible below. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-11-expected.txt b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-11-expected.txt index 4e844fb..e1b068ad 100644 --- a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-11-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-11-expected.txt
@@ -1,7 +1,5 @@ This test verifies that resources served with a mime type of 'text/javascript1.2' is not rendered as HTML. It passes if no "FAIL: ..." alert is present, and if the textual content of the frame is visible below. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-12-expected.txt b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-12-expected.txt index 92e1fdc2..537af2c 100644 --- a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-12-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-12-expected.txt
@@ -1,7 +1,5 @@ This test verifies that resources served with a mime type of 'text/javascript1.3' is not rendered as HTML. It passes if no "FAIL: ..." alert is present, and if the textual content of the frame is visible below. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-13-expected.txt b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-13-expected.txt index 72163b0..bd217ee 100644 --- a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-13-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-13-expected.txt
@@ -1,7 +1,5 @@ This test verifies that resources served with a mime type of 'text/jscript' is not rendered as HTML. It passes if no "FAIL: ..." alert is present, and if the textual content of the frame is visible below. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-14-expected.txt b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-14-expected.txt index 09f4506..0149c8a 100644 --- a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-14-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-14-expected.txt
@@ -1,7 +1,5 @@ This test verifies that resources served with a mime type of 'text/livescript' is not rendered as HTML. It passes if no "FAIL: ..." alert is present, and if the textual content of the frame is visible below. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-15-expected.txt b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-15-expected.txt index ca577d35..eefa338 100644 --- a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-15-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-15-expected.txt
@@ -1,7 +1,5 @@ This test verifies that resources served with a mime type of 'text/plain' is not rendered as HTML. It passes if no "FAIL: ..." alert is present, and if the textual content of the frame is visible below. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-16-expected.txt b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-16-expected.txt index 151f75b..90aaa4fc 100644 --- a/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-16-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mime-type-execute-as-html-16-expected.txt
@@ -1,7 +1,5 @@ This test verifies that resources served with a mime type of 'application/x-foo+json' is not rendered as HTML. It passes if no "FAIL: ..." alert is present, and if the textual content of the frame is visible below. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/active-subresource-in-iframe-blocked.https-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/active-subresource-in-iframe-blocked.https-expected.txt index 81f2fb68..c53814e3a 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/active-subresource-in-iframe-blocked.https-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/active-subresource-in-iframe-blocked.https-expected.txt
@@ -1,5 +1,2 @@ -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/active-subresource-in-iframe-blocked.https.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css.html' over broken HTTPS. CONSOLE ERROR: line 4: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/active-subresource-in-iframe-blocked.https.html' was loaded over HTTPS, but requested an insecure stylesheet 'http://example.test:8080/security/mixedContent/resources/style.css'. This request has been blocked; the content must be served over HTTPS. This test passes if the active subresource in the frame below is blocked. - -
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/blob-url-in-iframe-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/blob-url-in-iframe-expected.txt index f2f38d0..0b93eee 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/blob-url-in-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/blob-url-in-iframe-expected.txt
@@ -1,4 +1,3 @@ - This tests that blob URLs created in a secure context are treated as secure origins. This test passes if the iframe renders PASS correctly, and no console warning appears. --------
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/data-url-script-in-iframe-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/data-url-script-in-iframe-expected.txt index 35222a3..bfab9f7 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/data-url-script-in-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/data-url-script-in-iframe-expected.txt
@@ -1,3 +1 @@ This test loads a secure iframe that loads a data URL script. We should *not* trigger a mixed content callback because the data URL cannot be corrupted by an active network attacker. - -
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/empty-url-plugin-in-frame-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/empty-url-plugin-in-frame-expected.txt index 33b28a73..d3e5458 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/empty-url-plugin-in-frame-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/empty-url-plugin-in-frame-expected.txt
@@ -1,3 +1 @@ This test loads a secure iframe that loads a plugin without a URL. We should *not* get a mixed content callback because the plugin cannot be controlled by an active network attacker. - -
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/filesystem-url-in-iframe-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/filesystem-url-in-iframe-expected.txt index c604da8..4d56c41 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/filesystem-url-in-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/filesystem-url-in-iframe-expected.txt
@@ -1,5 +1,4 @@ ALERT: PASS (1/2): File written - This tests that filesystem URLs created in a secure context are treated as secure origins. This test passes if the iframe renders PASS correctly, and no console warning appears. --------
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-image-with-reload-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-image-with-reload-expected.txt index 09aa8621..607bd51 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-image-with-reload-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-image-with-reload-expected.txt
@@ -1,9 +1,5 @@ -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-subframe-and-reload.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css-image.html' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css-image.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/fetch-insecure-css-image.css' over broken HTTPS. CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-subframe-and-reload.html' was loaded over HTTPS, but requested an insecure image 'http://example.test:8080/security/resources/compass.jpg'. This content should also be served over HTTPS. CONSOLE MESSAGE: line 12: Reloading... -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-subframe-and-reload.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css-image.html' over broken HTTPS. -CONSOLE ERROR: line 2: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css-image.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/fetch-insecure-css-image.css' over broken HTTPS. CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-subframe-and-reload.html' was loaded over HTTPS, but requested an insecure image 'http://example.test:8080/security/resources/compass.jpg'. This content should also be served over HTTPS. CONSOLE MESSAGE: line 17: Second load finished. This test opens a window that loads a frame with a subframe which contains insecure css image. The subframe is refreshed after it loads. We should trigger a mixed content callback twice despite the fact that on a second load of the subframe a css cache might be used to fetch an image.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-in-iframe-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-in-iframe-expected.txt index 6e4ea32..4d4c6c9 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-in-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-in-iframe-expected.txt
@@ -1,4 +1,2 @@ CONSOLE WARNING: line 4: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css.html' was loaded over HTTPS, but requested an insecure stylesheet 'http://example.test:8080/security/mixedContent/resources/style.css'. This content should also be served over HTTPS. This test loads a secure iframe that loads an insecure style sheet. We should trigger a mixed content callback because an active network attacker can use CSS3 to breach the confidentiality of the HTTPS security origin. - -
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-resources-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-resources-expected.txt index 6b333e7..523fd49 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-resources-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-css-resources-expected.txt
@@ -1,4 +1,3 @@ -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css-resources.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/fetch-insecure-css-resources.css' over broken HTTPS. CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css-resources.html' was loaded over HTTPS, but requested an insecure font 'http://example.test:8080/css/resources/cors-ahem.php'. This content should also be served over HTTPS. CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-css-resources.html' was loaded over HTTPS, but requested an insecure image 'http://example.test:8080/resources/square20.png'. This content should also be served over HTTPS. This test opens a window that loads a style sheet which fetches an insecure background image and an insecure web font. We should trigger a mixed content callback because the main frame in the window is HTTPS but is running insecure content.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-fetch-on-dedicated-worker-allowed.https-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-fetch-on-dedicated-worker-allowed.https-expected.txt index 47c2dc0d..ff75b78d 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-fetch-on-dedicated-worker-allowed.https-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-fetch-on-dedicated-worker-allowed.https-expected.txt
@@ -1,6 +1,3 @@ -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-fetch-on-dedicated-worker-allowed.https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharness.js' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-fetch-on-dedicated-worker-allowed.https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharnessreport.js' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-fetch-on-dedicated-worker-allowed.https.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/insecure-fetch-in-dedicated-worker.js' over broken HTTPS. CONSOLE WARNING: line 1: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/insecure-fetch-in-dedicated-worker.js' was loaded over HTTPS, but requested an insecure resource 'http://example.test:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=*'. This content should also be served over HTTPS. This is a testharness.js-based test. PASS Insecure resource loads inside Worker when 'AllowRunningInsecureContent' is set.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-fetch-on-dedicated-worker-blocked.https-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-fetch-on-dedicated-worker-blocked.https-expected.txt index 717c6c3..f9e4011e 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-fetch-on-dedicated-worker-blocked.https-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-fetch-on-dedicated-worker-blocked.https-expected.txt
@@ -1,6 +1,3 @@ -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-fetch-on-dedicated-worker-blocked.https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharness.js' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-fetch-on-dedicated-worker-blocked.https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharnessreport.js' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-fetch-on-dedicated-worker-blocked.https.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/insecure-fetch-in-dedicated-worker.js' over broken HTTPS. CONSOLE ERROR: line 1: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/insecure-fetch-in-dedicated-worker.js' was loaded over HTTPS, but requested an insecure resource 'http://example.test:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=*'. This request has been blocked; the content must be served over HTTPS. This is a testharness.js-based test. PASS Insecure resource loads inside Worker failes when 'AllowRunningInsecureContent' is not set.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-iframe-in-iframe-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-iframe-in-iframe-expected.txt index 6d9e2fa..4048afa 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-iframe-in-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-iframe-in-iframe-expected.txt
@@ -1,4 +1,2 @@ CONSOLE WARNING: line 8: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-frame.html' was loaded over HTTPS, but requested an insecure resource 'http://example.test:8080/security/mixedContent/resources/boring.html'. This content should also be served over HTTPS. This test loads a secure iframe that loads an insecure iframe. We should get a mixed content callback becase the child frame is HTTPS. - -
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-iframe-with-hsts.https-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-iframe-with-hsts.https-expected.txt index c70f6d2..121dc87 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-iframe-with-hsts.https-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-iframe-with-hsts.https-expected.txt
@@ -1,10 +1,7 @@ -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-iframe-with-hsts.https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharness.js' over broken HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-iframe-with-hsts.https.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/testharnessreport.js' over broken HTTPS. main frame - didReceiveTitle: main frame - didFinishDocumentLoadForFrame main frame - didHandleOnloadEventsForFrame main frame - didFinishLoadForFrame -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-iframe-with-hsts.https.html' attempted to load subresource at 'https://hsts-example.test:8443/security/resources/hsts.php?as-fetch' over broken HTTPS. frame "<!--framePath //<!--frame0-->-->" - didReceiveTitle: frame "<!--framePath //<!--frame0-->-->" - didStartProvisionalLoadForFrame CONSOLE ERROR: line 18: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/insecure-iframe-with-hsts.https.html' was loaded over HTTPS, but requested an insecure resource 'http://hsts-example.test:8443/security/resources/hsts.php'. This request has been blocked; the content must be served over HTTPS.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-image-in-iframe-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-image-in-iframe-expected.txt index a16488cd..0ec4e93 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-image-in-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-image-in-iframe-expected.txt
@@ -1,4 +1,2 @@ CONSOLE WARNING: line 9: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-image.html' was loaded over HTTPS, but requested an insecure image 'http://example.test:8080/security/resources/compass.jpg'. This content should also be served over HTTPS. This test loads a secure iframe that loads an insecure image. We should get a mixed content callback becase the frame is HTTPS and the image is not. - -
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-plugin-in-iframe-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-plugin-in-iframe-expected.txt index 5e903ec..a5199a0 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-plugin-in-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-plugin-in-iframe-expected.txt
@@ -1,5 +1,3 @@ CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-plugin.html' was loaded over HTTPS, but requested an insecure plugin resource 'http://example.test:8000/security/mixedContent/resources/dummy.swf'. This content should also be served over HTTPS. CONSOLE MESSAGE: Blink Test Plugin: initializing This test loads a secure iframe that loads an insecure plugin. We should get a mixed content callback because the insecure plugin can script the secure origin. - -
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-script-in-iframe-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-script-in-iframe-expected.txt index 29022f1..80494ea 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-script-in-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/insecure-script-in-iframe-expected.txt
@@ -1,4 +1,2 @@ CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-script.html' was loaded over HTTPS, but requested an insecure script 'http://example.test:8080/security/mixedContent/resources/script.js'. This content should also be served over HTTPS. This test loads a secure iframe that loads an insecure script. We should trigger a mixed content callback even though the main frame is HTTP because the HTTPS frame's origin is contaminated with an insecure script. - -
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/nonwebby-scheme-in-iframe-allowed.https-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/nonwebby-scheme-in-iframe-allowed.https-expected.txt index 6107019..9c3a6056 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/nonwebby-scheme-in-iframe-allowed.https-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/nonwebby-scheme-in-iframe-allowed.https-expected.txt
@@ -1,8 +1,6 @@ CONSOLE WARNING: line 16: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/nonwebby-scheme-in-iframe-allowed.https.html' was loaded over HTTPS, but requested an insecure resource 'nonwebbyscheme://this-will-fail-but-no-mixed-content-error-should-appear'. This content should also be served over HTTPS. This tests that non-webby URLs are not blocked as mixed content. The test passes if a mixed content warning is displayed and the load proceeds. The test fails if a mixed content error is displayed, and the load is blocked. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-http-to-https-iframe-in-main-frame-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-http-to-https-iframe-in-main-frame-expected.txt index e48e146..e10c3a30 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-http-to-https-iframe-in-main-frame-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-http-to-https-iframe-in-main-frame-expected.txt
@@ -1,3 +1,2 @@ CONSOLE WARNING: line 8: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-http-to-https-frame.html' was loaded over HTTPS, but requested an insecure resource 'http://example.test:8080/security/resources/redir.php?url=https://127.0.0.1:8443/security/mixedContent/resources/boring.html'. This content should also be served over HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-http-to-https-frame.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/boring.html' over broken HTTPS. This test opens a window that loads an insecure iframe (via a tricky redirect). We should trigger a mixed content callback because the main frame in the window is HTTPS but is running content that can be controlled by an active network attacker.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-http-to-https-script-in-iframe-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-http-to-https-script-in-iframe-expected.txt index b91b259..555131b 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-http-to-https-script-in-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-http-to-https-script-in-iframe-expected.txt
@@ -1,5 +1,2 @@ CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-http-to-https-script.html' was loaded over HTTPS, but requested an insecure script 'http://example.test:8080/security/resources/redir.php?url=https://127.0.0.1:8443/security/mixedContent/resources/script.js'. This content should also be served over HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-http-to-https-script.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/script.js' over broken HTTPS. This test loads a secure iframe that loads an insecure script (but with a tricky redirect). We should trigger a mixed content callback because an active network attacker could have redirected the script load to https://attacker.com. - -
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-https-to-http-iframe-in-main-frame-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-https-to-http-iframe-in-main-frame-expected.txt index e48e146..e10c3a30 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-https-to-http-iframe-in-main-frame-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-https-to-http-iframe-in-main-frame-expected.txt
@@ -1,3 +1,2 @@ CONSOLE WARNING: line 8: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-http-to-https-frame.html' was loaded over HTTPS, but requested an insecure resource 'http://example.test:8080/security/resources/redir.php?url=https://127.0.0.1:8443/security/mixedContent/resources/boring.html'. This content should also be served over HTTPS. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-http-to-https-frame.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/boring.html' over broken HTTPS. This test opens a window that loads an insecure iframe (via a tricky redirect). We should trigger a mixed content callback because the main frame in the window is HTTPS but is running content that can be controlled by an active network attacker.
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-https-to-http-script-in-iframe-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-https-to-http-script-in-iframe-expected.txt index 9724502..4e16f98 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-https-to-http-script-in-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/redirect-https-to-http-script-in-iframe-expected.txt
@@ -1,4 +1,2 @@ CONSOLE WARNING: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-redirect-https-to-http-script.html' was loaded over HTTPS, but requested an insecure script 'http://example.test:8080/security/mixedContent/resources/script.js'. This content should also be served over HTTPS. This test loads a secure iframe that loads an insecure script (but with a tricky redirect). We should trigger a mixed content callback because an active network attacker can end up controling the script. - -
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/strict-mode-image-in-frame-blocked.https-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/strict-mode-image-in-frame-blocked.https-expected.txt index a6feeff..e317165a 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/strict-mode-image-in-frame-blocked.https-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/strict-mode-image-in-frame-blocked.https-expected.txt
@@ -1,5 +1,2 @@ -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/strict-mode-image-in-frame-blocked.https.html' attempted to load subresource at 'https://127.0.0.1:8443/security/mixedContent/resources/frame-with-insecure-image.html' over broken HTTPS. CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/strict-mode-image-in-frame-blocked.https.html' was loaded over HTTPS, but requested an insecure image 'http://example.test:8080/security/resources/compass.jpg'. This request has been blocked; the content must be served over HTTPS. This test passes if the image in the frame below is treated as blockable content. - -
diff --git a/third_party/blink/web_tests/http/tests/security/mixedContent/strict-mode-via-pref-image-blocked.https-expected.txt b/third_party/blink/web_tests/http/tests/security/mixedContent/strict-mode-via-pref-image-blocked.https-expected.txt index c0e6df2..ce77c77 100644 --- a/third_party/blink/web_tests/http/tests/security/mixedContent/strict-mode-via-pref-image-blocked.https-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/mixedContent/strict-mode-via-pref-image-blocked.https-expected.txt
@@ -1,4 +1,2 @@ CONSOLE ERROR: line 13: Mixed Content: The page at 'https://127.0.0.1:8443/security/mixedContent/strict-mode-via-pref-image-blocked.https.html' was loaded over HTTPS, but requested an insecure image 'http://example.test:8080/security/resources/compass.jpg'. This request has been blocked; the content must be served over HTTPS. This test passes if the image below is treated as blockable content. - -
diff --git a/third_party/blink/web_tests/http/tests/security/no-popup-from-sandbox-expected.txt b/third_party/blink/web_tests/http/tests/security/no-popup-from-sandbox-expected.txt index b58cce0..01dd3cb 100644 --- a/third_party/blink/web_tests/http/tests/security/no-popup-from-sandbox-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/no-popup-from-sandbox-expected.txt
@@ -1,5 +1,3 @@ CONSOLE ERROR: line 3: Blocked opening 'about:blank' in a new window because the request was made in a sandboxed frame whose 'allow-popups' permission is not set. CONSOLE MESSAGE: line 4: PASS To run this test outside of DumpRenderTree, please disable your popup blocker! - -
diff --git a/third_party/blink/web_tests/http/tests/security/no-popup-from-sandbox-top-expected.txt b/third_party/blink/web_tests/http/tests/security/no-popup-from-sandbox-top-expected.txt index 046e9c17..8c8b26a 100644 --- a/third_party/blink/web_tests/http/tests/security/no-popup-from-sandbox-top-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/no-popup-from-sandbox-top-expected.txt
@@ -2,5 +2,3 @@ CONSOLE MESSAGE: line 4: PASS To run this test outside of DumpRenderTree, please disable your popup blocker! - -
diff --git a/third_party/blink/web_tests/http/tests/security/object-literals-expected.txt b/third_party/blink/web_tests/http/tests/security/object-literals-expected.txt index 2fbb00b..4b77d23 100644 --- a/third_party/blink/web_tests/http/tests/security/object-literals-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/object-literals-expected.txt
@@ -1,2 +1 @@ - PASS: Called the correct method.
diff --git a/third_party/blink/web_tests/http/tests/security/popup-allowed-by-sandbox-can-navigate-expected.txt b/third_party/blink/web_tests/http/tests/security/popup-allowed-by-sandbox-can-navigate-expected.txt index c1b12c5..b249b53 100644 --- a/third_party/blink/web_tests/http/tests/security/popup-allowed-by-sandbox-can-navigate-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/popup-allowed-by-sandbox-can-navigate-expected.txt
@@ -1,5 +1,3 @@ To run this test outside of DumpRenderTree, please disable your popup blocker! This test passes if it doesn't hang. - -
diff --git a/third_party/blink/web_tests/http/tests/security/popup-allowed-by-sandbox-is-sandboxed-control-expected.txt b/third_party/blink/web_tests/http/tests/security/popup-allowed-by-sandbox-is-sandboxed-control-expected.txt index 59a7c8d..122b036 100644 --- a/third_party/blink/web_tests/http/tests/security/popup-allowed-by-sandbox-is-sandboxed-control-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/popup-allowed-by-sandbox-is-sandboxed-control-expected.txt
@@ -2,5 +2,3 @@ To run this test outside of DumpRenderTree, please disable your popup blocker! If you change this test, please be sure to change popup-allowed-by-sandbox-is-sandboxed.html as well! - -
diff --git a/third_party/blink/web_tests/http/tests/security/popup-allowed-by-sandbox-is-sandboxed-expected.txt b/third_party/blink/web_tests/http/tests/security/popup-allowed-by-sandbox-is-sandboxed-expected.txt index 1451fb1b..82a1ddd 100644 --- a/third_party/blink/web_tests/http/tests/security/popup-allowed-by-sandbox-is-sandboxed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/popup-allowed-by-sandbox-is-sandboxed-expected.txt
@@ -4,5 +4,3 @@ If you change this test, please be sure to change popup-allowed-by-sandbox-is-sandboxed-control.html as well! This test passes if it doesn't alert FAIL. - -
diff --git a/third_party/blink/web_tests/http/tests/security/popup-allowed-by-sandbox-when-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/popup-allowed-by-sandbox-when-allowed-expected.txt index d31b4d9f..4a36fefe 100644 --- a/third_party/blink/web_tests/http/tests/security/popup-allowed-by-sandbox-when-allowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/popup-allowed-by-sandbox-when-allowed-expected.txt
@@ -1,4 +1,2 @@ CONSOLE MESSAGE: line 5: PASS To run this test outside of DumpRenderTree, please disable your popup blocker! - -
diff --git a/third_party/blink/web_tests/http/tests/security/postMessage/data-url-sends-null-origin-expected.txt b/third_party/blink/web_tests/http/tests/security/postMessage/data-url-sends-null-origin-expected.txt index 2d981a2..bbb117e 100644 --- a/third_party/blink/web_tests/http/tests/security/postMessage/data-url-sends-null-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/postMessage/data-url-sends-null-origin-expected.txt
@@ -1,3 +1,2 @@ window.location.href = http://127.0.0.1:8000/security/postMessage/data-url-sends-null-origin.html - Received message: data="Hello from child" origin="null"
diff --git a/third_party/blink/web_tests/http/tests/security/postMessage/delivery-order-expected.txt b/third_party/blink/web_tests/http/tests/security/postMessage/delivery-order-expected.txt index bb2b7b9..cae52e49 100644 --- a/third_party/blink/web_tests/http/tests/security/postMessage/delivery-order-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/postMessage/delivery-order-expected.txt
@@ -1,5 +1,4 @@ window.location.href = http://127.0.0.1:8000/security/postMessage/delivery-order.html - waiting... Before calling postMessage After calling postMessage
diff --git a/third_party/blink/web_tests/http/tests/security/postMessage/invalid-origin-throws-exception-expected.txt b/third_party/blink/web_tests/http/tests/security/postMessage/invalid-origin-throws-exception-expected.txt index e868067e..d607c71 100644 --- a/third_party/blink/web_tests/http/tests/security/postMessage/invalid-origin-throws-exception-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/postMessage/invalid-origin-throws-exception-expected.txt
@@ -7,4 +7,3 @@ Encountered exception "SyntaxError: Failed to execute 'postMessage' on 'Window': Invalid target origin 'asdf:' in a call to 'postMessage'." while posting message to 'asdf:'. Encountered exception "SyntaxError: Failed to execute 'postMessage' on 'Window': Invalid target origin 'http:' in a call to 'postMessage'." while posting message to 'http:'. Received message: data="Received message: data="done" origin="http://127.0.0.1:8000"" origin="http://localhost:8000" -
diff --git a/third_party/blink/web_tests/http/tests/security/postMessage/javascript-page-still-sends-origin-expected.txt b/third_party/blink/web_tests/http/tests/security/postMessage/javascript-page-still-sends-origin-expected.txt index 7d871e1..1ce448d 100644 --- a/third_party/blink/web_tests/http/tests/security/postMessage/javascript-page-still-sends-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/postMessage/javascript-page-still-sends-origin-expected.txt
@@ -1,3 +1,2 @@ window.location.href = http://127.0.0.1:8000/security/postMessage/javascript-page-still-sends-origin.html - Received message: data="Hello from child" origin="http://localhost:8000"
diff --git a/third_party/blink/web_tests/http/tests/security/postMessage/origin-unaffected-by-base-tag-expected.txt b/third_party/blink/web_tests/http/tests/security/postMessage/origin-unaffected-by-base-tag-expected.txt index 64e357b..4a2b608 100644 --- a/third_party/blink/web_tests/http/tests/security/postMessage/origin-unaffected-by-base-tag-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/postMessage/origin-unaffected-by-base-tag-expected.txt
@@ -1,5 +1,4 @@ window.location.href = http://127.0.0.1:8000/security/postMessage/origin-unaffected-by-base-tag.html - waiting... Received message: data="Received message: data="Message from parent" origin="http://127.0.0.1:8000"" origin="http://localhost:8000" Received message: data="Received message: data="done" origin="http://127.0.0.1:8000"" origin="http://localhost:8000"
diff --git a/third_party/blink/web_tests/http/tests/security/postMessage/target-origin-expected.txt b/third_party/blink/web_tests/http/tests/security/postMessage/target-origin-expected.txt index c096fc7..d0e65a3 100644 --- a/third_party/blink/web_tests/http/tests/security/postMessage/target-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/postMessage/target-origin-expected.txt
@@ -1,5 +1,4 @@ window.location.href = http://127.0.0.1:8000/security/postMessage/target-origin.html - waiting... Error sending message to //. SyntaxError: Failed to execute 'postMessage' on 'Window': Invalid target origin '//' in a call to 'postMessage'. Received message: data="Received message: data="Trying origin=*" origin="http://127.0.0.1:8000"" origin="http://localhost:8000"
diff --git a/third_party/blink/web_tests/http/tests/security/postMessage/target-origin-same-site-expected.txt b/third_party/blink/web_tests/http/tests/security/postMessage/target-origin-same-site-expected.txt index e1da21b4d..a88f1d6 100644 --- a/third_party/blink/web_tests/http/tests/security/postMessage/target-origin-same-site-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/postMessage/target-origin-same-site-expected.txt
@@ -4,7 +4,6 @@ CONSOLE ERROR: line 16: Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://127.0.0.1:8000') does not match the recipient window's origin ('http://127.0.0.1:8000'). CONSOLE ERROR: line 16: Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('http://www.example.com') does not match the recipient window's origin ('http://127.0.0.1:8000'). window.location.href = http://127.0.0.1:8000/security/postMessage/target-origin-same-site.html - waiting... Error sending message to asdf:. SyntaxError: Failed to execute 'postMessage' on 'Window': Invalid target origin 'asdf:' in a call to 'postMessage'. Error sending message to . SyntaxError: Failed to execute 'postMessage' on 'Window': Invalid target origin '' in a call to 'postMessage'.
diff --git a/third_party/blink/web_tests/http/tests/security/preload-script-crossorigin-fails-cross-origin-expected.txt b/third_party/blink/web_tests/http/tests/security/preload-script-crossorigin-fails-cross-origin-expected.txt index fc0a447..4650e5c 100644 --- a/third_party/blink/web_tests/http/tests/security/preload-script-crossorigin-fails-cross-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/preload-script-crossorigin-fails-cross-origin-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS Did preload. PASS Script error. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/security/protocol-compare-case-insensitive-expected.txt b/third_party/blink/web_tests/http/tests/security/protocol-compare-case-insensitive-expected.txt index 3dc5ec1d7..10ab47b 100644 --- a/third_party/blink/web_tests/http/tests/security/protocol-compare-case-insensitive-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/protocol-compare-case-insensitive-expected.txt
@@ -1,4 +1,3 @@ - PASS: Protocol name compare is case insensitive!
diff --git a/third_party/blink/web_tests/http/tests/security/redirect-BLOCKED-to-localURL-expected.txt b/third_party/blink/web_tests/http/tests/security/redirect-BLOCKED-to-localURL-expected.txt index 8d435c7..459ec75 100644 --- a/third_party/blink/web_tests/http/tests/security/redirect-BLOCKED-to-localURL-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/redirect-BLOCKED-to-localURL-expected.txt
@@ -1,2 +1,4 @@ + + This attempts to open a redirect link to a file URL, which should be blocked.
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-on-client-redirect-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-on-client-redirect-expected.txt index fb5e0f07b4..c2217e8 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-on-client-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-on-client-redirect-expected.txt
@@ -1,2 +1 @@ -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/resources/referrer-on-client-redirect.html' attempted to load subresource at 'https://127.0.0.1:8443/security/resources/referrer-on-client-redirect.html?frame' over broken HTTPS. PASS: Referrer is empty
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-always-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-always-expected.txt index 87ea258..855a1e57 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-always-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-always-expected.txt
@@ -1,7 +1,5 @@ This test checks the always referrer policy when navigating from an insecure URL to another insecure URL. The test passes if the printed referrer is http://127.0.0.1:8000/security/resources/referrer-policy-start.html?always - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-attribute-img-no-referrer-when-downgrade-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-attribute-img-no-referrer-when-downgrade-expected.txt deleted file mode 100644 index 9b2a185..0000000 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-attribute-img-no-referrer-when-downgrade-expected.txt +++ /dev/null
@@ -1 +0,0 @@ -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/referrer-policy-attribute-img-no-referrer-when-downgrade.html' attempted to load subresource at 'https://127.0.0.1:8443/resources/get-host-info.js' over broken HTTPS.
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-default-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-default-expected.txt index 1124260..32e9eca9 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-default-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-default-expected.txt
@@ -1,7 +1,5 @@ This test checks the default referrer policy when navigating from an insecure URL to another insecure URL. The test passes if the printed referrer is http://127.0.0.1:8000/security/resources/referrer-policy-start.html?default - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-https-always-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-https-always-expected.txt index 5e51de1..f8f0d55b 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-https-always-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-https-always-expected.txt
@@ -1,7 +1,5 @@ This test checks the always referrer policy when navigating from a secure URL to an insecure URL. The test passes if the printed referrer is https://127.0.0.1:8443/security/resources/referrer-policy-start.html?always - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-https-default-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-https-default-expected.txt index e476c26..8eec5ea5 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-https-default-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-https-default-expected.txt
@@ -1,7 +1,5 @@ This test checks the default referrer policy when navigating from a secure URL to an insecure URL. The test passes if the printed referrer is empty. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-https-never-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-https-never-expected.txt index 6c12ec92..6821ce8 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-https-never-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-https-never-expected.txt
@@ -1,7 +1,5 @@ This test checks the never referrer policy when navigating from a secure URL to an insecure URL. The test passes if the printed referrer is empty. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-https-no-referrer-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-https-no-referrer-expected.txt index e476c26..8eec5ea5 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-https-no-referrer-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-https-no-referrer-expected.txt
@@ -1,7 +1,5 @@ This test checks the default referrer policy when navigating from a secure URL to an insecure URL. The test passes if the printed referrer is empty. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-https-no-referrer-when-downgrade-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-https-no-referrer-when-downgrade-expected.txt index e476c26..8eec5ea5 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-https-no-referrer-when-downgrade-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-https-no-referrer-when-downgrade-expected.txt
@@ -1,7 +1,5 @@ This test checks the default referrer policy when navigating from a secure URL to an insecure URL. The test passes if the printed referrer is empty. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-https-origin-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-https-origin-expected.txt index c0f9b81f..2574e32 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-https-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-https-origin-expected.txt
@@ -1,7 +1,5 @@ This test checks the origin referrer policy when navigating from a secure URL to an insecure URL. The test passes if the printed referrer is https://127.0.0.1:8443 - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-https-origin-when-crossorigin-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-https-origin-when-crossorigin-expected.txt index c0f9b81f..2574e32 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-https-origin-when-crossorigin-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-https-origin-when-crossorigin-expected.txt
@@ -1,7 +1,5 @@ This test checks the origin referrer policy when navigating from a secure URL to an insecure URL. The test passes if the printed referrer is https://127.0.0.1:8443 - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-https-unsafe-url-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-https-unsafe-url-expected.txt index e62d48c..ffe30b36 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-https-unsafe-url-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-https-unsafe-url-expected.txt
@@ -1,7 +1,5 @@ This test checks the always referrer policy when navigating from a secure URL to an insecure URL. The test passes if the printed referrer is https://127.0.0.1:8443/security/resources/referrer-policy-start.html?unsafe-url - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-invalid-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-invalid-expected.txt index 75cd596..799f00d8 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-invalid-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-invalid-expected.txt
@@ -1,8 +1,6 @@ CONSOLE ERROR: line 8: Failed to set referrer policy: The value 'invalid' is not one of 'always', 'default', 'never', 'origin-when-crossorigin', 'no-referrer', 'no-referrer-when-downgrade', 'origin', 'origin-when-cross-origin', 'same-origin', 'strict-origin', 'strict-origin-when-cross-origin', or 'unsafe-url'. The referrer policy has been left unchanged. This test checks that an invalid referrer policy is ignored when navigating from an insecure URL to another insecure URL. The test passes if the printed referrer is the full URL. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-never-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-never-expected.txt index 2f04f7a..865f950f 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-never-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-never-expected.txt
@@ -1,7 +1,5 @@ This test checks the never referrer policy when navigating from an insecure URL to another insecure URL. The test passes if the printed referrer is empty. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-no-referrer-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-no-referrer-expected.txt index 2f04f7a..865f950f 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-no-referrer-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-no-referrer-expected.txt
@@ -1,7 +1,5 @@ This test checks the never referrer policy when navigating from an insecure URL to another insecure URL. The test passes if the printed referrer is empty. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-no-referrer-when-downgrade-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-no-referrer-when-downgrade-expected.txt index 46d7d69..c492ae5 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-no-referrer-when-downgrade-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-no-referrer-when-downgrade-expected.txt
@@ -1,7 +1,5 @@ This test checks the default referrer policy when navigating from an insecure URL to another insecure URL. The test passes if the printed referrer is http://127.0.0.1:8000/security/resources/referrer-policy-start.html?no-referrer-when-downgrade - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-origin-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-origin-expected.txt index bff723c..84bbd46 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-origin-expected.txt
@@ -1,7 +1,5 @@ This test checks the origin referrer policy when navigating from an insecure URL to another insecure URL. The test passes if the printed referrer is http://127.0.0.1:8000 - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-origin-when-crossorigin-is-crossorigin-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-origin-when-crossorigin-is-crossorigin-expected.txt index b6fed73..8f02ee8 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-origin-when-crossorigin-is-crossorigin-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-origin-when-crossorigin-is-crossorigin-expected.txt
@@ -1,7 +1,5 @@ This test checks the origin referrer policy when navigating from an insecure URL to a cross-origin insecure URL. The test passes if the printed referrer is http://127.0.0.1:8000 - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-origin-when-crossorigin-is-sameorigin-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-origin-when-crossorigin-is-sameorigin-expected.txt index f9886fb..a5ec91f 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-origin-when-crossorigin-is-sameorigin-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-origin-when-crossorigin-is-sameorigin-expected.txt
@@ -1,7 +1,5 @@ This test checks the origin referrer policy when navigating from an insecure URL to a same-origin insecure URL. The test passes if the printed referrer is http://127.0.0.1:8000/security/referrer-policy-origin-when-crossorigin-is-sameorigin.html - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-redirect-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-redirect-expected.txt index 3d1c975..d334f9c7 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-redirect-expected.txt
@@ -1,7 +1,5 @@ This test checks the referrer policy is obeyed along the redirect chain. The test passes if the referrer is http://127.0.0.1:8000 - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-redirect-link-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-redirect-link-expected.txt index 9a66f7c..b43fd84d 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-redirect-link-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-redirect-link-expected.txt
@@ -1,7 +1,5 @@ This test checks the referrer policy is obeyed along the redirect chain. The test passes if the referrer is https://127.0.0.1:8443 - - -------- Frame: 'iframe' --------
diff --git a/third_party/blink/web_tests/http/tests/security/referrer-policy-rel-noreferrer-expected.txt b/third_party/blink/web_tests/http/tests/security/referrer-policy-rel-noreferrer-expected.txt index 1920c1a..d1b606a1 100644 --- a/third_party/blink/web_tests/http/tests/security/referrer-policy-rel-noreferrer-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/referrer-policy-rel-noreferrer-expected.txt
@@ -1,7 +1,5 @@ This test navigates a frame by clicking on a link with rel=noreferrer. It passes, if the referrer is empty, even though the referrer policy is set to always. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/sandbox-inherit-to-initial-document-2-expected.txt b/third_party/blink/web_tests/http/tests/security/sandbox-inherit-to-initial-document-2-expected.txt index 62425221..a83e7b1c 100644 --- a/third_party/blink/web_tests/http/tests/security/sandbox-inherit-to-initial-document-2-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/sandbox-inherit-to-initial-document-2-expected.txt
@@ -2,4 +2,3 @@ Test how sandbox flags get inherited to initial document in subframe. PASS -
diff --git a/third_party/blink/web_tests/http/tests/security/sandbox-inherit-to-initial-document-expected.txt b/third_party/blink/web_tests/http/tests/security/sandbox-inherit-to-initial-document-expected.txt index 00b2dc5..bfad4fcc 100644 --- a/third_party/blink/web_tests/http/tests/security/sandbox-inherit-to-initial-document-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/sandbox-inherit-to-initial-document-expected.txt
@@ -1,4 +1,3 @@ Test how sandbox flags get inherited to initial document in subframe. PASS -
diff --git a/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-blocks-access-from-parent-expected.txt b/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-blocks-access-from-parent-expected.txt index a8162376..1385920 100644 --- a/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-blocks-access-from-parent-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-blocks-access-from-parent-expected.txt
@@ -1,8 +1,6 @@ ALERT: PASS: Cross-origin access to the Location object threw an exception. Sandboxing a frame puts it into a unique origin by default, which the containing document shouldn't have script access to. This test passes if an exception is thrown upon the access violation. - - -------- Frame: 'testframe' --------
diff --git a/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-document-cookie-expected.txt b/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-document-cookie-expected.txt index ea17cfb..6f17375 100644 --- a/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-document-cookie-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-document-cookie-expected.txt
@@ -1,7 +1,5 @@ This test checks that a SECURITY_ERR exception is raised while accessing document.domain in a sandboxed iframe (without "allow-origin" set). This test will print "PASS" on success. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-form-top-expected.txt b/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-form-top-expected.txt index befb4d7b..de8060f 100644 --- a/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-form-top-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-form-top-expected.txt
@@ -3,5 +3,3 @@ This tests passes if the sandboxed frame cannot navigate the top frame. PASS - -
diff --git a/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-meta-refresh-expected.txt b/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-meta-refresh-expected.txt index 02a71c6c..bb47433a 100644 --- a/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-meta-refresh-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-meta-refresh-expected.txt
@@ -1,8 +1,6 @@ CONSOLE ERROR: line 1: Refused to execute the redirect specified via '<meta http-equiv='refresh' content='...'>'. The document is sandboxed, and the 'allow-scripts' keyword is not set. Sandboxing a frame puts it into a unique origin by default, which the containing document shouldn't have script access to. This test passes if an exception is thrown upon the access violation. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-modify-self-expected.txt b/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-modify-self-expected.txt index afce7ae..caa95ea 100644 --- a/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-modify-self-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-modify-self-expected.txt
@@ -3,8 +3,7 @@ First, an attempt is made to modify the sandbox attribute of the "self" object, referring to the frame's window. This should not have any effect (the attribute is associated with the iframe DOM node, not the window). No warning is expected. Second, an attempt is made to modify the iframe DOM object's sandbox attribute. A warning message (about cross-site scripting) is expected, and the sandbox attribute should remain intact. + This test will print "PASS" on success. PASS - -
diff --git a/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-origin-add-expected.txt b/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-origin-add-expected.txt index 28a4ea8f8..3f8daed 100644 --- a/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-origin-add-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-origin-add-expected.txt
@@ -1,4 +1,3 @@ Test that adding allow-origin after creating an iframe doesn't modify the origin of an existing document, but it doesn modify the origin of the next document. PASS -
diff --git a/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-origin-remove-expected.txt b/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-origin-remove-expected.txt index 0d24637..514cf60 100644 --- a/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-origin-remove-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/sandboxed-iframe-origin-remove-expected.txt
@@ -1,4 +1,3 @@ Test that removing allow-origin after creating an iframe doesn't modify the origin of an existing document, but it doesn modify the origin of the next document. PASS -
diff --git a/third_party/blink/web_tests/http/tests/security/sandboxed-opener-can-close-window-expected.txt b/third_party/blink/web_tests/http/tests/security/sandboxed-opener-can-close-window-expected.txt index 2d8d1cf..a79f225 100644 --- a/third_party/blink/web_tests/http/tests/security/sandboxed-opener-can-close-window-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/sandboxed-opener-can-close-window-expected.txt
@@ -2,8 +2,6 @@ This test passes if it doesn't hang. - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/script-crossorigin-loads-cross-origin-conditional-expected.txt b/third_party/blink/web_tests/http/tests/security/script-crossorigin-loads-cross-origin-conditional-expected.txt index edc4aef..bb21d87 100644 --- a/third_party/blink/web_tests/http/tests/security/script-crossorigin-loads-cross-origin-conditional-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/script-crossorigin-loads-cross-origin-conditional-expected.txt
@@ -1,4 +1,3 @@ Test that script elements that are fetched with CORS enabled and conditionally, pass the expected access controls. PASS: crossorigin script repeatedly and conditionally loaded. -
diff --git a/third_party/blink/web_tests/http/tests/security/script-crossorigin-redirect-anonymous-expected.txt b/third_party/blink/web_tests/http/tests/security/script-crossorigin-redirect-anonymous-expected.txt index a31e7726..cce36a3a 100644 --- a/third_party/blink/web_tests/http/tests/security/script-crossorigin-redirect-anonymous-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/script-crossorigin-redirect-anonymous-expected.txt
@@ -5,9 +5,9 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS/FAIL descriptions are of the form, 'CORS request type': 'redirect CORS type' => 'resource' + PASS: Anonymous request: anonymous => no-CORS script resource. PASS: Anonymous request: anonymous => anonymous-CORS script resource. PASS: Credentialled request: anonymous => credentialled script resource (same origin.)
diff --git a/third_party/blink/web_tests/http/tests/security/script-crossorigin-redirect-credentials-expected.txt b/third_party/blink/web_tests/http/tests/security/script-crossorigin-redirect-credentials-expected.txt index afaa703..0efcdec3 100644 --- a/third_party/blink/web_tests/http/tests/security/script-crossorigin-redirect-credentials-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/script-crossorigin-redirect-credentials-expected.txt
@@ -6,9 +6,9 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS/FAIL descriptions are of the form, 'CORS request type': 'redirect CORS type' => 'resource' + PASS: Anonymous request: credentialled => no-CORS script resource. PASS: Anonymous request: credentialled => anonymous CORS script resource (same origin.) PASS: Anonymous request: credentialled => anonymous CORS script resource (cross origin.)
diff --git a/third_party/blink/web_tests/http/tests/security/script-crossorigin-redirect-no-cors-expected.txt b/third_party/blink/web_tests/http/tests/security/script-crossorigin-redirect-no-cors-expected.txt index 8817333..1868d92a 100644 --- a/third_party/blink/web_tests/http/tests/security/script-crossorigin-redirect-no-cors-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/script-crossorigin-redirect-no-cors-expected.txt
@@ -6,6 +6,7 @@ PASS/FAIL descriptions are of the form, 'CORS request type': 'redirect CORS type' => 'resource' + PASS: Anonymous request: no-CORS => no-CORS script resource. PASS: Anonymous request: no-CORS => anonymous-CORS script resource. PASS: Credentialled request: no-CORS => credential-CORS script resource (same origin.)
diff --git a/third_party/blink/web_tests/http/tests/security/script-onerror-crossorigin-cors-expected.txt b/third_party/blink/web_tests/http/tests/security/script-onerror-crossorigin-cors-expected.txt index 00498751..08551c9 100644 --- a/third_party/blink/web_tests/http/tests/security/script-onerror-crossorigin-cors-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/script-onerror-crossorigin-cors-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS /SomeError/.test(msg) is true PASS url is "http://localhost:8000/security/resources/cors-script.php?fail=true&cors=true" PASS line is 1
diff --git a/third_party/blink/web_tests/http/tests/security/script-onerror-crossorigin-no-cors-expected.txt b/third_party/blink/web_tests/http/tests/security/script-onerror-crossorigin-no-cors-expected.txt index 547202d6..4c736c3 100644 --- a/third_party/blink/web_tests/http/tests/security/script-onerror-crossorigin-no-cors-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/script-onerror-crossorigin-no-cors-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/http/tests/security/script-onerror-crossorigin-same-origin-expected.txt b/third_party/blink/web_tests/http/tests/security/script-onerror-crossorigin-same-origin-expected.txt index 167d454f..10ae122 100644 --- a/third_party/blink/web_tests/http/tests/security/script-onerror-crossorigin-same-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/script-onerror-crossorigin-same-origin-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS /SomeError/.test(msg) is true PASS url is "http://127.0.0.1:8000/security/resources/cors-script.php?fail=true&cors=false" PASS line is 1
diff --git a/third_party/blink/web_tests/http/tests/security/script-onerror-no-crossorigin-cors-expected.txt b/third_party/blink/web_tests/http/tests/security/script-onerror-no-crossorigin-cors-expected.txt index c0cbe74..0c5cbc48 100644 --- a/third_party/blink/web_tests/http/tests/security/script-onerror-no-crossorigin-cors-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/script-onerror-no-crossorigin-cors-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS msg is "Script error." PASS url is "" PASS line is 0
diff --git a/third_party/blink/web_tests/http/tests/security/script-onerror-no-crossorigin-no-cors-expected.txt b/third_party/blink/web_tests/http/tests/security/script-onerror-no-crossorigin-no-cors-expected.txt index fe44636..c1ed10b 100644 --- a/third_party/blink/web_tests/http/tests/security/script-onerror-no-crossorigin-no-cors-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/script-onerror-no-crossorigin-no-cors-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS msg is "Script error." PASS url is "" PASS line is 0
diff --git a/third_party/blink/web_tests/http/tests/security/srcdoc-can-access-parent-expected.txt b/third_party/blink/web_tests/http/tests/security/srcdoc-can-access-parent-expected.txt index 69cfc5a9..7ef22e9 100644 --- a/third_party/blink/web_tests/http/tests/security/srcdoc-can-access-parent-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/srcdoc-can-access-parent-expected.txt
@@ -1,2 +1 @@ PASS -
diff --git a/third_party/blink/web_tests/http/tests/security/srcdoc-in-sandbox-cannot-access-parent-expected.txt b/third_party/blink/web_tests/http/tests/security/srcdoc-in-sandbox-cannot-access-parent-expected.txt index cb2c8f7..26b90c5 100644 --- a/third_party/blink/web_tests/http/tests/security/srcdoc-in-sandbox-cannot-access-parent-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/srcdoc-in-sandbox-cannot-access-parent-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 4: Uncaught SecurityError: Sandbox access violation: Blocked a frame at "null" from accessing a frame at "http://127.0.0.1:8000". The frame requesting access is sandboxed and lacks the "allow-same-origin" flag. PASS -
diff --git a/third_party/blink/web_tests/http/tests/security/srcdoc-inherits-referrer-for-forms-expected.txt b/third_party/blink/web_tests/http/tests/security/srcdoc-inherits-referrer-for-forms-expected.txt index 8408f6ac..e1ba10ed 100644 --- a/third_party/blink/web_tests/http/tests/security/srcdoc-inherits-referrer-for-forms-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/srcdoc-inherits-referrer-for-forms-expected.txt
@@ -6,7 +6,6 @@ This iframe logs information about its referrer: - -------- Frame: 'tg' --------
diff --git a/third_party/blink/web_tests/http/tests/security/subresourceIntegrity/clear-integrity-attribute-expected.txt b/third_party/blink/web_tests/http/tests/security/subresourceIntegrity/clear-integrity-attribute-expected.txt index f5ff0f2..7f75869 100644 --- a/third_party/blink/web_tests/http/tests/security/subresourceIntegrity/clear-integrity-attribute-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/subresourceIntegrity/clear-integrity-attribute-expected.txt
@@ -2,5 +2,3 @@ ALERT: FAIL CONSOLE ERROR: line 15: Failed to find a valid digest in the 'integrity' attribute for resource 'http://127.0.0.1:8000/security/subresourceIntegrity/resources/clear-integrity-attribute.js' with computed SHA-256 integrity 'yM5ZyzNsyKfaXRY78zSGapeQKtl0oGdpPpYxgwl8XW8='. The resource has been blocked. This test passes if only one 'FAIL' alert appears. - -
diff --git a/third_party/blink/web_tests/http/tests/security/subresourceIntegrity/integrity-attribute-expected.txt b/third_party/blink/web_tests/http/tests/security/subresourceIntegrity/integrity-attribute-expected.txt index 5620b97..e234f726 100644 --- a/third_party/blink/web_tests/http/tests/security/subresourceIntegrity/integrity-attribute-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/subresourceIntegrity/integrity-attribute-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS <link> has an 'integrity' attribute. PASS <script> has an 'integrity' attribute. PASS <a> does not have an 'integrity' attribute.
diff --git a/third_party/blink/web_tests/http/tests/security/subresourceIntegrity/shared-with-xhtml-expected.txt b/third_party/blink/web_tests/http/tests/security/subresourceIntegrity/shared-with-xhtml-expected.txt index b426507..45a5fe3 100644 --- a/third_party/blink/web_tests/http/tests/security/subresourceIntegrity/shared-with-xhtml-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/subresourceIntegrity/shared-with-xhtml-expected.txt
@@ -2,4 +2,4 @@ CONSOLE ERROR: Failed to find a valid digest in the 'integrity' attribute for resource 'http://127.0.0.1:8000/security/subresourceIntegrity/resources/shared-with-xhtml.js' with computed SHA-256 integrity 'yM5ZyzNsyKfaXRY78zSGapeQKtl0oGdpPpYxgwl8XW8='. The resource has been blocked. This test passes if no 'FAIL' alert appears. - +
diff --git a/third_party/blink/web_tests/http/tests/security/synchronous-frame-load-in-javascript-url-inherits-correct-origin-expected.txt b/third_party/blink/web_tests/http/tests/security/synchronous-frame-load-in-javascript-url-inherits-correct-origin-expected.txt index 9a4f9f42..c694a96 100644 --- a/third_party/blink/web_tests/http/tests/security/synchronous-frame-load-in-javascript-url-inherits-correct-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/synchronous-frame-load-in-javascript-url-inherits-correct-origin-expected.txt
@@ -1,4 +1,2 @@ CONSOLE ERROR: line 1: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8080". Protocols, domains, and ports must match. This test passes if there's no alert dialog. - -
diff --git a/third_party/blink/web_tests/http/tests/security/vibration/vibrate-in-cross-origin-iframe-with-user-gesture-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/vibration/vibrate-in-cross-origin-iframe-with-user-gesture-allowed-expected.txt index 3aecb43..ee4c801 100644 --- a/third_party/blink/web_tests/http/tests/security/vibration/vibrate-in-cross-origin-iframe-with-user-gesture-allowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/vibration/vibrate-in-cross-origin-iframe-with-user-gesture-allowed-expected.txt
@@ -3,7 +3,6 @@ 127.0.0.1 - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/vibration/vibrate-in-same-origin-iframe-with-user-gesture-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/vibration/vibrate-in-same-origin-iframe-with-user-gesture-allowed-expected.txt index 47d28de..0fbd37f 100644 --- a/third_party/blink/web_tests/http/tests/security/vibration/vibrate-in-same-origin-iframe-with-user-gesture-allowed-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/vibration/vibrate-in-same-origin-iframe-with-user-gesture-allowed-expected.txt
@@ -3,7 +3,6 @@ 127.0.0.1 - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/video-poster-cross-origin-crash2-expected.txt b/third_party/blink/web_tests/http/tests/security/video-poster-cross-origin-crash2-expected.txt index 9f627c58..2ae8bc2 100644 --- a/third_party/blink/web_tests/http/tests/security/video-poster-cross-origin-crash2-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/video-poster-cross-origin-crash2-expected.txt
@@ -1,4 +1,2 @@ CONSOLE ERROR: Access to image at 'http://localhost:8080/nonesuch.png' from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Test passes if it doesn't crash. - -
diff --git a/third_party/blink/web_tests/http/tests/security/webgl-cross-origin-ImageBitmap-blocked-expected.txt b/third_party/blink/web_tests/http/tests/security/webgl-cross-origin-ImageBitmap-blocked-expected.txt index 33f111d..8abbf11c 100644 --- a/third_party/blink/web_tests/http/tests/security/webgl-cross-origin-ImageBitmap-blocked-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/webgl-cross-origin-ImageBitmap-blocked-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS gl.getError() is gl.NO_ERROR PASS gl.getError() is gl.NO_ERROR PASS gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap) did not throw exception.
diff --git a/third_party/blink/web_tests/http/tests/security/window-events-clear-domain-expected.txt b/third_party/blink/web_tests/http/tests/security/window-events-clear-domain-expected.txt index 95f6418..63776e4 100644 --- a/third_party/blink/web_tests/http/tests/security/window-events-clear-domain-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/window-events-clear-domain-expected.txt
@@ -1,2 +1,3 @@ Test that window event handlers set for initial document are reset upon navigation if security check failed. There will be 'PASS' below if the test passes: + PASS
diff --git a/third_party/blink/web_tests/http/tests/security/window-events-clear-port-expected.txt b/third_party/blink/web_tests/http/tests/security/window-events-clear-port-expected.txt index 95f6418..63776e4 100644 --- a/third_party/blink/web_tests/http/tests/security/window-events-clear-port-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/window-events-clear-port-expected.txt
@@ -1,2 +1,3 @@ Test that window event handlers set for initial document are reset upon navigation if security check failed. There will be 'PASS' below if the test passes: + PASS
diff --git a/third_party/blink/web_tests/http/tests/security/window-events-pass-expected.txt b/third_party/blink/web_tests/http/tests/security/window-events-pass-expected.txt index 17561d8..121abf7 100644 --- a/third_party/blink/web_tests/http/tests/security/window-events-pass-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/window-events-pass-expected.txt
@@ -1,3 +1,4 @@ Test that window event handlers set for initial document are kept if security check passes. There will be 2 'PASS' messages below if the test passes: + PASS: unload fired. PASS: load fired.
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-hash-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-hash-expected.txt index f7d1190..dbf0278b 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-hash-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-hash-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 4: Uncaught SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a frame with origin "http://127.0.0.1:8000". Protocols, domains, and ports must match. - PASS: cross-site assignment of location.hash not allowed
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-host-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-host-expected.txt index 52f21ed..bead20e 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-host-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-host-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 4: Uncaught SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a frame with origin "http://127.0.0.1:8000". Protocols, domains, and ports must match. - PASS: cross-site assignment of location.host not allowed
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-hostname-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-hostname-expected.txt index deeaf2d..ce7beda 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-hostname-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-hostname-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 4: Uncaught SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a frame with origin "http://127.0.0.1:8000". Protocols, domains, and ports must match. - PASS: cross-site assignment of location.hostname not allowed
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-nonstandardProperty-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-nonstandardProperty-expected.txt index 6db7b6b5..99d3695 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-nonstandardProperty-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-nonstandardProperty-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 4: Uncaught SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a frame with origin "http://127.0.0.1:8000". Protocols, domains, and ports must match. - PASS: cross-site assignment of location.nonstandardProperty not allowed
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-pathname-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-pathname-expected.txt index e99dcb3..d0c97b2 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-pathname-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-pathname-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 4: Uncaught SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a frame with origin "http://127.0.0.1:8000". Protocols, domains, and ports must match. - PASS: cross-site assignment of location.pathname not allowed
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-protocol-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-protocol-expected.txt index 6438a09..5d044abe 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-protocol-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-protocol-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 4: Uncaught SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a frame with origin "http://127.0.0.1:8000". Protocols, domains, and ports must match. - PASS: cross-site assignment of location.protocol not allowed
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-reload-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-reload-expected.txt index 45825ca..7980c24 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-reload-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-reload-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 4: Uncaught SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a frame with origin "http://127.0.0.1:8000". Protocols, domains, and ports must match. - PASS: cross-site assignment of location.replace not allowed
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-search-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-search-expected.txt index baa4c5a..7aa38726 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-search-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-assign-location-search-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 4: Uncaught SecurityError: Blocked a frame with origin "http://localhost:8000" from accessing a frame with origin "http://127.0.0.1:8000". Protocols, domains, and ports must match. - PASS: cross-site assignment of location.search not allowed
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-cross-origin-stack-overflow-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-cross-origin-stack-overflow-expected.txt index a6ec845..02c3739 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-cross-origin-stack-overflow-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-cross-origin-stack-overflow-expected.txt
@@ -1,2 +1 @@ PASS: non-cross-site exception thrown. -
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-defineProperty-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-defineProperty-expected.txt index 60a809d4..fce7652 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-defineProperty-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-defineProperty-expected.txt
@@ -1,4 +1,3 @@ - PASS: cross-site assignment of Object constructor not allowed PASS: cross-site assignment of new property not allowed PASS: cross-site assignment of location.hash not allowed
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-invalid-domain-change-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-invalid-domain-change-expected.txt index deb6e22..81f5b8f4 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-invalid-domain-change-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-invalid-domain-change-expected.txt
@@ -1,2 +1 @@ - PASS: cross-site not access allowed
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-javascript-variations-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-javascript-variations-expected.txt index 48d5d642..da818166 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-javascript-variations-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-javascript-variations-expected.txt
@@ -23,5 +23,3 @@ Frame: 'VictimFrame' -------- Inner text should not be replaced. - -
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-javascript-with-spaces-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-javascript-with-spaces-expected.txt index 7299682..df36bdc 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-javascript-with-spaces-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-javascript-with-spaces-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 13: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match. - There should be no alert displayed.
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-object-element-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-object-element-expected.txt index fa96d2901..8766ebc 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-object-element-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-object-element-expected.txt
@@ -1 +1 @@ -There should be no alert displayed. +There should be no alert displayed.
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-sandboxed-iframe-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-sandboxed-iframe-expected.txt index eab8599..4193f725 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-sandboxed-iframe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-sandboxed-iframe-expected.txt
@@ -1,5 +1,4 @@ CONSOLE ERROR: line 4: Uncaught SecurityError: Sandbox access violation: Blocked a frame at "http://127.0.0.1:8000" from accessing a frame at "http://127.0.0.1:8000". The frame requesting access is sandboxed and lacks the "allow-same-origin" flag. This test verifies that sandboxed iframe prevents cross-domain script access. It will print "PASS" on success. - PASS: cross-domain script access disallowed from sandboxed iframe
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-synchronous-form-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-synchronous-form-expected.txt index 1215b2e..02d7ac2 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-synchronous-form-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-synchronous-form-expected.txt
@@ -1,3 +1,2 @@ Waiting for iframe... Done. -
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-xsl-external-entity-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-xsl-external-entity-expected.txt index 4ccb03e..adce72a 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-xsl-external-entity-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-xsl-external-entity-expected.txt
@@ -3,4 +3,3 @@ CONSOLE ERROR: Unsafe attempt to load URL http://localhost:8000/security/resources/target.xml from frame with URL http://127.0.0.1:8000/security/xss-DENIED-xsl-external-entity.xml. Domains, protocols and ports must match. This test includes a cross-origin external entity. It passes if the load fails and thus there is no text below this line. -
diff --git a/third_party/blink/web_tests/http/tests/security/xss-DENIED-xsl-external-entity-redirect-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-DENIED-xsl-external-entity-redirect-expected.txt index 3831903f..9661b08 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-DENIED-xsl-external-entity-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-DENIED-xsl-external-entity-redirect-expected.txt
@@ -3,4 +3,3 @@ CONSOLE ERROR: Unsafe attempt to load URL http://localhost:8000/security/resources/target.xml from frame with URL http://127.0.0.1:8000/security/xss-DENIED-xsl-external-entity-redirect.xml. Domains, protocols and ports must match. This test includes a cross-origin external entity. It passes if the load fails and thus there is no text below this line. -
diff --git a/third_party/blink/web_tests/http/tests/security/xss-exception-expected.txt b/third_party/blink/web_tests/http/tests/security/xss-exception-expected.txt index bb746a04..bada2106b 100644 --- a/third_party/blink/web_tests/http/tests/security/xss-exception-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xss-exception-expected.txt
@@ -1,4 +1,4 @@ CONSOLE MESSAGE: PASS: not executed in iframe context CONSOLE MESSAGE: PASS: not executed in iframe context CONSOLE MESSAGE: PASS: not executed in iframe context -Test passes if three "PASS" messages are logged to the console. +Test passes if three "PASS" messages are logged to the console.
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/base-href-direct-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/base-href-direct-expected.txt index 8ada282..bbd18ad 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/base-href-direct-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/base-href-direct-expected.txt
@@ -1,4 +1,2 @@ ALERT: /XSS/ We allow direct injections into base tags to reduce false positives. - -
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/block-does-not-leak-location-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/block-does-not-leak-location-expected.txt index 4ae3352..4ea767d 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/block-does-not-leak-location-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/block-does-not-leak-location-expected.txt
@@ -4,4 +4,5 @@ PASS successfullyParsed is true TEST COMPLETE - + +
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/cached-frame-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/cached-frame-expected.txt index 2e3cb67..7308fa8e 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/cached-frame-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/cached-frame-expected.txt
@@ -4,11 +4,11 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Two console messages should be generated, noting that JavaScript was blocked. Check that the nonce is the same, meaning that the document was only generated once: PASS frame1.contentDocument.querySelector("input").value == frame2.contentDocument.querySelector("input").value is true PASS successfullyParsed is true TEST COMPLETE - + +
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/chunked-big-script-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/chunked-big-script-expected.txt index ab1192e..ac7eb5af 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/chunked-big-script-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/chunked-big-script-expected.txt
@@ -1,7 +1,5 @@ Test passes if xss auditor does not mistakenly fire in the middle of chunked content - - -------- Frame: '<!--framePath //<!--frame0-->-->' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/embed-tag-in-path-unterminated-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/embed-tag-in-path-unterminated-expected.txt index 48ff3face..2c47407 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/embed-tag-in-path-unterminated-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/embed-tag-in-path-unterminated-expected.txt
@@ -1,4 +1,2 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://localhost:8000/security/xssAuditor/intercept/echo-intertag.pl/%3Cembed%20height=%22500%22src=%22https://127.0.0.1:8443/security/xssAuditor/resources/dummy.swf%22.xml&clutter=%3Cp%3E' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. Check that the XSSAuditor catches reflected tags in path components - -
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-base-href-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-base-href-expected.txt index 3afa3ff4..d6cc8e7 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-base-href-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-base-href-expected.txt
@@ -2,8 +2,6 @@ CONSOLE MESSAGE: line 31: PASS: "frame" is cross-origin. The loading of iframe below should be blocked: - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-iframe-javascript-url-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-iframe-javascript-url-expected.txt index 70bb2c9..f0b0e9c 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-iframe-javascript-url-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-iframe-javascript-url-expected.txt
@@ -2,8 +2,6 @@ CONSOLE MESSAGE: line 31: PASS: "frame" is cross-origin. The loading of iframe below should be blocked: - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-iframe-no-inherit-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-iframe-no-inherit-expected.txt index f9c5c8a..b622438 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-iframe-no-inherit-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-iframe-no-inherit-expected.txt
@@ -1,8 +1,6 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://127.0.0.1:8000/security/xssAuditor/resources/echo-intertag.pl?q=%3Cscript%3Ealert(/XSS/)%3C/script%3E%3Cp%3EIf%20you%20see%20this%20message%20and%20no%20JavaScript%20alert()%20then%20the%20test%20PASSED.%3C/p%3E' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. This tests that the header X-XSS-Protection is not inherited by the iframe below: - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-javascript-link-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-javascript-link-expected.txt index fbb67be..5fd559a3d 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-javascript-link-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-javascript-link-expected.txt
@@ -2,8 +2,6 @@ CONSOLE MESSAGE: line 31: PASS: "frame" is cross-origin. The loading of iframe below should be blocked: - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-link-onclick-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-link-onclick-expected.txt index 9d92a4c..5924823 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-link-onclick-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-link-onclick-expected.txt
@@ -2,8 +2,6 @@ CONSOLE MESSAGE: line 31: PASS: "frame" is cross-origin. The loading of iframe below should be blocked: - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-object-tag-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-object-tag-expected.txt index 4d1ae2c9..86577aec 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-object-tag-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-object-tag-expected.txt
@@ -2,8 +2,6 @@ CONSOLE MESSAGE: line 31: PASS: "frame" is cross-origin. The loading of iframe below should be blocked: - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-script-tag-cross-domain-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-script-tag-cross-domain-expected.txt index 3f57932..14eef55c 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-script-tag-cross-domain-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-script-tag-cross-domain-expected.txt
@@ -3,8 +3,6 @@ ALERT: URL mismatch: '[Location object access threw exception]' vs. 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl?enable-full-block=1&q=%3Cscript%3Ealert(String.fromCharCode(0x58,0x53,0x53))%3C/script%3E' The loading of iframe below should be blocked: - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-script-tag-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-script-tag-expected.txt index bca5cb15..3d54e87 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-script-tag-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-script-tag-expected.txt
@@ -3,8 +3,6 @@ ALERT: URL mismatch: '[Location object access threw exception]' vs. 'http://127.0.0.1:8000/security/xssAuditor/resources/echo-intertag.pl?enable-full-block=1&q=%3Cscript%3Ealert(String.fromCharCode(0x58,0x53,0x53))%3C/script%3E' The loading of iframe below should be blocked: - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-script-tag-with-source-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-script-tag-with-source-expected.txt index 2b2462d..b31874b8e 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-script-tag-with-source-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/full-block-script-tag-with-source-expected.txt
@@ -2,8 +2,6 @@ CONSOLE MESSAGE: line 31: PASS: "frame" is cross-origin. The loading of iframe below should be blocked: - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/html5-import-CORS-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/html5-import-CORS-expected.txt index 0287476..7740090 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/html5-import-CORS-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/html5-import-CORS-expected.txt
@@ -1,4 +1,3 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl?q=%3clink%20rel=%22import%22%20href=%22http://127.0.0.1:8000/security/xssAuditor/resources/xss.js%22%3e' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. CONSOLE WARNING: HTML Imports is deprecated and will be removed in M73, around March 2019. Please use ES modules instead. See https://www.chromestatus.com/features/5144752345317376 for more details. - This test passes if the XSSAuditor blocks the load prior to the CORS restriction kicking in. We've not bothered to enable CORS for this test, unlike what a real attacker would do, so a CORS error here means failure.
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/html5-import-safe-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/html5-import-safe-expected.txt index 00412310..47d18bf 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/html5-import-safe-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/html5-import-safe-expected.txt
@@ -1,5 +1,4 @@ CONSOLE WARNING: HTML Imports is deprecated and will be removed in M73, around March 2019. Please use ES modules instead. See https://www.chromestatus.com/features/5144752345317376 for more details. - This test passes if the "safe" HTML5 import occurs, because XSSAuditor gives a pass to resources from the same origin to cut down on the false positive rate. --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/iframe-srcdoc-property-blocked-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/iframe-srcdoc-property-blocked-expected.txt index 6e908d4..5affb6a3 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/iframe-srcdoc-property-blocked-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/iframe-srcdoc-property-blocked-expected.txt
@@ -1,4 +1,2 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://localhost:8000/security/xssAuditor/resources/echo-frame-src.pl?q=%22srcdoc=%22%3Cscript%3Ealert(0)%3C/script%3E' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. Catch injected srcdoc properties when there is punctuation enabing the auditor - -
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/img-tag-with-comma-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/img-tag-with-comma-expected.txt index babbb3b..db2a784 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/img-tag-with-comma-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/img-tag-with-comma-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 5: The XSS Auditor refused to execute a script in 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl?clutter=,&q=%3cimg%20src=x%20onerror=%22[]&q2=alert(1)%22%3c' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. - Test that the XSSAuditor catches the specific case where the IIS webserver resovles multiply occuring query parameters by concatenating them before passing the result to the application. Conceptually, its as if ?a=1&a=2 becomes ?a=1,2. The test passes if the XSSAuditor logs console messages and no alerts fire.
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/malformed-xss-protection-header-1-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/malformed-xss-protection-header-1-expected.txt index ff0ed78..932c79a 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/malformed-xss-protection-header-1-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/malformed-xss-protection-header-1-expected.txt
@@ -3,8 +3,6 @@ ALERT: URL mismatch: '[Location object access threw exception]' vs. 'http://127.0.0.1:8000/security/xssAuditor/resources/echo-intertag.pl?notifyDone=1&malformed-header=1&q=%3Cscript%3Ealert(String.fromCharCode(0x58,0x53,0x53))%3C/script%3E%3Cp%3EIf%20you%20see%20this%20message%20and%20no%20JavaScript%20alert()%20then%20the%20test%20PASSED.%3C/p%3E' This tests that a malformed X-XSS-Protection header is not ignored when the length of its value exceeds 16 characters, and that an error is reported. - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/no-protection-script-tag-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/no-protection-script-tag-expected.txt index cb5a12a..b1a0feb 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/no-protection-script-tag-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/no-protection-script-tag-expected.txt
@@ -1,4 +1,2 @@ ALERT: /PASS/ This script should run because XSS protection is disabled. - -
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/property-escape-noquotes-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/property-escape-noquotes-expected.txt index b795675..40cc544 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/property-escape-noquotes-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/property-escape-noquotes-expected.txt
@@ -1,4 +1,2 @@ ALERT: XSS This test fails because the XSSAuditor allows requests that do not contain illegal URI characters. Thus, the XSSAuditor does not detect breaking out of an unquoted property. A future update may reinstate this functionality. - -
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/property-escape-noquotes-tab-slash-chars-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/property-escape-noquotes-tab-slash-chars-expected.txt index b795675..40cc544 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/property-escape-noquotes-tab-slash-chars-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/property-escape-noquotes-tab-slash-chars-expected.txt
@@ -1,4 +1,2 @@ ALERT: XSS This test fails because the XSSAuditor allows requests that do not contain illegal URI characters. Thus, the XSSAuditor does not detect breaking out of an unquoted property. A future update may reinstate this functionality. - -
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/property-inject-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/property-inject-expected.txt index 9e0cd34..93c0f39 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/property-inject-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/property-inject-expected.txt
@@ -1,4 +1,2 @@ ALERT: XSS This test fails because the XSSAuditor allows requests that do not contain illegal URI characters. Thus, the XSSAuditor does not detect the injection of an inline event handler within a tag. A future update may reinstate this functionality. - -
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/reflection-in-path-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/reflection-in-path-expected.txt index f6c7b46..00701e5 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/reflection-in-path-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/reflection-in-path-expected.txt
@@ -5,5 +5,3 @@ Frame: '<!--framePath //<!--frame0-->-->' -------- This is an iframe with a injected form - -
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-cross-origin-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-cross-origin-expected.txt index b0905206..f56d00a 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-cross-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-cross-origin-expected.txt
@@ -1,8 +1,6 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://127.0.0.1:8000/security/xssAuditor/resources/echo-intertag.pl?test=report-script-tag.html&echo-report=1&enable-report-cross-origin=1&q=%3Cscript%3Ealert(String.fromCharCode(0x58,0x53,0x53))%3C/script%3E%3Cp%3EIf%20you%20see%20this%20message,%20no%20JavaScript%20alert(),%20and%20not%20dump%20of%20a%20report%20is%20displayed%20below,%20then%20the%20test%20PASSED.%3C/p%3E' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. This tests that the X-XSS-Protection reports are sent out properly - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-cross-origin-https-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-cross-origin-https-expected.txt index f70c9d7..e2188eb 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-cross-origin-https-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-cross-origin-https-expected.txt
@@ -1,9 +1,6 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'https://127.0.0.1:8443/security/xssAuditor/resources/echo-intertag.pl?test=report-script-tag.html&echo-report=1&enable-report-cross-origin=1&q=%3Cscript%3Ealert(String.fromCharCode(0x58,0x53,0x53))%3C/script%3E%3Cp%3EIf%20you%20see%20this%20message,%20no%20JavaScript%20alert(),%20and%20not%20dump%20of%20a%20report%20is%20displayed%20below,%20then%20the%20test%20PASSED.%3C/p%3E' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. -CONSOLE ERROR: Mixed Content: The page at 'https://127.0.0.1:8443/security/xssAuditor/resources/echo-intertag.pl?test=report-script-tag.html&echo-report=1&enable-report-cross-origin=1&q=%3Cscript%3Ealert(String.fromCharCode(0x58,0x53,0x53))%3C/script%3E%3Cp%3EIf%20you%20see%20this%20message,%20no%20JavaScript%20alert(),%20and%20not%20dump%20of%20a%20report%20is%20displayed%20below,%20then%20the%20test%20PASSED.%3C/p%3E' attempted to load subresource at 'https://127.0.0.1:8443/security/contentSecurityPolicy/resources/go-to-echo-report.js' over broken HTTPS. This tests that the X-XSS-Protection reports are sent out properly - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-expected.txt index 65828542..be4c927 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-expected.txt
@@ -1,8 +1,6 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://127.0.0.1:8000/security/xssAuditor/resources/echo-intertag.pl?test=report-script-tag.html&echo-report=1&enable-report=1&q=%3Cscript%3Ealert(String.fromCharCode(0x58,0x53,0x53))%3C/script%3E%3Cp%3EIf%20you%20see%20this%20message,%20no%20JavaScript%20alert(),%20and%20a%20dump%20of%20the%20report%20below,%20then%20the%20test%20PASSED.%3C/p%3E' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. This tests that the X-XSS-Protection reports are sent out properly - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-replace-state-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-replace-state-expected.txt index 9989d25..be1e85d 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-replace-state-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/report-script-tag-replace-state-expected.txt
@@ -1,8 +1,6 @@ CONSOLE ERROR: line 5: The XSS Auditor refused to execute a script in 'http://127.0.0.1:8000/security/xssAuditor/resources/echo-intertag.pl?test=report-script-tag.html&echo-report=1&enable-report=1&replaceState=1&q=%3Cscript%3Ealert(String.fromCharCode(0x58,0x53,0x53))%3C/script%3E%3Cp%3EIf%20you%20see%20this%20message,%20no%20JavaScript%20alert(),%20and%20a%20dump%20of%20the%20report%20below,%20then%20the%20test%20PASSED.%3C/p%3E' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. This tests that the X-XSS-Protection reports are sent out properly with the original, unmodified URL even when a history.replaceState() changes it. - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-post-control-char-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-post-control-char-expected.txt index b6d852e..9e1b3f26 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-post-control-char-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-post-control-char-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. -
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-post-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-post-expected.txt index b6d852e..9e1b3f26 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-post-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-post-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. -
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-post-null-char-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-post-null-char-expected.txt index b6d852e..9e1b3f26 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-post-null-char-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-post-null-char-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. -
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-post-redirect-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-post-redirect-expected.txt index 346ca192..0692867 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-post-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-post-redirect-expected.txt
@@ -1,7 +1,6 @@ CONSOLE ERROR: line 4: Uncaught ReferenceError: hunter is not defined Test for use of original post body in redirect. If the auditor fires, we've got a false positive from that. - --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-with-actual-comma-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-with-actual-comma-expected.txt index dba4f5e..131392ea 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-with-actual-comma-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-with-actual-comma-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl?q=%3Cscript%3E/**/0,0/*,*/-alert(0)%3C/script%3E' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. - Test that the XSSAuditor's tolerance for the IIS webserver's comma concatenation doesn't open holes when the reflected argument contains an actual comma. The test passes if the XSSAuditor logs console messages and no alerts fire.
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-with-comma-01-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-with-comma-01-expected.txt index dea666c..f9d8931 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-with-comma-01-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-with-comma-01-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl?clutter=,&q=%3Cscript%20x=%271&%3E&q2=1%27%3Ealert(String.fromCharCode(0x58,0x53,0x53,0x31))%3C/script%3E' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. - Test that the XSSAuditor catches the specific case where the IIS webserver resovles multiply occuring query parameters by concatenating them before passing the result to the application. Conceptually, its as if ?a=1&a=2 becomes ?a=1,2. The test passes if the XSSAuditor logs console messages and no alerts fire.
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-with-comma-02-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-with-comma-02-expected.txt index 0a292e0b..611938a 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-with-comma-02-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/script-tag-with-comma-02-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl?clutter=,&q=%3Cscript%3Ealert(String.fromCharCode(0x58&q2=0x53,0x53,0x32))%3C/script%3E' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. - Test that the XSSAuditor catches the specific case where the IIS webserver resovles multiply occuring query parameters by concatenating them before passing the result to the application. Conceptually, its as if ?a=1&a=2 becomes ?a=1,2. The test passes if the XSSAuditor logs console messages and no alerts fire.
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/svg-animate-clutter-2-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/svg-animate-clutter-2-expected.txt index 13e29f8..92169645 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/svg-animate-clutter-2-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/svg-animate-clutter-2-expected.txt
@@ -1,12 +1,11 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl?q=%3Csvg%20xmlns:xlink=%27http://www.w3.org/1999/xlink%27%3E%3Ca%3E%3Ccircle%20r=100%20/%3E%3Canimate%20attributeName=xlink:href%20values=javascript%3Aalert(1)%3B%3B&clutter=blah%27%3E¬ifyDone=1&dumpElementBySelector=animate' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. This test passes if the element displayed in the frame below has a 'values' attribute containing only 'javascript:void(0)'. - - -------- Frame: '<!--framePath //<!--frame0-->-->' -------- animate => animate * attributeName: xlink:href * values: javascript:void(0) + Page rendered here.
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/svg-animate-clutter-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/svg-animate-clutter-expected.txt index dc76947..cea8369d 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/svg-animate-clutter-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/svg-animate-clutter-expected.txt
@@ -1,12 +1,11 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl?q=%3Csvg%20xmlns:xlink=%27http://www.w3.org/1999/xlink%27%3E%3Ca%3E%3Ccircle%20r=100%20/%3E%3Canimate%20attributeName=xlink:href%20values=%3Bjavascript%3Aalert(1)%3B&clutter=blah%27%3E¬ifyDone=1&dumpElementBySelector=animate' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. This test passes if the element displayed in the frame below has a 'values' attribute containing only 'javascript:void(0)'. - - -------- Frame: '<!--framePath //<!--frame0-->-->' -------- animate => animate * attributeName: xlink:href * values: javascript:void(0) + Page rendered here.
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/svg-animate-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/svg-animate-expected.txt index 841acb6..8960f0ed 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/svg-animate-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/svg-animate-expected.txt
@@ -1,8 +1,6 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl?q=%3Csvg%20xmlns:xlink=%27http://www.w3.org/1999/xlink%27%3E%3Ca%3E%3Ccircle%20r=100%20/%3E%3Canimate%20attributeName=xlink:href%20values=%3Bjavascript%3Aalert(1)%20begin=0s%20end=0.1s%20fill=freeze%20/%3E%3C/a%3E%3C/svg%3E¬ifyDone=1&dumpElementBySelector=animate' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. This test passes if the element displayed in the frame below has a 'values' attribute containing only 'javascript:void(0)'. - - -------- Frame: '<!--framePath //<!--frame0-->-->' -------- @@ -12,4 +10,5 @@ * begin: 0s * end: 0.1s * fill: freeze + Page rendered here.
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/svg-animate-href-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/svg-animate-href-expected.txt index eaa75c186..978946f4 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/svg-animate-href-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/svg-animate-href-expected.txt
@@ -1,8 +1,6 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl?q=%3Csvg%3E%3Ca%3E%3Ccircle%20r=100%20/%3E%3Canimate%20attributeName=href%20values=%3Bj%26%23x61%3Bvascript%3Aalert(1)%20begin=0s%20end=0.1s%20fill=freeze%20/%3E%3C/a%3E%3C/svg%3E¬ifyDone=1&dumpElementBySelector=animate' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. This test passes if the element displayed in the frame below has a 'values' attribute containing only 'javascript:void(0)'. - - -------- Frame: '<!--framePath //<!--frame0-->-->' -------- @@ -12,4 +10,5 @@ * begin: 0s * end: 0.1s * fill: freeze + Page rendered here.
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/xss-filter-bypass-long-string-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/xss-filter-bypass-long-string-expected.txt index 02cd5b0..f28c9e15 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/xss-filter-bypass-long-string-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/xss-filter-bypass-long-string-expected.txt
@@ -1,3 +1,2 @@ CONSOLE ERROR: line 79: The XSS Auditor refused to execute a script in 'http://localhost:8000/security/xssAuditor/resources/xss-filter-bypass-long-string-reply.php' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. -
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/xss-protection-parsing-02-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/xss-protection-parsing-02-expected.txt index c70ed56..ee87851 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/xss-protection-parsing-02-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/xss-protection-parsing-02-expected.txt
@@ -1,8 +1,6 @@ CONSOLE ERROR: line 4: The XSS Auditor refused to execute a script in 'http://127.0.0.1:8000/security/xssAuditor/resources/echo-intertag.pl?notifyDone=1&valid-header=2&q=%3Cscript%3Ealert(String.fromCharCode(0x58,0x53,0x53))%3C/script%3E%3Cp%3EIf%20you%20see%20this%20message%20and%20no%20JavaScript%20alert()%20then%20the%20test%20PASSED.%3C/p%3E' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior. This tests that the X-XSS-Protection header is not ignored when there is a trailing semicolon. Although theoretically malformed, we tolerate this case without issuing an error. - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/xss-protection-parsing-03-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/xss-protection-parsing-03-expected.txt index 6e8e305..4b45864 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/xss-protection-parsing-03-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/xss-protection-parsing-03-expected.txt
@@ -2,8 +2,6 @@ CONSOLE MESSAGE: line 31: PASS: "frame" is cross-origin. This tests that the X-XSS-Protection header is not ignored when there is a trailing semicolon following mode=blank. Although theoretically malformed, we tolerate this case without issuing an error. - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/security/xssAuditor/xss-protection-parsing-04-expected.txt b/third_party/blink/web_tests/http/tests/security/xssAuditor/xss-protection-parsing-04-expected.txt index f482cb2..695e8322 100644 --- a/third_party/blink/web_tests/http/tests/security/xssAuditor/xss-protection-parsing-04-expected.txt +++ b/third_party/blink/web_tests/http/tests/security/xssAuditor/xss-protection-parsing-04-expected.txt
@@ -2,8 +2,6 @@ CONSOLE MESSAGE: line 31: PASS: "frame" is cross-origin. This tests that the X-XSS-Protection header is not ignored when the report and mode directives are swapped. - - -------- Frame: 'frame' --------
diff --git a/third_party/blink/web_tests/http/tests/sendbeacon/beacon-allowance-expected.txt b/third_party/blink/web_tests/http/tests/sendbeacon/beacon-allowance-expected.txt index a81e1b8e..f967b61 100644 --- a/third_party/blink/web_tests/http/tests/sendbeacon/beacon-allowance-expected.txt +++ b/third_party/blink/web_tests/http/tests/sendbeacon/beacon-allowance-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS result is false PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/sendbeacon/beacon-cookie-expected.txt b/third_party/blink/web_tests/http/tests/sendbeacon/beacon-cookie-expected.txt index 3068d5819..7e4f674 100644 --- a/third_party/blink/web_tests/http/tests/sendbeacon/beacon-cookie-expected.txt +++ b/third_party/blink/web_tests/http/tests/sendbeacon/beacon-cookie-expected.txt
@@ -4,7 +4,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS navigator.sendBeacon("resources/save-beacon.php?name=cookie", "Blip"); is true PASS Beacon sent successfully PASS Content-Type: text/plain;charset=UTF-8
diff --git a/third_party/blink/web_tests/http/tests/sendbeacon/beacon-cross-origin-expected.txt b/third_party/blink/web_tests/http/tests/sendbeacon/beacon-cross-origin-expected.txt index e85e3a14..3b8deb41e9 100644 --- a/third_party/blink/web_tests/http/tests/sendbeacon/beacon-cross-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/sendbeacon/beacon-cross-origin-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS navigator.sendBeacon("http://localhost:8000/sendbeacon/resources/save-beacon.php?name=cross-origin", "CrossOrigin"); is true PASS Beacon sent successfully PASS Content-Type: text/plain;charset=UTF-8
diff --git a/third_party/blink/web_tests/http/tests/sendbeacon/beacon-cross-origin-redirect-blob-expected.txt b/third_party/blink/web_tests/http/tests/sendbeacon/beacon-cross-origin-redirect-blob-expected.txt index e1d6444d..4e8d4b7 100644 --- a/third_party/blink/web_tests/http/tests/sendbeacon/beacon-cross-origin-redirect-blob-expected.txt +++ b/third_party/blink/web_tests/http/tests/sendbeacon/beacon-cross-origin-redirect-blob-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS navigator.sendBeacon("http://127.0.0.1:8080/resources/redirection-response.php?status=302&simple=true&target=/non-existent.php", blob); is true PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/sendbeacon/beacon-cross-origin-redirect-expected.txt b/third_party/blink/web_tests/http/tests/sendbeacon/beacon-cross-origin-redirect-expected.txt index 6579136bb..fcc9ceae 100644 --- a/third_party/blink/web_tests/http/tests/sendbeacon/beacon-cross-origin-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/sendbeacon/beacon-cross-origin-redirect-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS navigator.sendBeacon("http://127.0.0.1:8080/resources/redirection-response.php?status=302&target=/non-existent.php", "CrossOrigin"); is true PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/sendbeacon/beacon-detached-no-crash-expected.txt b/third_party/blink/web_tests/http/tests/sendbeacon/beacon-detached-no-crash-expected.txt index 23247ec..4a8426c 100644 --- a/third_party/blink/web_tests/http/tests/sendbeacon/beacon-detached-no-crash-expected.txt +++ b/third_party/blink/web_tests/http/tests/sendbeacon/beacon-detached-no-crash-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS w.navigator.sendBeacon() threw exception TypeError: Failed to execute 'sendBeacon' on 'Navigator': 1 argument required, but only 0 present.. PASS w.navigator.sendBeacon('resources/blank.txt', 'detached-should-return false') is false PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/sendbeacon/beacon-same-origin-expected.txt b/third_party/blink/web_tests/http/tests/sendbeacon/beacon-same-origin-expected.txt index c45d9430..ab26cc6 100644 --- a/third_party/blink/web_tests/http/tests/sendbeacon/beacon-same-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/sendbeacon/beacon-same-origin-expected.txt
@@ -6,7 +6,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Sending beacon with type: [object String] PASS navigator.sendBeacon("resources/save-beacon.php?name=same-origin", payload); is true PASS Beacon sent successfully
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/resolve-after-window-close-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/resolve-after-window-close-expected.txt index 35c86cad..4f7a8c3 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/resolve-after-window-close-expected.txt +++ b/third_party/blink/web_tests/http/tests/serviceworker/resolve-after-window-close-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/service-worker-gc-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/service-worker-gc-expected.txt index 9d35da1..226b651 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/service-worker-gc-expected.txt +++ b/third_party/blink/web_tests/http/tests/serviceworker/service-worker-gc-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS registrationObservation.wasCollected is false PASS swObservation.wasCollected is false PASS registrationObservation.wasCollected is false
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 1b27136..e6e8f7f 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -369,6 +369,14 @@ method constructor method contains method item +interface ErrorEvent : Event + attribute @@toStringTag + getter colno + getter error + getter filename + getter lineno + getter message + method constructor interface Event attribute @@toStringTag attribute AT_TARGET
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/window-close-during-registration-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/window-close-during-registration-expected.txt index 3683e922..fbfff29 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/window-close-during-registration-expected.txt +++ b/third_party/blink/web_tests/http/tests/serviceworker/window-close-during-registration-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/http/tests/shapes/crash-image-changed-during-layout-expected.txt b/third_party/blink/web_tests/http/tests/shapes/crash-image-changed-during-layout-expected.txt index 24c32e2c..22a8779 100644 --- a/third_party/blink/web_tests/http/tests/shapes/crash-image-changed-during-layout-expected.txt +++ b/third_party/blink/web_tests/http/tests/shapes/crash-image-changed-during-layout-expected.txt
@@ -1 +1,2 @@ -crbug.com/423891: Crashes if we remove a float from the floating objects list during layout. This test should not crash. If you see this that means the test has PASSED. +crbug.com/423891: Crashes if we remove a float from the floating objects list during layout. This test should not crash. +If you see this that means the test has PASSED.
diff --git a/third_party/blink/web_tests/http/tests/streams/transferable/resources/echo-worker.js b/third_party/blink/web_tests/http/tests/streams/transferable/resources/echo-worker.js new file mode 100644 index 0000000..806c237 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/streams/transferable/resources/echo-worker.js
@@ -0,0 +1,2 @@ +// A worker that just transfers back any message that is sent to it. +onmessage = evt => postMessage(evt.data, [evt.data]);
diff --git a/third_party/blink/web_tests/http/tests/streams/transferable/worker.html b/third_party/blink/web_tests/http/tests/streams/transferable/worker.html index 9c9c8151..c5dc9fc 100644 --- a/third_party/blink/web_tests/http/tests/streams/transferable/worker.html +++ b/third_party/blink/web_tests/http/tests/streams/transferable/worker.html
@@ -3,6 +3,7 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/helpers.js"></script> +<script src="../resources/test-utils.js"></script> <script> 'use strict'; @@ -32,4 +33,44 @@ }); }, 'postMessage in a worker should be able to transfer a ReadableStream'); +promise_test(async t => { + const w = new Worker('resources/echo-worker.js'); + let controller; + const orig = new ReadableStream({ + start(c) { + controller = c; + } + }); + const targetStream = await new Promise((resolve, reject) => { + w.onmessage = evt => resolve(evt.data); + w.onerror = () => reject('error in worker'); + w.postMessage(orig, [orig]); + }); + const reader = targetStream.getReader(); + const reads = []; + // Place a lot of chunks "in transit". This should increase the likelihood + // that they is a chunk at each relevant step when the worker is terminated. + for (let i = 0; i < 50; ++i) { + await delay(0); + controller.enqueue(i); + const expected = i; + reads.push(reader.read().then(({value, done}) => { + assert_false(done, 'we should not be done'); + assert_equals(value, expected, 'value should match expectation'); + })); + } + w.terminate(); + for (let i = 50; i < 60; ++i) { + controller.enqueue(i); + reads.push( + reader.read().then(t.unreached_func('read() should not resolve'))); + await delay(0); + } + // We don't expect every read() to complete, but we want to give them a chance + // to reject if they're going to. + return Promise.race([ + Promise.all(reads), + flushAsyncEvents() + ]); +}, 'terminating a worker should not error the stream'); </script>
diff --git a/third_party/blink/web_tests/http/tests/svg/dynamic-image-after-docload-expected.txt b/third_party/blink/web_tests/http/tests/svg/dynamic-image-after-docload-expected.txt index db418b2..863339fb 100644 --- a/third_party/blink/web_tests/http/tests/svg/dynamic-image-after-docload-expected.txt +++ b/third_party/blink/web_tests/http/tests/svg/dynamic-image-after-docload-expected.txt
@@ -1,2 +1 @@ Passed -
diff --git a/third_party/blink/web_tests/http/tests/svg/dynamic-image-root-expected.txt b/third_party/blink/web_tests/http/tests/svg/dynamic-image-root-expected.txt index 90e847e4..24c58e3 100644 --- a/third_party/blink/web_tests/http/tests/svg/dynamic-image-root-expected.txt +++ b/third_party/blink/web_tests/http/tests/svg/dynamic-image-root-expected.txt
@@ -1,2 +1 @@ Result: load([object SVGImageElement]) -
diff --git a/third_party/blink/web_tests/http/tests/svg/image-fetch-fail-expected.txt b/third_party/blink/web_tests/http/tests/svg/image-fetch-fail-expected.txt index 474d536..aa8f300 100644 --- a/third_party/blink/web_tests/http/tests/svg/image-fetch-fail-expected.txt +++ b/third_party/blink/web_tests/http/tests/svg/image-fetch-fail-expected.txt
@@ -1,2 +1 @@ PASS: Did not crash. -
diff --git a/third_party/blink/web_tests/http/tests/svg/svgload-vs-load-expected.txt b/third_party/blink/web_tests/http/tests/svg/svgload-vs-load-expected.txt index ab71f7a0..93f1674 100644 --- a/third_party/blink/web_tests/http/tests/svg/svgload-vs-load-expected.txt +++ b/third_party/blink/web_tests/http/tests/svg/svgload-vs-load-expected.txt
@@ -1,2 +1 @@ load(image) load(svg) -
diff --git a/third_party/blink/web_tests/http/tests/uri/assign-path-with-leading-slash-expected.txt b/third_party/blink/web_tests/http/tests/uri/assign-path-with-leading-slash-expected.txt index bb76798..e58c3f2a 100644 --- a/third_party/blink/web_tests/http/tests/uri/assign-path-with-leading-slash-expected.txt +++ b/third_party/blink/web_tests/http/tests/uri/assign-path-with-leading-slash-expected.txt
@@ -1,4 +1,5 @@ The path assignment test redirected successfully. Checking path... + PASS location.pathname is '/uri/resources/assign-path-landing.html' PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/uri/assign-path-without-leading-slash-expected.txt b/third_party/blink/web_tests/http/tests/uri/assign-path-without-leading-slash-expected.txt index bb76798..e58c3f2a 100644 --- a/third_party/blink/web_tests/http/tests/uri/assign-path-without-leading-slash-expected.txt +++ b/third_party/blink/web_tests/http/tests/uri/assign-path-without-leading-slash-expected.txt
@@ -1,4 +1,5 @@ The path assignment test redirected successfully. Checking path... + PASS location.pathname is '/uri/resources/assign-path-landing.html' PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/webfont/same-origin-credentials-expected.txt b/third_party/blink/web_tests/http/tests/webfont/same-origin-credentials-expected.txt index 6d07ad02..2438ea3 100644 --- a/third_party/blink/web_tests/http/tests/webfont/same-origin-credentials-expected.txt +++ b/third_party/blink/web_tests/http/tests/webfont/same-origin-credentials-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/webfont/webfont-performance-duration-expected.txt b/third_party/blink/web_tests/http/tests/webfont/webfont-performance-duration-expected.txt index ddd0a15..41a98354 100644 --- a/third_party/blink/web_tests/http/tests/webfont/webfont-performance-duration-expected.txt +++ b/third_party/blink/web_tests/http/tests/webfont/webfont-performance-duration-expected.txt
@@ -2,4 +2,5 @@ PASS successfullyParsed is true TEST COMPLETE + Hello webfont
diff --git a/third_party/blink/web_tests/http/tests/websocket/accept-language-header-expected.txt b/third_party/blink/web_tests/http/tests/websocket/accept-language-header-expected.txt index f3a499c2..0c63484 100644 --- a/third_party/blink/web_tests/http/tests/websocket/accept-language-header-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/accept-language-header-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS accept_language_value is non-null. PASS accept_language_value is defined. PASS accept_language_value is not ""
diff --git a/third_party/blink/web_tests/http/tests/websocket/bufferedAmount-after-send-expected.txt b/third_party/blink/web_tests/http/tests/websocket/bufferedAmount-after-send-expected.txt index f1721619..86231f4 100644 --- a/third_party/blink/web_tests/http/tests/websocket/bufferedAmount-after-send-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/bufferedAmount-after-send-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - onopen PASS ws.bufferedAmount is 5 PASS ws.bufferedAmount is 37
diff --git a/third_party/blink/web_tests/http/tests/websocket/close-code-and-reason-expected.txt b/third_party/blink/web_tests/http/tests/websocket/close-code-and-reason-expected.txt index 2b6cceb..dcc7403e 100644 --- a/third_party/blink/web_tests/http/tests/websocket/close-code-and-reason-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/close-code-and-reason-expected.txt
@@ -7,7 +7,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - ws.onclose() was called. PASS closeEvent.wasClean is false PASS closeEvent.code is codeAbnormalClosure
diff --git a/third_party/blink/web_tests/http/tests/websocket/close-in-order-expected.txt b/third_party/blink/web_tests/http/tests/websocket/close-in-order-expected.txt index 2b8f941..376e5e47 100644 --- a/third_party/blink/web_tests/http/tests/websocket/close-in-order-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/close-in-order-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS bufferedAmount is 196608 onclose PASS bufferedAmount is 0
diff --git a/third_party/blink/web_tests/http/tests/websocket/construct-in-detached-frame-expected.txt b/third_party/blink/web_tests/http/tests/websocket/construct-in-detached-frame-expected.txt index a42f895..e4d9a80 100644 --- a/third_party/blink/web_tests/http/tests/websocket/construct-in-detached-frame-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/construct-in-detached-frame-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/http/tests/websocket/cookie-http-to-ws-expected.txt b/third_party/blink/web_tests/http/tests/websocket/cookie-http-to-ws-expected.txt index 5b994a3..c4c1d165 100644 --- a/third_party/blink/web_tests/http/tests/websocket/cookie-http-to-ws-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/cookie-http-to-ws-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS cookie is "ws-path-origin-script=1; ws-path-root-domain-local-ip=1" PASS cookie is "ws-path-root-domain-local-ip=1" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/websocket/cookie-ws-to-ws-expected.txt b/third_party/blink/web_tests/http/tests/websocket/cookie-ws-to-ws-expected.txt index c08104b9..7a65eb7 100644 --- a/third_party/blink/web_tests/http/tests/websocket/cookie-ws-to-ws-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/cookie-ws-to-ws-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS cookie is "same-site-lax=1; same-site-strict=1; ws-domain-local-ip=1; ws-path-root=1; ws=1" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/websocket/extensions-expected.txt b/third_party/blink/web_tests/http/tests/websocket/extensions-expected.txt index 1e9ed12..d0d00831 100644 --- a/third_party/blink/web_tests/http/tests/websocket/extensions-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/extensions-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Check the value before opening the connection: PASS ws.extensions is "" Check if the value is read only:
diff --git a/third_party/blink/web_tests/http/tests/websocket/handshake-challenge-randomness-expected.txt b/third_party/blink/web_tests/http/tests/websocket/handshake-challenge-randomness-expected.txt index 2732718..c1bdcd78 100644 --- a/third_party/blink/web_tests/http/tests/websocket/handshake-challenge-randomness-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/handshake-challenge-randomness-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS challenge1 === challenge2 is false PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/websocket/httponly-cookie-expected.txt b/third_party/blink/web_tests/http/tests/websocket/httponly-cookie-expected.txt index 04e3698..11a98710 100644 --- a/third_party/blink/web_tests/http/tests/websocket/httponly-cookie-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/httponly-cookie-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS cookie is "ws-httponly=1; ws=1" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/websocket/iframe-sandbox-expected.txt b/third_party/blink/web_tests/http/tests/websocket/iframe-sandbox-expected.txt index 6a5e047..2950a56 100644 --- a/third_party/blink/web_tests/http/tests/websocket/iframe-sandbox-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/iframe-sandbox-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS wsOrigin is "null" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/websocket/multiple-connections-expected.txt b/third_party/blink/web_tests/http/tests/websocket/multiple-connections-expected.txt index 256256f..05baf74a 100644 --- a/third_party/blink/web_tests/http/tests/websocket/multiple-connections-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/multiple-connections-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS socketsOpened is 50 PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/websocket/multiple-connections-throttled-expected.txt b/third_party/blink/web_tests/http/tests/websocket/multiple-connections-throttled-expected.txt index 6ab426fb..9c2e71b 100644 --- a/third_party/blink/web_tests/http/tests/websocket/multiple-connections-throttled-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/multiple-connections-throttled-expected.txt
@@ -47,7 +47,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS openedCount is 255 PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/websocket/nocache-expected.txt b/third_party/blink/web_tests/http/tests/websocket/nocache-expected.txt index 2a336ef..69b675e 100644 --- a/third_party/blink/web_tests/http/tests/websocket/nocache-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/nocache-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS pragma is "no-cache" PASS cache_control is "no-cache" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/websocket/permessage-deflate-split-frames-expected.txt b/third_party/blink/web_tests/http/tests/websocket/permessage-deflate-split-frames-expected.txt index 1110e70..798f72d 100644 --- a/third_party/blink/web_tests/http/tests/websocket/permessage-deflate-split-frames-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/permessage-deflate-split-frames-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - onmessage: HelloHello onclose PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/websocket/receive-pong-with-payload-expected.txt b/third_party/blink/web_tests/http/tests/websocket/receive-pong-with-payload-expected.txt index 556601a..b7e39753 100644 --- a/third_party/blink/web_tests/http/tests/websocket/receive-pong-with-payload-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/receive-pong-with-payload-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS message is "sent pong" PASS wasClean is true PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/websocket/send-blob-onmessage-origin-expected.txt b/third_party/blink/web_tests/http/tests/websocket/send-blob-onmessage-origin-expected.txt index b760893..05a7e05 100644 --- a/third_party/blink/web_tests/http/tests/websocket/send-blob-onmessage-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/send-blob-onmessage-origin-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS PASS: Message #0. PASS origin is "ws://127.0.0.1:8880" PASS PASS: Message #1.
diff --git a/third_party/blink/web_tests/http/tests/websocket/send-object-tostring-check-expected.txt b/third_party/blink/web_tests/http/tests/websocket/send-object-tostring-check-expected.txt index ec77f58..f555e4b 100644 --- a/third_party/blink/web_tests/http/tests/websocket/send-object-tostring-check-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/send-object-tostring-check-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS event.data is "Goodbye" PASS testObj.callCounter is 1 PASS closeEvent.wasClean is true
diff --git a/third_party/blink/web_tests/http/tests/websocket/send-onmessage-origin-expected.txt b/third_party/blink/web_tests/http/tests/websocket/send-onmessage-origin-expected.txt index a337073..7019673 100644 --- a/third_party/blink/web_tests/http/tests/websocket/send-onmessage-origin-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/send-onmessage-origin-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Connected. PASS data is firstMessageToSend PASS wsOrigin is "ws://localhost:8880"
diff --git a/third_party/blink/web_tests/http/tests/websocket/url-no-trailing-slash-expected.txt b/third_party/blink/web_tests/http/tests/websocket/url-no-trailing-slash-expected.txt index f4f964f..3a02bb9 100644 --- a/third_party/blink/web_tests/http/tests/websocket/url-no-trailing-slash-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/url-no-trailing-slash-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS host is "127.0.0.1:8880" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/websocket/url-with-credential-expected.txt b/third_party/blink/web_tests/http/tests/websocket/url-with-credential-expected.txt index 2b3b9ce..4fadc70 100644 --- a/third_party/blink/web_tests/http/tests/websocket/url-with-credential-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/url-with-credential-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS host is "127.0.0.1:8880" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/websocket/useragent-in-openinghandshake-expected.txt b/third_party/blink/web_tests/http/tests/websocket/useragent-in-openinghandshake-expected.txt index d0b09ea..a7316a7 100644 --- a/third_party/blink/web_tests/http/tests/websocket/useragent-in-openinghandshake-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/useragent-in-openinghandshake-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS user_agent is navigator.userAgent PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/websocket/websocket-pending-activity-expected.txt b/third_party/blink/web_tests/http/tests/websocket/websocket-pending-activity-expected.txt index 4de4778..0f7895de 100644 --- a/third_party/blink/web_tests/http/tests/websocket/websocket-pending-activity-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/websocket-pending-activity-expected.txt
@@ -2,4 +2,6 @@ PASS successfullyParsed is true TEST COMPLETE + + Should alert "PASS".
diff --git a/third_party/blink/web_tests/http/tests/websocket/workers/close-code-and-reason-expected.txt b/third_party/blink/web_tests/http/tests/websocket/workers/close-code-and-reason-expected.txt index a78a4c9..19165619 100644 --- a/third_party/blink/web_tests/http/tests/websocket/workers/close-code-and-reason-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/workers/close-code-and-reason-expected.txt
@@ -7,7 +7,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: resources/close-code-and-reason.js [Worker] ws.onclose() was called. PASS [Worker] closeEvent.wasClean is false
diff --git a/third_party/blink/web_tests/http/tests/websocket/workers/worker-handshake-challenge-randomness-expected.txt b/third_party/blink/web_tests/http/tests/websocket/workers/worker-handshake-challenge-randomness-expected.txt index ab3b203e..75773de6 100644 --- a/third_party/blink/web_tests/http/tests/websocket/workers/worker-handshake-challenge-randomness-expected.txt +++ b/third_party/blink/web_tests/http/tests/websocket/workers/worker-handshake-challenge-randomness-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: resources/worker-handshake-challenge-randomness.js PASS [Worker] challenge1 === challenge2 is false PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/workers/shared-worker-name-expected.txt b/third_party/blink/web_tests/http/tests/workers/shared-worker-name-expected.txt index e2d7e11..0e5a9199 100644 --- a/third_party/blink/web_tests/http/tests/workers/shared-worker-name-expected.txt +++ b/third_party/blink/web_tests/http/tests/workers/shared-worker-name-expected.txt
@@ -2,11 +2,11 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS created SharedWorker with no name PASS successfullyParsed is true TEST COMPLETE + PASS setting self.foo PASS creating worker with no name PASS creating worker with empty name
diff --git a/third_party/blink/web_tests/http/tests/workers/text-encoding-expected.txt b/third_party/blink/web_tests/http/tests/workers/text-encoding-expected.txt index bbf2053..f7faaea 100644 --- a/third_party/blink/web_tests/http/tests/workers/text-encoding-expected.txt +++ b/third_party/blink/web_tests/http/tests/workers/text-encoding-expected.txt
@@ -7,6 +7,7 @@ - The URLs used in workers (for subworkers or XHR) are always encoded using UTF-8 (in regular html documents parts of the query an hash may be encoded with other encodings). - The base URL for the worker (used to resolve relative URLs for subworkers and XHR) is the URL of its script. - importScripts() decodes the scripts using UTF-8. + Document encoding: windows-1251 Document, Workers: All XHR responses should match this: Привет Document: : XHR: Привет
diff --git a/third_party/blink/web_tests/http/tests/workers/worker-importScripts-onerror-crossorigin-expected.txt b/third_party/blink/web_tests/http/tests/workers/worker-importScripts-onerror-crossorigin-expected.txt index 7b0a687..8e24a0420 100644 --- a/third_party/blink/web_tests/http/tests/workers/worker-importScripts-onerror-crossorigin-expected.txt +++ b/third_party/blink/web_tests/http/tests/workers/worker-importScripts-onerror-crossorigin-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS workerOnerror.message is "Script error." PASS workerOnerror.filename is "" PASS workerOnerror.lineno is 0
diff --git a/third_party/blink/web_tests/http/tests/workers/worker-importScripts-onerror-redirect-to-crossorigin-expected.txt b/third_party/blink/web_tests/http/tests/workers/worker-importScripts-onerror-redirect-to-crossorigin-expected.txt index 273cc9f..7064271 100644 --- a/third_party/blink/web_tests/http/tests/workers/worker-importScripts-onerror-redirect-to-crossorigin-expected.txt +++ b/third_party/blink/web_tests/http/tests/workers/worker-importScripts-onerror-redirect-to-crossorigin-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS workerOnerror.message is "Script error." PASS workerOnerror.filename is "" PASS workerOnerror.lineno is 0
diff --git a/third_party/blink/web_tests/http/tests/workers/worker-importScripts-onerror-sameorigin-expected.txt b/third_party/blink/web_tests/http/tests/workers/worker-importScripts-onerror-sameorigin-expected.txt index 416cc393..a5cd7b36 100644 --- a/third_party/blink/web_tests/http/tests/workers/worker-importScripts-onerror-sameorigin-expected.txt +++ b/third_party/blink/web_tests/http/tests/workers/worker-importScripts-onerror-sameorigin-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS workerOnerror.message is "Uncaught This is a custom error message." PASS workerOnerror.filename is "http://127.0.0.1:8000/workers/resources/worker-importScripts-throw.js" PASS workerOnerror.lineno is 1
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/async-xhr-revalidate-after-sync-xhr-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/async-xhr-revalidate-after-sync-xhr-expected.txt index 59f491df..c311ced6 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/async-xhr-revalidate-after-sync-xhr-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/async-xhr-revalidate-after-sync-xhr-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS xhr2SendIsReturned is true PASS xhr1.responseText is not xhr2.responseText PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/bom-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/bom-expected.txt index 0ab296f..70b246e 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/bom-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/bom-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS xhr.responseText is "三村かな子" PASS xhr2.responseText is "三村かな子" PASS xhr3.responseText is "三村かな子"
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/cache-control-request-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/cache-control-request-expected.txt index 5cd9767..22d1722 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/cache-control-request-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/cache-control-request-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS MemoryCache is not used. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/close-window-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/close-window-expected.txt index e6ac5f0..0ba5508 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/close-window-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/close-window-expected.txt
@@ -1,5 +1,3 @@ Test for bug 22630: Assertion failure in XMLHttpRequest::contextDestroyed. SUCCESS! Did not assert! - -
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/detaching-frame-2-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/detaching-frame-2-expected.txt index 36d08c91..fc3b0b22 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/detaching-frame-2-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/detaching-frame-2-expected.txt
@@ -1,4 +1,3 @@ bug 25240 - PASS
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/duplicate-revalidation-reload-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/duplicate-revalidation-reload-expected.txt index ead1665..c5dd5cf 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/duplicate-revalidation-reload-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/duplicate-revalidation-reload-expected.txt
@@ -4,7 +4,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS result1 is "PASS" PASS result2 is "PASS" PASS DONE
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/encoding-send-latin-1-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/encoding-send-latin-1-expected.txt index c502213..76b1a75 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/encoding-send-latin-1-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/encoding-send-latin-1-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS xhr.responseText is tests[0] PASS xhr.responseText is tests[1] PASS xhr.responseText is tests[2]
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/event-listener-gc-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/event-listener-gc-expected.txt index f84abcce..61b78da 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/event-listener-gc-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/event-listener-gc-expected.txt
@@ -1,6 +1,8 @@ PASS successfullyParsed is true TEST COMPLETE + + This test checks whether event handlers for outstanding XMLHttpRequests survive garbage collection. See https://bugs.webkit.org/show_bug.cgi?id=9113 REGRESSION (14581): XMLHttpRequest never calls onreadystatechange with a readystate == 4
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/filename-encoding-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/filename-encoding-expected.txt index 46f96743..6c5097d 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/filename-encoding-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/filename-encoding-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS file.name is request.filename PASS response.field is request.field PASS response.filename is request.filename
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/frame-load-cancelled-abort-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/frame-load-cancelled-abort-expected.txt index ea35776..314f032 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/frame-load-cancelled-abort-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/frame-load-cancelled-abort-expected.txt
@@ -10,4 +10,3 @@ Body of subframe is loaded. XMLHttpRequest should be in progress. Nuking the iframe Iframe unloaded Iframe removed -
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/getAllResponseHeaders-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/getAllResponseHeaders-expected.txt index 4496c8c..2e1d8baa 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/getAllResponseHeaders-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/getAllResponseHeaders-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS {state: 0}; headerValues = xhr.getAllResponseHeaders(); did not throw exception. PASS headerValues is the empty string PASS {state: 1}; headerValues = xhr.getAllResponseHeaders(); did not throw exception.
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/getResponseHeader-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/getResponseHeader-expected.txt index 0ad7ab57..1d1dfc0 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/getResponseHeader-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/getResponseHeader-expected.txt
@@ -8,7 +8,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS {state: 0}; headerValue = xhr.getResponseHeader('Content-Type'); did not throw exception. PASS headerValue is null PASS {state: 1}; headerValue = xhr.getResponseHeader('Content-Type'); did not throw exception.
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/00-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/00-expected.txt index 75ebd13..8f2c8ac 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/00-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/00-expected.txt
@@ -8,7 +8,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should allow origin: '*' PASS xhr.send(null) is undefined. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/01-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/01-expected.txt index c1e627d..10fa480 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/01-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/01-expected.txt
@@ -8,7 +8,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should allow origin: ' * ' PASS xhr.send(null) is undefined. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/02-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/02-expected.txt index 36056074..97191ff8 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/02-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/02-expected.txt
@@ -8,7 +8,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should allow origin: ' *' PASS xhr.send(null) is undefined. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/03-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/03-expected.txt index 0a42de3..20c495f 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/03-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/03-expected.txt
@@ -8,7 +8,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should allow origin: 'http://localhost:8000' PASS xhr.send(null) is undefined. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/04-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/04-expected.txt index d84d4c4..0ca7bc7b 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/04-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/04-expected.txt
@@ -8,7 +8,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should allow origin: ' http://localhost:8000' PASS xhr.send(null) is undefined. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/05-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/05-expected.txt index c9fcd05..c9f3a6d 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/05-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/05-expected.txt
@@ -8,7 +8,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should allow origin: ' http://localhost:8000 ' PASS xhr.send(null) is undefined. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/06-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/06-expected.txt index 7efad0b3..93582fe2 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/06-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/06-expected.txt
@@ -8,7 +8,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should allow origin: ' http://localhost:8000' PASS xhr.send(null) is undefined. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/07-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/07-expected.txt index efe5c77c..bd501ad4 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/07-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/07-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://www2.localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%2F%2Fwww2.localhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/08-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/08-expected.txt index f811345..0486188 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/08-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/08-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: '//localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=%2F%2Flocalhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/09-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/09-expected.txt index 034cd61f..0c0acab 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/09-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/09-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: '://localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=%3A%2F%2Flocalhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/10-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/10-expected.txt index 8e6b10f..719fbae 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/10-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/10-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'ftp://localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=ftp%3A%2F%2Flocalhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/11-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/11-expected.txt index d8b2b2e..412e967 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/11-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/11-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http:://localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%3A%2F%2Flocalhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/12-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/12-expected.txt index 8654527..02ed272 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/12-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/12-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http:/localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%2Flocalhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/13-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/13-expected.txt index f011b3ac..708c772d 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/13-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/13-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http:localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3Alocalhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/14-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/14-expected.txt index 218d13e..0249c7d 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/14-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/14-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=localhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/15-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/15-expected.txt index a440dc6f..a9353ed 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/15-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/15-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://localhost:8000?' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%2F%2Flocalhost%3A8000%3F'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/16-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/16-expected.txt index 2f973b2..45445d6 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/16-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/16-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://localhost:8000/' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%2F%2Flocalhost%3A8000%2F'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/17-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/17-expected.txt index 57ee13b..89493ea 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/17-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/17-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://localhost:8000 /' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%2F%2Flocalhost%3A8000%20%2F'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/18-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/18-expected.txt index 72ca417..70e78ab 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/18-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/18-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://localhost:8000#' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%2F%2Flocalhost%3A8000%23'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/19-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/19-expected.txt index 13322ca..62f7bfc 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/19-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/19-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://localhost:8000%23' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%2F%2Flocalhost%3A8000%2523'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/20-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/20-expected.txt index c8f93e0..40d204a 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/20-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/20-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://localhost:8000:80' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%2F%2Flocalhost%3A8000%3A80'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/21-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/21-expected.txt index a8706ad..fa8cd92 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/21-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/21-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://localhost:8000, *' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%2F%2Flocalhost%3A8000%2C%20*'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/22-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/22-expected.txt index 4eff14d..b8de6a71 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/22-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/22-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%2F%2Flocalhost%3A8000%00'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/23-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/23-expected.txt index 803b780..da620100 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/23-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/23-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'HTTP://LOCALHOST:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=HTTP%3A%2F%2FLOCALHOST%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/24-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/24-expected.txt index fc720e9..fb6cda95 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/24-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/24-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'HTTP://localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=HTTP%3A%2F%2Flocalhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/25-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/25-expected.txt index 3a568d11..692babf44 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/25-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/25-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: '-' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=-'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/26-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/26-expected.txt index 74ff49c..491c789 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/26-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/26-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: '**' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=**'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/27-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/27-expected.txt index 98671f9..91d7724d 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/27-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/27-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: '*' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=%00*'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/28-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/28-expected.txt index dad5727..a0a6771 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/28-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/28-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: '*' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=*%00'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/29-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/29-expected.txt index f8b91d66..3f320c9 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/29-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/29-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: ''*'' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=%27*%27'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/30-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/30-expected.txt index c1efd9f5..ed3abcce 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/30-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/30-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: '"*"' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=%22*%22'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/31-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/31-expected.txt index 075b75f..4f4d190e 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/31-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/31-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: '* *' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=*%20*'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/32-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/32-expected.txt index 25c2a04..ded5d4d 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/32-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/32-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: '*http://*' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=*http%3A%2F%2F*'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/33-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/33-expected.txt index 92b66da8..c828457 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/33-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/33-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: '*http://localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=*http%3A%2F%2Flocalhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/34-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/34-expected.txt index 014cfb0..7c9fbf7 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/34-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/34-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: '* http://localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=*%20http%3A%2F%2Flocalhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/35-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/35-expected.txt index 3bcfb9ec..38ab613 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/35-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/35-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: '*, http://localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=*%2C%20http%3A%2F%2Flocalhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/36-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/36-expected.txt index a51b8e64..0548cc5 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/36-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/36-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=%00http%3A%2F%2Flocalhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/37-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/37-expected.txt index 5dfe5a3..73e9568 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/37-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/37-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'null http://localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=null%20http%3A%2F%2Flocalhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/38-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/38-expected.txt index 8cc0532..1faca74a 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/38-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/38-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://example.net' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%2F%2Fexample.net'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/39-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/39-expected.txt index 8fb0deb..f700915 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/39-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/39-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://example.net http://localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%2F%2Fexample.net%20http%3A%2F%2Flocalhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/40-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/40-expected.txt index a5e09fa..105f76888 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/40-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/40-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://example.net, http://localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%2F%2Fexample.net%2C%20http%3A%2F%2Flocalhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/41-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/41-expected.txt index f0a3eda..028f9a6c 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/41-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/41-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://example.net,http://localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origins=http%3A%2F%2Fexample.net,http%3A%2F%2Flocalhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/42-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/42-expected.txt index 6cc7fbc4..cf5cd539 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/42-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/42-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://localhost:8000,http://localhost:8000' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origins=http%3A%2F%2Flocalhost%3A8000,http%3A%2F%2Flocalhost%3A8000'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/43-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/43-expected.txt index 00b33b26..cd1aa89d 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/43-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/43-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'null' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=null'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/44-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/44-expected.txt index 9e8d17b..cf46e04 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/44-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/44-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: '' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin='.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/45-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/45-expected.txt index 211beb4..631fba0 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/45-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/45-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://localhost:8000/xmlhttprequest/resources/origin-exact-matching-iframe.html?45' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%2F%2Flocalhost%3A8000%2Fxmlhttprequest%2Fresources%2Forigin-exact-matching-iframe.html%3F45'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/46-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/46-expected.txt index 3ed8695..41b9181 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/46-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/46-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://localhost:8000/xmlhttprequest/resources/' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%2F%2Flocalhost%3A8000%2Fxmlhttprequest%2Fresources%2F'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/47-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/47-expected.txt index 89a7691..4f394314 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/47-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/origin-exact-matching/47-expected.txt
@@ -9,7 +9,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Should disallow origin: 'http://localhost:8000/xmlhttprequest/resources/origin-exact-matching-iframe.html?47' PASS xhr.send(null) threw exception NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/access-control-allow-lists.php?origin=http%3A%2F%2Flocalhost%3A8000%2Fxmlhttprequest%2Fresources%2Forigin-exact-matching-iframe.html%3F47'.. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/post-arraybuffer-data-view-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/post-arraybuffer-data-view-expected.txt index 96b0412..5061fac 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/post-arraybuffer-data-view-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/post-arraybuffer-data-view-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - xhr.readyState = 4: responseURL = http://127.0.0.1:8000/xmlhttprequest/resources/post-echo-as-ascii.cgi PASS status is "200" PASS responseText is "0 1 2 25 45 58 255"
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/post-blob-content-type-async-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/post-blob-content-type-async-expected.txt index a5f6b2ea..9364506 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/post-blob-content-type-async-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/post-blob-content-type-async-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS postedMimeType is "text/plain;charset=utf-8" PASS postedMimeType === undefined is true PASS postedMimeType === undefined is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/post-blob-content-type-sync-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/post-blob-content-type-sync-expected.txt index 353c26c..7cbb5be 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/post-blob-content-type-sync-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/post-blob-content-type-sync-expected.txt
@@ -4,7 +4,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS postedMimeType is "text/plain;charset=utf-8" PASS postedMimeType === undefined is true PASS postedMimeType === undefined is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/post-formdata-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/post-formdata-expected.txt index 296dc7b..6645ab8 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/post-formdata-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/post-formdata-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS echoResult is "string=string value" PASS echoResult is "bareBlob=blob:application/octet-stream:blob-value" PASS echoResult is "mimeBlob=blob:text/html:blob-value"
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/redirect-cross-origin-tripmine-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/redirect-cross-origin-tripmine-expected.txt index 99d88dd..078adfa3 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/redirect-cross-origin-tripmine-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/redirect-cross-origin-tripmine-expected.txt
@@ -23,7 +23,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Asynchronous XMLHttpRequest 307 POST redirect: PASS tripmineStatus is "" Asynchronous XMLHttpRequest 307 GET redirect:
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/remember-bad-password-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/remember-bad-password-expected.txt index 585d0516..621c9be 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/remember-bad-password-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/remember-bad-password-expected.txt
@@ -5,8 +5,9 @@ PASS + Sync With credentials Without credentials Async -With credentials Without credentials +With credentials Without credentials Status
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/reopen-encoding-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/reopen-encoding-expected.txt index fa6babf2..5d6d4da 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/reopen-encoding-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/reopen-encoding-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS req.getResponseHeader('Content-Type') is "text/plain; charset=utf-8" PASS req.responseText is "Проверка" PASS req.getResponseHeader('Content-Type') is "text/plain; charset=windows-1251"
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/response-array-buffer-abort-in-loading-state-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/response-array-buffer-abort-in-loading-state-expected.txt index e7cba64..cb7514e 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/response-array-buffer-abort-in-loading-state-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/response-array-buffer-abort-in-loading-state-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS xhr.status is 200 PASS xhr.response is null PASS xhr.response is null
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/response-blob-abort-in-loading-state-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/response-blob-abort-in-loading-state-expected.txt index e7cba64..cb7514e 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/response-blob-abort-in-loading-state-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/response-blob-abort-in-loading-state-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS xhr.status is 200 PASS xhr.response is null PASS xhr.response is null
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/response-blob-mimetype-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/response-blob-mimetype-expected.txt index b887720f..3a7aaedf 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/response-blob-mimetype-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/response-blob-mimetype-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS returnedMimeType is "multipart/mixed" PASS returnedMimeType is "text/plain" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/response-document-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/response-document-expected.txt index 3aab5e1..9cf95521 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/response-document-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/response-document-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS req.status is 200 PASS req.response is non-null. PASS result is "PASS"
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/response-text-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/response-text-expected.txt index f3dcab1..d030625 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/response-text-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/response-text-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS req.status is 200 PASS req.response is "PASS" PASS req.status is 200
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/responsexml-type-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/responsexml-type-expected.txt index 814ecb9..2b5c9886 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/responsexml-type-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/responsexml-type-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS responseDocument is "[object XMLDocument]" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/send-object-tostring-check-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/send-object-tostring-check-expected.txt index 11bd7f2..a159169 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/send-object-tostring-check-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/send-object-tostring-check-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS testObj.callCounter is 1 PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-expected.txt index 3bdff9dbd..b63d259 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS text/xml PASS image/svg+xml PASS application/soap+xml
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-invalid-1-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-invalid-1-expected.txt index a7413515..48394876 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-invalid-1-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-invalid-1-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS foo bar/baz+xml PASS foo[bar/baz+xml PASS foo]bar/baz+xml
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-invalid-2-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-invalid-2-expected.txt index 1e77e4f0..a413ad5 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-invalid-2-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-invalid-2-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS foo,bar/baz+xml PASS foo;bar/baz+xml PASS foo:bar/baz+xml
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-strange-valid-1-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-strange-valid-1-expected.txt index c485ea2..28470a67 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-strange-valid-1-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-strange-valid-1-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS foo_bar/baz+xml PASS foo-bar/baz+xml PASS foo+bar/baz+xml
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-strange-valid-2-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-strange-valid-2-expected.txt index ce3b2879..4797874 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-strange-valid-2-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/supported-xml-content-types-strange-valid-2-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS foo{bar/baz+xml PASS foo}bar/baz+xml PASS foo|bar/baz+xml
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/sync-xhr-revalidate-after-async-xhr-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/sync-xhr-revalidate-after-async-xhr-expected.txt index 1515392..40cc2ae 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/sync-xhr-revalidate-after-async-xhr-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/sync-xhr-revalidate-after-async-xhr-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS xhr2SendIsReturned is false PASS xhr1.responseText is not xhr2.responseText PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/upload-request-error-event-order-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/upload-request-error-event-order-expected.txt index a8a5912c..7059e0f 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/upload-request-error-event-order-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/upload-request-error-event-order-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS actualOrder is "rsdone,upload.onerror,upload.onloadend,onerror,onloadend," PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/web-apps/007-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/web-apps/007-expected.txt index 178f926..a7642360 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/web-apps/007-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/web-apps/007-expected.txt
@@ -1,4 +1,2 @@ CONSOLE WARNING: line 22: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. PASS - -
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/post-formdata-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/post-formdata-expected.txt index 8c4544c..9ef8ac6 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/post-formdata-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/post-formdata-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: ./resources/post-formdata-worker.js PASS [Worker] echoResult is "string=string value" PASS [Worker] echoResult is "bareBlob=blob:application/octet-stream:blob-value"
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/shared-worker-response-type-blob-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/shared-worker-response-type-blob-expected.txt index 6d361b2..4d743ca70 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/shared-worker-response-type-blob-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/shared-worker-response-type-blob-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: resources/xmlhttprequest-response-type-blob.js PASS [Worker] req.status is 200 PASS [Worker] req.response.size is 4
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/shared-worker-response-type-blob-sync-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/shared-worker-response-type-blob-sync-expected.txt index db64a7a..2c019cb 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/shared-worker-response-type-blob-sync-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/shared-worker-response-type-blob-sync-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: resources/xmlhttprequest-response-type-blob-sync.js PASS [Worker] req.status is 200 PASS [Worker] req.response.size is 4
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/xmlhttprequest-response-type-blob-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/xmlhttprequest-response-type-blob-expected.txt index b17a8c0..b1ca36a 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/xmlhttprequest-response-type-blob-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/xmlhttprequest-response-type-blob-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: resources/xmlhttprequest-response-type-blob.js PASS [Worker] req.status is 200 PASS [Worker] req.response.size is 4
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/xmlhttprequest-response-type-blob-sync-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/xmlhttprequest-response-type-blob-sync-expected.txt index 8be92fe..97164f2 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/xmlhttprequest-response-type-blob-sync-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/workers/xmlhttprequest-response-type-blob-sync-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: resources/xmlhttprequest-response-type-blob-sync.js PASS [Worker] req.status is 200 PASS [Worker] req.response.size is 4
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-inheritance-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-inheritance-expected.txt index feecd5b..215d74b 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-inheritance-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-inheritance-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS XMLHttpRequest.__proto__.name is "XMLHttpRequestEventTarget" PASS XMLHttpRequest.prototype.__proto__.constructor.name is "XMLHttpRequestEventTarget" FAIL className(XMLHttpRequest.prototype.__proto__) should be XMLHttpRequestEventTargetPrototype. Was XMLHttpRequestEventTarget.
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-mimetype-mixed-case-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-mimetype-mixed-case-expected.txt index f559e8e..5019e939 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-mimetype-mixed-case-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-mimetype-mixed-case-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS xhr.responseXML is non-null. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-overridemimetype-content-type-header-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-overridemimetype-content-type-header-expected.txt index 880b205..efcbe9a7 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-overridemimetype-content-type-header-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-overridemimetype-content-type-header-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS xhr.getResponseHeader("Content-Type") is "application/xml" PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-overridemimetype-mixed-case-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-overridemimetype-mixed-case-expected.txt index 9e63ca5..464d02b 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-overridemimetype-mixed-case-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-overridemimetype-mixed-case-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS xhr.responseXML is non-null. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-response-type-blob-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-response-type-blob-expected.txt index 858cf368..af351d80 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-response-type-blob-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-response-type-blob-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS req.status is 200 PASS req.response.size is 4 PASS buffer is "PASS"
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-responseText-exception-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-responseText-exception-expected.txt index 022f000..1c50a65 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-responseText-exception-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-responseText-exception-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS readyState = 1 PASS readyState = 2 PASS readyState = 3
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-sync-no-progress-events-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-sync-no-progress-events-expected.txt index 4a45f7fc1..d7cb951d 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-sync-no-progress-events-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-sync-no-progress-events-expected.txt
@@ -4,7 +4,7 @@ bug 40996: Progress event should not be fired during synchronous XMLHttpRequest; bug 17502: Assertion failure when trying to restart a sync XMLHttpRequest as an async one from onreadystatechange. - Step 1: Same origin request +Step 1: Same origin request readystatechange 4 load loadend
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-test-custom-headers-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-test-custom-headers-expected.txt index adf316e..d3d98e44 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-test-custom-headers-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-test-custom-headers-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS xhr.getResponseHeader("CONTENT-TYPE").indexOf("text/plain") is >= 0 PASS xhr.getResponseHeader("x-custom-header-single") is "single" PASS xhr.getResponseHeader("x-custom-header-empty") is ""
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-unload-sync-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-unload-sync-expected.txt index 5e9a72c..4b0cf22 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-unload-sync-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-unload-sync-expected.txt
@@ -2,4 +2,3 @@ Test behavior of sync XHR during unload PASS: sync XHR completed successfully -
diff --git a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-unsafe-redirect-expected.txt b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-unsafe-redirect-expected.txt index 4c1fd95..051f2c2b 100644 --- a/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-unsafe-redirect-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlhttprequest/xmlhttprequest-unsafe-redirect-expected.txt
@@ -3,9 +3,15 @@ CONSOLE ERROR: Access to XMLHttpRequest at 'http://localhost:8080/xmlhttprequest/resources/forbidden.txt' (redirected from 'http://127.0.0.1:8000/xmlhttprequest/resources/redirect.php?url=http://localhost:8080/xmlhttprequest/resources/forbidden.txt') from origin 'http://127.0.0.1:8000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. This tests that unsafe redirects won't be allowed when making an XMLHttpRequest. Sync XHR started. + readyState change 1 + Exception: NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://127.0.0.1:8000/xmlhttprequest/resources/redirect.php?url=http://localhost:8080/xmlhttprequest/resources/forbidden.txt'. + Async XHR started. + readyState change 1 + readyState change 4 + SUCCESS: Error handler was called with readyState 4
diff --git a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/mathml-expected.txt b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/mathml-expected.txt index a33ef7d..337e9cd 100644 --- a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/mathml-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/mathml-expected.txt
@@ -1,4 +1,5 @@ This XML file does not appear to have any style information associated with it. The document tree is shown below. + <!-- If you can see this, this test has failed, except if you are not using a MathML-aware client.
diff --git a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/svg-expected.txt b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/svg-expected.txt index 7e78584a..7ebd6cb 100644 --- a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/svg-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/svg-expected.txt
@@ -1,3 +1,2 @@ This tests that xml viewer is not used when there is a tag in SVG namespace. SUCCESS -
diff --git a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xlink-expected.txt b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xlink-expected.txt index 0ca26c54..c728d5d 100644 --- a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xlink-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xlink-expected.txt
@@ -1,4 +1,5 @@ This XML file does not appear to have any style information associated with it. The document tree is shown below. + <!-- If you can see this, this test has failed. --> <test xmlns="http://still-unknown.example.org/"> <header>
diff --git a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-charset-cp1251-expected.txt b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-charset-cp1251-expected.txt index 125772b..6900cf8 100644 --- a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-charset-cp1251-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-charset-cp1251-expected.txt
@@ -1,4 +1,5 @@ This XML file does not appear to have any style information associated with it. The document tree is shown below. + <root> <cp1251>SUССЕSS - These 'CCE' are cyrillic letters.</cp1251> </root>
diff --git a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-charset-utf8-expected.txt b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-charset-utf8-expected.txt index 41f0c7fe..15e05ea 100644 --- a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-charset-utf8-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-charset-utf8-expected.txt
@@ -1,4 +1,5 @@ This XML file does not appear to have any style information associated with it. The document tree is shown below. + <root> <utf8>SUССЕSS - These 'CCE' are cyrillic letters.</utf8> </root>
diff --git a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-clashing-element-id-tree-crash-expected.txt b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-clashing-element-id-tree-crash-expected.txt index 8e7847a0..904cc15 100644 --- a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-clashing-element-id-tree-crash-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-clashing-element-id-tree-crash-expected.txt
@@ -1,4 +1,5 @@ This XML file does not appear to have any style information associated with it. The document tree is shown below. + <organizations> <organization name="A"> <CEO name="B" id="tree">
diff --git a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-expected.txt b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-expected.txt index dfe510b..77c68c9 100644 --- a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-expected.txt
@@ -1,4 +1,5 @@ This XML file does not appear to have any style information associated with it. The document tree is shown below. + <?some-short-processing-instruction short-params?> <?some-long-processing-instruction The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy @@ -8,6 +9,7 @@ brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. + ?> <root-tag-with-mixed-content> <empty-tag/>
diff --git a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-root-element-id-tree-appearing-blank-expected.txt b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-root-element-id-tree-appearing-blank-expected.txt index 99d96c2f..44b1f61 100644 --- a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-root-element-id-tree-appearing-blank-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xmlviewer-root-element-id-tree-appearing-blank-expected.txt
@@ -1,4 +1,5 @@ This XML file does not appear to have any style information associated with it. The document tree is shown below. + <organization name="A" id="tree"> <CEO name="B"> <SalesManager name="C"/>
diff --git a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xul-expected.txt b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xul-expected.txt index 871d0ba..94115a9a 100644 --- a/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xul-expected.txt +++ b/third_party/blink/web_tests/http/tests/xmlviewer/dumpAsText/xul-expected.txt
@@ -1,4 +1,5 @@ This XML file does not appear to have any style information associated with it. The document tree is shown below. + <!-- If you can see this, this test has failed. --> <FAIL xmlns:a="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <header>
diff --git a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-worker-pause-task-order-expected.txt b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-worker-pause-task-order-expected.txt new file mode 100644 index 0000000..bb4bbb7 --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-worker-pause-task-order-expected.txt
@@ -0,0 +1,4 @@ +Tests that tasks order is not changed when worker is resumed. +Worker created +count must be 1: 1 +
diff --git a/third_party/blink/web_tests/inspector-protocol/debugger/debugger-worker-pause-task-order.js b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-worker-pause-task-order.js new file mode 100644 index 0000000..21764d4 --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/debugger/debugger-worker-pause-task-order.js
@@ -0,0 +1,41 @@ +(async function(testRunner) { + var {page, session, dp} = await testRunner.startBlank( + 'Tests that tasks order is not changed when worker is resumed.'); + dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: true}); + + await session.evaluate(` + const workerScript = \` + self.count = 0; + self.onmessage = msg => { + if (++self.count === 1) { + debugger; + console.log("Should be one:", self.count); + debugger; + } else { + (function FAIL_Should_Not_Pause_Here() { debugger; })(); + } + }; + //# sourceURL=worker.js\`; + const blob = new Blob([workerScript], { type: "text/javascript" }); + worker = new Worker(URL.createObjectURL(blob)); + worker.postMessage(1); + `); + + const event = await dp.Target.onceAttachedToTarget(); + const worker = new WorkerProtocol(dp, event.params.sessionId); + testRunner.log('Worker created'); + + await worker.dp.Debugger.enable(); + + worker.dp.Runtime.runIfWaitingForDebugger(); + await worker.dp.Debugger.oncePaused(); + + await session.evaluate(`worker.postMessage(2)`); + worker.dp.Debugger.resume(); + await worker.dp.Debugger.oncePaused(); + const result = await worker.dp.Runtime.evaluate({expression: 'self.count'}); + testRunner.log(`count must be 1: ${result.result.value}`); + + await worker.dp.Debugger.disable(); + testRunner.completeTest(); +})
diff --git a/third_party/blink/web_tests/media/controls/controls-layout-in-different-size.html b/third_party/blink/web_tests/media/controls/controls-layout-in-different-size.html new file mode 100644 index 0000000..143b16a --- /dev/null +++ b/third_party/blink/web_tests/media/controls/controls-layout-in-different-size.html
@@ -0,0 +1,56 @@ +<!DOCTYPE html> +<html> +<title>Media Controls: Test controls layout correctly in different small sizes.</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../media-controls.js"></script> +<video controls></video> +<script> +async_test(t => { + const video = document.querySelector('video'); + video.src = '../content/test.ogv'; + + video.onloadedmetadata = t.step_func(() => { + // We are testing the changing of sizes instead of single test cases + // because the layout flilkering issue typically happen when changing + // from small size to big size. + const testCases = [ 400, 100, 180, 200, 100, 200, 100, 250, 100, 300 ]; + const buttonPanel = buttonPanelElement(video); + const overflowBtn = overflowButton(video); + + runTestCase(0); + + function runTestCase(index) { + let test = testCases[index]; + video.width = test; + testRunner.layoutAndPaintAsyncThen(t.step_func(() => { + expectLayoutCorrectly(); + + assert_not_equals(getComputedStyle(overflowBtn), 'none', + 'Overflow button should always be visible'); + + let nextIndex = index + 1; + if (nextIndex === testCases.length) { + t.done(); + return; + } + runTestCase(nextIndex); + })); + } + + function expectLayoutCorrectly() { + let totalWidth = 0; + let children = buttonPanel.children; + for (let i = 0; i < children.length; i++) { + let child = children[i]; + if (getComputedStyle(child).display != 'none') + totalWidth += child.getBoundingClientRect().width; + } + + assert_true(totalWidth <= buttonPanel.getBoundingClientRect().width, + 'All element should fit in button panel'); + } + }); +}); +</script> +</html>
diff --git a/third_party/blink/web_tests/media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html b/third_party/blink/web_tests/media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html index 1c434cf8..fb861ad 100644 --- a/third_party/blink/web_tests/media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html +++ b/third_party/blink/web_tests/media/controls/video-enter-exit-fullscreen-without-hovering-doesnt-show-controls.html
@@ -29,6 +29,8 @@ // Move mouse away so it no longer hovers over controls/video. eventSender.mouseMoveTo(0, 0); + video.blur(); + runAfterHideMediaControlsTimerFired(t.step_func(function() { assert_equals(getComputedStyle(panel).opacity, "0", "Inline controls should be hidden by timer");
diff --git a/third_party/blink/web_tests/media/video-controls-mouse-events-captured.html b/third_party/blink/web_tests/media/video-controls-mouse-events-captured.html index 85c1e1a..3406961 100644 --- a/third_party/blink/web_tests/media/video-controls-mouse-events-captured.html +++ b/third_party/blink/web_tests/media/video-controls-mouse-events-captured.html
@@ -14,7 +14,6 @@ video.onpointerup = t.unreached_func(); video.onmousedown = t.unreached_func(); video.onmouseup = t.unreached_func(); - video.onkeydown = t.unreached_func(); video.onloadeddata = t.step_func_done(function() { // click the play button. @@ -58,7 +57,6 @@ function sendMouseAndKeyEvents() { eventSender.mouseDown(); eventSender.mouseUp(); - eventSender.keyDown('A'); } video.src = "content/test.ogv";
diff --git a/third_party/blink/web_tests/media/video-mouse-focus.html b/third_party/blink/web_tests/media/video-mouse-focus.html index 8b8ba7e..e119f0041 100644 --- a/third_party/blink/web_tests/media/video-mouse-focus.html +++ b/third_party/blink/web_tests/media/video-mouse-focus.html
@@ -1,5 +1,5 @@ <!DOCTYPE html> -<title>This tests that a mouse click event will not cause a media element to gain focus.</title> +<title>This tests that a mouse click event will cause a media element to gain focus.</title> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="media-controls.js"></script> @@ -14,10 +14,10 @@ eventSender.mouseMoveTo(x, y); eventSender.mouseDown(); eventSender.mouseUp(); - assert_not_equals(document.activeElement, video); + assert_equals(document.activeElement, video); // Click on the play button. mediaControlsButton(video, "play-button").click(); - assert_not_equals(document.activeElement, video); + assert_equals(document.activeElement, video); }); -</script> \ No newline at end of file +</script>
diff --git a/third_party/blink/web_tests/mojo/bind-interface.html b/third_party/blink/web_tests/mojo/bind-interface.html index f068eac2..c11e1e8 100644 --- a/third_party/blink/web_tests/mojo/bind-interface.html +++ b/third_party/blink/web_tests/mojo/bind-interface.html
@@ -2,13 +2,13 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/content/test/data/mojo_layouttest_test.mojom.js"></script> +<script src="file:///gen/content/test/data/mojo_web_test_helper_test.mojom.js"></script> <script src="resources/helpers.js"></script> <script> promise_test(() => { - let helper = new content.mojom.MojoLayoutTestHelperPtr; - Mojo.bindInterface(content.mojom.MojoLayoutTestHelper.name, + let helper = new content.mojom.MojoWebTestHelperPtr; + Mojo.bindInterface(content.mojom.MojoWebTestHelper.name, mojo.makeRequest(helper).handle); const kTestMessage = "hello world."; @@ -21,14 +21,14 @@ promise_test(() => { let helperImpl = new TestHelperImpl; let interceptor = - new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name); + new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name); interceptor.oninterfacerequest = e => { helperImpl.bindRequest(e.handle); }; interceptor.start(); - let helper = new content.mojom.MojoLayoutTestHelperPtr; - Mojo.bindInterface(content.mojom.MojoLayoutTestHelper.name, + let helper = new content.mojom.MojoWebTestHelperPtr; + Mojo.bindInterface(content.mojom.MojoWebTestHelper.name, mojo.makeRequest(helper).handle); interceptor.stop(); @@ -42,14 +42,14 @@ // requested at "process" scope. let helperImpl = new TestHelperImpl; let interceptor = - new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name); + new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name); interceptor.oninterfacerequest = e => { helperImpl.bindRequest(e.handle); }; interceptor.start(); - let helper = new content.mojom.MojoLayoutTestHelperPtr; - Mojo.bindInterface(content.mojom.MojoLayoutTestHelper.name, + let helper = new content.mojom.MojoWebTestHelperPtr; + Mojo.bindInterface(content.mojom.MojoWebTestHelper.name, mojo.makeRequest(helper).handle, "process"); @@ -65,14 +65,14 @@ promise_test(() => { let helperImpl = new TestHelperImpl; let interceptor = new MojoInterfaceInterceptor( - content.mojom.MojoLayoutTestHelper.name, "process"); + content.mojom.MojoWebTestHelper.name, "process"); interceptor.oninterfacerequest = e => { helperImpl.bindRequest(e.handle); }; interceptor.start(); - let helper = new content.mojom.MojoLayoutTestHelperPtr; - Mojo.bindInterface(content.mojom.MojoLayoutTestHelper.name, + let helper = new content.mojom.MojoWebTestHelperPtr; + Mojo.bindInterface(content.mojom.MojoWebTestHelper.name, mojo.makeRequest(helper).handle, "process"); interceptor.stop(); @@ -83,8 +83,8 @@ }, "can intercept interfaces at process scope"); test(() => { - let a = new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name); - let b = new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name); + let a = new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name); + let b = new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name); a.oninterfacerequest = () => {}; b.oninterfacerequest = () => {}; a.start(); @@ -93,9 +93,9 @@ }, "interface interceptors are mutually exclusive"); test(() => { - let a = new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name, + let a = new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name, "process"); - let b = new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name, + let b = new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name, "process"); a.oninterfacerequest = () => {}; b.oninterfacerequest = () => {}; @@ -107,7 +107,7 @@ promise_test(async t => { // First check that the interceptor can be started and intercepts requests. let interceptor = - new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name); + new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name); let promise = new Promise(resolve => { interceptor.oninterfacerequest = e => { resolve(e.handle); @@ -116,7 +116,7 @@ interceptor.start(); let pipe = Mojo.createMessagePipe(); - Mojo.bindInterface(content.mojom.MojoLayoutTestHelper.name, pipe.handle0); + Mojo.bindInterface(content.mojom.MojoWebTestHelper.name, pipe.handle0); let interceptedHandle = await promise; assert_true(interceptedHandle instanceof MojoHandle); interceptedHandle.close(); @@ -125,11 +125,11 @@ // Stop the interceptor and make another request. interceptor.stop(); - let helper = new content.mojom.MojoLayoutTestHelperPtr; + let helper = new content.mojom.MojoWebTestHelperPtr; interceptor.oninterfacerequest = t.step_func(() => { assert_unreached("unexpected 'interfacerequest' event after stop"); }); - Mojo.bindInterface(content.mojom.MojoLayoutTestHelper.name, + Mojo.bindInterface(content.mojom.MojoWebTestHelper.name, mojo.makeRequest(helper).handle); // Enusre that the interface is functioning, i.e. the request definitely was @@ -142,7 +142,7 @@ // And ensure that we can start a new interceptor for the same interface since // the previous one was stopped. interceptor = - new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name); + new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name); interceptor.oninterfacerequest = e => {}; interceptor.start(); interceptor.stop();
diff --git a/third_party/blink/web_tests/mojo/detached-frame.html b/third_party/blink/web_tests/mojo/detached-frame.html index 0bea05d..b8a7d644 100644 --- a/third_party/blink/web_tests/mojo/detached-frame.html +++ b/third_party/blink/web_tests/mojo/detached-frame.html
@@ -2,7 +2,7 @@ <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/content/test/data/mojo_layouttest_test.mojom.js"></script> +<script src="file:///gen/content/test/data/mojo_web_test_helper_test.mojom.js"></script> <body> <script> @@ -27,8 +27,8 @@ let frameMojo = frame.contentWindow.Mojo; document.body.removeChild(frame); - let helper = new content.mojom.MojoLayoutTestHelperPtr; - frameMojo.bindInterface(content.mojom.MojoLayoutTestHelper.name, + let helper = new content.mojom.MojoWebTestHelperPtr; + frameMojo.bindInterface(content.mojom.MojoWebTestHelper.name, mojo.makeRequest(helper).handle); try { @@ -52,7 +52,7 @@ document.body.removeChild(frame); let interceptor = new frameMojoInterfaceInterceptor( - content.mojom.MojoLayoutTestHelper.name); + content.mojom.MojoWebTestHelper.name); try { interceptor.start(); assert_unreached(); @@ -70,7 +70,7 @@ // Create the interceptor while the frame is attached so that it is associated // with the frame's execution context. let interceptor = new frame.contentWindow.MojoInterfaceInterceptor( - content.mojom.MojoLayoutTestHelper.name); + content.mojom.MojoWebTestHelper.name); document.body.removeChild(frame); try { @@ -89,7 +89,7 @@ // Create the interceptor and start it while the frame is attached. let interceptor = new frame.contentWindow.MojoInterfaceInterceptor( - content.mojom.MojoLayoutTestHelper.name); + content.mojom.MojoWebTestHelper.name); interceptor.start(); document.body.removeChild(frame);
diff --git a/third_party/blink/web_tests/mojo/resources/bind-intercepted-interface-in-worker.js b/third_party/blink/web_tests/mojo/resources/bind-intercepted-interface-in-worker.js index 3b1340a..7386652 100644 --- a/third_party/blink/web_tests/mojo/resources/bind-intercepted-interface-in-worker.js +++ b/third_party/blink/web_tests/mojo/resources/bind-intercepted-interface-in-worker.js
@@ -1,19 +1,19 @@ importScripts('../../resources/testharness.js'); importScripts('file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js'); -importScripts('file:///gen/content/test/data/mojo_layouttest_test.mojom.js'); +importScripts('file:///gen/content/test/data/mojo_web_test_helper_test.mojom.js'); importScripts('helpers.js'); promise_test(async () => { let helperImpl = new TestHelperImpl; let interceptor = - new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name); + new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name); interceptor.oninterfacerequest = e => { helperImpl.bindRequest(e.handle); }; interceptor.start(); - let helper = new content.mojom.MojoLayoutTestHelperPtr; - Mojo.bindInterface(content.mojom.MojoLayoutTestHelper.name, + let helper = new content.mojom.MojoWebTestHelperPtr; + Mojo.bindInterface(content.mojom.MojoWebTestHelper.name, mojo.makeRequest(helper).handle); let response = await helper.reverse('the string'); @@ -25,7 +25,7 @@ assert_throws( 'NotSupportedError', () => { - new MojoInterfaceInterceptor(content.mojom.MojoLayoutTestHelper.name, + new MojoInterfaceInterceptor(content.mojom.MojoWebTestHelper.name, "process"); }); }, 'Cannot create a MojoInterfaceInterceptor with process scope');
diff --git a/third_party/blink/web_tests/mojo/resources/helpers.js b/third_party/blink/web_tests/mojo/resources/helpers.js index 31178fe..ed50937a 100644 --- a/third_party/blink/web_tests/mojo/resources/helpers.js +++ b/third_party/blink/web_tests/mojo/resources/helpers.js
@@ -5,7 +5,7 @@ class TestHelperImpl { constructor() { this.binding_ = - new mojo.Binding(content.mojom.MojoLayoutTestHelper, this); + new mojo.Binding(content.mojom.MojoWebTestHelper, this); } bindRequest(request) { this.binding_.bind(request); } getLastString() { return this.lastString_; }
diff --git a/third_party/blink/web_tests/paint/invalidation/clip/clip-path-constant-repaint-expected.txt b/third_party/blink/web_tests/paint/invalidation/clip/clip-path-constant-repaint-expected.txt index 6409953..e41d2677 100644 --- a/third_party/blink/web_tests/paint/invalidation/clip/clip-path-constant-repaint-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/clip/clip-path-constant-repaint-expected.txt
@@ -26,6 +26,7 @@ { "name": "Mask Layer", "bounds": [800, 300], + "backfaceVisibility": "hidden", "paintInvalidations": [ { "object": "Mask Layer",
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants-expected.txt index 690d34d..78d6b28 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants-expected.txt
@@ -24,12 +24,6 @@ "transform": 1 }, { - "name": "Child Containment Layer", - "bounds": [100, 100], - "drawsContent": false, - "transform": 1 - }, - { "name": "LayoutBlockFlow DIV class='clipped-composited-child'", "bounds": [252, 252], "contentsOpaque": true, @@ -43,12 +37,6 @@ "transform": 3 }, { - "name": "Child Containment Layer", - "bounds": [100, 100], - "drawsContent": false, - "transform": 3 - }, - { "name": "LayoutBlockFlow DIV class='clipped-composited-child'", "bounds": [252, 252], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/overlap-test-with-filter-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/overlap-test-with-filter-expected.txt index 06f94a7..d4917843 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/overlap-test-with-filter-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/compositing/overlap-test-with-filter-expected.txt
@@ -27,11 +27,6 @@ "backgroundColor": "#FFFF00" }, { - "name": "Child Containment Layer", - "bounds": [300, 100], - "drawsContent": false - }, - { "name": "LayoutBlockFlow BODY", "bounds": [284, 84], "backgroundColor": "#FFFF00",
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt index 15fb475..5986dc3 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt
@@ -18,9 +18,7 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Ancestor Clipping Layer", - "position": [8, 8], - "bounds": [185, 185], + "name": "Squashing Containment Layer", "drawsContent": false }, {
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/scrolling-neg-z-index-descendants-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/scrolling-neg-z-index-descendants-expected.txt index e24b05c..77025f8e2 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/scrolling-neg-z-index-descendants-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/compositing/scrolling-neg-z-index-descendants-expected.txt
@@ -25,7 +25,8 @@ { "name": "LayoutBlockFlow (relative positioned) DIV id='neg-z'", "position": [9, -81], - "bounds": [100, 410] + "bounds": [100, 410], + "backfaceVisibility": "hidden" }, { "name": "LayoutBlockFlow HTML (foreground) Layer", @@ -48,6 +49,7 @@ "position": [9, 9], "bounds": [100, 430], "drawsContent": false, + "backfaceVisibility": "hidden", "transform": 1 }, { @@ -60,12 +62,14 @@ { "name": "Horizontal Scrollbar Layer", "position": [9, 309], - "bounds": [100, 0] + "bounds": [100, 0], + "backfaceVisibility": "hidden" }, { "name": "Vertical Scrollbar Layer", "position": [109, 9], - "bounds": [0, 300] + "bounds": [0, 300], + "backfaceVisibility": "hidden" } ], "transforms": [
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/should-not-repaint-composited-descendants-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/should-not-repaint-composited-descendants-expected.txt index b479ab4..ec7710c 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/should-not-repaint-composited-descendants-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/compositing/should-not-repaint-composited-descendants-expected.txt
@@ -38,12 +38,6 @@ ] }, { - "name": "Child Containment Layer", - "position": [38, 38], - "bounds": [90, 90], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV class='composited child'", "position": [8, 58], "bounds": [50, 50],
diff --git a/third_party/blink/web_tests/paint/invalidation/compositing/should-not-repaint-composited-descendants-on-overflow-change-expected.txt b/third_party/blink/web_tests/paint/invalidation/compositing/should-not-repaint-composited-descendants-on-overflow-change-expected.txt index 06aafe1..1e0b2bb 100644 --- a/third_party/blink/web_tests/paint/invalidation/compositing/should-not-repaint-composited-descendants-on-overflow-change-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/compositing/should-not-repaint-composited-descendants-on-overflow-change-expected.txt
@@ -25,12 +25,6 @@ "backgroundColor": "#008000" }, { - "name": "Ancestor Clipping Layer", - "position": [0, 200], - "bounds": [200, 200], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV class='composited-child'", "position": [0, 200], "bounds": [100, 100], @@ -47,12 +41,6 @@ "backgroundColor": "#008000" }, { - "name": "Ancestor Clipping Layer", - "position": [0, 200], - "bounds": [200, 200], - "drawsContent": false - }, - { "name": "LayoutBlockFlow (relative positioned) DIV class='composited-child overflow-child'", "position": [150, 350], "bounds": [100, 100],
diff --git a/third_party/blink/web_tests/paint/invalidation/scroll/composited-iframe-scroll-repaint-expected.txt b/third_party/blink/web_tests/paint/invalidation/scroll/composited-iframe-scroll-repaint-expected.txt index d7a9f930..4e0f7c45 100644 --- a/third_party/blink/web_tests/paint/invalidation/scroll/composited-iframe-scroll-repaint-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/scroll/composited-iframe-scroll-repaint-expected.txt
@@ -18,12 +18,6 @@ "backgroundColor": "#FFFFFF" }, { - "name": "Ancestor Clipping Layer", - "position": [8, 8], - "bounds": [784, 159], - "drawsContent": false - }, - { "name": "LayoutIFrame IFRAME", "position": [8, 8], "bounds": [304, 154]
diff --git a/third_party/blink/web_tests/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container-expected.txt b/third_party/blink/web_tests/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container-expected.txt index 04c2902..18abbef 100644 --- a/third_party/blink/web_tests/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container-expected.txt +++ b/third_party/blink/web_tests/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container-expected.txt
@@ -25,12 +25,6 @@ ] }, { - "name": "Ancestor Clipping Layer", - "position": [8, 8], - "bounds": [285, 285], - "drawsContent": false - }, - { "name": "LayoutBlockFlow (positioned) DIV id='container'", "bounds": [600, 600], "contentsOpaque": true, @@ -53,8 +47,7 @@ [0, 1, 0, 0], [0, 0, 1, 0], [-307, 8, 0, 1] - ], - "flattenInheritedTransform": false + ] } ] }
diff --git a/third_party/blink/web_tests/fast/repaint/sub-frame-svg-background-expected.html b/third_party/blink/web_tests/paint/invalidation/sub-frame-svg-background-expected.html similarity index 100% rename from third_party/blink/web_tests/fast/repaint/sub-frame-svg-background-expected.html rename to third_party/blink/web_tests/paint/invalidation/sub-frame-svg-background-expected.html
diff --git a/third_party/blink/web_tests/fast/repaint/sub-frame-svg-background.html b/third_party/blink/web_tests/paint/invalidation/sub-frame-svg-background.html similarity index 100% rename from third_party/blink/web_tests/fast/repaint/sub-frame-svg-background.html rename to third_party/blink/web_tests/paint/invalidation/sub-frame-svg-background.html
diff --git a/third_party/blink/web_tests/platform/android/webmidi/send-messages-expected.txt b/third_party/blink/web_tests/platform/android/webmidi/send-messages-expected.txt index 27b298d..452bf1e 100644 --- a/third_party/blink/web_tests/platform/android/webmidi/send-messages-expected.txt +++ b/third_party/blink/web_tests/platform/android/webmidi/send-messages-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS navigator.requestMIDIAccess is defined. PASS output.send([0x00, 0x01]) threw exception TypeError: Failed to execute 'send' on 'MIDIOutput': Running status is not allowed at index 0 (0).. PASS output.send([0xf7]) threw exception TypeError: Failed to execute 'send' on 'MIDIOutput': Unexpected end of system exclusive message at index 0 (247)..
diff --git a/third_party/blink/web_tests/platform/linux/compositing/direct-image-compositing-expected.png b/third_party/blink/web_tests/platform/linux/compositing/direct-image-compositing-expected.png index bb3c623..b9ff78c 100644 --- a/third_party/blink/web_tests/platform/linux/compositing/direct-image-compositing-expected.png +++ b/third_party/blink/web_tests/platform/linux/compositing/direct-image-compositing-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/compositing/geometry/layer-due-to-layer-children-expected.png b/third_party/blink/web_tests/platform/linux/compositing/geometry/layer-due-to-layer-children-expected.png index 59e62676..6779dec 100644 --- a/third_party/blink/web_tests/platform/linux/compositing/geometry/layer-due-to-layer-children-expected.png +++ b/third_party/blink/web_tests/platform/linux/compositing/geometry/layer-due-to-layer-children-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/compositing/masks/direct-image-mask-expected.png b/third_party/blink/web_tests/platform/linux/compositing/masks/direct-image-mask-expected.png index 187bc849..e7dcf18 100644 --- a/third_party/blink/web_tests/platform/linux/compositing/masks/direct-image-mask-expected.png +++ b/third_party/blink/web_tests/platform/linux/compositing/masks/direct-image-mask-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/compositing/masks/mask-with-added-filters-expected.png b/third_party/blink/web_tests/platform/linux/compositing/masks/mask-with-added-filters-expected.png index 95d697f..fd5a085 100644 --- a/third_party/blink/web_tests/platform/linux/compositing/masks/mask-with-added-filters-expected.png +++ b/third_party/blink/web_tests/platform/linux/compositing/masks/mask-with-added-filters-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/compositing/masks/mask-with-removed-filters-expected.png b/third_party/blink/web_tests/platform/linux/compositing/masks/mask-with-removed-filters-expected.png index bf05d030..297dbc4 100644 --- a/third_party/blink/web_tests/platform/linux/compositing/masks/mask-with-removed-filters-expected.png +++ b/third_party/blink/web_tests/platform/linux/compositing/masks/mask-with-removed-filters-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/compositing/masks/masked-ancestor-expected.png b/third_party/blink/web_tests/platform/linux/compositing/masks/masked-ancestor-expected.png index 2893d5c6..a204713 100644 --- a/third_party/blink/web_tests/platform/linux/compositing/masks/masked-ancestor-expected.png +++ b/third_party/blink/web_tests/platform/linux/compositing/masks/masked-ancestor-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/compositing/masks/multiple-masks-expected.png b/third_party/blink/web_tests/platform/linux/compositing/masks/multiple-masks-expected.png index 50633eb..0989690 100644 --- a/third_party/blink/web_tests/platform/linux/compositing/masks/multiple-masks-expected.png +++ b/third_party/blink/web_tests/platform/linux/compositing/masks/multiple-masks-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/compositing/masks/simple-composited-mask-expected.png b/third_party/blink/web_tests/platform/linux/compositing/masks/simple-composited-mask-expected.png index a4ea481..97c3286 100644 --- a/third_party/blink/web_tests/platform/linux/compositing/masks/simple-composited-mask-expected.png +++ b/third_party/blink/web_tests/platform/linux/compositing/masks/simple-composited-mask-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/compositing/overflow/nested-border-radius-clipping-expected.png b/third_party/blink/web_tests/platform/linux/compositing/overflow/nested-border-radius-clipping-expected.png index f422893..2d2b608c 100644 --- a/third_party/blink/web_tests/platform/linux/compositing/overflow/nested-border-radius-clipping-expected.png +++ b/third_party/blink/web_tests/platform/linux/compositing/overflow/nested-border-radius-clipping-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png b/third_party/blink/web_tests/platform/linux/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png index 9d6184b2..f2408a41 100644 --- a/third_party/blink/web_tests/platform/linux/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png +++ b/third_party/blink/web_tests/platform/linux/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/custom-elements/form-validation-bubble-appearance-expected.png b/third_party/blink/web_tests/platform/linux/custom-elements/form-validation-bubble-appearance-expected.png new file mode 100644 index 0000000..6d6b8882 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/custom-elements/form-validation-bubble-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-canvas-border-expected.png b/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-canvas-border-expected.png index b74dd02..10863d7 100644 --- a/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-canvas-border-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-canvas-border-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-canvas-expected.png b/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-canvas-expected.png index ee379af6..e4c1f2e 100644 --- a/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-canvas-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-canvas-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-canvas-with-mask-expected.png b/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-canvas-with-mask-expected.png index c6f4b6f..80ef073 100644 --- a/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-canvas-with-mask-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-canvas-with-mask-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-video-expected.png b/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-video-expected.png index 6e29ef2..286f1e2f 100644 --- a/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-video-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-video-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-video-ratio-expected.png b/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-video-ratio-expected.png index cea0333..b07697d1 100644 --- a/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-video-ratio-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-video-ratio-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-video-shadow-expected.png b/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-video-shadow-expected.png index de945bf..7e26cf82 100644 --- a/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-video-shadow-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/borders/border-radius-mask-video-shadow-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/clip/overflow-border-radius-composited-expected.png b/third_party/blink/web_tests/platform/linux/fast/clip/overflow-border-radius-composited-expected.png index 3e6a684..ee5d598 100644 --- a/third_party/blink/web_tests/platform/linux/fast/clip/overflow-border-radius-composited-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/clip/overflow-border-radius-composited-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/clip/overflow-border-radius-composited-parent-expected.png b/third_party/blink/web_tests/platform/linux/fast/clip/overflow-border-radius-composited-parent-expected.png index f1f8011..c484574 100644 --- a/third_party/blink/web_tests/platform/linux/fast/clip/overflow-border-radius-composited-parent-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/clip/overflow-border-radius-composited-parent-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/multicol/composited-layer-nested-expected.png b/third_party/blink/web_tests/platform/linux/fast/multicol/composited-layer-nested-expected.png index f7c58c98..d749b58 100644 --- a/third_party/blink/web_tests/platform/linux/fast/multicol/composited-layer-nested-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/multicol/composited-layer-nested-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/multicol/vertical-rl/composited-relpos-overlapping-will-change-expected.png b/third_party/blink/web_tests/platform/linux/fast/multicol/vertical-rl/composited-relpos-overlapping-will-change-expected.png index d64e33c..ba0f2e7 100644 --- a/third_party/blink/web_tests/platform/linux/fast/multicol/vertical-rl/composited-relpos-overlapping-will-change-expected.png +++ b/third_party/blink/web_tests/platform/linux/fast/multicol/vertical-rl/composited-relpos-overlapping-will-change-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/media/video-zoom-controls-expected.png b/third_party/blink/web_tests/platform/linux/media/video-zoom-controls-expected.png index 158cb0c9..88a4bf83 100644 --- a/third_party/blink/web_tests/platform/linux/media/video-zoom-controls-expected.png +++ b/third_party/blink/web_tests/platform/linux/media/video-zoom-controls-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/composite-after-paint/selection-within-composited-scroller-expected.png b/third_party/blink/web_tests/platform/linux/paint/invalidation/composite-after-paint/selection-within-composited-scroller-expected.png deleted file mode 100644 index 1685c1de..0000000 --- a/third_party/blink/web_tests/platform/linux/paint/invalidation/composite-after-paint/selection-within-composited-scroller-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/composite-after-paint/text-match-highlight-expected.png b/third_party/blink/web_tests/platform/linux/paint/invalidation/composite-after-paint/text-match-highlight-expected.png deleted file mode 100644 index 62738a2..0000000 --- a/third_party/blink/web_tests/platform/linux/paint/invalidation/composite-after-paint/text-match-highlight-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/filters-example-01-b-expected.png b/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/filters-example-01-b-expected.png index aba609595..e8f85c4 100644 --- a/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/filters-example-01-b-expected.png +++ b/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/filters-example-01-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/text-deco-01-b-expected.png b/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/text-deco-01-b-expected.png index fe57cbd..6337816e 100644 --- a/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/text-deco-01-b-expected.png +++ b/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/text-deco-01-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/text-text-08-b-expected.png b/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/text-text-08-b-expected.png index c30799cd..de0a1de 100644 --- a/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/text-text-08-b-expected.png +++ b/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/text-text-08-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/text/text-selection-deco-01-b-expected.png b/third_party/blink/web_tests/platform/linux/svg/text/text-selection-deco-01-b-expected.png index ba058117..417c29a8 100644 --- a/third_party/blink/web_tests/platform/linux/svg/text/text-selection-deco-01-b-expected.png +++ b/third_party/blink/web_tests/platform/linux/svg/text/text-selection-deco-01-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/text/text-selection-text-08-b-expected.png b/third_party/blink/web_tests/platform/linux/svg/text/text-selection-text-08-b-expected.png index a0836426..bbb2a862 100644 --- a/third_party/blink/web_tests/platform/linux/svg/text/text-selection-text-08-b-expected.png +++ b/third_party/blink/web_tests/platform/linux/svg/text/text-selection-text-08-b-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-2-expected.png b/third_party/blink/web_tests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-2-expected.png index b311d811..de65a5a 100644 --- a/third_party/blink/web_tests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-2-expected.png +++ b/third_party/blink/web_tests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/blink/web_tests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png index 17f9339..8e82ce5 100644 --- a/third_party/blink/web_tests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png +++ b/third_party/blink/web_tests/platform/linux/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/compositing/geometry/outline-change-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/compositing/geometry/outline-change-expected.png deleted file mode 100644 index d41c276..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/compositing/geometry/outline-change-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/block/basic/018-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/block/basic/018-expected.png deleted file mode 100644 index 67f8f31..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/block/basic/018-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/borders/border-image-scale-transform-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/borders/border-image-scale-transform-expected.png deleted file mode 100644 index d59f93ec..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/borders/border-image-scale-transform-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/001-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/001-expected.png deleted file mode 100644 index 567d32a..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/001-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/002-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/002-expected.png deleted file mode 100644 index 8ae790fd..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/002-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/002-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/002-expected.txt deleted file mode 100644 index c92f50b5..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/002-expected.txt +++ /dev/null
@@ -1,12 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x136 - LayoutBlockFlow {HTML} at (0,0) size 800x136 - LayoutBlockFlow {BODY} at (8,8) size 784x120 - LayoutBlockFlow (anonymous) at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 514x19 - text run at (0,0) width 291: "You should see a 100x100 green square below. " - text run at (290,0) width 224: "If you see any red, the test has failed." -layer at (8,28) size 100x100 scrollHeight 200 - LayoutBlockFlow {DIV} at (0,20) size 100x100 [bgcolor=#008000] - LayoutBlockFlow {DIV} at (0,100) size 100x100 [bgcolor=#FF0000]
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/003-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/003-expected.png deleted file mode 100644 index 479e9d6..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/003-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/003-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/003-expected.txt deleted file mode 100644 index 3c1ff0ae..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/003-expected.txt +++ /dev/null
@@ -1,14 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x136 - LayoutBlockFlow {HTML} at (0,0) size 800x136 - LayoutBlockFlow {BODY} at (8,8) size 784x120 - LayoutBlockFlow (anonymous) at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 514x19 - text run at (0,0) width 291: "You should see a 100x100 green square below. " - text run at (290,0) width 224: "If you see any red, the test has failed." -layer at (8,28) size 100x100 scrollWidth 200 scrollHeight 200 - LayoutBlockFlow {DIV} at (0,20) size 100x100 - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (150,100) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (150,100) size 100x100 [bgcolor=#008000]
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/004-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/004-expected.png deleted file mode 100644 index 419a195..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/004-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/004-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/004-expected.txt deleted file mode 100644 index 479c115..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/004-expected.txt +++ /dev/null
@@ -1,17 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x56 - LayoutBlockFlow {HTML} at (0,0) size 800x56 - LayoutBlockFlow {BODY} at (8,8) size 784x40 - LayoutText {#text} at (0,0) size 777x39 - text run at (0,0) width 291: "You should see a 100x100 green square below. " - text run at (290,0) width 228: "If you see any red, the test has failed. " - text run at (517,0) width 260: "This test is checking to make sure overflow" - text run at (0,20) width 81: "is done using " - text run at (81,20) width 154: "a containing block model." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,48) size 100x100 scrollWidth 200 scrollHeight 400 - LayoutBlockFlow (positioned) {DIV} at (8,48) size 100x100 [bgcolor=#008000] - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (108,348) size 100x100 backgroundClip at (8,48) size 100x100 clip at (8,48) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (100,300) size 100x100 [bgcolor=#FF0000]
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/005-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/005-expected.png deleted file mode 100644 index 419a195..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/005-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/005-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/005-expected.txt deleted file mode 100644 index 9b3a4e2..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/005-expected.txt +++ /dev/null
@@ -1,17 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x156 - LayoutBlockFlow {HTML} at (0,0) size 800x156 - LayoutBlockFlow {BODY} at (8,8) size 784x140 - LayoutBlockFlow (anonymous) at (0,0) size 784x40 - LayoutText {#text} at (0,0) size 777x39 - text run at (0,0) width 291: "You should see a 100x100 green square below. " - text run at (290,0) width 228: "If you see any red, the test has failed. " - text run at (517,0) width 260: "This test is checking to make sure overflow" - text run at (0,20) width 81: "is done using " - text run at (81,20) width 154: "a containing block model." -layer at (8,48) size 100x100 scrollWidth 200 scrollHeight 400 - LayoutBlockFlow (relative positioned) {DIV} at (0,40) size 100x100 [bgcolor=#008000] - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (108,348) size 100x100 backgroundClip at (8,48) size 100x100 clip at (8,48) size 100x100 - LayoutBlockFlow (relative positioned) {DIV} at (100,300) size 100x100 [bgcolor=#FF0000]
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/006-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/006-expected.png deleted file mode 100644 index 32e74931..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/006-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/006-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/006-expected.txt deleted file mode 100644 index b2cc3d3..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/006-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x76 - LayoutBlockFlow {HTML} at (0,0) size 800x76 - LayoutBlockFlow {BODY} at (8,8) size 784x60 - LayoutText {#text} at (0,0) size 774x59 - text run at (0,0) width 291: "You should see a 100x100 green square below. " - text run at (290,0) width 348: "If you see nothing at all or see any red, the test has failed. " - text run at (637,0) width 137: "This test is checking to" - text run at (0,20) width 204: "make sure overflow is done using " - text run at (204,20) width 552: "a containing block model, and that a fixed positioned element inside another fixed positioned" - text run at (0,40) width 212: "element is not considered overflow." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,68) size 100x100 scrollWidth 200 scrollHeight 200 - LayoutBlockFlow (positioned) {DIV} at (8,68) size 100x100 - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (100,70) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (100,70) size 100x100 [bgcolor=#008000]
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/007-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/007-expected.png deleted file mode 100644 index 2fc419bb..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/007-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/008-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/008-expected.png deleted file mode 100644 index 2fc419bb..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/008-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/008-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/008-expected.txt deleted file mode 100644 index ee50c6c..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/008-expected.txt +++ /dev/null
@@ -1,19 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x76 - LayoutBlockFlow {HTML} at (0,0) size 800x76 - LayoutBlockFlow {BODY} at (8,8) size 784x60 - LayoutText {#text} at (0,0) size 774x59 - text run at (0,0) width 291: "You should see a 100x100 green square below. " - text run at (290,0) width 348: "If you see nothing at all or see any red, the test has failed. " - text run at (637,0) width 137: "This test is checking to" - text run at (0,20) width 204: "make sure overflow is done using " - text run at (204,20) width 542: "a containing block model, and that a fixed positioned element inside an absolute positioned" - text run at (0,40) width 212: "element is not considered overflow." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,68) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (8,68) size 100x100 -layer at (100,100) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (100,100) size 100x100 -layer at (200,200) size 100x100 - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#008000]
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/009-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/009-expected.png deleted file mode 100644 index 2e505fe..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/009-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/009-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/009-expected.txt deleted file mode 100644 index 17e1aa2..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/009-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x56 - LayoutBlockFlow {HTML} at (0,0) size 800x56 - LayoutBlockFlow {BODY} at (8,8) size 784x40 - LayoutText {#text} at (0,0) size 758x39 - text run at (0,0) width 291: "You should see a 100x100 green square below. " - text run at (290,0) width 228: "If you see any red, the test has failed. " - text run at (517,0) width 241: "This test is checking to make sure clip is" - text run at (0,20) width 165: "applying to all descendants." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,48) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (8,48) size 100x100 [bgcolor=#008000] - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (108,348) size 100x100 backgroundClip at (8,48) size 100x100 clip at (8,48) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (100,300) size 100x100 [bgcolor=#FF0000]
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/011-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/011-expected.png deleted file mode 100644 index 2e505fe..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/011-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/012-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/012-expected.png deleted file mode 100644 index 2e505fe..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/012-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/012-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/012-expected.txt deleted file mode 100644 index d219c2f88..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/012-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x56 - LayoutBlockFlow {HTML} at (0,0) size 800x56 - LayoutBlockFlow {BODY} at (8,8) size 784x40 - LayoutText {#text} at (0,0) size 758x39 - text run at (0,0) width 291: "You should see a 100x100 green square below. " - text run at (290,0) width 228: "If you see any red, the test has failed. " - text run at (517,0) width 241: "This test is checking to make sure clip is" - text run at (0,20) width 165: "applying to all descendants." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,48) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (8,48) size 100x100 [bgcolor=#008000] - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (108,348) size 100x100 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0 - LayoutBlockFlow {DIV} at (100,300) size 100x100 [bgcolor=#FF0000]
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/013-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/013-expected.png deleted file mode 100644 index 468d3ebc..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/013-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/014-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/014-expected.png deleted file mode 100644 index c5c8ed8..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/014-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/014-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/014-expected.txt deleted file mode 100644 index 5d52d53..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/014-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x76 - LayoutBlockFlow {HTML} at (0,0) size 800x76 - LayoutBlockFlow {BODY} at (8,8) size 784x60 - LayoutText {#text} at (0,0) size 750x59 - text run at (0,0) width 387: "You should see a 100x100 green square with a scrollbar below. " - text run at (386,0) width 228: "If you see any red, the test has failed. " - text run at (613,0) width 137: "This test is checking to" - text run at (0,20) width 578: "make sure clip applies to the element itself, starts from the border edge, and clips out scrollbars. " - text run at (578,20) width 161: "The bottom of the scrolling" - text run at (0,40) width 180: "mechanism should be clipped." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,68) size 120x220 backgroundClip at (18,78) size 100x100 clip at (18,78) size 85x100 scrollHeight 1000 - LayoutBlockFlow (positioned) {DIV} at (8,68) size 120x220 [bgcolor=#008000] [border: (10px solid #FF0000)] - LayoutBlockFlow {DIV} at (10,10) size 85x1000
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/015-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/015-expected.png deleted file mode 100644 index a44df5e..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/015-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/015-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/015-expected.txt deleted file mode 100644 index 2cdec981..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/015-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x136 - LayoutBlockFlow {HTML} at (0,0) size 800x136 - LayoutBlockFlow {BODY} at (8,8) size 784x120 - LayoutBlockFlow (anonymous) at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 698x19 - text run at (0,0) width 291: "You should see a 100x100 green square below. " - text run at (290,0) width 408: "This test makes sure overflow uses containing blocks when clipping." -layer at (8,28) size 100x100 scrollWidth 300 scrollHeight 300 - LayoutBlockFlow {DIV} at (0,20) size 100x100 [bgcolor=#008000] -layer at (108,128) size 100x100 backgroundClip at (8,28) size 100x100 clip at (8,28) size 100x100 - LayoutBlockFlow (relative positioned) {DIV} at (0,0) size 100x100 [bgcolor=#FF0000] -layer at (208,228) size 100x100 backgroundClip at (8,28) size 100x100 clip at (8,28) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (100,100) size 100x100
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/016-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/016-expected.png deleted file mode 100644 index 57ff64f7..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/016-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/016-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/016-expected.txt deleted file mode 100644 index c5fe588..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/clip/016-expected.txt +++ /dev/null
@@ -1,10 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutText {#text} at (0,0) size 287x19 - text run at (0,0) width 287: "You should see a 100x100 green square below." - LayoutText {#text} at (0,0) size 0x0 -layer at (50,50) size 100x500 backgroundClip at (50,50) size 100x100 clip at (50,50) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (50,50) size 100x500 [bgcolor=#008000]
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/004-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/004-expected.png deleted file mode 100644 index 2d963519..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/004-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/004-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/004-expected.txt deleted file mode 100644 index ee0fe3c4..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/004-expected.txt +++ /dev/null
@@ -1,12 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x536 - LayoutBlockFlow {HTML} at (0,0) size 800x536 - LayoutBlockFlow {BODY} at (8,8) size 784x520 - LayoutBlockFlow (anonymous) at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 668x19 - text run at (0,0) width 668: "The two green blocks below should be identical and should each take up half the width of the browser window." - LayoutBlockFlow (floating) {DIV} at (392,20) size 392x500 [bgcolor=#008000] [border: (1px solid #000000)] - LayoutText {#text} at (0,0) size 0x0 -layer at (8,28) size 392x500 clip at (9,29) size 390x498 - LayoutBlockFlow {DIV} at (0,20) size 392x500 [bgcolor=#008000] [border: (1px solid #000000)]
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/005-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/005-expected.png deleted file mode 100644 index 49710430..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/005-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/008-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/008-expected.png deleted file mode 100644 index a89c619..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/008-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/line-clamp-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/line-clamp-expected.png deleted file mode 100644 index 6b93db2..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/line-clamp-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/overflow-auto-position-absolute-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/overflow-auto-position-absolute-expected.png deleted file mode 100644 index 9e17866..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/overflow-auto-position-absolute-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/overflow-auto-position-absolute-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/overflow-auto-position-absolute-expected.txt deleted file mode 100644 index 5b30f069..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/overflow-auto-position-absolute-expected.txt +++ /dev/null
@@ -1,11 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 -layer at (16,16) size 768x568 clip at (16,16) size 753x568 scrollHeight 1024 - LayoutBlockFlow (positioned) {DIV} at (16,16) size 768x568 -layer at (16,16) size 753x1024 backgroundClip at (16,16) size 753x568 clip at (16,16) size 753x568 - LayoutBlockFlow (positioned) {DIV} at (0,0) size 753x1024 [bgcolor=#008000] - LayoutText {#text} at (0,0) size 293x19 - text run at (0,0) width 293: "This test passes if there is no horizontal scrollbar."
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.png deleted file mode 100644 index 8a35ad48..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.txt deleted file mode 100644 index 52ad4401..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.txt +++ /dev/null
@@ -1,21 +0,0 @@ -layer at (0,0) size 800x600 scrollWidth 7618 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x168 - LayoutBlockFlow {HTML} at (0,0) size 800x168 - LayoutBlockFlow {BODY} at (8,16) size 784x144 - LayoutBlockFlow {P} at (0,0) size 784x60 - LayoutText {#text} at (0,0) size 773x59 - text run at (0,0) width 739: "This tests the interaction of overflow on some very wide text with auto table layout. The CSS 2.1 spec does not define how" - text run at (0,20) width 773: "overflow interacts with intrinsic width, so we copy the IE behavior. Therefore the lines should come out very very wide and scroll" - text run at (0,40) width 132: "along with the border." - LayoutTable {TABLE} at (0,76) size 7610x68 [border: (1px solid #FF0000)] - LayoutTableSection {TBODY} at (1,1) size 7608x66 - LayoutTableRow {TR} at (0,2) size 7608x62 - LayoutTableCell {TD} at (2,2) size 7604x62 [r=0 c=0 rs=1 cs=1] -layer at (12,109) size 7602x34 backgroundClip at (12,109) size 788x34 clip at (13,110) size 787x32 - LayoutBlockFlow {PRE} at (1,14) size 7602x34 [border: (1px solid #0000FF)] - LayoutText {#text} at (1,1) size 7600x32 - text run at (1,1) width 3200: "this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line " - text run at (3201,1) width 0: " " - text run at (1,17) width 7600: "this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line " - text run at (7601,17) width 0: " "
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/unreachable-overflow-rtl-bug-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/unreachable-overflow-rtl-bug-expected.png deleted file mode 100644 index 21bcb098..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/overflow/unreachable-overflow-rtl-bug-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/block-layout-inline-children-float-positioned-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/block-layout-inline-children-float-positioned-expected.txt deleted file mode 100644 index 0d7fbf14..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/block-layout-inline-children-float-positioned-expected.txt +++ /dev/null
@@ -1,25 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [324, 37, 278, 20], - [324, 37, 278, 19], - [162, 37, 279, 20], - [162, 37, 279, 19] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (floating) SPAN", - "LayoutText #text", - "InlineTextBox 'the quick brown fox jumped over the lazy dog'", - "LayoutBlockFlow (positioned) SPAN", - "LayoutText #text", - "InlineTextBox 'the quick brown fox jumped over the lazy dog'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/box-inline-resize-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/box-inline-resize-expected.txt deleted file mode 100644 index 1b552f2d..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/box-inline-resize-expected.txt +++ /dev/null
@@ -1,30 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [40, 107, 111, 28], - [40, 107, 111, 27], - [8, 107, 111, 28], - [8, 107, 111, 27], - [8, 88, 32, 67], - [8, 88, 32, 32] - ], - "paintInvalidationClients": [ - "RootInlineBox", - "InlineBox", - "InlineBox", - "RootInlineBox", - "LayoutBlockFlow (anonymous)", - "LayoutImage IMG id='foo'", - "LayoutBlockFlow H2", - "LayoutText #text", - "InlineTextBox 'Chromium'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/caret-invalidation-in-overflow-scroll-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/caret-invalidation-in-overflow-scroll-expected.txt deleted file mode 100644 index 8a498e5..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/caret-invalidation-in-overflow-scroll-expected.txt +++ /dev/null
@@ -1,19 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [381, 10, 3, 18], - [378, 10, 3, 18] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow DIV id='inner-editor'", - "LayoutBlockFlow DIV id='inner-editor'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/focus-continuations-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/focus-continuations-expected.txt deleted file mode 100644 index 027038b..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/focus-continuations-expected.txt +++ /dev/null
@@ -1,24 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [8, 88, 83, 20], - [7, 87, 85, 22], - [7, 87, 85, 22], - [7, 87, 85, 22] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (positioned) DIV id='container'", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/focus-enable-continuations-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/focus-enable-continuations-expected.txt deleted file mode 100644 index 8bf2b885..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/focus-enable-continuations-expected.txt +++ /dev/null
@@ -1,25 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [8, 88, 83, 20], - [7, 87, 85, 22], - [7, 87, 85, 22], - [7, 87, 85, 22] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (positioned) DIV id='container'", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "LayoutInline SPAN id='outer'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/focus-ring-on-continuation-move-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/focus-ring-on-continuation-move-expected.txt deleted file mode 100644 index 3cf1167..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/focus-ring-on-continuation-move-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [208, 200, 100, 100], - [8, 200, 100, 100] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (relative positioned) DIV id='block'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/inline-outline-repaint-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/inline-outline-repaint-expected.txt deleted file mode 100644 index 1c1dfbd9..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/inline-outline-repaint-expected.txt +++ /dev/null
@@ -1,129 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [43, 174, 3, 22], - [8, 156, 86, 39], - [8, 156, 83, 39], - [5, 153, 103, 45], - [5, 153, 92, 45], - [5, 153, 89, 45] - ], - "paintInvalidationClients": [ - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "LayoutText #text", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'dolor sit amet'", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'dolor sit'", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'dolor sit'", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'dolor'", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'dolor'", - "InlineFlowBox", - "RootInlineBox", - "LayoutBlockFlow DIV", - "LayoutInline SPAN id='test'", - "InlineFlowBox", - "InlineFlowBox", - "LayoutText #text", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineTextBox 'dolor\u00A0'", - "LayoutBlockFlow DIV" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-1-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-1-expected.txt deleted file mode 100644 index b072d59d..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-1-expected.txt +++ /dev/null
@@ -1,149 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [420, 180, 1, 59], - [378, 138, 70, 30], - [369, 80, 52, 119], - [303, 420, 67, 19], - [244, 420, 65, 19], - [151, 180, 40, 19], - [134, 360, 132, 19], - [84, 180, 40, 19], - [65, 380, 304, 59], - [65, 360, 132, 19], - [14, 440, 354, 59], - [14, 420, 355, 79], - [14, 380, 355, 59], - [14, 363, 48, 65], - [14, 359, 407, 20], - [14, 343, 48, 65], - [14, 239, 406, 20], - [8, 120, 418, 479] - ], - "paintInvalidationClients": [ - "InlineTextBox 'comfortably enough, under her arm, with its legs hanging'", - "RootInlineBox", - "InlineTextBox 'down,\n'", - "InlineTextBox 'but generally, just as she had got its neck nicely'", - "RootInlineBox", - "InlineTextBox 'straightened\n'", - "InlineTextBox 'out, and was going to give the hedgehog a'", - "RootInlineBox", - "InlineTextBox 'blow with its head, it\n'", - "InlineTextBox 'would'", - "InlineTextBox ' twist itself round and look up in her'", - "RootInlineBox", - "InlineTextBox 'face, with\n'", - "InlineTextBox 'such a puzzled expression that she could not help'", - "RootInlineBox", - "InlineTextBox 'bursting out\n'", - "InlineTextBox 'laughing: and when she had got its head down, and was'", - "RootInlineBox", - "InlineTextBox 'going to\n'", - "InlineTextBox 'begin again, it was very provoking to find that the'", - "RootInlineBox", - "InlineTextBox 'hedgehog had\n'", - "InlineTextBox 'unrolled itself, and was in the act of crawling away:'", - "RootInlineBox", - "InlineTextBox 'besides all\n'", - "InlineTextBox 'this, there was generally a ridge or furrow in the way'", - "RootInlineBox", - "InlineTextBox 'wherever\n'", - "InlineTextBox 'she wanted to send the hedgehog to, and, as the'", - "RootInlineBox", - "InlineTextBox 'doubled-up\n'", - "InlineTextBox 'soldiers were always getting up and walking off to'", - "RootInlineBox", - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion that it'", - "RootInlineBox", - "InlineTextBox 'was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting\n'", - "InlineTextBox 'for'", - "RootInlineBox", - "InlineTextBox 'turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting for the'", - "RootInlineBox", - "InlineTextBox 'hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the Queen'", - "RootInlineBox", - "InlineTextBox 'was in a furious passion, and went\n'", - "InlineTextBox 'stamping about, and'", - "RootInlineBox", - "InlineTextBox 'shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019 about'", - "RootInlineBox", - "InlineTextBox 'once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet had'", - "RootInlineBox", - "InlineTextBox 'any dispute with the Queen, but she knew that it might\n'", - "InlineTextBox 'happen any'", - "RootInlineBox", - "InlineTextBox 'minute, \u2018and then,\u2019 thought she, \u2018what would become of\n'", - "InlineTextBox 'me?'", - "RootInlineBox", - "InlineTextBox 'They\u2019re dreadfully fond of beheading people here; the great'", - "RootInlineBox", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "LayoutBlockFlow (floating) DIV id='pinkFloat'", - "LayoutBlockFlow P", - "LayoutText #text", - "InlineTextBox 'The chief difficulty Alice found at first was in managing her'", - "InlineTextBox 'flamingo: she succeeded in getting its body tucked away,'", - "InlineTextBox 'comfortably enough, under her arm, with its legs hanging'", - "InlineTextBox 'down,\n'", - "InlineTextBox 'but generally, just as she had got its neck nicely'", - "InlineTextBox 'straightened\n'", - "InlineTextBox 'out, and was going to give the hedgehog a blow with'", - "InlineTextBox 'its head, it\n'", - "LayoutText #text", - "InlineTextBox 'would'", - "LayoutText #text", - "InlineTextBox ' twist itself round and look up in her face, with'", - "InlineTextBox 'such a puzzled expression that she could not help bursting out'", - "InlineTextBox 'laughing: and when she had got its head down, and was going to'", - "LayoutText #text", - "InlineTextBox 'begin again, it was very provoking to find that the hedgehog had'", - "InlineTextBox 'unrolled itself, and was in the act of crawling away: besides all\n'", - "InlineTextBox 'this,'", - "InlineTextBox 'there was generally a ridge or furrow in the way wherever\n'", - "InlineTextBox 'she'", - "InlineTextBox 'wanted to send the hedgehog to, and, as the doubled-up\n'", - "InlineTextBox 'soldiers'", - "InlineTextBox 'were always getting up and walking off to other parts of\n'", - "InlineTextBox 'the ground,'", - "InlineTextBox 'Alice soon came to the conclusion that it was a very'", - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "LayoutText #text", - "InlineTextBox 'difficult game indeed.\n'", - "LayoutText #text", - "InlineTextBox 'for'", - "InlineTextBox 'turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting for the'", - "InlineTextBox 'hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "LayoutText #text", - "InlineTextBox 'the Queen'", - "LayoutText #text", - "InlineTextBox ' was in a'", - "InlineTextBox 'furious passion, and went\n'", - "InlineTextBox 'stamping about, and shouting'", - "InlineTextBox '\u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019 about once in a'", - "InlineTextBox 'minute.\n'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-10-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-10-expected.txt deleted file mode 100644 index 0b4c06b..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-10-expected.txt +++ /dev/null
@@ -1,64 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [368, 440, 2, 59], - [14, 374, 48, 64], - [14, 363, 48, 65], - [8, 340, 418, 259] - ], - "paintInvalidationClients": [ - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion that it'", - "RootInlineBox", - "InlineTextBox 'was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting\n'", - "InlineTextBox 'for'", - "RootInlineBox", - "InlineTextBox 'turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting for the'", - "RootInlineBox", - "InlineTextBox 'hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the Queen'", - "RootInlineBox", - "InlineTextBox 'was in a furious passion, and went\n'", - "InlineTextBox 'stamping about, and'", - "RootInlineBox", - "InlineTextBox 'shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019 about'", - "RootInlineBox", - "InlineTextBox 'once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet had'", - "RootInlineBox", - "InlineTextBox 'any dispute with the Queen, but she knew that it might\n'", - "InlineTextBox 'happen any'", - "RootInlineBox", - "InlineTextBox 'minute, \u2018and then,\u2019 thought she, \u2018what would become of\n'", - "InlineTextBox 'me?'", - "RootInlineBox", - "InlineTextBox 'They\u2019re dreadfully fond of beheading people here; the great'", - "RootInlineBox", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "LayoutText #text", - "InlineTextBox 'was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her'", - "InlineTextBox 'head!\u2019 about once in a minute.\n'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-2-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-2-expected.txt deleted file mode 100644 index bfe97a7..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-2-expected.txt +++ /dev/null
@@ -1,114 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [485, 0, 15, 600], - [372, 384, 48, 81], - [372, 383, 48, 81], - [303, 421, 67, 19], - [303, 420, 67, 19], - [151, 180, 40, 19], - [149, 180, 45, 20], - [134, 361, 132, 19], - [134, 360, 132, 19], - [65, 381, 304, 59], - [65, 381, 287, 19], - [65, 380, 304, 59], - [65, 380, 287, 19], - [14, 501, 407, 99], - [14, 500, 407, 99], - [14, 441, 354, 59], - [14, 440, 354, 59], - [14, 364, 48, 65], - [14, 363, 48, 65], - [14, 241, 407, 139], - [14, 240, 407, 139], - [14, 199, 355, 1], - [14, 181, 406, 79], - [14, 180, 406, 79], - [8, 160, 418, 440], - [0, 0, 485, 600] - ], - "paintInvalidationClients": [ - "InlineTextBox 'straightened\n'", - "InlineTextBox 'out, and was going to give the hedgehog a'", - "RootInlineBox", - "InlineTextBox 'blow with its head, it\n'", - "InlineTextBox ''", - "InlineTextBox ' twist itself round and look up in her'", - "RootInlineBox", - "VerticalScrollbar", - "LayoutIFrame IFRAME id='iframe'", - "LayoutBlockFlow HTML", - "LayoutBlockFlow P", - "LayoutBlockFlow P", - "LayoutText #text", - "InlineTextBox 'The chief difficulty Alice found at first was in managing her'", - "InlineTextBox 'flamingo: she succeeded in getting its body tucked away,'", - "InlineTextBox 'comfortably enough, under her arm, with its legs hanging'", - "InlineTextBox 'down,\n'", - "InlineTextBox 'but generally, just as she had got its neck nicely'", - "InlineTextBox 'straightened\n'", - "InlineTextBox 'out, and was going to give the hedgehog a'", - "InlineTextBox 'blow with its head, it\n'", - "LayoutInline I id='would'", - "LayoutText #text", - "InlineTextBox 'would'", - "LayoutText #text", - "InlineTextBox ' twist itself round and look up in her'", - "InlineTextBox 'face, with\n'", - "InlineTextBox 'such a puzzled expression that she could not help'", - "InlineTextBox 'bursting out\n'", - "InlineTextBox 'laughing: and when she had got its head down, and was'", - "InlineTextBox 'going to\n'", - "LayoutText #text", - "InlineTextBox 'begin again, it was very provoking to find that the'", - "InlineTextBox 'hedgehog had\n'", - "InlineTextBox 'unrolled itself, and was in the act of crawling away:'", - "InlineTextBox 'besides all\n'", - "InlineTextBox 'this, there was generally a ridge or furrow in the way'", - "InlineTextBox 'wherever\n'", - "InlineTextBox 'she wanted to send the hedgehog to, and, as the'", - "InlineTextBox 'doubled-up\n'", - "InlineTextBox 'soldiers were always getting up and walking off to'", - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion that it'", - "InlineTextBox 'was a very\n'", - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "LayoutText #text", - "InlineTextBox 'difficult game indeed.\n'", - "LayoutText #text", - "InlineTextBox 'The players all played at once without waiting\n'", - "LayoutBlockFlow (floating) SPAN id='greenFloat'", - "LayoutText #text", - "InlineTextBox 'for'", - "InlineTextBox 'turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting for the'", - "InlineTextBox 'hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "LayoutText #text", - "InlineTextBox 'the Queen'", - "LayoutText #text", - "InlineTextBox 'was in a furious passion, and went\n'", - "InlineTextBox 'stamping about, and'", - "InlineTextBox 'shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019 about'", - "InlineTextBox 'once in a minute.\n'", - "LayoutText #text", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet had'", - "InlineTextBox 'any dispute with the Queen, but she knew that it might\n'", - "InlineTextBox 'happen any'", - "InlineTextBox 'minute, \u2018and then,\u2019 thought she, \u2018what would become of\n'", - "InlineTextBox 'me?'", - "InlineTextBox 'They\u2019re dreadfully fond of beheading people here; the great'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-3-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-3-expected.txt deleted file mode 100644 index 23b5b5c..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-3-expected.txt +++ /dev/null
@@ -1,73 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [372, 383, 48, 81], - [356, 383, 64, 81], - [353, 440, 15, 59], - [352, 380, 2, 19], - [303, 420, 67, 19], - [65, 400, 289, 39], - [65, 380, 304, 59], - [14, 420, 339, 39], - [8, 380, 418, 219] - ], - "paintInvalidationClients": [ - "InlineTextBox 'The players all played at once without waiting\n'", - "InlineTextBox 'for'", - "RootInlineBox", - "InlineTextBox 'turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting for the'", - "RootInlineBox", - "InlineTextBox 'hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the Queen'", - "RootInlineBox", - "InlineTextBox 'was in a furious passion, and went\n'", - "InlineTextBox 'stamping about, and'", - "RootInlineBox", - "InlineTextBox 'shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019 about'", - "RootInlineBox", - "InlineTextBox 'once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet had'", - "RootInlineBox", - "InlineTextBox 'any dispute with the Queen, but she knew that it might\n'", - "InlineTextBox 'happen any'", - "RootInlineBox", - "InlineTextBox 'minute, \u2018and then,\u2019 thought she, \u2018what would become of\n'", - "InlineTextBox 'me?'", - "RootInlineBox", - "InlineTextBox 'They\u2019re dreadfully fond of beheading people here; the great'", - "RootInlineBox", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutText #text", - "InlineTextBox 'The players all played at once without waiting'", - "LayoutBlockFlow (floating) SPAN id='greenFloat'", - "LayoutText #text", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "LayoutText #text", - "InlineTextBox 'the'", - "InlineTextBox 'Queen'", - "LayoutText #text", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her'", - "InlineTextBox 'head!\u2019 about once in a minute.\n'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-4-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-4-expected.txt deleted file mode 100644 index 43e90c1..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-4-expected.txt +++ /dev/null
@@ -1,57 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [372, 447, 48, 17], - [368, 440, 53, 59], - [8, 380, 418, 219] - ], - "paintInvalidationClients": [ - "InlineTextBox 'The players all played at once without waiting\n'", - "InlineTextBox 'for'", - "RootInlineBox", - "InlineTextBox 'turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting for the'", - "RootInlineBox", - "InlineTextBox 'hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the Queen'", - "RootInlineBox", - "InlineTextBox 'was in a furious passion, and went\n'", - "InlineTextBox 'stamping about, and'", - "RootInlineBox", - "InlineTextBox 'shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019 about'", - "RootInlineBox", - "InlineTextBox 'once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet had'", - "RootInlineBox", - "InlineTextBox 'any dispute with the Queen, but she knew that it might\n'", - "InlineTextBox 'happen any'", - "RootInlineBox", - "InlineTextBox 'minute, \u2018and then,\u2019 thought she, \u2018what would become of\n'", - "InlineTextBox 'me?'", - "RootInlineBox", - "InlineTextBox 'They\u2019re dreadfully fond of beheading people here; the great'", - "RootInlineBox", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutBlockFlow (floating) SPAN id='greenFloat'", - "LayoutText #text", - "InlineTextBox 'was in a furious passion, and went\n'", - "InlineTextBox 'stamping about, and'", - "InlineTextBox 'shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019 about once in'", - "InlineTextBox 'a minute.\n'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-5-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-5-expected.txt deleted file mode 100644 index afeb3a8a..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-5-expected.txt +++ /dev/null
@@ -1,85 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [303, 420, 67, 19], - [275, 420, 65, 19], - [134, 360, 132, 19], - [118, 360, 132, 19], - [65, 380, 304, 59], - [65, 380, 287, 19], - [49, 380, 320, 59], - [49, 380, 303, 19], - [46, 363, 16, 65], - [14, 440, 354, 59], - [14, 420, 355, 79], - [8, 340, 418, 259] - ], - "paintInvalidationClients": [ - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion that it'", - "RootInlineBox", - "InlineTextBox 'was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting\n'", - "InlineTextBox 'for'", - "RootInlineBox", - "InlineTextBox 'turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting for the'", - "RootInlineBox", - "InlineTextBox 'hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the Queen'", - "RootInlineBox", - "InlineTextBox 'was in a furious passion, and went\n'", - "InlineTextBox 'stamping about, and'", - "RootInlineBox", - "InlineTextBox 'shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019 about'", - "RootInlineBox", - "InlineTextBox 'once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet had'", - "RootInlineBox", - "InlineTextBox 'any dispute with the Queen, but she knew that it might\n'", - "InlineTextBox 'happen any'", - "RootInlineBox", - "InlineTextBox 'minute, \u2018and then,\u2019 thought she, \u2018what would become of\n'", - "InlineTextBox 'me?'", - "RootInlineBox", - "InlineTextBox 'They\u2019re dreadfully fond of beheading people here; the great'", - "RootInlineBox", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "LayoutText #text", - "InlineTextBox 'difficult game indeed.\n'", - "LayoutText #text", - "InlineTextBox 'The players all played at once without waiting\n'", - "LayoutText #text", - "InlineTextBox 'for'", - "InlineTextBox 'turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting for the'", - "InlineTextBox 'hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "LayoutText #text", - "InlineTextBox 'the Queen'", - "LayoutText #text", - "InlineTextBox ' was'", - "InlineTextBox 'in a furious passion, and went\n'", - "InlineTextBox 'stamping about, and'", - "InlineTextBox 'shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019 about'", - "InlineTextBox 'once in a minute.\n'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-6-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-6-expected.txt deleted file mode 100644 index fb7e6ed..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-6-expected.txt +++ /dev/null
@@ -1,38 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [28, 363, 20, 20], - [14, 363, 48, 65], - [8, 340, 418, 99] - ], - "paintInvalidationClients": [ - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion that it'", - "RootInlineBox", - "InlineTextBox 'was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting\n'", - "InlineTextBox 'for'", - "RootInlineBox", - "InlineTextBox 'turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting for the'", - "RootInlineBox", - "InlineTextBox 'hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the Queen'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "LayoutText #text", - "InlineTextBox 'foo'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-8-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-8-expected.txt deleted file mode 100644 index 6dd2967..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-8-expected.txt +++ /dev/null
@@ -1,126 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [485, 0, 15, 600], - [303, 420, 67, 19], - [143, 420, 65, 19], - [134, 360, 132, 19], - [83, 360, 131, 19], - [65, 380, 304, 59], - [65, 380, 287, 19], - [14, 500, 407, 99], - [14, 480, 407, 99], - [14, 440, 354, 59], - [14, 420, 354, 59], - [14, 380, 354, 59], - [14, 380, 298, 19], - [14, 363, 48, 65], - [8, 586, 418, 14], - [8, 583, 418, 17], - [8, 80, 418, 519], - [0, 0, 485, 600] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "InlineTextBox 'The chief difficulty Alice found at first was in managing her'", - "RootInlineBox", - "InlineTextBox 'flamingo: she succeeded in getting its body tucked away,'", - "RootInlineBox", - "InlineTextBox 'comfortably enough, under her arm, with its legs hanging'", - "RootInlineBox", - "InlineTextBox 'down,\n'", - "InlineTextBox 'but generally, just as she had got its neck nicely'", - "RootInlineBox", - "InlineTextBox 'straightened\n'", - "InlineTextBox 'out, and was going to give the hedgehog a'", - "RootInlineBox", - "InlineTextBox 'blow with its head, it\n'", - "InlineTextBox 'would'", - "InlineTextBox ' twist itself round and look up in her'", - "RootInlineBox", - "InlineTextBox 'face, with\n'", - "InlineTextBox 'such a puzzled expression that she could not help'", - "RootInlineBox", - "InlineTextBox 'bursting out\n'", - "InlineTextBox 'laughing: and when she had got its head down, and was'", - "RootInlineBox", - "InlineTextBox 'going to\n'", - "InlineTextBox 'begin again, it was very provoking to find that the'", - "RootInlineBox", - "InlineTextBox 'hedgehog had\n'", - "InlineTextBox 'unrolled itself, and was in the act of crawling away:'", - "RootInlineBox", - "InlineTextBox 'besides all\n'", - "InlineTextBox 'this, there was generally a ridge or furrow in the way'", - "RootInlineBox", - "InlineTextBox 'wherever\n'", - "InlineTextBox 'she wanted to send the hedgehog to, and, as the'", - "RootInlineBox", - "InlineTextBox 'doubled-up\n'", - "InlineTextBox 'soldiers were always getting up and walking off to'", - "RootInlineBox", - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion that it'", - "RootInlineBox", - "InlineTextBox 'was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting\n'", - "InlineTextBox 'for'", - "RootInlineBox", - "InlineTextBox 'turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting for the'", - "RootInlineBox", - "InlineTextBox 'hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the Queen'", - "RootInlineBox", - "InlineTextBox 'was in a furious passion, and went\n'", - "InlineTextBox 'stamping about, and'", - "RootInlineBox", - "InlineTextBox 'shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019 about'", - "RootInlineBox", - "InlineTextBox 'once in a minute.\n'", - "RootInlineBox", - "VerticalScrollbar", - "LayoutIFrame IFRAME id='iframe'", - "LayoutBlockFlow HTML", - "LayoutBlockFlow P", - "LayoutBlockFlow P", - "LayoutText #text", - "InlineTextBox 'difficult game indeed.\n'", - "LayoutText #text", - "InlineTextBox 'The players all played at once without waiting\n'", - "LayoutText #text", - "InlineTextBox 'for turns,'", - "InlineTextBox 'quarrelling all the while, and fighting for the hedgehogs; and'", - "InlineTextBox 'in\n'", - "InlineTextBox 'a very short time '", - "LayoutText #text", - "InlineTextBox 'the Queen'", - "LayoutText #text", - "InlineTextBox ' was in a furious passion,'", - "InlineTextBox 'and went\n'", - "InlineTextBox 'stamping about, and shouting \u2018Off with his head!\u2019'", - "InlineTextBox 'or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'", - "LayoutText #text", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet had'", - "InlineTextBox 'any dispute with the Queen, but she knew that it might\n'", - "InlineTextBox 'happen any'", - "InlineTextBox 'minute, \u2018and then,\u2019 thought she, \u2018what would become of\n'", - "InlineTextBox 'me?'", - "InlineTextBox 'They\u2019re dreadfully fond of beheading people here; the great'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-9-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-9-expected.txt deleted file mode 100644 index 2340f3a..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-9-expected.txt +++ /dev/null
@@ -1,107 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [420, 240, 1, 139], - [372, 243, 48, 49], - [8, 80, 418, 519] - ], - "paintInvalidationClients": [ - "InlineTextBox 'The chief difficulty Alice found at first was in managing her'", - "RootInlineBox", - "InlineTextBox 'flamingo: she succeeded in getting its body tucked away,'", - "RootInlineBox", - "InlineTextBox 'comfortably enough, under her arm, with its legs hanging'", - "RootInlineBox", - "InlineTextBox 'down,\n'", - "InlineTextBox 'but generally, just as she had got its neck nicely'", - "RootInlineBox", - "InlineTextBox 'straightened\n'", - "InlineTextBox 'out, and was going to give the hedgehog a'", - "RootInlineBox", - "InlineTextBox 'blow with its head, it\n'", - "InlineTextBox 'would'", - "InlineTextBox ' twist itself round and look up in her'", - "RootInlineBox", - "InlineTextBox 'face, with\n'", - "InlineTextBox 'such a puzzled expression that she could not help'", - "RootInlineBox", - "InlineTextBox 'bursting out\n'", - "InlineTextBox 'laughing: and when she had got its head down, and was'", - "RootInlineBox", - "InlineTextBox 'going to\n'", - "InlineTextBox 'begin again, it was very provoking to find that the'", - "RootInlineBox", - "InlineTextBox 'hedgehog had\n'", - "InlineTextBox 'unrolled itself, and was in the act of crawling away:'", - "RootInlineBox", - "InlineTextBox 'besides all\n'", - "InlineTextBox 'this, there was generally a ridge or furrow in the way'", - "RootInlineBox", - "InlineTextBox 'wherever\n'", - "InlineTextBox 'she wanted to send the hedgehog to, and, as the'", - "RootInlineBox", - "InlineTextBox 'doubled-up\n'", - "InlineTextBox 'soldiers were always getting up and walking off to'", - "RootInlineBox", - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion that it'", - "RootInlineBox", - "InlineTextBox 'was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting\n'", - "InlineTextBox 'for'", - "RootInlineBox", - "InlineTextBox 'turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting for the'", - "RootInlineBox", - "InlineTextBox 'hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the Queen'", - "RootInlineBox", - "InlineTextBox 'was in a furious passion, and went\n'", - "InlineTextBox 'stamping about, and'", - "RootInlineBox", - "InlineTextBox 'shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019 about'", - "RootInlineBox", - "InlineTextBox 'once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet had'", - "RootInlineBox", - "InlineTextBox 'any dispute with the Queen, but she knew that it might\n'", - "InlineTextBox 'happen any'", - "RootInlineBox", - "InlineTextBox 'minute, \u2018and then,\u2019 thought she, \u2018what would become of\n'", - "InlineTextBox 'me?'", - "RootInlineBox", - "InlineTextBox 'They\u2019re dreadfully fond of beheading people here; the great'", - "RootInlineBox", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutBlockFlow (floating) SPAN id='yellowFloat'", - "LayoutText #text", - "InlineTextBox 'begin again, it was very provoking to find that the'", - "InlineTextBox 'hedgehog had\n'", - "InlineTextBox 'unrolled itself, and was in the act of crawling'", - "InlineTextBox 'away: besides all\n'", - "InlineTextBox 'this, there was generally a ridge or furrow'", - "InlineTextBox 'in the way wherever\n'", - "InlineTextBox 'she wanted to send the hedgehog to, and, as'", - "InlineTextBox 'the doubled-up\n'", - "InlineTextBox 'soldiers were always getting up and walking off to'", - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion that it'", - "InlineTextBox 'was a very\n'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/offset-change-wrong-invalidation-with-float-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/offset-change-wrong-invalidation-with-float-expected.txt deleted file mode 100644 index 7e42147..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/offset-change-wrong-invalidation-with-float-expected.txt +++ /dev/null
@@ -1,24 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [70, 94, 18, 20], - [70, 94, 7, 19], - [70, -156, 18, 20], - [70, -156, 7, 19], - [48, 94, 40, 20], - [48, -156, 40, 20] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (positioned) UL id='submenu'", - "LayoutListItem LI", - "LayoutListMarker (anonymous)" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/outline-change-continuations-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/outline-change-continuations-expected.txt deleted file mode 100644 index 6e832de..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/outline-change-continuations-expected.txt +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [6, 86, 87, 24], - [6, 86, 87, 24], - [6, 86, 85, 4] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "LayoutText #text", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/outline-change-offset-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/outline-change-offset-expected.txt deleted file mode 100644 index e4f270f..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/outline-change-offset-expected.txt +++ /dev/null
@@ -1,20 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [40, 40, 120, 120], - [35, 35, 130, 130], - [35, 35, 130, 130] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (positioned) DIV id='indicator'", - "LayoutBlockFlow (positioned) DIV id='target'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.png deleted file mode 100644 index cbf6b7a6b..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.txt deleted file mode 100644 index ce18003..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.txt +++ /dev/null
@@ -1,33 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [18, 150, 200, 20], - [18, 110, 200, 20], - [16, 148, 204, 44], - [16, 148, 202, 23], - [16, 108, 204, 84], - [16, 108, 204, 84] - ], - "paintInvalidationClients": [ - "InlineTextBox 'CONTENTS'", - "RootInlineBox", - "InlineTextBox 'CONTENTS'", - "RootInlineBox", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "InlineFlowBox", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "InlineFlowBox", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/positioned-document-element-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/positioned-document-element-expected.txt deleted file mode 100644 index c469a75..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/positioned-document-element-expected.txt +++ /dev/null
@@ -1,33 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "backgroundColor": "#008000", - "repaintRects": [ - [108, 116, 403, 20], - [108, 116, 403, 20], - [108, 116, 403, 19], - [100, 100, 419, 52], - [8, 16, 784, 20], - [8, 16, 784, 20], - [8, 16, 403, 19], - [0, 0, 800, 600], - [0, 0, 800, 52] - ], - "paintInvalidationClients": [ - "RootInlineBox", - "InlineTextBox 'Tests that the entire viewport is painted with a floated html element.'", - "LayoutView #document", - "LayoutBlockFlow (positioned) HTML class='changed'", - "LayoutBlockFlow BODY", - "LayoutBlockFlow P", - "LayoutText #text", - "InlineTextBox 'Tests that the entire viewport is painted with a floated html element.'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/relative-inline-positioned-movement-repaint-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/relative-inline-positioned-movement-repaint-expected.txt deleted file mode 100644 index f6915695..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/relative-inline-positioned-movement-repaint-expected.txt +++ /dev/null
@@ -1,28 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [69, 8, 346, 19], - [68, 7, 348, 21], - [29, 8, 346, 19], - [28, 7, 348, 21], - [8, 7, 784, 21] - ], - "paintInvalidationClients": [ - "InlineTextBox 'When this layer moves it shouldn't generate a repaint rect.'", - "InlineFlowBox", - "RootInlineBox", - "LayoutBlockFlow BODY", - "LayoutInline (relative positioned) DIV id='block'", - "InlineFlowBox", - "LayoutText #text", - "InlineTextBox 'When this layer moves it shouldn't generate a repaint rect.'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/remove-inline-after-layout-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/remove-inline-after-layout-expected.txt deleted file mode 100644 index bebae6b0..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/remove-inline-after-layout-expected.txt +++ /dev/null
@@ -1,34 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [283, 108, 100, 100], - [112, 193, 171, 19], - [112, 108, 100, 100], - [8, 108, 784, 104] - ], - "paintInvalidationClients": [ - "InlineBox", - "InlineTextBox '\n'", - "InlineTextBox 'This span should disappear.\n'", - "InlineBox", - "RootInlineBox", - "InlineTextBox 'This span should disappear.\n'", - "LayoutText #text", - "InlineFlowBox", - "LayoutInline SPAN id='target'", - "InlineBox", - "InlineTextBox '\n'", - "InlineBox", - "RootInlineBox", - "LayoutBlockFlow (anonymous)", - "LayoutBlockFlow DIV" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/remove-inline-layer-after-layout-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/remove-inline-layer-after-layout-expected.txt deleted file mode 100644 index 883ce9e8..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/remove-inline-layer-after-layout-expected.txt +++ /dev/null
@@ -1,36 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [283, 108, 100, 100], - [112, 193, 171, 19], - [112, 108, 171, 104], - [112, 108, 100, 100], - [8, 108, 784, 104] - ], - "paintInvalidationClients": [ - "InlineBox", - "InlineTextBox '\n'", - "InlineTextBox 'This span should disappear.\n'", - "InlineFlowBox", - "InlineBox", - "RootInlineBox", - "InlineTextBox 'This span should disappear.\n'", - "LayoutText #text", - "InlineFlowBox", - "LayoutInline SPAN id='target'", - "InlineBox", - "InlineTextBox '\n'", - "InlineBox", - "RootInlineBox", - "LayoutBlockFlow (anonymous)", - "LayoutBlockFlow DIV" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/repaint-during-scroll-with-zoom-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/repaint-during-scroll-with-zoom-expected.txt deleted file mode 100644 index 059f5b1..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/repaint-during-scroll-with-zoom-expected.txt +++ /dev/null
@@ -1,34 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "backgroundColor": "#C0C0C0", - "repaintRects": [ - [237, 64, 15, 236], - [2, 299, 235, 16], - [2, 64, 235, 236], - [2, 64, 235, 236], - [2, 64, 235, 236], - [2, 64, 225, 226], - [2, 64, 135, 136], - [2, 64, 52, 18] - ], - "paintInvalidationClients": [ - "HorizontalScrollbar", - "LayoutIFrame (positioned) IFRAME", - "VerticalScrollbar", - "LayoutIFrame (positioned) IFRAME", - "LayoutIFrame (positioned) IFRAME", - "LayoutView #document", - "LayoutBlockFlow HTML", - "LayoutBlockFlow BODY", - "LayoutText #text", - "InlineTextBox 'scroll me'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt deleted file mode 100644 index 0739722..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/fast/repaint/scroll-stacking-context-backface-visiblity-leaves-traces-expected.txt +++ /dev/null
@@ -1,21 +0,0 @@ -{ - "bounds": [785, 5056], - "children": [ - { - "bounds": [785, 5056], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [18, 1850, 150, 150], - [18, 1850, 150, 150], - [18, 1450, 150, 150], - [18, 1450, 150, 150] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (positioned) DIV id='searchbar'", - "LayoutBlockFlow DIV id='recentlink'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/inline/outline-offset-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/inline/outline-offset-expected.png deleted file mode 100644 index 16820886..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/inline/outline-offset-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/invalidation/composite-after-paint/image-resize-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/invalidation/composite-after-paint/image-resize-expected.png deleted file mode 100644 index fac21c3..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/invalidation/composite-after-paint/image-resize-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/invalidation/composite-after-paint/image-resize-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/invalidation/composite-after-paint/image-resize-expected.txt deleted file mode 100644 index dd184de6..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/invalidation/composite-after-paint/image-resize-expected.txt +++ /dev/null
@@ -1 +0,0 @@ -["LayoutImage (positioned) IMG"]
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/invalidation/composite-after-paint/percent-size-image-resize-container-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/invalidation/composite-after-paint/percent-size-image-resize-container-expected.png deleted file mode 100644 index a4b8a61..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/invalidation/composite-after-paint/percent-size-image-resize-container-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/invalidation/composite-after-paint/text-match-highlight-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/invalidation/composite-after-paint/text-match-highlight-expected.png deleted file mode 100644 index 0336532..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/invalidation/composite-after-paint/text-match-highlight-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/invalidation/non-text-link-invalidation-optimization-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/invalidation/non-text-link-invalidation-optimization-expected.txt deleted file mode 100644 index 81fe928..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/invalidation/non-text-link-invalidation-optimization-expected.txt +++ /dev/null
@@ -1,33 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [336, 8, 49, 19], - [303, 8, 23, 19], - [156, 8, 137, 19], - [131, 8, 26, 19], - [72, 8, 59, 19], - [8, 8, 54, 19] - ], - "paintInvalidationClients": [ - "LayoutText #text", - "InlineTextBox 'This test '", - "LayoutText #text", - "InlineTextBox ' passes if '", - "LayoutText #text", - "InlineTextBox 'only'", - "LayoutText #text", - "InlineTextBox ' text is invalidated and '", - "LayoutText #text", - "InlineTextBox ' no '", - "LayoutText #text", - "InlineTextBox ' images.'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/roundedrects/circle-with-shadow-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/roundedrects/circle-with-shadow-expected.png deleted file mode 100644 index 12b81e9..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/roundedrects/circle-with-shadow-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/selection/selection-within-composited-scroller-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/selection/selection-within-composited-scroller-expected.txt deleted file mode 100644 index e601295..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/selection/selection-within-composited-scroller-expected.txt +++ /dev/null
@@ -1,22 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [8, 168, 21, 19] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow HTML", - "LayoutBlockFlow BODY", - "LayoutBlockFlow DIV id='scroller'", - "LayoutBlockFlow DIV id='target'", - "LayoutText #text", - "InlineTextBox 'test'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.png deleted file mode 100644 index 20659a0..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.txt deleted file mode 100644 index 56e88501..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.txt +++ /dev/null
@@ -1,17 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x136 - LayoutBlockFlow {HTML} at (0,0) size 800x136 - LayoutBlockFlow {BODY} at (8,16) size 784x112 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 321x19 - text run at (0,0) width 321: "Passes if there are no overpainted selection highlights." - LayoutBlockFlow (anonymous) at (0,36) size 784x76 - LayoutInline {SPAN} at (0,0) size 188x73 - LayoutText {#text} at (0,1) size 188x73 - text run at (0,1) width 96: "text" - text run at (96,1) width 92 RTL: "\x{645}\x{62A}\x{646}:" - LayoutText {#text} at (0,0) size 0x0 - LayoutText {#text} at (0,0) size 0x0 -selection start: position 5 of child 0 {#text} of child 2 {SPAN} of body -selection end: position 13 of child 0 {#text} of child 2 {SPAN} of body
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.png deleted file mode 100644 index 3f2bb471..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.txt deleted file mode 100644 index 803f395..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x212 - LayoutBlockFlow {HTML} at (0,0) size 800x212 - LayoutBlockFlow {BODY} at (8,16) size 784x188 - LayoutBlockFlow {P} at (0,0) size 784x20 - LayoutText {#text} at (0,0) size 321x19 - text run at (0,0) width 321: "Passes if there are no overpainted selection highlights." - LayoutBlockFlow {DIV} at (0,36) size 784x152 - LayoutText {#text} at (756,1) size 28x73 - text run at (756,1) width 28: "a" - LayoutBR {BR} at (756,1) size 0x73 - LayoutBR {BR} at (784,77) size 0x73 -selection start: position 0 of child 0 {#text} of child 2 {DIV} of body -selection end: position 1 of child 1 {BR} of child 2 {DIV} of body
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/svg/custom/object-sizing-explicit-height-expected.png b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/svg/custom/object-sizing-explicit-height-expected.png deleted file mode 100644 index 6fb3f99b3a..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/svg/custom/object-sizing-explicit-height-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/svg/custom/object-sizing-explicit-height-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/svg/custom/object-sizing-explicit-height-expected.txt deleted file mode 100644 index ef898ca..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/composite-after-paint/svg/custom/object-sizing-explicit-height-expected.txt +++ /dev/null
@@ -1,83 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x376 - LayoutBlockFlow {html} at (0,0) size 800x376 - LayoutBlockFlow {body} at (8,8) size 784x360 - LayoutText {#text} at (175,160) size 4x19 - text run at (175,160) width 4: " " - LayoutText {#text} at (354,160) size 4x19 - text run at (354,160) width 4: " " - LayoutText {#text} at (533,160) size 4x19 - text run at (533,160) width 4: " " - LayoutText {#text} at (0,0) size 0x0 - LayoutText {#text} at (175,340) size 4x19 - text run at (175,340) width 4: " " - LayoutText {#text} at (354,340) size 4x19 - text run at (354,340) width 4: " " - LayoutText {#text} at (533,340) size 4x19 - text run at (533,340) width 4: " " - LayoutText {#text} at (0,0) size 0x0 -layer at (8,8) size 175x175 - LayoutEmbeddedObject {object} at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (187,8) size 175x175 - LayoutEmbeddedObject {object} at (179,0) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (366,8) size 175x175 - LayoutEmbeddedObject {object} at (358,0) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (545,8) size 175x175 - LayoutEmbeddedObject {object} at (537,0) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (8,188) size 175x175 - LayoutEmbeddedObject {object} at (0,180) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (187,188) size 175x175 - LayoutEmbeddedObject {object} at (179,180) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (366,188) size 175x175 - LayoutEmbeddedObject {object} at (358,180) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (545,188) size 175x175 - LayoutEmbeddedObject {object} at (537,180) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00]
diff --git a/third_party/blink/web_tests/platform/linux/virtual/layout_ng_experimental/fast/multicol/composited-layer-nested-expected.png b/third_party/blink/web_tests/platform/linux/virtual/layout_ng_experimental/fast/multicol/composited-layer-nested-expected.png new file mode 100644 index 0000000..d749b58 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/virtual/layout_ng_experimental/fast/multicol/composited-layer-nested-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping-expected.png b/third_party/blink/web_tests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping-expected.png deleted file mode 100644 index 44c979b..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-border-radius-clipping-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt index aa51b9d..4a6572b 100644 --- a/third_party/blink/web_tests/platform/linux/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt +++ b/third_party/blink/web_tests/platform/linux/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - [INTERFACES] interface Navigator interface Notification : EventTarget
diff --git a/third_party/blink/web_tests/platform/linux/virtual/video-surface-layer/media/video-zoom-controls-expected.png b/third_party/blink/web_tests/platform/linux/virtual/video-surface-layer/media/video-zoom-controls-expected.png index b7fcfb2..88a4bf83 100644 --- a/third_party/blink/web_tests/platform/linux/virtual/video-surface-layer/media/video-zoom-controls-expected.png +++ b/third_party/blink/web_tests/platform/linux/virtual/video-surface-layer/media/video-zoom-controls-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/custom-elements/form-validation-bubble-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/custom-elements/form-validation-bubble-appearance-expected.png new file mode 100644 index 0000000..d86617d --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.10/custom-elements/form-validation-bubble-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/fast/text/stroking-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/fast/text/stroking-expected.png index 25036b8..6858d46 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.10/fast/text/stroking-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.10/fast/text/stroking-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.png deleted file mode 100644 index 579a255..0000000 --- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/custom-elements/form-validation-bubble-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/custom-elements/form-validation-bubble-appearance-expected.png new file mode 100644 index 0000000..94cc585 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.11/custom-elements/form-validation-bubble-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png deleted file mode 100644 index b6c82a2..0000000 --- a/third_party/blink/web_tests/platform/mac-mac10.12/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/custom-elements/form-validation-bubble-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/custom-elements/form-validation-bubble-appearance-expected.png new file mode 100644 index 0000000..75eb01d --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.12/custom-elements/form-validation-bubble-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/text/stroking-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/text/stroking-expected.png index ec230a9a..10a43c3 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.12/fast/text/stroking-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.12/fast/text/stroking-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/media/video-zoom-controls-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/media/video-zoom-controls-expected.png index e3c7936..c7a8133 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.12/media/video-zoom-controls-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.12/media/video-zoom-controls-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/video-surface-layer/media/video-zoom-controls-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/video-surface-layer/media/video-zoom-controls-expected.png index 503862dc..c7a8133 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/video-surface-layer/media/video-zoom-controls-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/video-surface-layer/media/video-zoom-controls-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/direct-image-compositing-expected.png b/third_party/blink/web_tests/platform/mac/compositing/direct-image-compositing-expected.png index f0fe9800..38758c7 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/direct-image-compositing-expected.png +++ b/third_party/blink/web_tests/platform/mac/compositing/direct-image-compositing-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/geometry/fixed-position-transform-composited-page-scale-down-expected.png b/third_party/blink/web_tests/platform/mac/compositing/geometry/fixed-position-transform-composited-page-scale-down-expected.png index 11cb2c6..44b42c2 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/geometry/fixed-position-transform-composited-page-scale-down-expected.png +++ b/third_party/blink/web_tests/platform/mac/compositing/geometry/fixed-position-transform-composited-page-scale-down-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/geometry/fixed-position-transform-composited-page-scale-expected.png b/third_party/blink/web_tests/platform/mac/compositing/geometry/fixed-position-transform-composited-page-scale-expected.png index 7f9d558..8a9e6cd 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/geometry/fixed-position-transform-composited-page-scale-expected.png +++ b/third_party/blink/web_tests/platform/mac/compositing/geometry/fixed-position-transform-composited-page-scale-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/geometry/layer-due-to-layer-children-expected.png b/third_party/blink/web_tests/platform/mac/compositing/geometry/layer-due-to-layer-children-expected.png index be16801..7172577 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/geometry/layer-due-to-layer-children-expected.png +++ b/third_party/blink/web_tests/platform/mac/compositing/geometry/layer-due-to-layer-children-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/iframes/invisible-nested-iframe-show-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/iframes/invisible-nested-iframe-show-expected.txt new file mode 100644 index 0000000..f3fc8de --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/compositing/iframes/invisible-nested-iframe-show-expected.txt
@@ -0,0 +1,111 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutIFrame IFRAME", + "position": [-11, -11], + "bounds": [368, 218] + }, + { + "name": "LayoutView #document", + "position": [23, 23], + "bounds": [300, 150], + "drawsContent": false + }, + { + "name": "Scrolling Layer", + "position": [23, 23], + "bounds": [285, 150], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "position": [23, 23], + "bounds": [285, 192] + }, + { + "name": "LayoutIFrame IFRAME", + "position": [31, 31], + "bounds": [252, 172] + }, + { + "name": "LayoutView #document", + "position": [32, 32], + "bounds": [250, 170], + "backgroundColor": "#C0C0C0" + }, + { + "name": "LayoutBlockFlow DIV id='iframe-content' class='box'", + "bounds": [210, 210], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "transform": 1 + }, + { + "name": "Overflow Controls Host Layer", + "position": [23, 23], + "bounds": [300, 150], + "drawsContent": false + }, + { + "name": "Vertical Scrollbar Layer", + "position": [308, 23], + "bounds": [15, 150], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV class='box'", + "bounds": [210, 210], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "transform": 3 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [50, 42, 0, 1] + ] + }, + { + "id": 2, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [18, 202, 0, 1] + ] + }, + { + "id": 3, + "parent": 2, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/platform/mac/compositing/lots-of-img-layers-expected.png b/third_party/blink/web_tests/platform/mac/compositing/lots-of-img-layers-expected.png new file mode 100644 index 0000000..d572056d --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/compositing/lots-of-img-layers-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/lots-of-img-layers-with-opacity-expected.png b/third_party/blink/web_tests/platform/mac/compositing/lots-of-img-layers-with-opacity-expected.png new file mode 100644 index 0000000..fdae228 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/compositing/lots-of-img-layers-with-opacity-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/masks/direct-image-mask-expected.png b/third_party/blink/web_tests/platform/mac/compositing/masks/direct-image-mask-expected.png index 7bc2d6e..61fc6164 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/masks/direct-image-mask-expected.png +++ b/third_party/blink/web_tests/platform/mac/compositing/masks/direct-image-mask-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/masks/mask-with-added-filters-expected.png b/third_party/blink/web_tests/platform/mac/compositing/masks/mask-with-added-filters-expected.png index 561186e..82f1ffb 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/masks/mask-with-added-filters-expected.png +++ b/third_party/blink/web_tests/platform/mac/compositing/masks/mask-with-added-filters-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/masks/mask-with-removed-filters-expected.png b/third_party/blink/web_tests/platform/mac/compositing/masks/mask-with-removed-filters-expected.png index 75feda9a..aa0f6173 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/masks/mask-with-removed-filters-expected.png +++ b/third_party/blink/web_tests/platform/mac/compositing/masks/mask-with-removed-filters-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/masks/masked-ancestor-expected.png b/third_party/blink/web_tests/platform/mac/compositing/masks/masked-ancestor-expected.png index 5981fad..2b7ccd8 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/masks/masked-ancestor-expected.png +++ b/third_party/blink/web_tests/platform/mac/compositing/masks/masked-ancestor-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/masks/multiple-masks-expected.png b/third_party/blink/web_tests/platform/mac/compositing/masks/multiple-masks-expected.png index 2986d8da..996a5560 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/masks/multiple-masks-expected.png +++ b/third_party/blink/web_tests/platform/mac/compositing/masks/multiple-masks-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/masks/simple-composited-mask-expected.png b/third_party/blink/web_tests/platform/mac/compositing/masks/simple-composited-mask-expected.png index 5608556b..dca2a9ff 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/masks/simple-composited-mask-expected.png +++ b/third_party/blink/web_tests/platform/mac/compositing/masks/simple-composited-mask-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/overflow/nested-border-radius-clipping-expected.png b/third_party/blink/web_tests/platform/mac/compositing/overflow/nested-border-radius-clipping-expected.png index e97ffd5..7150b21 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/overflow/nested-border-radius-clipping-expected.png +++ b/third_party/blink/web_tests/platform/mac/compositing/overflow/nested-border-radius-clipping-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/overflow/nested-render-surfaces-with-rotation-expected.png b/third_party/blink/web_tests/platform/mac/compositing/overflow/nested-render-surfaces-with-rotation-expected.png index 12eb170..98125e0 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/overflow/nested-render-surfaces-with-rotation-expected.png +++ b/third_party/blink/web_tests/platform/mac/compositing/overflow/nested-render-surfaces-with-rotation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/compositing/squashing/no-squashing-into-another-clip-layer-expected.txt b/third_party/blink/web_tests/platform/mac/compositing/squashing/no-squashing-into-another-clip-layer-expected.txt index 1d92541..30a315ac 100644 --- a/third_party/blink/web_tests/platform/mac/compositing/squashing/no-squashing-into-another-clip-layer-expected.txt +++ b/third_party/blink/web_tests/platform/mac/compositing/squashing/no-squashing-into-another-clip-layer-expected.txt
@@ -25,12 +25,6 @@ "transform": 1 }, { - "name": "Child Containment Layer", - "bounds": [784, 10], - "drawsContent": false, - "transform": 1 - }, - { "name": "LayoutBlockFlow DIV id='inner'", "bounds": [784, 10], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/platform/mac/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png b/third_party/blink/web_tests/platform/mac/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png index 2db5f77..e640c29 100644 --- a/third_party/blink/web_tests/platform/mac/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png +++ b/third_party/blink/web_tests/platform/mac/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/custom-elements/form-validation-bubble-appearance-expected.png b/third_party/blink/web_tests/platform/mac/custom-elements/form-validation-bubble-appearance-expected.png new file mode 100644 index 0000000..d3abce0 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/custom-elements/form-validation-bubble-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-canvas-border-expected.png b/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-canvas-border-expected.png index b26a4dc..f70b2e3 100644 --- a/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-canvas-border-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-canvas-border-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-canvas-expected.png b/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-canvas-expected.png index 50e87f4c..2a7eb24 100644 --- a/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-canvas-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-canvas-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-canvas-with-mask-expected.png b/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-canvas-with-mask-expected.png index 8c84638..a418ea8 100644 --- a/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-canvas-with-mask-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-canvas-with-mask-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-video-expected.png b/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-video-expected.png index 1532d51a..555b749 100644 --- a/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-video-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-video-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-video-ratio-expected.png b/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-video-ratio-expected.png index cfb83ff3..a925361a 100644 --- a/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-video-ratio-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-video-ratio-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-video-shadow-expected.png b/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-video-shadow-expected.png index b3e404cf..173da9ca 100644 --- a/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-video-shadow-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/borders/border-radius-mask-video-shadow-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/clip/overflow-border-radius-composited-expected.png b/third_party/blink/web_tests/platform/mac/fast/clip/overflow-border-radius-composited-expected.png index cfb8441b..64eef08a 100644 --- a/third_party/blink/web_tests/platform/mac/fast/clip/overflow-border-radius-composited-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/clip/overflow-border-radius-composited-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/clip/overflow-border-radius-composited-parent-expected.png b/third_party/blink/web_tests/platform/mac/fast/clip/overflow-border-radius-composited-parent-expected.png index 623125e..3cb3285d 100644 --- a/third_party/blink/web_tests/platform/mac/fast/clip/overflow-border-radius-composited-parent-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/clip/overflow-border-radius-composited-parent-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/multicol/composited-layer-nested-expected.png b/third_party/blink/web_tests/platform/mac/fast/multicol/composited-layer-nested-expected.png index 9d8a7df..b6a4ea4 100644 --- a/third_party/blink/web_tests/platform/mac/fast/multicol/composited-layer-nested-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/multicol/composited-layer-nested-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/multicol/vertical-rl/composited-relpos-overlapping-will-change-expected.png b/third_party/blink/web_tests/platform/mac/fast/multicol/vertical-rl/composited-relpos-overlapping-will-change-expected.png index cfa7310..c7f852d 100644 --- a/third_party/blink/web_tests/platform/mac/fast/multicol/vertical-rl/composited-relpos-overlapping-will-change-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/multicol/vertical-rl/composited-relpos-overlapping-will-change-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/repaint/border-fit-lines-expected.txt b/third_party/blink/web_tests/platform/mac/fast/repaint/border-fit-lines-expected.txt deleted file mode 100644 index 84dcd245..0000000 --- a/third_party/blink/web_tests/platform/mac/fast/repaint/border-fit-lines-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [8, 24, 104, 104], - [8, 24, 14, 104] - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/fast/text/stroking-expected.png b/third_party/blink/web_tests/platform/mac/fast/text/stroking-expected.png index 830820c..86fc5cb 100644 --- a/third_party/blink/web_tests/platform/mac/fast/text/stroking-expected.png +++ b/third_party/blink/web_tests/platform/mac/fast/text/stroking-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/http/tests/webfont/popup-menu-load-webfont-after-open-expected.txt b/third_party/blink/web_tests/platform/mac/http/tests/webfont/popup-menu-load-webfont-after-open-expected.txt index 6acbbd8..9817da62 100644 --- a/third_party/blink/web_tests/platform/mac/http/tests/webfont/popup-menu-load-webfont-after-open-expected.txt +++ b/third_party/blink/web_tests/platform/mac/http/tests/webfont/popup-menu-load-webfont-after-open-expected.txt
@@ -1,9 +1,10 @@ +foo +bar Test that fonts loaded after a popup menu is opened triggers a style recalc. On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - FAIL picker didn't open PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/platform/mac/media/video-zoom-controls-expected.png b/third_party/blink/web_tests/platform/mac/media/video-zoom-controls-expected.png index 8ecaf64..d38f7e7e 100644 --- a/third_party/blink/web_tests/platform/mac/media/video-zoom-controls-expected.png +++ b/third_party/blink/web_tests/platform/mac/media/video-zoom-controls-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/composite-after-paint/selection-change-in-iframe-with-relative-parent-expected.png b/third_party/blink/web_tests/platform/mac/paint/invalidation/composite-after-paint/selection-change-in-iframe-with-relative-parent-expected.png deleted file mode 100644 index 657ffeb..0000000 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/composite-after-paint/selection-change-in-iframe-with-relative-parent-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/composite-after-paint/selection-within-composited-scroller-expected.png b/third_party/blink/web_tests/platform/mac/paint/invalidation/composite-after-paint/selection-within-composited-scroller-expected.png deleted file mode 100644 index f9697380..0000000 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/composite-after-paint/selection-within-composited-scroller-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/composite-after-paint/text-match-highlight-expected.png b/third_party/blink/web_tests/platform/mac/paint/invalidation/composite-after-paint/text-match-highlight-expected.png deleted file mode 100644 index 37f9f97..0000000 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/composite-after-paint/text-match-highlight-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/composited-iframe-scroll-repaint-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/composited-iframe-scroll-repaint-expected.txt deleted file mode 100644 index dd9907a2..0000000 --- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/composited-iframe-scroll-repaint-expected.txt +++ /dev/null
@@ -1,96 +0,0 @@ -{ - "layers": [ - { - "name": "LayoutView #document", - "bounds": [800, 600], - "drawsContent": false, - "backgroundColor": "#FFFFFF" - }, - { - "name": "Scrolling Layer", - "bounds": [800, 600], - "drawsContent": false - }, - { - "name": "Scrolling Contents Layer", - "bounds": [800, 600], - "contentsOpaque": true, - "backgroundColor": "#FFFFFF" - }, - { - "name": "Ancestor Clipping Layer", - "position": [8, 8], - "bounds": [784, 158], - "drawsContent": false - }, - { - "name": "LayoutIFrame IFRAME", - "position": [8, 8], - "bounds": [304, 154] - }, - { - "name": "LayoutView #document", - "position": [10, 10], - "bounds": [300, 150], - "drawsContent": false, - "backgroundColor": "#EEEEEE" - }, - { - "name": "Scrolling Layer", - "position": [10, 10], - "bounds": [300, 150], - "drawsContent": false - }, - { - "name": "Scrolling Contents Layer", - "position": [10, 10], - "bounds": [300, 516], - "backgroundColor": "#EEEEEE", - "transform": 1 - }, - { - "name": "LayoutBlockFlow BODY", - "bounds": [284, 500], - "transform": 2 - }, - { - "name": "Overflow Controls Host Layer", - "position": [10, 10], - "bounds": [300, 150], - "drawsContent": false - }, - { - "name": "Horizontal Scrollbar Layer", - "position": [10, 160], - "bounds": [300, 0] - }, - { - "name": "Vertical Scrollbar Layer", - "position": [310, 10], - "bounds": [0, 150] - } - ], - "transforms": [ - { - "id": 1, - "transform": [ - [1, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 1, 0], - [0, -20, 0, 1] - ], - "flattenInheritedTransform": false - }, - { - "id": 2, - "parent": 1, - "transform": [ - [1, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 1, 0], - [18, 18, 0, 1] - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-2-expected.png b/third_party/blink/web_tests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-2-expected.png index be542869..999393a 100644 --- a/third_party/blink/web_tests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-2-expected.png +++ b/third_party/blink/web_tests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/blink/web_tests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png index 4596d32..7297a86 100644 --- a/third_party/blink/web_tests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png +++ b/third_party/blink/web_tests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/blink/web_tests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png index 0aca9887..f04f971 100644 --- a/third_party/blink/web_tests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png +++ b/third_party/blink/web_tests/platform/mac/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/block/basic/018-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/block/basic/018-expected.png deleted file mode 100644 index ff73093..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/block/basic/018-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/001-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/001-expected.png deleted file mode 100644 index 7b120be..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/001-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/002-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/002-expected.png deleted file mode 100644 index 36c8e271..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/002-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/002-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/002-expected.txt deleted file mode 100644 index d0f8fff..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/002-expected.txt +++ /dev/null
@@ -1,12 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x134 - LayoutBlockFlow {HTML} at (0,0) size 800x134 - LayoutBlockFlow {BODY} at (8,8) size 784x118 - LayoutBlockFlow (anonymous) at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 542x18 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 239: "If you see any red, the test has failed." -layer at (8,26) size 100x100 scrollHeight 200 - LayoutBlockFlow {DIV} at (0,18) size 100x100 [bgcolor=#008000] - LayoutBlockFlow {DIV} at (0,100) size 100x100 [bgcolor=#FF0000]
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/003-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/003-expected.png deleted file mode 100644 index a7ce662..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/003-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/003-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/003-expected.txt deleted file mode 100644 index b6207be..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/003-expected.txt +++ /dev/null
@@ -1,14 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x134 - LayoutBlockFlow {HTML} at (0,0) size 800x134 - LayoutBlockFlow {BODY} at (8,8) size 784x118 - LayoutBlockFlow (anonymous) at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 542x18 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 239: "If you see any red, the test has failed." -layer at (8,26) size 100x100 scrollWidth 200 scrollHeight 200 - LayoutBlockFlow {DIV} at (0,18) size 100x100 - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (150,100) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (150,100) size 100x100 [bgcolor=#008000]
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/004-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/004-expected.png deleted file mode 100644 index 508fb7b3b..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/004-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/004-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/004-expected.txt deleted file mode 100644 index 70658311..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/004-expected.txt +++ /dev/null
@@ -1,17 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x52 - LayoutBlockFlow {HTML} at (0,0) size 800x52 - LayoutBlockFlow {BODY} at (8,8) size 784x36 - LayoutText {#text} at (0,0) size 763x36 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 243: "If you see any red, the test has failed. " - text run at (545,0) width 218: "This test is checking to make sure" - text run at (0,18) width 150: "overflow is done using " - text run at (149,18) width 167: "a containing block model." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,44) size 100x100 scrollWidth 200 scrollHeight 400 - LayoutBlockFlow (positioned) {DIV} at (8,44) size 100x100 [bgcolor=#008000] - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (108,344) size 100x100 backgroundClip at (8,44) size 100x100 clip at (8,44) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (100,300) size 100x100 [bgcolor=#FF0000]
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/005-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/005-expected.png deleted file mode 100644 index 508fb7b3b..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/005-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/005-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/005-expected.txt deleted file mode 100644 index bdf38ae..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/005-expected.txt +++ /dev/null
@@ -1,17 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x152 - LayoutBlockFlow {HTML} at (0,0) size 800x152 - LayoutBlockFlow {BODY} at (8,8) size 784x136 - LayoutBlockFlow (anonymous) at (0,0) size 784x36 - LayoutText {#text} at (0,0) size 763x36 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 243: "If you see any red, the test has failed. " - text run at (545,0) width 218: "This test is checking to make sure" - text run at (0,18) width 150: "overflow is done using " - text run at (149,18) width 167: "a containing block model." -layer at (8,44) size 100x100 scrollWidth 200 scrollHeight 400 - LayoutBlockFlow (relative positioned) {DIV} at (0,36) size 100x100 [bgcolor=#008000] - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (108,344) size 100x100 backgroundClip at (8,44) size 100x100 clip at (8,44) size 100x100 - LayoutBlockFlow (relative positioned) {DIV} at (100,300) size 100x100 [bgcolor=#FF0000]
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/006-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/006-expected.png deleted file mode 100644 index bfd5179b..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/006-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/006-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/006-expected.txt deleted file mode 100644 index 4214f330..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/006-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x70 - LayoutBlockFlow {HTML} at (0,0) size 800x70 - LayoutBlockFlow {BODY} at (8,8) size 784x54 - LayoutText {#text} at (0,0) size 746x54 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 373: "If you see nothing at all or see any red, the test has failed. " - text run at (675,0) width 71: "This test is" - text run at (0,18) width 297: "checking to make sure overflow is done using " - text run at (296,18) width 437: "a containing block model, and that a fixed positioned element inside" - text run at (0,36) width 386: "another fixed positioned element is not considered overflow." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,62) size 100x100 scrollWidth 200 scrollHeight 200 - LayoutBlockFlow (positioned) {DIV} at (8,62) size 100x100 - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (100,70) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (100,70) size 100x100 [bgcolor=#008000]
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/007-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/007-expected.png deleted file mode 100644 index 3403fa4..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/007-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/008-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/008-expected.png deleted file mode 100644 index 3403fa4..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/008-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/008-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/008-expected.txt deleted file mode 100644 index 08292dd..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/008-expected.txt +++ /dev/null
@@ -1,19 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x70 - LayoutBlockFlow {HTML} at (0,0) size 800x70 - LayoutBlockFlow {BODY} at (8,8) size 784x54 - LayoutText {#text} at (0,0) size 752x54 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 373: "If you see nothing at all or see any red, the test has failed. " - text run at (675,0) width 71: "This test is" - text run at (0,18) width 297: "checking to make sure overflow is done using " - text run at (296,18) width 456: "a containing block model, and that a fixed positioned element inside an" - text run at (0,36) width 355: "absolute positioned element is not considered overflow." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,62) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (8,62) size 100x100 -layer at (100,100) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (100,100) size 100x100 -layer at (200,200) size 100x100 - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#008000]
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/009-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/009-expected.png deleted file mode 100644 index c0b12536..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/009-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/009-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/009-expected.txt deleted file mode 100644 index 1d06fcf9..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/009-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x52 - LayoutBlockFlow {HTML} at (0,0) size 800x52 - LayoutBlockFlow {BODY} at (8,8) size 784x36 - LayoutText {#text} at (0,0) size 763x36 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 243: "If you see any red, the test has failed. " - text run at (545,0) width 218: "This test is checking to make sure" - text run at (0,18) width 221: "clip is applying to all descendants." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,44) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (8,44) size 100x100 [bgcolor=#008000] - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (108,344) size 100x100 backgroundClip at (8,44) size 100x100 clip at (8,44) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (100,300) size 100x100 [bgcolor=#FF0000]
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/011-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/011-expected.png deleted file mode 100644 index c0b12536..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/011-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/012-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/012-expected.png deleted file mode 100644 index c0b12536..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/012-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/012-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/012-expected.txt deleted file mode 100644 index 94ab98e5..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/012-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x52 - LayoutBlockFlow {HTML} at (0,0) size 800x52 - LayoutBlockFlow {BODY} at (8,8) size 784x36 - LayoutText {#text} at (0,0) size 763x36 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 243: "If you see any red, the test has failed. " - text run at (545,0) width 218: "This test is checking to make sure" - text run at (0,18) width 221: "clip is applying to all descendants." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,44) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (8,44) size 100x100 [bgcolor=#008000] - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (108,344) size 100x100 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0 - LayoutBlockFlow {DIV} at (100,300) size 100x100 [bgcolor=#FF0000]
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/013-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/013-expected.png deleted file mode 100644 index 9e3a5bb..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/013-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/014-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/014-expected.png deleted file mode 100644 index 4a1690d8..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/014-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/014-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/014-expected.txt deleted file mode 100644 index 3f88ab67..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/014-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x70 - LayoutBlockFlow {HTML} at (0,0) size 800x70 - LayoutBlockFlow {BODY} at (8,8) size 784x54 - LayoutText {#text} at (0,0) size 781x54 - text run at (0,0) width 408: "You should see a 100x100 green square with a scrollbar below. " - text run at (407,0) width 243: "If you see any red, the test has failed. " - text run at (649,0) width 132: "This test is checking" - text run at (0,18) width 635: "to make sure clip applies to the element itself, starts from the border edge, and clips out scrollbars. " - text run at (634,18) width 116: "The bottom of the" - text run at (0,36) width 254: "scrolling mechanism should be clipped." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,62) size 120x220 backgroundClip at (18,72) size 100x100 clip at (18,72) size 85x100 scrollHeight 1000 - LayoutBlockFlow (positioned) {DIV} at (8,62) size 120x220 [bgcolor=#008000] [border: (10px solid #FF0000)] - LayoutBlockFlow {DIV} at (10,10) size 85x1000
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/015-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/015-expected.png deleted file mode 100644 index 2426f87..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/015-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/015-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/015-expected.txt deleted file mode 100644 index 552edfc..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/015-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x134 - LayoutBlockFlow {HTML} at (0,0) size 800x134 - LayoutBlockFlow {BODY} at (8,8) size 784x118 - LayoutBlockFlow (anonymous) at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 743x18 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 440: "This test makes sure overflow uses containing blocks when clipping." -layer at (8,26) size 100x100 scrollWidth 300 scrollHeight 300 - LayoutBlockFlow {DIV} at (0,18) size 100x100 [bgcolor=#008000] -layer at (108,126) size 100x100 backgroundClip at (8,26) size 100x100 clip at (8,26) size 100x100 - LayoutBlockFlow (relative positioned) {DIV} at (0,0) size 100x100 [bgcolor=#FF0000] -layer at (208,226) size 100x100 backgroundClip at (8,26) size 100x100 clip at (8,26) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (100,100) size 100x100
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/016-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/016-expected.png deleted file mode 100644 index 03a1ddb..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/016-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/016-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/016-expected.txt deleted file mode 100644 index a518f153..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/clip/016-expected.txt +++ /dev/null
@@ -1,10 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutText {#text} at (0,0) size 300x18 - text run at (0,0) width 300: "You should see a 100x100 green square below." - LayoutText {#text} at (0,0) size 0x0 -layer at (50,50) size 100x500 backgroundClip at (50,50) size 100x100 clip at (50,50) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (50,50) size 100x500 [bgcolor=#008000]
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/004-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/004-expected.png deleted file mode 100644 index 8392905e..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/004-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/004-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/004-expected.txt deleted file mode 100644 index 3461a142..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/004-expected.txt +++ /dev/null
@@ -1,12 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x534 - LayoutBlockFlow {HTML} at (0,0) size 800x534 - LayoutBlockFlow {BODY} at (8,8) size 784x518 - LayoutBlockFlow (anonymous) at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 712x18 - text run at (0,0) width 712: "The two green blocks below should be identical and should each take up half the width of the browser window." - LayoutBlockFlow (floating) {DIV} at (392,18) size 392x500 [bgcolor=#008000] [border: (1px solid #000000)] - LayoutText {#text} at (0,0) size 0x0 -layer at (8,26) size 392x500 clip at (9,27) size 390x498 - LayoutBlockFlow {DIV} at (0,18) size 392x500 [bgcolor=#008000] [border: (1px solid #000000)]
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/line-clamp-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/line-clamp-expected.png deleted file mode 100644 index e479e5c..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/line-clamp-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/overflow-auto-position-absolute-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/overflow-auto-position-absolute-expected.txt deleted file mode 100644 index 7c472418..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/overflow-auto-position-absolute-expected.txt +++ /dev/null
@@ -1,11 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 -layer at (16,16) size 768x568 clip at (16,16) size 753x568 scrollHeight 1024 - LayoutBlockFlow (positioned) {DIV} at (16,16) size 768x568 -layer at (16,16) size 753x1024 backgroundClip at (16,16) size 753x568 clip at (16,16) size 753x568 - LayoutBlockFlow (positioned) {DIV} at (0,0) size 753x1024 [bgcolor=#008000] - LayoutText {#text} at (0,0) size 316x18 - text run at (0,0) width 316: "This test passes if there is no horizontal scrollbar."
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.png deleted file mode 100644 index f850436..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.txt deleted file mode 100644 index 54cffffe8..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.txt +++ /dev/null
@@ -1,21 +0,0 @@ -layer at (0,0) size 800x600 scrollWidth 7430 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x160 - LayoutBlockFlow {HTML} at (0,0) size 800x160 - LayoutBlockFlow {BODY} at (8,16) size 784x136 - LayoutBlockFlow {P} at (0,0) size 784x54 - LayoutText {#text} at (0,0) size 762x54 - text run at (0,0) width 755: "This tests the interaction of overflow on some very wide text with auto table layout. The CSS 2.1 spec does not define" - text run at (0,18) width 762: "how overflow interacts with intrinsic width, so we copy the IE behavior. Therefore the lines should come out very very" - text run at (0,36) width 243: "wide and scroll along with the border." - LayoutTable {TABLE} at (0,70) size 7422x66 [border: (1px solid #FF0000)] - LayoutTableSection {TBODY} at (1,1) size 7420x64 - LayoutTableRow {TR} at (0,2) size 7420x60 - LayoutTableCell {TD} at (2,2) size 7416x60 [r=0 c=0 rs=1 cs=1] -layer at (12,103) size 7414x32 backgroundClip at (12,103) size 788x32 clip at (13,104) size 787x30 - LayoutBlockFlow {PRE} at (1,14) size 7414x32 [border: (1px solid #0000FF)] - LayoutText {#text} at (1,1) size 7412x30 - text run at (1,1) width 3121: "this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line " - text run at (3121,1) width 1: " " - text run at (1,16) width 7412: "this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line " - text run at (7412,16) width 1: " "
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/block-layout-inline-children-float-positioned-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/block-layout-inline-children-float-positioned-expected.txt deleted file mode 100644 index c8954b20..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/block-layout-inline-children-float-positioned-expected.txt +++ /dev/null
@@ -1,25 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [305, 35, 297, 18], - [305, 35, 296, 18], - [153, 35, 297, 18], - [153, 35, 296, 18] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (floating) SPAN", - "LayoutText #text", - "InlineTextBox 'the quick brown fox jumped over the lazy dog'", - "LayoutBlockFlow (positioned) SPAN", - "LayoutText #text", - "InlineTextBox 'the quick brown fox jumped over the lazy dog'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/box-inline-resize-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/box-inline-resize-expected.txt deleted file mode 100644 index 379229d..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/box-inline-resize-expected.txt +++ /dev/null
@@ -1,30 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [40, 103, 114, 29], - [40, 103, 114, 29], - [8, 103, 114, 29], - [8, 103, 114, 29], - [8, 84, 32, 68], - [8, 84, 32, 32] - ], - "paintInvalidationClients": [ - "RootInlineBox", - "InlineBox", - "InlineBox", - "RootInlineBox", - "LayoutBlockFlow (anonymous)", - "LayoutImage IMG id='foo'", - "LayoutBlockFlow H2", - "LayoutText #text", - "InlineTextBox 'Chromium'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/button-checkbox-click-method-repaint-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/button-checkbox-click-method-repaint-expected.txt deleted file mode 100644 index 2642dfd8b..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/button-checkbox-click-method-repaint-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [10, 61, 31, 30] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow INPUT id='checkbox'", - "LayoutBlockFlow INPUT id='checkbox'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/caret-invalidation-in-overflow-scroll-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/caret-invalidation-in-overflow-scroll-expected.txt deleted file mode 100644 index 23335333..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/caret-invalidation-in-overflow-scroll-expected.txt +++ /dev/null
@@ -1,19 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [408, 10, 4, 15], - [405, 10, 4, 15] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow DIV id='inner-editor'", - "LayoutBlockFlow DIV id='inner-editor'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/control-clip-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/control-clip-expected.txt deleted file mode 100644 index 52742cb..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/control-clip-expected.txt +++ /dev/null
@@ -1,31 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [84, 114, 48, 13], - [80, 114, 56, 13], - [16, 114, 184, 13], - [9, 84, 198, 14], - [9, 84, 55, 14], - [9, 84, 48, 14] - ], - "paintInvalidationClients": [ - "InlineTextBox ''", - "RootInlineBox", - "InlineTextBox ''", - "RootInlineBox", - "LayoutBlockFlow (anonymous)", - "LayoutText (anonymous)", - "InlineTextBox 'SUCCESS'", - "LayoutBlockFlow (anonymous)", - "LayoutText #text", - "InlineTextBox 'SUCCESS'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/focus-continuations-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/focus-continuations-expected.txt deleted file mode 100644 index cea18ce..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/focus-continuations-expected.txt +++ /dev/null
@@ -1,24 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [8, 88, 84, 20], - [3, 83, 94, 30], - [3, 83, 94, 30], - [3, 83, 94, 30] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (positioned) DIV id='container'", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/focus-enable-continuations-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/focus-enable-continuations-expected.txt deleted file mode 100644 index d82d06c..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/focus-enable-continuations-expected.txt +++ /dev/null
@@ -1,25 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [8, 88, 84, 20], - [3, 83, 94, 30], - [3, 83, 94, 30], - [3, 83, 94, 30] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (positioned) DIV id='container'", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "LayoutInline SPAN id='outer'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/focus-ring-on-continuation-move-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/focus-ring-on-continuation-move-expected.txt deleted file mode 100644 index 3cf1167..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/focus-ring-on-continuation-move-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [208, 200, 100, 100], - [8, 200, 100, 100] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (relative positioned) DIV id='block'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/inline-outline-repaint-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/inline-outline-repaint-expected.txt deleted file mode 100644 index d469111..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/inline-outline-repaint-expected.txt +++ /dev/null
@@ -1,129 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [45, 183, 3, 20], - [8, 166, 92, 36], - [8, 166, 90, 36], - [5, 163, 103, 42], - [5, 163, 98, 42], - [5, 163, 96, 42] - ], - "paintInvalidationClients": [ - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "LayoutText #text", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'dolor sit amet'", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'dolor sit'", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'dolor sit'", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'dolor'", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'dolor'", - "InlineFlowBox", - "RootInlineBox", - "LayoutBlockFlow DIV", - "LayoutInline SPAN id='test'", - "InlineFlowBox", - "InlineFlowBox", - "LayoutText #text", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineTextBox 'dolor\u00A0'", - "LayoutBlockFlow DIV" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-1-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-1-expected.txt deleted file mode 100644 index d203637..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-1-expected.txt +++ /dev/null
@@ -1,147 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [378, 138, 70, 30], - [369, 80, 51, 108], - [305, 170, 41, 18], - [301, 404, 67, 18], - [178, 350, 146, 18], - [65, 386, 303, 36], - [65, 350, 146, 18], - [14, 404, 355, 36], - [14, 386, 354, 36], - [14, 353, 48, 65], - [14, 335, 48, 65], - [14, 242, 406, 126], - [14, 224, 406, 126], - [14, 188, 407, 72], - [14, 188, 41, 18], - [14, 170, 407, 72], - [8, 116, 418, 450] - ], - "paintInvalidationClients": [ - "InlineTextBox 'body tucked away,\n'", - "InlineTextBox 'comfortably enough, under her'", - "RootInlineBox", - "InlineTextBox 'arm, with its legs hanging down,\n'", - "InlineTextBox 'but generally, just as'", - "RootInlineBox", - "InlineTextBox 'she had got its neck nicely straightened\n'", - "InlineTextBox 'out, and was'", - "RootInlineBox", - "InlineTextBox 'going to give the hedgehog a blow with its head, it'", - "RootInlineBox", - "InlineTextBox 'would'", - "InlineTextBox ' twist itself round and look up in her face, with\n'", - "InlineTextBox 'such a'", - "RootInlineBox", - "InlineTextBox 'puzzled expression that she could not help bursting out'", - "RootInlineBox", - "InlineTextBox 'laughing: and when she had got its head down, and was going'", - "RootInlineBox", - "InlineTextBox 'to\n'", - "InlineTextBox 'begin again, it was very provoking to find that the hedgehog'", - "RootInlineBox", - "InlineTextBox 'had\n'", - "InlineTextBox 'unrolled itself, and was in the act of crawling away:'", - "RootInlineBox", - "InlineTextBox 'besides all\n'", - "InlineTextBox 'this, there was generally a ridge or furrow in the'", - "RootInlineBox", - "InlineTextBox 'way wherever\n'", - "InlineTextBox 'she wanted to send the hedgehog to, and, as the'", - "RootInlineBox", - "InlineTextBox 'doubled-up\n'", - "InlineTextBox 'soldiers were always getting up and walking off to'", - "RootInlineBox", - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion'", - "RootInlineBox", - "InlineTextBox 'that it was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting'", - "RootInlineBox", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "RootInlineBox", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the'", - "RootInlineBox", - "InlineTextBox 'Queen'", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "RootInlineBox", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with'", - "RootInlineBox", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet'", - "RootInlineBox", - "InlineTextBox 'had any dispute with the Queen, but she knew that it might'", - "RootInlineBox", - "InlineTextBox 'happen any minute, \u2018and then,\u2019 thought she, \u2018what would'", - "RootInlineBox", - "InlineTextBox 'become of\n'", - "InlineTextBox 'me? They\u2019re dreadfully fond of beheading people'", - "RootInlineBox", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "LayoutBlockFlow (floating) DIV id='pinkFloat'", - "LayoutBlockFlow P", - "LayoutText #text", - "InlineTextBox 'The chief difficulty Alice found at first was in'", - "InlineTextBox 'managing her\n'", - "InlineTextBox 'flamingo: she succeeded in getting its'", - "InlineTextBox 'body tucked away,\n'", - "InlineTextBox 'comfortably enough, under her'", - "InlineTextBox 'arm, with its legs hanging down,\n'", - "InlineTextBox 'but generally, just as'", - "InlineTextBox 'she had got its neck nicely straightened\n'", - "InlineTextBox 'out, and was going to'", - "InlineTextBox 'give the hedgehog a blow with its head, it\n'", - "LayoutText #text", - "InlineTextBox 'would'", - "LayoutText #text", - "InlineTextBox ' twist itself'", - "InlineTextBox 'round and look up in her face, with\n'", - "InlineTextBox 'such a puzzled expression'", - "InlineTextBox 'that she could not help bursting out\n'", - "InlineTextBox 'laughing: and when she'", - "InlineTextBox 'had got its head down, and was going to\n'", - "LayoutText #text", - "InlineTextBox 'begin again, it was'", - "InlineTextBox 'very provoking to find that the hedgehog had\n'", - "InlineTextBox 'unrolled itself,'", - "InlineTextBox 'and was in the act of crawling away: besides all\n'", - "InlineTextBox 'this, there was'", - "InlineTextBox 'generally a ridge or furrow in the way wherever\n'", - "InlineTextBox 'she wanted to'", - "InlineTextBox 'send the hedgehog to, and, as the doubled-up\n'", - "InlineTextBox 'soldiers were'", - "InlineTextBox 'always getting up and walking off to other parts of\n'", - "InlineTextBox 'the ground,'", - "InlineTextBox 'Alice soon came to the conclusion that it was a very'", - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "LayoutText #text", - "InlineTextBox 'difficult game indeed.\n'", - "LayoutText #text", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "LayoutText #text", - "InlineTextBox 'the Queen'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-10-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-10-expected.txt deleted file mode 100644 index 4dbd2fd..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-10-expected.txt +++ /dev/null
@@ -1,67 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [369, 422, 1, 54], - [65, 404, 304, 36], - [14, 404, 355, 36], - [14, 364, 48, 64], - [14, 353, 48, 65], - [8, 332, 418, 234] - ], - "paintInvalidationClients": [ - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion'", - "RootInlineBox", - "InlineTextBox 'that it was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting'", - "RootInlineBox", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "RootInlineBox", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the'", - "RootInlineBox", - "InlineTextBox 'Queen'", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "RootInlineBox", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with'", - "RootInlineBox", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet'", - "RootInlineBox", - "InlineTextBox 'had any dispute with the Queen, but she knew that it might'", - "RootInlineBox", - "InlineTextBox 'happen any minute, \u2018and then,\u2019 thought she, \u2018what would'", - "RootInlineBox", - "InlineTextBox 'become of\n'", - "InlineTextBox 'me? They\u2019re dreadfully fond of beheading people'", - "RootInlineBox", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "LayoutText #text", - "InlineTextBox 'the'", - "InlineTextBox 'Queen'", - "LayoutText #text", - "InlineTextBox ' was in a furious passion, and went'", - "InlineTextBox 'stamping about, and shouting \u2018Off with his head!\u2019 or'", - "InlineTextBox '\u2018Off with\n'", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-2-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-2-expected.txt deleted file mode 100644 index 5155730..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-2-expected.txt +++ /dev/null
@@ -1,98 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [372, 375, 48, 81], - [372, 371, 48, 81], - [178, 354, 146, 18], - [178, 350, 146, 18], - [65, 390, 303, 36], - [65, 386, 303, 36], - [65, 372, 304, 18], - [65, 368, 304, 18], - [14, 480, 407, 90], - [14, 476, 407, 90], - [14, 426, 355, 54], - [14, 422, 355, 54], - [14, 408, 355, 36], - [14, 404, 355, 36], - [14, 357, 48, 65], - [14, 353, 48, 65], - [14, 246, 406, 126], - [14, 242, 406, 126], - [14, 191, 407, 73], - [14, 188, 407, 72], - [14, 188, 45, 22], - [14, 188, 41, 18], - [8, 572, 418, 4], - [8, 569, 418, 7], - [8, 170, 418, 400] - ], - "paintInvalidationClients": [ - "InlineTextBox 'going to give the hedgehog a blow with its head, it'", - "RootInlineBox", - "InlineTextBox ''", - "InlineTextBox ' twist itself round and look up in her face, with\n'", - "InlineTextBox 'such a'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutBlockFlow P", - "LayoutInline I id='would'", - "LayoutText #text", - "InlineTextBox 'would'", - "LayoutText #text", - "InlineTextBox ' twist itself round and look up in her face, with\n'", - "InlineTextBox 'such a'", - "InlineTextBox 'puzzled expression that she could not help bursting out'", - "InlineTextBox 'laughing: and when she had got its head down, and was going'", - "InlineTextBox 'to\n'", - "LayoutText #text", - "InlineTextBox 'begin again, it was very provoking to find that the hedgehog'", - "InlineTextBox 'had\n'", - "InlineTextBox 'unrolled itself, and was in the act of crawling away:'", - "InlineTextBox 'besides all\n'", - "InlineTextBox 'this, there was generally a ridge or furrow in the'", - "InlineTextBox 'way wherever\n'", - "InlineTextBox 'she wanted to send the hedgehog to, and, as the'", - "InlineTextBox 'doubled-up\n'", - "InlineTextBox 'soldiers were always getting up and walking off to'", - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion'", - "InlineTextBox 'that it was a very\n'", - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "LayoutText #text", - "InlineTextBox 'difficult game indeed.\n'", - "LayoutText #text", - "InlineTextBox 'The players all played at once without waiting'", - "LayoutBlockFlow (floating) SPAN id='greenFloat'", - "LayoutText #text", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "LayoutText #text", - "InlineTextBox 'the'", - "InlineTextBox 'Queen'", - "LayoutText #text", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with'", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'", - "LayoutText #text", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet'", - "InlineTextBox 'had any dispute with the Queen, but she knew that it might'", - "InlineTextBox 'happen any minute, \u2018and then,\u2019 thought she, \u2018what would'", - "InlineTextBox 'become of\n'", - "InlineTextBox 'me? They\u2019re dreadfully fond of beheading people'", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-3-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-3-expected.txt deleted file mode 100644 index bd84dea..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-3-expected.txt +++ /dev/null
@@ -1,71 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [372, 371, 48, 81], - [369, 368, 32, 18], - [356, 389, 64, 81], - [354, 422, 15, 54], - [65, 386, 303, 36], - [65, 368, 356, 54], - [14, 422, 72, 18], - [14, 404, 355, 36], - [8, 368, 418, 198] - ], - "paintInvalidationClients": [ - "InlineTextBox 'The players all played at once without waiting'", - "RootInlineBox", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "RootInlineBox", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the'", - "RootInlineBox", - "InlineTextBox 'Queen'", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "RootInlineBox", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with'", - "RootInlineBox", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet'", - "RootInlineBox", - "InlineTextBox 'had any dispute with the Queen, but she knew that it might'", - "RootInlineBox", - "InlineTextBox 'happen any minute, \u2018and then,\u2019 thought she, \u2018what would'", - "RootInlineBox", - "InlineTextBox 'become of\n'", - "InlineTextBox 'me? They\u2019re dreadfully fond of beheading people'", - "RootInlineBox", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutText #text", - "InlineTextBox 'The players all played at once without waiting\n'", - "LayoutBlockFlow (floating) SPAN id='greenFloat'", - "LayoutText #text", - "InlineTextBox 'for'", - "InlineTextBox 'turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time'", - "LayoutText #text", - "InlineTextBox 'the Queen'", - "LayoutText #text", - "InlineTextBox ' was in a furious passion, and went'", - "InlineTextBox 'stamping about, and shouting \u2018Off with his head!\u2019 or'", - "InlineTextBox '\u2018Off with\n'", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-4-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-4-expected.txt deleted file mode 100644 index 4715f1f..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-4-expected.txt +++ /dev/null
@@ -1,56 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [372, 435, 48, 17], - [369, 422, 52, 54], - [8, 368, 418, 198] - ], - "paintInvalidationClients": [ - "InlineTextBox 'The players all played at once without waiting'", - "RootInlineBox", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "RootInlineBox", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the'", - "RootInlineBox", - "InlineTextBox 'Queen'", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "RootInlineBox", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with'", - "RootInlineBox", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet'", - "RootInlineBox", - "InlineTextBox 'had any dispute with the Queen, but she knew that it might'", - "RootInlineBox", - "InlineTextBox 'happen any minute, \u2018and then,\u2019 thought she, \u2018what would'", - "RootInlineBox", - "InlineTextBox 'become of\n'", - "InlineTextBox 'me? They\u2019re dreadfully fond of beheading people'", - "RootInlineBox", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutBlockFlow (floating) SPAN id='greenFloat'", - "LayoutText #text", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her'", - "InlineTextBox 'head!\u2019 about once in a minute.\n'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-6-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-6-expected.txt deleted file mode 100644 index 75469f1b..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-6-expected.txt +++ /dev/null
@@ -1,37 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [27, 353, 22, 19], - [14, 353, 48, 65], - [8, 332, 418, 90] - ], - "paintInvalidationClients": [ - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion'", - "RootInlineBox", - "InlineTextBox 'that it was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting'", - "RootInlineBox", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "RootInlineBox", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "LayoutText #text", - "InlineTextBox 'foo'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-8-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-8-expected.txt deleted file mode 100644 index 8d7a49bd..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-8-expected.txt +++ /dev/null
@@ -1,110 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [246, 404, 66, 18], - [178, 350, 146, 18], - [127, 350, 146, 18], - [65, 386, 303, 36], - [65, 368, 304, 18], - [14, 422, 355, 54], - [14, 404, 355, 72], - [14, 404, 355, 36], - [14, 368, 355, 54], - [14, 368, 336, 18], - [14, 353, 48, 65], - [8, 80, 418, 396] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "InlineTextBox 'The chief difficulty Alice found at first was in'", - "RootInlineBox", - "InlineTextBox 'managing her\n'", - "InlineTextBox 'flamingo: she succeeded in getting its'", - "RootInlineBox", - "InlineTextBox 'body tucked away,\n'", - "InlineTextBox 'comfortably enough, under her'", - "RootInlineBox", - "InlineTextBox 'arm, with its legs hanging down,\n'", - "InlineTextBox 'but generally, just as'", - "RootInlineBox", - "InlineTextBox 'she had got its neck nicely straightened\n'", - "InlineTextBox 'out, and was'", - "RootInlineBox", - "InlineTextBox 'going to give the hedgehog a blow with its head, it'", - "RootInlineBox", - "InlineTextBox 'would'", - "InlineTextBox ' twist itself round and look up in her face, with\n'", - "InlineTextBox 'such a'", - "RootInlineBox", - "InlineTextBox 'puzzled expression that she could not help bursting out'", - "RootInlineBox", - "InlineTextBox 'laughing: and when she had got its head down, and was going'", - "RootInlineBox", - "InlineTextBox 'to\n'", - "InlineTextBox 'begin again, it was very provoking to find that the hedgehog'", - "RootInlineBox", - "InlineTextBox 'had\n'", - "InlineTextBox 'unrolled itself, and was in the act of crawling away:'", - "RootInlineBox", - "InlineTextBox 'besides all\n'", - "InlineTextBox 'this, there was generally a ridge or furrow in the'", - "RootInlineBox", - "InlineTextBox 'way wherever\n'", - "InlineTextBox 'she wanted to send the hedgehog to, and, as the'", - "RootInlineBox", - "InlineTextBox 'doubled-up\n'", - "InlineTextBox 'soldiers were always getting up and walking off to'", - "RootInlineBox", - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion'", - "RootInlineBox", - "InlineTextBox 'that it was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting'", - "RootInlineBox", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "RootInlineBox", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the'", - "RootInlineBox", - "InlineTextBox 'Queen'", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "RootInlineBox", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with'", - "RootInlineBox", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutText #text", - "InlineTextBox 'difficult game indeed.\n'", - "LayoutText #text", - "InlineTextBox 'The players all played at once without waiting\n'", - "LayoutText #text", - "InlineTextBox 'for'", - "InlineTextBox 'turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting for the'", - "InlineTextBox 'hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "LayoutText #text", - "InlineTextBox 'the Queen'", - "LayoutText #text", - "InlineTextBox ' was in a'", - "InlineTextBox 'furious passion, and went\n'", - "InlineTextBox 'stamping about, and'", - "InlineTextBox 'shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019'", - "InlineTextBox 'about once in a minute.\n'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-9-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-9-expected.txt deleted file mode 100644 index 41b084dd6..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-9-expected.txt +++ /dev/null
@@ -1,170 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [485, 297, 15, 303], - [485, 15, 15, 585], - [485, 0, 15, 600], - [485, 0, 15, 600], - [485, 0, 15, 600], - [485, 0, 15, 594], - [485, 0, 15, 297], - [372, 389, 48, 81], - [372, 371, 48, 81], - [372, 245, 48, 49], - [301, 422, 67, 18], - [178, 350, 146, 18], - [65, 386, 304, 18], - [65, 386, 303, 36], - [65, 368, 304, 18], - [65, 350, 356, 36], - [14, 494, 407, 90], - [14, 476, 407, 90], - [14, 440, 355, 54], - [14, 422, 355, 54], - [14, 404, 355, 36], - [14, 404, 354, 36], - [8, 572, 418, 18], - [8, 569, 418, 21], - [0, 0, 500, 600], - [0, 0, 485, 600], - [0, 0, 485, 600], - [0, 0, 15, 15], - [0, 0, 15, 15] - ], - "paintInvalidationClients": [ - "InlineTextBox 'The chief difficulty Alice found at first was in'", - "RootInlineBox", - "InlineTextBox 'managing her\n'", - "InlineTextBox 'flamingo: she succeeded in getting its'", - "RootInlineBox", - "InlineTextBox 'body tucked away,\n'", - "InlineTextBox 'comfortably enough, under her'", - "RootInlineBox", - "InlineTextBox 'arm, with its legs hanging down,\n'", - "InlineTextBox 'but generally, just as'", - "RootInlineBox", - "InlineTextBox 'she had got its neck nicely straightened\n'", - "InlineTextBox 'out, and was'", - "RootInlineBox", - "InlineTextBox 'going to give the hedgehog a blow with its head, it'", - "RootInlineBox", - "InlineTextBox 'would'", - "InlineTextBox ' twist itself round and look up in her face, with\n'", - "InlineTextBox 'such a'", - "RootInlineBox", - "InlineTextBox 'puzzled expression that she could not help bursting out'", - "RootInlineBox", - "InlineTextBox 'laughing: and when she had got its head down, and was going'", - "RootInlineBox", - "InlineTextBox 'to\n'", - "InlineTextBox 'begin again, it was very provoking to find that the hedgehog'", - "RootInlineBox", - "InlineTextBox 'had\n'", - "InlineTextBox 'unrolled itself, and was in the act of crawling away:'", - "RootInlineBox", - "InlineTextBox 'besides all\n'", - "InlineTextBox 'this, there was generally a ridge or furrow in the'", - "RootInlineBox", - "InlineTextBox 'way wherever\n'", - "InlineTextBox 'she wanted to send the hedgehog to, and, as the'", - "RootInlineBox", - "InlineTextBox 'doubled-up\n'", - "InlineTextBox 'soldiers were always getting up and walking off to'", - "RootInlineBox", - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion'", - "RootInlineBox", - "InlineTextBox 'that it was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting'", - "RootInlineBox", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "RootInlineBox", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the'", - "RootInlineBox", - "InlineTextBox 'Queen'", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "RootInlineBox", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with'", - "RootInlineBox", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet'", - "RootInlineBox", - "InlineTextBox 'had any dispute with the Queen, but she knew that it might'", - "RootInlineBox", - "InlineTextBox 'happen any minute, \u2018and then,\u2019 thought she, \u2018what would'", - "RootInlineBox", - "InlineTextBox 'become of\n'", - "InlineTextBox 'me? They\u2019re dreadfully fond of beheading people'", - "RootInlineBox", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "VerticalScrollbar", - "LayoutIFrame IFRAME id='iframe'", - "LayoutIFrame IFRAME id='iframe'", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "VerticalScrollbar", - "LayoutIFrame IFRAME id='iframe'", - "VerticalScrollbar", - "LayoutIFrame IFRAME id='iframe'", - "VerticalScrollbar", - "LayoutIFrame IFRAME id='iframe'", - "VerticalScrollbar", - "LayoutIFrame IFRAME id='iframe'", - "VerticalScrollbar", - "LayoutIFrame IFRAME id='iframe'", - "VerticalScrollbar", - "LayoutIFrame IFRAME id='iframe'", - "LayoutView #document", - "LayoutView #document", - "LayoutBlockFlow HTML", - "LayoutBlockFlow P", - "LayoutBlockFlow (floating) SPAN id='yellowFloat'", - "LayoutText #text", - "InlineTextBox 'difficult'", - "InlineTextBox 'game indeed.\n'", - "LayoutText #text", - "InlineTextBox 'The players all played at once without waiting'", - "LayoutBlockFlow (floating) SPAN id='greenFloat'", - "LayoutText #text", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "LayoutText #text", - "InlineTextBox 'the Queen'", - "LayoutText #text", - "InlineTextBox 'was in a furious passion, and went\n'", - "InlineTextBox 'stamping about, and'", - "InlineTextBox 'shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019'", - "InlineTextBox 'about once in a minute.\n'", - "LayoutText #text", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet'", - "InlineTextBox 'had any dispute with the Queen, but she knew that it might'", - "InlineTextBox 'happen any minute, \u2018and then,\u2019 thought she, \u2018what would'", - "InlineTextBox 'become of\n'", - "InlineTextBox 'me? They\u2019re dreadfully fond of beheading people'", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-overflow-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-overflow-expected.txt deleted file mode 100644 index b6ad968..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/line-overflow-expected.txt +++ /dev/null
@@ -1,46 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [115, 114, 37, 18], - [115, 84, 37, 48], - [38, 132, 36, 18], - [38, 132, 36, 18], - [8, 132, 192, 72], - [8, 114, 200, 90], - [8, 84, 200, 120] - ], - "paintInvalidationClients": [ - "InlineTextBox 'convallis,\n'", - "InlineTextBox 'augue'", - "RootInlineBox", - "InlineTextBox 'purus'", - "InlineFlowBox", - "InlineTextBox ' eleifend lacus,'", - "RootInlineBox", - "InlineTextBox 'at sagittis eros leo pulvinar'", - "RootInlineBox", - "InlineTextBox 'velit. Integer sollicitudin nisi'", - "RootInlineBox", - "InlineTextBox 'ut urna blandit convallis.'", - "RootInlineBox", - "LayoutBlockFlow DIV", - "LayoutInline SPAN id='t'", - "InlineFlowBox", - "LayoutText #text", - "InlineTextBox 'purus'", - "LayoutText #text", - "InlineTextBox ' eleifend'", - "InlineTextBox 'lacus, at sagittis eros leo'", - "InlineTextBox 'pulvinar velit. Integer'", - "InlineTextBox 'sollicitudin nisi ut urna blandit'", - "InlineTextBox 'convallis.'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/offset-change-wrong-invalidation-with-float-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/offset-change-wrong-invalidation-with-float-expected.txt deleted file mode 100644 index d567d77..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/offset-change-wrong-invalidation-with-float-expected.txt +++ /dev/null
@@ -1,24 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [71, 92, 17, 18], - [71, 92, 7, 18], - [71, -158, 17, 18], - [71, -158, 7, 18], - [48, 92, 40, 18], - [48, -158, 40, 18] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (positioned) UL id='submenu'", - "LayoutListItem LI", - "LayoutListMarker (anonymous)" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/outline-change-offset-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/outline-change-offset-expected.txt deleted file mode 100644 index e4f270f..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/outline-change-offset-expected.txt +++ /dev/null
@@ -1,20 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [40, 40, 120, 120], - [35, 35, 130, 130], - [35, 35, 130, 130] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (positioned) DIV id='indicator'", - "LayoutBlockFlow (positioned) DIV id='target'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.png deleted file mode 100644 index 3ba6dc02..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.txt deleted file mode 100644 index 5bbe7c0..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.txt +++ /dev/null
@@ -1,33 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [18, 148, 200, 18], - [18, 110, 200, 18], - [16, 146, 204, 42], - [16, 146, 202, 22], - [16, 108, 204, 80], - [16, 108, 204, 80] - ], - "paintInvalidationClients": [ - "InlineTextBox 'CONTENTS'", - "RootInlineBox", - "InlineTextBox 'CONTENTS'", - "RootInlineBox", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "InlineFlowBox", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "InlineFlowBox", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/relative-inline-positioned-movement-repaint-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/relative-inline-positioned-movement-repaint-expected.txt deleted file mode 100644 index 2d9f78b..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/relative-inline-positioned-movement-repaint-expected.txt +++ /dev/null
@@ -1,28 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [69, 8, 372, 18], - [68, 7, 374, 20], - [29, 8, 372, 18], - [28, 7, 374, 20], - [8, 7, 784, 20] - ], - "paintInvalidationClients": [ - "InlineTextBox 'When this layer moves it shouldn't generate a repaint rect.'", - "InlineFlowBox", - "RootInlineBox", - "LayoutBlockFlow BODY", - "LayoutInline (relative positioned) DIV id='block'", - "InlineFlowBox", - "LayoutText #text", - "InlineTextBox 'When this layer moves it shouldn't generate a repaint rect.'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/remove-inline-after-layout-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/remove-inline-after-layout-expected.txt deleted file mode 100644 index f662714..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/remove-inline-after-layout-expected.txt +++ /dev/null
@@ -1,35 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [293, 108, 101, 100], - [112, 194, 182, 18], - [112, 108, 100, 100], - [8, 108, 784, 208] - ], - "paintInvalidationClients": [ - "InlineBox", - "InlineTextBox '\n'", - "InlineTextBox 'This span should disappear.\n'", - "InlineBox", - "RootInlineBox", - "InlineTextBox 'This span should disappear.'", - "LayoutText #text", - "InlineFlowBox", - "LayoutInline SPAN id='target'", - "InlineBox", - "InlineTextBox '\n'", - "RootInlineBox", - "InlineBox", - "RootInlineBox", - "LayoutBlockFlow (anonymous)", - "LayoutBlockFlow DIV" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/remove-inline-layer-after-layout-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/remove-inline-layer-after-layout-expected.txt deleted file mode 100644 index 60ab9c8c..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/remove-inline-layer-after-layout-expected.txt +++ /dev/null
@@ -1,36 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [293, 108, 101, 100], - [112, 194, 182, 18], - [112, 108, 182, 104], - [112, 108, 100, 100], - [8, 108, 784, 104] - ], - "paintInvalidationClients": [ - "InlineBox", - "InlineTextBox '\n'", - "InlineTextBox 'This span should disappear.\n'", - "InlineFlowBox", - "InlineBox", - "RootInlineBox", - "InlineTextBox 'This span should disappear.\n'", - "LayoutText #text", - "InlineFlowBox", - "LayoutInline SPAN id='target'", - "InlineBox", - "InlineTextBox '\n'", - "InlineBox", - "RootInlineBox", - "LayoutBlockFlow (anonymous)", - "LayoutBlockFlow DIV" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/repaint-across-writing-mode-boundary-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/repaint-across-writing-mode-boundary-expected.txt deleted file mode 100644 index 7794544..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/repaint-across-writing-mode-boundary-expected.txt +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [548, 191, 24, 35] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow HTML", - "LayoutBlockFlow BODY", - "LayoutBlockFlow DIV class='lrblock'", - "LayoutBlockFlow DIV class='basic d1 vert'", - "LayoutBlockFlow P", - "LayoutText #text", - "InlineTextBox '\u7B2C\u4E00\u6BB5\u843D paragraph 1'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/repaint-during-scroll-with-zoom-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/repaint-during-scroll-with-zoom-expected.txt deleted file mode 100644 index 54c86235..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/repaint-during-scroll-with-zoom-expected.txt +++ /dev/null
@@ -1,46 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "backgroundColor": "#C0C0C0", - "repaintRects": [ - [237, 78, 15, 222], - [237, 65, 15, 28], - [237, 64, 15, 15], - [17, 299, 220, 16], - [3, 299, 28, 16], - [2, 299, 15, 16], - [2, 64, 235, 236], - [2, 64, 235, 236], - [2, 64, 235, 236], - [2, 64, 225, 226], - [2, 64, 135, 136], - [2, 64, 58, 17] - ], - "paintInvalidationClients": [ - "HorizontalScrollbar", - "LayoutIFrame (positioned) IFRAME", - "HorizontalScrollbar", - "LayoutIFrame (positioned) IFRAME", - "HorizontalScrollbar", - "LayoutIFrame (positioned) IFRAME", - "VerticalScrollbar", - "LayoutIFrame (positioned) IFRAME", - "VerticalScrollbar", - "LayoutIFrame (positioned) IFRAME", - "VerticalScrollbar", - "LayoutIFrame (positioned) IFRAME", - "LayoutIFrame (positioned) IFRAME", - "LayoutView #document", - "LayoutBlockFlow HTML", - "LayoutBlockFlow BODY", - "LayoutText #text", - "InlineTextBox 'scroll me'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/select-option-background-color-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/select-option-background-color-expected.txt deleted file mode 100644 index f11900b..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/fast/repaint/select-option-background-color-expected.txt +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [1, 35, 12, 15] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow OPTION id='option'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/inline/outline-offset-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/inline/outline-offset-expected.png deleted file mode 100644 index 839eee9..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/inline/outline-offset-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/inline/outline-offset-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/inline/outline-offset-expected.txt deleted file mode 100644 index 360706f..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/inline/outline-offset-expected.txt +++ /dev/null
@@ -1,47 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x474 - LayoutBlockFlow {HTML} at (0,0) size 800x474 - LayoutBlockFlow {BODY} at (8,50) size 784x374 - LayoutBlockFlow {DIV} at (50,0) size 140x162 - LayoutText {#text} at (0,0) size 50x18 - text run at (0,0) width 50: "Lorem " - LayoutInline {SPAN} at (0,0) size 133x36 - LayoutText {#text} at (49,0) size 133x36 - text run at (49,0) width 84: "ipsum dolor" - text run at (0,18) width 57: "sit amet" - LayoutText {#text} at (56,18) size 101x72 - text run at (56,18) width 5: "," - text run at (0,36) width 83: "consectetur" - text run at (0,54) width 101: "adipiscing elit." - text run at (0,72) width 65: "Quisque " - LayoutInline {SPAN} at (0,0) size 115x36 - LayoutText {#text} at (64,72) size 115x36 - text run at (64,72) width 51: "fringilla" - text run at (0,90) width 65: "libero vel" - LayoutText {#text} at (64,90) size 125x72 - text run at (64,90) width 42: " ligula" - text run at (0,108) width 117: "viverra tincidunt." - text run at (0,126) width 110: "Quisque lacinia" - text run at (0,144) width 125: "tincidunt tristique." - LayoutBlockFlow {DIV} at (50,212) size 140x162 - LayoutText {#text} at (0,0) size 50x18 - text run at (0,0) width 50: "Lorem " - LayoutInline {SPAN} at (0,0) size 133x36 - LayoutText {#text} at (49,0) size 133x36 - text run at (49,0) width 84: "ipsum dolor" - text run at (0,18) width 57: "sit amet" - LayoutText {#text} at (56,18) size 101x72 - text run at (56,18) width 5: "," - text run at (0,36) width 83: "consectetur" - text run at (0,54) width 101: "adipiscing elit." - text run at (0,72) width 65: "Quisque " - LayoutInline {SPAN} at (0,0) size 115x36 - LayoutText {#text} at (64,72) size 115x36 - text run at (64,72) width 51: "fringilla" - text run at (0,90) width 65: "libero vel" - LayoutText {#text} at (64,90) size 125x72 - text run at (64,90) width 42: " ligula" - text run at (0,108) width 117: "viverra tincidunt." - text run at (0,126) width 110: "Quisque lacinia" - text run at (0,144) width 125: "tincidunt tristique."
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/animated-gif-background-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/animated-gif-background-expected.txt deleted file mode 100644 index c5eebda..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/animated-gif-background-expected.txt +++ /dev/null
@@ -1,19 +0,0 @@ -{ - "bounds": [2008, 2016], - "children": [ - { - "bounds": [2008, 2016], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [8, 58, 50, 50], - [8, 8, 50, 50] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow DIV id='targetImage'", - "LayoutImage IMG id='testTarget'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/animated-gif-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/animated-gif-expected.txt deleted file mode 100644 index c0e0ebef..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/animated-gif-expected.txt +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "bounds": [2008, 2016], - "children": [ - { - "bounds": [2008, 2016], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [8, 8, 50, 50] - ], - "paintInvalidationClients": [ - "LayoutImage IMG id='targetImage'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/composite-after-paint/image-resize-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/composite-after-paint/image-resize-expected.png deleted file mode 100644 index f3c604d..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/composite-after-paint/image-resize-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/composite-after-paint/percent-size-image-resize-container-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/composite-after-paint/percent-size-image-resize-container-expected.png deleted file mode 100644 index 767b178..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/composite-after-paint/percent-size-image-resize-container-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/composite-after-paint/selection-change-in-iframe-with-relative-parent-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/composite-after-paint/selection-change-in-iframe-with-relative-parent-expected.png deleted file mode 100644 index e8c6a0d..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/composite-after-paint/selection-change-in-iframe-with-relative-parent-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/composite-after-paint/text-match-highlight-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/composite-after-paint/text-match-highlight-expected.png deleted file mode 100644 index da01876..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/invalidation/composite-after-paint/text-match-highlight-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/roundedrects/circle-with-shadow-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/roundedrects/circle-with-shadow-expected.png deleted file mode 100644 index efefbf6d..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/roundedrects/circle-with-shadow-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/roundedrects/input-with-rounded-rect-and-shadow-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/roundedrects/input-with-rounded-rect-and-shadow-expected.png deleted file mode 100644 index 40080e17..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/roundedrects/input-with-rounded-rect-and-shadow-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/selection-within-composited-scroller-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/selection-within-composited-scroller-expected.txt deleted file mode 100644 index 62c2d2a..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/selection-within-composited-scroller-expected.txt +++ /dev/null
@@ -1,22 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [8, 168, 23, 18] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow HTML", - "LayoutBlockFlow BODY", - "LayoutBlockFlow DIV id='scroller'", - "LayoutBlockFlow DIV id='target'", - "LayoutText #text", - "InlineTextBox 'test'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-across-blocks-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-across-blocks-expected.png deleted file mode 100644 index 65720485..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-across-blocks-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-br-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-br-expected.png deleted file mode 100644 index 65720485..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-expected.png deleted file mode 100644 index b48ac90..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.png deleted file mode 100644 index 1504616b..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.txt deleted file mode 100644 index 32c5a47..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.txt +++ /dev/null
@@ -1,17 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x145 - LayoutBlockFlow {HTML} at (0,0) size 800x145 - LayoutBlockFlow {BODY} at (8,16) size 784x121 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 348x18 - text run at (0,0) width 348: "Passes if there are no overpainted selection highlights." - LayoutBlockFlow (anonymous) at (0,34) size 784x87 - LayoutInline {SPAN} at (0,0) size 189x74 - LayoutText {#text} at (0,3) size 189x74 - text run at (0,3) width 96: "text" - text run at (95,3) width 94 RTL: "\x{645}\x{62A}\x{646}:" - LayoutText {#text} at (0,0) size 0x0 - LayoutText {#text} at (0,0) size 0x0 -selection start: position 5 of child 0 {#text} of child 2 {SPAN} of body -selection end: position 13 of child 0 {#text} of child 2 {SPAN} of body
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.png deleted file mode 100644 index e63a896..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.txt deleted file mode 100644 index 1472c415..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x206 - LayoutBlockFlow {HTML} at (0,0) size 800x206 - LayoutBlockFlow {BODY} at (8,16) size 784x182 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 348x18 - text run at (0,0) width 348: "Passes if there are no overpainted selection highlights." - LayoutBlockFlow {DIV} at (0,34) size 784x148 - LayoutText {#text} at (755,0) size 29x74 - text run at (755,0) width 29: "a" - LayoutBR {BR} at (755,0) size 1x74 - LayoutBR {BR} at (784,74) size 0x74 -selection start: position 0 of child 0 {#text} of child 2 {DIV} of body -selection end: position 1 of child 1 {BR} of child 2 {DIV} of body
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-expected.png deleted file mode 100644 index d291c255..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-span-across-line-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-span-across-line-expected.png deleted file mode 100644 index e8550d1..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-span-across-line-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-span-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-span-expected.png deleted file mode 100644 index 3ecf63d..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-span-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-vertical-lr-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-vertical-lr-expected.png deleted file mode 100644 index 40eacd7..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-vertical-lr-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-vertical-rl-expected.png b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-vertical-rl-expected.png deleted file mode 100644 index 2aa093bd..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/paint/selection/text-selection-newline-vertical-rl-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/svg/custom/object-sizing-explicit-height-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/svg/custom/object-sizing-explicit-height-expected.txt deleted file mode 100644 index 5f3d7eb..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/composite-after-paint/svg/custom/object-sizing-explicit-height-expected.txt +++ /dev/null
@@ -1,83 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x374 - LayoutBlockFlow {html} at (0,0) size 800x374 - LayoutBlockFlow {body} at (8,8) size 784x358 - LayoutText {#text} at (175,161) size 4x18 - text run at (175,161) width 4: " " - LayoutText {#text} at (354,161) size 4x18 - text run at (354,161) width 4: " " - LayoutText {#text} at (533,161) size 4x18 - text run at (533,161) width 4: " " - LayoutText {#text} at (0,0) size 0x0 - LayoutText {#text} at (175,340) size 4x18 - text run at (175,340) width 4: " " - LayoutText {#text} at (354,340) size 4x18 - text run at (354,340) width 4: " " - LayoutText {#text} at (533,340) size 4x18 - text run at (533,340) width 4: " " - LayoutText {#text} at (0,0) size 0x0 -layer at (8,8) size 175x175 - LayoutEmbeddedObject {object} at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (187,8) size 175x175 - LayoutEmbeddedObject {object} at (179,0) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (366,8) size 175x175 - LayoutEmbeddedObject {object} at (358,0) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (545,8) size 175x175 - LayoutEmbeddedObject {object} at (537,0) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (8,187) size 175x175 - LayoutEmbeddedObject {object} at (0,179) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (187,187) size 175x175 - LayoutEmbeddedObject {object} at (179,179) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (366,187) size 175x175 - LayoutEmbeddedObject {object} at (358,179) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (545,187) size 175x175 - LayoutEmbeddedObject {object} at (537,179) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00]
diff --git a/third_party/blink/web_tests/platform/mac/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt index 0ef62a7..aa8a3f01 100644 --- a/third_party/blink/web_tests/platform/mac/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt +++ b/third_party/blink/web_tests/platform/mac/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - [INTERFACES] interface Bluetooth attribute @@toStringTag
diff --git a/third_party/blink/web_tests/platform/mac/virtual/threaded/printing/absolute-position-headers-and-footers-expected.png b/third_party/blink/web_tests/platform/mac/virtual/threaded/printing/absolute-position-headers-and-footers-expected.png deleted file mode 100644 index c4503d6..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/threaded/printing/absolute-position-headers-and-footers-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/video-surface-layer/media/video-zoom-controls-expected.png b/third_party/blink/web_tests/platform/mac/virtual/video-surface-layer/media/video-zoom-controls-expected.png deleted file mode 100644 index 555c3d0..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/video-surface-layer/media/video-zoom-controls-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/direct-image-compositing-expected.png b/third_party/blink/web_tests/platform/win/compositing/direct-image-compositing-expected.png index c6e23ba..6d558fb 100644 --- a/third_party/blink/web_tests/platform/win/compositing/direct-image-compositing-expected.png +++ b/third_party/blink/web_tests/platform/win/compositing/direct-image-compositing-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/geometry/layer-due-to-layer-children-expected.png b/third_party/blink/web_tests/platform/win/compositing/geometry/layer-due-to-layer-children-expected.png index afc7fc4f..77c74a3 100644 --- a/third_party/blink/web_tests/platform/win/compositing/geometry/layer-due-to-layer-children-expected.png +++ b/third_party/blink/web_tests/platform/win/compositing/geometry/layer-due-to-layer-children-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/iframes/invisible-nested-iframe-show-expected.txt b/third_party/blink/web_tests/platform/win/compositing/iframes/invisible-nested-iframe-show-expected.txt index 392b2cc1..1dc93089 100644 --- a/third_party/blink/web_tests/platform/win/compositing/iframes/invisible-nested-iframe-show-expected.txt +++ b/third_party/blink/web_tests/platform/win/compositing/iframes/invisible-nested-iframe-show-expected.txt
@@ -51,12 +51,6 @@ "backgroundColor": "#C0C0C0" }, { - "name": "Child Containment Layer", - "position": [32, 32], - "bounds": [250, 170], - "drawsContent": false - }, - { "name": "LayoutBlockFlow DIV id='iframe-content' class='box'", "bounds": [210, 210], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/platform/win/compositing/lots-of-img-layers-expected.png b/third_party/blink/web_tests/platform/win/compositing/lots-of-img-layers-expected.png new file mode 100644 index 0000000..34f07c89 --- /dev/null +++ b/third_party/blink/web_tests/platform/win/compositing/lots-of-img-layers-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/lots-of-img-layers-with-opacity-expected.png b/third_party/blink/web_tests/platform/win/compositing/lots-of-img-layers-with-opacity-expected.png new file mode 100644 index 0000000..511dca7 --- /dev/null +++ b/third_party/blink/web_tests/platform/win/compositing/lots-of-img-layers-with-opacity-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/masks/direct-image-mask-expected.png b/third_party/blink/web_tests/platform/win/compositing/masks/direct-image-mask-expected.png index e6191de..2cc607b8 100644 --- a/third_party/blink/web_tests/platform/win/compositing/masks/direct-image-mask-expected.png +++ b/third_party/blink/web_tests/platform/win/compositing/masks/direct-image-mask-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/masks/mask-with-added-filters-expected.png b/third_party/blink/web_tests/platform/win/compositing/masks/mask-with-added-filters-expected.png index 91ab8c9..3b0126ad 100644 --- a/third_party/blink/web_tests/platform/win/compositing/masks/mask-with-added-filters-expected.png +++ b/third_party/blink/web_tests/platform/win/compositing/masks/mask-with-added-filters-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/masks/mask-with-removed-filters-expected.png b/third_party/blink/web_tests/platform/win/compositing/masks/mask-with-removed-filters-expected.png index cf14770..7064ec9 100644 --- a/third_party/blink/web_tests/platform/win/compositing/masks/mask-with-removed-filters-expected.png +++ b/third_party/blink/web_tests/platform/win/compositing/masks/mask-with-removed-filters-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/masks/masked-ancestor-expected.png b/third_party/blink/web_tests/platform/win/compositing/masks/masked-ancestor-expected.png index 053c3aa..9d839d7 100644 --- a/third_party/blink/web_tests/platform/win/compositing/masks/masked-ancestor-expected.png +++ b/third_party/blink/web_tests/platform/win/compositing/masks/masked-ancestor-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/masks/multiple-masks-expected.png b/third_party/blink/web_tests/platform/win/compositing/masks/multiple-masks-expected.png index 995ebc7..d6f7bdb9 100644 --- a/third_party/blink/web_tests/platform/win/compositing/masks/multiple-masks-expected.png +++ b/third_party/blink/web_tests/platform/win/compositing/masks/multiple-masks-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/masks/simple-composited-mask-expected.png b/third_party/blink/web_tests/platform/win/compositing/masks/simple-composited-mask-expected.png index 3a267bf6..321aff9 100644 --- a/third_party/blink/web_tests/platform/win/compositing/masks/simple-composited-mask-expected.png +++ b/third_party/blink/web_tests/platform/win/compositing/masks/simple-composited-mask-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/overflow/nested-border-radius-clipping-expected.png b/third_party/blink/web_tests/platform/win/compositing/overflow/nested-border-radius-clipping-expected.png index 75f9d10..c81b3d5 100644 --- a/third_party/blink/web_tests/platform/win/compositing/overflow/nested-border-radius-clipping-expected.png +++ b/third_party/blink/web_tests/platform/win/compositing/overflow/nested-border-radius-clipping-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/overflow/nested-render-surfaces-with-rotation-expected.png b/third_party/blink/web_tests/platform/win/compositing/overflow/nested-render-surfaces-with-rotation-expected.png index 1600edb..f123843 100644 --- a/third_party/blink/web_tests/platform/win/compositing/overflow/nested-render-surfaces-with-rotation-expected.png +++ b/third_party/blink/web_tests/platform/win/compositing/overflow/nested-render-surfaces-with-rotation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/compositing/squashing/no-squashing-into-another-clip-layer-expected.txt b/third_party/blink/web_tests/platform/win/compositing/squashing/no-squashing-into-another-clip-layer-expected.txt index 4a56b34..c0ba5fe 100644 --- a/third_party/blink/web_tests/platform/win/compositing/squashing/no-squashing-into-another-clip-layer-expected.txt +++ b/third_party/blink/web_tests/platform/win/compositing/squashing/no-squashing-into-another-clip-layer-expected.txt
@@ -25,12 +25,6 @@ "transform": 1 }, { - "name": "Child Containment Layer", - "bounds": [784, 10], - "drawsContent": false, - "transform": 1 - }, - { "name": "LayoutBlockFlow DIV id='inner'", "bounds": [784, 10], "contentsOpaque": true,
diff --git a/third_party/blink/web_tests/platform/win/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png b/third_party/blink/web_tests/platform/win/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png index dcae8a2f..0e2768b 100644 --- a/third_party/blink/web_tests/platform/win/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png +++ b/third_party/blink/web_tests/platform/win/css3/blending/background-blend-mode-overlapping-accelerated-elements-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/custom-elements/form-validation-bubble-appearance-expected.png b/third_party/blink/web_tests/platform/win/custom-elements/form-validation-bubble-appearance-expected.png new file mode 100644 index 0000000..a97540f --- /dev/null +++ b/third_party/blink/web_tests/platform/win/custom-elements/form-validation-bubble-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-canvas-border-expected.png b/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-canvas-border-expected.png index 66d2ac6e..99dd40a 100644 --- a/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-canvas-border-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-canvas-border-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-canvas-expected.png b/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-canvas-expected.png index baf012d..0f1dadd 100644 --- a/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-canvas-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-canvas-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-canvas-with-mask-expected.png b/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-canvas-with-mask-expected.png index 495db63e..84d728a 100644 --- a/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-canvas-with-mask-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-canvas-with-mask-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-video-expected.png b/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-video-expected.png index 669e7ee02..96a3d6f 100644 --- a/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-video-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-video-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-video-ratio-expected.png b/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-video-ratio-expected.png index ec815b20..2696097 100644 --- a/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-video-ratio-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-video-ratio-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-video-shadow-expected.png b/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-video-shadow-expected.png index 8857bd2..c2818b3 100644 --- a/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-video-shadow-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/borders/border-radius-mask-video-shadow-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/clip/overflow-border-radius-composited-expected.png b/third_party/blink/web_tests/platform/win/fast/clip/overflow-border-radius-composited-expected.png index dcf2f1a..3b5df5c 100644 --- a/third_party/blink/web_tests/platform/win/fast/clip/overflow-border-radius-composited-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/clip/overflow-border-radius-composited-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/clip/overflow-border-radius-composited-parent-expected.png b/third_party/blink/web_tests/platform/win/fast/clip/overflow-border-radius-composited-parent-expected.png index b8f93907..0e15586 100644 --- a/third_party/blink/web_tests/platform/win/fast/clip/overflow-border-radius-composited-parent-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/clip/overflow-border-radius-composited-parent-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/multicol/composited-layer-nested-expected.png b/third_party/blink/web_tests/platform/win/fast/multicol/composited-layer-nested-expected.png index e861f013..707199d4 100644 --- a/third_party/blink/web_tests/platform/win/fast/multicol/composited-layer-nested-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/multicol/composited-layer-nested-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/multicol/vertical-rl/composited-relpos-overlapping-will-change-expected.png b/third_party/blink/web_tests/platform/win/fast/multicol/vertical-rl/composited-relpos-overlapping-will-change-expected.png index 03a08a20..d895060e 100644 --- a/third_party/blink/web_tests/platform/win/fast/multicol/vertical-rl/composited-relpos-overlapping-will-change-expected.png +++ b/third_party/blink/web_tests/platform/win/fast/multicol/vertical-rl/composited-relpos-overlapping-will-change-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/http/tests/webfont/popup-menu-load-webfont-after-open-expected.txt b/third_party/blink/web_tests/platform/win/http/tests/webfont/popup-menu-load-webfont-after-open-expected.txt index 5d437fe..457826b 100644 --- a/third_party/blink/web_tests/platform/win/http/tests/webfont/popup-menu-load-webfont-after-open-expected.txt +++ b/third_party/blink/web_tests/platform/win/http/tests/webfont/popup-menu-load-webfont-after-open-expected.txt
@@ -1,9 +1,10 @@ +foo +bar Test that fonts loaded after a popup menu is opened triggers a style recalc. On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/platform/win/media/video-zoom-controls-expected.png b/third_party/blink/web_tests/platform/win/media/video-zoom-controls-expected.png index 67b2be0..a59d59f 100644 --- a/third_party/blink/web_tests/platform/win/media/video-zoom-controls-expected.png +++ b/third_party/blink/web_tests/platform/win/media/video-zoom-controls-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/composite-after-paint/selection-change-in-iframe-with-relative-parent-expected.png b/third_party/blink/web_tests/platform/win/paint/invalidation/composite-after-paint/selection-change-in-iframe-with-relative-parent-expected.png deleted file mode 100644 index 20c2d53..0000000 --- a/third_party/blink/web_tests/platform/win/paint/invalidation/composite-after-paint/selection-change-in-iframe-with-relative-parent-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/composite-after-paint/selection-within-composited-scroller-expected.png b/third_party/blink/web_tests/platform/win/paint/invalidation/composite-after-paint/selection-within-composited-scroller-expected.png deleted file mode 100644 index c10cf3f..0000000 --- a/third_party/blink/web_tests/platform/win/paint/invalidation/composite-after-paint/selection-within-composited-scroller-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/composite-after-paint/text-match-highlight-expected.png b/third_party/blink/web_tests/platform/win/paint/invalidation/composite-after-paint/text-match-highlight-expected.png deleted file mode 100644 index 7a49066..0000000 --- a/third_party/blink/web_tests/platform/win/paint/invalidation/composite-after-paint/text-match-highlight-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/printing/absolute-position-headers-and-footers-expected.png b/third_party/blink/web_tests/platform/win/printing/absolute-position-headers-and-footers-expected.png index bfbe55a..179ba46e 100644 --- a/third_party/blink/web_tests/platform/win/printing/absolute-position-headers-and-footers-expected.png +++ b/third_party/blink/web_tests/platform/win/printing/absolute-position-headers-and-footers-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/touchadjustment/html-label-expected.txt b/third_party/blink/web_tests/platform/win/touchadjustment/html-label-expected.txt index af76f73..7878d24a 100644 --- a/third_party/blink/web_tests/platform/win/touchadjustment/html-label-expected.txt +++ b/third_party/blink/web_tests/platform/win/touchadjustment/html-label-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Testing small direct hits. PASS adjusted node was A#mylink. PASS adjusted node was LABEL#mylabel.
diff --git a/third_party/blink/web_tests/platform/win/transforms/3d/point-mapping/3d-point-mapping-2-expected.png b/third_party/blink/web_tests/platform/win/transforms/3d/point-mapping/3d-point-mapping-2-expected.png index f8591a19..55027cce 100644 --- a/third_party/blink/web_tests/platform/win/transforms/3d/point-mapping/3d-point-mapping-2-expected.png +++ b/third_party/blink/web_tests/platform/win/transforms/3d/point-mapping/3d-point-mapping-2-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png b/third_party/blink/web_tests/platform/win/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png index 00e1cc82..87f4ce42 100644 --- a/third_party/blink/web_tests/platform/win/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png +++ b/third_party/blink/web_tests/platform/win/transforms/3d/point-mapping/3d-point-mapping-deep-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png b/third_party/blink/web_tests/platform/win/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png index 296086c..d8a90879 100644 --- a/third_party/blink/web_tests/platform/win/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png +++ b/third_party/blink/web_tests/platform/win/transforms/3d/point-mapping/3d-point-mapping-preserve-3d-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/block/basic/018-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/block/basic/018-expected.png deleted file mode 100644 index b5166ca..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/block/basic/018-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/001-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/001-expected.png deleted file mode 100644 index a580908..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/001-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/002-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/002-expected.png deleted file mode 100644 index 058bfc9..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/002-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/002-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/002-expected.txt deleted file mode 100644 index e844a693..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/002-expected.txt +++ /dev/null
@@ -1,12 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x134 - LayoutBlockFlow {HTML} at (0,0) size 800x134 - LayoutBlockFlow {BODY} at (8,8) size 784x118 - LayoutBlockFlow (anonymous) at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 542x17 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 239: "If you see any red, the test has failed." -layer at (8,26) size 100x100 scrollHeight 200 - LayoutBlockFlow {DIV} at (0,18) size 100x100 [bgcolor=#008000] - LayoutBlockFlow {DIV} at (0,100) size 100x100 [bgcolor=#FF0000]
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/003-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/003-expected.png deleted file mode 100644 index da5e76e..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/003-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/003-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/003-expected.txt deleted file mode 100644 index 5a582c1..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/003-expected.txt +++ /dev/null
@@ -1,14 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x134 - LayoutBlockFlow {HTML} at (0,0) size 800x134 - LayoutBlockFlow {BODY} at (8,8) size 784x118 - LayoutBlockFlow (anonymous) at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 542x17 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 239: "If you see any red, the test has failed." -layer at (8,26) size 100x100 scrollWidth 200 scrollHeight 200 - LayoutBlockFlow {DIV} at (0,18) size 100x100 - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (150,100) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (150,100) size 100x100 [bgcolor=#008000]
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/004-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/004-expected.png deleted file mode 100644 index d37c5c79..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/004-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/004-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/004-expected.txt deleted file mode 100644 index 93be63f0..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/004-expected.txt +++ /dev/null
@@ -1,17 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x52 - LayoutBlockFlow {HTML} at (0,0) size 800x52 - LayoutBlockFlow {BODY} at (8,8) size 784x36 - LayoutText {#text} at (0,0) size 763x35 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 243: "If you see any red, the test has failed. " - text run at (545,0) width 218: "This test is checking to make sure" - text run at (0,18) width 151: "overflow is done using " - text run at (150,18) width 167: "a containing block model." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,44) size 100x100 scrollWidth 200 scrollHeight 400 - LayoutBlockFlow (positioned) {DIV} at (8,44) size 100x100 [bgcolor=#008000] - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (108,344) size 100x100 backgroundClip at (8,44) size 100x100 clip at (8,44) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (100,300) size 100x100 [bgcolor=#FF0000]
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/005-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/005-expected.png deleted file mode 100644 index d37c5c79..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/005-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/005-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/005-expected.txt deleted file mode 100644 index 02a6101bde..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/005-expected.txt +++ /dev/null
@@ -1,17 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x152 - LayoutBlockFlow {HTML} at (0,0) size 800x152 - LayoutBlockFlow {BODY} at (8,8) size 784x136 - LayoutBlockFlow (anonymous) at (0,0) size 784x36 - LayoutText {#text} at (0,0) size 763x35 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 243: "If you see any red, the test has failed. " - text run at (545,0) width 218: "This test is checking to make sure" - text run at (0,18) width 151: "overflow is done using " - text run at (150,18) width 167: "a containing block model." -layer at (8,44) size 100x100 scrollWidth 200 scrollHeight 400 - LayoutBlockFlow (relative positioned) {DIV} at (0,36) size 100x100 [bgcolor=#008000] - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (108,344) size 100x100 backgroundClip at (8,44) size 100x100 clip at (8,44) size 100x100 - LayoutBlockFlow (relative positioned) {DIV} at (100,300) size 100x100 [bgcolor=#FF0000]
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/006-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/006-expected.png deleted file mode 100644 index 0dedfa4..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/006-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/006-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/006-expected.txt deleted file mode 100644 index 2660871..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/006-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x70 - LayoutBlockFlow {HTML} at (0,0) size 800x70 - LayoutBlockFlow {BODY} at (8,8) size 784x54 - LayoutText {#text} at (0,0) size 746x53 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 373: "If you see nothing at all or see any red, the test has failed. " - text run at (675,0) width 71: "This test is" - text run at (0,18) width 298: "checking to make sure overflow is done using " - text run at (297,18) width 438: "a containing block model, and that a fixed positioned element inside" - text run at (0,36) width 388: "another fixed positioned element is not considered overflow." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,62) size 100x100 scrollWidth 200 scrollHeight 200 - LayoutBlockFlow (positioned) {DIV} at (8,62) size 100x100 - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (100,70) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (100,70) size 100x100 [bgcolor=#008000]
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/007-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/007-expected.png deleted file mode 100644 index a9109c2..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/007-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/008-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/008-expected.png deleted file mode 100644 index a9109c2..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/008-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/008-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/008-expected.txt deleted file mode 100644 index 49af757..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/008-expected.txt +++ /dev/null
@@ -1,19 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x70 - LayoutBlockFlow {HTML} at (0,0) size 800x70 - LayoutBlockFlow {BODY} at (8,8) size 784x54 - LayoutText {#text} at (0,0) size 754x53 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 373: "If you see nothing at all or see any red, the test has failed. " - text run at (675,0) width 71: "This test is" - text run at (0,18) width 298: "checking to make sure overflow is done using " - text run at (297,18) width 457: "a containing block model, and that a fixed positioned element inside an" - text run at (0,36) width 356: "absolute positioned element is not considered overflow." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,62) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (8,62) size 100x100 -layer at (100,100) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (100,100) size 100x100 -layer at (200,200) size 100x100 - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#008000]
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/009-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/009-expected.png deleted file mode 100644 index e60d620..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/009-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/009-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/009-expected.txt deleted file mode 100644 index 3e31527..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/009-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x52 - LayoutBlockFlow {HTML} at (0,0) size 800x52 - LayoutBlockFlow {BODY} at (8,8) size 784x36 - LayoutText {#text} at (0,0) size 763x35 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 243: "If you see any red, the test has failed. " - text run at (545,0) width 218: "This test is checking to make sure" - text run at (0,18) width 221: "clip is applying to all descendants." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,44) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (8,44) size 100x100 [bgcolor=#008000] - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (108,344) size 100x100 backgroundClip at (8,44) size 100x100 clip at (8,44) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (100,300) size 100x100 [bgcolor=#FF0000]
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/011-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/011-expected.png deleted file mode 100644 index e60d620..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/011-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/012-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/012-expected.png deleted file mode 100644 index e60d620..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/012-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/012-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/012-expected.txt deleted file mode 100644 index 39daec6a..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/012-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x52 - LayoutBlockFlow {HTML} at (0,0) size 800x52 - LayoutBlockFlow {BODY} at (8,8) size 784x36 - LayoutText {#text} at (0,0) size 763x35 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 243: "If you see any red, the test has failed. " - text run at (545,0) width 218: "This test is checking to make sure" - text run at (0,18) width 221: "clip is applying to all descendants." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,44) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (8,44) size 100x100 [bgcolor=#008000] - LayoutBlockFlow {DIV} at (100,100) size 100x100 [bgcolor=#FF0000] -layer at (108,344) size 100x100 backgroundClip at (0,0) size 0x0 clip at (0,0) size 0x0 - LayoutBlockFlow {DIV} at (100,300) size 100x100 [bgcolor=#FF0000]
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/013-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/013-expected.png deleted file mode 100644 index 1eecb87..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/013-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/014-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/014-expected.png deleted file mode 100644 index 12ed93b..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/014-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/014-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/014-expected.txt deleted file mode 100644 index 8b4025c4..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/014-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x70 - LayoutBlockFlow {HTML} at (0,0) size 800x70 - LayoutBlockFlow {BODY} at (8,8) size 784x54 - LayoutText {#text} at (0,0) size 781x53 - text run at (0,0) width 408: "You should see a 100x100 green square with a scrollbar below. " - text run at (407,0) width 243: "If you see any red, the test has failed. " - text run at (649,0) width 132: "This test is checking" - text run at (0,18) width 635: "to make sure clip applies to the element itself, starts from the border edge, and clips out scrollbars. " - text run at (634,18) width 116: "The bottom of the" - text run at (0,36) width 254: "scrolling mechanism should be clipped." - LayoutText {#text} at (0,0) size 0x0 -layer at (8,62) size 120x220 backgroundClip at (18,72) size 100x100 clip at (18,72) size 85x100 scrollHeight 1000 - LayoutBlockFlow (positioned) {DIV} at (8,62) size 120x220 [bgcolor=#008000] [border: (10px solid #FF0000)] - LayoutBlockFlow {DIV} at (10,10) size 85x1000
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/015-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/015-expected.png deleted file mode 100644 index 8619d3a..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/015-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/015-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/015-expected.txt deleted file mode 100644 index 8021f2a..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/015-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x134 - LayoutBlockFlow {HTML} at (0,0) size 800x134 - LayoutBlockFlow {BODY} at (8,8) size 784x118 - LayoutBlockFlow (anonymous) at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 744x17 - text run at (0,0) width 304: "You should see a 100x100 green square below. " - text run at (303,0) width 441: "This test makes sure overflow uses containing blocks when clipping." -layer at (8,26) size 100x100 scrollWidth 300 scrollHeight 300 - LayoutBlockFlow {DIV} at (0,18) size 100x100 [bgcolor=#008000] -layer at (108,126) size 100x100 backgroundClip at (8,26) size 100x100 clip at (8,26) size 100x100 - LayoutBlockFlow (relative positioned) {DIV} at (0,0) size 100x100 [bgcolor=#FF0000] -layer at (208,226) size 100x100 backgroundClip at (8,26) size 100x100 clip at (8,26) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (100,100) size 100x100
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/016-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/016-expected.png deleted file mode 100644 index fbce715..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/016-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/016-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/016-expected.txt deleted file mode 100644 index 2069cca..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/clip/016-expected.txt +++ /dev/null
@@ -1,10 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutText {#text} at (0,0) size 300x17 - text run at (0,0) width 300: "You should see a 100x100 green square below." - LayoutText {#text} at (0,0) size 0x0 -layer at (50,50) size 100x500 backgroundClip at (50,50) size 100x100 clip at (50,50) size 100x100 - LayoutBlockFlow (positioned) {DIV} at (50,50) size 100x500 [bgcolor=#008000]
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/004-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/004-expected.png deleted file mode 100644 index f65e036..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/004-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/004-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/004-expected.txt deleted file mode 100644 index d6b86ab..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/004-expected.txt +++ /dev/null
@@ -1,12 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x534 - LayoutBlockFlow {HTML} at (0,0) size 800x534 - LayoutBlockFlow {BODY} at (8,8) size 784x518 - LayoutBlockFlow (anonymous) at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 712x17 - text run at (0,0) width 712: "The two green blocks below should be identical and should each take up half the width of the browser window." - LayoutBlockFlow (floating) {DIV} at (392,18) size 392x500 [bgcolor=#008000] [border: (1px solid #000000)] - LayoutText {#text} at (0,0) size 0x0 -layer at (8,26) size 392x500 clip at (9,27) size 390x498 - LayoutBlockFlow {DIV} at (0,18) size 392x500 [bgcolor=#008000] [border: (1px solid #000000)]
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/005-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/005-expected.png deleted file mode 100644 index 444e7cf..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/005-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/008-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/008-expected.png deleted file mode 100644 index 3de56fd..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/008-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/line-clamp-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/line-clamp-expected.png deleted file mode 100644 index 938c859..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/line-clamp-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/overflow-auto-position-absolute-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/overflow-auto-position-absolute-expected.png deleted file mode 100644 index f7f00a9..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/overflow-auto-position-absolute-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/overflow-auto-position-absolute-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/overflow-auto-position-absolute-expected.txt deleted file mode 100644 index b51792fb..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/overflow-auto-position-absolute-expected.txt +++ /dev/null
@@ -1,11 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 -layer at (16,16) size 768x568 clip at (16,16) size 753x568 scrollHeight 1024 - LayoutBlockFlow (positioned) {DIV} at (16,16) size 768x568 -layer at (16,16) size 753x1024 backgroundClip at (16,16) size 753x568 clip at (16,16) size 753x568 - LayoutBlockFlow (positioned) {DIV} at (0,0) size 753x1024 [bgcolor=#008000] - LayoutText {#text} at (0,0) size 316x17 - text run at (0,0) width 316: "This test passes if there is no horizontal scrollbar."
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.png deleted file mode 100644 index 0082720..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.txt deleted file mode 100644 index deea5c0..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/overflow-auto-table-expected.txt +++ /dev/null
@@ -1,21 +0,0 @@ -layer at (0,0) size 800x600 scrollWidth 7618 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x162 - LayoutBlockFlow {HTML} at (0,0) size 800x162 - LayoutBlockFlow {BODY} at (8,16) size 784x138 - LayoutBlockFlow {P} at (0,0) size 784x54 - LayoutText {#text} at (0,0) size 763x53 - text run at (0,0) width 756: "This tests the interaction of overflow on some very wide text with auto table layout. The CSS 2.1 spec does not define" - text run at (0,18) width 763: "how overflow interacts with intrinsic width, so we copy the IE behavior. Therefore the lines should come out very very" - text run at (0,36) width 243: "wide and scroll along with the border." - LayoutTable {TABLE} at (0,70) size 7610x68 [border: (1px solid #FF0000)] - LayoutTableSection {TBODY} at (1,1) size 7608x66 - LayoutTableRow {TR} at (0,2) size 7608x62 - LayoutTableCell {TD} at (2,2) size 7604x62 [r=0 c=0 rs=1 cs=1] -layer at (12,103) size 7602x34 backgroundClip at (12,103) size 788x34 clip at (13,104) size 787x32 - LayoutBlockFlow {PRE} at (1,14) size 7602x34 [border: (1px solid #0000FF)] - LayoutText {#text} at (1,1) size 7600x32 - text run at (1,1) width 3200: "this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line " - text run at (3201,1) width 0: " " - text run at (1,17) width 7600: "this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line this is a very long line " - text run at (7601,17) width 0: " "
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/unreachable-overflow-rtl-bug-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/unreachable-overflow-rtl-bug-expected.png deleted file mode 100644 index be2107fb..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/overflow/unreachable-overflow-rtl-bug-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/block-layout-inline-children-float-positioned-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/block-layout-inline-children-float-positioned-expected.txt deleted file mode 100644 index 2e31912..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/block-layout-inline-children-float-positioned-expected.txt +++ /dev/null
@@ -1,25 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [305, 35, 297, 18], - [305, 35, 297, 18], - [153, 35, 297, 18], - [153, 35, 297, 18] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (floating) SPAN", - "LayoutText #text", - "InlineTextBox 'the quick brown fox jumped over the lazy dog'", - "LayoutBlockFlow (positioned) SPAN", - "LayoutText #text", - "InlineTextBox 'the quick brown fox jumped over the lazy dog'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/box-inline-resize-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/box-inline-resize-expected.txt deleted file mode 100644 index 0e6241f..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/box-inline-resize-expected.txt +++ /dev/null
@@ -1,30 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [40, 103, 114, 28], - [40, 103, 114, 27], - [8, 103, 114, 28], - [8, 103, 114, 27], - [8, 84, 32, 67], - [8, 84, 32, 32] - ], - "paintInvalidationClients": [ - "RootInlineBox", - "InlineBox", - "InlineBox", - "RootInlineBox", - "LayoutBlockFlow (anonymous)", - "LayoutImage IMG id='foo'", - "LayoutBlockFlow H2", - "LayoutText #text", - "InlineTextBox 'Chromium'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/caret-invalidation-in-overflow-scroll-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/caret-invalidation-in-overflow-scroll-expected.txt deleted file mode 100644 index f8abebb..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/caret-invalidation-in-overflow-scroll-expected.txt +++ /dev/null
@@ -1,19 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [406, 10, 4, 18], - [403, 10, 4, 18] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow DIV id='inner-editor'", - "LayoutBlockFlow DIV id='inner-editor'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/focus-continuations-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/focus-continuations-expected.txt deleted file mode 100644 index 4a1a920..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/focus-continuations-expected.txt +++ /dev/null
@@ -1,24 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [8, 88, 84, 20], - [7, 87, 86, 22], - [7, 87, 86, 22], - [7, 87, 86, 22] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (positioned) DIV id='container'", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/focus-enable-continuations-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/focus-enable-continuations-expected.txt deleted file mode 100644 index 822b716..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/focus-enable-continuations-expected.txt +++ /dev/null
@@ -1,25 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [8, 88, 84, 20], - [7, 87, 86, 22], - [7, 87, 86, 22], - [7, 87, 86, 22] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (positioned) DIV id='container'", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "LayoutInline SPAN id='outer'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-1-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-1-expected.txt deleted file mode 100644 index c1db456..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-1-expected.txt +++ /dev/null
@@ -1,154 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [378, 138, 70, 30], - [369, 422, 1, 53], - [369, 80, 51, 108], - [305, 170, 41, 17], - [301, 404, 67, 18], - [178, 350, 146, 18], - [65, 386, 303, 36], - [65, 350, 146, 18], - [14, 404, 355, 36], - [14, 386, 354, 36], - [14, 353, 48, 65], - [14, 335, 48, 65], - [14, 224, 406, 126], - [14, 188, 41, 17], - [14, 170, 408, 72], - [13, 242, 407, 126], - [13, 188, 408, 71], - [8, 116, 418, 450] - ], - "paintInvalidationClients": [ - "InlineTextBox 'body tucked away,\n'", - "InlineTextBox 'comfortably enough, under her'", - "RootInlineBox", - "InlineTextBox 'arm, with its legs hanging down,\n'", - "InlineTextBox 'but generally, just as'", - "RootInlineBox", - "InlineTextBox 'she had got its neck nicely straightened\n'", - "InlineTextBox 'out, and was'", - "RootInlineBox", - "InlineTextBox 'going to give the hedgehog a blow with its head, it'", - "RootInlineBox", - "InlineTextBox 'would'", - "InlineTextBox ' twist itself round and look up in her face, with\n'", - "InlineTextBox 'such a'", - "RootInlineBox", - "InlineTextBox 'puzzled expression that she could not help bursting out'", - "RootInlineBox", - "InlineTextBox 'laughing: and when she had got its head down, and was going'", - "RootInlineBox", - "InlineTextBox 'to\n'", - "InlineTextBox 'begin again, it was very provoking to find that the hedgehog'", - "RootInlineBox", - "InlineTextBox 'had\n'", - "InlineTextBox 'unrolled itself, and was in the act of crawling away:'", - "RootInlineBox", - "InlineTextBox 'besides all\n'", - "InlineTextBox 'this, there was generally a ridge or furrow in the'", - "RootInlineBox", - "InlineTextBox 'way wherever\n'", - "InlineTextBox 'she wanted to send the hedgehog to, and, as the'", - "RootInlineBox", - "InlineTextBox 'doubled-up\n'", - "InlineTextBox 'soldiers were always getting up and walking off to'", - "RootInlineBox", - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion'", - "RootInlineBox", - "InlineTextBox 'that it was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting'", - "RootInlineBox", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "RootInlineBox", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the'", - "RootInlineBox", - "InlineTextBox 'Queen'", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "RootInlineBox", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with'", - "RootInlineBox", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet'", - "RootInlineBox", - "InlineTextBox 'had any dispute with the Queen, but she knew that it might'", - "RootInlineBox", - "InlineTextBox 'happen any minute, \u2018and then,\u2019 thought she, \u2018what would'", - "RootInlineBox", - "InlineTextBox 'become of\n'", - "InlineTextBox 'me? They\u2019re dreadfully fond of beheading people'", - "RootInlineBox", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "LayoutBlockFlow (floating) DIV id='pinkFloat'", - "LayoutBlockFlow P", - "LayoutText #text", - "InlineTextBox 'The chief difficulty Alice found at first was in'", - "InlineTextBox 'managing her\n'", - "InlineTextBox 'flamingo: she succeeded in getting its'", - "InlineTextBox 'body tucked away,\n'", - "InlineTextBox 'comfortably enough, under her'", - "InlineTextBox 'arm, with its legs hanging down,\n'", - "InlineTextBox 'but generally, just as'", - "InlineTextBox 'she had got its neck nicely straightened\n'", - "InlineTextBox 'out, and was going to'", - "InlineTextBox 'give the hedgehog a blow with its head, it\n'", - "LayoutText #text", - "InlineTextBox 'would'", - "LayoutText #text", - "InlineTextBox ' twist itself'", - "InlineTextBox 'round and look up in her face, with\n'", - "InlineTextBox 'such a puzzled expression'", - "InlineTextBox 'that she could not help bursting out\n'", - "InlineTextBox 'laughing: and when she'", - "InlineTextBox 'had got its head down, and was going to\n'", - "LayoutText #text", - "InlineTextBox 'begin again, it was'", - "InlineTextBox 'very provoking to find that the hedgehog had\n'", - "InlineTextBox 'unrolled itself,'", - "InlineTextBox 'and was in the act of crawling away: besides all\n'", - "InlineTextBox 'this, there was'", - "InlineTextBox 'generally a ridge or furrow in the way wherever\n'", - "InlineTextBox 'she wanted to'", - "InlineTextBox 'send the hedgehog to, and, as the doubled-up\n'", - "InlineTextBox 'soldiers were'", - "InlineTextBox 'always getting up and walking off to other parts of\n'", - "InlineTextBox 'the ground,'", - "InlineTextBox 'Alice soon came to the conclusion that it was a very'", - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "LayoutText #text", - "InlineTextBox 'difficult game indeed.\n'", - "LayoutText #text", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "LayoutText #text", - "InlineTextBox 'the Queen'", - "LayoutText #text", - "InlineTextBox 'was in a furious passion, and went\n'", - "InlineTextBox 'stamping about, and'", - "InlineTextBox 'shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019'", - "InlineTextBox 'about once in a minute.\n'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-10-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-10-expected.txt deleted file mode 100644 index 7dd3ef5..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-10-expected.txt +++ /dev/null
@@ -1,67 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [369, 422, 1, 53], - [65, 404, 304, 36], - [14, 404, 355, 36], - [14, 364, 48, 64], - [14, 353, 48, 65], - [8, 332, 418, 234] - ], - "paintInvalidationClients": [ - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion'", - "RootInlineBox", - "InlineTextBox 'that it was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting'", - "RootInlineBox", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "RootInlineBox", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the'", - "RootInlineBox", - "InlineTextBox 'Queen'", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "RootInlineBox", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with'", - "RootInlineBox", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet'", - "RootInlineBox", - "InlineTextBox 'had any dispute with the Queen, but she knew that it might'", - "RootInlineBox", - "InlineTextBox 'happen any minute, \u2018and then,\u2019 thought she, \u2018what would'", - "RootInlineBox", - "InlineTextBox 'become of\n'", - "InlineTextBox 'me? They\u2019re dreadfully fond of beheading people'", - "RootInlineBox", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "LayoutText #text", - "InlineTextBox 'the'", - "InlineTextBox 'Queen'", - "LayoutText #text", - "InlineTextBox ' was in a furious passion, and went'", - "InlineTextBox 'stamping about, and shouting \u2018Off with his head!\u2019 or'", - "InlineTextBox '\u2018Off with\n'", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-2-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-2-expected.txt deleted file mode 100644 index 2aa29c3..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-2-expected.txt +++ /dev/null
@@ -1,98 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [372, 374, 48, 81], - [372, 371, 48, 81], - [178, 353, 146, 18], - [178, 350, 146, 18], - [65, 389, 303, 36], - [65, 386, 303, 36], - [65, 371, 304, 18], - [65, 368, 304, 18], - [14, 425, 355, 53], - [14, 422, 355, 53], - [14, 407, 355, 36], - [14, 404, 355, 36], - [14, 356, 48, 65], - [14, 353, 48, 65], - [14, 188, 45, 20], - [14, 188, 41, 17], - [13, 479, 408, 90], - [13, 476, 408, 90], - [13, 245, 407, 126], - [13, 242, 407, 126], - [13, 190, 408, 72], - [13, 188, 408, 71], - [8, 572, 418, 3], - [8, 569, 418, 6], - [8, 170, 418, 399] - ], - "paintInvalidationClients": [ - "InlineTextBox 'going to give the hedgehog a blow with its head, it'", - "RootInlineBox", - "InlineTextBox ''", - "InlineTextBox ' twist itself round and look up in her face, with\n'", - "InlineTextBox 'such a'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutBlockFlow P", - "LayoutInline I id='would'", - "LayoutText #text", - "InlineTextBox 'would'", - "LayoutText #text", - "InlineTextBox ' twist itself round and look up in her face, with\n'", - "InlineTextBox 'such a'", - "InlineTextBox 'puzzled expression that she could not help bursting out'", - "InlineTextBox 'laughing: and when she had got its head down, and was going'", - "InlineTextBox 'to\n'", - "LayoutText #text", - "InlineTextBox 'begin again, it was very provoking to find that the hedgehog'", - "InlineTextBox 'had\n'", - "InlineTextBox 'unrolled itself, and was in the act of crawling away:'", - "InlineTextBox 'besides all\n'", - "InlineTextBox 'this, there was generally a ridge or furrow in the'", - "InlineTextBox 'way wherever\n'", - "InlineTextBox 'she wanted to send the hedgehog to, and, as the'", - "InlineTextBox 'doubled-up\n'", - "InlineTextBox 'soldiers were always getting up and walking off to'", - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion'", - "InlineTextBox 'that it was a very\n'", - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "LayoutText #text", - "InlineTextBox 'difficult game indeed.\n'", - "LayoutText #text", - "InlineTextBox 'The players all played at once without waiting'", - "LayoutBlockFlow (floating) SPAN id='greenFloat'", - "LayoutText #text", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "LayoutText #text", - "InlineTextBox 'the'", - "InlineTextBox 'Queen'", - "LayoutText #text", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with'", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'", - "LayoutText #text", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet'", - "InlineTextBox 'had any dispute with the Queen, but she knew that it might'", - "InlineTextBox 'happen any minute, \u2018and then,\u2019 thought she, \u2018what would'", - "InlineTextBox 'become of\n'", - "InlineTextBox 'me? They\u2019re dreadfully fond of beheading people'", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-3-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-3-expected.txt deleted file mode 100644 index ed2e469f..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-3-expected.txt +++ /dev/null
@@ -1,71 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [372, 371, 48, 81], - [369, 368, 32, 18], - [356, 389, 64, 81], - [354, 422, 15, 53], - [65, 386, 303, 36], - [65, 368, 356, 54], - [14, 422, 72, 18], - [14, 404, 355, 36], - [8, 368, 418, 198] - ], - "paintInvalidationClients": [ - "InlineTextBox 'The players all played at once without waiting'", - "RootInlineBox", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "RootInlineBox", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the'", - "RootInlineBox", - "InlineTextBox 'Queen'", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "RootInlineBox", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with'", - "RootInlineBox", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet'", - "RootInlineBox", - "InlineTextBox 'had any dispute with the Queen, but she knew that it might'", - "RootInlineBox", - "InlineTextBox 'happen any minute, \u2018and then,\u2019 thought she, \u2018what would'", - "RootInlineBox", - "InlineTextBox 'become of\n'", - "InlineTextBox 'me? They\u2019re dreadfully fond of beheading people'", - "RootInlineBox", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutText #text", - "InlineTextBox 'The players all played at once without waiting\n'", - "LayoutBlockFlow (floating) SPAN id='greenFloat'", - "LayoutText #text", - "InlineTextBox 'for'", - "InlineTextBox 'turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time'", - "LayoutText #text", - "InlineTextBox 'the Queen'", - "LayoutText #text", - "InlineTextBox ' was in a furious passion, and went'", - "InlineTextBox 'stamping about, and shouting \u2018Off with his head!\u2019 or'", - "InlineTextBox '\u2018Off with\n'", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-4-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-4-expected.txt deleted file mode 100644 index 1af78851..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-4-expected.txt +++ /dev/null
@@ -1,56 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [372, 435, 48, 17], - [369, 422, 52, 53], - [8, 368, 418, 198] - ], - "paintInvalidationClients": [ - "InlineTextBox 'The players all played at once without waiting'", - "RootInlineBox", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "RootInlineBox", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the'", - "RootInlineBox", - "InlineTextBox 'Queen'", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "RootInlineBox", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with'", - "RootInlineBox", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet'", - "RootInlineBox", - "InlineTextBox 'had any dispute with the Queen, but she knew that it might'", - "RootInlineBox", - "InlineTextBox 'happen any minute, \u2018and then,\u2019 thought she, \u2018what would'", - "RootInlineBox", - "InlineTextBox 'become of\n'", - "InlineTextBox 'me? They\u2019re dreadfully fond of beheading people'", - "RootInlineBox", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutBlockFlow (floating) SPAN id='greenFloat'", - "LayoutText #text", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her'", - "InlineTextBox 'head!\u2019 about once in a minute.\n'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-6-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-6-expected.txt deleted file mode 100644 index 124d6ad19..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-6-expected.txt +++ /dev/null
@@ -1,37 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [27, 353, 22, 18], - [14, 353, 48, 65], - [8, 332, 418, 90] - ], - "paintInvalidationClients": [ - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion'", - "RootInlineBox", - "InlineTextBox 'that it was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting'", - "RootInlineBox", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "RootInlineBox", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "LayoutText #text", - "InlineTextBox 'foo'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-8-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-8-expected.txt deleted file mode 100644 index e0fb03e..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-8-expected.txt +++ /dev/null
@@ -1,110 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [246, 404, 66, 18], - [178, 350, 146, 18], - [127, 350, 146, 18], - [65, 386, 303, 36], - [65, 368, 304, 18], - [14, 422, 355, 53], - [14, 404, 355, 71], - [14, 404, 355, 36], - [14, 368, 355, 54], - [14, 368, 336, 18], - [14, 353, 48, 65], - [8, 80, 418, 395] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "InlineTextBox 'The chief difficulty Alice found at first was in'", - "RootInlineBox", - "InlineTextBox 'managing her\n'", - "InlineTextBox 'flamingo: she succeeded in getting its'", - "RootInlineBox", - "InlineTextBox 'body tucked away,\n'", - "InlineTextBox 'comfortably enough, under her'", - "RootInlineBox", - "InlineTextBox 'arm, with its legs hanging down,\n'", - "InlineTextBox 'but generally, just as'", - "RootInlineBox", - "InlineTextBox 'she had got its neck nicely straightened\n'", - "InlineTextBox 'out, and was'", - "RootInlineBox", - "InlineTextBox 'going to give the hedgehog a blow with its head, it'", - "RootInlineBox", - "InlineTextBox 'would'", - "InlineTextBox ' twist itself round and look up in her face, with\n'", - "InlineTextBox 'such a'", - "RootInlineBox", - "InlineTextBox 'puzzled expression that she could not help bursting out'", - "RootInlineBox", - "InlineTextBox 'laughing: and when she had got its head down, and was going'", - "RootInlineBox", - "InlineTextBox 'to\n'", - "InlineTextBox 'begin again, it was very provoking to find that the hedgehog'", - "RootInlineBox", - "InlineTextBox 'had\n'", - "InlineTextBox 'unrolled itself, and was in the act of crawling away:'", - "RootInlineBox", - "InlineTextBox 'besides all\n'", - "InlineTextBox 'this, there was generally a ridge or furrow in the'", - "RootInlineBox", - "InlineTextBox 'way wherever\n'", - "InlineTextBox 'she wanted to send the hedgehog to, and, as the'", - "RootInlineBox", - "InlineTextBox 'doubled-up\n'", - "InlineTextBox 'soldiers were always getting up and walking off to'", - "RootInlineBox", - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion'", - "RootInlineBox", - "InlineTextBox 'that it was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting'", - "RootInlineBox", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "RootInlineBox", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the'", - "RootInlineBox", - "InlineTextBox 'Queen'", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "RootInlineBox", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with'", - "RootInlineBox", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutText #text", - "InlineTextBox 'difficult game indeed.\n'", - "LayoutText #text", - "InlineTextBox 'The players all played at once without waiting\n'", - "LayoutText #text", - "InlineTextBox 'for'", - "InlineTextBox 'turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting for the'", - "InlineTextBox 'hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "LayoutText #text", - "InlineTextBox 'the Queen'", - "LayoutText #text", - "InlineTextBox ' was in a'", - "InlineTextBox 'furious passion, and went\n'", - "InlineTextBox 'stamping about, and'", - "InlineTextBox 'shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019'", - "InlineTextBox 'about once in a minute.\n'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-9-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-9-expected.txt deleted file mode 100644 index 4d8e2ece..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/line-flow-with-floats-9-expected.txt +++ /dev/null
@@ -1,179 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [485, 15, 15, 585], - [485, 0, 15, 600], - [485, 0, 15, 600], - [485, 0, 15, 600], - [485, 0, 15, 600], - [372, 389, 48, 81], - [372, 371, 48, 81], - [372, 245, 48, 49], - [301, 422, 67, 18], - [178, 350, 146, 18], - [65, 386, 304, 18], - [65, 386, 303, 36], - [65, 368, 304, 18], - [65, 350, 356, 36], - [14, 440, 356, 53], - [14, 422, 355, 53], - [14, 404, 355, 36], - [14, 404, 354, 36], - [14, 242, 406, 126], - [13, 494, 408, 90], - [13, 476, 408, 90], - [13, 242, 407, 126], - [8, 572, 418, 18], - [8, 569, 418, 21], - [0, 0, 500, 600], - [0, 0, 485, 600], - [0, 0, 485, 600], - [0, 0, 15, 15], - [0, 0, 15, 15] - ], - "paintInvalidationClients": [ - "InlineTextBox 'The chief difficulty Alice found at first was in'", - "RootInlineBox", - "InlineTextBox 'managing her\n'", - "InlineTextBox 'flamingo: she succeeded in getting its'", - "RootInlineBox", - "InlineTextBox 'body tucked away,\n'", - "InlineTextBox 'comfortably enough, under her'", - "RootInlineBox", - "InlineTextBox 'arm, with its legs hanging down,\n'", - "InlineTextBox 'but generally, just as'", - "RootInlineBox", - "InlineTextBox 'she had got its neck nicely straightened\n'", - "InlineTextBox 'out, and was'", - "RootInlineBox", - "InlineTextBox 'going to give the hedgehog a blow with its head, it'", - "RootInlineBox", - "InlineTextBox 'would'", - "InlineTextBox ' twist itself round and look up in her face, with\n'", - "InlineTextBox 'such a'", - "RootInlineBox", - "InlineTextBox 'puzzled expression that she could not help bursting out'", - "RootInlineBox", - "InlineTextBox 'laughing: and when she had got its head down, and was going'", - "RootInlineBox", - "InlineTextBox 'to\n'", - "InlineTextBox 'begin again, it was very provoking to find that the hedgehog'", - "RootInlineBox", - "InlineTextBox 'had\n'", - "InlineTextBox 'unrolled itself, and was in the act of crawling away:'", - "RootInlineBox", - "InlineTextBox 'besides all\n'", - "InlineTextBox 'this, there was generally a ridge or furrow in the'", - "RootInlineBox", - "InlineTextBox 'way wherever\n'", - "InlineTextBox 'she wanted to send the hedgehog to, and, as the'", - "RootInlineBox", - "InlineTextBox 'doubled-up\n'", - "InlineTextBox 'soldiers were always getting up and walking off to'", - "RootInlineBox", - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion'", - "RootInlineBox", - "InlineTextBox 'that it was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting'", - "RootInlineBox", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "RootInlineBox", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the'", - "RootInlineBox", - "InlineTextBox 'Queen'", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "RootInlineBox", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with'", - "RootInlineBox", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet'", - "RootInlineBox", - "InlineTextBox 'had any dispute with the Queen, but she knew that it might'", - "RootInlineBox", - "InlineTextBox 'happen any minute, \u2018and then,\u2019 thought she, \u2018what would'", - "RootInlineBox", - "InlineTextBox 'become of\n'", - "InlineTextBox 'me? They\u2019re dreadfully fond of beheading people'", - "RootInlineBox", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "VerticalScrollbar", - "LayoutIFrame IFRAME id='iframe'", - "LayoutIFrame IFRAME id='iframe'", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "VerticalScrollbar", - "LayoutIFrame IFRAME id='iframe'", - "VerticalScrollbar", - "LayoutIFrame IFRAME id='iframe'", - "VerticalScrollbar", - "LayoutIFrame IFRAME id='iframe'", - "VerticalScrollbar", - "LayoutIFrame IFRAME id='iframe'", - "LayoutView #document", - "LayoutView #document", - "LayoutBlockFlow HTML", - "LayoutBlockFlow P", - "LayoutBlockFlow (floating) SPAN id='yellowFloat'", - "LayoutText #text", - "InlineTextBox 'begin again, it was very provoking to find that the'", - "InlineTextBox 'hedgehog had\n'", - "InlineTextBox 'unrolled itself, and was in the act of'", - "InlineTextBox 'crawling away: besides all\n'", - "InlineTextBox 'this, there was generally a'", - "InlineTextBox 'ridge or furrow in the way wherever\n'", - "InlineTextBox 'she wanted to send the'", - "InlineTextBox 'hedgehog to, and, as the doubled-up\n'", - "InlineTextBox 'soldiers were always'", - "InlineTextBox 'getting up and walking off to other parts of\n'", - "InlineTextBox 'the ground, Alice'", - "InlineTextBox 'soon came to the conclusion that it was a very\n'", - "LayoutText #text", - "InlineTextBox 'difficult'", - "InlineTextBox 'game indeed.\n'", - "LayoutText #text", - "InlineTextBox 'The players all played at once without waiting'", - "LayoutBlockFlow (floating) SPAN id='greenFloat'", - "LayoutText #text", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "LayoutText #text", - "InlineTextBox 'the Queen'", - "LayoutText #text", - "InlineTextBox 'was in a furious passion, and went\n'", - "InlineTextBox 'stamping about, and'", - "InlineTextBox 'shouting \u2018Off with his head!\u2019 or \u2018Off with\n'", - "InlineTextBox 'her head!\u2019'", - "InlineTextBox 'about once in a minute.\n'", - "LayoutText #text", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet'", - "InlineTextBox 'had any dispute with the Queen, but she knew that it might'", - "InlineTextBox 'happen any minute, \u2018and then,\u2019 thought she, \u2018what would'", - "InlineTextBox 'become of\n'", - "InlineTextBox 'me? They\u2019re dreadfully fond of beheading people'", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/offset-change-wrong-invalidation-with-float-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/offset-change-wrong-invalidation-with-float-expected.txt deleted file mode 100644 index 9f339e4..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/offset-change-wrong-invalidation-with-float-expected.txt +++ /dev/null
@@ -1,24 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [71, 92, 17, 18], - [71, 92, 7, 17], - [71, -158, 17, 18], - [71, -158, 7, 17], - [48, 92, 40, 18], - [48, -158, 40, 18] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (positioned) UL id='submenu'", - "LayoutListItem LI", - "LayoutListMarker (anonymous)" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.txt deleted file mode 100644 index 5ea2c9e..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.txt +++ /dev/null
@@ -1,33 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [18, 148, 200, 18], - [18, 110, 200, 18], - [16, 146, 204, 42], - [16, 146, 202, 21], - [16, 108, 204, 80], - [16, 108, 204, 80] - ], - "paintInvalidationClients": [ - "InlineTextBox 'CONTENTS'", - "RootInlineBox", - "InlineTextBox 'CONTENTS'", - "RootInlineBox", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "InlineFlowBox", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "InlineFlowBox", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/relative-inline-positioned-movement-repaint-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/relative-inline-positioned-movement-repaint-expected.txt deleted file mode 100644 index 0d3211bd..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/relative-inline-positioned-movement-repaint-expected.txt +++ /dev/null
@@ -1,28 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [69, 8, 372, 18], - [68, 7, 374, 19], - [29, 8, 372, 18], - [28, 7, 374, 19], - [8, 7, 784, 19] - ], - "paintInvalidationClients": [ - "InlineTextBox 'When this layer moves it shouldn't generate a repaint rect.'", - "InlineFlowBox", - "RootInlineBox", - "LayoutBlockFlow BODY", - "LayoutInline (relative positioned) DIV id='block'", - "InlineFlowBox", - "LayoutText #text", - "InlineTextBox 'When this layer moves it shouldn't generate a repaint rect.'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/remove-inline-after-layout-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/remove-inline-after-layout-expected.txt deleted file mode 100644 index 26ce2566..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/remove-inline-after-layout-expected.txt +++ /dev/null
@@ -1,35 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [293, 108, 101, 100], - [112, 194, 182, 18], - [112, 108, 100, 100], - [8, 108, 784, 207] - ], - "paintInvalidationClients": [ - "InlineBox", - "InlineTextBox '\n'", - "InlineTextBox 'This span should disappear.\n'", - "InlineBox", - "RootInlineBox", - "InlineTextBox 'This span should disappear.'", - "LayoutText #text", - "InlineFlowBox", - "LayoutInline SPAN id='target'", - "InlineBox", - "InlineTextBox '\n'", - "RootInlineBox", - "InlineBox", - "RootInlineBox", - "LayoutBlockFlow (anonymous)", - "LayoutBlockFlow DIV" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/remove-inline-layer-after-layout-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/remove-inline-layer-after-layout-expected.txt deleted file mode 100644 index 5c36767..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/remove-inline-layer-after-layout-expected.txt +++ /dev/null
@@ -1,36 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [293, 108, 101, 100], - [112, 194, 182, 18], - [112, 108, 182, 104], - [112, 108, 100, 100], - [8, 108, 784, 103] - ], - "paintInvalidationClients": [ - "InlineBox", - "InlineTextBox '\n'", - "InlineTextBox 'This span should disappear.\n'", - "InlineFlowBox", - "InlineBox", - "RootInlineBox", - "InlineTextBox 'This span should disappear.\n'", - "LayoutText #text", - "InlineFlowBox", - "LayoutInline SPAN id='target'", - "InlineBox", - "InlineTextBox '\n'", - "InlineBox", - "RootInlineBox", - "LayoutBlockFlow (anonymous)", - "LayoutBlockFlow DIV" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/repaint-across-writing-mode-boundary-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/repaint-across-writing-mode-boundary-expected.txt deleted file mode 100644 index a54761e..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/repaint-across-writing-mode-boundary-expected.txt +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [548, 191, 23, 35] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow HTML", - "LayoutBlockFlow BODY", - "LayoutBlockFlow DIV class='lrblock'", - "LayoutBlockFlow DIV class='basic d1 vert'", - "LayoutBlockFlow P", - "LayoutText #text", - "InlineTextBox '\u7B2C\u4E00\u6BB5\u843D paragraph 1'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/repaint-during-scroll-with-zoom-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/repaint-during-scroll-with-zoom-expected.txt deleted file mode 100644 index 046abf9..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/fast/repaint/repaint-during-scroll-with-zoom-expected.txt +++ /dev/null
@@ -1,34 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "backgroundColor": "#C0C0C0", - "repaintRects": [ - [237, 64, 15, 236], - [2, 299, 235, 16], - [2, 64, 235, 236], - [2, 64, 235, 236], - [2, 64, 235, 236], - [2, 64, 225, 226], - [2, 64, 135, 136], - [2, 64, 58, 16] - ], - "paintInvalidationClients": [ - "HorizontalScrollbar", - "LayoutIFrame (positioned) IFRAME", - "VerticalScrollbar", - "LayoutIFrame (positioned) IFRAME", - "LayoutIFrame (positioned) IFRAME", - "LayoutView #document", - "LayoutBlockFlow HTML", - "LayoutBlockFlow BODY", - "LayoutText #text", - "InlineTextBox 'scroll me'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/inline/outline-offset-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/inline/outline-offset-expected.png deleted file mode 100644 index e8a48cff..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/inline/outline-offset-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/invalidation/composite-after-paint/image-resize-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/invalidation/composite-after-paint/image-resize-expected.png deleted file mode 100644 index f7b736b7..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/invalidation/composite-after-paint/image-resize-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/invalidation/composite-after-paint/percent-size-image-resize-container-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/invalidation/composite-after-paint/percent-size-image-resize-container-expected.png deleted file mode 100644 index 7a249b5..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/invalidation/composite-after-paint/percent-size-image-resize-container-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/invalidation/composite-after-paint/selection-change-in-iframe-with-relative-parent-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/invalidation/composite-after-paint/selection-change-in-iframe-with-relative-parent-expected.png deleted file mode 100644 index 3afe787..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/invalidation/composite-after-paint/selection-change-in-iframe-with-relative-parent-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/invalidation/composite-after-paint/text-match-highlight-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/invalidation/composite-after-paint/text-match-highlight-expected.png deleted file mode 100644 index 442b827..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/invalidation/composite-after-paint/text-match-highlight-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/invalidation/non-text-link-invalidation-optimization-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/invalidation/non-text-link-invalidation-optimization-expected.txt deleted file mode 100644 index 922e92c..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/invalidation/non-text-link-invalidation-optimization-expected.txt +++ /dev/null
@@ -1,33 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [360, 8, 54, 18], - [326, 8, 25, 17], - [167, 8, 150, 17], - [139, 8, 29, 18], - [75, 8, 65, 18], - [8, 8, 59, 17] - ], - "paintInvalidationClients": [ - "LayoutText #text", - "InlineTextBox 'This test '", - "LayoutText #text", - "InlineTextBox ' passes if '", - "LayoutText #text", - "InlineTextBox 'only'", - "LayoutText #text", - "InlineTextBox ' text is invalidated and '", - "LayoutText #text", - "InlineTextBox ' no '", - "LayoutText #text", - "InlineTextBox ' images.'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/roundedrects/circle-with-shadow-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/roundedrects/circle-with-shadow-expected.png deleted file mode 100644 index 70a7377..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/roundedrects/circle-with-shadow-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/roundedrects/input-with-rounded-rect-and-shadow-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/roundedrects/input-with-rounded-rect-and-shadow-expected.png deleted file mode 100644 index d8d8dacd..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/roundedrects/input-with-rounded-rect-and-shadow-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/selection-within-composited-scroller-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/selection-within-composited-scroller-expected.txt deleted file mode 100644 index 2cd7697..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/selection-within-composited-scroller-expected.txt +++ /dev/null
@@ -1,22 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [8, 168, 23, 17] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow HTML", - "LayoutBlockFlow BODY", - "LayoutBlockFlow DIV id='scroller'", - "LayoutBlockFlow DIV id='target'", - "LayoutText #text", - "InlineTextBox 'test'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-across-blocks-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-across-blocks-expected.png deleted file mode 100644 index ae94bee..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-across-blocks-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-br-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-br-expected.png deleted file mode 100644 index ae94bee..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-br-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-expected.png deleted file mode 100644 index 956d8017..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.png deleted file mode 100644 index f243a28..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.txt deleted file mode 100644 index 3c5026b..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-mixed-ltr-rtl-expected.txt +++ /dev/null
@@ -1,17 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x132 - LayoutBlockFlow {HTML} at (0,0) size 800x132 - LayoutBlockFlow {BODY} at (8,16) size 784x108 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 348x17 - text run at (0,0) width 348: "Passes if there are no overpainted selection highlights." - LayoutBlockFlow (anonymous) at (0,34) size 784x74 - LayoutInline {SPAN} at (0,0) size 189x71 - LayoutText {#text} at (0,1) size 189x71 - text run at (0,1) width 96: "text" - text run at (95,1) width 94 RTL: "\x{645}\x{62A}\x{646}:" - LayoutText {#text} at (0,0) size 0x0 - LayoutText {#text} at (0,0) size 0x0 -selection start: position 5 of child 0 {#text} of child 2 {SPAN} of body -selection end: position 13 of child 0 {#text} of child 2 {SPAN} of body
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.png deleted file mode 100644 index 8a50b030..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.txt deleted file mode 100644 index 3793014..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-double-linebreak-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x206 - LayoutBlockFlow {HTML} at (0,0) size 800x206 - LayoutBlockFlow {BODY} at (8,16) size 784x182 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 348x17 - text run at (0,0) width 348: "Passes if there are no overpainted selection highlights." - LayoutBlockFlow {DIV} at (0,34) size 784x148 - LayoutText {#text} at (755,1) size 29x71 - text run at (755,1) width 29: "a" - LayoutBR {BR} at (755,1) size 1x71 - LayoutBR {BR} at (784,75) size 0x71 -selection start: position 0 of child 0 {#text} of child 2 {DIV} of body -selection end: position 1 of child 1 {BR} of child 2 {DIV} of body
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-expected.png deleted file mode 100644 index 29d786f..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-rtl-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-span-across-line-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-span-across-line-expected.png deleted file mode 100644 index 4dcedcab..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-span-across-line-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-span-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-span-expected.png deleted file mode 100644 index c200cb4..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-span-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-vertical-lr-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-vertical-lr-expected.png deleted file mode 100644 index b1ee98b..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-vertical-lr-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-vertical-rl-expected.png b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-vertical-rl-expected.png deleted file mode 100644 index ab2ad5e1..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/paint/selection/text-selection-newline-vertical-rl-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/svg/custom/object-sizing-explicit-height-expected.txt b/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/svg/custom/object-sizing-explicit-height-expected.txt deleted file mode 100644 index 2a002a9..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/composite-after-paint/svg/custom/object-sizing-explicit-height-expected.txt +++ /dev/null
@@ -1,83 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x374 - LayoutBlockFlow {html} at (0,0) size 800x374 - LayoutBlockFlow {body} at (8,8) size 784x358 - LayoutText {#text} at (175,161) size 4x17 - text run at (175,161) width 4: " " - LayoutText {#text} at (354,161) size 4x17 - text run at (354,161) width 4: " " - LayoutText {#text} at (533,161) size 4x17 - text run at (533,161) width 4: " " - LayoutText {#text} at (0,0) size 0x0 - LayoutText {#text} at (175,340) size 4x17 - text run at (175,340) width 4: " " - LayoutText {#text} at (354,340) size 4x17 - text run at (354,340) width 4: " " - LayoutText {#text} at (533,340) size 4x17 - text run at (533,340) width 4: " " - LayoutText {#text} at (0,0) size 0x0 -layer at (8,8) size 175x175 - LayoutEmbeddedObject {object} at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (187,8) size 175x175 - LayoutEmbeddedObject {object} at (179,0) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (366,8) size 175x175 - LayoutEmbeddedObject {object} at (358,0) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (545,8) size 175x175 - LayoutEmbeddedObject {object} at (537,0) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (8,187) size 175x175 - LayoutEmbeddedObject {object} at (0,179) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (187,187) size 175x175 - LayoutEmbeddedObject {object} at (179,179) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (366,187) size 175x175 - LayoutEmbeddedObject {object} at (358,179) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00] -layer at (545,187) size 175x175 - LayoutEmbeddedObject {object} at (537,179) size 175x175 - layer at (0,0) size 175x175 - LayoutView at (0,0) size 175x175 - layer at (0,0) size 175x175 - LayoutSVGRoot {svg} at (0,0) size 175x175 - LayoutSVGRect {rect} at (0,0) size 300x300 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=0.00] [width=300.00] [height=300.00] - LayoutSVGEllipse {circle} at (120,120) size 60x60 [fill={[type=SOLID] [color=#008000]}] [cx=150.00] [cy=150.00] [r=30.00]
diff --git a/third_party/blink/web_tests/platform/win/virtual/threaded/fast/scroll-behavior/smooth-scroll/fixed-background-in-iframe-expected.txt b/third_party/blink/web_tests/platform/win/virtual/threaded/fast/scroll-behavior/smooth-scroll/fixed-background-in-iframe-expected.txt index 4c41b141..7ba6c6c 100644 --- a/third_party/blink/web_tests/platform/win/virtual/threaded/fast/scroll-behavior/smooth-scroll/fixed-background-in-iframe-expected.txt +++ b/third_party/blink/web_tests/platform/win/virtual/threaded/fast/scroll-behavior/smooth-scroll/fixed-background-in-iframe-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS isScrollAnimatingOnMainThread(iframeDoc) is true PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/platform/win/virtual/video-surface-layer/media/video-zoom-controls-expected.png b/third_party/blink/web_tests/platform/win/virtual/video-surface-layer/media/video-zoom-controls-expected.png deleted file mode 100644 index cbfb1da..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/video-surface-layer/media/video-zoom-controls-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/custom-elements/form-validation-bubble-appearance-expected.png b/third_party/blink/web_tests/platform/win7/custom-elements/form-validation-bubble-appearance-expected.png new file mode 100644 index 0000000..1f00461 --- /dev/null +++ b/third_party/blink/web_tests/platform/win7/custom-elements/form-validation-bubble-appearance-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/media/video-zoom-controls-expected.png b/third_party/blink/web_tests/platform/win7/media/video-zoom-controls-expected.png new file mode 100644 index 0000000..67b2be0 --- /dev/null +++ b/third_party/blink/web_tests/platform/win7/media/video-zoom-controls-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/printing/absolute-position-headers-and-footers-expected.png b/third_party/blink/web_tests/platform/win7/printing/absolute-position-headers-and-footers-expected.png deleted file mode 100644 index 179ba46e..0000000 --- a/third_party/blink/web_tests/platform/win7/printing/absolute-position-headers-and-footers-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/fast/repaint/focus-ring-on-continuation-move-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/fast/repaint/focus-ring-on-continuation-move-expected.txt deleted file mode 100644 index 3cf1167..0000000 --- a/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/fast/repaint/focus-ring-on-continuation-move-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [208, 200, 100, 100], - [8, 200, 100, 100] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (relative positioned) DIV id='block'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/fast/repaint/inline-outline-repaint-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/fast/repaint/inline-outline-repaint-expected.txt deleted file mode 100644 index 732cb80..0000000 --- a/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/fast/repaint/inline-outline-repaint-expected.txt +++ /dev/null
@@ -1,129 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [45, 182, 3, 20], - [8, 166, 92, 35], - [8, 166, 90, 35], - [5, 163, 103, 41], - [5, 163, 98, 41], - [5, 163, 96, 41] - ], - "paintInvalidationClients": [ - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "LayoutText #text", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'dolor sit amet'", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'dolor sit'", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'dolor sit'", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox ''", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'dolor'", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineFlowBox", - "RootInlineBox", - "InlineTextBox 'dolor'", - "InlineFlowBox", - "RootInlineBox", - "LayoutBlockFlow DIV", - "LayoutInline SPAN id='test'", - "InlineFlowBox", - "InlineFlowBox", - "LayoutText #text", - "InlineTextBox 'Lorem ipsum'", - "InlineTextBox ' '", - "InlineTextBox 'dolor\u00A0'", - "LayoutBlockFlow DIV" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/fast/repaint/outline-change-offset-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/fast/repaint/outline-change-offset-expected.txt deleted file mode 100644 index e4f270f..0000000 --- a/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/fast/repaint/outline-change-offset-expected.txt +++ /dev/null
@@ -1,20 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [40, 40, 120, 120], - [35, 35, 130, 130], - [35, 35, 130, 130] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (positioned) DIV id='indicator'", - "LayoutBlockFlow (positioned) DIV id='target'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.png b/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.png deleted file mode 100644 index c7f0bdd..0000000 --- a/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/fast/repaint/outline-continuations-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/paint/invalidation/composite-after-paint/image-resize-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/paint/invalidation/composite-after-paint/image-resize-expected.txt deleted file mode 100644 index dd184de6..0000000 --- a/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/paint/invalidation/composite-after-paint/image-resize-expected.txt +++ /dev/null
@@ -1 +0,0 @@ -["LayoutImage (positioned) IMG"]
diff --git a/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/paint/invalidation/composite-after-paint/text-match-highlight-expected.png b/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/paint/invalidation/composite-after-paint/text-match-highlight-expected.png deleted file mode 100644 index f83e65d..0000000 --- a/third_party/blink/web_tests/platform/win7/virtual/composite-after-paint/paint/invalidation/composite-after-paint/text-match-highlight-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt index aa51b9d..4a6572b 100644 --- a/third_party/blink/web_tests/platform/win7/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt +++ b/third_party/blink/web_tests/platform/win7/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - [INTERFACES] interface Navigator interface Notification : EventTarget
diff --git a/third_party/blink/web_tests/platform/win7/virtual/threaded/printing/absolute-position-headers-and-footers-expected.png b/third_party/blink/web_tests/platform/win7/virtual/threaded/printing/absolute-position-headers-and-footers-expected.png deleted file mode 100644 index 179ba46e..0000000 --- a/third_party/blink/web_tests/platform/win7/virtual/threaded/printing/absolute-position-headers-and-footers-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/touchadjustment/big-div-expected.txt b/third_party/blink/web_tests/touchadjustment/big-div-expected.txt index 01e3b8f..bc6ff18 100644 --- a/third_party/blink/web_tests/touchadjustment/big-div-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/big-div-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Overlapping touch above the target should snap to the top of the target element. PASS adjustedNode.id is element.id PASS adjustedPoint.x >= targetBounds.left is true
diff --git a/third_party/blink/web_tests/touchadjustment/block-testing-expected.txt b/third_party/blink/web_tests/touchadjustment/block-testing-expected.txt index 6d9e58d..c1aa3ca9 100644 --- a/third_party/blink/web_tests/touchadjustment/block-testing-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/block-testing-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS adjusted node was DIV#div1. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/touchadjustment/context-menu-expected.txt b/third_party/blink/web_tests/touchadjustment/context-menu-expected.txt index 674f0797..d6be2112 100644 --- a/third_party/blink/web_tests/touchadjustment/context-menu-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/context-menu-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS adjusted node was A#a0. PASS adjusted node was SPAN#span0. PASS adjusted node was null.
diff --git a/third_party/blink/web_tests/touchadjustment/context-menu-select-text-expected.txt b/third_party/blink/web_tests/touchadjustment/context-menu-select-text-expected.txt index f8f3700..1a605e2 100644 --- a/third_party/blink/web_tests/touchadjustment/context-menu-select-text-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/context-menu-select-text-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS adjusted node was null. PASS adjusted node was 'Text text text.'. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/touchadjustment/context-menu-shadow-node-expected.txt b/third_party/blink/web_tests/touchadjustment/context-menu-shadow-node-expected.txt index 13c4251e..a7c17fe0 100644 --- a/third_party/blink/web_tests/touchadjustment/context-menu-shadow-node-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/context-menu-shadow-node-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS adjusted node was null. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/touchadjustment/context-menu-text-subtargets-expected.txt b/third_party/blink/web_tests/touchadjustment/context-menu-text-subtargets-expected.txt index 01bfd79..4a2657c 100644 --- a/third_party/blink/web_tests/touchadjustment/context-menu-text-subtargets-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/context-menu-text-subtargets-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS adjusted point was within (10,10)x(80,20) PASS adjusted point was within (10,10)x(80,20) PASS adjusted point was within (170,10)x(80,20)
diff --git a/third_party/blink/web_tests/touchadjustment/disabled-formelements-expected.txt b/third_party/blink/web_tests/touchadjustment/disabled-formelements-expected.txt index 651a827..9079a2c 100644 --- a/third_party/blink/web_tests/touchadjustment/disabled-formelements-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/disabled-formelements-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Test we can hit the form elements directly. PASS adjusted node was null. PASS adjusted node was LABEL#label2.
diff --git a/third_party/blink/web_tests/touchadjustment/editable-content-expected.txt b/third_party/blink/web_tests/touchadjustment/editable-content-expected.txt index 2fc6ed86..d00db9e 100644 --- a/third_party/blink/web_tests/touchadjustment/editable-content-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/editable-content-expected.txt
@@ -1,12 +1,11 @@ - Hello World + Tests touch adjustment on a text-area. On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - test textarea test direct touches PASS Math.floor((adjustedPoint.y - origin) / rowHeight) is 0
diff --git a/third_party/blink/web_tests/touchadjustment/event-triggered-widgets-expected.txt b/third_party/blink/web_tests/touchadjustment/event-triggered-widgets-expected.txt index 2180098..ef5f46b9 100644 --- a/third_party/blink/web_tests/touchadjustment/event-triggered-widgets-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/event-triggered-widgets-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Testing small direct hits PASS adjustedNode.id is element.id PASS adjustedNode.id is element.id
diff --git a/third_party/blink/web_tests/touchadjustment/focusout-on-touch-expected.txt b/third_party/blink/web_tests/touchadjustment/focusout-on-touch-expected.txt index a1d9026..00af170 100644 --- a/third_party/blink/web_tests/touchadjustment/focusout-on-touch-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/focusout-on-touch-expected.txt
@@ -1,3 +1,2 @@ ALERT: PASS! You should see "ALERT: PASS!" -
diff --git a/third_party/blink/web_tests/touchadjustment/html-label-expected.txt b/third_party/blink/web_tests/touchadjustment/html-label-expected.txt index dd1c921..e93317dbc 100644 --- a/third_party/blink/web_tests/touchadjustment/html-label-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/html-label-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Testing small direct hits. PASS adjusted node was A#mylink. PASS adjusted node was LABEL#mylabel.
diff --git a/third_party/blink/web_tests/touchadjustment/iframe-expected.txt b/third_party/blink/web_tests/touchadjustment/iframe-expected.txt index 743d1f8e..d3df78c 100644 --- a/third_party/blink/web_tests/touchadjustment/iframe-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/iframe-expected.txt
@@ -1,9 +1,7 @@ - Test touch-adjustment on links in an iframe. Making sure we iframe position is correctly adjusted for. On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Test fat direct touches. PASS adjustedNode.id is "a1" PASS adjustedNode.id is "a2"
diff --git a/third_party/blink/web_tests/touchadjustment/nested-shadow-node-expected.txt b/third_party/blink/web_tests/touchadjustment/nested-shadow-node-expected.txt index 6b62b44b..9a20e7b 100644 --- a/third_party/blink/web_tests/touchadjustment/nested-shadow-node-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/nested-shadow-node-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS adjusted node was DIV#targetDiv. PASS adjustedPoint.x is within 10 of 88 PASS adjustedPoint.y is within 10 of 28
diff --git a/third_party/blink/web_tests/touchadjustment/nested-touch-expected.txt b/third_party/blink/web_tests/touchadjustment/nested-touch-expected.txt index c93af2d..e27e1485 100644 --- a/third_party/blink/web_tests/touchadjustment/nested-touch-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/nested-touch-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Testing small direct hits. PASS adjusted node was DIV#mybox1. PASS adjusted node was DIV#mybox2.
diff --git a/third_party/blink/web_tests/touchadjustment/plugin-expected.txt b/third_party/blink/web_tests/touchadjustment/plugin-expected.txt index 909a6fd..25c8e25 100644 --- a/third_party/blink/web_tests/touchadjustment/plugin-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/plugin-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Test direct hits. PASS adjusted node was EMBED#plugin. PASS adjusted node was BUTTON#button1.
diff --git a/third_party/blink/web_tests/touchadjustment/pseudo-element-expected.txt b/third_party/blink/web_tests/touchadjustment/pseudo-element-expected.txt index 052c7827..3be27765 100644 --- a/third_party/blink/web_tests/touchadjustment/pseudo-element-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/pseudo-element-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Test touch area contained within the pseudo element. PASS adjustedNode.id is element.id PASS adjustedPoint.x >= targetBounds.left is true @@ -14,6 +13,7 @@ PASS adjustedPoint.y >= touchBounds.y is true PASS adjustedPoint.y <= touchBounds.y + touchBounds.height is true + Overlapping touch above the target should snap to the top of the pseudo element. PASS adjustedNode.id is element.id PASS adjustedPoint.x >= targetBounds.left is true @@ -25,6 +25,7 @@ PASS adjustedPoint.y >= touchBounds.y is true PASS adjustedPoint.y <= touchBounds.y + touchBounds.height is true + Overlapping touch below the target should snap to the bottom of the pseudo element. PASS adjustedNode.id is element.id PASS adjustedPoint.x >= targetBounds.left is true @@ -36,6 +37,7 @@ PASS adjustedPoint.y >= touchBounds.y is true PASS adjustedPoint.y <= touchBounds.y + touchBounds.height is true + Overlapping touch left of the target should snap to the left side of the pseudo element. PASS adjustedNode.id is element.id PASS adjustedPoint.x >= targetBounds.left is true @@ -47,6 +49,7 @@ PASS adjustedPoint.y >= touchBounds.y is true PASS adjustedPoint.y <= touchBounds.y + touchBounds.height is true + Overlapping touch right of the target should snap to the right side of the pseudo element. PASS adjustedNode.id is element.id PASS adjustedPoint.x >= targetBounds.left is true @@ -58,6 +61,7 @@ PASS adjustedPoint.y >= touchBounds.y is true PASS adjustedPoint.y <= touchBounds.y + touchBounds.height is true + PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/touchadjustment/rotated-node-expected.txt b/third_party/blink/web_tests/touchadjustment/rotated-node-expected.txt index e28f37f..5660f1f 100644 --- a/third_party/blink/web_tests/touchadjustment/rotated-node-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/rotated-node-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Direct Touches PASS adjusted node was DIV#rotated. PASS adjusted node was DIV#rotated.
diff --git a/third_party/blink/web_tests/touchadjustment/scroll-offset-expected.txt b/third_party/blink/web_tests/touchadjustment/scroll-offset-expected.txt index 532c520..e2c0bdc 100644 --- a/third_party/blink/web_tests/touchadjustment/scroll-offset-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/scroll-offset-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS adjusted node was A#a0. PASS adjusted node was A#a1. PASS adjustedPoint is non-null.
diff --git a/third_party/blink/web_tests/touchadjustment/search-cancel-expected.txt b/third_party/blink/web_tests/touchadjustment/search-cancel-expected.txt index 212625c..b644fa5e 100644 --- a/third_party/blink/web_tests/touchadjustment/search-cancel-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/search-cancel-expected.txt
@@ -1,10 +1,8 @@ - Test touch adjustment on a search field with a visible cancel button. On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Touch centered on cancel button but overlapping neighboring candidate. PASS targetContainsPoint is true PASS touchContainsPoint is true
diff --git a/third_party/blink/web_tests/touchadjustment/simple-shadow-dom-expected.txt b/third_party/blink/web_tests/touchadjustment/simple-shadow-dom-expected.txt index 5f88264d..8a7ae39 100644 --- a/third_party/blink/web_tests/touchadjustment/simple-shadow-dom-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/simple-shadow-dom-expected.txt
@@ -3,7 +3,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS adjusted node was DIV#shadowDiv. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/touchadjustment/small-target-test-expected.txt b/third_party/blink/web_tests/touchadjustment/small-target-test-expected.txt index 65903216..b21ca77 100644 --- a/third_party/blink/web_tests/touchadjustment/small-target-test-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/small-target-test-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Testing small direct hits. PASS adjusted node was DIV#check. PASS adjusted node was INPUT#task.
diff --git a/third_party/blink/web_tests/touchadjustment/touch-inlines-expected.txt b/third_party/blink/web_tests/touchadjustment/touch-inlines-expected.txt index 004f036f..05cbd7ce 100644 --- a/third_party/blink/web_tests/touchadjustment/touch-inlines-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/touch-inlines-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Test some direct hits. PASS adjusted node was A#1. PASS adjusted node was A#2.
diff --git a/third_party/blink/web_tests/touchadjustment/touch-links-active-expected.txt b/third_party/blink/web_tests/touchadjustment/touch-links-active-expected.txt index dd4fed2..5e3e4216 100644 --- a/third_party/blink/web_tests/touchadjustment/touch-links-active-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/touch-links-active-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Testing indirect hits. PASS isLinkActive() is true PASS isLinkActive() is true
diff --git a/third_party/blink/web_tests/touchadjustment/touch-links-longpress-expected.txt b/third_party/blink/web_tests/touchadjustment/touch-links-longpress-expected.txt index c22036c..6308649 100644 --- a/third_party/blink/web_tests/touchadjustment/touch-links-longpress-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/touch-links-longpress-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Testing direct hits. PASS PASS
diff --git a/third_party/blink/web_tests/touchadjustment/touch-links-two-finger-tap-expected.txt b/third_party/blink/web_tests/touchadjustment/touch-links-two-finger-tap-expected.txt index be178196..0855018b 100644 --- a/third_party/blink/web_tests/touchadjustment/touch-links-two-finger-tap-expected.txt +++ b/third_party/blink/web_tests/touchadjustment/touch-links-two-finger-tap-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Testing direct hits. PASS PASS
diff --git a/third_party/blink/web_tests/transforms/2d/computed-style-origin-expected.txt b/third_party/blink/web_tests/transforms/2d/computed-style-origin-expected.txt index 68f42b0..030846c 100644 --- a/third_party/blink/web_tests/transforms/2d/computed-style-origin-expected.txt +++ b/third_party/blink/web_tests/transforms/2d/computed-style-origin-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS test1Style.webkitTransformOrigin is '10px 10px' PASS test2Style.webkitTransformOrigin is '10px 10px' PASS test3Style.webkitTransformOrigin is '0px 20px' @@ -15,6 +14,7 @@ PASS test5Style.webkitPerspectiveOrigin is '15px 15px' PASS test6Style.webkitPerspectiveOrigin is '50px 50px' + PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/transforms/2d/set-transform-and-top-expected.txt b/third_party/blink/web_tests/transforms/2d/set-transform-and-top-expected.txt index 75c40d5..46d0f82 100644 --- a/third_party/blink/web_tests/transforms/2d/set-transform-and-top-expected.txt +++ b/third_party/blink/web_tests/transforms/2d/set-transform-and-top-expected.txt
@@ -1,3 +1,4 @@ -AB +A +B PASS - Element a moved past y=250px PASS - Element b moved past y=250px
diff --git a/third_party/blink/web_tests/transforms/3d/hit-testing/coplanar-with-camera-expected.txt b/third_party/blink/web_tests/transforms/3d/hit-testing/coplanar-with-camera-expected.txt index c20bd36a..60957ed 100644 --- a/third_party/blink/web_tests/transforms/3d/hit-testing/coplanar-with-camera-expected.txt +++ b/third_party/blink/web_tests/transforms/3d/hit-testing/coplanar-with-camera-expected.txt
@@ -1,4 +1,5 @@ -The text on this element should be selectable. Hovering on this element should cause a highlight. Element at 98, 200 has id "background": PASS +The text on this element should be selectable. Hovering on this element should cause a highlight. +Element at 98, 200 has id "background": PASS Element at 302, 200 has id "background": PASS Element at 200, 98 has id "background": PASS Element at 200, 302 has id "background": PASS
diff --git a/third_party/blink/web_tests/transforms/3d/hit-testing/hover-rotated-with-children-negative-z-expected.txt b/third_party/blink/web_tests/transforms/3d/hit-testing/hover-rotated-with-children-negative-z-expected.txt index 74c28f07..16ef69fc 100644 --- a/third_party/blink/web_tests/transforms/3d/hit-testing/hover-rotated-with-children-negative-z-expected.txt +++ b/third_party/blink/web_tests/transforms/3d/hit-testing/hover-rotated-with-children-negative-z-expected.txt
@@ -2,6 +2,7 @@ child 1 non transformed child child 2 + Checks that hit testing is correct when a transformed element has childs with negative z-offset Element at 70, 70 has id "transformed": PASS
diff --git a/third_party/blink/web_tests/transforms/container-transform-crash-expected.txt b/third_party/blink/web_tests/transforms/container-transform-crash-expected.txt index 4395897..be21d8c 100644 --- a/third_party/blink/web_tests/transforms/container-transform-crash-expected.txt +++ b/third_party/blink/web_tests/transforms/container-transform-crash-expected.txt
@@ -1,4 +1,3 @@ Inline with -webkit-transform that contains positioned element. This should not crash. + some text here - -
diff --git a/third_party/blink/web_tests/transforms/cssmatrix-2d-interface-expected.txt b/third_party/blink/web_tests/transforms/cssmatrix-2d-interface-expected.txt index 66b3e49c..231a294 100644 --- a/third_party/blink/web_tests/transforms/cssmatrix-2d-interface-expected.txt +++ b/third_party/blink/web_tests/transforms/cssmatrix-2d-interface-expected.txt
@@ -3,6 +3,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + CSSMatrix constructors PASS m is non-null. PASS new WebKitCSSMatrix() is non-null. @@ -12,6 +13,7 @@ PASS new WebKitCSSMatrix("none") is non-null. PASS new WebKitCSSMatrix(" none ") is non-null. + Test toString PASS a[0] is "matrix" PASS parseFloat(a2[0]) is 1 @@ -22,9 +24,11 @@ PASS parseFloat(a3[0]) is 0 PASS a3[1] is "" + Test bad input to string constructor PASS new WebKitCSSMatrix("banana") threw exception SyntaxError: Failed to construct 'DOMMatrix': Failed to parse 'banana'.. + Test attributes on default matrix PASS m.a is 1 PASS m.b is 0 @@ -33,6 +37,7 @@ PASS m.e is 0 PASS m.f is 0 + Test attributes on custom matrix PASS m.a is 11 PASS m.b is 12 @@ -41,6 +46,7 @@ PASS m.e is 41 PASS m.f is 42 + Test setMatrixValue - set to matrix() PASS m.a is 11 PASS m.b is 12 @@ -49,6 +55,7 @@ PASS m.e is 41 PASS m.f is 42 + Test setMatrixValue - set to translate(10px, 20px) scale(2, 3) PASS m.a is 2 PASS m.b is 0 @@ -57,11 +64,13 @@ PASS m.e is 10 PASS m.f is 20 + Test throwing exception from setMatrixValue PASS m.setMatrixValue("banana") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Failed to parse 'banana'.. PASS m.setMatrixValue("translate(10em, 20%)") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Lengths must be absolute, not relative. PASS m.setMatrixValue("translate(10px, 20px) scale()") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Failed to parse 'translate(10px, 20px) scale()'.. + Test attributes on translate() and accumulation PASS m2.a is 1 PASS m2.b is 0 @@ -70,6 +79,7 @@ PASS m2.e is 100 PASS m2.f is 50 + Test immutability of translate PASS parseFloat(m.a) is 1 PASS parseFloat(m.b) is 0 @@ -78,6 +88,7 @@ PASS parseFloat(m.e) is 0 PASS parseFloat(m.f) is 0 + Test attributes on scale() PASS m3.a is 5 PASS m3.b is 0 @@ -86,6 +97,7 @@ PASS m3.e is 100 PASS m3.f is 50 + Test immutability of scale() PASS parseFloat(m2.a) is 1 PASS parseFloat(m2.b) is 0 @@ -94,6 +106,7 @@ PASS parseFloat(m2.e) is 100 PASS parseFloat(m2.f) is 50 + Test attributes on non-uniform scale() PASS m4.a is 10 PASS m4.b is 0 @@ -102,6 +115,7 @@ PASS m4.e is 100 PASS m4.f is 50 + Test immutability of non-uniform scale() PASS parseFloat(m3.a) is 5 PASS parseFloat(m3.b) is 0 @@ -110,6 +124,7 @@ PASS parseFloat(m3.e) is 100 PASS parseFloat(m3.f) is 50 + Test rotate PASS parseFloat(m2.a.toPrecision(6)) is 0.984808 PASS parseFloat(m2.b.toPrecision(6)) is 0.173648 @@ -118,6 +133,7 @@ PASS m.e is 0 PASS m.f is 0 + Test immutability of rotate PASS parseFloat(m.a) is 1 PASS parseFloat(m.b) is 0 @@ -126,6 +142,7 @@ PASS parseFloat(m.e) is 0 PASS parseFloat(m.f) is 0 + Test skew in horizontal direction PASS parseFloat(m2.a) is 1 PASS parseFloat(m2.b) is 0 @@ -134,6 +151,7 @@ PASS parseFloat(m2.e) is 0 PASS parseFloat(m2.f) is 0 + Test immutability of horizontal skew PASS parseFloat(m.a) is 1 PASS parseFloat(m.b) is 0 @@ -142,6 +160,7 @@ PASS parseFloat(m.e) is 0 PASS parseFloat(m.f) is 0 + Test skew in vertical direction PASS parseFloat(m2.a) is 1 PASS parseFloat(m2.b.toPrecision(6)) is 0.700208 @@ -150,6 +169,7 @@ PASS parseFloat(m2.e) is 0 PASS parseFloat(m2.f) is 0 + Test immutability of vertical skew PASS parseFloat(m.a) is 1 PASS parseFloat(m.b) is 0 @@ -158,6 +178,7 @@ PASS parseFloat(m.e) is 0 PASS parseFloat(m.f) is 0 + Test multiply PASS parseFloat(m3.a) is 31 PASS parseFloat(m3.b) is 46 @@ -166,6 +187,7 @@ PASS parseFloat(m3.e) is 52 PASS parseFloat(m3.f) is 76 + Test that multiply works in the right direction PASS m.a is 2 PASS m.b is 0 @@ -174,6 +196,7 @@ PASS m.e is 100 PASS m.f is 0 + Test immutability of multiply PASS tx.a is 1 PASS tx.b is 0 @@ -188,6 +211,7 @@ PASS sx.e is 0 PASS sx.f is 0 + Test multiply with missing argument PASS m2.a is 1 PASS m2.b is 2 @@ -196,6 +220,7 @@ PASS m2.e is 5 PASS m2.f is 6 + Test inverse PASS parseFloat(m2.a) is 0.5 PASS parseFloat(m2.b) is 0 @@ -204,6 +229,7 @@ PASS parseFloat(m2.e) is -5 PASS parseFloat(m2.f) is -10 + Test immutability of inverse PASS parseFloat(m.a) is 2 PASS parseFloat(m.b) is 0 @@ -212,6 +238,7 @@ PASS parseFloat(m.e) is 10 PASS parseFloat(m.f) is 20 + Test not invertible matrix PASS m2.a is NaN PASS m2.b is NaN @@ -220,6 +247,7 @@ PASS m2.e is NaN PASS m2.f is NaN + Test immutability of inverse PASS m.a is 0 PASS m.b is 0 @@ -228,6 +256,7 @@ PASS m.e is 0 PASS m.f is 0 + PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/transforms/cssmatrix-3d-interface-expected.txt b/third_party/blink/web_tests/transforms/cssmatrix-3d-interface-expected.txt index 3563c33..e854d54 100644 --- a/third_party/blink/web_tests/transforms/cssmatrix-3d-interface-expected.txt +++ b/third_party/blink/web_tests/transforms/cssmatrix-3d-interface-expected.txt
@@ -3,11 +3,13 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". + CSSMatrix constructors PASS default constructor PASS object constructor PASS string constructor + Test toString PASS a[0] is "matrix3d" PASS parseFloat(a2[0]) is 1 @@ -28,9 +30,11 @@ PASS parseFloat(a3[0]) is 1 PASS a3[1] is "" + Test bad input to string constructor PASS new WebKitCSSMatrix("banana") threw exception SyntaxError: Failed to construct 'DOMMatrix': Failed to parse 'banana'.. + Test attributes on default matrix PASS m.m11 is 1 PASS m.m12 is 0 @@ -49,6 +53,7 @@ PASS m.m43 is 0 PASS m.m44 is 1 + Test attributes on custom matrix PASS m.m11 is 11 PASS m.m12 is 12 @@ -67,6 +72,7 @@ PASS m.m43 is 43 PASS m.m44 is 44 + Test setMatrixValue - set to matrix() PASS m.m11 is 11 PASS m.m12 is 12 @@ -85,6 +91,7 @@ PASS m.m43 is 43 PASS m.m44 is 44 + Test setMatrixValue - set to translate(10px, 20px, 30px) scale(2, 3, 4) PASS m.m11 is 2 PASS m.m12 is 0 @@ -103,11 +110,13 @@ PASS m.m43 is 30 PASS m.m44 is 1 + Test throwing exception from setMatrixValue PASS m.setMatrixValue("banana") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Failed to parse 'banana'.. PASS m.setMatrixValue("translate3d(10em, 20%, 40)") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Failed to parse 'translate3d(10em, 20%, 40)'.. PASS m.setMatrixValue("translate3d(10px, 20px, 30px) scale3d()") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Failed to parse 'translate3d(10px, 20px, 30px) scale3d()'.. + Test multiply PASS parseFloat(m3.m11) is 538 PASS parseFloat(m3.m12) is 612 @@ -126,6 +135,7 @@ PASS parseFloat(m3.m43) is 1118 PASS parseFloat(m3.m44) is 1240 + Test immutability of multiply PASS parseFloat(m.m11) is 1 PASS parseFloat(m.m12) is 2 @@ -144,6 +154,7 @@ PASS parseFloat(m.m43) is 15 PASS parseFloat(m.m44) is 16 + Test multiply in an affine matrix PASS parseFloat(m3.m11) is 31 PASS parseFloat(m3.m12) is 46 @@ -162,6 +173,7 @@ PASS parseFloat(m3.m43) is 0 PASS parseFloat(m3.m44) is 1 + Test that multiply works in the right direction PASS m.m11 is 2 PASS m.m12 is 0 @@ -180,6 +192,7 @@ PASS m.m43 is 0 PASS m.m44 is 1 + Test inverse PASS parseFloat(m2.m11) is 0.5 PASS parseFloat(m2.m12) is 0 @@ -198,6 +211,7 @@ PASS parseFloat(m2.m43) is -15 PASS parseFloat(m2.m44) is 1 + Test immutability of inverse PASS parseFloat(m.m11) is 2 PASS parseFloat(m.m12) is 0 @@ -216,6 +230,7 @@ PASS parseFloat(m.m43) is 30 PASS parseFloat(m.m44) is 1 + Test not invertible 3d matrix PASS m2.m11 is NaN PASS m2.m12 is NaN @@ -234,6 +249,7 @@ PASS m2.m43 is NaN PASS m2.m44 is NaN + Test immutability of inverse PASS m.m11 is 0 PASS m.m12 is 0 @@ -252,6 +268,7 @@ PASS m.m43 is 0 PASS m.m44 is 0 + Test translate PASS m2.m11 is 1 PASS m2.m12 is 0 @@ -270,6 +287,7 @@ PASS m2.m43 is 30 PASS m2.m44 is 1 + Test immutability of translate PASS m.m11 is 1 PASS m.m12 is 0 @@ -288,6 +306,7 @@ PASS m.m43 is 0 PASS m.m44 is 1 + Test scale PASS m2.m11 is 10 PASS m2.m12 is 0 @@ -306,6 +325,7 @@ PASS m2.m43 is 0 PASS m2.m44 is 1 + Test immutability of scale PASS m.m11 is 1 PASS m.m12 is 0 @@ -324,6 +344,7 @@ PASS m.m43 is 0 PASS m.m44 is 1 + Test rotate PASS parseFloat(m2.m11.toPrecision(6)) is 0.813798 PASS parseFloat(m2.m12.toPrecision(6)) is 0.469846 @@ -342,6 +363,7 @@ PASS parseFloat(m2.m43.toPrecision(6)) is 0 PASS parseFloat(m2.m44.toPrecision(6)) is 1 + Test immutability of rotate PASS m.m11 is 1 PASS m.m12 is 0 @@ -360,6 +382,7 @@ PASS m.m43 is 0 PASS m.m44 is 1 + Test rotateAxisAngle PASS parseFloat(m2.m11.toPrecision(6)) is 0.804738 PASS parseFloat(m2.m12.toPrecision(6)) is 0.505879 @@ -378,6 +401,7 @@ PASS parseFloat(m2.m43.toPrecision(6)) is 0 PASS parseFloat(m2.m44.toPrecision(6)) is 1 + Test immutability of rotateAxisAngle PASS m.m11 is 1 PASS m.m12 is 0 @@ -396,6 +420,7 @@ PASS m.m43 is 0 PASS m.m44 is 1 + PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/transforms/no_transform_hit_testing-expected.txt b/third_party/blink/web_tests/transforms/no_transform_hit_testing-expected.txt index 9f56990a..e0b9393 100644 --- a/third_party/blink/web_tests/transforms/no_transform_hit_testing-expected.txt +++ b/third_party/blink/web_tests/transforms/no_transform_hit_testing-expected.txt
@@ -1,5 +1,10 @@ Testing hittest on a layer with null transform + https://bugs.webkit.org/show_bug.cgi?id=24252 transformed element + + + + Pass.
diff --git a/third_party/blink/web_tests/transforms/scrollIntoView-transformed-expected.txt b/third_party/blink/web_tests/transforms/scrollIntoView-transformed-expected.txt index aba3fcf2..03b9c1ac 100644 --- a/third_party/blink/web_tests/transforms/scrollIntoView-transformed-expected.txt +++ b/third_party/blink/web_tests/transforms/scrollIntoView-transformed-expected.txt
@@ -5,19 +5,30 @@ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - +one +two +three +four + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - +one +two +three +four -This text should not be cut off This text should not be cut off + +This text should not be cut off + + + PASS - Element a and Element b had different scrollTop PASS - Element b had scrollTop: 0 PASS - Element c and Element d had same scrollTop
diff --git a/third_party/blink/web_tests/transforms/topmost-becomes-bottomost-for-scrolling-expected.txt b/third_party/blink/web_tests/transforms/topmost-becomes-bottomost-for-scrolling-expected.txt index 2d510c3..bda8793 100644 --- a/third_party/blink/web_tests/transforms/topmost-becomes-bottomost-for-scrolling-expected.txt +++ b/third_party/blink/web_tests/transforms/topmost-becomes-bottomost-for-scrolling-expected.txt
@@ -1,3 +1 @@ SUCCESS! The transform was applied to the scrollHeight! - -
diff --git a/third_party/blink/web_tests/transforms/transform-inherit-initial-unprefixed-expected.txt b/third_party/blink/web_tests/transforms/transform-inherit-initial-unprefixed-expected.txt index d80b8035..fc62e5b 100644 --- a/third_party/blink/web_tests/transforms/transform-inherit-initial-unprefixed-expected.txt +++ b/third_party/blink/web_tests/transforms/transform-inherit-initial-unprefixed-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Testing inherit. PASS computedStyle.transform is 'matrix(0.5, 0.866025, -0.866025, 0.5, 0, 0)' PASS computedStyle.webkitTransform is 'matrix(0.5, 0.866025, -0.866025, 0.5, 0, 0)'
diff --git a/third_party/blink/web_tests/transforms/transform-inside-overflow-scroll-expected.txt b/third_party/blink/web_tests/transforms/transform-inside-overflow-scroll-expected.txt index 2d510c3..bda8793 100644 --- a/third_party/blink/web_tests/transforms/transform-inside-overflow-scroll-expected.txt +++ b/third_party/blink/web_tests/transforms/transform-inside-overflow-scroll-expected.txt
@@ -1,3 +1 @@ SUCCESS! The transform was applied to the scrollHeight! - -
diff --git a/third_party/blink/web_tests/transitions/bad-transition-shorthand-crash-expected.txt b/third_party/blink/web_tests/transitions/bad-transition-shorthand-crash-expected.txt index 7857c299..ee581bc 100644 --- a/third_party/blink/web_tests/transitions/bad-transition-shorthand-crash-expected.txt +++ b/third_party/blink/web_tests/transitions/bad-transition-shorthand-crash-expected.txt
@@ -1,3 +1 @@ This tests a crash that was occuring when you have both an explicit property and 'all' in the transition-property CSS property. The crash would occur when you retarget the transition. This test should not crash. - -
diff --git a/third_party/blink/web_tests/transitions/hang-with-bad-transition-list-expected.txt b/third_party/blink/web_tests/transitions/hang-with-bad-transition-list-expected.txt index c4eb325..7734a9a 100644 --- a/third_party/blink/web_tests/transitions/hang-with-bad-transition-list-expected.txt +++ b/third_party/blink/web_tests/transitions/hang-with-bad-transition-list-expected.txt
@@ -1,2 +1 @@ PASS: If you can see this then we didn't hang!!! -
diff --git a/third_party/blink/web_tests/transitions/transition-end-event-prefixed-01-expected.txt b/third_party/blink/web_tests/transitions/transition-end-event-prefixed-01-expected.txt index caa9d6c..aaa23c2 100644 --- a/third_party/blink/web_tests/transitions/transition-end-event-prefixed-01-expected.txt +++ b/third_party/blink/web_tests/transitions/transition-end-event-prefixed-01-expected.txt
@@ -2,10 +2,10 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE + PASS transitionEventContainer.type is transitionEventBox.type PASS transitionEventContainer.bubbles is transitionEventBox.bubbles PASS transitionEventContainer.timeStamp is transitionEventBox.timeStamp @@ -18,4 +18,3 @@ PASS transitionEventContainer.pseudoElement is transitionEventBox.pseudoElement PASS transitionEventContainer.elapsedTime is transitionEventBox.elapsedTime PASS transitionEventContainer.propertyName is transitionEventBox.propertyName -
diff --git a/third_party/blink/web_tests/transitions/transition-end-event-prefixed-02-expected.txt b/third_party/blink/web_tests/transitions/transition-end-event-prefixed-02-expected.txt index 218fb9e..35d2538 100644 --- a/third_party/blink/web_tests/transitions/transition-end-event-prefixed-02-expected.txt +++ b/third_party/blink/web_tests/transitions/transition-end-event-prefixed-02-expected.txt
@@ -2,9 +2,8 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE -PASS transitionEventBox.currentTarget is transitionEventBox.target +PASS transitionEventBox.currentTarget is transitionEventBox.target
diff --git a/third_party/blink/web_tests/transitions/transition-end-event-prefixed-03-expected.txt b/third_party/blink/web_tests/transitions/transition-end-event-prefixed-03-expected.txt index caa9d6c..aaa23c2 100644 --- a/third_party/blink/web_tests/transitions/transition-end-event-prefixed-03-expected.txt +++ b/third_party/blink/web_tests/transitions/transition-end-event-prefixed-03-expected.txt
@@ -2,10 +2,10 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE + PASS transitionEventContainer.type is transitionEventBox.type PASS transitionEventContainer.bubbles is transitionEventBox.bubbles PASS transitionEventContainer.timeStamp is transitionEventBox.timeStamp @@ -18,4 +18,3 @@ PASS transitionEventContainer.pseudoElement is transitionEventBox.pseudoElement PASS transitionEventContainer.elapsedTime is transitionEventBox.elapsedTime PASS transitionEventContainer.propertyName is transitionEventBox.propertyName -
diff --git a/third_party/blink/web_tests/transitions/transition-inherit-initial-unprefixed-expected.txt b/third_party/blink/web_tests/transitions/transition-inherit-initial-unprefixed-expected.txt index 3581a98..3eb5c22 100644 --- a/third_party/blink/web_tests/transitions/transition-inherit-initial-unprefixed-expected.txt +++ b/third_party/blink/web_tests/transitions/transition-inherit-initial-unprefixed-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Testing inherit. PASS computedStyle.transitionProperty is 'width' PASS computedStyle.webkitTransitionProperty is 'width'
diff --git a/third_party/blink/web_tests/transitions/transition-shape-outside-crash-expected.txt b/third_party/blink/web_tests/transitions/transition-shape-outside-crash-expected.txt index 8cf03bf..656d72ce 100644 --- a/third_party/blink/web_tests/transitions/transition-shape-outside-crash-expected.txt +++ b/third_party/blink/web_tests/transitions/transition-shape-outside-crash-expected.txt
@@ -1,3 +1 @@ This test passes if it does not assert or crash. - -
diff --git a/third_party/blink/web_tests/transitions/transition-transform-translate-calculated-length-crash-expected.txt b/third_party/blink/web_tests/transitions/transition-transform-translate-calculated-length-crash-expected.txt index 92260cc..4fa776bd 100644 --- a/third_party/blink/web_tests/transitions/transition-transform-translate-calculated-length-crash-expected.txt +++ b/third_party/blink/web_tests/transitions/transition-transform-translate-calculated-length-crash-expected.txt
@@ -1,5 +1,3 @@ Bug http://crbug.com/261474: Dereference null pointer crash in Length::decrementCalculatedRef() The test passes if it does not crash. - -
diff --git a/third_party/blink/web_tests/transitions/unprefixed-perspective-expected.txt b/third_party/blink/web_tests/transitions/unprefixed-perspective-expected.txt index ee1c0c9..d0ffae80 100644 --- a/third_party/blink/web_tests/transitions/unprefixed-perspective-expected.txt +++ b/third_party/blink/web_tests/transitions/unprefixed-perspective-expected.txt
@@ -1,9 +1,11 @@ all 10ms fired transitionend with propertyName: perspective + perspective 10ms fired transitionend with propertyName: perspective + -webkit-perspective 10ms fired transitionend with propertyName: perspective
diff --git a/third_party/blink/web_tests/transitions/unprefixed-perspective-origin-expected.txt b/third_party/blink/web_tests/transitions/unprefixed-perspective-origin-expected.txt index 907f1661..aa48e926 100644 --- a/third_party/blink/web_tests/transitions/unprefixed-perspective-origin-expected.txt +++ b/third_party/blink/web_tests/transitions/unprefixed-perspective-origin-expected.txt
@@ -1,15 +1,19 @@ all 10ms fired transitionend with propertyName: perspective-origin + perspective-origin 10ms fired transitionend with propertyName: perspective-origin + -webkit-perspective-origin 10ms fired transitionend with propertyName: perspective-origin + -webkit-perspective-origin-x 10ms fired transitionend with propertyName: -webkit-perspective-origin-x + -webkit-perspective-origin-y 10ms fired transitionend with propertyName: -webkit-perspective-origin-y
diff --git a/third_party/blink/web_tests/transitions/unprefixed-transform-origin-expected.txt b/third_party/blink/web_tests/transitions/unprefixed-transform-origin-expected.txt index 56fa0f20..00ecd1a 100644 --- a/third_party/blink/web_tests/transitions/unprefixed-transform-origin-expected.txt +++ b/third_party/blink/web_tests/transitions/unprefixed-transform-origin-expected.txt
@@ -1,18 +1,23 @@ all 10ms fired transitionend with propertyName: transform-origin + transform-origin 10ms fired transitionend with propertyName: transform-origin + -webkit-transform-origin 10ms fired transitionend with propertyName: transform-origin + -webkit-transform-origin-x 10ms fired transitionend with propertyName: -webkit-transform-origin-x + -webkit-transform-origin-y 10ms fired transitionend with propertyName: -webkit-transform-origin-y + -webkit-transform-origin-z 10ms fired transitionend with propertyName: -webkit-transform-origin-z
diff --git a/third_party/blink/web_tests/traversal/acid3-test-2-expected.txt b/third_party/blink/web_tests/traversal/acid3-test-2-expected.txt index 79aba27..efa1e127 100644 --- a/third_party/blink/web_tests/traversal/acid3-test-2-expected.txt +++ b/third_party/blink/web_tests/traversal/acid3-test-2-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS count is 1 PASS nodea is nodeb PASS count is 2
diff --git a/third_party/blink/web_tests/traversal/exception-forwarding-expected.txt b/third_party/blink/web_tests/traversal/exception-forwarding-expected.txt index 8173f20f..c553540 100644 --- a/third_party/blink/web_tests/traversal/exception-forwarding-expected.txt +++ b/third_party/blink/web_tests/traversal/exception-forwarding-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS i.nextNode() threw exception Roses. PASS i.nextNode() is document.documentElement PASS i.previousNode() threw exception Roses.
diff --git a/third_party/blink/web_tests/traversal/hixie-node-iterator/003-expected.txt b/third_party/blink/web_tests/traversal/hixie-node-iterator/003-expected.txt index 69cfc5a9..7ef22e9 100644 --- a/third_party/blink/web_tests/traversal/hixie-node-iterator/003-expected.txt +++ b/third_party/blink/web_tests/traversal/hixie-node-iterator/003-expected.txt
@@ -1,2 +1 @@ PASS -
diff --git a/third_party/blink/web_tests/traversal/hixie-node-iterator/004-expected.txt b/third_party/blink/web_tests/traversal/hixie-node-iterator/004-expected.txt index 69cfc5a9..7ef22e9 100644 --- a/third_party/blink/web_tests/traversal/hixie-node-iterator/004-expected.txt +++ b/third_party/blink/web_tests/traversal/hixie-node-iterator/004-expected.txt
@@ -1,2 +1 @@ PASS -
diff --git a/third_party/blink/web_tests/traversal/hixie-node-iterator/005-expected.txt b/third_party/blink/web_tests/traversal/hixie-node-iterator/005-expected.txt index 69cfc5a9..7ef22e9 100644 --- a/third_party/blink/web_tests/traversal/hixie-node-iterator/005-expected.txt +++ b/third_party/blink/web_tests/traversal/hixie-node-iterator/005-expected.txt
@@ -1,2 +1 @@ PASS -
diff --git a/third_party/blink/web_tests/traversal/hixie-node-iterator/006-expected.txt b/third_party/blink/web_tests/traversal/hixie-node-iterator/006-expected.txt index 69cfc5a9..7ef22e9 100644 --- a/third_party/blink/web_tests/traversal/hixie-node-iterator/006-expected.txt +++ b/third_party/blink/web_tests/traversal/hixie-node-iterator/006-expected.txt
@@ -1,2 +1 @@ PASS -
diff --git a/third_party/blink/web_tests/traversal/hixie-node-iterator/007-expected.txt b/third_party/blink/web_tests/traversal/hixie-node-iterator/007-expected.txt index 69cfc5a9..7ef22e9 100644 --- a/third_party/blink/web_tests/traversal/hixie-node-iterator/007-expected.txt +++ b/third_party/blink/web_tests/traversal/hixie-node-iterator/007-expected.txt
@@ -1,2 +1 @@ PASS -
diff --git a/third_party/blink/web_tests/traversal/hixie-node-iterator/008-expected.txt b/third_party/blink/web_tests/traversal/hixie-node-iterator/008-expected.txt index 69cfc5a9..7ef22e9 100644 --- a/third_party/blink/web_tests/traversal/hixie-node-iterator/008-expected.txt +++ b/third_party/blink/web_tests/traversal/hixie-node-iterator/008-expected.txt
@@ -1,2 +1 @@ PASS -
diff --git a/third_party/blink/web_tests/traversal/hixie-node-iterator/009-expected.txt b/third_party/blink/web_tests/traversal/hixie-node-iterator/009-expected.txt index 69cfc5a9..7ef22e9 100644 --- a/third_party/blink/web_tests/traversal/hixie-node-iterator/009-expected.txt +++ b/third_party/blink/web_tests/traversal/hixie-node-iterator/009-expected.txt
@@ -1,2 +1 @@ PASS -
diff --git a/third_party/blink/web_tests/traversal/moz-bug559526-expected.txt b/third_party/blink/web_tests/traversal/moz-bug559526-expected.txt index b9b52ff..4231075a 100644 --- a/third_party/blink/web_tests/traversal/moz-bug559526-expected.txt +++ b/third_party/blink/web_tests/traversal/moz-bug559526-expected.txt
@@ -7,3 +7,4 @@ +
diff --git a/third_party/blink/web_tests/traversal/node-iterator-009-expected.txt b/third_party/blink/web_tests/traversal/node-iterator-009-expected.txt index e787f20..e3a85d26 100644 --- a/third_party/blink/web_tests/traversal/node-iterator-009-expected.txt +++ b/third_party/blink/web_tests/traversal/node-iterator-009-expected.txt
@@ -1,25 +1,33 @@ CONSOLE WARNING: line 18: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. XML doc elements: records + Across the Universe 2:30 Not yet rated Sony Pictures 2007-02-15 2007-09-28 movieinfo + Across the Universe 2:30 Not yet rated Sony Pictures 2007-02-15 2007-09-28 info + Across the Universe 2:30 Not yet rated Sony Pictures 2007-02-15 2007-09-28 title + Across the Universe runtime + 2:30 rating + Not yet rated postdate + 2007-02-15 releasedate + 2007-09-28
diff --git a/third_party/blink/web_tests/traversal/tree-walker-001-expected.txt b/third_party/blink/web_tests/traversal/tree-walker-001-expected.txt index fbdfeff..4b2dd0b 100644 --- a/third_party/blink/web_tests/traversal/tree-walker-001-expected.txt +++ b/third_party/blink/web_tests/traversal/tree-walker-001-expected.txt
@@ -1,4 +1,6 @@ - + + + Tree Walker: A A.1
diff --git a/third_party/blink/web_tests/traversal/tree-walker-002-expected.txt b/third_party/blink/web_tests/traversal/tree-walker-002-expected.txt index b0c7d8b..2724ebe 100644 --- a/third_party/blink/web_tests/traversal/tree-walker-002-expected.txt +++ b/third_party/blink/web_tests/traversal/tree-walker-002-expected.txt
@@ -1,4 +1,6 @@ - + + + Tree Walker: B B.1
diff --git a/third_party/blink/web_tests/traversal/tree-walker-003-expected.txt b/third_party/blink/web_tests/traversal/tree-walker-003-expected.txt index 6e44a99..df1a4a4 100644 --- a/third_party/blink/web_tests/traversal/tree-walker-003-expected.txt +++ b/third_party/blink/web_tests/traversal/tree-walker-003-expected.txt
@@ -1,4 +1,6 @@ - + + + Tree Walker: A A.1 @@ -13,6 +15,7 @@ C.2.1 D + Tree Walker: D C.2.1
diff --git a/third_party/blink/web_tests/traversal/tree-walker-004-expected.txt b/third_party/blink/web_tests/traversal/tree-walker-004-expected.txt index bb1fbd6..4dea2e4a 100644 --- a/third_party/blink/web_tests/traversal/tree-walker-004-expected.txt +++ b/third_party/blink/web_tests/traversal/tree-walker-004-expected.txt
@@ -1,4 +1,6 @@ - + + + Tree Walker: A A.1 @@ -20,6 +22,7 @@ C.2.1 D + Tree Walker: D C.2.1
diff --git a/third_party/blink/web_tests/traversal/tree-walker-005-expected.txt b/third_party/blink/web_tests/traversal/tree-walker-005-expected.txt index f26c978..18c3152 100644 --- a/third_party/blink/web_tests/traversal/tree-walker-005-expected.txt +++ b/third_party/blink/web_tests/traversal/tree-walker-005-expected.txt
@@ -1,4 +1,6 @@ - + + + Tree Walker: B B.2
diff --git a/third_party/blink/web_tests/traversal/tree-walker-006-expected.txt b/third_party/blink/web_tests/traversal/tree-walker-006-expected.txt index e787f20..e3a85d26 100644 --- a/third_party/blink/web_tests/traversal/tree-walker-006-expected.txt +++ b/third_party/blink/web_tests/traversal/tree-walker-006-expected.txt
@@ -1,25 +1,33 @@ CONSOLE WARNING: line 18: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. XML doc elements: records + Across the Universe 2:30 Not yet rated Sony Pictures 2007-02-15 2007-09-28 movieinfo + Across the Universe 2:30 Not yet rated Sony Pictures 2007-02-15 2007-09-28 info + Across the Universe 2:30 Not yet rated Sony Pictures 2007-02-15 2007-09-28 title + Across the Universe runtime + 2:30 rating + Not yet rated postdate + 2007-02-15 releasedate + 2007-09-28
diff --git a/third_party/blink/web_tests/vibration/cancel-vibration-during-pattern-vibrating-expected.txt b/third_party/blink/web_tests/vibration/cancel-vibration-during-pattern-vibrating-expected.txt index 15bb9770..bc0efa3 100644 --- a/third_party/blink/web_tests/vibration/cancel-vibration-during-pattern-vibrating-expected.txt +++ b/third_party/blink/web_tests/vibration/cancel-vibration-during-pattern-vibrating-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS internals.isVibrating(navigator) is false PASS internals.isVibrating(navigator) is true PASS internals.isVibrating(navigator) is false
diff --git a/third_party/blink/web_tests/vibration/vibration-detached-no-crash-expected.txt b/third_party/blink/web_tests/vibration/vibration-detached-no-crash-expected.txt index cfe1d7e..7b4736d 100644 --- a/third_party/blink/web_tests/vibration/vibration-detached-no-crash-expected.txt +++ b/third_party/blink/web_tests/vibration/vibration-detached-no-crash-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS w.navigator.vibrate([]) is false PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/vibration/vibration-durations-expected.txt b/third_party/blink/web_tests/vibration/vibration-durations-expected.txt index bf6892f7..06b5585 100644 --- a/third_party/blink/web_tests/vibration/vibration-durations-expected.txt +++ b/third_party/blink/web_tests/vibration/vibration-durations-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS navigator.vibrate([]) is true PASS areArraysEqual(internals.pendingVibrationPattern(navigator), []) is true PASS internals.isVibrating(navigator) is false
diff --git a/third_party/blink/web_tests/vibration/vibration-exceptions-expected.txt b/third_party/blink/web_tests/vibration/vibration-exceptions-expected.txt index 624845e..d72ab3b 100644 --- a/third_party/blink/web_tests/vibration/vibration-exceptions-expected.txt +++ b/third_party/blink/web_tests/vibration/vibration-exceptions-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS navigator.vibrate() threw exception TypeError: Failed to execute 'vibrate' on 'Navigator': 1 argument required, but only 0 present.. PASS navigator.vibrate(1, 2) is true PASS navigator.vibrate([1], [2]) is true
diff --git a/third_party/blink/web_tests/vibration/vibration-patterns-expected.txt b/third_party/blink/web_tests/vibration/vibration-patterns-expected.txt index dddbe1a..5bb8ab3 100644 --- a/third_party/blink/web_tests/vibration/vibration-patterns-expected.txt +++ b/third_party/blink/web_tests/vibration/vibration-patterns-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS navigator.vibrate(newPattern(1, 4)) is true PASS areArraysEqual(internals.pendingVibrationPattern(navigator), newPattern(1, 3)) is true PASS internals.isVibrating(navigator) is true
diff --git a/third_party/blink/web_tests/virtual/android/fullscreen/video-overlay-scroll-expected.txt b/third_party/blink/web_tests/virtual/android/fullscreen/video-overlay-scroll-expected.txt index af4b383..ae2843c 100644 --- a/third_party/blink/web_tests/virtual/android/fullscreen/video-overlay-scroll-expected.txt +++ b/third_party/blink/web_tests/virtual/android/fullscreen/video-overlay-scroll-expected.txt
@@ -1,5 +1,6 @@ EVENT(fullscreenchange) END OF TEST + { "layers": [ {
diff --git a/third_party/blink/web_tests/virtual/blink-gen-property-trees/paint/transparency/README.txt b/third_party/blink/web_tests/virtual/blink-gen-property-trees/paint/transparency/README.txt deleted file mode 100644 index 43c81db..0000000 --- a/third_party/blink/web_tests/virtual/blink-gen-property-trees/paint/transparency/README.txt +++ /dev/null
@@ -1,2 +0,0 @@ -# This suite runs tests with --enable-blink-gen-property-trees -# This is only for test coverage on the CQ. Prefer the flag-specific expectations in flag-specific/enable-blink-gen-property-trees
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/borders/border-image-scale-transform-expected.png b/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/borders/border-image-scale-transform-expected.png deleted file mode 100644 index 96bfcf1..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/borders/border-image-scale-transform-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/repaint/line-flow-with-floats-5-expected.txt b/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/repaint/line-flow-with-floats-5-expected.txt deleted file mode 100644 index 44fe33f6..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/repaint/line-flow-with-floats-5-expected.txt +++ /dev/null
@@ -1,71 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [178, 350, 146, 18], - [162, 350, 146, 18], - [65, 386, 303, 36], - [65, 368, 304, 18], - [49, 368, 321, 54], - [49, 368, 301, 18], - [46, 353, 16, 65], - [8, 332, 418, 234] - ], - "paintInvalidationClients": [ - "InlineTextBox 'other parts of\n'", - "InlineTextBox 'the ground, Alice soon came to the conclusion'", - "RootInlineBox", - "InlineTextBox 'that it was a very\n'", - "InlineTextBox 'difficult game indeed.\n'", - "RootInlineBox", - "InlineTextBox 'The players all played at once without waiting'", - "RootInlineBox", - "InlineTextBox 'for turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting'", - "RootInlineBox", - "InlineTextBox 'for the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '", - "InlineTextBox 'the'", - "RootInlineBox", - "InlineTextBox 'Queen'", - "InlineTextBox ' was in a furious passion, and went\n'", - "InlineTextBox 'stamping'", - "RootInlineBox", - "InlineTextBox 'about, and shouting \u2018Off with his head!\u2019 or \u2018Off with'", - "RootInlineBox", - "InlineTextBox 'her head!\u2019 about once in a minute.\n'", - "RootInlineBox", - "InlineTextBox 'Alice began to feel very uneasy: to be sure, she had not as\n'", - "InlineTextBox 'yet'", - "RootInlineBox", - "InlineTextBox 'had any dispute with the Queen, but she knew that it might'", - "RootInlineBox", - "InlineTextBox 'happen any minute, \u2018and then,\u2019 thought she, \u2018what would'", - "RootInlineBox", - "InlineTextBox 'become of\n'", - "InlineTextBox 'me? They\u2019re dreadfully fond of beheading people'", - "RootInlineBox", - "InlineTextBox 'here; the great\n'", - "InlineTextBox 'wonder is, that there\u2018s any one left alive!\u2019'", - "RootInlineBox", - "LayoutBlockFlow P", - "LayoutBlockFlow (floating) SPAN id='blueFloat'", - "LayoutText #text", - "InlineTextBox 'difficult game indeed.\n'", - "LayoutText #text", - "InlineTextBox 'The players all played at once without waiting\n'", - "LayoutText #text", - "InlineTextBox 'for'", - "InlineTextBox 'turns,\n'", - "InlineTextBox 'quarrelling all the while, and fighting for'", - "InlineTextBox 'the hedgehogs; and in\n'", - "InlineTextBox 'a very short time '" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/repaint/outline-change-continuations-expected.txt b/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/repaint/outline-change-continuations-expected.txt deleted file mode 100644 index 522c9378..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/repaint/outline-change-continuations-expected.txt +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [6, 86, 88, 24], - [6, 86, 88, 24], - [6, 86, 86, 4] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'", - "LayoutText #text", - "LayoutBlockFlow (anonymous)", - "LayoutInline SPAN id='outer'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/repaint/positioned-document-element-expected.txt b/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/repaint/positioned-document-element-expected.txt deleted file mode 100644 index 996a18d..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/repaint/positioned-document-element-expected.txt +++ /dev/null
@@ -1,33 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "backgroundColor": "#008000", - "repaintRects": [ - [108, 116, 437, 18], - [108, 116, 437, 18], - [108, 116, 437, 18], - [100, 100, 453, 50], - [8, 16, 784, 18], - [8, 16, 784, 18], - [8, 16, 437, 18], - [0, 0, 800, 600], - [0, 0, 800, 50] - ], - "paintInvalidationClients": [ - "RootInlineBox", - "InlineTextBox 'Tests that the entire viewport is painted with a floated html element.'", - "LayoutView #document", - "LayoutBlockFlow (positioned) HTML class='changed'", - "LayoutBlockFlow BODY", - "LayoutBlockFlow P", - "LayoutText #text", - "InlineTextBox 'Tests that the entire viewport is painted with a floated html element.'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/repaint/transform-translate-expected.txt b/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/repaint/transform-translate-expected.txt deleted file mode 100644 index 403f85e1..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/repaint/transform-translate-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [28, 66, 106, 107], - [8, 66, 106, 107] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow DIV id='target'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/repaint/window-resize-percent-html-expected.txt b/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/repaint/window-resize-percent-html-expected.txt deleted file mode 100644 index 33d49e64..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/fast/repaint/window-resize-percent-html-expected.txt +++ /dev/null
@@ -1,91 +0,0 @@ -{ - "bounds": [200, 300], - "children": [ - { - "bounds": [200, 300], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [0, 200, 200, 100], - [0, 50, 100, 25], - [0, 0, 200, 150], - [0, 0, 200, 100] - ], - "paintInvalidationClients": [ - "VerticalScrollbar", - "LayoutView #document", - "LayoutBlockFlow HTML", - "LayoutBlockFlow DIV" - ] - } - ] -} -{ - "bounds": [300, 300], - "children": [ - { - "bounds": [300, 300], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [200, 0, 100, 300], - [100, 0, 50, 75], - [0, 0, 300, 300], - [0, 0, 300, 150], - [0, 0, 200, 150] - ], - "paintInvalidationClients": [ - "HorizontalScrollbar", - "LayoutView #document", - "LayoutView #document", - "LayoutBlockFlow HTML", - "LayoutBlockFlow DIV" - ] - } - ] -} -{ - "bounds": [300, 250], - "children": [ - { - "bounds": [300, 250], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [0, 250, 300, 50], - [0, 62, 150, 13], - [0, 0, 300, 150], - [0, 0, 300, 125] - ], - "paintInvalidationClients": [ - "LayoutView #document", - "LayoutBlockFlow HTML", - "LayoutBlockFlow DIV" - ] - } - ] -} -{ - "bounds": [250, 250], - "children": [ - { - "bounds": [250, 250], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [250, 0, 50, 250], - [125, 0, 25, 63], - [0, 0, 300, 125], - [0, 0, 250, 250], - [0, 0, 250, 125] - ], - "paintInvalidationClients": [ - "LayoutView #document", - "LayoutView #document", - "LayoutBlockFlow HTML", - "LayoutBlockFlow DIV" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/invalidate-descendants-when-receiving-paint-layer-expected.txt b/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/invalidate-descendants-when-receiving-paint-layer-expected.txt deleted file mode 100644 index 886f9f6..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/invalidate-descendants-when-receiving-paint-layer-expected.txt +++ /dev/null
@@ -1,21 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "repaintRects": [ - [9, 9, 100, 100], - [9, 9, 100, 100], - [8, 60, 784, 49] - ], - "paintInvalidationClients": [ - "LayoutBlockFlow (relative positioned) DIV", - "LayoutBlockFlow DIV id='target'", - "LayoutBlockFlow DIV id='child'" - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/spv2/background-resize-height-expected.png b/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/spv2/background-resize-height-expected.png deleted file mode 100644 index 60a5dfb..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/spv2/background-resize-height-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/spv2/background-resize-width-expected.png b/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/spv2/background-resize-width-expected.png deleted file mode 100644 index a4955fa7a..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/spv2/background-resize-width-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/spv2/percent-size-image-resize-container-expected.txt b/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/spv2/percent-size-image-resize-container-expected.txt deleted file mode 100644 index 62109bb..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/spv2/percent-size-image-resize-container-expected.txt +++ /dev/null
@@ -1,2 +0,0 @@ -["LayoutBlockFlow (positioned) DIV", - "LayoutImage (positioned) IMG"]
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/spv2/selection-change-in-iframe-with-relative-parent-expected.txt b/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/spv2/selection-change-in-iframe-with-relative-parent-expected.txt deleted file mode 100644 index 02078a3..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/spv2/selection-change-in-iframe-with-relative-parent-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -["LayoutBlockFlow HTML", - "LayoutBlockFlow BODY", - "LayoutText #text", - "InlineTextBox 'Foo'", - "LayoutBR BR", - "InlineTextBox '\n'", - "LayoutBR BR", - "InlineTextBox '\n'", - "LayoutText #text", - "InlineTextBox 'Bar'", - "LayoutBR BR", - "InlineTextBox '\n'", - "LayoutBR BR", - "InlineTextBox '\n'", - "LayoutText #text", - "InlineTextBox 'Bazz'", - "LayoutBR BR", - "InlineTextBox '\n'"]
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/spv2/selection-within-composited-scroller-expected.txt b/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/spv2/selection-within-composited-scroller-expected.txt deleted file mode 100644 index 522cd4d..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/paint/invalidation/spv2/selection-within-composited-scroller-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -["LayoutBlockFlow HTML", - "LayoutBlockFlow BODY", - "LayoutBlockFlow DIV id='scroller'", - "LayoutBlockFlow DIV id='target'", - "LayoutText #text", - "InlineTextBox 'test'"]
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/svg/custom/object-sizing-explicit-height-expected.png b/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/svg/custom/object-sizing-explicit-height-expected.png deleted file mode 100644 index 5f034aa1..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/svg/custom/object-sizing-explicit-height-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/svg/custom/object-sizing-no-width-height-change-content-box-size-expected.txt b/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/svg/custom/object-sizing-no-width-height-change-content-box-size-expected.txt deleted file mode 100644 index aa5b612..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/composite-after-paint/svg/custom/object-sizing-no-width-height-change-content-box-size-expected.txt +++ /dev/null
@@ -1,65 +0,0 @@ -{ - "bounds": [800, 600], - "children": [ - { - "bounds": [800, 600], - "contentsOpaque": true, - "drawsContent": true, - "paintInvalidations": [ - { - "object": "LayoutBlockFlow div id='contentBox'", - "rect": [8, 8, 402, 402], - "reason": "forced by layout" - }, - { - "object": "LayoutSVGRect rect", - "rect": [9, 9, 400, 400], - "reason": "forced by layout" - }, - { - "object": "LayoutSVGRoot svg", - "rect": [9, 9, 400, 400], - "reason": "forced by layout" - }, - { - "object": "LayoutView #document", - "rect": [9, 9, 400, 400], - "reason": "full" - }, - { - "object": "LayoutEmbeddedObject object", - "rect": [209, 9, 200, 400], - "reason": "incremental" - }, - { - "object": "LayoutView #document", - "rect": [209, 9, 200, 400], - "reason": "incremental" - }, - { - "object": "LayoutSVGEllipse circle", - "rect": [169, 169, 80, 80], - "reason": "forced by layout" - }, - { - "object": "LayoutSVGEllipse circle", - "rect": [89, 189, 40, 40], - "reason": "forced by layout" - }, - { - "object": "InlineBox", - "reason": "full" - }, - { - "object": "RootInlineBox", - "reason": "full" - }, - { - "object": "RootInlineBox", - "reason": "full" - } - ] - } - ] -} -
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/compositing/README.txt b/third_party/blink/web_tests/virtual/composite-after-paint/compositing/README.txt index 488f68c..fbb282b 100644 --- a/third_party/blink/web_tests/virtual/composite-after-paint/compositing/README.txt +++ b/third_party/blink/web_tests/virtual/composite-after-paint/compositing/README.txt
@@ -1,3 +1 @@ # This suite runs tests with --enable-blink-features=CompositeAfterPaint -# We also have try bots running full set of layout tests for spv2: -# https://codereview.chromium.org/1283823002
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/fast/block/README.txt b/third_party/blink/web_tests/virtual/composite-after-paint/fast/block/README.txt deleted file mode 100644 index 488f68c..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/fast/block/README.txt +++ /dev/null
@@ -1,3 +0,0 @@ -# This suite runs tests with --enable-blink-features=CompositeAfterPaint -# We also have try bots running full set of layout tests for spv2: -# https://codereview.chromium.org/1283823002
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/fast/borders/README.txt b/third_party/blink/web_tests/virtual/composite-after-paint/fast/borders/README.txt deleted file mode 100644 index 488f68c..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/fast/borders/README.txt +++ /dev/null
@@ -1,3 +0,0 @@ -# This suite runs tests with --enable-blink-features=CompositeAfterPaint -# We also have try bots running full set of layout tests for spv2: -# https://codereview.chromium.org/1283823002
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/fast/clip/README.txt b/third_party/blink/web_tests/virtual/composite-after-paint/fast/clip/README.txt deleted file mode 100644 index 488f68c..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/fast/clip/README.txt +++ /dev/null
@@ -1,3 +0,0 @@ -# This suite runs tests with --enable-blink-features=CompositeAfterPaint -# We also have try bots running full set of layout tests for spv2: -# https://codereview.chromium.org/1283823002
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/fast/css/README.txt b/third_party/blink/web_tests/virtual/composite-after-paint/fast/css/README.txt deleted file mode 100644 index 488f68c..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/fast/css/README.txt +++ /dev/null
@@ -1,3 +0,0 @@ -# This suite runs tests with --enable-blink-features=CompositeAfterPaint -# We also have try bots running full set of layout tests for spv2: -# https://codereview.chromium.org/1283823002
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/fast/overflow/README.txt b/third_party/blink/web_tests/virtual/composite-after-paint/fast/overflow/README.txt deleted file mode 100644 index 488f68c..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/fast/overflow/README.txt +++ /dev/null
@@ -1,3 +0,0 @@ -# This suite runs tests with --enable-blink-features=CompositeAfterPaint -# We also have try bots running full set of layout tests for spv2: -# https://codereview.chromium.org/1283823002
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/fast/repaint/README.txt b/third_party/blink/web_tests/virtual/composite-after-paint/fast/repaint/README.txt deleted file mode 100644 index 488f68c..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/fast/repaint/README.txt +++ /dev/null
@@ -1,3 +0,0 @@ -# This suite runs tests with --enable-blink-features=CompositeAfterPaint -# We also have try bots running full set of layout tests for spv2: -# https://codereview.chromium.org/1283823002
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/paint/README.txt b/third_party/blink/web_tests/virtual/composite-after-paint/paint/README.txt index 488f68c..fbb282b 100644 --- a/third_party/blink/web_tests/virtual/composite-after-paint/paint/README.txt +++ b/third_party/blink/web_tests/virtual/composite-after-paint/paint/README.txt
@@ -1,3 +1 @@ # This suite runs tests with --enable-blink-features=CompositeAfterPaint -# We also have try bots running full set of layout tests for spv2: -# https://codereview.chromium.org/1283823002
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/paint/subpixel/README.txt b/third_party/blink/web_tests/virtual/composite-after-paint/paint/subpixel/README.txt deleted file mode 100644 index 488f68c..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/paint/subpixel/README.txt +++ /dev/null
@@ -1,3 +0,0 @@ -# This suite runs tests with --enable-blink-features=CompositeAfterPaint -# We also have try bots running full set of layout tests for spv2: -# https://codereview.chromium.org/1283823002
diff --git a/third_party/blink/web_tests/virtual/composite-after-paint/svg/README.txt b/third_party/blink/web_tests/virtual/composite-after-paint/svg/README.txt deleted file mode 100644 index 488f68c..0000000 --- a/third_party/blink/web_tests/virtual/composite-after-paint/svg/README.txt +++ /dev/null
@@ -1,3 +0,0 @@ -# This suite runs tests with --enable-blink-features=CompositeAfterPaint -# We also have try bots running full set of layout tests for spv2: -# https://codereview.chromium.org/1283823002
diff --git a/third_party/blink/web_tests/virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/README.txt b/third_party/blink/web_tests/virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/README.txt new file mode 100644 index 0000000..3fadfb4 --- /dev/null +++ b/third_party/blink/web_tests/virtual/disabled-service-worker-servicification/external/wpt/service-workers/service-worker/README.txt
@@ -0,0 +1,2 @@ +This directory is for testing the case where ServiceWorkerServicification (aka NetS13nServiceWorker) and NetworkService are off. +The tracking bug is crbug.com/846235.
diff --git a/third_party/blink/web_tests/virtual/disabled-service-worker-servicification/http/tests/serviceworker/README.txt b/third_party/blink/web_tests/virtual/disabled-service-worker-servicification/http/tests/serviceworker/README.txt new file mode 100644 index 0000000..3fadfb4 --- /dev/null +++ b/third_party/blink/web_tests/virtual/disabled-service-worker-servicification/http/tests/serviceworker/README.txt
@@ -0,0 +1,2 @@ +This directory is for testing the case where ServiceWorkerServicification (aka NetS13nServiceWorker) and NetworkService are off. +The tracking bug is crbug.com/846235.
diff --git a/third_party/blink/web_tests/virtual/feature-policy-vibrate/http/tests/feature-policy-vibrate/README.txt b/third_party/blink/web_tests/virtual/feature-policy-vibrate/http/tests/feature-policy-vibrate/README.txt deleted file mode 100644 index 4bd38b26..0000000 --- a/third_party/blink/web_tests/virtual/feature-policy-vibrate/http/tests/feature-policy-vibrate/README.txt +++ /dev/null
@@ -1 +0,0 @@ -Tests which run under the FeaturePolicyVibrateFeature flag
diff --git a/third_party/blink/web_tests/virtual/feature-policy-vibrate/http/tests/feature-policy-vibrate/vibrate-allowed-by-container-policy-relocate-and-no-reload-expected.txt b/third_party/blink/web_tests/virtual/feature-policy-vibrate/http/tests/feature-policy-vibrate/vibrate-allowed-by-container-policy-relocate-and-no-reload-expected.txt deleted file mode 100644 index 7954d1fa..0000000 --- a/third_party/blink/web_tests/virtual/feature-policy-vibrate/http/tests/feature-policy-vibrate/vibrate-allowed-by-container-policy-relocate-and-no-reload-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -CONSOLE ERROR: line 15: Navigator.vibrate() is not enabled in feature policy for this frame. -This is a testharness.js-based test. -PASS Iframe navigated itself to a new origin, vibrate is disabled by container policy. -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/feature-policy-vibrate/http/tests/feature-policy-vibrate/vibrate-disabled-expected.txt b/third_party/blink/web_tests/virtual/feature-policy-vibrate/http/tests/feature-policy-vibrate/vibrate-disabled-expected.txt deleted file mode 100644 index 7d7b11d7..0000000 --- a/third_party/blink/web_tests/virtual/feature-policy-vibrate/http/tests/feature-policy-vibrate/vibrate-disabled-expected.txt +++ /dev/null
@@ -1,7 +0,0 @@ -CONSOLE ERROR: line 15: Navigator.vibrate() is not enabled in feature policy for this frame. -CONSOLE ERROR: line 15: Navigator.vibrate() is not enabled in feature policy for this frame. -This is a testharness.js-based test. -PASS Navigator.vibrate disabled on URL: resources/feature-policy-vibrate.html -PASS Navigator.vibrate disabled on URL: http://localhost:8000/feature-policy-vibrate/resources/feature-policy-vibrate.html -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/feature-policy-vibrate/http/tests/feature-policy-vibrate/vibrate-enabledforself-expected.txt b/third_party/blink/web_tests/virtual/feature-policy-vibrate/http/tests/feature-policy-vibrate/vibrate-enabledforself-expected.txt deleted file mode 100644 index ee754a3..0000000 --- a/third_party/blink/web_tests/virtual/feature-policy-vibrate/http/tests/feature-policy-vibrate/vibrate-enabledforself-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -CONSOLE ERROR: line 15: Navigator.vibrate() is not enabled in feature policy for this frame. -This is a testharness.js-based test. -PASS Navigator.vibrate enabled for self on URL: resources/feature-policy-vibrate.html -PASS Navigator.vibrate enabled for self on URL: http://localhost:8000/feature-policy-vibrate/resources/feature-policy-vibrate.html -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/README.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/README.txt new file mode 100644 index 0000000..902eb3c2 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/README.txt
@@ -0,0 +1 @@ +# This suite runs tests with --disable-blink-features=BlinkGenPropertyTrees
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png new file mode 100644 index 0000000..446aa85 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/composited-scaled-child-with-border-radius-parent-clip-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png new file mode 100644 index 0000000..5393c95 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/composited-translated-child-with-border-radius-parent-clip-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/direct-image-compositing-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/direct-image-compositing-expected.png new file mode 100644 index 0000000..bb3c623 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/direct-image-compositing-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/fixed-body-background-positioned-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/fixed-body-background-positioned-expected.txt new file mode 100644 index 0000000..a9d5368 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/fixed-body-background-positioned-expected.txt
@@ -0,0 +1,68 @@ +{ + "layers": [ + { + "name": "Root Transform Layer", + "drawsContent": false + }, + { + "name": "Inner Viewport Container Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Overscroll Elasticity Layer", + "drawsContent": false + }, + { + "name": "Page Scale Layer", + "drawsContent": false + }, + { + "name": "Inner Viewport Scroll Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "LayoutView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [785, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [785, 3700], + "backgroundColor": "#FFFFFF", + "transform": 1 + }, + { + "name": "Overflow Controls Host Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Vertical Scrollbar Layer", + "position": [785, 0], + "bounds": [15, 600], + "contentsOpaque": true, + "drawsContent": false + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, -200, 0, 1] + ], + "flattenInheritedTransform": false + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/geometry/clip-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/geometry/clip-expected.txt new file mode 100644 index 0000000..100aca1 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/geometry/clip-expected.txt
@@ -0,0 +1,84 @@ +Test CSS clip with composited layers. Left and right sides should look the same. + +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='composited box'", + "bounds": [110, 110], + "backgroundColor": "#808080", + "transform": 2 + }, + { + "name": "Ancestor Clipping Layer", + "position": [215, 15], + "bounds": [110, 110], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='composited inner'", + "bounds": [120, 120], + "backgroundColor": "#00000033", + "transform": 4 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [15, 15, 0, 1] + ] + }, + { + "id": 2, + "parent": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ] + }, + { + "id": 3, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [210, 10, 0, 1] + ], + "flattenInheritedTransform": false + }, + { + "id": 4, + "parent": 3, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ], + "flattenInheritedTransform": false + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/geometry/clip-inside-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/geometry/clip-inside-expected.txt new file mode 100644 index 0000000..3566aba2 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/geometry/clip-inside-expected.txt
@@ -0,0 +1,85 @@ +Test CSS clip with composited layers. Left and right sides should look the same. + +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='composited box'", + "bounds": [90, 80], + "contentsOpaque": true, + "backgroundColor": "#808080", + "transform": 2 + }, + { + "name": "Ancestor Clipping Layer", + "position": [225, 35], + "bounds": [90, 80], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='composited inner'", + "bounds": [120, 120], + "backgroundColor": "#00000033", + "transform": 4 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [25, 35, 0, 1] + ] + }, + { + "id": 2, + "parent": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ] + }, + { + "id": 3, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [210, 10, 0, 1] + ], + "flattenInheritedTransform": false + }, + { + "id": 4, + "parent": 3, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ], + "flattenInheritedTransform": false + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/geometry/clip-with-shadow-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/geometry/clip-with-shadow-expected.txt new file mode 100644 index 0000000..3a44c3e --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/geometry/clip-with-shadow-expected.txt
@@ -0,0 +1,82 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='composited box'", + "bounds": [110, 110], + "backgroundColor": "#808080", + "transform": 2 + }, + { + "name": "Ancestor Clipping Layer", + "position": [215, 15], + "bounds": [110, 110], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='composited inner'", + "bounds": [120, 120], + "backgroundColor": "#00000033", + "transform": 4 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [15, 15, 0, 1] + ] + }, + { + "id": 2, + "parent": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ] + }, + { + "id": 3, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [210, 10, 0, 1] + ], + "flattenInheritedTransform": false + }, + { + "id": 4, + "parent": 3, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ], + "flattenInheritedTransform": false + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/geometry/foreground-layer-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/geometry/foreground-layer-expected.txt new file mode 100644 index 0000000..1617299 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/geometry/foreground-layer-expected.txt
@@ -0,0 +1,125 @@ + +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='main box'", + "bounds": [318, 318], + "backgroundColor": "#FF0000", + "transform": 1 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='negative child'", + "bounds": [50, 50], + "drawsContent": false, + "transform": 3 + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='main box' (foreground) Layer", + "bounds": [318, 318], + "transform": 1 + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='main box'", + "bounds": [318, 318], + "backgroundColor": "#FF0000", + "transform": 4 + }, + { + "name": "Child Containment Layer", + "position": [59, 59], + "bounds": [200, 200], + "drawsContent": false, + "transform": 4 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='negative child'", + "bounds": [50, 50], + "drawsContent": false, + "transform": 6 + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='main box' (foreground) Layer", + "position": [59, 59], + "bounds": [200, 200], + "transform": 4 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [19, 89, 0, 1] + ] + }, + { + "id": 2, + "parent": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [59, 59, 0, 1] + ] + }, + { + "id": 3, + "parent": 2, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ] + }, + { + "id": 4, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [363, 19, 0, 1] + ] + }, + { + "id": 5, + "parent": 4, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [59, 59, 0, 1] + ] + }, + { + "id": 6, + "parent": 5, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/geometry/layer-due-to-layer-children-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/geometry/layer-due-to-layer-children-expected.png new file mode 100644 index 0000000..59e62676 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/geometry/layer-due-to-layer-children-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/iframes/become-composited-nested-iframes-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/iframes/become-composited-nested-iframes-expected.txt new file mode 100644 index 0000000..2021656 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/iframes/become-composited-nested-iframes-expected.txt
@@ -0,0 +1,128 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [785, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [785, 1500], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutIFrame IFRAME", + "position": [20, 120], + "bounds": [284, 204] + }, + { + "name": "LayoutView #document", + "position": [22, 122], + "bounds": [280, 200] + }, + { + "name": "Child Containment Layer", + "position": [22, 122], + "bounds": [280, 200], + "drawsContent": false + }, + { + "name": "LayoutIFrame IFRAME", + "position": [30, 130], + "bounds": [252, 172] + }, + { + "name": "LayoutView #document", + "position": [31, 131], + "bounds": [250, 170], + "backgroundColor": "#C0C0C0" + }, + { + "name": "Child Containment Layer", + "position": [31, 131], + "bounds": [250, 170], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV id='iframe-content' class='box'", + "bounds": [210, 210], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "transform": 1 + }, + { + "name": "LayoutIFrame IFRAME", + "position": [20, 344], + "bounds": [284, 204] + }, + { + "name": "LayoutView #document", + "position": [22, 346], + "bounds": [280, 200] + }, + { + "name": "Child Containment Layer", + "position": [22, 346], + "bounds": [280, 200], + "drawsContent": false + }, + { + "name": "LayoutIFrame IFRAME", + "position": [30, 354], + "bounds": [252, 172] + }, + { + "name": "LayoutView #document", + "position": [31, 355], + "bounds": [250, 170], + "backgroundColor": "#C0C0C0" + }, + { + "name": "Child Containment Layer", + "position": [31, 355], + "bounds": [250, 170], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV id='iframe-content' class='box'", + "bounds": [210, 210], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "transform": 2 + }, + { + "name": "LayoutBlockFlow DIV id='box' class='composited'", + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#0000FF" + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [49, 141, 0, 1] + ] + }, + { + "id": 2, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [49, 365, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/iframes/invisible-nested-iframe-show-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/iframes/invisible-nested-iframe-show-expected.txt new file mode 100644 index 0000000..392b2cc1 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/iframes/invisible-nested-iframe-show-expected.txt
@@ -0,0 +1,117 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutIFrame IFRAME", + "position": [-11, -11], + "bounds": [368, 218] + }, + { + "name": "LayoutView #document", + "position": [23, 23], + "bounds": [300, 150], + "drawsContent": false + }, + { + "name": "Scrolling Layer", + "position": [23, 23], + "bounds": [285, 150], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "position": [23, 23], + "bounds": [285, 193] + }, + { + "name": "LayoutIFrame IFRAME", + "position": [31, 31], + "bounds": [252, 172] + }, + { + "name": "LayoutView #document", + "position": [32, 32], + "bounds": [250, 170], + "backgroundColor": "#C0C0C0" + }, + { + "name": "Child Containment Layer", + "position": [32, 32], + "bounds": [250, 170], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV id='iframe-content' class='box'", + "bounds": [210, 210], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "transform": 1 + }, + { + "name": "Overflow Controls Host Layer", + "position": [23, 23], + "bounds": [300, 150], + "drawsContent": false + }, + { + "name": "Vertical Scrollbar Layer", + "position": [308, 23], + "bounds": [15, 150], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV class='box'", + "bounds": [210, 210], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "transform": 3 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [50, 42, 0, 1] + ] + }, + { + "id": 2, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [18, 203, 0, 1] + ] + }, + { + "id": 3, + "parent": 2, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/iframes/overlapped-iframe-iframe-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/iframes/overlapped-iframe-iframe-expected.txt new file mode 100644 index 0000000..c3c1d6f8 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/iframes/overlapped-iframe-iframe-expected.txt
@@ -0,0 +1,61 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutIFrame (positioned) IFRAME", + "bounds": [304, 304] + }, + { + "name": "LayoutView #document", + "position": [2, 2], + "bounds": [300, 300], + "backgroundColor": "#C0C0C0" + }, + { + "name": "Child Containment Layer", + "position": [2, 2], + "bounds": [300, 300], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV id='iframe-content' class='box'", + "bounds": [210, 210], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "transform": 1 + }, + { + "name": "LayoutIFrame (positioned) IFRAME id='overlap'", + "position": [250, 0], + "bounds": [304, 304] + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [20, 12, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/iframes/overlapped-nested-iframes-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/iframes/overlapped-nested-iframes-expected.txt new file mode 100644 index 0000000..368814d --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/iframes/overlapped-nested-iframes-expected.txt
@@ -0,0 +1,154 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [785, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [785, 1650], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "transform": 1 + }, + { + "name": "LayoutIFrame IFRAME", + "position": [20, 150], + "bounds": [284, 204], + "transform": 1 + }, + { + "name": "LayoutView #document", + "position": [22, 152], + "bounds": [280, 200], + "transform": 1 + }, + { + "name": "Child Containment Layer", + "position": [22, 152], + "bounds": [280, 200], + "drawsContent": false, + "transform": 1 + }, + { + "name": "LayoutIFrame IFRAME", + "position": [30, 160], + "bounds": [252, 172], + "transform": 1 + }, + { + "name": "LayoutView #document", + "position": [31, 161], + "bounds": [250, 170], + "backgroundColor": "#C0C0C0", + "transform": 1 + }, + { + "name": "Child Containment Layer", + "position": [31, 161], + "bounds": [250, 170], + "drawsContent": false, + "transform": 1 + }, + { + "name": "LayoutBlockFlow DIV id='iframe-content' class='box'", + "bounds": [210, 210], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "transform": 2 + }, + { + "name": "LayoutIFrame IFRAME", + "position": [20, 374], + "bounds": [284, 204], + "transform": 1 + }, + { + "name": "LayoutView #document", + "position": [22, 376], + "bounds": [280, 200], + "transform": 1 + }, + { + "name": "Child Containment Layer", + "position": [22, 376], + "bounds": [280, 200], + "drawsContent": false, + "transform": 1 + }, + { + "name": "LayoutIFrame IFRAME", + "position": [30, 384], + "bounds": [252, 172], + "transform": 1 + }, + { + "name": "LayoutView #document", + "position": [31, 385], + "bounds": [250, 170], + "backgroundColor": "#C0C0C0", + "transform": 1 + }, + { + "name": "Child Containment Layer", + "position": [31, 385], + "bounds": [250, 170], + "drawsContent": false, + "transform": 1 + }, + { + "name": "LayoutBlockFlow DIV id='iframe-content' class='box'", + "bounds": [210, 210], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "transform": 3 + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='banner'", + "position": [0, 100], + "bounds": [785, 120], + "backgroundColor": "#00000080", + "transform": 1 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, -100, 0, 1] + ], + "flattenInheritedTransform": false + }, + { + "id": 2, + "parent": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [49, 171, 0, 1] + ] + }, + { + "id": 3, + "parent": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [49, 395, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overflow-scroll-overlap-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overflow-scroll-overlap-expected.txt new file mode 100644 index 0000000..0bc9060 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overflow-scroll-overlap-expected.txt
@@ -0,0 +1,67 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Squashing Containment Layer", + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV class='composited'", + "bounds": [30, 30], + "drawsContent": false, + "transform": 1 + }, + { + "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='scroller' class='overflow')", + "position": [20, 20], + "bounds": [306, 206] + }, + { + "name": "Ancestor Clipping Layer", + "position": [23, 23], + "bounds": [285, 200], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='box'", + "position": [43, 29], + "bounds": [200, 100], + "contentsOpaque": true, + "backgroundColor": "#0000FF" + }, + { + "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV class='box')", + "position": [43, 184], + "bounds": [210, 100] + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 8, 0, 1] + ], + "flattenInheritedTransform": false + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overlap-animation-clipping-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overlap-animation-clipping-expected.txt new file mode 100644 index 0000000..1d920582 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overlap-animation-clipping-expected.txt
@@ -0,0 +1,129 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [785, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [785, 812], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV id='to-animate1' class='box animating1'", + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "transform": 2 + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='container'", + "position": [58, 230], + "bounds": [122, 462], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Child Containment Layer", + "position": [59, 231], + "bounds": [120, 460], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='box gray force-layer'", + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#808080", + "transform": 4 + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV id='to-animate2' class='box animating2'", + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "transform": 6 + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='box yellow'", + "position": [69, 571], + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#FFFF00" + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='box yellow'", + "position": [18, 702], + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#FFFF00" + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [...], + [...], + [...], + [...] + ] + }, + { + "id": 2, + "parent": 1, + "transform": [ + [...], + [...], + [...], + [...] + ] + }, + { + "id": 3, + "transform": [ + [...], + [...], + [...], + [...] + ] + }, + { + "id": 4, + "parent": 3, + "transform": [ + [...], + [...], + [...], + [...] + ] + }, + { + "id": 5, + "transform": [ + [...], + [...], + [...], + [...] + ] + }, + { + "id": 6, + "parent": 5, + "transform": [ + [...], + [...], + [...], + [...] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overlap-animation-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overlap-animation-expected.txt new file mode 100644 index 0000000..0f1c74b --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overlap-animation-expected.txt
@@ -0,0 +1,69 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='container'", + "position": [8, 8], + "bounds": [122, 242] + }, + { + "name": "Child Containment Layer", + "position": [9, 9], + "bounds": [120, 240], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV id='to-animate' class='animating box'", + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "transform": 2 + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='box'", + "position": [19, 129], + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#0000FF" + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [...], + [...], + [...], + [...] + ] + }, + { + "id": 2, + "parent": 1, + "transform": [ + [...], + [...], + [...], + [...] + ], + "origin": [50, 50] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overlap-clipping-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overlap-clipping-expected.txt new file mode 100644 index 0000000..f2c359c09 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overlap-clipping-expected.txt
@@ -0,0 +1,73 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Ancestor Clipping Layer", + "position": [50, 50], + "bounds": [100, 100], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV id='child'", + "bounds": [500, 100], + "contentsOpaque": true, + "backgroundColor": "#008000", + "transform": 1 + }, + { + "name": "Squashing Containment Layer", + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV id='child'", + "bounds": [500, 100], + "contentsOpaque": true, + "backgroundColor": "#008000", + "transform": 2 + }, + { + "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='overlap')", + "position": [450, 200], + "bounds": [100, 100] + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [50, 50, 0, 1] + ], + "flattenInheritedTransform": false + }, + { + "id": 2, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [50, 200, 0, 1] + ], + "flattenInheritedTransform": false + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt new file mode 100644 index 0000000..7f07d31 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overlap-transformed-and-clipped-expected.txt
@@ -0,0 +1,61 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='container clips'", + "bounds": [100, 100], + "transform": 1 + }, + { + "name": "Child Containment Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 1 + }, + { + "name": "Squashing Containment Layer", + "drawsContent": false, + "transform": 1 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='under composited'", + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#FF0000", + "transform": 1 + }, + { + "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV class='over')", + "bounds": [100, 100], + "transform": 1 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [110, 0, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overlap-transforms-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overlap-transforms-expected.txt new file mode 100644 index 0000000..6d2c9d99 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/overlap-transforms-expected.txt
@@ -0,0 +1,61 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='container'", + "position": [8, 8], + "bounds": [122, 242] + }, + { + "name": "Child Containment Layer", + "position": [9, 9], + "bounds": [120, 240], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='transformed box'", + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "transform": 2 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [19, 19, 0, 1] + ] + }, + { + "id": 2, + "parent": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt new file mode 100644 index 0000000..623ad00 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change-expected.txt
@@ -0,0 +1,52 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Ancestor Clipping Layer", + "position": [8, 8], + "bounds": [100, 100], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV id='composited'", + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#FA8072", + "transform": 1 + }, + { + "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV id='squashed')", + "position": [8, 58], + "bounds": [100, 100] + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 58, 0, 1] + ], + "flattenInheritedTransform": false + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-tree-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-tree-expected.txt new file mode 100644 index 0000000..18acd2b --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/layer-tree-expected.txt
@@ -0,0 +1,146 @@ +Layer tree: +{ + "name": "Root Transform Layer", + "drawsContent": false, + "children": [ + { + "name": "Inner Viewport Container Layer", + "bounds": [800, 600], + "drawsContent": false, + "children": [ + { + "name": "Overscroll Elasticity Layer", + "drawsContent": false, + "children": [ + { + "name": "Page Scale Layer", + "drawsContent": false, + "children": [ + { + "name": "Inner Viewport Scroll Layer", + "bounds": [800, 600], + "drawsContent": false, + "children": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF", + "shouldFlattenTransform": false, + "children": [ + { + "name": "Scrolling Layer", + "bounds": [780, 580], + "drawsContent": false, + "flattenInheritedTransform": false, + "shouldFlattenTransform": false, + "children": [ + { + "name": "Scrolling Contents Layer", + "bounds": [1200, 900], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "flattenInheritedTransform": false + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "name": "Overflow Controls Host Layer", + "bounds": [800, 600], + "drawsContent": false, + "children": [ + { + "name": "Horizontal Scrollbar Layer", + "position": [0, 580], + "bounds": [780, 20] + }, + { + "name": "Vertical Scrollbar Layer", + "position": [780, 0], + "bounds": [20, 580] + }, + { + "name": "Scroll Corner Layer", + "position": [780, 580], + "bounds": [20, 20] + } + ] + } + ] + } + ] +} + +Layer list +{ + "layers": [ + { + "name": "Root Transform Layer", + "drawsContent": false + }, + { + "name": "Inner Viewport Container Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Overscroll Elasticity Layer", + "drawsContent": false + }, + { + "name": "Page Scale Layer", + "drawsContent": false + }, + { + "name": "Inner Viewport Scroll Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [780, 580], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [1200, 900], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Overflow Controls Host Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Horizontal Scrollbar Layer", + "position": [0, 580], + "bounds": [780, 20] + }, + { + "name": "Vertical Scrollbar Layer", + "position": [780, 0], + "bounds": [20, 580] + }, + { + "name": "Scroll Corner Layer", + "position": [780, 580], + "bounds": [20, 20] + } + ] +} +
diff --git a/third_party/blink/web_tests/compositing/lots-of-img-layers-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/lots-of-img-layers-expected.png similarity index 100% rename from third_party/blink/web_tests/compositing/lots-of-img-layers-expected.png rename to third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/lots-of-img-layers-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/compositing/lots-of-img-layers-with-opacity-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/lots-of-img-layers-with-opacity-expected.png similarity index 100% rename from third_party/blink/web_tests/compositing/lots-of-img-layers-with-opacity-expected.png rename to third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/lots-of-img-layers-with-opacity-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/masks/direct-image-mask-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/masks/direct-image-mask-expected.png new file mode 100644 index 0000000..187bc849 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/masks/direct-image-mask-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/masks/mask-with-removed-filters-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/masks/mask-with-removed-filters-expected.png new file mode 100644 index 0000000..bf05d030 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/masks/mask-with-removed-filters-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/masks/masked-ancestor-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/masks/masked-ancestor-expected.png new file mode 100644 index 0000000..2893d5c6 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/masks/masked-ancestor-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/masks/multiple-masks-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/masks/multiple-masks-expected.png new file mode 100644 index 0000000..50633eb --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/masks/multiple-masks-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/masks/simple-composited-mask-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/masks/simple-composited-mask-expected.png new file mode 100644 index 0000000..a4ea481 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/masks/simple-composited-mask-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/opacity-with-mask-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/opacity-with-mask-expected.png new file mode 100644 index 0000000..b39d0c8 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/opacity-with-mask-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-above-composited-subframe-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-above-composited-subframe-expected.png new file mode 100644 index 0000000..3c73dc0 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-above-composited-subframe-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-composited-subframe-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-composited-subframe-expected.png new file mode 100644 index 0000000..8540490 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-composited-subframe-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-on-grandparent-composited-grandchild-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-on-grandparent-composited-grandchild-expected.png new file mode 100644 index 0000000..f4b4fff8 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-on-grandparent-composited-grandchild-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-on-parent-composited-grandchild-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-on-parent-composited-grandchild-expected.png new file mode 100644 index 0000000..f380d7a --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-on-parent-composited-grandchild-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png new file mode 100644 index 0000000..61743f1 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-styles-with-composited-child-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-styles-with-composited-child-expected.png new file mode 100644 index 0000000..969f416 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/border-radius-styles-with-composited-child-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/clear-scroll-parent-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/clear-scroll-parent-expected.txt new file mode 100644 index 0000000..9b7a2ba --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/clear-scroll-parent-expected.txt
@@ -0,0 +1,93 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow DIV class='container'", + "position": [8, 8], + "bounds": [308, 208], + "backgroundColor": "#00FF0080" + }, + { + "name": "Scrolling Layer", + "position": [12, 12], + "bounds": [285, 200], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "position": [12, 12], + "bounds": [285, 530], + "backgroundColor": "#00FF0080" + }, + { + "name": "Overflow Controls Host Layer", + "position": [8, 8], + "bounds": [308, 208], + "drawsContent": false + }, + { + "name": "Vertical Scrollbar Layer", + "position": [297, 12], + "bounds": [15, 185], + "drawsContent": false + }, + { + "name": "Scroll Corner Layer", + "position": [297, 197], + "bounds": [15, 15] + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='fixed'", + "position": [50, 200], + "bounds": [200, 200], + "contentsOpaque": true, + "backgroundColor": "#008000" + }, + { + "name": "Ancestor Clipping Layer", + "position": [12, 12], + "bounds": [80, 80], + "drawsContent": false, + "hasScrollParent": true + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='box red'", + "position": [22, 22], + "bounds": [100, 100], + "backgroundColor": "#FF000080" + }, + { + "name": "Squashing Containment Layer", + "drawsContent": false, + "hasScrollParent": true + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='box'", + "position": [22, 102], + "bounds": [100, 100], + "backgroundColor": "#0000FF80" + }, + { + "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV class='box')", + "position": [22, 212], + "bounds": [100, 320] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/clip-descendents-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/clip-descendents-expected.txt new file mode 100644 index 0000000..048aec8 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/clip-descendents-expected.txt
@@ -0,0 +1,166 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Ancestor Clipping Layer", + "position": [48, 38], + "bounds": [60, 70], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV class='box'", + "bounds": [100, 150], + "contentsOpaque": true, + "backgroundColor": "#808080", + "transform": 2 + }, + { + "name": "Ancestor Clipping Layer", + "position": [240, 38], + "bounds": [60, 70], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV class='box'", + "bounds": [100, 150], + "contentsOpaque": true, + "backgroundColor": "#808080", + "transform": 4 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='container'", + "position": [48, 230], + "bounds": [60, 70] + }, + { + "name": "Child Containment Layer", + "position": [48, 230], + "bounds": [60, 70], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV class='box'", + "bounds": [100, 150], + "contentsOpaque": true, + "backgroundColor": "#808080", + "transform": 6 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='container'", + "position": [240, 230], + "bounds": [60, 70] + }, + { + "name": "Child Containment Layer", + "position": [240, 230], + "bounds": [60, 70], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV class='box'", + "bounds": [100, 150], + "contentsOpaque": true, + "backgroundColor": "#808080", + "transform": 8 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [50, 50, 0, 1] + ], + "flattenInheritedTransform": false + }, + { + "id": 2, + "parent": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ], + "flattenInheritedTransform": false + }, + { + "id": 3, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [242, 50, 0, 1] + ], + "flattenInheritedTransform": false + }, + { + "id": 4, + "parent": 3, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ], + "flattenInheritedTransform": false + }, + { + "id": 5, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [50, 242, 0, 1] + ] + }, + { + "id": 6, + "parent": 5, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ] + }, + { + "id": 7, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [242, 242, 0, 1] + ] + }, + { + "id": 8, + "parent": 7, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/content-gains-scrollbars-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/content-gains-scrollbars-expected.txt new file mode 100644 index 0000000..285f901d --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/content-gains-scrollbars-expected.txt
@@ -0,0 +1,210 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='container'", + "bounds": [100, 100], + "transform": 1 + }, + { + "name": "Scrolling Layer", + "bounds": [85, 100], + "drawsContent": false, + "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [85, 200], + "drawsContent": false, + "transform": 1 + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='vertical' class='content tall'", + "bounds": [10, 200], + "drawsContent": false, + "transform": 1 + }, + { + "name": "Overflow Controls Host Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 1 + }, + { + "name": "Vertical Scrollbar Layer", + "position": [85, 0], + "bounds": [15, 100], + "drawsContent": false, + "transform": 1 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='container'", + "bounds": [100, 100], + "transform": 2 + }, + { + "name": "Scrolling Layer", + "bounds": [100, 85], + "drawsContent": false, + "transform": 2 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [200, 85], + "drawsContent": false, + "transform": 2 + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='horizontal' class='content wide'", + "bounds": [200, 10], + "drawsContent": false, + "transform": 2 + }, + { + "name": "Overflow Controls Host Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 2 + }, + { + "name": "Horizontal Scrollbar Layer", + "position": [0, 85], + "bounds": [100, 15], + "drawsContent": false, + "transform": 2 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='container'", + "bounds": [100, 100], + "transform": 3 + }, + { + "name": "Scrolling Layer", + "bounds": [85, 85], + "drawsContent": false, + "transform": 3 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [200, 200], + "drawsContent": false, + "transform": 3 + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='both' class='content wide tall'", + "bounds": [200, 200], + "drawsContent": false, + "transform": 3 + }, + { + "name": "Overflow Controls Host Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 3 + }, + { + "name": "Horizontal Scrollbar Layer", + "position": [0, 85], + "bounds": [85, 15], + "drawsContent": false, + "transform": 3 + }, + { + "name": "Vertical Scrollbar Layer", + "position": [85, 0], + "bounds": [15, 85], + "drawsContent": false, + "transform": 3 + }, + { + "name": "Scroll Corner Layer", + "position": [85, 85], + "bounds": [15, 15], + "transform": 3 + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='corner' class='container resizeWidget'", + "bounds": [100, 100], + "transform": 4 + }, + { + "name": "Child Containment Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 4 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='content'", + "bounds": [10, 10], + "drawsContent": false, + "transform": 4 + }, + { + "name": "Overflow Controls Host Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 4 + }, + { + "name": "Scroll Corner Layer", + "position": [85, 85], + "bounds": [15, 15], + "transform": 4 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 13, 0, 1] + ] + }, + { + "id": 2, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 13, 0, 1] + ] + }, + { + "id": 3, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 13, 0, 1] + ] + }, + { + "id": 4, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 13, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/content-loses-scrollbars-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/content-loses-scrollbars-expected.txt new file mode 100644 index 0000000..28e47b8 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/content-loses-scrollbars-expected.txt
@@ -0,0 +1,132 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='container'", + "bounds": [100, 100], + "drawsContent": false, + "transform": 1 + }, + { + "name": "Child Containment Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 1 + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='vertical' class='content'", + "bounds": [10, 10], + "drawsContent": false, + "transform": 1 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='container'", + "bounds": [100, 100], + "drawsContent": false, + "transform": 2 + }, + { + "name": "Child Containment Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 2 + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='horizontal' class='content'", + "bounds": [10, 10], + "drawsContent": false, + "transform": 2 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='container'", + "bounds": [100, 100], + "drawsContent": false, + "transform": 3 + }, + { + "name": "Child Containment Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 3 + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='both' class='content'", + "bounds": [10, 10], + "drawsContent": false, + "transform": 3 + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='corner' class='container'", + "bounds": [100, 100], + "drawsContent": false, + "transform": 4 + }, + { + "name": "Child Containment Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 4 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='content'", + "bounds": [10, 10], + "drawsContent": false, + "transform": 4 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 13, 0, 1] + ] + }, + { + "id": 2, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 13, 0, 1] + ] + }, + { + "id": 3, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 13, 0, 1] + ] + }, + { + "id": 4, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 13, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/grandchild-composited-with-border-radius-ancestor-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/grandchild-composited-with-border-radius-ancestor-expected.png new file mode 100644 index 0000000..b219e48 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/grandchild-composited-with-border-radius-ancestor-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png new file mode 100644 index 0000000..b219e48 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/nested-render-surfaces-with-rotation-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/nested-render-surfaces-with-rotation-expected.png new file mode 100644 index 0000000..1600edb --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/nested-render-surfaces-with-rotation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/no-excessive-clip-parent-if-parent-escaped-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/no-excessive-clip-parent-if-parent-escaped-expected.txt new file mode 100644 index 0000000..cc0d374d --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/no-excessive-clip-parent-if-parent-escaped-expected.txt
@@ -0,0 +1,43 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow DIV", + "position": [8, 8], + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#FF0000" + }, + { + "name": "Child Containment Layer", + "position": [8, 8], + "bounds": [100, 100], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (positioned) DIV", + "position": [8, 8], + "bounds": [50, 50], + "contentsOpaque": true, + "backgroundColor": "#008000", + "hasClipParent": true + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/overflow-scrollbar-layers-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/overflow-scrollbar-layers-expected.txt new file mode 100644 index 0000000..f679344 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/overflow-scrollbar-layers-expected.txt
@@ -0,0 +1,210 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='container'", + "bounds": [100, 100], + "transform": 1 + }, + { + "name": "Scrolling Layer", + "bounds": [85, 100], + "drawsContent": false, + "transform": 1 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [85, 200], + "drawsContent": false, + "transform": 1 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='content tall'", + "bounds": [10, 200], + "drawsContent": false, + "transform": 1 + }, + { + "name": "Overflow Controls Host Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 1 + }, + { + "name": "Vertical Scrollbar Layer", + "position": [85, 0], + "bounds": [15, 100], + "drawsContent": false, + "transform": 1 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='container'", + "bounds": [100, 100], + "transform": 2 + }, + { + "name": "Scrolling Layer", + "bounds": [100, 85], + "drawsContent": false, + "transform": 2 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [200, 85], + "drawsContent": false, + "transform": 2 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='content wide'", + "bounds": [200, 10], + "drawsContent": false, + "transform": 2 + }, + { + "name": "Overflow Controls Host Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 2 + }, + { + "name": "Horizontal Scrollbar Layer", + "position": [0, 85], + "bounds": [100, 15], + "drawsContent": false, + "transform": 2 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='container'", + "bounds": [100, 100], + "transform": 3 + }, + { + "name": "Scrolling Layer", + "bounds": [85, 85], + "drawsContent": false, + "transform": 3 + }, + { + "name": "Scrolling Contents Layer", + "bounds": [200, 200], + "drawsContent": false, + "transform": 3 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='content wide tall'", + "bounds": [200, 200], + "drawsContent": false, + "transform": 3 + }, + { + "name": "Overflow Controls Host Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 3 + }, + { + "name": "Horizontal Scrollbar Layer", + "position": [0, 85], + "bounds": [85, 15], + "drawsContent": false, + "transform": 3 + }, + { + "name": "Vertical Scrollbar Layer", + "position": [85, 0], + "bounds": [15, 85], + "drawsContent": false, + "transform": 3 + }, + { + "name": "Scroll Corner Layer", + "position": [85, 85], + "bounds": [15, 15], + "transform": 3 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='container resizeWidget'", + "bounds": [100, 100], + "transform": 4 + }, + { + "name": "Child Containment Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 4 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='content'", + "bounds": [10, 10], + "drawsContent": false, + "transform": 4 + }, + { + "name": "Overflow Controls Host Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 4 + }, + { + "name": "Scroll Corner Layer", + "position": [85, 85], + "bounds": [15, 15], + "transform": 4 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 13, 0, 1] + ] + }, + { + "id": 2, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 13, 0, 1] + ] + }, + { + "id": 3, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 13, 0, 1] + ] + }, + { + "id": 4, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 13, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt new file mode 100644 index 0000000..c8f192a --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/reparented-scrollbars-non-sc-anc-expected.txt
@@ -0,0 +1,85 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [1208, 821], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Ancestor Clipping Layer", + "position": [8, 8], + "bounds": [1200, 800], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV id='positioned'", + "position": [8, 8], + "bounds": [1200, 800] + }, + { + "name": "Child Containment Layer", + "position": [8, 8], + "bounds": [1200, 800], + "drawsContent": false + }, + { + "name": "Ancestor Clipping Layer", + "position": [8, 8], + "bounds": [1200, 1000], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV id='scroller'", + "position": [8, 8], + "bounds": [1200, 1000] + }, + { + "name": "Scrolling Layer", + "position": [8, 8], + "bounds": [1200, 1000], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "position": [8, 8], + "bounds": [1200, 10000] + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV id='foreground'", + "position": [8, 10008], + "contentsOpaque": true, + "drawsContent": false + }, + { + "name": "Overflow Controls Ancestor Clipping Layer", + "position": [8, 8], + "bounds": [1200, 1000], + "drawsContent": false + }, + { + "name": "Overflow Controls Host Layer", + "position": [8, 8], + "bounds": [1200, 1000], + "drawsContent": false + }, + { + "name": "Vertical Scrollbar Layer", + "position": [1201, 8], + "bounds": [7, 1000], + "drawsContent": false + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/rotate-clip-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/rotate-clip-expected.txt new file mode 100644 index 0000000..9801d91 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/rotate-clip-expected.txt
@@ -0,0 +1,64 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow DIV", + "bounds": [240, 240], + "transform": 2 + }, + { + "name": "Child Containment Layer", + "position": [20, 20], + "bounds": [200, 200], + "drawsContent": false, + "transform": 2 + }, + { + "name": "LayoutBlockFlow DIV", + "position": [20, 20], + "bounds": [400, 400], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "transform": 2 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [108, 100, 0, 1] + ] + }, + { + "id": 2, + "parent": 1, + "transform": [ + [0.707106781186548, 0.707106781186548, 0, 0], + [-0.707106781186548, 0.707106781186548, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1] + ], + "origin": [120, 120] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/rotate-then-clip-effect-interleave-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/rotate-then-clip-effect-interleave-expected.txt new file mode 100644 index 0000000..a390599f --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/rotate-then-clip-effect-interleave-expected.txt
@@ -0,0 +1,94 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow DIV", + "bounds": [240, 240], + "drawsContent": false, + "transform": 2 + }, + { + "name": "LayoutBlockFlow DIV", + "bounds": [240, 240], + "opacity": 0.899999976158142, + "transform": 2 + }, + { + "name": "Ancestor Clipping Layer", + "position": [20, 20], + "bounds": [200, 200], + "drawsContent": false, + "transform": 2 + }, + { + "name": "LayoutBlockFlow DIV", + "position": [20, 20], + "bounds": [400, 400], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "transform": 2 + }, + { + "name": "LayoutBlockFlow (positioned) DIV", + "position": [20, 0], + "bounds": [400, 100], + "contentsOpaque": true, + "backgroundColor": "#00FFFF", + "transform": 2 + }, + { + "name": "Ancestor Clipping Layer", + "position": [20, 20], + "bounds": [200, 200], + "drawsContent": false, + "transform": 2 + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV", + "position": [20, 20], + "bounds": [100, 400], + "contentsOpaque": true, + "backgroundColor": "#FF00FF", + "transform": 2 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [108, 100, 0, 1] + ] + }, + { + "id": 2, + "parent": 1, + "transform": [ + [0.707106781186548, 0.707106781186548, 0, 0], + [-0.707106781186548, 0.707106781186548, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1] + ], + "origin": [120, 120] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/rotate-then-clip-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/rotate-then-clip-expected.txt new file mode 100644 index 0000000..fbb4681 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/rotate-then-clip-expected.txt
@@ -0,0 +1,64 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow DIV", + "bounds": [240, 240], + "transform": 2 + }, + { + "name": "Ancestor Clipping Layer", + "position": [20, 20], + "bounds": [200, 200], + "drawsContent": false, + "transform": 2 + }, + { + "name": "LayoutBlockFlow DIV", + "position": [20, 20], + "bounds": [400, 400], + "contentsOpaque": true, + "backgroundColor": "#0000FF", + "transform": 2 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [108, 100, 0, 1] + ] + }, + { + "id": 2, + "parent": 1, + "transform": [ + [0.707106781186548, 0.707106781186548, 0, 0], + [-0.707106781186548, 0.707106781186548, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1] + ], + "origin": [120, 120] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png new file mode 100644 index 0000000..0edab25 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/rotate-then-clip-z-order-interleave-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/rotate-then-clip-z-order-interleave-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/rotate-then-clip-z-order-interleave-expected.txt new file mode 100644 index 0000000..f97eb4f --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/rotate-then-clip-z-order-interleave-expected.txt
@@ -0,0 +1,82 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow DIV", + "bounds": [300, 100], + "transform": 2 + }, + { + "name": "Ancestor Clipping Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 2 + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV", + "bounds": [200, 100], + "contentsOpaque": true, + "backgroundColor": "#008000", + "transform": 2 + }, + { + "name": "LayoutBlockFlow (positioned) DIV", + "bounds": [200, 22], + "contentsOpaque": true, + "backgroundColor": "#FFFF00", + "transform": 2 + }, + { + "name": "Ancestor Clipping Layer", + "bounds": [100, 100], + "drawsContent": false, + "transform": 2 + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV", + "bounds": [50, 200], + "contentsOpaque": true, + "backgroundColor": "#FF0000", + "transform": 2 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [108, 100, 0, 1] + ] + }, + { + "id": 2, + "parent": 1, + "transform": [ + [0.707106781186548, 0.707106781186548, 0, 0], + [-0.707106781186548, 0.707106781186548, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1] + ], + "origin": [150, 50] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt new file mode 100644 index 0000000..15c58a53 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor-expected.txt
@@ -0,0 +1,82 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow DIV id='intervening'", + "position": [98, 90], + "bounds": [300, 300], + "contentsOpaque": true, + "backfaceVisibility": "hidden", + "backgroundColor": "#FFEFD5" + }, + { + "name": "LayoutBlockFlow DIV id='scroller'", + "position": [98, 90], + "bounds": [102, 102] + }, + { + "name": "Scrolling Layer", + "position": [99, 91], + "bounds": [100, 100], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "position": [99, 91], + "bounds": [100, 180], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='fixed'", + "position": [60, 60], + "bounds": [80, 80], + "contentsOpaque": true, + "backgroundColor": "#008000" + }, + { + "name": "Squashing Containment Layer", + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='scrolled'", + "position": [103, 95], + "bounds": [60, 40], + "contentsOpaque": true, + "backgroundColor": "#0000FF" + }, + { + "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV class='scrolled')", + "position": [103, 139], + "bounds": [60, 128] + }, + { + "name": "Overflow Controls Host Layer", + "position": [98, 90], + "bounds": [102, 102], + "drawsContent": false + }, + { + "name": "Vertical Scrollbar Layer", + "position": [192, 91], + "bounds": [7, 100], + "drawsContent": false + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/scrollbar-layer-placement-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/scrollbar-layer-placement-expected.txt new file mode 100644 index 0000000..7be354a --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/scrollbar-layer-placement-expected.txt
@@ -0,0 +1,218 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='outer A'", + "position": [6, 6], + "bounds": [340, 282] + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='scroller'", + "position": [38, 38], + "bounds": [278, 218], + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "position": [67, 67], + "bounds": [220, 160], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "position": [67, 67], + "bounds": [220, 236], + "backgroundColor": "#FFFFFF" + }, + { + "name": "Overflow Controls Host Layer", + "position": [62, 62], + "bounds": [230, 170], + "drawsContent": false + }, + { + "name": "Vertical Scrollbar Layer", + "position": [280, 67], + "bounds": [7, 160], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='outer B'", + "position": [355, 6], + "bounds": [340, 282] + }, + { + "name": "LayoutBlockFlow DIV class='scroller'", + "position": [387, 38], + "bounds": [278, 218], + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "position": [416, 67], + "bounds": [220, 160], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "position": [416, 67], + "bounds": [220, 236], + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='content'", + "position": [428, 79], + "bounds": [196, 212], + "contentsOpaque": true, + "backgroundColor": "#DDDDDD" + }, + { + "name": "Overflow Controls Host Layer", + "position": [411, 62], + "bounds": [230, 170], + "drawsContent": false + }, + { + "name": "Vertical Scrollbar Layer", + "position": [629, 67], + "bounds": [7, 160], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='outer C'", + "position": [6, 297], + "bounds": [340, 282] + }, + { + "name": "Ancestor Clipping Layer", + "position": [46, 337], + "bounds": [260, 100], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV class='scroller'", + "position": [37, 328], + "bounds": [278, 218], + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "position": [66, 357], + "bounds": [220, 160], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "position": [66, 357], + "bounds": [220, 236], + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='content'", + "position": [78, 369], + "bounds": [196, 212], + "contentsOpaque": true, + "backgroundColor": "#DDDDDD" + }, + { + "name": "Overflow Controls Ancestor Clipping Layer", + "position": [46, 337], + "bounds": [260, 100], + "drawsContent": false + }, + { + "name": "Overflow Controls Host Layer", + "position": [61, 352], + "bounds": [230, 170], + "drawsContent": false + }, + { + "name": "Vertical Scrollbar Layer", + "position": [279, 357], + "bounds": [7, 160], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='outer D'", + "position": [355, 297], + "bounds": [340, 282] + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='clipper'", + "position": [379, 321], + "bounds": [292, 200] + }, + { + "name": "Child Containment Layer", + "position": [389, 331], + "bounds": [272, 180], + "drawsContent": false + }, + { + "name": "Ancestor Clipping Layer", + "position": [395, 337], + "bounds": [260, 100], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV class='scroller'", + "position": [386, 328], + "bounds": [278, 218], + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "position": [415, 357], + "bounds": [220, 160], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "position": [415, 357], + "bounds": [220, 236], + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='content'", + "position": [427, 369], + "bounds": [196, 212], + "contentsOpaque": true, + "backgroundColor": "#DDDDDD" + }, + { + "name": "Overflow Controls Ancestor Clipping Layer", + "position": [395, 337], + "bounds": [260, 100], + "drawsContent": false + }, + { + "name": "Overflow Controls Host Layer", + "position": [410, 352], + "bounds": [230, 170], + "drawsContent": false + }, + { + "name": "Vertical Scrollbar Layer", + "position": [628, 357], + "bounds": [7, 160], + "drawsContent": false + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/siblings-composited-with-border-radius-ancestor-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/siblings-composited-with-border-radius-ancestor-expected.png new file mode 100644 index 0000000..b219e48 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/siblings-composited-with-border-radius-ancestor-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped-expected.png new file mode 100644 index 0000000..ef41de3 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/siblings-with-border-radius-ancestor-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/siblings-with-border-radius-ancestor-expected.png new file mode 100644 index 0000000..fa893ed --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/siblings-with-border-radius-ancestor-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/tiled-mask-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/tiled-mask-expected.png similarity index 100% rename from third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/tiled-mask-expected.png rename to third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/overflow/tiled-mask-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/perpendicular-layer-sorting-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/perpendicular-layer-sorting-expected.png new file mode 100644 index 0000000..fa252db --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/perpendicular-layer-sorting-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/perspective-interest-rect-expected.png b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/perspective-interest-rect-expected.png new file mode 100644 index 0000000..6beffe78 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/perspective-interest-rect-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/rtl/rtl-iframe-absolute-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/rtl/rtl-iframe-absolute-expected.txt new file mode 100644 index 0000000..11a5e14 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/rtl/rtl-iframe-absolute-expected.txt
@@ -0,0 +1,54 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutIFrame (positioned) IFRAME", + "bounds": [400, 400] + }, + { + "name": "LayoutView #document", + "bounds": [400, 400], + "backgroundColor": "#FF0000" + }, + { + "name": "Child Containment Layer", + "bounds": [400, 400], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='positioned layer'", + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#008000", + "transform": 1 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [50, 50, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/rtl/rtl-iframe-fixed-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/rtl/rtl-iframe-fixed-expected.txt new file mode 100644 index 0000000..11a5e14 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/rtl/rtl-iframe-fixed-expected.txt
@@ -0,0 +1,54 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutIFrame (positioned) IFRAME", + "bounds": [400, 400] + }, + { + "name": "LayoutView #document", + "bounds": [400, 400], + "backgroundColor": "#FF0000" + }, + { + "name": "Child Containment Layer", + "bounds": [400, 400], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='positioned layer'", + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#008000", + "transform": 1 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [50, 50, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/rtl/rtl-iframe-relative-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/rtl/rtl-iframe-relative-expected.txt new file mode 100644 index 0000000..7d4fc5b --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/rtl/rtl-iframe-relative-expected.txt
@@ -0,0 +1,53 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutIFrame (positioned) IFRAME", + "bounds": [400, 400] + }, + { + "name": "LayoutView #document", + "bounds": [400, 400] + }, + { + "name": "Child Containment Layer", + "bounds": [400, 400], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV id='layer'", + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#008000", + "transform": 1 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [242, 58, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/squashing/clipping-ancestor-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/squashing/clipping-ancestor-expected.txt new file mode 100644 index 0000000..7298b1c --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/squashing/clipping-ancestor-expected.txt
@@ -0,0 +1,54 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Ancestor Clipping Layer", + "position": [8, 8], + "bounds": [200, 10], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV id='inner'", + "bounds": [200, 10], + "contentsOpaque": true, + "backgroundColor": "#F5F5F5", + "transform": 1 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='hoverable'", + "position": [8, 0], + "bounds": [100, 100], + "contentsOpaque": true, + "backgroundColor": "#90EE90" + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 8, 0, 1] + ], + "flattenInheritedTransform": false + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/squashing/no-squashing-into-another-clip-layer-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/squashing/no-squashing-into-another-clip-layer-expected.txt new file mode 100644 index 0000000..4a56b34 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/squashing/no-squashing-into-another-clip-layer-expected.txt
@@ -0,0 +1,59 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow DIV", + "bounds": [784, 10], + "contentsOpaque": true, + "backgroundColor": "#ADD8E6", + "transform": 1 + }, + { + "name": "Child Containment Layer", + "bounds": [784, 10], + "drawsContent": false, + "transform": 1 + }, + { + "name": "LayoutBlockFlow DIV id='inner'", + "bounds": [784, 10], + "contentsOpaque": true, + "backgroundColor": "#F5F5F5", + "transform": 1 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='hoverable'", + "position": [8, 0], + "bounds": [216, 100], + "backgroundColor": "#90EE90" + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 8, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/squashing/no-squashing-into-fixed-position-that-clips-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/squashing/no-squashing-into-fixed-position-that-clips-expected.txt new file mode 100644 index 0000000..f13b579 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/squashing/no-squashing-into-fixed-position-that-clips-expected.txt
@@ -0,0 +1,59 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='fixedpos'", + "position": [0, 50], + "bounds": [800, 550], + "contentsOpaque": true, + "backgroundColor": "#ADD8E6" + }, + { + "name": "Child Containment Layer", + "position": [0, 50], + "bounds": [800, 550], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='compositedlayer'", + "bounds": [24, 100], + "contentsOpaque": true, + "backgroundColor": "#D3D3D3", + "transform": 1 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='notsquashedelement'", + "bounds": [800, 60], + "contentsOpaque": true, + "backgroundColor": "#008000" + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [400, 40, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/visibility/layer-visible-content-expected.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/visibility/layer-visible-content-expected.txt new file mode 100644 index 0000000..0b05974b --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/compositing/visibility/layer-visible-content-expected.txt
@@ -0,0 +1,41 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='container'", + "bounds": [200, 200] + }, + { + "name": "Child Containment Layer", + "bounds": [200, 200], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV class='composited box'", + "bounds": [10, 10], + "drawsContent": false + }, + { + "name": "LayoutBlockFlow PRE id='layer-tree'", + "bounds": [800, 16], + "opacity": 0 + } + ] +} +
diff --git a/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/paint/README.txt b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/paint/README.txt new file mode 100644 index 0000000..902eb3c2 --- /dev/null +++ b/third_party/blink/web_tests/virtual/not-blink-gen-property-trees/paint/README.txt
@@ -0,0 +1 @@ +# This suite runs tests with --disable-blink-features=BlinkGenPropertyTrees
diff --git a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png new file mode 100644 index 0000000..f38a1b2 --- /dev/null +++ b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/grandchild-with-border-radius-ancestor-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png index 4c296cd..672088db 100644 --- a/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png +++ b/third_party/blink/web_tests/virtual/prefer_compositing_to_lcd_text/compositing/overflow/nested-render-surfaces-with-rotation-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/service-worker-servicification/external/wpt/service-workers/service-worker/README.txt b/third_party/blink/web_tests/virtual/service-worker-servicification/external/wpt/service-workers/service-worker/README.txt deleted file mode 100644 index b0e1403..0000000 --- a/third_party/blink/web_tests/virtual/service-worker-servicification/external/wpt/service-workers/service-worker/README.txt +++ /dev/null
@@ -1,2 +0,0 @@ -This directory is for testing the case where ServiceWorkerServicification (aka NetS13nServiceWorker) is on and NetworkService is off. -The tracking bug is crbug.com/846235.
diff --git a/third_party/blink/web_tests/virtual/service-worker-servicification/http/tests/serviceworker/README.txt b/third_party/blink/web_tests/virtual/service-worker-servicification/http/tests/serviceworker/README.txt deleted file mode 100644 index b0e1403..0000000 --- a/third_party/blink/web_tests/virtual/service-worker-servicification/http/tests/serviceworker/README.txt +++ /dev/null
@@ -1,2 +0,0 @@ -This directory is for testing the case where ServiceWorkerServicification (aka NetS13nServiceWorker) is on and NetworkService is off. -The tracking bug is crbug.com/846235.
diff --git a/third_party/blink/web_tests/virtual/service-worker-servicification/http/tests/serviceworker/navigation_preload/use-counter-expected.txt b/third_party/blink/web_tests/virtual/service-worker-servicification/http/tests/serviceworker/navigation_preload/use-counter-expected.txt deleted file mode 100644 index 2a7c5b20..0000000 --- a/third_party/blink/web_tests/virtual/service-worker-servicification/http/tests/serviceworker/navigation_preload/use-counter-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -PASS Navigation Preload is not counted if not enabled. -PASS Navigation Preload is use counted. -FAIL Navigation Preload is use counted even if preloadResponse is not used. assert_true: expected true got false -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/form-targets-cross-site-frame-get-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/form-targets-cross-site-frame-get-expected.txt index 0942fb3..54d1f09 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/form-targets-cross-site-frame-get-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/form-targets-cross-site-frame-get-expected.txt
@@ -1,5 +1,4 @@ -Test field: - +Test field: -------- Frame: 'cross-site-frame' @@ -9,6 +8,7 @@ Parameters: test-field = test-value + Http headers: HTTP_CONNECTION = keep-alive
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/form-targets-cross-site-frame-no-referrer-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/form-targets-cross-site-frame-no-referrer-expected.txt index e9e9393..d6199c1c 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/form-targets-cross-site-frame-no-referrer-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/form-targets-cross-site-frame-no-referrer-expected.txt
@@ -1,5 +1,4 @@ -Test field: - +Test field: -------- Frame: 'cross-site-frame' @@ -9,6 +8,7 @@ Parameters: test-field = test-value + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/form-targets-cross-site-frame-post-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/form-targets-cross-site-frame-post-expected.txt index 4488d48..9f5e396 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/form-targets-cross-site-frame-post-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/form-targets-cross-site-frame-post-expected.txt
@@ -1,5 +1,4 @@ -Test field: - +Test field: -------- Frame: 'cross-site-frame' @@ -9,6 +8,7 @@ Parameters: test-field = test-value + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/form-with-enctype-targets-cross-site-frame-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/form-with-enctype-targets-cross-site-frame-expected.txt index c04a025..fadc4c7 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/form-with-enctype-targets-cross-site-frame-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/form-with-enctype-targets-cross-site-frame-expected.txt
@@ -1,5 +1,4 @@ -Test field: - +Test field: -------- Frame: 'cross-site-frame' @@ -9,6 +8,7 @@ Parameters: test-field = test-value + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/post-basic-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/post-basic-expected.txt index 430aa43..72298a0 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/post-basic-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/post-basic-expected.txt
@@ -4,6 +4,7 @@ the-input = input value goes here submitwithpost = Submit with POST + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/post-frames-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/post-frames-expected.txt index 2c640e9..218a33e 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/post-frames-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/post-frames-expected.txt
@@ -1,7 +1,5 @@ Tests that a POST request in a frame is handled correctly. If this test passes, you will see a page indicating a form was POSTed. - - -------- Frame: '<!--framePath //<!--frame0-->-->' -------- @@ -11,6 +9,7 @@ the-input = input value goes here submitwithpost = Submit with POST + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/post-frames-goback1-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/post-frames-goback1-expected.txt index 47fb769..863d0ca5 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/post-frames-goback1-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/post-frames-goback1-expected.txt
@@ -1,8 +1,5 @@ Tests that a POST targetted to a frame is handled correctly when navigating away and coming back to the page. - - - -------- Frame: 'target-frame' -------- @@ -11,6 +8,7 @@ Parameters: the-input = input value goes here + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/post-goback1-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/post-goback1-expected.txt index f844d6b..d7b0e125d 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/post-goback1-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/post-goback1-expected.txt
@@ -4,6 +4,7 @@ the-input = input value goes here submitwithpost = Submit with POST + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/rename-subframe-goback-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/rename-subframe-goback-expected.txt index ecd8238..1657767 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/navigation/rename-subframe-goback-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/navigation/rename-subframe-goback-expected.txt
@@ -12,6 +12,7 @@ the-input = input value goes here submitwithpost = Submit with POST + Http headers: HTTP_CACHE_CONTROL = max-age=0
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 146ea79c..5d7d2de 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -317,6 +317,14 @@ method constructor method contains method item +interface ErrorEvent : Event + attribute @@toStringTag + getter colno + getter error + getter filename + getter lineno + getter message + method constructor interface Event attribute @@toStringTag attribute AT_TARGET
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/css-properties-as-js-properties-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/css-properties-as-js-properties-expected.txt index 412866d..1fe2253 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/css-properties-as-js-properties-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/css-properties-as-js-properties-expected.txt
@@ -1,5 +1,6 @@ This test (crudely) documents Blink's web-exposed CSS properties. All changes to this list should go through Blink's feature review process: http://www.chromium.org/blink#new-features + alignContent alignItems alignSelf
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/element-instance-property-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/element-instance-property-listing-expected.txt index 3592be2..76c19c2 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/element-instance-property-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/element-instance-property-listing-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - [HTML NAMESPACE ELEMENT PROPERTIES] namespace http://www.w3.org/1999/xhtml <common>
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/event-target-in-prototype-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/event-target-in-prototype-expected.txt index f18baba5..836e6ff 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/event-target-in-prototype-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/event-target-in-prototype-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS EventSource.prototype.__proto__ is EventTarget.prototype PASS FileReader.prototype.__proto__ is EventTarget.prototype PASS MediaSource.prototype.__proto__ is EventTarget.prototype
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt index 722e04c..06b45201 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: resources/global-interface-listing-worker.js [Worker] [INTERFACES] [Worker] interface AbortController @@ -301,6 +300,14 @@ [Worker] attribute PERSISTENT [Worker] attribute TEMPORARY [Worker] method constructor +[Worker] interface ErrorEvent : Event +[Worker] attribute @@toStringTag +[Worker] getter colno +[Worker] getter error +[Worker] getter filename +[Worker] getter lineno +[Worker] getter message +[Worker] method constructor [Worker] interface Event [Worker] attribute @@toStringTag [Worker] attribute AT_TARGET
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt index 6d6fa02..a0f8026c 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - [INTERFACES] interface AbortController attribute @@toStringTag
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt index a1f0040..fd516d14 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: resources/global-interface-listing-worker.js [Worker] [INTERFACES] [Worker] interface AbortController @@ -296,6 +295,14 @@ [Worker] method constructor [Worker] method contains [Worker] method item +[Worker] interface ErrorEvent : Event +[Worker] attribute @@toStringTag +[Worker] getter colno +[Worker] getter error +[Worker] getter filename +[Worker] getter lineno +[Worker] getter message +[Worker] method constructor [Worker] interface Event [Worker] attribute @@toStringTag [Worker] attribute AT_TARGET
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/nonstable-css-properties-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/nonstable-css-properties-expected.txt index 2006a79..266775f 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/nonstable-css-properties-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/nonstable-css-properties-expected.txt
@@ -2,107 +2,131 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - el.style.setProperty('shape-margin', '10px') el.style.getPropertyValue('shape-margin') is 10px getComputedStyle(el).getPropertyValue('shape-margin') is 10px + el.style.setProperty('shape-outside', 'circle(10px at 10px 10px)') el.style.getPropertyValue('shape-outside') is circle(10px at 10px 10px) getComputedStyle(el).getPropertyValue('shape-outside') is circle(10px at 10px 10px) + el.style.setProperty('grid-auto-columns', 'auto') el.style.getPropertyValue('grid-auto-columns') is auto getComputedStyle(el).getPropertyValue('grid-auto-columns') is auto + el.style.setProperty('grid-auto-rows', 'auto') el.style.getPropertyValue('grid-auto-rows') is auto getComputedStyle(el).getPropertyValue('grid-auto-rows') is auto + el.style.setProperty('grid-template-columns', 'min-content') el.style.getPropertyValue('grid-template-columns') is min-content getComputedStyle(el).getPropertyValue('grid-template-columns') is min-content + el.style.setProperty('grid-template-rows', 'max-content') el.style.getPropertyValue('grid-template-rows') is max-content getComputedStyle(el).getPropertyValue('grid-template-rows') is max-content + el.style.setProperty('grid-column-start', 'auto') el.style.getPropertyValue('grid-column-start') is auto getComputedStyle(el).getPropertyValue('grid-column-start') is auto + el.style.setProperty('grid-column-end', '2') el.style.getPropertyValue('grid-column-end') is 2 getComputedStyle(el).getPropertyValue('grid-column-end') is 2 + el.style.setProperty('grid-row-start', '1') el.style.getPropertyValue('grid-row-start') is 1 getComputedStyle(el).getPropertyValue('grid-row-start') is 1 + el.style.setProperty('grid-column', 'auto') el.style.getPropertyValue('grid-column') is auto / auto getComputedStyle(el).getPropertyValue('grid-column') is auto / auto + el.style.setProperty('grid-row', '1') el.style.getPropertyValue('grid-row') is 1 / auto getComputedStyle(el).getPropertyValue('grid-row') is 1 / auto + el.style.setProperty('grid-area', '2') el.style.getPropertyValue('grid-area') is 2 / auto / auto / auto getComputedStyle(el).getPropertyValue('grid-area') is 2 / auto / auto / auto + el.style.setProperty('grid-auto-flow', 'column') el.style.getPropertyValue('grid-auto-flow') is column getComputedStyle(el).getPropertyValue('grid-auto-flow') is column + el.style.setProperty('grid-template-areas', '"test"') el.style.getPropertyValue('grid-template-areas') is "test" getComputedStyle(el).getPropertyValue('grid-template-areas') is "test" + el.style.setProperty('text-justify', 'distribute') el.style.getPropertyValue('text-justify') is getComputedStyle(el).getPropertyValue('text-justify') is + el.style.setProperty('text-underline-position', 'left') el.style.getPropertyValue('text-underline-position') is left getComputedStyle(el).getPropertyValue('text-underline-position') is left + el.style.setProperty('text-underline-position', 'right') el.style.getPropertyValue('text-underline-position') is right getComputedStyle(el).getPropertyValue('text-underline-position') is right + el.style.setProperty('text-underline-position', 'under left') el.style.getPropertyValue('text-underline-position') is under left getComputedStyle(el).getPropertyValue('text-underline-position') is under left + el.style.setProperty('text-underline-position', 'right under') el.style.getPropertyValue('text-underline-position') is under right getComputedStyle(el).getPropertyValue('text-underline-position') is under right + el.style.setProperty('clear', 'inline-start') el.style.getPropertyValue('clear') is getComputedStyle(el).getPropertyValue('clear') is none + el.style.setProperty('clear', 'inline-end') el.style.getPropertyValue('clear') is getComputedStyle(el).getPropertyValue('clear') is none + el.style.setProperty('float', 'inline-start') el.style.getPropertyValue('float') is getComputedStyle(el).getPropertyValue('float') is none + el.style.setProperty('float', 'inline-end') el.style.getPropertyValue('float') is getComputedStyle(el).getPropertyValue('float') is none + el.style.setProperty('resize', 'block') el.style.getPropertyValue('resize') is getComputedStyle(el).getPropertyValue('resize') is none + el.style.setProperty('resize', 'inline') el.style.getPropertyValue('resize') is getComputedStyle(el).getPropertyValue('resize') is none + PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/virtual/threaded/animations/skew-notsequential-compositor-expected.png b/third_party/blink/web_tests/virtual/threaded/animations/skew-notsequential-compositor-expected.png index ba96552d..05fcf75 100644 --- a/third_party/blink/web_tests/virtual/threaded/animations/skew-notsequential-compositor-expected.png +++ b/third_party/blink/web_tests/virtual/threaded/animations/skew-notsequential-compositor-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/threaded/fast/scroll-behavior/smooth-scroll/fixed-background-in-iframe-expected.txt b/third_party/blink/web_tests/virtual/threaded/fast/scroll-behavior/smooth-scroll/fixed-background-in-iframe-expected.txt index 4c41b141..7ba6c6c 100644 --- a/third_party/blink/web_tests/virtual/threaded/fast/scroll-behavior/smooth-scroll/fixed-background-in-iframe-expected.txt +++ b/third_party/blink/web_tests/virtual/threaded/fast/scroll-behavior/smooth-scroll/fixed-background-in-iframe-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS isScrollAnimatingOnMainThread(iframeDoc) is true PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/virtual/threaded/fast/scroll-behavior/smooth-scroll/main-thread-scrolling-reason-correctness-expected.txt b/third_party/blink/web_tests/virtual/threaded/fast/scroll-behavior/smooth-scroll/main-thread-scrolling-reason-correctness-expected.txt index f77ee28a..6fa60e8 100644 --- a/third_party/blink/web_tests/virtual/threaded/fast/scroll-behavior/smooth-scroll/main-thread-scrolling-reason-correctness-expected.txt +++ b/third_party/blink/web_tests/virtual/threaded/fast/scroll-behavior/smooth-scroll/main-thread-scrolling-reason-correctness-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS internals.getScrollAnimationState(document) is RUNNING_ON_COMPOSITOR PASS internals.mainThreadScrollingReasons(document) is ANIMATING_TEXT PASS needsUpdateOrRunningOnCompositor(document) is true
diff --git a/third_party/blink/web_tests/virtual/threaded/printing/absolute-position-headers-and-footers-expected.png b/third_party/blink/web_tests/virtual/threaded/printing/absolute-position-headers-and-footers-expected.png deleted file mode 100644 index 5ed417b..0000000 --- a/third_party/blink/web_tests/virtual/threaded/printing/absolute-position-headers-and-footers-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/virtual/user-activation-v2/fast/dom/Window/window-postmessage-user-gesture-expected.txt b/third_party/blink/web_tests/virtual/user-activation-v2/fast/dom/Window/window-postmessage-user-gesture-expected.txt index eaa0e8a..9a165aff 100644 --- a/third_party/blink/web_tests/virtual/user-activation-v2/fast/dom/Window/window-postmessage-user-gesture-expected.txt +++ b/third_party/blink/web_tests/virtual/user-activation-v2/fast/dom/Window/window-postmessage-user-gesture-expected.txt
@@ -1,8 +1,8 @@ -Test that user gesture is available through postMessages to appropriate frames. +Test that user gesture is kept when postMessage() to self or across frames. Click me PASS Stack postMessages on self window and the user gesture is only consumed once PASS Bounce postMessages between self and frame window and the user gesture is consumed only once in self window -PASS Bounce postMessages between self and frame window and the user gesture is consumed 0 times in frame +PASS Bounce postMessages between self and frame window and the user gesture is consumed only once in frame PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/virtual/user-activation-v2/fast/events/open-window-from-another-frame-expected.txt b/third_party/blink/web_tests/virtual/user-activation-v2/fast/events/open-window-from-another-frame-expected.txt index 7a6533d..bd2118e8 100644 --- a/third_party/blink/web_tests/virtual/user-activation-v2/fast/events/open-window-from-another-frame-expected.txt +++ b/third_party/blink/web_tests/virtual/user-activation-v2/fast/events/open-window-from-another-frame-expected.txt
@@ -1,8 +1,8 @@ -This tests that window.open from a subframe doesn't work with main frame activation. +This tests that window.open works across frames. To run manually click the link below. GreenBox or Success page. -Window was not opened! Test succeeded! +Window was opened! Test succeeded! --------
diff --git a/third_party/blink/web_tests/webaudio/internals/audiocontext-lock-threading-race-expected.txt b/third_party/blink/web_tests/webaudio/internals/audiocontext-lock-threading-race-expected.txt index ede5150..ae5fabda 100644 --- a/third_party/blink/web_tests/webaudio/internals/audiocontext-lock-threading-race-expected.txt +++ b/third_party/blink/web_tests/webaudio/internals/audiocontext-lock-threading-race-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/webaudio/internals/cycle-connection-gc-expected.txt b/third_party/blink/web_tests/webaudio/internals/cycle-connection-gc-expected.txt index 096f495d..c547a18 100644 --- a/third_party/blink/web_tests/webaudio/internals/cycle-connection-gc-expected.txt +++ b/third_party/blink/web_tests/webaudio/internals/cycle-connection-gc-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - A cycle was created: PASS internals.audioHandlerCount() > initialCount is true GC happened:
diff --git a/third_party/blink/web_tests/webaudio/internals/mediaelementaudiosourcenode-wrapper-expected.txt b/third_party/blink/web_tests/webaudio/internals/mediaelementaudiosourcenode-wrapper-expected.txt index 7135f382..595839f 100644 --- a/third_party/blink/web_tests/webaudio/internals/mediaelementaudiosourcenode-wrapper-expected.txt +++ b/third_party/blink/web_tests/webaudio/internals/mediaelementaudiosourcenode-wrapper-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS source.mediaElement.nonExistentProperty is undefined. PASS source.mediaElement.nonExistentProperty is undefined. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/webaudio/internals/offlineaudiocontext-detached-no-crash-expected.txt b/third_party/blink/web_tests/webaudio/internals/offlineaudiocontext-detached-no-crash-expected.txt index 9e3b5ae..b740669 100644 --- a/third_party/blink/web_tests/webaudio/internals/offlineaudiocontext-detached-no-crash-expected.txt +++ b/third_party/blink/web_tests/webaudio/internals/offlineaudiocontext-detached-no-crash-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS OfflineAudioContext.startRendering() on a closed context threw an exception. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/webaudio/internals/scriptprocessornode-detached-no-crash-expected.txt b/third_party/blink/web_tests/webaudio/internals/scriptprocessornode-detached-no-crash-expected.txt index 65e125c5..eb4bd0c 100644 --- a/third_party/blink/web_tests/webaudio/internals/scriptprocessornode-detached-no-crash-expected.txt +++ b/third_party/blink/web_tests/webaudio/internals/scriptprocessornode-detached-no-crash-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/webaudio/internals/scriptprocessornode-premature-death-expected.txt b/third_party/blink/web_tests/webaudio/internals/scriptprocessornode-premature-death-expected.txt index ea5bedf..fa88ee6b7 100644 --- a/third_party/blink/web_tests/webaudio/internals/scriptprocessornode-premature-death-expected.txt +++ b/third_party/blink/web_tests/webaudio/internals/scriptprocessornode-premature-death-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Testing with explicitly keeping a reference to the script processor node alive. PASS wasCollectedPrematurely is false PASS wasCalled is true
diff --git a/third_party/blink/web_tests/webaudio/internals/scriptprocessornode-rewrap-expected.txt b/third_party/blink/web_tests/webaudio/internals/scriptprocessornode-rewrap-expected.txt index 7cade7e1..385ee64 100644 --- a/third_party/blink/web_tests/webaudio/internals/scriptprocessornode-rewrap-expected.txt +++ b/third_party/blink/web_tests/webaudio/internals/scriptprocessornode-rewrap-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS onaudioprocess was called with correct input data. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/webaudio/internals/self-connection-gc.html b/third_party/blink/web_tests/webaudio/internals/self-connection-gc.html new file mode 100644 index 0000000..6554aa82 --- /dev/null +++ b/third_party/blink/web_tests/webaudio/internals/self-connection-gc.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<script src="../../resources/gc.js"></script> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script> +function soon() { return new Promise(resolve => setTimeout(resolve, 0)); } +async function becomesTrue(predicate) { + while (!predicate()) await soon(); +} + +function createSelfConnectedNode(context) { + const gain = context.createGain(); + gain.connect(gain); +} + +promise_test(async () => { + await asyncGC(); + await becomesTrue(() => internals.audioHandlerCount() == 0); + + let context = new OfflineAudioContext(2, 1024, 44100); + let initialCount = internals.audioHandlerCount(); + createSelfConnectedNode(context); + assert_greater_than(internals.audioHandlerCount(), 0); + + // Need to render to clean up a cycle on an offline context. + await context.startRendering(); + + // Wait until the gain node's handler has been destroyed to declare victory. + await asyncGC(); + await becomesTrue(() => internals.audioHandlerCount() <= initialCount); +}, "No crash should occur when a node connected to itself is collected."); +</script>
diff --git a/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt b/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt index c47863e..554686b 100644 --- a/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt +++ b/third_party/blink/web_tests/webexposed/css-properties-as-js-properties-expected.txt
@@ -1,5 +1,6 @@ This test (crudely) documents Blink's web-exposed CSS properties. All changes to this list should go through Blink's feature review process: http://www.chromium.org/blink#new-features + alignContent alignItems alignSelf
diff --git a/third_party/blink/web_tests/webexposed/custom-elements-expected.txt b/third_party/blink/web_tests/webexposed/custom-elements-expected.txt index be1ab28..84c52e1 100644 --- a/third_party/blink/web_tests/webexposed/custom-elements-expected.txt +++ b/third_party/blink/web_tests/webexposed/custom-elements-expected.txt
@@ -3,22 +3,26 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Document.prototype.hasOwnProperty("registerElement") true + typeof Document.prototype.registerElement function + document.createElement("x-a") instanceof HTMLUnknownElement false + document.querySelector(":unresolved") [object HTMLDivElement] + span.getAttribute("is") type-extension + PASS window.customElements.define("a-a", A, {extends: "b"}) did not throw exception. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt b/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt index 9224e00..8f62293 100644 --- a/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - [HTML NAMESPACE ELEMENT PROPERTIES] namespace http://www.w3.org/1999/xhtml <common>
diff --git a/third_party/blink/web_tests/webexposed/event-target-in-prototype-expected.txt b/third_party/blink/web_tests/webexposed/event-target-in-prototype-expected.txt index f18baba5..836e6ff 100644 --- a/third_party/blink/web_tests/webexposed/event-target-in-prototype-expected.txt +++ b/third_party/blink/web_tests/webexposed/event-target-in-prototype-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS EventSource.prototype.__proto__ is EventTarget.prototype PASS FileReader.prototype.__proto__ is EventTarget.prototype PASS MediaSource.prototype.__proto__ is EventTarget.prototype
diff --git a/third_party/blink/web_tests/webexposed/global-constructors-attributes-expected.txt b/third_party/blink/web_tests/webexposed/global-constructors-attributes-expected.txt index ee4b9cf..d4f83f8 100644 --- a/third_party/blink/web_tests/webexposed/global-constructors-attributes-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-constructors-attributes-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS Object.getOwnPropertyDescriptor(global, 'CSSRuleList').value is CSSRuleList PASS Object.getOwnPropertyDescriptor(global, 'CSSRuleList').hasOwnProperty('get') is false PASS Object.getOwnPropertyDescriptor(global, 'CSSRuleList').hasOwnProperty('set') is false
diff --git a/third_party/blink/web_tests/webexposed/global-constructors-attributes-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-constructors-attributes-worker-expected.txt index 1b7a84a..b050997b 100644 --- a/third_party/blink/web_tests/webexposed/global-constructors-attributes-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-constructors-attributes-worker-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: resources/global-constructors-attributes-worker.js PASS [Worker] Object.getOwnPropertyDescriptor(global, 'DataView').value is DataView PASS [Worker] Object.getOwnPropertyDescriptor(global, 'DataView').hasOwnProperty('get') is false
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt index a6ebd40..b6c32cb 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: resources/global-interface-listing-worker.js [Worker] [INTERFACES] [Worker] interface AbortController @@ -329,6 +328,14 @@ [Worker] attribute PERSISTENT [Worker] attribute TEMPORARY [Worker] method constructor +[Worker] interface ErrorEvent : Event +[Worker] attribute @@toStringTag +[Worker] getter colno +[Worker] getter error +[Worker] getter filename +[Worker] getter lineno +[Worker] getter message +[Worker] method constructor [Worker] interface Event [Worker] attribute @@toStringTag [Worker] attribute AT_TARGET
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index de901a7..57aeb0c 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - [INTERFACES] interface AbortController attribute @@toStringTag
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-platform-specific-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-platform-specific-expected.txt index 72d6afde..f27f170 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-platform-specific-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-platform-specific-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - [INTERFACES] interface Bluetooth attribute @@toStringTag
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt index ec6454a2..fc5cd07 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - Starting worker: resources/global-interface-listing-worker.js [Worker] [INTERFACES] [Worker] interface AbortController @@ -324,6 +323,14 @@ [Worker] method constructor [Worker] method contains [Worker] method item +[Worker] interface ErrorEvent : Event +[Worker] attribute @@toStringTag +[Worker] getter colno +[Worker] getter error +[Worker] getter filename +[Worker] getter lineno +[Worker] getter message +[Worker] method constructor [Worker] interface Event [Worker] attribute @@toStringTag [Worker] attribute AT_TARGET
diff --git a/third_party/blink/web_tests/webexposed/internal-properties-should-not-be-exposed-expected.txt b/third_party/blink/web_tests/webexposed/internal-properties-should-not-be-exposed-expected.txt index 5aab4d9..605710aa 100644 --- a/third_party/blink/web_tests/webexposed/internal-properties-should-not-be-exposed-expected.txt +++ b/third_party/blink/web_tests/webexposed/internal-properties-should-not-be-exposed-expected.txt
@@ -1,12 +1,15 @@ This test checks that -internal-* properties are not exposed to JS. + + Testing -internal-marquee-direction PASS window.getComputedStyle(element).getPropertyValue(property) is "" PASS element.style[property] is undefined. Value after setting -internal-marquee-direction to alternate PASS element.style[property] is undefined. + PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/webexposed/nonstable-css-properties-expected.txt b/third_party/blink/web_tests/webexposed/nonstable-css-properties-expected.txt index afd01b0..ce318b34 100644 --- a/third_party/blink/web_tests/webexposed/nonstable-css-properties-expected.txt +++ b/third_party/blink/web_tests/webexposed/nonstable-css-properties-expected.txt
@@ -2,107 +2,131 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - el.style.setProperty('shape-margin', '10px') el.style.getPropertyValue('shape-margin') is 10px getComputedStyle(el).getPropertyValue('shape-margin') is 10px + el.style.setProperty('shape-outside', 'circle(10px at 10px 10px)') el.style.getPropertyValue('shape-outside') is circle(10px at 10px 10px) getComputedStyle(el).getPropertyValue('shape-outside') is circle(10px at 10px 10px) + el.style.setProperty('grid-auto-columns', 'auto') el.style.getPropertyValue('grid-auto-columns') is auto getComputedStyle(el).getPropertyValue('grid-auto-columns') is auto + el.style.setProperty('grid-auto-rows', 'auto') el.style.getPropertyValue('grid-auto-rows') is auto getComputedStyle(el).getPropertyValue('grid-auto-rows') is auto + el.style.setProperty('grid-template-columns', 'min-content') el.style.getPropertyValue('grid-template-columns') is min-content getComputedStyle(el).getPropertyValue('grid-template-columns') is min-content + el.style.setProperty('grid-template-rows', 'max-content') el.style.getPropertyValue('grid-template-rows') is max-content getComputedStyle(el).getPropertyValue('grid-template-rows') is max-content + el.style.setProperty('grid-column-start', 'auto') el.style.getPropertyValue('grid-column-start') is auto getComputedStyle(el).getPropertyValue('grid-column-start') is auto + el.style.setProperty('grid-column-end', '2') el.style.getPropertyValue('grid-column-end') is 2 getComputedStyle(el).getPropertyValue('grid-column-end') is 2 + el.style.setProperty('grid-row-start', '1') el.style.getPropertyValue('grid-row-start') is 1 getComputedStyle(el).getPropertyValue('grid-row-start') is 1 + el.style.setProperty('grid-column', 'auto') el.style.getPropertyValue('grid-column') is auto / auto getComputedStyle(el).getPropertyValue('grid-column') is auto / auto + el.style.setProperty('grid-row', '1') el.style.getPropertyValue('grid-row') is 1 / auto getComputedStyle(el).getPropertyValue('grid-row') is 1 / auto + el.style.setProperty('grid-area', '2') el.style.getPropertyValue('grid-area') is 2 / auto / auto / auto getComputedStyle(el).getPropertyValue('grid-area') is 2 / auto / auto / auto + el.style.setProperty('grid-auto-flow', 'column') el.style.getPropertyValue('grid-auto-flow') is column getComputedStyle(el).getPropertyValue('grid-auto-flow') is column + el.style.setProperty('grid-template-areas', '"test"') el.style.getPropertyValue('grid-template-areas') is "test" getComputedStyle(el).getPropertyValue('grid-template-areas') is "test" + el.style.setProperty('text-justify', 'distribute') el.style.getPropertyValue('text-justify') is distribute getComputedStyle(el).getPropertyValue('text-justify') is distribute + el.style.setProperty('text-underline-position', 'left') el.style.getPropertyValue('text-underline-position') is left getComputedStyle(el).getPropertyValue('text-underline-position') is left + el.style.setProperty('text-underline-position', 'right') el.style.getPropertyValue('text-underline-position') is right getComputedStyle(el).getPropertyValue('text-underline-position') is right + el.style.setProperty('text-underline-position', 'under left') el.style.getPropertyValue('text-underline-position') is under left getComputedStyle(el).getPropertyValue('text-underline-position') is under left + el.style.setProperty('text-underline-position', 'right under') el.style.getPropertyValue('text-underline-position') is under right getComputedStyle(el).getPropertyValue('text-underline-position') is under right + el.style.setProperty('clear', 'inline-start') el.style.getPropertyValue('clear') is inline-start getComputedStyle(el).getPropertyValue('clear') is inline-start + el.style.setProperty('clear', 'inline-end') el.style.getPropertyValue('clear') is inline-end getComputedStyle(el).getPropertyValue('clear') is inline-end + el.style.setProperty('float', 'inline-start') el.style.getPropertyValue('float') is inline-start getComputedStyle(el).getPropertyValue('float') is inline-start + el.style.setProperty('float', 'inline-end') el.style.getPropertyValue('float') is inline-end getComputedStyle(el).getPropertyValue('float') is inline-end + el.style.setProperty('resize', 'block') el.style.getPropertyValue('resize') is block getComputedStyle(el).getPropertyValue('resize') is block + el.style.setProperty('resize', 'inline') el.style.getPropertyValue('resize') is inline getComputedStyle(el).getPropertyValue('resize') is inline + PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/webexposed/permissions-attribute-expected.txt b/third_party/blink/web_tests/webexposed/permissions-attribute-expected.txt index ee94514..da873da 100644 --- a/third_party/blink/web_tests/webexposed/permissions-attribute-expected.txt +++ b/third_party/blink/web_tests/webexposed/permissions-attribute-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/webmidi/implicit-open-expected.txt b/third_party/blink/web_tests/webmidi/implicit-open-expected.txt index ee00c38e..033860d69 100644 --- a/third_party/blink/web_tests/webmidi/implicit-open-expected.txt +++ b/third_party/blink/web_tests/webmidi/implicit-open-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS PermissionsHelper.setPermission is defined. PASS requestMIDIAccess() succeeded with access [object MIDIAccess]. Check state transition for setonmidimessage on closed state.
diff --git a/third_party/blink/web_tests/webmidi/loopback-receive-expected.txt b/third_party/blink/web_tests/webmidi/loopback-receive-expected.txt index 95d751e..becb11a2 100644 --- a/third_party/blink/web_tests/webmidi/loopback-receive-expected.txt +++ b/third_party/blink/web_tests/webmidi/loopback-receive-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS navigator.requestMIDIAccess is defined. running test with useAddEventListener = false receiving data 0: 128,0,0
diff --git a/third_party/blink/web_tests/webmidi/open-close-expected.txt b/third_party/blink/web_tests/webmidi/open-close-expected.txt index 22e558bb..82f685d 100644 --- a/third_party/blink/web_tests/webmidi/open-close-expected.txt +++ b/third_party/blink/web_tests/webmidi/open-close-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS PermissionsHelper.setPermission is defined. PASS requestMIDIAccess() succeeded with access [object MIDIAccess]. Check state transition for close on closed state.
diff --git a/third_party/blink/web_tests/webmidi/permission-expected.txt b/third_party/blink/web_tests/webmidi/permission-expected.txt index 65441331..6596321 100644 --- a/third_party/blink/web_tests/webmidi/permission-expected.txt +++ b/third_party/blink/web_tests/webmidi/permission-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS navigator.requestMIDIAccess is defined. PASS PermissionsHelper.setPermission is defined. PASS promise is defined.
diff --git a/third_party/blink/web_tests/webmidi/requestmidiaccess-basic-expected.txt b/third_party/blink/web_tests/webmidi/requestmidiaccess-basic-expected.txt index bc78381..fa4ae18 100644 --- a/third_party/blink/web_tests/webmidi/requestmidiaccess-basic-expected.txt +++ b/third_party/blink/web_tests/webmidi/requestmidiaccess-basic-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS navigator.requestMIDIAccess is defined. PASS promise is defined. PASS promise.then is defined.
diff --git a/third_party/blink/web_tests/webmidi/requestmidiaccess-expected.txt b/third_party/blink/web_tests/webmidi/requestmidiaccess-expected.txt index 71d1265..1dd4d99f 100644 --- a/third_party/blink/web_tests/webmidi/requestmidiaccess-expected.txt +++ b/third_party/blink/web_tests/webmidi/requestmidiaccess-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS PermissionsHelper.setPermission is defined. PASS requestMIDIAccess() succeeded with access [object MIDIAccess]. PASS access.sysexEnabled is defined.
diff --git a/third_party/blink/web_tests/webmidi/requestmidiaccess-fail-expected.txt b/third_party/blink/web_tests/webmidi/requestmidiaccess-fail-expected.txt index 8c9aad4..473a110b 100644 --- a/third_party/blink/web_tests/webmidi/requestmidiaccess-fail-expected.txt +++ b/third_party/blink/web_tests/webmidi/requestmidiaccess-fail-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS PermissionsHelper.setPermission is defined. PASS errorName is 'InvalidStateError' PASS requestMIDIAccess() fail as expected.
diff --git a/third_party/blink/web_tests/webmidi/requestmidiaccess-in-detached-frame-expected.txt b/third_party/blink/web_tests/webmidi/requestmidiaccess-in-detached-frame-expected.txt index 711be74d..2c3373f 100644 --- a/third_party/blink/web_tests/webmidi/requestmidiaccess-in-detached-frame-expected.txt +++ b/third_party/blink/web_tests/webmidi/requestmidiaccess-in-detached-frame-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS errorName is "AbortError" PASS requestMIDIAccess() fail as expected. PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/webmidi/requestmidiaccess-options-expected.txt b/third_party/blink/web_tests/webmidi/requestmidiaccess-options-expected.txt index 83ae6a7..dbddd4f 100644 --- a/third_party/blink/web_tests/webmidi/requestmidiaccess-options-expected.txt +++ b/third_party/blink/web_tests/webmidi/requestmidiaccess-options-expected.txt
@@ -2,58 +2,66 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS navigator.requestMIDIAccess is defined. PASS PermissionsHelper.setPermission is defined. + Start test with following configurations: options: {} configurations: {"midi":"denied","sysex":"denied"} PASS permissions[permissionIndex].midi is 'denied' Done. + Start test with following configurations: options: {"sysex":false} configurations: {"midi":"denied","sysex":"denied"} PASS permissions[permissionIndex].midi is 'denied' Done. + Start test with following configurations: options: {"sysex":true} configurations: {"midi":"denied","sysex":"denied"} PASS permissions[permissionIndex].sysex is 'denied' Done. + Start test with following configurations: options: {} configurations: {"midi":"granted","sysex":"denied"} PASS permissions[permissionIndex].midi is 'granted' Done. + Start test with following configurations: options: {"sysex":false} configurations: {"midi":"granted","sysex":"denied"} PASS permissions[permissionIndex].midi is 'granted' Done. + Start test with following configurations: options: {"sysex":true} configurations: {"midi":"granted","sysex":"denied"} PASS permissions[permissionIndex].sysex is 'denied' Done. + Start test with following configurations: options: {} configurations: {"midi":"granted","sysex":"granted"} PASS permissions[permissionIndex].midi is 'granted' Done. + Start test with following configurations: options: {"sysex":false} configurations: {"midi":"granted","sysex":"granted"} PASS permissions[permissionIndex].midi is 'granted' Done. + Start test with following configurations: options: {"sysex":true} configurations: {"midi":"granted","sysex":"granted"}
diff --git a/third_party/blink/web_tests/webmidi/send-messages-expected.txt b/third_party/blink/web_tests/webmidi/send-messages-expected.txt index 27b298d..452bf1e 100644 --- a/third_party/blink/web_tests/webmidi/send-messages-expected.txt +++ b/third_party/blink/web_tests/webmidi/send-messages-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS navigator.requestMIDIAccess is defined. PASS output.send([0x00, 0x01]) threw exception TypeError: Failed to execute 'send' on 'MIDIOutput': Running status is not allowed at index 0 (0).. PASS output.send([0xf7]) threw exception TypeError: Failed to execute 'send' on 'MIDIOutput': Unexpected end of system exclusive message at index 0 (247)..
diff --git a/third_party/blink/web_tests/webmidi/send-system-messages-expected.txt b/third_party/blink/web_tests/webmidi/send-system-messages-expected.txt index b453e8d..35110279 100644 --- a/third_party/blink/web_tests/webmidi/send-system-messages-expected.txt +++ b/third_party/blink/web_tests/webmidi/send-system-messages-expected.txt
@@ -2,7 +2,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - PASS output.send([241,0]) PASS output.send([241,0,241,0]) PASS output.send([241,0,241,0,241,0])
diff --git a/third_party/closure_compiler/externs/pending.js b/third_party/closure_compiler/externs/pending.js index 2f8e0af..b90ab81 100644 --- a/third_party/closure_compiler/externs/pending.js +++ b/third_party/closure_compiler/externs/pending.js
@@ -124,3 +124,12 @@ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap */ Array.prototype.flatMap = function(callback, opt_this) {}; + +/** + * @param {string} name + * @param {boolean=} force + * @return {boolean} + * @throws {DOMException} + * @see https://dom.spec.whatwg.org/#dom-element-toggleattribute + */ +Element.prototype.toggleAttribute = function(name, force) {};
diff --git a/third_party/feed/README.chromium b/third_party/feed/README.chromium index 1304ba2..d7e9ace4 100644 --- a/third_party/feed/README.chromium +++ b/third_party/feed/README.chromium
@@ -2,7 +2,7 @@ Short name: feed URL: https://chromium.googlesource.com/feed Version: 0 -Revision: 5eaab0ec4f162c4f8d7901e14333127b16bcb7ac +Revision: 8f0baf678cd55565412717d583f036a9b529bfdc License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/third_party/feed/java_sources.gni b/third_party/feed/java_sources.gni index 43bd1f5ea..131a8479 100644 --- a/third_party/feed/java_sources.gni +++ b/third_party/feed/java_sources.gni
@@ -268,5 +268,7 @@ "src/src/main/java/com/google/android/libraries/feed/testing/conformance/network/NetworkClientConformanceTest.java", "src/src/main/java/com/google/android/libraries/feed/testing/conformance/scheduler/SchedulerConformanceTest.java", "src/src/main/java/com/google/android/libraries/feed/testing/conformance/storage/ContentStorageConformanceTest.java", + "src/src/main/java/com/google/android/libraries/feed/testing/conformance/storage/ContentStorageDirectConformanceTest.java", "src/src/main/java/com/google/android/libraries/feed/testing/conformance/storage/JournalStorageConformanceTest.java", + "src/src/main/java/com/google/android/libraries/feed/testing/conformance/storage/JournalStorageDirectConformanceTest.java", ]
diff --git a/third_party/feed/proto_sources.gni b/third_party/feed/proto_sources.gni index 8bdb85e..695713f 100644 --- a/third_party/feed/proto_sources.gni +++ b/third_party/feed/proto_sources.gni
@@ -3,6 +3,7 @@ # found in the LICENSE file. feed_lib_proto_sources = [ + "src/src/main/java/com/google/android/libraries/feed/sharedstream/proto/scroll_state.proto", "src/src/main/proto/com/google/android/libraries/feed/api/proto/stream_data.proto", "src/src/main/proto/com/google/android/libraries/feed/basicstream/internal/proto/stream_saved_instance_state.proto", "src/src/main/proto/search/now/ui/action/feed_action.proto",
diff --git a/third_party/fontconfig/BUILD.gn b/third_party/fontconfig/BUILD.gn index 36f8800..3175758 100644 --- a/third_party/fontconfig/BUILD.gn +++ b/third_party/fontconfig/BUILD.gn
@@ -76,9 +76,6 @@ configs += [ "//build/config/compiler:no_chromium_code" ] public_configs = [ ":fontconfig_config" ] - public_deps = [ - "//third_party:freetype_harfbuzz", - ] if (is_clang) { cflags = [
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index cd13ed30..37de1d9f 100644 --- a/third_party/freetype/README.chromium +++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@ Name: FreeType URL: http://www.freetype.org/ -Version: VER-2-9-1-313 -Revision: 3dd4e76b19f3cd4f706c3455d6ae01765d07eee5 +Version: VER-2-9-1-317 +Revision: d01e28f41f8810c8ea422b854f8722659589fa99 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses" License File: src/docs/FTL.TXT
diff --git a/third_party/harfbuzz-ng/BUILD.gn b/third_party/harfbuzz-ng/BUILD.gn index 578c3a31..1dfcf27 100644 --- a/third_party/harfbuzz-ng/BUILD.gn +++ b/third_party/harfbuzz-ng/BUILD.gn
@@ -45,6 +45,7 @@ visibility = [ "//third_party:freetype_harfbuzz" ] sources = [ + "src/src/hb-aat-fdsc-table.hh", "src/src/hb-aat-layout-ankr-table.hh", "src/src/hb-aat-layout-bsln-table.hh", "src/src/hb-aat-layout-feat-table.hh", @@ -103,6 +104,7 @@ "src/src/hb-ot-face.hh", "src/src/hb-ot-font.cc", "src/src/hb-ot-font.h", + "src/src/hb-ot-gasp-table.hh", "src/src/hb-ot-hdmx-table.hh", "src/src/hb-ot-head-table.hh", "src/src/hb-ot-hhea-table.hh",
diff --git a/third_party/harfbuzz-ng/README.chromium b/third_party/harfbuzz-ng/README.chromium index ac74112..d1620c8 100644 --- a/third_party/harfbuzz-ng/README.chromium +++ b/third_party/harfbuzz-ng/README.chromium
@@ -1,9 +1,9 @@ Name: harfbuzz-ng Short Name: harfbuzz-ng URL: http://harfbuzz.org -Version: 2.2.0-265 -Date: 20181205 -Revision: 79e7e3445efef2dc57f8a10c7e355e802af08868 +Version: 2.2.0-298 +Date: 20181207 +Revision: 59345cdef38cf1f514a6a0eb6e8852350acb6166 Security Critical: yes License: MIT License File: src/COPYING
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium index 7f38600..f6ea001 100644 --- a/third_party/libvpx/README.chromium +++ b/third_party/libvpx/README.chromium
@@ -5,9 +5,9 @@ License File: source/libvpx/LICENSE Security Critical: yes -Date: Thursday November 29 2018 +Date: Friday December 07 2018 Branch: master -Commit: 932f8fa04dc15f4adf16df37402556e8c4dc72e7 +Commit: 418acaa0bd06e0666d5a55743e3a85b83c759619 Description: Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/generate_gni.sh b/third_party/libvpx/generate_gni.sh index 692b6fb2..899ed25 100755 --- a/third_party/libvpx/generate_gni.sh +++ b/third_party/libvpx/generate_gni.sh
@@ -354,8 +354,8 @@ gen_config_files linux/mips64el "--target=mips64-linux-gcc ${all_platforms}" gen_config_files linux/generic "--target=generic-gnu $HIGHBD ${all_platforms}" gen_config_files win/arm64 "--target=arm64-win64-vs15 ${all_platforms} ${HIGHBD}" -gen_config_files win/ia32 "--target=x86-win32-vs12 ${all_platforms} ${x86_platforms}" -gen_config_files win/x64 "--target=x86_64-win64-vs12 ${all_platforms} ${x86_platforms}" +gen_config_files win/ia32 "--target=x86-win32-vs14 ${all_platforms} ${x86_platforms}" +gen_config_files win/x64 "--target=x86_64-win64-vs14 ${all_platforms} ${x86_platforms}" gen_config_files mac/ia32 "--target=x86-darwin9-gcc ${all_platforms} ${x86_platforms}" gen_config_files mac/x64 "--target=x86_64-darwin9-gcc ${all_platforms} ${x86_platforms}" gen_config_files ios/arm-neon "--target=armv7-linux-gcc ${all_platforms}"
diff --git a/third_party/libvpx/libvpx_srcs.gni b/third_party/libvpx/libvpx_srcs.gni index 30560ea..67453749 100644 --- a/third_party/libvpx/libvpx_srcs.gni +++ b/third_party/libvpx/libvpx_srcs.gni
@@ -333,6 +333,7 @@ "//third_party/libvpx/source/libvpx/vpx_dsp/x86/inv_txfm_ssse3.h", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/mem_sse2.h", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/quantize_sse2.h", + "//third_party/libvpx/source/libvpx/vpx_dsp/x86/quantize_ssse3.h", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/transpose_sse2.h", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/txfm_common_sse2.h", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/vpx_asm_stubs.c", @@ -809,6 +810,7 @@ "//third_party/libvpx/source/libvpx/vpx_dsp/x86/inv_txfm_ssse3.h", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/mem_sse2.h", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/quantize_sse2.h", + "//third_party/libvpx/source/libvpx/vpx_dsp/x86/quantize_ssse3.h", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/transpose_sse2.h", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/txfm_common_sse2.h", "//third_party/libvpx/source/libvpx/vpx_dsp/x86/vpx_asm_stubs.c",
diff --git a/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h index b2b02a5..2cf6856 100644 --- a/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/linux/ia32/vpx_dsp_rtcd.h
@@ -3962,7 +3962,12 @@ void vpx_highbd_hadamard_8x8_c(const int16_t* src_diff, ptrdiff_t src_stride, tran_low_t* coeff); -#define vpx_highbd_hadamard_8x8 vpx_highbd_hadamard_8x8_c +void vpx_highbd_hadamard_8x8_avx2(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); +RTCD_EXTERN void (*vpx_highbd_hadamard_8x8)(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); void vpx_highbd_idct16x16_10_add_c(const tran_low_t* input, uint16_t* dest, @@ -7687,6 +7692,9 @@ vpx_highbd_d63_predictor_8x8 = vpx_highbd_d63_predictor_8x8_c; if (flags & HAS_SSSE3) vpx_highbd_d63_predictor_8x8 = vpx_highbd_d63_predictor_8x8_ssse3; + vpx_highbd_hadamard_8x8 = vpx_highbd_hadamard_8x8_c; + if (flags & HAS_AVX2) + vpx_highbd_hadamard_8x8 = vpx_highbd_hadamard_8x8_avx2; vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_sse2; if (flags & HAS_SSE4_1) vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_sse4_1;
diff --git a/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h index 3b28a11..5b5d17b 100644 --- a/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/linux/x64/vpx_dsp_rtcd.h
@@ -4039,7 +4039,12 @@ void vpx_highbd_hadamard_8x8_c(const int16_t* src_diff, ptrdiff_t src_stride, tran_low_t* coeff); -#define vpx_highbd_hadamard_8x8 vpx_highbd_hadamard_8x8_c +void vpx_highbd_hadamard_8x8_avx2(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); +RTCD_EXTERN void (*vpx_highbd_hadamard_8x8)(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); void vpx_highbd_idct16x16_10_add_c(const tran_low_t* input, uint16_t* dest, @@ -7767,6 +7772,9 @@ vpx_highbd_d63_predictor_8x8 = vpx_highbd_d63_predictor_8x8_c; if (flags & HAS_SSSE3) vpx_highbd_d63_predictor_8x8 = vpx_highbd_d63_predictor_8x8_ssse3; + vpx_highbd_hadamard_8x8 = vpx_highbd_hadamard_8x8_c; + if (flags & HAS_AVX2) + vpx_highbd_hadamard_8x8 = vpx_highbd_hadamard_8x8_avx2; vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_sse2; if (flags & HAS_SSE4_1) vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_sse4_1;
diff --git a/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h index b2b02a5..2cf6856 100644 --- a/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/mac/ia32/vpx_dsp_rtcd.h
@@ -3962,7 +3962,12 @@ void vpx_highbd_hadamard_8x8_c(const int16_t* src_diff, ptrdiff_t src_stride, tran_low_t* coeff); -#define vpx_highbd_hadamard_8x8 vpx_highbd_hadamard_8x8_c +void vpx_highbd_hadamard_8x8_avx2(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); +RTCD_EXTERN void (*vpx_highbd_hadamard_8x8)(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); void vpx_highbd_idct16x16_10_add_c(const tran_low_t* input, uint16_t* dest, @@ -7687,6 +7692,9 @@ vpx_highbd_d63_predictor_8x8 = vpx_highbd_d63_predictor_8x8_c; if (flags & HAS_SSSE3) vpx_highbd_d63_predictor_8x8 = vpx_highbd_d63_predictor_8x8_ssse3; + vpx_highbd_hadamard_8x8 = vpx_highbd_hadamard_8x8_c; + if (flags & HAS_AVX2) + vpx_highbd_hadamard_8x8 = vpx_highbd_hadamard_8x8_avx2; vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_sse2; if (flags & HAS_SSE4_1) vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_sse4_1;
diff --git a/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h index 3b28a11..5b5d17b 100644 --- a/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/mac/x64/vpx_dsp_rtcd.h
@@ -4039,7 +4039,12 @@ void vpx_highbd_hadamard_8x8_c(const int16_t* src_diff, ptrdiff_t src_stride, tran_low_t* coeff); -#define vpx_highbd_hadamard_8x8 vpx_highbd_hadamard_8x8_c +void vpx_highbd_hadamard_8x8_avx2(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); +RTCD_EXTERN void (*vpx_highbd_hadamard_8x8)(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); void vpx_highbd_idct16x16_10_add_c(const tran_low_t* input, uint16_t* dest, @@ -7767,6 +7772,9 @@ vpx_highbd_d63_predictor_8x8 = vpx_highbd_d63_predictor_8x8_c; if (flags & HAS_SSSE3) vpx_highbd_d63_predictor_8x8 = vpx_highbd_d63_predictor_8x8_ssse3; + vpx_highbd_hadamard_8x8 = vpx_highbd_hadamard_8x8_c; + if (flags & HAS_AVX2) + vpx_highbd_hadamard_8x8 = vpx_highbd_hadamard_8x8_avx2; vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_sse2; if (flags & HAS_SSE4_1) vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_sse4_1;
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h index ff39bf83..e11db916 100644 --- a/third_party/libvpx/source/config/vpx_version.h +++ b/third_party/libvpx/source/config/vpx_version.h
@@ -2,7 +2,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 7 #define VERSION_PATCH 0 -#define VERSION_EXTRA "1420-g932f8fa04" +#define VERSION_EXTRA "1462-g418acaa0b" #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH)) -#define VERSION_STRING_NOSP "v1.7.0-1420-g932f8fa04" -#define VERSION_STRING " v1.7.0-1420-g932f8fa04" +#define VERSION_STRING_NOSP "v1.7.0-1462-g418acaa0b" +#define VERSION_STRING " v1.7.0-1462-g418acaa0b"
diff --git a/third_party/libvpx/source/config/win/arm64/vpx_config.h b/third_party/libvpx/source/config/win/arm64/vpx_config.h index e567c26ef..0f793cb6 100644 --- a/third_party/libvpx/source/config/win/arm64/vpx_config.h +++ b/third_party/libvpx/source/config/win/arm64/vpx_config.h
@@ -8,8 +8,8 @@ /* This file automatically generated by configure. Do not edit! */ #ifndef VPX_CONFIG_H #define VPX_CONFIG_H -#define RESTRICT -#define INLINE __inline +#define RESTRICT +#define INLINE __inline #define ARCH_ARM 1 #define ARCH_MIPS 0 #define ARCH_X86 0
diff --git a/third_party/libvpx/source/config/win/ia32/vpx_config.c b/third_party/libvpx/source/config/win/ia32/vpx_config.c index 7f90ecc..9f7d5be 100644 --- a/third_party/libvpx/source/config/win/ia32/vpx_config.c +++ b/third_party/libvpx/source/config/win/ia32/vpx_config.c
@@ -6,5 +6,5 @@ /* in the file PATENTS. All contributing project authors may */ /* be found in the AUTHORS file in the root of the source tree. */ #include "vpx/vpx_codec.h" -static const char* const cfg = "--target=x86-win32-vs12 --enable-external-build --enable-postproc --enable-multi-res-encoding --enable-temporal-denoising --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --enable-realtime-only --disable-install-docs --enable-pic --as=yasm --disable-avx512 --enable-vp9-highbitdepth"; +static const char* const cfg = "--target=x86-win32-vs14 --enable-external-build --enable-postproc --enable-multi-res-encoding --enable-temporal-denoising --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --enable-realtime-only --disable-install-docs --enable-pic --as=yasm --disable-avx512 --enable-vp9-highbitdepth"; const char *vpx_codec_build_config(void) {return cfg;}
diff --git a/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h index b2b02a5..2cf6856 100644 --- a/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/win/ia32/vpx_dsp_rtcd.h
@@ -3962,7 +3962,12 @@ void vpx_highbd_hadamard_8x8_c(const int16_t* src_diff, ptrdiff_t src_stride, tran_low_t* coeff); -#define vpx_highbd_hadamard_8x8 vpx_highbd_hadamard_8x8_c +void vpx_highbd_hadamard_8x8_avx2(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); +RTCD_EXTERN void (*vpx_highbd_hadamard_8x8)(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); void vpx_highbd_idct16x16_10_add_c(const tran_low_t* input, uint16_t* dest, @@ -7687,6 +7692,9 @@ vpx_highbd_d63_predictor_8x8 = vpx_highbd_d63_predictor_8x8_c; if (flags & HAS_SSSE3) vpx_highbd_d63_predictor_8x8 = vpx_highbd_d63_predictor_8x8_ssse3; + vpx_highbd_hadamard_8x8 = vpx_highbd_hadamard_8x8_c; + if (flags & HAS_AVX2) + vpx_highbd_hadamard_8x8 = vpx_highbd_hadamard_8x8_avx2; vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_sse2; if (flags & HAS_SSE4_1) vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_sse4_1;
diff --git a/third_party/libvpx/source/config/win/x64/vpx_config.c b/third_party/libvpx/source/config/win/x64/vpx_config.c index 1d316b7..a5a6e03 100644 --- a/third_party/libvpx/source/config/win/x64/vpx_config.c +++ b/third_party/libvpx/source/config/win/x64/vpx_config.c
@@ -6,5 +6,5 @@ /* in the file PATENTS. All contributing project authors may */ /* be found in the AUTHORS file in the root of the source tree. */ #include "vpx/vpx_codec.h" -static const char* const cfg = "--target=x86_64-win64-vs12 --enable-external-build --enable-postproc --enable-multi-res-encoding --enable-temporal-denoising --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --enable-realtime-only --disable-install-docs --enable-pic --as=yasm --disable-avx512 --enable-vp9-highbitdepth"; +static const char* const cfg = "--target=x86_64-win64-vs14 --enable-external-build --enable-postproc --enable-multi-res-encoding --enable-temporal-denoising --enable-vp9-temporal-denoising --enable-vp9-postproc --size-limit=16384x16384 --enable-realtime-only --disable-install-docs --enable-pic --as=yasm --disable-avx512 --enable-vp9-highbitdepth"; const char *vpx_codec_build_config(void) {return cfg;}
diff --git a/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h b/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h index 3b28a11..5b5d17b 100644 --- a/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h +++ b/third_party/libvpx/source/config/win/x64/vpx_dsp_rtcd.h
@@ -4039,7 +4039,12 @@ void vpx_highbd_hadamard_8x8_c(const int16_t* src_diff, ptrdiff_t src_stride, tran_low_t* coeff); -#define vpx_highbd_hadamard_8x8 vpx_highbd_hadamard_8x8_c +void vpx_highbd_hadamard_8x8_avx2(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); +RTCD_EXTERN void (*vpx_highbd_hadamard_8x8)(const int16_t* src_diff, + ptrdiff_t src_stride, + tran_low_t* coeff); void vpx_highbd_idct16x16_10_add_c(const tran_low_t* input, uint16_t* dest, @@ -7767,6 +7772,9 @@ vpx_highbd_d63_predictor_8x8 = vpx_highbd_d63_predictor_8x8_c; if (flags & HAS_SSSE3) vpx_highbd_d63_predictor_8x8 = vpx_highbd_d63_predictor_8x8_ssse3; + vpx_highbd_hadamard_8x8 = vpx_highbd_hadamard_8x8_c; + if (flags & HAS_AVX2) + vpx_highbd_hadamard_8x8 = vpx_highbd_hadamard_8x8_avx2; vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_sse2; if (flags & HAS_SSE4_1) vpx_highbd_idct16x16_10_add = vpx_highbd_idct16x16_10_add_sse4_1;
diff --git a/third_party/libwebp/BUILD.gn b/third_party/libwebp/BUILD.gn index 94ac4c65..1f93409a 100644 --- a/third_party/libwebp/BUILD.gn +++ b/third_party/libwebp/BUILD.gn
@@ -568,6 +568,7 @@ ":libwebp_webp", ] cflags_cc = [ "-Wno-unused-function" ] + defines = [ "WEBP_MAX_IMAGE_SIZE=838860800" ] additional_configs = [ ":libwebp_config_internal" ] } @@ -582,6 +583,7 @@ ":libwebp_webp", ] cflags_cc = [ "-Wno-unused-function" ] + defines = [ "WEBP_MAX_IMAGE_SIZE=838860800" ] additional_configs = [ ":libwebp_config_internal" ] } @@ -597,6 +599,7 @@ ":libwebp_webp", ] cflags_cc = [ "-Wno-unused-function" ] + defines = [ "WEBP_MAX_IMAGE_SIZE=838860800" ] additional_configs = [ ":libwebp_config_internal" ] } @@ -611,6 +614,7 @@ ":libwebp_webp", ] cflags_cc = [ "-Wno-unused-function" ] + defines = [ "WEBP_MAX_IMAGE_SIZE=838860800" ] additional_configs = [ ":libwebp_config_internal" ] } @@ -625,6 +629,7 @@ ":libwebp_webp", ] cflags_cc = [ "-Wno-unused-function" ] + defines = [ "WEBP_MAX_IMAGE_SIZE=838860800" ] additional_configs = [ ":libwebp_config_internal" ] } @@ -639,5 +644,6 @@ ":libwebp_webp", ] cflags_cc = [ "-Wno-unused-function" ] + defines = [ "WEBP_MAX_IMAGE_SIZE=838860800" ] additional_configs = [ ":libwebp_config_internal" ] }
diff --git a/third_party/r8/OWNERS b/third_party/r8/OWNERS index 85d7ba74..fffc56f0 100644 --- a/third_party/r8/OWNERS +++ b/third_party/r8/OWNERS
@@ -1,2 +1,3 @@ +smaier@chromium.org estevenson@chromium.org -agrieve@chromium.org \ No newline at end of file +agrieve@chromium.org
diff --git a/third_party/r8/README.chromium b/third_party/r8/README.chromium index e7cdbf8..0d13c15 100644 --- a/third_party/r8/README.chromium +++ b/third_party/r8/README.chromium
@@ -1,7 +1,7 @@ Name: R8 URL: https://r8.googlesource.com/r8 -Revision: 6116972ceac511b57c91aabd9e9fc0ed6e58381f -Version: 1.4.13-dev +Revision: 03ab76ff37d7995f76b639dec680cd49ff6fbc41 +Version: 1.4.14-dev License: BSD 3-Clause License File: NOT_SHIPPED Security Critical: no
diff --git a/third_party/sqlite/BUILD.gn b/third_party/sqlite/BUILD.gn index cbd700a..7c6e8a1 100644 --- a/third_party/sqlite/BUILD.gn +++ b/third_party/sqlite/BUILD.gn
@@ -183,8 +183,8 @@ } if (using_sanitizer) { - # Limit max length of data blobs and queries to 128 MB for fuzzing builds. defines += [ + # Limit max length of data blobs and queries to 128 MB for fuzzing builds. "SQLITE_MAX_LENGTH=128000000", "SQLITE_MAX_SQL_LENGTH=128000000", "SQLITE_PRINTF_PRECISION_LIMIT=1280000", @@ -197,7 +197,13 @@ # pages, so fuzzer will not crash when reaching the limit. # Apply this for fuzzing builds only, not for all builds with sanitizers. if (use_fuzzing_engine) { - defines += [ "SQLITE_MAX_PAGE_COUNT=16384" ] + defines += [ + "SQLITE_MAX_PAGE_COUNT=16384", + + # Used to deserialize a database from a libfuzzer-provided data blob. + # This is to fuzz SQLite's resilience to database corruption. + "SQLITE_ENABLE_DESERIALIZE", + ] } } @@ -419,3 +425,23 @@ ] dict = "fuzz/sql.dict" } + +config("sqlite3_dbfuzz2_config") { + cflags = [ "-Wno-sign-compare" ] + configs = [ ":sqlite_warnings" ] +} + +# Upstream fuzzer that tests corrupted database files. +if (use_fuzzing_engine) { + fuzzer_test("sqlite3_dbfuzz2_fuzzer") { + include_dirs = [ "." ] + sources = [ + "src/test/dbfuzz2.c", + ] + deps = [ + ":sqlite", + ] + additional_configs = [ ":sqlite3_dbfuzz2_config" ] + seed_corpus = "fuzz/db_corpus" + } +}
diff --git a/third_party/sqlite/README.chromium b/third_party/sqlite/README.chromium index 6eb0320c..0f82951 100644 --- a/third_party/sqlite/README.chromium +++ b/third_party/sqlite/README.chromium
@@ -1,6 +1,6 @@ Name: sqlite URL: https://sqlite.org/ -Version: 3.25.3 +Version: 3.26.0 Included In Release: Yes Security Critical: Yes License: Public domain @@ -150,8 +150,8 @@ # The numbers below are SQLite version numbers, and use upstream's convention # for tagging release binaries and source zipballs. -export OLD=3250300 -export NEW=3260000 +export OLD=3260000 +export NEW=3270000 export GNU_SED=sed # OSX: "brew install gnu-sed", then use "gsed" here. #### Download and unpack the new SQLite release. @@ -220,6 +220,14 @@ ./scripts/generate_amalgamation.sh git cl format amalgamation/rename_exports.h +#### Copy any new entries to the seed-corpus for dbfuzz2. +# We use a set of seed databases for fuzzing SQLite's resilience to database +# corruption. Sometimes, new seed databases are added upstream. +# Find any files of the pattern src/test/dbfuzz2-seed*.db, and copy them to +# the fuzz/db_corpus directory. +cp --no-clobber third_party/sqlite/src/test/dbfuzz2-seed*.db \ + third_party/sqlite/fuzz/db_corpus + #### Validate the upgrade. # The goal is to have a set of reasonably-independent CLs which can be # understood separately, so that future importers can sensibly determine how to
diff --git a/third_party/sqlite/amalgamation/rename_exports.h b/third_party/sqlite/amalgamation/rename_exports.h index bbf27c2..84e9f331 100644 --- a/third_party/sqlite/amalgamation/rename_exports.h +++ b/third_party/sqlite/amalgamation/rename_exports.h
@@ -7,384 +7,390 @@ #ifndef THIRD_PARTY_SQLITE_AMALGAMATION_RENAME_EXPORTS_H_ #define THIRD_PARTY_SQLITE_AMALGAMATION_RENAME_EXPORTS_H_ -#define sqlite3_activate_cerod chrome_sqlite3_activate_cerod // Lines 5530-5532 -#define sqlite3_activate_see chrome_sqlite3_activate_see // Lines 5520-5522 -#define sqlite3_aggregate_context chrome_sqlite3_aggregate_context // Line 5067 -#define sqlite3_aggregate_count chrome_sqlite3_aggregate_count // Line 4850 -#define sqlite3_auto_extension chrome_sqlite3_auto_extension // Line 6196 -#define sqlite3_backup_finish chrome_sqlite3_backup_finish // Line 8187 -#define sqlite3_backup_init chrome_sqlite3_backup_init // Lines 8180-8185 -#define sqlite3_backup_pagecount chrome_sqlite3_backup_pagecount // Line 8189 -#define sqlite3_backup_remaining chrome_sqlite3_backup_remaining // Line 8188 -#define sqlite3_backup_step chrome_sqlite3_backup_step // Line 8186 -#define sqlite3_bind_blob chrome_sqlite3_bind_blob // Line 4025 -#define sqlite3_bind_blob64 chrome_sqlite3_bind_blob64 // Lines 4026-4027 -#define sqlite3_bind_double chrome_sqlite3_bind_double // Line 4028 -#define sqlite3_bind_int chrome_sqlite3_bind_int // Line 4029 -#define sqlite3_bind_int64 chrome_sqlite3_bind_int64 // Line 4030 -#define sqlite3_bind_null chrome_sqlite3_bind_null // Line 4031 +#define sqlite3_activate_cerod chrome_sqlite3_activate_cerod // Lines 5566-5568 +#define sqlite3_activate_see chrome_sqlite3_activate_see // Lines 5556-5558 +#define sqlite3_aggregate_context chrome_sqlite3_aggregate_context // Line 5103 +#define sqlite3_aggregate_count chrome_sqlite3_aggregate_count // Line 4886 +#define sqlite3_auto_extension chrome_sqlite3_auto_extension // Line 6232 +#define sqlite3_backup_finish chrome_sqlite3_backup_finish // Line 8227 +#define sqlite3_backup_init chrome_sqlite3_backup_init // Lines 8220-8225 +#define sqlite3_backup_pagecount chrome_sqlite3_backup_pagecount // Line 8229 +#define sqlite3_backup_remaining chrome_sqlite3_backup_remaining // Line 8228 +#define sqlite3_backup_step chrome_sqlite3_backup_step // Line 8226 +#define sqlite3_bind_blob chrome_sqlite3_bind_blob // Line 4061 +#define sqlite3_bind_blob64 chrome_sqlite3_bind_blob64 // Lines 4062-4063 +#define sqlite3_bind_double chrome_sqlite3_bind_double // Line 4064 +#define sqlite3_bind_int chrome_sqlite3_bind_int // Line 4065 +#define sqlite3_bind_int64 chrome_sqlite3_bind_int64 // Line 4066 +#define sqlite3_bind_null chrome_sqlite3_bind_null // Line 4067 #define sqlite3_bind_parameter_count \ - chrome_sqlite3_bind_parameter_count // Line 4060 + chrome_sqlite3_bind_parameter_count // Line 4096 #define sqlite3_bind_parameter_index \ - chrome_sqlite3_bind_parameter_index // Line 4106 + chrome_sqlite3_bind_parameter_index // Line 4142 #define sqlite3_bind_parameter_name \ - chrome_sqlite3_bind_parameter_name // Line 4088 -#define sqlite3_bind_pointer chrome_sqlite3_bind_pointer // Line 4037 -#define sqlite3_bind_text chrome_sqlite3_bind_text // Line 4032 -#define sqlite3_bind_text16 chrome_sqlite3_bind_text16 // Line 4033 -#define sqlite3_bind_text64 chrome_sqlite3_bind_text64 // Lines 4034-4035 -#define sqlite3_bind_value chrome_sqlite3_bind_value // Line 4036 -#define sqlite3_bind_zeroblob chrome_sqlite3_bind_zeroblob // Line 4038 -#define sqlite3_bind_zeroblob64 chrome_sqlite3_bind_zeroblob64 // Line 4039 -#define sqlite3_blob_bytes chrome_sqlite3_blob_bytes // Line 6742 -#define sqlite3_blob_close chrome_sqlite3_blob_close // Line 6726 -#define sqlite3_blob_open chrome_sqlite3_blob_open // Lines 6670-6678 -#define sqlite3_blob_read chrome_sqlite3_blob_read // Line 6771 -#define sqlite3_blob_reopen chrome_sqlite3_blob_reopen // Line 6703 -#define sqlite3_blob_write chrome_sqlite3_blob_write // Line 6813 -#define sqlite3_busy_handler chrome_sqlite3_busy_handler // Line 2485 -#define sqlite3_busy_timeout chrome_sqlite3_busy_timeout // Line 2508 + chrome_sqlite3_bind_parameter_name // Line 4124 +#define sqlite3_bind_pointer chrome_sqlite3_bind_pointer // Line 4073 +#define sqlite3_bind_text chrome_sqlite3_bind_text // Line 4068 +#define sqlite3_bind_text16 chrome_sqlite3_bind_text16 // Line 4069 +#define sqlite3_bind_text64 chrome_sqlite3_bind_text64 // Lines 4070-4071 +#define sqlite3_bind_value chrome_sqlite3_bind_value // Line 4072 +#define sqlite3_bind_zeroblob chrome_sqlite3_bind_zeroblob // Line 4074 +#define sqlite3_bind_zeroblob64 chrome_sqlite3_bind_zeroblob64 // Line 4075 +#define sqlite3_blob_bytes chrome_sqlite3_blob_bytes // Line 6781 +#define sqlite3_blob_close chrome_sqlite3_blob_close // Line 6765 +#define sqlite3_blob_open chrome_sqlite3_blob_open // Lines 6709-6717 +#define sqlite3_blob_read chrome_sqlite3_blob_read // Line 6810 +#define sqlite3_blob_reopen chrome_sqlite3_blob_reopen // Line 6742 +#define sqlite3_blob_write chrome_sqlite3_blob_write // Line 6852 +#define sqlite3_busy_handler chrome_sqlite3_busy_handler // Line 2504 +#define sqlite3_busy_timeout chrome_sqlite3_busy_timeout // Line 2527 #define sqlite3_cancel_auto_extension \ - chrome_sqlite3_cancel_auto_extension // Line 6208 -#define sqlite3_changes chrome_sqlite3_changes // Line 2314 -#define sqlite3_clear_bindings chrome_sqlite3_clear_bindings // Line 4116 + chrome_sqlite3_cancel_auto_extension // Line 6244 +#define sqlite3_changes chrome_sqlite3_changes // Line 2333 +#define sqlite3_clear_bindings chrome_sqlite3_clear_bindings // Line 4152 #define sqlite3_close chrome_sqlite3_close // Line 331 #define sqlite3_close_v2 chrome_sqlite3_close_v2 // Line 332 #define sqlite3_collation_needed \ - chrome_sqlite3_collation_needed // Lines 5469-5473 + chrome_sqlite3_collation_needed // Lines 5505-5509 #define sqlite3_collation_needed16 \ - chrome_sqlite3_collation_needed16 // Lines 5474-5478 -#define sqlite3_column_blob chrome_sqlite3_column_blob // Line 4596 -#define sqlite3_column_bytes chrome_sqlite3_column_bytes // Line 4603 -#define sqlite3_column_bytes16 chrome_sqlite3_column_bytes16 // Line 4604 -#define sqlite3_column_count chrome_sqlite3_column_count // Line 4132 + chrome_sqlite3_collation_needed16 // Lines 5510-5514 +#define sqlite3_column_blob chrome_sqlite3_column_blob // Line 4632 +#define sqlite3_column_bytes chrome_sqlite3_column_bytes // Line 4639 +#define sqlite3_column_bytes16 chrome_sqlite3_column_bytes16 // Line 4640 +#define sqlite3_column_count chrome_sqlite3_column_count // Line 4168 #define sqlite3_column_database_name \ - chrome_sqlite3_column_database_name // Line 4210 + chrome_sqlite3_column_database_name // Line 4246 #define sqlite3_column_database_name16 \ - chrome_sqlite3_column_database_name16 // Line 4211 -#define sqlite3_column_decltype chrome_sqlite3_column_decltype // Line 4247 -#define sqlite3_column_decltype16 chrome_sqlite3_column_decltype16 // Line 4248 -#define sqlite3_column_double chrome_sqlite3_column_double // Line 4597 -#define sqlite3_column_int chrome_sqlite3_column_int // Line 4598 -#define sqlite3_column_int64 chrome_sqlite3_column_int64 // Line 4599 -#define sqlite3_column_name chrome_sqlite3_column_name // Line 4161 -#define sqlite3_column_name16 chrome_sqlite3_column_name16 // Line 4162 + chrome_sqlite3_column_database_name16 // Line 4247 +#define sqlite3_column_decltype chrome_sqlite3_column_decltype // Line 4283 +#define sqlite3_column_decltype16 chrome_sqlite3_column_decltype16 // Line 4284 +#define sqlite3_column_double chrome_sqlite3_column_double // Line 4633 +#define sqlite3_column_int chrome_sqlite3_column_int // Line 4634 +#define sqlite3_column_int64 chrome_sqlite3_column_int64 // Line 4635 +#define sqlite3_column_name chrome_sqlite3_column_name // Line 4197 +#define sqlite3_column_name16 chrome_sqlite3_column_name16 // Line 4198 #define sqlite3_column_origin_name \ - chrome_sqlite3_column_origin_name // Line 4214 + chrome_sqlite3_column_origin_name // Line 4250 #define sqlite3_column_origin_name16 \ - chrome_sqlite3_column_origin_name16 // Line 4215 -#define sqlite3_column_table_name chrome_sqlite3_column_table_name // Line 4212 + chrome_sqlite3_column_origin_name16 // Line 4251 +#define sqlite3_column_table_name chrome_sqlite3_column_table_name // Line 4248 #define sqlite3_column_table_name16 \ - chrome_sqlite3_column_table_name16 // Line 4213 -#define sqlite3_column_text chrome_sqlite3_column_text // Line 4600 -#define sqlite3_column_text16 chrome_sqlite3_column_text16 // Line 4601 -#define sqlite3_column_type chrome_sqlite3_column_type // Line 4605 -#define sqlite3_column_value chrome_sqlite3_column_value // Line 4602 -#define sqlite3_commit_hook chrome_sqlite3_commit_hook // Line 5811 + chrome_sqlite3_column_table_name16 // Line 4249 +#define sqlite3_column_text chrome_sqlite3_column_text // Line 4636 +#define sqlite3_column_text16 chrome_sqlite3_column_text16 // Line 4637 +#define sqlite3_column_type chrome_sqlite3_column_type // Line 4641 +#define sqlite3_column_value chrome_sqlite3_column_value // Line 4638 +#define sqlite3_commit_hook chrome_sqlite3_commit_hook // Line 5847 #define sqlite3_compileoption_get chrome_sqlite3_compileoption_get // Line 191 #define sqlite3_compileoption_used \ chrome_sqlite3_compileoption_used // Line 190 -#define sqlite3_complete chrome_sqlite3_complete // Line 2423 -#define sqlite3_complete16 chrome_sqlite3_complete16 // Line 2424 +#define sqlite3_complete chrome_sqlite3_complete // Line 2442 +#define sqlite3_complete16 chrome_sqlite3_complete16 // Line 2443 #define sqlite3_config chrome_sqlite3_config // Line 1540 -#define sqlite3_context_db_handle chrome_sqlite3_context_db_handle // Line 5094 +#define sqlite3_context_db_handle chrome_sqlite3_context_db_handle // Line 5130 #define sqlite3_create_collation \ - chrome_sqlite3_create_collation // Lines 5419-5425 + chrome_sqlite3_create_collation // Lines 5455-5461 #define sqlite3_create_collation16 \ - chrome_sqlite3_create_collation16 // Lines 5434-5440 + chrome_sqlite3_create_collation16 // Lines 5470-5476 #define sqlite3_create_collation_v2 \ - chrome_sqlite3_create_collation_v2 // Lines 5426-5433 + chrome_sqlite3_create_collation_v2 // Lines 5462-5469 #define sqlite3_create_function \ - chrome_sqlite3_create_function // Lines 4772-4781 + chrome_sqlite3_create_function // Lines 4808-4817 #define sqlite3_create_function16 \ - chrome_sqlite3_create_function16 // Lines 4782-4791 + chrome_sqlite3_create_function16 // Lines 4818-4827 #define sqlite3_create_function_v2 \ - chrome_sqlite3_create_function_v2 // Lines 4792-4802 -#define sqlite3_create_module chrome_sqlite3_create_module // Lines 6473-6478 + chrome_sqlite3_create_function_v2 // Lines 4828-4838 +#define sqlite3_create_module chrome_sqlite3_create_module // Lines 6512-6517 #define sqlite3_create_module_v2 \ - chrome_sqlite3_create_module_v2 // Lines 6479-6485 + chrome_sqlite3_create_module_v2 // Lines 6518-6524 #define sqlite3_create_window_function \ - chrome_sqlite3_create_window_function // Lines 4803-4814 -#define sqlite3_data_count chrome_sqlite3_data_count // Line 4353 -#define sqlite3_data_directory chrome_sqlite3_data_directory // Line 5647 -#define sqlite3_db_cacheflush chrome_sqlite3_db_cacheflush // Line 8871 + chrome_sqlite3_create_window_function // Lines 4839-4850 +#define sqlite3_data_count chrome_sqlite3_data_count // Line 4389 +#define sqlite3_data_directory chrome_sqlite3_data_directory // Line 5683 +#define sqlite3_db_cacheflush chrome_sqlite3_db_cacheflush // Line 8912 #define sqlite3_db_config chrome_sqlite3_db_config // Line 1559 -#define sqlite3_db_filename chrome_sqlite3_db_filename // Line 5736 -#define sqlite3_db_handle chrome_sqlite3_db_handle // Line 5719 -#define sqlite3_db_mutex chrome_sqlite3_db_mutex // Line 7117 -#define sqlite3_db_readonly chrome_sqlite3_db_readonly // Line 5746 -#define sqlite3_db_release_memory chrome_sqlite3_db_release_memory // Line 5934 -#define sqlite3_db_status chrome_sqlite3_db_status // Line 7537 -#define sqlite3_declare_vtab chrome_sqlite3_declare_vtab // Line 6542 -#define sqlite3_deserialize chrome_sqlite3_deserialize // Lines 9265-9272 +#define sqlite3_db_filename chrome_sqlite3_db_filename // Line 5772 +#define sqlite3_db_handle chrome_sqlite3_db_handle // Line 5755 +#define sqlite3_db_mutex chrome_sqlite3_db_mutex // Line 7156 +#define sqlite3_db_readonly chrome_sqlite3_db_readonly // Line 5782 +#define sqlite3_db_release_memory chrome_sqlite3_db_release_memory // Line 5970 +#define sqlite3_db_status chrome_sqlite3_db_status // Line 7577 +#define sqlite3_declare_vtab chrome_sqlite3_declare_vtab // Line 6581 +#define sqlite3_deserialize chrome_sqlite3_deserialize // Lines 9306-9313 #define sqlite3_enable_load_extension \ - chrome_sqlite3_enable_load_extension // Line 6158 + chrome_sqlite3_enable_load_extension // Line 6194 #define sqlite3_enable_shared_cache \ - chrome_sqlite3_enable_shared_cache // Line 5904 -#define sqlite3_errcode chrome_sqlite3_errcode // Line 3449 -#define sqlite3_errmsg chrome_sqlite3_errmsg // Line 3451 -#define sqlite3_errmsg16 chrome_sqlite3_errmsg16 // Line 3452 -#define sqlite3_errstr chrome_sqlite3_errstr // Line 3453 + chrome_sqlite3_enable_shared_cache // Line 5940 +#define sqlite3_errcode chrome_sqlite3_errcode // Line 3468 +#define sqlite3_errmsg chrome_sqlite3_errmsg // Line 3470 +#define sqlite3_errmsg16 chrome_sqlite3_errmsg16 // Line 3471 +#define sqlite3_errstr chrome_sqlite3_errstr // Line 3472 #define sqlite3_exec chrome_sqlite3_exec // Lines 403-409 -#define sqlite3_expanded_sql chrome_sqlite3_expanded_sql // Line 3794 -#define sqlite3_expired chrome_sqlite3_expired // Line 4851 -#define sqlite3_extended_errcode chrome_sqlite3_extended_errcode // Line 3450 +#define sqlite3_expanded_sql chrome_sqlite3_expanded_sql // Line 3829 +#define sqlite3_expired chrome_sqlite3_expired // Line 4887 +#define sqlite3_extended_errcode chrome_sqlite3_extended_errcode // Line 3469 #define sqlite3_extended_result_codes \ - chrome_sqlite3_extended_result_codes // Line 2184 -#define sqlite3_file_control chrome_sqlite3_file_control // Line 7160 -#define sqlite3_finalize chrome_sqlite3_finalize // Line 4633 -#define sqlite3_free chrome_sqlite3_free // Line 2730 -#define sqlite3_free_table chrome_sqlite3_free_table // Line 2591 -#define sqlite3_get_autocommit chrome_sqlite3_get_autocommit // Line 5706 -#define sqlite3_get_auxdata chrome_sqlite3_get_auxdata // Line 5153 -#define sqlite3_get_table chrome_sqlite3_get_table // Lines 2583-2590 -#define sqlite3_global_recover chrome_sqlite3_global_recover // Line 4853 + chrome_sqlite3_extended_result_codes // Line 2203 +#define sqlite3_file_control chrome_sqlite3_file_control // Line 7199 +#define sqlite3_finalize chrome_sqlite3_finalize // Line 4669 +#define sqlite3_free chrome_sqlite3_free // Line 2749 +#define sqlite3_free_table chrome_sqlite3_free_table // Line 2610 +#define sqlite3_get_autocommit chrome_sqlite3_get_autocommit // Line 5742 +#define sqlite3_get_auxdata chrome_sqlite3_get_auxdata // Line 5189 +#define sqlite3_get_table chrome_sqlite3_get_table // Lines 2602-2609 +#define sqlite3_global_recover chrome_sqlite3_global_recover // Line 4889 #define sqlite3_initialize chrome_sqlite3_initialize // Line 1504 -#define sqlite3_interrupt chrome_sqlite3_interrupt // Line 2388 -#define sqlite3_key chrome_sqlite3_key // Lines 5488-5491 -#define sqlite3_key_v2 chrome_sqlite3_key_v2 // Lines 5492-5496 -#define sqlite3_keyword_check chrome_sqlite3_keyword_check // Line 7267 -#define sqlite3_keyword_count chrome_sqlite3_keyword_count // Line 7265 -#define sqlite3_keyword_name chrome_sqlite3_keyword_name // Line 7266 -#define sqlite3_last_insert_rowid chrome_sqlite3_last_insert_rowid // Line 2246 +#define sqlite3_interrupt chrome_sqlite3_interrupt // Line 2407 +#define sqlite3_key chrome_sqlite3_key // Lines 5524-5527 +#define sqlite3_key_v2 chrome_sqlite3_key_v2 // Lines 5528-5532 +#define sqlite3_keyword_check chrome_sqlite3_keyword_check // Line 7307 +#define sqlite3_keyword_count chrome_sqlite3_keyword_count // Line 7305 +#define sqlite3_keyword_name chrome_sqlite3_keyword_name // Line 7306 +#define sqlite3_last_insert_rowid chrome_sqlite3_last_insert_rowid // Line 2265 #define sqlite3_libversion chrome_sqlite3_libversion // Line 163 #define sqlite3_libversion_number chrome_sqlite3_libversion_number // Line 165 -#define sqlite3_limit chrome_sqlite3_limit // Line 3521 -#define sqlite3_load_extension chrome_sqlite3_load_extension // Lines 6126-6131 -#define sqlite3_log chrome_sqlite3_log // Line 8408 -#define sqlite3_malloc chrome_sqlite3_malloc // Line 2726 -#define sqlite3_malloc64 chrome_sqlite3_malloc64 // Line 2727 -#define sqlite3_memory_alarm chrome_sqlite3_memory_alarm // Lines 4855-4856 -#define sqlite3_memory_highwater chrome_sqlite3_memory_highwater // Line 2757 -#define sqlite3_memory_used chrome_sqlite3_memory_used // Line 2756 -#define sqlite3_mprintf chrome_sqlite3_mprintf // Line 2633 -#define sqlite3_msize chrome_sqlite3_msize // Line 2731 -#define sqlite3_mutex_alloc chrome_sqlite3_mutex_alloc // Line 6962 -#define sqlite3_mutex_enter chrome_sqlite3_mutex_enter // Line 6964 -#define sqlite3_mutex_free chrome_sqlite3_mutex_free // Line 6963 -#define sqlite3_mutex_held chrome_sqlite3_mutex_held // Line 7076 -#define sqlite3_mutex_leave chrome_sqlite3_mutex_leave // Line 6966 -#define sqlite3_mutex_notheld chrome_sqlite3_mutex_notheld // Line 7077 -#define sqlite3_mutex_try chrome_sqlite3_mutex_try // Line 6965 -#define sqlite3_next_stmt chrome_sqlite3_next_stmt // Line 5762 -#define sqlite3_open chrome_sqlite3_open // Lines 3338-3341 -#define sqlite3_open16 chrome_sqlite3_open16 // Lines 3342-3345 -#define sqlite3_open_v2 chrome_sqlite3_open_v2 // Lines 3346-3351 +#define sqlite3_limit chrome_sqlite3_limit // Line 3540 +#define sqlite3_load_extension chrome_sqlite3_load_extension // Lines 6162-6167 +#define sqlite3_log chrome_sqlite3_log // Line 8448 +#define sqlite3_malloc chrome_sqlite3_malloc // Line 2745 +#define sqlite3_malloc64 chrome_sqlite3_malloc64 // Line 2746 +#define sqlite3_memory_alarm chrome_sqlite3_memory_alarm // Lines 4891-4892 +#define sqlite3_memory_highwater chrome_sqlite3_memory_highwater // Line 2776 +#define sqlite3_memory_used chrome_sqlite3_memory_used // Line 2775 +#define sqlite3_mprintf chrome_sqlite3_mprintf // Line 2652 +#define sqlite3_msize chrome_sqlite3_msize // Line 2750 +#define sqlite3_mutex_alloc chrome_sqlite3_mutex_alloc // Line 7001 +#define sqlite3_mutex_enter chrome_sqlite3_mutex_enter // Line 7003 +#define sqlite3_mutex_free chrome_sqlite3_mutex_free // Line 7002 +#define sqlite3_mutex_held chrome_sqlite3_mutex_held // Line 7115 +#define sqlite3_mutex_leave chrome_sqlite3_mutex_leave // Line 7005 +#define sqlite3_mutex_notheld chrome_sqlite3_mutex_notheld // Line 7116 +#define sqlite3_mutex_try chrome_sqlite3_mutex_try // Line 7004 +#define sqlite3_next_stmt chrome_sqlite3_next_stmt // Line 5798 +#define sqlite3_normalized_sql chrome_sqlite3_normalized_sql // Line 3830 +#define sqlite3_open chrome_sqlite3_open // Lines 3357-3360 +#define sqlite3_open16 chrome_sqlite3_open16 // Lines 3361-3364 +#define sqlite3_open_v2 chrome_sqlite3_open_v2 // Lines 3365-3370 #define sqlite3_os_end chrome_sqlite3_os_end // Line 1507 #define sqlite3_os_init chrome_sqlite3_os_init // Line 1506 -#define sqlite3_overload_function chrome_sqlite3_overload_function // Line 6561 -#define sqlite3_prepare chrome_sqlite3_prepare // Lines 3716-3722 -#define sqlite3_prepare16 chrome_sqlite3_prepare16 // Lines 3738-3744 -#define sqlite3_prepare16_v2 chrome_sqlite3_prepare16_v2 // Lines 3745-3751 -#define sqlite3_prepare16_v3 chrome_sqlite3_prepare16_v3 // Lines 3752-3759 -#define sqlite3_prepare_v2 chrome_sqlite3_prepare_v2 // Lines 3723-3729 -#define sqlite3_prepare_v3 chrome_sqlite3_prepare_v3 // Lines 3730-3737 -#define sqlite3_preupdate_count chrome_sqlite3_preupdate_count // Line 8970 -#define sqlite3_preupdate_depth chrome_sqlite3_preupdate_depth // Line 8971 -#define sqlite3_preupdate_hook chrome_sqlite3_preupdate_hook // Lines 8956-8968 -#define sqlite3_preupdate_new chrome_sqlite3_preupdate_new // Line 8972 -#define sqlite3_preupdate_old chrome_sqlite3_preupdate_old // Line 8969 -#define sqlite3_profile chrome_sqlite3_profile // Lines 2981-2982 -#define sqlite3_progress_handler chrome_sqlite3_progress_handler // Line 3109 -#define sqlite3_randomness chrome_sqlite3_randomness // Line 2780 -#define sqlite3_realloc chrome_sqlite3_realloc // Line 2728 -#define sqlite3_realloc64 chrome_sqlite3_realloc64 // Line 2729 -#define sqlite3_rekey chrome_sqlite3_rekey // Lines 5506-5509 -#define sqlite3_rekey_v2 chrome_sqlite3_rekey_v2 // Lines 5510-5514 -#define sqlite3_release_memory chrome_sqlite3_release_memory // Line 5920 -#define sqlite3_reset chrome_sqlite3_reset // Line 4660 +#define sqlite3_overload_function chrome_sqlite3_overload_function // Line 6600 +#define sqlite3_prepare chrome_sqlite3_prepare // Lines 3745-3751 +#define sqlite3_prepare16 chrome_sqlite3_prepare16 // Lines 3767-3773 +#define sqlite3_prepare16_v2 chrome_sqlite3_prepare16_v2 // Lines 3774-3780 +#define sqlite3_prepare16_v3 chrome_sqlite3_prepare16_v3 // Lines 3781-3788 +#define sqlite3_prepare_v2 chrome_sqlite3_prepare_v2 // Lines 3752-3758 +#define sqlite3_prepare_v3 chrome_sqlite3_prepare_v3 // Lines 3759-3766 +#define sqlite3_preupdate_count chrome_sqlite3_preupdate_count // Line 9011 +#define sqlite3_preupdate_depth chrome_sqlite3_preupdate_depth // Line 9012 +#define sqlite3_preupdate_hook chrome_sqlite3_preupdate_hook // Lines 8997-9009 +#define sqlite3_preupdate_new chrome_sqlite3_preupdate_new // Line 9013 +#define sqlite3_preupdate_old chrome_sqlite3_preupdate_old // Line 9010 +#define sqlite3_profile chrome_sqlite3_profile // Lines 3000-3001 +#define sqlite3_progress_handler chrome_sqlite3_progress_handler // Line 3128 +#define sqlite3_randomness chrome_sqlite3_randomness // Line 2799 +#define sqlite3_realloc chrome_sqlite3_realloc // Line 2747 +#define sqlite3_realloc64 chrome_sqlite3_realloc64 // Line 2748 +#define sqlite3_rekey chrome_sqlite3_rekey // Lines 5542-5545 +#define sqlite3_rekey_v2 chrome_sqlite3_rekey_v2 // Lines 5546-5550 +#define sqlite3_release_memory chrome_sqlite3_release_memory // Line 5956 +#define sqlite3_reset chrome_sqlite3_reset // Line 4696 #define sqlite3_reset_auto_extension \ - chrome_sqlite3_reset_auto_extension // Line 6216 -#define sqlite3_result_blob chrome_sqlite3_result_blob // Line 5301 -#define sqlite3_result_blob64 chrome_sqlite3_result_blob64 // Lines 5302-5303 -#define sqlite3_result_double chrome_sqlite3_result_double // Line 5304 -#define sqlite3_result_error chrome_sqlite3_result_error // Line 5305 -#define sqlite3_result_error16 chrome_sqlite3_result_error16 // Line 5306 -#define sqlite3_result_error_code chrome_sqlite3_result_error_code // Line 5309 + chrome_sqlite3_reset_auto_extension // Line 6252 +#define sqlite3_result_blob chrome_sqlite3_result_blob // Line 5337 +#define sqlite3_result_blob64 chrome_sqlite3_result_blob64 // Lines 5338-5339 +#define sqlite3_result_double chrome_sqlite3_result_double // Line 5340 +#define sqlite3_result_error chrome_sqlite3_result_error // Line 5341 +#define sqlite3_result_error16 chrome_sqlite3_result_error16 // Line 5342 +#define sqlite3_result_error_code chrome_sqlite3_result_error_code // Line 5345 #define sqlite3_result_error_nomem \ - chrome_sqlite3_result_error_nomem // Line 5308 + chrome_sqlite3_result_error_nomem // Line 5344 #define sqlite3_result_error_toobig \ - chrome_sqlite3_result_error_toobig // Line 5307 -#define sqlite3_result_int chrome_sqlite3_result_int // Line 5310 -#define sqlite3_result_int64 chrome_sqlite3_result_int64 // Line 5311 -#define sqlite3_result_null chrome_sqlite3_result_null // Line 5312 -#define sqlite3_result_pointer chrome_sqlite3_result_pointer // Line 5320 -#define sqlite3_result_subtype chrome_sqlite3_result_subtype // Line 5337 -#define sqlite3_result_text chrome_sqlite3_result_text // Line 5313 -#define sqlite3_result_text16 chrome_sqlite3_result_text16 // Line 5316 -#define sqlite3_result_text16be chrome_sqlite3_result_text16be // Line 5318 -#define sqlite3_result_text16le chrome_sqlite3_result_text16le // Line 5317 -#define sqlite3_result_text64 chrome_sqlite3_result_text64 // Lines 5314-5315 -#define sqlite3_result_value chrome_sqlite3_result_value // Line 5319 -#define sqlite3_result_zeroblob chrome_sqlite3_result_zeroblob // Line 5321 -#define sqlite3_result_zeroblob64 chrome_sqlite3_result_zeroblob64 // Line 5322 -#define sqlite3_rollback_hook chrome_sqlite3_rollback_hook // Line 5812 + chrome_sqlite3_result_error_toobig // Line 5343 +#define sqlite3_result_int chrome_sqlite3_result_int // Line 5346 +#define sqlite3_result_int64 chrome_sqlite3_result_int64 // Line 5347 +#define sqlite3_result_null chrome_sqlite3_result_null // Line 5348 +#define sqlite3_result_pointer chrome_sqlite3_result_pointer // Line 5356 +#define sqlite3_result_subtype chrome_sqlite3_result_subtype // Line 5373 +#define sqlite3_result_text chrome_sqlite3_result_text // Line 5349 +#define sqlite3_result_text16 chrome_sqlite3_result_text16 // Line 5352 +#define sqlite3_result_text16be chrome_sqlite3_result_text16be // Line 5354 +#define sqlite3_result_text16le chrome_sqlite3_result_text16le // Line 5353 +#define sqlite3_result_text64 chrome_sqlite3_result_text64 // Lines 5350-5351 +#define sqlite3_result_value chrome_sqlite3_result_value // Line 5355 +#define sqlite3_result_zeroblob chrome_sqlite3_result_zeroblob // Line 5357 +#define sqlite3_result_zeroblob64 chrome_sqlite3_result_zeroblob64 // Line 5358 +#define sqlite3_rollback_hook chrome_sqlite3_rollback_hook // Line 5848 #define sqlite3_rtree_geometry_callback \ - chrome_sqlite3_rtree_geometry_callback // Lines 9352-9357 + chrome_sqlite3_rtree_geometry_callback // Lines 9393-9398 #define sqlite3_rtree_query_callback \ - chrome_sqlite3_rtree_query_callback // Lines 9378-9384 -#define sqlite3_serialize chrome_sqlite3_serialize // Lines 9213-9218 -#define sqlite3_set_authorizer chrome_sqlite3_set_authorizer // Lines 2871-2875 -#define sqlite3_set_auxdata chrome_sqlite3_set_auxdata // Line 5154 + chrome_sqlite3_rtree_query_callback // Lines 9419-9425 +#define sqlite3_serialize chrome_sqlite3_serialize // Lines 9254-9259 +#define sqlite3_set_authorizer chrome_sqlite3_set_authorizer // Lines 2890-2894 +#define sqlite3_set_auxdata chrome_sqlite3_set_auxdata // Line 5190 #define sqlite3_set_last_insert_rowid \ - chrome_sqlite3_set_last_insert_rowid // Line 2256 + chrome_sqlite3_set_last_insert_rowid // Line 2275 #define sqlite3_shutdown chrome_sqlite3_shutdown // Line 1505 -#define sqlite3_sleep chrome_sqlite3_sleep // Line 5552 -#define sqlite3_snapshot_cmp chrome_sqlite3_snapshot_cmp // Lines 9147-9150 -#define sqlite3_snapshot_free chrome_sqlite3_snapshot_free // Line 9120 -#define sqlite3_snapshot_get chrome_sqlite3_snapshot_get // Lines 9054-9058 -#define sqlite3_snapshot_open chrome_sqlite3_snapshot_open // Lines 9103-9107 -#define sqlite3_snapshot_recover chrome_sqlite3_snapshot_recover // Line 9175 -#define sqlite3_snprintf chrome_sqlite3_snprintf // Line 2635 -#define sqlite3_soft_heap_limit chrome_sqlite3_soft_heap_limit // Line 5998 -#define sqlite3_soft_heap_limit64 chrome_sqlite3_soft_heap_limit64 // Line 5987 +#define sqlite3_sleep chrome_sqlite3_sleep // Line 5588 +#define sqlite3_snapshot_cmp chrome_sqlite3_snapshot_cmp // Lines 9188-9191 +#define sqlite3_snapshot_free chrome_sqlite3_snapshot_free // Line 9161 +#define sqlite3_snapshot_get chrome_sqlite3_snapshot_get // Lines 9095-9099 +#define sqlite3_snapshot_open chrome_sqlite3_snapshot_open // Lines 9144-9148 +#define sqlite3_snapshot_recover chrome_sqlite3_snapshot_recover // Line 9216 +#define sqlite3_snprintf chrome_sqlite3_snprintf // Line 2654 +#define sqlite3_soft_heap_limit chrome_sqlite3_soft_heap_limit // Line 6034 +#define sqlite3_soft_heap_limit64 chrome_sqlite3_soft_heap_limit64 // Line 6023 #define sqlite3_sourceid chrome_sqlite3_sourceid // Line 164 -#define sqlite3_sql chrome_sqlite3_sql // Line 3793 -#define sqlite3_status chrome_sqlite3_status // Line 7427 -#define sqlite3_status64 chrome_sqlite3_status64 // Lines 7428-7433 -#define sqlite3_step chrome_sqlite3_step // Line 4332 -#define sqlite3_stmt_busy chrome_sqlite3_stmt_busy // Line 3851 -#define sqlite3_stmt_readonly chrome_sqlite3_stmt_readonly // Line 3830 +#define sqlite3_sql chrome_sqlite3_sql // Line 3828 +#define sqlite3_status chrome_sqlite3_status // Line 7467 +#define sqlite3_status64 chrome_sqlite3_status64 // Lines 7468-7473 +#define sqlite3_step chrome_sqlite3_step // Line 4368 +#define sqlite3_stmt_busy chrome_sqlite3_stmt_busy // Line 3887 +#define sqlite3_stmt_readonly chrome_sqlite3_stmt_readonly // Line 3866 #define sqlite3_stmt_scanstatus \ - chrome_sqlite3_stmt_scanstatus // Lines 8823-8828 + chrome_sqlite3_stmt_scanstatus // Lines 8864-8869 #define sqlite3_stmt_scanstatus_reset \ - chrome_sqlite3_stmt_scanstatus_reset // Line 8839 -#define sqlite3_stmt_status chrome_sqlite3_stmt_status // Line 7690 -#define sqlite3_str_append chrome_sqlite3_str_append // Line 7363 -#define sqlite3_str_appendall chrome_sqlite3_str_appendall // Line 7364 -#define sqlite3_str_appendchar chrome_sqlite3_str_appendchar // Line 7365 -#define sqlite3_str_appendf chrome_sqlite3_str_appendf // Line 7361 -#define sqlite3_str_errcode chrome_sqlite3_str_errcode // Line 7397 -#define sqlite3_str_finish chrome_sqlite3_str_finish // Line 7327 -#define sqlite3_str_length chrome_sqlite3_str_length // Line 7398 -#define sqlite3_str_new chrome_sqlite3_str_new // Line 7312 -#define sqlite3_str_reset chrome_sqlite3_str_reset // Line 7366 -#define sqlite3_str_value chrome_sqlite3_str_value // Line 7399 -#define sqlite3_str_vappendf chrome_sqlite3_str_vappendf // Line 7362 -#define sqlite3_strglob chrome_sqlite3_strglob // Line 8339 -#define sqlite3_stricmp chrome_sqlite3_stricmp // Line 8321 -#define sqlite3_strlike chrome_sqlite3_strlike // Line 8385 -#define sqlite3_strnicmp chrome_sqlite3_strnicmp // Line 8322 -#define sqlite3_system_errno chrome_sqlite3_system_errno // Line 8985 + chrome_sqlite3_stmt_scanstatus_reset // Line 8880 +#define sqlite3_stmt_status chrome_sqlite3_stmt_status // Line 7730 +#define sqlite3_str_append chrome_sqlite3_str_append // Line 7403 +#define sqlite3_str_appendall chrome_sqlite3_str_appendall // Line 7404 +#define sqlite3_str_appendchar chrome_sqlite3_str_appendchar // Line 7405 +#define sqlite3_str_appendf chrome_sqlite3_str_appendf // Line 7401 +#define sqlite3_str_errcode chrome_sqlite3_str_errcode // Line 7437 +#define sqlite3_str_finish chrome_sqlite3_str_finish // Line 7367 +#define sqlite3_str_length chrome_sqlite3_str_length // Line 7438 +#define sqlite3_str_new chrome_sqlite3_str_new // Line 7352 +#define sqlite3_str_reset chrome_sqlite3_str_reset // Line 7406 +#define sqlite3_str_value chrome_sqlite3_str_value // Line 7439 +#define sqlite3_str_vappendf chrome_sqlite3_str_vappendf // Line 7402 +#define sqlite3_strglob chrome_sqlite3_strglob // Line 8379 +#define sqlite3_stricmp chrome_sqlite3_stricmp // Line 8361 +#define sqlite3_strlike chrome_sqlite3_strlike // Line 8425 +#define sqlite3_strnicmp chrome_sqlite3_strnicmp // Line 8362 +#define sqlite3_system_errno chrome_sqlite3_system_errno // Line 9026 #define sqlite3_table_column_metadata \ - chrome_sqlite3_table_column_metadata // Lines 6070-6080 -#define sqlite3_temp_directory chrome_sqlite3_temp_directory // Line 5610 -#define sqlite3_test_control chrome_sqlite3_test_control // Line 7179 -#define sqlite3_thread_cleanup chrome_sqlite3_thread_cleanup // Line 4854 + chrome_sqlite3_table_column_metadata // Lines 6106-6116 +#define sqlite3_temp_directory chrome_sqlite3_temp_directory // Line 5646 +#define sqlite3_test_control chrome_sqlite3_test_control // Line 7218 +#define sqlite3_thread_cleanup chrome_sqlite3_thread_cleanup // Line 4890 #define sqlite3_threadsafe chrome_sqlite3_threadsafe // Line 230 -#define sqlite3_total_changes chrome_sqlite3_total_changes // Line 2351 -#define sqlite3_trace chrome_sqlite3_trace // Lines 2979-2980 -#define sqlite3_trace_v2 chrome_sqlite3_trace_v2 // Lines 3070-3075 -#define sqlite3_transfer_bindings chrome_sqlite3_transfer_bindings // Line 4852 -#define sqlite3_unlock_notify chrome_sqlite3_unlock_notify // Lines 8306-8310 -#define sqlite3_update_hook chrome_sqlite3_update_hook // Lines 5863-5867 -#define sqlite3_uri_boolean chrome_sqlite3_uri_boolean // Line 3393 -#define sqlite3_uri_int64 chrome_sqlite3_uri_int64 // Line 3394 -#define sqlite3_uri_parameter chrome_sqlite3_uri_parameter // Line 3392 -#define sqlite3_user_data chrome_sqlite3_user_data // Line 5082 -#define sqlite3_value_blob chrome_sqlite3_value_blob // Line 4980 -#define sqlite3_value_bytes chrome_sqlite3_value_bytes // Line 4989 -#define sqlite3_value_bytes16 chrome_sqlite3_value_bytes16 // Line 4990 -#define sqlite3_value_double chrome_sqlite3_value_double // Line 4981 -#define sqlite3_value_dup chrome_sqlite3_value_dup // Line 5021 -#define sqlite3_value_free chrome_sqlite3_value_free // Line 5022 -#define sqlite3_value_int chrome_sqlite3_value_int // Line 4982 -#define sqlite3_value_int64 chrome_sqlite3_value_int64 // Line 4983 -#define sqlite3_value_nochange chrome_sqlite3_value_nochange // Line 4993 +#define sqlite3_total_changes chrome_sqlite3_total_changes // Line 2370 +#define sqlite3_trace chrome_sqlite3_trace // Lines 2998-2999 +#define sqlite3_trace_v2 chrome_sqlite3_trace_v2 // Lines 3089-3094 +#define sqlite3_transfer_bindings chrome_sqlite3_transfer_bindings // Line 4888 +#define sqlite3_unlock_notify chrome_sqlite3_unlock_notify // Lines 8346-8350 +#define sqlite3_update_hook chrome_sqlite3_update_hook // Lines 5899-5903 +#define sqlite3_uri_boolean chrome_sqlite3_uri_boolean // Line 3412 +#define sqlite3_uri_int64 chrome_sqlite3_uri_int64 // Line 3413 +#define sqlite3_uri_parameter chrome_sqlite3_uri_parameter // Line 3411 +#define sqlite3_user_data chrome_sqlite3_user_data // Line 5118 +#define sqlite3_value_blob chrome_sqlite3_value_blob // Line 5016 +#define sqlite3_value_bytes chrome_sqlite3_value_bytes // Line 5025 +#define sqlite3_value_bytes16 chrome_sqlite3_value_bytes16 // Line 5026 +#define sqlite3_value_double chrome_sqlite3_value_double // Line 5017 +#define sqlite3_value_dup chrome_sqlite3_value_dup // Line 5057 +#define sqlite3_value_free chrome_sqlite3_value_free // Line 5058 +#define sqlite3_value_int chrome_sqlite3_value_int // Line 5018 +#define sqlite3_value_int64 chrome_sqlite3_value_int64 // Line 5019 +#define sqlite3_value_nochange chrome_sqlite3_value_nochange // Line 5029 #define sqlite3_value_numeric_type \ - chrome_sqlite3_value_numeric_type // Line 4992 -#define sqlite3_value_pointer chrome_sqlite3_value_pointer // Line 4984 -#define sqlite3_value_subtype chrome_sqlite3_value_subtype // Line 5005 -#define sqlite3_value_text chrome_sqlite3_value_text // Line 4985 -#define sqlite3_value_text16 chrome_sqlite3_value_text16 // Line 4986 -#define sqlite3_value_text16be chrome_sqlite3_value_text16be // Line 4988 -#define sqlite3_value_text16le chrome_sqlite3_value_text16le // Line 4987 -#define sqlite3_value_type chrome_sqlite3_value_type // Line 4991 + chrome_sqlite3_value_numeric_type // Line 5028 +#define sqlite3_value_pointer chrome_sqlite3_value_pointer // Line 5020 +#define sqlite3_value_subtype chrome_sqlite3_value_subtype // Line 5041 +#define sqlite3_value_text chrome_sqlite3_value_text // Line 5021 +#define sqlite3_value_text16 chrome_sqlite3_value_text16 // Line 5022 +#define sqlite3_value_text16be chrome_sqlite3_value_text16be // Line 5024 +#define sqlite3_value_text16le chrome_sqlite3_value_text16le // Line 5023 +#define sqlite3_value_type chrome_sqlite3_value_type // Line 5027 #define sqlite3_version chrome_sqlite3_version // Line 162 -#define sqlite3_vfs_find chrome_sqlite3_vfs_find // Line 6844 -#define sqlite3_vfs_register chrome_sqlite3_vfs_register // Line 6845 -#define sqlite3_vfs_unregister chrome_sqlite3_vfs_unregister // Line 6846 -#define sqlite3_vmprintf chrome_sqlite3_vmprintf // Line 2634 -#define sqlite3_vsnprintf chrome_sqlite3_vsnprintf // Line 2636 -#define sqlite3_vtab_collation chrome_sqlite3_vtab_collation // Line 8718 -#define sqlite3_vtab_config chrome_sqlite3_vtab_config // Line 8631 -#define sqlite3_vtab_nochange chrome_sqlite3_vtab_nochange // Line 8703 -#define sqlite3_vtab_on_conflict chrome_sqlite3_vtab_on_conflict // Line 8684 +#define sqlite3_vfs_find chrome_sqlite3_vfs_find // Line 6883 +#define sqlite3_vfs_register chrome_sqlite3_vfs_register // Line 6884 +#define sqlite3_vfs_unregister chrome_sqlite3_vfs_unregister // Line 6885 +#define sqlite3_vmprintf chrome_sqlite3_vmprintf // Line 2653 +#define sqlite3_vsnprintf chrome_sqlite3_vsnprintf // Line 2655 +#define sqlite3_vtab_collation chrome_sqlite3_vtab_collation // Line 8759 +#define sqlite3_vtab_config chrome_sqlite3_vtab_config // Line 8671 +#define sqlite3_vtab_nochange chrome_sqlite3_vtab_nochange // Line 8744 +#define sqlite3_vtab_on_conflict chrome_sqlite3_vtab_on_conflict // Line 8725 #define sqlite3_wal_autocheckpoint \ - chrome_sqlite3_wal_autocheckpoint // Line 8479 -#define sqlite3_wal_checkpoint chrome_sqlite3_wal_checkpoint // Line 8501 + chrome_sqlite3_wal_autocheckpoint // Line 8519 +#define sqlite3_wal_checkpoint chrome_sqlite3_wal_checkpoint // Line 8541 #define sqlite3_wal_checkpoint_v2 \ - chrome_sqlite3_wal_checkpoint_v2 // Lines 8595-8601 -#define sqlite3_wal_hook chrome_sqlite3_wal_hook // Lines 8444-8448 + chrome_sqlite3_wal_checkpoint_v2 // Lines 8635-8641 +#define sqlite3_wal_hook chrome_sqlite3_wal_hook // Lines 8484-8488 #define sqlite3_win32_set_directory \ - chrome_sqlite3_win32_set_directory // Lines 5668-5671 + chrome_sqlite3_win32_set_directory // Lines 5704-5707 #define sqlite3_win32_set_directory16 \ - chrome_sqlite3_win32_set_directory16 // Line 5673 + chrome_sqlite3_win32_set_directory16 // Line 5709 #define sqlite3_win32_set_directory8 \ - chrome_sqlite3_win32_set_directory8 // Line 5672 -#define sqlite3changegroup_add chrome_sqlite3changegroup_add // Line 10339 + chrome_sqlite3_win32_set_directory8 // Line 5708 +#define sqlite3changegroup_add chrome_sqlite3changegroup_add // Line 10406 #define sqlite3changegroup_add_strm \ - chrome_sqlite3changegroup_add_strm // Lines 10989-10992 + chrome_sqlite3changegroup_add_strm // Lines 11068-11071 #define sqlite3changegroup_delete \ - chrome_sqlite3changegroup_delete // Line 10376 -#define sqlite3changegroup_new chrome_sqlite3changegroup_new // Line 10261 + chrome_sqlite3changegroup_delete // Line 10443 +#define sqlite3changegroup_new chrome_sqlite3changegroup_new // Line 10328 #define sqlite3changegroup_output \ - chrome_sqlite3changegroup_output // Lines 10366-10370 + chrome_sqlite3changegroup_output // Lines 10433-10437 #define sqlite3changegroup_output_strm \ - chrome_sqlite3changegroup_output_strm // Lines 10993-10996 + chrome_sqlite3changegroup_output_strm // Lines 11072-11075 #define sqlite3changeset_apply \ - chrome_sqlite3changeset_apply // Lines 10536-10550 + chrome_sqlite3changeset_apply // Lines 10603-10617 #define sqlite3changeset_apply_strm \ - chrome_sqlite3changeset_apply_strm // Lines 10928-10942 + chrome_sqlite3changeset_apply_strm // Lines 11001-11015 #define sqlite3changeset_apply_v2 \ - chrome_sqlite3changeset_apply_v2 // Lines 10551-10567 + chrome_sqlite3changeset_apply_v2 // Lines 10618-10634 #define sqlite3changeset_apply_v2_strm \ - chrome_sqlite3changeset_apply_v2_strm // Lines 10943-10959 + chrome_sqlite3changeset_apply_v2_strm // Lines 11016-11032 #define sqlite3changeset_concat \ - chrome_sqlite3changeset_concat // Lines 10207-10214 + chrome_sqlite3changeset_concat // Lines 10274-10281 #define sqlite3changeset_concat_strm \ - chrome_sqlite3changeset_concat_strm // Lines 10960-10967 + chrome_sqlite3changeset_concat_strm // Lines 11033-11040 #define sqlite3changeset_conflict \ - chrome_sqlite3changeset_conflict // Lines 10093-10097 + chrome_sqlite3changeset_conflict // Lines 10160-10164 #define sqlite3changeset_finalize \ - chrome_sqlite3changeset_finalize // Line 10146 + chrome_sqlite3changeset_finalize // Line 10213 #define sqlite3changeset_fk_conflicts \ - chrome_sqlite3changeset_fk_conflicts // Lines 10110-10113 + chrome_sqlite3changeset_fk_conflicts // Lines 10177-10180 #define sqlite3changeset_invert \ - chrome_sqlite3changeset_invert // Lines 10176-10179 + chrome_sqlite3changeset_invert // Lines 10243-10246 #define sqlite3changeset_invert_strm \ - chrome_sqlite3changeset_invert_strm // Lines 10968-10973 -#define sqlite3changeset_new chrome_sqlite3changeset_new // Lines 10065-10069 -#define sqlite3changeset_next chrome_sqlite3changeset_next // Line 9937 -#define sqlite3changeset_old chrome_sqlite3changeset_old // Lines 10031-10035 -#define sqlite3changeset_op chrome_sqlite3changeset_op // Lines 9966-9972 -#define sqlite3changeset_pk chrome_sqlite3changeset_pk // Lines 10000-10004 -#define sqlite3changeset_start chrome_sqlite3changeset_start // Lines 9907-9911 + chrome_sqlite3changeset_invert_strm // Lines 11041-11046 +#define sqlite3changeset_new chrome_sqlite3changeset_new // Lines 10132-10136 +#define sqlite3changeset_next chrome_sqlite3changeset_next // Line 10004 +#define sqlite3changeset_old chrome_sqlite3changeset_old // Lines 10098-10102 +#define sqlite3changeset_op chrome_sqlite3changeset_op // Lines 10033-10039 +#define sqlite3changeset_pk chrome_sqlite3changeset_pk // Lines 10067-10071 +#define sqlite3changeset_start chrome_sqlite3changeset_start // Lines 9955-9959 #define sqlite3changeset_start_strm \ - chrome_sqlite3changeset_start_strm // Lines 10974-10978 + chrome_sqlite3changeset_start_strm // Lines 11047-11051 +#define sqlite3changeset_start_v2 \ + chrome_sqlite3changeset_start_v2 // Lines 9960-9965 +#define sqlite3changeset_start_v2_strm \ + chrome_sqlite3changeset_start_v2_strm // Lines 11052-11057 #define sqlite3rebaser_configure \ - chrome_sqlite3rebaser_configure // Lines 10803-10806 -#define sqlite3rebaser_create chrome_sqlite3rebaser_create // Line 10792 -#define sqlite3rebaser_delete chrome_sqlite3rebaser_delete // Line 10836 -#define sqlite3rebaser_rebase chrome_sqlite3rebaser_rebase // Lines 10822-10826 + chrome_sqlite3rebaser_configure // Lines 10876-10879 +#define sqlite3rebaser_create chrome_sqlite3rebaser_create // Line 10865 +#define sqlite3rebaser_delete chrome_sqlite3rebaser_delete // Line 10909 +#define sqlite3rebaser_rebase chrome_sqlite3rebaser_rebase // Lines 10895-10899 #define sqlite3rebaser_rebase_strm \ - chrome_sqlite3rebaser_rebase_strm // Lines 10997-11003 -#define sqlite3session_attach chrome_sqlite3session_attach // Lines 9621-9624 + chrome_sqlite3rebaser_rebase_strm // Lines 11076-11082 +#define sqlite3session_attach chrome_sqlite3session_attach // Lines 9662-9665 #define sqlite3session_changeset \ - chrome_sqlite3session_changeset // Lines 9750-9754 + chrome_sqlite3session_changeset // Lines 9791-9795 #define sqlite3session_changeset_strm \ - chrome_sqlite3session_changeset_strm // Lines 10979-10983 -#define sqlite3session_create chrome_sqlite3session_create // Lines 9491-9495 -#define sqlite3session_delete chrome_sqlite3session_delete // Line 9510 -#define sqlite3session_diff chrome_sqlite3session_diff // Lines 9813-9818 -#define sqlite3session_enable chrome_sqlite3session_enable // Line 9531 -#define sqlite3session_indirect chrome_sqlite3session_indirect // Line 9561 -#define sqlite3session_isempty chrome_sqlite3session_isempty // Line 9871 + chrome_sqlite3session_changeset_strm // Lines 11058-11062 +#define sqlite3session_config chrome_sqlite3session_config // Line 11117 +#define sqlite3session_create chrome_sqlite3session_create // Lines 9532-9536 +#define sqlite3session_delete chrome_sqlite3session_delete // Line 9551 +#define sqlite3session_diff chrome_sqlite3session_diff // Lines 9854-9859 +#define sqlite3session_enable chrome_sqlite3session_enable // Line 9572 +#define sqlite3session_indirect chrome_sqlite3session_indirect // Line 9602 +#define sqlite3session_isempty chrome_sqlite3session_isempty // Line 9912 #define sqlite3session_patchset \ - chrome_sqlite3session_patchset // Lines 9850-9854 + chrome_sqlite3session_patchset // Lines 9891-9895 #define sqlite3session_patchset_strm \ - chrome_sqlite3session_patchset_strm // Lines 10984-10988 + chrome_sqlite3session_patchset_strm // Lines 11063-11067 #define sqlite3session_table_filter \ - chrome_sqlite3session_table_filter // Lines 9636-9643 + chrome_sqlite3session_table_filter // Lines 9677-9684 #endif // THIRD_PARTY_SQLITE_AMALGAMATION_RENAME_EXPORTS_H_
diff --git a/third_party/sqlite/amalgamation/shell/shell.c b/third_party/sqlite/amalgamation/shell/shell.c index 0871dde..04ff456 100644 --- a/third_party/sqlite/amalgamation/shell/shell.c +++ b/third_party/sqlite/amalgamation/shell/shell.c
@@ -1317,7 +1317,7 @@ ** ****************************************************************************** ** -** This SQLite extension implements a functions that compute SHA1 hashes. +** This SQLite extension implements functions that compute SHA3 hashes. ** Two SQL functions are implemented: ** ** sha3(X,SIZE) @@ -2128,7 +2128,18 @@ #include <errno.h> +/* +** Structure of the fsdir() table-valued function +*/ + /* 0 1 2 3 4 5 */ #define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)" +#define FSDIR_COLUMN_NAME 0 /* Name of the file */ +#define FSDIR_COLUMN_MODE 1 /* Access mode */ +#define FSDIR_COLUMN_MTIME 2 /* Last modification time */ +#define FSDIR_COLUMN_DATA 3 /* File content */ +#define FSDIR_COLUMN_PATH 4 /* Path to top of search */ +#define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */ + /* ** Set the result stored by context ctx to a blob containing the @@ -2717,20 +2728,20 @@ ){ fsdir_cursor *pCur = (fsdir_cursor*)cur; switch( i ){ - case 0: { /* name */ + case FSDIR_COLUMN_NAME: { sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT); break; } - case 1: /* mode */ + case FSDIR_COLUMN_MODE: sqlite3_result_int64(ctx, pCur->sStat.st_mode); break; - case 2: /* mtime */ + case FSDIR_COLUMN_MTIME: sqlite3_result_int64(ctx, pCur->sStat.st_mtime); break; - case 3: { /* data */ + case FSDIR_COLUMN_DATA: { mode_t m = pCur->sStat.st_mode; if( S_ISDIR(m) ){ sqlite3_result_null(ctx); @@ -2760,6 +2771,12 @@ readFileContents(ctx, pCur->zPath); } } + case FSDIR_COLUMN_PATH: + default: { + /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters. + ** always return their values as NULL */ + break; + } } return SQLITE_OK; } @@ -2786,6 +2803,9 @@ /* ** xFilter callback. +** +** idxNum==1 PATH parameter only +** idxNum==2 Both PATH and DIR supplied */ static int fsdirFilter( sqlite3_vtab_cursor *cur, @@ -2838,40 +2858,63 @@ ** In this implementation idxNum is used to represent the ** query plan. idxStr is unused. ** -** The query plan is represented by bits in idxNum: +** The query plan is represented by values of idxNum: ** -** (1) start = $value -- constraint exists -** (2) stop = $value -- constraint exists -** (4) step = $value -- constraint exists -** (8) output in descending order +** (1) The path value is supplied by argv[0] +** (2) Path is in argv[0] and dir is in argv[1] */ static int fsdirBestIndex( sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ int i; /* Loop over constraints */ - int idx4 = -1; - int idx5 = -1; + int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */ + int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */ + int seenPath = 0; /* True if an unusable PATH= constraint is seen */ + int seenDir = 0; /* True if an unusable DIR= constraint is seen */ const struct sqlite3_index_constraint *pConstraint; (void)tab; pConstraint = pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ - if( pConstraint->usable==0 ) continue; if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; - if( pConstraint->iColumn==4 ) idx4 = i; - if( pConstraint->iColumn==5 ) idx5 = i; + switch( pConstraint->iColumn ){ + case FSDIR_COLUMN_PATH: { + if( pConstraint->usable ){ + idxPath = i; + seenPath = 0; + }else if( idxPath<0 ){ + seenPath = 1; + } + break; + } + case FSDIR_COLUMN_DIR: { + if( pConstraint->usable ){ + idxDir = i; + seenDir = 0; + }else if( idxDir<0 ){ + seenDir = 1; + } + break; + } + } + } + if( seenPath || seenDir ){ + /* If input parameters are unusable, disallow this plan */ + return SQLITE_CONSTRAINT; } - if( idx4<0 ){ + if( idxPath<0 ){ pIdxInfo->idxNum = 0; - pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50); + /* The pIdxInfo->estimatedCost should have been initialized to a huge + ** number. Leave it unchanged. */ + pIdxInfo->estimatedRows = 0x7fffffff; }else{ - pIdxInfo->aConstraintUsage[idx4].omit = 1; - pIdxInfo->aConstraintUsage[idx4].argvIndex = 1; - if( idx5>=0 ){ - pIdxInfo->aConstraintUsage[idx5].omit = 1; - pIdxInfo->aConstraintUsage[idx5].argvIndex = 2; + pIdxInfo->aConstraintUsage[idxPath].omit = 1; + pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1; + if( idxDir>=0 ){ + pIdxInfo->aConstraintUsage[idxDir].omit = 1; + pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2; pIdxInfo->idxNum = 2; pIdxInfo->estimatedCost = 10.0; }else{ @@ -2910,7 +2953,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0, /* xShadowName */ }; int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0); @@ -3418,7 +3462,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -5315,25 +5360,26 @@ sqlite3_index_info *pIdxInfo ){ int i; + int idx = -1; + int unusable = 0; for(i=0; i<pIdxInfo->nConstraint; i++){ const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i]; - if( pCons->usable==0 ) continue; - if( pCons->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue; - break; + if( pCons->usable==0 ){ + unusable = 1; + }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + idx = i; + } } - - if( i<pIdxInfo->nConstraint ){ - pIdxInfo->aConstraintUsage[i].argvIndex = 1; - pIdxInfo->aConstraintUsage[i].omit = 1; + if( idx>=0 ){ + pIdxInfo->aConstraintUsage[idx].argvIndex = 1; + pIdxInfo->aConstraintUsage[idx].omit = 1; pIdxInfo->estimatedCost = 1000.0; pIdxInfo->idxNum = 1; - }else{ - pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50); - pIdxInfo->idxNum = 0; + }else if( unusable ){ + return SQLITE_CONSTRAINT; } - return SQLITE_OK; } @@ -7136,6 +7182,7 @@ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ + 0, /* xShadowName */ }; return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p); @@ -8560,11 +8607,12 @@ /* Allowed values for ShellState.openMode */ -#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */ -#define SHELL_OPEN_NORMAL 1 /* Normal database file */ -#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */ -#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */ -#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */ +#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */ +#define SHELL_OPEN_NORMAL 1 /* Normal database file */ +#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */ +#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */ +#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */ +#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */ /* ** These are the allowed shellFlgs values @@ -8774,7 +8822,7 @@ if( bBin ){ sqlite3_result_blob64(context, p, sz, sqlite3_free); }else{ - int i, j; + sqlite3_int64 i, j; if( hasCRNL ){ /* If the original contains \r\n then do no conversions back to \n */ j = sz; @@ -10836,137 +10884,238 @@ } /* -** Text of a help message +** Text of help messages. +** +** The help text for each individual command begins with a line that starts +** with ".". Subsequent lines are supplimental information. +** +** There must be two or more spaces between the end of the command and the +** start of the description of what that command does. */ -static char zHelp[] = +static const char *(azHelp[]) = { #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE) - ".archive ... Manage SQL archives: \".archive --help\" for details\n" + ".archive ... Manage SQL archives", + " Each command must have exactly one of the following options:", + " -c, --create Create a new archive", + " -u, --update Update or add files to an existing archive", + " -t, --list List contents of archive", + " -x, --extract Extract files from archive", + " Optional arguments:", + " -v, --verbose Print each filename as it is processed", + " -f FILE, --file FILE Operate on archive FILE (default is current db)", + " -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS", + " -C DIR, --directory DIR Change to directory DIR to read/extract files", + " -n, --dryrun Show the SQL that would have occurred", + " Examples:", + " .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar", + " .ar -tf archive.sar # List members of archive.sar", + " .ar -xvf archive.sar # Verbosely extract files from archive.sar", + " See also:", + " http://sqlite.org/cli.html#sqlar_archive_support", #endif #ifndef SQLITE_OMIT_AUTHORIZATION - ".auth ON|OFF Show authorizer callbacks\n" + ".auth ON|OFF Show authorizer callbacks", #endif - ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" - " Add \"--append\" to open using appendvfs.\n" - ".bail on|off Stop after hitting an error. Default OFF\n" - ".binary on|off Turn binary output on or off. Default OFF\n" - ".cd DIRECTORY Change the working directory to DIRECTORY\n" - ".changes on|off Show number of rows changed by SQL\n" - ".check GLOB Fail if output since .testcase does not match\n" - ".clone NEWDB Clone data into NEWDB from the existing database\n" - ".databases List names and files of attached databases\n" - ".dbconfig ?op? ?val? List or change sqlite3_db_config() options\n" - ".dbinfo ?DB? Show status information about the database\n" - ".dump ?TABLE? ... Dump the database in an SQL text format\n" - " If TABLE specified, only dump tables matching\n" - " LIKE pattern TABLE.\n" - ".echo on|off Turn command echo on or off\n" - ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN\n" - ".excel Display the output of next command in a spreadsheet\n" - ".exit Exit this program\n" - ".expert EXPERIMENTAL. Suggest indexes for specified queries\n" + ".backup ?DB? FILE Backup DB (default \"main\") to FILE", + " --append Use the appendvfs", + ".bail on|off Stop after hitting an error. Default OFF", + ".binary on|off Turn binary output on or off. Default OFF", + ".cd DIRECTORY Change the working directory to DIRECTORY", + ".changes on|off Show number of rows changed by SQL", + ".check GLOB Fail if output since .testcase does not match", + ".clone NEWDB Clone data into NEWDB from the existing database", + ".databases List names and files of attached databases", + ".dbconfig ?op? ?val? List or change sqlite3_db_config() options", + ".dbinfo ?DB? Show status information about the database", + ".dump ?TABLE? ... Render all database content as SQL", + " Options:", + " --preserve-rowids Include ROWID values in the output", + " --newlines Allow unescaped newline characters in output", + " TABLE is LIKE pattern for the tables to dump", + ".echo on|off Turn command echo on or off", + ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN", + ".excel Display the output of next command in a spreadsheet", + ".exit ?CODE? Exit this program with return-code CODE", + ".expert EXPERIMENTAL. Suggest indexes for specified queries", /* Because explain mode comes on automatically now, the ".explain" mode ** is removed from the help screen. It is still supported for legacy, however */ -/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"*/ - ".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n" - ".headers on|off Turn display of headers on or off\n" - ".help Show this message\n" - ".import FILE TABLE Import data from FILE into TABLE\n" +/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic",*/ + ".fullschema ?--indent? Show schema and the content of sqlite_stat tables", + ".headers on|off Turn display of headers on or off", + ".help ?-all? ?PATTERN? Show help text for PATTERN", + ".import FILE TABLE Import data from FILE into TABLE", #ifndef SQLITE_OMIT_TEST_CONTROL - ".imposter INDEX TABLE Create imposter table TABLE on index INDEX\n" + ".imposter INDEX TABLE Create imposter table TABLE on index INDEX", #endif - ".indexes ?TABLE? Show names of all indexes\n" - " If TABLE specified, only show indexes for tables\n" - " matching LIKE pattern TABLE.\n" + ".indexes ?TABLE? Show names of indexes", + " If TABLE is specified, only show indexes for", + " tables matching TABLE using the LIKE operator.", #ifdef SQLITE_ENABLE_IOTRACE - ".iotrace FILE Enable I/O diagnostic logging to FILE\n" + ".iotrace FILE Enable I/O diagnostic logging to FILE", #endif - ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n" - ".lint OPTIONS Report potential schema issues. Options:\n" - " fkey-indexes Find missing foreign key indexes\n" + ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT", + ".lint OPTIONS Report potential schema issues.", + " Options:", + " fkey-indexes Find missing foreign key indexes", #ifndef SQLITE_OMIT_LOAD_EXTENSION - ".load FILE ?ENTRY? Load an extension library\n" + ".load FILE ?ENTRY? Load an extension library", #endif - ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n" - ".mode MODE ?TABLE? Set output mode where MODE is one of:\n" - " ascii Columns/rows delimited by 0x1F and 0x1E\n" - " csv Comma-separated values\n" - " column Left-aligned columns. (See .width)\n" - " html HTML <table> code\n" - " insert SQL insert statements for TABLE\n" - " line One value per line\n" - " list Values delimited by \"|\"\n" - " quote Escape answers as for SQL\n" - " tabs Tab-separated values\n" - " tcl TCL list elements\n" - ".nullvalue STRING Use STRING in place of NULL values\n" - ".once (-e|-x|FILE) Output for the next SQL command only to FILE\n" - " or invoke system text editor (-e) or spreadsheet (-x)\n" - " on the output.\n" - ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n" - " The --new option starts with an empty file\n" - " Other options: --readonly --append --zip\n" - ".output ?FILE? Send output to FILE or stdout\n" - ".print STRING... Print literal STRING\n" - ".prompt MAIN CONTINUE Replace the standard prompts\n" - ".quit Exit this program\n" - ".read FILENAME Execute SQL in FILENAME\n" - ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" - ".save FILE Write in-memory database into FILE\n" - ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n" - ".schema ?PATTERN? Show the CREATE statements matching PATTERN\n" - " Add --indent for pretty-printing\n" - ".selftest ?--init? Run tests defined in the SELFTEST table\n" - ".separator COL ?ROW? Change the column separator and optionally the row\n" - " separator for both the output mode and .import\n" + ".log FILE|off Turn logging on or off. FILE can be stderr/stdout", + ".mode MODE ?TABLE? Set output mode", + " MODE is one of:", + " ascii Columns/rows delimited by 0x1F and 0x1E", + " csv Comma-separated values", + " column Left-aligned columns. (See .width)", + " html HTML <table> code", + " insert SQL insert statements for TABLE", + " line One value per line", + " list Values delimited by \"|\"", + " quote Escape answers as for SQL", + " tabs Tab-separated values", + " tcl TCL list elements", + ".nullvalue STRING Use STRING in place of NULL values", + ".once (-e|-x|FILE) Output for the next SQL command only to FILE", + " If FILE begins with '|' then open as a pipe", + " Other options:", + " -e Invoke system text editor", + " -x Open in a spreadsheet", + ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE", + " Options:", + " --append Use appendvfs to append database to the end of FILE", +#ifdef SQLITE_ENABLE_DESERIALIZE + " --deserialize Load into memory useing sqlite3_deserialize()", +#endif + " --new Initialize FILE to an empty database", + " --readonly Open FILE readonly", + " --zip FILE is a ZIP archive", + ".output ?FILE? Send output to FILE or stdout if FILE is omitted", + " If FILE begins with '|' then open it as a pipe.", + ".print STRING... Print literal STRING", + ".prompt MAIN CONTINUE Replace the standard prompts", + ".quit Exit this program", + ".read FILE Read input from FILE", + ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE", + ".save FILE Write in-memory database into FILE", + ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off", + ".schema ?PATTERN? Show the CREATE statements matching PATTERN", + " Options:", + " --indent Try to pretty-print the schema", + ".selftest ?OPTIONS? Run tests defined in the SELFTEST table", + " Options:", + " --init Create a new SELFTEST table", + " -v Verbose output", + ".separator COL ?ROW? Change the column and row separators", #if defined(SQLITE_ENABLE_SESSION) - ".session CMD ... Create or control sessions\n" + ".session ?NAME? CMD ... Create or control sessions", + " Subcommands:", + " attach TABLE Attach TABLE", + " changeset FILE Write a changeset into FILE", + " close Close one session", + " enable ?BOOLEAN? Set or query the enable bit", + " filter GLOB... Reject tables matching GLOBs", + " indirect ?BOOLEAN? Mark or query the indirect status", + " isempty Query whether the session is empty", + " list List currently open session names", + " open DB NAME Open a new session on DB", + " patchset FILE Write a patchset into FILE", + " If ?NAME? is omitted, the first defined session is used.", #endif - ".sha3sum ?OPTIONS...? Compute a SHA3 hash of database content\n" + ".sha3sum ... Compute a SHA3 hash of database content", + " Options:", + " --schema Also hash the sqlite_master table", + " --sha3-224 Use the sha3-224 algorithm", + " --sha3-256 Use the sha3-256 algorithm. This is the default.", + " --sha3-384 Use the sha3-384 algorithm", + " --sha3-512 Use the sha3-512 algorithm", + " Any other argument is a LIKE pattern for tables to hash", #ifndef SQLITE_NOHAVE_SYSTEM - ".shell CMD ARGS... Run CMD ARGS... in a system shell\n" + ".shell CMD ARGS... Run CMD ARGS... in a system shell", #endif - ".show Show the current values for various settings\n" - ".stats ?on|off? Show stats or turn stats on or off\n" + ".show Show the current values for various settings", + ".stats ?on|off? Show stats or turn stats on or off", #ifndef SQLITE_NOHAVE_SYSTEM - ".system CMD ARGS... Run CMD ARGS... in a system shell\n" + ".system CMD ARGS... Run CMD ARGS... in a system shell", #endif - ".tables ?TABLE? List names of tables\n" - " If TABLE specified, only list tables matching\n" - " LIKE pattern TABLE.\n" - ".testcase NAME Begin redirecting output to 'testcase-out.txt'\n" - ".timeout MS Try opening locked tables for MS milliseconds\n" - ".timer on|off Turn SQL timer on or off\n" - ".trace FILE|off Output each SQL statement as it is run\n" - ".vfsinfo ?AUX? Information about the top-level VFS\n" - ".vfslist List all available VFSes\n" - ".vfsname ?AUX? Print the name of the VFS stack\n" - ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" - " Negative values right-justify\n" -; + ".tables ?TABLE? List names of tables matching LIKE pattern TABLE", + ".testcase NAME Begin redirecting output to 'testcase-out.txt'", + ".timeout MS Try opening locked tables for MS milliseconds", + ".timer on|off Turn SQL timer on or off", + ".trace FILE|off Output each SQL statement as it is run", + ".vfsinfo ?AUX? Information about the top-level VFS", + ".vfslist List all available VFSes", + ".vfsname ?AUX? Print the name of the VFS stack", + ".width NUM1 NUM2 ... Set column widths for \"column\" mode", + " Negative values right-justify", +}; -#if defined(SQLITE_ENABLE_SESSION) /* -** Print help information for the ".sessions" command +** Output help text. +** +** zPattern describes the set of commands for which help text is provided. +** If zPattern is NULL, then show all commands, but only give a one-line +** description of each. +** +** Return the number of matches. */ -void session_help(ShellState *p){ - raw_printf(p->out, - ".session ?NAME? SUBCOMMAND ?ARGS...?\n" - "If ?NAME? is omitted, the first defined session is used.\n" - "Subcommands:\n" - " attach TABLE Attach TABLE\n" - " changeset FILE Write a changeset into FILE\n" - " close Close one session\n" - " enable ?BOOLEAN? Set or query the enable bit\n" - " filter GLOB... Reject tables matching GLOBs\n" - " indirect ?BOOLEAN? Mark or query the indirect status\n" - " isempty Query whether the session is empty\n" - " list List currently open session names\n" - " open DB NAME Open a new session on DB\n" - " patchset FILE Write a patchset into FILE\n" - ); +static int showHelp(FILE *out, const char *zPattern){ + int i = 0; + int j = 0; + int n = 0; + char *zPat; + if( zPattern==0 + || zPattern[0]=='0' + || strcmp(zPattern,"-a")==0 + || strcmp(zPattern,"-all")==0 + ){ + /* Show all commands, but only one line per command */ + if( zPattern==0 ) zPattern = ""; + for(i=0; i<ArraySize(azHelp); i++){ + if( azHelp[i][0]=='.' || zPattern[0] ){ + utf8_printf(out, "%s\n", azHelp[i]); + n++; + } + } + }else{ + /* Look for commands that for which zPattern is an exact prefix */ + zPat = sqlite3_mprintf(".%s*", zPattern); + for(i=0; i<ArraySize(azHelp); i++){ + if( sqlite3_strglob(zPat, azHelp[i])==0 ){ + utf8_printf(out, "%s\n", azHelp[i]); + j = i+1; + n++; + } + } + sqlite3_free(zPat); + if( n ){ + if( n==1 ){ + /* when zPattern is a prefix of exactly one command, then include the + ** details of that command, which should begin at offset j */ + while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){ + utf8_printf(out, "%s\n", azHelp[j]); + j++; + } + } + return n; + } + /* Look for commands that contain zPattern anywhere. Show the complete + ** text of all commands that match. */ + zPat = sqlite3_mprintf("%%%s%%", zPattern); + for(i=0; i<ArraySize(azHelp); i++){ + if( azHelp[i][0]=='.' ) j = i; + if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){ + utf8_printf(out, "%s\n", azHelp[j]); + while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){ + j++; + utf8_printf(out, "%s\n", azHelp[j]); + } + i = j; + n++; + } + } + sqlite3_free(zPat); + } + return n; } -#endif - /* Forward reference */ static int process_input(ShellState *p, FILE *in); @@ -10996,7 +11145,7 @@ nIn = ftell(in); rewind(in); pBuf = sqlite3_malloc64( nIn+1 ); - if( pBuf==0 ) return 0; + if( pBuf==0 ){ fclose(in); return 0; } nRead = fread(pBuf, nIn, 1, in); fclose(in); if( nRead!=1 ){ @@ -11076,6 +11225,11 @@ return SHELL_OPEN_NORMAL; } } + n = fread(zBuf, 16, 1, f); + if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){ + fclose(f); + return SHELL_OPEN_NORMAL; + } fseek(f, -25, SEEK_END); n = fread(zBuf, 25, 1, f); if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){ @@ -11127,6 +11281,10 @@ SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs"); break; } + case SHELL_OPEN_DESERIALIZE: { + sqlite3_open(0, &p->db); + break; + } case SHELL_OPEN_ZIPFILE: { sqlite3_open(":memory:", &p->db); break; @@ -11176,6 +11334,18 @@ sqlite3_exec(p->db, zSql, 0, 0, 0); sqlite3_free(zSql); } +#ifdef SQLITE_ENABLE_DESERIALIZE + else if( p->openMode==SHELL_OPEN_DESERIALIZE ){ + int nData = 0; + unsigned char *aData = (unsigned char*)readFile(p->zDbFilename, &nData); + int rc = sqlite3_deserialize(p->db, "main", aData, nData, nData, + SQLITE_DESERIALIZE_RESIZEABLE | + SQLITE_DESERIALIZE_FREEONCLOSE); + if( rc ){ + utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc); + } + } +#endif } } @@ -12380,6 +12550,7 @@ char *z; va_start(ap, zFmt); z = sqlite3_vmprintf(zFmt, ap); + va_end(ap); if( z==0 ){ *pRc = SQLITE_NOMEM; }else{ @@ -12442,32 +12613,7 @@ ** Print a usage message for the .ar command to stderr and return SQLITE_ERROR. */ static int arUsage(FILE *f){ - raw_printf(f, -"\n" -"Usage: .ar [OPTION...] [FILE...]\n" -"The .ar command manages sqlar archives.\n" -"\n" -"Examples:\n" -" .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar\n" -" .ar -tf archive.sar # List members of archive.sar\n" -" .ar -xvf archive.sar # Verbosely extract files from archive.sar\n" -"\n" -"Each command line must feature exactly one command option:\n" -" -c, --create Create a new archive\n" -" -u, --update Update or add files to an existing archive\n" -" -t, --list List contents of archive\n" -" -x, --extract Extract files from archive\n" -"\n" -"And zero or more optional options:\n" -" -v, --verbose Print each filename as it is processed\n" -" -f FILE, --file FILE Operate on archive FILE (default is current db)\n" -" -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS\n" -" -C DIR, --directory DIR Change to directory DIR to read/extract files\n" -" -n, --dryrun Show the SQL that would have occurred\n" -"\n" -"See also: http://sqlite.org/cli.html#sqlar_archive_support\n" -"\n" -); + showHelp(f,"archive"); return SQLITE_ERROR; } @@ -12574,6 +12720,7 @@ struct ArSwitch *pEnd = &aSwitch[nSwitch]; if( nArg<=1 ){ + utf8_printf(stderr, "Wrong number of arguments. Usage:\n"); return arUsage(stderr); }else{ char *z = azArg[1]; @@ -13345,7 +13492,10 @@ }else if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){ - static const struct DbConfigChoices {const char *zName; int op;} aDbConfig[] = { + static const struct DbConfigChoices { + const char *zName; + int op; + } aDbConfig[] = { { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY }, { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER }, { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, @@ -13354,6 +13504,7 @@ { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG }, { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP }, { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE }, + { "defensive", SQLITE_DBCONFIG_DEFENSIVE }, }; int ii, v; open_db(p, 0); @@ -13592,7 +13743,14 @@ }else if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ - utf8_printf(p->out, "%s", zHelp); + if( nArg>=2 ){ + n = showHelp(p->out, azArg[1]); + if( n==0 ){ + utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]); + } + }else{ + showHelp(p->out, 0); + } }else if( c=='i' && strncmp(azArg[0], "import", n)==0 ){ @@ -14069,6 +14227,10 @@ p->openMode = SHELL_OPEN_APPENDVFS; }else if( optionMatch(z, "readonly") ){ p->openMode = SHELL_OPEN_READONLY; +#ifdef SQLITE_ENABLE_DESERIALIZE + }else if( optionMatch(z, "deserialize") ){ + p->openMode = SHELL_OPEN_DESERIALIZE; +#endif }else if( z[0]=='-' ){ utf8_printf(stderr, "unknown option: %s\n", z); rc = 1; @@ -14596,7 +14758,7 @@ }else /* If no command name matches, show a syntax error */ session_syntax_error: - session_help(p); + showHelp(p->out, "session"); }else #endif @@ -15063,6 +15225,7 @@ { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" }, /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */ { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"}, + { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" }, { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" }, { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" }, { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" }, @@ -15157,6 +15320,7 @@ /* sqlite3_test_control(int, int) */ case SQLITE_TESTCTRL_ASSERT: case SQLITE_TESTCTRL_ALWAYS: + case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: if( nArg==3 ){ int opt = booleanValue(azArg[2]); rc2 = sqlite3_test_control(testctrl, opt); @@ -15451,7 +15615,7 @@ ** user-friendly, but it does seem to work. */ #ifdef SQLITE_OMIT_COMPLETE -int sqlite3_complete(const char *zSql){ return 1; } +#define sqlite3_complete(x) 1 #endif /* @@ -16047,6 +16211,10 @@ #endif }else if( strcmp(z,"-append")==0 ){ data.openMode = SHELL_OPEN_APPENDVFS; +#ifdef SQLITE_ENABLE_DESERIALIZE + }else if( strcmp(z,"-deserialize")==0 ){ + data.openMode = SHELL_OPEN_DESERIALIZE; +#endif }else if( strcmp(z,"-readonly")==0 ){ data.openMode = SHELL_OPEN_READONLY; #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) @@ -16142,6 +16310,10 @@ #endif }else if( strcmp(z,"-append")==0 ){ data.openMode = SHELL_OPEN_APPENDVFS; +#ifdef SQLITE_ENABLE_DESERIALIZE + }else if( strcmp(z,"-deserialize")==0 ){ + data.openMode = SHELL_OPEN_DESERIALIZE; +#endif }else if( strcmp(z,"-readonly")==0 ){ data.openMode = SHELL_OPEN_READONLY; }else if( strcmp(z,"-ascii")==0 ){ @@ -16286,7 +16458,7 @@ */ if( stdin_is_interactive ){ char *zHome; - char *zHistory = 0; + char *zHistory; int nHistory; printf( "SQLite version %s %.19s\n" /*extra-version-info*/ @@ -16299,8 +16471,10 @@ printf(".\nUse \".open FILENAME\" to reopen on a " "persistent database.\n"); } - zHome = find_home_dir(0); - if( zHome ){ + zHistory = getenv("SQLITE_HISTORY"); + if( zHistory ){ + zHistory = strdup(zHistory); + }else if( (zHome = find_home_dir(0))!=0 ){ nHistory = strlen30(zHome) + 20; if( (zHistory = malloc(nHistory))!=0 ){ sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
diff --git a/third_party/sqlite/amalgamation/sqlite3.c b/third_party/sqlite/amalgamation/sqlite3.c index f8273ff..75cc12fd 100644 --- a/third_party/sqlite/amalgamation/sqlite3.c +++ b/third_party/sqlite/amalgamation/sqlite3.c
@@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.25.3. By combining all the individual C code files into this +** version 3.26.0. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -260,6 +260,9 @@ #if SQLITE_ENABLE_FTS5 "ENABLE_FTS5", #endif +#if SQLITE_ENABLE_GEOPOLY + "ENABLE_GEOPOLY", +#endif #if SQLITE_ENABLE_HIDDEN_COLUMNS "ENABLE_HIDDEN_COLUMNS", #endif @@ -290,6 +293,9 @@ #if SQLITE_ENABLE_MULTIPLEX "ENABLE_MULTIPLEX", #endif +#if SQLITE_ENABLE_NORMALIZE + "ENABLE_NORMALIZE", +#endif #if SQLITE_ENABLE_NULL_TRIM "ENABLE_NULL_TRIM", #endif @@ -1156,9 +1162,9 @@ ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.25.3" -#define SQLITE_VERSION_NUMBER 3025003 -#define SQLITE_SOURCE_ID "2018-11-05 20:37:38 89e099fbe5e13c33e683bef07361231ca525b88f7907be7092058007b750alt1" +#define SQLITE_VERSION "3.26.0" +#define SQLITE_VERSION_NUMBER 3026000 +#define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238alt1" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -3050,6 +3056,7 @@ ** is invoked. ** ** <dl> +** [[SQLITE_DBCONFIG_LOOKASIDE]] ** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt> ** <dd> ^This option takes three additional arguments that determine the ** [lookaside memory allocator] configuration for the [database connection]. @@ -3072,6 +3079,7 @@ ** memory is in use leaves the configuration unchanged and returns ** [SQLITE_BUSY].)^</dd> ** +** [[SQLITE_DBCONFIG_ENABLE_FKEY]] ** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt> ** <dd> ^This option is used to enable or disable the enforcement of ** [foreign key constraints]. There should be two additional arguments. @@ -3082,6 +3090,7 @@ ** following this call. The second parameter may be a NULL pointer, in ** which case the FK enforcement setting is not reported back. </dd> ** +** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]] ** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt> ** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers]. ** There should be two additional arguments. @@ -3092,6 +3101,7 @@ ** following this call. The second parameter may be a NULL pointer, in ** which case the trigger setting is not reported back. </dd> ** +** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt> ** <dd> ^This option is used to enable or disable the two-argument ** version of the [fts3_tokenizer()] function which is part of the @@ -3105,6 +3115,7 @@ ** following this call. The second parameter may be a NULL pointer, in ** which case the new setting is not reported back. </dd> ** +** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]] ** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt> ** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()] ** interface independently of the [load_extension()] SQL function. @@ -3122,7 +3133,7 @@ ** be a NULL pointer, in which case the new setting is not reported back. ** </dd> ** -** <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> +** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> ** <dd> ^This option is used to change the name of the "main" database ** schema. ^The sole argument is a pointer to a constant UTF8 string ** which will become the new schema name in place of "main". ^SQLite @@ -3131,6 +3142,7 @@ ** until after the database connection closes. ** </dd> ** +** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]] ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> ** <dd> Usually, when a database in wal mode is closed or detached from a ** database handle, SQLite checks if this will mean that there are now no @@ -3144,7 +3156,7 @@ ** have been disabled - 0 if they are not disabled, 1 if they are. ** </dd> ** -** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> +** [[SQLITE_DBCONFIG_ENABLE_QPSG]] <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> ** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates ** the [query planner stability guarantee] (QPSG). When the QPSG is active, ** a single SQL query statement will always use the same algorithm regardless @@ -3160,7 +3172,7 @@ ** following this call. ** </dd> ** -** <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt> +** [[SQLITE_DBCONFIG_TRIGGER_EQP]] <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt> ** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not ** include output for any operations performed by trigger programs. This ** option is used to set or clear (the default) a flag that governs this @@ -3172,7 +3184,7 @@ ** it is not disabled, 1 if it is. ** </dd> ** -** <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt> +** [[SQLITE_DBCONFIG_RESET_DATABASE]] <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt> ** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run ** [VACUUM] in order to reset a database back to an empty database ** with no schema and no content. The following process works even for @@ -3191,6 +3203,18 @@ ** Because resetting a database is destructive and irreversible, the ** process requires the use of this obscure API and multiple steps to help ** ensure that it does not happen by accident. +** +** [[SQLITE_DBCONFIG_DEFENSIVE]] <dt>SQLITE_DBCONFIG_DEFENSIVE</dt> +** <dd>The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the +** "defensive" flag for a database connection. When the defensive +** flag is enabled, language features that allow ordinary SQL to +** deliberately corrupt the database file are disabled. The disabled +** features include but are not limited to the following: +** <ul> +** <li> The [PRAGMA writable_schema=ON] statement. +** <li> Writes to the [sqlite_dbpage] virtual table. +** <li> Direct writes to [shadow tables]. +** </ul> ** </dd> ** </dl> */ @@ -3204,7 +3228,8 @@ #define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */ #define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */ #define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ -#define SQLITE_DBCONFIG_MAX 1009 /* Largest DBCONFIG */ +#define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */ +#define SQLITE_DBCONFIG_MAX 1010 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes @@ -4642,9 +4667,19 @@ ** on this hint by avoiding the use of [lookaside memory] so as not to ** deplete the limited store of lookaside memory. Future versions of ** SQLite may act on this hint differently. +** +** [[SQLITE_PREPARE_NORMALIZE]] ^(<dt>SQLITE_PREPARE_NORMALIZE</dt> +** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized +** representation of the SQL statement should be calculated and then +** associated with the prepared statement, which can be obtained via +** the [sqlite3_normalized_sql()] interface.)^ The semantics used to +** normalize a SQL statement are unspecified and subject to change. +** At a minimum, literal values will be replaced with suitable +** placeholders. ** </dl> */ #define SQLITE_PREPARE_PERSISTENT 0x01 +#define SQLITE_PREPARE_NORMALIZE 0x02 /* ** CAPI3REF: Compiling An SQL Statement @@ -4802,6 +4837,11 @@ ** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8 ** string containing the SQL text of prepared statement P with ** [bound parameters] expanded. +** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8 +** string containing the normalized SQL text of prepared statement P. The +** semantics used to normalize a SQL statement are unspecified and subject +** to change. At a minimum, literal values will be replaced with suitable +** placeholders. ** ** ^(For example, if a prepared statement is created using the SQL ** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 @@ -4817,14 +4857,16 @@ ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time ** option causes sqlite3_expanded_sql() to always return NULL. ** -** ^The string returned by sqlite3_sql(P) is managed by SQLite and is -** automatically freed when the prepared statement is finalized. +** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P) +** are managed by SQLite and are automatically freed when the prepared +** statement is finalized. ** ^The string returned by sqlite3_expanded_sql(P), on the other hand, ** is obtained from [sqlite3_malloc()] and must be free by the application ** by passing it to [sqlite3_free()]. */ SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); +SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If An SQL Statement Writes The Database @@ -7314,6 +7356,9 @@ int (*xSavepoint)(sqlite3_vtab *pVTab, int); int (*xRelease)(sqlite3_vtab *pVTab, int); int (*xRollbackTo)(sqlite3_vtab *pVTab, int); + /* The methods above are in versions 1 and 2 of the sqlite_module object. + ** Those below are for version 3 and greater. */ + int (*xShadowName)(const char*); }; /* @@ -8236,6 +8281,7 @@ #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ +#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 @@ -9671,6 +9717,7 @@ ** can use to customize and optimize their behavior. ** ** <dl> +** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]] ** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT ** <dd>Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, @@ -10440,7 +10487,7 @@ sqlite3_int64 iRowid; /* Rowid for current entry */ sqlite3_rtree_dbl rParentScore; /* Score of parent node */ int eParentWithin; /* Visibility of parent node */ - int eWithin; /* OUT: Visiblity */ + int eWithin; /* OUT: Visibility */ sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ /* The following fields are only available in 3.8.11 and later */ sqlite3_value **apSqlParam; /* Original SQL values of parameters */ @@ -10936,12 +10983,38 @@ ** consecutively. There is no chance that the iterator will visit a change ** the applies to table X, then one for table Y, and then later on visit ** another change for table X. +** +** The behavior of sqlite3changeset_start_v2() and its streaming equivalent +** may be modified by passing a combination of +** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter. +** +** Note that the sqlite3changeset_start_v2() API is still <b>experimental</b> +** and therefore subject to change. */ SQLITE_API int sqlite3changeset_start( sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ int nChangeset, /* Size of changeset blob in bytes */ void *pChangeset /* Pointer to blob containing changeset */ ); +SQLITE_API int sqlite3changeset_start_v2( + sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ + int nChangeset, /* Size of changeset blob in bytes */ + void *pChangeset, /* Pointer to blob containing changeset */ + int flags /* SESSION_CHANGESETSTART_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3changeset_start_v2 +** +** The following flags may passed via the 4th parameter to +** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]: +** +** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd> +** Invert the changeset while iterating through it. This is equivalent to +** inverting a changeset using sqlite3changeset_invert() before applying it. +** It is an error to specify this flag with a patchset. +*/ +#define SQLITE_CHANGESETSTART_INVERT 0x0002 /* @@ -11596,7 +11669,7 @@ ), void *pCtx, /* First argument passed to xConflict */ void **ppRebase, int *pnRebase, /* OUT: Rebase data */ - int flags /* Combination of SESSION_APPLY_* flags */ + int flags /* SESSION_CHANGESETAPPLY_* flags */ ); /* @@ -11614,8 +11687,14 @@ ** causes the sessions module to omit this savepoint. In this case, if the ** caller has an open transaction or savepoint when apply_v2() is called, ** it may revert the partially applied changeset by rolling it back. +** +** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd> +** Invert the changeset before applying it. This is equivalent to inverting +** a changeset using sqlite3changeset_invert() before applying it. It is +** an error to specify this flag with a patchset. */ #define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 +#define SQLITE_CHANGESETAPPLY_INVERT 0x0002 /* ** CAPI3REF: Constants Passed To The Conflict Handler @@ -12009,6 +12088,12 @@ int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); +SQLITE_API int sqlite3changeset_start_v2_strm( + sqlite3_changeset_iter **pp, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int flags +); SQLITE_API int sqlite3session_changeset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), @@ -12035,6 +12120,45 @@ void *pOut ); +/* +** CAPI3REF: Configure global parameters +** +** The sqlite3session_config() interface is used to make global configuration +** changes to the sessions module in order to tune it to the specific needs +** of the application. +** +** The sqlite3session_config() interface is not threadsafe. If it is invoked +** while any other thread is inside any other sessions method then the +** results are undefined. Furthermore, if it is invoked after any sessions +** related objects have been created, the results are also undefined. +** +** The first argument to the sqlite3session_config() function must be one +** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The +** interpretation of the (void*) value passed as the second parameter and +** the effect of calling this function depends on the value of the first +** parameter. +** +** <dl> +** <dt>SQLITE_SESSION_CONFIG_STRMSIZE<dd> +** By default, the sessions module streaming interfaces attempt to input +** and output data in approximately 1 KiB chunks. This operand may be used +** to set and query the value of this configuration setting. The pointer +** passed as the second argument must point to a value of type (int). +** If this value is greater than 0, it is used as the new streaming data +** chunk size for both input and output. Before returning, the (int) value +** pointed to by pArg is set to the final value of the streaming interface +** chunk size. +** </dl> +** +** This function returns SQLITE_OK if successful, or an SQLite error code +** otherwise. +*/ +SQLITE_API int sqlite3session_config(int op, void *pArg); + +/* +** CAPI3REF: Values for sqlite3session_config(). +*/ +#define SQLITE_SESSION_CONFIG_STRMSIZE 1 /* ** Make sure we can call this stuff from C++. @@ -15291,9 +15415,6 @@ SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); -# ifdef SQLITE_DIRECT_OVERFLOW_READ -SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno); -# endif # ifdef SQLITE_ENABLE_SNAPSHOT SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); @@ -15301,8 +15422,10 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot); SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager); # endif -#else -# define sqlite3PagerUseWal(x,y) 0 +#endif + +#ifdef SQLITE_DIRECT_OVERFLOW_READ +SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno); #endif #ifdef SQLITE_ENABLE_ZIPVFS @@ -15547,6 +15670,10 @@ /* Number of dirty pages as a percentage of the configured cache size */ SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache*); +#ifdef SQLITE_DIRECT_OVERFLOW_READ +SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache); +#endif + #endif /* _PCACHE_H_ */ /************** End of pcache.h **********************************************/ @@ -16052,12 +16179,14 @@ ** functions use a regular table table from hash.h.) ** ** Hash each FuncDef structure into one of the FuncDefHash.a[] slots. -** Collisions are on the FuncDef.u.pHash chain. +** Collisions are on the FuncDef.u.pHash chain. Use the SQLITE_FUNC_HASH() +** macro to compute a hash on the function name. */ #define SQLITE_FUNC_HASH_SZ 23 struct FuncDefHash { FuncDef *a[SQLITE_FUNC_HASH_SZ]; /* Hash table for functions */ }; +#define SQLITE_FUNC_HASH(C,L) (((C)+(L))%SQLITE_FUNC_HASH_SZ) #ifdef SQLITE_USER_AUTHENTICATION /* @@ -16118,7 +16247,7 @@ Db *aDb; /* All backends */ int nDb; /* Number of backends currently in use */ u32 mDbFlags; /* flags recording internal state */ - u32 flags; /* flags settable by pragmas. See below */ + u64 flags; /* flags settable by pragmas. See below */ i64 lastRowid; /* ROWID of most recent insert (see above) */ i64 szMmap; /* Default mmap_size setting */ u32 nSchemaLock; /* Do not reset the schema when non-zero */ @@ -16284,14 +16413,17 @@ #define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */ #define SQLITE_ResetDatabase 0x02000000 /* Reset the database */ #define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */ +#define SQLITE_NoSchemaError 0x08000000 /* Do not report schema parse errors*/ +#define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */ /* Flags used only if debugging */ +#define HI(X) ((u64)(X)<<32) #ifdef SQLITE_DEBUG -#define SQLITE_SqlTrace 0x08000000 /* Debug print SQL as it executes */ -#define SQLITE_VdbeListing 0x10000000 /* Debug listings of VDBE programs */ -#define SQLITE_VdbeTrace 0x20000000 /* True to trace VDBE execution */ -#define SQLITE_VdbeAddopTrace 0x40000000 /* Trace sqlite3VdbeAddOp() calls */ -#define SQLITE_VdbeEQP 0x80000000 /* Debug EXPLAIN QUERY PLAN */ +#define SQLITE_SqlTrace HI(0x0001) /* Debug print SQL as it executes */ +#define SQLITE_VdbeListing HI(0x0002) /* Debug listings of VDBE progs */ +#define SQLITE_VdbeTrace HI(0x0004) /* True to trace VDBE execution */ +#define SQLITE_VdbeAddopTrace HI(0x0008) /* Trace sqlite3VdbeAddOp() calls */ +#define SQLITE_VdbeEQP HI(0x0010) /* Debug EXPLAIN QUERY PLAN */ #endif /* @@ -16425,8 +16557,9 @@ ** single query - might change over time */ #define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ #define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ -#define SQLITE_FUNC_WINDOW 0x10000 /* Built-in window-only function */ -#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */ +#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ +#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */ +#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are @@ -16502,10 +16635,13 @@ #define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}} - #define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}} +#define INTERNAL_FUNCTION(zName, nArg, xFunc) \ + {nArg, SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \ + 0, 0, xFunc, 0, 0, 0, #zName, {0} } + /* ** All current savepoints are stored in a linked list starting at @@ -16690,6 +16826,9 @@ struct Table { char *zName; /* Name of the table or view */ Column *aCol; /* Information about each column */ +#ifdef SQLITE_ENABLE_NORMALIZE + Hash *pColHash; /* All columns indexed by name */ +#endif Index *pIndex; /* List of SQL indexes on this table. */ Select *pSelect; /* NULL for tables. Points to definition if a view. */ FKey *pFKey; /* Linked list of all foreign keys in this table */ @@ -16740,6 +16879,7 @@ #define TF_StatsUsed 0x0100 /* Query planner decisions affected by ** Index.aiRowLogEst[] values */ #define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */ +#define TF_Shadow 0x0400 /* True for a shadow table */ /* ** Test to see whether or not a table is a virtual table. This is @@ -17027,6 +17167,12 @@ }; /* +** Possible values to use within the flags argument to sqlite3GetToken(). +*/ +#define SQLITE_TOKEN_QUOTED 0x1 /* Token is a quoted identifier. */ +#define SQLITE_TOKEN_KEYWORD 0x2 /* Token is a keyword. */ + +/* ** Each token coming out of the lexer is an instance of ** this structure. Tokens are also used as part of an expression. ** @@ -17207,11 +17353,11 @@ ** TK_COLUMN: the value of p5 for OP_Column ** TK_AGG_FUNCTION: nesting depth */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ - Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL - ** for a column of an index on an expression */ -#ifndef SQLITE_OMIT_WINDOWFUNC - Window *pWin; /* Window definition for window functions */ -#endif + union { + Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL + ** for a column of an index on an expression */ + Window *pWin; /* TK_FUNCTION: Window definition for the func */ + } y; }; /* @@ -17241,6 +17387,7 @@ #define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ #define EP_Alias 0x400000 /* Is an alias for a result set column */ #define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */ +#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */ /* ** The EP_Propagate mask is a set of properties that automatically propagate @@ -18145,6 +18292,7 @@ int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ #endif int bLocaltimeFault; /* True to fail localtime() calls */ + int bInternalFunctions; /* Internal SQL functions are visible */ int iOnceResetThreshold; /* When to reset OP_Once counters */ u32 szSorterRef; /* Min size in bytes to use sorter-refs */ }; @@ -18398,6 +18546,7 @@ */ SQLITE_PRIVATE int sqlite3StrICmp(const char*,const char*); SQLITE_PRIVATE int sqlite3Strlen30(const char*); +#define sqlite3Strlen30NN(C) (strlen(C)&0x3fffffff) SQLITE_PRIVATE char *sqlite3ColumnType(Column*,char*); #define sqlite3StrNICmp sqlite3_strnicmp @@ -18514,6 +18663,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8); SQLITE_PRIVATE void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*); SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*); +SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView*, const SrcList*); SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8); SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8); #ifndef SQLITE_OMIT_WINDOWFUNC @@ -18746,11 +18896,15 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*); SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); SQLITE_PRIVATE int sqlite3IsRowid(const char*); +#ifdef SQLITE_ENABLE_NORMALIZE +SQLITE_PRIVATE int sqlite3IsRowidN(const char*, int); +#endif SQLITE_PRIVATE void sqlite3GenerateRowDelete( Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int); SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int); +SQLITE_PRIVATE int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int); SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, u8,u8,int,int*,int*,Upsert*); #ifdef SQLITE_ENABLE_NULL_TRIM @@ -18771,6 +18925,9 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*); SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int); +#ifdef SQLITE_ENABLE_NORMALIZE +SQLITE_PRIVATE FuncDef *sqlite3FunctionSearchN(int,const char*,int); +#endif SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(FuncDef*,int); SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8); SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void); @@ -18928,6 +19085,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*); SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *); +SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3*); SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *); SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int); SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64); @@ -18974,6 +19132,9 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*); SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *); +#ifdef SQLITE_ENABLE_NORMALIZE +SQLITE_PRIVATE int sqlite3GetTokenNormalized(const unsigned char *, int *, int *); +#endif SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int); SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr *, int, int); @@ -19131,6 +19292,9 @@ SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); SQLITE_PRIVATE void sqlite3ParserReset(Parse*); +#ifdef SQLITE_ENABLE_NORMALIZE +SQLITE_PRIVATE void sqlite3Normalize(Vdbe*, const char*, int, u8); +#endif SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*); SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); @@ -19592,6 +19756,7 @@ 0, /* xTestCallback */ #endif 0, /* bLocaltimeFault */ + 0, /* bInternalFunctions */ 0x7ffffffe, /* iOnceResetThreshold */ SQLITE_DEFAULT_SORTERREF_SIZE /* szSorterRef */ }; @@ -20083,6 +20248,9 @@ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */ char *zSql; /* Text of the SQL statement that generated this */ +#ifdef SQLITE_ENABLE_NORMALIZE + char *zNormSql; /* Normalization of the associated SQL statement */ +#endif void *pFree; /* Free this when deleting the vdbe */ VdbeFrame *pFrame; /* Parent frame */ VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ @@ -20145,7 +20313,9 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*); SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*); SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*); +#ifndef SQLITE_OMIT_EXPLAIN SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*); +#endif SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*); SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int); SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*); @@ -20184,7 +20354,9 @@ #ifndef SQLITE_OMIT_WINDOWFUNC SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*); #endif +#ifndef SQLITE_OMIT_EXPLAIN SQLITE_PRIVATE const char *sqlite3OpcodeName(int); +#endif SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int); @@ -28311,6 +28483,42 @@ } } +/* +** Generate a human-readable description of a SrcList object. +*/ +SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){ + int i; + for(i=0; i<pSrc->nSrc; i++){ + const struct SrcList_item *pItem = &pSrc->a[i]; + StrAccum x; + char zLine[100]; + sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); + sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor); + if( pItem->zDatabase ){ + sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName); + }else if( pItem->zName ){ + sqlite3_str_appendf(&x, " %s", pItem->zName); + } + if( pItem->pTab ){ + sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName); + } + if( pItem->zAlias ){ + sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias); + } + if( pItem->fg.jointype & JT_LEFT ){ + sqlite3_str_appendf(&x, " LEFT-JOIN"); + } + sqlite3StrAccumFinish(&x); + sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1); + if( pItem->pSelect ){ + sqlite3TreeViewSelect(pView, pItem->pSelect, 0); + } + if( pItem->fg.isTabFunc ){ + sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); + } + sqlite3TreeViewPop(pView); + } +} /* ** Generate a human-readable description of a Select object. @@ -28365,39 +28573,9 @@ } #endif if( p->pSrc && p->pSrc->nSrc ){ - int i; pView = sqlite3TreeViewPush(pView, (n--)>0); sqlite3TreeViewLine(pView, "FROM"); - for(i=0; i<p->pSrc->nSrc; i++){ - struct SrcList_item *pItem = &p->pSrc->a[i]; - StrAccum x; - char zLine[100]; - sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); - sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor); - if( pItem->zDatabase ){ - sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName); - }else if( pItem->zName ){ - sqlite3_str_appendf(&x, " %s", pItem->zName); - } - if( pItem->pTab ){ - sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName); - } - if( pItem->zAlias ){ - sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias); - } - if( pItem->fg.jointype & JT_LEFT ){ - sqlite3_str_appendf(&x, " LEFT-JOIN"); - } - sqlite3StrAccumFinish(&x); - sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1); - if( pItem->pSelect ){ - sqlite3TreeViewSelect(pView, pItem->pSelect, 0); - } - if( pItem->fg.isTabFunc ){ - sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); - } - sqlite3TreeViewPop(pView); - } + sqlite3TreeViewSrcList(pView, p->pSrc); sqlite3TreeViewPop(pView); } if( p->pWhere ){ @@ -28687,7 +28865,7 @@ }else{ pFarg = pExpr->x.pList; #ifndef SQLITE_OMIT_WINDOWFUNC - pWin = pExpr->pWin; + pWin = pExpr->y.pWin; #else pWin = 0; #endif @@ -31515,6 +31693,20 @@ } return h; } +#ifdef SQLITE_ENABLE_NORMALIZE +static unsigned int strHashN(const char *z, int n){ + unsigned int h = 0; + int i; + for(i=0; i<n; i++){ + /* Knuth multiplicative hashing. (Sorting & Searching, p. 510). + ** 0x9e3779b1 is 2654435761 which is the closest prime number to + ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */ + h += sqlite3UpperToLower[z[i]]; + h *= 0x9e3779b1; + } + return h; +} +#endif /* SQLITE_ENABLE_NORMALIZE */ /* Link pNew element into the hash table pH. If pEntry!=0 then also @@ -31626,6 +31818,40 @@ } return &nullElement; } +#ifdef SQLITE_ENABLE_NORMALIZE +static HashElem *findElementWithHashN( + const Hash *pH, /* The pH to be searched */ + const char *pKey, /* The key we are searching for */ + int nKey, /* Number of key bytes to use */ + unsigned int *pHash /* Write the hash value here */ +){ + HashElem *elem; /* Used to loop thru the element list */ + int count; /* Number of elements left to test */ + unsigned int h; /* The computed hash */ + static HashElem nullElement = { 0, 0, 0, 0 }; + + if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/ + struct _ht *pEntry; + h = strHashN(pKey, nKey) % pH->htsize; + pEntry = &pH->ht[h]; + elem = pEntry->chain; + count = pEntry->count; + }else{ + h = 0; + elem = pH->first; + count = pH->count; + } + if( pHash ) *pHash = h; + while( count-- ){ + assert( elem!=0 ); + if( sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){ + return elem; + } + elem = elem->next; + } + return &nullElement; +} +#endif /* SQLITE_ENABLE_NORMALIZE */ /* Remove a single entry from the hash table given a pointer to that ** element and a hash on the element's key. @@ -31670,6 +31896,14 @@ assert( pKey!=0 ); return findElementWithHash(pH, pKey, 0)->data; } +#ifdef SQLITE_ENABLE_NORMALIZE +SQLITE_PRIVATE void *sqlite3HashFindN(const Hash *pH, const char *pKey, int nKey){ + assert( pH!=0 ); + assert( pKey!=0 ); + assert( nKey>=0 ); + return findElementWithHashN(pH, pKey, nKey, 0)->data; +} +#endif /* SQLITE_ENABLE_NORMALIZE */ /* Insert an element into the hash table pH. The key is pKey ** and the data is "data". @@ -32052,12 +32286,10 @@ #define SQLITE_FSFLAGS_IS_MSDOS 0x1 /* -** If we are to be thread-safe, include the pthreads header and define -** the SQLITE_UNIX_THREADS macro. +** If we are to be thread-safe, include the pthreads header. */ #if SQLITE_THREADSAFE /* # include <pthread.h> */ -# define SQLITE_UNIX_THREADS 1 #endif /* @@ -33233,8 +33465,7 @@ /* ** An instance of the following structure is allocated for each open -** inode. Or, on LinuxThreads, there is one of these structures for -** each inode opened by each thread. +** inode. ** ** A single inode can have multiple file descriptors, so each unixFile ** structure contains a pointer to an instance of this object and this @@ -33280,13 +33511,16 @@ /* ** A lists of all unixInodeInfo objects. +** +** Must hold unixBigLock in order to read or write this variable. */ static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */ #ifdef SQLITE_DEBUG /* -** True if the inode mutex is held, or not. Used only within assert() -** to help verify correct mutex usage. +** True if the inode mutex (on the unixFile.pFileMutex field) is held, or not. +** This routine is used only within assert() to help verify correct mutex +** usage. */ int unixFileMutexHeld(unixFile *pFile){ assert( pFile->pInode ); @@ -33414,8 +33648,8 @@ /* ** Release a unixInodeInfo structure previously allocated by findInodeInfo(). ** -** The mutex entered using the unixEnterMutex() function must be held -** when this function is called. +** The global mutex must be held when this routine is called, but the mutex +** on the inode being deleted must NOT be held. */ static void releaseInodeInfo(unixFile *pFile){ unixInodeInfo *pInode = pFile->pInode; @@ -33450,8 +33684,7 @@ ** describes that file descriptor. Create a new one if necessary. The ** return value might be uninitialized if an error occurs. ** -** The mutex entered using the unixEnterMutex() function must be held -** when this function is called. +** The global mutex must held when calling this routine. ** ** Return an appropriate error code. */ @@ -33512,6 +33745,7 @@ #else fileId.ino = (u64)statbuf.st_ino; #endif + assert( unixMutexHeld() ); pInode = inodeList; while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){ pInode = pInode->pNext; @@ -33531,6 +33765,7 @@ } } pInode->nRef = 1; + assert( unixMutexHeld() ); pInode->pNext = inodeList; pInode->pPrev = 0; if( inodeList ) inodeList->pPrev = pInode; @@ -36334,18 +36569,18 @@ ** ** The following fields are read-only after the object is created: ** -** fid +** hShm ** zFilename ** -** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and +** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and ** unixMutexHeld() is true when reading or writing any other field ** in this structure. */ struct unixShmNode { unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */ - sqlite3_mutex *mutex; /* Mutex to access this object */ + sqlite3_mutex *pShmMutex; /* Mutex to access this object */ char *zFilename; /* Name of the mmapped file */ - int h; /* Open file descriptor */ + int hShm; /* Open file descriptor */ int szRegion; /* Size of shared-memory regions */ u16 nRegion; /* Size of array apRegion */ u8 isReadonly; /* True if read-only */ @@ -36367,16 +36602,16 @@ ** The following fields are initialized when this object is created and ** are read-only thereafter: ** -** unixShm.pFile +** unixShm.pShmNode ** unixShm.id ** -** All other fields are read/write. The unixShm.pFile->mutex must be held -** while accessing any read/write fields. +** All other fields are read/write. The unixShm.pShmNode->pShmMutex must +** be held while accessing any read/write fields. */ struct unixShm { unixShmNode *pShmNode; /* The underlying unixShmNode object */ unixShm *pNext; /* Next unixShm with the same unixShmNode */ - u8 hasMutex; /* True if holding the unixShmNode mutex */ + u8 hasMutex; /* True if holding the unixShmNode->pShmMutex */ u8 id; /* Id of this connection within its unixShmNode */ u16 sharedMask; /* Mask of shared locks held */ u16 exclMask; /* Mask of exclusive locks held */ @@ -36406,7 +36641,8 @@ /* Access to the unixShmNode object is serialized by the caller */ pShmNode = pFile->pInode->pShmNode; - assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->mutex) ); + assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) ); + assert( pShmNode->nRef>0 || unixMutexHeld() ); /* Shared locks never span more than one byte */ assert( n==1 || lockType!=F_RDLCK ); @@ -36414,13 +36650,13 @@ /* Locks are within range */ assert( n>=1 && n<=SQLITE_SHM_NLOCK ); - if( pShmNode->h>=0 ){ + if( pShmNode->hShm>=0 ){ /* Initialize the locking parameters */ f.l_type = lockType; f.l_whence = SEEK_SET; f.l_start = ofst; f.l_len = n; - rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile); + rc = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile); rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY; } @@ -36492,18 +36728,18 @@ int nShmPerMap = unixShmRegionPerMap(); int i; assert( p->pInode==pFd->pInode ); - sqlite3_mutex_free(p->mutex); + sqlite3_mutex_free(p->pShmMutex); for(i=0; i<p->nRegion; i+=nShmPerMap){ - if( p->h>=0 ){ + if( p->hShm>=0 ){ osMunmap(p->apRegion[i], p->szRegion); }else{ sqlite3_free(p->apRegion[i]); } } sqlite3_free(p->apRegion); - if( p->h>=0 ){ - robust_close(pFd, p->h, __LINE__); - p->h = -1; + if( p->hShm>=0 ){ + robust_close(pFd, p->hShm, __LINE__); + p->hShm = -1; } p->pInode->pShmNode = 0; sqlite3_free(p); @@ -36545,7 +36781,7 @@ lock.l_start = UNIX_SHM_DMS; lock.l_len = 1; lock.l_type = F_WRLCK; - if( osFcntl(pShmNode->h, F_GETLK, &lock)!=0 ) { + if( osFcntl(pShmNode->hShm, F_GETLK, &lock)!=0 ) { rc = SQLITE_IOERR_LOCK; }else if( lock.l_type==F_UNLCK ){ if( pShmNode->isReadonly ){ @@ -36553,7 +36789,12 @@ rc = SQLITE_READONLY_CANTINIT; }else{ rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1); - if( rc==SQLITE_OK && robust_ftruncate(pShmNode->h, 0) ){ + /* The first connection to attach must truncate the -shm file. We + ** truncate to 3 bytes (an arbitrary small number, less than the + ** -shm header size) rather than 0 as a system debugging aid, to + ** help detect if a -shm file truncation is legitimate or is the work + ** or a rogue process. */ + if( rc==SQLITE_OK && robust_ftruncate(pShmNode->hShm, 3) ){ rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename); } } @@ -36659,12 +36900,12 @@ sqlite3_snprintf(nShmFilename, zShm, "%s-shm", zBasePath); sqlite3FileSuffix3(pDbFd->zPath, zShm); #endif - pShmNode->h = -1; + pShmNode->hShm = -1; pDbFd->pInode->pShmNode = pShmNode; pShmNode->pInode = pDbFd->pInode; if( sqlite3GlobalConfig.bCoreMutex ){ - pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - if( pShmNode->mutex==0 ){ + pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + if( pShmNode->pShmMutex==0 ){ rc = SQLITE_NOMEM_BKPT; goto shm_open_err; } @@ -36672,11 +36913,11 @@ if( pInode->bProcessLock==0 ){ if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ - pShmNode->h = robust_open(zShm, O_RDWR|O_CREAT, (sStat.st_mode&0777)); + pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT,(sStat.st_mode&0777)); } - if( pShmNode->h<0 ){ - pShmNode->h = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777)); - if( pShmNode->h<0 ){ + if( pShmNode->hShm<0 ){ + pShmNode->hShm = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777)); + if( pShmNode->hShm<0 ){ rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm); goto shm_open_err; } @@ -36687,7 +36928,7 @@ ** is owned by the same user that owns the original database. Otherwise, ** the original owner will not be able to connect. */ - robustFchown(pShmNode->h, sStat.st_uid, sStat.st_gid); + robustFchown(pShmNode->hShm, sStat.st_uid, sStat.st_gid); rc = unixLockSharedMemory(pDbFd, pShmNode); if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err; @@ -36707,13 +36948,13 @@ ** the cover of the unixEnterMutex() mutex and the pointer from the ** new (struct unixShm) object to the pShmNode has been set. All that is ** left to do is to link the new object into the linked list starting - ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex - ** mutex. + ** at pShmNode->pFirst. This must be done while holding the + ** pShmNode->pShmMutex. */ - sqlite3_mutex_enter(pShmNode->mutex); + sqlite3_mutex_enter(pShmNode->pShmMutex); p->pNext = pShmNode->pFirst; pShmNode->pFirst = p; - sqlite3_mutex_leave(pShmNode->mutex); + sqlite3_mutex_leave(pShmNode->pShmMutex); return rc; /* Jump here on any error */ @@ -36765,7 +37006,7 @@ p = pDbFd->pShm; pShmNode = p->pShmNode; - sqlite3_mutex_enter(pShmNode->mutex); + sqlite3_mutex_enter(pShmNode->pShmMutex); if( pShmNode->isUnlocked ){ rc = unixLockSharedMemory(pDbFd, pShmNode); if( rc!=SQLITE_OK ) goto shmpage_out; @@ -36773,8 +37014,8 @@ } assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); assert( pShmNode->pInode==pDbFd->pInode ); - assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 ); - assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 ); + assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 ); + assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 ); /* Minimum number of regions required to be mapped. */ nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap; @@ -36786,12 +37027,12 @@ pShmNode->szRegion = szRegion; - if( pShmNode->h>=0 ){ + if( pShmNode->hShm>=0 ){ /* The requested region is not mapped into this processes address space. ** Check to see if it has been allocated (i.e. if the wal-index file is ** large enough to contain the requested region). */ - if( osFstat(pShmNode->h, &sStat) ){ + if( osFstat(pShmNode->hShm, &sStat) ){ rc = SQLITE_IOERR_SHMSIZE; goto shmpage_out; } @@ -36819,7 +37060,7 @@ assert( (nByte % pgsz)==0 ); for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){ int x = 0; - if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, &x)!=1 ){ + if( seekAndWriteFd(pShmNode->hShm, iPg*pgsz + pgsz-1,"",1,&x)!=1 ){ const char *zFile = pShmNode->zFilename; rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile); goto shmpage_out; @@ -36842,22 +37083,22 @@ int nMap = szRegion*nShmPerMap; int i; void *pMem; - if( pShmNode->h>=0 ){ + if( pShmNode->hShm>=0 ){ pMem = osMmap(0, nMap, pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, - MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion + MAP_SHARED, pShmNode->hShm, szRegion*(i64)pShmNode->nRegion ); if( pMem==MAP_FAILED ){ rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename); goto shmpage_out; } }else{ - pMem = sqlite3_malloc64(szRegion); + pMem = sqlite3_malloc64(nMap); if( pMem==0 ){ rc = SQLITE_NOMEM_BKPT; goto shmpage_out; } - memset(pMem, 0, szRegion); + memset(pMem, 0, nMap); } for(i=0; i<nShmPerMap; i++){ @@ -36874,7 +37115,7 @@ *pp = 0; } if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY; - sqlite3_mutex_leave(pShmNode->mutex); + sqlite3_mutex_leave(pShmNode->pShmMutex); return rc; } @@ -36908,12 +37149,12 @@ || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); - assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 ); - assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 ); + assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 ); + assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 ); mask = (1<<(ofst+n)) - (1<<ofst); assert( n>1 || mask==(1<<ofst) ); - sqlite3_mutex_enter(pShmNode->mutex); + sqlite3_mutex_enter(pShmNode->pShmMutex); if( flags & SQLITE_SHM_UNLOCK ){ u16 allMask = 0; /* Mask of locks held by siblings */ @@ -36986,7 +37227,7 @@ } } } - sqlite3_mutex_leave(pShmNode->mutex); + sqlite3_mutex_leave(pShmNode->pShmMutex); OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n", p->id, osGetpid(0), p->sharedMask, p->exclMask)); return rc; @@ -37036,14 +37277,14 @@ /* Remove connection p from the set of connections associated ** with pShmNode */ - sqlite3_mutex_enter(pShmNode->mutex); + sqlite3_mutex_enter(pShmNode->pShmMutex); for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){} *pp = p->pNext; /* Free the connection p */ sqlite3_free(p); pDbFd->pShm = 0; - sqlite3_mutex_leave(pShmNode->mutex); + sqlite3_mutex_leave(pShmNode->pShmMutex); /* If pShmNode->nRef has reached 0, then close the underlying ** shared-memory file, too */ @@ -37052,7 +37293,7 @@ assert( pShmNode->nRef>0 ); pShmNode->nRef--; if( pShmNode->nRef==0 ){ - if( deleteFlag && pShmNode->h>=0 ){ + if( deleteFlag && pShmNode->hShm>=0 ){ osUnlink(pShmNode->zFilename); } unixShmPurge(pDbFd); @@ -40519,8 +40760,7 @@ int nFetchOut; /* Number of outstanding xFetch references */ HANDLE hMap; /* Handle for accessing memory mapping */ void *pMapRegion; /* Area memory mapped */ - sqlite3_int64 mmapSize; /* Usable size of mapped region */ - sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */ + sqlite3_int64 mmapSize; /* Size of mapped region */ sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ #endif }; @@ -43141,7 +43381,26 @@ DWORD lastErrno; #if SQLITE_MAX_MMAP_SIZE>0 sqlite3_int64 oldMmapSize; - if( pFile->nFetchOut>0 ) return SQLITE_OK; + if( pFile->nFetchOut>0 ){ + /* File truncation is a no-op if there are outstanding memory mapped + ** pages. This is because truncating the file means temporarily unmapping + ** the file, and that might delete memory out from under existing cursors. + ** + ** This can result in incremental vacuum not truncating the file, + ** if there is an active read cursor when the incremental vacuum occurs. + ** No real harm comes of this - the database file is not corrupted, + ** though some folks might complain that the file is bigger than it + ** needs to be. + ** + ** The only feasible work-around is to defer the truncation until after + ** all references to memory-mapped content are closed. That is doable, + ** but involves adding a few branches in the common write code path which + ** could slow down normal operations slightly. Hence, we have decided for + ** now to simply make trancations a no-op if there are pending reads. We + ** can maybe revisit this decision in the future. + */ + return SQLITE_OK; + } #endif assert( pFile ); @@ -44570,9 +44829,9 @@ static int winUnmapfile(winFile *pFile){ assert( pFile!=0 ); OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, " - "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n", + "mmapSize=%lld, mmapSizeMax=%lld\n", osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion, - pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax)); + pFile->mmapSize, pFile->mmapSizeMax)); if( pFile->pMapRegion ){ if( !osUnmapViewOfFile(pFile->pMapRegion) ){ pFile->lastErrno = osGetLastError(); @@ -44584,7 +44843,6 @@ } pFile->pMapRegion = 0; pFile->mmapSize = 0; - pFile->mmapSizeActual = 0; } if( pFile->hMap!=NULL ){ if( !osCloseHandle(pFile->hMap) ){ @@ -44695,7 +44953,6 @@ } pFd->pMapRegion = pNew; pFd->mmapSize = nMap; - pFd->mmapSizeActual = nMap; } OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n", @@ -45497,7 +45754,6 @@ pFile->hMap = NULL; pFile->pMapRegion = 0; pFile->mmapSize = 0; - pFile->mmapSizeActual = 0; pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap; #endif @@ -47402,7 +47658,7 @@ ** The PCache.pSynced variable is used to optimize searching for a dirty ** page to eject from the cache mid-transaction. It is better to eject ** a page that does not require a journal sync than one that does. -** Therefore, pSynced is maintained to that it *almost* always points +** Therefore, pSynced is maintained so that it *almost* always points ** to either the oldest page in the pDirty/pDirtyTail list that has a ** clear PGHDR_NEED_SYNC flag or to a page that is older than this one ** (so that the right page to eject can be found by following pDirtyPrev @@ -48226,6 +48482,15 @@ return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0; } +#ifdef SQLITE_DIRECT_OVERFLOW_READ +/* +** Return true if there are one or more dirty pages in the cache. Else false. +*/ +SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache){ + return (pCache->pDirty!=0); +} +#endif + #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) /* ** For all dirty pages currently in the cache, invoke the specified @@ -48349,7 +48614,8 @@ }; /* -** A page is pinned if it is no on the LRU list +** A page is pinned if it is not on the LRU list. To be "pinned" means +** that the page is in active use and must not be deallocated. */ #define PAGE_IS_PINNED(p) ((p)->pLruNext==0) #define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0) @@ -50989,19 +51255,30 @@ */ #define isOpen(pFd) ((pFd)->pMethods!=0) +#ifdef SQLITE_DIRECT_OVERFLOW_READ /* -** Return true if this pager uses a write-ahead log to read page pgno. -** Return false if the pager reads pgno directly from the database. +** Return true if page pgno can be read directly from the database file +** by the b-tree layer. This is the case if: +** +** * the database file is open, +** * there are no dirty pages in the cache, and +** * the desired page is not currently in the wal file. */ -#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_DIRECT_OVERFLOW_READ) -SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno pgno){ - u32 iRead = 0; - int rc; - if( pPager->pWal==0 ) return 0; - rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); - return rc || iRead; +SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){ + if( pPager->fd->pMethods==0 ) return 0; + if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; +#ifndef SQLITE_OMIT_WAL + if( pPager->pWal ){ + u32 iRead = 0; + int rc; + rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); + return (rc==SQLITE_OK && iRead==0); + } +#endif + return 1; } #endif + #ifndef SQLITE_OMIT_WAL # define pagerUseWal(x) ((x)->pWal!=0) #else @@ -57185,7 +57462,11 @@ void (*xCodecFree)(void*), void *pCodec ){ - if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); + if( pPager->xCodecFree ){ + pPager->xCodecFree(pPager->pCodec); + }else{ + pager_reset(pPager); + } pPager->xCodec = pPager->memDb ? 0 : xCodec; pPager->xCodecSizeChng = xCodecSizeChng; pPager->xCodecFree = xCodecFree; @@ -65845,7 +66126,7 @@ pageSize-usableSize); return rc; } - if( (pBt->db->flags & SQLITE_WriteSchema)==0 && nPage>nPageFile ){ + if( sqlite3WritableSchema(pBt->db)==0 && nPage>nPageFile ){ rc = SQLITE_CORRUPT_BKPT; goto page1_init_failed; } @@ -66319,6 +66600,7 @@ eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); assert( sqlite3_mutex_held(pBt->mutex) ); assert( pDbPage->pBt==pBt ); + if( iDbPage<3 ) return SQLITE_CORRUPT_BKPT; /* Move page iDbPage from its current location to page number iFreePage */ TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", @@ -67490,9 +67772,6 @@ /* Need to read this page properly. It contains some of the ** range of data that is being read (eOp==0) or written (eOp!=0). */ -#ifdef SQLITE_DIRECT_OVERFLOW_READ - sqlite3_file *fd; /* File from which to do direct overflow read */ -#endif int a = amt; if( a + offset > ovflSize ){ a = ovflSize - offset; @@ -67503,7 +67782,7 @@ ** ** 1) this is a read operation, and ** 2) data is required from the start of this overflow page, and - ** 3) there is no open write-transaction, and + ** 3) there are no dirty pages in the page-cache ** 4) the database is file-backed, and ** 5) the page is not in the WAL file ** 6) at least 4 bytes have already been read into the output buffer @@ -67514,11 +67793,10 @@ */ if( eOp==0 /* (1) */ && offset==0 /* (2) */ - && pBt->inTransaction==TRANS_READ /* (3) */ - && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (4) */ - && 0==sqlite3PagerUseWal(pBt->pPager, nextPage) /* (5) */ + && sqlite3PagerDirectReadOk(pBt->pPager, nextPage) /* (3,4,5) */ && &pBuf[-4]>=pBufStart /* (6) */ ){ + sqlite3_file *fd = sqlite3PagerFile(pBt->pPager); u8 aSave[4]; u8 *aWrite = &pBuf[-4]; assert( aWrite>=pBufStart ); /* due to (6) */ @@ -74114,7 +74392,8 @@ assert( fg & MEM_Real ); sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r); } - pMem->n = sqlite3Strlen30(pMem->z); + assert( pMem->z!=0 ); + pMem->n = sqlite3Strlen30NN(pMem->z); pMem->enc = SQLITE_UTF8; pMem->flags |= MEM_Str|MEM_Term; if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real); @@ -75689,6 +75968,13 @@ } assert( p->zSql==0 ); p->zSql = sqlite3DbStrNDup(p->db, z, n); +#ifdef SQLITE_ENABLE_NORMALIZE + assert( p->zNormSql==0 ); + if( p->zSql && (prepFlags & SQLITE_PREPARE_NORMALIZE)!=0 ){ + sqlite3Normalize(p, p->zSql, n, prepFlags); + assert( p->zNormSql!=0 || p->db->mallocFailed ); + } +#endif } /* @@ -75710,6 +75996,11 @@ zTmp = pA->zSql; pA->zSql = pB->zSql; pB->zSql = zTmp; +#ifdef SQLITE_ENABLE_NORMALIZE + zTmp = pA->zNormSql; + pA->zNormSql = pB->zNormSql; + pB->zNormSql = zTmp; +#endif pB->expmask = pA->expmask; pB->prepFlags = pA->prepFlags; memcpy(pB->aCounter, pA->aCounter, sizeof(pB->aCounter)); @@ -78781,6 +79072,9 @@ vdbeFreeOpArray(db, p->aOp, p->nOp); sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); +#ifdef SQLITE_ENABLE_NORMALIZE + sqlite3DbFree(db, p->zNormSql); +#endif #ifdef SQLITE_ENABLE_STMT_SCANSTATUS { int i; @@ -82195,6 +82489,16 @@ #endif } +#ifdef SQLITE_ENABLE_NORMALIZE +/* +** Return the normalized SQL associated with a prepared statement. +*/ +SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt){ + Vdbe *p = (Vdbe *)pStmt; + return p ? p->zNormSql : 0; +} +#endif /* SQLITE_ENABLE_NORMALIZE */ + #ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* ** Allocate and populate an UnpackedRecord structure based on the serialized @@ -85634,17 +85938,25 @@ if( nVarint<sqlite3VarintLen(nHdr) ) nHdr++; } nByte = nHdr+nData; - if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } /* Make sure the output register has a buffer large enough to store ** the new record. The output register (pOp->p3) is not allowed to ** be one of the input registers (because the following call to ** sqlite3VdbeMemClearAndResize() could clobber the value before it is used). */ - if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){ - goto no_mem; + if( nByte+nZero<=pOut->szMalloc ){ + /* The output register is already large enough to hold the record. + ** No error checks or buffer enlargement is required */ + pOut->z = pOut->zMalloc; + }else{ + /* Need to make sure that the output is not too big and then enlarge + ** the output register to hold the full result */ + if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){ + goto no_mem; + } } zNewRecord = (u8 *)pOut->z; @@ -88500,7 +88812,7 @@ { zMaster = MASTER_NAME; initData.db = db; - initData.iDb = pOp->p1; + initData.iDb = iDb; initData.pzErrMsg = &p->zErrMsg; initData.mInitFlags = 0; zSql = sqlite3MPrintf(db, @@ -94083,8 +94395,8 @@ if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; } #ifndef SQLITE_OMIT_WINDOWFUNC - if( !ExprHasProperty(pExpr, EP_Reduced) && pExpr->pWin ){ - Window *pWin = pExpr->pWin; + if( ExprHasProperty(pExpr, EP_WinFunc) ){ + Window *pWin = pExpr->y.pWin; if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort; if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort; if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort; @@ -94357,7 +94669,7 @@ ** (even if X is implied). ** pExpr->iTable Set to the cursor number for the table obtained ** from pSrcList. -** pExpr->pTab Points to the Table structure of X.Y (even if +** pExpr->y.pTab Points to the Table structure of X.Y (even if ** X and/or Y are implied.) ** pExpr->iColumn Set to the column number within the table. ** pExpr->op Set to TK_COLUMN. @@ -94401,7 +94713,6 @@ /* Initialize the node to no-match */ pExpr->iTable = -1; - pExpr->pTab = 0; ExprSetVVAProperty(pExpr, EP_NoReduce); /* Translate the schema name in zDb into a pointer to the corresponding @@ -94463,7 +94774,7 @@ continue; } if( IN_RENAME_OBJECT && pItem->zAlias ){ - sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->pTab); + sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab); } } if( 0==(cntTab++) ){ @@ -94489,13 +94800,13 @@ } if( pMatch ){ pExpr->iTable = pMatch->iCursor; - pExpr->pTab = pMatch->pTab; + pExpr->y.pTab = pMatch->pTab; /* RIGHT JOIN not (yet) supported */ assert( (pMatch->fg.jointype & JT_RIGHT)==0 ); if( (pMatch->fg.jointype & JT_LEFT)!=0 ){ ExprSetProperty(pExpr, EP_CanBeNull); } - pSchema = pExpr->pTab->pSchema; + pSchema = pExpr->y.pTab->pSchema; } } /* if( pSrcList ) */ @@ -94552,7 +94863,7 @@ testcase( iCol==(-1) ); if( IN_RENAME_OBJECT ){ pExpr->iColumn = iCol; - pExpr->pTab = pTab; + pExpr->y.pTab = pTab; eNewExprOp = TK_COLUMN; }else{ pExpr->iTable = pNC->uNC.pUpsert->regData + iCol; @@ -94574,7 +94885,7 @@ testcase( iCol==32 ); pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol)); } - pExpr->pTab = pTab; + pExpr->y.pTab = pTab; pExpr->iColumn = (i16)iCol; eNewExprOp = TK_TRIGGER; #endif /* SQLITE_OMIT_TRIGGER */ @@ -94674,7 +94985,7 @@ assert( pExpr->op==TK_ID ); if( ExprHasProperty(pExpr,EP_DblQuoted) ){ pExpr->op = TK_STRING; - pExpr->pTab = 0; + pExpr->y.pTab = 0; return WRC_Prune; } if( sqlite3ExprIdToTrueFalse(pExpr) ){ @@ -94752,9 +95063,9 @@ Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0); if( p ){ struct SrcList_item *pItem = &pSrc->a[iSrc]; - p->pTab = pItem->pTab; + p->y.pTab = pItem->pTab; p->iTable = pItem->iCursor; - if( p->pTab->iPKey==iCol ){ + if( p->y.pTab->iPKey==iCol ){ p->iColumn = -1; }else{ p->iColumn = (ynVar)iCol; @@ -94844,7 +95155,7 @@ pItem = pSrcList->a; assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 ); pExpr->op = TK_COLUMN; - pExpr->pTab = pItem->pTab; + pExpr->y.pTab = pItem->pTab; pExpr->iTable = pItem->iCursor; pExpr->iColumn = -1; pExpr->affinity = SQLITE_AFF_INTEGER; @@ -94888,9 +95199,7 @@ zColumn = pRight->u.zToken; if( IN_RENAME_OBJECT ){ sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight); - } - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, (void*)&pExpr->pTab, (void*)pLeft); + sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft); } } return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); @@ -94972,6 +95281,15 @@ notValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr|NC_PartIdx); } + if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0 + && pParse->nested==0 + && sqlite3Config.bInternalFunctions==0 + ){ + /* Internal-use-only functions are disallowed unless the + ** SQL is being compiled using sqlite3NestedParse() */ + no_such_func = 1; + pDef = 0; + } } if( 0==IN_RENAME_OBJECT ){ @@ -94980,18 +95298,18 @@ || (pDef->xValue==0 && pDef->xInverse==0) || (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize) ); - if( pDef && pDef->xValue==0 && pExpr->pWin ){ + if( pDef && pDef->xValue==0 && ExprHasProperty(pExpr, EP_WinFunc) ){ sqlite3ErrorMsg(pParse, "%.*s() may not be used as a window function", nId, zId ); pNC->nErr++; }else if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) - || (is_agg && (pDef->funcFlags & SQLITE_FUNC_WINDOW) && !pExpr->pWin) - || (is_agg && pExpr->pWin && (pNC->ncFlags & NC_AllowWin)==0) + || (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pExpr->y.pWin) + || (is_agg && pExpr->y.pWin && (pNC->ncFlags & NC_AllowWin)==0) ){ const char *zType; - if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->pWin ){ + if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->y.pWin ){ zType = "window"; }else{ zType = "aggregate"; @@ -95021,7 +95339,7 @@ } if( is_agg ){ #ifndef SQLITE_OMIT_WINDOWFUNC - pNC->ncFlags &= ~(pExpr->pWin ? NC_AllowWin : NC_AllowAgg); + pNC->ncFlags &= ~(pExpr->y.pWin ? NC_AllowWin : NC_AllowAgg); #else pNC->ncFlags &= ~NC_AllowAgg; #endif @@ -95030,17 +95348,17 @@ sqlite3WalkExprList(pWalker, pList); if( is_agg ){ #ifndef SQLITE_OMIT_WINDOWFUNC - if( pExpr->pWin ){ + if( pExpr->y.pWin ){ Select *pSel = pNC->pWinSelect; - sqlite3WalkExprList(pWalker, pExpr->pWin->pPartition); - sqlite3WalkExprList(pWalker, pExpr->pWin->pOrderBy); - sqlite3WalkExpr(pWalker, pExpr->pWin->pFilter); - sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->pWin, pDef); + sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition); + sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy); + sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter); + sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef); if( 0==pSel->pWin - || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->pWin) + || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin) ){ - pExpr->pWin->pNextWin = pSel->pWin; - pSel->pWin = pExpr->pWin; + pExpr->y.pWin->pNextWin = pSel->pWin; + pSel->pWin = pExpr->y.pWin; } pNC->ncFlags |= NC_AllowWin; }else @@ -95463,13 +95781,13 @@ for(j=0; j<pSelect->pEList->nExpr; j++){ if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ #ifndef SQLITE_OMIT_WINDOWFUNC - if( pE->pWin ){ + if( ExprHasProperty(pE, EP_WinFunc) ){ /* Since this window function is being changed into a reference ** to the same window function the result set, remove the instance ** of this window function from the Select.pWin list. */ Window **pp; for(pp=&pSelect->pWin; *pp; pp=&(*pp)->pNextWin){ - if( *pp==pE->pWin ){ + if( *pp==pE->y.pWin ){ *pp = (*pp)->pNextWin; } } @@ -95932,8 +96250,8 @@ return sqlite3AffinityType(pExpr->u.zToken, 0); } #endif - if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){ - return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn); + if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->y.pTab ){ + return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); } if( op==TK_SELECT_COLUMN ){ assert( pExpr->pLeft->flags&EP_xIsSelect ); @@ -96017,13 +96335,13 @@ if( p->flags & EP_Generic ) break; if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER) - && p->pTab!=0 + && p->y.pTab!=0 ){ - /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally + /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally ** a TK_COLUMN but was previously evaluated and cached in a register */ int j = p->iColumn; if( j>=0 ){ - const char *zColl = p->pTab->aCol[j].zColl; + const char *zColl = p->y.pTab->aCol[j].zColl; pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); } break; @@ -96926,6 +97244,10 @@ assert( p!=0 ); /* Sanity check: Assert that the IntValue is non-negative if it exists */ assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 ); + + assert( !ExprHasProperty(p, EP_WinFunc) || p->y.pWin!=0 || db->mallocFailed ); + assert( p->op!=TK_FUNCTION || ExprHasProperty(p, EP_TokenOnly|EP_Reduced) + || p->y.pWin==0 || ExprHasProperty(p, EP_WinFunc) ); #ifdef SQLITE_DEBUG if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){ assert( p->pLeft==0 ); @@ -96944,8 +97266,9 @@ }else{ sqlite3ExprListDelete(db, p->x.pList); } - if( !ExprHasProperty(p, EP_Reduced) ){ - sqlite3WindowDelete(db, p->pWin); + if( ExprHasProperty(p, EP_WinFunc) ){ + assert( p->op==TK_FUNCTION ); + sqlite3WindowDelete(db, p->y.pWin); } } if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); @@ -97009,7 +97332,7 @@ assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 ); if( 0==flags || p->op==TK_SELECT_COLUMN #ifndef SQLITE_OMIT_WINDOWFUNC - || p->pWin + || ExprHasProperty(p, EP_WinFunc) #endif ){ nSize = EXPR_FULLSIZE; @@ -97036,7 +97359,7 @@ static int dupedExprNodeSize(Expr *p, int flags){ int nByte = dupedExprStructSize(p, flags) & 0xfff; if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ - nByte += sqlite3Strlen30(p->u.zToken)+1; + nByte += sqlite3Strlen30NN(p->u.zToken)+1; } return ROUND8(nByte); } @@ -97139,22 +97462,24 @@ } /* Fill in pNew->pLeft and pNew->pRight. */ - zAlloc += dupedExprNodeSize(p, dupFlags); - if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ + if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly|EP_WinFunc) ){ + zAlloc += dupedExprNodeSize(p, dupFlags); if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){ pNew->pLeft = p->pLeft ? exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0; pNew->pRight = p->pRight ? exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0; } - }else{ #ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(p, EP_Reduced|EP_TokenOnly) ){ - pNew->pWin = 0; - }else{ - pNew->pWin = sqlite3WindowDup(db, pNew, p->pWin); + if( ExprHasProperty(p, EP_WinFunc) ){ + pNew->y.pWin = sqlite3WindowDup(db, pNew, p->y.pWin); + assert( ExprHasProperty(pNew, EP_WinFunc) ); } #endif /* SQLITE_OMIT_WINDOWFUNC */ + if( pzBuffer ){ + *pzBuffer = zAlloc; + } + }else{ if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ if( pNew->op==TK_SELECT_COLUMN ){ pNew->pLeft = p->pLeft; @@ -97166,9 +97491,6 @@ pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); } } - if( pzBuffer ){ - *pzBuffer = zAlloc; - } } return pNew; } @@ -97963,8 +98285,8 @@ return 0; case TK_COLUMN: return ExprHasProperty(p, EP_CanBeNull) || - p->pTab==0 || /* Reference to column of index on expression */ - (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0); + p->y.pTab==0 || /* Reference to column of index on expression */ + (p->iColumn>=0 && p->y.pTab->aCol[p->iColumn].notNull==0); default: return 1; } @@ -98019,6 +98341,14 @@ if( sqlite3StrICmp(z, "OID")==0 ) return 1; return 0; } +#ifdef SQLITE_ENABLE_NORMALIZE +SQLITE_PRIVATE int sqlite3IsRowidN(const char *z, int n){ + if( sqlite3StrNICmp(z, "_ROWID_", n)==0 ) return 1; + if( sqlite3StrNICmp(z, "ROWID", n)==0 ) return 1; + if( sqlite3StrNICmp(z, "OID", n)==0 ) return 1; + return 0; +} +#endif /* ** pX is the RHS of an IN operator. If pX is a SELECT statement @@ -99252,7 +99582,7 @@ ** constant. */ int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target); - int aff = sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn); + int aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); if( aff!=SQLITE_AFF_BLOB ){ static const char zAff[] = "B\000C\000D\000E"; assert( SQLITE_AFF_BLOB=='A' ); @@ -99276,7 +99606,7 @@ iTab = pParse->iSelfTab - 1; } } - return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, + return sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab, pExpr->iColumn, iTab, target, pExpr->op2); } @@ -99490,8 +99820,8 @@ CollSeq *pColl = 0; /* A collating sequence */ #ifndef SQLITE_OMIT_WINDOWFUNC - if( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) && pExpr->pWin ){ - return pExpr->pWin->regResult; + if( ExprHasProperty(pExpr, EP_WinFunc) ){ + return pExpr->y.pWin->regResult; } #endif @@ -99734,7 +100064,7 @@ ** p1==1 -> old.a p1==4 -> new.a ** p1==2 -> old.b p1==5 -> new.b */ - Table *pTab = pExpr->pTab; + Table *pTab = pExpr->y.pTab; int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn; assert( pExpr->iTable==0 || pExpr->iTable==1 ); @@ -99745,7 +100075,7 @@ sqlite3VdbeAddOp2(v, OP_Param, p1, target); VdbeComment((v, "r[%d]=%s.%s", target, (pExpr->iTable ? "new" : "old"), - (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName) + (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[pExpr->iColumn].zName) )); #ifndef SQLITE_OMIT_FLOATING_POINT @@ -100596,6 +100926,20 @@ if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){ if( pA->op==TK_FUNCTION ){ if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; +#ifndef SQLITE_OMIT_WINDOWFUNC + /* Justification for the assert(): + ** window functions have p->op==TK_FUNCTION but aggregate functions + ** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate + ** function and a window function should have failed before reaching + ** this point. And, it is not possible to have a window function and + ** a scalar function with the same name and number of arguments. So + ** if we reach this point, either A and B both window functions or + ** neither are a window functions. */ + assert( ExprHasProperty(pA,EP_WinFunc)==ExprHasProperty(pB,EP_WinFunc) ); + if( ExprHasProperty(pA,EP_WinFunc) ){ + if( sqlite3WindowCompare(pParse,pA->y.pWin,pB->y.pWin)!=0 ) return 2; + } +#endif }else if( pA->op==TK_COLLATE ){ if( sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; }else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ @@ -100615,21 +100959,6 @@ if( pA->iTable!=pB->iTable && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2; } -#ifndef SQLITE_OMIT_WINDOWFUNC - /* Justification for the assert(): - ** window functions have p->op==TK_FUNCTION but aggregate functions - ** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate - ** function and a window function should have failed before reaching - ** this point. And, it is not possible to have a window function and - ** a scalar function with the same name and number of arguments. So - ** if we reach this point, either A and B both window functions or - ** neither are a window functions. */ - assert( (pA->pWin==0)==(pB->pWin==0) ); - - if( pA->pWin!=0 ){ - if( sqlite3WindowCompare(pParse,pA->pWin,pB->pWin)!=0 ) return 2; - } -#endif } return 0; } @@ -100770,8 +101099,8 @@ testcase( pExpr->op==TK_LE ); testcase( pExpr->op==TK_GT ); testcase( pExpr->op==TK_GE ); - if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab)) - || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab)) + if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->y.pTab)) + || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->y.pTab)) ){ return WRC_Prune; } @@ -101002,7 +101331,7 @@ && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0 ){ pCol = &pAggInfo->aCol[k]; - pCol->pTab = pExpr->pTab; + pCol->pTab = pExpr->y.pTab; pCol->iTable = pExpr->iTable; pCol->iColumn = pExpr->iColumn; pCol->iMem = ++pParse->nMem; @@ -101885,10 +102214,16 @@ #endif /* -** Add a new RenameToken object mapping parse tree element pPtr into -** token *pToken to the Parse object currently under construction. +** Remember that the parser tree element pPtr was created using +** the token pToken. ** -** Return a copy of pPtr. +** In other words, construct a new RenameToken object and add it +** to the list of RenameToken objects currently being built up +** in pParse->pRename. +** +** The pPtr argument is returned so that this routine can be used +** with tail recursion in tokenExpr() routine, for a small performance +** improvement. */ SQLITE_PRIVATE void *sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pToken){ RenameToken *pNew; @@ -102021,7 +102356,7 @@ renameTokenFind(pWalker->pParse, p, (void*)pExpr); }else if( pExpr->op==TK_COLUMN && pExpr->iColumn==p->iCol - && p->pTab==pExpr->pTab + && p->pTab==pExpr->y.pTab ){ renameTokenFind(pWalker->pParse, p, (void*)pExpr); } @@ -102279,9 +102614,14 @@ db->aDb[sqlite3SchemaToIndex(db, pNew->pTabSchema)].zDbSName ); pParse->eTriggerOp = pNew->op; + /* ALWAYS() because if the table of the trigger does not exist, the + ** error would have been hit before this point */ + if( ALWAYS(pParse->pTriggerTab) ){ + rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab); + } /* Resolve symbols in WHEN clause */ - if( pNew->pWhen ){ + if( rc==SQLITE_OK && pNew->pWhen ){ rc = sqlite3ResolveExprNames(&sNC, pNew->pWhen); } @@ -102395,15 +102735,8 @@ ** into zNew. The name should be quoted if bQuote is true. ** ** This function is used internally by the ALTER TABLE RENAME COLUMN command. -** Though accessible to application code, it is not intended for use by -** applications. The existance of this function, and the way it works, -** is subject to change without notice. -** -** If any of the parameters are out-of-bounds, then simply return NULL. -** An out-of-bounds parameter can only occur when the application calls -** this function directly. The parameters will always be well-formed when -** this routine is invoked by the bytecode for a legitimate ALTER TABLE -** statement. +** It is only accessible to SQL created using sqlite3NestedParse(). It is +** not reachable from ordinary SQL passed into sqlite3_prepare(). */ static void renameColumnFunc( sqlite3_context *context, @@ -102559,8 +102892,8 @@ */ static int renameTableExprCb(Walker *pWalker, Expr *pExpr){ RenameCtx *p = pWalker->u.pRename; - if( pExpr->op==TK_COLUMN && p->pTab==pExpr->pTab ){ - renameTokenFind(pWalker->pParse, p, (void*)&pExpr->pTab); + if( pExpr->op==TK_COLUMN && p->pTab==pExpr->y.pTab ){ + renameTokenFind(pWalker->pParse, p, (void*)&pExpr->y.pTab); } return WRC_Continue; } @@ -102657,7 +102990,7 @@ }else{ /* Modify any FK definitions to point to the new table. */ #ifndef SQLITE_OMIT_FOREIGN_KEY - if( db->flags & SQLITE_ForeignKeys ){ + if( isLegacy==0 || (db->flags & SQLITE_ForeignKeys) ){ FKey *pFKey; for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){ @@ -102811,9 +103144,9 @@ */ SQLITE_PRIVATE void sqlite3AlterFunctions(void){ static FuncDef aAlterTableFuncs[] = { - FUNCTION(sqlite_rename_column, 9, 0, 0, renameColumnFunc), - FUNCTION(sqlite_rename_table, 7, 0, 0, renameTableFunc), - FUNCTION(sqlite_rename_test, 5, 0, 0, renameTableTest), + INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc), + INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc), + INTERNAL_FUNCTION(sqlite_rename_test, 5, renameTableTest), }; sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); } @@ -104862,7 +105195,7 @@ if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt); pNew->pBt = 0; pNew->pSchema = 0; - rc = sqlite3BtreeOpen(pVfs, "x", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB); + rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB); }else{ /* This is a real ATTACH ** @@ -105542,6 +105875,7 @@ int iCol; /* Index of column in table */ assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ); + assert( !IN_RENAME_OBJECT || db->xAuth==0 ); if( db->xAuth==0 ) return; iDb = sqlite3SchemaToIndex(pParse->db, pSchema); if( iDb<0 ){ @@ -105598,6 +105932,7 @@ /* Don't do any authorization checks if the database is initialising ** or if the parser is being invoked from within sqlite3_declare_vtab. */ + assert( !IN_RENAME_OBJECT || db->xAuth==0 ); if( db->init.busy || IN_SPECIAL_PARSE ){ return SQLITE_OK; } @@ -106021,17 +106356,15 @@ if( p==0 ){ const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table"; #ifndef SQLITE_OMIT_VIRTUALTABLE - if( sqlite3FindDbName(db, zDbase)<1 ){ - /* If zName is the not the name of a table in the schema created using - ** CREATE, then check to see if it is the name of an virtual table that - ** can be an eponymous virtual table. */ - Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName); - if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ - pMod = sqlite3PragmaVtabRegister(db, zName); - } - if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ - return pMod->pEpoTab; - } + /* If zName is the not the name of a table in the schema created using + ** CREATE, then check to see if it is the name of an virtual table that + ** can be an eponymous virtual table. */ + Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName); + if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ + pMod = sqlite3PragmaVtabRegister(db, zName); + } + if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ + return pMod->pEpoTab; } #endif if( (flags & LOCATE_NOERR)==0 ){ @@ -106211,17 +106544,22 @@ SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){ int i; sqlite3BtreeEnterAll(db); - assert( db->nSchemaLock==0 ); for(i=0; i<db->nDb; i++){ Db *pDb = &db->aDb[i]; if( pDb->pSchema ){ - sqlite3SchemaClear(pDb->pSchema); + if( db->nSchemaLock==0 ){ + sqlite3SchemaClear(pDb->pSchema); + }else{ + DbSetProperty(db, i, DB_ResetWanted); + } } } db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk); sqlite3VtabUnlockList(db); sqlite3BtreeLeaveAll(db); - sqlite3CollapseDatabaseArray(db); + if( db->nSchemaLock==0 ){ + sqlite3CollapseDatabaseArray(db); + } } /* @@ -106298,6 +106636,12 @@ /* Delete the Table structure itself. */ +#ifdef SQLITE_ENABLE_NORMALIZE + if( pTable->pColHash ){ + sqlite3HashClear(pTable->pColHash); + sqlite3_free(pTable->pColHash); + } +#endif sqlite3DeleteColumnNames(db, pTable); sqlite3DbFree(db, pTable->zName); sqlite3DbFree(db, pTable->zColAff); @@ -106457,6 +106801,20 @@ } /* +** True if PRAGMA writable_schema is ON +*/ +SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3 *db){ + testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==0 ); + testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== + SQLITE_WriteSchema ); + testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== + SQLITE_Defensive ); + testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== + (SQLITE_WriteSchema|SQLITE_Defensive) ); + return (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==SQLITE_WriteSchema; +} + +/* ** This routine is used to check if the UTF-8 string zName is a legal ** unqualified name for a new schema object (table, index, view or ** trigger). All names are legal except those that begin with the string @@ -106465,7 +106823,7 @@ */ SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *pParse, const char *zName){ if( !pParse->db->init.busy && pParse->nested==0 - && (pParse->db->flags & SQLITE_WriteSchema)==0 + && sqlite3WritableSchema(pParse->db)==0 && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName); return SQLITE_ERROR; @@ -107541,6 +107899,36 @@ recomputeColumnsNotIndexed(pPk); } +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* +** Return true if zName is a shadow table name in the current database +** connection. +** +** zName is temporarily modified while this routine is running, but is +** restored to its original value prior to this routine returning. +*/ +static int isShadowTableName(sqlite3 *db, char *zName){ + char *zTail; /* Pointer to the last "_" in zName */ + Table *pTab; /* Table that zName is a shadow of */ + Module *pMod; /* Module for the virtual table */ + + zTail = strrchr(zName, '_'); + if( zTail==0 ) return 0; + *zTail = 0; + pTab = sqlite3FindTable(db, zName, 0); + *zTail = '_'; + if( pTab==0 ) return 0; + if( !IsVirtual(pTab) ) return 0; + pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]); + if( pMod==0 ) return 0; + if( pMod->pModule->iVersion<3 ) return 0; + if( pMod->pModule->xShadowName==0 ) return 0; + return pMod->pModule->xShadowName(zTail+1); +} +#else +# define isShadowTableName(x,y) 0 +#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ + /* ** This routine is called to report the final ")" that terminates ** a CREATE TABLE statement. @@ -107580,6 +107968,10 @@ p = pParse->pNewTable; if( p==0 ) return; + if( pSelect==0 && isShadowTableName(db, p->zName) ){ + p->tabFlags |= TF_Shadow; + } + /* If the db->init.busy is 1 it means we are reading the SQL off the ** "sqlite_master" or "sqlite_temp_master" table on the disk. ** So do not write to the disk again. Extract the root page number @@ -108087,7 +108479,7 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){ Vdbe *v = sqlite3GetVdbe(pParse); int r1 = sqlite3GetTempReg(pParse); - assert( iTable>1 ); + if( iTable<2 ) sqlite3ErrorMsg(pParse, "corrupt schema"); sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb); sqlite3MayAbort(pParse); #ifndef SQLITE_OMIT_AUTOVACUUM @@ -110542,6 +110934,21 @@ } return 0; } +#ifdef SQLITE_ENABLE_NORMALIZE +SQLITE_PRIVATE FuncDef *sqlite3FunctionSearchN( + int h, /* Hash of the name */ + const char *zFunc, /* Name of function */ + int nFunc /* Length of the name */ +){ + FuncDef *p; + for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){ + if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 ){ + return p; + } + } + return 0; +} +#endif /* SQLITE_ENABLE_NORMALIZE */ /* ** Insert a new FuncDef into a FuncDefHash hash table. @@ -110555,7 +110962,7 @@ FuncDef *pOther; const char *zName = aDef[i].zName; int nName = sqlite3Strlen30(zName); - int h = (zName[0] + nName) % SQLITE_FUNC_HASH_SZ; + int h = SQLITE_FUNC_HASH(zName[0], nName); assert( zName[0]>='a' && zName[0]<='z' ); pOther = functionSearch(h, zName); if( pOther ){ @@ -110634,7 +111041,7 @@ */ if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){ bestScore = 0; - h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ; + h = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zName[0]], nName); p = functionSearch(h, zName); while( p ){ int score = matchQuality(p, nArg, enc); @@ -110782,32 +111189,49 @@ return pTab; } +/* Return true if table pTab is read-only. +** +** A table is read-only if any of the following are true: +** +** 1) It is a virtual table and no implementation of the xUpdate method +** has been provided +** +** 2) It is a system table (i.e. sqlite_master), this call is not +** part of a nested parse and writable_schema pragma has not +** been specified +** +** 3) The table is a shadow table, the database connection is in +** defensive mode, and the current sqlite3_prepare() +** is for a top-level SQL statement. +*/ +static int tabIsReadOnly(Parse *pParse, Table *pTab){ + sqlite3 *db; + if( IsVirtual(pTab) ){ + return sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0; + } + if( (pTab->tabFlags & (TF_Readonly|TF_Shadow))==0 ) return 0; + db = pParse->db; + if( (pTab->tabFlags & TF_Readonly)!=0 ){ + return sqlite3WritableSchema(db)==0 && pParse->nested==0; + } + assert( pTab->tabFlags & TF_Shadow ); + return (db->flags & SQLITE_Defensive)!=0 +#ifndef SQLITE_OMIT_VIRTUALTABLE + && db->pVtabCtx==0 +#endif + && db->nVdbeExec==0; +} + /* ** Check to make sure the given table is writable. If it is not ** writable, generate an error message and return 1. If it is ** writable return 0; */ SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ - /* A table is not writable under the following circumstances: - ** - ** 1) It is a virtual table and no implementation of the xUpdate method - ** has been provided, or - ** 2) It is a system table (i.e. sqlite_master), this call is not - ** part of a nested parse and writable_schema pragma has not - ** been specified. - ** - ** In either case leave an error message in pParse and return non-zero. - */ - if( ( IsVirtual(pTab) - && sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ) - || ( (pTab->tabFlags & TF_Readonly)!=0 - && (pParse->db->flags & SQLITE_WriteSchema)==0 - && pParse->nested==0 ) - ){ + if( tabIsReadOnly(pParse, pTab) ){ sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); return 1; } - #ifndef SQLITE_OMIT_VIEW if( !viewOk && pTab->pSelect ){ sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); @@ -114211,7 +114635,7 @@ ){ Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0); if( pExpr ){ - pExpr->pTab = pTab; + pExpr->y.pTab = pTab; pExpr->iTable = iCursor; pExpr->iColumn = iCol; } @@ -115287,7 +115711,8 @@ }while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB ); pTab->zColAff = zColAff; } - i = sqlite3Strlen30(zColAff); + assert( zColAff!=0 ); + i = sqlite3Strlen30NN(zColAff); if( i ){ if( iReg ){ sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i); @@ -116267,14 +116692,15 @@ #endif /* -** Meanings of bits in of pWalker->eCode for checkConstraintUnchanged() +** Meanings of bits in of pWalker->eCode for +** sqlite3ExprReferencesUpdatedColumn() */ #define CKCNSTRNT_COLUMN 0x01 /* CHECK constraint uses a changing column */ #define CKCNSTRNT_ROWID 0x02 /* CHECK constraint references the ROWID */ -/* This is the Walker callback from checkConstraintUnchanged(). Set -** bit 0x01 of pWalker->eCode if -** pWalker->eCode to 0 if this expression node references any of the +/* This is the Walker callback from sqlite3ExprReferencesUpdatedColumn(). +* Set bit 0x01 of pWalker->eCode if pWalker->eCode to 0 and if this +** expression node references any of the ** columns that are being modifed by an UPDATE statement. */ static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ @@ -116296,12 +116722,21 @@ ** only columns that are modified by the UPDATE are those for which ** aiChng[i]>=0, and also the ROWID is modified if chngRowid is true. ** -** Return true if CHECK constraint pExpr does not use any of the +** Return true if CHECK constraint pExpr uses any of the ** changing columns (or the rowid if it is changing). In other words, -** return true if this CHECK constraint can be skipped when validating +** return true if this CHECK constraint must be validated for ** the new row in the UPDATE statement. +** +** 2018-09-15: pExpr might also be an expression for an index-on-expressions. +** The operation of this routine is the same - return true if an only if +** the expression uses one or more of columns identified by the second and +** third arguments. */ -static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){ +SQLITE_PRIVATE int sqlite3ExprReferencesUpdatedColumn( + Expr *pExpr, /* The expression to be checked */ + int *aiChng, /* aiChng[x]>=0 if column x changed by the UPDATE */ + int chngRowid /* True if UPDATE changes the rowid */ +){ Walker w; memset(&w, 0, sizeof(w)); w.eCode = 0; @@ -116316,7 +116751,7 @@ testcase( w.eCode==CKCNSTRNT_COLUMN ); testcase( w.eCode==CKCNSTRNT_ROWID ); testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) ); - return !w.eCode; + return w.eCode!=0; } /* @@ -116522,7 +116957,13 @@ for(i=0; i<pCheck->nExpr; i++){ int allOk; Expr *pExpr = pCheck->a[i].pExpr; - if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue; + if( aiChng + && !sqlite3ExprReferencesUpdatedColumn(pExpr, aiChng, pkChng) + ){ + /* The check constraints do not reference any of the columns being + ** updated so there is no point it verifying the check constraint */ + continue; + } allOk = sqlite3VdbeMakeLabel(v); sqlite3VdbeVerifyAbortable(v, onError); sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL); @@ -118023,12 +118464,15 @@ int (*str_errcode)(sqlite3_str*); int (*str_length)(sqlite3_str*); char *(*str_value)(sqlite3_str*); + /* Version 3.25.0 and later */ int (*create_window_function)(sqlite3*,const char*,int,int,void*, void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*), void (*xValue)(sqlite3_context*), void (*xInv)(sqlite3_context*,int,sqlite3_value**), void(*xDestroy)(void*)); + /* Version 3.26.0 and later */ + const char *(*normalized_sql)(sqlite3_stmt*); }; /* @@ -118316,6 +118760,8 @@ #define sqlite3_str_value sqlite3_api->str_value /* Version 3.25.0 and later */ #define sqlite3_create_window_function sqlite3_api->create_window_function +/* Version 3.26.0 and later */ +#define sqlite3_normalized_sql sqlite3_api->normalized_sql #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) @@ -118404,6 +118850,7 @@ # define sqlite3_declare_vtab 0 # define sqlite3_vtab_config 0 # define sqlite3_vtab_on_conflict 0 +# define sqlite3_vtab_collation 0 #endif #ifdef SQLITE_OMIT_SHARED_CACHE @@ -118771,7 +119218,13 @@ sqlite3_str_length, sqlite3_str_value, /* Version 3.25.0 and later */ - sqlite3_create_window_function + sqlite3_create_window_function, + /* Version 3.26.0 and later */ +#ifdef SQLITE_ENABLE_NORMALIZE + sqlite3_normalized_sql +#else + 0 +#endif }; /* @@ -119221,10 +119674,9 @@ #define PragTyp_ACTIVATE_EXTENSIONS 40 #define PragTyp_HEXKEY 41 #define PragTyp_KEY 42 -#define PragTyp_REKEY 43 -#define PragTyp_LOCK_STATUS 44 -#define PragTyp_PARSER_TRACE 45 -#define PragTyp_STATS 46 +#define PragTyp_LOCK_STATUS 43 +#define PragTyp_PARSER_TRACE 44 +#define PragTyp_STATS 45 /* Property flags associated with various pragma. */ #define PragFlg_NeedSchema 0x01 /* Force schema load before running */ @@ -119241,58 +119693,57 @@ ** result column is different from the name of the pragma */ static const char *const pragCName[] = { - /* 0 */ "cache_size", /* Used by: default_cache_size */ - /* 1 */ "cid", /* Used by: table_info */ - /* 2 */ "name", - /* 3 */ "type", - /* 4 */ "notnull", - /* 5 */ "dflt_value", - /* 6 */ "pk", - /* 7 */ "tbl", /* Used by: stats */ - /* 8 */ "idx", - /* 9 */ "wdth", - /* 10 */ "hght", - /* 11 */ "flgs", - /* 12 */ "seqno", /* Used by: index_info */ - /* 13 */ "cid", - /* 14 */ "name", + /* 0 */ "id", /* Used by: foreign_key_list */ + /* 1 */ "seq", + /* 2 */ "table", + /* 3 */ "from", + /* 4 */ "to", + /* 5 */ "on_update", + /* 6 */ "on_delete", + /* 7 */ "match", + /* 8 */ "cid", /* Used by: table_xinfo */ + /* 9 */ "name", + /* 10 */ "type", + /* 11 */ "notnull", + /* 12 */ "dflt_value", + /* 13 */ "pk", + /* 14 */ "hidden", + /* table_info reuses 8 */ /* 15 */ "seqno", /* Used by: index_xinfo */ /* 16 */ "cid", /* 17 */ "name", /* 18 */ "desc", /* 19 */ "coll", /* 20 */ "key", - /* 21 */ "seq", /* Used by: index_list */ - /* 22 */ "name", - /* 23 */ "unique", - /* 24 */ "origin", - /* 25 */ "partial", - /* 26 */ "seq", /* Used by: database_list */ + /* 21 */ "tbl", /* Used by: stats */ + /* 22 */ "idx", + /* 23 */ "wdth", + /* 24 */ "hght", + /* 25 */ "flgs", + /* 26 */ "seq", /* Used by: index_list */ /* 27 */ "name", - /* 28 */ "file", - /* 29 */ "name", /* Used by: function_list */ - /* 30 */ "builtin", - /* 31 */ "name", /* Used by: module_list pragma_list */ - /* 32 */ "seq", /* Used by: collation_list */ - /* 33 */ "name", - /* 34 */ "id", /* Used by: foreign_key_list */ - /* 35 */ "seq", - /* 36 */ "table", - /* 37 */ "from", - /* 38 */ "to", - /* 39 */ "on_update", - /* 40 */ "on_delete", - /* 41 */ "match", - /* 42 */ "table", /* Used by: foreign_key_check */ - /* 43 */ "rowid", - /* 44 */ "parent", - /* 45 */ "fkid", - /* 46 */ "busy", /* Used by: wal_checkpoint */ - /* 47 */ "log", - /* 48 */ "checkpointed", - /* 49 */ "timeout", /* Used by: busy_timeout */ - /* 50 */ "database", /* Used by: lock_status */ - /* 51 */ "status", + /* 28 */ "unique", + /* 29 */ "origin", + /* 30 */ "partial", + /* 31 */ "table", /* Used by: foreign_key_check */ + /* 32 */ "rowid", + /* 33 */ "parent", + /* 34 */ "fkid", + /* index_info reuses 15 */ + /* 35 */ "seq", /* Used by: database_list */ + /* 36 */ "name", + /* 37 */ "file", + /* 38 */ "busy", /* Used by: wal_checkpoint */ + /* 39 */ "log", + /* 40 */ "checkpointed", + /* 41 */ "name", /* Used by: function_list */ + /* 42 */ "builtin", + /* collation_list reuses 26 */ + /* 43 */ "database", /* Used by: lock_status */ + /* 44 */ "status", + /* 45 */ "cache_size", /* Used by: default_cache_size */ + /* module_list pragma_list reuses 9 */ + /* 46 */ "timeout", /* Used by: busy_timeout */ }; /* Definitions of all built-in pragmas */ @@ -119302,7 +119753,7 @@ u8 mPragFlg; /* Zero or more PragFlg_XXX values */ u8 iPragCName; /* Start of column names in pragCName[] */ u8 nPragCName; /* Num of col names. 0 means use pragma name */ - u32 iArg; /* Extra argument */ + u64 iArg; /* Extra argument */ } PragmaName; static const PragmaName aPragmaName[] = { #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) @@ -119338,7 +119789,7 @@ {/* zName: */ "busy_timeout", /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 49, 1, + /* ColNames: */ 46, 1, /* iArg: */ 0 }, #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) {/* zName: */ "cache_size", @@ -119375,7 +119826,7 @@ {/* zName: */ "collation_list", /* ePragTyp: */ PragTyp_COLLATION_LIST, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 32, 2, + /* ColNames: */ 26, 2, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) @@ -119410,14 +119861,14 @@ {/* zName: */ "database_list", /* ePragTyp: */ PragTyp_DATABASE_LIST, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, - /* ColNames: */ 26, 3, + /* ColNames: */ 35, 3, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) {/* zName: */ "default_cache_size", /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, - /* ColNames: */ 0, 1, + /* ColNames: */ 45, 1, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) @@ -119447,14 +119898,14 @@ {/* zName: */ "foreign_key_check", /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, - /* ColNames: */ 42, 4, + /* ColNames: */ 31, 4, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FOREIGN_KEY) {/* zName: */ "foreign_key_list", /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 34, 8, + /* ColNames: */ 0, 8, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) @@ -119490,7 +119941,7 @@ {/* zName: */ "function_list", /* ePragTyp: */ PragTyp_FUNCTION_LIST, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 29, 2, + /* ColNames: */ 41, 2, /* iArg: */ 0 }, #endif #endif @@ -119499,12 +119950,12 @@ /* ePragTyp: */ PragTyp_HEXKEY, /* ePragFlg: */ 0, /* ColNames: */ 0, 0, - /* iArg: */ 0 }, + /* iArg: */ 2 }, {/* zName: */ "hexrekey", /* ePragTyp: */ PragTyp_HEXKEY, /* ePragFlg: */ 0, /* ColNames: */ 0, 0, - /* iArg: */ 0 }, + /* iArg: */ 3 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if !defined(SQLITE_OMIT_CHECK) @@ -119526,12 +119977,12 @@ {/* zName: */ "index_info", /* ePragTyp: */ PragTyp_INDEX_INFO, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 12, 3, + /* ColNames: */ 15, 3, /* iArg: */ 0 }, {/* zName: */ "index_list", /* ePragTyp: */ PragTyp_INDEX_LIST, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 21, 5, + /* ColNames: */ 26, 5, /* iArg: */ 0 }, {/* zName: */ "index_xinfo", /* ePragTyp: */ PragTyp_INDEX_INFO, @@ -119588,7 +120039,7 @@ {/* zName: */ "lock_status", /* ePragTyp: */ PragTyp_LOCK_STATUS, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 50, 2, + /* ColNames: */ 43, 2, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) @@ -119614,7 +120065,7 @@ {/* zName: */ "module_list", /* ePragTyp: */ PragTyp_MODULE_LIST, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 31, 1, + /* ColNames: */ 9, 1, /* iArg: */ 0 }, #endif #endif @@ -119647,7 +120098,7 @@ {/* zName: */ "pragma_list", /* ePragTyp: */ PragTyp_PRAGMA_LIST, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 31, 1, + /* ColNames: */ 9, 1, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) @@ -119678,10 +120129,10 @@ #endif #if defined(SQLITE_HAS_CODEC) {/* zName: */ "rekey", - /* ePragTyp: */ PragTyp_REKEY, + /* ePragTyp: */ PragTyp_KEY, /* ePragFlg: */ 0, /* ColNames: */ 0, 0, - /* iArg: */ 0 }, + /* iArg: */ 1 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "reverse_unordered_selects", @@ -119734,7 +120185,7 @@ {/* zName: */ "stats", /* ePragTyp: */ PragTyp_STATS, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, - /* ColNames: */ 7, 5, + /* ColNames: */ 21, 5, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) @@ -119748,8 +120199,13 @@ {/* zName: */ "table_info", /* ePragTyp: */ PragTyp_TABLE_INFO, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 1, 6, + /* ColNames: */ 8, 6, /* iArg: */ 0 }, + {/* zName: */ "table_xinfo", + /* ePragTyp: */ PragTyp_TABLE_INFO, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, + /* ColNames: */ 8, 7, + /* iArg: */ 1 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) {/* zName: */ "temp_store", @@ -119763,6 +120219,18 @@ /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif +#if defined(SQLITE_HAS_CODEC) + {/* zName: */ "textkey", + /* ePragTyp: */ PragTyp_KEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 4 }, + {/* zName: */ "textrekey", + /* ePragTyp: */ PragTyp_KEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 5 }, +#endif {/* zName: */ "threads", /* ePragTyp: */ PragTyp_THREADS, /* ePragFlg: */ PragFlg_Result0, @@ -119813,7 +120281,7 @@ {/* zName: */ "wal_checkpoint", /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, /* ePragFlg: */ PragFlg_NeedSchema, - /* ColNames: */ 46, 3, + /* ColNames: */ 38, 3, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) @@ -119821,10 +120289,10 @@ /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_WriteSchema }, + /* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError }, #endif }; -/* Number of pragmas: 61 on by default, 78 total. */ +/* Number of pragmas: 62 on by default, 81 total. */ /************** End of pragma.h **********************************************/ /************** Continuing where we left off in pragma.c *********************/ @@ -120836,7 +121304,7 @@ setPragmaResultColumnNames(v, pPragma); returnSingleInt(v, (db->flags & pPragma->iArg)!=0 ); }else{ - int mask = pPragma->iArg; /* Mask of bits to set or clear. */ + u64 mask = pPragma->iArg; /* Mask of bits to set or clear. */ if( db->autoCommit==0 ){ /* Foreign key support may not be enabled or disabled while not ** in auto-commit mode. */ @@ -120885,15 +121353,17 @@ Table *pTab; pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb); if( pTab ){ + int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); int i, k; int nHidden = 0; Column *pCol; Index *pPk = sqlite3PrimaryKeyIndex(pTab); - pParse->nMem = 6; - sqlite3CodeVerifySchema(pParse, iDb); + pParse->nMem = 7; + sqlite3CodeVerifySchema(pParse, iTabDb); sqlite3ViewGetColumnNames(pParse, pTab); for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ - if( IsHiddenColumn(pCol) ){ + int isHidden = IsHiddenColumn(pCol); + if( isHidden && pPragma->iArg==0 ){ nHidden++; continue; } @@ -120905,13 +121375,14 @@ for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} } assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN ); - sqlite3VdbeMultiLoad(v, 1, "issisi", + sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi", i-nHidden, pCol->zName, sqlite3ColumnType(pCol,""), pCol->notNull ? 1 : 0, pCol->pDflt ? pCol->pDflt->u.zToken : 0, - k); + k, + isHidden); } } } @@ -120949,6 +121420,7 @@ Table *pTab; pIdx = sqlite3FindIndex(db, zRight, zDb); if( pIdx ){ + int iIdxDb = sqlite3SchemaToIndex(db, pIdx->pSchema); int i; int mx; if( pPragma->iArg ){ @@ -120961,7 +121433,7 @@ pParse->nMem = 3; } pTab = pIdx->pTable; - sqlite3CodeVerifySchema(pParse, iDb); + sqlite3CodeVerifySchema(pParse, iIdxDb); assert( pParse->nMem<=pPragma->nPragCName ); for(i=0; i<mx; i++){ i16 cnum = pIdx->aiColumn[i]; @@ -120985,8 +121457,9 @@ int i; pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ + int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); pParse->nMem = 5; - sqlite3CodeVerifySchema(pParse, iDb); + sqlite3CodeVerifySchema(pParse, iTabDb); for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){ const char *azOrigin[] = { "c", "u", "pk" }; sqlite3VdbeMultiLoad(v, 1, "isisi", @@ -121033,6 +121506,7 @@ pParse->nMem = 2; for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){ for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){ + if( p->funcFlags & SQLITE_FUNC_INTERNAL ) continue; sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1); } } @@ -121074,9 +121548,10 @@ if( pTab ){ pFK = pTab->pFKey; if( pFK ){ + int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); int i = 0; pParse->nMem = 8; - sqlite3CodeVerifySchema(pParse, iDb); + sqlite3CodeVerifySchema(pParse, iTabDb); while(pFK){ int j; for(j=0; j<pFK->nCol; j++){ @@ -121121,9 +121596,9 @@ pParse->nMem += 4; regKey = ++pParse->nMem; regRow = ++pParse->nMem; - sqlite3CodeVerifySchema(pParse, iDb); k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); while( k ){ + int iTabDb; if( zRight ){ pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); k = 0; @@ -121132,21 +121607,23 @@ k = sqliteHashNext(k); } if( pTab==0 || pTab->pFKey==0 ) continue; - sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); + iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); + sqlite3CodeVerifySchema(pParse, iTabDb); + sqlite3TableLock(pParse, iTabDb, pTab->tnum, 0, pTab->zName); if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; - sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); + sqlite3OpenTable(pParse, 0, iTabDb, pTab, OP_OpenRead); sqlite3VdbeLoadString(v, regResult, pTab->zName); for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ pParent = sqlite3FindTable(db, pFK->zTo, zDb); if( pParent==0 ) continue; pIdx = 0; - sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); + sqlite3TableLock(pParse, iTabDb, pParent->tnum, 0, pParent->zName); x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); if( x==0 ){ if( pIdx==0 ){ - sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead); + sqlite3OpenTable(pParse, i, iTabDb, pParent, OP_OpenRead); }else{ - sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb); + sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iTabDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); } }else{ @@ -121915,12 +122392,24 @@ #endif #ifdef SQLITE_HAS_CODEC + /* Pragma iArg + ** ---------- ------ + ** key 0 + ** rekey 1 + ** hexkey 2 + ** hexrekey 3 + ** textkey 4 + ** textrekey 5 + */ case PragTyp_KEY: { - if( zRight ) sqlite3_key_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); - break; - } - case PragTyp_REKEY: { - if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); + if( zRight ){ + int n = pPragma->iArg<4 ? sqlite3Strlen30(zRight) : -1; + if( (pPragma->iArg & 1)==0 ){ + sqlite3_key_v2(db, zDb, zRight, n); + }else{ + sqlite3_rekey_v2(db, zDb, zRight, n); + } + } break; } case PragTyp_HEXKEY: { @@ -121932,7 +122421,7 @@ iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]); if( (i&1)!=0 ) zKey[i/2] = iByte; } - if( (zLeft[3] & 0xf)==0xb ){ + if( (pPragma->iArg & 1)==0 ){ sqlite3_key_v2(db, zDb, zKey, i/2); }else{ sqlite3_rekey_v2(db, zDb, zKey, i/2); @@ -122262,7 +122751,8 @@ 0, /* xRename - rename the table */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; /* @@ -122615,8 +123105,8 @@ rc = SQLITE_NOMEM_BKPT; sqlite3ResetAllSchemasOfConnection(db); } - if( rc==SQLITE_OK || (db->flags&SQLITE_WriteSchema)){ - /* Black magic: If the SQLITE_WriteSchema flag is set, then consider + if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){ + /* Black magic: If the SQLITE_NoSchemaError flag is set, then consider ** the schema loaded, even if errors occurred. In this situation the ** current sqlite3_prepare() operation will fail, but the following one ** will attempt to compile the supplied statement against whatever subset @@ -122997,6 +123487,294 @@ return rc; } +#ifdef SQLITE_ENABLE_NORMALIZE +/* +** Checks if the specified token is a table, column, or function name, +** based on the databases associated with the statement being prepared. +** If the function fails, zero is returned and pRc is filled with the +** error code. +*/ +static int shouldTreatAsIdentifier( + sqlite3 *db, /* Database handle. */ + const char *zToken, /* Pointer to start of token to be checked */ + int nToken, /* Length of token to be checked */ + int *pRc /* Pointer to error code upon failure */ +){ + int bFound = 0; /* Non-zero if token is an identifier name. */ + int i, j; /* Database and column loop indexes. */ + Schema *pSchema; /* Schema for current database. */ + Hash *pHash; /* Hash table of tables for current database. */ + HashElem *e; /* Hash element for hash table iteration. */ + Table *pTab; /* Database table for columns being checked. */ + + if( sqlite3IsRowidN(zToken, nToken) ){ + return 1; + } + if( nToken>0 ){ + int hash = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zToken[0]], nToken); + if( sqlite3FunctionSearchN(hash, zToken, nToken) ) return 1; + } + assert( db!=0 ); + sqlite3_mutex_enter(db->mutex); + sqlite3BtreeEnterAll(db); + for(i=0; i<db->nDb; i++){ + pHash = &db->aFunc; + if( sqlite3HashFindN(pHash, zToken, nToken) ){ + bFound = 1; + break; + } + pSchema = db->aDb[i].pSchema; + if( pSchema==0 ) continue; + pHash = &pSchema->tblHash; + if( sqlite3HashFindN(pHash, zToken, nToken) ){ + bFound = 1; + break; + } + for(e=sqliteHashFirst(pHash); e; e=sqliteHashNext(e)){ + pTab = sqliteHashData(e); + if( pTab==0 ) continue; + pHash = pTab->pColHash; + if( pHash==0 ){ + pTab->pColHash = pHash = sqlite3_malloc(sizeof(Hash)); + if( pHash ){ + sqlite3HashInit(pHash); + for(j=0; j<pTab->nCol; j++){ + Column *pCol = &pTab->aCol[j]; + sqlite3HashInsert(pHash, pCol->zName, pCol); + } + }else{ + *pRc = SQLITE_NOMEM_BKPT; + bFound = 0; + goto done; + } + } + if( pHash && sqlite3HashFindN(pHash, zToken, nToken) ){ + bFound = 1; + goto done; + } + } + } +done: + sqlite3BtreeLeaveAll(db); + sqlite3_mutex_leave(db->mutex); + return bFound; +} + +/* +** Attempt to estimate the final output buffer size needed for the fully +** normalized version of the specified SQL string. This should take into +** account any potential expansion that could occur (e.g. via IN clauses +** being expanded, etc). This size returned is the total number of bytes +** including the NUL terminator. +*/ +static int estimateNormalizedSize( + const char *zSql, /* The original SQL string */ + int nSql, /* Length of original SQL string */ + u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */ +){ + int nOut = nSql + 4; + const char *z = zSql; + while( nOut<nSql*5 ){ + while( z[0]!=0 && z[0]!='I' && z[0]!='i' ){ z++; } + if( z[0]==0 ) break; + z++; + if( z[0]!='N' && z[0]!='n' ) break; + z++; + while( sqlite3Isspace(z[0]) ){ z++; } + if( z[0]!='(' ) break; + z++; + nOut += 5; /* ?,?,? */ + } + return nOut; +} + +/* +** Copy the current token into the output buffer while dealing with quoted +** identifiers. By default, all letters will be converted into lowercase. +** If the bUpper flag is set, uppercase will be used. The piOut argument +** will be used to update the target index into the output string. +*/ +static void copyNormalizedToken( + const char *zSql, /* The original SQL string */ + int iIn, /* Current index into the original SQL string */ + int nToken, /* Number of bytes in the current token */ + int tokenFlags, /* Flags returned by the tokenizer */ + char *zOut, /* The output string */ + int *piOut /* Pointer to target index into the output string */ +){ + int bQuoted = tokenFlags & SQLITE_TOKEN_QUOTED; + int bKeyword = tokenFlags & SQLITE_TOKEN_KEYWORD; + int j = *piOut, k = 0; + for(; k<nToken; k++){ + if( bQuoted ){ + if( k==0 && iIn>0 ){ + zOut[j++] = '"'; + continue; + }else if( k==nToken-1 ){ + zOut[j++] = '"'; + continue; + } + } + if( bKeyword ){ + zOut[j++] = sqlite3Toupper(zSql[iIn+k]); + }else{ + zOut[j++] = sqlite3Tolower(zSql[iIn+k]); + } + } + *piOut = j; +} + +/* +** Perform normalization of the SQL contained in the prepared statement and +** store the result in the zNormSql field. The schema for the associated +** databases are consulted while performing the normalization in order to +** determine if a token appears to be an identifier. All identifiers are +** left intact in the normalized SQL and all literals are replaced with a +** single '?'. +*/ +SQLITE_PRIVATE void sqlite3Normalize( + Vdbe *pVdbe, /* VM being reprepared */ + const char *zSql, /* The original SQL string */ + int nSql, /* Size of the input string in bytes */ + u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */ +){ + sqlite3 *db; /* Database handle. */ + char *z; /* The output string */ + int nZ; /* Size of the output string in bytes */ + int i; /* Next character to read from zSql[] */ + int j; /* Next character to fill in on z[] */ + int tokenType = 0; /* Type of the next token */ + int prevTokenType = 0; /* Type of the previous token, except spaces */ + int n; /* Size of the next token */ + int nParen = 0; /* Nesting level of parenthesis */ + Hash inHash; /* Table of parenthesis levels to output index. */ + + db = sqlite3VdbeDb(pVdbe); + assert( db!=0 ); + assert( pVdbe->zNormSql==0 ); + if( zSql==0 ) return; + nZ = estimateNormalizedSize(zSql, nSql, prepFlags); + z = sqlite3DbMallocRawNN(db, nZ); + if( z==0 ) return; + sqlite3HashInit(&inHash); + for(i=j=0; i<nSql && zSql[i]; i+=n){ + int flags = 0; + if( tokenType!=TK_SPACE ) prevTokenType = tokenType; + n = sqlite3GetTokenNormalized((unsigned char*)zSql+i, &tokenType, &flags); + switch( tokenType ){ + case TK_SPACE: { + break; + } + case TK_ILLEGAL: { + sqlite3DbFree(db, z); + sqlite3HashClear(&inHash); + return; + } + case TK_STRING: + case TK_INTEGER: + case TK_FLOAT: + case TK_VARIABLE: + case TK_BLOB: { + z[j++] = '?'; + break; + } + case TK_LP: + case TK_RP: { + if( tokenType==TK_LP ){ + nParen++; + if( prevTokenType==TK_IN ){ + assert( nParen<nSql ); + sqlite3HashInsert(&inHash, zSql+nParen, SQLITE_INT_TO_PTR(j)); + } + }else{ + int jj; + assert( nParen<nSql ); + jj = SQLITE_PTR_TO_INT(sqlite3HashFind(&inHash, zSql+nParen)); + if( jj>0 ){ + sqlite3HashInsert(&inHash, zSql+nParen, 0); + assert( jj+6<nZ ); + memcpy(z+jj+1, "?,?,?", 5); + j = jj+6; + assert( nZ-1-j>=0 ); + assert( nZ-1-j<nZ ); + memset(z+j, 0, nZ-1-j); + } + nParen--; + } + assert( nParen>=0 ); + /* Fall through */ + } + case TK_MINUS: + case TK_SEMI: + case TK_PLUS: + case TK_STAR: + case TK_SLASH: + case TK_REM: + case TK_EQ: + case TK_LE: + case TK_NE: + case TK_LSHIFT: + case TK_LT: + case TK_RSHIFT: + case TK_GT: + case TK_GE: + case TK_BITOR: + case TK_CONCAT: + case TK_COMMA: + case TK_BITAND: + case TK_BITNOT: + case TK_DOT: + case TK_IN: + case TK_IS: + case TK_NOT: + case TK_NULL: + case TK_ID: { + if( tokenType==TK_NULL ){ + if( prevTokenType==TK_IS || prevTokenType==TK_NOT ){ + /* NULL is a keyword in this case, not a literal value */ + }else{ + /* Here the NULL is a literal value */ + z[j++] = '?'; + break; + } + } + if( j>0 && sqlite3IsIdChar(z[j-1]) && sqlite3IsIdChar(zSql[i]) ){ + z[j++] = ' '; + } + if( tokenType==TK_ID ){ + int i2 = i, n2 = n, rc = SQLITE_OK; + if( nParen>0 ){ + assert( nParen<nSql ); + sqlite3HashInsert(&inHash, zSql+nParen, 0); + } + if( flags&SQLITE_TOKEN_QUOTED ){ i2++; n2-=2; } + if( shouldTreatAsIdentifier(db, zSql+i2, n2, &rc)==0 ){ + if( rc!=SQLITE_OK ){ + sqlite3DbFree(db, z); + sqlite3HashClear(&inHash); + return; + } + if( sqlite3_keyword_check(zSql+i2, n2)==0 ){ + z[j++] = '?'; + break; + } + } + } + copyNormalizedToken(zSql, i, n, flags, z, &j); + break; + } + } + } + assert( j<nZ && "one" ); + while( j>0 && z[j-1]==' ' ){ j--; } + if( j>0 && z[j-1]!=';' ){ z[j++] = ';'; } + z[j] = 0; + assert( j<nZ && "two" ); + pVdbe->zNormSql = z; + sqlite3HashClear(&inHash); +} +#endif /* SQLITE_ENABLE_NORMALIZE */ + /* ** Rerun the compilation of a statement after a schema change. ** @@ -124009,7 +124787,7 @@ struct ExprList_item *pItem = &pEList->a[i]; if( pItem->u.x.iOrderByCol==0 ){ Expr *pExpr = pItem->pExpr; - Table *pTab = pExpr->pTab; + Table *pTab = pExpr->y.pTab; if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab) && (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF) ){ @@ -124032,12 +124810,12 @@ Expr *pNew = sqlite3PExpr(pParse, TK_COLUMN, 0, 0); if( pNew ){ pNew->iTable = pExpr->iTable; - pNew->pTab = pExpr->pTab; + pNew->y.pTab = pExpr->y.pTab; pNew->iColumn = pPk ? pPk->aiColumn[k] : -1; pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew); } } - pSort->aDefer[nDefer].pTab = pExpr->pTab; + pSort->aDefer[nDefer].pTab = pExpr->y.pTab; pSort->aDefer[nDefer].iCsr = pExpr->iTable; pSort->aDefer[nDefer].nKey = nKey; nDefer++; @@ -124886,7 +125664,7 @@ break; } - assert( pTab && pExpr->pTab==pTab ); + assert( pTab && pExpr->y.pTab==pTab ); if( pS ){ /* The "table" is actually a sub-select or a view in the FROM clause ** of the SELECT statement. Return the declaration type and origin @@ -125071,7 +125849,7 @@ assert( p!=0 ); assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */ - assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering idx not yet coded */ + assert( p->op!=TK_COLUMN || p->y.pTab!=0 ); /* Covering idx not yet coded */ if( pEList->a[i].zName ){ /* An AS clause always takes first priority */ char *zName = pEList->a[i].zName; @@ -125079,7 +125857,7 @@ }else if( srcName && p->op==TK_COLUMN ){ char *zCol; int iCol = p->iColumn; - pTab = p->pTab; + pTab = p->y.pTab; assert( pTab!=0 ); if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); @@ -125170,7 +125948,7 @@ if( pColExpr->op==TK_COLUMN ){ /* For columns use the column name name */ int iCol = pColExpr->iColumn; - Table *pTab = pColExpr->pTab; + Table *pTab = pColExpr->y.pTab; assert( pTab!=0 ); if( iCol<0 ) iCol = pTab->iPKey; zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid"; @@ -131296,6 +132074,57 @@ } /* +** Check to see if column iCol of index pIdx references any of the +** columns defined by aXRef and chngRowid. Return true if it does +** and false if not. This is an optimization. False-positives are a +** performance degradation, but false-negatives can result in a corrupt +** index and incorrect answers. +** +** aXRef[j] will be non-negative if column j of the original table is +** being updated. chngRowid will be true if the rowid of the table is +** being updated. +*/ +static int indexColumnIsBeingUpdated( + Index *pIdx, /* The index to check */ + int iCol, /* Which column of the index to check */ + int *aXRef, /* aXRef[j]>=0 if column j is being updated */ + int chngRowid /* true if the rowid is being updated */ +){ + i16 iIdxCol = pIdx->aiColumn[iCol]; + assert( iIdxCol!=XN_ROWID ); /* Cannot index rowid */ + if( iIdxCol>=0 ){ + return aXRef[iIdxCol]>=0; + } + assert( iIdxCol==XN_EXPR ); + assert( pIdx->aColExpr!=0 ); + assert( pIdx->aColExpr->a[iCol].pExpr!=0 ); + return sqlite3ExprReferencesUpdatedColumn(pIdx->aColExpr->a[iCol].pExpr, + aXRef,chngRowid); +} + +/* +** Check to see if index pIdx is a partial index whose conditional +** expression might change values due to an UPDATE. Return true if +** the index is subject to change and false if the index is guaranteed +** to be unchanged. This is an optimization. False-positives are a +** performance degradation, but false-negatives can result in a corrupt +** index and incorrect answers. +** +** aXRef[j] will be non-negative if column j of the original table is +** being updated. chngRowid will be true if the rowid of the table is +** being updated. +*/ +static int indexWhereClauseMightChange( + Index *pIdx, /* The index to check */ + int *aXRef, /* aXRef[j]>=0 if column j is being updated */ + int chngRowid /* true if the rowid is being updated */ +){ + if( pIdx->pPartIdxWhere==0 ) return 0; + return sqlite3ExprReferencesUpdatedColumn(pIdx->pPartIdxWhere, + aXRef, chngRowid); +} + +/* ** Process an UPDATE statement. ** ** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; @@ -131518,19 +132347,18 @@ /* There is one entry in the aRegIdx[] array for each index on the table ** being updated. Fill in aRegIdx[] with a register number that will hold ** the key for accessing each index. - ** - ** FIXME: Be smarter about omitting indexes that use expressions. */ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int reg; - if( chngKey || hasFK>1 || pIdx->pPartIdxWhere || pIdx==pPk ){ + if( chngKey || hasFK>1 || pIdx==pPk + || indexWhereClauseMightChange(pIdx,aXRef,chngRowid) + ){ reg = ++pParse->nMem; pParse->nMem += pIdx->nColumn; }else{ reg = 0; for(i=0; i<pIdx->nKeyCol; i++){ - i16 iIdxCol = pIdx->aiColumn[i]; - if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){ + if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){ reg = ++pParse->nMem; pParse->nMem += pIdx->nColumn; if( (onError==OE_Replace) @@ -132580,7 +133408,8 @@ saved_mTrace = db->mTrace; db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum; - db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_CountRows); + db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder + | SQLITE_Defensive | SQLITE_CountRows); db->mTrace = 0; zDbMain = db->aDb[iDb].zDbSName; @@ -133122,7 +133951,6 @@ Token *pModuleName, /* Name of the module for the virtual table */ int ifNotExists /* No error if the table already exists */ ){ - int iDb; /* The database the table is being created in */ Table *pTable; /* The new virtual table */ sqlite3 *db; /* Database connection */ @@ -133132,8 +133960,6 @@ assert( 0==pTable->pIndex ); db = pParse->db; - iDb = sqlite3SchemaToIndex(db, pTable->pSchema); - assert( iDb>=0 ); assert( pTable->nModuleArg==0 ); addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); @@ -133153,6 +133979,8 @@ ** The second call, to obtain permission to create the table, is made now. */ if( pTable->azModuleArg ){ + int iDb = sqlite3SchemaToIndex(db, pTable->pSchema); + assert( iDb>=0 ); /* The database the table is being created in */ sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName); } @@ -133847,7 +134675,7 @@ /* Check to see the left operand is a column in a virtual table */ if( NEVER(pExpr==0) ) return pDef; if( pExpr->op!=TK_COLUMN ) return pDef; - pTab = pExpr->pTab; + pTab = pExpr->y.pTab; if( pTab==0 ) return pDef; if( !IsVirtual(pTab) ) return pDef; pVtab = sqlite3GetVTable(db, pTab)->pVtab; @@ -134467,12 +135295,33 @@ int nRecValid; /* Number of valid fields currently in pRec */ #endif unsigned int bldFlags; /* SQLITE_BLDF_* flags */ + unsigned int iPlanLimit; /* Search limiter */ }; /* Allowed values for WhereLoopBuider.bldFlags */ #define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */ #define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */ +/* The WhereLoopBuilder.iPlanLimit is used to limit the number of +** index+constraint combinations the query planner will consider for a +** particular query. If this parameter is unlimited, then certain +** pathological queries can spend excess time in the sqlite3WhereBegin() +** routine. The limit is high enough that is should not impact real-world +** queries. +** +** SQLITE_QUERY_PLANNER_LIMIT is the baseline limit. The limit is +** increased by SQLITE_QUERY_PLANNER_LIMIT_INCR before each term of the FROM +** clause is processed, so that every table in a join is guaranteed to be +** able to propose a some index+constraint combinations even if the initial +** baseline limit was exhausted by prior tables of the join. +*/ +#ifndef SQLITE_QUERY_PLANNER_LIMIT +# define SQLITE_QUERY_PLANNER_LIMIT 20000 +#endif +#ifndef SQLITE_QUERY_PLANNER_LIMIT_INCR +# define SQLITE_QUERY_PLANNER_LIMIT_INCR 1000 +#endif + /* ** The WHERE clause processing routine has two halves. The ** first part does the start of the WHERE loop and the second @@ -135726,7 +136575,7 @@ pExpr->op = TK_COLUMN; pExpr->iTable = pX->iIdxCur; pExpr->iColumn = pX->iIdxCol; - pExpr->pTab = 0; + pExpr->y.pTab = 0; return WRC_Prune; }else{ return WRC_Continue; @@ -137126,7 +137975,7 @@ ){ if( pLeft->op!=TK_COLUMN || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT - || IsVirtual(pLeft->pTab) /* Value might be numeric */ + || IsVirtual(pLeft->y.pTab) /* Value might be numeric */ ){ sqlite3ExprDelete(db, pPrefix); sqlite3ValueFree(pVal); @@ -137227,7 +138076,7 @@ ** MATCH(expression,vtab_column) */ pCol = pList->a[1].pExpr; - if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){ + if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ for(i=0; i<ArraySize(aOp); i++){ if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){ *peOp2 = aOp[i].eOp2; @@ -137249,12 +138098,12 @@ ** with function names in an arbitrary case. */ pCol = pList->a[0].pExpr; - if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){ + if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ sqlite3_vtab *pVtab; sqlite3_module *pMod; void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); void *pNotUsed; - pVtab = sqlite3GetVTable(db, pCol->pTab)->pVtab; + pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab; assert( pVtab!=0 ); assert( pVtab->pModule!=0 ); pMod = (sqlite3_module *)pVtab->pModule; @@ -137272,10 +138121,10 @@ int res = 0; Expr *pLeft = pExpr->pLeft; Expr *pRight = pExpr->pRight; - if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){ + if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab) ){ res++; } - if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->pTab) ){ + if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab) ){ res++; SWAP(Expr*, pLeft, pRight); } @@ -138419,6 +139268,7 @@ pArgs = pItem->u1.pFuncArg; if( pArgs==0 ) return; for(j=k=0; j<pArgs->nExpr; j++){ + Expr *pRhs; while( k<pTab->nCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){k++;} if( k>=pTab->nCol ){ sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d", @@ -138429,9 +139279,10 @@ if( pColRef==0 ) return; pColRef->iTable = pItem->iCursor; pColRef->iColumn = k++; - pColRef->pTab = pTab; - pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, - sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0)); + pColRef->y.pTab = pTab; + pRhs = sqlite3PExpr(pParse, TK_UPLUS, + sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); + pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs); whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); } } @@ -139294,7 +140145,6 @@ translateColumnToCopy(pParse, addrTop, pLevel->iTabCur, pTabItem->regResult, 1); sqlite3VdbeGoto(v, addrTop); - pTabItem->fg.viaCoroutine = 0; }else{ sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); } @@ -139472,9 +140322,11 @@ ** method of the virtual table with the sqlite3_index_info object that ** comes in as the 3rd argument to this function. ** -** If an error occurs, pParse is populated with an error message and a -** non-zero value is returned. Otherwise, 0 is returned and the output -** part of the sqlite3_index_info structure is left populated. +** If an error occurs, pParse is populated with an error message and an +** appropriate error code is returned. A return of SQLITE_CONSTRAINT from +** xBestIndex is not considered an error. SQLITE_CONSTRAINT indicates that +** the current configuration of "unusable" flags in sqlite3_index_info can +** not result in a valid plan. ** ** Whether or not an error is returned, it is the responsibility of the ** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates @@ -139488,7 +140340,7 @@ rc = pVtab->pModule->xBestIndex(pVtab, p); TRACE_IDX_OUTPUTS(p); - if( rc!=SQLITE_OK ){ + if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){ if( rc==SQLITE_NOMEM ){ sqlite3OomFault(pParse->db); }else if( !pVtab->zErrMsg ){ @@ -139499,19 +140351,7 @@ } sqlite3_free(pVtab->zErrMsg); pVtab->zErrMsg = 0; - -#if 0 - /* This error is now caught by the caller. - ** Search for "xBestIndex malfunction" below */ - for(i=0; i<p->nConstraint; i++){ - if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){ - sqlite3ErrorMsg(pParse, - "table %s: xBestIndex returned an invalid plan", pTab->zName); - } - } -#endif - - return pParse->nErr; + return rc; } #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ @@ -140566,6 +141406,14 @@ sqlite3 *db = pWInfo->pParse->db; int rc; + /* Stop the search once we hit the query planner search limit */ + if( pBuilder->iPlanLimit==0 ){ + WHERETRACE(0xffffffff,("=== query planner search limit reached ===\n")); + if( pBuilder->pOrSet ) pBuilder->pOrSet->n = 0; + return SQLITE_DONE; + } + pBuilder->iPlanLimit--; + /* If pBuilder->pOrSet is defined, then only keep track of the costs ** and prereqs. */ @@ -141576,7 +142424,17 @@ /* Invoke the virtual table xBestIndex() method */ rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo); - if( rc ) return rc; + if( rc ){ + if( rc==SQLITE_CONSTRAINT ){ + /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means + ** that the particular combination of parameters provided is unusable. + ** Make no entries in the loop table. + */ + WHERETRACE(0xffff, (" ^^^^--- non-viable plan rejected!\n")); + return SQLITE_OK; + } + return rc; + } mxTerm = -1; assert( pNew->nLSlot>=nConstraint ); @@ -141972,9 +142830,11 @@ /* Loop over the tables in the join, from left to right */ pNew = pBuilder->pNew; whereLoopInit(pNew); + pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT; for(iTab=0, pItem=pTabList->a; pItem<pEnd; iTab++, pItem++){ Bitmask mUnusable = 0; pNew->iTab = iTab; + pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR; pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor); if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){ /* This condition is true when pItem is the FROM clause term on the @@ -142000,7 +142860,15 @@ rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable); } mPrior |= pNew->maskSelf; - if( rc || db->mallocFailed ) break; + if( rc || db->mallocFailed ){ + if( rc==SQLITE_DONE ){ + /* We hit the query planner search limit set by iPlanLimit */ + sqlite3_log(SQLITE_WARNING, "abbreviated query algorithm search"); + rc = SQLITE_OK; + }else{ + break; + } + } } whereLoopClear(db, pNew); @@ -144382,12 +145250,12 @@ switch( pExpr->op ){ case TK_FUNCTION: - if( pExpr->pWin==0 ){ + if( !ExprHasProperty(pExpr, EP_WinFunc) ){ break; }else{ Window *pWin; for(pWin=p->pWin; pWin; pWin=pWin->pNextWin){ - if( pExpr->pWin==pWin ){ + if( pExpr->y.pWin==pWin ){ assert( pWin->pOwner==pExpr ); return WRC_Prune; } @@ -144504,7 +145372,7 @@ */ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){ int rc = SQLITE_OK; - if( p->pWin ){ + if( p->pWin && p->pPrior==0 ){ Vdbe *v = sqlite3GetVdbe(pParse); sqlite3 *db = pParse->db; Select *pSub = 0; /* The subquery */ @@ -144717,11 +145585,13 @@ */ SQLITE_PRIVATE void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){ if( p ){ + assert( p->op==TK_FUNCTION ); /* This routine is only called for the parser. If pWin was not ** allocated due to an OOM, then the parser would fail before ever ** invoking this routine */ if( ALWAYS(pWin) ){ - p->pWin = pWin; + p->y.pWin = pWin; + ExprSetProperty(p, EP_WinFunc); pWin->pOwner = p; if( p->flags & EP_Distinct ){ sqlite3ErrorMsg(pParse, @@ -145884,7 +146754,7 @@ */ SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){ Window *pNew = 0; - if( p ){ + if( ALWAYS(p) ){ pNew = sqlite3DbMallocZero(db, sizeof(Window)); if( pNew ){ pNew->zName = sqlite3DbStrDup(db, p->zName); @@ -146036,6 +146906,7 @@ ** input grammar file: */ /* #include <stdio.h> */ +/* #include <assert.h> */ /************ Begin %include sections from the grammar ************************/ /* #include "sqliteInt.h" */ @@ -146137,13 +147008,10 @@ p->pLeft = p->pRight = 0; p->x.pList = 0; p->pAggInfo = 0; - p->pTab = 0; + p->y.pTab = 0; p->op2 = 0; p->iTable = 0; p->iColumn = 0; -#ifndef SQLITE_OMIT_WINDOWFUNC - p->pWin = 0; -#endif p->u.zToken = (char*)&p[1]; memcpy(p->u.zToken, t.z, t.n); p->u.zToken[t.n] = 0; @@ -149992,10 +150860,9 @@ yymajor = YYNOCODE; }else{ while( yypParser->yytos >= yypParser->yystack - && yymx != YYERRORSYMBOL && (yyact = yy_find_reduce_action( yypParser->yytos->stateno, - YYERRORSYMBOL)) >= YY_MIN_REDUCE + YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE ){ yy_pop_parser_stack(yypParser); } @@ -150933,6 +151800,73 @@ return i; } +#ifdef SQLITE_ENABLE_NORMALIZE +/* +** Return the length (in bytes) of the token that begins at z[0]. +** Store the token type in *tokenType before returning. If flags has +** SQLITE_TOKEN_NORMALIZE flag enabled, use the identifier token type +** for keywords. Add SQLITE_TOKEN_QUOTED to flags if the token was +** actually a quoted identifier. Add SQLITE_TOKEN_KEYWORD to flags +** if the token was recognized as a keyword; this is useful when the +** SQLITE_TOKEN_NORMALIZE flag is used, because it enables the caller +** to differentiate between a keyword being treated as an identifier +** (for normalization purposes) and an actual identifier. +*/ +SQLITE_PRIVATE int sqlite3GetTokenNormalized( + const unsigned char *z, + int *tokenType, + int *flags +){ + int n; + unsigned char iClass = aiClass[*z]; + if( iClass==CC_KYWD ){ + int i; + for(i=1; aiClass[z[i]]<=CC_KYWD; i++){} + if( IdChar(z[i]) ){ + /* This token started out using characters that can appear in keywords, + ** but z[i] is a character not allowed within keywords, so this must + ** be an identifier instead */ + i++; + while( IdChar(z[i]) ){ i++; } + *tokenType = TK_ID; + return i; + } + *tokenType = TK_ID; + n = keywordCode((char*)z, i, tokenType); + /* If the token is no longer considered to be an identifier, then it is a + ** keyword of some kind. Make the token back into an identifier and then + ** set the SQLITE_TOKEN_KEYWORD flag. Several non-identifier tokens are + ** used verbatim, including IN, IS, NOT, and NULL. */ + switch( *tokenType ){ + case TK_ID: { + /* do nothing, handled by caller */ + break; + } + case TK_IN: + case TK_IS: + case TK_NOT: + case TK_NULL: { + *flags |= SQLITE_TOKEN_KEYWORD; + break; + } + default: { + *tokenType = TK_ID; + *flags |= SQLITE_TOKEN_KEYWORD; + break; + } + } + }else{ + n = sqlite3GetToken(z, tokenType); + /* If the token is considered to be an identifier and the character class + ** of the first character is a quote, set the SQLITE_TOKEN_QUOTED flag. */ + if( *tokenType==TK_ID && (iClass==CC_QUOTE || iClass==CC_QUOTE2) ){ + *flags |= SQLITE_TOKEN_QUOTED; + } + } + return n; +} +#endif /* SQLITE_ENABLE_NORMALIZE */ + /* ** Run the parser on the given SQL string. The parser structure is ** passed in. An SQLITE_ status code is returned. If an error occurs @@ -152330,6 +153264,7 @@ { SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG }, { SQLITE_DBCONFIG_TRIGGER_EQP, SQLITE_TriggerEQP }, { SQLITE_DBCONFIG_RESET_DATABASE, SQLITE_ResetDatabase }, + { SQLITE_DBCONFIG_DEFENSIVE, SQLITE_Defensive }, }; unsigned int i; rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ @@ -154557,6 +155492,9 @@ #if defined(SQLITE_ENABLE_QPSG) | SQLITE_EnableQPSG #endif +#if defined(SQLITE_DEFAULT_DEFENSIVE) + | SQLITE_Defensive +#endif ; sqlite3HashInit(&db->aCollSeq); #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -155452,15 +156390,26 @@ /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff); ** - ** If parameter onoff is non-zero, configure the wrappers so that all - ** subsequent calls to localtime() and variants fail. If onoff is zero, - ** undo this setting. + ** If parameter onoff is non-zero, subsequent calls to localtime() + ** and its variants fail. If onoff is zero, undo this setting. */ case SQLITE_TESTCTRL_LOCALTIME_FAULT: { sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int); break; } + /* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCS, int onoff); + ** + ** If parameter onoff is non-zero, internal-use-only SQL functions + ** are visible to ordinary SQL. This is useful for testing but is + ** unsafe because invalid parameters to those internal-use-only functions + ** can result in crashes or segfaults. + */ + case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: { + sqlite3GlobalConfig.bInternalFunctions = va_arg(ap, int); + break; + } + /* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int); ** ** Set or clear a flag that indicates that the database file is always well- @@ -157239,7 +158188,7 @@ # define sqlite3Fts3DeferToken(x,y,z) SQLITE_OK # define sqlite3Fts3CacheDeferredDoclists(x) SQLITE_OK # define sqlite3Fts3FreeDeferredDoclists(x) -# define sqlite3Fts3DeferredTokenList(x,y,z) ((*(y)=0),(*(z)=0),SQLITE_OK) +# define sqlite3Fts3DeferredTokenList(x,y,z) SQLITE_OK #endif SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *); @@ -160929,8 +161878,23 @@ return SQLITE_OK; } +/* +** Return true if zName is the extension on one of the shadow tables used +** by this module. +*/ +static int fts3ShadowName(const char *zName){ + static const char *azName[] = { + "content", "docsize", "segdir", "segments", "stat", + }; + unsigned int i; + for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ + if( sqlite3_stricmp(zName, azName[i])==0 ) return 1; + } + return 0; +} + static const sqlite3_module fts3Module = { - /* iVersion */ 2, + /* iVersion */ 3, /* xCreate */ fts3CreateMethod, /* xConnect */ fts3ConnectMethod, /* xBestIndex */ fts3BestIndexMethod, @@ -160953,6 +161917,7 @@ /* xSavepoint */ fts3SavepointMethod, /* xRelease */ fts3ReleaseMethod, /* xRollbackTo */ fts3RollbackToMethod, + /* xShadowName */ fts3ShadowName, }; /* @@ -161241,6 +162206,7 @@ return rc; } +#ifndef SQLITE_DISABLE_FTS4_DEFERRED /* ** This function is called on each phrase after the position lists for ** any deferred tokens have been loaded into memory. It updates the phrases @@ -161344,6 +162310,7 @@ return SQLITE_OK; } +#endif /* SQLITE_DISABLE_FTS4_DEFERRED */ /* ** Maximum number of tokens a phrase may have to be considered for the @@ -163592,7 +164559,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; int rc; /* Return code */ @@ -167151,7 +168119,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; int rc; /* Return code */ @@ -177328,6 +178297,9 @@ #define JEACH_PARENT 5 #define JEACH_FULLKEY 6 #define JEACH_PATH 7 +/* The xBestIndex method assumes that the JSON and ROOT columns are +** the last two columns in the table. Should this ever changes, be +** sure to update the xBestIndex method. */ #define JEACH_JSON 8 #define JEACH_ROOT 9 @@ -177585,35 +178557,54 @@ sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ - int i; - int jsonIdx = -1; - int rootIdx = -1; + int i; /* Loop counter or computed array index */ + int aIdx[2]; /* Index of constraints for JSON and ROOT */ + int unusableMask = 0; /* Mask of unusable JSON and ROOT constraints */ + int idxMask = 0; /* Mask of usable == constraints JSON and ROOT */ const struct sqlite3_index_constraint *pConstraint; + /* This implementation assumes that JSON and ROOT are the last two + ** columns in the table */ + assert( JEACH_ROOT == JEACH_JSON+1 ); UNUSED_PARAM(tab); + aIdx[0] = aIdx[1] = -1; pConstraint = pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ - if( pConstraint->usable==0 ) continue; - if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; - switch( pConstraint->iColumn ){ - case JEACH_JSON: jsonIdx = i; break; - case JEACH_ROOT: rootIdx = i; break; - default: /* no-op */ break; + int iCol; + int iMask; + if( pConstraint->iColumn < JEACH_JSON ) continue; + iCol = pConstraint->iColumn - JEACH_JSON; + assert( iCol==0 || iCol==1 ); + iMask = 1 << iCol; + if( pConstraint->usable==0 ){ + unusableMask |= iMask; + }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + aIdx[iCol] = i; + idxMask |= iMask; } } - if( jsonIdx<0 ){ + if( (unusableMask & ~idxMask)!=0 ){ + /* If there are any unusable constraints on JSON or ROOT, then reject + ** this entire plan */ + return SQLITE_CONSTRAINT; + } + if( aIdx[0]<0 ){ + /* No JSON input. Leave estimatedCost at the huge value that it was + ** initialized to to discourage the query planner from selecting this + ** plan. */ pIdxInfo->idxNum = 0; - pIdxInfo->estimatedCost = 1e99; }else{ pIdxInfo->estimatedCost = 1.0; - pIdxInfo->aConstraintUsage[jsonIdx].argvIndex = 1; - pIdxInfo->aConstraintUsage[jsonIdx].omit = 1; - if( rootIdx<0 ){ - pIdxInfo->idxNum = 1; + i = aIdx[0]; + pIdxInfo->aConstraintUsage[i].argvIndex = 1; + pIdxInfo->aConstraintUsage[i].omit = 1; + if( aIdx[1]<0 ){ + pIdxInfo->idxNum = 1; /* Only JSON supplied. Plan 1 */ }else{ - pIdxInfo->aConstraintUsage[rootIdx].argvIndex = 2; - pIdxInfo->aConstraintUsage[rootIdx].omit = 1; - pIdxInfo->idxNum = 3; + i = aIdx[1]; + pIdxInfo->aConstraintUsage[i].argvIndex = 2; + pIdxInfo->aConstraintUsage[i].omit = 1; + pIdxInfo->idxNum = 3; /* Both JSON and ROOT are supplied. Plan 3 */ } } return SQLITE_OK; @@ -177722,7 +178713,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; /* The methods of the json_tree virtual table. */ @@ -177749,7 +178741,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -181179,8 +182172,24 @@ return rc; } + +/* +** Return true if zName is the extension on one of the shadow tables used +** by this module. +*/ +static int rtreeShadowName(const char *zName){ + static const char *azName[] = { + "node", "parent", "rowid" + }; + unsigned int i; + for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ + if( sqlite3_stricmp(zName, azName[i])==0 ) return 1; + } + return 0; +} + static sqlite3_module rtreeModule = { - 2, /* iVersion */ + 3, /* iVersion */ rtreeCreate, /* xCreate - create a table */ rtreeConnect, /* xConnect - connect to an existing table */ rtreeBestIndex, /* xBestIndex - Determine search strategy */ @@ -181203,6 +182212,7 @@ rtreeSavepoint, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ + rtreeShadowName /* xShadowName */ }; static int rtreeSqlInit( @@ -182193,14 +183203,24 @@ ** ** encoding (1 byte) 0=big-endian, 1=little-endian ** nvertex (3 bytes) Number of vertexes as a big-endian integer +** +** Enough space is allocated for 4 coordinates, to work around over-zealous +** warnings coming from some compiler (notably, clang). In reality, the size +** of each GeoPoly memory allocate is adjusted as necessary so that the +** GeoPoly.a[] array at the end is the appropriate size. */ typedef struct GeoPoly GeoPoly; struct GeoPoly { int nVertex; /* Number of vertexes */ unsigned char hdr[4]; /* Header for on-disk representation */ - GeoCoord a[2]; /* 2*nVertex values. X (longitude) first, then Y */ + GeoCoord a[8]; /* 2*nVertex values. X (longitude) first, then Y */ }; +/* The size of a memory allocation needed for a GeoPoly object sufficient +** to hold N coordinate pairs. +*/ +#define GEOPOLY_SZ(N) (sizeof(GeoPoly) + sizeof(GeoCoord)*2*((N)-4)) + /* ** State of a parse of a GeoJSON input. */ @@ -182225,7 +183245,7 @@ /* Skip whitespace. Return the next non-whitespace character. */ static char geopolySkipSpace(GeoParse *p){ - while( p->z[0] && safe_isspace(p->z[0]) ) p->z++; + while( safe_isspace(p->z[0]) ) p->z++; return p->z[0]; } @@ -182245,7 +183265,7 @@ if( c=='0' && z[j+1]>='0' && z[j+1]<='9' ) return 0; for(;; j++){ c = z[j]; - if( c>='0' && c<='9' ) continue; + if( safe_isdigit(c) ) continue; if( c=='.' ){ if( z[j-1]=='-' ) return 0; if( seenDP ) return 0; @@ -182267,7 +183287,17 @@ break; } if( z[j-1]<'0' ) return 0; - if( pVal ) *pVal = (GeoCoord)atof((const char*)p->z); + if( pVal ){ +#ifdef SQLITE_AMALGAMATION + /* The sqlite3AtoF() routine is much much faster than atof(), if it + ** is available */ + double r; + (void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8); + *pVal = r; +#else + *pVal = (GeoCoord)atof((const char*)p->z); +#endif + } p->z += j; return 1; } @@ -182325,12 +183355,10 @@ && s.a[1]==s.a[s.nVertex*2-1] && (s.z++, geopolySkipSpace(&s)==0) ){ - int nByte; GeoPoly *pOut; int x = 1; s.nVertex--; /* Remove the redundant vertex at the end */ - nByte = sizeof(GeoPoly) * s.nVertex*2*sizeof(GeoCoord); - pOut = sqlite3_malloc64( nByte ); + pOut = sqlite3_malloc64( GEOPOLY_SZ(s.nVertex) ); x = 1; if( pOut==0 ) goto parse_json_err; pOut->nVertex = s.nVertex; @@ -182534,6 +183562,27 @@ } /* +** Compute the area enclosed by the polygon. +** +** This routine can also be used to detect polygons that rotate in +** the wrong direction. Polygons are suppose to be counter-clockwise (CCW). +** This routine returns a negative value for clockwise (CW) polygons. +*/ +static double geopolyArea(GeoPoly *p){ + double rArea = 0.0; + int ii; + for(ii=0; ii<p->nVertex-1; ii++){ + rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */ + * (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */ + * 0.5; + } + rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */ + * (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */ + * 0.5; + return rArea; +} + +/* ** Implementation of the geopoly_area(X) function. ** ** If the input is a well-formed Geopoly BLOB then return the area @@ -182548,22 +183597,107 @@ ){ GeoPoly *p = geopolyFuncParam(context, argv[0], 0); if( p ){ - double rArea = 0.0; - int ii; - for(ii=0; ii<p->nVertex-1; ii++){ - rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */ - * (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */ - * 0.5; - } - rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */ - * (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */ - * 0.5; - sqlite3_result_double(context, rArea); + sqlite3_result_double(context, geopolyArea(p)); sqlite3_free(p); } } /* +** Implementation of the geopoly_ccw(X) function. +** +** If the rotation of polygon X is clockwise (incorrect) instead of +** counter-clockwise (the correct winding order according to RFC7946) +** then reverse the order of the vertexes in polygon X. +** +** In other words, this routine returns a CCW polygon regardless of the +** winding order of its input. +** +** Use this routine to sanitize historical inputs that that sometimes +** contain polygons that wind in the wrong direction. +*/ +static void geopolyCcwFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + GeoPoly *p = geopolyFuncParam(context, argv[0], 0); + if( p ){ + if( geopolyArea(p)<0.0 ){ + int ii, jj; + for(ii=2, jj=p->nVertex*2 - 2; ii<jj; ii+=2, jj-=2){ + GeoCoord t = p->a[ii]; + p->a[ii] = p->a[jj]; + p->a[jj] = t; + t = p->a[ii+1]; + p->a[ii+1] = p->a[jj+1]; + p->a[jj+1] = t; + } + } + sqlite3_result_blob(context, p->hdr, + 4+8*p->nVertex, SQLITE_TRANSIENT); + sqlite3_free(p); + } +} + +#define GEOPOLY_PI 3.1415926535897932385 + +/* Fast approximation for sine(X) for X between -0.5*pi and 2*pi +*/ +static double geopolySine(double r){ + assert( r>=-0.5*GEOPOLY_PI && r<=2.0*GEOPOLY_PI ); + if( r>=1.5*GEOPOLY_PI ){ + r -= 2.0*GEOPOLY_PI; + } + if( r>=0.5*GEOPOLY_PI ){ + return -geopolySine(r-GEOPOLY_PI); + }else{ + double r2 = r*r; + double r3 = r2*r; + double r5 = r3*r2; + return 0.9996949*r - 0.1656700*r3 + 0.0075134*r5; + } +} + +/* +** Function: geopoly_regular(X,Y,R,N) +** +** Construct a simple, convex, regular polygon centered at X, Y +** with circumradius R and with N sides. +*/ +static void geopolyRegularFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + double x = sqlite3_value_double(argv[0]); + double y = sqlite3_value_double(argv[1]); + double r = sqlite3_value_double(argv[2]); + int n = sqlite3_value_int(argv[3]); + int i; + GeoPoly *p; + + if( n<3 || r<=0.0 ) return; + if( n>1000 ) n = 1000; + p = sqlite3_malloc64( sizeof(*p) + (n-1)*2*sizeof(GeoCoord) ); + if( p==0 ){ + sqlite3_result_error_nomem(context); + return; + } + i = 1; + p->hdr[0] = *(unsigned char*)&i; + p->hdr[1] = 0; + p->hdr[2] = (n>>8)&0xff; + p->hdr[3] = n&0xff; + for(i=0; i<n; i++){ + double rAngle = 2.0*GEOPOLY_PI*i/n; + p->a[i*2] = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI); + p->a[i*2+1] = y + r*geopolySine(rAngle); + } + sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT); + sqlite3_free(p); +} + +/* ** If pPoly is a polygon, compute its bounding box. Then: ** ** (1) if aCoord!=0 store the bounding box in aCoord, returning NULL @@ -182607,7 +183741,7 @@ if( pRc ) *pRc = SQLITE_OK; if( aCoord==0 ){ geopolyBboxFill: - pOut = sqlite3_realloc(p, sizeof(GeoPoly)+sizeof(GeoCoord)*6); + pOut = sqlite3_realloc(p, GEOPOLY_SZ(4)); if( pOut==0 ){ sqlite3_free(p); if( context ) sqlite3_result_error_nomem(context); @@ -183635,7 +184769,16 @@ if( sqlite3_value_nochange(aData[2]) ){ sqlite3_bind_null(pUp, 2); }else{ - sqlite3_bind_value(pUp, 2, aData[2]); + GeoPoly *p = 0; + if( sqlite3_value_type(aData[2])==SQLITE_TEXT + && (p = geopolyFuncParam(0, aData[2], &rc))!=0 + && rc==SQLITE_OK + ){ + sqlite3_bind_blob(pUp, 2, p->hdr, 4+8*p->nVertex, SQLITE_TRANSIENT); + }else{ + sqlite3_bind_value(pUp, 2, aData[2]); + } + sqlite3_free(p); nChange = 1; } for(jj=1; jj<pRtree->nAux; jj++){ @@ -183679,7 +184822,7 @@ static sqlite3_module geopolyModule = { - 2, /* iVersion */ + 3, /* iVersion */ geopolyCreate, /* xCreate - create a table */ geopolyConnect, /* xConnect - connect to an existing table */ geopolyBestIndex, /* xBestIndex - Determine search strategy */ @@ -183702,25 +184845,29 @@ rtreeSavepoint, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ + rtreeShadowName /* xShadowName */ }; static int sqlite3_geopoly_init(sqlite3 *db){ int rc = SQLITE_OK; static const struct { void (*xFunc)(sqlite3_context*,int,sqlite3_value**); - int nArg; + signed char nArg; + unsigned char bPure; const char *zName; } aFunc[] = { - { geopolyAreaFunc, 1, "geopoly_area" }, - { geopolyBlobFunc, 1, "geopoly_blob" }, - { geopolyJsonFunc, 1, "geopoly_json" }, - { geopolySvgFunc, -1, "geopoly_svg" }, - { geopolyWithinFunc, 2, "geopoly_within" }, - { geopolyContainsPointFunc, 3, "geopoly_contains_point" }, - { geopolyOverlapFunc, 2, "geopoly_overlap" }, - { geopolyDebugFunc, 1, "geopoly_debug" }, - { geopolyBBoxFunc, 1, "geopoly_bbox" }, - { geopolyXformFunc, 7, "geopoly_xform" }, + { geopolyAreaFunc, 1, 1, "geopoly_area" }, + { geopolyBlobFunc, 1, 1, "geopoly_blob" }, + { geopolyJsonFunc, 1, 1, "geopoly_json" }, + { geopolySvgFunc, -1, 1, "geopoly_svg" }, + { geopolyWithinFunc, 2, 1, "geopoly_within" }, + { geopolyContainsPointFunc, 3, 1, "geopoly_contains_point" }, + { geopolyOverlapFunc, 2, 1, "geopoly_overlap" }, + { geopolyDebugFunc, 1, 0, "geopoly_debug" }, + { geopolyBBoxFunc, 1, 1, "geopoly_bbox" }, + { geopolyXformFunc, 7, 1, "geopoly_xform" }, + { geopolyRegularFunc, 4, 1, "geopoly_regular" }, + { geopolyCcwFunc, 1, 1, "geopoly_ccw" }, }; static const struct { void (*xStep)(sqlite3_context*,int,sqlite3_value**); @@ -183731,8 +184878,9 @@ }; int i; for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){ + int enc = aFunc[i].bPure ? SQLITE_UTF8|SQLITE_DETERMINISTIC : SQLITE_UTF8; rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg, - SQLITE_UTF8, 0, + enc, 0, aFunc[i].xFunc, 0, 0); } for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){ @@ -185759,7 +186907,8 @@ sqlite3_vfs *pRealVfs; /* Underlying VFS */ sqlite3_mutex *mutex; /* Mutex to protect pMain */ sqlite3rbu *pRbu; /* Owner RBU object */ - rbu_file *pMain; /* Linked list of main db files */ + rbu_file *pMain; /* List of main db files */ + rbu_file *pMainRbu; /* List of main db files with pRbu!=0 */ }; /* @@ -185788,6 +186937,7 @@ const char *zWal; /* Wal filename for this main db file */ rbu_file *pWalFd; /* Wal file descriptor for this main db */ rbu_file *pMainNext; /* Next MAIN_DB file */ + rbu_file *pMainRbuNext; /* Next MAIN_DB file with pRbu!=0 */ }; /* @@ -189385,6 +190535,69 @@ } /* +** Add an item to the main-db lists, if it is not already present. +** +** There are two main-db lists. One for all file descriptors, and one +** for all file descriptors with rbu_file.pDb!=0. If the argument has +** rbu_file.pDb!=0, then it is assumed to already be present on the +** main list and is only added to the pDb!=0 list. +*/ +static void rbuMainlistAdd(rbu_file *p){ + rbu_vfs *pRbuVfs = p->pRbuVfs; + rbu_file *pIter; + assert( (p->openFlags & SQLITE_OPEN_MAIN_DB) ); + sqlite3_mutex_enter(pRbuVfs->mutex); + if( p->pRbu==0 ){ + for(pIter=pRbuVfs->pMain; pIter; pIter=pIter->pMainNext); + p->pMainNext = pRbuVfs->pMain; + pRbuVfs->pMain = p; + }else{ + for(pIter=pRbuVfs->pMainRbu; pIter && pIter!=p; pIter=pIter->pMainRbuNext){} + if( pIter==0 ){ + p->pMainRbuNext = pRbuVfs->pMainRbu; + pRbuVfs->pMainRbu = p; + } + } + sqlite3_mutex_leave(pRbuVfs->mutex); +} + +/* +** Remove an item from the main-db lists. +*/ +static void rbuMainlistRemove(rbu_file *p){ + rbu_file **pp; + sqlite3_mutex_enter(p->pRbuVfs->mutex); + for(pp=&p->pRbuVfs->pMain; *pp && *pp!=p; pp=&((*pp)->pMainNext)){} + if( *pp ) *pp = p->pMainNext; + p->pMainNext = 0; + for(pp=&p->pRbuVfs->pMainRbu; *pp && *pp!=p; pp=&((*pp)->pMainRbuNext)){} + if( *pp ) *pp = p->pMainRbuNext; + p->pMainRbuNext = 0; + sqlite3_mutex_leave(p->pRbuVfs->mutex); +} + +/* +** Given that zWal points to a buffer containing a wal file name passed to +** either the xOpen() or xAccess() VFS method, search the main-db list for +** a file-handle opened by the same database connection on the corresponding +** database file. +** +** If parameter bRbu is true, only search for file-descriptors with +** rbu_file.pDb!=0. +*/ +static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal, int bRbu){ + rbu_file *pDb; + sqlite3_mutex_enter(pRbuVfs->mutex); + if( bRbu ){ + for(pDb=pRbuVfs->pMainRbu; pDb && pDb->zWal!=zWal; pDb=pDb->pMainRbuNext){} + }else{ + for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){} + } + sqlite3_mutex_leave(pRbuVfs->mutex); + return pDb; +} + +/* ** Close an rbu file. */ static int rbuVfsClose(sqlite3_file *pFile){ @@ -189401,17 +190614,14 @@ sqlite3_free(p->zDel); if( p->openFlags & SQLITE_OPEN_MAIN_DB ){ - rbu_file **pp; - sqlite3_mutex_enter(p->pRbuVfs->mutex); - for(pp=&p->pRbuVfs->pMain; *pp!=p; pp=&((*pp)->pMainNext)); - *pp = p->pMainNext; - sqlite3_mutex_leave(p->pRbuVfs->mutex); + rbuMainlistRemove(p); rbuUnlockShm(p); p->pReal->pMethods->xShmUnmap(p->pReal, 0); } else if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){ rbuUpdateTempSize(p, 0); } + assert( p->pMainNext==0 && p->pRbuVfs->pMain!=p ); /* Close the underlying file handle */ rc = p->pReal->pMethods->xClose(p->pReal); @@ -189670,6 +190880,9 @@ }else if( rc==SQLITE_NOTFOUND ){ pRbu->pTargetFd = p; p->pRbu = pRbu; + if( p->openFlags & SQLITE_OPEN_MAIN_DB ){ + rbuMainlistAdd(p); + } if( p->pWalFd ) p->pWalFd->pRbu = pRbu; rc = SQLITE_OK; } @@ -189832,20 +191045,6 @@ } /* -** Given that zWal points to a buffer containing a wal file name passed to -** either the xOpen() or xAccess() VFS method, return a pointer to the -** file-handle opened by the same database connection on the corresponding -** database file. -*/ -static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal){ - rbu_file *pDb; - sqlite3_mutex_enter(pRbuVfs->mutex); - for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){} - sqlite3_mutex_leave(pRbuVfs->mutex); - return pDb; -} - -/* ** A main database named zName has just been opened. The following ** function returns a pointer to a buffer owned by SQLite that contains ** the name of the *-wal file this db connection will use. SQLite @@ -189923,7 +191122,7 @@ pFd->zWal = rbuMainToWal(zName, flags); } else if( flags & SQLITE_OPEN_WAL ){ - rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName); + rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0); if( pDb ){ if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){ /* This call is to open a *-wal file. Intead, open the *-oal. This @@ -189975,10 +191174,7 @@ ** mutex protected linked list of all such files. */ pFile->pMethods = &rbuvfs_io_methods; if( flags & SQLITE_OPEN_MAIN_DB ){ - sqlite3_mutex_enter(pRbuVfs->mutex); - pFd->pMainNext = pRbuVfs->pMain; - pRbuVfs->pMain = pFd; - sqlite3_mutex_leave(pRbuVfs->mutex); + rbuMainlistAdd(pFd); } }else{ sqlite3_free(pFd->zDel); @@ -190026,7 +191222,7 @@ ** file opened instead. */ if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){ - rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath); + rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath, 1); if( pDb && pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){ if( *pResOut ){ rc = SQLITE_CANTOPEN; @@ -190439,17 +191635,15 @@ static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ int i; - pIdxInfo->estimatedCost = 1.0e6; /* Initial cost estimate */ - /* Look for a valid schema=? constraint. If found, change the idxNum to ** 1 and request the value of that constraint be sent to xFilter. And ** lower the cost estimate to encourage the constrained version to be ** used. */ for(i=0; i<pIdxInfo->nConstraint; i++){ - if( pIdxInfo->aConstraint[i].usable==0 ) continue; - if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; if( pIdxInfo->aConstraint[i].iColumn!=10 ) continue; + if( pIdxInfo->aConstraint[i].usable==0 ) return SQLITE_CONSTRAINT; + if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; pIdxInfo->idxNum = 1; pIdxInfo->estimatedCost = 1.0; pIdxInfo->aConstraintUsage[i].argvIndex = 1; @@ -190499,7 +191693,7 @@ return SQLITE_OK; } -static void statClearPage(StatPage *p){ +static void statClearCells(StatPage *p){ int i; if( p->aCell ){ for(i=0; i<p->nCell; i++){ @@ -190507,6 +191701,12 @@ } sqlite3_free(p->aCell); } + p->nCell = 0; + p->aCell = 0; +} + +static void statClearPage(StatPage *p){ + statClearCells(p); sqlite3PagerUnref(p->pPg); sqlite3_free(p->zPath); memset(p, 0, sizeof(StatPage)); @@ -190569,22 +191769,33 @@ u8 *aHdr = &aData[p->iPgno==1 ? 100 : 0]; p->flags = aHdr[0]; + if( p->flags==0x0A || p->flags==0x0D ){ + isLeaf = 1; + nHdr = 8; + }else if( p->flags==0x05 || p->flags==0x02 ){ + isLeaf = 0; + nHdr = 12; + }else{ + goto statPageIsCorrupt; + } + if( p->iPgno==1 ) nHdr += 100; p->nCell = get2byte(&aHdr[3]); p->nMxPayload = 0; - - isLeaf = (p->flags==0x0A || p->flags==0x0D); - nHdr = 12 - isLeaf*4 + (p->iPgno==1)*100; + szPage = sqlite3BtreeGetPageSize(pBt); nUnused = get2byte(&aHdr[5]) - nHdr - 2*p->nCell; nUnused += (int)aHdr[7]; iOff = get2byte(&aHdr[1]); while( iOff ){ + int iNext; + if( iOff>=szPage ) goto statPageIsCorrupt; nUnused += get2byte(&aData[iOff+2]); - iOff = get2byte(&aData[iOff]); + iNext = get2byte(&aData[iOff]); + if( iNext<iOff+4 && iNext>0 ) goto statPageIsCorrupt; + iOff = iNext; } p->nUnused = nUnused; p->iRightChildPg = isLeaf ? 0 : sqlite3Get4byte(&aHdr[8]); - szPage = sqlite3BtreeGetPageSize(pBt); if( p->nCell ){ int i; /* Used to iterate through cells */ @@ -190601,6 +191812,7 @@ StatCell *pCell = &p->aCell[i]; iOff = get2byte(&aData[nHdr+i*2]); + if( iOff<nHdr || iOff>=szPage ) goto statPageIsCorrupt; if( !isLeaf ){ pCell->iChildPg = sqlite3Get4byte(&aData[iOff]); iOff += 4; @@ -190617,13 +191829,14 @@ } if( nPayload>(u32)p->nMxPayload ) p->nMxPayload = nPayload; getLocalPayload(nUsable, p->flags, nPayload, &nLocal); + if( nLocal<0 ) goto statPageIsCorrupt; pCell->nLocal = nLocal; - assert( nLocal>=0 ); assert( nPayload>=(u32)nLocal ); assert( nLocal<=(nUsable-35) ); if( nPayload>(u32)nLocal ){ int j; int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4); + if( iOff+nLocal>nUsable ) goto statPageIsCorrupt; pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4); pCell->nOvfl = nOvfl; pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl); @@ -190647,6 +191860,11 @@ } return SQLITE_OK; + +statPageIsCorrupt: + p->flags = 0; + statClearCells(p); + return SQLITE_OK; } /* @@ -190942,6 +192160,7 @@ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ + 0 /* xShadowName */ }; return sqlite3_create_module(db, "dbstat", &dbstat_module, 0); } @@ -191072,9 +192291,8 @@ if( p->iColumn!=DBPAGE_COLUMN_SCHEMA ) continue; if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; if( !p->usable ){ - /* No solution. Use the default SQLITE_BIG_DBL cost */ - pIdxInfo->estimatedRows = 0x7fffffff; - return SQLITE_OK; + /* No solution. */ + return SQLITE_CONSTRAINT; } iPlan = 2; pIdxInfo->aConstraintUsage[i].argvIndex = 1; @@ -191266,6 +192484,10 @@ Pager *pPager; int szPage; + if( pTab->db->flags & SQLITE_Defensive ){ + zErr = "read-only"; + goto update_fail; + } if( argc==1 ){ zErr = "cannot delete"; goto update_fail; @@ -191356,6 +192578,7 @@ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ + 0 /* xShadowName */ }; return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0); } @@ -191392,6 +192615,8 @@ # endif #endif +static int sessions_strm_chunk_size = SESSIONS_STRM_CHUNK_SIZE; + typedef struct SessionHook SessionHook; struct SessionHook { void *pCtx; @@ -191454,6 +192679,7 @@ SessionInput in; /* Input buffer or stream */ SessionBuffer tblhdr; /* Buffer to hold apValue/zTab/abPK/ */ int bPatchset; /* True if this is a patchset */ + int bInvert; /* True to invert changeset */ int rc; /* Iterator error code */ sqlite3_stmt *pConflict; /* Points to conflicting row, if any */ char *zTab; /* Current table */ @@ -191610,6 +192836,42 @@ ** The records associated with INSERT changes are in the same format as for ** changesets. It is not possible for a record associated with an INSERT ** change to contain a field set to "undefined". +** +** REBASE BLOB FORMAT: +** +** A rebase blob may be output by sqlite3changeset_apply_v2() and its +** streaming equivalent for use with the sqlite3_rebaser APIs to rebase +** existing changesets. A rebase blob contains one entry for each conflict +** resolved using either the OMIT or REPLACE strategies within the apply_v2() +** call. +** +** The format used for a rebase blob is very similar to that used for +** changesets. All entries related to a single table are grouped together. +** +** Each group of entries begins with a table header in changeset format: +** +** 1 byte: Constant 0x54 (capital 'T') +** Varint: Number of columns in the table. +** nCol bytes: 0x01 for PK columns, 0x00 otherwise. +** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated. +** +** Followed by one or more entries associated with the table. +** +** 1 byte: Either SQLITE_INSERT (0x12), DELETE (0x09). +** 1 byte: Flag. 0x01 for REPLACE, 0x00 for OMIT. +** record: (in the record format defined above). +** +** In a rebase blob, the first field is set to SQLITE_INSERT if the change +** that caused the conflict was an INSERT or UPDATE, or to SQLITE_DELETE if +** it was a DELETE. The second field is set to 0x01 if the conflict +** resolution strategy was REPLACE, or 0x00 if it was OMIT. +** +** If the change that caused the conflict was a DELETE, then the single +** record is a copy of the old.* record from the original changeset. If it +** was an INSERT, then the single record is a copy of the new.* record. If +** the conflicting change was an UPDATE, then the single record is a copy +** of the new.* record with the PK fields filled in based on the original +** old.* record. */ /* @@ -193160,12 +194422,12 @@ static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){ if( *pRc==SQLITE_OK && p->nAlloc-p->nBuf<nByte ){ u8 *aNew; - int nNew = p->nAlloc ? p->nAlloc : 128; + i64 nNew = p->nAlloc ? p->nAlloc : 128; do { nNew = nNew*2; - }while( nNew<(p->nBuf+nByte) ); + }while( (nNew-p->nBuf)<nByte ); - aNew = (u8 *)sqlite3_realloc(p->aBuf, nNew); + aNew = (u8 *)sqlite3_realloc64(p->aBuf, nNew); if( 0==aNew ){ *pRc = SQLITE_NOMEM; }else{ @@ -193763,12 +195025,12 @@ rc = sqlite3_reset(pSel); } - /* If the buffer is now larger than SESSIONS_STRM_CHUNK_SIZE, pass + /* If the buffer is now larger than sessions_strm_chunk_size, pass ** its contents to the xOutput() callback. */ if( xOutput && rc==SQLITE_OK && buf.nBuf>nNoop - && buf.nBuf>SESSIONS_STRM_CHUNK_SIZE + && buf.nBuf>sessions_strm_chunk_size ){ rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf); nNoop = -1; @@ -193907,7 +195169,8 @@ int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn, int nChangeset, /* Size of buffer pChangeset in bytes */ - void *pChangeset /* Pointer to buffer containing changeset */ + void *pChangeset, /* Pointer to buffer containing changeset */ + int bInvert /* True to invert changeset */ ){ sqlite3_changeset_iter *pRet; /* Iterator to return */ int nByte; /* Number of bytes to allocate for iterator */ @@ -193927,6 +195190,7 @@ pRet->in.xInput = xInput; pRet->in.pIn = pIn; pRet->in.bEof = (xInput ? 0 : 1); + pRet->bInvert = bInvert; /* Populate the output variable and return success. */ *pp = pRet; @@ -193941,7 +195205,16 @@ int nChangeset, /* Size of buffer pChangeset in bytes */ void *pChangeset /* Pointer to buffer containing changeset */ ){ - return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset); + return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0); +} +SQLITE_API int sqlite3changeset_start_v2( + sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ + int nChangeset, /* Size of buffer pChangeset in bytes */ + void *pChangeset, /* Pointer to buffer containing changeset */ + int flags +){ + int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT); + return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, bInvert); } /* @@ -193952,7 +195225,16 @@ int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ){ - return sessionChangesetStart(pp, xInput, pIn, 0, 0); + return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0); +} +SQLITE_API int sqlite3changeset_start_v2_strm( + sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int flags +){ + int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT); + return sessionChangesetStart(pp, xInput, pIn, 0, 0, bInvert); } /* @@ -193960,7 +195242,7 @@ ** object and the buffer is full, discard some data to free up space. */ static void sessionDiscardData(SessionInput *pIn){ - if( pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){ + if( pIn->xInput && pIn->iNext>=sessions_strm_chunk_size ){ int nMove = pIn->buf.nBuf - pIn->iNext; assert( nMove>=0 ); if( nMove>0 ){ @@ -193983,7 +195265,7 @@ int rc = SQLITE_OK; if( pIn->xInput ){ while( !pIn->bEof && (pIn->iNext+nByte)>=pIn->nData && rc==SQLITE_OK ){ - int nNew = SESSIONS_STRM_CHUNK_SIZE; + int nNew = sessions_strm_chunk_size; if( pIn->bNoDiscard==0 ) sessionDiscardData(pIn); if( SQLITE_OK==sessionBufferGrow(&pIn->buf, nNew, &rc) ){ @@ -194331,10 +195613,10 @@ op = p->in.aData[p->in.iNext++]; } - if( p->zTab==0 ){ + if( p->zTab==0 || (p->bPatchset && p->bInvert) ){ /* The first record in the changeset is not a table header. Must be a ** corrupt changeset. */ - assert( p->in.iNext==1 ); + assert( p->in.iNext==1 || p->zTab ); return (p->rc = SQLITE_CORRUPT_BKPT); } @@ -194359,33 +195641,39 @@ *paRec = &p->in.aData[p->in.iNext]; p->in.iNext += *pnRec; }else{ + sqlite3_value **apOld = (p->bInvert ? &p->apValue[p->nCol] : p->apValue); + sqlite3_value **apNew = (p->bInvert ? p->apValue : &p->apValue[p->nCol]); /* If this is an UPDATE or DELETE, read the old.* record. */ if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){ u8 *abPK = p->bPatchset ? p->abPK : 0; - p->rc = sessionReadRecord(&p->in, p->nCol, abPK, p->apValue); + p->rc = sessionReadRecord(&p->in, p->nCol, abPK, apOld); if( p->rc!=SQLITE_OK ) return p->rc; } /* If this is an INSERT or UPDATE, read the new.* record. */ if( p->op!=SQLITE_DELETE ){ - p->rc = sessionReadRecord(&p->in, p->nCol, 0, &p->apValue[p->nCol]); + p->rc = sessionReadRecord(&p->in, p->nCol, 0, apNew); if( p->rc!=SQLITE_OK ) return p->rc; } - if( p->bPatchset && p->op==SQLITE_UPDATE ){ + if( (p->bPatchset || p->bInvert) && p->op==SQLITE_UPDATE ){ /* If this is an UPDATE that is part of a patchset, then all PK and ** modified fields are present in the new.* record. The old.* record ** is currently completely empty. This block shifts the PK fields from ** new.* to old.*, to accommodate the code that reads these arrays. */ for(i=0; i<p->nCol; i++){ - assert( p->apValue[i]==0 ); + assert( p->bPatchset==0 || p->apValue[i]==0 ); if( p->abPK[i] ){ + assert( p->apValue[i]==0 ); p->apValue[i] = p->apValue[i+p->nCol]; if( p->apValue[i]==0 ) return (p->rc = SQLITE_CORRUPT_BKPT); p->apValue[i+p->nCol] = 0; } } + }else if( p->bInvert ){ + if( p->op==SQLITE_INSERT ) p->op = SQLITE_DELETE; + else if( p->op==SQLITE_DELETE ) p->op = SQLITE_INSERT; } } @@ -194702,7 +195990,7 @@ } assert( rc==SQLITE_OK ); - if( xOutput && sOut.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ + if( xOutput && sOut.nBuf>=sessions_strm_chunk_size ){ rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); sOut.nBuf = 0; if( rc!=SQLITE_OK ) goto finished_invert; @@ -194781,7 +196069,8 @@ int bDeferConstraints; /* True to defer constraints */ SessionBuffer constraints; /* Deferred constraints are stored here */ SessionBuffer rebase; /* Rebase information (if any) here */ - int bRebaseStarted; /* If table header is already in rebase */ + u8 bRebaseStarted; /* If table header is already in rebase */ + u8 bRebase; /* True to collect rebase information */ }; /* @@ -195178,35 +196467,36 @@ sqlite3_changeset_iter *pIter /* Iterator pointing at current change */ ){ int rc = SQLITE_OK; - int i; - int eOp = pIter->op; - if( p->bRebaseStarted==0 ){ - /* Append a table-header to the rebase buffer */ - const char *zTab = pIter->zTab; - sessionAppendByte(&p->rebase, 'T', &rc); - sessionAppendVarint(&p->rebase, p->nCol, &rc); - sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc); - sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc); - p->bRebaseStarted = 1; - } - - assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT ); - assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE ); - - sessionAppendByte(&p->rebase, - (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc - ); - sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc); - for(i=0; i<p->nCol; i++){ - sqlite3_value *pVal = 0; - if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){ - sqlite3changeset_old(pIter, i, &pVal); - }else{ - sqlite3changeset_new(pIter, i, &pVal); + if( p->bRebase ){ + int i; + int eOp = pIter->op; + if( p->bRebaseStarted==0 ){ + /* Append a table-header to the rebase buffer */ + const char *zTab = pIter->zTab; + sessionAppendByte(&p->rebase, 'T', &rc); + sessionAppendVarint(&p->rebase, p->nCol, &rc); + sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc); + sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc); + p->bRebaseStarted = 1; } - sessionAppendValue(&p->rebase, pVal, &rc); - } + assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT ); + assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE ); + + sessionAppendByte(&p->rebase, + (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc + ); + sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc); + for(i=0; i<p->nCol; i++){ + sqlite3_value *pVal = 0; + if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){ + sqlite3changeset_old(pIter, i, &pVal); + }else{ + sqlite3changeset_new(pIter, i, &pVal); + } + sessionAppendValue(&p->rebase, pVal, &rc); + } + } return rc; } @@ -195549,7 +196839,7 @@ SessionBuffer cons = pApply->constraints; memset(&pApply->constraints, 0, sizeof(SessionBuffer)); - rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf); + rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf, 0); if( rc==SQLITE_OK ){ int nByte = 2*pApply->nCol*sizeof(sqlite3_value*); int rc2; @@ -195615,6 +196905,7 @@ pIter->in.bNoDiscard = 1; memset(&sApply, 0, sizeof(sApply)); + sApply.bRebase = (ppRebase && pnRebase); sqlite3_mutex_enter(sqlite3_db_mutex(db)); if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){ rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); @@ -195765,7 +197056,8 @@ } } - if( rc==SQLITE_OK && bPatchset==0 && ppRebase && pnRebase ){ + assert( sApply.bRebase || sApply.rebase.nBuf==0 ); + if( rc==SQLITE_OK && bPatchset==0 && sApply.bRebase ){ *ppRebase = (void*)sApply.rebase.aBuf; *pnRebase = sApply.rebase.nBuf; sApply.rebase.aBuf = 0; @@ -195803,7 +197095,8 @@ int flags ){ sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ - int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); + int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); + int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset,bInverse); if( rc==SQLITE_OK ){ rc = sessionChangesetApply( db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags @@ -195860,7 +197153,8 @@ int flags ){ sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ - int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); + int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); + int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse); if( rc==SQLITE_OK ){ rc = sessionChangesetApply( db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags @@ -196233,13 +197527,12 @@ sessionAppendByte(&buf, p->op, &rc); sessionAppendByte(&buf, p->bIndirect, &rc); sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); + if( rc==SQLITE_OK && xOutput && buf.nBuf>=sessions_strm_chunk_size ){ + rc = xOutput(pOut, buf.aBuf, buf.nBuf); + buf.nBuf = 0; + } } } - - if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ - rc = xOutput(pOut, buf.aBuf, buf.nBuf); - buf.nBuf = 0; - } } if( rc==SQLITE_OK ){ @@ -196630,7 +197923,7 @@ sessionAppendByte(&sOut, pIter->bIndirect, &rc); sessionAppendBlob(&sOut, aRec, nRec, &rc); } - if( rc==SQLITE_OK && xOutput && sOut.nBuf>SESSIONS_STRM_CHUNK_SIZE ){ + if( rc==SQLITE_OK && xOutput && sOut.nBuf>sessions_strm_chunk_size ){ rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); sOut.nBuf = 0; } @@ -196741,6 +198034,27 @@ } } +/* +** Global configuration +*/ +SQLITE_API int sqlite3session_config(int op, void *pArg){ + int rc = SQLITE_OK; + switch( op ){ + case SQLITE_SESSION_CONFIG_STRMSIZE: { + int *pInt = (int*)pArg; + if( *pInt>0 ){ + sessions_strm_chunk_size = *pInt; + } + *pInt = sessions_strm_chunk_size; + break; + } + default: + rc = SQLITE_MISUSE; + break; + } + return rc; +} + #endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ /************** End of sqlite3session.c **************************************/ @@ -198175,6 +199489,7 @@ ** input grammar file: */ /* #include <stdio.h> */ +/* #include <assert.h> */ /************ Begin %include sections from the grammar ************************/ /* #include "fts5Int.h" */ @@ -199497,10 +200812,9 @@ fts5yymajor = fts5YYNOCODE; }else{ while( fts5yypParser->fts5yytos >= fts5yypParser->fts5yystack - && fts5yymx != fts5YYERRORSYMBOL && (fts5yyact = fts5yy_find_reduce_action( fts5yypParser->fts5yytos->stateno, - fts5YYERRORSYMBOL)) >= fts5YY_MIN_REDUCE + fts5YYERRORSYMBOL)) > fts5YY_MAX_SHIFTREDUCE ){ fts5yy_pop_parser_stack(fts5yypParser); } @@ -210450,7 +211764,7 @@ fts5CloseReader(p); } - *ppIter = &pRet->base; + *ppIter = (Fts5IndexIter*)pRet; sqlite3Fts5BufferFree(&buf); } return fts5IndexReturn(p); @@ -214199,12 +215513,27 @@ ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2018-11-05 20:37:38 89e099fbe5e13c33e683bef07361231ca525b88f7907be7092058007b75036f2", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238b4f9", -1, SQLITE_TRANSIENT); +} + +/* +** Return true if zName is the extension on one of the shadow tables used +** by this module. +*/ +static int fts5ShadowName(const char *zName){ + static const char *azName[] = { + "config", "content", "data", "docsize", "idx" + }; + unsigned int i; + for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ + if( sqlite3_stricmp(zName, azName[i])==0 ) return 1; + } + return 0; } static int fts5Init(sqlite3 *db){ static const sqlite3_module fts5Mod = { - /* iVersion */ 2, + /* iVersion */ 3, /* xCreate */ fts5CreateMethod, /* xConnect */ fts5ConnectMethod, /* xBestIndex */ fts5BestIndexMethod, @@ -214227,6 +215556,7 @@ /* xSavepoint */ fts5SavepointMethod, /* xRelease */ fts5ReleaseMethod, /* xRollbackTo */ fts5RollbackToMethod, + /* xShadowName */ fts5ShadowName }; int rc; @@ -218271,6 +219601,8 @@ i64 *pp = &pCsr->iInstPos; int *po = &pCsr->iInstOff; + assert( sqlite3Fts5IterEof(pIter)==0 ); + assert( pCsr->bEof==0 ); while( eDetail==FTS5_DETAIL_NONE || sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp) ){ @@ -218280,7 +219612,7 @@ rc = sqlite3Fts5IterNextScan(pCsr->pIter); if( rc==SQLITE_OK ){ rc = fts5VocabInstanceNewTerm(pCsr); - if( eDetail==FTS5_DETAIL_NONE ) break; + if( pCsr->bEof || eDetail==FTS5_DETAIL_NONE ) break; } if( rc ){ pCsr->bEof = 1; @@ -218595,6 +219927,7 @@ /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, + /* xShadowName */ 0 }; void *p = (void*)pGlobal; @@ -218603,8 +219936,6 @@ - - #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) */ /************** End of fts5.c ************************************************/ @@ -218877,6 +220208,7 @@ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ + 0, /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -218909,9 +220241,9 @@ #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ -#if __LINE__!=218912 +#if __LINE__!=220244 #undef SQLITE_SOURCE_ID -#define SQLITE_SOURCE_ID "2018-11-05 20:37:38 89e099fbe5e13c33e683bef07361231ca525b88f7907be7092058007b750alt2" +#define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238alt2" #endif /* Return the source-id for this library */ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
diff --git a/third_party/sqlite/amalgamation/sqlite3.h b/third_party/sqlite/amalgamation/sqlite3.h index 165bd8a2..fe53843 100644 --- a/third_party/sqlite/amalgamation/sqlite3.h +++ b/third_party/sqlite/amalgamation/sqlite3.h
@@ -123,9 +123,9 @@ ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.25.3" -#define SQLITE_VERSION_NUMBER 3025003 -#define SQLITE_SOURCE_ID "2018-11-05 20:37:38 89e099fbe5e13c33e683bef07361231ca525b88f7907be7092058007b750alt1" +#define SQLITE_VERSION "3.26.0" +#define SQLITE_VERSION_NUMBER 3026000 +#define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238alt1" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -2017,6 +2017,7 @@ ** is invoked. ** ** <dl> +** [[SQLITE_DBCONFIG_LOOKASIDE]] ** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt> ** <dd> ^This option takes three additional arguments that determine the ** [lookaside memory allocator] configuration for the [database connection]. @@ -2039,6 +2040,7 @@ ** memory is in use leaves the configuration unchanged and returns ** [SQLITE_BUSY].)^</dd> ** +** [[SQLITE_DBCONFIG_ENABLE_FKEY]] ** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt> ** <dd> ^This option is used to enable or disable the enforcement of ** [foreign key constraints]. There should be two additional arguments. @@ -2049,6 +2051,7 @@ ** following this call. The second parameter may be a NULL pointer, in ** which case the FK enforcement setting is not reported back. </dd> ** +** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]] ** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt> ** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers]. ** There should be two additional arguments. @@ -2059,6 +2062,7 @@ ** following this call. The second parameter may be a NULL pointer, in ** which case the trigger setting is not reported back. </dd> ** +** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt> ** <dd> ^This option is used to enable or disable the two-argument ** version of the [fts3_tokenizer()] function which is part of the @@ -2072,6 +2076,7 @@ ** following this call. The second parameter may be a NULL pointer, in ** which case the new setting is not reported back. </dd> ** +** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]] ** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt> ** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()] ** interface independently of the [load_extension()] SQL function. @@ -2089,7 +2094,7 @@ ** be a NULL pointer, in which case the new setting is not reported back. ** </dd> ** -** <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> +** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> ** <dd> ^This option is used to change the name of the "main" database ** schema. ^The sole argument is a pointer to a constant UTF8 string ** which will become the new schema name in place of "main". ^SQLite @@ -2098,6 +2103,7 @@ ** until after the database connection closes. ** </dd> ** +** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]] ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> ** <dd> Usually, when a database in wal mode is closed or detached from a ** database handle, SQLite checks if this will mean that there are now no @@ -2111,7 +2117,7 @@ ** have been disabled - 0 if they are not disabled, 1 if they are. ** </dd> ** -** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> +** [[SQLITE_DBCONFIG_ENABLE_QPSG]] <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> ** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates ** the [query planner stability guarantee] (QPSG). When the QPSG is active, ** a single SQL query statement will always use the same algorithm regardless @@ -2127,7 +2133,7 @@ ** following this call. ** </dd> ** -** <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt> +** [[SQLITE_DBCONFIG_TRIGGER_EQP]] <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt> ** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not ** include output for any operations performed by trigger programs. This ** option is used to set or clear (the default) a flag that governs this @@ -2139,7 +2145,7 @@ ** it is not disabled, 1 if it is. ** </dd> ** -** <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt> +** [[SQLITE_DBCONFIG_RESET_DATABASE]] <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt> ** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run ** [VACUUM] in order to reset a database back to an empty database ** with no schema and no content. The following process works even for @@ -2158,6 +2164,18 @@ ** Because resetting a database is destructive and irreversible, the ** process requires the use of this obscure API and multiple steps to help ** ensure that it does not happen by accident. +** +** [[SQLITE_DBCONFIG_DEFENSIVE]] <dt>SQLITE_DBCONFIG_DEFENSIVE</dt> +** <dd>The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the +** "defensive" flag for a database connection. When the defensive +** flag is enabled, language features that allow ordinary SQL to +** deliberately corrupt the database file are disabled. The disabled +** features include but are not limited to the following: +** <ul> +** <li> The [PRAGMA writable_schema=ON] statement. +** <li> Writes to the [sqlite_dbpage] virtual table. +** <li> Direct writes to [shadow tables]. +** </ul> ** </dd> ** </dl> */ @@ -2171,7 +2189,8 @@ #define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */ #define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */ #define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ -#define SQLITE_DBCONFIG_MAX 1009 /* Largest DBCONFIG */ +#define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */ +#define SQLITE_DBCONFIG_MAX 1010 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes @@ -3609,9 +3628,19 @@ ** on this hint by avoiding the use of [lookaside memory] so as not to ** deplete the limited store of lookaside memory. Future versions of ** SQLite may act on this hint differently. +** +** [[SQLITE_PREPARE_NORMALIZE]] ^(<dt>SQLITE_PREPARE_NORMALIZE</dt> +** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized +** representation of the SQL statement should be calculated and then +** associated with the prepared statement, which can be obtained via +** the [sqlite3_normalized_sql()] interface.)^ The semantics used to +** normalize a SQL statement are unspecified and subject to change. +** At a minimum, literal values will be replaced with suitable +** placeholders. ** </dl> */ #define SQLITE_PREPARE_PERSISTENT 0x01 +#define SQLITE_PREPARE_NORMALIZE 0x02 /* ** CAPI3REF: Compiling An SQL Statement @@ -3769,6 +3798,11 @@ ** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8 ** string containing the SQL text of prepared statement P with ** [bound parameters] expanded. +** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8 +** string containing the normalized SQL text of prepared statement P. The +** semantics used to normalize a SQL statement are unspecified and subject +** to change. At a minimum, literal values will be replaced with suitable +** placeholders. ** ** ^(For example, if a prepared statement is created using the SQL ** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 @@ -3784,14 +3818,16 @@ ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time ** option causes sqlite3_expanded_sql() to always return NULL. ** -** ^The string returned by sqlite3_sql(P) is managed by SQLite and is -** automatically freed when the prepared statement is finalized. +** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P) +** are managed by SQLite and are automatically freed when the prepared +** statement is finalized. ** ^The string returned by sqlite3_expanded_sql(P), on the other hand, ** is obtained from [sqlite3_malloc()] and must be free by the application ** by passing it to [sqlite3_free()]. */ SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); +SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If An SQL Statement Writes The Database @@ -6281,6 +6317,9 @@ int (*xSavepoint)(sqlite3_vtab *pVTab, int); int (*xRelease)(sqlite3_vtab *pVTab, int); int (*xRollbackTo)(sqlite3_vtab *pVTab, int); + /* The methods above are in versions 1 and 2 of the sqlite_module object. + ** Those below are for version 3 and greater. */ + int (*xShadowName)(const char*); }; /* @@ -7203,6 +7242,7 @@ #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ +#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 @@ -8638,6 +8678,7 @@ ** can use to customize and optimize their behavior. ** ** <dl> +** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]] ** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT ** <dd>Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, @@ -9407,7 +9448,7 @@ sqlite3_int64 iRowid; /* Rowid for current entry */ sqlite3_rtree_dbl rParentScore; /* Score of parent node */ int eParentWithin; /* Visibility of parent node */ - int eWithin; /* OUT: Visiblity */ + int eWithin; /* OUT: Visibility */ sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ /* The following fields are only available in 3.8.11 and later */ sqlite3_value **apSqlParam; /* Original SQL values of parameters */ @@ -9903,12 +9944,38 @@ ** consecutively. There is no chance that the iterator will visit a change ** the applies to table X, then one for table Y, and then later on visit ** another change for table X. +** +** The behavior of sqlite3changeset_start_v2() and its streaming equivalent +** may be modified by passing a combination of +** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter. +** +** Note that the sqlite3changeset_start_v2() API is still <b>experimental</b> +** and therefore subject to change. */ SQLITE_API int sqlite3changeset_start( sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ int nChangeset, /* Size of changeset blob in bytes */ void *pChangeset /* Pointer to blob containing changeset */ ); +SQLITE_API int sqlite3changeset_start_v2( + sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ + int nChangeset, /* Size of changeset blob in bytes */ + void *pChangeset, /* Pointer to blob containing changeset */ + int flags /* SESSION_CHANGESETSTART_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3changeset_start_v2 +** +** The following flags may passed via the 4th parameter to +** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]: +** +** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd> +** Invert the changeset while iterating through it. This is equivalent to +** inverting a changeset using sqlite3changeset_invert() before applying it. +** It is an error to specify this flag with a patchset. +*/ +#define SQLITE_CHANGESETSTART_INVERT 0x0002 /* @@ -10563,7 +10630,7 @@ ), void *pCtx, /* First argument passed to xConflict */ void **ppRebase, int *pnRebase, /* OUT: Rebase data */ - int flags /* Combination of SESSION_APPLY_* flags */ + int flags /* SESSION_CHANGESETAPPLY_* flags */ ); /* @@ -10581,8 +10648,14 @@ ** causes the sessions module to omit this savepoint. In this case, if the ** caller has an open transaction or savepoint when apply_v2() is called, ** it may revert the partially applied changeset by rolling it back. +** +** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd> +** Invert the changeset before applying it. This is equivalent to inverting +** a changeset using sqlite3changeset_invert() before applying it. It is +** an error to specify this flag with a patchset. */ #define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 +#define SQLITE_CHANGESETAPPLY_INVERT 0x0002 /* ** CAPI3REF: Constants Passed To The Conflict Handler @@ -10976,6 +11049,12 @@ int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); +SQLITE_API int sqlite3changeset_start_v2_strm( + sqlite3_changeset_iter **pp, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int flags +); SQLITE_API int sqlite3session_changeset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), @@ -11002,6 +11081,45 @@ void *pOut ); +/* +** CAPI3REF: Configure global parameters +** +** The sqlite3session_config() interface is used to make global configuration +** changes to the sessions module in order to tune it to the specific needs +** of the application. +** +** The sqlite3session_config() interface is not threadsafe. If it is invoked +** while any other thread is inside any other sessions method then the +** results are undefined. Furthermore, if it is invoked after any sessions +** related objects have been created, the results are also undefined. +** +** The first argument to the sqlite3session_config() function must be one +** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The +** interpretation of the (void*) value passed as the second parameter and +** the effect of calling this function depends on the value of the first +** parameter. +** +** <dl> +** <dt>SQLITE_SESSION_CONFIG_STRMSIZE<dd> +** By default, the sessions module streaming interfaces attempt to input +** and output data in approximately 1 KiB chunks. This operand may be used +** to set and query the value of this configuration setting. The pointer +** passed as the second argument must point to a value of type (int). +** If this value is greater than 0, it is used as the new streaming data +** chunk size for both input and output. Before returning, the (int) value +** pointed to by pArg is set to the final value of the streaming interface +** chunk size. +** </dl> +** +** This function returns SQLITE_OK if successful, or an SQLite error code +** otherwise. +*/ +SQLITE_API int sqlite3session_config(int op, void *pArg); + +/* +** CAPI3REF: Values for sqlite3session_config(). +*/ +#define SQLITE_SESSION_CONFIG_STRMSIZE 1 /* ** Make sure we can call this stuff from C++.
diff --git a/third_party/sqlite/fuzz/db_corpus/dbfuzz2-seed1.db b/third_party/sqlite/fuzz/db_corpus/dbfuzz2-seed1.db new file mode 100644 index 0000000..17f0550 --- /dev/null +++ b/third_party/sqlite/fuzz/db_corpus/dbfuzz2-seed1.db Binary files differ
diff --git a/third_party/sqlite/fuzz/db_corpus/fuzzdata1.db b/third_party/sqlite/fuzz/db_corpus/fuzzdata1.db new file mode 100644 index 0000000..4b4a6b5 --- /dev/null +++ b/third_party/sqlite/fuzz/db_corpus/fuzzdata1.db Binary files differ
diff --git a/third_party/sqlite/fuzz/db_corpus/fuzzdata2.db b/third_party/sqlite/fuzz/db_corpus/fuzzdata2.db new file mode 100644 index 0000000..76827900 --- /dev/null +++ b/third_party/sqlite/fuzz/db_corpus/fuzzdata2.db Binary files differ
diff --git a/third_party/sqlite/fuzz/db_corpus/fuzzdata3.db b/third_party/sqlite/fuzz/db_corpus/fuzzdata3.db new file mode 100644 index 0000000..0a41fd6e --- /dev/null +++ b/third_party/sqlite/fuzz/db_corpus/fuzzdata3.db Binary files differ
diff --git a/third_party/sqlite/fuzz/db_corpus/fuzzdata4.db b/third_party/sqlite/fuzz/db_corpus/fuzzdata4.db new file mode 100644 index 0000000..254bf83 --- /dev/null +++ b/third_party/sqlite/fuzz/db_corpus/fuzzdata4.db Binary files differ
diff --git a/third_party/sqlite/fuzz/db_corpus/fuzzdata5.db b/third_party/sqlite/fuzz/db_corpus/fuzzdata5.db new file mode 100644 index 0000000..cfb0ebe --- /dev/null +++ b/third_party/sqlite/fuzz/db_corpus/fuzzdata5.db Binary files differ
diff --git a/third_party/sqlite/fuzz/db_corpus/fuzzdata6.db b/third_party/sqlite/fuzz/db_corpus/fuzzdata6.db new file mode 100644 index 0000000..b1424c2 --- /dev/null +++ b/third_party/sqlite/fuzz/db_corpus/fuzzdata6.db Binary files differ
diff --git a/third_party/sqlite/fuzz/db_corpus/fuzzdata7.db b/third_party/sqlite/fuzz/db_corpus/fuzzdata7.db new file mode 100644 index 0000000..69469f9 --- /dev/null +++ b/third_party/sqlite/fuzz/db_corpus/fuzzdata7.db Binary files differ
diff --git a/third_party/sqlite/patches/0001-test-SQLite-tests-compiling-on-Linux.patch b/third_party/sqlite/patches/0001-test-SQLite-tests-compiling-on-Linux.patch index 388c93d..97cd2bd4f 100644 --- a/third_party/sqlite/patches/0001-test-SQLite-tests-compiling-on-Linux.patch +++ b/third_party/sqlite/patches/0001-test-SQLite-tests-compiling-on-Linux.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Scott Hess <shess@chromium.org> Date: Fri, 16 Jan 2015 10:24:30 -0800 -Subject: [PATCH 1/9] [test] SQLite tests compiling on Linux. +Subject: [PATCH 1/6] [test] SQLite tests compiling on Linux. --- third_party/sqlite/src/Makefile.linux-gcc | 41 ++++++++++++++++------- @@ -18,7 +18,7 @@ # -TOP = ../sqlite +TOP = .. - + #### C Compiler and options for use in building executables that # will run on the platform that is doing the build. @@ -32,19 +32,19 @@ USLEEP = -DHAVE_USLEEP=1 @@ -29,7 +29,7 @@ -THREADSAFE = -DTHREADSAFE=0 +THREADSAFE = -DTHREADSAFE=1 +#THREADSAFE = -DTHREADSAFE=0 - + #### Specify any extra linker options needed to make the library # thread safe # @@ -37,13 +37,13 @@ -THREADLIB = +THREADLIB = -lpthread +#THREADLIB = - + #### Specify any extra libraries needed to access required functions. # #TLIBS = -lrt # fdatasync on Solaris 8 -TLIBS = +TLIBS = -ldl - + #### Leave SQLITE_DEBUG undefined for maximum speed. Use SQLITE_DEBUG=1 # to check for memory leaks. Use SQLITE_DEBUG=2 to print a log of all @@ -58,7 +58,24 @@ TLIBS = @@ -69,7 +69,7 @@ + +# TODO(shess) I can't see why I need this setting. +OPTS += -DOS_UNIX=1 - + #### The suffix to add to executable files. ".exe" for windows. # Nothing for unix. @@ -70,7 +87,7 @@ EXE = @@ -82,7 +82,7 @@ #TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage #TCC = /opt/mingw/bin/i386-mingw32-gcc -O6 @@ -91,16 +108,16 @@ SHPREFIX = lib - + #### Extra compiler options needed for programs that use the TCL library. # -#TCL_FLAGS = @@ -92,7 +92,7 @@ +#TCL_FLAGS = -I/home/drh/tcltk/8.5linux #TCL_FLAGS = -I/home/drh/tcltk/8.5win -DSTATIC_BUILD=1 #TCL_FLAGS = -I/home/drh/tcltk/8.3hpux - + #### Linker options needed to link against the TCL library. # -#LIBTCL = -ltcl -lm -ldl @@ -101,20 +101,20 @@ +#LIBTCL = /home/drh/tcltk/8.5linux/libtcl8.5g.a -lm -ldl #LIBTCL = /home/drh/tcltk/8.5win/libtcl85s.a -lmsvcrt #LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc - + diff --git a/third_party/sqlite/src/main.mk b/third_party/sqlite/src/main.mk -index 051257e532a2..ef2b67bd5116 100644 +index d18313bdc79a..05c8f83b4212 100644 --- a/third_party/sqlite/src/main.mk +++ b/third_party/sqlite/src/main.mk -@@ -833,7 +833,7 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $ +@@ -836,7 +836,7 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $ tclsh $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c - + sqlite3_analyzer$(EXE): sqlite3_analyzer.c - $(TCCX) $(TCL_FLAGS) sqlite3_analyzer.c -o $@ $(LIBTCL) $(THREADLIB) + $(TCCX) $(TCL_FLAGS) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS) $(THREADLIB) - + sqltclsh.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/sqltclsh.tcl $(TOP)/ext/misc/appendvfs.c $(TOP)/tool/mkccode.tcl tclsh $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqltclsh.c.in >sqltclsh.c --- +-- 2.18.0
diff --git a/third_party/sqlite/patches/0002-Modify-default-VFS-to-support-WebDatabase.patch b/third_party/sqlite/patches/0002-Modify-default-VFS-to-support-WebDatabase.patch index a68a8e7..1dd942c5 100644 --- a/third_party/sqlite/patches/0002-Modify-default-VFS-to-support-WebDatabase.patch +++ b/third_party/sqlite/patches/0002-Modify-default-VFS-to-support-WebDatabase.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: dumi <dumi@chromium.org> Date: Mon, 20 Jul 2009 23:40:51 +0000 -Subject: [PATCH 2/9] Modify default VFS to support WebDatabase. +Subject: [PATCH 2/6] Modify default VFS to support WebDatabase. The renderer WebDatabase implementation needs to broker certain requests to the browser. This modifies SQLite to allow monkey-patching the VFS @@ -23,10 +23,10 @@ 3 files changed, 82 insertions(+) diff --git a/third_party/sqlite/src/src/os_unix.c b/third_party/sqlite/src/src/os_unix.c -index 745573fa84b1..ebae2eb47043 100644 +index 52ef64116444..d0e1c39bc4b8 100644 --- a/third_party/sqlite/src/src/os_unix.c +++ b/third_party/sqlite/src/src/os_unix.c -@@ -1436,6 +1436,12 @@ static int fileHasMoved(unixFile *pFile){ +@@ -1437,6 +1437,12 @@ static int fileHasMoved(unixFile *pFile){ return pFile->pInode!=0 && pFile->pId!=pFile->pInode->fileId.pId; #else struct stat buf; @@ -39,10 +39,10 @@ return pFile->pInode!=0 && (osStat(pFile->zPath, &buf)!=0 || (u64)buf.st_ino!=pFile->pInode->fileId.ino); -@@ -5872,6 +5878,45 @@ static int findCreateFileMode( +@@ -5879,6 +5885,45 @@ static int findCreateFileMode( return rc; } - + +/* +** Initialize |unixFile| internals of |file| on behalf of chromiumOpen() in +** WebDatabase SQLiteFileSystemPosix.cpp. Function is a subset of unixOpen(), @@ -85,16 +85,16 @@ /* ** Open the file zPath. ** -@@ -5972,6 +6017,8 @@ static int unixOpen( +@@ -5979,6 +6024,8 @@ static int unixOpen( randomnessPid = osGetpid(0); sqlite3_randomness(0,0); } + + /* Duplicated in chromium_sqlite3_fill_in_unix_sqlite3_file(). */ memset(p, 0, sizeof(unixFile)); - + if( eType==SQLITE_OPEN_MAIN_DB ){ -@@ -5980,6 +6027,7 @@ static int unixOpen( +@@ -5987,6 +6034,7 @@ static int unixOpen( if( pUnused ){ fd = pUnused->fd; }else{ @@ -102,21 +102,21 @@ pUnused = sqlite3_malloc64(sizeof(*pUnused)); if( !pUnused ){ return SQLITE_NOMEM_BKPT; -@@ -6064,6 +6112,7 @@ static int unixOpen( +@@ -6071,6 +6119,7 @@ static int unixOpen( } - + if( p->pPreallocatedUnused ){ + /* Duplicated in chromium_sqlite3_fill_in_unix_sqlite3_file(). */ p->pPreallocatedUnused->fd = fd; p->pPreallocatedUnused->flags = flags; } -@@ -6145,10 +6194,12 @@ static int unixOpen( +@@ -6152,10 +6201,12 @@ static int unixOpen( assert( zPath==0 || zPath[0]=='/' || eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL ); + /* Duplicated in chromium_sqlite3_fill_in_unix_sqlite3_file(). */ rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags); - + open_finished: if( rc!=SQLITE_OK ){ + /* Duplicated in chromium_sqlite3_fill_in_unix_sqlite3_file(). */ @@ -124,13 +124,13 @@ } return rc; diff --git a/third_party/sqlite/src/src/os_win.c b/third_party/sqlite/src/src/os_win.c -index 2a4b613ff869..dfefc4452f02 100644 +index aafc89f7d2d5..76743781a019 100644 --- a/third_party/sqlite/src/src/os_win.c +++ b/third_party/sqlite/src/src/os_win.c -@@ -6114,4 +6114,12 @@ int sqlite3_os_end(void){ +@@ -6130,4 +6130,12 @@ int sqlite3_os_end(void){ return SQLITE_OK; } - + +CHROMIUM_SQLITE_API +void chromium_sqlite3_initialize_win_sqlite3_file(sqlite3_file* file, HANDLE handle) { + winFile* winSQLite3File = (winFile*)file; @@ -141,13 +141,13 @@ + #endif /* SQLITE_OS_WIN */ diff --git a/third_party/sqlite/src/src/sqlite.h.in b/third_party/sqlite/src/src/sqlite.h.in -index 6749aa0082d4..620f10e631cc 100644 +index cf17bc015fa7..11622a49697f 100644 --- a/third_party/sqlite/src/src/sqlite.h.in +++ b/third_party/sqlite/src/src/sqlite.h.in -@@ -8338,6 +8338,29 @@ int sqlite3_strnicmp(const char *, const char *, int); +@@ -8378,6 +8378,29 @@ int sqlite3_strnicmp(const char *, const char *, int); */ int sqlite3_strglob(const char *zGlob, const char *zStr); - + +/* Begin WebDatabase patch for Chromium */ +/* Expose some SQLite internals for the WebDatabase vfs. +** DO NOT EXTEND THE USE OF THIS. @@ -174,6 +174,6 @@ /* ** CAPI3REF: String LIKE Matching * --- +-- 2.18.0
diff --git a/third_party/sqlite/patches/0003-Virtual-table-supporting-recovery-of-corrupted-datab.patch b/third_party/sqlite/patches/0003-Virtual-table-supporting-recovery-of-corrupted-datab.patch index 6227215..f7f7e3e 100644 --- a/third_party/sqlite/patches/0003-Virtual-table-supporting-recovery-of-corrupted-datab.patch +++ b/third_party/sqlite/patches/0003-Virtual-table-supporting-recovery-of-corrupted-datab.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Scott Hess <shess@chromium.org> Date: Sat, 20 Jul 2013 11:42:21 -0700 -Subject: [PATCH 3/9] Virtual table supporting recovery of corrupted databases. +Subject: [PATCH 3/6] Virtual table supporting recovery of corrupted databases. "recover" implements a virtual table which uses the SQLite pager layer to read table pages and pull out the data which is structurally sound @@ -33,19 +33,19 @@ create mode 100644 third_party/sqlite/src/test/recover2.test diff --git a/third_party/sqlite/src/main.mk b/third_party/sqlite/src/main.mk -index ef2b67bd5116..f44fab7f777d 100644 +index 05c8f83b4212..9b50874926dc 100644 --- a/third_party/sqlite/src/main.mk +++ b/third_party/sqlite/src/main.mk @@ -77,6 +77,8 @@ LIBOBJ+= vdbe.o parse.o \ vdbetrace.o wal.o walker.o where.o wherecode.o whereexpr.o \ utf.o vtab.o window.o - + +LIBOBJ += recover.o recover_varint.o + LIBOBJ += sqlite3session.o - + # All of the source code files. -@@ -407,6 +409,8 @@ TESTSRC2 = \ +@@ -409,6 +411,8 @@ TESTSRC2 = \ $(TOP)/src/prepare.c \ $(TOP)/src/printf.c \ $(TOP)/src/random.c \ @@ -54,22 +54,22 @@ $(TOP)/src/pcache.c \ $(TOP)/src/pcache1.c \ $(TOP)/src/select.c \ -@@ -873,6 +877,7 @@ TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024 +@@ -876,6 +880,7 @@ TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024 TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB TESTFIXTURE_FLAGS += -DTCLSH_INIT_PROC=sqlite3TestInit +TESTFIXTURE_FLAGS += -DDEFAULT_ENABLE_RECOVER=1 - + testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c $(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \ diff --git a/third_party/sqlite/src/src/main.c b/third_party/sqlite/src/src/main.c -index 24ca264d6408..f070fed33989 100644 +index d994c7176ea4..478428ac27c8 100644 --- a/third_party/sqlite/src/src/main.c +++ b/third_party/sqlite/src/src/main.c -@@ -3197,6 +3197,14 @@ static int openDatabase( +@@ -3201,6 +3201,14 @@ static int openDatabase( } #endif - + +#ifdef DEFAULT_ENABLE_RECOVER + /* Initialize recover virtual table for testing. */ + extern int chrome_sqlite3_recoverVtableInit(sqlite3 *db); @@ -3899,6 +3899,6 @@ +} [list 4 1024 1 text [string length $substr] $substr] + +finish_test --- +-- 2.18.0
diff --git a/third_party/sqlite/patches/0004-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch b/third_party/sqlite/patches/0004-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch index 2cd489be4..932b65a 100644 --- a/third_party/sqlite/patches/0004-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch +++ b/third_party/sqlite/patches/0004-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: "tc@google.com" <tc@google.com> Date: Tue, 6 Jan 2009 22:39:41 +0000 -Subject: [PATCH 4/9] Custom shell.c helpers to load Chromium's ICU data. +Subject: [PATCH 4/6] Custom shell.c helpers to load Chromium's ICU data. History uses fts3 with an icu-based segmenter. These changes allow building a sqlite3 binary for Linux or Windows which can read those files. @@ -24,7 +24,7 @@ @@ -77,6 +77,13 @@ OPTS += -DSQLITE_MEMDEBUG=1 # TODO(shess) I can't see why I need this setting. OPTS += -DOS_UNIX=1 - + +# Support for loading Chromium ICU data in sqlite3. +ifeq ($(shell uname -s),Darwin) +SHELL_ICU = @@ -36,26 +36,26 @@ # Nothing for unix. # diff --git a/third_party/sqlite/src/main.mk b/third_party/sqlite/src/main.mk -index f44fab7f777d..8992aadf9373 100644 +index 9b50874926dc..40ab267ec72c 100644 --- a/third_party/sqlite/src/main.mk +++ b/third_party/sqlite/src/main.mk -@@ -546,7 +546,7 @@ libsqlite3.a: $(LIBOBJ) - +@@ -549,7 +549,7 @@ libsqlite3.a: $(LIBOBJ) + sqlite3$(EXE): shell.c libsqlite3.a sqlite3.h $(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) $(SHELL_OPT) \ - shell.c libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB) + shell.c $(SHELL_ICU) libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB) - + sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h $(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \ diff --git a/third_party/sqlite/src/src/shell.c.in b/third_party/sqlite/src/src/shell.c.in -index 5cc06e4ec63c..28d3d82a4203 100644 +index 0007d984d045..b13551dc61f2 100644 --- a/third_party/sqlite/src/src/shell.c.in +++ b/third_party/sqlite/src/src/shell.c.in -@@ -8438,6 +8438,16 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ +@@ -8555,6 +8555,16 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ } #endif - + + /* Begin evanm patch. */ +#if !defined(__APPLE__) + extern int sqlite_shell_init_icu(); @@ -140,6 +140,6 @@ + + return 1; +} --- +-- 2.18.0
diff --git a/third_party/sqlite/patches/0005-fts3-Disable-fts3_tokenizer-and-fts4.patch b/third_party/sqlite/patches/0005-fts3-Disable-fts3_tokenizer-and-fts4.patch index 64f6eff..922a41f 100644 --- a/third_party/sqlite/patches/0005-fts3-Disable-fts3_tokenizer-and-fts4.patch +++ b/third_party/sqlite/patches/0005-fts3-Disable-fts3_tokenizer-and-fts4.patch
@@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Scott Hess <shess@chromium.org> Date: Tue, 16 Dec 2014 13:02:27 -0800 -Subject: [PATCH 5/9] [fts3] Disable fts3_tokenizer and fts4. +Subject: [PATCH 5/6] [fts3] Disable fts3_tokenizer and fts4. fts3_tokenizer allows a SQLite user to specify a pointer to call as a function, which has obvious sercurity implications. Disable fts4 until @@ -14,7 +14,7 @@ 1 file changed, 9 insertions(+) diff --git a/third_party/sqlite/src/ext/fts3/fts3.c b/third_party/sqlite/src/ext/fts3/fts3.c -index e8c6a0090216..fd6d58c69b7d 100644 +index 44d9e20cc667..ef69a7b18681 100644 --- a/third_party/sqlite/src/ext/fts3/fts3.c +++ b/third_party/sqlite/src/ext/fts3/fts3.c @@ -287,6 +287,7 @@ @@ -22,10 +22,10 @@ ** older data. */ +#define CHROMIUM_FTS3_CHANGES 1 - + #include "fts3Int.h" #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) -@@ -3972,7 +3973,11 @@ int sqlite3Fts3Init(sqlite3 *db){ +@@ -3988,7 +3989,11 @@ int sqlite3Fts3Init(sqlite3 *db){ ** module with sqlite. */ if( SQLITE_OK==rc @@ -37,7 +37,7 @@ && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1)) -@@ -3982,6 +3987,9 @@ int sqlite3Fts3Init(sqlite3 *db){ +@@ -3998,6 +4003,9 @@ int sqlite3Fts3Init(sqlite3 *db){ rc = sqlite3_create_module_v2( db, "fts3", &fts3Module, (void *)pHash, hashDestroy ); @@ -47,14 +47,14 @@ if( rc==SQLITE_OK ){ rc = sqlite3_create_module_v2( db, "fts4", &fts3Module, (void *)pHash, 0 -@@ -3990,6 +3998,7 @@ int sqlite3Fts3Init(sqlite3 *db){ +@@ -4006,6 +4014,7 @@ int sqlite3Fts3Init(sqlite3 *db){ if( rc==SQLITE_OK ){ rc = sqlite3Fts3InitTok(db, (void *)pHash); } +#endif return rc; } - --- + +-- 2.18.0
diff --git a/third_party/sqlite/patches/0006-fts3-Fix-uninit-variable-in-fts3EvalDeferredPhrase.patch b/third_party/sqlite/patches/0006-fts3-Fix-uninit-variable-in-fts3EvalDeferredPhrase.patch deleted file mode 100644 index a18419a..0000000 --- a/third_party/sqlite/patches/0006-fts3-Fix-uninit-variable-in-fts3EvalDeferredPhrase.patch +++ /dev/null
@@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Scott Hess <shess@chromium.org> -Date: Thu, 12 Feb 2015 15:01:26 -0800 -Subject: [PATCH 6/9] [fts3] Fix uninit variable in fts3EvalDeferredPhrase. - -Chromium compiles with SQLITE_DISABLE_FTS4_DEFERRED since fts4 is -disabled. That compiles away sqlite3Fts3DeferredTokenList() which -otherwise initialized pList and nList in fts3EvalDeferredPhrase(). - -BUG=458266 -R=thakis@chromium.org ---- - third_party/sqlite/src/ext/fts3/fts3Int.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/third_party/sqlite/src/ext/fts3/fts3Int.h b/third_party/sqlite/src/ext/fts3/fts3Int.h -index 3c6501cea432..24c0f2940f33 100644 ---- a/third_party/sqlite/src/ext/fts3/fts3Int.h -+++ b/third_party/sqlite/src/ext/fts3/fts3Int.h -@@ -487,7 +487,7 @@ int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *); - # define sqlite3Fts3DeferToken(x,y,z) SQLITE_OK - # define sqlite3Fts3CacheDeferredDoclists(x) SQLITE_OK - # define sqlite3Fts3FreeDeferredDoclists(x) --# define sqlite3Fts3DeferredTokenList(x,y,z) SQLITE_OK -+# define sqlite3Fts3DeferredTokenList(x,y,z) ((*(y)=0),(*(z)=0),SQLITE_OK) - #endif - - void sqlite3Fts3SegmentsClose(Fts3Table *); --- -2.18.0 -
diff --git a/third_party/sqlite/patches/0006-fuchsia-Use-dot-file-locking-for-sqlite.patch b/third_party/sqlite/patches/0006-fuchsia-Use-dot-file-locking-for-sqlite.patch new file mode 100644 index 0000000..c8aa08d --- /dev/null +++ b/third_party/sqlite/patches/0006-fuchsia-Use-dot-file-locking-for-sqlite.patch
@@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Scott Graham <scottmg@chromium.org> +Date: Mon, 11 Sep 2017 13:37:46 -0700 +Subject: [PATCH 6/6] fuchsia: Use dot-file locking for sqlite + +--- + third_party/sqlite/src/src/os_unix.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/third_party/sqlite/src/src/os_unix.c b/third_party/sqlite/src/src/os_unix.c +index d0e1c39bc4b8..d0736e0a63de 100644 +--- a/third_party/sqlite/src/src/os_unix.c ++++ b/third_party/sqlite/src/src/os_unix.c +@@ -7873,6 +7873,10 @@ int sqlite3_os_init(void){ + UNIXVFS("unix", autolockIoFinder ), + #elif OS_VXWORKS + UNIXVFS("unix", vxworksIoFinder ), ++#elif __Fuchsia__ ++ /* None of the system calls for other exclusion methods are currently ++ ** implemented on Fuchsia, so use simple dot-file locking for now. */ ++ UNIXVFS("unix", dotlockIoFinder ), + #else + UNIXVFS("unix", posixIoFinder ), + #endif +-- +2.18.0 +
diff --git a/third_party/sqlite/patches/0007-dbfuzz2-fix-for-chrome-config.patch b/third_party/sqlite/patches/0007-dbfuzz2-fix-for-chrome-config.patch new file mode 100644 index 0000000..bcb4d968 --- /dev/null +++ b/third_party/sqlite/patches/0007-dbfuzz2-fix-for-chrome-config.patch
@@ -0,0 +1,22 @@ +diff --git a/third_party/sqlite/src/test/dbfuzz2.c b/third_party/sqlite/src/test/dbfuzz2.c +index 0833f0386884..4ec43302ac37 100644 +--- a/third_party/sqlite/src/test/dbfuzz2.c ++++ b/third_party/sqlite/src/test/dbfuzz2.c +@@ -56,7 +56,9 @@ static const char *azSql[] = { + "ALTER TABLE t1 RENAME TO alkjalkjdfiiiwuer987lkjwer82mx97sf98788s9789s;", + "INSERT INTO t3 SELECT * FROM t2;", + "DELETE FROM t3 WHERE x IN (SELECT x FROM t4);", ++#if !defined(SQLITE_OMIT_REINDEX) + "REINDEX;", ++#endif + "DROP TABLE t3;", + "VACUUM;", + }; +@@ -78,6 +80,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){ + printf("************** nByte=%d ***************\n", (int)nByte); + fflush(stdout); + } ++ if( sqlite3_initialize() ) return 0; + rc = sqlite3_open(0, &db); + if( rc ) return 1; + a = sqlite3_malloc64(nByte+1);
diff --git a/third_party/sqlite/patches/0007-fuchsia-Use-dot-file-locking-for-sqlite.patch b/third_party/sqlite/patches/0007-fuchsia-Use-dot-file-locking-for-sqlite.patch deleted file mode 100644 index 18e89e3..0000000 --- a/third_party/sqlite/patches/0007-fuchsia-Use-dot-file-locking-for-sqlite.patch +++ /dev/null
@@ -1,27 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Scott Graham <scottmg@chromium.org> -Date: Mon, 11 Sep 2017 13:37:46 -0700 -Subject: [PATCH 7/9] fuchsia: Use dot-file locking for sqlite - ---- - third_party/sqlite/src/src/os_unix.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/third_party/sqlite/src/src/os_unix.c b/third_party/sqlite/src/src/os_unix.c -index ebae2eb47043..96802e62d7cb 100644 ---- a/third_party/sqlite/src/src/os_unix.c -+++ b/third_party/sqlite/src/src/os_unix.c -@@ -7866,6 +7866,10 @@ int sqlite3_os_init(void){ - UNIXVFS("unix", autolockIoFinder ), - #elif OS_VXWORKS - UNIXVFS("unix", vxworksIoFinder ), -+#elif __Fuchsia__ -+ /* None of the system calls for other exclusion methods are currently -+ ** implemented on Fuchsia, so use simple dot-file locking for now. */ -+ UNIXVFS("unix", dotlockIoFinder ), - #else - UNIXVFS("unix", posixIoFinder ), - #endif --- -2.18.0 -
diff --git a/third_party/sqlite/patches/0008-Fix-ossfuzz.c-to-compile-and-run-with-our-config.patch b/third_party/sqlite/patches/0008-Fix-ossfuzz.c-to-compile-and-run-with-our-config.patch deleted file mode 100644 index 1b82ddd2..0000000 --- a/third_party/sqlite/patches/0008-Fix-ossfuzz.c-to-compile-and-run-with-our-config.patch +++ /dev/null
@@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Matthew Denton <mpdenton@chromium.org> -Date: Fri, 16 Nov 2018 10:32:17 -0800 -Subject: [PATCH 8/9] Fix ossfuzz.c to compile and run with our config - ---- - third_party/sqlite/src/test/ossfuzz.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/third_party/sqlite/src/test/ossfuzz.c b/third_party/sqlite/src/test/ossfuzz.c -index a8a637f2ac85..7b69015129d9 100644 ---- a/third_party/sqlite/src/test/ossfuzz.c -+++ b/third_party/sqlite/src/test/ossfuzz.c -@@ -30,6 +30,7 @@ void ossfuzz_set_debug_flags(unsigned x){ - mDebug = x; - } - -+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - /* Return the current real-world time in milliseconds since the - ** Julian epoch (-4714-11-24). - */ -@@ -46,6 +47,7 @@ static sqlite3_int64 timeOfDay(void){ - } - return t; - } -+#endif - - /* An instance of the following object is passed by pointer as the - ** client data to various callbacks. -@@ -133,6 +135,11 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - uSelector = 0xfd; - } - -+#ifdef SQLITE_OMIT_AUTOINIT -+ rc = sqlite3_initialize(); -+ if( rc ) return 0; -+#endif -+ - /* Open the database connection. Only use an in-memory database. */ - rc = sqlite3_open_v2("fuzz.db", &cx.db, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0); --- -2.18.0 -
diff --git a/third_party/sqlite/patches/0009-Backport-Windows-VFS-mmap-fix.patch b/third_party/sqlite/patches/0009-Backport-Windows-VFS-mmap-fix.patch deleted file mode 100644 index 568a8c2..0000000 --- a/third_party/sqlite/patches/0009-Backport-Windows-VFS-mmap-fix.patch +++ /dev/null
@@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Victor Costan <pwnall@chromium.org> -Date: Fri, 23 Nov 2018 10:51:10 -0800 -Subject: [PATCH 9/9] Backport Windows VFS mmap fix - -Original change: https://www.sqlite.org/src/info/8576ccb479fc4b76 - -Original change description: -Make the winTruncate() method of the windows VFS be a no-op if there are -outstanding references to the memory-mapped pages. Otherwise, memory -might be deleted out from under those references when the file is -remapped during the truncate operation. - -Bug: 897576 ---- - third_party/sqlite/src/src/os_win.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/third_party/sqlite/src/src/os_win.c b/third_party/sqlite/src/src/os_win.c -index dfefc4452f02..5cd28a20e427 100644 ---- a/third_party/sqlite/src/src/os_win.c -+++ b/third_party/sqlite/src/src/os_win.c -@@ -2906,6 +2906,7 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ - DWORD lastErrno; - #if SQLITE_MAX_MMAP_SIZE>0 - sqlite3_int64 oldMmapSize; -+ if( pFile->nFetchOut>0 ) return SQLITE_OK; - #endif - - assert( pFile ); --- -2.18.0 -
diff --git a/third_party/sqlite/sqlite3.h b/third_party/sqlite/sqlite3.h index 059bbf7..a1b69691 100644 --- a/third_party/sqlite/sqlite3.h +++ b/third_party/sqlite/sqlite3.h
@@ -13,6 +13,31 @@ // using the component build, where our SQLite's symbols are visible to the // dynamic library loader. #include "third_party/sqlite/amalgamation/rename_exports.h" + +#if defined(SQLITE_OMIT_COMPLETE) +// When SQLITE_OMIT_COMPLETE is defined, sqlite3.h does not emit a declaration +// for sqlite3_complete(). SQLite's shell.c stubs out the function by #defining +// a macro. +// +// In order to avoid a macro redefinition warning, we must undo the #define in +// rename_exports.h. +// +// Historical note: SQLite's shell.c initially did not support building against +// a libary with SQLITE_OMIT_COMPLETE at all. The first attempt at adding +// support was https://www.sqlite.org/src/info/c3e816cca4ddf096 which defined +// sqlite_complete() as a stub function in shell.c. This worked on UNIX systems, +// but caused a compilation error on Windows, where sqlite3.h declares +// sqlite3_complete() as a __declspec(dllimport). The Windows build error was +// fixed in https://www.sqlite.org/src/info/d584a0cb51281594 at our request. +// While the current approach of using a macro requires the workaround here, it +// is preferable to the previous version, which did not build at all on Windows. +#if defined(sqlite3_complete) +#undef sqlite3_complete +#else +#error "This workaround is no longer needed." +#endif // !defined(sqlite3_complete) +#endif // defined(SQLITE_OMIT_COMPLETE) + #include "third_party/sqlite/amalgamation/sqlite3.h" #endif // THIRD_PARTY_SQLITE_SQLITE3_H_
diff --git a/third_party/sqlite/src/Makefile.in b/third_party/sqlite/src/Makefile.in index 2d9d28af..d2f9710 100644 --- a/third_party/sqlite/src/Makefile.in +++ b/third_party/sqlite/src/Makefile.in
@@ -32,6 +32,7 @@ CFLAGS = @CPPFLAGS@ @CFLAGS@ TCC = ${CC} ${CFLAGS} -I. -I${TOP}/src -I${TOP}/ext/rtree -I${TOP}/ext/icu TCC += -I${TOP}/ext/fts3 -I${TOP}/ext/async -I${TOP}/ext/session +TCC += -I${TOP}/ext/userauth # Define this for the autoconf-based build, so that the code knows it can # include the generated config.h @@ -187,7 +188,7 @@ random.lo resolve.lo rowset.lo rtree.lo \ sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \ table.lo threads.lo tokenize.lo treeview.lo trigger.lo \ - update.lo upsert.lo util.lo vacuum.lo \ + update.lo userauth.lo upsert.lo util.lo vacuum.lo \ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \ window.lo utf.lo vtab.lo @@ -356,6 +357,9 @@ $(TOP)/ext/session/sqlite3session.c \ $(TOP)/ext/session/sqlite3session.h SRC += \ + $(TOP)/ext/userauth/userauth.c \ + $(TOP)/ext/userauth/sqlite3userauth.h +SRC += \ $(TOP)/ext/rbu/sqlite3rbu.h \ $(TOP)/ext/rbu/sqlite3rbu.c SRC += \ @@ -437,6 +441,7 @@ $(TOP)/ext/misc/closure.c \ $(TOP)/ext/misc/csv.c \ $(TOP)/ext/misc/eval.c \ + $(TOP)/ext/misc/explain.c \ $(TOP)/ext/misc/fileio.c \ $(TOP)/ext/misc/fuzzer.c \ $(TOP)/ext/fts5/fts5_tcl.c \ @@ -454,7 +459,8 @@ $(TOP)/ext/misc/totype.c \ $(TOP)/ext/misc/unionvtab.c \ $(TOP)/ext/misc/wholenumber.c \ - $(TOP)/ext/misc/zipfile.c + $(TOP)/ext/misc/zipfile.c \ + $(TOP)/ext/userauth/userauth.c # Source code to the library files needed by the test fixture # @@ -470,6 +476,7 @@ $(TOP)/src/dbstat.c \ $(TOP)/src/expr.c \ $(TOP)/src/func.c \ + $(TOP)/src/global.c \ $(TOP)/src/insert.c \ $(TOP)/src/wal.c \ $(TOP)/src/main.c \ @@ -559,6 +566,8 @@ $(TOP)/ext/icu/sqliteicu.h EXTHDR += \ $(TOP)/ext/rtree/sqlite3rtree.h +EXTHDR += \ + $(TOP)/ext/userauth/sqlite3userauth.h # executables needed for testing # @@ -578,7 +587,8 @@ $(TOP)/test/fuzzdata3.db \ $(TOP)/test/fuzzdata4.db \ $(TOP)/test/fuzzdata5.db \ - $(TOP)/test/fuzzdata6.db + $(TOP)/test/fuzzdata6.db \ + $(TOP)/test/fuzzdata7.db # Standard options to testfixture # @@ -595,6 +605,7 @@ SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC +SHELL_OPT += -DSQLITE_ENABLE_DESERIALIZE SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1 FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ @@ -663,6 +674,22 @@ dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h $(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS) +DBFUZZ2_OPTS = \ + -DSQLITE_THREADSAFE=0 \ + -DSQLITE_OMIT_LOAD_EXTENSION \ + -DSQLITE_ENABLE_DESERIALIZE \ + -DSQLITE_DEBUG \ + -DSQLITE_ENABLE_DBSTAT_VTAB \ + -DSQLITE_ENABLE_RTREE \ + -DSQLITE_ENABLE_FTS4 \ + -DSQLITE_EANBLE_FTS5 + +dbfuzz2: $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h + clang-6.0 -I. -g -O0 -fsanitize=fuzzer,undefined,address -o dbfuzz2 \ + $(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c + mkdir -p dbfuzz2-dir + cp $(TOP)/test/dbfuzz2-seed* dbfuzz2-dir + mptester$(TEXE): sqlite3.lo $(TOP)/mptest/mptest.c $(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.lo \ $(TLIBS) -rpath "$(libdir)" @@ -1098,7 +1125,10 @@ rtree.lo: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR) $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c -sqlite3session.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR) +sqlite3session.lo: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR) + $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c + +userauth.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR) $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c json1.lo: $(TOP)/ext/misc/json1.c @@ -1169,6 +1199,10 @@ $(LTLINK) -DSQLITE_NO_SYNC=1 $(TEMP_STORE) $(TESTFIXTURE_FLAGS) \ -o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS) +coretestprogs: $(TESTPROGS) + +testprogs: coretestprogs srcck1$(BEXE) fuzzcheck$(TEXE) sessionfuzz$(TEXE) + # A very detailed test running most or all test cases fulltest: $(TESTPROGS) fuzztest ./testfixture$(TEXE) $(TOP)/test/all.test $(TESTOPTS) @@ -1275,6 +1309,9 @@ changeset$(TEXE): $(TOP)/ext/session/changeset.c sqlite3.lo $(LTLINK) -o $@ $(TOP)/ext/session/changeset.c sqlite3.lo $(TLIBS) +changesetfuzz$(TEXE): $(TOP)/ext/session/changesetfuzz.c sqlite3.lo + $(LTLINK) -o $@ $(TOP)/ext/session/changesetfuzz.c sqlite3.lo $(TLIBS) + rollback-test$(TEXE): $(TOP)/tool/rollback-test.c sqlite3.lo $(LTLINK) -o $@ $(TOP)/tool/rollback-test.c sqlite3.lo $(TLIBS)
diff --git a/third_party/sqlite/src/Makefile.msc b/third_party/sqlite/src/Makefile.msc index 4c6cdfb..e3feffa 100644 --- a/third_party/sqlite/src/Makefile.msc +++ b/third_party/sqlite/src/Makefile.msc
@@ -345,6 +345,7 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_INTROSPECTION_PRAGMAS=1 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1 !ENDIF OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 !ENDIF @@ -1515,6 +1516,7 @@ $(TOP)\ext\misc\closure.c \ $(TOP)\ext\misc\csv.c \ $(TOP)\ext\misc\eval.c \ + $(TOP)\ext\misc\explain.c \ $(TOP)\ext\misc\fileio.c \ $(TOP)\ext\misc\fuzzer.c \ $(TOP)\ext\fts5\fts5_tcl.c \ @@ -1622,7 +1624,8 @@ $(TOP)\test\fuzzdata3.db \ $(TOP)\test\fuzzdata4.db \ $(TOP)\test\fuzzdata5.db \ - $(TOP)\test\fuzzdata6.db + $(TOP)\test\fuzzdata6.db \ + $(TOP)\test\fuzzdata7.db # <</mark>> # Additional compiler options for the shell. These are only effective @@ -1632,6 +1635,7 @@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1 +SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1 !ENDIF # <<mark>> @@ -2334,6 +2338,10 @@ @set PATH=$(LIBTCLPATH);$(PATH) .\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS) +coretestprogs: $(TESTPROGS) + +testprogs: coretestprogs srcck1.exe fuzzcheck.exe sessionfuzz.exe + fulltest: $(TESTPROGS) fuzztest @set PATH=$(LIBTCLPATH);$(PATH) .\testfixture.exe $(TOP)\test\all.test $(TESTOPTS) @@ -2441,6 +2449,11 @@ -DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \ $(TOP)\ext\session\changeset.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) +changesetfuzz.exe: $(TOP)\ext\session\changesetfuzz.c $(SQLITE3C) $(SQLITE3H) + $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ + -DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \ + $(TOP)\ext\session\changesetfuzz.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) + fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \ $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
diff --git a/third_party/sqlite/src/VERSION b/third_party/sqlite/src/VERSION index 703e89e7..419ede3 100644 --- a/third_party/sqlite/src/VERSION +++ b/third_party/sqlite/src/VERSION
@@ -1 +1 @@ -3.25.3 +3.26.0
diff --git a/third_party/sqlite/src/configure b/third_party/sqlite/src/configure index 6dde7464..51653aa 100755 --- a/third_party/sqlite/src/configure +++ b/third_party/sqlite/src/configure
@@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for sqlite 3.25.3. +# Generated by GNU Autoconf 2.69 for sqlite 3.26.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -726,8 +726,8 @@ # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' -PACKAGE_VERSION='3.25.3' -PACKAGE_STRING='sqlite 3.25.3' +PACKAGE_VERSION='3.26.0' +PACKAGE_STRING='sqlite 3.26.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1466,7 +1466,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sqlite 3.25.3 to adapt to many kinds of systems. +\`configure' configures sqlite 3.26.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1531,7 +1531,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sqlite 3.25.3:";; + short | recursive ) echo "Configuration of sqlite 3.26.0:";; esac cat <<\_ACEOF @@ -1657,7 +1657,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sqlite configure 3.25.3 +sqlite configure 3.26.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2076,7 +2076,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sqlite $as_me 3.25.3, which was +It was created by sqlite $as_me 3.26.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -12232,7 +12232,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sqlite $as_me 3.25.3, which was +This file was extended by sqlite $as_me 3.26.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -12298,7 +12298,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -sqlite config.status 3.25.3 +sqlite config.status 3.26.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\"
diff --git a/third_party/sqlite/src/doc/lemon.html b/third_party/sqlite/src/doc/lemon.html index 98c816f..3f51ba9f 100644 --- a/third_party/sqlite/src/doc/lemon.html +++ b/third_party/sqlite/src/doc/lemon.html
@@ -777,6 +777,9 @@ <p>This might be needed, for example, if some of the C actions in the grammar call functions that are prototyped in unistd.h.</p> +<p>Use the <tt><a href="#pcode">%code</a></tt> directive to add code to +the end of the generated parser.</p> + <a name='pleft'></a> <h4>The <tt>%left</tt> directive</h4>
diff --git a/third_party/sqlite/src/ext/expert/sqlite3expert.c b/third_party/sqlite/src/ext/expert/sqlite3expert.c index 6878449..b94182f 100644 --- a/third_party/sqlite/src/ext/expert/sqlite3expert.c +++ b/third_party/sqlite/src/ext/expert/sqlite3expert.c
@@ -644,6 +644,7 @@ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ + 0, /* xShadowName */ }; return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p);
diff --git a/third_party/sqlite/src/ext/fts3/fts3.c b/third_party/sqlite/src/ext/fts3/fts3.c index fd6d58c6..ef69a7b 100644 --- a/third_party/sqlite/src/ext/fts3/fts3.c +++ b/third_party/sqlite/src/ext/fts3/fts3.c
@@ -3847,8 +3847,23 @@ return SQLITE_OK; } +/* +** Return true if zName is the extension on one of the shadow tables used +** by this module. +*/ +static int fts3ShadowName(const char *zName){ + static const char *azName[] = { + "content", "docsize", "segdir", "segments", "stat", + }; + unsigned int i; + for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ + if( sqlite3_stricmp(zName, azName[i])==0 ) return 1; + } + return 0; +} + static const sqlite3_module fts3Module = { - /* iVersion */ 2, + /* iVersion */ 3, /* xCreate */ fts3CreateMethod, /* xConnect */ fts3ConnectMethod, /* xBestIndex */ fts3BestIndexMethod, @@ -3871,6 +3886,7 @@ /* xSavepoint */ fts3SavepointMethod, /* xRelease */ fts3ReleaseMethod, /* xRollbackTo */ fts3RollbackToMethod, + /* xShadowName */ fts3ShadowName, }; /* @@ -4159,6 +4175,7 @@ return rc; } +#ifndef SQLITE_DISABLE_FTS4_DEFERRED /* ** This function is called on each phrase after the position lists for ** any deferred tokens have been loaded into memory. It updates the phrases @@ -4262,6 +4279,7 @@ return SQLITE_OK; } +#endif /* SQLITE_DISABLE_FTS4_DEFERRED */ /* ** Maximum number of tokens a phrase may have to be considered for the
diff --git a/third_party/sqlite/src/ext/fts3/fts3Int.h b/third_party/sqlite/src/ext/fts3/fts3Int.h index 24c0f29..3c6501c 100644 --- a/third_party/sqlite/src/ext/fts3/fts3Int.h +++ b/third_party/sqlite/src/ext/fts3/fts3Int.h
@@ -487,7 +487,7 @@ # define sqlite3Fts3DeferToken(x,y,z) SQLITE_OK # define sqlite3Fts3CacheDeferredDoclists(x) SQLITE_OK # define sqlite3Fts3FreeDeferredDoclists(x) -# define sqlite3Fts3DeferredTokenList(x,y,z) ((*(y)=0),(*(z)=0),SQLITE_OK) +# define sqlite3Fts3DeferredTokenList(x,y,z) SQLITE_OK #endif void sqlite3Fts3SegmentsClose(Fts3Table *);
diff --git a/third_party/sqlite/src/ext/fts3/fts3_aux.c b/third_party/sqlite/src/ext/fts3/fts3_aux.c index 258d3da..1ca830dd2 100644 --- a/third_party/sqlite/src/ext/fts3/fts3_aux.c +++ b/third_party/sqlite/src/ext/fts3/fts3_aux.c
@@ -539,7 +539,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; int rc; /* Return code */
diff --git a/third_party/sqlite/src/ext/fts3/fts3_term.c b/third_party/sqlite/src/ext/fts3/fts3_term.c index 644cfa8..4b2872f 100644 --- a/third_party/sqlite/src/ext/fts3/fts3_term.c +++ b/third_party/sqlite/src/ext/fts3/fts3_term.c
@@ -361,7 +361,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; int rc; /* Return code */
diff --git a/third_party/sqlite/src/ext/fts3/fts3_tokenize_vtab.c b/third_party/sqlite/src/ext/fts3/fts3_tokenize_vtab.c index 611c5eb..87c5da3 100644 --- a/third_party/sqlite/src/ext/fts3/fts3_tokenize_vtab.c +++ b/third_party/sqlite/src/ext/fts3/fts3_tokenize_vtab.c
@@ -443,7 +443,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; int rc; /* Return code */
diff --git a/third_party/sqlite/src/ext/fts5/fts5_index.c b/third_party/sqlite/src/ext/fts5/fts5_index.c index b970e2cc..833b5e2 100644 --- a/third_party/sqlite/src/ext/fts5/fts5_index.c +++ b/third_party/sqlite/src/ext/fts5/fts5_index.c
@@ -5402,7 +5402,7 @@ fts5CloseReader(p); } - *ppIter = &pRet->base; + *ppIter = (Fts5IndexIter*)pRet; sqlite3Fts5BufferFree(&buf); } return fts5IndexReturn(p);
diff --git a/third_party/sqlite/src/ext/fts5/fts5_main.c b/third_party/sqlite/src/ext/fts5/fts5_main.c index aa4df70..9c10405 100644 --- a/third_party/sqlite/src/ext/fts5/fts5_main.c +++ b/third_party/sqlite/src/ext/fts5/fts5_main.c
@@ -2645,9 +2645,24 @@ sqlite3_result_text(pCtx, "--FTS5-SOURCE-ID--", -1, SQLITE_TRANSIENT); } +/* +** Return true if zName is the extension on one of the shadow tables used +** by this module. +*/ +static int fts5ShadowName(const char *zName){ + static const char *azName[] = { + "config", "content", "data", "docsize", "idx" + }; + unsigned int i; + for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ + if( sqlite3_stricmp(zName, azName[i])==0 ) return 1; + } + return 0; +} + static int fts5Init(sqlite3 *db){ static const sqlite3_module fts5Mod = { - /* iVersion */ 2, + /* iVersion */ 3, /* xCreate */ fts5CreateMethod, /* xConnect */ fts5ConnectMethod, /* xBestIndex */ fts5BestIndexMethod, @@ -2670,6 +2685,7 @@ /* xSavepoint */ fts5SavepointMethod, /* xRelease */ fts5ReleaseMethod, /* xRollbackTo */ fts5RollbackToMethod, + /* xShadowName */ fts5ShadowName }; int rc;
diff --git a/third_party/sqlite/src/ext/fts5/fts5_test_tok.c b/third_party/sqlite/src/ext/fts5/fts5_test_tok.c index 2b7b3e2..7453638b 100644 --- a/third_party/sqlite/src/ext/fts5/fts5_test_tok.c +++ b/third_party/sqlite/src/ext/fts5/fts5_test_tok.c
@@ -471,7 +471,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; int rc; /* Return code */
diff --git a/third_party/sqlite/src/ext/fts5/fts5_vocab.c b/third_party/sqlite/src/ext/fts5/fts5_vocab.c index 7ac5658..6820706f 100644 --- a/third_party/sqlite/src/ext/fts5/fts5_vocab.c +++ b/third_party/sqlite/src/ext/fts5/fts5_vocab.c
@@ -431,6 +431,8 @@ i64 *pp = &pCsr->iInstPos; int *po = &pCsr->iInstOff; + assert( sqlite3Fts5IterEof(pIter)==0 ); + assert( pCsr->bEof==0 ); while( eDetail==FTS5_DETAIL_NONE || sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp) ){ @@ -440,7 +442,7 @@ rc = sqlite3Fts5IterNextScan(pCsr->pIter); if( rc==SQLITE_OK ){ rc = fts5VocabInstanceNewTerm(pCsr); - if( eDetail==FTS5_DETAIL_NONE ) break; + if( pCsr->bEof || eDetail==FTS5_DETAIL_NONE ) break; } if( rc ){ pCsr->bEof = 1; @@ -755,10 +757,9 @@ /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ 0, + /* xShadowName */ 0 }; void *p = (void*)pGlobal; return sqlite3_create_module_v2(db, "fts5vocab", &fts5Vocab, p, 0); } - -
diff --git a/third_party/sqlite/src/ext/fts5/test/fts5aa.test b/third_party/sqlite/src/ext/fts5/test/fts5aa.test index 7ea2002..bb6e8fc 100644 --- a/third_party/sqlite/src/ext/fts5/test/fts5aa.test +++ b/third_party/sqlite/src/ext/fts5/test/fts5aa.test
@@ -409,6 +409,7 @@ do_execsql_test 15.0 { INSERT INTO t1(t1) VALUES('integrity-check'); } +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 15.1 { UPDATE t1_content SET c1 = 'xyz xyz xyz xyz xyz abc' WHERE rowid = 1; }
diff --git a/third_party/sqlite/src/ext/fts5/test/fts5connect.test b/third_party/sqlite/src/ext/fts5/test/fts5connect.test index d48a428..2d179b9 100644 --- a/third_party/sqlite/src/ext/fts5/test/fts5connect.test +++ b/third_party/sqlite/src/ext/fts5/test/fts5connect.test
@@ -244,4 +244,3 @@ } finish_test -
diff --git a/third_party/sqlite/src/ext/fts5/test/fts5corrupt.test b/third_party/sqlite/src/ext/fts5/test/fts5corrupt.test index a6b1c98..872eb1bb 100644 --- a/third_party/sqlite/src/ext/fts5/test/fts5corrupt.test +++ b/third_party/sqlite/src/ext/fts5/test/fts5corrupt.test
@@ -41,6 +41,7 @@ do_execsql_test 1.2 { INSERT INTO t1(t1) VALUES('integrity-check') } set segid [lindex [fts5_level_segids t1] 0] +sqlite3_db_config db DEFENSIVE 0 do_test 1.3 { execsql { DELETE FROM t1_data WHERE rowid = fts5_rowid('segment', $segid, 4); @@ -50,6 +51,7 @@ do_test 1.4 { db_restore_and_reopen + sqlite3_db_config db DEFENSIVE 0 execsql { UPDATE t1_data set block = X'00000000' || substr(block, 5) WHERE rowid = fts5_rowid('segment', $segid, 4); @@ -89,7 +91,7 @@ do_execsql_test 3.1 { SELECT * FROM t3 WHERE t3 MATCH 'o' } {{one o} {three o} {five o}} - +sqlite3_db_config db DEFENSIVE 0 do_catchsql_test 3.1 { DELETE FROM t3_content WHERE rowid = 3; SELECT * FROM t3 WHERE t3 MATCH 'o';
diff --git a/third_party/sqlite/src/ext/fts5/test/fts5corrupt2.test b/third_party/sqlite/src/ext/fts5/test/fts5corrupt2.test index 4e346f0..b249471 100644 --- a/third_party/sqlite/src/ext/fts5/test/fts5corrupt2.test +++ b/third_party/sqlite/src/ext/fts5/test/fts5corrupt2.test
@@ -99,6 +99,7 @@ set lrowid [db one {SELECT max(rowid) FROM t1_data WHERE (rowid & $mask)=0}] set nbyte [db one {SELECT length(block) FROM t1_data WHERE rowid=$lrowid}] set all [db eval {SELECT rowid FROM t1}] +sqlite3_db_config db DEFENSIVE 0 for {set i [expr $nbyte-2]} {$i>=0} {incr i -1} { do_execsql_test 2.$i.1 { BEGIN; @@ -248,6 +249,7 @@ #-------------------------------------------------------------------- reset_db +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 6.1 { CREATE VIRTUAL TABLE x5 USING fts5(tt); INSERT INTO x5 VALUES('a');
diff --git a/third_party/sqlite/src/ext/fts5/test/fts5corrupt3.test b/third_party/sqlite/src/ext/fts5/test/fts5corrupt3.test index dab34f1..9551d2d 100644 --- a/third_party/sqlite/src/ext/fts5/test/fts5corrupt3.test +++ b/third_party/sqlite/src/ext/fts5/test/fts5corrupt3.test
@@ -51,6 +51,7 @@ set {} {} } {} +sqlite3_db_config db DEFENSIVE 0 for {set i 0} {$i < $L} {incr i} { do_test 1.2.$i { catchsql { @@ -86,6 +87,7 @@ # reset_db do_test 3.0 { create_t1 } {} +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 3.1 { SELECT count(*) FROM t1_data; @@ -158,6 +160,7 @@ # Test that segments that end unexpectedly are identified as corruption. # reset_db +sqlite3_db_config db DEFENSIVE 0 do_test 4.0 { execsql { CREATE VIRTUAL TABLE t1 USING fts5(x); @@ -182,6 +185,7 @@ db close sqlite3 db test.db + sqlite3_db_config db DEFENSIVE 0 db eval { BEGIN; @@ -257,6 +261,7 @@ #------------------------------------------------------------------------ # reset_db +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 6.1.0 { CREATE VIRTUAL TABLE t1 USING fts5(a); INSERT INTO t1 VALUES('bbbbb ccccc'); @@ -273,6 +278,7 @@ #------- reset_db +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 6.2.0 { CREATE VIRTUAL TABLE t1 USING fts5(a); INSERT INTO t1(t1, rank) VALUES('pgsz', 32); @@ -288,6 +294,7 @@ #------- reset_db +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 6.3.0 { CREATE VIRTUAL TABLE t1 USING fts5(a); INSERT INTO t1 VALUES('abc abcdef abcdefghi'); @@ -362,6 +369,7 @@ } } {} +sqlite3_db_config db DEFENSIVE 0 do_test 7.1 { foreach i [db eval { SELECT rowid FROM t5_data WHERE rowid>100 }] { db eval BEGIN @@ -383,6 +391,7 @@ INSERT INTO t1 VALUES('one', 'two'); } +sqlite3_db_config db DEFENSIVE 0 do_test 9.1.1 { set blob "12345678" ;# cookie append blob "0105" ;# 1 level, total of 5 segments
diff --git a/third_party/sqlite/src/ext/fts5/test/fts5first.test b/third_party/sqlite/src/ext/fts5/test/fts5first.test index e91193f3..4b13b07 100644 --- a/third_party/sqlite/src/ext/fts5/test/fts5first.test +++ b/third_party/sqlite/src/ext/fts5/test/fts5first.test
@@ -93,4 +93,3 @@ SELECT * FROM x2('^a'); } {1 {fts5: phrase queries are not supported (detail!=full)}} finish_test -
diff --git a/third_party/sqlite/src/ext/fts5/test/fts5integrity.test b/third_party/sqlite/src/ext/fts5/test/fts5integrity.test index 9116793..0705b80 100644 --- a/third_party/sqlite/src/ext/fts5/test/fts5integrity.test +++ b/third_party/sqlite/src/ext/fts5/test/fts5integrity.test
@@ -71,6 +71,7 @@ INSERT INTO aa(aa) VALUES('integrity-check'); } +sqlite3_db_config db DEFENSIVE 0 do_catchsql_test 4.2 { BEGIN; UPDATE aa_docsize SET sz = X'44' WHERE rowid = 3;
diff --git a/third_party/sqlite/src/ext/fts5/test/fts5rank.test b/third_party/sqlite/src/ext/fts5/test/fts5rank.test index 7bc874d..2c63395 100644 --- a/third_party/sqlite/src/ext/fts5/test/fts5rank.test +++ b/third_party/sqlite/src/ext/fts5/test/fts5rank.test
@@ -163,4 +163,3 @@ } {30 31 32 33 34 35 36 37 38 39 40} finish_test -
diff --git a/third_party/sqlite/src/ext/fts5/test/fts5rebuild.test b/third_party/sqlite/src/ext/fts5/test/fts5rebuild.test index 01918310..ae881c0 100644 --- a/third_party/sqlite/src/ext/fts5/test/fts5rebuild.test +++ b/third_party/sqlite/src/ext/fts5/test/fts5rebuild.test
@@ -39,6 +39,7 @@ INSERT INTO f1(f1) VALUES('integrity-check'); } {} +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.5 { DELETE FROM f1_data; } {}
diff --git a/third_party/sqlite/src/ext/fts5/test/fts5rowid.test b/third_party/sqlite/src/ext/fts5/test/fts5rowid.test index e6e2bcf..cabe094 100644 --- a/third_party/sqlite/src/ext/fts5/test/fts5rowid.test +++ b/third_party/sqlite/src/ext/fts5/test/fts5rowid.test
@@ -70,6 +70,7 @@ do_execsql_test 2.3 { SELECT count(fts5_decode(rowid, block)) FROM x1_data; } $res +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 2.4 { UPDATE x1_data SET block = X''; SELECT count(fts5_decode(rowid, block)) FROM x1_data;
diff --git a/third_party/sqlite/src/ext/fts5/test/fts5version.test b/third_party/sqlite/src/ext/fts5/test/fts5version.test index e79016c4..60ec81c0 100644 --- a/third_party/sqlite/src/ext/fts5/test/fts5version.test +++ b/third_party/sqlite/src/ext/fts5/test/fts5version.test
@@ -36,6 +36,7 @@ SELECT rowid FROM t1 WHERE t1 MATCH 'a'; } {1} +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.4 { UPDATE t1_config set v=5 WHERE k='version'; } @@ -53,6 +54,7 @@ } {1 {invalid fts5 file format (found 5, expected 4) - run 'rebuild'}} do_test 1.7 { + sqlite3_db_config db DEFENSIVE 0 execsql { DELETE FROM t1_config WHERE k='version' } db close sqlite3 db test.db
diff --git a/third_party/sqlite/src/ext/fts5/test/fts5vocab.test b/third_party/sqlite/src/ext/fts5/test/fts5vocab.test index 6f226dd5..19eafff6 100644 --- a/third_party/sqlite/src/ext/fts5/test/fts5vocab.test +++ b/third_party/sqlite/src/ext/fts5/test/fts5vocab.test
@@ -420,6 +420,7 @@ do_execsql_test 8.1.1 { SELECT * FROM x1_r; } $resr do_execsql_test 8.1.2 { SELECT * FROM x1_c } $resc +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 8.2 { PRAGMA writable_schema = 1; UPDATE sqlite_master @@ -481,4 +482,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/fts5/test/fts5vocab2.test b/third_party/sqlite/src/ext/fts5/test/fts5vocab2.test index 4a0a1f4..8edea54 100644 --- a/third_party/sqlite/src/ext/fts5/test/fts5vocab2.test +++ b/third_party/sqlite/src/ext/fts5/test/fts5vocab2.test
@@ -13,7 +13,7 @@ # source [file join [file dirname [info script]] fts5_common.tcl] -set testprefix fts5vocab +set testprefix fts5vocab2 # If SQLITE_ENABLE_FTS5 is defined, omit this file. ifcapable !fts5 { @@ -206,4 +206,3 @@ } finish_test -
diff --git a/third_party/sqlite/src/ext/misc/amatch.c b/third_party/sqlite/src/ext/misc/amatch.c index 6438028..519a5a0b 100644 --- a/third_party/sqlite/src/ext/misc/amatch.c +++ b/third_party/sqlite/src/ext/misc/amatch.c
@@ -1473,7 +1473,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/third_party/sqlite/src/ext/misc/btreeinfo.c b/third_party/sqlite/src/ext/misc/btreeinfo.c index de0392bc..9b298a4b 100644 --- a/third_party/sqlite/src/ext/misc/btreeinfo.c +++ b/third_party/sqlite/src/ext/misc/btreeinfo.c
@@ -411,6 +411,7 @@ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ + 0 /* xShadowName */ }; return sqlite3_create_module(db, "sqlite_btreeinfo", &binfo_module, 0); }
diff --git a/third_party/sqlite/src/ext/misc/closure.c b/third_party/sqlite/src/ext/misc/closure.c index 60c52938..bf1a8696 100644 --- a/third_party/sqlite/src/ext/misc/closure.c +++ b/third_party/sqlite/src/ext/misc/closure.c
@@ -938,7 +938,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/third_party/sqlite/src/ext/misc/completion.c b/third_party/sqlite/src/ext/misc/completion.c index e6ce62d..363c1f3 100644 --- a/third_party/sqlite/src/ext/misc/completion.c +++ b/third_party/sqlite/src/ext/misc/completion.c
@@ -468,7 +468,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/third_party/sqlite/src/ext/misc/csv.c b/third_party/sqlite/src/ext/misc/csv.c index 55cc45a5..be58a3a 100644 --- a/third_party/sqlite/src/ext/misc/csv.c +++ b/third_party/sqlite/src/ext/misc/csv.c
@@ -19,9 +19,9 @@ ** CREATE VIRTUAL TABLE temp.csv USING csv(filename=FILENAME); ** SELECT * FROM csv; ** -** The columns are named "c1", "c2", "c3", ... by default. But the -** application can define its own CREATE TABLE statement as an additional -** parameter. For example: +** The columns are named "c1", "c2", "c3", ... by default. Or the +** application can define its own CREATE TABLE statement using the +** schema= parameter, like this: ** ** CREATE VIRTUAL TABLE temp.csv2 USING csv( ** filename = "../http.log", @@ -32,9 +32,9 @@ ** the data= parameter. ** ** If the columns=N parameter is supplied, then the CSV file is assumed to have -** N columns. If the columns parameter is omitted, the CSV file is opened -** as soon as the virtual table is constructed and the first row of the CSV -** is read in order to count the tables. +** N columns. If both the columns= and schema= parameters are omitted, then +** the number and names of the columns is determined by the first line of +** the CSV input. ** ** Some extra debugging features (used for testing virtual tables) are available ** if this module is compiled with -DSQLITE_TEST. @@ -436,6 +436,34 @@ return -1; } +/* Check to see if the string is of the form: "TAG = BOOLEAN" or just "TAG". +** If it is, set *pValue to be the value of the boolean ("true" if there is +** not "= BOOLEAN" component) and return non-zero. If the input string +** does not begin with TAG, return zero. +*/ +static int csv_boolean_parameter( + const char *zTag, /* Tag we are looking for */ + int nTag, /* Size of the tag in bytes */ + const char *z, /* Input parameter */ + int *pValue /* Write boolean value here */ +){ + int b; + z = csv_skip_whitespace(z); + if( strncmp(zTag, z, nTag)!=0 ) return 0; + z = csv_skip_whitespace(z + nTag); + if( z[0]==0 ){ + *pValue = 1; + return 1; + } + if( z[0]!='=' ) return 0; + z = csv_skip_whitespace(z+1); + b = csv_boolean(z); + if( b>=0 ){ + *pValue = b; + return 1; + } + return 0; +} /* ** Parameters: @@ -469,6 +497,7 @@ #ifdef SQLITE_TEST int tstFlags = 0; /* Value for testflags=N parameter */ #endif + int b; /* Value of a boolean parameter */ int nCol = -99; /* Value of the columns= parameter */ CsvReader sRdr; /* A CSV file reader used to store an error ** message and/or to count the number of columns */ @@ -493,21 +522,12 @@ if( j<sizeof(azParam)/sizeof(azParam[0]) ){ if( sRdr.zErr[0] ) goto csvtab_connect_error; }else - if( (zValue = csv_parameter("header",6,z))!=0 ){ - int x; + if( csv_boolean_parameter("header",6,z,&b) ){ if( bHeader>=0 ){ csv_errmsg(&sRdr, "more than one 'header' parameter"); goto csvtab_connect_error; } - x = csv_boolean(zValue); - if( x==1 ){ - bHeader = 1; - }else if( x==0 ){ - bHeader = 0; - }else{ - csv_errmsg(&sRdr, "unrecognized argument to 'header': %s", zValue); - goto csvtab_connect_error; - } + bHeader = b; }else #ifdef SQLITE_TEST if( (zValue = csv_parameter("testflags",9,z))!=0 ){ @@ -521,53 +541,94 @@ } nCol = atoi(zValue); if( nCol<=0 ){ - csv_errmsg(&sRdr, "must have at least one column"); + csv_errmsg(&sRdr, "column= value must be positive"); goto csvtab_connect_error; } }else { - csv_errmsg(&sRdr, "unrecognized parameter '%s'", z); + csv_errmsg(&sRdr, "bad parameter: '%s'", z); goto csvtab_connect_error; } } if( (CSV_FILENAME==0)==(CSV_DATA==0) ){ - csv_errmsg(&sRdr, "must either filename= or data= but not both"); + csv_errmsg(&sRdr, "must specify either filename= or data= but not both"); goto csvtab_connect_error; } - if( nCol<=0 && csv_reader_open(&sRdr, CSV_FILENAME, CSV_DATA) ){ + + if( (nCol<=0 || bHeader==1) + && csv_reader_open(&sRdr, CSV_FILENAME, CSV_DATA) + ){ goto csvtab_connect_error; } pNew = sqlite3_malloc( sizeof(*pNew) ); *ppVtab = (sqlite3_vtab*)pNew; if( pNew==0 ) goto csvtab_connect_oom; memset(pNew, 0, sizeof(*pNew)); - if( nCol>0 ){ + if( CSV_SCHEMA==0 ){ + sqlite3_str *pStr = sqlite3_str_new(0); + char *zSep = ""; + int iCol = 0; + sqlite3_str_appendf(pStr, "CREATE TABLE x("); + if( nCol<0 && bHeader<1 ){ + nCol = 0; + do{ + csv_read_one_field(&sRdr); + nCol++; + }while( sRdr.cTerm==',' ); + } + if( nCol>0 && bHeader<1 ){ + for(iCol=0; iCol<nCol; iCol++){ + sqlite3_str_appendf(pStr, "%sc%d TEXT", zSep, iCol); + zSep = ","; + } + }else{ + do{ + char *z = csv_read_one_field(&sRdr); + if( (nCol>0 && iCol<nCol) || (nCol<0 && bHeader) ){ + sqlite3_str_appendf(pStr,"%s\"%w\" TEXT", zSep, z); + zSep = ","; + iCol++; + } + }while( sRdr.cTerm==',' ); + if( nCol<0 ){ + nCol = iCol; + }else{ + while( iCol<nCol ){ + sqlite3_str_appendf(pStr,"%sc%d TEXT", zSep, ++iCol); + zSep = ","; + } + } + } pNew->nCol = nCol; - }else{ + sqlite3_str_appendf(pStr, ")"); + CSV_SCHEMA = sqlite3_str_finish(pStr); + if( CSV_SCHEMA==0 ) goto csvtab_connect_oom; + }else if( nCol<0 ){ do{ csv_read_one_field(&sRdr); pNew->nCol++; }while( sRdr.cTerm==',' ); + }else{ + pNew->nCol = nCol; } pNew->zFilename = CSV_FILENAME; CSV_FILENAME = 0; pNew->zData = CSV_DATA; CSV_DATA = 0; #ifdef SQLITE_TEST pNew->tstFlags = tstFlags; #endif - pNew->iStart = bHeader==1 ? ftell(sRdr.in) : 0; - csv_reader_reset(&sRdr); - if( CSV_SCHEMA==0 ){ - char *zSep = ""; - CSV_SCHEMA = sqlite3_mprintf("CREATE TABLE x("); - if( CSV_SCHEMA==0 ) goto csvtab_connect_oom; - for(i=0; i<pNew->nCol; i++){ - CSV_SCHEMA = sqlite3_mprintf("%z%sc%d TEXT",CSV_SCHEMA, zSep, i); - zSep = ","; - } - CSV_SCHEMA = sqlite3_mprintf("%z);", CSV_SCHEMA); + if( bHeader!=1 ){ + pNew->iStart = 0; + }else if( pNew->zData ){ + pNew->iStart = (int)sRdr.iIn; + }else{ + pNew->iStart = ftell(sRdr.in); } + csv_reader_reset(&sRdr); rc = sqlite3_declare_vtab(db, CSV_SCHEMA); - if( rc ) goto csvtab_connect_error; + if( rc ){ + csv_errmsg(&sRdr, "bad schema: '%s' - %s", CSV_SCHEMA, sqlite3_errmsg(db)); + goto csvtab_connect_error; + } for(i=0; i<sizeof(azPValue)/sizeof(azPValue[0]); i++){ sqlite3_free(azPValue[i]); }
diff --git a/third_party/sqlite/src/ext/misc/explain.c b/third_party/sqlite/src/ext/misc/explain.c new file mode 100644 index 0000000..917b3ad7 --- /dev/null +++ b/third_party/sqlite/src/ext/misc/explain.c
@@ -0,0 +1,322 @@ +/* +** 2018-09-16 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file demonstrates an eponymous virtual table that returns the +** EXPLAIN output from an SQL statement. +** +** Usage example: +** +** .load ./explain +** SELECT p2 FROM explain('SELECT * FROM sqlite_master') +** WHERE opcode='OpenRead'; +** +** This module was originally written to help simplify SQLite testing, +** by providing an easier means of verifying certain patterns in the +** generated bytecode. +*/ +#if !defined(SQLITEINT_H) +#include "sqlite3ext.h" +#endif +SQLITE_EXTENSION_INIT1 +#include <assert.h> +#include <string.h> + +#ifndef SQLITE_OMIT_VIRTUALTABLE + +/* explain_vtab is a subclass of sqlite3_vtab which will +** serve as the underlying representation of a explain virtual table +*/ +typedef struct explain_vtab explain_vtab; +struct explain_vtab { + sqlite3_vtab base; /* Base class - must be first */ + sqlite3 *db; /* Database connection for this explain vtab */ +}; + +/* explain_cursor is a subclass of sqlite3_vtab_cursor which will +** serve as the underlying representation of a cursor that scans +** over rows of the result from an EXPLAIN operation. +*/ +typedef struct explain_cursor explain_cursor; +struct explain_cursor { + sqlite3_vtab_cursor base; /* Base class - must be first */ + sqlite3 *db; /* Database connection for this cursor */ + char *zSql; /* Value for the EXPLN_COLUMN_SQL column */ + sqlite3_stmt *pExplain; /* Statement being explained */ + int rc; /* Result of last sqlite3_step() on pExplain */ +}; + +/* +** The explainConnect() method is invoked to create a new +** explain_vtab that describes the explain virtual table. +** +** Think of this routine as the constructor for explain_vtab objects. +** +** All this routine needs to do is: +** +** (1) Allocate the explain_vtab object and initialize all fields. +** +** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the +** result set of queries against explain will look like. +*/ +static int explainConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + explain_vtab *pNew; + int rc; + +/* Column numbers */ +#define EXPLN_COLUMN_ADDR 0 /* Instruction address */ +#define EXPLN_COLUMN_OPCODE 1 /* Opcode */ +#define EXPLN_COLUMN_P1 2 /* Operand 1 */ +#define EXPLN_COLUMN_P2 3 /* Operand 2 */ +#define EXPLN_COLUMN_P3 4 /* Operand 3 */ +#define EXPLN_COLUMN_P4 5 /* Operand 4 */ +#define EXPLN_COLUMN_P5 6 /* Operand 5 */ +#define EXPLN_COLUMN_COMMENT 7 /* Comment */ +#define EXPLN_COLUMN_SQL 8 /* SQL that is being explained */ + + + rc = sqlite3_declare_vtab(db, + "CREATE TABLE x(addr,opcode,p1,p2,p3,p4,p5,comment,sql HIDDEN)"); + if( rc==SQLITE_OK ){ + pNew = sqlite3_malloc( sizeof(*pNew) ); + *ppVtab = (sqlite3_vtab*)pNew; + if( pNew==0 ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(*pNew)); + pNew->db = db; + } + return rc; +} + +/* +** This method is the destructor for explain_cursor objects. +*/ +static int explainDisconnect(sqlite3_vtab *pVtab){ + sqlite3_free(pVtab); + return SQLITE_OK; +} + +/* +** Constructor for a new explain_cursor object. +*/ +static int explainOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ + explain_cursor *pCur; + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + pCur->db = ((explain_vtab*)p)->db; + *ppCursor = &pCur->base; + return SQLITE_OK; +} + +/* +** Destructor for a explain_cursor. +*/ +static int explainClose(sqlite3_vtab_cursor *cur){ + explain_cursor *pCur = (explain_cursor*)cur; + sqlite3_finalize(pCur->pExplain); + sqlite3_free(pCur->zSql); + sqlite3_free(pCur); + return SQLITE_OK; +} + + +/* +** Advance a explain_cursor to its next row of output. +*/ +static int explainNext(sqlite3_vtab_cursor *cur){ + explain_cursor *pCur = (explain_cursor*)cur; + pCur->rc = sqlite3_step(pCur->pExplain); + if( pCur->rc!=SQLITE_DONE && pCur->rc!=SQLITE_ROW ) return pCur->rc; + return SQLITE_OK; +} + +/* +** Return values of columns for the row at which the explain_cursor +** is currently pointing. +*/ +static int explainColumn( + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int i /* Which column to return */ +){ + explain_cursor *pCur = (explain_cursor*)cur; + if( i==EXPLN_COLUMN_SQL ){ + sqlite3_result_text(ctx, pCur->zSql, -1, SQLITE_TRANSIENT); + }else{ + sqlite3_result_value(ctx, sqlite3_column_value(pCur->pExplain, i)); + } + return SQLITE_OK; +} + +/* +** Return the rowid for the current row. In this implementation, the +** rowid is the same as the output value. +*/ +static int explainRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + explain_cursor *pCur = (explain_cursor*)cur; + *pRowid = sqlite3_column_int64(pCur->pExplain, 0); + return SQLITE_OK; +} + +/* +** Return TRUE if the cursor has been moved off of the last +** row of output. +*/ +static int explainEof(sqlite3_vtab_cursor *cur){ + explain_cursor *pCur = (explain_cursor*)cur; + return pCur->rc!=SQLITE_ROW; +} + +/* +** This method is called to "rewind" the explain_cursor object back +** to the first row of output. This method is always called at least +** once prior to any call to explainColumn() or explainRowid() or +** explainEof(). +** +** The argv[0] is the SQL statement that is to be explained. +*/ +static int explainFilter( + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + explain_cursor *pCur = (explain_cursor *)pVtabCursor; + char *zSql = 0; + int rc; + sqlite3_finalize(pCur->pExplain); + pCur->pExplain = 0; + if( sqlite3_value_type(argv[0])!=SQLITE_TEXT ){ + pCur->rc = SQLITE_DONE; + return SQLITE_OK; + } + sqlite3_free(pCur->zSql); + pCur->zSql = sqlite3_mprintf("%s", sqlite3_value_text(argv[0])); + if( pCur->zSql ){ + zSql = sqlite3_mprintf("EXPLAIN %s", pCur->zSql); + } + if( zSql==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pExplain, 0); + sqlite3_free(zSql); + } + if( rc ){ + sqlite3_finalize(pCur->pExplain); + pCur->pExplain = 0; + sqlite3_free(pCur->zSql); + pCur->zSql = 0; + }else{ + pCur->rc = sqlite3_step(pCur->pExplain); + rc = (pCur->rc==SQLITE_DONE || pCur->rc==SQLITE_ROW) ? SQLITE_OK : pCur->rc; + } + return rc; +} + +/* +** SQLite will invoke this method one or more times while planning a query +** that uses the explain virtual table. This routine needs to create +** a query plan for each invocation and compute an estimated cost for that +** plan. +*/ +static int explainBestIndex( + sqlite3_vtab *tab, + sqlite3_index_info *pIdxInfo +){ + int i; /* Loop counter */ + int idx = -1; /* Index of a usable == constraint against SQL */ + int unusable = 0; /* True if there are unusable constraints on SQL */ + + pIdxInfo->estimatedRows = 500; + for(i=0; i<pIdxInfo->nConstraint; i++){ + struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i]; + if( p->iColumn!=EXPLN_COLUMN_SQL ) continue; + if( !p->usable ){ + unusable = 1; + }else if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + idx = i; + } + } + if( idx>=0 ){ + /* There exists a usable == constraint against the SQL column */ + pIdxInfo->estimatedCost = 10.0; + pIdxInfo->idxNum = 1; + pIdxInfo->aConstraintUsage[idx].argvIndex = 1; + pIdxInfo->aConstraintUsage[idx].omit = 1; + }else if( unusable ){ + /* There are unusable constraints against the SQL column. Do not allow + ** this plan to continue forward. */ + return SQLITE_CONSTRAINT; + } + return SQLITE_OK; +} + +/* +** This following structure defines all the methods for the +** explain virtual table. +*/ +static sqlite3_module explainModule = { + 0, /* iVersion */ + 0, /* xCreate */ + explainConnect, /* xConnect */ + explainBestIndex, /* xBestIndex */ + explainDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + explainOpen, /* xOpen - open a cursor */ + explainClose, /* xClose - close a cursor */ + explainFilter, /* xFilter - configure scan constraints */ + explainNext, /* xNext - advance a cursor */ + explainEof, /* xEof - check for end of scan */ + explainColumn, /* xColumn - read data */ + explainRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ + 0, /* xShadowName */ +}; + +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +int sqlite3ExplainVtabInit(sqlite3 *db){ + int rc = SQLITE_OK; +#ifndef SQLITE_OMIT_VIRTUALTABLE + rc = sqlite3_create_module(db, "explain", &explainModule, 0); +#endif + return rc; +} + +#ifdef _WIN32 +__declspec(dllexport) +#endif +int sqlite3_explain_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + int rc = SQLITE_OK; + SQLITE_EXTENSION_INIT2(pApi); +#ifndef SQLITE_OMIT_VIRTUALTABLE + rc = sqlite3ExplainVtabInit(db); +#endif + return rc; +}
diff --git a/third_party/sqlite/src/ext/misc/fileio.c b/third_party/sqlite/src/ext/misc/fileio.c index a468127..49f6f8a 100644 --- a/third_party/sqlite/src/ext/misc/fileio.c +++ b/third_party/sqlite/src/ext/misc/fileio.c
@@ -106,7 +106,18 @@ #include <errno.h> +/* +** Structure of the fsdir() table-valued function +*/ + /* 0 1 2 3 4 5 */ #define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)" +#define FSDIR_COLUMN_NAME 0 /* Name of the file */ +#define FSDIR_COLUMN_MODE 1 /* Access mode */ +#define FSDIR_COLUMN_MTIME 2 /* Last modification time */ +#define FSDIR_COLUMN_DATA 3 /* File content */ +#define FSDIR_COLUMN_PATH 4 /* Path to top of search */ +#define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */ + /* ** Set the result stored by context ctx to a blob containing the @@ -695,20 +706,20 @@ ){ fsdir_cursor *pCur = (fsdir_cursor*)cur; switch( i ){ - case 0: { /* name */ + case FSDIR_COLUMN_NAME: { sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT); break; } - case 1: /* mode */ + case FSDIR_COLUMN_MODE: sqlite3_result_int64(ctx, pCur->sStat.st_mode); break; - case 2: /* mtime */ + case FSDIR_COLUMN_MTIME: sqlite3_result_int64(ctx, pCur->sStat.st_mtime); break; - case 3: { /* data */ + case FSDIR_COLUMN_DATA: { mode_t m = pCur->sStat.st_mode; if( S_ISDIR(m) ){ sqlite3_result_null(ctx); @@ -738,6 +749,12 @@ readFileContents(ctx, pCur->zPath); } } + case FSDIR_COLUMN_PATH: + default: { + /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters. + ** always return their values as NULL */ + break; + } } return SQLITE_OK; } @@ -764,6 +781,9 @@ /* ** xFilter callback. +** +** idxNum==1 PATH parameter only +** idxNum==2 Both PATH and DIR supplied */ static int fsdirFilter( sqlite3_vtab_cursor *cur, @@ -816,40 +836,63 @@ ** In this implementation idxNum is used to represent the ** query plan. idxStr is unused. ** -** The query plan is represented by bits in idxNum: +** The query plan is represented by values of idxNum: ** -** (1) start = $value -- constraint exists -** (2) stop = $value -- constraint exists -** (4) step = $value -- constraint exists -** (8) output in descending order +** (1) The path value is supplied by argv[0] +** (2) Path is in argv[0] and dir is in argv[1] */ static int fsdirBestIndex( sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ int i; /* Loop over constraints */ - int idx4 = -1; - int idx5 = -1; + int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */ + int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */ + int seenPath = 0; /* True if an unusable PATH= constraint is seen */ + int seenDir = 0; /* True if an unusable DIR= constraint is seen */ const struct sqlite3_index_constraint *pConstraint; (void)tab; pConstraint = pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ - if( pConstraint->usable==0 ) continue; if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; - if( pConstraint->iColumn==4 ) idx4 = i; - if( pConstraint->iColumn==5 ) idx5 = i; + switch( pConstraint->iColumn ){ + case FSDIR_COLUMN_PATH: { + if( pConstraint->usable ){ + idxPath = i; + seenPath = 0; + }else if( idxPath<0 ){ + seenPath = 1; + } + break; + } + case FSDIR_COLUMN_DIR: { + if( pConstraint->usable ){ + idxDir = i; + seenDir = 0; + }else if( idxDir<0 ){ + seenDir = 1; + } + break; + } + } + } + if( seenPath || seenDir ){ + /* If input parameters are unusable, disallow this plan */ + return SQLITE_CONSTRAINT; } - if( idx4<0 ){ + if( idxPath<0 ){ pIdxInfo->idxNum = 0; - pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50); + /* The pIdxInfo->estimatedCost should have been initialized to a huge + ** number. Leave it unchanged. */ + pIdxInfo->estimatedRows = 0x7fffffff; }else{ - pIdxInfo->aConstraintUsage[idx4].omit = 1; - pIdxInfo->aConstraintUsage[idx4].argvIndex = 1; - if( idx5>=0 ){ - pIdxInfo->aConstraintUsage[idx5].omit = 1; - pIdxInfo->aConstraintUsage[idx5].argvIndex = 2; + pIdxInfo->aConstraintUsage[idxPath].omit = 1; + pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1; + if( idxDir>=0 ){ + pIdxInfo->aConstraintUsage[idxDir].omit = 1; + pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2; pIdxInfo->idxNum = 2; pIdxInfo->estimatedCost = 10.0; }else{ @@ -888,7 +931,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0, /* xShadowName */ }; int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
diff --git a/third_party/sqlite/src/ext/misc/json1.c b/third_party/sqlite/src/ext/misc/json1.c index f3c3b1cf..2a99e3b 100644 --- a/third_party/sqlite/src/ext/misc/json1.c +++ b/third_party/sqlite/src/ext/misc/json1.c
@@ -1994,6 +1994,9 @@ #define JEACH_PARENT 5 #define JEACH_FULLKEY 6 #define JEACH_PATH 7 +/* The xBestIndex method assumes that the JSON and ROOT columns are +** the last two columns in the table. Should this ever changes, be +** sure to update the xBestIndex method. */ #define JEACH_JSON 8 #define JEACH_ROOT 9 @@ -2251,35 +2254,54 @@ sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ - int i; - int jsonIdx = -1; - int rootIdx = -1; + int i; /* Loop counter or computed array index */ + int aIdx[2]; /* Index of constraints for JSON and ROOT */ + int unusableMask = 0; /* Mask of unusable JSON and ROOT constraints */ + int idxMask = 0; /* Mask of usable == constraints JSON and ROOT */ const struct sqlite3_index_constraint *pConstraint; + /* This implementation assumes that JSON and ROOT are the last two + ** columns in the table */ + assert( JEACH_ROOT == JEACH_JSON+1 ); UNUSED_PARAM(tab); + aIdx[0] = aIdx[1] = -1; pConstraint = pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ - if( pConstraint->usable==0 ) continue; - if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; - switch( pConstraint->iColumn ){ - case JEACH_JSON: jsonIdx = i; break; - case JEACH_ROOT: rootIdx = i; break; - default: /* no-op */ break; + int iCol; + int iMask; + if( pConstraint->iColumn < JEACH_JSON ) continue; + iCol = pConstraint->iColumn - JEACH_JSON; + assert( iCol==0 || iCol==1 ); + iMask = 1 << iCol; + if( pConstraint->usable==0 ){ + unusableMask |= iMask; + }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + aIdx[iCol] = i; + idxMask |= iMask; } } - if( jsonIdx<0 ){ + if( (unusableMask & ~idxMask)!=0 ){ + /* If there are any unusable constraints on JSON or ROOT, then reject + ** this entire plan */ + return SQLITE_CONSTRAINT; + } + if( aIdx[0]<0 ){ + /* No JSON input. Leave estimatedCost at the huge value that it was + ** initialized to to discourage the query planner from selecting this + ** plan. */ pIdxInfo->idxNum = 0; - pIdxInfo->estimatedCost = 1e99; }else{ pIdxInfo->estimatedCost = 1.0; - pIdxInfo->aConstraintUsage[jsonIdx].argvIndex = 1; - pIdxInfo->aConstraintUsage[jsonIdx].omit = 1; - if( rootIdx<0 ){ - pIdxInfo->idxNum = 1; + i = aIdx[0]; + pIdxInfo->aConstraintUsage[i].argvIndex = 1; + pIdxInfo->aConstraintUsage[i].omit = 1; + if( aIdx[1]<0 ){ + pIdxInfo->idxNum = 1; /* Only JSON supplied. Plan 1 */ }else{ - pIdxInfo->aConstraintUsage[rootIdx].argvIndex = 2; - pIdxInfo->aConstraintUsage[rootIdx].omit = 1; - pIdxInfo->idxNum = 3; + i = aIdx[1]; + pIdxInfo->aConstraintUsage[i].argvIndex = 2; + pIdxInfo->aConstraintUsage[i].omit = 1; + pIdxInfo->idxNum = 3; /* Both JSON and ROOT are supplied. Plan 3 */ } } return SQLITE_OK; @@ -2388,7 +2410,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; /* The methods of the json_tree virtual table. */ @@ -2415,7 +2438,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/third_party/sqlite/src/ext/misc/memstat.c b/third_party/sqlite/src/ext/misc/memstat.c new file mode 100644 index 0000000..f072398 --- /dev/null +++ b/third_party/sqlite/src/ext/misc/memstat.c
@@ -0,0 +1,428 @@ +/* +** 2018-09-27 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file demonstrates an eponymous virtual table that returns information +** from sqlite3_status64() and sqlite3_db_status(). +** +** Usage example: +** +** .load ./memstat +** .mode quote +** .header on +** SELECT * FROM memstat; +*/ +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_MEMSTATVTAB) +#if !defined(SQLITEINT_H) +#include "sqlite3ext.h" +#endif +SQLITE_EXTENSION_INIT1 +#include <assert.h> +#include <string.h> + +#ifndef SQLITE_OMIT_VIRTUALTABLE + +/* memstat_vtab is a subclass of sqlite3_vtab which will +** serve as the underlying representation of a memstat virtual table +*/ +typedef struct memstat_vtab memstat_vtab; +struct memstat_vtab { + sqlite3_vtab base; /* Base class - must be first */ + sqlite3 *db; /* Database connection for this memstat vtab */ +}; + +/* memstat_cursor is a subclass of sqlite3_vtab_cursor which will +** serve as the underlying representation of a cursor that scans +** over rows of the result +*/ +typedef struct memstat_cursor memstat_cursor; +struct memstat_cursor { + sqlite3_vtab_cursor base; /* Base class - must be first */ + sqlite3 *db; /* Database connection for this cursor */ + int iRowid; /* Current row in aMemstatColumn[] */ + int iDb; /* Which schema we are looking at */ + int nDb; /* Number of schemas */ + char **azDb; /* Names of all schemas */ + sqlite3_int64 aVal[2]; /* Result values */ +}; + +/* +** The memstatConnect() method is invoked to create a new +** memstat_vtab that describes the memstat virtual table. +** +** Think of this routine as the constructor for memstat_vtab objects. +** +** All this routine needs to do is: +** +** (1) Allocate the memstat_vtab object and initialize all fields. +** +** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the +** result set of queries against memstat will look like. +*/ +static int memstatConnect( + sqlite3 *db, + void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVtab, + char **pzErr +){ + memstat_vtab *pNew; + int rc; + +/* Column numbers */ +#define MSV_COLUMN_NAME 0 /* Name of quantity being measured */ +#define MSV_COLUMN_SCHEMA 1 /* schema name */ +#define MSV_COLUMN_VALUE 2 /* Current value */ +#define MSV_COLUMN_HIWTR 3 /* Highwater mark */ + + rc = sqlite3_declare_vtab(db,"CREATE TABLE x(name,schema,value,hiwtr)"); + if( rc==SQLITE_OK ){ + pNew = sqlite3_malloc( sizeof(*pNew) ); + *ppVtab = (sqlite3_vtab*)pNew; + if( pNew==0 ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(*pNew)); + pNew->db = db; + } + return rc; +} + +/* +** This method is the destructor for memstat_cursor objects. +*/ +static int memstatDisconnect(sqlite3_vtab *pVtab){ + sqlite3_free(pVtab); + return SQLITE_OK; +} + +/* +** Constructor for a new memstat_cursor object. +*/ +static int memstatOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ + memstat_cursor *pCur; + pCur = sqlite3_malloc( sizeof(*pCur) ); + if( pCur==0 ) return SQLITE_NOMEM; + memset(pCur, 0, sizeof(*pCur)); + pCur->db = ((memstat_vtab*)p)->db; + *ppCursor = &pCur->base; + return SQLITE_OK; +} + +/* +** Clear all the schema names from a cursor +*/ +static void memstatClearSchema(memstat_cursor *pCur){ + int i; + if( pCur->azDb==0 ) return; + for(i=0; i<pCur->nDb; i++){ + sqlite3_free(pCur->azDb[i]); + } + sqlite3_free(pCur->azDb); + pCur->azDb = 0; + pCur->nDb = 0; +} + +/* +** Fill in the azDb[] array for the cursor. +*/ +static int memstatFindSchemas(memstat_cursor *pCur){ + sqlite3_stmt *pStmt = 0; + int rc; + if( pCur->nDb ) return SQLITE_OK; + rc = sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pStmt, 0); + if( rc ){ + sqlite3_finalize(pStmt); + return rc; + } + while( sqlite3_step(pStmt)==SQLITE_ROW ){ + char **az, *z; + az = sqlite3_realloc(pCur->azDb, sizeof(char*)*(pCur->nDb+1)); + if( az==0 ){ + memstatClearSchema(pCur); + return SQLITE_NOMEM; + } + pCur->azDb = az; + z = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1)); + if( z==0 ){ + memstatClearSchema(pCur); + return SQLITE_NOMEM; + } + pCur->azDb[pCur->nDb] = z; + pCur->nDb++; + } + sqlite3_finalize(pStmt); + return SQLITE_OK; +} + + +/* +** Destructor for a memstat_cursor. +*/ +static int memstatClose(sqlite3_vtab_cursor *cur){ + memstat_cursor *pCur = (memstat_cursor*)cur; + memstatClearSchema(pCur); + sqlite3_free(cur); + return SQLITE_OK; +} + + +/* +** Allowed values for aMemstatColumn[].eType +*/ +#define MSV_GSTAT 0 /* sqlite3_status64() information */ +#define MSV_DB 1 /* sqlite3_db_status() information */ +#define MSV_ZIPVFS 2 /* ZIPVFS file-control with 64-bit return */ + +/* +** An array of quantities that can be measured and reported by +** this virtual table +*/ +static const struct MemstatColumns { + const char *zName; /* Symbolic name */ + unsigned char eType; /* Type of interface */ + unsigned char mNull; /* Bitmask of which columns are NULL */ + /* 2: dbname, 4: current, 8: hiwtr */ + int eOp; /* Opcode */ +} aMemstatColumn[] = { + {"MEMORY_USED", MSV_GSTAT, 2, SQLITE_STATUS_MEMORY_USED }, + {"MALLOC_SIZE", MSV_GSTAT, 6, SQLITE_STATUS_MALLOC_SIZE }, + {"MALLOC_COUNT", MSV_GSTAT, 2, SQLITE_STATUS_MALLOC_COUNT }, + {"PAGECACHE_USED", MSV_GSTAT, 2, SQLITE_STATUS_PAGECACHE_USED }, + {"PAGECACHE_OVERFLOW", MSV_GSTAT, 2, SQLITE_STATUS_PAGECACHE_OVERFLOW }, + {"PAGECACHE_SIZE", MSV_GSTAT, 6, SQLITE_STATUS_PAGECACHE_SIZE }, + {"PARSER_STACK", MSV_GSTAT, 6, SQLITE_STATUS_PARSER_STACK }, + {"DB_LOOKASIDE_USED", MSV_DB, 2, SQLITE_DBSTATUS_LOOKASIDE_USED }, + {"DB_LOOKASIDE_HIT", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_HIT }, + {"DB_LOOKASIDE_MISS_SIZE", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE}, + {"DB_LOOKASIDE_MISS_FULL", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL}, + {"DB_CACHE_USED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED }, +#if SQLITE_VERSION_NUMBER >= 3140000 + {"DB_CACHE_USED_SHARED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED_SHARED }, +#endif + {"DB_SCHEMA_USED", MSV_DB, 10, SQLITE_DBSTATUS_SCHEMA_USED }, + {"DB_STMT_USED", MSV_DB, 10, SQLITE_DBSTATUS_STMT_USED }, + {"DB_CACHE_HIT", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_HIT }, + {"DB_CACHE_MISS", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_MISS }, + {"DB_CACHE_WRITE", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_WRITE }, +#if SQLITE_VERSION_NUMBER >= 3230000 + {"DB_CACHE_SPILL", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_SPILL }, +#endif + {"DB_DEFERRED_FKS", MSV_DB, 10, SQLITE_DBSTATUS_DEFERRED_FKS }, +#ifdef SQLITE_ENABLE_ZIPVFS + {"ZIPVFS_CACHE_USED", MSV_ZIPVFS, 8, 231454 }, + {"ZIPVFS_CACHE_HIT", MSV_ZIPVFS, 8, 231455 }, + {"ZIPVFS_CACHE_MISS", MSV_ZIPVFS, 8, 231456 }, + {"ZIPVFS_CACHE_WRITE", MSV_ZIPVFS, 8, 231457 }, + {"ZIPVFS_DIRECT_READ", MSV_ZIPVFS, 8, 231458 }, + {"ZIPVFS_DIRECT_BYTES", MSV_ZIPVFS, 8, 231459 }, +#endif /* SQLITE_ENABLE_ZIPVFS */ +}; +#define MSV_NROW (sizeof(aMemstatColumn)/sizeof(aMemstatColumn[0])) + +/* +** Advance a memstat_cursor to its next row of output. +*/ +static int memstatNext(sqlite3_vtab_cursor *cur){ + memstat_cursor *pCur = (memstat_cursor*)cur; + int i; + assert( pCur->iRowid<=MSV_NROW ); + while(1){ + i = (int)pCur->iRowid - 1; + if( i<0 || (aMemstatColumn[i].mNull & 2)!=0 || (++pCur->iDb)>=pCur->nDb ){ + pCur->iRowid++; + if( pCur->iRowid>MSV_NROW ) return SQLITE_OK; /* End of the table */ + pCur->iDb = 0; + i++; + } + pCur->aVal[0] = 0; + pCur->aVal[1] = 0; + switch( aMemstatColumn[i].eType ){ + case MSV_GSTAT: { + if( sqlite3_libversion_number()>=3010000 ){ + sqlite3_status64(aMemstatColumn[i].eOp, + &pCur->aVal[0], &pCur->aVal[1],0); + }else{ + int xCur, xHiwtr; + sqlite3_status(aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0); + pCur->aVal[0] = xCur; + pCur->aVal[1] = xHiwtr; + } + break; + } + case MSV_DB: { + int xCur, xHiwtr; + sqlite3_db_status(pCur->db, aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0); + pCur->aVal[0] = xCur; + pCur->aVal[1] = xHiwtr; + break; + } + case MSV_ZIPVFS: { + int rc; + rc = sqlite3_file_control(pCur->db, pCur->azDb[pCur->iDb], + aMemstatColumn[i].eOp, (void*)&pCur->aVal[0]); + if( rc!=SQLITE_OK ) continue; + break; + } + } + break; + } + return SQLITE_OK; +} + + +/* +** Return values of columns for the row at which the memstat_cursor +** is currently pointing. +*/ +static int memstatColumn( + sqlite3_vtab_cursor *cur, /* The cursor */ + sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ + int iCol /* Which column to return */ +){ + memstat_cursor *pCur = (memstat_cursor*)cur; + int i; + assert( pCur->iRowid>0 && pCur->iRowid<=MSV_NROW ); + i = (int)pCur->iRowid - 1; + if( (aMemstatColumn[i].mNull & (1<<iCol))!=0 ){ + return SQLITE_OK; + } + switch( iCol ){ + case MSV_COLUMN_NAME: { + sqlite3_result_text(ctx, aMemstatColumn[i].zName, -1, SQLITE_STATIC); + break; + } + case MSV_COLUMN_SCHEMA: { + sqlite3_result_text(ctx, pCur->azDb[pCur->iDb], -1, 0); + break; + } + case MSV_COLUMN_VALUE: { + sqlite3_result_int64(ctx, pCur->aVal[0]); + break; + } + case MSV_COLUMN_HIWTR: { + sqlite3_result_int64(ctx, pCur->aVal[1]); + break; + } + } + return SQLITE_OK; +} + +/* +** Return the rowid for the current row. In this implementation, the +** rowid is the same as the output value. +*/ +static int memstatRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + memstat_cursor *pCur = (memstat_cursor*)cur; + *pRowid = pCur->iRowid*1000 + pCur->iDb; + return SQLITE_OK; +} + +/* +** Return TRUE if the cursor has been moved off of the last +** row of output. +*/ +static int memstatEof(sqlite3_vtab_cursor *cur){ + memstat_cursor *pCur = (memstat_cursor*)cur; + return pCur->iRowid>MSV_NROW; +} + +/* +** This method is called to "rewind" the memstat_cursor object back +** to the first row of output. This method is always called at least +** once prior to any call to memstatColumn() or memstatRowid() or +** memstatEof(). +*/ +static int memstatFilter( + sqlite3_vtab_cursor *pVtabCursor, + int idxNum, const char *idxStr, + int argc, sqlite3_value **argv +){ + memstat_cursor *pCur = (memstat_cursor *)pVtabCursor; + int rc = memstatFindSchemas(pCur); + if( rc ) return rc; + pCur->iRowid = 0; + pCur->iDb = 0; + return memstatNext(pVtabCursor); +} + +/* +** SQLite will invoke this method one or more times while planning a query +** that uses the memstat virtual table. This routine needs to create +** a query plan for each invocation and compute an estimated cost for that +** plan. +*/ +static int memstatBestIndex( + sqlite3_vtab *tab, + sqlite3_index_info *pIdxInfo +){ + pIdxInfo->estimatedCost = (double)500; + pIdxInfo->estimatedRows = 500; + return SQLITE_OK; +} + +/* +** This following structure defines all the methods for the +** memstat virtual table. +*/ +static sqlite3_module memstatModule = { + 0, /* iVersion */ + 0, /* xCreate */ + memstatConnect, /* xConnect */ + memstatBestIndex, /* xBestIndex */ + memstatDisconnect, /* xDisconnect */ + 0, /* xDestroy */ + memstatOpen, /* xOpen - open a cursor */ + memstatClose, /* xClose - close a cursor */ + memstatFilter, /* xFilter - configure scan constraints */ + memstatNext, /* xNext - advance a cursor */ + memstatEof, /* xEof - check for end of scan */ + memstatColumn, /* xColumn - read data */ + memstatRowid, /* xRowid - read data */ + 0, /* xUpdate */ + 0, /* xBegin */ + 0, /* xSync */ + 0, /* xCommit */ + 0, /* xRollback */ + 0, /* xFindMethod */ + 0, /* xRename */ + 0, /* xSavepoint */ + 0, /* xRelease */ + 0, /* xRollbackTo */ + 0, /* xShadowName */ +}; + +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + +int sqlite3MemstatVtabInit(sqlite3 *db){ + int rc = SQLITE_OK; +#ifndef SQLITE_OMIT_VIRTUALTABLE + rc = sqlite3_create_module(db, "sqlite_memstat", &memstatModule, 0); +#endif + return rc; +} + +#ifndef SQLITE_CORE +#ifdef _WIN32 +__declspec(dllexport) +#endif +int sqlite3_memstat_init( + sqlite3 *db, + char **pzErrMsg, + const sqlite3_api_routines *pApi +){ + int rc = SQLITE_OK; + SQLITE_EXTENSION_INIT2(pApi); +#ifndef SQLITE_OMIT_VIRTUALTABLE + rc = sqlite3MemstatVtabInit(db); +#endif + return rc; +} +#endif /* SQLITE_CORE */ +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_MEMSTATVTAB) */
diff --git a/third_party/sqlite/src/ext/misc/series.c b/third_party/sqlite/src/ext/misc/series.c index cf591bf..2c69b741 100644 --- a/third_party/sqlite/src/ext/misc/series.c +++ b/third_party/sqlite/src/ext/misc/series.c
@@ -313,44 +313,45 @@ sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo ){ - int i; /* Loop over constraints */ + int i, j; /* Loop over constraints */ int idxNum = 0; /* The query plan bitmask */ - int startIdx = -1; /* Index of the start= constraint, or -1 if none */ - int stopIdx = -1; /* Index of the stop= constraint, or -1 if none */ - int stepIdx = -1; /* Index of the step= constraint, or -1 if none */ + int unusableMask = 0; /* Mask of unusable constraints */ int nArg = 0; /* Number of arguments that seriesFilter() expects */ - + int aIdx[3]; /* Constraints on start, stop, and step */ const struct sqlite3_index_constraint *pConstraint; + + /* This implementation assumes that the start, stop, and step columns + ** are the last three columns in the virtual table. */ + assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 ); + assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 ); + aIdx[0] = aIdx[1] = aIdx[2] = -1; pConstraint = pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){ - if( pConstraint->usable==0 ) continue; - if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; - switch( pConstraint->iColumn ){ - case SERIES_COLUMN_START: - startIdx = i; - idxNum |= 1; - break; - case SERIES_COLUMN_STOP: - stopIdx = i; - idxNum |= 2; - break; - case SERIES_COLUMN_STEP: - stepIdx = i; - idxNum |= 4; - break; + int iCol; /* 0 for start, 1 for stop, 2 for step */ + int iMask; /* bitmask for those column */ + if( pConstraint->iColumn<SERIES_COLUMN_START ) continue; + iCol = pConstraint->iColumn - SERIES_COLUMN_START; + assert( iCol>=0 && iCol<=2 ); + iMask = 1 << iCol; + if( pConstraint->usable==0 ){ + unusableMask |= iMask; + continue; + }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + idxNum |= iMask; + aIdx[iCol] = i; } } - if( startIdx>=0 ){ - pIdxInfo->aConstraintUsage[startIdx].argvIndex = ++nArg; - pIdxInfo->aConstraintUsage[startIdx].omit= !SQLITE_SERIES_CONSTRAINT_VERIFY; + for(i=0; i<3; i++){ + if( (j = aIdx[i])>=0 ){ + pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg; + pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY; + } } - if( stopIdx>=0 ){ - pIdxInfo->aConstraintUsage[stopIdx].argvIndex = ++nArg; - pIdxInfo->aConstraintUsage[stopIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY; - } - if( stepIdx>=0 ){ - pIdxInfo->aConstraintUsage[stepIdx].argvIndex = ++nArg; - pIdxInfo->aConstraintUsage[stepIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY; + if( (unusableMask & ~idxNum)!=0 ){ + /* The start, stop, and step columns are inputs. Therefore if there + ** are unusable constraints on any of start, stop, or step then + ** this plan is unusable */ + return SQLITE_CONSTRAINT; } if( (idxNum & 3)==3 ){ /* Both start= and stop= boundaries are available. This is the @@ -365,7 +366,6 @@ /* If either boundary is missing, we have to generate a huge span ** of numbers. Make this case very expensive so that the query ** planner will work hard to avoid it. */ - pIdxInfo->estimatedCost = (double)2147483647; pIdxInfo->estimatedRows = 2147483647; } pIdxInfo->idxNum = idxNum;
diff --git a/third_party/sqlite/src/ext/misc/sha1.c b/third_party/sqlite/src/ext/misc/sha1.c index e2843bd..886b1db 100644 --- a/third_party/sqlite/src/ext/misc/sha1.c +++ b/third_party/sqlite/src/ext/misc/sha1.c
@@ -10,7 +10,7 @@ ** ****************************************************************************** ** -** This SQLite extension implements a functions that compute SHA1 hashes. +** This SQLite extension implements functions that compute SHA1 hashes. ** Two SQL functions are implemented: ** ** sha1(X)
diff --git a/third_party/sqlite/src/ext/misc/shathree.c b/third_party/sqlite/src/ext/misc/shathree.c index 9ffa120..e5ae69af 100644 --- a/third_party/sqlite/src/ext/misc/shathree.c +++ b/third_party/sqlite/src/ext/misc/shathree.c
@@ -10,7 +10,7 @@ ** ****************************************************************************** ** -** This SQLite extension implements a functions that compute SHA1 hashes. +** This SQLite extension implements functions that compute SHA3 hashes. ** Two SQL functions are implemented: ** ** sha3(X,SIZE)
diff --git a/third_party/sqlite/src/ext/misc/spellfix.c b/third_party/sqlite/src/ext/misc/spellfix.c index 981bd391..271f561 100644 --- a/third_party/sqlite/src/ext/misc/spellfix.c +++ b/third_party/sqlite/src/ext/misc/spellfix.c
@@ -1295,6 +1295,9 @@ struct Transliteration { unsigned short int cFrom; unsigned char cTo0, cTo1, cTo2, cTo3; +#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS + unsigned char cTo4; +#endif }; /* @@ -1708,7 +1711,11 @@ ** should be freed by the caller. */ static unsigned char *transliterate(const unsigned char *zIn, int nIn){ +#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS + unsigned char *zOut = sqlite3_malloc64( nIn*5 + 1 ); +#else unsigned char *zOut = sqlite3_malloc64( nIn*4 + 1 ); +#endif int c, sz, nOut; if( zOut==0 ) return 0; nOut = 0; @@ -1732,6 +1739,11 @@ zOut[nOut++] = tbl[x].cTo2; if( tbl[x].cTo3 ){ zOut[nOut++] = tbl[x].cTo3; +#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS + if( tbl[x].cTo4 ){ + zOut[nOut++] = tbl[x].cTo4; + } +#endif /* SQLITE_SPELLFIX_5BYTE_MAPPINGS */ } } }
diff --git a/third_party/sqlite/src/ext/misc/stmt.c b/third_party/sqlite/src/ext/misc/stmt.c index be216ee..5983e12 100644 --- a/third_party/sqlite/src/ext/misc/stmt.c +++ b/third_party/sqlite/src/ext/misc/stmt.c
@@ -266,6 +266,7 @@ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ + 0, /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/third_party/sqlite/src/ext/misc/templatevtab.c b/third_party/sqlite/src/ext/misc/templatevtab.c index 31d7c4e..5202487 100644 --- a/third_party/sqlite/src/ext/misc/templatevtab.c +++ b/third_party/sqlite/src/ext/misc/templatevtab.c
@@ -248,7 +248,8 @@ /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, - /* xRollbackTo */ 0 + /* xRollbackTo */ 0, + /* xShadowName */ 0 };
diff --git a/third_party/sqlite/src/ext/misc/unionvtab.c b/third_party/sqlite/src/ext/misc/unionvtab.c index ed58ed3..8a1d493 100644 --- a/third_party/sqlite/src/ext/misc/unionvtab.c +++ b/third_party/sqlite/src/ext/misc/unionvtab.c
@@ -1350,7 +1350,8 @@ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; int rc;
diff --git a/third_party/sqlite/src/ext/misc/vtablog.c b/third_party/sqlite/src/ext/misc/vtablog.c index e183906..8312387 100644 --- a/third_party/sqlite/src/ext/misc/vtablog.c +++ b/third_party/sqlite/src/ext/misc/vtablog.c
@@ -492,6 +492,7 @@ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ + 0, /* xShadowName */ }; #ifdef _WIN32
diff --git a/third_party/sqlite/src/ext/misc/zipfile.c b/third_party/sqlite/src/ext/misc/zipfile.c index 0466c81..a69f3a7e 100644 --- a/third_party/sqlite/src/ext/misc/zipfile.c +++ b/third_party/sqlite/src/ext/misc/zipfile.c
@@ -1296,25 +1296,26 @@ sqlite3_index_info *pIdxInfo ){ int i; + int idx = -1; + int unusable = 0; for(i=0; i<pIdxInfo->nConstraint; i++){ const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i]; - if( pCons->usable==0 ) continue; - if( pCons->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue; - break; + if( pCons->usable==0 ){ + unusable = 1; + }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){ + idx = i; + } } - - if( i<pIdxInfo->nConstraint ){ - pIdxInfo->aConstraintUsage[i].argvIndex = 1; - pIdxInfo->aConstraintUsage[i].omit = 1; + if( idx>=0 ){ + pIdxInfo->aConstraintUsage[idx].argvIndex = 1; + pIdxInfo->aConstraintUsage[idx].omit = 1; pIdxInfo->estimatedCost = 1000.0; pIdxInfo->idxNum = 1; - }else{ - pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50); - pIdxInfo->idxNum = 0; + }else if( unusable ){ + return SQLITE_CONSTRAINT; } - return SQLITE_OK; }
diff --git a/third_party/sqlite/src/ext/rbu/rbu1.test b/third_party/sqlite/src/ext/rbu/rbu1.test index baa382a..5552f40 100644 --- a/third_party/sqlite/src/ext/rbu/rbu1.test +++ b/third_party/sqlite/src/ext/rbu/rbu1.test
@@ -670,4 +670,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbu10.test b/third_party/sqlite/src/ext/rbu/rbu10.test index 98d6076..a2c7258 100644 --- a/third_party/sqlite/src/ext/rbu/rbu10.test +++ b/third_party/sqlite/src/ext/rbu/rbu10.test
@@ -185,4 +185,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbu11.test b/third_party/sqlite/src/ext/rbu/rbu11.test index 77b7a09..8244e4c3 100644 --- a/third_party/sqlite/src/ext/rbu/rbu11.test +++ b/third_party/sqlite/src/ext/rbu/rbu11.test
@@ -195,4 +195,3 @@ } {1 {SQLITE_ERROR - rbu_state mismatch error}} finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbu12.test b/third_party/sqlite/src/ext/rbu/rbu12.test index 20b1d9e..43126b1 100644 --- a/third_party/sqlite/src/ext/rbu/rbu12.test +++ b/third_party/sqlite/src/ext/rbu/rbu12.test
@@ -232,4 +232,3 @@ } finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbu13.test b/third_party/sqlite/src/ext/rbu/rbu13.test index ad67a98..624c587c 100644 --- a/third_party/sqlite/src/ext/rbu/rbu13.test +++ b/third_party/sqlite/src/ext/rbu/rbu13.test
@@ -62,4 +62,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbu14.test b/third_party/sqlite/src/ext/rbu/rbu14.test index c4c3be6b..ce0055d 100644 --- a/third_party/sqlite/src/ext/rbu/rbu14.test +++ b/third_party/sqlite/src/ext/rbu/rbu14.test
@@ -92,4 +92,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbu3.test b/third_party/sqlite/src/ext/rbu/rbu3.test index 7d418d8..7751c6c 100644 --- a/third_party/sqlite/src/ext/rbu/rbu3.test +++ b/third_party/sqlite/src/ext/rbu/rbu3.test
@@ -203,5 +203,3 @@ do_test 6.1 { sqlite3rbu_internal_test } {} finish_test - -
diff --git a/third_party/sqlite/src/ext/rbu/rbu5.test b/third_party/sqlite/src/ext/rbu/rbu5.test index 94e38031..0542f60 100644 --- a/third_party/sqlite/src/ext/rbu/rbu5.test +++ b/third_party/sqlite/src/ext/rbu/rbu5.test
@@ -300,7 +300,3 @@ finish_test - - - -
diff --git a/third_party/sqlite/src/ext/rbu/rbu6.test b/third_party/sqlite/src/ext/rbu/rbu6.test index ad8dd78..979f545 100644 --- a/third_party/sqlite/src/ext/rbu/rbu6.test +++ b/third_party/sqlite/src/ext/rbu/rbu6.test
@@ -100,4 +100,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbu7.test b/third_party/sqlite/src/ext/rbu/rbu7.test index c2f2211..81704d21 100644 --- a/third_party/sqlite/src/ext/rbu/rbu7.test +++ b/third_party/sqlite/src/ext/rbu/rbu7.test
@@ -106,5 +106,3 @@ } finish_test - -
diff --git a/third_party/sqlite/src/ext/rbu/rbu8.test b/third_party/sqlite/src/ext/rbu/rbu8.test index 75edd4ef..c0ccd8c5 100644 --- a/third_party/sqlite/src/ext/rbu/rbu8.test +++ b/third_party/sqlite/src/ext/rbu/rbu8.test
@@ -72,4 +72,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbu9.test b/third_party/sqlite/src/ext/rbu/rbu9.test index 4524b0a..233eaa3 100644 --- a/third_party/sqlite/src/ext/rbu/rbu9.test +++ b/third_party/sqlite/src/ext/rbu/rbu9.test
@@ -125,4 +125,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbuA.test b/third_party/sqlite/src/ext/rbu/rbuA.test index 286194c..642caca 100644 --- a/third_party/sqlite/src/ext/rbu/rbuA.test +++ b/third_party/sqlite/src/ext/rbu/rbuA.test
@@ -80,4 +80,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbuB.test b/third_party/sqlite/src/ext/rbu/rbuB.test index bbc10a3..9d2ab59c 100644 --- a/third_party/sqlite/src/ext/rbu/rbuB.test +++ b/third_party/sqlite/src/ext/rbu/rbuB.test
@@ -59,4 +59,3 @@ test_sqlite3_log sqlite3_initialize finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbuC.test b/third_party/sqlite/src/ext/rbu/rbuC.test index e3083222..004def6 100644 --- a/third_party/sqlite/src/ext/rbu/rbuC.test +++ b/third_party/sqlite/src/ext/rbu/rbuC.test
@@ -139,4 +139,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbucollate.test b/third_party/sqlite/src/ext/rbu/rbucollate.test index a9c3b4d..62935b5a 100644 --- a/third_party/sqlite/src/ext/rbu/rbucollate.test +++ b/third_party/sqlite/src/ext/rbu/rbucollate.test
@@ -60,4 +60,3 @@ #forcedelete testrbu.db finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbucrash.test b/third_party/sqlite/src/ext/rbu/rbucrash.test index 8602b6a..8a9ca66 100644 --- a/third_party/sqlite/src/ext/rbu/rbucrash.test +++ b/third_party/sqlite/src/ext/rbu/rbucrash.test
@@ -145,4 +145,3 @@ } finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbucrash2.test b/third_party/sqlite/src/ext/rbu/rbucrash2.test index 6db3833..59e700e 100644 --- a/third_party/sqlite/src/ext/rbu/rbucrash2.test +++ b/third_party/sqlite/src/ext/rbu/rbucrash2.test
@@ -103,4 +103,3 @@ } finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbudiff.test b/third_party/sqlite/src/ext/rbu/rbudiff.test index 97e89b57..4dbfce2 100644 --- a/third_party/sqlite/src/ext/rbu/rbudiff.test +++ b/third_party/sqlite/src/ext/rbu/rbudiff.test
@@ -300,4 +300,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbudor.test b/third_party/sqlite/src/ext/rbu/rbudor.test index f69468c..16ba18b 100644 --- a/third_party/sqlite/src/ext/rbu/rbudor.test +++ b/third_party/sqlite/src/ext/rbu/rbudor.test
@@ -56,4 +56,3 @@ } [list 1 $bigA 2 $bigB] finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbufault.test b/third_party/sqlite/src/ext/rbu/rbufault.test index c7fb057..3e1642ce 100644 --- a/third_party/sqlite/src/ext/rbu/rbufault.test +++ b/third_party/sqlite/src/ext/rbu/rbufault.test
@@ -234,4 +234,3 @@ } finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbufault2.test b/third_party/sqlite/src/ext/rbu/rbufault2.test index 8e6a476..0f4542fa 100644 --- a/third_party/sqlite/src/ext/rbu/rbufault2.test +++ b/third_party/sqlite/src/ext/rbu/rbufault2.test
@@ -55,4 +55,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbufault3.test b/third_party/sqlite/src/ext/rbu/rbufault3.test index 3e8f8cc..cdf0d7f 100644 --- a/third_party/sqlite/src/ext/rbu/rbufault3.test +++ b/third_party/sqlite/src/ext/rbu/rbufault3.test
@@ -95,4 +95,3 @@ } finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbufault4.test b/third_party/sqlite/src/ext/rbu/rbufault4.test index 507a361..f1fe0c89 100644 --- a/third_party/sqlite/src/ext/rbu/rbufault4.test +++ b/third_party/sqlite/src/ext/rbu/rbufault4.test
@@ -63,4 +63,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbufts.test b/third_party/sqlite/src/ext/rbu/rbufts.test index dd41482..d065bfc 100644 --- a/third_party/sqlite/src/ext/rbu/rbufts.test +++ b/third_party/sqlite/src/ext/rbu/rbufts.test
@@ -131,4 +131,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbumulti.test b/third_party/sqlite/src/ext/rbu/rbumulti.test index 14880027..9be186f9 100644 --- a/third_party/sqlite/src/ext/rbu/rbumulti.test +++ b/third_party/sqlite/src/ext/rbu/rbumulti.test
@@ -172,4 +172,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbuprogress.test b/third_party/sqlite/src/ext/rbu/rbuprogress.test index 66c66e8a..058b89e 100644 --- a/third_party/sqlite/src/ext/rbu/rbuprogress.test +++ b/third_party/sqlite/src/ext/rbu/rbuprogress.test
@@ -416,4 +416,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rburesume.test b/third_party/sqlite/src/ext/rbu/rburesume.test index 5dc3c0e..2d118d16 100644 --- a/third_party/sqlite/src/ext/rbu/rburesume.test +++ b/third_party/sqlite/src/ext/rbu/rburesume.test
@@ -251,4 +251,3 @@ } finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbusave.test b/third_party/sqlite/src/ext/rbu/rbusave.test index eb94b62..fa7c445 100644 --- a/third_party/sqlite/src/ext/rbu/rbusave.test +++ b/third_party/sqlite/src/ext/rbu/rbusave.test
@@ -102,4 +102,3 @@ } {1 one 1 3 3 3 4 4 4 1 one 1 3 3 3 4 4 4} finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbusplit.test b/third_party/sqlite/src/ext/rbu/rbusplit.test index 8e088fe..9bd689af 100644 --- a/third_party/sqlite/src/ext/rbu/rbusplit.test +++ b/third_party/sqlite/src/ext/rbu/rbusplit.test
@@ -92,4 +92,3 @@ } finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbutemplimit.test b/third_party/sqlite/src/ext/rbu/rbutemplimit.test index 066c61e..686c5530 100644 --- a/third_party/sqlite/src/ext/rbu/rbutemplimit.test +++ b/third_party/sqlite/src/ext/rbu/rbutemplimit.test
@@ -126,4 +126,3 @@ do_test 1.6.2 { info commands rbu } {} finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbuvacuum.test b/third_party/sqlite/src/ext/rbu/rbuvacuum.test index 2a03c93..4fc7a4e 100644 --- a/third_party/sqlite/src/ext/rbu/rbuvacuum.test +++ b/third_party/sqlite/src/ext/rbu/rbuvacuum.test
@@ -397,4 +397,3 @@ catch { db close } finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/rbuvacuum2.test b/third_party/sqlite/src/ext/rbu/rbuvacuum2.test index 8a2cd411..140a0c1 100644 --- a/third_party/sqlite/src/ext/rbu/rbuvacuum2.test +++ b/third_party/sqlite/src/ext/rbu/rbuvacuum2.test
@@ -232,4 +232,3 @@ } {ok} finish_test -
diff --git a/third_party/sqlite/src/ext/rbu/sqlite3rbu.c b/third_party/sqlite/src/ext/rbu/sqlite3rbu.c index 0a3d15e..0762529 100644 --- a/third_party/sqlite/src/ext/rbu/sqlite3rbu.c +++ b/third_party/sqlite/src/ext/rbu/sqlite3rbu.c
@@ -405,7 +405,8 @@ sqlite3_vfs *pRealVfs; /* Underlying VFS */ sqlite3_mutex *mutex; /* Mutex to protect pMain */ sqlite3rbu *pRbu; /* Owner RBU object */ - rbu_file *pMain; /* Linked list of main db files */ + rbu_file *pMain; /* List of main db files */ + rbu_file *pMainRbu; /* List of main db files with pRbu!=0 */ }; /* @@ -434,6 +435,7 @@ const char *zWal; /* Wal filename for this main db file */ rbu_file *pWalFd; /* Wal file descriptor for this main db */ rbu_file *pMainNext; /* Next MAIN_DB file */ + rbu_file *pMainRbuNext; /* Next MAIN_DB file with pRbu!=0 */ }; /* @@ -4031,6 +4033,69 @@ } /* +** Add an item to the main-db lists, if it is not already present. +** +** There are two main-db lists. One for all file descriptors, and one +** for all file descriptors with rbu_file.pDb!=0. If the argument has +** rbu_file.pDb!=0, then it is assumed to already be present on the +** main list and is only added to the pDb!=0 list. +*/ +static void rbuMainlistAdd(rbu_file *p){ + rbu_vfs *pRbuVfs = p->pRbuVfs; + rbu_file *pIter; + assert( (p->openFlags & SQLITE_OPEN_MAIN_DB) ); + sqlite3_mutex_enter(pRbuVfs->mutex); + if( p->pRbu==0 ){ + for(pIter=pRbuVfs->pMain; pIter; pIter=pIter->pMainNext); + p->pMainNext = pRbuVfs->pMain; + pRbuVfs->pMain = p; + }else{ + for(pIter=pRbuVfs->pMainRbu; pIter && pIter!=p; pIter=pIter->pMainRbuNext){} + if( pIter==0 ){ + p->pMainRbuNext = pRbuVfs->pMainRbu; + pRbuVfs->pMainRbu = p; + } + } + sqlite3_mutex_leave(pRbuVfs->mutex); +} + +/* +** Remove an item from the main-db lists. +*/ +static void rbuMainlistRemove(rbu_file *p){ + rbu_file **pp; + sqlite3_mutex_enter(p->pRbuVfs->mutex); + for(pp=&p->pRbuVfs->pMain; *pp && *pp!=p; pp=&((*pp)->pMainNext)){} + if( *pp ) *pp = p->pMainNext; + p->pMainNext = 0; + for(pp=&p->pRbuVfs->pMainRbu; *pp && *pp!=p; pp=&((*pp)->pMainRbuNext)){} + if( *pp ) *pp = p->pMainRbuNext; + p->pMainRbuNext = 0; + sqlite3_mutex_leave(p->pRbuVfs->mutex); +} + +/* +** Given that zWal points to a buffer containing a wal file name passed to +** either the xOpen() or xAccess() VFS method, search the main-db list for +** a file-handle opened by the same database connection on the corresponding +** database file. +** +** If parameter bRbu is true, only search for file-descriptors with +** rbu_file.pDb!=0. +*/ +static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal, int bRbu){ + rbu_file *pDb; + sqlite3_mutex_enter(pRbuVfs->mutex); + if( bRbu ){ + for(pDb=pRbuVfs->pMainRbu; pDb && pDb->zWal!=zWal; pDb=pDb->pMainRbuNext){} + }else{ + for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){} + } + sqlite3_mutex_leave(pRbuVfs->mutex); + return pDb; +} + +/* ** Close an rbu file. */ static int rbuVfsClose(sqlite3_file *pFile){ @@ -4047,17 +4112,14 @@ sqlite3_free(p->zDel); if( p->openFlags & SQLITE_OPEN_MAIN_DB ){ - rbu_file **pp; - sqlite3_mutex_enter(p->pRbuVfs->mutex); - for(pp=&p->pRbuVfs->pMain; *pp!=p; pp=&((*pp)->pMainNext)); - *pp = p->pMainNext; - sqlite3_mutex_leave(p->pRbuVfs->mutex); + rbuMainlistRemove(p); rbuUnlockShm(p); p->pReal->pMethods->xShmUnmap(p->pReal, 0); } else if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){ rbuUpdateTempSize(p, 0); } + assert( p->pMainNext==0 && p->pRbuVfs->pMain!=p ); /* Close the underlying file handle */ rc = p->pReal->pMethods->xClose(p->pReal); @@ -4316,6 +4378,9 @@ }else if( rc==SQLITE_NOTFOUND ){ pRbu->pTargetFd = p; p->pRbu = pRbu; + if( p->openFlags & SQLITE_OPEN_MAIN_DB ){ + rbuMainlistAdd(p); + } if( p->pWalFd ) p->pWalFd->pRbu = pRbu; rc = SQLITE_OK; } @@ -4478,20 +4543,6 @@ } /* -** Given that zWal points to a buffer containing a wal file name passed to -** either the xOpen() or xAccess() VFS method, return a pointer to the -** file-handle opened by the same database connection on the corresponding -** database file. -*/ -static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal){ - rbu_file *pDb; - sqlite3_mutex_enter(pRbuVfs->mutex); - for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){} - sqlite3_mutex_leave(pRbuVfs->mutex); - return pDb; -} - -/* ** A main database named zName has just been opened. The following ** function returns a pointer to a buffer owned by SQLite that contains ** the name of the *-wal file this db connection will use. SQLite @@ -4569,7 +4620,7 @@ pFd->zWal = rbuMainToWal(zName, flags); } else if( flags & SQLITE_OPEN_WAL ){ - rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName); + rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0); if( pDb ){ if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){ /* This call is to open a *-wal file. Intead, open the *-oal. This @@ -4621,10 +4672,7 @@ ** mutex protected linked list of all such files. */ pFile->pMethods = &rbuvfs_io_methods; if( flags & SQLITE_OPEN_MAIN_DB ){ - sqlite3_mutex_enter(pRbuVfs->mutex); - pFd->pMainNext = pRbuVfs->pMain; - pRbuVfs->pMain = pFd; - sqlite3_mutex_leave(pRbuVfs->mutex); + rbuMainlistAdd(pFd); } }else{ sqlite3_free(pFd->zDel); @@ -4672,7 +4720,7 @@ ** file opened instead. */ if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){ - rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath); + rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath, 1); if( pDb && pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){ if( *pResOut ){ rc = SQLITE_CANTOPEN;
diff --git a/third_party/sqlite/src/ext/repair/test/checkindex01.test b/third_party/sqlite/src/ext/repair/test/checkindex01.test index 2c985a84..c67fce77 100644 --- a/third_party/sqlite/src/ext/repair/test/checkindex01.test +++ b/third_party/sqlite/src/ext/repair/test/checkindex01.test
@@ -347,5 +347,3 @@ do_index_check_test 7.4 t7i4 { {} 1,1 {} 3,3 } - -
diff --git a/third_party/sqlite/src/ext/rtree/geopoly.c b/third_party/sqlite/src/ext/rtree/geopoly.c index e315b01..d7f6cd5 100644 --- a/third_party/sqlite/src/ext/rtree/geopoly.c +++ b/third_party/sqlite/src/ext/rtree/geopoly.c
@@ -106,14 +106,24 @@ ** ** encoding (1 byte) 0=big-endian, 1=little-endian ** nvertex (3 bytes) Number of vertexes as a big-endian integer +** +** Enough space is allocated for 4 coordinates, to work around over-zealous +** warnings coming from some compiler (notably, clang). In reality, the size +** of each GeoPoly memory allocate is adjusted as necessary so that the +** GeoPoly.a[] array at the end is the appropriate size. */ typedef struct GeoPoly GeoPoly; struct GeoPoly { int nVertex; /* Number of vertexes */ unsigned char hdr[4]; /* Header for on-disk representation */ - GeoCoord a[2]; /* 2*nVertex values. X (longitude) first, then Y */ + GeoCoord a[8]; /* 2*nVertex values. X (longitude) first, then Y */ }; +/* The size of a memory allocation needed for a GeoPoly object sufficient +** to hold N coordinate pairs. +*/ +#define GEOPOLY_SZ(N) (sizeof(GeoPoly) + sizeof(GeoCoord)*2*((N)-4)) + /* ** State of a parse of a GeoJSON input. */ @@ -138,7 +148,7 @@ /* Skip whitespace. Return the next non-whitespace character. */ static char geopolySkipSpace(GeoParse *p){ - while( p->z[0] && safe_isspace(p->z[0]) ) p->z++; + while( safe_isspace(p->z[0]) ) p->z++; return p->z[0]; } @@ -158,7 +168,7 @@ if( c=='0' && z[j+1]>='0' && z[j+1]<='9' ) return 0; for(;; j++){ c = z[j]; - if( c>='0' && c<='9' ) continue; + if( safe_isdigit(c) ) continue; if( c=='.' ){ if( z[j-1]=='-' ) return 0; if( seenDP ) return 0; @@ -180,7 +190,17 @@ break; } if( z[j-1]<'0' ) return 0; - if( pVal ) *pVal = (GeoCoord)atof((const char*)p->z); + if( pVal ){ +#ifdef SQLITE_AMALGAMATION + /* The sqlite3AtoF() routine is much much faster than atof(), if it + ** is available */ + double r; + (void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8); + *pVal = r; +#else + *pVal = (GeoCoord)atof((const char*)p->z); +#endif + } p->z += j; return 1; } @@ -238,12 +258,10 @@ && s.a[1]==s.a[s.nVertex*2-1] && (s.z++, geopolySkipSpace(&s)==0) ){ - int nByte; GeoPoly *pOut; int x = 1; s.nVertex--; /* Remove the redundant vertex at the end */ - nByte = sizeof(GeoPoly) * s.nVertex*2*sizeof(GeoCoord); - pOut = sqlite3_malloc64( nByte ); + pOut = sqlite3_malloc64( GEOPOLY_SZ(s.nVertex) ); x = 1; if( pOut==0 ) goto parse_json_err; pOut->nVertex = s.nVertex; @@ -447,6 +465,27 @@ } /* +** Compute the area enclosed by the polygon. +** +** This routine can also be used to detect polygons that rotate in +** the wrong direction. Polygons are suppose to be counter-clockwise (CCW). +** This routine returns a negative value for clockwise (CW) polygons. +*/ +static double geopolyArea(GeoPoly *p){ + double rArea = 0.0; + int ii; + for(ii=0; ii<p->nVertex-1; ii++){ + rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */ + * (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */ + * 0.5; + } + rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */ + * (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */ + * 0.5; + return rArea; +} + +/* ** Implementation of the geopoly_area(X) function. ** ** If the input is a well-formed Geopoly BLOB then return the area @@ -461,22 +500,107 @@ ){ GeoPoly *p = geopolyFuncParam(context, argv[0], 0); if( p ){ - double rArea = 0.0; - int ii; - for(ii=0; ii<p->nVertex-1; ii++){ - rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */ - * (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */ - * 0.5; - } - rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */ - * (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */ - * 0.5; - sqlite3_result_double(context, rArea); + sqlite3_result_double(context, geopolyArea(p)); sqlite3_free(p); } } /* +** Implementation of the geopoly_ccw(X) function. +** +** If the rotation of polygon X is clockwise (incorrect) instead of +** counter-clockwise (the correct winding order according to RFC7946) +** then reverse the order of the vertexes in polygon X. +** +** In other words, this routine returns a CCW polygon regardless of the +** winding order of its input. +** +** Use this routine to sanitize historical inputs that that sometimes +** contain polygons that wind in the wrong direction. +*/ +static void geopolyCcwFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + GeoPoly *p = geopolyFuncParam(context, argv[0], 0); + if( p ){ + if( geopolyArea(p)<0.0 ){ + int ii, jj; + for(ii=2, jj=p->nVertex*2 - 2; ii<jj; ii+=2, jj-=2){ + GeoCoord t = p->a[ii]; + p->a[ii] = p->a[jj]; + p->a[jj] = t; + t = p->a[ii+1]; + p->a[ii+1] = p->a[jj+1]; + p->a[jj+1] = t; + } + } + sqlite3_result_blob(context, p->hdr, + 4+8*p->nVertex, SQLITE_TRANSIENT); + sqlite3_free(p); + } +} + +#define GEOPOLY_PI 3.1415926535897932385 + +/* Fast approximation for sine(X) for X between -0.5*pi and 2*pi +*/ +static double geopolySine(double r){ + assert( r>=-0.5*GEOPOLY_PI && r<=2.0*GEOPOLY_PI ); + if( r>=1.5*GEOPOLY_PI ){ + r -= 2.0*GEOPOLY_PI; + } + if( r>=0.5*GEOPOLY_PI ){ + return -geopolySine(r-GEOPOLY_PI); + }else{ + double r2 = r*r; + double r3 = r2*r; + double r5 = r3*r2; + return 0.9996949*r - 0.1656700*r3 + 0.0075134*r5; + } +} + +/* +** Function: geopoly_regular(X,Y,R,N) +** +** Construct a simple, convex, regular polygon centered at X, Y +** with circumradius R and with N sides. +*/ +static void geopolyRegularFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + double x = sqlite3_value_double(argv[0]); + double y = sqlite3_value_double(argv[1]); + double r = sqlite3_value_double(argv[2]); + int n = sqlite3_value_int(argv[3]); + int i; + GeoPoly *p; + + if( n<3 || r<=0.0 ) return; + if( n>1000 ) n = 1000; + p = sqlite3_malloc64( sizeof(*p) + (n-1)*2*sizeof(GeoCoord) ); + if( p==0 ){ + sqlite3_result_error_nomem(context); + return; + } + i = 1; + p->hdr[0] = *(unsigned char*)&i; + p->hdr[1] = 0; + p->hdr[2] = (n>>8)&0xff; + p->hdr[3] = n&0xff; + for(i=0; i<n; i++){ + double rAngle = 2.0*GEOPOLY_PI*i/n; + p->a[i*2] = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI); + p->a[i*2+1] = y + r*geopolySine(rAngle); + } + sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT); + sqlite3_free(p); +} + +/* ** If pPoly is a polygon, compute its bounding box. Then: ** ** (1) if aCoord!=0 store the bounding box in aCoord, returning NULL @@ -520,7 +644,7 @@ if( pRc ) *pRc = SQLITE_OK; if( aCoord==0 ){ geopolyBboxFill: - pOut = sqlite3_realloc(p, sizeof(GeoPoly)+sizeof(GeoCoord)*6); + pOut = sqlite3_realloc(p, GEOPOLY_SZ(4)); if( pOut==0 ){ sqlite3_free(p); if( context ) sqlite3_result_error_nomem(context); @@ -1548,7 +1672,16 @@ if( sqlite3_value_nochange(aData[2]) ){ sqlite3_bind_null(pUp, 2); }else{ - sqlite3_bind_value(pUp, 2, aData[2]); + GeoPoly *p = 0; + if( sqlite3_value_type(aData[2])==SQLITE_TEXT + && (p = geopolyFuncParam(0, aData[2], &rc))!=0 + && rc==SQLITE_OK + ){ + sqlite3_bind_blob(pUp, 2, p->hdr, 4+8*p->nVertex, SQLITE_TRANSIENT); + }else{ + sqlite3_bind_value(pUp, 2, aData[2]); + } + sqlite3_free(p); nChange = 1; } for(jj=1; jj<pRtree->nAux; jj++){ @@ -1592,7 +1725,7 @@ static sqlite3_module geopolyModule = { - 2, /* iVersion */ + 3, /* iVersion */ geopolyCreate, /* xCreate - create a table */ geopolyConnect, /* xConnect - connect to an existing table */ geopolyBestIndex, /* xBestIndex - Determine search strategy */ @@ -1615,25 +1748,29 @@ rtreeSavepoint, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ + rtreeShadowName /* xShadowName */ }; static int sqlite3_geopoly_init(sqlite3 *db){ int rc = SQLITE_OK; static const struct { void (*xFunc)(sqlite3_context*,int,sqlite3_value**); - int nArg; + signed char nArg; + unsigned char bPure; const char *zName; } aFunc[] = { - { geopolyAreaFunc, 1, "geopoly_area" }, - { geopolyBlobFunc, 1, "geopoly_blob" }, - { geopolyJsonFunc, 1, "geopoly_json" }, - { geopolySvgFunc, -1, "geopoly_svg" }, - { geopolyWithinFunc, 2, "geopoly_within" }, - { geopolyContainsPointFunc, 3, "geopoly_contains_point" }, - { geopolyOverlapFunc, 2, "geopoly_overlap" }, - { geopolyDebugFunc, 1, "geopoly_debug" }, - { geopolyBBoxFunc, 1, "geopoly_bbox" }, - { geopolyXformFunc, 7, "geopoly_xform" }, + { geopolyAreaFunc, 1, 1, "geopoly_area" }, + { geopolyBlobFunc, 1, 1, "geopoly_blob" }, + { geopolyJsonFunc, 1, 1, "geopoly_json" }, + { geopolySvgFunc, -1, 1, "geopoly_svg" }, + { geopolyWithinFunc, 2, 1, "geopoly_within" }, + { geopolyContainsPointFunc, 3, 1, "geopoly_contains_point" }, + { geopolyOverlapFunc, 2, 1, "geopoly_overlap" }, + { geopolyDebugFunc, 1, 0, "geopoly_debug" }, + { geopolyBBoxFunc, 1, 1, "geopoly_bbox" }, + { geopolyXformFunc, 7, 1, "geopoly_xform" }, + { geopolyRegularFunc, 4, 1, "geopoly_regular" }, + { geopolyCcwFunc, 1, 1, "geopoly_ccw" }, }; static const struct { void (*xStep)(sqlite3_context*,int,sqlite3_value**); @@ -1644,8 +1781,9 @@ }; int i; for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){ + int enc = aFunc[i].bPure ? SQLITE_UTF8|SQLITE_DETERMINISTIC : SQLITE_UTF8; rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg, - SQLITE_UTF8, 0, + enc, 0, aFunc[i].xFunc, 0, 0); } for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
diff --git a/third_party/sqlite/src/ext/rtree/rtree.c b/third_party/sqlite/src/ext/rtree/rtree.c index e25bc86..9c436d5 100644 --- a/third_party/sqlite/src/ext/rtree/rtree.c +++ b/third_party/sqlite/src/ext/rtree/rtree.c
@@ -3325,8 +3325,24 @@ return rc; } + +/* +** Return true if zName is the extension on one of the shadow tables used +** by this module. +*/ +static int rtreeShadowName(const char *zName){ + static const char *azName[] = { + "node", "parent", "rowid" + }; + unsigned int i; + for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){ + if( sqlite3_stricmp(zName, azName[i])==0 ) return 1; + } + return 0; +} + static sqlite3_module rtreeModule = { - 2, /* iVersion */ + 3, /* iVersion */ rtreeCreate, /* xCreate - create a table */ rtreeConnect, /* xConnect - connect to an existing table */ rtreeBestIndex, /* xBestIndex - Determine search strategy */ @@ -3349,6 +3365,7 @@ rtreeSavepoint, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ + rtreeShadowName /* xShadowName */ }; static int rtreeSqlInit(
diff --git a/third_party/sqlite/src/ext/rtree/rtree8.test b/third_party/sqlite/src/ext/rtree/rtree8.test index facf426..d682fe2 100644 --- a/third_party/sqlite/src/ext/rtree/rtree8.test +++ b/third_party/sqlite/src/ext/rtree/rtree8.test
@@ -101,6 +101,7 @@ # populate_t1 50 do_execsql_test rtree8-2.1.1 { SELECT max(nodeno) FROM t1_node } {5} +sqlite3_db_config db DEFENSIVE 0 do_execsql_test rtree8-2.1.2 { DELETE FROM t1_node } {} for {set i 1} {$i <= 50} {incr i} { do_catchsql_test rtree8-2.1.3.$i { @@ -121,6 +122,7 @@ populate_t1 50 +sqlite3_db_config db DEFENSIVE 0 do_execsql_test rtree8-2.2.1 { DELETE FROM t1_parent } {}
diff --git a/third_party/sqlite/src/ext/rtree/rtreeA.test b/third_party/sqlite/src/ext/rtree/rtreeA.test index eb01271..0d69fb8a 100644 --- a/third_party/sqlite/src/ext/rtree/rtreeA.test +++ b/third_party/sqlite/src/ext/rtree/rtreeA.test
@@ -36,6 +36,7 @@ execsql { INSERT INTO t1 VALUES($i, $i, $x2, $i, $y2) } } execsql COMMIT + sqlite3_db_config db DEFENSIVE 0 } proc truncate_node {nodeno nTrunc} { @@ -246,6 +247,7 @@ create_t1 populate_t1 sqlite3 db test.db +sqlite3_db_config db DEFENSIVE 0 do_execsql_test rtreeA-7.100 { UPDATE t1_node SET data=x'' WHERE rowid=1; } {} @@ -258,4 +260,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/rtree/rtreecheck.test b/third_party/sqlite/src/ext/rtree/rtreecheck.test index be4e487..e795acac 100644 --- a/third_party/sqlite/src/ext/rtree/rtreecheck.test +++ b/third_party/sqlite/src/ext/rtree/rtreecheck.test
@@ -61,6 +61,7 @@ INSERT INTO r1 VALUES(4, 8, 8, 8, 8); -- 21 INSERT INTO r1 VALUES(5, 9, 9, 9, 9); -- 27 " + sqlite3_db_config db DEFENSIVE 0 } setup_simple_db @@ -112,6 +113,7 @@ SELECT rtreecheck('r2') } {ok} +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 3.2 { BEGIN; UPDATE r2_node SET data = X'123456'; @@ -140,6 +142,7 @@ ) INSERT INTO r3 SELECT i, i, i, i, i FROM x; } +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 5.1 { BEGIN; UPDATE r3_node SET data = set_int32(data, 3, 5000); @@ -155,4 +158,3 @@ } 0 finish_test -
diff --git a/third_party/sqlite/src/ext/rtree/sqlite3rtree.h b/third_party/sqlite/src/ext/rtree/sqlite3rtree.h index 8035d5f..682070a6 100644 --- a/third_party/sqlite/src/ext/rtree/sqlite3rtree.h +++ b/third_party/sqlite/src/ext/rtree/sqlite3rtree.h
@@ -96,7 +96,7 @@ sqlite3_int64 iRowid; /* Rowid for current entry */ sqlite3_rtree_dbl rParentScore; /* Score of parent node */ int eParentWithin; /* Visibility of parent node */ - int eWithin; /* OUT: Visiblity */ + int eWithin; /* OUT: Visibility */ sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ /* The following fields are only available in 3.8.11 and later */ sqlite3_value **apSqlParam; /* Original SQL values of parameters */
diff --git a/third_party/sqlite/src/ext/rtree/visual01.txt b/third_party/sqlite/src/ext/rtree/visual01.txt index d7a9152..287e4471 100644 --- a/third_party/sqlite/src/ext/rtree/visual01.txt +++ b/third_party/sqlite/src/ext/rtree/visual01.txt
@@ -586,4 +586,17 @@ ROLLBACK; .print '</svg>' +.print '<h1>Regular Polygons</h1>' +.print '<svg width="1000" height="200" style="border:1px solid black">' +SELECT geopoly_svg(geopoly_regular(100,100,40,3),'style="fill:none;stroke:red;stroke-width:1"'); +SELECT geopoly_svg(geopoly_regular(200,100,40,4),'style="fill:none;stroke:orange;stroke-width:1"'); +SELECT geopoly_svg(geopoly_regular(300,100,40,5),'style="fill:none;stroke:green;stroke-width:1"'); +SELECT geopoly_svg(geopoly_regular(400,100,40,6),'style="fill:none;stroke:blue;stroke-width:1"'); +SELECT geopoly_svg(geopoly_regular(500,100,40,7),'style="fill:none;stroke:purple;stroke-width:1"'); +SELECT geopoly_svg(geopoly_regular(600,100,40,8),'style="fill:none;stroke:red;stroke-width:1"'); +SELECT geopoly_svg(geopoly_regular(700,100,40,10),'style="fill:none;stroke:orange;stroke-width:1"'); +SELECT geopoly_svg(geopoly_regular(800,100,40,20),'style="fill:none;stroke:green;stroke-width:1"'); +SELECT geopoly_svg(geopoly_regular(900,100,40,30),'style="fill:none;stroke:blue;stroke-width:1"'); +.print '</svg>' + .print '</html>'
diff --git a/third_party/sqlite/src/ext/session/changesetfuzz.c b/third_party/sqlite/src/ext/session/changesetfuzz.c new file mode 100644 index 0000000..9b3619d --- /dev/null +++ b/third_party/sqlite/src/ext/session/changesetfuzz.c
@@ -0,0 +1,1240 @@ +/* +** 2018-11-01 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code to implement the "changesetfuzz" command +** line utility for fuzzing changeset blobs without corrupting them. +*/ + + +/************************************************************************ +** USAGE: +** +** This program may be invoked in two ways: +** +** changesetfuzz INPUT +** changesetfuzz INPUT SEED N +** +** Argument INPUT must be the name of a file containing a binary changeset. +** In the first form above, this program outputs a human-readable version +** of the same changeset. This is chiefly for debugging. +** +** As well as changesets, this program can also dump and fuzz patchsets. +** The term "changeset" is used for both patchsets and changesets from this +** point on. +** +** In the second form, arguments SEED and N must both be integers. In this +** case, this program writes N binary changesets to disk. Each output +** changeset is a slightly modified - "fuzzed" - version of the input. +** The output changesets are written to files name "INPUT-$n", where $n is +** an integer between 0 and N-1, inclusive. Output changesets are always +** well-formed. Parameter SEED is used to seed the PRNG - any two +** invocations of this program with the same SEED and input changeset create +** the same N output changesets. +** +** The ways in which an input changeset may be fuzzed are as follows: +** +** 1. Any two values within the changeset may be exchanged. +** +** 2. Any TEXT, BLOB, INTEGER or REAL value within the changeset +** may have a single bit of its content flipped. +** +** 3. Any value within a changeset may be replaced by a pseudo-randomly +** generated value. +** +** The above operations never set a PRIMARY KEY column to NULL. Nor do they +** set any value to "undefined", or replace any "undefined" value with +** another. Any such operation risks producing a changeset that is not +** well-formed. +** +** 4. A single change may be duplicated. +** +** 5. A single change may be removed, so long as this does not mean that +** there are zero changes following a table-header within the changeset. +** +** 6. A single change may have its type (INSERT, DELETE, UPDATE) changed. +** If an INSERT is changed to a DELETE (or vice versa), the type is +** simply changed - no other modifications are required. If an INSERT +** or DELETE is changed to an UPDATE, then the single record is duplicated +** (as both the old.* and new.* records of the new UPDATE change). If an +** UPDATE is changed to a DELETE or INSERT, the new.* record is discarded +** and any "undefined" fields replaced with pseudo-randomly generated +** values. +** +** 7. An UPDATE change that modifies N table columns may be modified so +** that it updates N-1 columns, so long as (N>1). +** +** 8. The "indirect" flag may be toggled for any change. +** +** Entire group of changes may also be operated on: +** +** 9. Duplicate an existing group. +** +** 10. Remove an existing group. +** +** 11. The positions of two groups may be exchanged. +** +** There are also schema changes: +** +** 12. A non-PK column may be added to a table. In this case a NULL +** value is appended to all records. +** +** 13. A PK column may be added to a table. In this case a non-NULL +** value is appended to all INSERT, DELETE and UPDATE old.* records. +** An "undefined" is appended to new.* UPDATE records. +** +** 14. A column may be removed from a table, provided that it is not the +** only PRIMARY KEY column in the table. In this case the corresponding +** field is removed from all records. In cases where this leaves an UPDATE +** with no non-PK, non-undefined fields, the entire change is removed. +*/ + +#include "sqlite3.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <ctype.h> + +#define FUZZ_VALUE_SUB 1 /* Replace one value with a copy of another */ +#define FUZZ_VALUE_MOD 2 /* Modify content by 1 bit */ +#define FUZZ_VALUE_RND 3 /* Replace with pseudo-random value */ + +#define FUZZ_CHANGE_DUP 4 /* Duplicate an existing change */ +#define FUZZ_CHANGE_DEL 5 /* Completely remove one change */ +#define FUZZ_CHANGE_TYPE 6 /* Change the type of one change */ +#define FUZZ_CHANGE_FIELD 7 /* Change an UPDATE to modify fewer columns */ +#define FUZZ_CHANGE_INDIRECT 8 /* Toggle the "indirect" flag of a change */ + +#define FUZZ_GROUP_DUP 9 /* Duplicate a change group */ +#define FUZZ_GROUP_DEL 10 /* Delete an entire change group */ +#define FUZZ_GROUP_SWAP 11 /* Exchange the position of two groups */ + +#define FUZZ_COLUMN_ADD 12 /* Add column to table definition */ +#define FUZZ_COLUMN_ADDPK 13 /* Add PK column to table definition */ +#define FUZZ_COLUMN_DEL 14 /* Remove column from table definition */ + + + +typedef unsigned char u8; +typedef sqlite3_uint64 u64; +typedef sqlite3_int64 i64; +typedef unsigned int u32; + +/* +** Show a usage message on stderr then quit. +*/ +static void usage(const char *argv0){ + fprintf(stderr, "Usage: %s FILENAME ?SEED N?\n", argv0); + exit(1); +} + +/* +** Read the content of a disk file into an in-memory buffer +*/ +static void fuzzReadFile(const char *zFilename, int *pSz, void **ppBuf){ + FILE *f; + int sz; + void *pBuf; + f = fopen(zFilename, "rb"); + if( f==0 ){ + fprintf(stderr, "cannot open \"%s\" for reading\n", zFilename); + exit(1); + } + fseek(f, 0, SEEK_END); + sz = (int)ftell(f); + rewind(f); + pBuf = sqlite3_malloc( sz ? sz : 1 ); + if( pBuf==0 ){ + fprintf(stderr, "cannot allocate %d to hold content of \"%s\"\n", + sz, zFilename); + exit(1); + } + if( sz>0 ){ + if( fread(pBuf, sz, 1, f)!=1 ){ + fprintf(stderr, "cannot read all %d bytes of \"%s\"\n", sz, zFilename); + exit(1); + } + fclose(f); + } + *pSz = sz; + *ppBuf = pBuf; +} + +/* +** Write the contents of buffer pBuf, size nBuf bytes, into file zFilename +** on disk. zFilename, if it already exists, is clobbered. +*/ +static void fuzzWriteFile(const char *zFilename, void *pBuf, int nBuf){ + FILE *f; + f = fopen(zFilename, "wb"); + if( f==0 ){ + fprintf(stderr, "cannot open \"%s\" for writing\n", zFilename); + exit(1); + } + if( fwrite(pBuf, nBuf, 1, f)!=1 ){ + fprintf(stderr, "cannot write to \"%s\"\n", zFilename); + exit(1); + } + fclose(f); +} + +static int fuzzCorrupt(){ + return SQLITE_CORRUPT; +} + +/************************************************************************* +** The following block is a copy of the implementation of SQLite function +** sqlite3_randomness. This version has two important differences: +** +** 1. It always uses the same seed. So the sequence of random data output +** is the same for every run of the program. +** +** 2. It is not threadsafe. +*/ +static struct sqlite3PrngType { + unsigned char i, j; /* State variables */ + unsigned char s[256]; /* State variables */ +} sqlite3Prng = { + 0xAF, 0x28, + { + 0x71, 0xF5, 0xB4, 0x6E, 0x80, 0xAB, 0x1D, 0xB8, + 0xFB, 0xB7, 0x49, 0xBF, 0xFF, 0x72, 0x2D, 0x14, + 0x79, 0x09, 0xE3, 0x78, 0x76, 0xB0, 0x2C, 0x0A, + 0x8E, 0x23, 0xEE, 0xDF, 0xE0, 0x9A, 0x2F, 0x67, + 0xE1, 0xBE, 0x0E, 0xA7, 0x08, 0x97, 0xEB, 0x77, + 0x78, 0xBA, 0x9D, 0xCA, 0x49, 0x4C, 0x60, 0x9A, + 0xF6, 0xBD, 0xDA, 0x7F, 0xBC, 0x48, 0x58, 0x52, + 0xE5, 0xCD, 0x83, 0x72, 0x23, 0x52, 0xFF, 0x6D, + 0xEF, 0x0F, 0x82, 0x29, 0xA0, 0x83, 0x3F, 0x7D, + 0xA4, 0x88, 0x31, 0xE7, 0x88, 0x92, 0x3B, 0x9B, + 0x3B, 0x2C, 0xC2, 0x4C, 0x71, 0xA2, 0xB0, 0xEA, + 0x36, 0xD0, 0x00, 0xF1, 0xD3, 0x39, 0x17, 0x5D, + 0x2A, 0x7A, 0xE4, 0xAD, 0xE1, 0x64, 0xCE, 0x0F, + 0x9C, 0xD9, 0xF5, 0xED, 0xB0, 0x22, 0x5E, 0x62, + 0x97, 0x02, 0xA3, 0x8C, 0x67, 0x80, 0xFC, 0x88, + 0x14, 0x0B, 0x15, 0x10, 0x0F, 0xC7, 0x40, 0xD4, + 0xF1, 0xF9, 0x0E, 0x1A, 0xCE, 0xB9, 0x1E, 0xA1, + 0x72, 0x8E, 0xD7, 0x78, 0x39, 0xCD, 0xF4, 0x5D, + 0x2A, 0x59, 0x26, 0x34, 0xF2, 0x73, 0x0B, 0xA0, + 0x02, 0x51, 0x2C, 0x03, 0xA3, 0xA7, 0x43, 0x13, + 0xE8, 0x98, 0x2B, 0xD2, 0x53, 0xF8, 0xEE, 0x91, + 0x7D, 0xE7, 0xE3, 0xDA, 0xD5, 0xBB, 0xC0, 0x92, + 0x9D, 0x98, 0x01, 0x2C, 0xF9, 0xB9, 0xA0, 0xEB, + 0xCF, 0x32, 0xFA, 0x01, 0x49, 0xA5, 0x1D, 0x9A, + 0x76, 0x86, 0x3F, 0x40, 0xD4, 0x89, 0x8F, 0x9C, + 0xE2, 0xE3, 0x11, 0x31, 0x37, 0xB2, 0x49, 0x28, + 0x35, 0xC0, 0x99, 0xB6, 0xD0, 0xBC, 0x66, 0x35, + 0xF7, 0x83, 0x5B, 0xD7, 0x37, 0x1A, 0x2B, 0x18, + 0xA6, 0xFF, 0x8D, 0x7C, 0x81, 0xA8, 0xFC, 0x9E, + 0xC4, 0xEC, 0x80, 0xD0, 0x98, 0xA7, 0x76, 0xCC, + 0x9C, 0x2F, 0x7B, 0xFF, 0x8E, 0x0E, 0xBB, 0x90, + 0xAE, 0x13, 0x06, 0xF5, 0x1C, 0x4E, 0x52, 0xF7 + } +}; + +/* +** Generate and return single random byte +*/ +static unsigned char fuzzRandomByte(void){ + unsigned char t; + sqlite3Prng.i++; + t = sqlite3Prng.s[sqlite3Prng.i]; + sqlite3Prng.j += t; + sqlite3Prng.s[sqlite3Prng.i] = sqlite3Prng.s[sqlite3Prng.j]; + sqlite3Prng.s[sqlite3Prng.j] = t; + t += sqlite3Prng.s[sqlite3Prng.i]; + return sqlite3Prng.s[t]; +} + +/* +** Return N random bytes. +*/ +static void fuzzRandomBlob(int nBuf, unsigned char *zBuf){ + int i; + for(i=0; i<nBuf; i++){ + zBuf[i] = fuzzRandomByte(); + } +} + +/* +** Return a random integer between 0 and nRange (not inclusive). +*/ +static unsigned int fuzzRandomInt(unsigned int nRange){ + unsigned int ret; + assert( nRange>0 ); + fuzzRandomBlob(sizeof(ret), (unsigned char*)&ret); + return (ret % nRange); +} + +static u64 fuzzRandomU64(){ + u64 ret; + fuzzRandomBlob(sizeof(ret), (unsigned char*)&ret); + return ret; +} + +static void fuzzRandomSeed(unsigned int iSeed){ + int i; + for(i=0; i<256; i+=4){ + sqlite3Prng.s[i] ^= ((iSeed >> 24) & 0xFF); + sqlite3Prng.s[i+1] ^= ((iSeed >> 16) & 0xFF); + sqlite3Prng.s[i+2] ^= ((iSeed >> 8) & 0xFF); + sqlite3Prng.s[i+3] ^= ((iSeed >> 0) & 0xFF); + } +} +/* +** End of code for generating pseudo-random values. +*************************************************************************/ + +typedef struct FuzzChangeset FuzzChangeset; +typedef struct FuzzChangesetGroup FuzzChangesetGroup; +typedef struct FuzzChange FuzzChange; + +/* +** Object containing partially parsed changeset. +*/ +struct FuzzChangeset { + int bPatchset; /* True for a patchset */ + FuzzChangesetGroup **apGroup; /* Array of groups in changeset */ + int nGroup; /* Number of items in list pGroup */ + u8 **apVal; /* Array of all values in changeset */ + int nVal; /* Number of used slots in apVal[] */ + int nChange; /* Number of changes in changeset */ + int nUpdate; /* Number of UPDATE changes in changeset */ +}; + +/* +** There is one object of this type for each change-group (table header) +** in the input changeset. +*/ +struct FuzzChangesetGroup { + const char *zTab; /* Name of table */ + int nCol; /* Number of columns in table */ + u8 *aPK; /* PK array for this table */ + u8 *aChange; /* Buffer containing array of changes */ + int szChange; /* Size of buffer aChange[] in bytes */ + int nChange; /* Number of changes in buffer aChange[] */ +}; + +/* +** Description of a fuzz change to be applied to a changeset. +*/ +struct FuzzChange { + int eType; /* One of the FUZZ_* constants above */ + int iChange; /* Change or UPDATE to modify */ + int iGroup; /* Group to modify */ + int iDelete; /* Field to remove (FUZZ_COLUMN_DEL) */ + u8 *pSub1; /* Replace this value with pSub2 */ + u8 *pSub2; /* And this one with pSub1 */ + u8 aSub[128]; /* Buffer for substitute value */ + int iCurrent; /* Current change number */ +}; + +/* +** Allocate and return nByte bytes of zeroed memory. +*/ +static void *fuzzMalloc(int nByte){ + void *pRet = sqlite3_malloc(nByte); + if( pRet ){ + memset(pRet, 0, nByte); + } + return pRet; +} + +/* +** Free the buffer indicated by the first argument. This function is used +** to free buffers allocated by fuzzMalloc(). +*/ +static void fuzzFree(void *p){ + sqlite3_free(p); +} + +/* +** Argument p points to a buffer containing an SQLite varint that, assuming the +** input is not corrupt, may be between 0 and 0x7FFFFFFF, inclusive. Before +** returning, this function sets (*pnVal) to the value of that varint, and +** returns the number of bytes of space that it takes up. +*/ +static int fuzzGetVarint(u8 *p, int *pnVal){ + int i; + sqlite3_uint64 nVal = 0; + for(i=0; i<9; i++){ + nVal = (nVal<<7) + (p[i] & 0x7F); + if( (p[i] & 0x80)==0 ){ + i++; + break; + } + } + *pnVal = (int)nVal; + return i; +} + +/* +** Write value nVal into the buffer indicated by argument p as an SQLite +** varint. nVal is guaranteed to be between 0 and (2^21-1), inclusive. +** Return the number of bytes written to buffer p. +*/ +static int fuzzPutVarint(u8 *p, int nVal){ + assert( nVal>0 && nVal<2097152 ); + if( nVal<128 ){ + p[0] = nVal; + return 1; + } + if( nVal<16384 ){ + p[0] = ((nVal >> 7) & 0x7F) | 0x80; + p[1] = (nVal & 0x7F); + return 2; + } + + p[0] = ((nVal >> 14) & 0x7F) | 0x80; + p[1] = ((nVal >> 7) & 0x7F) | 0x80; + p[2] = (nVal & 0x7F); + return 3; +} + +/* +** Read a 64-bit big-endian integer value from buffer aRec[]. Return +** the value read. +*/ +static i64 fuzzGetI64(u8 *aRec){ + return (i64)( + (((u64)aRec[0]) << 56) + + (((u64)aRec[1]) << 48) + + (((u64)aRec[2]) << 40) + + (((u64)aRec[3]) << 32) + + (((u64)aRec[4]) << 24) + + (((u64)aRec[5]) << 16) + + (((u64)aRec[6]) << 8) + + (((u64)aRec[7]) << 0) + ); +} + +/* +** Write value iVal to buffer aRec[] as an unsigned 64-bit big-endian integer. +*/ +static void fuzzPutU64(u8 *aRec, u64 iVal){ + aRec[0] = (iVal>>56) & 0xFF; + aRec[1] = (iVal>>48) & 0xFF; + aRec[2] = (iVal>>40) & 0xFF; + aRec[3] = (iVal>>32) & 0xFF; + aRec[4] = (iVal>>24) & 0xFF; + aRec[5] = (iVal>>16) & 0xFF; + aRec[6] = (iVal>> 8) & 0xFF; + aRec[7] = (iVal) & 0xFF; +} + +/* +** Parse a single table-header from the input. Allocate a new change-group +** object with the results. Return SQLITE_OK if successful, or an error code +** otherwise. +*/ +static int fuzzParseHeader( + FuzzChangeset *pParse, /* Changeset parse object */ + u8 **ppHdr, /* IN/OUT: Iterator */ + u8 *pEnd, /* 1 byte past EOF */ + FuzzChangesetGroup **ppGrp /* OUT: New change-group object */ +){ + int rc = SQLITE_OK; + FuzzChangesetGroup *pGrp; + u8 cHdr = (pParse->bPatchset ? 'P' : 'T'); + + assert( pEnd>(*ppHdr) ); + pGrp = (FuzzChangesetGroup*)fuzzMalloc(sizeof(FuzzChangesetGroup)); + if( !pGrp ){ + rc = SQLITE_NOMEM; + }else{ + u8 *p = *ppHdr; + if( p[0]!=cHdr ){ + rc = fuzzCorrupt(); + }else{ + p++; + p += fuzzGetVarint(p, &pGrp->nCol); + pGrp->aPK = p; + p += pGrp->nCol; + pGrp->zTab = (const char*)p; + p = &p[strlen(p)+1]; + + if( p>=pEnd ){ + rc = fuzzCorrupt(); + } + } + *ppHdr = p; + } + + if( rc!=SQLITE_OK ){ + fuzzFree(pGrp); + pGrp = 0; + } + + *ppGrp = pGrp; + return rc; +} + +/* +** Argument p points to a buffer containing a single changeset-record value. +** This function attempts to determine the size of the value in bytes. If +** successful, it sets (*pSz) to the size and returns SQLITE_OK. Or, if the +** buffer does not contain a valid value, SQLITE_CORRUPT is returned and +** the final value of (*pSz) is undefined. +*/ +static int fuzzChangeSize(u8 *p, int *pSz){ + u8 eType = p[0]; + switch( eType ){ + case 0x00: /* undefined */ + case 0x05: /* null */ + *pSz = 1; + break; + + case 0x01: /* integer */ + case 0x02: /* real */ + *pSz = 9; + break; + + case 0x03: /* text */ + case 0x04: { /* blob */ + int nTxt; + int sz; + sz = fuzzGetVarint(&p[1], &nTxt); + *pSz = 1 + sz + nTxt; + break; + } + + default: + return fuzzCorrupt(); + } + return SQLITE_OK; +} + +/* +** When this function is called, (*ppRec) points to the start of a +** record in a changeset being parsed. This function adds entries +** to the pParse->apVal[] array for all values and advances (*ppRec) +** to one byte past the end of the record. Argument pEnd points to +** one byte past the end of the input changeset. +** +** Argument bPkOnly is true if the record being parsed is part of +** a DELETE record in a patchset. In this case, all non-primary-key +** fields have been omitted from the record. +** +** SQLITE_OK is returned if successful, or an SQLite error code otherwise. +*/ +static int fuzzParseRecord( + u8 **ppRec, /* IN/OUT: Iterator */ + u8 *pEnd, /* One byte after end of input data */ + FuzzChangeset *pParse, /* Changeset parse context */ + int bPkOnly /* True if non-PK fields omitted */ +){ + int rc = SQLITE_OK; + FuzzChangesetGroup *pGrp = pParse->apGroup[pParse->nGroup-1]; + int i; + u8 *p = *ppRec; + + for(i=0; rc==SQLITE_OK && i<pGrp->nCol; i++){ + if( bPkOnly==0 || pGrp->aPK[i] ){ + int sz; + if( p>=pEnd ) break; + if( (pParse->nVal & (pParse->nVal-1))==0 ){ + int nNew = pParse->nVal ? pParse->nVal*2 : 4; + u8 **apNew = (u8**)sqlite3_realloc(pParse->apVal, nNew*sizeof(u8*)); + if( apNew==0 ) return SQLITE_NOMEM; + pParse->apVal = apNew; + } + pParse->apVal[pParse->nVal++] = p; + rc = fuzzChangeSize(p, &sz); + p += sz; + } + } + + if( rc==SQLITE_OK && i<pGrp->nCol ){ + rc = fuzzCorrupt(); + } + + *ppRec = p; + return rc; +} + +/* +** Parse the array of changes starting at (*ppData) and add entries for +** all values to the pParse->apVal[] array. Argument pEnd points to one byte +** past the end of the input changeset. If successful, set (*ppData) to point +** to one byte past the end of the change array and return SQLITE_OK. +** Otherwise, return an SQLite error code. The final value of (*ppData) is +** undefined in this case. +*/ +static int fuzzParseChanges(u8 **ppData, u8 *pEnd, FuzzChangeset *pParse){ + u8 cHdr = (pParse->bPatchset ? 'P' : 'T'); + FuzzChangesetGroup *pGrp = pParse->apGroup[pParse->nGroup-1]; + int rc = SQLITE_OK; + u8 *p = *ppData; + + pGrp->aChange = p; + while( rc==SQLITE_OK && p<pEnd && p[0]!=cHdr ){ + u8 eOp = p[0]; + u8 bIndirect = p[1]; + + p += 2; + if( eOp==SQLITE_UPDATE ){ + pParse->nUpdate++; + if( pParse->bPatchset==0 ){ + rc = fuzzParseRecord(&p, pEnd, pParse, 0); + } + }else if( eOp!=SQLITE_INSERT && eOp!=SQLITE_DELETE ){ + rc = fuzzCorrupt(); + } + if( rc==SQLITE_OK ){ + int bPkOnly = (eOp==SQLITE_DELETE && pParse->bPatchset); + rc = fuzzParseRecord(&p, pEnd, pParse, bPkOnly); + } + pGrp->nChange++; + pParse->nChange++; + } + pGrp->szChange = p - pGrp->aChange; + + *ppData = p; + return rc; +} + +/* +** Parse the changeset stored in buffer pChangeset (nChangeset bytes in +** size). If successful, write the results into (*pParse) and return +** SQLITE_OK. Or, if an error occurs, return an SQLite error code. The +** final state of (*pParse) is undefined in this case. +*/ +static int fuzzParseChangeset( + u8 *pChangeset, /* Buffer containing changeset */ + int nChangeset, /* Size of buffer in bytes */ + FuzzChangeset *pParse /* OUT: Results of parse */ +){ + u8 *pEnd = &pChangeset[nChangeset]; + u8 *p = pChangeset; + int rc = SQLITE_OK; + + memset(pParse, 0, sizeof(FuzzChangeset)); + if( nChangeset>0 ){ + pParse->bPatchset = (pChangeset[0]=='P'); + } + + while( rc==SQLITE_OK && p<pEnd ){ + FuzzChangesetGroup *pGrp = 0; + + /* Read a table-header from the changeset */ + rc = fuzzParseHeader(pParse, &p, pEnd, &pGrp); + assert( (rc==SQLITE_OK)==(pGrp!=0) ); + + /* If the table-header was successfully parsed, add the new change-group + ** to the array and parse the associated changes. */ + if( rc==SQLITE_OK ){ + FuzzChangesetGroup **apNew = (FuzzChangesetGroup**)sqlite3_realloc( + pParse->apGroup, sizeof(FuzzChangesetGroup*)*(pParse->nGroup+1) + ); + if( apNew==0 ){ + rc = SQLITE_NOMEM; + }else{ + apNew[pParse->nGroup] = pGrp; + pParse->apGroup = apNew; + pParse->nGroup++; + } + rc = fuzzParseChanges(&p, pEnd, pParse); + } + } + + return rc; +} + +/* +** When this function is called, (*ppRec) points to the first byte of +** a record that is part of change-group pGrp. This function attempts +** to output a human-readable version of the record to stdout and advance +** (*ppRec) to point to the first byte past the end of the record before +** returning. If successful, SQLITE_OK is returned. Otherwise, an SQLite +** error code. +** +** If parameter bPkOnly is non-zero, then all non-primary-key fields have +** been omitted from the record. This occurs for records that are part +** of DELETE changes in patchsets. +*/ +static int fuzzPrintRecord(FuzzChangesetGroup *pGrp, u8 **ppRec, int bPKOnly){ + int rc = SQLITE_OK; + u8 *p = *ppRec; + int i; + const char *zPre = " ("; + + for(i=0; i<pGrp->nCol; i++){ + if( bPKOnly==0 || pGrp->aPK[i] ){ + u8 eType = p++[0]; + switch( eType ){ + case 0x00: /* undefined */ + printf("%sn/a", zPre); + break; + + case 0x01: { /* integer */ + sqlite3_int64 iVal = 0; + iVal = fuzzGetI64(p); + printf("%s%lld", zPre, iVal); + p += 8; + break; + } + + case 0x02: { /* real */ + sqlite3_int64 iVal = 0; + double fVal = 0.0; + iVal = fuzzGetI64(p); + memcpy(&fVal, &iVal, 8); + printf("%s%f", zPre, fVal); + p += 8; + break; + } + + case 0x03: /* text */ + case 0x04: { /* blob */ + int nTxt; + int sz; + int i; + p += fuzzGetVarint(p, &nTxt); + printf("%s%s", zPre, eType==0x03 ? "'" : "X'"); + for(i=0; i<nTxt; i++){ + if( eType==0x03 ){ + printf("%c", p[i]); + }else{ + char aHex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; + printf("%c", aHex[ p[i]>>4 ]); + printf("%c", aHex[ p[i] & 0x0F ]); + } + } + printf("'"); + p += nTxt; + break; + } + + case 0x05: /* null */ + printf("%sNULL", zPre); + break; + } + zPre = ", "; + } + } + printf(")"); + + *ppRec = p; + return rc; +} + +/* +** Print a human-readable version of the table-header and all changes in the +** change-group passed as the second argument. +*/ +static void fuzzPrintGroup(FuzzChangeset *pParse, FuzzChangesetGroup *pGrp){ + int i; + u8 *p; + + /* The table header */ + printf("TABLE: %s nCol=%d aPK=", pGrp->zTab, pGrp->nCol); + for(i=0; i<pGrp->nCol; i++){ + printf("%d", (int)pGrp->aPK[i]); + } + printf("\n"); + + /* The array of changes */ + p = pGrp->aChange; + for(i=0; i<pGrp->nChange; i++){ + u8 eType = p[0]; + u8 bIndirect = p[1]; + printf("%s (ind=%d):", + (eType==SQLITE_INSERT) ? "INSERT" : + (eType==SQLITE_DELETE ? "DELETE" : "UPDATE"), + bIndirect + ); + p += 2; + + if( pParse->bPatchset==0 && eType==SQLITE_UPDATE ){ + fuzzPrintRecord(pGrp, &p, 0); + } + fuzzPrintRecord(pGrp, &p, eType==SQLITE_DELETE && pParse->bPatchset); + printf("\n"); + } +} + +/* +** Initialize the object passed as the second parameter with details +** of the change that will be attempted (type of change, to which part of the +** changeset it applies etc.). If successful, return SQLITE_OK. Or, if an +** error occurs, return an SQLite error code. +** +** If a negative value is returned, then the selected change would have +** produced a non-well-formed changeset. In this case the caller should +** call this function again. +*/ +static int fuzzSelectChange(FuzzChangeset *pParse, FuzzChange *pChange){ + int iSub; + + memset(pChange, 0, sizeof(FuzzChange)); + pChange->eType = fuzzRandomInt(FUZZ_COLUMN_DEL) + 1; + + assert( pChange->eType==FUZZ_VALUE_SUB + || pChange->eType==FUZZ_VALUE_MOD + || pChange->eType==FUZZ_VALUE_RND + || pChange->eType==FUZZ_CHANGE_DUP + || pChange->eType==FUZZ_CHANGE_DEL + || pChange->eType==FUZZ_CHANGE_TYPE + || pChange->eType==FUZZ_CHANGE_FIELD + || pChange->eType==FUZZ_CHANGE_INDIRECT + || pChange->eType==FUZZ_GROUP_DUP + || pChange->eType==FUZZ_GROUP_DEL + || pChange->eType==FUZZ_GROUP_SWAP + || pChange->eType==FUZZ_COLUMN_ADD + || pChange->eType==FUZZ_COLUMN_ADDPK + || pChange->eType==FUZZ_COLUMN_DEL + ); + + pChange->iGroup = fuzzRandomInt(pParse->nGroup); + pChange->iChange = fuzzRandomInt(pParse->nChange); + if( pChange->eType==FUZZ_CHANGE_FIELD ){ + if( pParse->nUpdate==0 ) return -1; + pChange->iChange = fuzzRandomInt(pParse->nUpdate); + } + + pChange->iDelete = -1; + if( pChange->eType==FUZZ_COLUMN_DEL ){ + FuzzChangesetGroup *pGrp = pParse->apGroup[pChange->iGroup]; + int i; + pChange->iDelete = fuzzRandomInt(pGrp->nCol); + for(i=pGrp->nCol-1; i>=0; i--){ + if( pGrp->aPK[i] && pChange->iDelete!=i ) break; + } + if( i<0 ) return -1; + } + + if( pChange->eType==FUZZ_GROUP_SWAP ){ + FuzzChangesetGroup *pGrp; + int iGrp = pChange->iGroup; + if( pParse->nGroup==1 ) return -1; + while( iGrp==pChange->iGroup ){ + iGrp = fuzzRandomInt(pParse->nGroup); + } + pGrp = pParse->apGroup[pChange->iGroup]; + pParse->apGroup[pChange->iGroup] = pParse->apGroup[iGrp]; + pParse->apGroup[iGrp] = pGrp; + } + + if( pChange->eType==FUZZ_VALUE_SUB + || pChange->eType==FUZZ_VALUE_MOD + || pChange->eType==FUZZ_VALUE_RND + ){ + iSub = fuzzRandomInt(pParse->nVal); + pChange->pSub1 = pParse->apVal[iSub]; + if( pChange->eType==FUZZ_VALUE_SUB ){ + iSub = fuzzRandomInt(pParse->nVal); + pChange->pSub2 = pParse->apVal[iSub]; + }else{ + pChange->pSub2 = pChange->aSub; + } + + if( pChange->eType==FUZZ_VALUE_RND ){ + pChange->aSub[0] = (u8)(fuzzRandomInt(5) + 1); + switch( pChange->aSub[0] ){ + case 0x01: { /* integer */ + u64 iVal = fuzzRandomU64(); + fuzzPutU64(&pChange->aSub[1], iVal); + break; + } + + case 0x02: { /* real */ + u64 iVal1 = fuzzRandomU64(); + u64 iVal2 = fuzzRandomU64(); + double d = (double)iVal1 / (double)iVal2; + memcpy(&iVal1, &d, sizeof(iVal1)); + fuzzPutU64(&pChange->aSub[1], iVal1); + break; + } + + case 0x03: /* text */ + case 0x04: { /* blob */ + int nByte = fuzzRandomInt(48); + pChange->aSub[1] = nByte; + fuzzRandomBlob(nByte, &pChange->aSub[2]); + if( pChange->aSub[0]==0x03 ){ + int i; + for(i=0; i<nByte; i++){ + pChange->aSub[2+i] &= 0x7F; + } + } + break; + } + } + } + if( pChange->eType==FUZZ_VALUE_MOD ){ + int sz; + int iMod = -1; + fuzzChangeSize(pChange->pSub1, &sz); + memcpy(pChange->aSub, pChange->pSub1, sz); + switch( pChange->aSub[0] ){ + case 0x01: + case 0x02: + iMod = fuzzRandomInt(8) + 1; + break; + + case 0x03: /* text */ + case 0x04: { /* blob */ + int nByte; + int iFirst = 1 + fuzzGetVarint(&pChange->aSub[1], &nByte); + if( nByte>0 ){ + iMod = fuzzRandomInt(nByte) + iFirst; + } + break; + } + } + + if( iMod>=0 ){ + u8 mask = (1 << fuzzRandomInt(8 - (pChange->aSub[0]==0x03))); + pChange->aSub[iMod] ^= mask; + } + } + } + + return SQLITE_OK; +} + +/* +** Copy a single change from the input to the output changeset, making +** any modifications specified by (*pFuzz). +*/ +static int fuzzCopyChange( + FuzzChangeset *pParse, + int iGrp, + FuzzChange *pFuzz, + u8 **pp, u8 **ppOut /* IN/OUT: Input and output pointers */ +){ + int bPS = pParse->bPatchset; + FuzzChangesetGroup *pGrp = pParse->apGroup[iGrp]; + u8 *p = *pp; + u8 *pOut = *ppOut; + u8 eType = p++[0]; + int iRec; + int nRec = ((eType==SQLITE_UPDATE && !bPS) ? 2 : 1); + int iUndef = -1; + int nUpdate = 0; + + u8 eNew = eType; + if( pFuzz->iCurrent==pFuzz->iChange && pFuzz->eType==FUZZ_CHANGE_TYPE ){ + switch( eType ){ + case SQLITE_INSERT: + eNew = SQLITE_DELETE; + break; + case SQLITE_DELETE: + eNew = SQLITE_UPDATE; + break; + case SQLITE_UPDATE: + eNew = SQLITE_INSERT; + break; + } + } + + if( pFuzz->iCurrent==pFuzz->iChange + && pFuzz->eType==FUZZ_CHANGE_FIELD && eType==SQLITE_UPDATE + ){ + int sz; + int i; + int nDef = 0; + u8 *pCsr = p+1; + for(i=0; i<pGrp->nCol; i++){ + if( pCsr[0] && pGrp->aPK[i]==0 ) nDef++; + fuzzChangeSize(pCsr, &sz); + pCsr += sz; + } + if( nDef<=1 ) return -1; + nDef = fuzzRandomInt(nDef); + pCsr = p+1; + for(i=0; i<pGrp->nCol; i++){ + if( pCsr[0] && pGrp->aPK[i]==0 ){ + if( nDef==0 ) iUndef = i; + nDef--; + } + fuzzChangeSize(pCsr, &sz); + pCsr += sz; + } + } + + /* Copy the change type and indirect flag. If the fuzz mode is + ** FUZZ_CHANGE_INDIRECT, and the current change is the one selected for + ** fuzzing, invert the indirect flag. */ + *(pOut++) = eNew; + if( pFuzz->eType==FUZZ_CHANGE_INDIRECT && pFuzz->iCurrent==pFuzz->iChange ){ + *(pOut++) = !(*(p++)); + }else{ + *(pOut++) = *(p++); + } + + for(iRec=0; iRec<nRec; iRec++){ + int i; + + /* Copy the next record from the output to the input. + */ + for(i=0; i<pGrp->nCol; i++){ + int sz; + u8 *pCopy = p; + + /* If this is a patchset, and the input is a DELETE, then the only + ** fields present are the PK fields. So, if this is not a PK, skip to + ** the next column. If the current fuzz is FUZZ_CHANGE_TYPE, then + ** write a randomly selected value to the output. */ + if( bPS && eType==SQLITE_DELETE && pGrp->aPK[i]==0 ){ + if( eType!=eNew ){ + assert( eNew==SQLITE_UPDATE ); + do { + pCopy = pParse->apVal[fuzzRandomInt(pParse->nVal)]; + }while( pCopy[0]==0x00 ); + fuzzChangeSize(pCopy, &sz); + memcpy(pOut, pCopy, sz); + pOut += sz; + } + continue; + } + + if( p==pFuzz->pSub1 ){ + pCopy = pFuzz->pSub2; + }else if( p==pFuzz->pSub2 ){ + pCopy = pFuzz->pSub1; + }else if( i==iUndef ){ + pCopy = "\0"; + } + + if( pCopy[0]==0x00 && eNew!=eType && eType==SQLITE_UPDATE && iRec==0 ){ + while( pCopy[0]==0x00 ){ + pCopy = pParse->apVal[fuzzRandomInt(pParse->nVal)]; + } + }else if( p[0]==0x00 && pCopy[0]!=0x00 ){ + return -1; + }else{ + if( pGrp->aPK[i]>0 && pCopy[0]==0x05 ) return -1; + } + + if( (pFuzz->iGroup!=iGrp || i!=pFuzz->iDelete) + && (eNew==eType || eType!=SQLITE_UPDATE || iRec==0) + && (eNew==eType || eNew!=SQLITE_DELETE || !bPS || pGrp->aPK[i]) + ){ + fuzzChangeSize(pCopy, &sz); + memcpy(pOut, pCopy, sz); + pOut += sz; + nUpdate += (pGrp->aPK[i]==0 && pCopy[0]!=0x00); + } + + fuzzChangeSize(p, &sz); + p += sz; + } + + if( iGrp==pFuzz->iGroup ){ + if( pFuzz->eType==FUZZ_COLUMN_ADD ){ + if( !bPS || eType!=SQLITE_DELETE ) *(pOut++) = 0x05; + }else if( pFuzz->eType==FUZZ_COLUMN_ADDPK ){ + if( iRec==1 ){ + *(pOut++) = 0x00; + }else{ + u8 *pNew; + int szNew; + do { + pNew = pParse->apVal[fuzzRandomInt(pParse->nVal)]; + }while( pNew[0]==0x00 || pNew[0]==0x05 ); + fuzzChangeSize(pNew, &szNew); + memcpy(pOut, pNew, szNew); + pOut += szNew; + } + } + } + } + + if( pFuzz->iCurrent==pFuzz->iChange ){ + if( pFuzz->eType==FUZZ_CHANGE_DUP ){ + int nByte = pOut - (*ppOut); + memcpy(pOut, *ppOut, nByte); + pOut += nByte; + } + + if( pFuzz->eType==FUZZ_CHANGE_DEL ){ + pOut = *ppOut; + } + if( eNew!=eType && eNew==SQLITE_UPDATE && !bPS ){ + int i; + u8 *pCsr = (*ppOut) + 2; + for(i=0; i<pGrp->nCol; i++){ + int sz; + u8 *pCopy = pCsr; + if( pGrp->aPK[i] ) pCopy = "\0"; + fuzzChangeSize(pCopy, &sz); + memcpy(pOut, pCopy, sz); + pOut += sz; + fuzzChangeSize(pCsr, &sz); + pCsr += sz; + } + } + } + + /* If a column is being deleted from this group, and this change was an + ** UPDATE, and there are now no non-PK, non-undefined columns in the + ** change, remove it altogether. */ + if( pFuzz->eType==FUZZ_COLUMN_DEL && pFuzz->iGroup==iGrp + && eType==SQLITE_UPDATE && nUpdate==0 + ){ + pOut = *ppOut; + } + + *pp = p; + *ppOut = pOut; + pFuzz->iCurrent += (eType==SQLITE_UPDATE || pFuzz->eType!=FUZZ_CHANGE_FIELD); + return SQLITE_OK; +} + +/* +** Fuzz the changeset parsed into object pParse and write the results +** to file zOut on disk. Argument pBuf points to a buffer that is guaranteed +** to be large enough to hold the fuzzed changeset. +** +** Return SQLITE_OK if successful, or an SQLite error code if an error occurs. +*/ +static int fuzzDoOneFuzz( + const char *zOut, /* Filename to write modified changeset to */ + u8 *pBuf, /* Buffer to use for modified changeset */ + FuzzChangeset *pParse /* Parse of input changeset */ +){ + FuzzChange change; + int iGrp; + int rc = -1; + + while( rc<0 ){ + u8 *pOut = pBuf; + rc = fuzzSelectChange(pParse, &change); + for(iGrp=0; rc==SQLITE_OK && iGrp<pParse->nGroup; iGrp++){ + FuzzChangesetGroup *pGrp = pParse->apGroup[iGrp]; + int nTab = strlen(pGrp->zTab) + 1; + int j; + int nRep = 1; + + /* If this is the group to delete for a FUZZ_GROUP_DEL change, jump to + ** the next group. Unless this is the only group in the changeset - in + ** that case this change cannot be applied. + ** + ** Or, if this is a FUZZ_GROUP_DUP, set nRep to 2 to output two + ** copies of the group. */ + if( change.iGroup==iGrp ){ + if( change.eType==FUZZ_GROUP_DEL ){ + if( pParse->nGroup==1 ) rc = -1; + continue; + } + else if( change.eType==FUZZ_GROUP_DUP ){ + nRep = 2; + } + } + + for(j=0; j<nRep; j++){ + int i; + u8 *pSaved; + u8 *p = pGrp->aChange; + int nCol = pGrp->nCol; + int iPKDel = 0; + if( iGrp==change.iGroup ){ + if( change.eType==FUZZ_COLUMN_ADD + || change.eType==FUZZ_COLUMN_ADDPK + ){ + nCol++; + }else if( change.eType==FUZZ_COLUMN_DEL ){ + nCol--; + iPKDel = pGrp->aPK[change.iDelete]; + } + } + + /* Output a table header */ + pOut++[0] = pParse->bPatchset ? 'P' : 'T'; + pOut += fuzzPutVarint(pOut, nCol); + + for(i=0; i<pGrp->nCol; i++){ + if( iGrp!=change.iGroup || i!=change.iDelete ){ + u8 v = pGrp->aPK[i]; + if( iPKDel && v>iPKDel ) v--; + *(pOut++) = v; + } + } + if( nCol>pGrp->nCol ){ + if( change.eType==FUZZ_COLUMN_ADD ){ + *(pOut++) = 0x00; + }else{ + u8 max = 0; + for(i=0; i<pGrp->nCol; i++){ + if( pGrp->aPK[i]>max ) max = pGrp->aPK[i]; + } + *(pOut++) = max+1; + } + } + memcpy(pOut, pGrp->zTab, nTab); + pOut += nTab; + + /* Output the change array. */ + pSaved = pOut; + for(i=0; rc==SQLITE_OK && i<pGrp->nChange; i++){ + rc = fuzzCopyChange(pParse, iGrp, &change, &p, &pOut); + } + if( pOut==pSaved ) rc = -1; + } + } + if( rc==SQLITE_OK ){ + fuzzWriteFile(zOut, pBuf, pOut-pBuf); + } + } + + return rc; +} + +int main(int argc, char **argv){ + int nRepeat = 0; /* Number of output files */ + int iSeed = 0; /* Value of PRNG seed */ + const char *zInput; /* Name of input file */ + void *pChangeset = 0; /* Input changeset */ + int nChangeset = 0; /* Size of input changeset in bytes */ + int i; /* Current output file */ + FuzzChangeset changeset; /* Partially parsed changeset */ + int rc; + u8 *pBuf = 0; + + if( argc!=4 && argc!=2 ) usage(argv[0]); + zInput = argv[1]; + + fuzzReadFile(zInput, &nChangeset, &pChangeset); + rc = fuzzParseChangeset(pChangeset, nChangeset, &changeset); + + if( rc==SQLITE_OK ){ + if( argc==2 ){ + for(i=0; i<changeset.nGroup; i++){ + fuzzPrintGroup(&changeset, changeset.apGroup[i]); + } + }else{ + pBuf = (u8*)fuzzMalloc(nChangeset*2 + 1024); + if( pBuf==0 ){ + rc = SQLITE_NOMEM; + }else{ + iSeed = atoi(argv[2]); + nRepeat = atoi(argv[3]); + fuzzRandomSeed((unsigned int)iSeed); + for(i=0; rc==SQLITE_OK && i<nRepeat; i++){ + char *zOut = sqlite3_mprintf("%s-%d", zInput, i); + rc = fuzzDoOneFuzz(zOut, pBuf, &changeset); + sqlite3_free(zOut); + } + fuzzFree(pBuf); + } + } + } + + if( rc!=SQLITE_OK ){ + fprintf(stderr, "error while processing changeset: %d\n", rc); + } + + return rc; +} +
diff --git a/third_party/sqlite/src/ext/session/changesetfuzz1.test b/third_party/sqlite/src/ext/session/changesetfuzz1.test new file mode 100644 index 0000000..f721e82 --- /dev/null +++ b/third_party/sqlite/src/ext/session/changesetfuzz1.test
@@ -0,0 +1,84 @@ +# 2018 November 08 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl +ifcapable !session {finish_test; return} +set testprefix changesetfuzz1 + + +set CF [test_find_binary changesetfuzz] +if {$CF==""} { + finish_test + return +} + +proc writefile {zFile data} { + set fd [open $zFile w] + fconfigure $fd -translation binary -encoding binary + puts -nonewline $fd $data + close $fd +} + +do_execsql_test 1.0 { + CREATE TABLE t1(a, b, c, d, PRIMARY KEY(c, d)); + CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c); + + INSERT INTO t1 VALUES ('one', 'two', 'three', 'four'), + ('five', 'six', 'seven', 'eight'), + ('nine', 'ten', 'eleven', 'twelve'); + INSERT INTO t2 VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9); +} + +set C [changeset_from_sql { + INSERT INTO t2 VALUES(10, 11, 12); + DELETE FROM t2 WHERE a=1; + UPDATE t1 SET b='forty-five' WHERE a='one'; + UPDATE t1 SET a='twenty-nine', b='seventy' WHERE a='five'; +}] +writefile c1.changeset $C + +do_test 1.1 { + for {set j 0} {$j < 200} {incr j} { + forcecopy c1.changeset input.changeset + for {set i 0} {$i < 6} {incr i} { + exec $CF input.changeset $i 1 + exec $CF input.changeset-0 + forcecopy input.changeset-0 input.changeset + } + } +} {} + +set P [patchset_from_sql { + INSERT INTO t2 VALUES(13, 14, 15); + DELETE FROM t2 WHERE a=4; + UPDATE t1 SET b='thirteen' WHERE a='one'; + UPDATE t1 SET a='ninety-seven', b='twenty' WHERE a='five'; +}] +writefile p1.patchset $P +do_test 1.2 { + for {set j 0} {$j < 200} {incr j} { + forcecopy p1.patchset input.patchset + for {set i 0} {$i < 6} {incr i} { + exec $CF input.patchset $i 1 + exec $CF input.patchset-0 + forcecopy input.patchset-0 input.patchset + } + } +} {} + + +finish_test +
diff --git a/third_party/sqlite/src/ext/session/session1.test b/third_party/sqlite/src/ext/session/session1.test index f3556167..7dfac95 100644 --- a/third_party/sqlite/src/ext/session/session1.test +++ b/third_party/sqlite/src/ext/session/session1.test
@@ -655,6 +655,13 @@ } {1 one 2 two 3 iii} execsql ROLLBACK +do_test $tn.14.1 { sqlite3session_config strm_size -1 } 64 +do_test $tn.14.2 { sqlite3session_config strm_size 65536 } 65536 +do_test $tn.14.3 { sqlite3session_config strm_size 64 } 64 +do_test $tn.14.4 { + list [catch {sqlite3session_config invalid 123} msg] $msg +} {1 SQLITE_MISUSE} + }] }
diff --git a/third_party/sqlite/src/ext/session/sessionC.test b/third_party/sqlite/src/ext/session/sessionC.test index dd48c5f8..d4bb1ab 100644 --- a/third_party/sqlite/src/ext/session/sessionC.test +++ b/third_party/sqlite/src/ext/session/sessionC.test
@@ -195,4 +195,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/session/sessionD.test b/third_party/sqlite/src/ext/session/sessionD.test index 0f69b2923..8012e500 100644 --- a/third_party/sqlite/src/ext/session/sessionD.test +++ b/third_party/sqlite/src/ext/session/sessionD.test
@@ -255,4 +255,3 @@ } {1 {no such table: ixua.i8}} finish_test -
diff --git a/third_party/sqlite/src/ext/session/sessionE.test b/third_party/sqlite/src/ext/session/sessionE.test index c4de1601..4c1fc5f 100644 --- a/third_party/sqlite/src/ext/session/sessionE.test +++ b/third_party/sqlite/src/ext/session/sessionE.test
@@ -111,5 +111,3 @@ S delete finish_test - -
diff --git a/third_party/sqlite/src/ext/session/sessionF.test b/third_party/sqlite/src/ext/session/sessionF.test index 14dd888..7c5e58c 100644 --- a/third_party/sqlite/src/ext/session/sessionF.test +++ b/third_party/sqlite/src/ext/session/sessionF.test
@@ -292,4 +292,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/session/sessionG.test b/third_party/sqlite/src/ext/session/sessionG.test index 465e330..dcd2718 100644 --- a/third_party/sqlite/src/ext/session/sessionG.test +++ b/third_party/sqlite/src/ext/session/sessionG.test
@@ -248,4 +248,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/session/sessionH.test b/third_party/sqlite/src/ext/session/sessionH.test index 696ef582..0022df95 100644 --- a/third_party/sqlite/src/ext/session/sessionH.test +++ b/third_party/sqlite/src/ext/session/sessionH.test
@@ -36,4 +36,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/session/session_common.tcl b/third_party/sqlite/src/ext/session/session_common.tcl index 350cba6e..3fe153d49 100644 --- a/third_party/sqlite/src/ext/session/session_common.tcl +++ b/third_party/sqlite/src/ext/session/session_common.tcl
@@ -95,6 +95,23 @@ return $changeset } +proc patchset_from_sql {sql {dbname main}} { + set rc [catch { + sqlite3session S db $dbname + db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" { + S attach $name + } + db eval $sql + S patchset + } patchset] + catch { S delete } + + if {$rc} { + error $patchset + } + return $patchset +} + proc do_then_apply_sql {sql {dbname main}} { proc xConflict args { return "OMIT" } set rc [catch {
diff --git a/third_party/sqlite/src/ext/session/sessionfault2.test b/third_party/sqlite/src/ext/session/sessionfault2.test index b91fb831..69a9267b 100644 --- a/third_party/sqlite/src/ext/session/sessionfault2.test +++ b/third_party/sqlite/src/ext/session/sessionfault2.test
@@ -282,4 +282,3 @@ finish_test -
diff --git a/third_party/sqlite/src/ext/session/sessioninvert.test b/third_party/sqlite/src/ext/session/sessioninvert.test new file mode 100644 index 0000000..67b7b85 --- /dev/null +++ b/third_party/sqlite/src/ext/session/sessioninvert.test
@@ -0,0 +1,159 @@ +# 2018 October 18 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. +# + +if {![info exists testdir]} { + set testdir [file join [file dirname [info script]] .. .. test] +} +source [file join [file dirname [info script]] session_common.tcl] +source $testdir/tester.tcl +ifcapable !session {finish_test; return} + +set testprefix sessioninvert + +proc iter_invert {C} { + set x [list] + sqlite3session_foreach -invert c $C { lappend x $c } + set x +} + +proc do_invert_test {tn sql {iter {}}} { + + forcecopy test.db test.db2 + sqlite3 db2 test.db2 + + set C [changeset_from_sql $sql] + + forcecopy test.db test.db3 + sqlite3 db3 test.db3 + uplevel [list do_test $tn.1 [list compare_db db db3] {}] + + set I [sqlite3changeset_invert $C] + sqlite3changeset_apply db $I {} + uplevel [list do_test $tn.2 [list compare_db db db2] {}] + + sqlite3changeset_apply_v2 -invert db3 $C {} + uplevel [list do_test $tn.3 [list compare_db db db3] {}] + + if {$iter!=""} { + uplevel [list do_test $tn.4 [list iter_invert $C] [list {*}$iter]] + } + + catch { db2 close } + catch { db3 close } +} + +do_execsql_test 1.0 { + CREATE TABLE t1(a PRIMARY KEY, b, c); + CREATE TABLE t2(d, e, f, PRIMARY KEY(e, f)); + + INSERT INTO t1 VALUES(1, 'one', 'i'); + INSERT INTO t1 VALUES(2, 'two', 'ii'); + INSERT INTO t1 VALUES(3, 'three', 'iii'); + INSERT INTO t1 VALUES(4, 'four', 'iv'); + INSERT INTO t1 VALUES(5, 'five', 'v'); + INSERT INTO t1 VALUES(6, 'six', 'vi'); + + INSERT INTO t2 SELECT * FROM t1; +} + +do_invert_test 1.1 { + INSERT INTO t1 VALUES(7, 'seven', 'vii'); +} { + {DELETE t1 0 X.. {i 7 t seven t vii} {}} +} + +do_invert_test 1.2 { + DELETE FROM t1 WHERE a<4; +} { + {INSERT t1 0 X.. {} {i 1 t one t i}} + {INSERT t1 0 X.. {} {i 2 t two t ii}} + {INSERT t1 0 X.. {} {i 3 t three t iii}} +} + +do_invert_test 1.3 { + UPDATE t1 SET c=5; +} { + {UPDATE t1 0 X.. {i 1 {} {} i 5} {{} {} {} {} t i}} + {UPDATE t1 0 X.. {i 2 {} {} i 5} {{} {} {} {} t ii}} + {UPDATE t1 0 X.. {i 3 {} {} i 5} {{} {} {} {} t iii}} + {UPDATE t1 0 X.. {i 4 {} {} i 5} {{} {} {} {} t iv}} + {UPDATE t1 0 X.. {i 5 {} {} i 5} {{} {} {} {} t v}} + {UPDATE t1 0 X.. {i 6 {} {} i 5} {{} {} {} {} t vi}} +} + +do_invert_test 1.4 { + UPDATE t1 SET b = a+1 WHERE a%2; + DELETE FROM t2; + INSERT INTO t1 VALUES(10, 'ten', NULL); +} + +do_invert_test 1.5 { + UPDATE t2 SET d = d-1; +} { + {UPDATE t2 0 .XX {i 2 t three t iii} {i 3 {} {} {} {}}} + {UPDATE t2 0 .XX {i 1 t two t ii} {i 2 {} {} {} {}}} + {UPDATE t2 0 .XX {i 5 t six t vi} {i 6 {} {} {} {}}} + {UPDATE t2 0 .XX {i 3 t four t iv} {i 4 {} {} {} {}}} + {UPDATE t2 0 .XX {i 0 t one t i} {i 1 {} {} {} {}}} + {UPDATE t2 0 .XX {i 4 t five t v} {i 5 {} {} {} {}}} +} + +do_execsql_test 2.0 { + ANALYZE; + PRAGMA writable_schema = 1; + DROP TABLE IF EXISTS sqlite_stat4; + SELECT * FROM sqlite_stat1; +} { + t2 sqlite_autoindex_t2_1 {6 1 1} + t1 sqlite_autoindex_t1_1 {6 1} +} + +do_invert_test 2.1 { + INSERT INTO sqlite_stat1 VALUES('t3', 'idx2', '1 2 3'); +} { + {DELETE sqlite_stat1 0 XX. {t t3 t idx2 t {1 2 3}} {}} +} + +do_invert_test 2.2 { + DELETE FROM sqlite_stat1; +} { + {INSERT sqlite_stat1 0 XX. {} {t t1 t sqlite_autoindex_t1_1 t {6 1}}} + {INSERT sqlite_stat1 0 XX. {} {t t2 t sqlite_autoindex_t2_1 t {6 1 1}}} +} + +do_invert_test 2.3 { + UPDATE sqlite_stat1 SET stat = 'hello world'; +} + +do_test 3.0 { + forcecopy test.db test.db2 + sqlite3 db2 test.db2 + set P [patchset_from_sql { + INSERT INTO t2 VALUES(1, 2, 3); + DELETE FROM t2 WHERE d = 3; + }] + + list [catch { sqlite3changeset_apply_v2 -invert db2 $P {} } msg] $msg +} {1 SQLITE_CORRUPT} + +do_test 3.1 { + list [catch { sqlite3session_foreach -invert db2 $P {} } msg] $msg +} {1 SQLITE_CORRUPT} + +do_test 3.2 { + sqlite3changeset_apply_v2 db2 $P {} + compare_db db db2 +} {} + + +finish_test
diff --git a/third_party/sqlite/src/ext/session/sessionrebase.test b/third_party/sqlite/src/ext/session/sessionrebase.test index cf267fa..c8dc43b 100644 --- a/third_party/sqlite/src/ext/session/sessionrebase.test +++ b/third_party/sqlite/src/ext/session/sessionrebase.test
@@ -474,4 +474,3 @@ catch { R delete } } finish_test -
diff --git a/third_party/sqlite/src/ext/session/sessionstat1.test b/third_party/sqlite/src/ext/session/sessionstat1.test index eefd876..a40cd94 100644 --- a/third_party/sqlite/src/ext/session/sessionstat1.test +++ b/third_party/sqlite/src/ext/session/sessionstat1.test
@@ -308,4 +308,3 @@ } {t3 null 3} finish_test -
diff --git a/third_party/sqlite/src/ext/session/sessionwor.test b/third_party/sqlite/src/ext/session/sessionwor.test index 72c46f1..e9545c53 100644 --- a/third_party/sqlite/src/ext/session/sessionwor.test +++ b/third_party/sqlite/src/ext/session/sessionwor.test
@@ -54,4 +54,3 @@ } finish_test -
diff --git a/third_party/sqlite/src/ext/session/sqlite3session.c b/third_party/sqlite/src/ext/session/sqlite3session.c index f7e7910..2e9a8ba 100644 --- a/third_party/sqlite/src/ext/session/sqlite3session.c +++ b/third_party/sqlite/src/ext/session/sqlite3session.c
@@ -25,6 +25,8 @@ # endif #endif +static int sessions_strm_chunk_size = SESSIONS_STRM_CHUNK_SIZE; + typedef struct SessionHook SessionHook; struct SessionHook { void *pCtx; @@ -87,6 +89,7 @@ SessionInput in; /* Input buffer or stream */ SessionBuffer tblhdr; /* Buffer to hold apValue/zTab/abPK/ */ int bPatchset; /* True if this is a patchset */ + int bInvert; /* True to invert changeset */ int rc; /* Iterator error code */ sqlite3_stmt *pConflict; /* Points to conflicting row, if any */ char *zTab; /* Current table */ @@ -243,6 +246,42 @@ ** The records associated with INSERT changes are in the same format as for ** changesets. It is not possible for a record associated with an INSERT ** change to contain a field set to "undefined". +** +** REBASE BLOB FORMAT: +** +** A rebase blob may be output by sqlite3changeset_apply_v2() and its +** streaming equivalent for use with the sqlite3_rebaser APIs to rebase +** existing changesets. A rebase blob contains one entry for each conflict +** resolved using either the OMIT or REPLACE strategies within the apply_v2() +** call. +** +** The format used for a rebase blob is very similar to that used for +** changesets. All entries related to a single table are grouped together. +** +** Each group of entries begins with a table header in changeset format: +** +** 1 byte: Constant 0x54 (capital 'T') +** Varint: Number of columns in the table. +** nCol bytes: 0x01 for PK columns, 0x00 otherwise. +** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated. +** +** Followed by one or more entries associated with the table. +** +** 1 byte: Either SQLITE_INSERT (0x12), DELETE (0x09). +** 1 byte: Flag. 0x01 for REPLACE, 0x00 for OMIT. +** record: (in the record format defined above). +** +** In a rebase blob, the first field is set to SQLITE_INSERT if the change +** that caused the conflict was an INSERT or UPDATE, or to SQLITE_DELETE if +** it was a DELETE. The second field is set to 0x01 if the conflict +** resolution strategy was REPLACE, or 0x00 if it was OMIT. +** +** If the change that caused the conflict was a DELETE, then the single +** record is a copy of the old.* record from the original changeset. If it +** was an INSERT, then the single record is a copy of the new.* record. If +** the conflicting change was an UPDATE, then the single record is a copy +** of the new.* record with the PK fields filled in based on the original +** old.* record. */ /* @@ -1793,12 +1832,12 @@ static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){ if( *pRc==SQLITE_OK && p->nAlloc-p->nBuf<nByte ){ u8 *aNew; - int nNew = p->nAlloc ? p->nAlloc : 128; + i64 nNew = p->nAlloc ? p->nAlloc : 128; do { nNew = nNew*2; - }while( nNew<(p->nBuf+nByte) ); + }while( (nNew-p->nBuf)<nByte ); - aNew = (u8 *)sqlite3_realloc(p->aBuf, nNew); + aNew = (u8 *)sqlite3_realloc64(p->aBuf, nNew); if( 0==aNew ){ *pRc = SQLITE_NOMEM; }else{ @@ -2396,12 +2435,12 @@ rc = sqlite3_reset(pSel); } - /* If the buffer is now larger than SESSIONS_STRM_CHUNK_SIZE, pass + /* If the buffer is now larger than sessions_strm_chunk_size, pass ** its contents to the xOutput() callback. */ if( xOutput && rc==SQLITE_OK && buf.nBuf>nNoop - && buf.nBuf>SESSIONS_STRM_CHUNK_SIZE + && buf.nBuf>sessions_strm_chunk_size ){ rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf); nNoop = -1; @@ -2540,7 +2579,8 @@ int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn, int nChangeset, /* Size of buffer pChangeset in bytes */ - void *pChangeset /* Pointer to buffer containing changeset */ + void *pChangeset, /* Pointer to buffer containing changeset */ + int bInvert /* True to invert changeset */ ){ sqlite3_changeset_iter *pRet; /* Iterator to return */ int nByte; /* Number of bytes to allocate for iterator */ @@ -2560,6 +2600,7 @@ pRet->in.xInput = xInput; pRet->in.pIn = pIn; pRet->in.bEof = (xInput ? 0 : 1); + pRet->bInvert = bInvert; /* Populate the output variable and return success. */ *pp = pRet; @@ -2574,7 +2615,16 @@ int nChangeset, /* Size of buffer pChangeset in bytes */ void *pChangeset /* Pointer to buffer containing changeset */ ){ - return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset); + return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0); +} +int sqlite3changeset_start_v2( + sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ + int nChangeset, /* Size of buffer pChangeset in bytes */ + void *pChangeset, /* Pointer to buffer containing changeset */ + int flags +){ + int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT); + return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, bInvert); } /* @@ -2585,7 +2635,16 @@ int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ){ - return sessionChangesetStart(pp, xInput, pIn, 0, 0); + return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0); +} +int sqlite3changeset_start_v2_strm( + sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int flags +){ + int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT); + return sessionChangesetStart(pp, xInput, pIn, 0, 0, bInvert); } /* @@ -2593,7 +2652,7 @@ ** object and the buffer is full, discard some data to free up space. */ static void sessionDiscardData(SessionInput *pIn){ - if( pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){ + if( pIn->xInput && pIn->iNext>=sessions_strm_chunk_size ){ int nMove = pIn->buf.nBuf - pIn->iNext; assert( nMove>=0 ); if( nMove>0 ){ @@ -2616,7 +2675,7 @@ int rc = SQLITE_OK; if( pIn->xInput ){ while( !pIn->bEof && (pIn->iNext+nByte)>=pIn->nData && rc==SQLITE_OK ){ - int nNew = SESSIONS_STRM_CHUNK_SIZE; + int nNew = sessions_strm_chunk_size; if( pIn->bNoDiscard==0 ) sessionDiscardData(pIn); if( SQLITE_OK==sessionBufferGrow(&pIn->buf, nNew, &rc) ){ @@ -2964,10 +3023,10 @@ op = p->in.aData[p->in.iNext++]; } - if( p->zTab==0 ){ + if( p->zTab==0 || (p->bPatchset && p->bInvert) ){ /* The first record in the changeset is not a table header. Must be a ** corrupt changeset. */ - assert( p->in.iNext==1 ); + assert( p->in.iNext==1 || p->zTab ); return (p->rc = SQLITE_CORRUPT_BKPT); } @@ -2992,33 +3051,39 @@ *paRec = &p->in.aData[p->in.iNext]; p->in.iNext += *pnRec; }else{ + sqlite3_value **apOld = (p->bInvert ? &p->apValue[p->nCol] : p->apValue); + sqlite3_value **apNew = (p->bInvert ? p->apValue : &p->apValue[p->nCol]); /* If this is an UPDATE or DELETE, read the old.* record. */ if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){ u8 *abPK = p->bPatchset ? p->abPK : 0; - p->rc = sessionReadRecord(&p->in, p->nCol, abPK, p->apValue); + p->rc = sessionReadRecord(&p->in, p->nCol, abPK, apOld); if( p->rc!=SQLITE_OK ) return p->rc; } /* If this is an INSERT or UPDATE, read the new.* record. */ if( p->op!=SQLITE_DELETE ){ - p->rc = sessionReadRecord(&p->in, p->nCol, 0, &p->apValue[p->nCol]); + p->rc = sessionReadRecord(&p->in, p->nCol, 0, apNew); if( p->rc!=SQLITE_OK ) return p->rc; } - if( p->bPatchset && p->op==SQLITE_UPDATE ){ + if( (p->bPatchset || p->bInvert) && p->op==SQLITE_UPDATE ){ /* If this is an UPDATE that is part of a patchset, then all PK and ** modified fields are present in the new.* record. The old.* record ** is currently completely empty. This block shifts the PK fields from ** new.* to old.*, to accommodate the code that reads these arrays. */ for(i=0; i<p->nCol; i++){ - assert( p->apValue[i]==0 ); + assert( p->bPatchset==0 || p->apValue[i]==0 ); if( p->abPK[i] ){ + assert( p->apValue[i]==0 ); p->apValue[i] = p->apValue[i+p->nCol]; if( p->apValue[i]==0 ) return (p->rc = SQLITE_CORRUPT_BKPT); p->apValue[i+p->nCol] = 0; } } + }else if( p->bInvert ){ + if( p->op==SQLITE_INSERT ) p->op = SQLITE_DELETE; + else if( p->op==SQLITE_DELETE ) p->op = SQLITE_INSERT; } } @@ -3335,7 +3400,7 @@ } assert( rc==SQLITE_OK ); - if( xOutput && sOut.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ + if( xOutput && sOut.nBuf>=sessions_strm_chunk_size ){ rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); sOut.nBuf = 0; if( rc!=SQLITE_OK ) goto finished_invert; @@ -3414,7 +3479,8 @@ int bDeferConstraints; /* True to defer constraints */ SessionBuffer constraints; /* Deferred constraints are stored here */ SessionBuffer rebase; /* Rebase information (if any) here */ - int bRebaseStarted; /* If table header is already in rebase */ + u8 bRebaseStarted; /* If table header is already in rebase */ + u8 bRebase; /* True to collect rebase information */ }; /* @@ -3811,35 +3877,36 @@ sqlite3_changeset_iter *pIter /* Iterator pointing at current change */ ){ int rc = SQLITE_OK; - int i; - int eOp = pIter->op; - if( p->bRebaseStarted==0 ){ - /* Append a table-header to the rebase buffer */ - const char *zTab = pIter->zTab; - sessionAppendByte(&p->rebase, 'T', &rc); - sessionAppendVarint(&p->rebase, p->nCol, &rc); - sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc); - sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc); - p->bRebaseStarted = 1; - } - - assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT ); - assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE ); - - sessionAppendByte(&p->rebase, - (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc - ); - sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc); - for(i=0; i<p->nCol; i++){ - sqlite3_value *pVal = 0; - if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){ - sqlite3changeset_old(pIter, i, &pVal); - }else{ - sqlite3changeset_new(pIter, i, &pVal); + if( p->bRebase ){ + int i; + int eOp = pIter->op; + if( p->bRebaseStarted==0 ){ + /* Append a table-header to the rebase buffer */ + const char *zTab = pIter->zTab; + sessionAppendByte(&p->rebase, 'T', &rc); + sessionAppendVarint(&p->rebase, p->nCol, &rc); + sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc); + sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc); + p->bRebaseStarted = 1; } - sessionAppendValue(&p->rebase, pVal, &rc); - } + assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT ); + assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE ); + + sessionAppendByte(&p->rebase, + (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc + ); + sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc); + for(i=0; i<p->nCol; i++){ + sqlite3_value *pVal = 0; + if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){ + sqlite3changeset_old(pIter, i, &pVal); + }else{ + sqlite3changeset_new(pIter, i, &pVal); + } + sessionAppendValue(&p->rebase, pVal, &rc); + } + } return rc; } @@ -4182,7 +4249,7 @@ SessionBuffer cons = pApply->constraints; memset(&pApply->constraints, 0, sizeof(SessionBuffer)); - rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf); + rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf, 0); if( rc==SQLITE_OK ){ int nByte = 2*pApply->nCol*sizeof(sqlite3_value*); int rc2; @@ -4248,6 +4315,7 @@ pIter->in.bNoDiscard = 1; memset(&sApply, 0, sizeof(sApply)); + sApply.bRebase = (ppRebase && pnRebase); sqlite3_mutex_enter(sqlite3_db_mutex(db)); if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){ rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); @@ -4398,7 +4466,8 @@ } } - if( rc==SQLITE_OK && bPatchset==0 && ppRebase && pnRebase ){ + assert( sApply.bRebase || sApply.rebase.nBuf==0 ); + if( rc==SQLITE_OK && bPatchset==0 && sApply.bRebase ){ *ppRebase = (void*)sApply.rebase.aBuf; *pnRebase = sApply.rebase.nBuf; sApply.rebase.aBuf = 0; @@ -4436,7 +4505,8 @@ int flags ){ sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ - int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); + int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); + int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset,bInverse); if( rc==SQLITE_OK ){ rc = sessionChangesetApply( db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags @@ -4493,7 +4563,8 @@ int flags ){ sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ - int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); + int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); + int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse); if( rc==SQLITE_OK ){ rc = sessionChangesetApply( db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags @@ -4866,13 +4937,12 @@ sessionAppendByte(&buf, p->op, &rc); sessionAppendByte(&buf, p->bIndirect, &rc); sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc); + if( rc==SQLITE_OK && xOutput && buf.nBuf>=sessions_strm_chunk_size ){ + rc = xOutput(pOut, buf.aBuf, buf.nBuf); + buf.nBuf = 0; + } } } - - if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){ - rc = xOutput(pOut, buf.aBuf, buf.nBuf); - buf.nBuf = 0; - } } if( rc==SQLITE_OK ){ @@ -5263,7 +5333,7 @@ sessionAppendByte(&sOut, pIter->bIndirect, &rc); sessionAppendBlob(&sOut, aRec, nRec, &rc); } - if( rc==SQLITE_OK && xOutput && sOut.nBuf>SESSIONS_STRM_CHUNK_SIZE ){ + if( rc==SQLITE_OK && xOutput && sOut.nBuf>sessions_strm_chunk_size ){ rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); sOut.nBuf = 0; } @@ -5374,4 +5444,25 @@ } } +/* +** Global configuration +*/ +int sqlite3session_config(int op, void *pArg){ + int rc = SQLITE_OK; + switch( op ){ + case SQLITE_SESSION_CONFIG_STRMSIZE: { + int *pInt = (int*)pArg; + if( *pInt>0 ){ + sessions_strm_chunk_size = *pInt; + } + *pInt = sessions_strm_chunk_size; + break; + } + default: + rc = SQLITE_MISUSE; + break; + } + return rc; +} + #endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */
diff --git a/third_party/sqlite/src/ext/session/sqlite3session.h b/third_party/sqlite/src/ext/session/sqlite3session.h index f0f785a3..c93d0ecd 100644 --- a/third_party/sqlite/src/ext/session/sqlite3session.h +++ b/third_party/sqlite/src/ext/session/sqlite3session.h
@@ -473,12 +473,38 @@ ** consecutively. There is no chance that the iterator will visit a change ** the applies to table X, then one for table Y, and then later on visit ** another change for table X. +** +** The behavior of sqlite3changeset_start_v2() and its streaming equivalent +** may be modified by passing a combination of +** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter. +** +** Note that the sqlite3changeset_start_v2() API is still <b>experimental</b> +** and therefore subject to change. */ int sqlite3changeset_start( sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ int nChangeset, /* Size of changeset blob in bytes */ void *pChangeset /* Pointer to blob containing changeset */ ); +int sqlite3changeset_start_v2( + sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */ + int nChangeset, /* Size of changeset blob in bytes */ + void *pChangeset, /* Pointer to blob containing changeset */ + int flags /* SESSION_CHANGESETSTART_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3changeset_start_v2 +** +** The following flags may passed via the 4th parameter to +** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]: +** +** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd> +** Invert the changeset while iterating through it. This is equivalent to +** inverting a changeset using sqlite3changeset_invert() before applying it. +** It is an error to specify this flag with a patchset. +*/ +#define SQLITE_CHANGESETSTART_INVERT 0x0002 /* @@ -1133,7 +1159,7 @@ ), void *pCtx, /* First argument passed to xConflict */ void **ppRebase, int *pnRebase, /* OUT: Rebase data */ - int flags /* Combination of SESSION_APPLY_* flags */ + int flags /* SESSION_CHANGESETAPPLY_* flags */ ); /* @@ -1151,8 +1177,14 @@ ** causes the sessions module to omit this savepoint. In this case, if the ** caller has an open transaction or savepoint when apply_v2() is called, ** it may revert the partially applied changeset by rolling it back. +** +** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd> +** Invert the changeset before applying it. This is equivalent to inverting +** a changeset using sqlite3changeset_invert() before applying it. It is +** an error to specify this flag with a patchset. */ #define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 +#define SQLITE_CHANGESETAPPLY_INVERT 0x0002 /* ** CAPI3REF: Constants Passed To The Conflict Handler @@ -1546,6 +1578,12 @@ int (*xInput)(void *pIn, void *pData, int *pnData), void *pIn ); +int sqlite3changeset_start_v2_strm( + sqlite3_changeset_iter **pp, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int flags +); int sqlite3session_changeset_strm( sqlite3_session *pSession, int (*xOutput)(void *pOut, const void *pData, int nData), @@ -1572,6 +1610,45 @@ void *pOut ); +/* +** CAPI3REF: Configure global parameters +** +** The sqlite3session_config() interface is used to make global configuration +** changes to the sessions module in order to tune it to the specific needs +** of the application. +** +** The sqlite3session_config() interface is not threadsafe. If it is invoked +** while any other thread is inside any other sessions method then the +** results are undefined. Furthermore, if it is invoked after any sessions +** related objects have been created, the results are also undefined. +** +** The first argument to the sqlite3session_config() function must be one +** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The +** interpretation of the (void*) value passed as the second parameter and +** the effect of calling this function depends on the value of the first +** parameter. +** +** <dl> +** <dt>SQLITE_SESSION_CONFIG_STRMSIZE<dd> +** By default, the sessions module streaming interfaces attempt to input +** and output data in approximately 1 KiB chunks. This operand may be used +** to set and query the value of this configuration setting. The pointer +** passed as the second argument must point to a value of type (int). +** If this value is greater than 0, it is used as the new streaming data +** chunk size for both input and output. Before returning, the (int) value +** pointed to by pArg is set to the final value of the streaming interface +** chunk size. +** </dl> +** +** This function returns SQLITE_OK if successful, or an SQLite error code +** otherwise. +*/ +int sqlite3session_config(int op, void *pArg); + +/* +** CAPI3REF: Values for sqlite3session_config(). +*/ +#define SQLITE_SESSION_CONFIG_STRMSIZE 1 /* ** Make sure we can call this stuff from C++.
diff --git a/third_party/sqlite/src/ext/session/test_session.c b/third_party/sqlite/src/ext/session/test_session.c index 3cd529a..7273ebe2 100644 --- a/third_party/sqlite/src/ext/session/test_session.c +++ b/third_party/sqlite/src/ext/session/test_session.c
@@ -737,20 +737,32 @@ sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR); /* Check for the -nosavepoint flag */ - if( bV2 && objc>1 ){ - const char *z1 = Tcl_GetString(objv[1]); - int n = strlen(z1); - if( n>1 && n<=12 && 0==sqlite3_strnicmp("-nosavepoint", z1, n) ){ - flags = SQLITE_CHANGESETAPPLY_NOSAVEPOINT; - objc--; - objv++; + if( bV2 ){ + if( objc>1 ){ + const char *z1 = Tcl_GetString(objv[1]); + int n = strlen(z1); + if( n>1 && n<=12 && 0==sqlite3_strnicmp("-nosavepoint", z1, n) ){ + flags |= SQLITE_CHANGESETAPPLY_NOSAVEPOINT; + objc--; + objv++; + } + } + if( objc>1 ){ + const char *z1 = Tcl_GetString(objv[1]); + int n = strlen(z1); + if( n>1 && n<=7 && 0==sqlite3_strnicmp("-invert", z1, n) ){ + flags |= SQLITE_CHANGESETAPPLY_INVERT; + objc--; + objv++; + } } } if( objc!=4 && objc!=5 ){ const char *zMsg; if( bV2 ){ - zMsg = "?-nosavepoint? DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?"; + zMsg = "?-nosavepoint? ?-inverse? " + "DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?"; }else{ zMsg = "DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?"; } @@ -969,31 +981,56 @@ Tcl_Obj *pCS; Tcl_Obj *pScript; int isCheckNext = 0; + int isInvert = 0; TestStreamInput sStr; memset(&sStr, 0, sizeof(sStr)); - if( objc>1 ){ + while( objc>1 ){ char *zOpt = Tcl_GetString(objv[1]); - isCheckNext = (strcmp(zOpt, "-next")==0); + int nOpt = strlen(zOpt); + if( zOpt[0]!='-' ) break; + if( nOpt<=7 && 0==sqlite3_strnicmp(zOpt, "-invert", nOpt) ){ + isInvert = 1; + }else + if( nOpt<=5 && 0==sqlite3_strnicmp(zOpt, "-next", nOpt) ){ + isCheckNext = 1; + }else{ + break; + } + objv++; + objc--; } - if( objc!=4+isCheckNext ){ - Tcl_WrongNumArgs(interp, 1, objv, "?-next? VARNAME CHANGESET SCRIPT"); + if( objc!=4 ){ + Tcl_WrongNumArgs( + interp, 1, objv, "?-next? ?-invert? VARNAME CHANGESET SCRIPT"); return TCL_ERROR; } - pVarname = objv[1+isCheckNext]; - pCS = objv[2+isCheckNext]; - pScript = objv[3+isCheckNext]; + pVarname = objv[1]; + pCS = objv[2]; + pScript = objv[3]; pChangeset = (void *)Tcl_GetByteArrayFromObj(pCS, &nChangeset); sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR); - if( sStr.nStream==0 ){ - rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); + if( isInvert ){ + int f = SQLITE_CHANGESETSTART_INVERT; + if( sStr.nStream==0 ){ + rc = sqlite3changeset_start_v2(&pIter, nChangeset, pChangeset, f); + }else{ + void *pCtx = (void*)&sStr; + sStr.aData = (unsigned char*)pChangeset; + sStr.nData = nChangeset; + rc = sqlite3changeset_start_v2_strm(&pIter, testStreamInput, pCtx, f); + } }else{ - sStr.aData = (unsigned char*)pChangeset; - sStr.nData = nChangeset; - rc = sqlite3changeset_start_strm(&pIter, testStreamInput, (void*)&sStr); + if( sStr.nStream==0 ){ + rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); + }else{ + sStr.aData = (unsigned char*)pChangeset; + sStr.nData = nChangeset; + rc = sqlite3changeset_start_strm(&pIter, testStreamInput, (void*)&sStr); + } } if( rc!=SQLITE_OK ){ return test_session_error(interp, rc, 0); @@ -1202,6 +1239,45 @@ return TCL_OK; } +/* +** tclcmd: sqlite3rebaser_configure OP VALUE +*/ +static int SQLITE_TCLAPI test_sqlite3session_config( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + struct ConfigOpt { + const char *zSub; + int op; + } aSub[] = { + { "strm_size", SQLITE_SESSION_CONFIG_STRMSIZE }, + { "invalid", 0 }, + { 0 } + }; + int rc; + int iSub; + int iVal; + + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "OP VALUE"); + return SQLITE_ERROR; + } + rc = Tcl_GetIndexFromObjStruct(interp, + objv[1], aSub, sizeof(aSub[0]), "sub-command", 0, &iSub + ); + if( rc!=TCL_OK ) return rc; + if( Tcl_GetIntFromObj(interp, objv[2], &iVal) ) return TCL_ERROR; + + rc = sqlite3session_config(aSub[iSub].op, (void*)&iVal); + if( rc!=SQLITE_OK ){ + return test_session_error(interp, rc, 0); + } + Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal)); + return TCL_OK; +} + int TestSession_Init(Tcl_Interp *interp){ struct Cmd { const char *zCmd; @@ -1217,6 +1293,7 @@ test_sqlite3changeset_apply_replace_all }, { "sql_exec_changeset", test_sql_exec_changeset }, { "sqlite3rebaser_create", test_sqlite3rebaser_create }, + { "sqlite3session_config", test_sqlite3session_config }, }; int i;
diff --git a/third_party/sqlite/src/main.mk b/third_party/sqlite/src/main.mk index 8992aad..40ab267ec 100644 --- a/third_party/sqlite/src/main.mk +++ b/third_party/sqlite/src/main.mk
@@ -363,6 +363,7 @@ $(TOP)/ext/misc/closure.c \ $(TOP)/ext/misc/csv.c \ $(TOP)/ext/misc/eval.c \ + $(TOP)/ext/misc/explain.c \ $(TOP)/ext/misc/fileio.c \ $(TOP)/ext/misc/fuzzer.c \ $(TOP)/ext/misc/ieee754.c \ @@ -397,6 +398,7 @@ $(TOP)/src/dbstat.c \ $(TOP)/src/expr.c \ $(TOP)/src/func.c \ + $(TOP)/src/global.c \ $(TOP)/src/insert.c \ $(TOP)/src/wal.c \ $(TOP)/src/main.c \ @@ -510,7 +512,8 @@ $(TOP)/test/fuzzdata3.db \ $(TOP)/test/fuzzdata4.db \ $(TOP)/test/fuzzdata5.db \ - $(TOP)/test/fuzzdata6.db + $(TOP)/test/fuzzdata6.db \ + $(TOP)/test/fuzzdata7.db # Standard options to testfixture # @@ -897,6 +900,10 @@ $(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c \ -o testfixture$(EXE) $(LIBTCL) $(THREADLIB) +coretestprogs: $(TESTPROGS) + +testprogs: coretestprogs srcck1$(EXE) fuzzcheck$(EXE) sessionfuzz$(EXE) + fulltest: $(TESTPROGS) fuzztest ./testfixture$(EXE) $(TOP)/test/all.test $(TESTOPTS) @@ -997,6 +1004,10 @@ $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o changeset$(EXE) \ $(TOP)/ext/session/changeset.c sqlite3.o $(THREADLIB) +changesetfuzz$(EXE): $(TOP)/ext/session/changesetfuzz.c sqlite3.o + $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o changesetfuzz$(EXE) \ + $(TOP)/ext/session/changesetfuzz.c sqlite3.o $(THREADLIB) + fts3view$(EXE): $(TOP)/ext/fts3/tool/fts3view.c sqlite3.o $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o fts3view$(EXE) \ $(TOP)/ext/fts3/tool/fts3view.c sqlite3.o $(THREADLIB)
diff --git a/third_party/sqlite/src/manifest b/third_party/sqlite/src/manifest index 3f62d03..bb8f3728 100644 --- a/third_party/sqlite/src/manifest +++ b/third_party/sqlite/src/manifest
@@ -1,12 +1,12 @@ -C Version\s3.25.3 -D 2018-11-05T20:37:38.221 +C Version\s3.26.0 +D 2018-12-01T12:34:55.966 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea -F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995 +F Makefile.in a050c8670ea0d7b37b2192306cbb50d392acd9902b84e9b56f3444d006f97a6c F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc a889c6981a222d639f8a548adcfb3183ac07871e27452ace4d810735750f216a +F Makefile.msc 0d6831ff7951b302e888d86d4c469e2ec3c22f59eba4118b8c38d5a51d9e2d4f F README.md 377233394b905d3b2e2b33741289e093bc93f2e7adbe00923b2c5958c9a9edee -F VERSION a0e6c0b0a597b690112e0efc8079eac843d09051529e7fd7451f893d03ba4a2c +F VERSION 654da1d4053fb09ffc33a3910e6d427182a7dcdc67e934fa83de2849ac83fccb F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2 F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90 @@ -33,11 +33,11 @@ F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977 F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 -F configure d48f51d52de9fda6eacabaa3c1ac43b0ac7137fa0fe5a3879f122a2de6ac8990 x +F configure 5811ffcd4866902d1706dcf8e0527f89165ec52859659942c9649bb1d3e4cc7b x F configure.ac 3552d3aecade98a9d4b64bceb48ffb7726cbc85902efde956812942f060fbd0a F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd -F doc/lemon.html ac63db056bce24b7368e29319cd1a7eb5f1798cc85922d96a80b6c3a4ff9f51b +F doc/lemon.html 24956ab2995e55fe171e55bdd04f22b553957dc8bb43501dbb9311e30187e0d3 F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710 F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd @@ -47,7 +47,7 @@ F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3 F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4 F ext/expert/expert1.test 333d037021c901322f9afc4a5687648ea23d56f1a0a079358a390664babf01be -F ext/expert/sqlite3expert.c 89b7b59be610b929958db02416539a46ac088fd84f81623c4190aff62e92c3c4 +F ext/expert/sqlite3expert.c 3da865f2286433588260f41e796422c611bceaca3a0bbf9139a619cf7d062c19 F ext/expert/sqlite3expert.h af6354f8ee5c9e025024e63fec3bd640a802afcc3099a44d804752cf0791d811 F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72 F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e @@ -80,19 +80,19 @@ F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d -F ext/fts3/fts3.c 012384f01df28345a8d0d0c7fe465ab211598a91d78a7331b3664533756ed9fa +F ext/fts3/fts3.c 65b8489e35da23b127992c6dd6cfd382a486f8c87bf26dfa72876efe46e551bb F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3Int.h 3378157f383540857a466420b8279626204434c3eb0dc948ad9bcd3991fc41f5 -F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1 +F ext/fts3/fts3_aux.c e9b465f8469acc2cd700a90c0242912a3202e4e4e15df72d7db7f1e3a2222c85 F ext/fts3/fts3_expr.c 3b1dbceddd8622599f3cc2626897667fe40487aaa1676707d6c37ec5a8422fc1 F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60 F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf F ext/fts3/fts3_icu.c deb46f7020d87ea7a14a433fb7a7f4bef42a9652 F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009 F ext/fts3/fts3_snippet.c 68ae118b0f834ea53d2b89e4087fc0f0b8c4ee4e -F ext/fts3/fts3_term.c 88c55a6fa1a51ab494e33dced0401a6c28791fd7 +F ext/fts3/fts3_term.c 9b8065cc70ad514fcc25a7b099ddab8b5333f724dedd57184b7e79238e2b2a39 F ext/fts3/fts3_test.c 79f2a7fbb3f672fa032e5a432ca274ea3ee93c34 -F ext/fts3/fts3_tokenize_vtab.c a27593ab19657166f6fa5ec073b678cc29a75860 +F ext/fts3/fts3_tokenize_vtab.c a47c2a33de6db00816704315ac0a9afdfa1c71fa5b99f79171c0f7b30861f784 F ext/fts3/fts3_tokenizer.c a22bf311a71f3efa9d7012d8cc48fc9b0f3dace7 F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3 F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004 @@ -115,20 +115,20 @@ F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857 F ext/fts5/fts5_expr.c 5aef080ba3c8947e22f38ce1ff9fe548e4a740e72b77241f35ed941ae128d2c7 F ext/fts5/fts5_hash.c 32be400cf761868c9db33efe81a06eb19a17c5402ad477ee9efb51301546dd55 -F ext/fts5/fts5_index.c d1b2d7d92cb2b72b9465da35b7d7c30e4b426c7f208bf6f94ce86b50eed8a1cb -F ext/fts5/fts5_main.c 7e52868e6b444e5353ff30e1dcd2a9273e8eaa543ddccf0c94b3cd2c235ff104 +F ext/fts5/fts5_index.c baf3ad4451d32d35c2bd692ee4a81235ca7f26bd6f7613f7f73505474c33bbf2 +F ext/fts5/fts5_main.c 287a1a56580df304d7fa2fc1890f85b9cb6ac6b9e7c8af7dfa2151528db4b059 F ext/fts5/fts5_storage.c 4bec8a1b3905978b22a67bca5f4a3cfdb94af234cf51efb36f4f2d733d278634 F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95 F ext/fts5/fts5_test_mi.c 65864ba1e5c34a61d409c4c587e0bbe0466eb4f8f478d85dc42a92caad1338e6 -F ext/fts5/fts5_test_tok.c ffd657dd67e7fcdb31bf63fb60b6d867299a581d0f46e97086abacd66c2a9b26 +F ext/fts5/fts5_test_tok.c 80de1a4b1a3caa216c3be8862440f0117a8357dd9b7cfc5a2a2ce11fe6eb64ae F ext/fts5/fts5_tokenize.c ebd13d034f3dc7c841e1c32c364a4fca5cc2e05a0b91682a93fa1e6defcd4292 F ext/fts5/fts5_unicode2.c 543cf0987c27ad59e5a7a6222480b917b5431009b7b139027c9581a63e39e37e F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738 -F ext/fts5/fts5_vocab.c 1cd79854cb21543e66507b25b0578bc1b20aa6a1349b7feceb8e8fed0e7a77a6 +F ext/fts5/fts5_vocab.c fbe38044889b2d2d99babeeef239c620fb0332bb928a84506ac748d81500b354 F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05 F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841 -F ext/fts5/test/fts5aa.test 87f4b50e755b52c6192c76ceccf4247d462bb44b52fa17358f273d8ce5d975f0 +F ext/fts5/test/fts5aa.test 840081efaee97f5ec570146bbdd79cfdfaea0ab303de3d5037b6d6c78b42ccdd F ext/fts5/test/fts5ab.test 9205c839332c908aaad2b01ab8670ece8b161e8f2ec8a9fabf18ca9385880bb7 F ext/fts5/test/fts5ac.test a7aa7e1fefc6e1918aa4d3111d5c44a09177168e962c5fd2cca9620de8a7ed6d F ext/fts5/test/fts5ad.test e8cf959dfcd57c8e46d6f5f25665686f3b6627130a9a981371dafdf6482790de @@ -151,11 +151,11 @@ F ext/fts5/test/fts5columnsize.test 45459ce4dd9fd853b6044cdc9674921bff89e3d840f348ca8c1630f9edbf5482 F ext/fts5/test/fts5config.test 60094712debc59286c59aef0e6cf511c37d866802776a825ce437d26afe0817f F ext/fts5/test/fts5conflict.test 655925678e630d3cdf145d18725a558971806416f453ac8410ca8c04d934238d -F ext/fts5/test/fts5connect.test b12a2a8b02af3c31c18abbc33aa8100d364de19a888a44457484d21dbccb18a7 +F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c073e19b3ae9126b2f4 F ext/fts5/test/fts5content.test 688d5ac7af194ebc67495daea76a69e3cd5480122c2320e72d41241b423b4116 -F ext/fts5/test/fts5corrupt.test 8957f0f7e57e0f8a102c5b6e1a7326d6a1966b28e1d99c5883822af1e6038e9e -F ext/fts5/test/fts5corrupt2.test 6deaf9f9606b3c957529db9881622bb3a7829b19bb3cdf8f276f074d684ede56 -F ext/fts5/test/fts5corrupt3.test 1b489101212206da1f27d0d03b9667e54571cba72db7e70b195fdf39f867b48c +F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe +F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f +F ext/fts5/test/fts5corrupt3.test ff9aee403611461e2619d2217c0d7d101a9c0179277c13c8a89516d7cf0dda43 F ext/fts5/test/fts5delete.test cbf87e3b8867c4d5cfcaed975c7475fd3f99d072bce2075fcedf43d1f82af775 F ext/fts5/test/fts5detail.test 31b240dbf6d44ac3507e2f8b65f29fdc12465ffd531212378c7ce1066766f54e F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11 @@ -175,11 +175,11 @@ F ext/fts5/test/fts5faultA.test be4487576bff8c22cee6597d1893b312f306504a8c6ccd3c53ca85af12290c8c F ext/fts5/test/fts5faultB.test e6d04f9ea7b21be1d89abb8df2cb4baf65b0453b744d5a805fcd3ef45ff86a7e F ext/fts5/test/fts5faultD.test cc5d1225556e356615e719c612e845d41bff7d5a -F ext/fts5/test/fts5first.test 707a591b1b7d893fcfcb2366cbfe56aefab5d9c7cfa58bef35eba73a1dbf3b29 +F ext/fts5/test/fts5first.test 3fcf2365c00a15fc9704233674789a3b95131d12de18a9b996159f6909dc8079 F ext/fts5/test/fts5full.test 49b565da02918c06e58f51f0b953b0302b96f155aa68baba24782b81570685e2 F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e F ext/fts5/test/fts5hash.test a4cf51acad99bfc43c16fb74f9d22495dc221ae0701fc5e908ca963a9b26a02b -F ext/fts5/test/fts5integrity.test 6c4aad7f7380ec459a0c27ebbc0cb314fa67f3a3dad0cc820f612d33aa887166 +F ext/fts5/test/fts5integrity.test 4317561cd25eca7df16aa1f7d1a700ee958059fa639785f94aba0a84df9ab17b F ext/fts5/test/fts5lastrowid.test be98fe3e03235296585b72daad7aed5717ba0062bae5e5c18dd6e04e194c6b28 F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad F ext/fts5/test/fts5matchinfo.test 79129ff6c9a2d86943b287a5a8caa7ee639f6dcf004d8975d15c279374e82e35 @@ -195,10 +195,10 @@ F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457 F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056 F ext/fts5/test/fts5query.test ac363b17a442620bb0780e93c24f16a5f963dfe2f23dc85647b869efcfada728 -F ext/fts5/test/fts5rank.test beb1adae7b076beea98277f140e713f9713f503866d3ff7286c9805b220dd4a2 -F ext/fts5/test/fts5rebuild.test 6d09fd54b1170a1e54fe17b808bbf17fba3154956cc2f065dd94bf1e3d254f63 +F ext/fts5/test/fts5rank.test ca5000241924ecc2882db33c60f4f3a62b1ee6b16b5a9c8c6ddd9b6b2138489c +F ext/fts5/test/fts5rebuild.test 55d6f17715cddbf825680dd6551efbc72ed916d8cf1cde40a46fc5d785b451e7 F ext/fts5/test/fts5restart.test 835ecc8f449e3919f72509ab58056d0cedca40d1fe04108ccf8ac4c2ba41f415 -F ext/fts5/test/fts5rowid.test 365997f5aebd619df3ae46c2a4bfc8edba361899bc4e52cebfba0dbcbf720522 +F ext/fts5/test/fts5rowid.test b8790ec170a8dc1942a15aef3db926a5f3061b1ff171013003d8297203a20ad6 F ext/fts5/test/fts5simple.test 313ad28ef38ebe25f0a1673dd18f2fac446e25feb15bbb0c223a65ea00594f72 F ext/fts5/test/fts5simple2.test 258a1b0c590409bfa5271e872c79572b319d2a56554d0585f68f146a0da603f0 F ext/fts5/test/fts5simple3.test d5c74a9d3ca71bd5dd5cacb7c55b86ea12cdddfc8b1910e3de2995206898380f @@ -213,9 +213,9 @@ F ext/fts5/test/fts5unicode4.test 6463301d669f963c83988017aa354108be0b947d325aef58d3abddf27147b687 F ext/fts5/test/fts5unindexed.test 9021af86a0fb9fc616f7a69a996db0116e7936d0db63892db6bafabbec21af4d F ext/fts5/test/fts5update.test 0737876e20e97a6a6abf45de19fc99315727bcee6a83fadcada1cc080b9aa8f0 -F ext/fts5/test/fts5version.test 99b81372630fbf359107c96580fa761e41cdfb1dafc9966e148629ca72efee71 -F ext/fts5/test/fts5vocab.test 2ba98bcef0fcab3e5fead8eaabd6c0efb7e57bfe707a5cfcc18572ca9b277360 -F ext/fts5/test/fts5vocab2.test 2beeec974a305a1d79b91426622cc922c87065874437d22b400de7438979959e +F ext/fts5/test/fts5version.test c8f2cc105f0abf0224965f93e584633dee3e06c91478bc67e468f7cfdf97fd6a +F ext/fts5/test/fts5vocab.test 2de834ee6405130d3373817ced8fefbfee392b63d932e471740e09829f1e4510 +F ext/fts5/test/fts5vocab2.test d6039b20118e886113fc63614d9ad39a466fc2af34184f3e915b9f92b7ebfa10 F ext/fts5/tool/fts5speed.tcl b0056f91a55b2d1a3684ec05729de92b042e2f85 F ext/fts5/tool/fts5txt2db.tcl 526a9979c963f1c54fd50976a05a502e533a4c59 F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093 @@ -270,21 +270,23 @@ F ext/lsm1/test/lsm1_simple.test ca949efefa102f4644231dcd9291d8cda7699a4ce1006b26e0e3fcb72233f422 F ext/lsm1/tool/mklsm1c.tcl f31561bbee5349f0a554d1ad7236ac1991fc09176626f529f6078e07335398b0 F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f238c240 -F ext/misc/amatch.c 6db4607cb17c54b853a2d7c7c36046d004853f65b9b733e6f019d543d5dfae87 +F ext/misc/amatch.c c0a6a807a553eaa220bf69fca0353cd1587a3bfb3d2224fa425e3e6efcacc98a F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb F ext/misc/appendvfs.c 3777f22ec1057dc4e5fd89f2fbddcc7a29fbeef1ad038c736c54411bb1967af7 -F ext/misc/btreeinfo.c 78c8c57d325185ccc04b7679e5b020e34a4d9c87453e6b7ac943d0a26cee3256 +F ext/misc/btreeinfo.c 4f0ebf278f46e68e6306c667917766cebc5550fd35d5de17847988e22892d4d2 F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c6005 -F ext/misc/closure.c fe928228e8dfb2f00227311c203ccba9c2e5561f4f6de6da87e5b4a30cd8af15 -F ext/misc/completion.c fc811dda86d899c15848079c32cad40c181da1dd7a1a4f8d768a2c6ce07a1904 +F ext/misc/closure.c 9f8fa11aa6c6e2f6d7296ffa88f103df4b46abd9602bcab3ea2f8fc24f334f63 +F ext/misc/completion.c cec672d40604075bb341a7f11ac48393efdcd90a979269b8fe7977ea62d0547f F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189 -F ext/misc/csv.c 65297bcce8d5acd5aadef42acbe739aef5a2ef5e74c7b73361ca19f3e21de657 +F ext/misc/csv.c 88333dc9f7dcf6a8148406f10ae04261e24e3b4c721550ae33e9e71f1265c1f1 F ext/misc/dbdump.c 12389a10c410fadf1e68eeb382def92d5a7fa9ce7cce4fb86a736fa2bac1000a F ext/misc/eval.c 6ea9b22a5fa0dd973b67ca4e53555be177bc0b7b263aadf1024429457c82c0e3 -F ext/misc/fileio.c 7317d825fab6a3c48f6e3822a00a6a22e08e55af31700ac96f16a523f83069fd +F ext/misc/explain.c d5c12962d79913ef774b297006872af1fccda388f61a11d37758f9179a09551f +F ext/misc/fileio.c e3153b04433897a18a3d17185845f286892e96fdf87f4301290d09c36ae1759f F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c -F ext/misc/json1.c 276f87dc8365b34b0fffb7ef32481dd07fac6fdb3224e2822396a48377ac8363 +F ext/misc/json1.c 3f017d2659e531d021d015ec5d69ea0b1c71f2e15bf9768b1e149fcdf6c3e0b1 +F ext/misc/memstat.c 941928c6104d8ed569a6c47caa756dc78b8091f7a15f87d3004f3b1e576b10da F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567 F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29 F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 @@ -294,59 +296,59 @@ F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c F ext/misc/rot13.c 540a169cb0d74f15522a8930b0cccdcb37a4fd071d219a5a083a319fc6e8db77 F ext/misc/scrub.c db9fff56fed322ca587d73727c6021b11ae79ce3f31b389e1d82891d144f22ad -F ext/misc/series.c c7197db304f7009b08d6459a9de02e7f51ad0e1a3fdacbc1ebf5252a9a346959 -F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56 -F ext/misc/shathree.c 9e960ba50483214c6a7a4b1517f8d8cef799e9db381195178c3fd3ad207e10c0 +F ext/misc/series.c 0c97f63378fddc9f425e82ba139b9aaf902211f24ced115c2b6ae12b425f7334 +F ext/misc/sha1.c df0a667211baa2c0612d8486acbf6331b9f8633fd4d605c17c7cccd26d59c6bd +F ext/misc/shathree.c 22ba7ca84a433d6466a7d05dcc876910b435a715da8cc462517db9351412b8c8 F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52 -F ext/misc/spellfix.c 54d650f44f3a69a851814791bd4d304575cdbbf78d96d4f0801b44a8f31a58c5 +F ext/misc/spellfix.c f88ecb2c0294453ce8b7704b211f5350c41b085b38c8e056852e3a08b0f5e484 F ext/misc/sqlar.c 57d5bc45cd5492208e451f697404be88f8612527d64c9d42f96b325b64983d74 -F ext/misc/stmt.c 6f16443abb3551e3f5813bb13ba19a30e7032830015b0f92fe0c0453045c0a11 -F ext/misc/templatevtab.c 8251b31011dd00fc38e739c78c234c930be42b3b274bbe0493b79cd40db02a9e +F ext/misc/stmt.c 8a8dc4675042e4551e4afe99b8d0cc7a4a2fc1a8dacc0a9ce1b1bbff145da93d +F ext/misc/templatevtab.c 8a16a91a5ceaccfcbd6aaaa56d46828806e460dd194965b3f77bf38f14b942c4 F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512 -F ext/misc/unionvtab.c 0b3173f69b8899da640a13a345dc5ef1400199405f738abe6145b2454195b8ff +F ext/misc/unionvtab.c acf947858054850db2d4a611bfeae072cdc6d9f517b46a993fe1f2f1ea20031e F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95 F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178 -F ext/misc/vtablog.c 31d0d8f4406795679dcd3a67917c213d3a2a5fb3ea5de35f6e773491ed7e13c9 +F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 -F ext/misc/zipfile.c c4de8f0ad446ce4a49aae11ff7b771cd7af60d7136c0bcfb53da1475b9075e79 +F ext/misc/zipfile.c 1d731db326c40e11fc608f38132acff31619946c000e85ab8efe75bbedc2a441 F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64 F ext/rbu/rbu.c 8681f6157db6adc82c34af24b14ea8a3be0146ad2a3b6c1d5da6cb8a5796c8ce -F ext/rbu/rbu1.test 41123c64e8c88bd14eb7d3f8562f37fa87aaeb154b1eade2881de21d3504be55 -F ext/rbu/rbu10.test 1846519a438697f45e9dcb246908af81b551c29e1078d0304fae83f1fed7e9ee -F ext/rbu/rbu11.test 9bc68c2d3dbeb1720153626e3bd0466dcc017702 -F ext/rbu/rbu12.test bde22ed0004dd5d1888c72a84ae407e574aeae16 -F ext/rbu/rbu13.test 462ff799c4afedc3ef8a47ff818c0ffbf14ae4f2 -F ext/rbu/rbu14.test 01f5dcba904aecadbaea69d4ccdc2ea43dd30560 -F ext/rbu/rbu3.test 8bd4c6b87367c358981b6a47dc3d654fa60bff90 -F ext/rbu/rbu5.test cf1fa84d6107efd73e292a7be8e1fb31953ca45c -F ext/rbu/rbu6.test 32e8ed60631b6facdb6366bd2b5f5f25245e7edb -F ext/rbu/rbu7.test fd025d5ba440fcfe151fbb0e3835e1e7fe964fa1 -F ext/rbu/rbu8.test 3bbf2c35d71a843c463efe93946f14ad10c3ede0 -F ext/rbu/rbu9.test 0806d1772c9f4981774ff028de6656e4183082af -F ext/rbu/rbuA.test 4e58e46e60d4064248614c43303d71f1b18cc804dd834ce6a913b3861828b28d -F ext/rbu/rbuB.test c25bc325b8072a766e56bb76c001866b405925c2 -F ext/rbu/rbuC.test efe47db508a0269b683cb2a1913a425ffd39a831 +F ext/rbu/rbu1.test 221d9c18a5e600ac9ac6b1810d99d9f99163a7909ba61597876ab6e4d4beb3d6 +F ext/rbu/rbu10.test 0a201c32202143f23c81c0144503da339786fc20acb7a2fda11601b65659f314 +F ext/rbu/rbu11.test 5c834cf491086b45e071eabf71f708febc143e86a384a92de69e0b1a4cace144 +F ext/rbu/rbu12.test 29f8b2118f6c96fac3755bd6d2b55c2db24f878b1f11fbfbe294f3a230a3dcdc +F ext/rbu/rbu13.test 1285298e3360ec74511764841b3c174dcfe21da2f618c22febf1a20abd0365c2 +F ext/rbu/rbu14.test 4a7bf0b3a4516d3ab0bc0ba4ceb53eb7e3324147ccda152e561060f659dbba31 +F ext/rbu/rbu3.test d6c6cc7a1326e8e23b9820f30bd3054f22092e503fadfd2a660ae006653f6d80 +F ext/rbu/rbu5.test 724b38ea5f722e3d22dc76343860bd998bb676c3f78c4bc8175df5c5d7720e23 +F ext/rbu/rbu6.test 401064236d3cf86b7edc01c586d7c5554f48553946fbfa1a3af35d7e47dce9e3 +F ext/rbu/rbu7.test ae25f47b56f178197fc1098537a35a39176cc73d1629b03dc9d795929fc36ec2 +F ext/rbu/rbu8.test b98a6fc58ead84a0e6ddee775b9702cd981f318d5d4fd1d4df0fa0c40db7251b +F ext/rbu/rbu9.test 0e4d985e25620d61920597e8ea69c871c9e8c1f5a0be2ae9fa70bb641d74378c +F ext/rbu/rbuA.test b34a90cb495682c25b5fc03a9d5e7a4fc99541c29256f25e2e2a4f6542b4f5b3 +F ext/rbu/rbuB.test 52b07158824c6927b7e25554ace92a695cdebfc296ae3d308ac386984aded9bc +F ext/rbu/rbuC.test 80f1cc2fb74f44b1128fd0ed8eedab3a76fefeb72a947860e2869ef76fc8dc6b F ext/rbu/rbu_common.tcl acfb7fbbaf8d46a9f6f6a5ec795616c84d705e1565d918afe43f0ff53ea0efa5 -F ext/rbu/rbucollate.test 86d6fc9b8f59a27b7b5a6e20b5e29816d338a0dbdea8c54bfcc549a0d437f3ea -F ext/rbu/rbucrash.test 61470d977a06a0abc2ec35b05d82a1d7d87d10f4ffabad14c1c231edc942ad66 -F ext/rbu/rbucrash2.test b2ecbdd7bb72c88bd217c65bd00dafa07f7f2d4d -F ext/rbu/rbudiff.test 3e605cf624d00d04d0fb1316a3acec4fbe3b3ac5 -F ext/rbu/rbudor.test 99b05cc0df613e962c2c8085cfb05686a09cf315 -F ext/rbu/rbufault.test 2654aef20f8ee7de37c9c1997a44f2773dc7bf24887adea39fb19314ef32cb90 -F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06 -F ext/rbu/rbufault3.test 0913c1aeaee266d9c36c33179341a5a504aad7d423d1979cfec43c8346a29899 -F ext/rbu/rbufault4.test 34e70701cbec51571ffbd9fbf9d4e0f2ec495ca7 -F ext/rbu/rbufts.test a2bbd202c9321fba15fb4a62a90add7d70e07bd8404e1e598135adbfff8a0508 -F ext/rbu/rbumulti.test 2cf153ab3d5861ff26517dc6cbaec430787a59f1d50e8771fe7a7529a0551cf1 -F ext/rbu/rbuprogress.test 1849d4e0e50616edf5ce75ce7db86622e656b5cf -F ext/rbu/rburesume.test 8acb77f4a422ff55acfcfc9cc15a5cb210b1de83 -F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48 -F ext/rbu/rbusplit.test 69271c790732b28bd465551d80b0a9a3f074e189896ee8490ce56d22078c124d -F ext/rbu/rbutemplimit.test cd553a9288d515d0b5f87d277e76fd18c4aa740b761e7880fab11ce986ea18d1 -F ext/rbu/rbuvacuum.test ff357e9b556ca7ad4673da0ff7f244def919ff858e0f9f350d3e30fdd83a62a8 -F ext/rbu/rbuvacuum2.test 2074ab14fe66e1c7e7210c62562650dcd215bbaa -F ext/rbu/sqlite3rbu.c f438fea899d15d13ff3e3133242b9e378c37b5a3d76add8c342c68bdd65c6819 +F ext/rbu/rbucollate.test cac528a9a46318cba42e61258bb42660bbbf4fdb9a8c863de5a54ad0c658d197 +F ext/rbu/rbucrash.test 000981a1fe8a6e4d9a684232f6a129e66a3ef595f5ed74655e2f9c68ffa613b4 +F ext/rbu/rbucrash2.test efa143cc94228eb0266d3f1abfbee60a5838a84cef7cc3fcb8c145b74d96fd41 +F ext/rbu/rbudiff.test 156957851136b63c143478518dc1bda6c832103cdbe8ac1d7cdd47edb3cbe0a3 +F ext/rbu/rbudor.test e3e8623926012f43eebe51fedf06a102df2640750d971596b052495f2536db20 +F ext/rbu/rbufault.test 2d7f567b79d558f6e093c58808cab4354f8a174e3802f69e7790a9689b3c09f8 +F ext/rbu/rbufault2.test 06e735c002c17802d93debca41f59b027e7429db7de17f2a81318ecfd3c651d4 +F ext/rbu/rbufault3.test e0052ccba428ffdd2bb989d3ae84716f058ec5ab5f7196c64ba407b9d23c7255 +F ext/rbu/rbufault4.test 03d2849c3df7d7bd14a622e789ff049e5080edd34a79cd432e01204db2a5930a +F ext/rbu/rbufts.test 0ae8d1da191c75bd776b86e24456db0fb6e97b7c944259fae5407ea55d23c31d +F ext/rbu/rbumulti.test 5fb139058f37ddc5a113c5b93238de915b769b7792de41b44c983bc7c18cf5b9 +F ext/rbu/rbuprogress.test 04614ff8820bab9c1ec1b7dbec1edc4b45474421d4fe7abbd2a879a9c02884f9 +F ext/rbu/rburesume.test dbdc4ca504e9c76375a69e5f0d91205db967dcc509a5166ca80231f8fda49eb1 +F ext/rbu/rbusave.test f4190a1a86fccf84f723af5c93813365ae33feda35845ba107b59683d1cdd926 +F ext/rbu/rbusplit.test b37e7b40b38760881dc9c854bd40b4744c6b6cd74990754eca3bda0f407051e8 +F ext/rbu/rbutemplimit.test 7f408f49b90fa0a720d7599f3aec74a3c85e6cd78e56fdf726ce00af9147a341 +F ext/rbu/rbuvacuum.test 55e101e90168c2b31df6c9638fe73dc7f7cc666b6142266d1563697d79f73534 +F ext/rbu/rbuvacuum2.test 0a7669bbabdaeed915f02f59f33fe20e13d4932ba2086fe00a82064d9424c80b +F ext/rbu/sqlite3rbu.c 71f8c09948d09ec9c5a8dbe7127e8ef61ef0853e698b2650be2485ac7b9c75c8 F ext/rbu/sqlite3rbu.h b42bcd4d8357268c6c39ab2a60b29c091e89328fa8cc49c8fac5ab8d007e79b2 F ext/rbu/test_rbu.c baa23eb28457580673d2175e5f0c29ced0cd320ee819b13ad362398c53b96e90 F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15 @@ -356,11 +358,11 @@ F ext/repair/sqlite3_checker.tcl a9a2caa9660567257c177a91124d8c0dccdfa341e25c51e6da7f1fd9e601eafa F ext/repair/test/README.md 34b2f542cf5be7bffe479242b33ee3492cea30711e447cc4a1a86cb5915f419e F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc78249442da72ff3f8297398a69 -F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f +F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/geopoly.c 415a8ca5dfab54eea779e0bf31a859afb0b869a5147a726df4aec4b57c1bad57 -F ext/rtree/rtree.c 6cc2e673cf1e9ea1619f13ab990f12389dfb951b131acbc2fbe164cee8992a20 +F ext/rtree/geopoly.c d56ff997f2646b03be742eb85e8206f779d777f3a282fe0da576780ca0e11f20 +F ext/rtree/rtree.c 7125183bf6c37b8b8ee1a04d2b0fe258531fd31650fdd050ed041817f1943d17 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349 F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2 @@ -369,9 +371,9 @@ F ext/rtree/rtree5.test 49c9041d713d54560b315c2c7ef7207ee287eba1b20f8266968a06f2e55d3142 F ext/rtree/rtree6.test 593e0d36510d5ac1d1fb39b018274ff17604fe8fdca8cf1f8e16559cea1477f4 F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5 -F ext/rtree/rtree8.test 924926d7c64ac59fcca0809de472d9dd73c612f54daae1cf992bdd7dac90305b +F ext/rtree/rtree8.test 2d99006a1386663978c9e1df167554671e4f711c419175b39f332719deb1ce0e F ext/rtree/rtree9.test c646f12c8c1c68ef015c6c043d86a0c42488e2e68ed1bb1b0771a7ca246cbabf -F ext/rtree/rtreeA.test 20623ca337ca3bd7e008cc9fb49e44dbe97f1a80b238e10a12bb4afcd0da3776 +F ext/rtree/rtreeA.test ed2f1be9c06dde0b1ab93a95dd9e87eeaa02db2d30bcb4b9179b69ee3dc3319b F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9 F ext/rtree/rtreeC.test 128928549d22b65c381ab1366760d08703cd75e34f6a7a506ece38f9330b7282 F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc @@ -381,15 +383,17 @@ F ext/rtree/rtreeH.test aa08cc4fa8005b4c67446c7110205055b4d6da90e760e6f44b82dfa4cdf8d87a F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195 F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed -F ext/rtree/rtreecheck.test 4d29103d1e16fcbf90135d1c637b833688492b063b2971dfb5dc6ba76555cfee +F ext/rtree/rtreecheck.test d67d5b3e9e45bfa8cd90734e8e9302144ac415b8e9176c6f02d4f92892ee8a35 F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d -F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28 +F ext/rtree/sqlite3rtree.h 03c8db3261e435fbddcfc961471795cbf12b24e03001d0015b2636b0f3881373 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c36c4bd0203b27dbff F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024 -F ext/rtree/visual01.txt 17c3afefc208c375607aa82242e97fa79c316e539bcd0b7b3e59344c69445d05 +F ext/rtree/visual01.txt e9c2564083bcd30ec51b07f881bffbf0e12b50a3f6fced0c222c5c1d2f94ac66 F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a -F ext/session/session1.test 4532116484f525110eb4cfff7030c59354c0cde9def4d109466b0df2b35ad5cc +F ext/session/changesetfuzz.c 255826ee367781ec4c29a36c7c63e9ee6387dc03a8346cf240feb8d597958b0e +F ext/session/changesetfuzz1.test 2e1b90d888fbf0eea5e1bd2f1e527a48cc85f8e0ff75df1ec4e320b21f580b3a +F ext/session/session1.test 0b2f88995832ea040ae8e83a1ad4afa99c00b85c779d213da73a95ea4113233e F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0 F ext/session/session3.test ce9ce3dfa489473987f899e9f6a0f2db9bde3479 F ext/session/session4.test 6778997065b44d99c51ff9cece047ff9244a32856b328735ae27ddef68979c40 @@ -399,31 +403,32 @@ F ext/session/session9.test 5409d90d8141881d08285ed1c2c0d8d10fb92069 F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f F ext/session/sessionB.test 886252dcb7e692e62ef7e357456200912e367823 -F ext/session/sessionC.test 97556f5164ac29f2344b24bd7de6a3a35a95c390 -F ext/session/sessionD.test d3617e29aa15c9413aee5286d99587633245d58d2ad28f3f331c822735418a22 -F ext/session/sessionE.test 0a616c4ad8fd2c05f23217ebb6212ef80b7fef30f5f086a6633a081f93e84637 -F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce -F ext/session/sessionG.test 3edde849c4071078d92bd682c836186f6e4e5a3fb6bcf3fc1de1a7caa5e4427d -F ext/session/sessionH.test 332b60e4c2e0a680105e11936201cabe378216f307e2747803cea56fa7d9ebae -F ext/session/session_common.tcl ee925e0d233677e45e395fb1f559b84068ce7baa8aa1034441739d3e87ee249c +F ext/session/sessionC.test f8a5508bc059ae646e5ec9bdbca66ad24bc92fe99fda5790ac57e1f59fce2fdf +F ext/session/sessionD.test 4f91d0ca8afc4c3969c72c9f0b5ea9527e21de29039937d0d973f821e8470724 +F ext/session/sessionE.test b2010949c9d7415306f64e3c2072ddabc4b8250c98478d3c0c4d064bce83111d +F ext/session/sessionF.test d37ed800881e742c208df443537bf29aa49fd56eac520d0f0c6df3e6320f3401 +F ext/session/sessionG.test 3828b944cd1285f4379340fd36f8b64c464fc84df6ff3ccbc95578fd87140b9c +F ext/session/sessionH.test a417559f29a7e775950fc5fc82b3d01256a7cbe793ddf1180df234df823d56e2 +F ext/session/session_common.tcl 29ec9910aca1e996ca1c8531b8cecabf96eb576aa53de65a8ff03d848b9a2a8b F ext/session/session_speed_test.c edc1f96fd5e0e4b16eb03e2a73041013d59e8723 F ext/session/sessionat.test efe88965e74ff1bc2af9c310b28358c02d420c1fb2705cc7a28f0c1cc142c3ec F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7 -F ext/session/sessionfault2.test 555a8504de03d59b369ef20209585da5aeb2671dedabc4584e9ffe6269689185 -F ext/session/sessionrebase.test 4e1bcfd26fd8ed8ac571746f56cceeb45184f4d65490ea0d405227cfc8a9cba8 -F ext/session/sessionstat1.test 41cd97c2e48619a41cdf8ae749e1b25f34719de638689221aa43971be693bf4e -F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc -F ext/session/sqlite3session.c 2d29bbd888599b94b2c8b31ff433675e008273a4d225b336508b18e6187fec1d -F ext/session/sqlite3session.h c01820d5b6e73e86d88008f4d1c1c7dfb83422963018292b864028a0400ceccf -F ext/session/test_session.c dba36c6c0153b22501112d3e8882b5c946cf617c955153b6712bd2f8ba1428c0 +F ext/session/sessionfault2.test dd593f80b6b4786f7adfe83c5939620bc505559770cc181332da26f29cddd7bb +F ext/session/sessioninvert.test ae1a003a9ab1f8d64227dbb5c3a4c97e65b561b01e7b2953cf48683fb2724169 +F ext/session/sessionrebase.test ccfa716b23bd1d3b03217ee58cfd90c78d4b99f53e6a9a2f05e82363b9142810 +F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c2666091b54450a68fb5 +F ext/session/sessionwor.test 07f0b304dc4df5454906069140bf6ec67edcaa3c548f3683354003cf2c22b64a +F ext/session/sqlite3session.c dbd6f7a89c1236d8e7b58f4e217391670ce91b9e6f85c16ba02832674ef0cf3c +F ext/session/sqlite3session.h 05351d2f50a1203fdffbeb590fdbbc796c9a6bfcd0c9b26cf6db3854e3eb4294 +F ext/session/test_session.c 98797aba475a799376c9a42214f2d1debf2d0c3cb657d9c8bbf4f70bf3fb4aec F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e629edbe2648 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 1db6df4bff24ed6684917e3fe311ce28f5924d6417c698fe4326f7cadf02df31 +F main.mk eeaa279fa6acdcfa6555058548075569a06f891fd67f5901b1e7700d18052fda F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -435,37 +440,37 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c 70dd115eb1f949f69f61773733dc89d6494915ec6a736f259c7a7de4aeb51726 +F src/alter.c f886160da189e4e99093cd5a2aca625652cc9b027d5100b87f81c175d1056387 F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9 -F src/attach.c 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a -F src/auth.c 32a5bbe3b755169ab6c66311c5225a3cd4f75a46c041f7fb117e0cbb68055114 +F src/attach.c 92b51739a885da8bd84bc9a05485f1e48148bce5c15432f059b45af98fff75cd +F src/auth.c 0fac71038875693a937e506bceb492c5f136dd7b1249fbd4ae70b4e8da14f9df F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 3f5e1a03db871e627bf5da21092bf7434ecfc5c5980bbd7d45eba13341340173 +F src/btree.c ba7c7eef4461790f37c309936bfc5d0d6ba9b194b02d3c8ff1fd53b420ea6d3b F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 -F src/build.c 0b3d422770877d74ee6d54f4c122d82c48f7d04ee3bfb91702e402de7f5c45ac -F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288 +F src/build.c 127d33ad57b455a9339e9fabff41284c8b030cc6247ca7a2a6c0ad7abfc1ce85 +F src/callback.c 789bd33d188146f66c0dd8306472a72d1c05f71924b24a91caf6bd45cf9aba73 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e -F src/ctime.c b157b01081f92442f8b0218ddb93ddce8ebddad36dbddeecfdd771561dd4f387 +F src/ctime.c 109e58d00f62e8e71ee1eb5944ac18b90171c928ab2e082e058056e1137cc20b F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 -F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3 -F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 -F src/delete.c 107e28d3ef8bd72fd11953374ca9107cd74e8b09c3ded076a6048742d26ce7d2 -F src/expr.c d8da79a5cb19bbded56181337a221ead5f4ad3cbf0fbcb5da2156abefab566cd +F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7 +F src/dbstat.c 3c8bd4e77f0244fd2bd7cc90acf116ad2f8e82d70e536637f35ac2bc99b726f9 +F src/delete.c f7938125847e8ef485448db5fbad29acb2991381a02887dd854c1617315ab9fb +F src/expr.c 9aacc0b72348ba90010b672dcbbbe2fa56e1182043bc917a3a147b2bc57a5497 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 -F src/fkey.c f59253c0be4b1e9dfcb073b6d6d6ab83090ae50c08b5c113b76013c4b157cd6a +F src/fkey.c 972a4ba14296bef2303a0abbad1e3d82bc3c61f9e6ce4e8e9528bdee68748812 F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f -F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128 -F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a +F src/global.c 8291eee0782b83124de14ec0389ec9fd6ae1873358a6b0d9469fe17a46ad803b +F src/hash.c 931ec82d7e070654a8facb42549bbb3a25720171d73ba94c3d3160580d01ef1f F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4 F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c c723716f0de7aa0a679300f7d3541c89645f4a9882161cecdb3093fc07f8cc4b +F src/insert.c 6b81aae27b196925d8ff78824f4bbd435d6a40cd38dc324685e21735bb402109 F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e -F src/loadext.c 30b140d0e5031924c56f802760506c0a235ced0dff9f3d95119aa86df12856e2 -F src/main.c 6275ece0699a957c4709a7ebe29476f132adbe459d18a6b497e234e4669abf91 +F src/loadext.c 9050dd153b5583804184be9c9dee9ebb554178d6db1f8ac280899e8aad9060e6 +F src/main.c 4cfb3913cc9e65d3ac649b1785ac753fc225d29425d5437e012f7eac0cefe0eb F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -485,33 +490,33 @@ F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 -F src/os_unix.c 7cfd67db0e2f926243f646db7ec1caa33ca9bee45799b0160ddfcd6ccfc175d2 -F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971 +F src/os_unix.c f6e91b8fd82af7afbfd073c4974ad6cdb8e62d9f65ceddb45167835a0567fdc0 +F src/os_win.c 85d9e532d0444ab6c16d7431490c2e279e282aa0917b0e988996b1ae0de5c5a0 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c a0d8f686ef64549ad5b356fd30429bd9ee7a06dd42b4d6faa096352ff26b1c5b -F src/pager.h ecc554a55bc55d1c4ba5e17137b72e238e00bd81e72ff2662d8b9c8c10ae3963 -F src/parse.y 4118dbf9c37c410e5c4775c033b1aaf67ac8ff7965df7a4bb429dd5db2dbe374 -F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd -F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170 -F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 -F src/pragma.c 79abc65c08d2754048efee3ba99fe91863dfeab0ba699a4439fa5053ec87cf36 -F src/pragma.h fb46b1e663128f6827979ad8ebddb55be2a0276ea923c47adeac02144207a682 -F src/prepare.c f8e260d940a0e08494c0f30744521b2f832d7263eca9d02b050cea0ba144b097 +F src/pager.c 75e0f3cfa3962c714f519f8a3d1e67ecca1c91de0e010a036b988e40ce9e4c73 +F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3 +F src/parse.y 6840fe7c0b5eb4dd25ee5d075213bc8255ed4c0678d71bfb6744d0520d91c179 +F src/pcache.c 696a01f1a6370c1b50a09c15972bc3bee3333f8fcd1f2da8e9a76b1b062c59ee +F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 +F src/pcache1.c bf9fcea656dce1cd2cca6b77a1d1d3552050d55a31c98bf0d9f405930a83bc95 +F src/pragma.c 4e056f042683b99c4ea0db395f68d051b1a95833ab40951c40d3ef7e1fee1354 +F src/pragma.h fdd03d78a7497f74a3f652909f945328480089189526841ae829ce7313d98d13 +F src/prepare.c f81f8d707e583192c28fea0b2e19385415b7d188123b23f49b038076408d7a69 F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 -F src/resolve.c 352c6af1a99441206ff62a6f7429dbf537827f42c428639695220b9c8639e33b +F src/resolve.c 4cfc44def0f0690ceaab8f6481f5d76284d7f9509aab6e218a679b4836a54614 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 -F src/select.c 0671309c245ecb2b75d8b33948cbcf039325468aaedc13f37c8c4f3f62f48d5f -F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1f -F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec +F src/select.c 61e867a906f140b73baf4ce7a201ad6dcba30820969f5618ee40e9a0d32c6f5f +F src/shell.c.in 482e23a370cbe5b0d4c73a0f0f5fce34f7caa08a14a8d75e12f0225c4e14915c +F src/sqlite.h.in cce9feede1c1c03923c091b4bbbd081dd77aaf92024cc2cdbf65f712c2f668c3 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 -F src/sqlite3ext.h 305adca1b5da4a33ce2db5bd236935768e951d5651bfe5560ed55cfcdbce6a63 -F src/sqliteInt.h 489bda7e69087742c4724bc85c21778703e0ee5cc463b4d89c0092ae8034896a +F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683 +F src/sqliteInt.h 1161f7579cdd6217737a66517ef27f4016426603eff492e9b31f45a7d7d4c61f F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/tclsqlite.c e72862a271348d779672b45a730c33fd0c535e630ff927e8ce4a0c908d1d28c6 -F src/test1.c 31c491ccb536bd9916a084e732ffe783b3c8973f2586d5a56aed0e3a9701dfff +F src/test1.c 5390e5afb31fed61f72d0be0cb1b322d198a6e03fc13ff245ae76d17b4dcf2e9 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6 @@ -526,7 +531,7 @@ F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857 F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274 -F src/test_config.c 6c3f341ece48020c4ddbce055643a91c653283b3a6853c46ea18d22e5c72847d +F src/test_config.c 5ebafbcd5c75ac1c16bb0c8fe926dc325cc03e780943a88ca50e0d9a4fc4d2f5 F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2 @@ -534,8 +539,8 @@ F src/test_func.c d12d805953bcb3bb19f71d29cdc93383b7b7a3369504d2b7e398a1bd77376294 F src/test_hexio.c 1d4469ca61ab202a1fcec6543f584d2407205e8d F src/test_init.c 4413c211a94b62157ca4c145b3f27c497f03c664 -F src/test_intarray.c 988fc61cb0ff539f4172c0d95f15287c92516f64 -F src/test_intarray.h f3b7672f5d1056eac563c0d6ea8480a660b1475c +F src/test_intarray.c 39b4181662a0f33a427748d87218e7578d913e683dc27eab7098bb41617cac71 +F src/test_intarray.h d57ae92f420cda25e22790dac474d60961bd0c500cbaa3338a05152d4a669ef7 F src/test_journal.c 619f2aa10e0d7a5f87c0f06825bc61dfce1c6b9c7f3ad990fb13de6c3b8874a3 F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd F src/test_malloc.c dec0aa821b230773aeb3dd11d652c1193f7cedb18a20b25659bc672288115242 @@ -543,7 +548,7 @@ F src/test_multiplex.c e054459f7633f3ff8ce1245da724f9a8be189e4e F src/test_multiplex.h 5436d03f2d0501d04f3ed50a75819e190495b635 F src/test_mutex.c 7f4337ba23ee6b1d2ec81c189653608cb069926a -F src/test_onefile.c 416f87a28d6d673352d33fc4b1c7d39db878e50f +F src/test_onefile.c f31e52e891c5fef6709b9fcef54ce660648a34172423a9cbdf4cbce3ba0049f4 F src/test_osinst.c 98ef31ff03d55497829ca0f6c74a9f4e1aa48690 F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00 F src/test_quota.c 6cb9297115b551f433a9ad1741817a9831abed99 @@ -564,33 +569,33 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c -F src/tokenize.c 9f55961518f77793edd56eee860ecf035d4370ebbb0726ad2f6cada6637fd16b -F src/treeview.c e7a7f90552bb418533cdd0309b5eb71d4effa50165b880fc8c2001e613577e5f +F src/tokenize.c 9e781e1ca80eefe7b5d6a9e2cd5c678c847da55fd6f093781fad7950934d4c83 +F src/treeview.c 7b12ac059de54c939b6eb0dbffc9410c29c80d2470cee5cbe07d5ff9ea2d9253 F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd -F src/update.c 0c9714a1dc954c261d7251dbf51067bf041f0a9a6003ba34999705e9e4ef03a3 +F src/update.c 1816d56c1bca1ba4e0ef98cac2f49be62858e9df1dc08844c7067eb41cc44274 F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 -F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855 -F src/vdbe.c b1b2142469a4eb177e712827f7c1ee376e41381eed870938d1494c13f55bf2e7 +F src/vacuum.c 836cadc922de866c849e23a75f93d344cdc143d388339305d09a3fed27e8798d +F src/vdbe.c 005e691ea4c7d51e6c1a69d9389aeb34700884c85f51681817ddea3fdc2fc39b F src/vdbe.h 5081dcc497777efe5e9ebe7330d283a044a005e4bdda2e2e984f03bf89a0d907 -F src/vdbeInt.h f1f35f70460698d8f5a2bdef1001114babf318e2983a067804e2ae077d8e9827 -F src/vdbeapi.c 2ba821c5929a2769e4b217dd85843479c718b8989d414723ec8af0616a83d611 -F src/vdbeaux.c 9fe7760a6b9739f21f3e19ad5364330b0f681998fc52c32358243b0060423474 +F src/vdbeInt.h 437e6c6af679fdf157867eb83a8adc6cf5145d6774453c2214cfd0bd01d92980 +F src/vdbeapi.c ecccfce6f614c33a95952efeec969d163e8349eac314ee2b7b163eda921b5eb0 +F src/vdbeaux.c f547901b1aa9e2d81c63f06893f633648e434180666a827aacb547d7d6c8a601 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191 -F src/vdbemem.c 81329ab760e4ec0162119d9cd10193e0303c45c5935bb20c7ae9139d44dd6641 +F src/vdbemem.c 7b3305bc4a5139f4536ac9b5f61da0f915e49d2e3fdfa87dfdfa9d7aba8bc1e9 F src/vdbesort.c 90aad5a92608f2dd771c96749beabdb562c9d881131a860a7a5bccf66dc3be7f F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392 -F src/vtab.c 8665561f244c137a2d17b5c3e5910d7303054fe841c5d510e53f23beb0089594 +F src/vtab.c 70188a745dc4e57d26e942681ff4b2912b7c8249ad5de3f60f0677b4337bcfaa F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a -F src/walker.c ba7225773931760cf60bf22f34d0cce2588df7ce5ce0f215a52eb88234b55ac4 -F src/where.c 2019126801437944c38cc62a99491e98591460b7cc07ab57eb66165f710a289b -F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4 -F src/wherecode.c cf6d3ac7b428102c1ebbff8758cf932ce38a31ed7704960010b6a90a9849b1f5 -F src/whereexpr.c 0f496c579f3c95aebb3d3e223ec6571d97dfd598140656c90ca93046bdfeaf69 -F src/window.c 4b503da928dace3e845b891381a4d98eeb8c5744313ae3643df8d8d21fdcca65 +F src/walker.c fb94aadc9099ff9c6506d0a8b88d51266005bcaa265403f3d7caf732a562eb66 +F src/where.c 3818e8a736a05d2cb194e64399af707e367fbcc5c251d785804d02eaf121288e +F src/whereInt.h f125f29fca80890768e0b2caa14f95db74b2dacd3a122a168f97aa7b64d6968f +F src/wherecode.c c45f03aefc2266b990df0fc4d7acc4e27f56f881f4fc0fc355b7cbc4d7189da5 +F src/whereexpr.c 491f0894ad9903750cdecb7894437a0cabdffdd88f574d2b1c9ac85d14fe4b9c +F src/window.c 6550e2850ebced51100ef83d49b00a1cf03f81a482dafedafb0320df647ed8fc F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d @@ -598,19 +603,20 @@ F test/aggnested.test 18b00de006597e960a6b27ccec51474ac66cf1070a87c1933e5694dc02190ef1 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13 -F test/alter.test 99e72759d48d6531ac2a9f346b4a9b5fe8f89c67a0fa5e916a3990d3b1fe9d09 -F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060 +F test/alter.test 93dee7c0ff9106fbd53a8bbf519107904b884050a99c4565412c58c37d68c802 +F test/alter2.test a966ccfcddf9ce0a4e0e6ff1aca9e6e7948e0e242cd7e43fc091948521807687 F test/alter3.test 4d79934d812eaeacc6f22781a080f8cfe012fdc3 F test/alter4.test 7e93a21fe131e1dfeb317e90056856f96b10381fc7fe3a05e765569a23400433 F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959 -F test/altercol.test 53fb5e218c9296afc160f2c4fcbeaf42bd0604815d9b3896a7d2eec583ad8704 -F test/alterlegacy.test e7c07d605c2a85e7d1696c89e6bf64dfc932fc6d9320fe8708c8f5fc0b524d41 -F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc +F test/alterauth2.test c0a1ddf5b93d93cb0d15ba7acaf0c5c6fb515bbe861ede75b2d3fabad33b6499 +F test/altercol.test 313ed080ed61691c52cd87053129889f71582d6d0efebdd5f3edad2a98c66874 +F test/alterlegacy.test 82022721ce0de29cedc9a7af63bc9fcc078b0ee000f8283b4b6ea9c3eab2f44b +F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9 F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b -F test/altertab.test 3b830144c18ae00abd2a27e3d2851c8bb1ee8fe655fa16d8a5971066dc71b58a -F test/altertab2.test 159fd5f7b23ddc841fe678f579f9b1b8e69f44296f3ff75d1b4c155d37a59832 +F test/altertab.test 17e46baa6b2234048c91891a303141afceca4da95a36ee1a0a9fec6ccef1f4da +F test/altertab2.test 0d64de5632ca5de13b023839cfe5b8952d029e4622befcea1433adaa93883220 F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f -F test/analyze.test b3a9c67d00e1df7588a5b7be9a0292899f94fe8cac1f94a017277474ca2e59df +F test/analyze.test 7168c8bffa5d5cbc53c05b7e9c7fcdd24b365a1bc5046ce80c45efa3c02e6b7c F test/analyze3.test ff62d9029e6deb2c914490c6b00caf7fae47cc85cdc046e4a0d0a4d4b87c71d8 F test/analyze4.test cdf88f3f72b0f0643a1ff6c730fc5af1e42464d47478d9fbac84c333f72c014e F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4 @@ -634,21 +640,21 @@ F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061 F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da F test/atrc.c ec92d56d8fbed9eb3e11aaf1ab98cf7dd59e69dae31f128013f1d97e54e7dfed -F test/attach.test f4b8918ba2f3e88e6883b8452340545f10a1388af808343c37fc5c577be8281c +F test/attach.test 21bce8681f780a8d631a5ec7ecd0d849bfe84611257b038ae4ffeccc609d8a4e F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3a0ce F test/attach3.test c59d92791070c59272e00183b7353eeb94915976 F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c -F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0 +F test/attachmalloc.test 12c4f028e570acf9e0a4b0b7fe6f536e21f3d5ebddcece423603d0569beaf438 F test/auth.test 3310d9c08e928beca42d3eadaaf53cef619d9d275f598565a3758a21ce63138e F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1 F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49 F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec -F test/autoinc.test 9d202b7dce6571e52b744138eff12610214501acd635abdd72d18736cd06fd22 +F test/autoinc.test 381f494fefa90acd999933829e2934efb6b40906db9d6a39e822e3f7b4c8bf61 F test/autoindex1.test a09958fa756129af10b6582bcbf3cbdf11e305e027b393f393caef801159dee0 F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df F test/autoindex3.test 2dd997d6590438b53e4f715f9278aa91c9299cf3f81246a0915269c35beb790e F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf -F test/autoindex5.test 5f0135dc3b266277b8c1904624439097d8e8020dd7197eda13fda23c35c21a05 +F test/autoindex5.test 4a0eb6c7c7ae456d97a2061d4c8d6380946272c5c91d91507c1feb1af3dc7cce F test/autovacuum.test 0831cd34e14695d297187f7f6519265e3121c5b0a1720e548e86829e796129e9 F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4 F test/avtrans.test b7dc25459ecbd86c6fa9c606ee3068f59d81e225118617dcf2bbb6ded2ade89e @@ -665,8 +671,8 @@ F test/bestindex1.test 852170bddbb21daa121fabcc274640ff83d7d8705912e8b5fe7ed2c5a9a9224a F test/bestindex2.test 9a0ccd320b6525eec3a706aae6cdab7e1b7b5abca75027e39f39f755e76e5928 F test/bestindex3.test 001788a114ad96d81d5154fe77c7f1e26e84b3a2b5635ca29e4f96f6decc534e -F test/bestindex4.test 4cb5ff7dbaebadb87d366f51969271778423b455 -F test/bestindex5.test 412b42f8036b28d8b2f3534d89389ad946a4b1a65a12263f51936f7424296f1b +F test/bestindex4.test 038e3d0789332f3f1d61474f9bbc9c6d08c6bd1783a978f31f38ad82688de601 +F test/bestindex5.test 67c1166131bb59f9e47c00118f7d432ca5491e6cae6ca3f87ca9db20103a78f9 F test/bestindex6.test d856a9bb63d927493575823eed44053bc36251e241aa364e54d0f2a2d302e1d4 F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59 @@ -694,9 +700,9 @@ F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61 F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9 F test/capi2.test 34a1a9a96d543a2ec2c209696b11b164444f57253b1f2cba1c2e53fadede6c7b -F test/capi3.test 36f5c859c91a9bb0075d6ddcfcf2476cad629b09f7bfd135776fb94b06c04706 +F test/capi3.test 3910a73c38ac76d69778dd9eb481ab7cd6ed59117fc047b4f6056a5c72529de1 F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4 -F test/capi3c.test 7ebed1d8fa2f3190149d556fe8cff5a006be62af437c5c4640db614470126098 +F test/capi3c.test 54e2dc0c8fd7c34ad1590d1be6864397da2438c95a9f5aee2f8fbc60c112e44b F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82 F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe F test/cast.test 5ceb920718d280b61163500a7d29e0e0a86458b1cbd92d96f962c9d970aa3857 @@ -722,11 +728,11 @@ F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c F test/conflict3.test a83db76a6c3503b2fa057c7bfb08c318d8a422202d8bc5b86226e078e5b49ff9 F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4 -F test/corrupt.test 141c39ea650c1365e85a49e402fa05cb9617fb97 -F test/corrupt2.test fdfdffab9bc37d6d173f56ffb82472206f11dd4a68caad9360ac4db2eddb34c8 +F test/corrupt.test d7cb0300e4a297147b6a05e92a1684bc8973635c3bcaa3d66e983c9cbdbf47a3 +F test/corrupt2.test a7f95356d19a4e8bf9423622ad865cabf48ae49dad40eb7a17a0b39f1cdd6948 F test/corrupt3.test f95d7bf78109e0b84eb285a787ce91a3fd6a2dd7d0cb55882abff3bdc081a57e F test/corrupt4.test 8d1d86b850fcc43e417450454f2044e52d55778a -F test/corrupt5.test 8ead52af76006f3286e9396cb41898018ccea107 +F test/corrupt5.test 387be3250795e2a86e6234745558b80efb248a357d0cd8e53bce75c7463f545d F test/corrupt6.test fc6a891716139665dae0073b6945e3670bf92568 F test/corrupt7.test b036f94bda4b0b23a2919bf717046ce9ecca4543 F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516 @@ -739,18 +745,18 @@ F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4 F test/corruptG.test adf79b669cbfd19e28c8191a610d083ae53a6d51 F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454 -F test/corruptI.test 075fe1d75aa1d84e2949be56b6264376c41502e4 +F test/corruptI.test a17bbf54fdde78d43cf3cc34b0057719fd4a173a3d824285b67dc5257c064c7b F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4 -F test/corruptK.test 91550557849244a9904f4e090052e3f2c1c3f1106840d58b00ffaa3a8c2d3fc0 +F test/corruptK.test 5ef338c560ca4dfb7360828da16f1829be4deba3b378cafdc7a1cdaf027eb5c4 F test/cost.test b37db8a10d467a69e71a9f3d40bbb266c2f587742b37c6912f6e3f7185a0e216 F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c -F test/countofview.test 2d0ce23daca1bada0522c3d62e0e0c0d69ec4e0fc41df2bcd662a5e11169b9c9 +F test/countofview.test e3d4cd6900e4e4f074968ab24b8b87d3671cd624961bef40fd3a6b8f574343cf F test/coveridxscan.test 5ec98719a2e2914e8908dc75f7247d9b54a26df04625f846ac7900d5483f7296 F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651 F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418 F test/crash4.test fe2821baf37168dc59dd733dcf7dba2a401487bc -F test/crash5.test 05dd3aa9dbb751a22d5cdaf22a9c49b6667aa219 +F test/crash5.test f14ff37eddc41991be4eb63568f86caa306fd9962a0ae3750db8836777bb7aae F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df F test/crash8.test 64366e459c28dd62edfb7ad87253a409c7533b92d16fcc479a6a8131bdcc3100 @@ -758,7 +764,7 @@ F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2 F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8 F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c -F test/csv01.test 6e1445b3207d574cff22fc41a8e549dfcf2466ee90546ada97d22a90fa89eb58 +F test/csv01.test 4a92840619ef435b905e6d3f35cd0644df23225d7b7967d7940b40f06d6a90a6 F test/ctime.test 78749e6c9a5f0010d67985be80788f841e3cd2da18114e2ed6010399a7d807f3 F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856 F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee9ae9c42f @@ -766,10 +772,12 @@ F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373 F test/date2.test 74c234bece1b016e94dd4ef9c8cc7a199a8806c0e2291cab7ba64bace6350b10 F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e -F test/dbpage.test dbf50a4d361f9e45a979432c727506065113124478a7d2db12074fa655e65d6c -F test/dbstatus.test c15fa97f743dac7ce996814c84b56317e138895ee15ce27f15b608aa6924c90a +F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee +F test/dbfuzz2.c 652f85bac1770e927da139db513234a3eba308f72ac2f8b32f0093d7d19def70 +F test/dbpage.test 650234ba683b9d82b899c6c51439819787e7609f17a0cc40e0080a7b6443bc38 +F test/dbstatus.test cd83aa623b8aab477269bc94cf8aa90c1e195a144561dd04a1620770aaa8524e F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef -F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d +F test/default.test 3e46c421eebefd2787c2f96673efabf792d360f3a1d5073918cbe450ce672a62 F test/delete.test 31832b0c45ecb51a54348c68db173be462985901e6ed7f403d6d7a8f70ab4ef0 F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab @@ -792,10 +800,10 @@ F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412 F test/e_dropview.test 21ce09c361227ddbc9819a5608ee2700c276bdd5 F test/e_expr.test ca8896601ade1e27c6559614c7f32c63d44636fdfa720436a160f09b8bf66c89 -F test/e_fkey.test 9778696ef9fceacebed8d482d02b47287981faaedf6f73db563ea8a7afb546da -F test/e_fts3.test 8cf40550bb088a6aa187c818c00fabe26ef82900a4cd5c66b427ccafe28bedaa +F test/e_fkey.test 2febb2084aef9b0186782421c07bc9d377abf067c9cb4efd49d9647ae31f5afe +F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07 F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e -F test/e_reindex.test 2bebf7b393e519198b7c654407221cf171a439b8 +F test/e_reindex.test 2b0e29344497d9a8a999453a003cb476b6b1d2eef2d6c120f83c2d3a429f3164 F test/e_resolve.test a61751c368b109db73df0f20fc75fb47e166b1d8 F test/e_select.test c5a669b4d63217aa10094ba737ba3ddd07bd439d4bc7a5b798f6ea32511cbe7c F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f @@ -826,7 +834,7 @@ F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3 F test/filefmt.test f393e80c4b8d493b7a7f8f3809a8425bbf4292af1f5140f01cb1427798a2bbd4 F test/fkey1.test d11dbb8a93ead9b5c46ae5d02da016d61245d47662fb2d844c99214f6163f768 -F test/fkey2.test 6206484a0eba570902a1a4d86489df24d0265f6994daebf851861d8f0cf4a27b +F test/fkey2.test d35d1c81e7569bdd2b872e91750f7098117d2e8291369f70b7e3d50a0e523dc2 F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49 F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d F test/fkey5.test 24dd28eb3d9f1b5a174f47e9899ace5facb08373a4223593c8c631e6cf9f7d5a @@ -889,21 +897,21 @@ F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18 F test/fts3ao.test 266989148fec6d9f1bb6c5382f7aa3dcea0e9cd444576e28dd2b9287ac7dd220 F test/fts3atoken.test 4b4c16fdcfc972f2cdbba212375a060a86ccf5f1 -F test/fts3auto.test b981fea19b132b4e6878f50d7c1f369b28f68eb9 +F test/fts3auto.test 19097050a3ca7ab7a43b2be967cb3dfd8ddf841dfdc4eac88deb172ad2f209f2 F test/fts3aux1.test 7a170e172afdbceb67f5baa05941fd4fbf56af42f61daa3d140f4b4bf4cb68f6 F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba F test/fts3b.test c15c4a9d04e210d0be67e54ce6a87b927168fbf9c1e3faec8c1a732c366fd491 F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958 F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f5a76b -F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb -F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba -F test/fts3corrupt3.test 56e0ee83e90b57f5f3644cb7d1b36a067b7b8b19cdf0dedce45e5e13cf752f65 -F test/fts3corrupt4.test 98022cbacbd6ddc4708f210768f5684f041f50ce330c461f2631752492611d96 -F test/fts3cov.test 9c3681325b9a850bca8dd75cc29dde73e9a87972bb75204e97d826f13c7181f9 -F test/fts3d.test d3e9c8fb75135ada06bf3bab4f9666224965d708 -F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963 -F test/fts3defer2.test c540f5f5c2840f70c68fd9b597df817ec7170468 +F test/fts3corrupt.test 46b9ddda7f6588fd5a5b1f4bb4fc0618dc45010e7dddb8a3a188baf3197177ae +F test/fts3corrupt2.test bf55c3fa0b0dc8ea1c0fe5543623bd27714585da6a129038fd6999fe3b0d25f3 +F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f +F test/fts3corrupt4.test a27259f4f25d60b4eca481d050b3cfee97eddb0d937d38f231408c5239066e11 +F test/fts3cov.test cb932743da52a1c79a1ab8983e26c8121cf02263d6ff16e1f642e6f9b8348338 +F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f +F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4d9f1de +F test/fts3defer2.test 3da52ca2114e300e9971eee2f0cc1a2e5f27e6a9ee67957d49e63e41fdfcc0e7 F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297 F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851 @@ -917,37 +925,37 @@ F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641 F test/fts3join.test 949b4f5ae3ae9cc2423cb865d711e32476bdb205ab2be923fdf48246e4a44166 F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6 -F test/fts3matchinfo.test ce864e0bd92429df8008f31cf557269ba172482a -F test/fts3misc.test ba03a83b831555cfd18c6c862b24b70a53ce7497fe55077f7c4b7c9ce83c2eed +F test/fts3matchinfo.test aa66cc50615578b30f6df9984819ae5b702511cf8a94251ec7c594096a703a4a +F test/fts3misc.test 0b20083efab36a42804bf8017a003f72f963c46163403dae7256493367d2f9d3 F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905 F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2 F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce -F test/fts3query.test ca5dffabdfe9aef2ebcc89e02ce515898f86f8c30a365283831c53e0e08e5821 +F test/fts3query.test ca033ff2ebcc22c69d89032fb0bc1850997d31e7e60ecd26440796ba1654e78f F test/fts3rank.test cd99bc83a3c923c8d52afd90d86979cf05fc41849f892faeac3988055ef37b99 F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0 F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e -F test/fts3snippet.test 01a4231816e03a0660ae53ba2404fe69012fe0db +F test/fts3snippet.test 8cf586fe4b6878192602a81a665448aacbbad80ade0867bb5299d40e73584311 F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca F test/fts3tok1.test a663f4cac22a9505400bc22aacb818d7055240409c28729669ea7d4cc2120d15 F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb -F test/fts4check.test c3056eab9524232e4c9bdcd119912947e07bcc1c +F test/fts4check.test 6259f856604445d7b684c9b306b2efb6346834c3f50e8fc4a59a2ca6d5319ad0 F test/fts4content.test 1518195a9f92b711d94419f76409a31cc78755854fb0abb1da2b74b9e0cf843e F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01 -F test/fts4growth.test e5390da74619cacc389711bac9349640b32c4f9a +F test/fts4growth.test 289833c34ad45a5e6e6133b53b6a71647231fb89d36ddcb8d9c87211b6721d7f F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269 F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d F test/fts4langid.test 2168ba330af34f8a1c8832de0aab4c4b6fa195a16419c9c0c8aad59ceb6ff714 F test/fts4lastrowid.test 185835895948d5325c7710649824042373b2203149abe8024a9319d25234dfd7 -F test/fts4merge.test 10b55f410fade8691a455210b0b9302ef178a4f06fba0ad1941801caab82f5a9 +F test/fts4merge.test 1096e30b58ad616bd502141bfe5bfe4c3a518df89e958d41a5ed1ce322369b9c F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891 F test/fts4merge3.test 8d9ccb4a3d41c4c617a149d6c4b13ad02de797d0 F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309 F test/fts4onepass.test d69ddc4ee3415e40b0c5d1d0408488a87614d4f63ba9c44f3e52db541d6b7cc7 -F test/fts4opt.test fd6a11684b965e1999564ae763797b7fb9e34c96 +F test/fts4opt.test 0fd0cc84000743ff2a883b9b84b4a5be07249f0ba790c8848a757164cdd46b2a F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95 F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d F test/func.test 09dda479bcfc568f99f3070413e9672a8eeedc1be9c5d819bf55d4788c2583b7 @@ -961,14 +969,15 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b -F test/fuzz_malloc.test 5b257a7652d8ee90b22e9cf80d9dbea31a4f3e6fed1d33de57b24b1bdb211d79 -F test/fuzzcheck.c 8074a35ed4ec3735a5e144b7e0e9123d9821a92281756c1a40d43e302dd79243 +F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2 +F test/fuzzcheck.c fda41c0e4e667fae96b002410bb19cece7a33314264ed6bbc6d012909ee9fd58 F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e42ed2 F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5 F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7 +F test/fuzzdata7.db a1bf54eb455e9772942abae1b2d1cf1e3d3659f0e5dd14f00792fd01411ae8ef F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8 F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14 F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536 @@ -992,16 +1001,16 @@ F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4 F test/incrblob4.test 21a52a6843a56cdcce968c6a86b72a7066d0e6ba -F test/incrblob_err.test 69f9247fed50278d48ea710d1a8f9cdb09e4c0b8 +F test/incrblob_err.test 89372a28f1d98254f03fed705f9efcd34ef61a674df16d2dbb4726944a2de5e9 F test/incrblobfault.test 74dd8ac108304cea0b4a0df6df63a1567e558758 F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a -F test/incrvacuum.test b729aab1d4983037da57e66c20dfd7458561a85626dcf824f60175e35f4ce152 +F test/incrvacuum.test 2aaee202b1f230e55779f70d155f6ba67bbdff8481d650214d256ab0f97d4a2b F test/incrvacuum2.test 7d26cfda66c7e55898d196de54ac4ec7d86a4e3d F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635 -F test/index.test fe3c7a1aad82af92623747e9c3f3aa94ccd51238 +F test/index.test df4cddf4435314a948237fdfa9acee67de21f7bebc789beab4b89b575b4f6a70 F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407 -F test/index3.test 81bc47890b8abfb181bc35f8d10b56c069803386 +F test/index3.test 51685f39345462b84fcf77eb8537af847fdf438cc96b05c45d6aaca4e473ade0 F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6 F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7 F test/index6.test d07ea75b8c21f125c6f325522e8df8c05c91e9251ec923a31d0582b2ba4a617d @@ -1010,7 +1019,7 @@ F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721 F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e F test/indexexpr1.test 635261197bcdc19b9b2c59bbfa7227d525c00e9587faddb2d293c44d287ce60e -F test/indexexpr2.test 08551aa8956a91582979e17b6d369f321a5cb6ed6d3e952925a3e54e9e7de216 +F test/indexexpr2.test fc994dcd4b3da932d4add8e65ed7ca08166d541e00a46874cfacd98dfb93a31b F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 F test/insert.test 5604b1ff5675cc84c34a5b315792b958f48c32edccc0dafcc81d3b776270b70a @@ -1020,7 +1029,7 @@ F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6 F test/instr.test 9a8802f28437d8ade53fedfc47b2ca599b4e48ba F test/instrfault.test 0f870b218ea17cd477bb19ed330eecdb460dd53a -F test/intarray.test 46d95b457916638c5d8b1af21fb174804b3acf8b +F test/intarray.test 8319986182af37c8eb4879c6bfe9cf0074e9d43b193a4c728a0efa3417c53fb7 F test/interrupt.test 16ea879ec728cb76414c148c5f24afd5d1f91054 F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d F test/intpkey.test ac71107a49a06492b69b82aafaf225400598d3c8 @@ -1052,12 +1061,13 @@ F test/kvtest.c 94da54bb66aae7a54e47cf7e4ea4acecc0f217560f79ad3abfcc0361d6d557ba F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63 F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200 +F test/lemon-test01.y 58b764610fd934e189ffbb0bbfa33d171b9cb06019b55bdc04d090d6767e11d7 F test/like.test 11cfd7d4ef8625389df9efc46735ff0b0b41d5e62047ef0f3bc24c380d28a7a6 F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da -F test/like3.test cf0ff2d06c9d8456283aeff405b911642298441206306aeaeaa93973233b1195 +F test/like3.test 430691e6057e11a59e934be74c06b85605b80061d45af5714d52886a811efeb7 F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e F test/limit2.test 9409b033284642a859fafc95f29a5a6a557bd57c1f0d7c3f554bd64ed69df77e -F test/loadext.test d077450695ddb5c1ea3ad7d48e5f5850fe732ad9 +F test/loadext.test faa4f6eed07a5aac35d57fdd7bc07f8fc82464cfd327567c10cf0ba3c86cde04 F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7 F test/lock.test be4fe08118fb988fed741f429b7dd5d65e1c90db F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff @@ -1093,6 +1103,7 @@ F test/mallocL.test fb311ff80afddf3b1a75e52289081f4754d901dc F test/mallocM.test 78bbe9d3da84a5c679123cdb40d7b2010b18fc46e13897e4f253c6ba6fbff134 F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f +F test/malloctraceviewer.tcl b7a54595270c1d201abf1c3f3d461f27eaf24cdef623ad08a0fe5e411264c8a9 F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7 @@ -1104,16 +1115,16 @@ F test/minmax2.test dae92964ac87c1d2ef978c582e81a95e11c00f1cbef68980bfb2abaf10315063 F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354 F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f -F test/misc1.test 704ea2cc7e7b9deb622b37953f0e77d0879826e8c3bfc1d7a691528035405061 +F test/misc1.test c8cfd1c3f842b3341fda9d81a96236d5c76ca89973aeff3fe50bac6fefcfc421 F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d -F test/misc4.test 0d8be3466adf123a7791a66ba2bc8e8d229e87f3 -F test/misc5.test 60e1fc758a93cacd19eb2fafcd1d40d150a05047546c7a92389c98047d621901 +F test/misc4.test 10cd6addb2fa9093df4751a1b92b50440175dd5468a6ec84d0386e78f087db0e +F test/misc5.test c4aeaa0fa28faa08f2485309c38db4719e6cd1364215d5687a5b96d340a3fa58 F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91 -F test/misc7.test 349855706310f0de6b91645d199f6874f518627fd057743fa4e3689b60d06efc +F test/misc7.test 10d639a5e0fdf1bd51ad42be705393a38780ad71b6957110035a4e6c1e5e7f40 F test/misc8.test 8fb0f31d7a8aed484d759773ab8ad12ec746a477f4a67394a4af0e677494c3ca F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7 -F test/mjournal.test 9d86e697dcbc5da2c4e8caba9b176b5765fe65e80c88c278b8c09a917e436795 +F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152 F test/mmap1.test fb04e0c10492455007624ade884ca0c8852ff3e4e11d95408f9709ca2ef7f626 F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022 F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e @@ -1129,11 +1140,11 @@ F test/nan.test 437d40e6d0778b050d7750726c0cbd2c9936b81962926e8f8c48ca698f00f4d1 F test/nockpt.test 8c43b25af63b0bd620cf1b003529e37b6f1dc53bd22690e96a1bd73f78dde53a F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e -F test/normalize.test 1dedf653ca33b0b55fd0c7967d2861a51f1801a7aa899a02d4c0d7adfcd5acdc +F test/normalize.test 6a80564d2000702b5919ed2c1069fef0f95762142bc96a71b4c124a845165713 F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161 F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934 -F test/notnull.test b6999231221df3534827e45e2005dd7a815fdd5f2c2e1afb9be21ead410816f8 +F test/notnull.test a37b663d5bb728d66fc182016613fb8e4a0a4bbf3d75b8876a7527f7d4ed3f18 F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3 F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1 F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823 @@ -1152,10 +1163,10 @@ F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3 F test/oserror.test e7b3416be4b9d5dd2fe0b42dd394daaddbb6c83eeec1f0e47b120b53e0ad3ace -F test/ossfuzz.c c4c4547e2c92ac52f10038b073a03248251a23c1c559728f63a18aeca0e79f03 +F test/ossfuzz.c 273eaea2d65b70d77ea4f01404114b9e0244488943f768dc39458c72bd722e0e F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17 F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f -F test/pager1.test a32ce299ed01ffb06e84a3af467ae1f3389786b316f40c4359f442c79144736b +F test/pager1.test 1e9ee778bdeaf4f7f09997d029cdaca6a42dfc2092edafe4f5e590acbf1eab13 F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71 F test/pager3.test 4e9a83d6ca0838d7c602c9eb93d1357562d9059c1e02ffb138a8271020838370 F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e @@ -1164,19 +1175,19 @@ F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8 F test/pageropt.test 84e4cc5cbca285357f7906e99b21be4f2bf5abc0 F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305 -F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854 +F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035ce4b3 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff -F test/permutations.test f6d25d2f978e6bb4d6aa08db82ec10d635c47e88b79f96d79d16860425dc6a8b +F test/permutations.test cf0b4e498db1d0143c19641d4420df7cc27fab2c95ed0abd2c7c5753beab25b8 F test/pg_common.tcl 301ac19c1a52fd55166d26db929b3b89165c634d52b5f8ad76ea8cb06960db30 -F test/pragma.test 7c8cfc328a1717a95663cf8edb06c52ddfeaf97bb0aee69ae7457132e8d39e7d +F test/pragma.test c267bf02742c823a191960895b3d52933cebd7beee26757d1ed694f213fcd867 F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f -F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed -F test/pragma4.test 3046501bee2f652dc2a4f9c87781e2741361d6864439c8381aba6c3b774b335c +F test/pragma3.test 8300aa9c63cff1027006ca34bf413a148abbd6dcd471fa9a1ded322fe18c0df9 +F test/pragma4.test 52d8186f9e8d09b87189432cdd401dfa66d0b32445e837fa19046c8ae7621b0e F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983 F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8 -F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc +F test/printf.test a3e559bc9d922e7fe44e9d05c6965fee34fe3bc28300a4248c6a063425246ffd F test/printf2.test 30b5dd0b4b992dc5626496846ecce17ff592cacbcb11c3e589f3ac4d7e129dae F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc @@ -1194,8 +1205,8 @@ F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 -F test/releasetest.tcl c5b474f9880073fc3b69729ee05d5284653a9ee101af572204917d9dcb1d9015 x -F test/resetdb.test 684a6ffde5a5141bba79f3101981cc38dcfc3403f61e643b7b3aa68bef0b8408 +F test/releasetest.tcl b290d538ffcb2ff711f09eadc7396c1a42580f3fb078605471dc8875ca0b4d1e x +F test/resetdb.test 373a9eb8fcbd58bf87affec6a88c6353038f98a5d25be5ab75a0b9636c462a36 F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6 @@ -1252,19 +1263,19 @@ F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb F test/sessionfuzz.c b0fcdcf757451957e17396a3af5171f1fdf9b2babc81da9fa35675df46c4729a -F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746 +F test/shared.test 1826673eb5eb745fb91a3bdac99a7737057742ae38dcb0fe076a384d6727578b F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879 F test/shared3.test ab693f9b6e156b8bfb2a0ad94f29fe69602a5d38 F test/shared4.test c75f476804e76e26bf6fa0e7b421fb0ca7d07558 F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9 F test/shared7.test a81e99f83e6c51b02ac99c96fb3a2a7b5978c956 -F test/shared8.test 00a07bf5e1337ecf72e94542bdefdc330d7a2538 +F test/shared8.test 933ed7d71f598bb6c7a8c192a3cd30f2562fdccf514df383798599c34ffa672f F test/shared9.test 5f2a8f79b4d6c7d107a01ffa1ed05ae7e6333e21 F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69e281 F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939 F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304 -F test/shell1.test 707c03fbd07ac506cfb6fa09da4ee22e2b50453c3db2f404694116eb990168f3 +F test/shell1.test d2bf5daeb6f449f0169c9ef3094db17a16a02199c5dcf1a635a3e79b07eb0edd F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494 F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d @@ -1282,11 +1293,11 @@ F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2 F test/skipscan6.test 0b4cd1b4ac9f84d91454df513c99a4932fa07e8f27b8049bea605068b3e34ac7 F test/snapshot.test a504f2e7009f512ef66c719f0ea1c55a556bdaf1e1312c80a04d46fc1a3e9632 -F test/snapshot2.test 4fc84a0121e882d6980333bf14dfc1143dfb94f5afbb909c084977a945b45beb -F test/snapshot3.test d6ec952e437e5c06a293d0f5ec1be1b45771d46d93bccfb3818ca2617dcb11e7 -F test/snapshot4.test 0f7e6bd6f1370d112ee820c541d0dd0e7b8ab4ea77429e65106d81c9ad2185a6 +F test/snapshot2.test 8d6ff5dd9cc503f6e12d408a30409c3f9c653507b24408d9cd7195931c89bc54 +F test/snapshot3.test 8744313270c55f6e18574283553d3c5c5fe4c5970585663613a0e75c151e599b +F test/snapshot4.test d4e9347ef2fcabc491fc893506c7bbaf334da3be111d6eb4f3a97cc623b78322 F test/snapshot_fault.test 508ae6f211d4991e9ff3b5080aeb0a179bf6755138aabeac4bca8083044d895a -F test/snapshot_up.test 93fec2d847ec12e3bae0f6486da2abc965a606e099e4e870454045f5f56f71ba +F test/snapshot_up.test a0a29c4cf33475fcef07c3f8e64af795e24ab91b4cc68295863402a393cdd41c F test/soak.test 18944cf21b94a7fe0df02016a6ee1e9632bc4e8d095a0cb49d95e15d5cca2d5c F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087 F test/sort.test c2adc635c2564241fefec0b3a68391ef6868fd3b @@ -1325,26 +1336,26 @@ F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12 F test/swarmvtab.test 9a3fd5ab3e9b3c976ad1b3d7646aab725114f2ac26b59395d0778b33bab6cdaf F test/swarmvtab2.test c948cb2fdfc5b01d85e8f6d6504854202dc1a0782ab2a0ed61538f27cbd0aa5c -F test/swarmvtab3.test 6cb664669630fcec4102a09333e52068734858fd2761eee3b0465c14cdbcee29 -F test/swarmvtabfault.test 00aec54665909490f5c383f3cae3b5d18bd97c12490b429ff8752a3027acfa42 +F test/swarmvtab3.test 247aa38b6ebd2b99db2075847ae47e789ac34f1c2ab5c720dfcffd990004c544 +F test/swarmvtabfault.test 8a67a9f27c61073a47990829e92bc0c64420a807cb642b15a25f6c788210ed95 F test/symlink.test 0d816670325536b8973ec08d32b45136baddb80bd45fd178e0ce7a9e8153f3e7 F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d4333092 F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039 F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04 -F test/tabfunc01.test c47171c36b3d411df2bd49719dcaa5d034f8d277477fd41d253940723b969a51 -F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f -F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126 +F test/tabfunc01.test 54300134f76db817685194d2f0e63e3fbf7380b45e0d426e00a9aee752497cfb +F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132 +F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 F test/tclsqlite.test dca8aa30d84175e7d8c8fc43d3ffa11fa56e23fbdac2679d03833a0f326edf34 F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08 -F test/tempdb2.test 4749545409c6d7438b435c3f05cdd139cf4145a954a6908d19e3443ffd8724b3 +F test/tempdb2.test 2479226e4cb96f4c663eccd2d12c077cf6bda29ca5cc69a8a58a06127105dd62 F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900 F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30 F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637 F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc -F test/tester.tcl d5138d226cc2aaacb6934cdd79acaa5edd17cad862482895b833bbf62c49aca0 +F test/tester.tcl fa5656391e3b477508abe12b3b81f019b2e71397399ab38a2f32d8d7f3bf8e56 F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58 F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7 @@ -1514,14 +1525,14 @@ F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359 F test/trigger5.test 619391a3e9fc194081d22cefd830d811e7badf83 F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9 -F test/trigger7.test 93cfa9b48ab9104b2b3d87bc544ac8021405643e36f23ee84635fbfaf9b8fef5 +F test/trigger7.test e7ce54bfda67a88d778aea42544e151c465547a7e617127b6914c2221a6d53c1 F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4 F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41 -F test/triggerA.test fe5597f47ee21bacb4936dc827994ed94161e332 +F test/triggerA.test 837be862d8721f903dba3f3ceff05b32e0bee5214cf6ea3da5fadf12d3650e9d F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe F test/triggerC.test 302d8995f5ffe63bbc15053abb3ef7a39cf5a092 F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650 -F test/triggerE.test d9e9b364dfd527c84ac0de53045406325487feecb32888d482eca64421a50d99 +F test/triggerE.test ede2e4bce4ba802337bd69d39447fa04a938e06d84a8bfc53c76850fc36ed86d F test/triggerF.test 6a8c22bd058cf467f0c7d112afe87f7a8c579c0c4681b914b8f19020f48528a4 F test/triggerG.test d5caeef6144ede2426dd13211fd72248241ff2ebc68e12a4c0bf30f5faa21499 F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1 @@ -1532,8 +1543,8 @@ F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff F test/types2.test 1aeb81976841a91eef292723649b5c4fe3bc3cac F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a -F test/unionvtab.test 595fb601de00188ca5e7c6dbe266c17a0faf234cf434ce85eccec1a929ef9baf -F test/unionvtabfault.test 26b6854d5aef9005cd630513025690bff1b7378ae9c97b81e2a3cbe84eee0f58 +F test/unionvtab.test 5ae0f0b4f302a4c6bb310b64386f9ac6a4c1c271c08f31cc7c5d92722e2b2729 +F test/unionvtabfault.test e8759f3d14fb938ce9657e2342db34aeac0fb9bc1692b0d1ebb0069630151d06 F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264 F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2 F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97 @@ -1558,7 +1569,7 @@ F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 F test/view.test 71e1bf4c0e2e0d37c84d7db5b33cd47eb4a7662c19d93ede4112b350b186f61f -F test/vtab1.test 8f91b9538d1404c3932293a588c4344218a0c94792d4289bb55e41020e7b3fff +F test/vtab1.test 60b4f70aafa6078d6fdfc11417af3bd216d7ef5eafce16707a6ca3dae5166d20 F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082 F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3 @@ -1577,7 +1588,7 @@ F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f F test/vtabJ.test d7b73675708cf63cfcb9d443bb451fc01a028347275b7311e51f9fdf3ca6757f F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783 -F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8 +F test/vtab_err.test dcc8b7b9cb67522b3fe7a272c73856829dae4ab7fdb30399aea1b6981bda2b65 F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad F test/wal.test 613efec03e517e1775d86b993a54877d2e29a477 F test/wal2.test 155b9efa999bdb38ce1cd729b9a4fcdbffd6b88be27f039bad1d2929d287d918 @@ -1585,7 +1596,7 @@ F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c F test/wal5.test 9c11da7aeccd83a46d79a556ad11a18d3cb15aa9 F test/wal6.test b602704e4b066199bc89d91ca9000f335dcf4572 -F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8 +F test/wal64k.test 2a525c0f45d709bae3765c71045ccec5df7d100ccbd3a7860fdba46c9addb965 F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd F test/wal8.test d9df3fba4caad5854ed69ed673c68482514203c8 F test/wal9.test 378e76a9ad09cd9bee06c172ad3547b0129a6750 @@ -1636,22 +1647,22 @@ F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864 F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3 F test/wherelimit.test 592081800806d297dd7449b1030c863d2883d6d42901837ccd2e5a9bd962edb0 -F test/wherelimit2.test be78ba3aa1831c6358fd7d5b9809bfd520f0c2a7d63a295e8f182e140ff137c3 +F test/wherelimit2.test 9bf0aa56cca40ea0e4c5e2915341355a2bbc0859ec4ce1589197fe2a9d94635f F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2aeee74 F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc -F test/window1.test 474bef1a6ac291755e51d1f9458dc11117c1870ac5e08b4d3938649b215f8334 +F test/window1.test 02e481ac48c445b43bab7b3cf1e4115165b5127a1aa29e14f5372922c836f1a4 F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143 F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e F test/window3.tcl 577a3b1ff913208e5248c04dab9df17fd760ce159a752789e26d0cb4a5f91823 F test/window3.test e274b7f8952ca4ed25996e0e45c047192b066e0aaff2a822d4293c8c4f1d8d98 F test/window4.tcl 511425f6b0abf9b953df54cc9c7295cc7c25d78f4ed6f7a74b094eec0120eccb F test/window4.test c5d6bf3403e4ade2f19df2afe4c16f29fb817c392c6c1c8017edb7165c191a62 -F test/window5.test 8187f46597c90b73e8f96659e893353cbda337479cc582f7a488eab351ba08d3 -F test/window6.test 7574778c79cae89f1781df237bf9ff5063886deca91a36efc53934315f0e7612 -F test/windowfault.test 23abad97b72c6f609002255ddd41ef5c8922408f918f9b98ad6005ab316e482f +F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652821e +F test/window6.test 5eae4ae7a590ccf1e605880969ca0bad3955616ac91cad3031baea38748badb3 +F test/windowfault.test 12ceb6bbb355d13e8fcd88c5731a57256dfdf77b9a7ae20842a76fcd4623df5b F test/with1.test 2465d98ffce80d00553ac7135697c18b0369275b6ecc750daa2af320b8c812ca F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d @@ -1659,7 +1670,7 @@ F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64 F test/without_rowid1.test 533add9100255e4cc430d371b3ecfb79f11f956b86c3a1b9d34413bf8e482d8f F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 -F test/without_rowid3.test e1bb85362d9b7b63ea2b93c433bb2923fff8badb98e463474365531c1cd5f880 +F test/without_rowid3.test ea4b59dd1b0d7f5f5e4b7cca978cdb905752a9d7c57dc4344a591dba765a3691 F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e @@ -1667,8 +1678,8 @@ F test/writecrash.test f1da7f7adfe8d7f09ea79b42e5ca6dcc41102f27f8e334ad71539501ddd910cc F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa F test/zerodamage.test 9c41628db7e8d9e8a0181e59ea5f189df311a9f6ce99cc376dc461f66db6f8dc -F test/zipfile.test a61f6ba6dbaaf4983849df84a31df140c7ddd1362e2fa9ecd3cdf5cd123b7f18 -F test/zipfile2.test 8a18965530258140ce301b2c2f4245bc505ffead2e17a97fa34c7ace379ea5e0 +F test/zipfile.test b3b558639f7a103e095713ad0f57fec1fce1b7d60c8054df5789b98f7547a395 +F test/zipfile2.test 9903388a602a3834189857a985106ff95c3bba6a3969e0134127df991889db5d F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a168827edbbc2c F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetTclKit.bat 8995df40c4209808b31f24de0b58f90930239a234f7591e3675d45bfbb990c5d @@ -1684,11 +1695,11 @@ F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439 F tool/fuzzershell.c e1d90a03ca790d7c331c2aae08ca46ff435f1ae1faa6cb9cc48f4687c18fdc6e F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4 -F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5 +F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a5a4f F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f F tool/lemon.c 60d1e1eb0f7ebae709f68f1472d77fbf291c5345cd98ff417219da7e74fd09e9 -F tool/lempar.c 6020ce61dd7a536a3866952eb1e616c7e8b14b8f623368ed5a98f0639cedf048 +F tool/lempar.c 452f12d40229847634a160e5666b6c4ec4392fd81941c3443861b48d497054cc F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca @@ -1701,7 +1712,7 @@ F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21 F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa -F tool/mkpragmatab.tcl 8b9b448b5eb7222d4e3f7afb3c678596784180d319eb4e01c842887ed8213b85 +F tool/mkpragmatab.tcl a1334e70a08fdf5de32cd0093613212bb11ac8f880487540987175c536ac335f F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5 F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 @@ -1733,7 +1744,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd F tool/split-sqlite3c.tcl 3efcd4240b738f6bb2b5af0aea7e1e0ef9bc1c61654f645076cec883030b710c -F tool/sqldiff.c 579d7e4e42c30a963781654c87d2868823120b55d59e16ca77b0edbab0218713 +F tool/sqldiff.c 7b9b7238284f02131dbb8f21a4e862409bff728045c5473139d28c67ac87580e F tool/sqlite3_analyzer.c.in 7eeaae8b0d7577662acaabbb11107af0659d1b41bc1dfdd4d91422de27127968 F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898 F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848 @@ -1745,7 +1756,7 @@ F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 -F tool/warnings.sh 8a4acea31e0f9c562949a2d767329533c0930d699ea19c6704c0ca0aa9154068 +F tool/warnings.sh 09311479bdc290e20ec8e35a3d1b14b096bbd96222277cfd6274c3a99b3d012f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F vsixtest/App.xaml b76d3b48860e7454775c47ea38ffea9c4abe3e85 F vsixtest/App.xaml.cpp c465147f50871165c60ca16955219f6c5812d6d8 @@ -1768,11 +1779,11 @@ F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8d09ce5d738bb00c4524c663ec69555fe917ac733d58b06a302675ce7fe33fca -R 00cfcd9deda5635c7483df5f9218a978 +P 23684cb841ac2cb0d69e5470253bd96feb733762a7553b952a08470834fe85fa +R dcc394af10af6094607f56a6086fb748 T +bgcolor * #d0c0ff T +sym-release * -T +sym-version-3.25.3 * +T +sym-version-3.26.0 * U drh -Z d2b8ccce3c6c80bcf2a7dfd041b6e7a9 +Z 560a5decbb241d53eb97e72267b6e6e8 # Remove this line to create a well-formed manifest.
diff --git a/third_party/sqlite/src/manifest.uuid b/third_party/sqlite/src/manifest.uuid index 8b7d03c..166b1b3d 100644 --- a/third_party/sqlite/src/manifest.uuid +++ b/third_party/sqlite/src/manifest.uuid
@@ -1 +1 @@ -89e099fbe5e13c33e683bef07361231ca525b88f7907be7092058007b75036f2 +bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238b4f9
diff --git a/third_party/sqlite/src/src/alter.c b/third_party/sqlite/src/src/alter.c index b505b73..fcddc40 100644 --- a/third_party/sqlite/src/src/alter.c +++ b/third_party/sqlite/src/src/alter.c
@@ -667,10 +667,16 @@ #endif /* -** Add a new RenameToken object mapping parse tree element pPtr into -** token *pToken to the Parse object currently under construction. +** Remember that the parser tree element pPtr was created using +** the token pToken. ** -** Return a copy of pPtr. +** In other words, construct a new RenameToken object and add it +** to the list of RenameToken objects currently being built up +** in pParse->pRename. +** +** The pPtr argument is returned so that this routine can be used +** with tail recursion in tokenExpr() routine, for a small performance +** improvement. */ void *sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pToken){ RenameToken *pNew; @@ -803,7 +809,7 @@ renameTokenFind(pWalker->pParse, p, (void*)pExpr); }else if( pExpr->op==TK_COLUMN && pExpr->iColumn==p->iCol - && p->pTab==pExpr->pTab + && p->pTab==pExpr->y.pTab ){ renameTokenFind(pWalker->pParse, p, (void*)pExpr); } @@ -1061,9 +1067,14 @@ db->aDb[sqlite3SchemaToIndex(db, pNew->pTabSchema)].zDbSName ); pParse->eTriggerOp = pNew->op; + /* ALWAYS() because if the table of the trigger does not exist, the + ** error would have been hit before this point */ + if( ALWAYS(pParse->pTriggerTab) ){ + rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab); + } /* Resolve symbols in WHEN clause */ - if( pNew->pWhen ){ + if( rc==SQLITE_OK && pNew->pWhen ){ rc = sqlite3ResolveExprNames(&sNC, pNew->pWhen); } @@ -1177,15 +1188,8 @@ ** into zNew. The name should be quoted if bQuote is true. ** ** This function is used internally by the ALTER TABLE RENAME COLUMN command. -** Though accessible to application code, it is not intended for use by -** applications. The existance of this function, and the way it works, -** is subject to change without notice. -** -** If any of the parameters are out-of-bounds, then simply return NULL. -** An out-of-bounds parameter can only occur when the application calls -** this function directly. The parameters will always be well-formed when -** this routine is invoked by the bytecode for a legitimate ALTER TABLE -** statement. +** It is only accessible to SQL created using sqlite3NestedParse(). It is +** not reachable from ordinary SQL passed into sqlite3_prepare(). */ static void renameColumnFunc( sqlite3_context *context, @@ -1341,8 +1345,8 @@ */ static int renameTableExprCb(Walker *pWalker, Expr *pExpr){ RenameCtx *p = pWalker->u.pRename; - if( pExpr->op==TK_COLUMN && p->pTab==pExpr->pTab ){ - renameTokenFind(pWalker->pParse, p, (void*)&pExpr->pTab); + if( pExpr->op==TK_COLUMN && p->pTab==pExpr->y.pTab ){ + renameTokenFind(pWalker->pParse, p, (void*)&pExpr->y.pTab); } return WRC_Continue; } @@ -1439,7 +1443,7 @@ }else{ /* Modify any FK definitions to point to the new table. */ #ifndef SQLITE_OMIT_FOREIGN_KEY - if( db->flags & SQLITE_ForeignKeys ){ + if( isLegacy==0 || (db->flags & SQLITE_ForeignKeys) ){ FKey *pFKey; for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){ @@ -1593,9 +1597,9 @@ */ void sqlite3AlterFunctions(void){ static FuncDef aAlterTableFuncs[] = { - FUNCTION(sqlite_rename_column, 9, 0, 0, renameColumnFunc), - FUNCTION(sqlite_rename_table, 7, 0, 0, renameTableFunc), - FUNCTION(sqlite_rename_test, 5, 0, 0, renameTableTest), + INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc), + INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc), + INTERNAL_FUNCTION(sqlite_rename_test, 5, renameTableTest), }; sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); }
diff --git a/third_party/sqlite/src/src/attach.c b/third_party/sqlite/src/src/attach.c index 19c75833..fcb0504 100644 --- a/third_party/sqlite/src/src/attach.c +++ b/third_party/sqlite/src/src/attach.c
@@ -100,7 +100,7 @@ if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt); pNew->pBt = 0; pNew->pSchema = 0; - rc = sqlite3BtreeOpen(pVfs, "x", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB); + rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB); }else{ /* This is a real ATTACH **
diff --git a/third_party/sqlite/src/src/auth.c b/third_party/sqlite/src/src/auth.c index 5d4ad89..ccf4981 100644 --- a/third_party/sqlite/src/src/auth.c +++ b/third_party/sqlite/src/src/auth.c
@@ -151,6 +151,7 @@ int iCol; /* Index of column in table */ assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ); + assert( !IN_RENAME_OBJECT || db->xAuth==0 ); if( db->xAuth==0 ) return; iDb = sqlite3SchemaToIndex(pParse->db, pSchema); if( iDb<0 ){ @@ -207,6 +208,7 @@ /* Don't do any authorization checks if the database is initialising ** or if the parser is being invoked from within sqlite3_declare_vtab. */ + assert( !IN_RENAME_OBJECT || db->xAuth==0 ); if( db->init.busy || IN_SPECIAL_PARSE ){ return SQLITE_OK; }
diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c index b125859b..7a8de2d 100644 --- a/third_party/sqlite/src/src/btree.c +++ b/third_party/sqlite/src/src/btree.c
@@ -3112,7 +3112,7 @@ pageSize-usableSize); return rc; } - if( (pBt->db->flags & SQLITE_WriteSchema)==0 && nPage>nPageFile ){ + if( sqlite3WritableSchema(pBt->db)==0 && nPage>nPageFile ){ rc = SQLITE_CORRUPT_BKPT; goto page1_init_failed; } @@ -3586,6 +3586,7 @@ eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); assert( sqlite3_mutex_held(pBt->mutex) ); assert( pDbPage->pBt==pBt ); + if( iDbPage<3 ) return SQLITE_CORRUPT_BKPT; /* Move page iDbPage from its current location to page number iFreePage */ TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", @@ -4757,9 +4758,6 @@ /* Need to read this page properly. It contains some of the ** range of data that is being read (eOp==0) or written (eOp!=0). */ -#ifdef SQLITE_DIRECT_OVERFLOW_READ - sqlite3_file *fd; /* File from which to do direct overflow read */ -#endif int a = amt; if( a + offset > ovflSize ){ a = ovflSize - offset; @@ -4770,7 +4768,7 @@ ** ** 1) this is a read operation, and ** 2) data is required from the start of this overflow page, and - ** 3) there is no open write-transaction, and + ** 3) there are no dirty pages in the page-cache ** 4) the database is file-backed, and ** 5) the page is not in the WAL file ** 6) at least 4 bytes have already been read into the output buffer @@ -4781,11 +4779,10 @@ */ if( eOp==0 /* (1) */ && offset==0 /* (2) */ - && pBt->inTransaction==TRANS_READ /* (3) */ - && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (4) */ - && 0==sqlite3PagerUseWal(pBt->pPager, nextPage) /* (5) */ + && sqlite3PagerDirectReadOk(pBt->pPager, nextPage) /* (3,4,5) */ && &pBuf[-4]>=pBufStart /* (6) */ ){ + sqlite3_file *fd = sqlite3PagerFile(pBt->pPager); u8 aSave[4]; u8 *aWrite = &pBuf[-4]; assert( aWrite>=pBufStart ); /* due to (6) */
diff --git a/third_party/sqlite/src/src/build.c b/third_party/sqlite/src/src/build.c index b1206e11..806c89f 100644 --- a/third_party/sqlite/src/src/build.c +++ b/third_party/sqlite/src/src/build.c
@@ -356,17 +356,15 @@ if( p==0 ){ const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table"; #ifndef SQLITE_OMIT_VIRTUALTABLE - if( sqlite3FindDbName(db, zDbase)<1 ){ - /* If zName is the not the name of a table in the schema created using - ** CREATE, then check to see if it is the name of an virtual table that - ** can be an eponymous virtual table. */ - Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName); - if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ - pMod = sqlite3PragmaVtabRegister(db, zName); - } - if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ - return pMod->pEpoTab; - } + /* If zName is the not the name of a table in the schema created using + ** CREATE, then check to see if it is the name of an virtual table that + ** can be an eponymous virtual table. */ + Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName); + if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ + pMod = sqlite3PragmaVtabRegister(db, zName); + } + if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ + return pMod->pEpoTab; } #endif if( (flags & LOCATE_NOERR)==0 ){ @@ -546,17 +544,22 @@ void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){ int i; sqlite3BtreeEnterAll(db); - assert( db->nSchemaLock==0 ); for(i=0; i<db->nDb; i++){ Db *pDb = &db->aDb[i]; if( pDb->pSchema ){ - sqlite3SchemaClear(pDb->pSchema); + if( db->nSchemaLock==0 ){ + sqlite3SchemaClear(pDb->pSchema); + }else{ + DbSetProperty(db, i, DB_ResetWanted); + } } } db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk); sqlite3VtabUnlockList(db); sqlite3BtreeLeaveAll(db); - sqlite3CollapseDatabaseArray(db); + if( db->nSchemaLock==0 ){ + sqlite3CollapseDatabaseArray(db); + } } /* @@ -633,6 +636,12 @@ /* Delete the Table structure itself. */ +#ifdef SQLITE_ENABLE_NORMALIZE + if( pTable->pColHash ){ + sqlite3HashClear(pTable->pColHash); + sqlite3_free(pTable->pColHash); + } +#endif sqlite3DeleteColumnNames(db, pTable); sqlite3DbFree(db, pTable->zName); sqlite3DbFree(db, pTable->zColAff); @@ -792,6 +801,20 @@ } /* +** True if PRAGMA writable_schema is ON +*/ +int sqlite3WritableSchema(sqlite3 *db){ + testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==0 ); + testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== + SQLITE_WriteSchema ); + testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== + SQLITE_Defensive ); + testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))== + (SQLITE_WriteSchema|SQLITE_Defensive) ); + return (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==SQLITE_WriteSchema; +} + +/* ** This routine is used to check if the UTF-8 string zName is a legal ** unqualified name for a new schema object (table, index, view or ** trigger). All names are legal except those that begin with the string @@ -800,7 +823,7 @@ */ int sqlite3CheckObjectName(Parse *pParse, const char *zName){ if( !pParse->db->init.busy && pParse->nested==0 - && (pParse->db->flags & SQLITE_WriteSchema)==0 + && sqlite3WritableSchema(pParse->db)==0 && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName); return SQLITE_ERROR; @@ -1876,6 +1899,36 @@ recomputeColumnsNotIndexed(pPk); } +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* +** Return true if zName is a shadow table name in the current database +** connection. +** +** zName is temporarily modified while this routine is running, but is +** restored to its original value prior to this routine returning. +*/ +static int isShadowTableName(sqlite3 *db, char *zName){ + char *zTail; /* Pointer to the last "_" in zName */ + Table *pTab; /* Table that zName is a shadow of */ + Module *pMod; /* Module for the virtual table */ + + zTail = strrchr(zName, '_'); + if( zTail==0 ) return 0; + *zTail = 0; + pTab = sqlite3FindTable(db, zName, 0); + *zTail = '_'; + if( pTab==0 ) return 0; + if( !IsVirtual(pTab) ) return 0; + pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]); + if( pMod==0 ) return 0; + if( pMod->pModule->iVersion<3 ) return 0; + if( pMod->pModule->xShadowName==0 ) return 0; + return pMod->pModule->xShadowName(zTail+1); +} +#else +# define isShadowTableName(x,y) 0 +#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ + /* ** This routine is called to report the final ")" that terminates ** a CREATE TABLE statement. @@ -1915,6 +1968,10 @@ p = pParse->pNewTable; if( p==0 ) return; + if( pSelect==0 && isShadowTableName(db, p->zName) ){ + p->tabFlags |= TF_Shadow; + } + /* If the db->init.busy is 1 it means we are reading the SQL off the ** "sqlite_master" or "sqlite_temp_master" table on the disk. ** So do not write to the disk again. Extract the root page number @@ -2422,7 +2479,7 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){ Vdbe *v = sqlite3GetVdbe(pParse); int r1 = sqlite3GetTempReg(pParse); - assert( iTable>1 ); + if( iTable<2 ) sqlite3ErrorMsg(pParse, "corrupt schema"); sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb); sqlite3MayAbort(pParse); #ifndef SQLITE_OMIT_AUTOVACUUM
diff --git a/third_party/sqlite/src/src/callback.c b/third_party/sqlite/src/src/callback.c index 7c42d93..3d55b286 100644 --- a/third_party/sqlite/src/src/callback.c +++ b/third_party/sqlite/src/src/callback.c
@@ -295,6 +295,21 @@ } return 0; } +#ifdef SQLITE_ENABLE_NORMALIZE +FuncDef *sqlite3FunctionSearchN( + int h, /* Hash of the name */ + const char *zFunc, /* Name of function */ + int nFunc /* Length of the name */ +){ + FuncDef *p; + for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){ + if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 ){ + return p; + } + } + return 0; +} +#endif /* SQLITE_ENABLE_NORMALIZE */ /* ** Insert a new FuncDef into a FuncDefHash hash table. @@ -308,7 +323,7 @@ FuncDef *pOther; const char *zName = aDef[i].zName; int nName = sqlite3Strlen30(zName); - int h = (zName[0] + nName) % SQLITE_FUNC_HASH_SZ; + int h = SQLITE_FUNC_HASH(zName[0], nName); assert( zName[0]>='a' && zName[0]<='z' ); pOther = functionSearch(h, zName); if( pOther ){ @@ -387,7 +402,7 @@ */ if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){ bestScore = 0; - h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ; + h = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zName[0]], nName); p = functionSearch(h, zName); while( p ){ int score = matchQuality(p, nArg, enc);
diff --git a/third_party/sqlite/src/src/ctime.c b/third_party/sqlite/src/src/ctime.c index aae082c..d783de6d 100644 --- a/third_party/sqlite/src/src/ctime.c +++ b/third_party/sqlite/src/src/ctime.c
@@ -235,6 +235,9 @@ #if SQLITE_ENABLE_FTS5 "ENABLE_FTS5", #endif +#if SQLITE_ENABLE_GEOPOLY + "ENABLE_GEOPOLY", +#endif #if SQLITE_ENABLE_HIDDEN_COLUMNS "ENABLE_HIDDEN_COLUMNS", #endif @@ -265,6 +268,9 @@ #if SQLITE_ENABLE_MULTIPLEX "ENABLE_MULTIPLEX", #endif +#if SQLITE_ENABLE_NORMALIZE + "ENABLE_NORMALIZE", +#endif #if SQLITE_ENABLE_NULL_TRIM "ENABLE_NULL_TRIM", #endif
diff --git a/third_party/sqlite/src/src/dbpage.c b/third_party/sqlite/src/src/dbpage.c index 66d0b97c..6c86b2b 100644 --- a/third_party/sqlite/src/src/dbpage.c +++ b/third_party/sqlite/src/src/dbpage.c
@@ -119,9 +119,8 @@ if( p->iColumn!=DBPAGE_COLUMN_SCHEMA ) continue; if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; if( !p->usable ){ - /* No solution. Use the default SQLITE_BIG_DBL cost */ - pIdxInfo->estimatedRows = 0x7fffffff; - return SQLITE_OK; + /* No solution. */ + return SQLITE_CONSTRAINT; } iPlan = 2; pIdxInfo->aConstraintUsage[i].argvIndex = 1; @@ -313,6 +312,10 @@ Pager *pPager; int szPage; + if( pTab->db->flags & SQLITE_Defensive ){ + zErr = "read-only"; + goto update_fail; + } if( argc==1 ){ zErr = "cannot delete"; goto update_fail; @@ -403,6 +406,7 @@ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ + 0 /* xShadowName */ }; return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0); }
diff --git a/third_party/sqlite/src/src/dbstat.c b/third_party/sqlite/src/src/dbstat.c index 7e7450e..73ab7d92 100644 --- a/third_party/sqlite/src/src/dbstat.c +++ b/third_party/sqlite/src/src/dbstat.c
@@ -194,17 +194,15 @@ static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ int i; - pIdxInfo->estimatedCost = 1.0e6; /* Initial cost estimate */ - /* Look for a valid schema=? constraint. If found, change the idxNum to ** 1 and request the value of that constraint be sent to xFilter. And ** lower the cost estimate to encourage the constrained version to be ** used. */ for(i=0; i<pIdxInfo->nConstraint; i++){ - if( pIdxInfo->aConstraint[i].usable==0 ) continue; - if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; if( pIdxInfo->aConstraint[i].iColumn!=10 ) continue; + if( pIdxInfo->aConstraint[i].usable==0 ) return SQLITE_CONSTRAINT; + if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; pIdxInfo->idxNum = 1; pIdxInfo->estimatedCost = 1.0; pIdxInfo->aConstraintUsage[i].argvIndex = 1; @@ -254,7 +252,7 @@ return SQLITE_OK; } -static void statClearPage(StatPage *p){ +static void statClearCells(StatPage *p){ int i; if( p->aCell ){ for(i=0; i<p->nCell; i++){ @@ -262,6 +260,12 @@ } sqlite3_free(p->aCell); } + p->nCell = 0; + p->aCell = 0; +} + +static void statClearPage(StatPage *p){ + statClearCells(p); sqlite3PagerUnref(p->pPg); sqlite3_free(p->zPath); memset(p, 0, sizeof(StatPage)); @@ -324,22 +328,33 @@ u8 *aHdr = &aData[p->iPgno==1 ? 100 : 0]; p->flags = aHdr[0]; + if( p->flags==0x0A || p->flags==0x0D ){ + isLeaf = 1; + nHdr = 8; + }else if( p->flags==0x05 || p->flags==0x02 ){ + isLeaf = 0; + nHdr = 12; + }else{ + goto statPageIsCorrupt; + } + if( p->iPgno==1 ) nHdr += 100; p->nCell = get2byte(&aHdr[3]); p->nMxPayload = 0; - - isLeaf = (p->flags==0x0A || p->flags==0x0D); - nHdr = 12 - isLeaf*4 + (p->iPgno==1)*100; + szPage = sqlite3BtreeGetPageSize(pBt); nUnused = get2byte(&aHdr[5]) - nHdr - 2*p->nCell; nUnused += (int)aHdr[7]; iOff = get2byte(&aHdr[1]); while( iOff ){ + int iNext; + if( iOff>=szPage ) goto statPageIsCorrupt; nUnused += get2byte(&aData[iOff+2]); - iOff = get2byte(&aData[iOff]); + iNext = get2byte(&aData[iOff]); + if( iNext<iOff+4 && iNext>0 ) goto statPageIsCorrupt; + iOff = iNext; } p->nUnused = nUnused; p->iRightChildPg = isLeaf ? 0 : sqlite3Get4byte(&aHdr[8]); - szPage = sqlite3BtreeGetPageSize(pBt); if( p->nCell ){ int i; /* Used to iterate through cells */ @@ -356,6 +371,7 @@ StatCell *pCell = &p->aCell[i]; iOff = get2byte(&aData[nHdr+i*2]); + if( iOff<nHdr || iOff>=szPage ) goto statPageIsCorrupt; if( !isLeaf ){ pCell->iChildPg = sqlite3Get4byte(&aData[iOff]); iOff += 4; @@ -372,13 +388,14 @@ } if( nPayload>(u32)p->nMxPayload ) p->nMxPayload = nPayload; getLocalPayload(nUsable, p->flags, nPayload, &nLocal); + if( nLocal<0 ) goto statPageIsCorrupt; pCell->nLocal = nLocal; - assert( nLocal>=0 ); assert( nPayload>=(u32)nLocal ); assert( nLocal<=(nUsable-35) ); if( nPayload>(u32)nLocal ){ int j; int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4); + if( iOff+nLocal>nUsable ) goto statPageIsCorrupt; pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4); pCell->nOvfl = nOvfl; pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl); @@ -402,6 +419,11 @@ } return SQLITE_OK; + +statPageIsCorrupt: + p->flags = 0; + statClearCells(p); + return SQLITE_OK; } /* @@ -697,6 +719,7 @@ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ + 0 /* xShadowName */ }; return sqlite3_create_module(db, "dbstat", &dbstat_module, 0); }
diff --git a/third_party/sqlite/src/src/delete.c b/third_party/sqlite/src/src/delete.c index 988a794..69135c2 100644 --- a/third_party/sqlite/src/src/delete.c +++ b/third_party/sqlite/src/src/delete.c
@@ -44,32 +44,49 @@ return pTab; } +/* Return true if table pTab is read-only. +** +** A table is read-only if any of the following are true: +** +** 1) It is a virtual table and no implementation of the xUpdate method +** has been provided +** +** 2) It is a system table (i.e. sqlite_master), this call is not +** part of a nested parse and writable_schema pragma has not +** been specified +** +** 3) The table is a shadow table, the database connection is in +** defensive mode, and the current sqlite3_prepare() +** is for a top-level SQL statement. +*/ +static int tabIsReadOnly(Parse *pParse, Table *pTab){ + sqlite3 *db; + if( IsVirtual(pTab) ){ + return sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0; + } + if( (pTab->tabFlags & (TF_Readonly|TF_Shadow))==0 ) return 0; + db = pParse->db; + if( (pTab->tabFlags & TF_Readonly)!=0 ){ + return sqlite3WritableSchema(db)==0 && pParse->nested==0; + } + assert( pTab->tabFlags & TF_Shadow ); + return (db->flags & SQLITE_Defensive)!=0 +#ifndef SQLITE_OMIT_VIRTUALTABLE + && db->pVtabCtx==0 +#endif + && db->nVdbeExec==0; +} + /* ** Check to make sure the given table is writable. If it is not ** writable, generate an error message and return 1. If it is ** writable return 0; */ int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ - /* A table is not writable under the following circumstances: - ** - ** 1) It is a virtual table and no implementation of the xUpdate method - ** has been provided, or - ** 2) It is a system table (i.e. sqlite_master), this call is not - ** part of a nested parse and writable_schema pragma has not - ** been specified. - ** - ** In either case leave an error message in pParse and return non-zero. - */ - if( ( IsVirtual(pTab) - && sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ) - || ( (pTab->tabFlags & TF_Readonly)!=0 - && (pParse->db->flags & SQLITE_WriteSchema)==0 - && pParse->nested==0 ) - ){ + if( tabIsReadOnly(pParse, pTab) ){ sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); return 1; } - #ifndef SQLITE_OMIT_VIEW if( !viewOk && pTab->pSelect ){ sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
diff --git a/third_party/sqlite/src/src/expr.c b/third_party/sqlite/src/src/expr.c index 657ff7ab..4aff7f6 100644 --- a/third_party/sqlite/src/src/expr.c +++ b/third_party/sqlite/src/src/expr.c
@@ -58,8 +58,8 @@ return sqlite3AffinityType(pExpr->u.zToken, 0); } #endif - if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){ - return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn); + if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->y.pTab ){ + return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); } if( op==TK_SELECT_COLUMN ){ assert( pExpr->pLeft->flags&EP_xIsSelect ); @@ -143,13 +143,13 @@ if( p->flags & EP_Generic ) break; if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER) - && p->pTab!=0 + && p->y.pTab!=0 ){ - /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally + /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally ** a TK_COLUMN but was previously evaluated and cached in a register */ int j = p->iColumn; if( j>=0 ){ - const char *zColl = p->pTab->aCol[j].zColl; + const char *zColl = p->y.pTab->aCol[j].zColl; pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); } break; @@ -1052,6 +1052,10 @@ assert( p!=0 ); /* Sanity check: Assert that the IntValue is non-negative if it exists */ assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 ); + + assert( !ExprHasProperty(p, EP_WinFunc) || p->y.pWin!=0 || db->mallocFailed ); + assert( p->op!=TK_FUNCTION || ExprHasProperty(p, EP_TokenOnly|EP_Reduced) + || p->y.pWin==0 || ExprHasProperty(p, EP_WinFunc) ); #ifdef SQLITE_DEBUG if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){ assert( p->pLeft==0 ); @@ -1070,8 +1074,9 @@ }else{ sqlite3ExprListDelete(db, p->x.pList); } - if( !ExprHasProperty(p, EP_Reduced) ){ - sqlite3WindowDelete(db, p->pWin); + if( ExprHasProperty(p, EP_WinFunc) ){ + assert( p->op==TK_FUNCTION ); + sqlite3WindowDelete(db, p->y.pWin); } } if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); @@ -1135,7 +1140,7 @@ assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 ); if( 0==flags || p->op==TK_SELECT_COLUMN #ifndef SQLITE_OMIT_WINDOWFUNC - || p->pWin + || ExprHasProperty(p, EP_WinFunc) #endif ){ nSize = EXPR_FULLSIZE; @@ -1162,7 +1167,7 @@ static int dupedExprNodeSize(Expr *p, int flags){ int nByte = dupedExprStructSize(p, flags) & 0xfff; if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ - nByte += sqlite3Strlen30(p->u.zToken)+1; + nByte += sqlite3Strlen30NN(p->u.zToken)+1; } return ROUND8(nByte); } @@ -1265,22 +1270,24 @@ } /* Fill in pNew->pLeft and pNew->pRight. */ - zAlloc += dupedExprNodeSize(p, dupFlags); - if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){ + if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly|EP_WinFunc) ){ + zAlloc += dupedExprNodeSize(p, dupFlags); if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){ pNew->pLeft = p->pLeft ? exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0; pNew->pRight = p->pRight ? exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0; } - }else{ #ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(p, EP_Reduced|EP_TokenOnly) ){ - pNew->pWin = 0; - }else{ - pNew->pWin = sqlite3WindowDup(db, pNew, p->pWin); + if( ExprHasProperty(p, EP_WinFunc) ){ + pNew->y.pWin = sqlite3WindowDup(db, pNew, p->y.pWin); + assert( ExprHasProperty(pNew, EP_WinFunc) ); } #endif /* SQLITE_OMIT_WINDOWFUNC */ + if( pzBuffer ){ + *pzBuffer = zAlloc; + } + }else{ if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ if( pNew->op==TK_SELECT_COLUMN ){ pNew->pLeft = p->pLeft; @@ -1292,9 +1299,6 @@ pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); } } - if( pzBuffer ){ - *pzBuffer = zAlloc; - } } return pNew; } @@ -2089,8 +2093,8 @@ return 0; case TK_COLUMN: return ExprHasProperty(p, EP_CanBeNull) || - p->pTab==0 || /* Reference to column of index on expression */ - (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0); + p->y.pTab==0 || /* Reference to column of index on expression */ + (p->iColumn>=0 && p->y.pTab->aCol[p->iColumn].notNull==0); default: return 1; } @@ -2145,6 +2149,14 @@ if( sqlite3StrICmp(z, "OID")==0 ) return 1; return 0; } +#ifdef SQLITE_ENABLE_NORMALIZE +int sqlite3IsRowidN(const char *z, int n){ + if( sqlite3StrNICmp(z, "_ROWID_", n)==0 ) return 1; + if( sqlite3StrNICmp(z, "ROWID", n)==0 ) return 1; + if( sqlite3StrNICmp(z, "OID", n)==0 ) return 1; + return 0; +} +#endif /* ** pX is the RHS of an IN operator. If pX is a SELECT statement @@ -3378,7 +3390,7 @@ ** constant. */ int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target); - int aff = sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn); + int aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn); if( aff!=SQLITE_AFF_BLOB ){ static const char zAff[] = "B\000C\000D\000E"; assert( SQLITE_AFF_BLOB=='A' ); @@ -3402,7 +3414,7 @@ iTab = pParse->iSelfTab - 1; } } - return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, + return sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab, pExpr->iColumn, iTab, target, pExpr->op2); } @@ -3616,8 +3628,8 @@ CollSeq *pColl = 0; /* A collating sequence */ #ifndef SQLITE_OMIT_WINDOWFUNC - if( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) && pExpr->pWin ){ - return pExpr->pWin->regResult; + if( ExprHasProperty(pExpr, EP_WinFunc) ){ + return pExpr->y.pWin->regResult; } #endif @@ -3860,7 +3872,7 @@ ** p1==1 -> old.a p1==4 -> new.a ** p1==2 -> old.b p1==5 -> new.b */ - Table *pTab = pExpr->pTab; + Table *pTab = pExpr->y.pTab; int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn; assert( pExpr->iTable==0 || pExpr->iTable==1 ); @@ -3871,7 +3883,7 @@ sqlite3VdbeAddOp2(v, OP_Param, p1, target); VdbeComment((v, "r[%d]=%s.%s", target, (pExpr->iTable ? "new" : "old"), - (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName) + (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[pExpr->iColumn].zName) )); #ifndef SQLITE_OMIT_FLOATING_POINT @@ -4722,6 +4734,20 @@ if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){ if( pA->op==TK_FUNCTION ){ if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; +#ifndef SQLITE_OMIT_WINDOWFUNC + /* Justification for the assert(): + ** window functions have p->op==TK_FUNCTION but aggregate functions + ** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate + ** function and a window function should have failed before reaching + ** this point. And, it is not possible to have a window function and + ** a scalar function with the same name and number of arguments. So + ** if we reach this point, either A and B both window functions or + ** neither are a window functions. */ + assert( ExprHasProperty(pA,EP_WinFunc)==ExprHasProperty(pB,EP_WinFunc) ); + if( ExprHasProperty(pA,EP_WinFunc) ){ + if( sqlite3WindowCompare(pParse,pA->y.pWin,pB->y.pWin)!=0 ) return 2; + } +#endif }else if( pA->op==TK_COLLATE ){ if( sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; }else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ @@ -4741,21 +4767,6 @@ if( pA->iTable!=pB->iTable && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2; } -#ifndef SQLITE_OMIT_WINDOWFUNC - /* Justification for the assert(): - ** window functions have p->op==TK_FUNCTION but aggregate functions - ** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate - ** function and a window function should have failed before reaching - ** this point. And, it is not possible to have a window function and - ** a scalar function with the same name and number of arguments. So - ** if we reach this point, either A and B both window functions or - ** neither are a window functions. */ - assert( (pA->pWin==0)==(pB->pWin==0) ); - - if( pA->pWin!=0 ){ - if( sqlite3WindowCompare(pParse,pA->pWin,pB->pWin)!=0 ) return 2; - } -#endif } return 0; } @@ -4896,8 +4907,8 @@ testcase( pExpr->op==TK_LE ); testcase( pExpr->op==TK_GT ); testcase( pExpr->op==TK_GE ); - if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab)) - || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab)) + if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->y.pTab)) + || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->y.pTab)) ){ return WRC_Prune; } @@ -5128,7 +5139,7 @@ && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0 ){ pCol = &pAggInfo->aCol[k]; - pCol->pTab = pExpr->pTab; + pCol->pTab = pExpr->y.pTab; pCol->iTable = pExpr->iTable; pCol->iColumn = pExpr->iColumn; pCol->iMem = ++pParse->nMem;
diff --git a/third_party/sqlite/src/src/fkey.c b/third_party/sqlite/src/src/fkey.c index 4dafd9e..71e55ada 100644 --- a/third_party/sqlite/src/src/fkey.c +++ b/third_party/sqlite/src/src/fkey.c
@@ -502,7 +502,7 @@ ){ Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0); if( pExpr ){ - pExpr->pTab = pTab; + pExpr->y.pTab = pTab; pExpr->iTable = iCursor; pExpr->iColumn = iCol; }
diff --git a/third_party/sqlite/src/src/global.c b/third_party/sqlite/src/src/global.c index 626487a0..8011df7 100644 --- a/third_party/sqlite/src/src/global.c +++ b/third_party/sqlite/src/src/global.c
@@ -240,6 +240,7 @@ 0, /* xTestCallback */ #endif 0, /* bLocaltimeFault */ + 0, /* bInternalFunctions */ 0x7ffffffe, /* iOnceResetThreshold */ SQLITE_DEFAULT_SORTERREF_SIZE /* szSorterRef */ };
diff --git a/third_party/sqlite/src/src/hash.c b/third_party/sqlite/src/src/hash.c index 1f0ef15..04f67f6 100644 --- a/third_party/sqlite/src/src/hash.c +++ b/third_party/sqlite/src/src/hash.c
@@ -64,6 +64,20 @@ } return h; } +#ifdef SQLITE_ENABLE_NORMALIZE +static unsigned int strHashN(const char *z, int n){ + unsigned int h = 0; + int i; + for(i=0; i<n; i++){ + /* Knuth multiplicative hashing. (Sorting & Searching, p. 510). + ** 0x9e3779b1 is 2654435761 which is the closest prime number to + ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */ + h += sqlite3UpperToLower[z[i]]; + h *= 0x9e3779b1; + } + return h; +} +#endif /* SQLITE_ENABLE_NORMALIZE */ /* Link pNew element into the hash table pH. If pEntry!=0 then also @@ -175,6 +189,40 @@ } return &nullElement; } +#ifdef SQLITE_ENABLE_NORMALIZE +static HashElem *findElementWithHashN( + const Hash *pH, /* The pH to be searched */ + const char *pKey, /* The key we are searching for */ + int nKey, /* Number of key bytes to use */ + unsigned int *pHash /* Write the hash value here */ +){ + HashElem *elem; /* Used to loop thru the element list */ + int count; /* Number of elements left to test */ + unsigned int h; /* The computed hash */ + static HashElem nullElement = { 0, 0, 0, 0 }; + + if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/ + struct _ht *pEntry; + h = strHashN(pKey, nKey) % pH->htsize; + pEntry = &pH->ht[h]; + elem = pEntry->chain; + count = pEntry->count; + }else{ + h = 0; + elem = pH->first; + count = pH->count; + } + if( pHash ) *pHash = h; + while( count-- ){ + assert( elem!=0 ); + if( sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){ + return elem; + } + elem = elem->next; + } + return &nullElement; +} +#endif /* SQLITE_ENABLE_NORMALIZE */ /* Remove a single entry from the hash table given a pointer to that ** element and a hash on the element's key. @@ -219,6 +267,14 @@ assert( pKey!=0 ); return findElementWithHash(pH, pKey, 0)->data; } +#ifdef SQLITE_ENABLE_NORMALIZE +void *sqlite3HashFindN(const Hash *pH, const char *pKey, int nKey){ + assert( pH!=0 ); + assert( pKey!=0 ); + assert( nKey>=0 ); + return findElementWithHashN(pH, pKey, nKey, 0)->data; +} +#endif /* SQLITE_ENABLE_NORMALIZE */ /* Insert an element into the hash table pH. The key is pKey ** and the data is "data".
diff --git a/third_party/sqlite/src/src/insert.c b/third_party/sqlite/src/src/insert.c index 6d1121e..cd2eec12 100644 --- a/third_party/sqlite/src/src/insert.c +++ b/third_party/sqlite/src/src/insert.c
@@ -146,7 +146,8 @@ }while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB ); pTab->zColAff = zColAff; } - i = sqlite3Strlen30(zColAff); + assert( zColAff!=0 ); + i = sqlite3Strlen30NN(zColAff); if( i ){ if( iReg ){ sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i); @@ -1126,14 +1127,15 @@ #endif /* -** Meanings of bits in of pWalker->eCode for checkConstraintUnchanged() +** Meanings of bits in of pWalker->eCode for +** sqlite3ExprReferencesUpdatedColumn() */ #define CKCNSTRNT_COLUMN 0x01 /* CHECK constraint uses a changing column */ #define CKCNSTRNT_ROWID 0x02 /* CHECK constraint references the ROWID */ -/* This is the Walker callback from checkConstraintUnchanged(). Set -** bit 0x01 of pWalker->eCode if -** pWalker->eCode to 0 if this expression node references any of the +/* This is the Walker callback from sqlite3ExprReferencesUpdatedColumn(). +* Set bit 0x01 of pWalker->eCode if pWalker->eCode to 0 and if this +** expression node references any of the ** columns that are being modifed by an UPDATE statement. */ static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){ @@ -1155,12 +1157,21 @@ ** only columns that are modified by the UPDATE are those for which ** aiChng[i]>=0, and also the ROWID is modified if chngRowid is true. ** -** Return true if CHECK constraint pExpr does not use any of the +** Return true if CHECK constraint pExpr uses any of the ** changing columns (or the rowid if it is changing). In other words, -** return true if this CHECK constraint can be skipped when validating +** return true if this CHECK constraint must be validated for ** the new row in the UPDATE statement. +** +** 2018-09-15: pExpr might also be an expression for an index-on-expressions. +** The operation of this routine is the same - return true if an only if +** the expression uses one or more of columns identified by the second and +** third arguments. */ -static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){ +int sqlite3ExprReferencesUpdatedColumn( + Expr *pExpr, /* The expression to be checked */ + int *aiChng, /* aiChng[x]>=0 if column x changed by the UPDATE */ + int chngRowid /* True if UPDATE changes the rowid */ +){ Walker w; memset(&w, 0, sizeof(w)); w.eCode = 0; @@ -1175,7 +1186,7 @@ testcase( w.eCode==CKCNSTRNT_COLUMN ); testcase( w.eCode==CKCNSTRNT_ROWID ); testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) ); - return !w.eCode; + return w.eCode!=0; } /* @@ -1381,7 +1392,13 @@ for(i=0; i<pCheck->nExpr; i++){ int allOk; Expr *pExpr = pCheck->a[i].pExpr; - if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue; + if( aiChng + && !sqlite3ExprReferencesUpdatedColumn(pExpr, aiChng, pkChng) + ){ + /* The check constraints do not reference any of the columns being + ** updated so there is no point it verifying the check constraint */ + continue; + } allOk = sqlite3VdbeMakeLabel(v); sqlite3VdbeVerifyAbortable(v, onError); sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL);
diff --git a/third_party/sqlite/src/src/loadext.c b/third_party/sqlite/src/src/loadext.c index 5f49872..142a89a5 100644 --- a/third_party/sqlite/src/src/loadext.c +++ b/third_party/sqlite/src/src/loadext.c
@@ -84,6 +84,7 @@ # define sqlite3_declare_vtab 0 # define sqlite3_vtab_config 0 # define sqlite3_vtab_on_conflict 0 +# define sqlite3_vtab_collation 0 #endif #ifdef SQLITE_OMIT_SHARED_CACHE @@ -451,7 +452,13 @@ sqlite3_str_length, sqlite3_str_value, /* Version 3.25.0 and later */ - sqlite3_create_window_function + sqlite3_create_window_function, + /* Version 3.26.0 and later */ +#ifdef SQLITE_ENABLE_NORMALIZE + sqlite3_normalized_sql +#else + 0 +#endif }; /*
diff --git a/third_party/sqlite/src/src/main.c b/third_party/sqlite/src/src/main.c index f070fed..478428a 100644 --- a/third_party/sqlite/src/src/main.c +++ b/third_party/sqlite/src/src/main.c
@@ -835,6 +835,7 @@ { SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG }, { SQLITE_DBCONFIG_TRIGGER_EQP, SQLITE_TriggerEQP }, { SQLITE_DBCONFIG_RESET_DATABASE, SQLITE_ResetDatabase }, + { SQLITE_DBCONFIG_DEFENSIVE, SQLITE_Defensive }, }; unsigned int i; rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ @@ -3062,6 +3063,9 @@ #if defined(SQLITE_ENABLE_QPSG) | SQLITE_EnableQPSG #endif +#if defined(SQLITE_DEFAULT_DEFENSIVE) + | SQLITE_Defensive +#endif ; sqlite3HashInit(&db->aCollSeq); #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -3957,15 +3961,26 @@ /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff); ** - ** If parameter onoff is non-zero, configure the wrappers so that all - ** subsequent calls to localtime() and variants fail. If onoff is zero, - ** undo this setting. + ** If parameter onoff is non-zero, subsequent calls to localtime() + ** and its variants fail. If onoff is zero, undo this setting. */ case SQLITE_TESTCTRL_LOCALTIME_FAULT: { sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int); break; } + /* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCS, int onoff); + ** + ** If parameter onoff is non-zero, internal-use-only SQL functions + ** are visible to ordinary SQL. This is useful for testing but is + ** unsafe because invalid parameters to those internal-use-only functions + ** can result in crashes or segfaults. + */ + case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: { + sqlite3GlobalConfig.bInternalFunctions = va_arg(ap, int); + break; + } + /* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int); ** ** Set or clear a flag that indicates that the database file is always well-
diff --git a/third_party/sqlite/src/src/os_unix.c b/third_party/sqlite/src/src/os_unix.c index 96802e6..d0736e0a 100644 --- a/third_party/sqlite/src/src/os_unix.c +++ b/third_party/sqlite/src/src/os_unix.c
@@ -136,12 +136,10 @@ #define SQLITE_FSFLAGS_IS_MSDOS 0x1 /* -** If we are to be thread-safe, include the pthreads header and define -** the SQLITE_UNIX_THREADS macro. +** If we are to be thread-safe, include the pthreads header. */ #if SQLITE_THREADSAFE # include <pthread.h> -# define SQLITE_UNIX_THREADS 1 #endif /* @@ -1119,8 +1117,7 @@ /* ** An instance of the following structure is allocated for each open -** inode. Or, on LinuxThreads, there is one of these structures for -** each inode opened by each thread. +** inode. ** ** A single inode can have multiple file descriptors, so each unixFile ** structure contains a pointer to an instance of this object and this @@ -1166,13 +1163,16 @@ /* ** A lists of all unixInodeInfo objects. +** +** Must hold unixBigLock in order to read or write this variable. */ static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */ #ifdef SQLITE_DEBUG /* -** True if the inode mutex is held, or not. Used only within assert() -** to help verify correct mutex usage. +** True if the inode mutex (on the unixFile.pFileMutex field) is held, or not. +** This routine is used only within assert() to help verify correct mutex +** usage. */ int unixFileMutexHeld(unixFile *pFile){ assert( pFile->pInode ); @@ -1300,8 +1300,8 @@ /* ** Release a unixInodeInfo structure previously allocated by findInodeInfo(). ** -** The mutex entered using the unixEnterMutex() function must be held -** when this function is called. +** The global mutex must be held when this routine is called, but the mutex +** on the inode being deleted must NOT be held. */ static void releaseInodeInfo(unixFile *pFile){ unixInodeInfo *pInode = pFile->pInode; @@ -1336,8 +1336,7 @@ ** describes that file descriptor. Create a new one if necessary. The ** return value might be uninitialized if an error occurs. ** -** The mutex entered using the unixEnterMutex() function must be held -** when this function is called. +** The global mutex must held when calling this routine. ** ** Return an appropriate error code. */ @@ -1398,6 +1397,7 @@ #else fileId.ino = (u64)statbuf.st_ino; #endif + assert( unixMutexHeld() ); pInode = inodeList; while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){ pInode = pInode->pNext; @@ -1417,6 +1417,7 @@ } } pInode->nRef = 1; + assert( unixMutexHeld() ); pInode->pNext = inodeList; pInode->pPrev = 0; if( inodeList ) inodeList->pPrev = pInode; @@ -4220,18 +4221,18 @@ ** ** The following fields are read-only after the object is created: ** -** fid +** hShm ** zFilename ** -** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and +** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and ** unixMutexHeld() is true when reading or writing any other field ** in this structure. */ struct unixShmNode { unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */ - sqlite3_mutex *mutex; /* Mutex to access this object */ + sqlite3_mutex *pShmMutex; /* Mutex to access this object */ char *zFilename; /* Name of the mmapped file */ - int h; /* Open file descriptor */ + int hShm; /* Open file descriptor */ int szRegion; /* Size of shared-memory regions */ u16 nRegion; /* Size of array apRegion */ u8 isReadonly; /* True if read-only */ @@ -4253,16 +4254,16 @@ ** The following fields are initialized when this object is created and ** are read-only thereafter: ** -** unixShm.pFile +** unixShm.pShmNode ** unixShm.id ** -** All other fields are read/write. The unixShm.pFile->mutex must be held -** while accessing any read/write fields. +** All other fields are read/write. The unixShm.pShmNode->pShmMutex must +** be held while accessing any read/write fields. */ struct unixShm { unixShmNode *pShmNode; /* The underlying unixShmNode object */ unixShm *pNext; /* Next unixShm with the same unixShmNode */ - u8 hasMutex; /* True if holding the unixShmNode mutex */ + u8 hasMutex; /* True if holding the unixShmNode->pShmMutex */ u8 id; /* Id of this connection within its unixShmNode */ u16 sharedMask; /* Mask of shared locks held */ u16 exclMask; /* Mask of exclusive locks held */ @@ -4292,7 +4293,8 @@ /* Access to the unixShmNode object is serialized by the caller */ pShmNode = pFile->pInode->pShmNode; - assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->mutex) ); + assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) ); + assert( pShmNode->nRef>0 || unixMutexHeld() ); /* Shared locks never span more than one byte */ assert( n==1 || lockType!=F_RDLCK ); @@ -4300,13 +4302,13 @@ /* Locks are within range */ assert( n>=1 && n<=SQLITE_SHM_NLOCK ); - if( pShmNode->h>=0 ){ + if( pShmNode->hShm>=0 ){ /* Initialize the locking parameters */ f.l_type = lockType; f.l_whence = SEEK_SET; f.l_start = ofst; f.l_len = n; - rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile); + rc = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile); rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY; } @@ -4378,18 +4380,18 @@ int nShmPerMap = unixShmRegionPerMap(); int i; assert( p->pInode==pFd->pInode ); - sqlite3_mutex_free(p->mutex); + sqlite3_mutex_free(p->pShmMutex); for(i=0; i<p->nRegion; i+=nShmPerMap){ - if( p->h>=0 ){ + if( p->hShm>=0 ){ osMunmap(p->apRegion[i], p->szRegion); }else{ sqlite3_free(p->apRegion[i]); } } sqlite3_free(p->apRegion); - if( p->h>=0 ){ - robust_close(pFd, p->h, __LINE__); - p->h = -1; + if( p->hShm>=0 ){ + robust_close(pFd, p->hShm, __LINE__); + p->hShm = -1; } p->pInode->pShmNode = 0; sqlite3_free(p); @@ -4431,7 +4433,7 @@ lock.l_start = UNIX_SHM_DMS; lock.l_len = 1; lock.l_type = F_WRLCK; - if( osFcntl(pShmNode->h, F_GETLK, &lock)!=0 ) { + if( osFcntl(pShmNode->hShm, F_GETLK, &lock)!=0 ) { rc = SQLITE_IOERR_LOCK; }else if( lock.l_type==F_UNLCK ){ if( pShmNode->isReadonly ){ @@ -4439,7 +4441,12 @@ rc = SQLITE_READONLY_CANTINIT; }else{ rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1); - if( rc==SQLITE_OK && robust_ftruncate(pShmNode->h, 0) ){ + /* The first connection to attach must truncate the -shm file. We + ** truncate to 3 bytes (an arbitrary small number, less than the + ** -shm header size) rather than 0 as a system debugging aid, to + ** help detect if a -shm file truncation is legitimate or is the work + ** or a rogue process. */ + if( rc==SQLITE_OK && robust_ftruncate(pShmNode->hShm, 3) ){ rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename); } } @@ -4545,12 +4552,12 @@ sqlite3_snprintf(nShmFilename, zShm, "%s-shm", zBasePath); sqlite3FileSuffix3(pDbFd->zPath, zShm); #endif - pShmNode->h = -1; + pShmNode->hShm = -1; pDbFd->pInode->pShmNode = pShmNode; pShmNode->pInode = pDbFd->pInode; if( sqlite3GlobalConfig.bCoreMutex ){ - pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); - if( pShmNode->mutex==0 ){ + pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); + if( pShmNode->pShmMutex==0 ){ rc = SQLITE_NOMEM_BKPT; goto shm_open_err; } @@ -4558,11 +4565,11 @@ if( pInode->bProcessLock==0 ){ if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){ - pShmNode->h = robust_open(zShm, O_RDWR|O_CREAT, (sStat.st_mode&0777)); + pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT,(sStat.st_mode&0777)); } - if( pShmNode->h<0 ){ - pShmNode->h = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777)); - if( pShmNode->h<0 ){ + if( pShmNode->hShm<0 ){ + pShmNode->hShm = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777)); + if( pShmNode->hShm<0 ){ rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm); goto shm_open_err; } @@ -4573,7 +4580,7 @@ ** is owned by the same user that owns the original database. Otherwise, ** the original owner will not be able to connect. */ - robustFchown(pShmNode->h, sStat.st_uid, sStat.st_gid); + robustFchown(pShmNode->hShm, sStat.st_uid, sStat.st_gid); rc = unixLockSharedMemory(pDbFd, pShmNode); if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err; @@ -4593,13 +4600,13 @@ ** the cover of the unixEnterMutex() mutex and the pointer from the ** new (struct unixShm) object to the pShmNode has been set. All that is ** left to do is to link the new object into the linked list starting - ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex - ** mutex. + ** at pShmNode->pFirst. This must be done while holding the + ** pShmNode->pShmMutex. */ - sqlite3_mutex_enter(pShmNode->mutex); + sqlite3_mutex_enter(pShmNode->pShmMutex); p->pNext = pShmNode->pFirst; pShmNode->pFirst = p; - sqlite3_mutex_leave(pShmNode->mutex); + sqlite3_mutex_leave(pShmNode->pShmMutex); return rc; /* Jump here on any error */ @@ -4651,7 +4658,7 @@ p = pDbFd->pShm; pShmNode = p->pShmNode; - sqlite3_mutex_enter(pShmNode->mutex); + sqlite3_mutex_enter(pShmNode->pShmMutex); if( pShmNode->isUnlocked ){ rc = unixLockSharedMemory(pDbFd, pShmNode); if( rc!=SQLITE_OK ) goto shmpage_out; @@ -4659,8 +4666,8 @@ } assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); assert( pShmNode->pInode==pDbFd->pInode ); - assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 ); - assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 ); + assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 ); + assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 ); /* Minimum number of regions required to be mapped. */ nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap; @@ -4672,12 +4679,12 @@ pShmNode->szRegion = szRegion; - if( pShmNode->h>=0 ){ + if( pShmNode->hShm>=0 ){ /* The requested region is not mapped into this processes address space. ** Check to see if it has been allocated (i.e. if the wal-index file is ** large enough to contain the requested region). */ - if( osFstat(pShmNode->h, &sStat) ){ + if( osFstat(pShmNode->hShm, &sStat) ){ rc = SQLITE_IOERR_SHMSIZE; goto shmpage_out; } @@ -4705,7 +4712,7 @@ assert( (nByte % pgsz)==0 ); for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){ int x = 0; - if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, &x)!=1 ){ + if( seekAndWriteFd(pShmNode->hShm, iPg*pgsz + pgsz-1,"",1,&x)!=1 ){ const char *zFile = pShmNode->zFilename; rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile); goto shmpage_out; @@ -4728,22 +4735,22 @@ int nMap = szRegion*nShmPerMap; int i; void *pMem; - if( pShmNode->h>=0 ){ + if( pShmNode->hShm>=0 ){ pMem = osMmap(0, nMap, pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE, - MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion + MAP_SHARED, pShmNode->hShm, szRegion*(i64)pShmNode->nRegion ); if( pMem==MAP_FAILED ){ rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename); goto shmpage_out; } }else{ - pMem = sqlite3_malloc64(szRegion); + pMem = sqlite3_malloc64(nMap); if( pMem==0 ){ rc = SQLITE_NOMEM_BKPT; goto shmpage_out; } - memset(pMem, 0, szRegion); + memset(pMem, 0, nMap); } for(i=0; i<nShmPerMap; i++){ @@ -4760,7 +4767,7 @@ *pp = 0; } if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY; - sqlite3_mutex_leave(pShmNode->mutex); + sqlite3_mutex_leave(pShmNode->pShmMutex); return rc; } @@ -4794,12 +4801,12 @@ || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); - assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 ); - assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 ); + assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 ); + assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 ); mask = (1<<(ofst+n)) - (1<<ofst); assert( n>1 || mask==(1<<ofst) ); - sqlite3_mutex_enter(pShmNode->mutex); + sqlite3_mutex_enter(pShmNode->pShmMutex); if( flags & SQLITE_SHM_UNLOCK ){ u16 allMask = 0; /* Mask of locks held by siblings */ @@ -4872,7 +4879,7 @@ } } } - sqlite3_mutex_leave(pShmNode->mutex); + sqlite3_mutex_leave(pShmNode->pShmMutex); OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n", p->id, osGetpid(0), p->sharedMask, p->exclMask)); return rc; @@ -4922,14 +4929,14 @@ /* Remove connection p from the set of connections associated ** with pShmNode */ - sqlite3_mutex_enter(pShmNode->mutex); + sqlite3_mutex_enter(pShmNode->pShmMutex); for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){} *pp = p->pNext; /* Free the connection p */ sqlite3_free(p); pDbFd->pShm = 0; - sqlite3_mutex_leave(pShmNode->mutex); + sqlite3_mutex_leave(pShmNode->pShmMutex); /* If pShmNode->nRef has reached 0, then close the underlying ** shared-memory file, too */ @@ -4938,7 +4945,7 @@ assert( pShmNode->nRef>0 ); pShmNode->nRef--; if( pShmNode->nRef==0 ){ - if( deleteFlag && pShmNode->h>=0 ){ + if( deleteFlag && pShmNode->hShm>=0 ){ osUnlink(pShmNode->zFilename); } unixShmPurge(pDbFd);
diff --git a/third_party/sqlite/src/src/os_win.c b/third_party/sqlite/src/src/os_win.c index 5cd28a2..76743781 100644 --- a/third_party/sqlite/src/src/os_win.c +++ b/third_party/sqlite/src/src/os_win.c
@@ -284,8 +284,7 @@ int nFetchOut; /* Number of outstanding xFetch references */ HANDLE hMap; /* Handle for accessing memory mapping */ void *pMapRegion; /* Area memory mapped */ - sqlite3_int64 mmapSize; /* Usable size of mapped region */ - sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */ + sqlite3_int64 mmapSize; /* Size of mapped region */ sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ #endif }; @@ -2906,7 +2905,26 @@ DWORD lastErrno; #if SQLITE_MAX_MMAP_SIZE>0 sqlite3_int64 oldMmapSize; - if( pFile->nFetchOut>0 ) return SQLITE_OK; + if( pFile->nFetchOut>0 ){ + /* File truncation is a no-op if there are outstanding memory mapped + ** pages. This is because truncating the file means temporarily unmapping + ** the file, and that might delete memory out from under existing cursors. + ** + ** This can result in incremental vacuum not truncating the file, + ** if there is an active read cursor when the incremental vacuum occurs. + ** No real harm comes of this - the database file is not corrupted, + ** though some folks might complain that the file is bigger than it + ** needs to be. + ** + ** The only feasible work-around is to defer the truncation until after + ** all references to memory-mapped content are closed. That is doable, + ** but involves adding a few branches in the common write code path which + ** could slow down normal operations slightly. Hence, we have decided for + ** now to simply make trancations a no-op if there are pending reads. We + ** can maybe revisit this decision in the future. + */ + return SQLITE_OK; + } #endif assert( pFile ); @@ -4335,9 +4353,9 @@ static int winUnmapfile(winFile *pFile){ assert( pFile!=0 ); OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, " - "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n", + "mmapSize=%lld, mmapSizeMax=%lld\n", osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion, - pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax)); + pFile->mmapSize, pFile->mmapSizeMax)); if( pFile->pMapRegion ){ if( !osUnmapViewOfFile(pFile->pMapRegion) ){ pFile->lastErrno = osGetLastError(); @@ -4349,7 +4367,6 @@ } pFile->pMapRegion = 0; pFile->mmapSize = 0; - pFile->mmapSizeActual = 0; } if( pFile->hMap!=NULL ){ if( !osCloseHandle(pFile->hMap) ){ @@ -4460,7 +4477,6 @@ } pFd->pMapRegion = pNew; pFd->mmapSize = nMap; - pFd->mmapSizeActual = nMap; } OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n", @@ -5262,7 +5278,6 @@ pFile->hMap = NULL; pFile->pMapRegion = 0; pFile->mmapSize = 0; - pFile->mmapSizeActual = 0; pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap; #endif
diff --git a/third_party/sqlite/src/src/pager.c b/third_party/sqlite/src/src/pager.c index 24f40514..771330e9 100644 --- a/third_party/sqlite/src/src/pager.c +++ b/third_party/sqlite/src/src/pager.c
@@ -825,19 +825,30 @@ */ #define isOpen(pFd) ((pFd)->pMethods!=0) +#ifdef SQLITE_DIRECT_OVERFLOW_READ /* -** Return true if this pager uses a write-ahead log to read page pgno. -** Return false if the pager reads pgno directly from the database. +** Return true if page pgno can be read directly from the database file +** by the b-tree layer. This is the case if: +** +** * the database file is open, +** * there are no dirty pages in the cache, and +** * the desired page is not currently in the wal file. */ -#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_DIRECT_OVERFLOW_READ) -int sqlite3PagerUseWal(Pager *pPager, Pgno pgno){ - u32 iRead = 0; - int rc; - if( pPager->pWal==0 ) return 0; - rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); - return rc || iRead; +int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){ + if( pPager->fd->pMethods==0 ) return 0; + if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; +#ifndef SQLITE_OMIT_WAL + if( pPager->pWal ){ + u32 iRead = 0; + int rc; + rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); + return (rc==SQLITE_OK && iRead==0); + } +#endif + return 1; } #endif + #ifndef SQLITE_OMIT_WAL # define pagerUseWal(x) ((x)->pWal!=0) #else @@ -7021,7 +7032,11 @@ void (*xCodecFree)(void*), void *pCodec ){ - if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); + if( pPager->xCodecFree ){ + pPager->xCodecFree(pPager->pCodec); + }else{ + pager_reset(pPager); + } pPager->xCodec = pPager->memDb ? 0 : xCodec; pPager->xCodecSizeChng = xCodecSizeChng; pPager->xCodecFree = xCodecFree;
diff --git a/third_party/sqlite/src/src/pager.h b/third_party/sqlite/src/src/pager.h index e51c2606..80e6ad43 100644 --- a/third_party/sqlite/src/src/pager.h +++ b/third_party/sqlite/src/src/pager.h
@@ -179,9 +179,6 @@ int sqlite3PagerWalCallback(Pager *pPager); int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); -# ifdef SQLITE_DIRECT_OVERFLOW_READ - int sqlite3PagerUseWal(Pager *pPager, Pgno); -# endif # ifdef SQLITE_ENABLE_SNAPSHOT int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); @@ -189,8 +186,10 @@ int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot); void sqlite3PagerSnapshotUnlock(Pager *pPager); # endif -#else -# define sqlite3PagerUseWal(x,y) 0 +#endif + +#ifdef SQLITE_DIRECT_OVERFLOW_READ + int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno); #endif #ifdef SQLITE_ENABLE_ZIPVFS
diff --git a/third_party/sqlite/src/src/parse.y b/third_party/sqlite/src/src/parse.y index e0f8c646..cd38ebf 100644 --- a/third_party/sqlite/src/src/parse.y +++ b/third_party/sqlite/src/src/parse.y
@@ -941,13 +941,10 @@ p->pLeft = p->pRight = 0; p->x.pList = 0; p->pAggInfo = 0; - p->pTab = 0; + p->y.pTab = 0; p->op2 = 0; p->iTable = 0; p->iColumn = 0; -#ifndef SQLITE_OMIT_WINDOWFUNC - p->pWin = 0; -#endif p->u.zToken = (char*)&p[1]; memcpy(p->u.zToken, t.z, t.n); p->u.zToken[t.n] = 0;
diff --git a/third_party/sqlite/src/src/pcache.c b/third_party/sqlite/src/src/pcache.c index d5e8711..d690931 100644 --- a/third_party/sqlite/src/src/pcache.c +++ b/third_party/sqlite/src/src/pcache.c
@@ -32,7 +32,7 @@ ** The PCache.pSynced variable is used to optimize searching for a dirty ** page to eject from the cache mid-transaction. It is better to eject ** a page that does not require a journal sync than one that does. -** Therefore, pSynced is maintained to that it *almost* always points +** Therefore, pSynced is maintained so that it *almost* always points ** to either the oldest page in the pDirty/pDirtyTail list that has a ** clear PGHDR_NEED_SYNC flag or to a page that is older than this one ** (so that the right page to eject can be found by following pDirtyPrev @@ -856,6 +856,15 @@ return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0; } +#ifdef SQLITE_DIRECT_OVERFLOW_READ +/* +** Return true if there are one or more dirty pages in the cache. Else false. +*/ +int sqlite3PCacheIsDirty(PCache *pCache){ + return (pCache->pDirty!=0); +} +#endif + #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) /* ** For all dirty pages currently in the cache, invoke the specified
diff --git a/third_party/sqlite/src/src/pcache.h b/third_party/sqlite/src/src/pcache.h index 8aadd02..d6cb4397 100644 --- a/third_party/sqlite/src/src/pcache.h +++ b/third_party/sqlite/src/src/pcache.h
@@ -183,4 +183,8 @@ /* Number of dirty pages as a percentage of the configured cache size */ int sqlite3PCachePercentDirty(PCache*); +#ifdef SQLITE_DIRECT_OVERFLOW_READ +int sqlite3PCacheIsDirty(PCache *pCache); +#endif + #endif /* _PCACHE_H_ */
diff --git a/third_party/sqlite/src/src/pcache1.c b/third_party/sqlite/src/src/pcache1.c index 2692bd6..59c1869 100644 --- a/third_party/sqlite/src/src/pcache1.c +++ b/third_party/sqlite/src/src/pcache1.c
@@ -105,7 +105,8 @@ }; /* -** A page is pinned if it is no on the LRU list +** A page is pinned if it is not on the LRU list. To be "pinned" means +** that the page is in active use and must not be deallocated. */ #define PAGE_IS_PINNED(p) ((p)->pLruNext==0) #define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0)
diff --git a/third_party/sqlite/src/src/pragma.c b/third_party/sqlite/src/src/pragma.c index 6e02655..264b10d9 100644 --- a/third_party/sqlite/src/src/pragma.c +++ b/third_party/sqlite/src/src/pragma.c
@@ -1037,7 +1037,7 @@ setPragmaResultColumnNames(v, pPragma); returnSingleInt(v, (db->flags & pPragma->iArg)!=0 ); }else{ - int mask = pPragma->iArg; /* Mask of bits to set or clear. */ + u64 mask = pPragma->iArg; /* Mask of bits to set or clear. */ if( db->autoCommit==0 ){ /* Foreign key support may not be enabled or disabled while not ** in auto-commit mode. */ @@ -1086,15 +1086,17 @@ Table *pTab; pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb); if( pTab ){ + int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); int i, k; int nHidden = 0; Column *pCol; Index *pPk = sqlite3PrimaryKeyIndex(pTab); - pParse->nMem = 6; - sqlite3CodeVerifySchema(pParse, iDb); + pParse->nMem = 7; + sqlite3CodeVerifySchema(pParse, iTabDb); sqlite3ViewGetColumnNames(pParse, pTab); for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ - if( IsHiddenColumn(pCol) ){ + int isHidden = IsHiddenColumn(pCol); + if( isHidden && pPragma->iArg==0 ){ nHidden++; continue; } @@ -1106,13 +1108,14 @@ for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){} } assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN ); - sqlite3VdbeMultiLoad(v, 1, "issisi", + sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi", i-nHidden, pCol->zName, sqlite3ColumnType(pCol,""), pCol->notNull ? 1 : 0, pCol->pDflt ? pCol->pDflt->u.zToken : 0, - k); + k, + isHidden); } } } @@ -1150,6 +1153,7 @@ Table *pTab; pIdx = sqlite3FindIndex(db, zRight, zDb); if( pIdx ){ + int iIdxDb = sqlite3SchemaToIndex(db, pIdx->pSchema); int i; int mx; if( pPragma->iArg ){ @@ -1162,7 +1166,7 @@ pParse->nMem = 3; } pTab = pIdx->pTable; - sqlite3CodeVerifySchema(pParse, iDb); + sqlite3CodeVerifySchema(pParse, iIdxDb); assert( pParse->nMem<=pPragma->nPragCName ); for(i=0; i<mx; i++){ i16 cnum = pIdx->aiColumn[i]; @@ -1186,8 +1190,9 @@ int i; pTab = sqlite3FindTable(db, zRight, zDb); if( pTab ){ + int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); pParse->nMem = 5; - sqlite3CodeVerifySchema(pParse, iDb); + sqlite3CodeVerifySchema(pParse, iTabDb); for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){ const char *azOrigin[] = { "c", "u", "pk" }; sqlite3VdbeMultiLoad(v, 1, "isisi", @@ -1234,6 +1239,7 @@ pParse->nMem = 2; for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){ for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){ + if( p->funcFlags & SQLITE_FUNC_INTERNAL ) continue; sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1); } } @@ -1275,9 +1281,10 @@ if( pTab ){ pFK = pTab->pFKey; if( pFK ){ + int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); int i = 0; pParse->nMem = 8; - sqlite3CodeVerifySchema(pParse, iDb); + sqlite3CodeVerifySchema(pParse, iTabDb); while(pFK){ int j; for(j=0; j<pFK->nCol; j++){ @@ -1322,9 +1329,9 @@ pParse->nMem += 4; regKey = ++pParse->nMem; regRow = ++pParse->nMem; - sqlite3CodeVerifySchema(pParse, iDb); k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); while( k ){ + int iTabDb; if( zRight ){ pTab = sqlite3LocateTable(pParse, 0, zRight, zDb); k = 0; @@ -1333,21 +1340,23 @@ k = sqliteHashNext(k); } if( pTab==0 || pTab->pFKey==0 ) continue; - sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); + iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema); + sqlite3CodeVerifySchema(pParse, iTabDb); + sqlite3TableLock(pParse, iTabDb, pTab->tnum, 0, pTab->zName); if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; - sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); + sqlite3OpenTable(pParse, 0, iTabDb, pTab, OP_OpenRead); sqlite3VdbeLoadString(v, regResult, pTab->zName); for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){ pParent = sqlite3FindTable(db, pFK->zTo, zDb); if( pParent==0 ) continue; pIdx = 0; - sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName); + sqlite3TableLock(pParse, iTabDb, pParent->tnum, 0, pParent->zName); x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0); if( x==0 ){ if( pIdx==0 ){ - sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead); + sqlite3OpenTable(pParse, i, iTabDb, pParent, OP_OpenRead); }else{ - sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb); + sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iTabDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); } }else{ @@ -2116,12 +2125,24 @@ #endif #ifdef SQLITE_HAS_CODEC + /* Pragma iArg + ** ---------- ------ + ** key 0 + ** rekey 1 + ** hexkey 2 + ** hexrekey 3 + ** textkey 4 + ** textrekey 5 + */ case PragTyp_KEY: { - if( zRight ) sqlite3_key_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); - break; - } - case PragTyp_REKEY: { - if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight)); + if( zRight ){ + int n = pPragma->iArg<4 ? sqlite3Strlen30(zRight) : -1; + if( (pPragma->iArg & 1)==0 ){ + sqlite3_key_v2(db, zDb, zRight, n); + }else{ + sqlite3_rekey_v2(db, zDb, zRight, n); + } + } break; } case PragTyp_HEXKEY: { @@ -2133,7 +2154,7 @@ iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]); if( (i&1)!=0 ) zKey[i/2] = iByte; } - if( (zLeft[3] & 0xf)==0xb ){ + if( (pPragma->iArg & 1)==0 ){ sqlite3_key_v2(db, zDb, zKey, i/2); }else{ sqlite3_rekey_v2(db, zDb, zKey, i/2); @@ -2463,7 +2484,8 @@ 0, /* xRename - rename the table */ 0, /* xSavepoint */ 0, /* xRelease */ - 0 /* xRollbackTo */ + 0, /* xRollbackTo */ + 0 /* xShadowName */ }; /*
diff --git a/third_party/sqlite/src/src/pragma.h b/third_party/sqlite/src/src/pragma.h index 82651620..c16dd2f0 100644 --- a/third_party/sqlite/src/src/pragma.h +++ b/third_party/sqlite/src/src/pragma.h
@@ -48,10 +48,9 @@ #define PragTyp_ACTIVATE_EXTENSIONS 40 #define PragTyp_HEXKEY 41 #define PragTyp_KEY 42 -#define PragTyp_REKEY 43 -#define PragTyp_LOCK_STATUS 44 -#define PragTyp_PARSER_TRACE 45 -#define PragTyp_STATS 46 +#define PragTyp_LOCK_STATUS 43 +#define PragTyp_PARSER_TRACE 44 +#define PragTyp_STATS 45 /* Property flags associated with various pragma. */ #define PragFlg_NeedSchema 0x01 /* Force schema load before running */ @@ -68,58 +67,57 @@ ** result column is different from the name of the pragma */ static const char *const pragCName[] = { - /* 0 */ "cache_size", /* Used by: default_cache_size */ - /* 1 */ "cid", /* Used by: table_info */ - /* 2 */ "name", - /* 3 */ "type", - /* 4 */ "notnull", - /* 5 */ "dflt_value", - /* 6 */ "pk", - /* 7 */ "tbl", /* Used by: stats */ - /* 8 */ "idx", - /* 9 */ "wdth", - /* 10 */ "hght", - /* 11 */ "flgs", - /* 12 */ "seqno", /* Used by: index_info */ - /* 13 */ "cid", - /* 14 */ "name", + /* 0 */ "id", /* Used by: foreign_key_list */ + /* 1 */ "seq", + /* 2 */ "table", + /* 3 */ "from", + /* 4 */ "to", + /* 5 */ "on_update", + /* 6 */ "on_delete", + /* 7 */ "match", + /* 8 */ "cid", /* Used by: table_xinfo */ + /* 9 */ "name", + /* 10 */ "type", + /* 11 */ "notnull", + /* 12 */ "dflt_value", + /* 13 */ "pk", + /* 14 */ "hidden", + /* table_info reuses 8 */ /* 15 */ "seqno", /* Used by: index_xinfo */ /* 16 */ "cid", /* 17 */ "name", /* 18 */ "desc", /* 19 */ "coll", /* 20 */ "key", - /* 21 */ "seq", /* Used by: index_list */ - /* 22 */ "name", - /* 23 */ "unique", - /* 24 */ "origin", - /* 25 */ "partial", - /* 26 */ "seq", /* Used by: database_list */ + /* 21 */ "tbl", /* Used by: stats */ + /* 22 */ "idx", + /* 23 */ "wdth", + /* 24 */ "hght", + /* 25 */ "flgs", + /* 26 */ "seq", /* Used by: index_list */ /* 27 */ "name", - /* 28 */ "file", - /* 29 */ "name", /* Used by: function_list */ - /* 30 */ "builtin", - /* 31 */ "name", /* Used by: module_list pragma_list */ - /* 32 */ "seq", /* Used by: collation_list */ - /* 33 */ "name", - /* 34 */ "id", /* Used by: foreign_key_list */ - /* 35 */ "seq", - /* 36 */ "table", - /* 37 */ "from", - /* 38 */ "to", - /* 39 */ "on_update", - /* 40 */ "on_delete", - /* 41 */ "match", - /* 42 */ "table", /* Used by: foreign_key_check */ - /* 43 */ "rowid", - /* 44 */ "parent", - /* 45 */ "fkid", - /* 46 */ "busy", /* Used by: wal_checkpoint */ - /* 47 */ "log", - /* 48 */ "checkpointed", - /* 49 */ "timeout", /* Used by: busy_timeout */ - /* 50 */ "database", /* Used by: lock_status */ - /* 51 */ "status", + /* 28 */ "unique", + /* 29 */ "origin", + /* 30 */ "partial", + /* 31 */ "table", /* Used by: foreign_key_check */ + /* 32 */ "rowid", + /* 33 */ "parent", + /* 34 */ "fkid", + /* index_info reuses 15 */ + /* 35 */ "seq", /* Used by: database_list */ + /* 36 */ "name", + /* 37 */ "file", + /* 38 */ "busy", /* Used by: wal_checkpoint */ + /* 39 */ "log", + /* 40 */ "checkpointed", + /* 41 */ "name", /* Used by: function_list */ + /* 42 */ "builtin", + /* collation_list reuses 26 */ + /* 43 */ "database", /* Used by: lock_status */ + /* 44 */ "status", + /* 45 */ "cache_size", /* Used by: default_cache_size */ + /* module_list pragma_list reuses 9 */ + /* 46 */ "timeout", /* Used by: busy_timeout */ }; /* Definitions of all built-in pragmas */ @@ -129,7 +127,7 @@ u8 mPragFlg; /* Zero or more PragFlg_XXX values */ u8 iPragCName; /* Start of column names in pragCName[] */ u8 nPragCName; /* Num of col names. 0 means use pragma name */ - u32 iArg; /* Extra argument */ + u64 iArg; /* Extra argument */ } PragmaName; static const PragmaName aPragmaName[] = { #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD) @@ -165,7 +163,7 @@ {/* zName: */ "busy_timeout", /* ePragTyp: */ PragTyp_BUSY_TIMEOUT, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 49, 1, + /* ColNames: */ 46, 1, /* iArg: */ 0 }, #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) {/* zName: */ "cache_size", @@ -202,7 +200,7 @@ {/* zName: */ "collation_list", /* ePragTyp: */ PragTyp_COLLATION_LIST, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 32, 2, + /* ColNames: */ 26, 2, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS) @@ -237,14 +235,14 @@ {/* zName: */ "database_list", /* ePragTyp: */ PragTyp_DATABASE_LIST, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, - /* ColNames: */ 26, 3, + /* ColNames: */ 35, 3, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) {/* zName: */ "default_cache_size", /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1, - /* ColNames: */ 0, 1, + /* ColNames: */ 45, 1, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) @@ -274,14 +272,14 @@ {/* zName: */ "foreign_key_check", /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, - /* ColNames: */ 42, 4, + /* ColNames: */ 31, 4, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FOREIGN_KEY) {/* zName: */ "foreign_key_list", /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 34, 8, + /* ColNames: */ 0, 8, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) @@ -317,7 +315,7 @@ {/* zName: */ "function_list", /* ePragTyp: */ PragTyp_FUNCTION_LIST, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 29, 2, + /* ColNames: */ 41, 2, /* iArg: */ 0 }, #endif #endif @@ -326,12 +324,12 @@ /* ePragTyp: */ PragTyp_HEXKEY, /* ePragFlg: */ 0, /* ColNames: */ 0, 0, - /* iArg: */ 0 }, + /* iArg: */ 2 }, {/* zName: */ "hexrekey", /* ePragTyp: */ PragTyp_HEXKEY, /* ePragFlg: */ 0, /* ColNames: */ 0, 0, - /* iArg: */ 0 }, + /* iArg: */ 3 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) #if !defined(SQLITE_OMIT_CHECK) @@ -353,12 +351,12 @@ {/* zName: */ "index_info", /* ePragTyp: */ PragTyp_INDEX_INFO, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 12, 3, + /* ColNames: */ 15, 3, /* iArg: */ 0 }, {/* zName: */ "index_list", /* ePragTyp: */ PragTyp_INDEX_LIST, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 21, 5, + /* ColNames: */ 26, 5, /* iArg: */ 0 }, {/* zName: */ "index_xinfo", /* ePragTyp: */ PragTyp_INDEX_INFO, @@ -415,7 +413,7 @@ {/* zName: */ "lock_status", /* ePragTyp: */ PragTyp_LOCK_STATUS, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 50, 2, + /* ColNames: */ 43, 2, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) @@ -441,7 +439,7 @@ {/* zName: */ "module_list", /* ePragTyp: */ PragTyp_MODULE_LIST, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 31, 1, + /* ColNames: */ 9, 1, /* iArg: */ 0 }, #endif #endif @@ -474,7 +472,7 @@ {/* zName: */ "pragma_list", /* ePragTyp: */ PragTyp_PRAGMA_LIST, /* ePragFlg: */ PragFlg_Result0, - /* ColNames: */ 31, 1, + /* ColNames: */ 9, 1, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) @@ -505,10 +503,10 @@ #endif #if defined(SQLITE_HAS_CODEC) {/* zName: */ "rekey", - /* ePragTyp: */ PragTyp_REKEY, + /* ePragTyp: */ PragTyp_KEY, /* ePragFlg: */ 0, /* ColNames: */ 0, 0, - /* iArg: */ 0 }, + /* iArg: */ 1 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) {/* zName: */ "reverse_unordered_selects", @@ -561,7 +559,7 @@ {/* zName: */ "stats", /* ePragTyp: */ PragTyp_STATS, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq, - /* ColNames: */ 7, 5, + /* ColNames: */ 21, 5, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) @@ -575,8 +573,13 @@ {/* zName: */ "table_info", /* ePragTyp: */ PragTyp_TABLE_INFO, /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, - /* ColNames: */ 1, 6, + /* ColNames: */ 8, 6, /* iArg: */ 0 }, + {/* zName: */ "table_xinfo", + /* ePragTyp: */ PragTyp_TABLE_INFO, + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt, + /* ColNames: */ 8, 7, + /* iArg: */ 1 }, #endif #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) {/* zName: */ "temp_store", @@ -590,6 +593,18 @@ /* ColNames: */ 0, 0, /* iArg: */ 0 }, #endif +#if defined(SQLITE_HAS_CODEC) + {/* zName: */ "textkey", + /* ePragTyp: */ PragTyp_KEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 4 }, + {/* zName: */ "textrekey", + /* ePragTyp: */ PragTyp_KEY, + /* ePragFlg: */ 0, + /* ColNames: */ 0, 0, + /* iArg: */ 5 }, +#endif {/* zName: */ "threads", /* ePragTyp: */ PragTyp_THREADS, /* ePragFlg: */ PragFlg_Result0, @@ -640,7 +655,7 @@ {/* zName: */ "wal_checkpoint", /* ePragTyp: */ PragTyp_WAL_CHECKPOINT, /* ePragFlg: */ PragFlg_NeedSchema, - /* ColNames: */ 46, 3, + /* ColNames: */ 38, 3, /* iArg: */ 0 }, #endif #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) @@ -648,7 +663,7 @@ /* ePragTyp: */ PragTyp_FLAG, /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1, /* ColNames: */ 0, 0, - /* iArg: */ SQLITE_WriteSchema }, + /* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError }, #endif }; -/* Number of pragmas: 61 on by default, 78 total. */ +/* Number of pragmas: 62 on by default, 81 total. */
diff --git a/third_party/sqlite/src/src/prepare.c b/third_party/sqlite/src/src/prepare.c index 76a7611..fe098cfa 100644 --- a/third_party/sqlite/src/src/prepare.c +++ b/third_party/sqlite/src/src/prepare.c
@@ -327,8 +327,8 @@ rc = SQLITE_NOMEM_BKPT; sqlite3ResetAllSchemasOfConnection(db); } - if( rc==SQLITE_OK || (db->flags&SQLITE_WriteSchema)){ - /* Black magic: If the SQLITE_WriteSchema flag is set, then consider + if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){ + /* Black magic: If the SQLITE_NoSchemaError flag is set, then consider ** the schema loaded, even if errors occurred. In this situation the ** current sqlite3_prepare() operation will fail, but the following one ** will attempt to compile the supplied statement against whatever subset @@ -709,6 +709,294 @@ return rc; } +#ifdef SQLITE_ENABLE_NORMALIZE +/* +** Checks if the specified token is a table, column, or function name, +** based on the databases associated with the statement being prepared. +** If the function fails, zero is returned and pRc is filled with the +** error code. +*/ +static int shouldTreatAsIdentifier( + sqlite3 *db, /* Database handle. */ + const char *zToken, /* Pointer to start of token to be checked */ + int nToken, /* Length of token to be checked */ + int *pRc /* Pointer to error code upon failure */ +){ + int bFound = 0; /* Non-zero if token is an identifier name. */ + int i, j; /* Database and column loop indexes. */ + Schema *pSchema; /* Schema for current database. */ + Hash *pHash; /* Hash table of tables for current database. */ + HashElem *e; /* Hash element for hash table iteration. */ + Table *pTab; /* Database table for columns being checked. */ + + if( sqlite3IsRowidN(zToken, nToken) ){ + return 1; + } + if( nToken>0 ){ + int hash = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zToken[0]], nToken); + if( sqlite3FunctionSearchN(hash, zToken, nToken) ) return 1; + } + assert( db!=0 ); + sqlite3_mutex_enter(db->mutex); + sqlite3BtreeEnterAll(db); + for(i=0; i<db->nDb; i++){ + pHash = &db->aFunc; + if( sqlite3HashFindN(pHash, zToken, nToken) ){ + bFound = 1; + break; + } + pSchema = db->aDb[i].pSchema; + if( pSchema==0 ) continue; + pHash = &pSchema->tblHash; + if( sqlite3HashFindN(pHash, zToken, nToken) ){ + bFound = 1; + break; + } + for(e=sqliteHashFirst(pHash); e; e=sqliteHashNext(e)){ + pTab = sqliteHashData(e); + if( pTab==0 ) continue; + pHash = pTab->pColHash; + if( pHash==0 ){ + pTab->pColHash = pHash = sqlite3_malloc(sizeof(Hash)); + if( pHash ){ + sqlite3HashInit(pHash); + for(j=0; j<pTab->nCol; j++){ + Column *pCol = &pTab->aCol[j]; + sqlite3HashInsert(pHash, pCol->zName, pCol); + } + }else{ + *pRc = SQLITE_NOMEM_BKPT; + bFound = 0; + goto done; + } + } + if( pHash && sqlite3HashFindN(pHash, zToken, nToken) ){ + bFound = 1; + goto done; + } + } + } +done: + sqlite3BtreeLeaveAll(db); + sqlite3_mutex_leave(db->mutex); + return bFound; +} + +/* +** Attempt to estimate the final output buffer size needed for the fully +** normalized version of the specified SQL string. This should take into +** account any potential expansion that could occur (e.g. via IN clauses +** being expanded, etc). This size returned is the total number of bytes +** including the NUL terminator. +*/ +static int estimateNormalizedSize( + const char *zSql, /* The original SQL string */ + int nSql, /* Length of original SQL string */ + u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */ +){ + int nOut = nSql + 4; + const char *z = zSql; + while( nOut<nSql*5 ){ + while( z[0]!=0 && z[0]!='I' && z[0]!='i' ){ z++; } + if( z[0]==0 ) break; + z++; + if( z[0]!='N' && z[0]!='n' ) break; + z++; + while( sqlite3Isspace(z[0]) ){ z++; } + if( z[0]!='(' ) break; + z++; + nOut += 5; /* ?,?,? */ + } + return nOut; +} + +/* +** Copy the current token into the output buffer while dealing with quoted +** identifiers. By default, all letters will be converted into lowercase. +** If the bUpper flag is set, uppercase will be used. The piOut argument +** will be used to update the target index into the output string. +*/ +static void copyNormalizedToken( + const char *zSql, /* The original SQL string */ + int iIn, /* Current index into the original SQL string */ + int nToken, /* Number of bytes in the current token */ + int tokenFlags, /* Flags returned by the tokenizer */ + char *zOut, /* The output string */ + int *piOut /* Pointer to target index into the output string */ +){ + int bQuoted = tokenFlags & SQLITE_TOKEN_QUOTED; + int bKeyword = tokenFlags & SQLITE_TOKEN_KEYWORD; + int j = *piOut, k = 0; + for(; k<nToken; k++){ + if( bQuoted ){ + if( k==0 && iIn>0 ){ + zOut[j++] = '"'; + continue; + }else if( k==nToken-1 ){ + zOut[j++] = '"'; + continue; + } + } + if( bKeyword ){ + zOut[j++] = sqlite3Toupper(zSql[iIn+k]); + }else{ + zOut[j++] = sqlite3Tolower(zSql[iIn+k]); + } + } + *piOut = j; +} + +/* +** Perform normalization of the SQL contained in the prepared statement and +** store the result in the zNormSql field. The schema for the associated +** databases are consulted while performing the normalization in order to +** determine if a token appears to be an identifier. All identifiers are +** left intact in the normalized SQL and all literals are replaced with a +** single '?'. +*/ +void sqlite3Normalize( + Vdbe *pVdbe, /* VM being reprepared */ + const char *zSql, /* The original SQL string */ + int nSql, /* Size of the input string in bytes */ + u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */ +){ + sqlite3 *db; /* Database handle. */ + char *z; /* The output string */ + int nZ; /* Size of the output string in bytes */ + int i; /* Next character to read from zSql[] */ + int j; /* Next character to fill in on z[] */ + int tokenType = 0; /* Type of the next token */ + int prevTokenType = 0; /* Type of the previous token, except spaces */ + int n; /* Size of the next token */ + int nParen = 0; /* Nesting level of parenthesis */ + Hash inHash; /* Table of parenthesis levels to output index. */ + + db = sqlite3VdbeDb(pVdbe); + assert( db!=0 ); + assert( pVdbe->zNormSql==0 ); + if( zSql==0 ) return; + nZ = estimateNormalizedSize(zSql, nSql, prepFlags); + z = sqlite3DbMallocRawNN(db, nZ); + if( z==0 ) return; + sqlite3HashInit(&inHash); + for(i=j=0; i<nSql && zSql[i]; i+=n){ + int flags = 0; + if( tokenType!=TK_SPACE ) prevTokenType = tokenType; + n = sqlite3GetTokenNormalized((unsigned char*)zSql+i, &tokenType, &flags); + switch( tokenType ){ + case TK_SPACE: { + break; + } + case TK_ILLEGAL: { + sqlite3DbFree(db, z); + sqlite3HashClear(&inHash); + return; + } + case TK_STRING: + case TK_INTEGER: + case TK_FLOAT: + case TK_VARIABLE: + case TK_BLOB: { + z[j++] = '?'; + break; + } + case TK_LP: + case TK_RP: { + if( tokenType==TK_LP ){ + nParen++; + if( prevTokenType==TK_IN ){ + assert( nParen<nSql ); + sqlite3HashInsert(&inHash, zSql+nParen, SQLITE_INT_TO_PTR(j)); + } + }else{ + int jj; + assert( nParen<nSql ); + jj = SQLITE_PTR_TO_INT(sqlite3HashFind(&inHash, zSql+nParen)); + if( jj>0 ){ + sqlite3HashInsert(&inHash, zSql+nParen, 0); + assert( jj+6<nZ ); + memcpy(z+jj+1, "?,?,?", 5); + j = jj+6; + assert( nZ-1-j>=0 ); + assert( nZ-1-j<nZ ); + memset(z+j, 0, nZ-1-j); + } + nParen--; + } + assert( nParen>=0 ); + /* Fall through */ + } + case TK_MINUS: + case TK_SEMI: + case TK_PLUS: + case TK_STAR: + case TK_SLASH: + case TK_REM: + case TK_EQ: + case TK_LE: + case TK_NE: + case TK_LSHIFT: + case TK_LT: + case TK_RSHIFT: + case TK_GT: + case TK_GE: + case TK_BITOR: + case TK_CONCAT: + case TK_COMMA: + case TK_BITAND: + case TK_BITNOT: + case TK_DOT: + case TK_IN: + case TK_IS: + case TK_NOT: + case TK_NULL: + case TK_ID: { + if( tokenType==TK_NULL ){ + if( prevTokenType==TK_IS || prevTokenType==TK_NOT ){ + /* NULL is a keyword in this case, not a literal value */ + }else{ + /* Here the NULL is a literal value */ + z[j++] = '?'; + break; + } + } + if( j>0 && sqlite3IsIdChar(z[j-1]) && sqlite3IsIdChar(zSql[i]) ){ + z[j++] = ' '; + } + if( tokenType==TK_ID ){ + int i2 = i, n2 = n, rc = SQLITE_OK; + if( nParen>0 ){ + assert( nParen<nSql ); + sqlite3HashInsert(&inHash, zSql+nParen, 0); + } + if( flags&SQLITE_TOKEN_QUOTED ){ i2++; n2-=2; } + if( shouldTreatAsIdentifier(db, zSql+i2, n2, &rc)==0 ){ + if( rc!=SQLITE_OK ){ + sqlite3DbFree(db, z); + sqlite3HashClear(&inHash); + return; + } + if( sqlite3_keyword_check(zSql+i2, n2)==0 ){ + z[j++] = '?'; + break; + } + } + } + copyNormalizedToken(zSql, i, n, flags, z, &j); + break; + } + } + } + assert( j<nZ && "one" ); + while( j>0 && z[j-1]==' ' ){ j--; } + if( j>0 && z[j-1]!=';' ){ z[j++] = ';'; } + z[j] = 0; + assert( j<nZ && "two" ); + pVdbe->zNormSql = z; + sqlite3HashClear(&inHash); +} +#endif /* SQLITE_ENABLE_NORMALIZE */ + /* ** Rerun the compilation of a statement after a schema change. **
diff --git a/third_party/sqlite/src/src/resolve.c b/third_party/sqlite/src/src/resolve.c index 090a4b0..9d03e07 100644 --- a/third_party/sqlite/src/src/resolve.c +++ b/third_party/sqlite/src/src/resolve.c
@@ -159,7 +159,7 @@ ** (even if X is implied). ** pExpr->iTable Set to the cursor number for the table obtained ** from pSrcList. -** pExpr->pTab Points to the Table structure of X.Y (even if +** pExpr->y.pTab Points to the Table structure of X.Y (even if ** X and/or Y are implied.) ** pExpr->iColumn Set to the column number within the table. ** pExpr->op Set to TK_COLUMN. @@ -203,7 +203,6 @@ /* Initialize the node to no-match */ pExpr->iTable = -1; - pExpr->pTab = 0; ExprSetVVAProperty(pExpr, EP_NoReduce); /* Translate the schema name in zDb into a pointer to the corresponding @@ -265,7 +264,7 @@ continue; } if( IN_RENAME_OBJECT && pItem->zAlias ){ - sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->pTab); + sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab); } } if( 0==(cntTab++) ){ @@ -291,13 +290,13 @@ } if( pMatch ){ pExpr->iTable = pMatch->iCursor; - pExpr->pTab = pMatch->pTab; + pExpr->y.pTab = pMatch->pTab; /* RIGHT JOIN not (yet) supported */ assert( (pMatch->fg.jointype & JT_RIGHT)==0 ); if( (pMatch->fg.jointype & JT_LEFT)!=0 ){ ExprSetProperty(pExpr, EP_CanBeNull); } - pSchema = pExpr->pTab->pSchema; + pSchema = pExpr->y.pTab->pSchema; } } /* if( pSrcList ) */ @@ -354,7 +353,7 @@ testcase( iCol==(-1) ); if( IN_RENAME_OBJECT ){ pExpr->iColumn = iCol; - pExpr->pTab = pTab; + pExpr->y.pTab = pTab; eNewExprOp = TK_COLUMN; }else{ pExpr->iTable = pNC->uNC.pUpsert->regData + iCol; @@ -376,7 +375,7 @@ testcase( iCol==32 ); pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol)); } - pExpr->pTab = pTab; + pExpr->y.pTab = pTab; pExpr->iColumn = (i16)iCol; eNewExprOp = TK_TRIGGER; #endif /* SQLITE_OMIT_TRIGGER */ @@ -476,7 +475,7 @@ assert( pExpr->op==TK_ID ); if( ExprHasProperty(pExpr,EP_DblQuoted) ){ pExpr->op = TK_STRING; - pExpr->pTab = 0; + pExpr->y.pTab = 0; return WRC_Prune; } if( sqlite3ExprIdToTrueFalse(pExpr) ){ @@ -554,9 +553,9 @@ Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0); if( p ){ struct SrcList_item *pItem = &pSrc->a[iSrc]; - p->pTab = pItem->pTab; + p->y.pTab = pItem->pTab; p->iTable = pItem->iCursor; - if( p->pTab->iPKey==iCol ){ + if( p->y.pTab->iPKey==iCol ){ p->iColumn = -1; }else{ p->iColumn = (ynVar)iCol; @@ -646,7 +645,7 @@ pItem = pSrcList->a; assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 ); pExpr->op = TK_COLUMN; - pExpr->pTab = pItem->pTab; + pExpr->y.pTab = pItem->pTab; pExpr->iTable = pItem->iCursor; pExpr->iColumn = -1; pExpr->affinity = SQLITE_AFF_INTEGER; @@ -690,9 +689,7 @@ zColumn = pRight->u.zToken; if( IN_RENAME_OBJECT ){ sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight); - } - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenRemap(pParse, (void*)&pExpr->pTab, (void*)pLeft); + sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft); } } return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); @@ -774,6 +771,15 @@ notValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr|NC_PartIdx); } + if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0 + && pParse->nested==0 + && sqlite3Config.bInternalFunctions==0 + ){ + /* Internal-use-only functions are disallowed unless the + ** SQL is being compiled using sqlite3NestedParse() */ + no_such_func = 1; + pDef = 0; + } } if( 0==IN_RENAME_OBJECT ){ @@ -782,18 +788,18 @@ || (pDef->xValue==0 && pDef->xInverse==0) || (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize) ); - if( pDef && pDef->xValue==0 && pExpr->pWin ){ + if( pDef && pDef->xValue==0 && ExprHasProperty(pExpr, EP_WinFunc) ){ sqlite3ErrorMsg(pParse, "%.*s() may not be used as a window function", nId, zId ); pNC->nErr++; }else if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) - || (is_agg && (pDef->funcFlags & SQLITE_FUNC_WINDOW) && !pExpr->pWin) - || (is_agg && pExpr->pWin && (pNC->ncFlags & NC_AllowWin)==0) + || (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pExpr->y.pWin) + || (is_agg && pExpr->y.pWin && (pNC->ncFlags & NC_AllowWin)==0) ){ const char *zType; - if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->pWin ){ + if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->y.pWin ){ zType = "window"; }else{ zType = "aggregate"; @@ -823,7 +829,7 @@ } if( is_agg ){ #ifndef SQLITE_OMIT_WINDOWFUNC - pNC->ncFlags &= ~(pExpr->pWin ? NC_AllowWin : NC_AllowAgg); + pNC->ncFlags &= ~(pExpr->y.pWin ? NC_AllowWin : NC_AllowAgg); #else pNC->ncFlags &= ~NC_AllowAgg; #endif @@ -832,17 +838,17 @@ sqlite3WalkExprList(pWalker, pList); if( is_agg ){ #ifndef SQLITE_OMIT_WINDOWFUNC - if( pExpr->pWin ){ + if( pExpr->y.pWin ){ Select *pSel = pNC->pWinSelect; - sqlite3WalkExprList(pWalker, pExpr->pWin->pPartition); - sqlite3WalkExprList(pWalker, pExpr->pWin->pOrderBy); - sqlite3WalkExpr(pWalker, pExpr->pWin->pFilter); - sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->pWin, pDef); + sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition); + sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy); + sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter); + sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef); if( 0==pSel->pWin - || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->pWin) + || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin) ){ - pExpr->pWin->pNextWin = pSel->pWin; - pSel->pWin = pExpr->pWin; + pExpr->y.pWin->pNextWin = pSel->pWin; + pSel->pWin = pExpr->y.pWin; } pNC->ncFlags |= NC_AllowWin; }else @@ -1265,13 +1271,13 @@ for(j=0; j<pSelect->pEList->nExpr; j++){ if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ #ifndef SQLITE_OMIT_WINDOWFUNC - if( pE->pWin ){ + if( ExprHasProperty(pE, EP_WinFunc) ){ /* Since this window function is being changed into a reference ** to the same window function the result set, remove the instance ** of this window function from the Select.pWin list. */ Window **pp; for(pp=&pSelect->pWin; *pp; pp=&(*pp)->pNextWin){ - if( *pp==pE->pWin ){ + if( *pp==pE->y.pWin ){ *pp = (*pp)->pNextWin; } }
diff --git a/third_party/sqlite/src/src/select.c b/third_party/sqlite/src/src/select.c index db1c896c..870c3b5 100644 --- a/third_party/sqlite/src/src/select.c +++ b/third_party/sqlite/src/src/select.c
@@ -803,7 +803,7 @@ struct ExprList_item *pItem = &pEList->a[i]; if( pItem->u.x.iOrderByCol==0 ){ Expr *pExpr = pItem->pExpr; - Table *pTab = pExpr->pTab; + Table *pTab = pExpr->y.pTab; if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab) && (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF) ){ @@ -826,12 +826,12 @@ Expr *pNew = sqlite3PExpr(pParse, TK_COLUMN, 0, 0); if( pNew ){ pNew->iTable = pExpr->iTable; - pNew->pTab = pExpr->pTab; + pNew->y.pTab = pExpr->y.pTab; pNew->iColumn = pPk ? pPk->aiColumn[k] : -1; pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew); } } - pSort->aDefer[nDefer].pTab = pExpr->pTab; + pSort->aDefer[nDefer].pTab = pExpr->y.pTab; pSort->aDefer[nDefer].iCsr = pExpr->iTable; pSort->aDefer[nDefer].nKey = nKey; nDefer++; @@ -1680,7 +1680,7 @@ break; } - assert( pTab && pExpr->pTab==pTab ); + assert( pTab && pExpr->y.pTab==pTab ); if( pS ){ /* The "table" is actually a sub-select or a view in the FROM clause ** of the SELECT statement. Return the declaration type and origin @@ -1865,7 +1865,7 @@ assert( p!=0 ); assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */ - assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering idx not yet coded */ + assert( p->op!=TK_COLUMN || p->y.pTab!=0 ); /* Covering idx not yet coded */ if( pEList->a[i].zName ){ /* An AS clause always takes first priority */ char *zName = pEList->a[i].zName; @@ -1873,7 +1873,7 @@ }else if( srcName && p->op==TK_COLUMN ){ char *zCol; int iCol = p->iColumn; - pTab = p->pTab; + pTab = p->y.pTab; assert( pTab!=0 ); if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) ); @@ -1964,7 +1964,7 @@ if( pColExpr->op==TK_COLUMN ){ /* For columns use the column name name */ int iCol = pColExpr->iColumn; - Table *pTab = pColExpr->pTab; + Table *pTab = pColExpr->y.pTab; assert( pTab!=0 ); if( iCol<0 ) iCol = pTab->iPKey; zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
diff --git a/third_party/sqlite/src/src/shell.c.in b/third_party/sqlite/src/src/shell.c.in index 28d3d82a..b13551d 100644 --- a/third_party/sqlite/src/src/shell.c.in +++ b/third_party/sqlite/src/src/shell.c.in
@@ -1059,11 +1059,12 @@ /* Allowed values for ShellState.openMode */ -#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */ -#define SHELL_OPEN_NORMAL 1 /* Normal database file */ -#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */ -#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */ -#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */ +#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */ +#define SHELL_OPEN_NORMAL 1 /* Normal database file */ +#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */ +#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */ +#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */ +#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */ /* ** These are the allowed shellFlgs values @@ -1273,7 +1274,7 @@ if( bBin ){ sqlite3_result_blob64(context, p, sz, sqlite3_free); }else{ - int i, j; + sqlite3_int64 i, j; if( hasCRNL ){ /* If the original contains \r\n then do no conversions back to \n */ j = sz; @@ -3335,137 +3336,238 @@ } /* -** Text of a help message +** Text of help messages. +** +** The help text for each individual command begins with a line that starts +** with ".". Subsequent lines are supplimental information. +** +** There must be two or more spaces between the end of the command and the +** start of the description of what that command does. */ -static char zHelp[] = +static const char *(azHelp[]) = { #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE) - ".archive ... Manage SQL archives: \".archive --help\" for details\n" + ".archive ... Manage SQL archives", + " Each command must have exactly one of the following options:", + " -c, --create Create a new archive", + " -u, --update Update or add files to an existing archive", + " -t, --list List contents of archive", + " -x, --extract Extract files from archive", + " Optional arguments:", + " -v, --verbose Print each filename as it is processed", + " -f FILE, --file FILE Operate on archive FILE (default is current db)", + " -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS", + " -C DIR, --directory DIR Change to directory DIR to read/extract files", + " -n, --dryrun Show the SQL that would have occurred", + " Examples:", + " .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar", + " .ar -tf archive.sar # List members of archive.sar", + " .ar -xvf archive.sar # Verbosely extract files from archive.sar", + " See also:", + " http://sqlite.org/cli.html#sqlar_archive_support", #endif #ifndef SQLITE_OMIT_AUTHORIZATION - ".auth ON|OFF Show authorizer callbacks\n" + ".auth ON|OFF Show authorizer callbacks", #endif - ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" - " Add \"--append\" to open using appendvfs.\n" - ".bail on|off Stop after hitting an error. Default OFF\n" - ".binary on|off Turn binary output on or off. Default OFF\n" - ".cd DIRECTORY Change the working directory to DIRECTORY\n" - ".changes on|off Show number of rows changed by SQL\n" - ".check GLOB Fail if output since .testcase does not match\n" - ".clone NEWDB Clone data into NEWDB from the existing database\n" - ".databases List names and files of attached databases\n" - ".dbconfig ?op? ?val? List or change sqlite3_db_config() options\n" - ".dbinfo ?DB? Show status information about the database\n" - ".dump ?TABLE? ... Dump the database in an SQL text format\n" - " If TABLE specified, only dump tables matching\n" - " LIKE pattern TABLE.\n" - ".echo on|off Turn command echo on or off\n" - ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN\n" - ".excel Display the output of next command in a spreadsheet\n" - ".exit Exit this program\n" - ".expert EXPERIMENTAL. Suggest indexes for specified queries\n" + ".backup ?DB? FILE Backup DB (default \"main\") to FILE", + " --append Use the appendvfs", + ".bail on|off Stop after hitting an error. Default OFF", + ".binary on|off Turn binary output on or off. Default OFF", + ".cd DIRECTORY Change the working directory to DIRECTORY", + ".changes on|off Show number of rows changed by SQL", + ".check GLOB Fail if output since .testcase does not match", + ".clone NEWDB Clone data into NEWDB from the existing database", + ".databases List names and files of attached databases", + ".dbconfig ?op? ?val? List or change sqlite3_db_config() options", + ".dbinfo ?DB? Show status information about the database", + ".dump ?TABLE? ... Render all database content as SQL", + " Options:", + " --preserve-rowids Include ROWID values in the output", + " --newlines Allow unescaped newline characters in output", + " TABLE is LIKE pattern for the tables to dump", + ".echo on|off Turn command echo on or off", + ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN", + ".excel Display the output of next command in a spreadsheet", + ".exit ?CODE? Exit this program with return-code CODE", + ".expert EXPERIMENTAL. Suggest indexes for specified queries", /* Because explain mode comes on automatically now, the ".explain" mode ** is removed from the help screen. It is still supported for legacy, however */ -/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"*/ - ".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n" - ".headers on|off Turn display of headers on or off\n" - ".help Show this message\n" - ".import FILE TABLE Import data from FILE into TABLE\n" +/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic",*/ + ".fullschema ?--indent? Show schema and the content of sqlite_stat tables", + ".headers on|off Turn display of headers on or off", + ".help ?-all? ?PATTERN? Show help text for PATTERN", + ".import FILE TABLE Import data from FILE into TABLE", #ifndef SQLITE_OMIT_TEST_CONTROL - ".imposter INDEX TABLE Create imposter table TABLE on index INDEX\n" + ".imposter INDEX TABLE Create imposter table TABLE on index INDEX", #endif - ".indexes ?TABLE? Show names of all indexes\n" - " If TABLE specified, only show indexes for tables\n" - " matching LIKE pattern TABLE.\n" + ".indexes ?TABLE? Show names of indexes", + " If TABLE is specified, only show indexes for", + " tables matching TABLE using the LIKE operator.", #ifdef SQLITE_ENABLE_IOTRACE - ".iotrace FILE Enable I/O diagnostic logging to FILE\n" + ".iotrace FILE Enable I/O diagnostic logging to FILE", #endif - ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n" - ".lint OPTIONS Report potential schema issues. Options:\n" - " fkey-indexes Find missing foreign key indexes\n" + ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT", + ".lint OPTIONS Report potential schema issues.", + " Options:", + " fkey-indexes Find missing foreign key indexes", #ifndef SQLITE_OMIT_LOAD_EXTENSION - ".load FILE ?ENTRY? Load an extension library\n" + ".load FILE ?ENTRY? Load an extension library", #endif - ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n" - ".mode MODE ?TABLE? Set output mode where MODE is one of:\n" - " ascii Columns/rows delimited by 0x1F and 0x1E\n" - " csv Comma-separated values\n" - " column Left-aligned columns. (See .width)\n" - " html HTML <table> code\n" - " insert SQL insert statements for TABLE\n" - " line One value per line\n" - " list Values delimited by \"|\"\n" - " quote Escape answers as for SQL\n" - " tabs Tab-separated values\n" - " tcl TCL list elements\n" - ".nullvalue STRING Use STRING in place of NULL values\n" - ".once (-e|-x|FILE) Output for the next SQL command only to FILE\n" - " or invoke system text editor (-e) or spreadsheet (-x)\n" - " on the output.\n" - ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n" - " The --new option starts with an empty file\n" - " Other options: --readonly --append --zip\n" - ".output ?FILE? Send output to FILE or stdout\n" - ".print STRING... Print literal STRING\n" - ".prompt MAIN CONTINUE Replace the standard prompts\n" - ".quit Exit this program\n" - ".read FILENAME Execute SQL in FILENAME\n" - ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" - ".save FILE Write in-memory database into FILE\n" - ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n" - ".schema ?PATTERN? Show the CREATE statements matching PATTERN\n" - " Add --indent for pretty-printing\n" - ".selftest ?--init? Run tests defined in the SELFTEST table\n" - ".separator COL ?ROW? Change the column separator and optionally the row\n" - " separator for both the output mode and .import\n" + ".log FILE|off Turn logging on or off. FILE can be stderr/stdout", + ".mode MODE ?TABLE? Set output mode", + " MODE is one of:", + " ascii Columns/rows delimited by 0x1F and 0x1E", + " csv Comma-separated values", + " column Left-aligned columns. (See .width)", + " html HTML <table> code", + " insert SQL insert statements for TABLE", + " line One value per line", + " list Values delimited by \"|\"", + " quote Escape answers as for SQL", + " tabs Tab-separated values", + " tcl TCL list elements", + ".nullvalue STRING Use STRING in place of NULL values", + ".once (-e|-x|FILE) Output for the next SQL command only to FILE", + " If FILE begins with '|' then open as a pipe", + " Other options:", + " -e Invoke system text editor", + " -x Open in a spreadsheet", + ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE", + " Options:", + " --append Use appendvfs to append database to the end of FILE", +#ifdef SQLITE_ENABLE_DESERIALIZE + " --deserialize Load into memory useing sqlite3_deserialize()", +#endif + " --new Initialize FILE to an empty database", + " --readonly Open FILE readonly", + " --zip FILE is a ZIP archive", + ".output ?FILE? Send output to FILE or stdout if FILE is omitted", + " If FILE begins with '|' then open it as a pipe.", + ".print STRING... Print literal STRING", + ".prompt MAIN CONTINUE Replace the standard prompts", + ".quit Exit this program", + ".read FILE Read input from FILE", + ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE", + ".save FILE Write in-memory database into FILE", + ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off", + ".schema ?PATTERN? Show the CREATE statements matching PATTERN", + " Options:", + " --indent Try to pretty-print the schema", + ".selftest ?OPTIONS? Run tests defined in the SELFTEST table", + " Options:", + " --init Create a new SELFTEST table", + " -v Verbose output", + ".separator COL ?ROW? Change the column and row separators", #if defined(SQLITE_ENABLE_SESSION) - ".session CMD ... Create or control sessions\n" + ".session ?NAME? CMD ... Create or control sessions", + " Subcommands:", + " attach TABLE Attach TABLE", + " changeset FILE Write a changeset into FILE", + " close Close one session", + " enable ?BOOLEAN? Set or query the enable bit", + " filter GLOB... Reject tables matching GLOBs", + " indirect ?BOOLEAN? Mark or query the indirect status", + " isempty Query whether the session is empty", + " list List currently open session names", + " open DB NAME Open a new session on DB", + " patchset FILE Write a patchset into FILE", + " If ?NAME? is omitted, the first defined session is used.", #endif - ".sha3sum ?OPTIONS...? Compute a SHA3 hash of database content\n" + ".sha3sum ... Compute a SHA3 hash of database content", + " Options:", + " --schema Also hash the sqlite_master table", + " --sha3-224 Use the sha3-224 algorithm", + " --sha3-256 Use the sha3-256 algorithm. This is the default.", + " --sha3-384 Use the sha3-384 algorithm", + " --sha3-512 Use the sha3-512 algorithm", + " Any other argument is a LIKE pattern for tables to hash", #ifndef SQLITE_NOHAVE_SYSTEM - ".shell CMD ARGS... Run CMD ARGS... in a system shell\n" + ".shell CMD ARGS... Run CMD ARGS... in a system shell", #endif - ".show Show the current values for various settings\n" - ".stats ?on|off? Show stats or turn stats on or off\n" + ".show Show the current values for various settings", + ".stats ?on|off? Show stats or turn stats on or off", #ifndef SQLITE_NOHAVE_SYSTEM - ".system CMD ARGS... Run CMD ARGS... in a system shell\n" + ".system CMD ARGS... Run CMD ARGS... in a system shell", #endif - ".tables ?TABLE? List names of tables\n" - " If TABLE specified, only list tables matching\n" - " LIKE pattern TABLE.\n" - ".testcase NAME Begin redirecting output to 'testcase-out.txt'\n" - ".timeout MS Try opening locked tables for MS milliseconds\n" - ".timer on|off Turn SQL timer on or off\n" - ".trace FILE|off Output each SQL statement as it is run\n" - ".vfsinfo ?AUX? Information about the top-level VFS\n" - ".vfslist List all available VFSes\n" - ".vfsname ?AUX? Print the name of the VFS stack\n" - ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" - " Negative values right-justify\n" -; + ".tables ?TABLE? List names of tables matching LIKE pattern TABLE", + ".testcase NAME Begin redirecting output to 'testcase-out.txt'", + ".timeout MS Try opening locked tables for MS milliseconds", + ".timer on|off Turn SQL timer on or off", + ".trace FILE|off Output each SQL statement as it is run", + ".vfsinfo ?AUX? Information about the top-level VFS", + ".vfslist List all available VFSes", + ".vfsname ?AUX? Print the name of the VFS stack", + ".width NUM1 NUM2 ... Set column widths for \"column\" mode", + " Negative values right-justify", +}; -#if defined(SQLITE_ENABLE_SESSION) /* -** Print help information for the ".sessions" command +** Output help text. +** +** zPattern describes the set of commands for which help text is provided. +** If zPattern is NULL, then show all commands, but only give a one-line +** description of each. +** +** Return the number of matches. */ -void session_help(ShellState *p){ - raw_printf(p->out, - ".session ?NAME? SUBCOMMAND ?ARGS...?\n" - "If ?NAME? is omitted, the first defined session is used.\n" - "Subcommands:\n" - " attach TABLE Attach TABLE\n" - " changeset FILE Write a changeset into FILE\n" - " close Close one session\n" - " enable ?BOOLEAN? Set or query the enable bit\n" - " filter GLOB... Reject tables matching GLOBs\n" - " indirect ?BOOLEAN? Mark or query the indirect status\n" - " isempty Query whether the session is empty\n" - " list List currently open session names\n" - " open DB NAME Open a new session on DB\n" - " patchset FILE Write a patchset into FILE\n" - ); +static int showHelp(FILE *out, const char *zPattern){ + int i = 0; + int j = 0; + int n = 0; + char *zPat; + if( zPattern==0 + || zPattern[0]=='0' + || strcmp(zPattern,"-a")==0 + || strcmp(zPattern,"-all")==0 + ){ + /* Show all commands, but only one line per command */ + if( zPattern==0 ) zPattern = ""; + for(i=0; i<ArraySize(azHelp); i++){ + if( azHelp[i][0]=='.' || zPattern[0] ){ + utf8_printf(out, "%s\n", azHelp[i]); + n++; + } + } + }else{ + /* Look for commands that for which zPattern is an exact prefix */ + zPat = sqlite3_mprintf(".%s*", zPattern); + for(i=0; i<ArraySize(azHelp); i++){ + if( sqlite3_strglob(zPat, azHelp[i])==0 ){ + utf8_printf(out, "%s\n", azHelp[i]); + j = i+1; + n++; + } + } + sqlite3_free(zPat); + if( n ){ + if( n==1 ){ + /* when zPattern is a prefix of exactly one command, then include the + ** details of that command, which should begin at offset j */ + while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){ + utf8_printf(out, "%s\n", azHelp[j]); + j++; + } + } + return n; + } + /* Look for commands that contain zPattern anywhere. Show the complete + ** text of all commands that match. */ + zPat = sqlite3_mprintf("%%%s%%", zPattern); + for(i=0; i<ArraySize(azHelp); i++){ + if( azHelp[i][0]=='.' ) j = i; + if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){ + utf8_printf(out, "%s\n", azHelp[j]); + while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){ + j++; + utf8_printf(out, "%s\n", azHelp[j]); + } + i = j; + n++; + } + } + sqlite3_free(zPat); + } + return n; } -#endif - /* Forward reference */ static int process_input(ShellState *p, FILE *in); @@ -3495,7 +3597,7 @@ nIn = ftell(in); rewind(in); pBuf = sqlite3_malloc64( nIn+1 ); - if( pBuf==0 ) return 0; + if( pBuf==0 ){ fclose(in); return 0; } nRead = fread(pBuf, nIn, 1, in); fclose(in); if( nRead!=1 ){ @@ -3575,6 +3677,11 @@ return SHELL_OPEN_NORMAL; } } + n = fread(zBuf, 16, 1, f); + if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){ + fclose(f); + return SHELL_OPEN_NORMAL; + } fseek(f, -25, SEEK_END); n = fread(zBuf, 25, 1, f); if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){ @@ -3626,6 +3733,10 @@ SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs"); break; } + case SHELL_OPEN_DESERIALIZE: { + sqlite3_open(0, &p->db); + break; + } case SHELL_OPEN_ZIPFILE: { sqlite3_open(":memory:", &p->db); break; @@ -3675,6 +3786,18 @@ sqlite3_exec(p->db, zSql, 0, 0, 0); sqlite3_free(zSql); } +#ifdef SQLITE_ENABLE_DESERIALIZE + else if( p->openMode==SHELL_OPEN_DESERIALIZE ){ + int nData = 0; + unsigned char *aData = (unsigned char*)readFile(p->zDbFilename, &nData); + int rc = sqlite3_deserialize(p->db, "main", aData, nData, nData, + SQLITE_DESERIALIZE_RESIZEABLE | + SQLITE_DESERIALIZE_FREEONCLOSE); + if( rc ){ + utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc); + } + } +#endif } } @@ -4879,6 +5002,7 @@ char *z; va_start(ap, zFmt); z = sqlite3_vmprintf(zFmt, ap); + va_end(ap); if( z==0 ){ *pRc = SQLITE_NOMEM; }else{ @@ -4941,32 +5065,7 @@ ** Print a usage message for the .ar command to stderr and return SQLITE_ERROR. */ static int arUsage(FILE *f){ - raw_printf(f, -"\n" -"Usage: .ar [OPTION...] [FILE...]\n" -"The .ar command manages sqlar archives.\n" -"\n" -"Examples:\n" -" .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar\n" -" .ar -tf archive.sar # List members of archive.sar\n" -" .ar -xvf archive.sar # Verbosely extract files from archive.sar\n" -"\n" -"Each command line must feature exactly one command option:\n" -" -c, --create Create a new archive\n" -" -u, --update Update or add files to an existing archive\n" -" -t, --list List contents of archive\n" -" -x, --extract Extract files from archive\n" -"\n" -"And zero or more optional options:\n" -" -v, --verbose Print each filename as it is processed\n" -" -f FILE, --file FILE Operate on archive FILE (default is current db)\n" -" -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS\n" -" -C DIR, --directory DIR Change to directory DIR to read/extract files\n" -" -n, --dryrun Show the SQL that would have occurred\n" -"\n" -"See also: http://sqlite.org/cli.html#sqlar_archive_support\n" -"\n" -); + showHelp(f,"archive"); return SQLITE_ERROR; } @@ -5073,6 +5172,7 @@ struct ArSwitch *pEnd = &aSwitch[nSwitch]; if( nArg<=1 ){ + utf8_printf(stderr, "Wrong number of arguments. Usage:\n"); return arUsage(stderr); }else{ char *z = azArg[1]; @@ -5844,7 +5944,10 @@ }else if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){ - static const struct DbConfigChoices {const char *zName; int op;} aDbConfig[] = { + static const struct DbConfigChoices { + const char *zName; + int op; + } aDbConfig[] = { { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY }, { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER }, { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, @@ -5853,6 +5956,7 @@ { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG }, { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP }, { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE }, + { "defensive", SQLITE_DBCONFIG_DEFENSIVE }, }; int ii, v; open_db(p, 0); @@ -6091,7 +6195,14 @@ }else if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ - utf8_printf(p->out, "%s", zHelp); + if( nArg>=2 ){ + n = showHelp(p->out, azArg[1]); + if( n==0 ){ + utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]); + } + }else{ + showHelp(p->out, 0); + } }else if( c=='i' && strncmp(azArg[0], "import", n)==0 ){ @@ -6568,6 +6679,10 @@ p->openMode = SHELL_OPEN_APPENDVFS; }else if( optionMatch(z, "readonly") ){ p->openMode = SHELL_OPEN_READONLY; +#ifdef SQLITE_ENABLE_DESERIALIZE + }else if( optionMatch(z, "deserialize") ){ + p->openMode = SHELL_OPEN_DESERIALIZE; +#endif }else if( z[0]=='-' ){ utf8_printf(stderr, "unknown option: %s\n", z); rc = 1; @@ -7095,7 +7210,7 @@ }else /* If no command name matches, show a syntax error */ session_syntax_error: - session_help(p); + showHelp(p->out, "session"); }else #endif @@ -7562,6 +7677,7 @@ { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" }, /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */ { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"}, + { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" }, { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" }, { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" }, { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" }, @@ -7656,6 +7772,7 @@ /* sqlite3_test_control(int, int) */ case SQLITE_TESTCTRL_ASSERT: case SQLITE_TESTCTRL_ALWAYS: + case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: if( nArg==3 ){ int opt = booleanValue(azArg[2]); rc2 = sqlite3_test_control(testctrl, opt); @@ -7950,7 +8067,7 @@ ** user-friendly, but it does seem to work. */ #ifdef SQLITE_OMIT_COMPLETE -int sqlite3_complete(const char *zSql){ return 1; } +#define sqlite3_complete(x) 1 #endif /* @@ -8546,6 +8663,10 @@ #endif }else if( strcmp(z,"-append")==0 ){ data.openMode = SHELL_OPEN_APPENDVFS; +#ifdef SQLITE_ENABLE_DESERIALIZE + }else if( strcmp(z,"-deserialize")==0 ){ + data.openMode = SHELL_OPEN_DESERIALIZE; +#endif }else if( strcmp(z,"-readonly")==0 ){ data.openMode = SHELL_OPEN_READONLY; #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) @@ -8641,6 +8762,10 @@ #endif }else if( strcmp(z,"-append")==0 ){ data.openMode = SHELL_OPEN_APPENDVFS; +#ifdef SQLITE_ENABLE_DESERIALIZE + }else if( strcmp(z,"-deserialize")==0 ){ + data.openMode = SHELL_OPEN_DESERIALIZE; +#endif }else if( strcmp(z,"-readonly")==0 ){ data.openMode = SHELL_OPEN_READONLY; }else if( strcmp(z,"-ascii")==0 ){ @@ -8785,7 +8910,7 @@ */ if( stdin_is_interactive ){ char *zHome; - char *zHistory = 0; + char *zHistory; int nHistory; printf( "SQLite version %s %.19s\n" /*extra-version-info*/ @@ -8798,8 +8923,10 @@ printf(".\nUse \".open FILENAME\" to reopen on a " "persistent database.\n"); } - zHome = find_home_dir(0); - if( zHome ){ + zHistory = getenv("SQLITE_HISTORY"); + if( zHistory ){ + zHistory = strdup(zHistory); + }else if( (zHome = find_home_dir(0))!=0 ){ nHistory = strlen30(zHome) + 20; if( (zHistory = malloc(nHistory))!=0 ){ sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
diff --git a/third_party/sqlite/src/src/sqlite.h.in b/third_party/sqlite/src/src/sqlite.h.in index 620f10e6..11622a4 100644 --- a/third_party/sqlite/src/src/sqlite.h.in +++ b/third_party/sqlite/src/src/sqlite.h.in
@@ -2017,6 +2017,7 @@ ** is invoked. ** ** <dl> +** [[SQLITE_DBCONFIG_LOOKASIDE]] ** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt> ** <dd> ^This option takes three additional arguments that determine the ** [lookaside memory allocator] configuration for the [database connection]. @@ -2039,6 +2040,7 @@ ** memory is in use leaves the configuration unchanged and returns ** [SQLITE_BUSY].)^</dd> ** +** [[SQLITE_DBCONFIG_ENABLE_FKEY]] ** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt> ** <dd> ^This option is used to enable or disable the enforcement of ** [foreign key constraints]. There should be two additional arguments. @@ -2049,6 +2051,7 @@ ** following this call. The second parameter may be a NULL pointer, in ** which case the FK enforcement setting is not reported back. </dd> ** +** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]] ** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt> ** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers]. ** There should be two additional arguments. @@ -2059,6 +2062,7 @@ ** following this call. The second parameter may be a NULL pointer, in ** which case the trigger setting is not reported back. </dd> ** +** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] ** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt> ** <dd> ^This option is used to enable or disable the two-argument ** version of the [fts3_tokenizer()] function which is part of the @@ -2072,6 +2076,7 @@ ** following this call. The second parameter may be a NULL pointer, in ** which case the new setting is not reported back. </dd> ** +** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]] ** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt> ** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()] ** interface independently of the [load_extension()] SQL function. @@ -2089,7 +2094,7 @@ ** be a NULL pointer, in which case the new setting is not reported back. ** </dd> ** -** <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> +** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt> ** <dd> ^This option is used to change the name of the "main" database ** schema. ^The sole argument is a pointer to a constant UTF8 string ** which will become the new schema name in place of "main". ^SQLite @@ -2098,6 +2103,7 @@ ** until after the database connection closes. ** </dd> ** +** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]] ** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt> ** <dd> Usually, when a database in wal mode is closed or detached from a ** database handle, SQLite checks if this will mean that there are now no @@ -2111,7 +2117,7 @@ ** have been disabled - 0 if they are not disabled, 1 if they are. ** </dd> ** -** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> +** [[SQLITE_DBCONFIG_ENABLE_QPSG]] <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt> ** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates ** the [query planner stability guarantee] (QPSG). When the QPSG is active, ** a single SQL query statement will always use the same algorithm regardless @@ -2127,7 +2133,7 @@ ** following this call. ** </dd> ** -** <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt> +** [[SQLITE_DBCONFIG_TRIGGER_EQP]] <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt> ** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not ** include output for any operations performed by trigger programs. This ** option is used to set or clear (the default) a flag that governs this @@ -2139,7 +2145,7 @@ ** it is not disabled, 1 if it is. ** </dd> ** -** <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt> +** [[SQLITE_DBCONFIG_RESET_DATABASE]] <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt> ** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run ** [VACUUM] in order to reset a database back to an empty database ** with no schema and no content. The following process works even for @@ -2158,6 +2164,18 @@ ** Because resetting a database is destructive and irreversible, the ** process requires the use of this obscure API and multiple steps to help ** ensure that it does not happen by accident. +** +** [[SQLITE_DBCONFIG_DEFENSIVE]] <dt>SQLITE_DBCONFIG_DEFENSIVE</dt> +** <dd>The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the +** "defensive" flag for a database connection. When the defensive +** flag is enabled, language features that allow ordinary SQL to +** deliberately corrupt the database file are disabled. The disabled +** features include but are not limited to the following: +** <ul> +** <li> The [PRAGMA writable_schema=ON] statement. +** <li> Writes to the [sqlite_dbpage] virtual table. +** <li> Direct writes to [shadow tables]. +** </ul> ** </dd> ** </dl> */ @@ -2171,7 +2189,8 @@ #define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */ #define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */ #define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ -#define SQLITE_DBCONFIG_MAX 1009 /* Largest DBCONFIG */ +#define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */ +#define SQLITE_DBCONFIG_MAX 1010 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes @@ -3609,9 +3628,19 @@ ** on this hint by avoiding the use of [lookaside memory] so as not to ** deplete the limited store of lookaside memory. Future versions of ** SQLite may act on this hint differently. +** +** [[SQLITE_PREPARE_NORMALIZE]] ^(<dt>SQLITE_PREPARE_NORMALIZE</dt> +** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized +** representation of the SQL statement should be calculated and then +** associated with the prepared statement, which can be obtained via +** the [sqlite3_normalized_sql()] interface.)^ The semantics used to +** normalize a SQL statement are unspecified and subject to change. +** At a minimum, literal values will be replaced with suitable +** placeholders. ** </dl> */ #define SQLITE_PREPARE_PERSISTENT 0x01 +#define SQLITE_PREPARE_NORMALIZE 0x02 /* ** CAPI3REF: Compiling An SQL Statement @@ -3769,6 +3798,11 @@ ** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8 ** string containing the SQL text of prepared statement P with ** [bound parameters] expanded. +** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8 +** string containing the normalized SQL text of prepared statement P. The +** semantics used to normalize a SQL statement are unspecified and subject +** to change. At a minimum, literal values will be replaced with suitable +** placeholders. ** ** ^(For example, if a prepared statement is created using the SQL ** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345 @@ -3784,14 +3818,16 @@ ** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time ** option causes sqlite3_expanded_sql() to always return NULL. ** -** ^The string returned by sqlite3_sql(P) is managed by SQLite and is -** automatically freed when the prepared statement is finalized. +** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P) +** are managed by SQLite and are automatically freed when the prepared +** statement is finalized. ** ^The string returned by sqlite3_expanded_sql(P), on the other hand, ** is obtained from [sqlite3_malloc()] and must be free by the application ** by passing it to [sqlite3_free()]. */ const char *sqlite3_sql(sqlite3_stmt *pStmt); char *sqlite3_expanded_sql(sqlite3_stmt *pStmt); +const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If An SQL Statement Writes The Database @@ -6281,6 +6317,9 @@ int (*xSavepoint)(sqlite3_vtab *pVTab, int); int (*xRelease)(sqlite3_vtab *pVTab, int); int (*xRollbackTo)(sqlite3_vtab *pVTab, int); + /* The methods above are in versions 1 and 2 of the sqlite_module object. + ** Those below are for version 3 and greater. */ + int (*xShadowName)(const char*); }; /* @@ -7203,6 +7242,7 @@ #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ +#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 @@ -8638,6 +8678,7 @@ ** can use to customize and optimize their behavior. ** ** <dl> +** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]] ** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT ** <dd>Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
diff --git a/third_party/sqlite/src/src/sqlite3ext.h b/third_party/sqlite/src/src/sqlite3ext.h index ae34572..eb606c7 100644 --- a/third_party/sqlite/src/src/sqlite3ext.h +++ b/third_party/sqlite/src/src/sqlite3ext.h
@@ -310,12 +310,15 @@ int (*str_errcode)(sqlite3_str*); int (*str_length)(sqlite3_str*); char *(*str_value)(sqlite3_str*); + /* Version 3.25.0 and later */ int (*create_window_function)(sqlite3*,const char*,int,int,void*, void (*xStep)(sqlite3_context*,int,sqlite3_value**), void (*xFinal)(sqlite3_context*), void (*xValue)(sqlite3_context*), void (*xInv)(sqlite3_context*,int,sqlite3_value**), void(*xDestroy)(void*)); + /* Version 3.26.0 and later */ + const char *(*normalized_sql)(sqlite3_stmt*); }; /* @@ -603,6 +606,8 @@ #define sqlite3_str_value sqlite3_api->str_value /* Version 3.25.0 and later */ #define sqlite3_create_window_function sqlite3_api->create_window_function +/* Version 3.26.0 and later */ +#define sqlite3_normalized_sql sqlite3_api->normalized_sql #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
diff --git a/third_party/sqlite/src/src/sqliteInt.h b/third_party/sqlite/src/src/sqliteInt.h index 0f6ef518..44d1406 100644 --- a/third_party/sqlite/src/src/sqliteInt.h +++ b/third_party/sqlite/src/src/sqliteInt.h
@@ -1305,12 +1305,14 @@ ** functions use a regular table table from hash.h.) ** ** Hash each FuncDef structure into one of the FuncDefHash.a[] slots. -** Collisions are on the FuncDef.u.pHash chain. +** Collisions are on the FuncDef.u.pHash chain. Use the SQLITE_FUNC_HASH() +** macro to compute a hash on the function name. */ #define SQLITE_FUNC_HASH_SZ 23 struct FuncDefHash { FuncDef *a[SQLITE_FUNC_HASH_SZ]; /* Hash table for functions */ }; +#define SQLITE_FUNC_HASH(C,L) (((C)+(L))%SQLITE_FUNC_HASH_SZ) #ifdef SQLITE_USER_AUTHENTICATION /* @@ -1371,7 +1373,7 @@ Db *aDb; /* All backends */ int nDb; /* Number of backends currently in use */ u32 mDbFlags; /* flags recording internal state */ - u32 flags; /* flags settable by pragmas. See below */ + u64 flags; /* flags settable by pragmas. See below */ i64 lastRowid; /* ROWID of most recent insert (see above) */ i64 szMmap; /* Default mmap_size setting */ u32 nSchemaLock; /* Do not reset the schema when non-zero */ @@ -1537,14 +1539,17 @@ #define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */ #define SQLITE_ResetDatabase 0x02000000 /* Reset the database */ #define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */ +#define SQLITE_NoSchemaError 0x08000000 /* Do not report schema parse errors*/ +#define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */ /* Flags used only if debugging */ +#define HI(X) ((u64)(X)<<32) #ifdef SQLITE_DEBUG -#define SQLITE_SqlTrace 0x08000000 /* Debug print SQL as it executes */ -#define SQLITE_VdbeListing 0x10000000 /* Debug listings of VDBE programs */ -#define SQLITE_VdbeTrace 0x20000000 /* True to trace VDBE execution */ -#define SQLITE_VdbeAddopTrace 0x40000000 /* Trace sqlite3VdbeAddOp() calls */ -#define SQLITE_VdbeEQP 0x80000000 /* Debug EXPLAIN QUERY PLAN */ +#define SQLITE_SqlTrace HI(0x0001) /* Debug print SQL as it executes */ +#define SQLITE_VdbeListing HI(0x0002) /* Debug listings of VDBE progs */ +#define SQLITE_VdbeTrace HI(0x0004) /* True to trace VDBE execution */ +#define SQLITE_VdbeAddopTrace HI(0x0008) /* Trace sqlite3VdbeAddOp() calls */ +#define SQLITE_VdbeEQP HI(0x0010) /* Debug EXPLAIN QUERY PLAN */ #endif /* @@ -1678,8 +1683,9 @@ ** single query - might change over time */ #define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ #define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ -#define SQLITE_FUNC_WINDOW 0x10000 /* Built-in window-only function */ -#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */ +#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ +#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */ +#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are @@ -1755,10 +1761,13 @@ #define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}} - #define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}} +#define INTERNAL_FUNCTION(zName, nArg, xFunc) \ + {nArg, SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \ + 0, 0, xFunc, 0, 0, 0, #zName, {0} } + /* ** All current savepoints are stored in a linked list starting at @@ -1943,6 +1952,9 @@ struct Table { char *zName; /* Name of the table or view */ Column *aCol; /* Information about each column */ +#ifdef SQLITE_ENABLE_NORMALIZE + Hash *pColHash; /* All columns indexed by name */ +#endif Index *pIndex; /* List of SQL indexes on this table. */ Select *pSelect; /* NULL for tables. Points to definition if a view. */ FKey *pFKey; /* Linked list of all foreign keys in this table */ @@ -1993,6 +2005,7 @@ #define TF_StatsUsed 0x0100 /* Query planner decisions affected by ** Index.aiRowLogEst[] values */ #define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */ +#define TF_Shadow 0x0400 /* True for a shadow table */ /* ** Test to see whether or not a table is a virtual table. This is @@ -2280,6 +2293,12 @@ }; /* +** Possible values to use within the flags argument to sqlite3GetToken(). +*/ +#define SQLITE_TOKEN_QUOTED 0x1 /* Token is a quoted identifier. */ +#define SQLITE_TOKEN_KEYWORD 0x2 /* Token is a keyword. */ + +/* ** Each token coming out of the lexer is an instance of ** this structure. Tokens are also used as part of an expression. ** @@ -2460,11 +2479,11 @@ ** TK_COLUMN: the value of p5 for OP_Column ** TK_AGG_FUNCTION: nesting depth */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ - Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL - ** for a column of an index on an expression */ -#ifndef SQLITE_OMIT_WINDOWFUNC - Window *pWin; /* Window definition for window functions */ -#endif + union { + Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL + ** for a column of an index on an expression */ + Window *pWin; /* TK_FUNCTION: Window definition for the func */ + } y; }; /* @@ -2494,6 +2513,7 @@ #define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ #define EP_Alias 0x400000 /* Is an alias for a result set column */ #define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */ +#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */ /* ** The EP_Propagate mask is a set of properties that automatically propagate @@ -3398,6 +3418,7 @@ int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ #endif int bLocaltimeFault; /* True to fail localtime() calls */ + int bInternalFunctions; /* Internal SQL functions are visible */ int iOnceResetThreshold; /* When to reset OP_Once counters */ u32 szSorterRef; /* Min size in bytes to use sorter-refs */ }; @@ -3651,6 +3672,7 @@ */ int sqlite3StrICmp(const char*,const char*); int sqlite3Strlen30(const char*); +#define sqlite3Strlen30NN(C) (strlen(C)&0x3fffffff) char *sqlite3ColumnType(Column*,char*); #define sqlite3StrNICmp sqlite3_strnicmp @@ -3767,6 +3789,7 @@ void sqlite3TreeViewExpr(TreeView*, const Expr*, u8); void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*); void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*); + void sqlite3TreeViewSrcList(TreeView*, const SrcList*); void sqlite3TreeViewSelect(TreeView*, const Select*, u8); void sqlite3TreeViewWith(TreeView*, const With*, u8); #ifndef SQLITE_OMIT_WINDOWFUNC @@ -3999,11 +4022,15 @@ int sqlite3ExprCanBeNull(const Expr*); int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); int sqlite3IsRowid(const char*); +#ifdef SQLITE_ENABLE_NORMALIZE +int sqlite3IsRowidN(const char*, int); +#endif void sqlite3GenerateRowDelete( Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int); void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int); void sqlite3ResolvePartIdxLabel(Parse*,int); +int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int); void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int, u8,u8,int,int*,int*,Upsert*); #ifdef SQLITE_ENABLE_NULL_TRIM @@ -4024,6 +4051,9 @@ SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); IdList *sqlite3IdListDup(sqlite3*,IdList*); Select *sqlite3SelectDup(sqlite3*,Select*,int); +#ifdef SQLITE_ENABLE_NORMALIZE +FuncDef *sqlite3FunctionSearchN(int,const char*,int); +#endif void sqlite3InsertBuiltinFuncs(FuncDef*,int); FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8); void sqlite3RegisterBuiltinFunctions(void); @@ -4181,6 +4211,7 @@ Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); Expr *sqlite3ExprSkipCollate(Expr*); int sqlite3CheckCollSeq(Parse *, CollSeq *); +int sqlite3WritableSchema(sqlite3*); int sqlite3CheckObjectName(Parse *, const char *); void sqlite3VdbeSetChanges(sqlite3 *, int); int sqlite3AddInt64(i64*,i64); @@ -4227,6 +4258,9 @@ void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*); int sqlite3GetToken(const unsigned char *, int *); +#ifdef SQLITE_ENABLE_NORMALIZE +int sqlite3GetTokenNormalized(const unsigned char *, int *, int *); +#endif void sqlite3NestedParse(Parse*, const char*, ...); void sqlite3ExpirePreparedStatements(sqlite3*, int); int sqlite3CodeSubselect(Parse*, Expr *, int, int); @@ -4384,6 +4418,9 @@ int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); void sqlite3ParserReset(Parse*); +#ifdef SQLITE_ENABLE_NORMALIZE +void sqlite3Normalize(Vdbe*, const char*, int, u8); +#endif int sqlite3Reprepare(Vdbe*); void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*); CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
diff --git a/third_party/sqlite/src/src/test1.c b/third_party/sqlite/src/src/test1.c index 1c9ebf8..5d6a01f3 100644 --- a/third_party/sqlite/src/src/test1.c +++ b/third_party/sqlite/src/src/test1.c
@@ -4218,6 +4218,7 @@ char *zCopy = 0; /* malloc() copy of zSql */ int bytes; const char *zTail = 0; + const char **pzTail; sqlite3_stmt *pStmt = 0; char zBuf[50]; int rc; @@ -4242,7 +4243,8 @@ zCopy = malloc(n); memcpy(zCopy, zSql, n); } - rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, objc>=5 ? &zTail : 0); + pzTail = objc>=5 ? &zTail : 0; + rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, pzTail); free(zCopy); zTail = &zSql[(zTail - zCopy)]; @@ -4270,6 +4272,79 @@ } /* +** Usage: sqlite3_prepare_v3 DB sql bytes flags ?tailvar? +** +** Compile up to <bytes> bytes of the supplied SQL string <sql> using +** database handle <DB> and flags <flags>. The parameter <tailval> is +** the name of a global variable that is set to the unused portion of +** <sql> (if any). A STMT handle is returned. +*/ +static int SQLITE_TCLAPI test_prepare_v3( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3 *db; + const char *zSql; + char *zCopy = 0; /* malloc() copy of zSql */ + int bytes, flags; + const char *zTail = 0; + const char **pzTail; + sqlite3_stmt *pStmt = 0; + char zBuf[50]; + int rc; + + if( objc!=6 && objc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetString(objv[0]), " DB sql bytes flags tailvar", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; + zSql = Tcl_GetString(objv[2]); + if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[4], &flags) ) return TCL_ERROR; + + /* Instead of using zSql directly, make a copy into a buffer obtained + ** directly from malloc(). The idea is to make it easier for valgrind + ** to spot buffer overreads. */ + if( bytes>=0 ){ + zCopy = malloc(bytes); + memcpy(zCopy, zSql, bytes); + }else{ + int n = (int)strlen(zSql) + 1; + zCopy = malloc(n); + memcpy(zCopy, zSql, n); + } + pzTail = objc>=6 ? &zTail : 0; + rc = sqlite3_prepare_v3(db, zCopy, bytes, (unsigned int)flags,&pStmt,pzTail); + free(zCopy); + zTail = &zSql[(zTail - zCopy)]; + + assert(rc==SQLITE_OK || pStmt==0); + Tcl_ResetResult(interp); + if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; + if( rc==SQLITE_OK && zTail && objc>=6 ){ + if( bytes>=0 ){ + bytes = bytes - (int)(zTail-zSql); + } + Tcl_ObjSetVar2(interp, objv[5], 0, Tcl_NewStringObj(zTail, bytes), 0); + } + if( rc!=SQLITE_OK ){ + assert( pStmt==0 ); + sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc); + Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0); + return TCL_ERROR; + } + + if( pStmt ){ + if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR; + Tcl_AppendResult(interp, zBuf, 0); + } + return TCL_OK; +} + +/* ** Usage: sqlite3_prepare_tkt3134 DB ** ** Generate a prepared statement for a zero-byte string as a test @@ -4676,6 +4751,25 @@ sqlite3_free(z); return TCL_OK; } +#ifdef SQLITE_ENABLE_NORMALIZE +static int SQLITE_TCLAPI test_norm_sql( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "STMT"); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + Tcl_SetResult(interp, (char *)sqlite3_normalized_sql(pStmt), TCL_VOLATILE); + return TCL_OK; +} +#endif /* SQLITE_ENABLE_NORMALIZE */ /* ** Usage: sqlite3_column_count STMT @@ -6235,7 +6329,7 @@ /* ** tclcmd: database_may_be_corrupt ** -** Indicate that database files might be corrupt. In other words, set the normal +** Indicate that database files might be corrupt. In other words, set the normal ** state of operation. */ static int SQLITE_TCLAPI database_may_be_corrupt( @@ -6250,8 +6344,9 @@ /* ** tclcmd: database_never_corrupt ** -** Indicate that database files are always well-formed. This enables extra assert() -** statements that test conditions that are always true for well-formed databases. +** Indicate that database files are always well-formed. This enables +** extra assert() statements that test conditions that are always true +** for well-formed databases. */ static int SQLITE_TCLAPI database_never_corrupt( ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ @@ -6617,9 +6712,10 @@ const char *zName; int i; } aVerb[] = { - { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT }, - { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP }, - { "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER }, + { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT }, + { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP }, + { "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER }, + { "SQLITE_TESTCTRL_INTERNAL_FUNCTIONS", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS}, }; int iVerb; int iFlag; @@ -6637,6 +6733,7 @@ iFlag = aVerb[iVerb].i; switch( iFlag ){ + case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: case SQLITE_TESTCTRL_LOCALTIME_FAULT: { int val; if( objc!=3 ){ @@ -6644,7 +6741,7 @@ return TCL_ERROR; } if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; - sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val); + sqlite3_test_control(iFlag, val); break; } @@ -7038,6 +7135,7 @@ extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_csv_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*); + extern int sqlite3_explain_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*); @@ -7062,6 +7160,7 @@ { "closure", sqlite3_closure_init }, { "csv", sqlite3_csv_init }, { "eval", sqlite3_eval_init }, + { "explain", sqlite3_explain_init }, { "fileio", sqlite3_fileio_init }, { "fuzzer", sqlite3_fuzzer_init }, { "ieee754", sqlite3_ieee_init }, @@ -7460,6 +7559,7 @@ { "QPSG", SQLITE_DBCONFIG_ENABLE_QPSG }, { "TRIGGER_EQP", SQLITE_DBCONFIG_TRIGGER_EQP }, { "RESET_DB", SQLITE_DBCONFIG_RESET_DATABASE }, + { "DEFENSIVE", SQLITE_DBCONFIG_DEFENSIVE }, }; int i; int v; @@ -7644,6 +7744,7 @@ { "sqlite3_prepare", test_prepare ,0 }, { "sqlite3_prepare16", test_prepare16 ,0 }, { "sqlite3_prepare_v2", test_prepare_v2 ,0 }, + { "sqlite3_prepare_v3", test_prepare_v3 ,0 }, { "sqlite3_prepare_tkt3134", test_prepare_tkt3134, 0}, { "sqlite3_prepare16_v2", test_prepare16_v2 ,0 }, { "sqlite3_finalize", test_finalize ,0 }, @@ -7655,6 +7756,9 @@ { "sqlite3_step", test_step ,0 }, { "sqlite3_sql", test_sql ,0 }, { "sqlite3_expanded_sql", test_ex_sql ,0 }, +#ifdef SQLITE_ENABLE_NORMALIZE + { "sqlite3_normalized_sql", test_norm_sql ,0 }, +#endif { "sqlite3_next_stmt", test_next_stmt ,0 }, { "sqlite3_stmt_readonly", test_stmt_readonly ,0 }, { "sqlite3_stmt_busy", test_stmt_busy ,0 },
diff --git a/third_party/sqlite/src/src/test_config.c b/third_party/sqlite/src/src/test_config.c index dd26913d..55a99bb9 100644 --- a/third_party/sqlite/src/src/test_config.c +++ b/third_party/sqlite/src/src/test_config.c
@@ -124,7 +124,7 @@ STRINGVALUE(SQLITE_MAX_WORKER_THREADS), TCL_GLOBAL_ONLY ); -#if 1 /* def SQLITE_MEMDEBUG */ +#ifdef SQLITE_MEMDEBUG Tcl_SetVar2(interp, "sqlite_options", "memdebug", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "memdebug", "0", TCL_GLOBAL_ONLY); @@ -762,6 +762,12 @@ Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "0", TCL_GLOBAL_ONLY); #endif +#if defined(SQLITE_ENABLE_NORMALIZE) + Tcl_SetVar2(interp, "sqlite_options", "normalize", "1", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "normalize", "0", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_OMIT_WINDOWFUNC Tcl_SetVar2(interp, "sqlite_options", "windowfunc", "0", TCL_GLOBAL_ONLY); #else
diff --git a/third_party/sqlite/src/src/test_intarray.c b/third_party/sqlite/src/src/test_intarray.c index 1f7a49a..ee19b1d7 100644 --- a/third_party/sqlite/src/src/test_intarray.c +++ b/third_party/sqlite/src/src/test_intarray.c
@@ -13,6 +13,10 @@ ** This file implements a read-only VIRTUAL TABLE that contains the ** content of a C-language array of integer values. See the corresponding ** header file for full details. +** +** This virtual table is used for internal testing of SQLite only. It is +** not recommended for use in production. For a similar virtual table that +** is production-ready, see the "carray" virtual table over in ext/misc. */ #include "test_intarray.h" #include <string.h> @@ -315,7 +319,6 @@ rc = sqlite3_intarray_create(db, zName, &pArray); #endif if( rc!=SQLITE_OK ){ - assert( pArray==0 ); Tcl_AppendResult(interp, sqlite3ErrName(rc), (char*)0); return TCL_ERROR; }
diff --git a/third_party/sqlite/src/src/test_intarray.h b/third_party/sqlite/src/src/test_intarray.h index cee55b5..116e3bdc 100644 --- a/third_party/sqlite/src/src/test_intarray.h +++ b/third_party/sqlite/src/src/test_intarray.h
@@ -13,6 +13,10 @@ ** This is the C-language interface definition for the "intarray" or ** integer array virtual table for SQLite. ** +** This virtual table is used for internal testing of SQLite only. It is +** not recommended for use in production. For a similar virtual table that +** is production-ready, see the "carray" virtual table over in ext/misc. +** ** The intarray virtual table is designed to facilitate using an ** array of integers as the right-hand side of an IN operator. So ** instead of doing a prepared statement like this: @@ -72,7 +76,10 @@ ** virtual table is dropped. Since the virtual tables are created in the ** TEMP database, they are automatically dropped when the database connection ** closes so the application does not normally need to take any special -** action to free the intarray objects. +** action to free the intarray objects. Because of the way virtual tables +** work and the (somewhat goofy) way that the intarray virtual table is +** implemented, it is not allowed to invoke sqlite3_intarray_create(D,N,P) +** more than once with the same D and N values. */ #include "sqlite3.h" #ifndef SQLITE_INTARRAY_H
diff --git a/third_party/sqlite/src/src/test_onefile.c b/third_party/sqlite/src/src/test_onefile.c index 7a99e3e..554842d9 100644 --- a/third_party/sqlite/src/src/test_onefile.c +++ b/third_party/sqlite/src/src/test_onefile.c
@@ -560,6 +560,7 @@ ** File control method. For custom operations on an fs-file. */ static int fsFileControl(sqlite3_file *pFile, int op, void *pArg){ + if( op==SQLITE_FCNTL_PRAGMA ) return SQLITE_NOTFOUND; return SQLITE_OK; }
diff --git a/third_party/sqlite/src/src/tokenize.c b/third_party/sqlite/src/src/tokenize.c index 8404726..4e56a48 100644 --- a/third_party/sqlite/src/src/tokenize.c +++ b/third_party/sqlite/src/src/tokenize.c
@@ -545,6 +545,73 @@ return i; } +#ifdef SQLITE_ENABLE_NORMALIZE +/* +** Return the length (in bytes) of the token that begins at z[0]. +** Store the token type in *tokenType before returning. If flags has +** SQLITE_TOKEN_NORMALIZE flag enabled, use the identifier token type +** for keywords. Add SQLITE_TOKEN_QUOTED to flags if the token was +** actually a quoted identifier. Add SQLITE_TOKEN_KEYWORD to flags +** if the token was recognized as a keyword; this is useful when the +** SQLITE_TOKEN_NORMALIZE flag is used, because it enables the caller +** to differentiate between a keyword being treated as an identifier +** (for normalization purposes) and an actual identifier. +*/ +int sqlite3GetTokenNormalized( + const unsigned char *z, + int *tokenType, + int *flags +){ + int n; + unsigned char iClass = aiClass[*z]; + if( iClass==CC_KYWD ){ + int i; + for(i=1; aiClass[z[i]]<=CC_KYWD; i++){} + if( IdChar(z[i]) ){ + /* This token started out using characters that can appear in keywords, + ** but z[i] is a character not allowed within keywords, so this must + ** be an identifier instead */ + i++; + while( IdChar(z[i]) ){ i++; } + *tokenType = TK_ID; + return i; + } + *tokenType = TK_ID; + n = keywordCode((char*)z, i, tokenType); + /* If the token is no longer considered to be an identifier, then it is a + ** keyword of some kind. Make the token back into an identifier and then + ** set the SQLITE_TOKEN_KEYWORD flag. Several non-identifier tokens are + ** used verbatim, including IN, IS, NOT, and NULL. */ + switch( *tokenType ){ + case TK_ID: { + /* do nothing, handled by caller */ + break; + } + case TK_IN: + case TK_IS: + case TK_NOT: + case TK_NULL: { + *flags |= SQLITE_TOKEN_KEYWORD; + break; + } + default: { + *tokenType = TK_ID; + *flags |= SQLITE_TOKEN_KEYWORD; + break; + } + } + }else{ + n = sqlite3GetToken(z, tokenType); + /* If the token is considered to be an identifier and the character class + ** of the first character is a quote, set the SQLITE_TOKEN_QUOTED flag. */ + if( *tokenType==TK_ID && (iClass==CC_QUOTE || iClass==CC_QUOTE2) ){ + *flags |= SQLITE_TOKEN_QUOTED; + } + } + return n; +} +#endif /* SQLITE_ENABLE_NORMALIZE */ + /* ** Run the parser on the given SQL string. The parser structure is ** passed in. An SQLITE_ status code is returned. If an error occurs
diff --git a/third_party/sqlite/src/src/treeview.c b/third_party/sqlite/src/src/treeview.c index 4b6ea4f..e7483dd 100644 --- a/third_party/sqlite/src/src/treeview.c +++ b/third_party/sqlite/src/src/treeview.c
@@ -121,6 +121,42 @@ } } +/* +** Generate a human-readable description of a SrcList object. +*/ +void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){ + int i; + for(i=0; i<pSrc->nSrc; i++){ + const struct SrcList_item *pItem = &pSrc->a[i]; + StrAccum x; + char zLine[100]; + sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); + sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor); + if( pItem->zDatabase ){ + sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName); + }else if( pItem->zName ){ + sqlite3_str_appendf(&x, " %s", pItem->zName); + } + if( pItem->pTab ){ + sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName); + } + if( pItem->zAlias ){ + sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias); + } + if( pItem->fg.jointype & JT_LEFT ){ + sqlite3_str_appendf(&x, " LEFT-JOIN"); + } + sqlite3StrAccumFinish(&x); + sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1); + if( pItem->pSelect ){ + sqlite3TreeViewSelect(pView, pItem->pSelect, 0); + } + if( pItem->fg.isTabFunc ){ + sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); + } + sqlite3TreeViewPop(pView); + } +} /* ** Generate a human-readable description of a Select object. @@ -175,39 +211,9 @@ } #endif if( p->pSrc && p->pSrc->nSrc ){ - int i; pView = sqlite3TreeViewPush(pView, (n--)>0); sqlite3TreeViewLine(pView, "FROM"); - for(i=0; i<p->pSrc->nSrc; i++){ - struct SrcList_item *pItem = &p->pSrc->a[i]; - StrAccum x; - char zLine[100]; - sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); - sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor); - if( pItem->zDatabase ){ - sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName); - }else if( pItem->zName ){ - sqlite3_str_appendf(&x, " %s", pItem->zName); - } - if( pItem->pTab ){ - sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName); - } - if( pItem->zAlias ){ - sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias); - } - if( pItem->fg.jointype & JT_LEFT ){ - sqlite3_str_appendf(&x, " LEFT-JOIN"); - } - sqlite3StrAccumFinish(&x); - sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1); - if( pItem->pSelect ){ - sqlite3TreeViewSelect(pView, pItem->pSelect, 0); - } - if( pItem->fg.isTabFunc ){ - sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); - } - sqlite3TreeViewPop(pView); - } + sqlite3TreeViewSrcList(pView, p->pSrc); sqlite3TreeViewPop(pView); } if( p->pWhere ){ @@ -497,7 +503,7 @@ }else{ pFarg = pExpr->x.pList; #ifndef SQLITE_OMIT_WINDOWFUNC - pWin = pExpr->pWin; + pWin = pExpr->y.pWin; #else pWin = 0; #endif
diff --git a/third_party/sqlite/src/src/update.c b/third_party/sqlite/src/src/update.c index 73b973b..b328d3b 100644 --- a/third_party/sqlite/src/src/update.c +++ b/third_party/sqlite/src/src/update.c
@@ -80,6 +80,57 @@ } /* +** Check to see if column iCol of index pIdx references any of the +** columns defined by aXRef and chngRowid. Return true if it does +** and false if not. This is an optimization. False-positives are a +** performance degradation, but false-negatives can result in a corrupt +** index and incorrect answers. +** +** aXRef[j] will be non-negative if column j of the original table is +** being updated. chngRowid will be true if the rowid of the table is +** being updated. +*/ +static int indexColumnIsBeingUpdated( + Index *pIdx, /* The index to check */ + int iCol, /* Which column of the index to check */ + int *aXRef, /* aXRef[j]>=0 if column j is being updated */ + int chngRowid /* true if the rowid is being updated */ +){ + i16 iIdxCol = pIdx->aiColumn[iCol]; + assert( iIdxCol!=XN_ROWID ); /* Cannot index rowid */ + if( iIdxCol>=0 ){ + return aXRef[iIdxCol]>=0; + } + assert( iIdxCol==XN_EXPR ); + assert( pIdx->aColExpr!=0 ); + assert( pIdx->aColExpr->a[iCol].pExpr!=0 ); + return sqlite3ExprReferencesUpdatedColumn(pIdx->aColExpr->a[iCol].pExpr, + aXRef,chngRowid); +} + +/* +** Check to see if index pIdx is a partial index whose conditional +** expression might change values due to an UPDATE. Return true if +** the index is subject to change and false if the index is guaranteed +** to be unchanged. This is an optimization. False-positives are a +** performance degradation, but false-negatives can result in a corrupt +** index and incorrect answers. +** +** aXRef[j] will be non-negative if column j of the original table is +** being updated. chngRowid will be true if the rowid of the table is +** being updated. +*/ +static int indexWhereClauseMightChange( + Index *pIdx, /* The index to check */ + int *aXRef, /* aXRef[j]>=0 if column j is being updated */ + int chngRowid /* true if the rowid is being updated */ +){ + if( pIdx->pPartIdxWhere==0 ) return 0; + return sqlite3ExprReferencesUpdatedColumn(pIdx->pPartIdxWhere, + aXRef, chngRowid); +} + +/* ** Process an UPDATE statement. ** ** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; @@ -302,19 +353,18 @@ /* There is one entry in the aRegIdx[] array for each index on the table ** being updated. Fill in aRegIdx[] with a register number that will hold ** the key for accessing each index. - ** - ** FIXME: Be smarter about omitting indexes that use expressions. */ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int reg; - if( chngKey || hasFK>1 || pIdx->pPartIdxWhere || pIdx==pPk ){ + if( chngKey || hasFK>1 || pIdx==pPk + || indexWhereClauseMightChange(pIdx,aXRef,chngRowid) + ){ reg = ++pParse->nMem; pParse->nMem += pIdx->nColumn; }else{ reg = 0; for(i=0; i<pIdx->nKeyCol; i++){ - i16 iIdxCol = pIdx->aiColumn[i]; - if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){ + if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){ reg = ++pParse->nMem; pParse->nMem += pIdx->nColumn; if( (onError==OE_Replace)
diff --git a/third_party/sqlite/src/src/vacuum.c b/third_party/sqlite/src/src/vacuum.c index 2d86344..6ee545d1 100644 --- a/third_party/sqlite/src/src/vacuum.c +++ b/third_party/sqlite/src/src/vacuum.c
@@ -166,7 +166,8 @@ saved_mTrace = db->mTrace; db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks; db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum; - db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_CountRows); + db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder + | SQLITE_Defensive | SQLITE_CountRows); db->mTrace = 0; zDbMain = db->aDb[iDb].zDbSName;
diff --git a/third_party/sqlite/src/src/vdbe.c b/third_party/sqlite/src/src/vdbe.c index 04cc2af..ae2ff53 100644 --- a/third_party/sqlite/src/src/vdbe.c +++ b/third_party/sqlite/src/src/vdbe.c
@@ -2894,17 +2894,25 @@ if( nVarint<sqlite3VarintLen(nHdr) ) nHdr++; } nByte = nHdr+nData; - if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } /* Make sure the output register has a buffer large enough to store ** the new record. The output register (pOp->p3) is not allowed to ** be one of the input registers (because the following call to ** sqlite3VdbeMemClearAndResize() could clobber the value before it is used). */ - if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){ - goto no_mem; + if( nByte+nZero<=pOut->szMalloc ){ + /* The output register is already large enough to hold the record. + ** No error checks or buffer enlargement is required */ + pOut->z = pOut->zMalloc; + }else{ + /* Need to make sure that the output is not too big and then enlarge + ** the output register to hold the full result */ + if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + goto too_big; + } + if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){ + goto no_mem; + } } zNewRecord = (u8 *)pOut->z; @@ -5760,7 +5768,7 @@ { zMaster = MASTER_NAME; initData.db = db; - initData.iDb = pOp->p1; + initData.iDb = iDb; initData.pzErrMsg = &p->zErrMsg; initData.mInitFlags = 0; zSql = sqlite3MPrintf(db,
diff --git a/third_party/sqlite/src/src/vdbeInt.h b/third_party/sqlite/src/src/vdbeInt.h index ed0aecbc..23c5b37 100644 --- a/third_party/sqlite/src/src/vdbeInt.h +++ b/third_party/sqlite/src/src/vdbeInt.h
@@ -406,6 +406,9 @@ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */ char *zSql; /* Text of the SQL statement that generated this */ +#ifdef SQLITE_ENABLE_NORMALIZE + char *zNormSql; /* Normalization of the associated SQL statement */ +#endif void *pFree; /* Free this when deleting the vdbe */ VdbeFrame *pFrame; /* Parent frame */ VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ @@ -468,7 +471,9 @@ int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*); int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*); int sqlite3VdbeExec(Vdbe*); +#ifndef SQLITE_OMIT_EXPLAIN int sqlite3VdbeList(Vdbe*); +#endif int sqlite3VdbeHalt(Vdbe*); int sqlite3VdbeChangeEncoding(Mem *, int); int sqlite3VdbeMemTooBig(Mem*); @@ -507,7 +512,9 @@ #ifndef SQLITE_OMIT_WINDOWFUNC int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*); #endif +#ifndef SQLITE_OMIT_EXPLAIN const char *sqlite3OpcodeName(int); +#endif int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); int sqlite3VdbeMemClearAndResize(Mem *pMem, int n); int sqlite3VdbeCloseStatement(Vdbe *, int);
diff --git a/third_party/sqlite/src/src/vdbeapi.c b/third_party/sqlite/src/src/vdbeapi.c index 9acb608..7cc7b1bd 100644 --- a/third_party/sqlite/src/src/vdbeapi.c +++ b/third_party/sqlite/src/src/vdbeapi.c
@@ -1702,6 +1702,16 @@ #endif } +#ifdef SQLITE_ENABLE_NORMALIZE +/* +** Return the normalized SQL associated with a prepared statement. +*/ +const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt){ + Vdbe *p = (Vdbe *)pStmt; + return p ? p->zNormSql : 0; +} +#endif /* SQLITE_ENABLE_NORMALIZE */ + #ifdef SQLITE_ENABLE_PREUPDATE_HOOK /* ** Allocate and populate an UnpackedRecord structure based on the serialized
diff --git a/third_party/sqlite/src/src/vdbeaux.c b/third_party/sqlite/src/src/vdbeaux.c index f23de9b..ebcb652 100644 --- a/third_party/sqlite/src/src/vdbeaux.c +++ b/third_party/sqlite/src/src/vdbeaux.c
@@ -64,6 +64,13 @@ } assert( p->zSql==0 ); p->zSql = sqlite3DbStrNDup(p->db, z, n); +#ifdef SQLITE_ENABLE_NORMALIZE + assert( p->zNormSql==0 ); + if( p->zSql && (prepFlags & SQLITE_PREPARE_NORMALIZE)!=0 ){ + sqlite3Normalize(p, p->zSql, n, prepFlags); + assert( p->zNormSql!=0 || p->db->mallocFailed ); + } +#endif } /* @@ -85,6 +92,11 @@ zTmp = pA->zSql; pA->zSql = pB->zSql; pB->zSql = zTmp; +#ifdef SQLITE_ENABLE_NORMALIZE + zTmp = pA->zNormSql; + pA->zNormSql = pB->zNormSql; + pB->zNormSql = zTmp; +#endif pB->expmask = pA->expmask; pB->prepFlags = pA->prepFlags; memcpy(pB->aCounter, pA->aCounter, sizeof(pB->aCounter)); @@ -3156,6 +3168,9 @@ vdbeFreeOpArray(db, p->aOp, p->nOp); sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); +#ifdef SQLITE_ENABLE_NORMALIZE + sqlite3DbFree(db, p->zNormSql); +#endif #ifdef SQLITE_ENABLE_STMT_SCANSTATUS { int i;
diff --git a/third_party/sqlite/src/src/vdbemem.c b/third_party/sqlite/src/src/vdbemem.c index c527800..04c8f9440 100644 --- a/third_party/sqlite/src/src/vdbemem.c +++ b/third_party/sqlite/src/src/vdbemem.c
@@ -377,7 +377,8 @@ assert( fg & MEM_Real ); sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r); } - pMem->n = sqlite3Strlen30(pMem->z); + assert( pMem->z!=0 ); + pMem->n = sqlite3Strlen30NN(pMem->z); pMem->enc = SQLITE_UTF8; pMem->flags |= MEM_Str|MEM_Term; if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real);
diff --git a/third_party/sqlite/src/src/vtab.c b/third_party/sqlite/src/src/vtab.c index 82a194c..0062984 100644 --- a/third_party/sqlite/src/src/vtab.c +++ b/third_party/sqlite/src/src/vtab.c
@@ -328,7 +328,6 @@ Token *pModuleName, /* Name of the module for the virtual table */ int ifNotExists /* No error if the table already exists */ ){ - int iDb; /* The database the table is being created in */ Table *pTable; /* The new virtual table */ sqlite3 *db; /* Database connection */ @@ -338,8 +337,6 @@ assert( 0==pTable->pIndex ); db = pParse->db; - iDb = sqlite3SchemaToIndex(db, pTable->pSchema); - assert( iDb>=0 ); assert( pTable->nModuleArg==0 ); addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); @@ -359,6 +356,8 @@ ** The second call, to obtain permission to create the table, is made now. */ if( pTable->azModuleArg ){ + int iDb = sqlite3SchemaToIndex(db, pTable->pSchema); + assert( iDb>=0 ); /* The database the table is being created in */ sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName); } @@ -1053,7 +1052,7 @@ /* Check to see the left operand is a column in a virtual table */ if( NEVER(pExpr==0) ) return pDef; if( pExpr->op!=TK_COLUMN ) return pDef; - pTab = pExpr->pTab; + pTab = pExpr->y.pTab; if( pTab==0 ) return pDef; if( !IsVirtual(pTab) ) return pDef; pVtab = sqlite3GetVTable(db, pTab)->pVtab;
diff --git a/third_party/sqlite/src/src/walker.c b/third_party/sqlite/src/src/walker.c index 7bb5884..3d36a8ca 100644 --- a/third_party/sqlite/src/src/walker.c +++ b/third_party/sqlite/src/src/walker.c
@@ -55,8 +55,8 @@ if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort; } #ifndef SQLITE_OMIT_WINDOWFUNC - if( !ExprHasProperty(pExpr, EP_Reduced) && pExpr->pWin ){ - Window *pWin = pExpr->pWin; + if( ExprHasProperty(pExpr, EP_WinFunc) ){ + Window *pWin = pExpr->y.pWin; if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort; if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort; if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort;
diff --git a/third_party/sqlite/src/src/where.c b/third_party/sqlite/src/src/where.c index d97922b19..0a264cf 100644 --- a/third_party/sqlite/src/src/where.c +++ b/third_party/sqlite/src/src/where.c
@@ -854,7 +854,6 @@ translateColumnToCopy(pParse, addrTop, pLevel->iTabCur, pTabItem->regResult, 1); sqlite3VdbeGoto(v, addrTop); - pTabItem->fg.viaCoroutine = 0; }else{ sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); } @@ -1032,9 +1031,11 @@ ** method of the virtual table with the sqlite3_index_info object that ** comes in as the 3rd argument to this function. ** -** If an error occurs, pParse is populated with an error message and a -** non-zero value is returned. Otherwise, 0 is returned and the output -** part of the sqlite3_index_info structure is left populated. +** If an error occurs, pParse is populated with an error message and an +** appropriate error code is returned. A return of SQLITE_CONSTRAINT from +** xBestIndex is not considered an error. SQLITE_CONSTRAINT indicates that +** the current configuration of "unusable" flags in sqlite3_index_info can +** not result in a valid plan. ** ** Whether or not an error is returned, it is the responsibility of the ** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates @@ -1048,7 +1049,7 @@ rc = pVtab->pModule->xBestIndex(pVtab, p); TRACE_IDX_OUTPUTS(p); - if( rc!=SQLITE_OK ){ + if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){ if( rc==SQLITE_NOMEM ){ sqlite3OomFault(pParse->db); }else if( !pVtab->zErrMsg ){ @@ -1059,19 +1060,7 @@ } sqlite3_free(pVtab->zErrMsg); pVtab->zErrMsg = 0; - -#if 0 - /* This error is now caught by the caller. - ** Search for "xBestIndex malfunction" below */ - for(i=0; i<p->nConstraint; i++){ - if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){ - sqlite3ErrorMsg(pParse, - "table %s: xBestIndex returned an invalid plan", pTab->zName); - } - } -#endif - - return pParse->nErr; + return rc; } #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ @@ -2126,6 +2115,14 @@ sqlite3 *db = pWInfo->pParse->db; int rc; + /* Stop the search once we hit the query planner search limit */ + if( pBuilder->iPlanLimit==0 ){ + WHERETRACE(0xffffffff,("=== query planner search limit reached ===\n")); + if( pBuilder->pOrSet ) pBuilder->pOrSet->n = 0; + return SQLITE_DONE; + } + pBuilder->iPlanLimit--; + /* If pBuilder->pOrSet is defined, then only keep track of the costs ** and prereqs. */ @@ -3136,7 +3133,17 @@ /* Invoke the virtual table xBestIndex() method */ rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo); - if( rc ) return rc; + if( rc ){ + if( rc==SQLITE_CONSTRAINT ){ + /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means + ** that the particular combination of parameters provided is unusable. + ** Make no entries in the loop table. + */ + WHERETRACE(0xffff, (" ^^^^--- non-viable plan rejected!\n")); + return SQLITE_OK; + } + return rc; + } mxTerm = -1; assert( pNew->nLSlot>=nConstraint ); @@ -3532,9 +3539,11 @@ /* Loop over the tables in the join, from left to right */ pNew = pBuilder->pNew; whereLoopInit(pNew); + pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT; for(iTab=0, pItem=pTabList->a; pItem<pEnd; iTab++, pItem++){ Bitmask mUnusable = 0; pNew->iTab = iTab; + pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR; pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor); if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){ /* This condition is true when pItem is the FROM clause term on the @@ -3560,7 +3569,15 @@ rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable); } mPrior |= pNew->maskSelf; - if( rc || db->mallocFailed ) break; + if( rc || db->mallocFailed ){ + if( rc==SQLITE_DONE ){ + /* We hit the query planner search limit set by iPlanLimit */ + sqlite3_log(SQLITE_WARNING, "abbreviated query algorithm search"); + rc = SQLITE_OK; + }else{ + break; + } + } } whereLoopClear(db, pNew);
diff --git a/third_party/sqlite/src/src/whereInt.h b/third_party/sqlite/src/src/whereInt.h index 86c47290..6925e39e 100644 --- a/third_party/sqlite/src/src/whereInt.h +++ b/third_party/sqlite/src/src/whereInt.h
@@ -402,12 +402,33 @@ int nRecValid; /* Number of valid fields currently in pRec */ #endif unsigned int bldFlags; /* SQLITE_BLDF_* flags */ + unsigned int iPlanLimit; /* Search limiter */ }; /* Allowed values for WhereLoopBuider.bldFlags */ #define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */ #define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */ +/* The WhereLoopBuilder.iPlanLimit is used to limit the number of +** index+constraint combinations the query planner will consider for a +** particular query. If this parameter is unlimited, then certain +** pathological queries can spend excess time in the sqlite3WhereBegin() +** routine. The limit is high enough that is should not impact real-world +** queries. +** +** SQLITE_QUERY_PLANNER_LIMIT is the baseline limit. The limit is +** increased by SQLITE_QUERY_PLANNER_LIMIT_INCR before each term of the FROM +** clause is processed, so that every table in a join is guaranteed to be +** able to propose a some index+constraint combinations even if the initial +** baseline limit was exhausted by prior tables of the join. +*/ +#ifndef SQLITE_QUERY_PLANNER_LIMIT +# define SQLITE_QUERY_PLANNER_LIMIT 20000 +#endif +#ifndef SQLITE_QUERY_PLANNER_LIMIT_INCR +# define SQLITE_QUERY_PLANNER_LIMIT_INCR 1000 +#endif + /* ** The WHERE clause processing routine has two halves. The ** first part does the start of the WHERE loop and the second
diff --git a/third_party/sqlite/src/src/wherecode.c b/third_party/sqlite/src/src/wherecode.c index 3fab79cf9..bbd738b8 100644 --- a/third_party/sqlite/src/src/wherecode.c +++ b/third_party/sqlite/src/src/wherecode.c
@@ -1117,7 +1117,7 @@ pExpr->op = TK_COLUMN; pExpr->iTable = pX->iIdxCur; pExpr->iColumn = pX->iIdxCol; - pExpr->pTab = 0; + pExpr->y.pTab = 0; return WRC_Prune; }else{ return WRC_Continue;
diff --git a/third_party/sqlite/src/src/whereexpr.c b/third_party/sqlite/src/src/whereexpr.c index f4ce447..e91f1d7 100644 --- a/third_party/sqlite/src/src/whereexpr.c +++ b/third_party/sqlite/src/src/whereexpr.c
@@ -281,7 +281,7 @@ ){ if( pLeft->op!=TK_COLUMN || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT - || IsVirtual(pLeft->pTab) /* Value might be numeric */ + || IsVirtual(pLeft->y.pTab) /* Value might be numeric */ ){ sqlite3ExprDelete(db, pPrefix); sqlite3ValueFree(pVal); @@ -382,7 +382,7 @@ ** MATCH(expression,vtab_column) */ pCol = pList->a[1].pExpr; - if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){ + if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ for(i=0; i<ArraySize(aOp); i++){ if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){ *peOp2 = aOp[i].eOp2; @@ -404,12 +404,12 @@ ** with function names in an arbitrary case. */ pCol = pList->a[0].pExpr; - if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){ + if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ sqlite3_vtab *pVtab; sqlite3_module *pMod; void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); void *pNotUsed; - pVtab = sqlite3GetVTable(db, pCol->pTab)->pVtab; + pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab; assert( pVtab!=0 ); assert( pVtab->pModule!=0 ); pMod = (sqlite3_module *)pVtab->pModule; @@ -427,10 +427,10 @@ int res = 0; Expr *pLeft = pExpr->pLeft; Expr *pRight = pExpr->pRight; - if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){ + if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab) ){ res++; } - if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->pTab) ){ + if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab) ){ res++; SWAP(Expr*, pLeft, pRight); } @@ -1574,6 +1574,7 @@ pArgs = pItem->u1.pFuncArg; if( pArgs==0 ) return; for(j=k=0; j<pArgs->nExpr; j++){ + Expr *pRhs; while( k<pTab->nCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){k++;} if( k>=pTab->nCol ){ sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d", @@ -1584,9 +1585,10 @@ if( pColRef==0 ) return; pColRef->iTable = pItem->iCursor; pColRef->iColumn = k++; - pColRef->pTab = pTab; - pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, - sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0)); + pColRef->y.pTab = pTab; + pRhs = sqlite3PExpr(pParse, TK_UPLUS, + sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); + pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs); whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); } }
diff --git a/third_party/sqlite/src/src/window.c b/third_party/sqlite/src/src/window.c index bf02a0d..ec3d55ce 100644 --- a/third_party/sqlite/src/src/window.c +++ b/third_party/sqlite/src/src/window.c
@@ -624,12 +624,12 @@ switch( pExpr->op ){ case TK_FUNCTION: - if( pExpr->pWin==0 ){ + if( !ExprHasProperty(pExpr, EP_WinFunc) ){ break; }else{ Window *pWin; for(pWin=p->pWin; pWin; pWin=pWin->pNextWin){ - if( pExpr->pWin==pWin ){ + if( pExpr->y.pWin==pWin ){ assert( pWin->pOwner==pExpr ); return WRC_Prune; } @@ -746,7 +746,7 @@ */ int sqlite3WindowRewrite(Parse *pParse, Select *p){ int rc = SQLITE_OK; - if( p->pWin ){ + if( p->pWin && p->pPrior==0 ){ Vdbe *v = sqlite3GetVdbe(pParse); sqlite3 *db = pParse->db; Select *pSub = 0; /* The subquery */ @@ -959,11 +959,13 @@ */ void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){ if( p ){ + assert( p->op==TK_FUNCTION ); /* This routine is only called for the parser. If pWin was not ** allocated due to an OOM, then the parser would fail before ever ** invoking this routine */ if( ALWAYS(pWin) ){ - p->pWin = pWin; + p->y.pWin = pWin; + ExprSetProperty(p, EP_WinFunc); pWin->pOwner = p; if( p->flags & EP_Distinct ){ sqlite3ErrorMsg(pParse, @@ -2126,7 +2128,7 @@ */ Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){ Window *pNew = 0; - if( p ){ + if( ALWAYS(p) ){ pNew = sqlite3DbMallocZero(db, sizeof(Window)); if( pNew ){ pNew->zName = sqlite3DbStrDup(db, p->zName);
diff --git a/third_party/sqlite/src/test/alter.test b/third_party/sqlite/src/test/alter.test index fb22ec6..0741a7ce 100644 --- a/third_party/sqlite/src/test/alter.test +++ b/third_party/sqlite/src/test/alter.test
@@ -684,6 +684,7 @@ # alter-9.X - Special test: Make sure the sqlite_rename_column() and # rename_table() functions do not crash when handed bad input. # +sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_test alter-9.1 { execsql {SELECT SQLITE_RENAME_COLUMN(0,0,0,0,0,0,0,0,0)} } {{}} @@ -696,6 +697,14 @@ catch { execsql $sql } } 1 } +sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 + +# If the INTERNAL_FUNCTIONS test-control is disabled (which is the default), +# then the sqlite_rename_table() SQL function is not accessible to ordinary SQL. +# +do_catchsql_test alter-9.3 { + SELECT sqlite_rename_table(0,0,0,0,0,0,0); +} {1 {no such function: sqlite_rename_table}} #------------------------------------------------------------------------ # alter-10.X - Make sure ALTER TABLE works with multi-byte UTF-8 characters
diff --git a/third_party/sqlite/src/test/alter2.test b/third_party/sqlite/src/test/alter2.test index ffb5541..3a95479 100644 --- a/third_party/sqlite/src/test/alter2.test +++ b/third_party/sqlite/src/test/alter2.test
@@ -64,6 +64,7 @@ sqlite3 dbat test.db set s [string map {' ''} $sql] set t [string map {' ''} $tbl] + sqlite3_db_config dbat DEFENSIVE 0 dbat eval [subst { PRAGMA writable_schema = 1; UPDATE sqlite_master SET sql = '$s' WHERE name = '$t' AND type = 'table'; @@ -91,6 +92,7 @@ #----------------------------------------------------------------------- # Some basic tests to make sure short rows are handled. # +sqlite3_db_config db DEFENSIVE 0 do_test alter2-1.1 { execsql { CREATE TABLE abc(a, b);
diff --git a/third_party/sqlite/src/test/alterauth2.test b/third_party/sqlite/src/test/alterauth2.test new file mode 100644 index 0000000..0bd39e1 --- /dev/null +++ b/third_party/sqlite/src/test/alterauth2.test
@@ -0,0 +1,98 @@ +# 2018 October 6 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#************************************************************************* +# + +set testdir [file dirname $argv0] + +source $testdir/tester.tcl + +# If SQLITE_OMIT_ALTERTABLE is defined, omit this file. +ifcapable !altertable { + finish_test + return +} +set testprefix alterauth2 + +set ::auth [list] +proc xAuth {type args} { + lappend ::auth [concat $type [lrange $args 0 3]] + if {$type=="SQLITE_READ" && [lindex $args 0] == "t2"} breakpoint + return SQLITE_OK +} +db auth xAuth + +proc do_auth_test {tn sql authcode} { + set script " + set ::auth \[list\] + execsql {$sql} + lsort -unique \[set ::auth\] + " + + set normal [list {*}$authcode] + uplevel [list do_test $tn $script $normal] +} + +do_execsql_test 1.0 { + CREATE TABLE t1(a, b, c); + CREATE VIEW v1 AS SELECT * FROM t1; + CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN + DELETE FROM t1 WHERE a<new.a; + END; + + CREATE TEMP TRIGGER tr2 AFTER UPDATE OF a, b ON t1 BEGIN + UPDATE t1 SET a=a+1 WHERE new.b<b; + END; +} + +do_auth_test 1.1 { + ALTER TABLE t1 RENAME TO t2; +} { + {SQLITE_ALTER_TABLE main t1 {} {}} + {SQLITE_FUNCTION {} like {} {}} + {SQLITE_FUNCTION {} sqlite_rename_table {} {}} + {SQLITE_FUNCTION {} sqlite_rename_test {} {}} + {SQLITE_FUNCTION {} substr {} {}} + {SQLITE_READ sqlite_master name main {}} + {SQLITE_READ sqlite_master sql main {}} + {SQLITE_READ sqlite_master tbl_name main {}} + {SQLITE_READ sqlite_master type main {}} + {SQLITE_READ sqlite_temp_master name temp {}} + {SQLITE_READ sqlite_temp_master sql temp {}} + {SQLITE_READ sqlite_temp_master tbl_name temp {}} + {SQLITE_READ sqlite_temp_master type temp {}} + {SQLITE_SELECT {} {} {} {}} + {SQLITE_UPDATE sqlite_master name main {}} + {SQLITE_UPDATE sqlite_master sql main {}} + {SQLITE_UPDATE sqlite_master tbl_name main {}} + {SQLITE_UPDATE sqlite_temp_master sql temp {}} + {SQLITE_UPDATE sqlite_temp_master tbl_name temp {}} +} + +do_auth_test 1.2 { + ALTER TABLE t2 RENAME a TO aaa; +} { + {SQLITE_ALTER_TABLE main t2 {} {}} + {SQLITE_FUNCTION {} like {} {}} + {SQLITE_FUNCTION {} sqlite_rename_column {} {}} + {SQLITE_FUNCTION {} sqlite_rename_test {} {}} + {SQLITE_READ sqlite_master name main {}} + {SQLITE_READ sqlite_master sql main {}} + {SQLITE_READ sqlite_master tbl_name main {}} + {SQLITE_READ sqlite_master type main {}} + {SQLITE_READ sqlite_temp_master name temp {}} + {SQLITE_READ sqlite_temp_master sql temp {}} + {SQLITE_READ sqlite_temp_master type temp {}} + {SQLITE_SELECT {} {} {} {}} + {SQLITE_UPDATE sqlite_master sql main {}} + {SQLITE_UPDATE sqlite_temp_master sql temp {}} +} + +finish_test
diff --git a/third_party/sqlite/src/test/altercol.test b/third_party/sqlite/src/test/altercol.test index bb9c656..1ebaced33 100644 --- a/third_party/sqlite/src/test/altercol.test +++ b/third_party/sqlite/src/test/altercol.test
@@ -553,6 +553,7 @@ SELECT sql FROM sqlite_master WHERE name='x1i'; } {{CREATE INDEX x1i ON x1(i)}} +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 13.1.4 { PRAGMA writable_schema = 1; UPDATE sqlite_master SET sql = 'CREATE INDEX x1i ON x1(j)' WHERE name='x1i'; @@ -617,6 +618,7 @@ #------------------------------------------------------------------------- # Passing invalid parameters directly to sqlite_rename_column(). # +sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_execsql_test 14.1 { CREATE TABLE ddd(sql, type, object, db, tbl, icol, znew, bquote); INSERT INTO ddd VALUES( @@ -639,6 +641,15 @@ sqlite_rename_column(sql, type, object, db, tbl, icol, znew, bquote, 0) FROM ddd; } {{} {} {} {}} +sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 + +# If the INTERNAL_FUNCTIONS test-control is disabled (which is the default) +# then the sqlite_rename_table() SQL function is not accessible to +# ordinary SQL. +# +do_catchsql_test 14.3 { + SELECT sqlite_rename_column(0,0,0,0,0,0,0,0,0); +} {1 {no such function: sqlite_rename_column}} #------------------------------------------------------------------------- #
diff --git a/third_party/sqlite/src/test/alterlegacy.test b/third_party/sqlite/src/test/alterlegacy.test index 888bbb2b..ae81e87a 100644 --- a/third_party/sqlite/src/test/alterlegacy.test +++ b/third_party/sqlite/src/test/alterlegacy.test
@@ -467,4 +467,3 @@ finish_test -
diff --git a/third_party/sqlite/src/test/altermalloc.test b/third_party/sqlite/src/test/altermalloc.test index 70aa4e80..4a3db3e2 100644 --- a/third_party/sqlite/src/test/altermalloc.test +++ b/third_party/sqlite/src/test/altermalloc.test
@@ -19,7 +19,7 @@ source $testdir/tester.tcl # If SQLITE_OMIT_ALTERTABLE is defined, omit this file. -ifcapable !altertable||!memdebug { +ifcapable !altertable { finish_test return }
diff --git a/third_party/sqlite/src/test/altertab.test b/third_party/sqlite/src/test/altertab.test index f692730..8256b09 100644 --- a/third_party/sqlite/src/test/altertab.test +++ b/third_party/sqlite/src/test/altertab.test
@@ -240,11 +240,13 @@ ); } {} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_execsql_test 7.2 { SELECT sqlite_rename_table(db, 0, 0, sql, zOld, zNew, bTemp) FROM ddd; } {{} {} {}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 } #------------------------------------------------------------------------- @@ -459,7 +461,49 @@ ALTER TABLE t1 RENAME TO tt1; } +#------------------------------------------------------------------------- +reset_db +do_execsql_test 15.0 { + CREATE TABLE t1(a integer NOT NULL PRIMARY KEY); + CREATE VIEW v1 AS SELECT a FROM t1; + CREATE TRIGGER tr1 INSTEAD OF INSERT ON v1 BEGIN + UPDATE t1 SET a = NEW.a; + END; + CREATE TRIGGER tr2 INSTEAD OF INSERT ON v1 BEGIN + SELECT new.a; + END; + CREATE TABLE t2 (b); +} + +do_execsql_test 15.1 { + INSERT INTO v1 VALUES(1); + ALTER TABLE t2 RENAME TO t3; +} + +do_execsql_test 15.2 { + CREATE TABLE x(f1 integer NOT NULL); + CREATE VIEW y AS SELECT f1 AS f1 FROM x; + CREATE TRIGGER t INSTEAD OF UPDATE OF f1 ON y BEGIN + UPDATE x SET f1 = NEW.f1; + END; + CREATE TABLE z (f1 integer NOT NULL PRIMARY KEY); + ALTER TABLE z RENAME TO z2; +} + +do_execsql_test 15.3 { + INSERT INTO x VALUES(1), (2), (3); + ALTER TABLE x RENAME f1 TO f2; + SELECT * FROM x; +} {1 2 3} + +do_execsql_test 15.4 { + UPDATE y SET f1 = 'x' WHERE f1 = 1; + SELECT * FROM x; +} {x x x} + +do_execsql_test 15.5 { + SELECT sql FROM sqlite_master WHERE name = 'y'; +} {{CREATE VIEW y AS SELECT f2 AS f1 FROM x}} finish_test -
diff --git a/third_party/sqlite/src/test/altertab2.test b/third_party/sqlite/src/test/altertab2.test index 5656def..2e4212c35 100644 --- a/third_party/sqlite/src/test/altertab2.test +++ b/third_party/sqlite/src/test/altertab2.test
@@ -41,6 +41,49 @@ } {hello world in tcl} } +#------------------------------------------------------------------------- +# Check that table names that appear in REFERENCES clauses are updated +# when a table is renamed unless: +# +# a) "PRAGMA legacy_alter_table" is true, and +# b) "PRAGMA foreign_keys" is false. +# +do_execsql_test 2.0 { + CREATE TABLE p1(a PRIMARY KEY, b); + CREATE TABLE c1(x REFERENCES p1); + CREATE TABLE c2(x, FOREIGN KEY (x) REFERENCES p1); + CREATE TABLE c3(x, FOREIGN KEY (x) REFERENCES p1(a)); +} + +do_execsql_test 2.1 { + ALTER TABLE p1 RENAME TO p2; + SELECT sql FROM sqlite_master WHERE name LIKE 'c%'; +} { + {CREATE TABLE c1(x REFERENCES "p2")} + {CREATE TABLE c2(x, FOREIGN KEY (x) REFERENCES "p2")} + {CREATE TABLE c3(x, FOREIGN KEY (x) REFERENCES "p2"(a))} +} + +do_execsql_test 2.2 { + PRAGMA legacy_alter_table = 1; + ALTER TABLE p2 RENAME TO p3; + SELECT sql FROM sqlite_master WHERE name LIKE 'c%'; +} { + {CREATE TABLE c1(x REFERENCES "p2")} + {CREATE TABLE c2(x, FOREIGN KEY (x) REFERENCES "p2")} + {CREATE TABLE c3(x, FOREIGN KEY (x) REFERENCES "p2"(a))} +} + +do_execsql_test 2.3 { + ALTER TABLE p3 RENAME TO p2; + PRAGMA foreign_keys = 1; + ALTER TABLE p2 RENAME TO p3; + SELECT sql FROM sqlite_master WHERE name LIKE 'c%'; +} { + {CREATE TABLE c1(x REFERENCES "p3")} + {CREATE TABLE c2(x, FOREIGN KEY (x) REFERENCES "p3")} + {CREATE TABLE c3(x, FOREIGN KEY (x) REFERENCES "p3"(a))} +} + finish_test -
diff --git a/third_party/sqlite/src/test/analyze.test b/third_party/sqlite/src/test/analyze.test index e2332830..97e524a 100644 --- a/third_party/sqlite/src/test/analyze.test +++ b/third_party/sqlite/src/test/analyze.test
@@ -350,6 +350,7 @@ # in the series. # do_test analyze-5.99 { + sqlite3_db_config db DEFENSIVE 0 execsql { PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='nonsense' WHERE name='sqlite_stat1';
diff --git a/third_party/sqlite/src/test/attach.test b/third_party/sqlite/src/test/attach.test index 3960ac4..c1f2adf 100644 --- a/third_party/sqlite/src/test/attach.test +++ b/third_party/sqlite/src/test/attach.test
@@ -726,6 +726,32 @@ } db2 } {1 {trigger r5 cannot reference objects in database temp}} } ;# endif subquery +ifcapable json1&&vtab { + do_test attach-5.10 { + db close + catch {db2 close} + forcedelete test.db + sqlite3 db test.db + db eval { + CREATE TABLE t1(x); + CREATE TABLE t2(a,b); + CREATE TRIGGER x1 AFTER INSERT ON t1 BEGIN + INSERT INTO t2(a,b) SELECT key, value FROM json_each(NEW.x); + END; + INSERT INTO t1(x) VALUES('{"a":1}'); + SELECT * FROM t2; + } + } {a 1} + do_test attach-5.11 { + sqlite3 db2 :memory: + db2 eval { + CREATE TABLE t3(y); + ATTACH 'test.db' AS aux; + INSERT INTO aux.t1(x) VALUES('{"b":2}'); + SELECT * FROM aux.t2; + } + } {a 1 b 2} +} ;# endif json1 } ;# endif trigger # Check to make sure we get a sensible error if unable to open
diff --git a/third_party/sqlite/src/test/attachmalloc.test b/third_party/sqlite/src/test/attachmalloc.test index 7fee1e1..7a82f41 100644 --- a/third_party/sqlite/src/test/attachmalloc.test +++ b/third_party/sqlite/src/test/attachmalloc.test
@@ -18,7 +18,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -ifcapable !memdebug||!attach { +ifcapable !attach { finish_test return }
diff --git a/third_party/sqlite/src/test/autoinc.test b/third_party/sqlite/src/test/autoinc.test index ba39bc0..ab07c92 100644 --- a/third_party/sqlite/src/test/autoinc.test +++ b/third_party/sqlite/src/test/autoinc.test
@@ -697,6 +697,7 @@ db close forcedelete test.db sqlite3 db test.db + sqlite3_db_config db DEFENSIVE 0 db eval { CREATE TABLE fake_sequence(name TEXT PRIMARY KEY,seq) WITHOUT ROWID; PRAGMA writable_schema=on; @@ -718,6 +719,7 @@ db close forcedelete test.db sqlite3 db test.db + sqlite3_db_config db DEFENSIVE 0 db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); @@ -744,6 +746,7 @@ db close forcedelete test.db sqlite3 db test.db + sqlite3_db_config db DEFENSIVE 0 db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); @@ -772,6 +775,7 @@ WHERE name='sqlite_sequence'}] set root2 [db one {SELECT rootpage FROM sqlite_master WHERE name='fake'}] + sqlite3_db_config db DEFENSIVE 0 db eval { PRAGMA writable_schema=on; UPDATE sqlite_master SET rootpage=$root2 @@ -791,6 +795,7 @@ db close forcedelete test.db sqlite3 db test.db + sqlite3_db_config db DEFENSIVE 0 db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); @@ -810,6 +815,7 @@ db close forcedelete test.db sqlite3 db test.db + sqlite3_db_config db DEFENSIVE 0 db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one'); @@ -831,6 +837,7 @@ db close forcedelete test.db sqlite3 db test.db + sqlite3_db_config db DEFENSIVE 0 db eval { CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); INSERT INTO t1(b) VALUES('one');
diff --git a/third_party/sqlite/src/test/autoindex5.test b/third_party/sqlite/src/test/autoindex5.test index 2bda408..d367767 100644 --- a/third_party/sqlite/src/test/autoindex5.test +++ b/third_party/sqlite/src/test/autoindex5.test
@@ -124,5 +124,90 @@ ) FROM one; } {8.0} +# Ticket https://www.sqlite.org/src/info/787fa716be3a7f65 +# Segfault due to multiple uses of the same subquery where the +# subquery is implemented via coroutine. +# +sqlite3 db :memory: +do_execsql_test 3.0 { + -- This is the original test case reported on the mailing list + CREATE TABLE artists ( + id integer NOT NULL PRIMARY KEY AUTOINCREMENT, + name varchar(255) + ); + CREATE TABLE albums ( + id integer NOT NULL PRIMARY KEY AUTOINCREMENT, + name varchar(255), + artist_id integer REFERENCES artists + ); + INSERT INTO artists (name) VALUES ('Ar'); + INSERT INTO albums (name, artist_id) VALUES ('Al', 1); + SELECT artists.* + FROM artists + INNER JOIN artists AS 'b' ON (b.id = artists.id) + WHERE (artists.id IN ( + SELECT albums.artist_id + FROM albums + WHERE ((name = 'Al') + AND (albums.artist_id IS NOT NULL) + AND (albums.id IN ( + SELECT id + FROM ( + SELECT albums.id, + row_number() OVER ( + PARTITION BY albums.artist_id + ORDER BY name + ) AS 'x' + FROM albums + WHERE (name = 'Al') + ) AS 't1' + WHERE (x = 1) + )) + AND (albums.id IN (1, 2))) + )); +} {1 Ar} +# The remaining test cases were discovered (by Dan) during trouble-shooting +sqlite3 db :memory: +do_execsql_test 3.1 { + CREATE TABLE t1 (a); INSERT INTO t1 (a) VALUES (104); + CREATE TABLE t2 (b); INSERT INTO t2 (b) VALUES (104); + CREATE TABLE t3 (c); INSERT INTO t3 (c) VALUES (104); + CREATE TABLE t4 (d); INSERT INTO t4 (d) VALUES (104); + SELECT * + FROM t1 CROSS JOIN t2 ON (t1.a = t2.b) WHERE t2.b IN ( + SELECT t3.c + FROM t3 + WHERE t3.c IN ( + SELECT d FROM (SELECT DISTINCT d FROM t4) AS x WHERE x.d=104 + ) + ); +} {104 104} +sqlite3 db :memory: +do_execsql_test 3.2 { + CREATE TABLE t5(a, b, c, d); + CREATE INDEX t5a ON t5(a); + CREATE INDEX t5b ON t5(b); + CREATE TABLE t6(e); + INSERT INTO t6 VALUES(1); + INSERT INTO t5 VALUES(1,1,1,1), (2,2,2,2); + SELECT * FROM t5 WHERE (a=1 OR b=2) AND c IN ( + SELECT e FROM (SELECT DISTINCT e FROM t6) WHERE e=1 + ); +} {1 1 1 1} +sqlite3 db :memory: +do_execsql_test 3.3 { + CREATE TABLE t1(a1, a2, a3); + CREATE INDEX t1a2 ON t1(a2, a1); + CREATE INDEX t1a3 ON t1(a3, a1); + CREATE TABLE t2(d); + INSERT INTO t1 VALUES(3, 1, 1), (3, 2, 2); + INSERT INTO t2 VALUES(3); + SELECT *, 'x' FROM t1 WHERE (a2=1 OR a3=2) AND a1 = ( + SELECT d FROM (SELECT DISTINCT d FROM t2) WHERE d=3 + ); +} {3 1 1 x 3 2 2 x} + + + finish_test
diff --git a/third_party/sqlite/src/test/bestindex4.test b/third_party/sqlite/src/test/bestindex4.test index 482714a..91b4be6 100644 --- a/third_party/sqlite/src/test/bestindex4.test +++ b/third_party/sqlite/src/test/bestindex4.test
@@ -117,4 +117,59 @@ } } +#------------------------------------------------------------------------- +# Test that a parameter passed to a table-valued function cannot be +# used to drive an index. i.e. that in the following: +# +# SELECT * FROM tbl, vtab(tbl.x); +# +# The implicit constraint "tbl.x = vtab.hidden" is not optimized using +# an index on tbl.x. +# +reset_db +register_tcl_module db +proc vtab_command {method args} { + switch -- $method { + xConnect { + return "CREATE TABLE t1(a, b, c, d HIDDEN)" + } + + xBestIndex { + set clist [lindex $args 0] + if {[llength $clist]!=1} { error "unexpected constraint list" } + catch { array unset C } + array set C [lindex $clist 0] + if {$C(usable)} { + return [list omit 0 idxnum 555 rows 10 cost 100] + } + return [list cost 100000000] + } + + } + + return {} +} + +do_execsql_test 2.0 { + CREATE VIRTUAL TABLE x1 USING tcl(vtab_command); + CREATE TABLE t1 (x INT PRIMARY KEY); +} {} + +do_eqp_test 2.1 { + SELECT * FROM t1, x1 WHERE x1.d=t1.x; +} { + QUERY PLAN + |--SCAN TABLE x1 VIRTUAL TABLE INDEX 0: + `--SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (x=?) +} + +do_eqp_test 2.2 { + SELECT * FROM t1, x1(t1.x) +} { + QUERY PLAN + |--SCAN TABLE t1 + `--SCAN TABLE x1 VIRTUAL TABLE INDEX 555: +} + + finish_test
diff --git a/third_party/sqlite/src/test/bestindex5.test b/third_party/sqlite/src/test/bestindex5.test index 0f1a669..728f8185 100644 --- a/third_party/sqlite/src/test/bestindex5.test +++ b/third_party/sqlite/src/test/bestindex5.test
@@ -247,4 +247,3 @@ finish_test -
diff --git a/third_party/sqlite/src/test/capi3.test b/third_party/sqlite/src/test/capi3.test index ebf937f..1c93c47 100644 --- a/third_party/sqlite/src/test/capi3.test +++ b/third_party/sqlite/src/test/capi3.test
@@ -741,6 +741,7 @@ } {} do_test capi3-8.2 { sqlite3 db test.db + sqlite3_db_config db DEFENSIVE 0 execsql { PRAGMA writable_schema=ON; INSERT INTO sqlite_master VALUES(NULL,NULL,NULL,NULL,NULL); @@ -759,6 +760,7 @@ db close forcedelete test.db test.db-journal sqlite3 db test.db + sqlite3_db_config db DEFENSIVE 0 execsql { CREATE TABLE t1(a); PRAGMA writable_schema=ON; @@ -811,7 +813,6 @@ # Test the error message when a "real" out of memory occurs. if { [permutation] != "nofaultsim" } { -ifcapable memdebug { do_test capi3-10-1 { sqlite3 db test.db set DB [sqlite3_connection_pointer db] @@ -849,7 +850,6 @@ db close sqlite3_memdebug_fail -1 } -} # The following tests - capi3-11.* - test that a COMMIT or ROLLBACK # statement issued while there are still outstanding VMs that are part of
diff --git a/third_party/sqlite/src/test/capi3c.test b/third_party/sqlite/src/test/capi3c.test index 1bedec1..ed70b69 100644 --- a/third_party/sqlite/src/test/capi3c.test +++ b/third_party/sqlite/src/test/capi3c.test
@@ -686,6 +686,7 @@ } {} do_test capi3c-8.2 { sqlite3 db test.db + sqlite3_db_config db DEFENSIVE 0 execsql { PRAGMA writable_schema=ON; INSERT INTO sqlite_master VALUES(NULL,NULL,NULL,NULL,NULL); @@ -704,6 +705,7 @@ db close forcedelete test.db test.db-journal sqlite3 db test.db + sqlite3_db_config db DEFENSIVE 0 execsql { CREATE TABLE t1(a); PRAGMA writable_schema=ON; @@ -757,7 +759,6 @@ # Test the error message when a "real" out of memory occurs. if { [permutation] != "nofaultsim" } { -ifcapable memdebug { do_test capi3c-10-1 { sqlite3 db test.db set DB [sqlite3_connection_pointer db] @@ -777,7 +778,6 @@ db close sqlite3_memdebug_fail -1 } -} # The following tests - capi3c-11.* - test that a COMMIT or ROLLBACK # statement issued while there are still outstanding VMs that are part of
diff --git a/third_party/sqlite/src/test/corrupt.test b/third_party/sqlite/src/test/corrupt.test index 7ce909ce..eac5b9b1 100644 --- a/third_party/sqlite/src/test/corrupt.test +++ b/third_party/sqlite/src/test/corrupt.test
@@ -132,6 +132,7 @@ set t1_r [execsql {SELECT rootpage FROM sqlite_master WHERE name = 't1i1'}] set t1i1_r [execsql {SELECT rootpage FROM sqlite_master WHERE name = 't1'}] set cookie [expr [execsql {PRAGMA schema_version}] + 1] + sqlite3_db_config db DEFENSIVE 0 execsql " PRAGMA writable_schema = 1; UPDATE sqlite_master SET rootpage = $t1_r WHERE name = 't1';
diff --git a/third_party/sqlite/src/test/corrupt2.test b/third_party/sqlite/src/test/corrupt2.test index 5941fe8..a5d2405 100644 --- a/third_party/sqlite/src/test/corrupt2.test +++ b/third_party/sqlite/src/test/corrupt2.test
@@ -133,6 +133,7 @@ forcecopy test.db corrupt.db sqlite3 db2 corrupt.db + sqlite3_db_config db2 DEFENSIVE 0 execsql " $::presql CREATE INDEX a1 ON abc(a); @@ -265,6 +266,7 @@ forcedelete corrupt.db-journal sqlite3 db corrupt.db + sqlite3_db_config db DEFENSIVE 0 db eval $::presql eval $A(-tclprep) db eval $A(-sqlprep)
diff --git a/third_party/sqlite/src/test/corrupt5.test b/third_party/sqlite/src/test/corrupt5.test index 09d236a7..f21a9c6 100644 --- a/third_party/sqlite/src/test/corrupt5.test +++ b/third_party/sqlite/src/test/corrupt5.test
@@ -33,6 +33,7 @@ # Create a database with a freelist containing at least two pages. # do_test corrupt5-1.1 { + sqlite3_db_config db DEFENSIVE 0 execsql { CREATE TABLE t1(a,b,c); CREATE INDEX i1 ON t1(a,b);
diff --git a/third_party/sqlite/src/test/corruptI.test b/third_party/sqlite/src/test/corruptI.test index 11266969..33197159 100644 --- a/third_party/sqlite/src/test/corruptI.test +++ b/third_party/sqlite/src/test/corruptI.test
@@ -222,6 +222,7 @@ INSERT INTO t1 VALUES('c', 'A'); SELECT name FROM sqlite_master; } {t1 sqlite_autoindex_t1_1} +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 7.1 { PRAGMA writable_schema = 1; DELETE FROM sqlite_master WHERE name = 'sqlite_autoindex_t1_1';
diff --git a/third_party/sqlite/src/test/corruptK.test b/third_party/sqlite/src/test/corruptK.test index 9bbc470..7c65cb0 100644 --- a/third_party/sqlite/src/test/corruptK.test +++ b/third_party/sqlite/src/test/corruptK.test
@@ -143,7 +143,7 @@ CREATE TABLE t4(a, b, c); CREATE TABLE t5(a, b, c); } - + sqlite3_db_config db DEFENSIVE 0 do_execsql_test 3.2 { UPDATE sqlite_dbpage SET data = hex2blob(' 000: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
diff --git a/third_party/sqlite/src/test/countofview.test b/third_party/sqlite/src/test/countofview.test index 04fadb4..f12af85 100644 --- a/third_party/sqlite/src/test/countofview.test +++ b/third_party/sqlite/src/test/countofview.test
@@ -41,4 +41,3 @@ } {3} finish_test -
diff --git a/third_party/sqlite/src/test/crash5.test b/third_party/sqlite/src/test/crash5.test index 4027a4e..c5becc8 100644 --- a/third_party/sqlite/src/test/crash5.test +++ b/third_party/sqlite/src/test/crash5.test
@@ -20,7 +20,7 @@ # Only run these tests if memory debugging is turned on. # -ifcapable !memdebug||!crashtest||!memorymanage { +ifcapable !crashtest||!memorymanage { puts "Skipping crash5 tests: not compiled with -DSQLITE_MEMDEBUG..." finish_test return
diff --git a/third_party/sqlite/src/test/csv01.test b/third_party/sqlite/src/test/csv01.test index 4c0389c3..472a87ec1 100644 --- a/third_party/sqlite/src/test/csv01.test +++ b/third_party/sqlite/src/test/csv01.test
@@ -38,6 +38,63 @@ SELECT rowid FROM t1; } {1 2 3 4} +do_execsql_test 1.3 { + DROP TABLE temp.t1; + CREATE VIRTUAL TABLE temp.t1 USING csv( + data= +'a,b,"mix-bloom-eel","soft opinion" +1,2,3,4 +5,6,7,8 +9,10,11,12 +13,14,15,16 +', + header=1 + ); + SELECT * FROM t1 WHERE "soft opinion"=12; +} {9 10 11 12} +do_execsql_test 1.4 { + SELECT name FROM pragma_table_xinfo('t1'); +} {a b mix-bloom-eel {soft opinion}} + +do_execsql_test 1.5 { + DROP TABLE temp.t1; + CREATE VIRTUAL TABLE temp.t1 USING csv( + data= +'a,b,"mix-bloom-eel","soft opinion" +1,2,3,4 +5,6,7,8 +9,10,11,12 +13,14,15,16 +', + header=false + ); + SELECT * FROM t1 WHERE c1='b'; +} {a b mix-bloom-eel {soft opinion}} +do_execsql_test 1.6 { + SELECT name FROM pragma_table_xinfo('t1'); +} {c0 c1 c2 c3} + +do_execsql_test 1.7 { + DROP TABLE temp.t1; + CREATE VIRTUAL TABLE temp.t1 USING csv( + data= +'a,b,"mix-bloom-eel","soft opinion" +1,2,3,4 +5,6,7,8 +9,10,11,12 +13,14,15,16 +', + header, + schema='CREATE TABLE x(x0,x1,x2,x3,x4)', + columns=5 + ); + SELECT * FROM t1 WHERE x1='6'; +} {5 6 7 8 {}} +do_execsql_test 1.8 { + SELECT name FROM pragma_table_xinfo('t1'); +} {x0 x1 x2 x3 x4} + + do_execsql_test 2.0 { DROP TABLE t1; CREATE VIRTUAL TABLE temp.t2 USING csv( @@ -107,7 +164,7 @@ 'CREATE TABLE t3(a,b,c,d,PRIMARY KEY(a,b)) WITHOUT ROWID', testflags=1 ); -} {1 {vtable constructor failed: t4}} +} {1 {bad schema: 'CREATE TABLE t3(a,b,c,d,PRIMARY KEY(a,b)) WITHOUT ROWID' - not an error}} # WITHOUT ROWID tables with a single-column PRIMARY KEY may be writable. do_catchsql_test 4.1 { @@ -138,7 +195,7 @@ 'CREATE TABLE t3(a,b,c,d) WITHOUT ROWID', testflags=1 ); -} {1 {vtable constructor failed: t5}} +} {1 {bad schema: 'CREATE TABLE t3(a,b,c,d) WITHOUT ROWID' - PRIMARY KEY missing on table t3}} # 2018-04-24 # Memory leak reported on the sqlite-users mailing list by Ralf Junker.
diff --git a/third_party/sqlite/src/test/dbfuzz2-seed1.db b/third_party/sqlite/src/test/dbfuzz2-seed1.db new file mode 100644 index 0000000..17f0550 --- /dev/null +++ b/third_party/sqlite/src/test/dbfuzz2-seed1.db Binary files differ
diff --git a/third_party/sqlite/src/test/dbfuzz2.c b/third_party/sqlite/src/test/dbfuzz2.c new file mode 100644 index 0000000..4ec43302 --- /dev/null +++ b/third_party/sqlite/src/test/dbfuzz2.c
@@ -0,0 +1,141 @@ +/* +** 2018-10-26 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This program is designed for fuzz-testing SQLite database files using +** the -fsanitize=fuzzer option of clang. +** +** The -fsanitize=fuzzer option causes a main() to be inserted automatically. +** That main() invokes LLVMFuzzerTestOneInput(D,S) to be invoked repeatedly. +** Each D is a fuzzed database file. The code in this file runs various +** SQL statements against that database, trying to provoke a failure. +** +** For best results the seed database files should have these tables: +** +** Table "t1" with columns "a" and "b" +** Tables "t2" and "t3 with the same number of compatible columns +** "t3" should have a column names "x" +** Table "t4" with a column "x" that is compatible with t3.x. +** +** Any of these tables can be virtual tables, for example FTS or RTree tables. +** +** To run this test: +** +** mkdir dir +** cp dbfuzz2-seed*.db dir +** clang-6.0 -I. -g -O1 -fsanitize=fuzzer \ +** -DTHREADSAFE=0 -DSQLITE_ENABLE_DESERIALIZE \ +** -DSQLITE_ENABLE_DBSTAT_VTAB dbfuzz2.c sqlite3.c -ldl +** ./a.out dir +*/ +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <ctype.h> +#include <stdint.h> +#include "sqlite3.h" + +/* +** This is the is the SQL that is run against the database. +*/ +static const char *azSql[] = { + "PRAGMA integrity_check;", + "SELECT * FROM sqlite_master;", + "SELECT sum(length(name)) FROM dbstat;", + "UPDATE t1 SET b=a, a=b WHERE a<b;", + "ALTER TABLE t1 RENAME TO alkjalkjdfiiiwuer987lkjwer82mx97sf98788s9789s;", + "INSERT INTO t3 SELECT * FROM t2;", + "DELETE FROM t3 WHERE x IN (SELECT x FROM t4);", +#if !defined(SQLITE_OMIT_REINDEX) + "REINDEX;", +#endif + "DROP TABLE t3;", + "VACUUM;", +}; + +/* Output verbosity level. 0 means complete silence */ +int eVerbosity = 0; + +/* libFuzzer invokes this routine with fuzzed database files (in aData). +** This routine run SQLite against the malformed database to see if it +** can provoke a failure or malfunction. +*/ +int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){ + unsigned char *a; + sqlite3 *db; + int rc; + int i; + + if( eVerbosity>=1 ){ + printf("************** nByte=%d ***************\n", (int)nByte); + fflush(stdout); + } + if( sqlite3_initialize() ) return 0; + rc = sqlite3_open(0, &db); + if( rc ) return 1; + a = sqlite3_malloc64(nByte+1); + if( a==0 ) return 1; + memcpy(a, aData, nByte); + sqlite3_deserialize(db, "main", a, nByte, nByte, + SQLITE_DESERIALIZE_RESIZEABLE | + SQLITE_DESERIALIZE_FREEONCLOSE); + for(i=0; i<sizeof(azSql)/sizeof(azSql[0]); i++){ + if( eVerbosity>=1 ){ + printf("%s\n", azSql[i]); + fflush(stdout); + } + sqlite3_exec(db, azSql[i], 0, 0, 0); + } + rc = sqlite3_close(db); + if( rc!=SQLITE_OK ){ + fprintf(stdout, "sqlite3_close() returns %d\n", rc); + } + if( sqlite3_memory_used()!=0 ){ + int nAlloc = 0; + int nNotUsed = 0; + sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &nAlloc, &nNotUsed, 0); + fprintf(stderr,"Memory leak: %lld bytes in %d allocations\n", + sqlite3_memory_used(), nAlloc); + exit(1); + } + return 0; +} + +/* libFuzzer invokes this routine once when the executable starts, to +** process the command-line arguments. +*/ +int LLVMFuzzerInitialize(int *pArgc, char ***pArgv){ + int i, j; + int argc = *pArgc; + char **newArgv; + char **argv = *pArgv; + newArgv = malloc( sizeof(char*)*(argc+1) ); + if( newArgv==0 ) return 0; + newArgv[0] = argv[0]; + for(i=j=1; i<argc; i++){ + char *z = argv[i]; + if( z[0]=='-' ){ + z++; + if( z[0]=='-' ) z++; + if( strcmp(z,"v")==0 ){ + eVerbosity++; + continue; + } + } + newArgv[j++] = argv[i]; + } + newArgv[j] = 0; + *pArgv = newArgv; + *pArgc = j; + return 0; +}
diff --git a/third_party/sqlite/src/test/dbpage.test b/third_party/sqlite/src/test/dbpage.test index 93ae2a9..faffff5 100644 --- a/third_party/sqlite/src/test/dbpage.test +++ b/third_party/sqlite/src/test/dbpage.test
@@ -21,6 +21,7 @@ return } +sqlite3_db_config db DEFENSIVE 0 do_test 100 { execsql { PRAGMA auto_vacuum=0;
diff --git a/third_party/sqlite/src/test/dbstatus.test b/third_party/sqlite/src/test/dbstatus.test index f6b5cab8..37676e3 100644 --- a/third_party/sqlite/src/test/dbstatus.test +++ b/third_party/sqlite/src/test/dbstatus.test
@@ -379,9 +379,9 @@ # The following tests focus on DBSTATUS_CACHE_USED_SHARED # ifcapable shared_cache { - if {[permutation]=="memsys3" + if {([permutation]=="memsys3" || [permutation]=="memsys5" - || $::tcl_platform(os)=="Linux"} { + || $::tcl_platform(os)=="Linux") && ![sqlite3 -has-codec]} { proc do_cacheused_test {tn db res} { set cu [sqlite3_db_status $db SQLITE_DBSTATUS_CACHE_USED 0] set pcu [sqlite3_db_status $db SQLITE_DBSTATUS_CACHE_USED_SHARED 0]
diff --git a/third_party/sqlite/src/test/default.test b/third_party/sqlite/src/test/default.test index 82e99f5..77fa88cf 100644 --- a/third_party/sqlite/src/test/default.test +++ b/third_party/sqlite/src/test/default.test
@@ -106,6 +106,7 @@ db close forcedelete test.db sqlite3 db test.db +sqlite3_db_config db DEFENSIVE 0 do_execsql_test default-4.0 { CREATE TABLE t1(a TEXT, b TEXT DEFAULT(99)); PRAGMA writable_schema=ON;
diff --git a/third_party/sqlite/src/test/e_fkey.test b/third_party/sqlite/src/test/e_fkey.test index 467c676..1f054dd 100644 --- a/third_party/sqlite/src/test/e_fkey.test +++ b/third_party/sqlite/src/test/e_fkey.test
@@ -2797,12 +2797,14 @@ do_test e_fkey-61.2.2 { execsql { PRAGMA foreign_keys = OFF; + PRAGMA legacy_alter_table = ON; ALTER TABLE p RENAME TO parent; SELECT sql FROM sqlite_master WHERE name = 'c'; } } {{CREATE TABLE c(b REFERENCES p(a))}} do_test e_fkey-61.2.3 { execsql { PRAGMA foreign_keys = ON } + execsql { PRAGMA legacy_alter_table = OFF } } {} do_test e_fkey-61.3.1 {
diff --git a/third_party/sqlite/src/test/e_fts3.test b/third_party/sqlite/src/test/e_fts3.test index 92662d6..873a37df 100644 --- a/third_party/sqlite/src/test/e_fts3.test +++ b/third_party/sqlite/src/test/e_fts3.test
@@ -677,6 +677,7 @@ INSERT INTO ta VALUES('During a summer vacation in 1790') } write_test 10.1.3 ta_content { INSERT INTO ta VALUES('Wordsworth went on a walking tour') } +sqlite3_db_config db DEFENSIVE 0 write_test 10.1.4 ta_content { DELETE FROM ta_content WHERE rowid = 2 } read_test 10.1.5 { SELECT * FROM ta WHERE ta MATCH 'summer'
diff --git a/third_party/sqlite/src/test/e_reindex.test b/third_party/sqlite/src/test/e_reindex.test index 8296a66d..f774215c 100644 --- a/third_party/sqlite/src/test/e_reindex.test +++ b/third_party/sqlite/src/test/e_reindex.test
@@ -44,6 +44,7 @@ # Test this by corrupting some database indexes, running REINDEX, and # observing that the corruption is gone. # +sqlite3_db_config db DEFENSIVE 0 do_execsql_test e_reindex-1.1 { INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); @@ -57,6 +58,7 @@ db close sqlite3 db test.db +sqlite3_db_config db DEFENSIVE 0 do_execsql_test e_reindex-1.2 { DELETE FROM t1 WHERE a = 3; INSERT INTO t1 VALUES(7, 8);
diff --git a/third_party/sqlite/src/test/fkey2.test b/third_party/sqlite/src/test/fkey2.test index 2054726f..6e15829 100644 --- a/third_party/sqlite/src/test/fkey2.test +++ b/third_party/sqlite/src/test/fkey2.test
@@ -987,6 +987,7 @@ 'main', 'table', 't1', $zCreate, $zOld, $zNew, 0 )} } + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_test fkey2-14.2.1.1 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} @@ -996,6 +997,7 @@ do_test fkey2-14.2.1.3 { test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 # Test ALTER TABLE RENAME TABLE a bit. # @@ -1068,6 +1070,7 @@ } } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_test fkey2-14.2tmp.1.1 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} @@ -1077,6 +1080,7 @@ do_test fkey2-14.2tmp.1.3 { test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 # Test ALTER TABLE RENAME TABLE a bit. # @@ -1150,6 +1154,7 @@ } } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_test fkey2-14.2aux.1.1 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} @@ -1159,6 +1164,7 @@ do_test fkey2-14.2aux.1.3 { test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 # Test ALTER TABLE RENAME TABLE a bit. #
diff --git a/third_party/sqlite/src/test/fts3auto.test b/third_party/sqlite/src/test/fts3auto.test index 7c0d77f9..c5eb25c 100644 --- a/third_party/sqlite/src/test/fts3auto.test +++ b/third_party/sqlite/src/test/fts3auto.test
@@ -134,6 +134,7 @@ # fts3_zero_long_segments TABLE ?LIMIT? # proc fts3_zero_long_segments {tbl limit} { + sqlite3_db_config db DEFENSIVE 0 execsql " UPDATE ${tbl}_segments SET block = zeroblob(length(block))
diff --git a/third_party/sqlite/src/test/fts3corrupt.test b/third_party/sqlite/src/test/fts3corrupt.test index e933a0a..12ebae9 100644 --- a/third_party/sqlite/src/test/fts3corrupt.test +++ b/third_party/sqlite/src/test/fts3corrupt.test
@@ -23,6 +23,7 @@ # extends past the end of the node on which it resides is correctly identified # as database corruption. # +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.0 { CREATE VIRTUAL TABLE t1 USING fts3; INSERT INTO t1 VALUES('hello');
diff --git a/third_party/sqlite/src/test/fts3corrupt2.test b/third_party/sqlite/src/test/fts3corrupt2.test index 78c76778f..40783fa 100644 --- a/third_party/sqlite/src/test/fts3corrupt2.test +++ b/third_party/sqlite/src/test/fts3corrupt2.test
@@ -49,6 +49,7 @@ "acvmldguld asdvz aqb aeomsyzyu aggylhprbdz asrfkwz auipybpsn agsnszzfb" } +sqlite3_db_config db DEFENSIVE 0 do_test fts3corrupt2-1.0 { execsql BEGIN execsql { CREATE VIRTUAL TABLE t2 USING FTS3(a, b); }
diff --git a/third_party/sqlite/src/test/fts3corrupt3.test b/third_party/sqlite/src/test/fts3corrupt3.test index 6c846e9..eae13f2 100644 --- a/third_party/sqlite/src/test/fts3corrupt3.test +++ b/third_party/sqlite/src/test/fts3corrupt3.test
@@ -33,6 +33,7 @@ do_execsql_test 1.1 { SELECT quote(root) from t1_segdir; } {X'00036F6E6509010200010200010200'} +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.2 { UPDATE t1_segdir SET root = X'00036F6E650EFFFFFFFFFFFFFFFFFFFFFFFF0200'; }
diff --git a/third_party/sqlite/src/test/fts3corrupt4.test b/third_party/sqlite/src/test/fts3corrupt4.test index c40ce47..f3e1d71 100644 --- a/third_party/sqlite/src/test/fts3corrupt4.test +++ b/third_party/sqlite/src/test/fts3corrupt4.test
@@ -40,6 +40,7 @@ SELECT quote(root) FROM ft_segdir; } {X'0005616261636B03010200030266740302020003046E646F6E03030200'} +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.2 { UPDATE ft_segdir SET root = blob( '0005616261636B03010200 FFFFFFFF0702 66740302020003046E646F6E03030200' @@ -83,6 +84,7 @@ } {X'00056162633130031F0200'} db func blob blob +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 2.3.1 { UPDATE ft_segments SET block = blob('00056162633130031F0200 FFFFFFFF07FF55 66740302020003046E646F6E03030200') @@ -133,6 +135,7 @@ } {X'0101056162633132040136030132030136'} db func blob blob +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 3.2 { UPDATE ft_segdir SET root = blob('0101056162633132FFFFFFFF070236030132030136'); @@ -143,5 +146,3 @@ } {1 {database disk image is malformed}} finish_test - -
diff --git a/third_party/sqlite/src/test/fts3cov.test b/third_party/sqlite/src/test/fts3cov.test index bff9a09..f3786b8 100644 --- a/third_party/sqlite/src/test/fts3cov.test +++ b/third_party/sqlite/src/test/fts3cov.test
@@ -89,6 +89,7 @@ } {03} # Test the "missing entry" case: +sqlite3_db_config db DEFENSIVE 0 do_test fts3cov-2.2 { set root [db one {SELECT root FROM t1_segdir}] read_fts3varint [string range $root 1 end] left_child @@ -405,6 +406,7 @@ # Test a corruption case. # +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 16.1 { CREATE VIRTUAL TABLE t16 USING fts4; INSERT INTO t16 VALUES('theoretical work to examine the relationship');
diff --git a/third_party/sqlite/src/test/fts3d.test b/third_party/sqlite/src/test/fts3d.test index 436d191..a375725 100644 --- a/third_party/sqlite/src/test/fts3d.test +++ b/third_party/sqlite/src/test/fts3d.test
@@ -296,6 +296,7 @@ } {{Index already optimal} 1 0} # Even if we move things around, still does nothing. +sqlite3_db_config db DEFENSIVE 0 do_test fts3d-5.1 { execsql { UPDATE t1_segdir SET level = 2 WHERE level = 1 AND idx = 0;
diff --git a/third_party/sqlite/src/test/fts3defer.test b/third_party/sqlite/src/test/fts3defer.test index 7f33917..d801dd16 100644 --- a/third_party/sqlite/src/test/fts3defer.test +++ b/third_party/sqlite/src/test/fts3defer.test
@@ -59,6 +59,7 @@ do_select_tests 1.2 $tests +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.3 { SELECT count(*) FROM t1_segments WHERE length(block)>10000; UPDATE t1_segments @@ -225,6 +226,7 @@ execsql { CREATE VIRTUAL TABLE t1 USING FTS4 } foreach doc $data { execsql { INSERT INTO t1 VALUES($doc) } } add_empty_records 1000 + sqlite3_db_config db DEFENSIVE 0 execsql $zero_long_doclists } 4 { @@ -233,6 +235,7 @@ foreach doc $data { execsql { INSERT INTO t1 VALUES($doc) } } add_empty_records 1000 execsql "INSERT INTO t1(t1) VALUES('optimize')" + sqlite3_db_config db DEFENSIVE 0 execsql $zero_long_doclists } 5 { @@ -240,6 +243,7 @@ execsql { CREATE VIRTUAL TABLE t1 USING FTS4(matchinfo=fts3) } foreach doc $data { execsql { INSERT INTO t1 VALUES($doc) } } add_empty_records 1000 + sqlite3_db_config db DEFENSIVE 0 execsql $zero_long_doclists } } {
diff --git a/third_party/sqlite/src/test/fts3defer2.test b/third_party/sqlite/src/test/fts3defer2.test index ae352d4..0d58796 100644 --- a/third_party/sqlite/src/test/fts3defer2.test +++ b/third_party/sqlite/src/test/fts3defer2.test
@@ -46,6 +46,7 @@ INSERT INTO t1 VALUES(''); INSERT INTO t1(t1) VALUES('optimize'); } +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.1.4 { SELECT count(*) FROM t1_segments WHERE length(block)>10000; UPDATE t1_segments SET block = zeroblob(length(block)) WHERE length(block)>10000; @@ -98,6 +99,7 @@ WHERE length(block)>10000; } } { + sqlite3_db_config db DEFENSIVE 0 execsql $sql do_execsql_test 2.2.$tn.1 { @@ -152,6 +154,7 @@ WHERE length(block)>10000; } } { + sqlite3_db_config db DEFENSIVE 0 execsql $sql do_execsql_test 2.4.$tn { SELECT docid, mit(matchinfo(t3, 'pcxnal')) FROM t3 WHERE t3 MATCH '"a b c"';
diff --git a/third_party/sqlite/src/test/fts3matchinfo.test b/third_party/sqlite/src/test/fts3matchinfo.test index 94ed821..bd16a63 100644 --- a/third_party/sqlite/src/test/fts3matchinfo.test +++ b/third_party/sqlite/src/test/fts3matchinfo.test
@@ -278,6 +278,7 @@ do_execsql_test 4.4.0.1 { INSERT INTO t5(t5) VALUES('optimize') } ifcapable fts4_deferred { + sqlite3_db_config db DEFENSIVE 0 do_execsql_test 4.4.0.2 { UPDATE t5_segments SET block = zeroblob(length(block)) @@ -339,6 +340,7 @@ SELECT offsets(t9) FROM t9 WHERE t9 MATCH 'to'; } {{0 0 20 2 0 0 27 2}} +sqlite3_db_config db DEFENSIVE 0 do_catchsql_test 6.2 { UPDATE t9_content SET c0content = 'this record is used to'; SELECT offsets(t9) FROM t9 WHERE t9 MATCH 'to'; @@ -392,6 +394,7 @@ } {{204 1 3 3 0} {204 1 3 3 0} {204 1 3 3 0}} # Corruption related tests. +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 8.4.1.1 { UPDATE t11_stat SET value = X'0000'; } do_catchsql_test 8.5.1.2 { SELECT mit(matchinfo(t11, 'nxa')) FROM t11 WHERE t11 MATCH 'a*'
diff --git a/third_party/sqlite/src/test/fts3misc.test b/third_party/sqlite/src/test/fts3misc.test index 42a09dd8..283b6b6e1 100644 --- a/third_party/sqlite/src/test/fts3misc.test +++ b/third_party/sqlite/src/test/fts3misc.test
@@ -160,6 +160,7 @@ do_execsql_test 4.2 { SELECT quote(value) from t4_stat where id=0 } {X'C03EC0B204C0A608'} + sqlite3_db_config db DEFENSIVE 0 do_execsql_test 4.3 { UPDATE t4_stat SET value = X'C03EC0B204C0A60800' WHERE id=0; }
diff --git a/third_party/sqlite/src/test/fts3query.test b/third_party/sqlite/src/test/fts3query.test index 97e9309..40861b0 100644 --- a/third_party/sqlite/src/test/fts3query.test +++ b/third_party/sqlite/src/test/fts3query.test
@@ -167,6 +167,7 @@ 3 "SELECT snippet(content) FROM t2 WHERE t2 MATCH 'history'" snippet 4 "SELECT optimize(content) FROM t2 WHERE t2 MATCH 'history'" optimize } +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 5.4.0 { UPDATE t2_content SET c0content = X'1234' } do_select_tests 5.4 -errorformat { illegal first argument to %s
diff --git a/third_party/sqlite/src/test/fts3snippet.test b/third_party/sqlite/src/test/fts3snippet.test index 1896338..a18b9746 100644 --- a/third_party/sqlite/src/test/fts3snippet.test +++ b/third_party/sqlite/src/test/fts3snippet.test
@@ -184,6 +184,7 @@ [list 0 0 $off 10 1 0 $off 10] [list 0 0 $off 10] # Test a corruption case: + sqlite3_db_config db DEFENSIVE 0 execsql { UPDATE ft_content SET c1b = 'hello world' WHERE c1b = $numbers } do_error_test $T.2.3 { SELECT offsets(ft) FROM ft WHERE ft MATCH 'onehundred'
diff --git a/third_party/sqlite/src/test/fts4check.test b/third_party/sqlite/src/test/fts4check.test index ee7b7c6..736e105 100644 --- a/third_party/sqlite/src/test/fts4check.test +++ b/third_party/sqlite/src/test/fts4check.test
@@ -66,6 +66,7 @@ ); } } { + sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.2.1.$tn "BEGIN; $disruption" do_catchsql_test 1.2.2.$tn { INSERT INTO t1 (t1) VALUES('integrity-check') @@ -100,6 +101,7 @@ ); } } { + sqlite3_db_config db DEFENSIVE 0 do_execsql_test 2.2.1.$tn "BEGIN; $disruption" do_catchsql_test 2.2.2.$tn { INSERT INTO t2 (t2) VALUES('integrity-check') @@ -145,6 +147,7 @@ ) } } { + sqlite3_db_config db DEFENSIVE 0 do_execsql_test 3.2.1.$tn "BEGIN; $disruption" do_catchsql_test 3.2.2.$tn { INSERT INTO t3 (t3) VALUES('integrity-check') @@ -163,6 +166,7 @@ INSERT INTO t4(t4) VALUES('integrity-check'); } +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 4.1 { PRAGMA writable_schema = 1; UPDATE sqlite_master @@ -197,6 +201,7 @@ INSERT INTO t5(t5) VALUES('integrity-check'); } {} +sqlite3_db_config db DEFENSIVE 0 do_catchsql_test 5.2 { INSERT INTO t5_content VALUES(5, 'his hardy mountain pony'); INSERT INTO t5(t5) VALUES('integrity-check');
diff --git a/third_party/sqlite/src/test/fts4growth.test b/third_party/sqlite/src/test/fts4growth.test index 1c6cf03..5c24c6e 100644 --- a/third_party/sqlite/src/test/fts4growth.test +++ b/third_party/sqlite/src/test/fts4growth.test
@@ -25,6 +25,7 @@ source $testdir/genesis.tcl +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.1 { CREATE VIRTUAL TABLE x1 USING fts3; } do_test 1.2 {
diff --git a/third_party/sqlite/src/test/fts4merge.test b/third_party/sqlite/src/test/fts4merge.test index fd49b83e..c248932 100644 --- a/third_party/sqlite/src/test/fts4merge.test +++ b/third_party/sqlite/src/test/fts4merge.test
@@ -156,6 +156,7 @@ SELECT quote(value) FROM t4_stat WHERE rowid=1 } {X'0006'} + sqlite3_db_config db DEFENSIVE 0 do_execsql_test 4.4.2 { DELETE FROM t4_stat WHERE rowid=1; INSERT INTO t4(t4) VALUES('merge=1,12');
diff --git a/third_party/sqlite/src/test/fts4opt.test b/third_party/sqlite/src/test/fts4opt.test index 3c3d578..d5e2c050 100644 --- a/third_party/sqlite/src/test/fts4opt.test +++ b/third_party/sqlite/src/test/fts4opt.test
@@ -37,6 +37,7 @@ # incremental optimize routine. # proc prepare_for_optimize {db tbl} { + sqlite3_db_config $db DEFENSIVE 0 $db eval [string map [list % $tbl] { BEGIN; CREATE TEMP TABLE tmp_segdir(
diff --git a/third_party/sqlite/src/test/fuzz_malloc.test b/third_party/sqlite/src/test/fuzz_malloc.test index 0734f84..5cb9678 100644 --- a/third_party/sqlite/src/test/fuzz_malloc.test +++ b/third_party/sqlite/src/test/fuzz_malloc.test
@@ -17,11 +17,6 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -ifcapable !memdebug { - finish_test - return -} - source $testdir/malloc_common.tcl source $testdir/fuzz_common.tcl
diff --git a/third_party/sqlite/src/test/fuzzcheck.c b/third_party/sqlite/src/test/fuzzcheck.c index 1f49763..61925fc 100644 --- a/third_party/sqlite/src/test/fuzzcheck.c +++ b/third_party/sqlite/src/test/fuzzcheck.c
@@ -405,7 +405,10 @@ static sqlite3_int64 timeOfDay(void){ static sqlite3_vfs *clockVfs = 0; sqlite3_int64 t; - if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); + if( clockVfs==0 ){ + clockVfs = sqlite3_vfs_find(0); + if( clockVfs==0 ) return 0; + } if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){ clockVfs->xCurrentTimeInt64(clockVfs, &t); }else{ @@ -866,6 +869,7 @@ sqlite3_vfs *pDfltVfs; /* The default VFS */ int openFlags4Data; /* Flags for sqlite3_open_v2() */ + sqlite3_initialize(); iBegin = timeOfDay(); #ifdef __unix__ signal(SIGALRM, timeoutHandler);
diff --git a/third_party/sqlite/src/test/fuzzdata7.db b/third_party/sqlite/src/test/fuzzdata7.db new file mode 100644 index 0000000..69469f9 --- /dev/null +++ b/third_party/sqlite/src/test/fuzzdata7.db Binary files differ
diff --git a/third_party/sqlite/src/test/incrblob_err.test b/third_party/sqlite/src/test/incrblob_err.test index 8c90cc0..b186a14 100644 --- a/third_party/sqlite/src/test/incrblob_err.test +++ b/third_party/sqlite/src/test/incrblob_err.test
@@ -16,7 +16,7 @@ source $testdir/tester.tcl set ::testprefix incrblob_err -ifcapable {!incrblob || !memdebug || !tclvar} { +ifcapable {!incrblob || !tclvar} { finish_test return }
diff --git a/third_party/sqlite/src/test/incrvacuum.test b/third_party/sqlite/src/test/incrvacuum.test index 89017ca..6b19b80 100644 --- a/third_party/sqlite/src/test/incrvacuum.test +++ b/third_party/sqlite/src/test/incrvacuum.test
@@ -783,4 +783,54 @@ } } {ok} +#------------------------------------------------------------------------- +# At one point it was unsafe to truncate a db file on windows while there +# were outstanding xFetch() references. This test case attempts to hit +# that case. +# +ifcapable mmap { + reset_db + do_execsql_test incrvacuum-16.0 { + PRAGMA auto_vacuum = 2; + CREATE TABLE t3(a); + INSERT INTO t3 VALUES(1), (2), (3), (4); + + CREATE TABLE t2(x); + INSERT INTO t2 VALUES( randomblob(1000) ); + INSERT INTO t2 VALUES( randomblob(1000) ); + INSERT INTO t2 VALUES( randomblob(1000) ); + INSERT INTO t2 VALUES( randomblob(1000) ); + INSERT INTO t2 VALUES( randomblob(1000) ); + INSERT INTO t2 VALUES( randomblob(1000) ); + } {} + + # Reopen db to ensure the page-cache is empty. + # + db close + sqlite3 db test.db + + # Open db in mmap-mode. Open a transaction, delete some data, then run + # incremental-vacuum. Do not commit the transaction. + # + do_execsql_test incrvacuum-16.1 { + PRAGMA mmap_size = 1000000; + BEGIN; + DELETE FROM t2; + PRAGMA incremental_vacuum = 1000; + } {1000000} + + # Scan through table t3 (which is all clean pages - so mmap is used). Then, + # midway through, commit the transaction. This causes the db to be truncated + # while there are outstanding xFetch pages. + # + do_test incrvacuum-16.2 { + set res [list] + db eval { SELECT a FROM t3 } { + if {$a==3} { db eval COMMIT } + lappend res $a + } + set res + } {1 2 3 4} +} + finish_test
diff --git a/third_party/sqlite/src/test/index.test b/third_party/sqlite/src/test/index.test index 6422213..7f1b090 100644 --- a/third_party/sqlite/src/test/index.test +++ b/third_party/sqlite/src/test/index.test
@@ -625,6 +625,12 @@ CREATE TABLE sqlite_t1(a, b, c); } } {1 {object name reserved for internal use: sqlite_t1}} +do_test index-18.1.2 { + catchsql { + CREATE TABLE sqlite_t1(a, b, c); + } +} {1 {object name reserved for internal use: sqlite_t1}} +sqlite3_db_config db DEFENSIVE 0 do_test index-18.2 { catchsql { CREATE INDEX sqlite_i1 ON t7(c);
diff --git a/third_party/sqlite/src/test/index3.test b/third_party/sqlite/src/test/index3.test index fae79c3..8f97fbc 100644 --- a/third_party/sqlite/src/test/index3.test +++ b/third_party/sqlite/src/test/index3.test
@@ -83,6 +83,7 @@ # in the series. # do_test index3-99.1 { + sqlite3_db_config db DEFENSIVE 0 execsql { PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='nonsense' WHERE name='t1d'
diff --git a/third_party/sqlite/src/test/indexexpr2.test b/third_party/sqlite/src/test/indexexpr2.test index 2822533..39b44f3 100644 --- a/third_party/sqlite/src/test/indexexpr2.test +++ b/third_party/sqlite/src/test/indexexpr2.test
@@ -159,5 +159,77 @@ SELECT * FROM t4 ORDER BY Substr(a,-2) COLLATE binary; } {.ABC1 1 .ABC3 3 .abc2 2 .abc4 4} +# 2014-09-15: Verify that UPDATEs of columns not referenced by a +# index on expression do not modify the index. +# +unset -nocomplain cnt +set cnt 0 +proc refcnt {x} { + global cnt + incr cnt + return $x +} +db close +sqlite3 db :memory: +db function refcnt -deterministic refcnt +do_test 4.100 { + db eval { + CREATE TABLE t1(a,b,c,d,e,f); + CREATE INDEX t1abc ON t1(refcnt(a+b+c)); + } + set ::cnt +} {0} +do_test 4.110 { + db eval {INSERT INTO t1 VALUES(1,2,3,4,5,6);} + set ::cnt + # The refcnt() function is invoked once to compute the index value +} {1} +do_test 4.120 { + set ::cnt 0 + db eval {UPDATE t1 SET b=b+1;} + set ::cnt + # The refcnt() function is invoked twice, once to remove the old index + # entry and a second time to insert the new one. +} {2} +do_test 4.130 { + set ::cnt 0 + db eval {UPDATE t1 SET d=d+1;} + set ::cnt + # Refcnt() should not be invoked because that index does not change. +} {0} + +# Additional test cases to show that UPDATE does not modify indexes that +# do not involve unchanged columns. +# +ifcapable vtab { + load_static_extension db explain + do_execsql_test 4.200 { + CREATE TABLE t2(a,b,c,d,e,f); + INSERT INTO t2 VALUES(2,3,4,5,6,7); + CREATE INDEX t2abc ON t2(a+b+c); + CREATE INDEX t2cd ON t2(c*d); + CREATE INDEX t2def ON t2(d,e+25*f); + SELECT sqlite_master.name + FROM sqlite_master, explain('UPDATE t2 SET b=b+1') + WHERE explain.opcode LIKE 'Open%' + AND sqlite_master.rootpage=explain.p2 + ORDER BY 1; + } {t2 t2abc} + do_execsql_test 4.210 { + SELECT sqlite_master.name + FROM sqlite_master, explain('UPDATE t2 SET c=c+1') + WHERE explain.opcode LIKE 'Open%' + AND sqlite_master.rootpage=explain.p2 + ORDER BY 1; + } {t2 t2abc t2cd} + do_execsql_test 4.220 { + SELECT sqlite_master.name + FROM sqlite_master, explain('UPDATE t2 SET c=c+1, f=NULL') + WHERE explain.opcode LIKE 'Open%' + AND sqlite_master.rootpage=explain.p2 + ORDER BY 1; + } {t2 t2abc t2cd t2def} +} + finish_test
diff --git a/third_party/sqlite/src/test/intarray.test b/third_party/sqlite/src/test/intarray.test index 5c70eba..049f117 100644 --- a/third_party/sqlite/src/test/intarray.test +++ b/third_party/sqlite/src/test/intarray.test
@@ -47,6 +47,13 @@ } } {table ia1 table ia2 table ia3 table ia4} +# Verify the inability to DROP and recreate an intarray virtual table. +do_test intarray-1.1b { + db eval {DROP TABLE ia1} + set rc [catch {sqlite3_intarray_create db ia1} msg] + lappend rc $msg +} {1 SQLITE_MISUSE} + do_test intarray-1.2 { db eval { SELECT b FROM t1 WHERE a IN ia3 ORDER BY a
diff --git a/third_party/sqlite/src/test/lemon-test01.y b/third_party/sqlite/src/test/lemon-test01.y new file mode 100644 index 0000000..0fd514f --- /dev/null +++ b/third_party/sqlite/src/test/lemon-test01.y
@@ -0,0 +1,75 @@ +// A test case for the LEMON parser generator. Run as follows: +// +// lemon lemon-test01.y && gcc -g lemon-test01.c && ./a.out +// +%token_prefix TK_ +%token_type int +%default_type int +%include { + static int nSyntaxError = 0; + static int nAccept = 0; + static int nFailure = 0; +} + +all ::= A B. +all ::= error B. + +%syntax_error { + nSyntaxError++; +} +%parse_accept { + nAccept++; +} +%parse_failure { + nFailure++; +} +%code { + #include <assert.h> + #include "lemon-test01.h" + static int nTest = 0; + static int nErr = 0; + static int testCase(int testId, int shouldBe, int actual){ + nTest++; + if( shouldBe==actual ){ + printf("test %d: ok\n", testId); + }else{ + printf("test %d: got %d, expected %d\n", testId, actual, shouldBe); + nErr++; + } + } + int main(int argc, char **argv){ + yyParser xp; + ParseInit(&xp); + Parse(&xp, TK_A, 0); + Parse(&xp, TK_B, 0); + Parse(&xp, 0, 0); + ParseFinalize(&xp); + testCase(100, 0, nSyntaxError); + testCase(110, 1, nAccept); + testCase(120, 0, nFailure); + nSyntaxError = nAccept = nFailure = 0; + ParseInit(&xp); + Parse(&xp, TK_B, 0); + Parse(&xp, TK_B, 0); + Parse(&xp, 0, 0); + ParseFinalize(&xp); + testCase(200, 1, nSyntaxError); + testCase(210, 1, nAccept); + testCase(220, 0, nFailure); + nSyntaxError = nAccept = nFailure = 0; + ParseInit(&xp); + Parse(&xp, TK_A, 0); + Parse(&xp, TK_A, 0); + Parse(&xp, 0, 0); + ParseFinalize(&xp); + testCase(200, 1, nSyntaxError); + testCase(210, 0, nAccept); + testCase(220, 0, nFailure); + if( nErr==0 ){ + printf("%d tests pass\n", nTest); + }else{ + printf("%d errors out %d tests\n", nErr, nTest); + } + return nErr; + } +}
diff --git a/third_party/sqlite/src/test/like3.test b/third_party/sqlite/src/test/like3.test index a7225ee0..575faaf 100644 --- a/third_party/sqlite/src/test/like3.test +++ b/third_party/sqlite/src/test/like3.test
@@ -130,12 +130,14 @@ do_execsql_test like3-5.110 { SELECT x FROM t5a WHERE x LIKE '/a%'; } {/abc} +ifcapable !icu { do_eqp_test like3-5.111 { SELECT x FROM t5a WHERE x LIKE '/a%'; } { QUERY PLAN `--SEARCH TABLE t5a USING COVERING INDEX sqlite_autoindex_t5a_1 (x>? AND x<?) } +} do_execsql_test like3-5.120 { SELECT x FROM t5a WHERE x LIKE '^12%' ESCAPE '^'; } {123}
diff --git a/third_party/sqlite/src/test/loadext.test b/third_party/sqlite/src/test/loadext.test index a234e22b..7214f14 100644 --- a/third_party/sqlite/src/test/loadext.test +++ b/third_party/sqlite/src/test/loadext.test
@@ -61,9 +61,9 @@ set dlerror_nosymbol {%s: undefined symbol: %s} if {$::tcl_platform(os) eq "Darwin"} { - set dlerror_nosuchfile {dlopen(%s, 10): image not found} - set dlerror_notadll {dlopen(%1$s, 10): no suitable image found.*} - set dlerror_nosymbol {dlsym(XXX, %2$s): symbol not found} + set dlerror_nosuchfile {dlopen.%s, 10.: .*image.*found.*} + set dlerror_notadll {dlopen.%1$s, 10.: .*image.*found.*} + set dlerror_nosymbol {dlsym.XXX, %2$s.: symbol not found} } if {$::tcl_platform(platform) eq "windows"} {
diff --git a/third_party/sqlite/src/test/malloctraceviewer.tcl b/third_party/sqlite/src/test/malloctraceviewer.tcl new file mode 100644 index 0000000..104d6b9 --- /dev/null +++ b/third_party/sqlite/src/test/malloctraceviewer.tcl
@@ -0,0 +1,253 @@ + +package require sqlite3 +package require Tk + +############################################################################# +# Code to set up scrollbars for widgets. This is generic, boring stuff. +# +namespace eval autoscroll { + proc scrollable {widget path args} { + ::ttk::frame $path + set w [$widget ${path}.widget {*}$args] + set vs [::ttk::scrollbar ${path}.vs] + set hs [::ttk::scrollbar ${path}.hs -orient horizontal] + grid $w -row 0 -column 0 -sticky nsew + + grid rowconfigure $path 0 -weight 1 + grid columnconfigure $path 0 -weight 1 + + set grid [list grid $vs -row 0 -column 1 -sticky nsew] + $w configure -yscrollcommand [list ::autoscroll::scrollcommand $grid $vs] + $vs configure -command [list $w yview] + set grid [list grid $hs -row 1 -column 0 -sticky nsew] + $w configure -xscrollcommand [list ::autoscroll::scrollcommand $grid $hs] + $hs configure -command [list $w xview] + + return $w + } + proc scrollcommand {grid sb args} { + $sb set {*}$args + set isRequired [expr {[lindex $args 0] != 0.0 || [lindex $args 1] != 1.0}] + if {$isRequired && ![winfo ismapped $sb]} { + {*}$grid + } + if {!$isRequired && [winfo ismapped $sb]} { + grid forget $sb + } + } + namespace export scrollable +} +namespace import ::autoscroll::* +############################################################################# + +proc populate_text_widget {db} { + $::O(text) configure -state normal + set id [lindex [$::O(tree) selection] 0] + set frame [lindex $id end] + + set line [$db one {SELECT line FROM frame WHERE frame = $frame}] + if {$line ne ""} { + foreach {file line} [split $line :] {} + set content [$db one "SELECT content FROM file WHERE name = '$file'"] + $::O(text) delete 0.0 end + + set iLine 1 + foreach L [split $content "\n"] { + if {$iLine == $line} { + $::O(text) insert end "$L\n" highlight + } else { + $::O(text) insert end "$L\n" + } + incr iLine + } + $::O(text) yview -pickplace ${line}.0 + } + $::O(text) configure -state disabled +} + +proc populate_index {db} { + $::O(text) configure -state normal + + $::O(text) delete 0.0 end + $::O(text) insert end "\n\n" + + set L [format " % -40s%12s%12s\n" "Test Case" "Allocations" "Bytes"] + $::O(text) insert end $L + $::O(text) insert end " [string repeat - 64]\n" + + $db eval { + SELECT 'TOTAL' AS ztest, sum(ncall) AS calls, sum(nbyte) AS bytes + FROM malloc + UNION ALL + SELECT ztest AS ztest, sum(ncall) AS calls, sum(nbyte) AS bytes + FROM malloc + GROUP BY ztest + + ORDER BY 3 DESC + } { + set tags [list $ztest] + if {$ztest eq $::O(current)} { + lappend tags highlight + } + set L [format " % -40s%12s%12s\n" $ztest $calls $bytes] + $::O(text) insert end $L $tags + + $::O(text) tag bind $ztest <1> [list populate_tree_widget $db $ztest] + $::O(text) tag bind $ztest <Enter> [list $::O(text) configure -cursor hand2] + $::O(text) tag bind $ztest <Leave> [list $::O(text) configure -cursor ""] + } + + $::O(text) configure -state disabled +} + +proc sort_tree_compare {iLeft iRight} { + global O + switch -- [expr (int($O(tree_sort)/2))] { + 0 { + set left [$O(tree) item $iLeft -text] + set right [$O(tree) item $iRight -text] + set res [string compare $left $right] + } + 1 { + set left [lindex [$O(tree) item $iLeft -values] 0] + set right [lindex [$O(tree) item $iRight -values] 0] + set res [expr $left - $right] + } + 2 { + set left [lindex [$O(tree) item $iLeft -values] 1] + set right [lindex [$O(tree) item $iRight -values] 1] + set res [expr $left - $right] + } + } + if {$O(tree_sort)&0x01} { + set res [expr -1 * $res] + } + return $res +} + +proc sort_tree {iMode} { + global O + if {$O(tree_sort) == $iMode} { + incr O(tree_sort) + } else { + set O(tree_sort) $iMode + } + set T $O(tree) + set items [$T children {}] + set items [lsort -command sort_tree_compare $items] + for {set ii 0} {$ii < [llength $items]} {incr ii} { + $T move [lindex $items $ii] {} $ii + } +} + +proc trim_frames {stack} { + while {[info exists ::O(ignore.[lindex $stack 0])]} { + set stack [lrange $stack 1 end] + } + return $stack +} + +proc populate_tree_widget {db zTest} { + $::O(tree) delete [$::O(tree) children {}] + + for {set ii 0} {$ii < 15} {incr ii} { + $db eval { + SELECT + sum(ncall) AS calls, + sum(nbyte) AS bytes, + trim_frames(lrange(lstack, 0, $ii)) AS stack + FROM malloc + WHERE (zTest = $zTest OR $zTest = 'TOTAL') AND llength(lstack)>$ii + GROUP BY stack + HAVING stack != '' + } { + set parent_id [lrange $stack 0 end-1] + set frame [lindex $stack end] + set line [$db one {SELECT line FROM frame WHERE frame = $frame}] + set line [lindex [split $line /] end] + set v [list $calls $bytes] + + catch { + $::O(tree) insert $parent_id end -id $stack -text $line -values $v + } + } + } + + set ::O(current) $zTest + populate_index $db +} + + + +set O(tree_sort) 0 + +::ttk::panedwindow .pan -orient horizontal +set O(tree) [scrollable ::ttk::treeview .pan.tree] + +frame .pan.right +set O(text) [scrollable text .pan.right.text] +button .pan.right.index -command {populate_index mddb} -text "Show Index" +pack .pan.right.index -side top -fill x +pack .pan.right.text -fill both -expand true + +$O(text) tag configure highlight -background wheat +$O(text) configure -wrap none -height 35 + +.pan add .pan.tree +.pan add .pan.right + +$O(tree) configure -columns {calls bytes} +$O(tree) heading #0 -text Line -anchor w -command {sort_tree 0} +$O(tree) heading calls -text Calls -anchor w -command {sort_tree 2} +$O(tree) heading bytes -text Bytes -anchor w -command {sort_tree 4} +$O(tree) column #0 -width 150 +$O(tree) column calls -width 100 +$O(tree) column bytes -width 100 + +pack .pan -fill both -expand 1 + +#-------------------------------------------------------------------- +# Open the database containing the malloc data. The user specifies the +# database to use by passing the file-name on the command line. +# +proc open_database {} { + if {[info exists ::BUILTIN]} { + sqlite3 mddb :memory: + mddb eval $::BUILTIN + wm title . $::argv0 + } else { + set zFilename [lindex $::argv 0] + if {$zFilename eq ""} { + set zFilename mallocs.sql + } + set fd [open $zFilename] + set zHdr [read $fd 15] + if {$zHdr eq "SQLite format 3"} { + close $fd + sqlite3 mddb $zFilename + } else { + seek $fd 0 + sqlite3 mddb :memory: + mddb eval [read $fd] + close $fd + } + wm title . $zFilename + } + + mddb function lrange -argcount 3 lrange + mddb function llength -argcount 1 llength + mddb function trim_frames -argcount 1 trim_frames + + mddb eval { + SELECT frame FROM frame + WHERE line LIKE '%malloc.c:%' OR line LIKE '%mem2.c:%' + } { + set ::O(ignore.$frame) 1 + } +} + +open_database +bind $O(tree) <<TreeviewSelect>> [list populate_text_widget mddb] + +populate_tree_widget mddb [mddb one {SELECT zTest FROM malloc LIMIT 1}] +
diff --git a/third_party/sqlite/src/test/misc1.test b/third_party/sqlite/src/test/misc1.test index f8c6a84..ed05d04 100644 --- a/third_party/sqlite/src/test/misc1.test +++ b/third_party/sqlite/src/test/misc1.test
@@ -659,6 +659,7 @@ # db close sqlite3 db :memory: +sqlite3_db_config db DEFENSIVE 0 do_execsql_test misc1-23.1 { CREATE TABLE t1(x); PRAGMA writable_schema=ON; @@ -674,6 +675,7 @@ db close database_may_be_corrupt sqlite3 db :memory: +sqlite3_db_config db DEFENSIVE 0 do_catchsql_test misc1-23.2 { CREATE TABLE t1(x UNIQUE); PRAGMA writable_schema=ON; @@ -685,6 +687,7 @@ } {1 {no such table: F}} db close sqlite3 db :memory: +sqlite3_db_config db DEFENSIVE 0 do_catchsql_test misc1-23.3 { CREATE TABLE t1(x UNIQUE); PRAGMA writable_schema=ON;
diff --git a/third_party/sqlite/src/test/misc4.test b/third_party/sqlite/src/test/misc4.test index eda26bb70..7897929 100644 --- a/third_party/sqlite/src/test/misc4.test +++ b/third_party/sqlite/src/test/misc4.test
@@ -212,6 +212,7 @@ # db close sqlite3 db :memory: +sqlite3_db_config db DEFENSIVE 0 do_catchsql_test misc4-7.1 { CREATE TABLE t7(x); PRAGMA writable_schema=ON;
diff --git a/third_party/sqlite/src/test/misc5.test b/third_party/sqlite/src/test/misc5.test index 068f741..b5d111c 100644 --- a/third_party/sqlite/src/test/misc5.test +++ b/third_party/sqlite/src/test/misc5.test
@@ -590,6 +590,7 @@ # do_test misc5-7.2 { sqlite3 db2 :memory: + sqlite3_db_config db2 DEFENSIVE 0 catchsql { CREATE TABLE t1(x UNIQUE); PRAGMA writable_schema=ON;
diff --git a/third_party/sqlite/src/test/misc7.test b/third_party/sqlite/src/test/misc7.test index 28a6099b..a445234 100644 --- a/third_party/sqlite/src/test/misc7.test +++ b/third_party/sqlite/src/test/misc7.test
@@ -434,6 +434,7 @@ set ::pending_byte_page [expr ($::sqlite_pending_byte / 1024) + 1] sqlite3_test_control_pending_byte $::sqlite_pending_byte do_test misc7-17.3 { + sqlite3_db_config db DEFENSIVE 0 db eval { pragma writable_schema = true; UPDATE sqlite_master
diff --git a/third_party/sqlite/src/test/mjournal.test b/third_party/sqlite/src/test/mjournal.test index 186ddae..577f3b2 100644 --- a/third_party/sqlite/src/test/mjournal.test +++ b/third_party/sqlite/src/test/mjournal.test
@@ -160,4 +160,3 @@ } {0} finish_test -
diff --git a/third_party/sqlite/src/test/normalize.test b/third_party/sqlite/src/test/normalize.test index 9e3ec9c9..e85bd00 100644 --- a/third_party/sqlite/src/test/normalize.test +++ b/third_party/sqlite/src/test/normalize.test
@@ -72,4 +72,293 @@ do_test $tnum [list sqlite3_normalize $sql] $norm } +ifcapable normalize { +do_test 200 { + execsql { + CREATE TABLE t1(a,b); + } +} {} +do_test 201 { + set STMT [sqlite3_prepare_v3 $DB \ + "SELECT a, b FROM t1 WHERE b = ? ORDER BY a;" -1 0 TAIL] + + sqlite3_bind_null $STMT 1 +} {} +do_test 202 { + sqlite3_normalized_sql $STMT +} {} +do_test 203 { + sqlite3_finalize $STMT +} {SQLITE_OK} + +do_test 210 { + set STMT [sqlite3_prepare_v3 $DB \ + "SELECT a, b FROM t1 WHERE b = ? ORDER BY a;" -1 2 TAIL] + + sqlite3_bind_null $STMT 1 +} {} +do_test 211 { + sqlite3_normalized_sql $STMT +} {SELECT a,b FROM t1 WHERE b=?ORDER BY a;} +do_test 212 { + sqlite3_finalize $STMT +} {SQLITE_OK} + +do_test 220 { + set STMT [sqlite3_prepare_v3 $DB \ + "SELECT a, b FROM t1 WHERE b = 'a' ORDER BY a;" -1 2 TAIL] +} {/^[0-9A-Fa-f]+$/} +do_test 221 { + sqlite3_normalized_sql $STMT +} {SELECT a,b FROM t1 WHERE b=?ORDER BY a;} +do_test 222 { + sqlite3_finalize $STMT +} {SQLITE_OK} + +do_test 297 { + execsql { + DROP TABLE t1; + } +} {} +do_test 298 { + execsql { + CREATE TABLE t1(a,b,c,d,e,"col f",w,x,y,z); + CREATE TABLE t2(x,"col y"); + } +} {} +do_test 299 { + sqlite3_create_function db +} {SQLITE_OK} + +foreach {tnum sql flags norm} { + 300 + {SELECT * FROM t1 WHERE a IN (1) AND b=51.42} + 0x2 + {0 {SELECT*FROM t1 WHERE a IN(?,?,?)AND b=?;}} + + 310 + {SELECT a, b+15, c FROM t1 WHERE d NOT IN (SELECT x FROM t2);} + 0x2 + {0 {SELECT a,b+?,c FROM t1 WHERE d NOT IN(SELECT x FROM t2);}} + + 320 + { SELECT NULL, b FROM t1 -- comment text + WHERE d IN (WITH t(a) AS (VALUES(5)) /* CTE */ + SELECT a FROM t) + OR e='hello'; + } + 0x2 + {0 {SELECT?,b FROM t1 WHERE d IN(WITH t(a)AS(VALUES(?))SELECT a FROM t)OR e=?;}} + + 321 + {/*Initial comment*/ + -- another comment line + SELECT NULL /* comment */ , b FROM t1 -- comment text + WHERE d IN (WITH t(a) AS (VALUES(5)) /* CTE */ + SELECT a FROM t) + OR e='hello'; + } + 0x2 + {0 {SELECT?,b FROM t1 WHERE d IN(WITH t(a)AS(VALUES(?))SELECT a FROM t)OR e=?;}} + + 330 + {/* Query containing parameters */ + SELECT x,$::abc(15),y,@abc,z,?99,w FROM t1 /* Trailing comment */} + 0x2 + {0 {SELECT x,?,y,?,z,?,w FROM t1;}} + + 340 + {/* Long list on the RHS of IN */ + SELECT 15 IN (1,2,3,(SELECT * FROM t1),'xyz',x'abcd',22*(x+5),null);} + 0x2 + {1 {(1) no such column: x}} + + 350 + {SELECT x'abc'; -- illegal token} + 0x2 + {1 {(1) unrecognized token: "x'abc'"}} + + 360 + {SELECT a,NULL,b FROM t1 WHERE c IS NOT NULL or D is null or e=5} + 0x2 + {0 {SELECT a,?,b FROM t1 WHERE c IS NOT NULL OR d IS NULL OR e=?;}} + + 370 + {/* IN list exactly 5 bytes long */ + SELECT * FROM t1 WHERE x IN (1,2,3);} + 0x2 + {0 {SELECT*FROM t1 WHERE x IN(?,?,?);}} + + 400 + {SELECT a FROM t1 WHERE x IN (1,2,3) AND sqlite_version();} + 0x2 + {0 {SELECT a FROM t1 WHERE x IN(?,?,?)AND sqlite_version();}} + + 410 + {SELECT a FROM t1 WHERE x IN (1,2,3) AND hex8();} + 0x2 + {1 {(1) wrong number of arguments to function hex8()}} + + 420 + {SELECT a FROM t1 WHERE x IN (1,2,3) AND hex8('abc');} + 0x2 + {0 {SELECT a FROM t1 WHERE x IN(?,?,?)AND hex8(?);}} + + 430 + {SELECT "a" FROM t1 WHERE "x" IN ("1","2",'3');} + 0x2 + {0 {SELECT"a"FROM t1 WHERE"x"IN(?,?,?);}} + + 440 + {SELECT 'a' FROM t1 WHERE 'x';} + 0x2 + {0 {SELECT?FROM t1 WHERE?;}} + + 450 + {SELECT [a] FROM t1 WHERE [x];} + 0x2 + {0 {SELECT"a"FROM t1 WHERE"x";}} + + 460 + {SELECT * FROM t1 WHERE x IN (x);} + 0x2 + {0 {SELECT*FROM t1 WHERE x IN(x);}} + + 470 + {SELECT * FROM t1 WHERE x IN (x,a);} + 0x2 + {0 {SELECT*FROM t1 WHERE x IN(x,a);}} + + 480 + {SELECT * FROM t1 WHERE x IN ([x],"a");} + 0x2 + {0 {SELECT*FROM t1 WHERE x IN("x","a");}} + + 500 + {SELECT * FROM t1 WHERE x IN ([x],"a",'b',sqlite_version());} + 0x2 + {0 {SELECT*FROM t1 WHERE x IN("x","a",?,sqlite_version());}} + + 520 + {SELECT * FROM t1 WHERE x IN (SELECT x FROM t1);} + 0x2 + {0 {SELECT*FROM t1 WHERE x IN(SELECT x FROM t1);}} + + 540 + {SELECT * FROM t1 WHERE x IN ((SELECT x FROM t1));} + 0x2 + {0 {SELECT*FROM t1 WHERE x IN(?,?,?);}} + + 550 + {SELECT a, a+1, a||'b', a+"b" FROM t1;} + 0x2 + {0 {SELECT a,a+?,a||?,a+"b"FROM t1;}} + + 570 + {SELECT * FROM t1 WHERE x IN (1);} + 0x2 + {0 {SELECT*FROM t1 WHERE x IN(?,?,?);}} + + 580 + {SELECT * FROM t1 WHERE x IN (1,2);} + 0x2 + {0 {SELECT*FROM t1 WHERE x IN(?,?,?);}} + + 590 + {SELECT * FROM t1 WHERE x IN (1,2,3);} + 0x2 + {0 {SELECT*FROM t1 WHERE x IN(?,?,?);}} + + 600 + {SELECT * FROM t1 WHERE x IN (1,2,3,4);} + 0x2 + {0 {SELECT*FROM t1 WHERE x IN(?,?,?);}} + + 610 + {SELECT * FROM t1 WHERE x IN (SELECT x FROM t1);} + 0x2 + {0 {SELECT*FROM t1 WHERE x IN(SELECT x FROM t1);}} + + 620 + {SELECT * FROM t1 WHERE x IN (SELECT x FROM t1 WHERE x IN (1,2,3));} + 0x2 + {0 {SELECT*FROM t1 WHERE x IN(SELECT x FROM t1 WHERE x IN(?,?,?));}} + + 630 + {SELECT * FROM t1 WHERE x IN (SELECT x FROM t1 WHERE x IN (x));} + 0x2 + {0 {SELECT*FROM t1 WHERE x IN(SELECT x FROM t1 WHERE x IN(x));}} + + 640 + {SELECT x FROM t1 WHERE x IN (SELECT x FROM t1 WHERE x IN ( + SELECT x FROM t1 WHERE x IN (SELECT x FROM t1 WHERE x IN ( + SELECT x FROM t1 WHERE x IN (x)))));} + 0x2 + {0 {SELECT x FROM t1 WHERE x IN(SELECT x FROM t1 WHERE x IN(SELECT x FROM t1 WHERE x IN(SELECT x FROM t1 WHERE x IN(SELECT x FROM t1 WHERE x IN(x)))));}} + + 650 + {SELECT x FROM t1 WHERE x IN (SELECT x FROM t1 WHERE x IN ( + SELECT x FROM t1 WHERE x IN (SELECT x FROM t1 WHERE x IN ( + SELECT x FROM t1 WHERE x IN (1)))));} + 0x2 + {0 {SELECT x FROM t1 WHERE x IN(SELECT x FROM t1 WHERE x IN(SELECT x FROM t1 WHERE x IN(SELECT x FROM t1 WHERE x IN(SELECT x FROM t1 WHERE x IN(?,?,?)))));}} + + 660 + {SELECT x FROM t1 WHERE x IN (1) UNION ALL SELECT x FROM t1 WHERE x IN (1);} + 0x2 + {0 {SELECT x FROM t1 WHERE x IN(?,?,?)UNION ALL SELECT x FROM t1 WHERE x IN(?,?,?);}} + + 670 + {SELECT "col f", [col f] FROM t1;} + 0x2 + {0 {SELECT"col f","col f"FROM t1;}} + + 680 + {SELECT a, "col f" FROM t1 LEFT OUTER JOIN t2 ON [t1].[col f] == [t2].[col y];} + 0x2 + {0 {SELECT a,"col f"FROM t1 LEFT OUTER JOIN t2 ON"t1"."col f"=="t2"."col y";}} + + 690 + {SELECT * FROM ( WITH x AS ( SELECT * FROM t1 WHERE x IN ( 1)) SELECT 10);} + 0x2 + {0 {SELECT*FROM(WITH x AS(SELECT*FROM t1 WHERE x IN(?,?,?))SELECT?);}} + + 700 + {SELECT rowid, oid, _rowid_ FROM t1;} + 0x2 + {0 {SELECT rowid,oid,_rowid_ FROM t1;}} + + 710 + {SELECT x FROM t1 WHERE x IS NULL;} + 0x2 + {0 {SELECT x FROM t1 WHERE x IS NULL;}} + + 740 + {SELECT x FROM t1 WHERE x IS NOT NULL;} + 0x2 + {0 {SELECT x FROM t1 WHERE x IS NOT NULL;}} + + 750 + {SELECT x FROM t1 WHERE x = NULL;} + 0x2 + {0 {SELECT x FROM t1 WHERE x=?;}} + + 760 + {SELECT x FROM t1 WHERE x IN ([x] IS NOT NULL, NULL, 1, 'a', "b", x'00');} + 0x2 + {0 {SELECT x FROM t1 WHERE x IN("x"IS NOT NULL,?,?,?,"b",?);}} +} { + do_test $tnum { + set code [catch { + set STMT [sqlite3_prepare_v3 $DB $sql -1 $flags TAIL] + sqlite3_normalized_sql $STMT + } res] + if {[info exists STMT]} { + sqlite3_finalize $STMT; unset STMT + } + list $code $res + } $norm +} +} + finish_test
diff --git a/third_party/sqlite/src/test/notnull.test b/third_party/sqlite/src/test/notnull.test index 32d95ea..23abe31 100644 --- a/third_party/sqlite/src/test/notnull.test +++ b/third_party/sqlite/src/test/notnull.test
@@ -606,4 +606,3 @@ do_uses_op_next_test notnull-6.10 "SELECT * FROM t8 WHERE a IS ?" 0 finish_test -
diff --git a/third_party/sqlite/src/test/ossfuzz.c b/third_party/sqlite/src/test/ossfuzz.c index 7b69015..c3d66eb 100644 --- a/third_party/sqlite/src/test/ossfuzz.c +++ b/third_party/sqlite/src/test/ossfuzz.c
@@ -30,14 +30,16 @@ mDebug = x; } -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK /* Return the current real-world time in milliseconds since the ** Julian epoch (-4714-11-24). */ static sqlite3_int64 timeOfDay(void){ static sqlite3_vfs *clockVfs = 0; sqlite3_int64 t; - if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); + if( clockVfs==0 ){ + clockVfs = sqlite3_vfs_find(0); + if( clockVfs==0 ) return 0; + } if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){ clockVfs->xCurrentTimeInt64(clockVfs, &t); }else{ @@ -47,7 +49,6 @@ } return t; } -#endif /* An instance of the following object is passed by pointer as the ** client data to various callbacks. @@ -58,9 +59,9 @@ sqlite3_int64 iLastCb; /* Time recorded for previous progress callback */ sqlite3_int64 mxInterval; /* Longest interval between two progress calls */ unsigned nCb; /* Number of progress callbacks */ + unsigned execCnt; /* Number of calls to the sqlite3_exec callback */ } FuzzCtx; -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK /* ** Progress handler callback. ** @@ -76,7 +77,6 @@ p->nCb++; return rc; } -#endif /* ** Disallow debugging pragmas such as "PRAGMA vdbe_debug" and @@ -103,12 +103,13 @@ /* ** Callback for sqlite3_exec(). */ -static int exec_handler(void *pCnt, int argc, char **argv, char **namev){ +static int exec_handler(void *pClientData, int argc, char **argv, char **namev){ + FuzzCtx *p = (FuzzCtx*)pClientData; int i; if( argv ){ for(i=0; i<argc; i++) sqlite3_free(sqlite3_mprintf("%s", argv[i])); } - return ((*(int*)pCnt)--)<=0; + return (p->execCnt--)<=0 || progress_handler(pClientData); } /* @@ -116,7 +117,6 @@ ** fuzzed input. */ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - int execCnt = 0; /* Abort row callback when count reaches zero */ char *zErrMsg = 0; /* Error message returned by sqlite_exec() */ uint8_t uSelector; /* First byte of input data[] */ int rc; /* Return code from various interfaces */ @@ -135,17 +135,12 @@ uSelector = 0xfd; } -#ifdef SQLITE_OMIT_AUTOINIT - rc = sqlite3_initialize(); - if( rc ) return 0; -#endif - /* Open the database connection. Only use an in-memory database. */ + if( sqlite3_initialize() ) return 0; rc = sqlite3_open_v2("fuzz.db", &cx.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0); if( rc ) return 0; -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK /* Invoke the progress handler frequently to check to see if we ** are taking too long. The progress handler will return true ** (which will block further processing) if more than 10 seconds have @@ -153,6 +148,7 @@ */ cx.iLastCb = timeOfDay(); cx.iCutoffTime = cx.iLastCb + 10000; /* Now + 10 seconds */ +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK sqlite3_progress_handler(cx.db, 10, progress_handler, (void*)&cx); #endif @@ -168,7 +164,7 @@ /* Remaining bits of the selector determine a limit on the number of ** output rows */ - execCnt = uSelector + 1; + cx.execCnt = uSelector + 1; /* Run the SQL. The sqlite_exec() interface expects a zero-terminated ** string, so make a copy. */ @@ -176,7 +172,7 @@ #ifndef SQLITE_OMIT_COMPLETE sqlite3_complete(zSql); #endif - sqlite3_exec(cx.db, zSql, exec_handler, (void*)&execCnt, &zErrMsg); + sqlite3_exec(cx.db, zSql, exec_handler, (void*)&cx, &zErrMsg); /* Show any errors */ if( (mDebug & FUZZ_SHOW_ERRORS)!=0 && zErrMsg ){
diff --git a/third_party/sqlite/src/test/pager1.test b/third_party/sqlite/src/test/pager1.test index b98fb70..13ae399 100644 --- a/third_party/sqlite/src/test/pager1.test +++ b/third_party/sqlite/src/test/pager1.test
@@ -1879,6 +1879,7 @@ do_test pager1-18.2 { set root [db one "SELECT rootpage FROM sqlite_master"] set lockingpage [expr (0x10000/1024) + 1] + sqlite3_db_config db DEFENSIVE 0 execsql { PRAGMA writable_schema = 1; UPDATE sqlite_master SET rootpage = $lockingpage; @@ -1931,6 +1932,7 @@ db2 close do_test pager1-18.5 { sqlite3 db "" + sqlite3_db_config db DEFENSIVE 0 execsql { CREATE TABLE t1(a, b); CREATE TABLE t2(a, b);
diff --git a/third_party/sqlite/src/test/parser1.test b/third_party/sqlite/src/test/parser1.test index 4b9d9df..2506936 100644 --- a/third_party/sqlite/src/test/parser1.test +++ b/third_party/sqlite/src/test/parser1.test
@@ -28,6 +28,7 @@ # COLLATE, ASC, and DESC keywords on the id list of a FK constraint, and that # those keywords are silently ignored. # +sqlite3_db_config db DEFENSIVE 0 do_execsql_test parser1-1.2 { CREATE TABLE t1( a TEXT PRIMARY KEY,
diff --git a/third_party/sqlite/src/test/permutations.test b/third_party/sqlite/src/test/permutations.test index 30d078b..d297a6f 100644 --- a/third_party/sqlite/src/test/permutations.test +++ b/third_party/sqlite/src/test/permutations.test
@@ -290,12 +290,6 @@ test_set [glob -nocomplain $::testdir/window*.test] ] -test_suite "alter" -prefix "" -description { - All ALTER function related tests . -} -files [ - test_set [glob -nocomplain $::testdir/alter*.test] -] - test_suite "lsm1" -prefix "" -description { All LSM1 tests. } -files [glob -nocomplain $::testdir/../ext/lsm1/test/*.test] @@ -561,20 +555,11 @@ test_suite "nomutex" -description { Tests run with the SQLITE_OPEN_MULTITHREADED flag passed to sqlite3_open(). } -initialize { - rename sqlite3 sqlite3_nomutex - proc sqlite3 {args} { - if {[string range [lindex $args 0] 0 0] ne "-"} { - lappend args -fullmutex 0 -nomutex 1 - } - uplevel [concat sqlite3_nomutex $args] - } + set ::G(perm:sqlite3_args) [list -fullmutex 0 -nomutex 1] } -files { delete.test delete2.test insert.test rollback.test select1.test select2.test trans.test update.test vacuum.test types.test types2.test types3.test -} -shutdown { - rename sqlite3 {} - rename sqlite3_nomutex sqlite3 } # Run some tests in SQLITE_CONFIG_MULTITHREAD mode. @@ -604,20 +589,11 @@ test_suite "fullmutex" -description { Tests run in SQLITE_OPEN_FULLMUTEX mode } -initialize { - rename sqlite3 sqlite3_fullmutex - proc sqlite3 {args} { - if {[string range [lindex $args 0] 0 0] ne "-"} { - lappend args -nomutex 0 -fullmutex 1 - } - uplevel [concat sqlite3_fullmutex $args] - } + set ::G(perm:sqlite3_args) [list -nomutex 0 -fullmutex 1] } -files { delete.test delete2.test insert.test rollback.test select1.test select2.test trans.test update.test vacuum.test types.test types2.test types3.test -} -shutdown { - rename sqlite3 {} - rename sqlite3_fullmutex sqlite3 } # Run some tests using the "onefile" demo. @@ -625,19 +601,10 @@ test_suite "onefile" -description { Run some tests using the "test_onefile.c" demo } -initialize { - rename sqlite3 sqlite3_onefile - proc sqlite3 {args} { - if {[string range [lindex $args 0] 0 0] ne "-"} { - lappend args -vfs fs - } - uplevel [concat sqlite3_onefile $args] - } + set ::G(perm:sqlite3_args) [list -vfs fs] } -files { conflict.test insert.test insert2.test insert3.test rollback.test select1.test select2.test select3.test -} -shutdown { - rename sqlite3 {} - rename sqlite3_onefile sqlite3 } # Run some tests using UTF-16 databases. @@ -939,17 +906,8 @@ test_suite "safe_append" -description { Run some tests on a SAFE_APPEND file-system. } -initialize { - rename sqlite3 sqlite3_safeappend - proc sqlite3 {args} { - if {[string range [lindex $args 0] 0 0] ne "-"} { - lappend args -vfs devsym - } - uplevel [concat sqlite3_safeappend $args] - } + set ::G(perm:sqlite3_args) [list -vfs devsym] sqlite3_simulate_device -char safe_append -} -shutdown { - rename sqlite3 {} - rename sqlite3_shutdown sqlite3 } -files [ test_set $::allquicktests shared_err.test -exclude async3.test ] @@ -1116,30 +1074,38 @@ # -description TITLE # -initialize SCRIPT # -shutdown SCRIPT -# -presql SQL # -files LIST-OF-FILES # -prefix NAME +# -dbconfig SCRIPT # proc run_tests {name args} { + set options(-initialize) "" + set options(-shutdown) "" + set options(-prefix) "" + set options(-dbconfig) "" + set options(-presql) "" + array set options $args set ::G(perm:name) $name set ::G(perm:prefix) $options(-prefix) - set ::G(perm:presql) $options(-presql) set ::G(isquick) 1 set ::G(perm:dbconfig) $options(-dbconfig) + set ::G(perm:presql) $options(-presql) foreach file [lsort $options(-files)] { uplevel $options(-initialize) if {[file tail $file] == $file} { set file [file join $::testdir $file] } slave_test_file $file uplevel $options(-shutdown) + + unset -nocomplain ::G(perm:sqlite3_args) } unset ::G(perm:name) unset ::G(perm:prefix) - unset ::G(perm:presql) unset ::G(perm:dbconfig) + unset ::G(perm:presql) } proc run_test_suite {name} { @@ -1153,19 +1119,29 @@ puts "Usage: $::argv0 TESTSUITE ?TESTFILE?" puts "" puts "Available test-suites are:" + + set iPos 0 foreach k $::testsuitelist { - if {[info exists ::testspec($k)]==0} { - puts " ----------------------------------------" - puts "" - } else { - array set o $::testspec($k) - puts "Test suite: \"$k\"" - set d [string trim $o(-description)] - set d [regsub {\n *} $d "\n "] - puts " $d" - puts "" + if {[info exists ::testspec($k)]} { + switch $iPos { + 0 { + puts "" + puts -nonewline " [format %-30s $k]" + } + + 1 { + puts -nonewline [format %-30s $k] + } + + 2 { + puts -nonewline $k + } + } + + set iPos [expr (($iPos+1) % 3)] } } + puts "" exit -1 } @@ -1174,11 +1150,35 @@ if {[llength $argv]==0} { help } else { + + # See if the first argument is a named test-suite. + # set suite [file tail [lindex $argv 0]] - if {[info exists ::testspec($suite)]==0} help + if {[info exists ::testspec($suite)]} { + set S $::testspec($suite) + set i 1 + } else { + set S [list] + set i 0 + } + set extra "" - if {[llength $argv]>1} { set extra [list -files [lrange $argv 1 end]] } - eval run_tests $suite $::testspec($suite) $extra + if {$i < [llength $argv] && [string range [lindex $argv $i] 0 0]!="-" } { + set files [list] + for {} {$i < [llength $argv]} {incr i} { + set pattern [string map {% *} [lindex $argv $i]] + if {[string range $pattern 0 0]=="-"} break + foreach f $::alltests { + set tail [file tail $f] + if {[lsearch $files $f]<0 && [string match $pattern $tail]} { + lappend files $f + } + } + } + set extra [list -files $files] + } + + eval run_tests $suite $S $extra } } main $argv
diff --git a/third_party/sqlite/src/test/pragma.test b/third_party/sqlite/src/test/pragma.test index 0b9ca293..fddec22f 100644 --- a/third_party/sqlite/src/test/pragma.test +++ b/third_party/sqlite/src/test/pragma.test
@@ -497,6 +497,7 @@ # Verify that PRAGMA integrity_check catches UNIQUE and NOT NULL # constraint violations. # +sqlite3_db_config db DEFENSIVE 0 do_execsql_test pragma-3.20 { CREATE TABLE t1(a,b); CREATE INDEX t1a ON t1(a);
diff --git a/third_party/sqlite/src/test/pragma3.test b/third_party/sqlite/src/test/pragma3.test index 71865b7..3b360ab0 100644 --- a/third_party/sqlite/src/test/pragma3.test +++ b/third_party/sqlite/src/test/pragma3.test
@@ -15,7 +15,11 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl -do_not_use_codec + +if {[sqlite3 -has-codec]} { + finish_test + return +} do_execsql_test pragma3-100 { PRAGMA data_version;
diff --git a/third_party/sqlite/src/test/pragma4.test b/third_party/sqlite/src/test/pragma4.test index d3ded75..7fba5199 100644 --- a/third_party/sqlite/src/test/pragma4.test +++ b/third_party/sqlite/src/test/pragma4.test
@@ -100,4 +100,146 @@ [db eval {EXPLAIN PRAGMA integrity_check}] } {/ IntegrityCk 2 2 1 x[0-9]+,1x /} + +#-------------------------------------------------------------------------- +# +reset_db +forcedelete test.db2 +do_execsql_test 4.1.1 { + CREATE TABLE t1(a, b, c); + ATTACH 'test.db2' AS aux; + CREATE TABLE aux.t2(d, e, f); +} +do_execsql_test 4.1.2 { PRAGMA table_info = t1 } { + 0 a {} 0 {} 0 1 b {} 0 {} 0 2 c {} 0 {} 0 +} +do_execsql_test 4.1.3 { PRAGMA table_info = t2 } { + 0 d {} 0 {} 0 1 e {} 0 {} 0 2 f {} 0 {} 0 +} +do_test 4.1.4 { + sqlite3 db3 test.db + sqlite3 db2 test.db2 + execsql { DROP TABLE t1 } db3 + execsql { DROP TABLE t2 } db2 +} {} +do_execsql_test 4.1.5 { PRAGMA table_info(t1) } +do_execsql_test 4.1.6 { PRAGMA table_info(t2) } + +db2 close +db3 close +reset_db +forcedelete test.db2 +do_execsql_test 4.2.1 { + CREATE TABLE t1(a, b, c); + ATTACH 'test.db2' AS aux; + CREATE TABLE aux.t2(d, e, f); +} +ifcapable vtab { + do_execsql_test 4.2.2 { SELECT * FROM pragma_table_info('t1') } { + 0 a {} 0 {} 0 1 b {} 0 {} 0 2 c {} 0 {} 0 + } + do_execsql_test 4.2.3 { SELECT * FROM pragma_table_info('t2') } { + 0 d {} 0 {} 0 1 e {} 0 {} 0 2 f {} 0 {} 0 + } +} +do_test 4.2.4 { + sqlite3 db3 test.db + sqlite3 db2 test.db2 + execsql { DROP TABLE t1 } db3 + execsql { DROP TABLE t2 } db2 +} {} +ifcapable vtab { + do_execsql_test 4.2.5 { SELECT * FROM pragma_table_info('t1') } + do_execsql_test 4.2.6 { SELECT * FROM pragma_table_info('t2') } +} + +db2 close +db3 close +reset_db +forcedelete test.db2 +do_execsql_test 4.3.1 { + CREATE TABLE t1(a, b, c); + CREATE INDEX i1 ON t1(b); + ATTACH 'test.db2' AS aux; + CREATE TABLE aux.t2(d, e, f); + CREATE INDEX aux.i2 ON t2(e); +} +ifcapable vtab { + do_execsql_test 4.3.2 { SELECT * FROM pragma_index_info('i1') } {0 1 b} + do_execsql_test 4.3.3 { SELECT * FROM pragma_index_info('i2') } {0 1 e} +} +do_test 4.3.4 { + sqlite3 db3 test.db + sqlite3 db2 test.db2 + execsql { DROP INDEX i1 } db3 + execsql { DROP INDEX i2 } db2 +} {} +ifcapable vtab { + do_execsql_test 4.3.5 { SELECT * FROM pragma_index_info('i1') } + do_execsql_test 4.3.6 { SELECT * FROM pragma_index_info('i2') } +} + +execsql {SELECT * FROM main.sqlite_master, aux.sqlite_master} +do_execsql_test 4.4.0 { + CREATE INDEX main.i1 ON t1(b, c); + CREATE INDEX aux.i2 ON t2(e, f); +} +ifcapable vtab { + do_execsql_test 4.4.1 { SELECT * FROM pragma_index_list('t1') } {0 i1 0 c 0} + do_execsql_test 4.4.2 { SELECT * FROM pragma_index_list('t2') } {0 i2 0 c 0} +} +do_test 4.4.3 { + execsql { DROP INDEX i1 } db3 + execsql { DROP INDEX i2 } db2 +} {} +ifcapable vtab { + do_execsql_test 4.4.5 { SELECT * FROM pragma_index_list('t1') } {} + do_execsql_test 4.4.6 { SELECT * FROM pragma_index_list('t2') } {} +} +execsql {SELECT * FROM main.sqlite_master, aux.sqlite_master} + +do_execsql_test 4.5.0 { + CREATE UNIQUE INDEX main.i1 ON t1(a); + CREATE UNIQUE INDEX aux.i2 ON t2(d); + CREATE TABLE main.c1 (a, b, c REFERENCES t1(a)); + CREATE TABLE aux.c2 (d, e, r REFERENCES t2(d)); +} +ifcapable vtab { + do_execsql_test 4.5.1 { SELECT * FROM pragma_foreign_key_list('c1') } { + 0 0 t1 c a {NO ACTION} {NO ACTION} NONE + } + do_execsql_test 4.5.2 { SELECT * FROM pragma_foreign_key_list('c2') } { + 0 0 t2 r d {NO ACTION} {NO ACTION} NONE + } +} +do_test 4.5.3 { + execsql { DROP TABLE c1 } db3 + execsql { DROP TABLE c2 } db2 +} {} +ifcapable vtab { + do_execsql_test 4.5.4 { SELECT * FROM pragma_foreign_key_list('c1') } + do_execsql_test 4.5.5 { SELECT * FROM pragma_foreign_key_list('c2') } +} +execsql {SELECT * FROM main.sqlite_master, aux.sqlite_master} + +do_execsql_test 4.6.0 { + CREATE TABLE main.c1 (a, b, c REFERENCES t1(a)); + CREATE TABLE aux.c2 (d, e, r REFERENCES t2(d)); + INSERT INTO main.c1 VALUES(1, 2, 3); + INSERT INTO aux.c2 VALUES(4, 5, 6); +} +do_execsql_test 4.6.1 { pragma foreign_key_check('c1') } { + c1 1 t1 0 +} +do_execsql_test 4.6.2 { pragma foreign_key_check('c2') } { + c2 1 t2 0 +} +do_test 4.6.3 { + execsql { DROP TABLE c2 } db2 +} {} +do_execsql_test 4.6.4 { pragma foreign_key_check('c1') } {c1 1 t1 0} +do_catchsql_test 4.6.5 { + pragma foreign_key_check('c2') +} {1 {no such table: c2}} + finish_test
diff --git a/third_party/sqlite/src/test/printf.test b/third_party/sqlite/src/test/printf.test index 6103d8ac..d768898f 100644 --- a/third_party/sqlite/src/test/printf.test +++ b/third_party/sqlite/src/test/printf.test
@@ -3757,25 +3757,23 @@ # Now test malloc() failure within a sqlite3_mprintf(): # -ifcapable memdebug { - foreach var {a b c d} { - set $var [string repeat $var 400] - } - set str1 "[string repeat A 360]%d%d%s" - set str2 [string repeat B 5000] - set zSuccess "[string repeat A 360]11[string repeat B 5000]" - foreach ::iRepeat {0 1} { - set nTestNum 1 - while {1} { - sqlite3_memdebug_fail $nTestNum -repeat $::iRepeat - set z [sqlite3_mprintf_str $str1 1 1 $str2] - set nFail [sqlite3_memdebug_fail -1 -benign nBenign] - do_test printf-malloc-$::iRepeat.$nTestNum { - expr {($nFail>0 && $z eq "") || ($nFail==$nBenign && $z eq $zSuccess)} - } {1} - if {$nFail == 0} break - incr nTestNum - } +foreach var {a b c d} { + set $var [string repeat $var 400] +} +set str1 "[string repeat A 360]%d%d%s" +set str2 [string repeat B 5000] +set zSuccess "[string repeat A 360]11[string repeat B 5000]" +foreach ::iRepeat {0 1} { + set nTestNum 1 + while {1} { + sqlite3_memdebug_fail $nTestNum -repeat $::iRepeat + set z [sqlite3_mprintf_str $str1 1 1 $str2] + set nFail [sqlite3_memdebug_fail -1 -benign nBenign] + do_test printf-malloc-$::iRepeat.$nTestNum { + expr {($nFail>0 && $z eq "") || ($nFail==$nBenign && $z eq $zSuccess)} + } {1} + if {$nFail == 0} break + incr nTestNum } }
diff --git a/third_party/sqlite/src/test/releasetest.tcl b/third_party/sqlite/src/test/releasetest.tcl index 2a93ebf5..766150f 100755 --- a/third_party/sqlite/src/test/releasetest.tcl +++ b/third_party/sqlite/src/test/releasetest.tcl
@@ -79,6 +79,9 @@ -DSQLITE_ENABLE_UNLOCK_NOTIFY -DSQLITE_THREADSAFE -DSQLITE_TCL_DEFAULT_FULLMUTEX=1 + } + "User-Auth" { + -O2 -DSQLITE_USER_AUTHENTICATION=1 } "Secure-Delete" { @@ -274,6 +277,7 @@ "Have-Not" test "Secure-Delete" test "Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test" + "User-Auth" tcltest "Update-Delete-Limit" test "Extra-Robustness" test "Device-Two" test
diff --git a/third_party/sqlite/src/test/resetdb.test b/third_party/sqlite/src/test/resetdb.test index 0515db7..5f816cae 100644 --- a/third_party/sqlite/src/test/resetdb.test +++ b/third_party/sqlite/src/test/resetdb.test
@@ -65,6 +65,7 @@ do_test 200 { # Thoroughly corrupt the database file by overwriting the first # page with randomness. + sqlite3_db_config db DEFENSIVE 0 catchsql { UPDATE sqlite_dbpage SET data=randomblob(4096) WHERE pgno=1; PRAGMA quick_check; @@ -125,6 +126,7 @@ } {210 26000 ok wal 8192 12} # Corrupt the database again +sqlite3_db_config db DEFENSIVE 0 do_catchsql_test 320 { UPDATE sqlite_dbpage SET data=randomblob(8192) WHERE pgno=1; PRAGMA quick_check @@ -228,6 +230,7 @@ return } +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 710 { UPDATE sqlite_dbpage SET data= X'53514C69746520666F726D61742033000200030100402020000000000000001300000000000000000000000300000004000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000D00000003017C0001D801AC017C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002E03061715110145696E6465787431626374310443524541544520494E4445582074316263204F4E20743128622C63292A0206171311013F696E64657874316174310343524541544520494E44455820743161204F4E20743128612926010617111101397461626C657431743102435245415445205441424C4520743128612C622C6329' WHERE pgno=1;
diff --git a/third_party/sqlite/src/test/shared.test b/third_party/sqlite/src/test/shared.test index 207ba1b..cb2267b0 100644 --- a/third_party/sqlite/src/test/shared.test +++ b/third_party/sqlite/src/test/shared.test
@@ -1145,38 +1145,40 @@ # Shared cache on named memory databases attached to readonly connections. # -do_test shared-$av-16.8.1 { +if {![sqlite3 -has-codec]} { + do_test shared-$av-16.8.1 { + db1 close + db2 close + + sqlite3 db test1.db + db eval { + CREATE TABLE yy(a, b); + INSERT INTO yy VALUES(77, 88); + } + db close + + sqlite3 db1 test1.db -uri 1 -readonly 1 + sqlite3 db2 test2.db -uri 1 + + db1 eval { + ATTACH 'file:mem?mode=memory&cache=shared' AS shared; + CREATE TABLE shared.xx(a, b); + INSERT INTO xx VALUES(55, 66); + } + db2 eval { + ATTACH 'file:mem?mode=memory&cache=shared' AS shared; + SELECT * FROM xx; + } + } {55 66} + + do_test shared-$av-16.8.2 { db1 eval { SELECT * FROM yy } } {77 88} + do_test shared-$av-16.8.3 { + list [catch {db1 eval { INSERT INTO yy VALUES(1, 2) }} msg] $msg + } {1 {attempt to write a readonly database}} + db1 close db2 close - - sqlite3 db test1.db - db eval { - CREATE TABLE yy(a, b); - INSERT INTO yy VALUES(77, 88); - } - db close - - sqlite3 db1 test1.db -uri 1 -readonly 1 - sqlite3 db2 test2.db -uri 1 - - db1 eval { - ATTACH 'file:mem?mode=memory&cache=shared' AS shared; - CREATE TABLE shared.xx(a, b); - INSERT INTO xx VALUES(55, 66); - } - db2 eval { - ATTACH 'file:mem?mode=memory&cache=shared' AS shared; - SELECT * FROM xx; - } -} {55 66} - -do_test shared-$av-16.8.2 { db1 eval { SELECT * FROM yy } } {77 88} -do_test shared-$av-16.8.3 { - list [catch {db1 eval { INSERT INTO yy VALUES(1, 2) }} msg] $msg -} {1 {attempt to write a readonly database}} - -db1 close -db2 close +} } ;# end of autovacuum on/off loop
diff --git a/third_party/sqlite/src/test/shared8.test b/third_party/sqlite/src/test/shared8.test index 8ac1cda..c4daa834d 100644 --- a/third_party/sqlite/src/test/shared8.test +++ b/third_party/sqlite/src/test/shared8.test
@@ -62,6 +62,7 @@ } {1 i 2 ii 3 iii 4 iv} do_test 1.1 { + sqlite3_db_config db1 DEFENSIVE 0 execsql { PRAGMA writable_schema = 1; DELETE FROM sqlite_master WHERE 1;
diff --git a/third_party/sqlite/src/test/shell1.test b/third_party/sqlite/src/test/shell1.test index 1bd7fbea..aaf7add 100644 --- a/third_party/sqlite/src/test/shell1.test +++ b/third_party/sqlite/src/test/shell1.test
@@ -378,7 +378,7 @@ } {1 1 1} do_test shell1-3.10.2 { # we allow .help to take extra args (it is help after all) - set res [catchcmd "test.db" ".help BAD"] + set res [catchcmd "test.db" ".help *"] # look for a few of the possible help commands list [regexp {.help} $res] \ [regexp {.quit} $res] \
diff --git a/third_party/sqlite/src/test/snapshot2.test b/third_party/sqlite/src/test/snapshot2.test index 1486d47e..48187021 100644 --- a/third_party/sqlite/src/test/snapshot2.test +++ b/third_party/sqlite/src/test/snapshot2.test
@@ -238,4 +238,3 @@ finish_test -
diff --git a/third_party/sqlite/src/test/snapshot3.test b/third_party/sqlite/src/test/snapshot3.test index 8c330d7c..4dca202b 100644 --- a/third_party/sqlite/src/test/snapshot3.test +++ b/third_party/sqlite/src/test/snapshot3.test
@@ -97,4 +97,3 @@ } {1 SQLITE_ERROR_SNAPSHOT} finish_test -
diff --git a/third_party/sqlite/src/test/snapshot4.test b/third_party/sqlite/src/test/snapshot4.test index e279f100..7ed3673 100644 --- a/third_party/sqlite/src/test/snapshot4.test +++ b/third_party/sqlite/src/test/snapshot4.test
@@ -72,4 +72,3 @@ finish_test -
diff --git a/third_party/sqlite/src/test/snapshot_up.test b/third_party/sqlite/src/test/snapshot_up.test index af56c01cd..36146f251 100644 --- a/third_party/sqlite/src/test/snapshot_up.test +++ b/third_party/sqlite/src/test/snapshot_up.test
@@ -181,4 +181,3 @@ sqlite3_snapshot_free $::snap2 finish_test -
diff --git a/third_party/sqlite/src/test/swarmvtab3.test b/third_party/sqlite/src/test/swarmvtab3.test index 6e52355d..b062f9e 100644 --- a/third_party/sqlite/src/test/swarmvtab3.test +++ b/third_party/sqlite/src/test/swarmvtab3.test
@@ -231,4 +231,3 @@ forcedelete {*}[glob test_remote.db*] finish_test -
diff --git a/third_party/sqlite/src/test/swarmvtabfault.test b/third_party/sqlite/src/test/swarmvtabfault.test index 083d80d..8cca3b27 100644 --- a/third_party/sqlite/src/test/swarmvtabfault.test +++ b/third_party/sqlite/src/test/swarmvtabfault.test
@@ -63,4 +63,3 @@ } finish_test -
diff --git a/third_party/sqlite/src/test/tabfunc01.test b/third_party/sqlite/src/test/tabfunc01.test index 0dc6408..63ef0792 100644 --- a/third_party/sqlite/src/test/tabfunc01.test +++ b/third_party/sqlite/src/test/tabfunc01.test
@@ -28,6 +28,9 @@ do_execsql_test tabfunc01-1.1 { SELECT *, '|' FROM generate_series WHERE start=1 AND stop=9 AND step=2; } {1 | 3 | 5 | 7 | 9 |} +do_execsql_test tabfunc01-1.1b { + PRAGMA table_xinfo(generate_series); +} {0 value {} 0 {} 0 0 1 start {} 0 {} 0 1 2 stop {} 0 {} 0 1 3 step {} 0 {} 0 1} do_execsql_test tabfunc01-1.2 { SELECT *, '|' FROM generate_series LIMIT 5; } {0 | 1 | 2 | 3 | 4 |} @@ -108,19 +111,19 @@ SELECT DISTINCT value FROM generate_series(1,x), t1 ORDER BY 1; } {1 2 3} -# Eponymous virtual table exists in the "main" schema only +# Eponymous virtual table exists in all schemas. # do_execsql_test tabfunc01-4.1 { SELECT * FROM main.generate_series(1,4) } {1 2 3 4} -do_catchsql_test tabfunc01-4.2 { +do_execsql_test tabfunc01-4.2 { SELECT * FROM temp.generate_series(1,4) -} {1 {no such table: temp.generate_series}} -do_catchsql_test tabfunc01-4.3 { +} {1 2 3 4} +do_execsql_test tabfunc01-4.3 { ATTACH ':memory:' AS aux1; CREATE TABLE aux1.t1(a,b,c); SELECT * FROM aux1.generate_series(1,4) -} {1 {no such table: aux1.generate_series}} +} {1 2 3 4} # The next series of tests is verifying that virtual table are able # to optimize the IN operator, even on terms that are not marked "omit".
diff --git a/third_party/sqlite/src/test/table.test b/third_party/sqlite/src/test/table.test index ed4bbb2..e81a6e6 100644 --- a/third_party/sqlite/src/test/table.test +++ b/third_party/sqlite/src/test/table.test
@@ -276,6 +276,7 @@ db close forcedelete test.db sqlite3 db test.db + sqlite3_db_config db DEFENSIVE 0 db eval { CREATE TABLE t0(a,b); CREATE INDEX t ON t0(a);
diff --git a/third_party/sqlite/src/test/tableapi.test b/third_party/sqlite/src/test/tableapi.test index 122267fe..02633cdc 100644 --- a/third_party/sqlite/src/test/tableapi.test +++ b/third_party/sqlite/src/test/tableapi.test
@@ -22,9 +22,7 @@ return } -ifcapable memdebug { - source $testdir/malloc_common.tcl -} +source $testdir/malloc_common.tcl do_test tableapi-1.0 { set ::dbx [sqlite3_open test.db] @@ -239,18 +237,16 @@ sqlite3_close $::dbx } {SQLITE_OK} -ifcapable memdebug { - do_malloc_test tableapi-7 -sqlprep { - DROP TABLE IF EXISTS t1; - CREATE TABLE t1(a,b); - INSERT INTO t1 VALUES(1,2); - INSERT INTO t1 VALUES(3,4); - INSERT INTO t1 SELECT a+4, b+4 FROM t1; - INSERT INTO t1 SELECT a+8, b+8 FROM t1; - } -tclbody { - set r [sqlite3_get_table_printf db {SELECT rowid, a, b FROM t1} {}] - if {[llength $r]<26} {error "out of memory"} - } +do_malloc_test tableapi-7 -sqlprep { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a,b); + INSERT INTO t1 VALUES(1,2); + INSERT INTO t1 VALUES(3,4); + INSERT INTO t1 SELECT a+4, b+4 FROM t1; + INSERT INTO t1 SELECT a+8, b+8 FROM t1; +} -tclbody { + set r [sqlite3_get_table_printf db {SELECT rowid, a, b FROM t1} {}] + if {[llength $r]<26} {error "out of memory"} } finish_test
diff --git a/third_party/sqlite/src/test/tempdb2.test b/third_party/sqlite/src/test/tempdb2.test index 4efe52e..b38609f 100644 --- a/third_party/sqlite/src/test/tempdb2.test +++ b/third_party/sqlite/src/test/tempdb2.test
@@ -76,4 +76,25 @@ SELECT b=int2str(2) FROM t1 } {1 1 1} +#------------------------------------------------------------------------- +db close +sqlite3 db "" +db func int2str int2str + +do_execsql_test 2.0 { + PRAGMA cache_size = -100; + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); + WITH c(x) AS ( VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100 ) + INSERT INTO t1 SELECT x, int2str(x) FROM c; +} + +do_execsql_test 2.1 { + INSERT INTO t1 VALUES(10001, int2str(1001) || int2str(1001) || int2str(1001)); +} + +do_execsql_test 2.2 { + SELECT b FROM t1 WHERE a = 10001; +} "[int2str 1001][int2str 1001][int2str 1001]" + finish_test +
diff --git a/third_party/sqlite/src/test/tester.tcl b/third_party/sqlite/src/test/tester.tcl index ecf6f192..183ffe70 100644 --- a/third_party/sqlite/src/test/tester.tcl +++ b/third_party/sqlite/src/test/tester.tcl
@@ -456,6 +456,11 @@ {^-+malloctrace=.+$} { foreach {dummy cmdlinearg(malloctrace)} [split $a =] break if {$cmdlinearg(malloctrace)} { + if {0==$::sqlite_options(memdebug)} { + set err "Error: --malloctrace=1 requires an SQLITE_MEMDEBUG build" + puts stderr $err + exit 1 + } sqlite3_memdebug_log start } } @@ -1258,13 +1263,13 @@ output2 "Unfreed memory: [sqlite3_memory_used] bytes in\ [lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1] allocations" incr nErr - ifcapable memdebug||mem5||(mem3&&debug) { + ifcapable mem5||(mem3&&debug) { output2 "Writing unfreed memory log to \"./memleak.txt\"" sqlite3_memdebug_dump ./memleak.txt } } else { output2 "All memory allocations freed - no leaks" - ifcapable memdebug||mem5 { + ifcapable mem5 { sqlite3_memdebug_dump ./memusage.txt } } @@ -1275,15 +1280,14 @@ output2 "Number of malloc() : [sqlite3_memdebug_malloc_count] calls" } if {$::cmdlinearg(malloctrace)} { - output2 "Writing mallocs.sql..." - memdebug_log_sql + output2 "Writing mallocs.tcl..." + memdebug_log_sql mallocs.tcl sqlite3_memdebug_log stop sqlite3_memdebug_log clear - if {[sqlite3_memory_used]>0} { - output2 "Writing leaks.sql..." + output2 "Writing leaks.tcl..." sqlite3_memdebug_log sync - memdebug_log_sql leaks.sql + memdebug_log_sql leaks.tcl } } foreach f [glob -nocomplain test.db-*-journal] { @@ -2019,7 +2023,7 @@ return [md5 $txt] } -proc memdebug_log_sql {{filename mallocs.sql}} { +proc memdebug_log_sql {filename} { set data [sqlite3_memdebug_log dump] set nFrame [expr [llength [lindex $data 0]]-2] @@ -2065,8 +2069,18 @@ append sql "INSERT INTO ${database}.file VALUES('$f', '$contents');\n" } + set escaped "BEGIN; ${tbl}${tbl2}${tbl3}${sql} ; COMMIT;" + set escaped [string map [list "{" "\\{" "}" "\\}"] $escaped] + set fd [open $filename w] - puts $fd "BEGIN; ${tbl}${tbl2}${tbl3}${sql} ; COMMIT;" + puts $fd "set BUILTIN {" + puts $fd $escaped + puts $fd "}" + puts $fd {set BUILTIN [string map [list "\\{" "{" "\\}" "}"] $BUILTIN]} + set mtv [open $::testdir/malloctraceviewer.tcl] + set txt [read $mtv] + close $mtv + puts $fd $txt close $fd }
diff --git a/third_party/sqlite/src/test/trigger7.test b/third_party/sqlite/src/test/trigger7.test index 5fa7638..ecc86dbb 100644 --- a/third_party/sqlite/src/test/trigger7.test +++ b/third_party/sqlite/src/test/trigger7.test
@@ -106,6 +106,7 @@ # in the series. # do_test trigger7-99.1 { + sqlite3_db_config db DEFENSIVE 0 execsql { PRAGMA writable_schema=on; UPDATE sqlite_master SET sql='nonsense';
diff --git a/third_party/sqlite/src/test/triggerA.test b/third_party/sqlite/src/test/triggerA.test index 47cd359..41afc44e 100644 --- a/third_party/sqlite/src/test/triggerA.test +++ b/third_party/sqlite/src/test/triggerA.test
@@ -200,13 +200,6 @@ } } {3 305 3 9900305 4 404 4 9900404 5 504 5 9900504} -# Only run the reamining tests if memory debugging is turned on. -# -ifcapable !memdebug { - puts "Skipping triggerA malloc tests: not compiled with -DSQLITE_MEMDEBUG..." - finish_test - return -} source $testdir/malloc_common.tcl # Save a copy of the current database configuration.
diff --git a/third_party/sqlite/src/test/triggerE.test b/third_party/sqlite/src/test/triggerE.test index 350f809..4d6f9cdf 100644 --- a/third_party/sqlite/src/test/triggerE.test +++ b/third_party/sqlite/src/test/triggerE.test
@@ -68,6 +68,7 @@ # Test that variable references within trigger definitions loaded from # the sqlite_master table are automatically converted to NULL. # +sqlite3_db_config db DEFENSIVE 0 do_execsql_test 2.1 { PRAGMA writable_schema = 1; INSERT INTO sqlite_master VALUES('trigger', 'tr1', 't1', 0,
diff --git a/third_party/sqlite/src/test/unionvtab.test b/third_party/sqlite/src/test/unionvtab.test index eb55f85..15f22d1 100644 --- a/third_party/sqlite/src/test/unionvtab.test +++ b/third_party/sqlite/src/test/unionvtab.test
@@ -455,4 +455,3 @@ } {six 6} finish_test -
diff --git a/third_party/sqlite/src/test/unionvtabfault.test b/third_party/sqlite/src/test/unionvtabfault.test index 6141bdd..aeb1696fc 100644 --- a/third_party/sqlite/src/test/unionvtabfault.test +++ b/third_party/sqlite/src/test/unionvtabfault.test
@@ -81,4 +81,3 @@ finish_test -
diff --git a/third_party/sqlite/src/test/vtab1.test b/third_party/sqlite/src/test/vtab1.test index 811f7f80..a95ac45 100644 --- a/third_party/sqlite/src/test/vtab1.test +++ b/third_party/sqlite/src/test/vtab1.test
@@ -1253,6 +1253,7 @@ # characters that can be mistaken for printf() formatting directives. # do_test vtab1-17.1 { + sqlite3_db_config db DEFENSIVE 0 execsql { PRAGMA writable_schema = 1; INSERT INTO sqlite_master VALUES(
diff --git a/third_party/sqlite/src/test/vtab_err.test b/third_party/sqlite/src/test/vtab_err.test index 1b088474..0b6ccd3 100644 --- a/third_party/sqlite/src/test/vtab_err.test +++ b/third_party/sqlite/src/test/vtab_err.test
@@ -20,7 +20,6 @@ } - unset -nocomplain echo_module_begin_fail do_ioerr_test vtab_err-1 -tclprep { register_echo_module [sqlite3_connection_pointer db] @@ -40,11 +39,6 @@ COMMIT; } -ifcapable !memdebug { - puts "Skipping vtab_err-2 tests: not compiled with -DSQLITE_MEMDEBUG..." - finish_test - return -} source $testdir/malloc_common.tcl @@ -68,4 +62,26 @@ sqlite3_memdebug_fail -1 +reset_db +register_echo_module [sqlite3_connection_pointer db] +do_execsql_test vtab_err-3.0 { + CREATE TABLE r(a PRIMARY KEY, b, c); + CREATE VIRTUAL TABLE e USING echo(r); +} +faultsim_save_and_close + +do_faultsim_test vtab_err-3 -faults oom-t* -prep { + faultsim_restore_and_reopen + register_echo_module [sqlite3_connection_pointer db] +} -body { + execsql { + BEGIN; + CREATE TABLE xyz(x); + SELECT a FROM e; + COMMIT; + } +} -test { + faultsim_test_result {0 {}} +} + finish_test
diff --git a/third_party/sqlite/src/test/wal64k.test b/third_party/sqlite/src/test/wal64k.test index 4d84d91..dab9371 100644 --- a/third_party/sqlite/src/test/wal64k.test +++ b/third_party/sqlite/src/test/wal64k.test
@@ -47,5 +47,17 @@ integrity_check 1.3 db close +forcedelete test.db +sqlite3 db test.db -vfs unix-excl +do_execsql_test 2.1 { + PRAGMA page_size=512; + PRAGMA journal_mode=WAL; + CREATE TABLE t1(a,b); + WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<8200) + INSERT INTO t1(a,b) SELECT x, zeroblob(300) FROM c; + PRAGMA integrity_check; +} {wal ok} + +db close test_syscall pagesize -1 finish_test
diff --git a/third_party/sqlite/src/test/wherelimit2.test b/third_party/sqlite/src/test/wherelimit2.test index 19b6d917..5edd65b 100644 --- a/third_party/sqlite/src/test/wherelimit2.test +++ b/third_party/sqlite/src/test/wherelimit2.test
@@ -297,4 +297,3 @@ finish_test -
diff --git a/third_party/sqlite/src/test/window1.test b/third_party/sqlite/src/test/window1.test index 78a5783..28b1242 100644 --- a/third_party/sqlite/src/test/window1.test +++ b/third_party/sqlite/src/test/window1.test
@@ -549,4 +549,49 @@ ORDER BY b LIMIT 2; } {2 B two 3 C three} +#------------------------------------------------------------------------- + +do_execsql_test 13.1 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a int, b int); + INSERT INTO t1 VALUES(1,11); + INSERT INTO t1 VALUES(2,12); +} + +do_execsql_test 13.2.1 { + SELECT a, rank() OVER(ORDER BY b) FROM t1; + SELECT a, rank() OVER(ORDER BY b DESC) FROM t1; +} { + 1 1 2 2 2 1 1 2 +} +do_execsql_test 13.2.2 { + SELECT a, rank() OVER(ORDER BY b) FROM t1 + UNION ALL + SELECT a, rank() OVER(ORDER BY b DESC) FROM t1; +} { + 1 1 2 2 2 1 1 2 +} +do_execsql_test 13.3 { + SELECT a, rank() OVER(ORDER BY b) FROM t1 + UNION + SELECT a, rank() OVER(ORDER BY b DESC) FROM t1; +} { + 1 1 1 2 2 1 2 2 +} + +do_execsql_test 13.4 { + SELECT a, rank() OVER(ORDER BY b) FROM t1 + EXCEPT + SELECT a, rank() OVER(ORDER BY b DESC) FROM t1; +} { + 1 1 2 2 +} + +do_execsql_test 13.5 { + SELECT a, rank() OVER(ORDER BY b) FROM t1 + INTERSECT + SELECT a, rank() OVER(ORDER BY b DESC) FROM t1; +} { +} + finish_test
diff --git a/third_party/sqlite/src/test/window5.test b/third_party/sqlite/src/test/window5.test index adcf58a..21ea67b9 100644 --- a/third_party/sqlite/src/test/window5.test +++ b/third_party/sqlite/src/test/window5.test
@@ -94,4 +94,3 @@ finish_test -
diff --git a/third_party/sqlite/src/test/window6.test b/third_party/sqlite/src/test/window6.test index f6984c8..ea0e5f6 100644 --- a/third_party/sqlite/src/test/window6.test +++ b/third_party/sqlite/src/test/window6.test
@@ -147,17 +147,17 @@ #------------------------------------------------------------------------- # -do_execsql_test 6.0 { - SELECT LIKE('!', '', '!') x WHERE x; -} {} - -do_execsql_test 6.1 { - SELECT LIKE("!","","!")""WHeRE""; -} {} - -do_catchsql_test 6.2 { - SELECT LIKE("!","","!")""window""; -} {1 {near "window": syntax error}} +ifcapable !icu { + do_execsql_test 6.0 { + SELECT LIKE('!', '', '!') x WHERE x; + } {} + do_execsql_test 6.1 { + SELECT LIKE("!","","!")""WHeRE""; + } {} + do_catchsql_test 6.2 { + SELECT LIKE("!","","!")""window""; + } {1 {near "window": syntax error}} +} reset_db do_execsql_test 7.0 { @@ -166,9 +166,11 @@ INSERT INTO t1 VALUES(''); } -do_execsql_test 7.1 { - SELECT count(*) FROM t1 WHERE x LIKE '!' ESCAPE '!'; -} {0} +ifcapable !icu { + do_execsql_test 7.1 { + SELECT count(*) FROM t1 WHERE x LIKE '!' ESCAPE '!'; + } {0} +} #------------------------------------------------------------------------- # @@ -336,4 +338,3 @@ } finish_test -
diff --git a/third_party/sqlite/src/test/windowfault.test b/third_party/sqlite/src/test/windowfault.test index 7699a10..c79ffe02 100644 --- a/third_party/sqlite/src/test/windowfault.test +++ b/third_party/sqlite/src/test/windowfault.test
@@ -163,4 +163,3 @@ } finish_test -
diff --git a/third_party/sqlite/src/test/without_rowid3.test b/third_party/sqlite/src/test/without_rowid3.test index 0f5333f..f34f30e8 100644 --- a/third_party/sqlite/src/test/without_rowid3.test +++ b/third_party/sqlite/src/test/without_rowid3.test
@@ -953,6 +953,7 @@ 'main', 'table', 't1', $zCreate, $zOld, $zNew, 0 )} } + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_test without_rowid3-14.2.1.1 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} @@ -962,6 +963,7 @@ do_test without_rowid3-14.2.1.3 { test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 # Test ALTER TABLE RENAME TABLE a bit. # @@ -1037,6 +1039,7 @@ } } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_test without_rowid3-14.2tmp.1.1 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} @@ -1046,6 +1049,7 @@ do_test without_rowid3-14.2tmp.1.3 { test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 # Test ALTER TABLE RENAME TABLE a bit. # @@ -1122,6 +1126,7 @@ } } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_test without_rowid3-14.2aux.1.1 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} @@ -1131,6 +1136,7 @@ do_test without_rowid3-14.2aux.1.3 { test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 # Test ALTER TABLE RENAME TABLE a bit. #
diff --git a/third_party/sqlite/src/test/zipfile.test b/third_party/sqlite/src/test/zipfile.test index bef7f31af..25dc5d64 100644 --- a/third_party/sqlite/src/test/zipfile.test +++ b/third_party/sqlite/src/test/zipfile.test
@@ -761,4 +761,38 @@ SELECT name, data FROM z ORDER BY name; } {b0suffix two b2suffix one} + +if {$tcl_platform(platform)!="windows"} { + do_test 12.0 { + catch { file delete -force subdir } + foreach {path sz} { + subdir/x1.txt 143 + subdir/x2.txt 153 + } { + set dir [file dirname $path] + catch { file mkdir $dir } + set fd [open $path w] + puts -nonewline $fd [string repeat 1 $sz] + close $fd + } + } {} + + do_execsql_test 12.1 { + SELECT name FROM fsdir('subdir') ORDER BY 1; + } {subdir subdir/x1.txt subdir/x2.txt} + + do_execsql_test 12.2 { + CREATE TABLE d AS SELECT 'subdir' d; + CREATE TABLE x AS SELECT 1 x; + } + + do_execsql_test 12.4 { + SELECT name FROM d JOIN x JOIN fsdir(d) ORDER BY 1; + } {subdir subdir/x1.txt subdir/x2.txt} + + do_execsql_test 12.5 { + SELECT name FROM d JOIN x JOIN fsdir('.', d) ORDER BY 1; + } {. ./x1.txt ./x2.txt} +} + finish_test
diff --git a/third_party/sqlite/src/test/zipfile2.test b/third_party/sqlite/src/test/zipfile2.test index 921f989..bb276b5 100644 --- a/third_party/sqlite/src/test/zipfile2.test +++ b/third_party/sqlite/src/test/zipfile2.test
@@ -241,4 +241,3 @@ } {test2} finish_test -
diff --git a/third_party/sqlite/src/tool/genfkey.test b/third_party/sqlite/src/tool/genfkey.test index 2c52acd..732043e 100644 --- a/third_party/sqlite/src/tool/genfkey.test +++ b/third_party/sqlite/src/tool/genfkey.test
@@ -351,4 +351,3 @@ SELECT * FROM child; } } {1 1} -
diff --git a/third_party/sqlite/src/tool/lempar.c b/third_party/sqlite/src/tool/lempar.c index ce485e9..2ea7915 100644 --- a/third_party/sqlite/src/tool/lempar.c +++ b/third_party/sqlite/src/tool/lempar.c
@@ -23,6 +23,7 @@ ** input grammar file: */ #include <stdio.h> +#include <assert.h> /************ Begin %include sections from the grammar ************************/ %% /**************** End of %include directives **********************************/ @@ -987,10 +988,9 @@ yymajor = YYNOCODE; }else{ while( yypParser->yytos >= yypParser->yystack - && yymx != YYERRORSYMBOL && (yyact = yy_find_reduce_action( yypParser->yytos->stateno, - YYERRORSYMBOL)) >= YY_MIN_REDUCE + YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE ){ yy_pop_parser_stack(yypParser); }
diff --git a/third_party/sqlite/src/tool/mkpragmatab.tcl b/third_party/sqlite/src/tool/mkpragmatab.tcl index 83a85db..f6cf779 100644 --- a/third_party/sqlite/src/tool/mkpragmatab.tcl +++ b/third_party/sqlite/src/tool/mkpragmatab.tcl
@@ -120,7 +120,7 @@ NAME: writable_schema TYPE: FLAG - ARG: SQLITE_WriteSchema + ARG: SQLITE_WriteSchema|SQLITE_NoSchemaError IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS) NAME: read_uncommitted @@ -220,9 +220,17 @@ NAME: table_info FLAG: NeedSchema Result1 SchemaOpt + ARG: 0 COLS: cid name type notnull dflt_value pk IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) + NAME: table_xinfo + TYPE: TABLE_INFO + FLAG: NeedSchema Result1 SchemaOpt + ARG: 1 + COLS: cid name type notnull dflt_value pk hidden + IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) + NAME: stats FLAG: NeedSchema Result0 SchemaReq COLS: tbl idx wdth hght flgs @@ -359,16 +367,33 @@ IF: defined(SQLITE_DEBUG) || defined(SQLITE_TEST) NAME: key + TYPE: KEY + ARG: 0 IF: defined(SQLITE_HAS_CODEC) NAME: rekey + TYPE: KEY + ARG: 1 IF: defined(SQLITE_HAS_CODEC) NAME: hexkey + TYPE: HEXKEY + ARG: 2 IF: defined(SQLITE_HAS_CODEC) NAME: hexrekey TYPE: HEXKEY + ARG: 3 + IF: defined(SQLITE_HAS_CODEC) + + NAME: textkey + TYPE: KEY + ARG: 4 + IF: defined(SQLITE_HAS_CODEC) + + NAME: textrekey + TYPE: KEY + ARG: 5 IF: defined(SQLITE_HAS_CODEC) NAME: activate_extensions @@ -410,20 +435,20 @@ set cols_list {} set arg 0 proc record_one {} { - global name type if arg allbyname typebyif flags cols allcols + global name type if arg allbyname typebyif flags cols all_cols global cols_list colUsedBy if {$name==""} return if {$cols!=""} { - if {![info exists allcols($cols)]} { + if {![info exists all_cols($cols)]} { + set all_cols($cols) 1 lappend cols_list $cols - set allcols($cols) [llength $cols_list] } - set cx $allcols($cols) + set cx $cols lappend colUsedBy($cols) $name } else { set cx 0 } - set allbyname($name) [list $type $arg $if $flags $cx] + set allbyname($name) [list $type $arg $if $flags $cols] set name {} set type {} set if {} @@ -505,6 +530,13 @@ set fv [expr {$fv*2}] } +# Sort the column lists so that longer column lists occur first +# +proc colscmp {a b} { + return [expr {[llength $b] - [llength $a]}] +} +set cols_list [lsort -command colscmp $cols_list] + # Generate the array of column names used by pragmas that act like # queries. # @@ -513,10 +545,23 @@ puts $fd "** result column is different from the name of the pragma\n*/" puts $fd "static const char *const pragCName\[\] = {" set offset 0 +set allcollist {} foreach cols $cols_list { - set cols_offset($allcols($cols)) $offset + set n [llength $cols] + set limit [expr {[llength $allcollist] - $n}] + for {set i 0} {$i<$limit} {incr i} { + set sublist [lrange $allcollist $i [expr {$i+$n-1}]] + if {$sublist==$cols} { + puts $fd [format "%27s/* $colUsedBy($cols) reuses $i */" ""] + set cols_offset($cols) $i + break + } + } + if {$i<$limit} continue + set cols_offset($cols) $offset set ub " /* Used by: $colUsedBy($cols) */" foreach c $cols { + lappend allcollist $c puts $fd [format " /* %3d */ %-14s%s" $offset \"$c\", $ub] set ub "" incr offset @@ -534,7 +579,7 @@ puts $fd { u8 iPragCName; /* Start of column names in pragCName[] */} puts $fd " u8 nPragCName; \ /* Num of col names. 0 means use pragma name */" -puts $fd " u32 iArg; /* Extra argument */" +puts $fd " u64 iArg; /* Extra argument */" puts $fd "\175 PragmaName;" puts $fd "static const PragmaName aPragmaName\[\] = \173" @@ -542,12 +587,12 @@ set spacer [format { %26s } {}] foreach name $allnames { foreach {type arg if flag cx} $allbyname($name) break - if {$cx==0} { + if {$cx==0 || $cx==""} { set cy 0 set nx 0 } else { set cy $cols_offset($cx) - set nx [llength [lindex $cols_list [expr {$cx-1}]]] + set nx [llength $cx] } if {$if!=$current_if} { if {$current_if!=""} {
diff --git a/third_party/sqlite/src/tool/sqldiff.c b/third_party/sqlite/src/tool/sqldiff.c index d398ae0..ed3d533 100644 --- a/third_party/sqlite/src/tool/sqldiff.c +++ b/third_party/sqlite/src/tool/sqldiff.c
@@ -1493,8 +1493,8 @@ /* ** Write an SQLite value onto out. */ -static void putValue(FILE *out, sqlite3_value *pVal){ - int iDType = sqlite3_value_type(pVal); +static void putValue(FILE *out, sqlite3_stmt *pStmt, int k){ + int iDType = sqlite3_column_type(pStmt, k); sqlite3_int64 iX; double rX; sqlite3_uint64 uX; @@ -1503,24 +1503,24 @@ putc(iDType, out); switch( iDType ){ case SQLITE_INTEGER: - iX = sqlite3_value_int64(pVal); + iX = sqlite3_column_int64(pStmt, k); memcpy(&uX, &iX, 8); for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out); break; case SQLITE_FLOAT: - rX = sqlite3_value_double(pVal); + rX = sqlite3_column_double(pStmt, k); memcpy(&uX, &rX, 8); for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out); break; case SQLITE_TEXT: - iX = sqlite3_value_bytes(pVal); + iX = sqlite3_column_bytes(pStmt, k); putsVarint(out, (sqlite3_uint64)iX); - fwrite(sqlite3_value_text(pVal),1,(size_t)iX,out); + fwrite(sqlite3_column_text(pStmt, k),1,(size_t)iX,out); break; case SQLITE_BLOB: - iX = sqlite3_value_bytes(pVal); + iX = sqlite3_column_bytes(pStmt, k); putsVarint(out, (sqlite3_uint64)iX); - fwrite(sqlite3_value_blob(pVal),1,(size_t)iX,out); + fwrite(sqlite3_column_blob(pStmt, k),1,(size_t)iX,out); break; case SQLITE_NULL: break; @@ -1650,10 +1650,10 @@ case SQLITE_UPDATE: { for(k=1, i=0; i<nCol; i++){ if( aiFlg[i] ){ - putValue(out, sqlite3_column_value(pStmt,k)); + putValue(out, pStmt, k); k++; }else if( sqlite3_column_int(pStmt,k) ){ - putValue(out, sqlite3_column_value(pStmt,k+1)); + putValue(out, pStmt, k+1); k += 3; }else{ putc(0, out); @@ -1665,7 +1665,7 @@ putc(0, out); k++; }else if( sqlite3_column_int(pStmt,k) ){ - putValue(out, sqlite3_column_value(pStmt,k+2)); + putValue(out, pStmt, k+2); k += 3; }else{ putc(0, out); @@ -1677,10 +1677,10 @@ case SQLITE_INSERT: { for(k=1, i=0; i<nCol; i++){ if( aiFlg[i] ){ - putValue(out, sqlite3_column_value(pStmt,k)); + putValue(out, pStmt, k); k++; }else{ - putValue(out, sqlite3_column_value(pStmt,k+2)); + putValue(out, pStmt, k+2); k += 3; } } @@ -1689,10 +1689,10 @@ case SQLITE_DELETE: { for(k=1, i=0; i<nCol; i++){ if( aiFlg[i] ){ - putValue(out, sqlite3_column_value(pStmt,k)); + putValue(out, pStmt, k); k++; }else{ - putValue(out, sqlite3_column_value(pStmt,k+1)); + putValue(out, pStmt, k+1); k += 3; } }
diff --git a/third_party/sqlite/src/tool/warnings.sh b/third_party/sqlite/src/tool/warnings.sh index 69bb556..f8778fb7 100644 --- a/third_party/sqlite/src/tool/warnings.sh +++ b/third_party/sqlite/src/tool/warnings.sh
@@ -16,10 +16,10 @@ rm -f sqlite3.c make sqlite3.c -echo '********** No optimizations. Includes FTS4/5, RTREE, JSON1 ***' +echo '********** No optimizations. Includes FTS4/5, GEOPOLY, JSON1 ***' echo '********** ' Options: $WARNING_OPTS gcc -c $WARNING_OPTS -std=c89 \ - -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \ + -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_GEOPOLY \ -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \ sqlite3.c if test x`uname` = 'xLinux'; then @@ -52,9 +52,9 @@ gcc -c $WARNING_OPTS -std=c89 \ -ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \ sqlite3.c -echo '********** Optimized -O3. Includes FTS4/5, RTREE, JSON1 ******' +echo '********** Optimized -O3. Includes FTS4/5, GEOPOLY, JSON1 ******' echo '********** ' Options: $WARNING_OPTS gcc -O3 -c $WARNING_OPTS -std=c89 \ - -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \ + -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_GEOPOLY \ -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \ sqlite3.c
diff --git a/third_party/zlib/deflate.c b/third_party/zlib/deflate.c index 471fb19..98da939c 100644 --- a/third_party/zlib/deflate.c +++ b/third_party/zlib/deflate.c
@@ -2274,7 +2274,7 @@ val &= 0xFFFFFF; /* Windows clang should use inline asm */ -#if defined(_MSC_VER) && !defined(__clang__) +#if defined(_MSC_VER) && !defined(__clang__) && (defined(_M_IX86) || defined(_M_X64)) h = _mm_crc32_u32(h, val); #elif defined(__i386__) || defined(__amd64__) __asm__ __volatile__ (
diff --git a/tools/android/loading/chrome_setup.py b/tools/android/customtabs_benchmark/scripts/chrome_setup.py similarity index 100% rename from tools/android/loading/chrome_setup.py rename to tools/android/customtabs_benchmark/scripts/chrome_setup.py
diff --git a/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py b/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py index a907ce77..b5a3afe 100755 --- a/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py +++ b/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py
@@ -29,7 +29,6 @@ sys.path.append(os.path.join(_SRC_PATH, 'build', 'android')) import devil_chromium -sys.path.append(os.path.join(_SRC_PATH, 'tools', 'android', 'loading')) import chrome_setup
diff --git a/tools/android/errorprone_plugin/BUILD.gn b/tools/android/errorprone_plugin/BUILD.gn index d28a2cf..e61b0c4 100644 --- a/tools/android/errorprone_plugin/BUILD.gn +++ b/tools/android/errorprone_plugin/BUILD.gn
@@ -8,6 +8,7 @@ java_files = [ # Turned off because of existing code which fails the check # "src/org/chromium/tools/errorprone/plugin/NoContextGetApplicationContext.java", + "src/org/chromium/tools/errorprone/plugin/AndroidNullableCheck.java", "src/org/chromium/tools/errorprone/plugin/NoSynchronizedMethodCheck.java", "src/org/chromium/tools/errorprone/plugin/NoRedundantFieldInitCheck.java", "src/org/chromium/tools/errorprone/plugin/NoAndroidAsyncTaskCheck.java",
diff --git a/tools/android/errorprone_plugin/src/org/chromium/tools/errorprone/plugin/AndroidNullableCheck.java b/tools/android/errorprone_plugin/src/org/chromium/tools/errorprone/plugin/AndroidNullableCheck.java new file mode 100644 index 0000000..a88c5e38 --- /dev/null +++ b/tools/android/errorprone_plugin/src/org/chromium/tools/errorprone/plugin/AndroidNullableCheck.java
@@ -0,0 +1,38 @@ +// 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. + +package org.chromium.tools.errorprone.plugin; + +import com.google.auto.service.AutoService; +import com.google.errorprone.BugPattern; +import com.google.errorprone.VisitorState; +import com.google.errorprone.bugpatterns.BugChecker; +import com.google.errorprone.matchers.Description; +import com.google.errorprone.matchers.Matcher; +import com.google.errorprone.matchers.Matchers; +import com.sun.source.tree.AnnotationTree; + +/** + * Assert android.support.annotation.Nullable is used instead of javax.annotation.Nullable. + */ +@AutoService(BugChecker.class) +@BugPattern(name = "AndroidNullableCheck", category = BugPattern.Category.ANDROID, + summary = "Use android.support.annotation.Nullable instead of javax.annotation.Nullable.", + severity = BugPattern.SeverityLevel.ERROR, linkType = BugPattern.LinkType.CUSTOM, + link = "http://crbug.com/771683") +public class AndroidNullableCheck extends BugChecker implements BugChecker.AnnotationTreeMatcher { + static final Matcher<AnnotationTree> IS_JAVAX_NULLABLE = + Matchers.anyOf(Matchers.isType("javax.annotation.Nullable")); + + /** + * Match if nullable annotation is of type javax.annotation.Nullable. + */ + @Override + public Description matchAnnotation(AnnotationTree annotationTree, VisitorState visitorState) { + if (IS_JAVAX_NULLABLE.matches(annotationTree, visitorState)) { + return describeMatch(annotationTree); + } + return Description.NO_MATCH; + } +}
diff --git a/tools/android/loading/OWNERS b/tools/android/loading/OWNERS deleted file mode 100644 index 82a4803..0000000 --- a/tools/android/loading/OWNERS +++ /dev/null
@@ -1,4 +0,0 @@ -droger@chromium.org -lizeb@chromium.org -mattcary@chromium.org -pasko@chromium.org
diff --git a/tools/android/loading/PRESUBMIT.py b/tools/android/loading/PRESUBMIT.py deleted file mode 100644 index cd740ef..0000000 --- a/tools/android/loading/PRESUBMIT.py +++ /dev/null
@@ -1,34 +0,0 @@ -# Copyright 2016 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. - -"""Top-level presubmit script for loading. - -See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts -for more details on the presubmit API built into depot_tools. -""" - - -def CommonChecks(input_api, output_api): - output = [] - blacklist = [r'cloud/frontend/lib/*'] - output.extend(input_api.canned_checks.RunPylint( - input_api, output_api, black_list=blacklist)) - output.extend(input_api.canned_checks.RunUnitTests( - input_api, - output_api, - [input_api.os_path.join(input_api.PresubmitLocalPath(), 'run_tests')])) - - if input_api.is_committing: - output.extend(input_api.canned_checks.PanProjectChecks(input_api, - output_api, - owners_check=False)) - return output - - -def CheckChangeOnUpload(input_api, output_api): - return CommonChecks(input_api, output_api) - - -def CheckChangeOnCommit(input_api, output_api): - return CommonChecks(input_api, output_api)
diff --git a/tools/android/loading/activity_lens.py b/tools/android/loading/activity_lens.py deleted file mode 100644 index 3e3a98ef..0000000 --- a/tools/android/loading/activity_lens.py +++ /dev/null
@@ -1,303 +0,0 @@ -# Copyright 2016 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. - -"""Gives a picture of the CPU activity between timestamps. - -When executed as a script, takes a loading trace, and prints the activity -breakdown for the request dependencies. -""" - -import collections -import logging -import operator - -import request_track - - -class ActivityLens(object): - """Reconstructs the activity of the main renderer thread between requests.""" - _SCRIPT_EVENT_NAMES = ('EvaluateScript', 'FunctionCall') - _PARSING_EVENT_NAMES = ('ParseHTML', 'ParseAuthorStyleSheet') - - def __init__(self, trace): - """Initializes an instance of ActivityLens. - - Args: - trace: (LoadingTrace) loading trace. - """ - self._trace = trace - events = trace.tracing_track.GetEvents() - self._renderer_main_pid_tid = self._GetRendererMainThreadId(events) - self._tracing = self._trace.tracing_track.Filter( - *self._renderer_main_pid_tid) - - @classmethod - def _GetRendererMainThreadId(cls, events): - """Returns the most active main renderer thread. - - Several renderers may be running concurrently, but we assume that only one - of them is busy during the time covered by the loading trace.. It can be - selected by looking at the number of trace events generated. - - Args: - events: [tracing.Event] List of trace events. - - Returns: - (PID (int), TID (int)) of the busiest renderer main thread. - """ - events_count_per_pid_tid = collections.defaultdict(int) - main_renderer_thread_ids = set() - for event in events: - tracing_event = event.tracing_event - pid = event.tracing_event['pid'] - tid = event.tracing_event['tid'] - events_count_per_pid_tid[(pid, tid)] += 1 - if (tracing_event['cat'] == '__metadata' - and tracing_event['name'] == 'thread_name' - and event.args['name'] == 'CrRendererMain'): - main_renderer_thread_ids.add((pid, tid)) - events_count_per_pid_tid = { - pid_tid: count for (pid_tid, count) in events_count_per_pid_tid.items() - if pid_tid in main_renderer_thread_ids} - pid_tid_events_counts = sorted(events_count_per_pid_tid.items(), - key=operator.itemgetter(1), reverse=True) - if (len(pid_tid_events_counts) > 1 - and pid_tid_events_counts[0][1] < 2 * pid_tid_events_counts[1][1]): - logging.warning( - 'Several active renderers (%d and %d with %d and %d events).' - % (pid_tid_events_counts[0][0][0], pid_tid_events_counts[1][0][0], - pid_tid_events_counts[0][1], pid_tid_events_counts[1][1])) - return pid_tid_events_counts[0][0] - - def _OverlappingMainRendererThreadEvents(self, start_msec, end_msec): - return self._tracing.OverlappingEvents(start_msec, end_msec) - - @classmethod - def _ClampedDuration(cls, event, start_msec, end_msec): - return max(0, (min(end_msec, event.end_msec) - - max(start_msec, event.start_msec))) - - @classmethod - def _ThreadBusyness(cls, events, start_msec, end_msec): - """Amount of time a thread spent executing from the message loop.""" - busy_duration = 0 - message_loop_events = [ - e for e in events - if (e.tracing_event['cat'] == 'toplevel' - and e.tracing_event['name'] == 'MessageLoop::RunTask')] - for event in message_loop_events: - clamped_duration = cls._ClampedDuration(event, start_msec, end_msec) - busy_duration += clamped_duration - interval_msec = end_msec - start_msec - assert busy_duration <= interval_msec - return busy_duration - - @classmethod - def _ScriptsExecuting(cls, events, start_msec, end_msec): - """Returns the time during which scripts executed within an interval. - - Args: - events: ([tracing.Event]) list of tracing events. - start_msec: (float) start time in ms, inclusive. - end_msec: (float) end time in ms, inclusive. - - Returns: - A dict {URL (str) -> duration_msec (float)}. The dict may have a None key - for scripts that aren't associated with a URL. - """ - script_to_duration = collections.defaultdict(float) - script_events = [e for e in events - if ('devtools.timeline' in e.tracing_event['cat'] - and (e.tracing_event['name'] - in cls._SCRIPT_EVENT_NAMES))] - for event in script_events: - clamped_duration = cls._ClampedDuration(event, start_msec, end_msec) - script_url = event.args['data'].get('scriptName', None) - script_to_duration[script_url] += clamped_duration - return dict(script_to_duration) - - @classmethod - def _FullyIncludedEvents(cls, events, event): - """Return a list of events wholly included in the |event| span.""" - (start, end) = (event.start_msec, event.end_msec) - result = [] - for event in events: - if start <= event.start_msec < end and start <= event.end_msec < end: - result.append(event) - return result - - @classmethod - def _Parsing(cls, events, start_msec, end_msec): - """Returns the HTML/CSS parsing time within an interval. - - Args: - events: ([tracing.Event]) list of events. - start_msec: (float) start time in ms, inclusive. - end_msec: (float) end time in ms, inclusive. - - Returns: - A dict {URL (str) -> duration_msec (float)}. The dict may have a None key - for tasks that aren't associated with a URL. - """ - url_to_duration = collections.defaultdict(float) - parsing_events = [e for e in events - if ('devtools.timeline' in e.tracing_event['cat'] - and (e.tracing_event['name'] - in cls._PARSING_EVENT_NAMES))] - for event in parsing_events: - # Parsing events can contain nested script execution events, avoid - # double-counting by discounting these. - nested_events = cls._FullyIncludedEvents(events, event) - events_tree = _EventsTree(event, nested_events) - js_events = events_tree.DominatingEventsWithNames(cls._SCRIPT_EVENT_NAMES) - duration_to_subtract = sum( - cls._ClampedDuration(e, start_msec, end_msec) for e in js_events) - tracing_event = event.tracing_event - clamped_duration = cls._ClampedDuration(event, start_msec, end_msec) - if tracing_event['name'] == 'ParseAuthorStyleSheet': - url = tracing_event['args']['data']['styleSheetUrl'] - else: - url = tracing_event['args']['beginData']['url'] - parsing_duration = clamped_duration - duration_to_subtract - assert parsing_duration >= 0 - url_to_duration[url] += parsing_duration - return dict(url_to_duration) - - def GenerateEdgeActivity(self, dep): - """For a dependency between two requests, returns the renderer activity - breakdown. - - Args: - dep: (Request, Request, str) As returned from - RequestDependencyLens.GetRequestDependencies(). - - Returns: - {'edge_cost': (float) ms, 'busy': (float) ms, - 'parsing': {'url' -> time_ms}, 'script' -> {'url' -> time_ms}} - """ - (first, second, reason) = dep - (start_msec, end_msec) = request_track.IntervalBetween( - first, second, reason) - assert end_msec - start_msec >= 0. - events = self._OverlappingMainRendererThreadEvents(start_msec, end_msec) - result = {'edge_cost': end_msec - start_msec, - 'busy': self._ThreadBusyness(events, start_msec, end_msec)} - result.update(self.ComputeActivity(start_msec, end_msec)) - return result - - def ComputeActivity(self, start_msec, end_msec): - """Returns a breakdown of the main renderer thread activity between two - timestamps. - - Args: - start_msec: (float) - end_msec: (float) - - Returns: - {'parsing': {'url' -> time_ms}, 'script': {'url' -> time_ms}}. - """ - assert end_msec - start_msec >= 0. - events = self._OverlappingMainRendererThreadEvents(start_msec, end_msec) - result = {'parsing': self._Parsing(events, start_msec, end_msec), - 'script': self._ScriptsExecuting(events, start_msec, end_msec)} - return result - - def BreakdownEdgeActivityByInitiator(self, dep): - """For a dependency between two requests, categorizes the renderer activity. - - Args: - dep: (Request, Request, str) As returned from - RequestDependencyLens.GetRequestDependencies(). - - Returns: - {'script': float, 'parsing': float, 'other_url': float, - 'unknown_url': float, 'unrelated_work': float} - where the values are durations in ms: - - idle: The renderer main thread was idle. - - script: The initiating file was executing. - - parsing: The initiating file was being parsed. - - other_url: Other scripts and/or parsing activities. - - unknown_url: Activity which is not associated with a URL. - - unrelated_work: Activity unrelated to scripts or parsing. - """ - activity = self.GenerateEdgeActivity(dep) - breakdown = {'unrelated_work': activity['busy'], - 'idle': activity['edge_cost'] - activity['busy'], - 'script': 0, 'parsing': 0, - 'other_url': 0, 'unknown_url': 0} - for kind in ('script', 'parsing'): - for (script_name, duration_ms) in activity[kind].items(): - if not script_name: - breakdown['unknown_url'] += duration_ms - elif script_name == dep[0].url: - breakdown[kind] += duration_ms - else: - breakdown['other_url'] += duration_ms - breakdown['unrelated_work'] -= sum( - breakdown[x] for x in ('script', 'parsing', 'other_url', 'unknown_url')) - return breakdown - - def MainRendererThreadBusyness(self, start_msec, end_msec): - """Returns the amount of time the main renderer thread was busy. - - Args: - start_msec: (float) Start of the interval. - end_msec: (float) End of the interval. - """ - events = self._OverlappingMainRendererThreadEvents(start_msec, end_msec) - return self._ThreadBusyness(events, start_msec, end_msec) - - -class _EventsTree(object): - """Builds the hierarchy of events from a list of fully nested events.""" - def __init__(self, root_event, events): - """Creates the tree. - - Args: - root_event: (Event) Event held by the tree root. - events: ([Event]) List of events that are fully included in |root_event|. - """ - self.event = root_event - self.start_msec = root_event.start_msec - self.end_msec = root_event.end_msec - self.children = [] - events.sort(key=operator.attrgetter('start_msec')) - if not events: - return - current_child = (events[0], []) - for event in events[1:]: - if event.end_msec < current_child[0].end_msec: - current_child[1].append(event) - else: - self.children.append(_EventsTree(current_child[0], current_child[1])) - current_child = (event, []) - self.children.append(_EventsTree(current_child[0], current_child[1])) - - def DominatingEventsWithNames(self, names): - """Returns a list of the top-most events in the tree with a matching name. - """ - if self.event.name in names: - return [self.event] - else: - result = [] - for child in self.children: - result += child.DominatingEventsWithNames(names) - return result - - -if __name__ == '__main__': - import sys - import json - import loading_trace - import request_dependencies_lens - - filename = sys.argv[1] - json_dict = json.load(open(filename)) - loading_trace = loading_trace.LoadingTrace.FromJsonDict(json_dict) - activity_lens = ActivityLens(loading_trace) - dependencies_lens = request_dependencies_lens.RequestDependencyLens( - loading_trace) - deps = dependencies_lens.GetRequestDependencies() - for requests_dep in deps: - print activity_lens.GenerateEdgeActivity(requests_dep)
diff --git a/tools/android/loading/activity_lens_unittest.py b/tools/android/loading/activity_lens_unittest.py deleted file mode 100644 index cfa4689..0000000 --- a/tools/android/loading/activity_lens_unittest.py +++ /dev/null
@@ -1,348 +0,0 @@ -# Copyright 2016 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. - -import collections -import copy -import unittest - -from activity_lens import (ActivityLens, _EventsTree) -import clovis_constants -import test_utils -import tracing_track - - -class ActivityLensTestCase(unittest.TestCase): - @classmethod - def _EventsFromRawEvents(cls, raw_events): - track = tracing_track.TracingTrack(None, - clovis_constants.DEFAULT_CATEGORIES) - track.Handle( - 'Tracing.dataCollected', {'params': {'value': raw_events}}) - return track.GetEvents() - - def setUp(self): - self.track = tracing_track.TracingTrack(None, - clovis_constants.DEFAULT_CATEGORIES) - - def testGetRendererMainThread(self): - first_renderer_tid = 12345 - second_renderer_tid = 123456 - raw_events = [ - {u'args': {u'name': u'CrBrowserMain'}, - u'cat': u'__metadata', - u'name': u'thread_name', - u'ph': u'M', - u'pid': 1, - u'tid': 123, - u'ts': 0}, - {u'args': {u'name': u'CrRendererMain'}, - u'cat': u'__metadata', - u'name': u'thread_name', - u'ph': u'M', - u'pid': 1, - u'tid': first_renderer_tid, - u'ts': 0}, - {u'args': {u'name': u'CrRendererMain'}, - u'cat': u'__metadata', - u'name': u'thread_name', - u'ph': u'M', - u'pid': 1, - u'tid': second_renderer_tid, - u'ts': 0}] - raw_events += [ - {u'args': {u'data': {}}, - u'cat': u'devtools.timeline,v8', - u'name': u'FunctionCall', - u'ph': u'X', - u'pid': 1, - u'tdur': 0, - u'tid': first_renderer_tid, - u'ts': 251427174674, - u'tts': 5107725}] * 100 - raw_events += [ - {u'args': {u'data': {}}, - u'cat': u'devtools.timeline,v8', - u'name': u'FunctionCall', - u'ph': u'X', - u'pid': 1, - u'tdur': 0, - u'tid': second_renderer_tid, - u'ts': 251427174674, - u'tts': 5107725}] * 150 - # There are more events from first_renderer_tid when (incorrectly) ignoring - # the PID. - raw_events += [ - {u'args': {u'data': {}}, - u'cat': u'devtools.timeline,v8', - u'name': u'FunctionCall', - u'ph': u'X', - u'pid': 12, - u'tdur': 0, - u'tid': first_renderer_tid, - u'ts': 251427174674, - u'tts': 5107725}] * 100 - events = self._EventsFromRawEvents(raw_events) - self.assertEquals((1, second_renderer_tid), - ActivityLens._GetRendererMainThreadId(events)) - - def testThreadBusyness(self): - raw_events = [ - {u'args': {}, - u'cat': u'toplevel', - u'dur': 200 * 1000, - u'name': u'MessageLoop::RunTask', - u'ph': u'X', - u'pid': 123, - u'tid': 123, - u'ts': 0, - u'tts': 56485}, - {u'args': {}, - u'cat': u'toplevel', - u'dur': 8 * 200, - u'name': u'MessageLoop::NestedSomething', - u'ph': u'X', - u'pid': 123, - u'tid': 123, - u'ts': 0, - u'tts': 0}] - events = self._EventsFromRawEvents(raw_events) - self.assertEquals(200, ActivityLens._ThreadBusyness(events, 0, 1000)) - # Clamping duration. - self.assertEquals(100, ActivityLens._ThreadBusyness(events, 0, 100)) - self.assertEquals(50, ActivityLens._ThreadBusyness(events, 25, 75)) - - def testScriptExecuting(self): - url = u'http://example.com/script.js' - raw_events = [ - {u'args': {u'data': {u'scriptName': url}}, - u'cat': u'devtools.timeline,v8', - u'dur': 250 * 1000, - u'name': u'FunctionCall', - u'ph': u'X', - u'pid': 123, - u'tdur': 247, - u'tid': 123, - u'ts': 0, - u'tts': 0}, - {u'args': {u'data': {}}, - u'cat': u'devtools.timeline,v8', - u'dur': 350 * 1000, - u'name': u'EvaluateScript', - u'ph': u'X', - u'pid': 123, - u'tdur': 247, - u'tid': 123, - u'ts': 0, - u'tts': 0}] - events = self._EventsFromRawEvents(raw_events) - self.assertEquals(2, len(ActivityLens._ScriptsExecuting(events, 0, 1000))) - self.assertTrue(None in ActivityLens._ScriptsExecuting(events, 0, 1000)) - self.assertEquals( - 350, ActivityLens._ScriptsExecuting(events, 0, 1000)[None]) - self.assertTrue(url in ActivityLens._ScriptsExecuting(events, 0, 1000)) - self.assertEquals(250, ActivityLens._ScriptsExecuting(events, 0, 1000)[url]) - # Aggreagates events. - raw_events.append({u'args': {u'data': {}}, - u'cat': u'devtools.timeline,v8', - u'dur': 50 * 1000, - u'name': u'EvaluateScript', - u'ph': u'X', - u'pid': 123, - u'tdur': 247, - u'tid': 123, - u'ts': 0, - u'tts': 0}) - events = self._EventsFromRawEvents(raw_events) - self.assertEquals( - 350 + 50, ActivityLens._ScriptsExecuting(events, 0, 1000)[None]) - - def testParsing(self): - css_url = u'http://example.com/style.css' - html_url = u'http://example.com/yeah.htnl' - raw_events = [ - {u'args': {u'data': {u'styleSheetUrl': css_url}}, - u'cat': u'blink,devtools.timeline', - u'dur': 400 * 1000, - u'name': u'ParseAuthorStyleSheet', - u'ph': u'X', - u'pid': 32723, - u'tdur': 49721, - u'tid': 32738, - u'ts': 0, - u'tts': 216148}, - {u'args': {u'beginData': {u'url': html_url}}, - u'cat': u'devtools.timeline', - u'dur': 42 * 1000, - u'name': u'ParseHTML', - u'ph': u'X', - u'pid': 32723, - u'tdur': 49721, - u'tid': 32738, - u'ts': 0, - u'tts': 5032310},] - events = self._EventsFromRawEvents(raw_events) - self.assertEquals(2, len(ActivityLens._Parsing(events, 0, 1000))) - self.assertTrue(css_url in ActivityLens._Parsing(events, 0, 1000)) - self.assertEquals(400, ActivityLens._Parsing(events, 0, 1000)[css_url]) - self.assertTrue(html_url in ActivityLens._Parsing(events, 0, 1000)) - self.assertEquals(42, ActivityLens._Parsing(events, 0, 1000)[html_url]) - - def testBreakdownEdgeActivityByInitiator(self): - requests = [test_utils.MakeRequest(0, 1, 10, 20, 30), - test_utils.MakeRequest(0, 1, 50, 60, 70)] - raw_events = [ - {u'args': {u'beginData': {u'url': requests[0].url}}, - u'cat': u'devtools.timeline', - u'dur': 12 * 1000, - u'name': u'ParseHTML', - u'ph': u'X', - u'pid': 1, - u'tid': 1, - u'ts': 25 * 1000}, - {u'args': {u'data': {'scriptName': requests[0].url}}, - u'cat': u'devtools.timeline,v8', - u'dur': 0, - u'name': u'EvaluateScript', - u'ph': u'X', - u'pid': 1, - u'tid': 1, - u'ts': 0}, - {u'cat': u'toplevel', - u'dur': 100 * 1000, - u'name': u'MessageLoop::RunTask', - u'ph': u'X', - u'pid': 1, - u'tid': 1, - u'ts': 0}, - {u'args': {u'name': u'CrRendererMain'}, - u'cat': u'__metadata', - u'name': u'thread_name', - u'ph': u'M', - u'pid': 1, - u'tid': 1, - u'ts': 0}] - activity = self._ActivityLens(requests, raw_events) - dep = (requests[0], requests[1], 'parser') - self.assertEquals( - {'unrelated_work': 18, 'idle': 0, 'script': 0, 'parsing': 12, - 'other_url': 0, 'unknown_url': 0}, - activity.BreakdownEdgeActivityByInitiator(dep)) - dep = (requests[0], requests[1], 'other') - # Truncating the event from the parent request end. - self.assertEquals( - {'unrelated_work': 13, 'idle': 0, 'script': 0, 'parsing': 7, - 'other_url': 0, 'unknown_url': 0}, - activity.BreakdownEdgeActivityByInitiator(dep)) - # Unknown URL - raw_events[0]['args']['beginData']['url'] = None - activity = self._ActivityLens(requests, raw_events) - dep = (requests[0], requests[1], 'parser') - self.assertEquals( - {'unrelated_work': 18, 'idle': 0, 'script': 0, 'parsing': 0, - 'other_url': 0, 'unknown_url': 12}, - activity.BreakdownEdgeActivityByInitiator(dep)) - # Script - raw_events[1]['ts'] = 40 * 1000 - raw_events[1]['dur'] = 6 * 1000 - activity = self._ActivityLens(requests, raw_events) - dep = (requests[0], requests[1], 'script') - self.assertEquals( - {'unrelated_work': 7, 'idle': 0, 'script': 6, 'parsing': 0, - 'other_url': 0, 'unknown_url': 7}, - activity.BreakdownEdgeActivityByInitiator(dep)) - # Other URL - raw_events[1]['args']['data']['scriptName'] = 'http://other.com/url' - activity = self._ActivityLens(requests, raw_events) - self.assertEquals( - {'unrelated_work': 7, 'idle': 0, 'script': 0., 'parsing': 0., - 'other_url': 6., 'unknown_url': 7.}, - activity.BreakdownEdgeActivityByInitiator(dep)) - - def testMainRendererThreadBusyness(self): - raw_events = [ - {u'args': {u'name': u'CrRendererMain'}, - u'cat': u'__metadata', - u'name': u'thread_name', - u'ph': u'M', - u'pid': 1, - u'tid': 12, - u'ts': 0}, - {u'args': {}, - u'cat': u'toplevel', - u'dur': 200 * 1000, - u'name': u'MessageLoop::RunTask', - u'ph': u'X', - u'pid': 1, - u'tid': 12, - u'ts': 0, - u'tts': 56485}, - {u'args': {}, - u'cat': u'toplevel', - u'dur': 8 * 200, - u'name': u'MessageLoop::NestedSomething', - u'ph': u'X', - u'pid': 1, - u'tid': 12, - u'ts': 0, - u'tts': 0}, - {u'args': {}, - u'cat': u'toplevel', - u'dur': 500 * 1000, - u'name': u'MessageLoop::RunTask', - u'ph': u'X', - u'pid': 12, - u'tid': 12, - u'ts': 0, - u'tts': 56485}] - lens = self._ActivityLens([], raw_events) - # Ignore events from another PID. - self.assertEquals(200, lens.MainRendererThreadBusyness(0, 1000)) - # Clamping duration. - self.assertEquals(100, lens.MainRendererThreadBusyness(0, 100)) - self.assertEquals(50, lens.MainRendererThreadBusyness(25, 75)) - # Other PID. - raw_events[0]['pid'] = 12 - lens = self._ActivityLens([], raw_events) - self.assertEquals(500, lens.MainRendererThreadBusyness(0, 1000)) - - def _ActivityLens(self, requests, raw_events): - loading_trace = test_utils.LoadingTraceFromEvents( - requests, None, raw_events) - return ActivityLens(loading_trace) - - -class EventsTreeTestCase(unittest.TestCase): - FakeEvent = collections.namedtuple( - 'FakeEvent', ('name', 'start_msec', 'end_msec')) - _ROOT_EVENT = FakeEvent('-1', 0, 20) - _EVENTS = [ - FakeEvent('0', 2, 4), FakeEvent('1', 1, 5), - FakeEvent('2', 6, 9), - FakeEvent('3', 13, 14), FakeEvent('4', 14, 17), FakeEvent('5', 12, 18)] - - def setUp(self): - self.tree = _EventsTree(self._ROOT_EVENT, copy.deepcopy(self._EVENTS)) - - def testEventsTreeConstruction(self): - self.assertEquals(self._ROOT_EVENT, self.tree.event) - self.assertEquals(3, len(self.tree.children)) - self.assertEquals(self._EVENTS[1], self.tree.children[0].event) - self.assertEquals(self._EVENTS[0], self.tree.children[0].children[0].event) - self.assertEquals(self._EVENTS[2], self.tree.children[1].event) - self.assertEquals([], self.tree.children[1].children) - self.assertEquals(self._EVENTS[5], self.tree.children[2].event) - self.assertEquals(2, len(self.tree.children[2].children)) - - def testDominatingEventsWithNames(self): - self.assertListEqual( - [self._ROOT_EVENT], self.tree.DominatingEventsWithNames(('-1'))) - self.assertListEqual( - [self._ROOT_EVENT], self.tree.DominatingEventsWithNames(('-1', '0'))) - self.assertListEqual( - [self._EVENTS[1], self._EVENTS[5]], - self.tree.DominatingEventsWithNames(('1', '5'))) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/analyze.py b/tools/android/loading/analyze.py deleted file mode 100755 index 91ed008c..0000000 --- a/tools/android/loading/analyze.py +++ /dev/null
@@ -1,339 +0,0 @@ -#! /usr/bin/python -# 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. - -import argparse -import cgi -import json -import logging -import os -import subprocess -import sys -import tempfile -import time - -_SRC_DIR = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..', '..', '..')) - -sys.path.append(os.path.join(_SRC_DIR, 'third_party', 'catapult', 'devil')) -from devil.android import device_utils -from devil.android.sdk import intent - -sys.path.append(os.path.join(_SRC_DIR, 'build', 'android')) -import devil_chromium -from pylib import constants - -import activity_lens -import clovis_constants -import content_classification_lens -import controller -import device_setup -import frame_load_lens -import loading_graph_view -import loading_graph_view_visualization -import loading_trace -import options -import request_dependencies_lens -import request_track -import xvfb_helper - -# TODO(mattcary): logging.info isn't that useful, as the whole (tools) world -# uses logging info; we need to introduce logging modules to get finer-grained -# output. For now we just do logging.warning. - - -OPTIONS = options.OPTIONS - - -def _LoadPage(device, url): - """Load a page on chrome on our device. - - Args: - device: an AdbWrapper for the device on which to load the page. - url: url as a string to load. - """ - load_intent = intent.Intent( - package=OPTIONS.ChromePackage().package, - activity=OPTIONS.ChromePackage().activity, - data=url) - logging.warning('Loading ' + url) - device.StartActivity(load_intent, blocking=True) - - -def _GetPrefetchHtml(graph_view, name=None): - """Generate prefetch page for the resources in resource graph. - - Args: - graph_view: (LoadingGraphView) - name: optional string used in the generated page. - - Returns: - HTML as a string containing all the link rel=prefetch directives necessary - for prefetching the given ResourceGraph. - """ - if name: - title = 'Prefetch for ' + cgi.escape(name) - else: - title = 'Generated prefetch page' - output = [] - output.append("""<!DOCTYPE html> -<html> -<head> -<title>%s</title> -""" % title) - for node in graph_view.deps_graph.graph.Nodes(): - output.append('<link rel="prefetch" href="%s">\n' % node.request.url) - output.append("""</head> -<body>%s</body> -</html> - """ % title) - return '\n'.join(output) - - -def _LogRequests(url, clear_cache_override=None): - """Logs requests for a web page. - - Args: - url: url to log as string. - clear_cache_override: if not None, set clear_cache different from OPTIONS. - - Returns: - JSON dict of logged information (ie, a dict that describes JSON). - """ - xvfb_process = None - if OPTIONS.local: - chrome_ctl = controller.LocalChromeController() - if OPTIONS.headless: - xvfb_process = xvfb_helper.LaunchXvfb() - chrome_ctl.SetChromeEnvOverride(xvfb_helper.GetChromeEnvironment()) - else: - chrome_ctl = controller.RemoteChromeController( - device_setup.GetFirstDevice()) - - clear_cache = (clear_cache_override if clear_cache_override is not None - else OPTIONS.clear_cache) - if OPTIONS.emulate_device: - chrome_ctl.SetDeviceEmulation(OPTIONS.emulate_device) - if OPTIONS.emulate_network: - chrome_ctl.SetNetworkEmulation(OPTIONS.emulate_network) - try: - with chrome_ctl.Open() as connection: - if clear_cache: - connection.ClearCache() - trace = loading_trace.LoadingTrace.RecordUrlNavigation( - url, connection, chrome_ctl.ChromeMetadata(), - categories=clovis_constants.DEFAULT_CATEGORIES) - except controller.ChromeControllerError as e: - e.Dump(sys.stderr) - raise - - if xvfb_process: - xvfb_process.terminate() - - return trace.ToJsonDict() - - -def _FullFetch(url, json_output, prefetch): - """Do a full fetch with optional prefetching.""" - if not url.startswith('http') and not url.startswith('file'): - url = 'http://' + url - logging.warning('Cold fetch') - cold_data = _LogRequests(url) - assert cold_data, 'Cold fetch failed to produce data. Check your phone.' - if prefetch: - assert not OPTIONS.local - logging.warning('Generating prefetch') - prefetch_html = _GetPrefetchHtml(_ProcessJsonTrace(cold_data), name=url) - tmp = tempfile.NamedTemporaryFile() - tmp.write(prefetch_html) - tmp.flush() - # We hope that the tmpfile name is unique enough for the device. - target = os.path.join('/sdcard/Download', os.path.basename(tmp.name)) - device = device_setup.GetFirstDevice() - device.adb.Push(tmp.name, target) - logging.warning('Pushed prefetch %s to device at %s' % (tmp.name, target)) - _LoadPage(device, 'file://' + target) - time.sleep(OPTIONS.prefetch_delay_seconds) - logging.warning('Warm fetch') - warm_data = _LogRequests(url, clear_cache_override=False) - with open(json_output, 'w') as f: - json.dump(warm_data, f) - logging.warning('Wrote ' + json_output) - with open(json_output + '.cold', 'w') as f: - json.dump(cold_data, f) - logging.warning('Wrote ' + json_output + '.cold') - else: - with open(json_output, 'w') as f: - json.dump(cold_data, f) - logging.warning('Wrote ' + json_output) - - -def _ProcessTraceFile(filename): - with open(filename) as f: - return _ProcessJsonTrace(json.load(f)) - - -def _ProcessJsonTrace(json_dict): - trace = loading_trace.LoadingTrace.FromJsonDict(json_dict) - content_lens = ( - content_classification_lens.ContentClassificationLens.WithRulesFiles( - trace, OPTIONS.ad_rules, OPTIONS.tracking_rules)) - frame_lens = frame_load_lens.FrameLoadLens(trace) - activity = activity_lens.ActivityLens(trace) - deps_lens = request_dependencies_lens.RequestDependencyLens(trace) - graph_view = loading_graph_view.LoadingGraphView( - trace, deps_lens, content_lens, frame_lens, activity) - if OPTIONS.noads: - graph_view.RemoveAds() - return graph_view - - -def InvalidCommand(cmd): - sys.exit('Invalid command "%s"\nChoices are: %s' % - (cmd, ' '.join(COMMAND_MAP.keys()))) - - -def DoPng(arg_str): - OPTIONS.ParseArgs(arg_str, description='Generates a PNG from a trace', - extra=['request_json', ('--png_output', ''), - ('--eog', False)]) - graph_view = _ProcessTraceFile(OPTIONS.request_json) - visualization = ( - loading_graph_view_visualization.LoadingGraphViewVisualization( - graph_view)) - tmp = tempfile.NamedTemporaryFile() - visualization.OutputDot(tmp) - tmp.flush() - png_output = OPTIONS.png_output - if not png_output: - if OPTIONS.request_json.endswith('.json'): - png_output = OPTIONS.request_json[ - :OPTIONS.request_json.rfind('.json')] + '.png' - else: - png_output = OPTIONS.request_json + '.png' - subprocess.check_call(['dot', '-Tpng', tmp.name, '-o', png_output]) - logging.warning('Wrote ' + png_output) - if OPTIONS.eog: - subprocess.Popen(['eog', png_output]) - tmp.close() - - -def DoPrefetchSetup(arg_str): - OPTIONS.ParseArgs(arg_str, description='Sets up prefetch', - extra=['request_json', 'target_html', ('--upload', False)]) - graph_view = _ProcessTraceFile(OPTIONS.request_json) - with open(OPTIONS.target_html, 'w') as html: - html.write(_GetPrefetchHtml( - graph_view, name=os.path.basename(OPTIONS.request_json))) - if OPTIONS.upload: - device = device_setup.GetFirstDevice() - destination = os.path.join('/sdcard/Download', - os.path.basename(OPTIONS.target_html)) - device.adb.Push(OPTIONS.target_html, destination) - - logging.warning( - 'Pushed %s to device at %s' % (OPTIONS.target_html, destination)) - - -def DoLogRequests(arg_str): - OPTIONS.ParseArgs(arg_str, description='Logs requests of a load', - extra=['--url', '--output', ('--prefetch', False)]) - _FullFetch(url=OPTIONS.url, - json_output=OPTIONS.output, - prefetch=OPTIONS.prefetch) - - -def DoFetch(arg_str): - OPTIONS.ParseArgs(arg_str, - description=('Fetches SITE into DIR with ' - 'standard naming that can be processed by ' - './cost_to_csv.py. Both warm and cold ' - 'fetches are done. SITE can be a full url ' - 'but the filename may be strange so better ' - 'to just use a site (ie, domain).'), - extra=['--site', '--dir']) - if not os.path.exists(OPTIONS.dir): - os.makedirs(OPTIONS.dir) - _FullFetch(url=OPTIONS.site, - json_output=os.path.join(OPTIONS.dir, OPTIONS.site + '.json'), - prefetch=True) - - -def DoLongPole(arg_str): - OPTIONS.ParseArgs(arg_str, description='Calculates long pole', - extra='request_json') - graph_view = _ProcessTraceFile(OPTIONS.request_json) - path_list = [] - cost = graph_view.deps_graph.Cost(path_list=path_list) - print '%s (%s)' % (path_list[-1].request.url, cost) - - -def DoNodeCost(arg_str): - OPTIONS.ParseArgs(arg_str, - description='Calculates node cost', - extra='request_json') - graph_view = _ProcessTraceFile(OPTIONS.request_json) - print sum((n.cost for n in graph_view.deps_graph.graph.Nodes())) - - -def DoCost(arg_str): - OPTIONS.ParseArgs(arg_str, - description='Calculates total cost', - extra=['request_json', ('--path', False)]) - graph_view = _ProcessTraceFile(OPTIONS.request_json) - path_list = [] - print 'Graph cost: %s' % graph_view.deps_graph.Cost(path_list=path_list) - if OPTIONS.path: - for n in path_list: - print ' ' + request_track.ShortName(n.request.url) - - -COMMAND_MAP = { - 'png': DoPng, - 'prefetch_setup': DoPrefetchSetup, - 'log_requests': DoLogRequests, - 'longpole': DoLongPole, - 'nodecost': DoNodeCost, - 'cost': DoCost, - 'fetch': DoFetch, -} - -def main(): - logging.basicConfig(level=logging.WARNING) - OPTIONS.AddGlobalArgument( - 'clear_cache', True, 'clear browser cache before loading') - OPTIONS.AddGlobalArgument( - 'emulate_device', '', - 'Name of the device to emulate. Must be present ' - 'in --devices_file, or empty for no emulation.') - OPTIONS.AddGlobalArgument('emulate_network', '', - 'Type of network emulation. Empty for no emulation.') - OPTIONS.AddGlobalArgument( - 'local', False, - 'run against local desktop chrome rather than device ' - '(see also --local_binary and local_profile_dir)') - OPTIONS.AddGlobalArgument( - 'noads', False, 'ignore ad resources in modeling') - OPTIONS.AddGlobalArgument( - 'ad_rules', '', 'AdBlocker+ ad rules file.') - OPTIONS.AddGlobalArgument( - 'tracking_rules', '', 'AdBlocker+ tracking rules file.') - OPTIONS.AddGlobalArgument( - 'prefetch_delay_seconds', 5, - 'delay after requesting load of prefetch page ' - '(only when running full fetch)') - OPTIONS.AddGlobalArgument( - 'headless', False, 'Do not display Chrome UI (only works in local mode).') - - parser = argparse.ArgumentParser(description='Analyzes loading') - parser.add_argument('command', help=' '.join(COMMAND_MAP.keys())) - parser.add_argument('rest', nargs=argparse.REMAINDER) - args = parser.parse_args() - devil_chromium.Initialize() - COMMAND_MAP.get(args.command, - lambda _: InvalidCommand(args.command))(args.rest) - - -if __name__ == '__main__': - main()
diff --git a/tools/android/loading/chrome_cache.py b/tools/android/loading/chrome_cache.py deleted file mode 100644 index 24d3f75..0000000 --- a/tools/android/loading/chrome_cache.py +++ /dev/null
@@ -1,423 +0,0 @@ -# Copyright 2016 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. - -"""Takes care of manipulating the chrome's HTTP cache. -""" - -from datetime import datetime -import json -import os -import re -import shutil -import subprocess -import sys -import tempfile -import zipfile - -_SRC_DIR = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..', '..', '..')) - -sys.path.append(os.path.join(_SRC_DIR, 'build', 'android')) -from pylib import constants - -import device_setup -import options - - -OPTIONS = options.OPTIONS - - -# Cache back-end types supported by cachetool. -BACKEND_TYPES = {'simple', 'blockfile'} - -# Regex used to parse HTTP headers line by line. -HEADER_PARSING_REGEX = re.compile(r'^(?P<header>\S+):(?P<value>.*)$') - - -def _EnsureCleanCacheDirectory(directory_dest_path): - """Ensure that a cache directory is created and clean. - - Args: - directory_dest_path: Path of the cache directory to ensure cleanliness. - """ - if os.path.isdir(directory_dest_path): - shutil.rmtree(directory_dest_path) - elif not os.path.isdir(os.path.dirname(directory_dest_path)): - os.makedirs(os.path.dirname(directory_dest_path)) - assert not os.path.exists(directory_dest_path) - - -def _RemoteCacheDirectory(): - """Returns the path of the cache directory's on the remote device.""" - return '/data/data/{}/cache/Cache'.format( - constants.PACKAGE_INFO[OPTIONS.chrome_package_name].package) - - -def _AdbShell(adb, cmd): - adb.Shell(subprocess.list2cmdline(cmd)) - - -def PullBrowserCache(device): - """Pulls the browser cache from the device and saves it locally. - - Cache is saved with the same file structure as on the device. Timestamps are - important to preserve because indexing and eviction depends on them. - - Returns: - Temporary directory containing all the browser cache. - """ - _INDEX_DIRECTORY_NAME = 'index-dir' - _REAL_INDEX_FILE_NAME = 'the-real-index' - - remote_cache_directory = _RemoteCacheDirectory() - save_target = tempfile.mkdtemp(suffix='.cache') - - # Pull the cache recursively. - device.adb.Pull(remote_cache_directory, save_target) - - # Update the modification time stamp on the local cache copy. - def _UpdateTimestampFromAdbStat(filename, stat): - assert os.path.exists(filename) - os.utime(filename, (stat.st_time, stat.st_time)) - - for filename, stat in device.adb.Ls(remote_cache_directory): - if filename == '..': - continue - if filename == '.': - cache_directory_stat = stat - continue - original_file = os.path.join(remote_cache_directory, filename) - saved_file = os.path.join(save_target, filename) - _UpdateTimestampFromAdbStat(saved_file, stat) - if filename == _INDEX_DIRECTORY_NAME: - # The directory containing the index was pulled recursively, update the - # timestamps for known files. They are ignored by cache backend, but may - # be useful for debugging. - index_dir_stat = stat - saved_index_dir = os.path.join(save_target, _INDEX_DIRECTORY_NAME) - saved_index_file = os.path.join(saved_index_dir, _REAL_INDEX_FILE_NAME) - for sub_file, sub_stat in device.adb.Ls(original_file): - if sub_file == _REAL_INDEX_FILE_NAME: - _UpdateTimestampFromAdbStat(saved_index_file, sub_stat) - break - _UpdateTimestampFromAdbStat(saved_index_dir, index_dir_stat) - - # Store the cache directory modification time. It is important to update it - # after all files in it have been written. The timestamp is compared with - # the contents of the index file when freshness is determined. - _UpdateTimestampFromAdbStat(save_target, cache_directory_stat) - return save_target - - -def PushBrowserCache(device, local_cache_path): - """Pushes the browser cache saved locally to the device. - - Args: - device: Android device. - local_cache_path: The directory's path containing the cache locally. - """ - remote_cache_directory = _RemoteCacheDirectory() - - # Clear previous cache. - _AdbShell(device.adb, ['rm', '-rf', remote_cache_directory]) - _AdbShell(device.adb, ['mkdir', '-p', remote_cache_directory]) - - # Push cache content. - device.adb.Push(local_cache_path, remote_cache_directory) - - # Command queue to touch all files with correct timestamp. - command_queue = [] - - # Walk through the local cache to update mtime on the device. - def MirrorMtime(local_path): - cache_relative_path = os.path.relpath(local_path, start=local_cache_path) - remote_path = os.path.join(remote_cache_directory, cache_relative_path) - timestamp = os.stat(local_path).st_mtime - touch_stamp = datetime.fromtimestamp(timestamp).strftime('%Y%m%d.%H%M%S') - command_queue.append(['touch', '-t', touch_stamp, remote_path]) - - for local_directory_path, dirnames, filenames in os.walk( - local_cache_path, topdown=False): - for filename in filenames: - MirrorMtime(os.path.join(local_directory_path, filename)) - for dirname in dirnames: - MirrorMtime(os.path.join(local_directory_path, dirname)) - MirrorMtime(local_cache_path) - - device_setup.DeviceSubmitShellCommandQueue(device, command_queue) - - -def ZipDirectoryContent(root_directory_path, archive_dest_path): - """Zip a directory's content recursively with all the directories' - timestamps preserved. - - Args: - root_directory_path: The directory's path to archive. - archive_dest_path: Archive destination's path. - """ - with zipfile.ZipFile(archive_dest_path, 'w') as zip_output: - timestamps = {} - root_directory_stats = os.stat(root_directory_path) - timestamps['.'] = { - 'atime': root_directory_stats.st_atime, - 'mtime': root_directory_stats.st_mtime} - for directory_path, dirnames, filenames in os.walk(root_directory_path): - for dirname in dirnames: - subdirectory_path = os.path.join(directory_path, dirname) - subdirectory_relative_path = os.path.relpath(subdirectory_path, - root_directory_path) - subdirectory_stats = os.stat(subdirectory_path) - timestamps[subdirectory_relative_path] = { - 'atime': subdirectory_stats.st_atime, - 'mtime': subdirectory_stats.st_mtime} - for filename in filenames: - file_path = os.path.join(directory_path, filename) - file_archive_name = os.path.join('content', - os.path.relpath(file_path, root_directory_path)) - file_stats = os.stat(file_path) - timestamps[file_archive_name[8:]] = { - 'atime': file_stats.st_atime, - 'mtime': file_stats.st_mtime} - zip_output.write(file_path, arcname=file_archive_name) - zip_output.writestr('timestamps.json', - json.dumps(timestamps, indent=2)) - - -def UnzipDirectoryContent(archive_path, directory_dest_path): - """Unzip a directory's content recursively with all the directories' - timestamps preserved. - - Args: - archive_path: Archive's path to unzip. - directory_dest_path: Directory destination path. - """ - _EnsureCleanCacheDirectory(directory_dest_path) - with zipfile.ZipFile(archive_path) as zip_input: - timestamps = None - for file_archive_name in zip_input.namelist(): - if file_archive_name == 'timestamps.json': - timestamps = json.loads(zip_input.read(file_archive_name)) - elif file_archive_name.startswith('content/'): - file_relative_path = file_archive_name[8:] - file_output_path = os.path.join(directory_dest_path, file_relative_path) - file_parent_directory_path = os.path.dirname(file_output_path) - if not os.path.exists(file_parent_directory_path): - os.makedirs(file_parent_directory_path) - with open(file_output_path, 'w') as f: - f.write(zip_input.read(file_archive_name)) - - assert timestamps - # os.utime(file_path, ...) modifies modification time of file_path's parent - # directories. Therefore we call os.utime on files and directories that have - # longer relative paths first. - for relative_path in sorted(timestamps.keys(), key=len, reverse=True): - stats = timestamps[relative_path] - output_path = os.path.join(directory_dest_path, relative_path) - if not os.path.exists(output_path): - os.makedirs(output_path) - os.utime(output_path, (stats['atime'], stats['mtime'])) - - -def CopyCacheDirectory(directory_src_path, directory_dest_path): - """Copies a cache directory recursively with all the directories' - timestamps preserved. - - Args: - directory_src_path: Path of the cache directory source. - directory_dest_path: Path of the cache directory destination. - """ - assert os.path.isdir(directory_src_path) - _EnsureCleanCacheDirectory(directory_dest_path) - shutil.copytree(directory_src_path, directory_dest_path) - - -class CacheBackend(object): - """Takes care of reading and deleting cached keys. - """ - - def __init__(self, cache_directory_path, cache_backend_type): - """Chrome cache back-end constructor. - - Args: - cache_directory_path: The directory path where the cache is locally - stored. - cache_backend_type: A cache back-end type in BACKEND_TYPES. - """ - assert os.path.isdir(cache_directory_path) - assert cache_backend_type in BACKEND_TYPES - self._cache_directory_path = cache_directory_path - self._cache_backend_type = cache_backend_type - # Make sure cache_directory_path is a valid cache. - self._CachetoolCmd('validate') - - def GetSize(self): - """Gets total size of cache entries in bytes.""" - size = self._CachetoolCmd('get_size') - return int(size.strip()) - - def ListKeys(self): - """Lists cache's keys. - - Returns: - A list of all keys stored in the cache. - """ - return [k.strip() for k in self._CachetoolCmd('list_keys').split('\n')[:-1]] - - def GetStreamForKey(self, key, index): - """Gets a key's stream. - - Args: - key: The key to access the stream. - index: The stream index: - index=0 is the HTTP response header; - index=1 is the transport encoded content; - index=2 is the compiled content. - - Returns: - String holding stream binary content. - """ - return self._CachetoolCmd('get_stream', [key, str(index)]) - - def DeleteStreamForKey(self, key, index): - """Delete a key's stream. - - Args: - key: The key to access the stream. - index: The stream index - """ - self._CachetoolCmd('delete_stream', [key, str(index)]) - - def DeleteKey(self, key): - """Deletes a key from the cache. - - Args: - key: The key delete. - """ - self._CachetoolCmd('delete_key', [key]) - - def _CachetoolCmd(self, operation, args=None, stdin=''): - """Runs the cache editor tool and return the stdout. - - Args: - operation: Cachetool operation. - args: Additional operation argument to append to the command line. - stdin: String to pipe to the Cachetool's stdin. - - Returns: - Cachetool's stdout string. - """ - editor_tool_cmd = [ - OPTIONS.LocalBinary('cachetool'), - self._cache_directory_path, - self._cache_backend_type, - operation] - editor_tool_cmd.extend(args or []) - process = subprocess.Popen( - editor_tool_cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE) - stdout_data, _ = process.communicate(input=stdin) - assert process.returncode == 0 - return stdout_data - - def UpdateRawResponseHeaders(self, key, raw_headers): - """Updates a key's raw response headers. - - Args: - key: The key to modify. - raw_headers: Raw response headers to set. - """ - self._CachetoolCmd('update_raw_headers', [key], stdin=raw_headers) - - def GetDecodedContentForKey(self, key): - """Gets a key's decoded content. - - HTTP cache is storing into key's index stream 1 the transport layer resource - binary. However, the resources might be encoded using a compression - algorithm specified in the Content-Encoding response header. This method - takes care of returning decoded binary content of the resource. - - Args: - key: The key to access the decoded content. - - Returns: - String holding binary content. - """ - response_headers = self.GetStreamForKey(key, 0) - content_encoding = None - for response_header_line in response_headers.split('\n'): - match = HEADER_PARSING_REGEX.match(response_header_line) - if not match: - continue - if match.group('header').lower() == 'content-encoding': - content_encoding = match.group('value') - break - encoded_content = self.GetStreamForKey(key, 1) - if content_encoding == None: - return encoded_content - - cmd = [OPTIONS.LocalBinary('content_decoder_tool')] - cmd.extend([s.strip() for s in content_encoding.split(',')]) - process = subprocess.Popen(cmd, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE) - decoded_content, _ = process.communicate(input=encoded_content) - assert process.returncode == 0 - return decoded_content - - -def ApplyUrlWhitelistToCacheArchive(cache_archive_path, - whitelisted_urls, - output_cache_archive_path): - """Generate a new cache archive containing only whitelisted urls. - - Args: - cache_archive_path: Path of the cache archive to apply the white listing. - whitelisted_urls: Set of url to keep in cache. - output_cache_archive_path: Destination path of cache archive containing only - white-listed urls. - """ - cache_temp_directory = tempfile.mkdtemp(suffix='.cache') - try: - UnzipDirectoryContent(cache_archive_path, cache_temp_directory) - backend = CacheBackend(cache_temp_directory, 'simple') - cached_urls = backend.ListKeys() - for cached_url in cached_urls: - if cached_url not in whitelisted_urls: - backend.DeleteKey(cached_url) - for cached_url in backend.ListKeys(): - assert cached_url in whitelisted_urls - ZipDirectoryContent(cache_temp_directory, output_cache_archive_path) - finally: - shutil.rmtree(cache_temp_directory) - - -def ManualTestMain(): - import argparse - parser = argparse.ArgumentParser(description='Tests cache back-end.') - parser.add_argument('cache_archive_path', type=str) - parser.add_argument('backend_type', type=str, choices=BACKEND_TYPES) - command_line_args = parser.parse_args() - - cache_path = tempfile.mkdtemp() - UnzipDirectoryContent(command_line_args.cache_archive_path, cache_path) - - cache_backend = CacheBackend( - cache_directory_path=cache_path, - cache_backend_type=command_line_args.backend_type) - keys = sorted(cache_backend.ListKeys()) - selected_key = None - for key in keys: - if key.endswith('.js'): - selected_key = key - break - assert selected_key - print '{}\'s HTTP response header:'.format(selected_key) - print cache_backend.GetStreamForKey(selected_key, 0) - print cache_backend.GetDecodedContentForKey(selected_key) - cache_backend.DeleteKey(keys[1]) - assert keys[1] not in cache_backend.ListKeys() - shutil.rmtree(cache_path) - - -if __name__ == '__main__': - ManualTestMain()
diff --git a/tools/android/loading/chrome_cache_unittest.py b/tools/android/loading/chrome_cache_unittest.py deleted file mode 100644 index 051a938a..0000000 --- a/tools/android/loading/chrome_cache_unittest.py +++ /dev/null
@@ -1,121 +0,0 @@ -# Copyright 2016 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. - -import os -import shutil -import tempfile -import unittest - -import chrome_cache - - -LOADING_DIR = os.path.dirname(os.path.abspath(__file__)) -THIS_BASEMAME = os.path.basename(__file__) - - -class CacheDirectoryTest(unittest.TestCase): - def setUp(self): - self._temp_dir = tempfile.mkdtemp() - - def tearDown(self): - shutil.rmtree(self._temp_dir) - - def GetTempPath(self, temp_name): - return os.path.join(self._temp_dir, temp_name) - - def CreateNewGarbageFile(self, file_path): - assert not os.path.exists(file_path) - with open(file_path, 'w') as f: - f.write('garbage content') - assert os.path.isfile(file_path) - - @classmethod - def CompareDirectories(cls, reference_path, generated_path): - def CompareNode(relative_path): - reference_stat = os.stat(os.path.join(reference_path, relative_path)) - generated_stat = os.stat(os.path.join(generated_path, relative_path)) - assert int(reference_stat.st_mtime) == int(generated_stat.st_mtime), \ - "{}: invalid mtime.".format(relative_path) - for reference_parent_path, dir_names, file_names in os.walk(reference_path): - parent_path = os.path.relpath(reference_parent_path, reference_path) - reference_nodes = sorted(dir_names + file_names) - generated_nodes = sorted(os.listdir( - os.path.join(generated_path, parent_path))) - assert reference_nodes == generated_nodes, \ - '{}: directory entries don\'t match.'.format(parent_path) - for node in file_names: - CompareNode(os.path.join(parent_path, node)) - CompareNode(parent_path) - - def testCompareDirectories(self): - generated_path = self.GetTempPath('dir0') - shutil.copytree(LOADING_DIR, generated_path) - self.CompareDirectories(LOADING_DIR, generated_path) - - generated_path = self.GetTempPath('dir1') - shutil.copytree(LOADING_DIR, generated_path) - self.CreateNewGarbageFile(os.path.join(generated_path, 'garbage')) - assert 'garbage' in os.listdir(generated_path) - with self.assertRaisesRegexp(AssertionError, r'^.* match\.$'): - self.CompareDirectories(LOADING_DIR, generated_path) - - generated_path = self.GetTempPath('dir2') - shutil.copytree(LOADING_DIR, generated_path) - self.CreateNewGarbageFile(os.path.join(generated_path, 'testdata/garbage')) - with self.assertRaisesRegexp(AssertionError, r'^.* match\.$'): - self.CompareDirectories(LOADING_DIR, generated_path) - - generated_path = self.GetTempPath('dir3') - shutil.copytree(LOADING_DIR, generated_path) - os.remove(os.path.join(generated_path, THIS_BASEMAME)) - with self.assertRaisesRegexp(AssertionError, r'^.* match\.$'): - self.CompareDirectories(LOADING_DIR, generated_path) - self.CreateNewGarbageFile(os.path.join(generated_path, 'garbage')) - with self.assertRaisesRegexp(AssertionError, r'^.* match\.$'): - self.CompareDirectories(LOADING_DIR, generated_path) - - def TouchHelper(temp_name, relative_name, timestamps): - generated_path = self.GetTempPath(temp_name) - shutil.copytree(LOADING_DIR, generated_path) - os.utime(os.path.join(generated_path, relative_name), timestamps) - with self.assertRaisesRegexp(AssertionError, r'^.* invalid mtime\.$'): - self.CompareDirectories(LOADING_DIR, generated_path) - - TouchHelper('dir4', THIS_BASEMAME, (1256925858, 1256463122)) - TouchHelper('dir5', 'testdata', (1256918318, 1256568641)) - TouchHelper('dir6', 'trace_test/test_server.py', (1255116211, 1256156632)) - TouchHelper('dir7', './', (1255115332, 1256251864)) - - def testCacheArchive(self): - zip_dest = self.GetTempPath('cache.zip') - chrome_cache.ZipDirectoryContent(LOADING_DIR, zip_dest) - - unzip_dest = self.GetTempPath('cache') - chrome_cache.UnzipDirectoryContent(zip_dest, unzip_dest) - self.CompareDirectories(LOADING_DIR, unzip_dest) - - self.CreateNewGarbageFile(os.path.join(unzip_dest, 'garbage')) - chrome_cache.UnzipDirectoryContent(zip_dest, unzip_dest) - self.CompareDirectories(LOADING_DIR, unzip_dest) - - unzip_dest = self.GetTempPath('foo/bar/cache') - chrome_cache.UnzipDirectoryContent(zip_dest, unzip_dest) - self.CompareDirectories(LOADING_DIR, unzip_dest) - - def testCopyCacheDirectory(self): - copy_dest = self.GetTempPath('cache') - chrome_cache.CopyCacheDirectory(LOADING_DIR, copy_dest) - self.CompareDirectories(LOADING_DIR, copy_dest) - - self.CreateNewGarbageFile(os.path.join(copy_dest, 'garbage')) - chrome_cache.CopyCacheDirectory(LOADING_DIR, copy_dest) - self.CompareDirectories(LOADING_DIR, copy_dest) - - copy_dest = self.GetTempPath('foo/bar/cache') - chrome_cache.CopyCacheDirectory(LOADING_DIR, copy_dest) - self.CompareDirectories(LOADING_DIR, copy_dest) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/cloud/__init__.py b/tools/android/loading/cloud/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/tools/android/loading/cloud/__init__.py +++ /dev/null
diff --git a/tools/android/loading/cloud/backend/README.md b/tools/android/loading/cloud/backend/README.md deleted file mode 100644 index 3376457..0000000 --- a/tools/android/loading/cloud/backend/README.md +++ /dev/null
@@ -1,197 +0,0 @@ -# Clovis in the Cloud: Developer Guide - -This document describes the backend-side of the trace collection, using Google -Compute Engine. - -When the [frontend][3] spawns new tasks, it pushes them into a [TaskQueue][4] -called `clovis-queue` with a unique tag. -Then it creates backend instances (as an instance group) and passes them the -TaskQueue tag. - -The backend instances then pull tasks from the TaskQueue and process them until -it is empty. When there is no task left in the queue, the backend instances -kill themselves. - -The main files for the backend are: - -- `startup-script.sh`: initializes an instance (installs the dependencies, - downloads the code and the configuration). -- `worker.py`: the main worker script. -- Task handlers have a `Run()` method taking a `ClovisTask` parameter. - - `clovis_task_handler.py`: Main entry point, dispatches the tasks to the - more specialized handlers below. - - `trace_task_handler.py`: Handles `trace` tasks. - - `report_task_handler.py`: Handles `report` tasks. - -[TOC] - -## Initial setup for development - -Install the [gcloud command line tool][1]. - -## Deploy the code - -This step deploys all the source code needed by the backend workers, as well as -the Chromium binaries required for trace collection. - -```shell -# Build Chrome (do not use the component build). -BUILD_DIR=out/Release -ninja -C $BUILD_DIR -j1000 -l60 chrome chrome_sandbox - -# Deploy to GCE -# CLOUD_STORAGE_PATH is the path in Google Cloud Storage under which the -# Clovis deployment will be uploaded. - -./tools/android/loading/cloud/backend/deploy.sh $BUILD_DIR $CLOUD_STORAGE_PATH -``` - -## Start the app in the cloud - -The application is automatically started by the frontend, and should not need to -be started manually. - -If you really want to create an instance manually (when debugging for example), -this can be done like this: - -```shell -gcloud compute instances create $INSTANCE_NAME \ - --machine-type n1-standard-1 \ - --image ubuntu-14-04 \ - --zone europe-west1-c \ - --scopes cloud-platform,https://www.googleapis.com/auth/cloud-taskqueue \ - --metadata \ - cloud-storage-path=$CLOUD_STORAGE_PATH,task-dir=dir,taskqueue-tag=tag \ - --metadata-from-file \ - startup-script=$CHROMIUM_SRC/tools/android/loading/cloud/backend/startup-script.sh -``` - -If you are debbugging, you probably want to set additional metadata: - -- `auto-start=false`: to start an instance without automatically starting the - app on it. This can be useful when doing iterative development on the - instance using ssh, to be able to stop and restart the app manually. -- `self-destruct=false`: to prevent the instance from self-destructing when - the queue is empty. - -**Notes:** - -- If you use `auto-start=false`, and then try to ssh on the instance and - launch `worker.py`, it will not work because of various issues, such as: - - Environment variables defined by the startup script are not available - to your user and you will need to redefine them. - - You will not have permissions to access the files, and need to run - `sudo chown` to give yourself permissions. - - You need to activate `virtualenv`. - Get in touch with *droger@* if you need this or want to improve it. -- It can take a few minutes for the instance to start. You can follow the - progress of the startup script on the gcloud console web interface (menu - "Compute Engine" > "VM instances" then click on your instance and scroll - down to see the "Serial console output") or from the command line using: - -```shell -gcloud compute instances get-serial-port-output $INSTANCE_NAME -``` - -## `worker.py` configuration file - -`worker.py` takes a configuration file as command line parameter. This is a JSON -dictionary with the keys: - -- `project_name` (string): Name of the Google Cloud project -- `task_storage_path` (string): Path in Google Storage where task output is - generated. -- `binaries_path` (string): Path to the executables (Containing chrome). -- `src_path` (string): Path to the Chromium source directory. -- `taskqueue_tag` (string): Tag used by the worker when pulling tasks from - `clovis-queue`. -- `ad_rules_filename` and `tracking_rules_filename` (string): Path to the ad - and tracking filtering rules. -- `instance_name` (string, optional): Name of the Compute Engine instance this - script is running on. -- `worker_log_path` (string, optional): Path to the log file capturing the - output of `worker.py`, to be uploaded to Cloud Storage. -- `self_destruct` (boolean, optional): Whether the worker will destroy the - Compute Engine instance when there are no remaining tasks to process. This - is only relevant when running in the cloud, and requires `instance_name` to - be defined. - -## Use the app - -Create tasks from the associated AppEngine application, see [documentation][3]. - -If you want the frontend to send tasks to a particular instance that you created -manually, make sure the `tag` and `storage_bucket` of the AppEngine request -match the ones of your ComputeEngine instance, and set `instance_count` to `0`. - -## Stop the app in the cloud - -To stop a single instance that you started manually, do: - -```shell -gcloud compute instances delete $INSTANCE_NAME -``` - -To stop instances that were created by the frontend, you must delete the -instance group, not the individual instances. Otherwise the instance group will -just recreate the deleted instances. You can do this from the Google Cloud -console web interface, or using the `gcloud compute groups` commands. - -## Connect to the instance with SSH - -```shell -gcloud compute ssh $INSTANCE_NAME -``` - -## Run the app locally - -From a new directory, set up a local environment: - -```shell -virtualenv env -source env/bin/activate -pip install -r \ - $CHROMIUM_SRC/tools/android/loading/cloud/backend/pip_requirements.txt -``` - -The first time, you may need to get more access tokens: - -```shell -gcloud beta auth application-default login --scopes \ - https://www.googleapis.com/auth/cloud-taskqueue \ - https://www.googleapis.com/auth/cloud-platform -``` - -Create a local configuration file for `worker.py`. Example: - -```shell -cat >$CONFIG_FILE << EOF -{ - "project_name" : "$PROJECT_NAME", - "cloud_storage_path" : "$CLOUD_STORAGE_PATH", - "binaries_path" : "$BUILD_DIR", - "src_path" : "$CHROMIUM_SRC", - "taskqueue_tag" : "some-tag" -} -EOF -``` - -Launch the app, passing the path to the deployment configuration file: - -```shell -python $CHROMIUM_SRC/tools/android/loading/cloud/backend/worker.py \ - --config $CONFIG_FILE -``` - -You can now [use the app][2]. - -Tear down the local environment: - -```shell -deactivate -``` - -[1]: https://cloud.google.com/sdk -[2]: #Use-the-app -[3]: ../frontend/README.md -[4]: https://cloud.google.com/appengine/docs/python/taskqueue
diff --git a/tools/android/loading/cloud/backend/clovis_task_handler.py b/tools/android/loading/cloud/backend/clovis_task_handler.py deleted file mode 100644 index 6e05ee9..0000000 --- a/tools/android/loading/cloud/backend/clovis_task_handler.py +++ /dev/null
@@ -1,60 +0,0 @@ -# Copyright 2016 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. - -import os - -from common.clovis_task import ClovisTask -from failure_database import FailureDatabase -from report_task_handler import ReportTaskHandler -from trace_task_handler import TraceTaskHandler - - -class ClovisTaskHandler(object): - """Handles all the supported clovis tasks.""" - - def __init__(self, project_name, base_path, failure_database, - google_storage_accessor, bigquery_service, binaries_path, - ad_rules_filename, tracking_rules_filename, logger, - instance_name=None): - """Creates a ClovisTaskHandler. - - Args: - project_name (str): Name of the project. - base_path(str): Base path where results are written. - failure_database (FailureDatabase): Failure Database. - google_storage_accessor (GoogleStorageAccessor): Cloud storage accessor. - bigquery_service (googleapiclient.discovery.Resource): Bigquery service. - binaries_path(str): Path to the directory where Chrome executables are. - ad_rules_filename (str): Path to the ad filtering rules. - tracking_rules_filename (str): Path to the tracking filtering rules. - instance_name(str, optional): Name of the ComputeEngine instance. - """ - self._failure_database = failure_database - self._handlers = { - 'trace': TraceTaskHandler( - base_path, failure_database, google_storage_accessor, binaries_path, - logger, instance_name), - 'report': ReportTaskHandler( - project_name, failure_database, google_storage_accessor, - bigquery_service, logger, ad_rules_filename, - tracking_rules_filename)} - - def Run(self, clovis_task): - """Runs a clovis_task. - - Args: - clovis_task(ClovisTask): The task to run. - """ - handler = self._handlers.get(clovis_task.Action()) - if not handler: - self._logger.error('Unsupported task action: %s' % clovis_task.Action()) - self._failure_database.AddFailure('unsupported_action', - clovis_task.Action()) - return - handler.Run(clovis_task) - - def Finalize(self): - """Called once before the handler is destroyed.""" - for handler in self._handlers.values(): - handler.Finalize()
diff --git a/tools/android/loading/cloud/backend/deploy.sh b/tools/android/loading/cloud/backend/deploy.sh deleted file mode 100755 index 75f07035..0000000 --- a/tools/android/loading/cloud/backend/deploy.sh +++ /dev/null
@@ -1,71 +0,0 @@ -#!/bin/bash -# Copyright 2016 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. - -# This script copies all dependencies required for trace collection. -# Usage: -# deploy.sh builddir gcs_path -# -# Where: -# builddir is the build directory for Chrome -# gcs_path is the Google Storage bucket under which the deployment is -# installed - -builddir=$1 -tmpdir=`mktemp -d` -deployment_gcs_path=$2/deployment - -# Extract needed sources. -src_suffix=src -tmp_src_dir=$tmpdir/$src_suffix - -# Copy files from tools/android/loading. -mkdir -p $tmp_src_dir/tools/android/loading/cloud -cp -r tools/android/loading/cloud/backend \ - $tmp_src_dir/tools/android/loading/cloud/ -cp -r tools/android/loading/cloud/common \ - $tmp_src_dir/tools/android/loading/cloud/ -cp tools/android/loading/*.py $tmp_src_dir/tools/android/loading -cp tools/android/loading/cloud/*.py $tmp_src_dir/tools/android/loading/cloud - -# Copy other dependencies. -mkdir $tmp_src_dir/third_party -rsync -av --exclude=".*" --exclude "*.pyc" --exclude "*.html" --exclude "*.md" \ - third_party/catapult $tmp_src_dir/third_party -mkdir $tmp_src_dir/tools/perf -cp -r tools/perf/chrome_telemetry_build $tmp_src_dir/tools/perf -mkdir -p $tmp_src_dir/build/android -cp build/android/devil_chromium.py $tmp_src_dir/build/android/ -cp build/android/video_recorder.py $tmp_src_dir/build/android/ -cp build/android/devil_chromium.json $tmp_src_dir/build/android/ -cp -r build/android/pylib $tmp_src_dir/build/android/ -mkdir -p \ - $tmp_src_dir/third_party/blink/renderer/devtools/front_end/emulated_devices -cp third_party/blink/renderer/devtools/front_end/emulated_devices/module.json \ - $tmp_src_dir/third_party/blink/renderer/devtools/front_end/emulated_devices/ - -# Tar up the source and copy it to Google Cloud Storage. -source_tarball=$tmpdir/source.tgz -tar -cvzf $source_tarball -C $tmpdir $src_suffix -gsutil cp $source_tarball gs://$deployment_gcs_path/source/ - -# Copy the chrome executable to Google Cloud Storage. -chrome/tools/build/make_zip.py $builddir chrome/tools/build/linux/FILES.cfg \ - $tmpdir/linux.zip -gsutil cp $tmpdir/linux.zip gs://$deployment_gcs_path/binaries/linux.zip - -# Copy the startup script uncompressed so that it can be executed. -gsutil cp tools/android/loading/cloud/backend/startup-script.sh \ - gs://$deployment_gcs_path/ - -# Generate and upload metadata about this deployment. -CHROMIUM_REV=$(git merge-base HEAD origin/master) -cat >$tmpdir/build_metadata.json << EOF -{ - "chromium_rev": "$CHROMIUM_REV" -} -EOF -gsutil cp $tmpdir/build_metadata.json \ - gs://$deployment_gcs_path/deployment_metadata.json -rm -rf $tmpdir
diff --git a/tools/android/loading/cloud/backend/failure_database.py b/tools/android/loading/cloud/backend/failure_database.py deleted file mode 100644 index a044f0428..0000000 --- a/tools/android/loading/cloud/backend/failure_database.py +++ /dev/null
@@ -1,44 +0,0 @@ -# Copyright 2016 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. - -import json - -class FailureDatabase(object): - """Logs the failures happening in the Clovis backend.""" - DIRTY_STATE_ERROR = 'startup_with_dirty_state' - CRITICAL_ERROR = 'critical_error' - - def __init__(self, json_string=None): - """Loads a FailureDatabase from a string returned by ToJsonString().""" - self.is_dirty = False - if json_string: - self._failures_dict = json.loads(json_string) - else: - self._failures_dict = {} - - def ToJsonDict(self): - """Returns a dict representing this instance.""" - return self._failures_dict - - def ToJsonString(self): - """Returns a string representing this instance.""" - return json.dumps(self.ToJsonDict(), indent=2) - - def AddFailure(self, failure_name, failure_content=None): - """Adds a failure with the given name and content. If the failure already - exists, it will increment the associated count. - Sets the 'is_dirty' bit to True. - - Args: - failure_name (str): name of the failure. - failure_content (str): content of the failure (e.g. the URL or task that - is failing). - """ - self.is_dirty = True - content = failure_content if failure_content else 'error_count' - if failure_name not in self._failures_dict: - self._failures_dict[failure_name] = {} - error_count = self._failures_dict[failure_name].get(content, 0) - self._failures_dict[failure_name][content] = error_count + 1 -
diff --git a/tools/android/loading/cloud/backend/google_storage_accessor.py b/tools/android/loading/cloud/backend/google_storage_accessor.py deleted file mode 100644 index c95d742..0000000 --- a/tools/android/loading/cloud/backend/google_storage_accessor.py +++ /dev/null
@@ -1,78 +0,0 @@ -# Copyright 2016 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. - -import gcloud.exceptions -import gcloud.storage - - -class GoogleStorageAccessor(object): - """Utility class providing helpers for Google Cloud Storage. - """ - def __init__(self, credentials, project_name, bucket_name): - """project_name is the name of the Google Cloud project. - bucket_name is the name of the bucket that is used for Cloud Storage calls. - """ - self._credentials = credentials - self._project_name = project_name - self._bucket_name = bucket_name - - def _GetStorageClient(self): - """Returns the storage client associated with the project.""" - return gcloud.storage.Client(project = self._project_name, - credentials = self._credentials) - - def _GetStorageBucket(self, storage_client): - return storage_client.get_bucket(self._bucket_name) - - def BucketName(self): - """Returns the name of the bucket associated with this instance.""" - return self._bucket_name - - def DownloadAsString(self, remote_filename): - """Returns the content of a remote file as a string, or None if the file - does not exist. - """ - client = self._GetStorageClient() - bucket = self._GetStorageBucket(client) - blob = bucket.get_blob(remote_filename) - if not blob: - return None - try: - return blob.download_as_string() - except gcloud.exceptions.NotFound: - return None - - def UploadFile(self, filename_src, filename_dest): - """Uploads a file to Google Cloud Storage. - - Args: - filename_src: name of the local file. - filename_dest: name of the file in Google Cloud Storage. - - Returns: - The URL of the file in Google Cloud Storage. - """ - client = self._GetStorageClient() - bucket = self._GetStorageBucket(client) - blob = bucket.blob(filename_dest) - with open(filename_src) as file_src: - blob.upload_from_file(file_src) - return blob.public_url - - def UploadString(self, data_string, filename_dest): - """Uploads a string to Google Cloud Storage. - - Args: - data_string: the contents of the file to be uploaded. - filename_dest: name of the file in Google Cloud Storage. - - Returns: - The URL of the file in Google Cloud Storage. - """ - client = self._GetStorageClient() - bucket = self._GetStorageBucket(client) - blob = bucket.blob(filename_dest) - blob.upload_from_string(data_string) - return blob.public_url -
diff --git a/tools/android/loading/cloud/backend/multiprocessing_helper.py b/tools/android/loading/cloud/backend/multiprocessing_helper.py deleted file mode 100644 index 3bd78793..0000000 --- a/tools/android/loading/cloud/backend/multiprocessing_helper.py +++ /dev/null
@@ -1,88 +0,0 @@ -# Copyright 2016 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. - -import multiprocessing -import os -import Queue -import resource -import signal - -import psutil - - -def _LimitMemory(memory_share): - """Limits the memory available to this process, to avoid OOM issues. - - Args: - memory_share: (float) Share coefficient of the total physical memory that - the process can use. - """ - total_memory = psutil.virtual_memory().total - memory_limit = memory_share * total_memory - resource.setrlimit(resource.RLIMIT_AS, (memory_limit, -1L)) - - -def _MultiprocessingWrapper(queue, memory_share, function, args): - """Helper function that sets a memory limit on the current process, then - calls |function| on |args| and writes the results to |queue|. - - Args: - queue: (multiprocessing.Queue) Queue where the results of the wrapped - function are written. - memory_share: (float) Share coefficient of the total physical memory that - the process can use. - function: The wrapped function. - args: (list) Arguments for the wrapped function. - """ - try: - if memory_share: - _LimitMemory(memory_share) - - queue.put(function(*args)) - except Exception: - queue.put(None) - - -def RunInSeparateProcess(function, args, logger, timeout_seconds, - memory_share=None): - """Runs a function in a separate process, and kills it after the timeout is - reached. - - Args: - function: The function to run. - args: (list) Arguments for the wrapped function. - timeout_seconds: (float) Timeout in seconds after which the subprocess is - terminated. - memory_share: (float) Set this parameter to limit the memory available to - the spawned subprocess. This is a ratio of the total system - memory (between 0 and 1). - Returns: - The result of the wrapped function, or None if the call failed. - """ - queue = multiprocessing.Queue() - process = multiprocessing.Process(target=_MultiprocessingWrapper, - args=(queue, memory_share, function, args)) - process.daemon = True - process.start() - - result = None - - try: - logger.info('Wait for result.') - # Note: If the subprocess somehow crashes (e.g. Python crashing), this - # process will wait the full timeout. Could be avoided but probably not - # worth the extra complexity. - result = queue.get(block=True, timeout=timeout_seconds) - except Queue.Empty: - logger.warning('Subprocess timeout.') - process.terminate() - - logger.info('Wait for process to terminate.') - process.join(timeout=5) - - if process.is_alive(): - logger.warning('Process still alive, hard killing now.') - os.kill(process.pid, signal.SIGKILL) - - return result
diff --git a/tools/android/loading/cloud/backend/pip_requirements.txt b/tools/android/loading/cloud/backend/pip_requirements.txt deleted file mode 100644 index f2eb36ba..0000000 --- a/tools/android/loading/cloud/backend/pip_requirements.txt +++ /dev/null
@@ -1,4 +0,0 @@ -gcloud==0.10.1 -google-api-python-client==1.5.0 -psutil==4.1.0 -adblockparser==0.5
diff --git a/tools/android/loading/cloud/backend/report_task_handler.py b/tools/android/loading/cloud/backend/report_task_handler.py deleted file mode 100644 index e59d65e..0000000 --- a/tools/android/loading/cloud/backend/report_task_handler.py +++ /dev/null
@@ -1,156 +0,0 @@ -# Copyright 2016 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. - -import json -import math - -from googleapiclient import errors - -import common.google_bigquery_helper -from common.loading_trace_database import LoadingTraceDatabase -import common.google_error_helper as google_error_helper -from failure_database import FailureDatabase -from loading_trace import LoadingTrace -from report import LoadingReport - - -def LoadRemoteTrace(storage_accessor, remote_trace_path, logger): - """Loads and returns the LoadingTrace located at the remote trace path. - - Args: - storage_accessor: (GoogleStorageAccessor) Used to download the trace from - CloudStorage. - remote_trace_path: (str) Path to the trace file. - """ - - # Cut the gs://<bucket_name> prefix from trace paths if needed. - prefix = 'gs://%s/' % storage_accessor.BucketName() - prefix_length = len(prefix) - if remote_trace_path.startswith(prefix): - remote_trace_path = remote_trace_path[prefix_length:] - - trace_string = storage_accessor.DownloadAsString( - remote_trace_path) - if not trace_string: - logger.error('Failed to download: ' + remote_trace_path) - return None - - trace_dict = json.loads(trace_string) - if not trace_dict: - logger.error('Failed to parse: ' + remote_trace_path) - return None - - trace = LoadingTrace.FromJsonDict(trace_dict) - if not trace: - logger.error('Invalid format for: ' + remote_trace_path) - return None - - return trace - - -class ReportTaskHandler(object): - """Handles 'report' tasks. - - This handler loads the traces given in the task parameters, generates a report - from them, and add them to a BigQuery table. - The BigQuery table is implicitly created from a template (using the stream - mode), and identified by the task tag. - """ - - def __init__(self, project_name, failure_database, google_storage_accessor, - bigquery_service, logger, ad_rules_filename, - tracking_rules_filename): - self._project_name = project_name - self._failure_database = failure_database - self._google_storage_accessor = google_storage_accessor - self._bigquery_service = bigquery_service - self._logger = logger - self._ad_rules_filename = ad_rules_filename - self._tracking_rules_filename = tracking_rules_filename - - def _IsBigQueryValueValid(self, value): - """Returns whether a value is valid and can be uploaded to BigQuery.""" - if value is None: - return False - # BigQuery rejects NaN. - if type(value) is float and (math.isnan(value) or math.isinf(value)): - return False - return True - - def _StreamRowsToBigQuery(self, rows, table_id): - """Uploads a list of rows to the BigQuery table associated with the given - table_id. - - Args: - rows: (list of dict) Each dictionary is a row to add to the table. - table_id: (str) Identifier of the BigQuery table to update. - """ - try: - response = common.google_bigquery_helper.InsertInTemplatedBigQueryTable( - self._bigquery_service, self._project_name, table_id, rows, - self._logger) - except errors.HttpError as http_error: - # Handles HTTP error response codes (such as 404), typically indicating a - # problem in parameters other than 'body'. - error_content = google_error_helper.GetErrorContent(http_error) - error_reason = google_error_helper.GetErrorReason(error_content) - self._logger.error('BigQuery API error (reason: "%s"):\n%s' % ( - error_reason, http_error)) - self._failure_database.AddFailure('big_query_error', error_reason) - if error_content: - self._logger.error('Error details:\n%s' % error_content) - return - - # Handles other errors, typically when the body is ill-formatted. - insert_errors = response.get('insertErrors') - if insert_errors: - self._logger.error('BigQuery API error:\n' + str(insert_errors)) - for insert_error in insert_errors: - self._failure_database.AddFailure('big_query_insert_error', - str(insert_error.get('errors'))) - - def Finalize(self): - """Called once before the handler is destroyed.""" - pass - - def Run(self, clovis_task): - """Runs a 'report' clovis_task. - - Args: - clovis_task: (ClovisTask) The task to run. - """ - if clovis_task.Action() != 'report': - self._logger.error('Unsupported task action: %s' % clovis_task.Action()) - self._failure_database.AddFailure(FailureDatabase.CRITICAL_ERROR, - 'report_task_handler_run') - return - - ad_rules = open(self._ad_rules_filename).readlines() - tracking_rules = open(self._tracking_rules_filename).readlines() - - rows = [] - for path in clovis_task.ActionParams()['traces']: - self._logger.info('Generating report for: ' + path) - trace = LoadRemoteTrace(self._google_storage_accessor, path, self._logger) - if not trace: - self._logger.error('Failed loading trace at: ' + path) - self._failure_database.AddFailure('missing_trace_for_report', path) - continue - report = LoadingReport(trace, ad_rules, tracking_rules).GenerateReport() - if not report: - self._logger.error('Failed generating report for: ' + path) - self._failure_database.AddFailure('report_generation_failed', path) - continue - # Filter out bad values. - for key, value in report.items(): - if not self._IsBigQueryValueValid(value): - url = report.get('url') - self._logger.error('Invalid %s for URL:%s' % (key, url)) - self._failure_database.AddFailure('invalid_bigquery_value', url) - del report[key] - rows.append(report) - - if rows: - table_id = common.google_bigquery_helper.GetBigQueryTableID(clovis_task) - self._StreamRowsToBigQuery(rows, table_id)
diff --git a/tools/android/loading/cloud/backend/startup-script.sh b/tools/android/loading/cloud/backend/startup-script.sh deleted file mode 100644 index 66ec2a4..0000000 --- a/tools/android/loading/cloud/backend/startup-script.sh +++ /dev/null
@@ -1,133 +0,0 @@ -# Copyright 2016 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. - -# Script executed at instance startup. It installs the required dependencies, -# downloads the source code, and starts a web server. - -set -v - -get_instance_metadata() { - curl -fs http://metadata/computeMetadata/v1/instance/attributes/$1 \ - -H "Metadata-Flavor: Google" -} - -# Talk to the metadata server to get the project id and the instance id -PROJECTID=$(curl -s \ - "http://metadata.google.internal/computeMetadata/v1/project/project-id" \ - -H "Metadata-Flavor: Google") - -INSTANCE_NAME=$(curl -s \ - "http://metadata.google.internal/computeMetadata/v1/instance/hostname" \ - -H "Metadata-Flavor: Google") - -# Install dependencies from apt -apt-get update -# Basic dependencies -apt-get install -yq git supervisor python-pip python-dev unzip -# Web server dependencies -apt-get install -yq libffi-dev libssl-dev -# Chrome dependencies -apt-get install -yq libpangocairo-1.0-0 libXcomposite1 libXcursor1 libXdamage1 \ - libXi6 libXtst6 libnss3 libcups2 libgconf2-4 libXss1 libXrandr2 \ - libatk1.0-0 libasound2 libgtk-3-0 -# Trace collection dependencies -apt-get install -yq xvfb - -# Create a pythonapp user. The application will run as this user. -useradd -m -d /home/pythonapp pythonapp - -# pip from apt is out of date, so make it update itself and install virtualenv. -pip install --upgrade pip virtualenv - -# Download the Clovis deployment from Google Cloud Storage and unzip it. -# It is expected that the contents of the deployment have been generated using -# the tools/android/loading/cloud/backend/deploy.sh script. -CLOUD_STORAGE_PATH=`get_instance_metadata cloud-storage-path` -DEPLOYMENT_PATH=$CLOUD_STORAGE_PATH/deployment - -mkdir -p /opt/app/clovis -gsutil cp gs://$DEPLOYMENT_PATH/source/source.tgz /opt/app/clovis/source.tgz -tar xvf /opt/app/clovis/source.tgz -C /opt/app/clovis -rm /opt/app/clovis/source.tgz - -# Install app dependencies -virtualenv /opt/app/clovis/env -/opt/app/clovis/env/bin/pip install -r \ - /opt/app/clovis/src/tools/android/loading/cloud/backend/pip_requirements.txt - -mkdir /opt/app/clovis/binaries -gsutil cp gs://$DEPLOYMENT_PATH/binaries/* /opt/app/clovis/binaries/ -unzip /opt/app/clovis/binaries/linux.zip -d /opt/app/clovis/binaries/ - -# Ad and tracking filtering rules. -# Made by the EasyList authors (https://easylist.github.io/). -DATA_DIR=/opt/app/clovis/data -mkdir $DATA_DIR && cd $DATA_DIR -curl https://easylist.github.io/easylist/easylist.txt > easylist.txt -curl https://easylist.github.io/easylist/easyprivacy.txt > easyprivacy.txt - -# Install the Chrome sandbox -cp /opt/app/clovis/binaries/chrome_sandbox /usr/local/sbin/chrome-devel-sandbox -chown root:root /usr/local/sbin/chrome-devel-sandbox -chmod 4755 /usr/local/sbin/chrome-devel-sandbox - -# Make sure the pythonapp user owns the application code. -chown -R pythonapp:pythonapp /opt/app - -# Create the configuration file for this deployment. -DEPLOYMENT_CONFIG_PATH=/opt/app/clovis/deployment_config.json -TASKQUEUE_TAG=`get_instance_metadata taskqueue-tag` -TASK_DIR=`get_instance_metadata task-dir` -TASK_STORAGE_PATH=$CLOUD_STORAGE_PATH/$TASK_DIR -if [ "$(get_instance_metadata self-destruct)" == "false" ]; then - SELF_DESTRUCT="False" -else - SELF_DESTRUCT="True" -fi -WORKER_LOG_PATH=/opt/app/clovis/worker.log - -cat >$DEPLOYMENT_CONFIG_PATH << EOF -{ - "instance_name" : "$INSTANCE_NAME", - "project_name" : "$PROJECTID", - "task_storage_path" : "$TASK_STORAGE_PATH", - "binaries_path" : "/opt/app/clovis/binaries", - "src_path" : "/opt/app/clovis/src", - "taskqueue_tag" : "$TASKQUEUE_TAG", - "worker_log_path" : "$WORKER_LOG_PATH", - "self_destruct" : "$SELF_DESTRUCT", - "ad_rules_filename": "$DATA_DIR/easylist.txt", - "tracking_rules_filename": "$DATA_DIR/easyprivacy.txt" -} -EOF - -# Check if auto-start is enabled -AUTO_START=`get_instance_metadata auto-start` - -# Exit early if auto start is not enabled. -if [ "$AUTO_START" == "false" ]; then - exit 1 -fi - -# Configure supervisor to start the worker inside of our virtualenv. -cat >/etc/supervisor/conf.d/python-app.conf << EOF -[program:pythonapp] -directory=/opt/app/clovis/src/tools/android/loading/cloud/backend -command=python -u worker.py --config $DEPLOYMENT_CONFIG_PATH -autostart=true -autorestart=unexpected -user=pythonapp -# Environment variables ensure that the application runs inside of the -# configured virtualenv. -environment=VIRTUAL_ENV="/opt/app/clovis/env", \ - PATH="/opt/app/clovis/env/bin:/usr/bin", \ - HOME="/home/pythonapp",USER="pythonapp", \ - CHROME_DEVEL_SANDBOX="/usr/local/sbin/chrome-devel-sandbox" -stdout_logfile=$WORKER_LOG_PATH -stderr_logfile=$WORKER_LOG_PATH -EOF - -supervisorctl reread -supervisorctl update -
diff --git a/tools/android/loading/cloud/backend/trace_task_handler.py b/tools/android/loading/cloud/backend/trace_task_handler.py deleted file mode 100644 index e031636..0000000 --- a/tools/android/loading/cloud/backend/trace_task_handler.py +++ /dev/null
@@ -1,272 +0,0 @@ -# Copyright 2016 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. - -import os -import re -import sys -import traceback - -import clovis_constants -import common.clovis_paths -from common.clovis_task import ClovisTask -from common.loading_trace_database import LoadingTraceDatabase -import controller -from failure_database import FailureDatabase -import loading_trace -import multiprocessing_helper -import options -import xvfb_helper - - -def GenerateTrace(url, emulate_device, emulate_network, filename, log_filename): - """ Generates a trace. - - Args: - url: URL as a string. - emulate_device: Name of the device to emulate. Empty for no emulation. - emulate_network: Type of network emulation. Empty for no emulation. - filename: Name of the file where the trace is saved. - log_filename: Name of the file where standard output and errors are - logged. - - Returns: - A dictionary of metadata about the trace, including a 'succeeded' field - indicating whether the trace was successfully generated. - """ - try: - os.remove(filename) # Remove any existing trace for this URL. - except OSError: - pass # Nothing to remove. - - old_stdout = sys.stdout - old_stderr = sys.stderr - - trace_metadata = { 'succeeded' : False, 'url' : url } - trace = None - if not url.startswith('http') and not url.startswith('file'): - url = 'http://' + url - with open(log_filename, 'w') as sys.stdout: - try: - sys.stderr = sys.stdout - - sys.stdout.write('Starting trace generation for: %s.\n' % url) - - # Set up the controller. - chrome_ctl = controller.LocalChromeController() - chrome_ctl.SetChromeEnvOverride(xvfb_helper.GetChromeEnvironment()) - if emulate_device: - chrome_ctl.SetDeviceEmulation(emulate_device) - if emulate_network: - chrome_ctl.SetNetworkEmulation(emulate_network) - - # Record and write the trace. - with chrome_ctl.Open() as connection: - connection.ClearCache() - trace = loading_trace.LoadingTrace.RecordUrlNavigation( - url, connection, chrome_ctl.ChromeMetadata(), - clovis_constants.DEFAULT_CATEGORIES) - trace_metadata['succeeded'] = True - trace_metadata.update(trace.ToJsonDict()[trace._METADATA_KEY]) - sys.stdout.write('Trace generation success.\n') - except controller.ChromeControllerError as e: - e.Dump(sys.stderr) - except Exception as e: - sys.stderr.write('Unknown exception:\n' + str(e)) - traceback.print_exc(file=sys.stderr) - - if trace: - sys.stdout.write('Dumping trace to file.\n') - trace.ToJsonFile(filename) - else: - sys.stderr.write('No trace generated.\n') - - sys.stdout.write('Trace generation finished.\n') - - sys.stdout = old_stdout - sys.stderr = old_stderr - - return trace_metadata - - -class TraceTaskHandler(object): - """Handles 'trace' tasks.""" - - def __init__(self, base_path, failure_database, - google_storage_accessor, binaries_path, logger, - instance_name=None): - """Args: - base_path(str): Base path where results are written. - binaries_path(str): Path to the directory where Chrome executables are. - instance_name(str, optional): Name of the ComputeEngine instance. - """ - self._failure_database = failure_database - self._logger = logger - self._google_storage_accessor = google_storage_accessor - self._base_path = base_path - self._is_initialized = False - self._trace_database = None - self._xvfb_process = None - trace_database_filename = common.clovis_paths.TRACE_DATABASE_PREFIX - if instance_name: - trace_database_filename += '_%s.json' % instance_name - else: - trace_database_filename += '.json' - self._trace_database_path = os.path.join(base_path, trace_database_filename) - - # Initialize the global options that will be used during trace generation. - options.OPTIONS.ParseArgs(['--local_build_dir', binaries_path]) - - def _Initialize(self): - """Initializes the trace task handler. Can be called multiple times.""" - if self._is_initialized: - return - self._is_initialized = True - - self._xvfb_process = xvfb_helper.LaunchXvfb() - - # Recover any existing traces in case the worker died. - self._DownloadTraceDatabase() - if self._trace_database.ToJsonDict(): - # There are already files from a previous run in the directory, likely - # because the script is restarting after a crash. - self._failure_database.AddFailure(FailureDatabase.DIRTY_STATE_ERROR, - 'trace_database') - - def _DownloadTraceDatabase(self): - """Downloads the trace database from CloudStorage.""" - self._logger.info('Downloading trace database') - trace_database_string = self._google_storage_accessor.DownloadAsString( - self._trace_database_path) or '{}' - self._trace_database = LoadingTraceDatabase.FromJsonString( - trace_database_string) - - def _UploadTraceDatabase(self): - """Uploads the trace database to CloudStorage.""" - self._logger.info('Uploading trace database') - assert self._is_initialized - self._google_storage_accessor.UploadString( - self._trace_database.ToJsonString(), - self._trace_database_path) - - def _GenerateTraceOutOfProcess(self, url, emulate_device, emulate_network, - filename, log_filename): - """ Generates a trace in a separate process by calling GenerateTrace(). - - The generation is done out of process to avoid issues where the system would - run out of memory when the trace is very large. This ensures that the system - can reclaim all the memory when the trace generation is done. - - See the GenerateTrace() documentation for a description of the parameters - and return values. - """ - self._logger.info('Starting external process for trace generation.') - result = multiprocessing_helper.RunInSeparateProcess( - GenerateTrace, - (url, emulate_device, emulate_network, filename, log_filename), - self._logger, timeout_seconds=180, memory_share=0.9) - - self._logger.info('Cleaning up Chrome processes.') - controller.LocalChromeController.KillChromeProcesses() - - if not result: - self._failure_database.AddFailure('trace_process_timeout', url) - return {'succeeded':False, 'url':url} - return result - - - def _HandleTraceGenerationResults(self, local_filename, log_filename, - remote_filename, trace_metadata): - """Updates the trace database and the failure database after a trace - generation. Uploads the trace and the log. - Results related to successful traces are uploaded in the 'traces' directory, - and failures are uploaded in the 'failures' directory. - - Args: - local_filename (str): Path to the local file containing the trace. - log_filename (str): Path to the local file containing the log. - remote_filename (str): Name of the target remote file where the trace and - the log (with a .log extension added) are uploaded. - trace_metadata (dict): Metadata associated with the trace generation. - """ - assert self._is_initialized - if trace_metadata['succeeded']: - traces_dir = os.path.join(self._base_path, 'traces') - remote_trace_location = os.path.join(traces_dir, remote_filename) - full_cloud_storage_path = os.path.join( - 'gs://' + self._google_storage_accessor.BucketName(), - remote_trace_location) - self._trace_database.SetTrace(full_cloud_storage_path, trace_metadata) - else: - url = trace_metadata['url'] - self._logger.warning('Trace generation failed for URL: %s' % url) - failures_dir = os.path.join(self._base_path, 'failures') - remote_trace_location = os.path.join(failures_dir, remote_filename) - self._failure_database.AddFailure('trace_collection', url) - - if os.path.isfile(local_filename): - self._logger.debug('Uploading: %s' % remote_trace_location) - self._google_storage_accessor.UploadFile(local_filename, - remote_trace_location) - os.remove(local_filename) # The trace may be very large. - else: - self._logger.warning('No trace found at: ' + local_filename) - - if os.path.isfile(log_filename): - self._logger.debug('Uploading analyze log') - remote_log_location = remote_trace_location + '.log' - self._google_storage_accessor.UploadFile( - log_filename, remote_log_location) - else: - self._logger.warning('No log file found at: {}'.format(log_filename)) - - def Finalize(self): - """Called once before the handler is destroyed.""" - if self._xvfb_process: - try: - self._xvfb_process.terminate() - except OSError: - self._logger.error('Could not terminate Xvfb.') - - def Run(self, clovis_task): - """Runs a 'trace' clovis_task. - - Args: - clovis_task(ClovisTask): The task to run. - """ - if clovis_task.Action() != 'trace': - self._logger.error('Unsupported task action: %s' % clovis_task.Action()) - self._failure_database.AddFailure(FailureDatabase.CRITICAL_ERROR, - 'trace_task_handler_run') - return - - self._Initialize() - - # Extract the task parameters. - params = clovis_task.ActionParams() - urls = params['urls'] - repeat_count = params.get('repeat_count', 1) - emulate_device = params.get('emulate_device') - emulate_network = params.get('emulate_network') - - log_filename = 'analyze.log' - # Avoid special characters in storage object names - pattern = re.compile(r"[#\?\[\]\*/]") - - success_happened = False - - while len(urls) > 0: - url = urls.pop() - local_filename = pattern.sub('_', url) - for repeat in range(repeat_count): - self._logger.debug('Generating trace for URL: %s' % url) - trace_metadata = self._GenerateTraceOutOfProcess( - url, emulate_device, emulate_network, local_filename, log_filename) - if trace_metadata['succeeded']: - success_happened = True - remote_filename = os.path.join(local_filename, str(repeat)) - self._HandleTraceGenerationResults( - local_filename, log_filename, remote_filename, trace_metadata) - - if success_happened: - self._UploadTraceDatabase()
diff --git a/tools/android/loading/cloud/backend/worker.py b/tools/android/loading/cloud/backend/worker.py deleted file mode 100644 index 6b3a369..0000000 --- a/tools/android/loading/cloud/backend/worker.py +++ /dev/null
@@ -1,226 +0,0 @@ -# Copyright 2016 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. - -import argparse -import json -import logging -import os -import random -import sys -import time - -from googleapiclient import discovery -from oauth2client.client import GoogleCredentials - -# NOTE: The parent directory needs to be first in sys.path to avoid conflicts -# with catapult modules that have colliding names, as catapult inserts itself -# into the path as the second element. This is an ugly and fragile hack. -_CLOUD_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), - os.pardir) -sys.path.insert(0, os.path.join(_CLOUD_DIR, os.pardir)) -# Add _CLOUD_DIR to the path to access common code through the same path as the -# frontend. -sys.path.append(_CLOUD_DIR) - -from common.clovis_task import ClovisTask -import common.google_bigquery_helper -from common.google_instance_helper import GoogleInstanceHelper -from clovis_task_handler import ClovisTaskHandler -from failure_database import FailureDatabase -from google_storage_accessor import GoogleStorageAccessor - - -class Worker(object): - def __init__(self, config, logger): - """See README.md for the config format.""" - self._project_name = config['project_name'] - self._taskqueue_tag = config['taskqueue_tag'] - self._src_path = config['src_path'] - self._instance_name = config.get('instance_name') - self._worker_log_path = config.get('worker_log_path') - self._credentials = GoogleCredentials.get_application_default() - self._logger = logger - self._self_destruct = config.get('self_destruct') - if self._self_destruct and not self._instance_name: - self._logger.error('Self destruction requires an instance name.') - - # Separate the task storage path into the bucket and the base path under - # the bucket. - storage_path_components = config['task_storage_path'].split('/') - self._bucket_name = storage_path_components[0] - self._base_path_in_bucket = '' - if len(storage_path_components) > 1: - self._base_path_in_bucket = '/'.join(storage_path_components[1:]) - if not self._base_path_in_bucket.endswith('/'): - self._base_path_in_bucket += '/' - - self._google_storage_accessor = GoogleStorageAccessor( - credentials=self._credentials, project_name=self._project_name, - bucket_name=self._bucket_name) - - if self._instance_name: - failure_database_filename = \ - 'failure_database_%s.json' % self._instance_name - else: - failure_database_filename = 'failure_dabatase.json' - self._failure_database_path = os.path.join(self._base_path_in_bucket, - failure_database_filename) - - # Recover any existing failures in case the worker died. - self._failure_database = self._GetFailureDatabase() - - if self._failure_database.ToJsonDict(): - # Script is restarting after a crash, or there are already files from a - # previous run in the directory. - self._failure_database.AddFailure(FailureDatabase.DIRTY_STATE_ERROR, - 'failure_database') - - bigquery_service = common.google_bigquery_helper.GetBigQueryService( - self._credentials) - self._clovis_task_handler = ClovisTaskHandler( - self._project_name, self._base_path_in_bucket, self._failure_database, - self._google_storage_accessor, bigquery_service, - config['binaries_path'], config['ad_rules_filename'], - config['tracking_rules_filename'], self._logger, self._instance_name) - - self._UploadFailureDatabase() - - def Start(self): - """Main worker loop. - - Repeatedly pulls tasks from the task queue and processes them. Returns when - the queue is empty. - """ - task_api = discovery.build('taskqueue', 'v1beta2', - credentials=self._credentials) - queue_name = 'clovis-queue' - # Workaround for - # https://code.google.com/p/googleappengine/issues/detail?id=10199 - project = 's~' + self._project_name - - while True: - self._logger.debug('Fetching new task.') - (clovis_task, task_id) = self._FetchClovisTask(project, task_api, - queue_name) - if not clovis_task: - break - - self._logger.info('Processing task %s' % task_id) - self._clovis_task_handler.Run(clovis_task) - self._UploadFailureDatabase() - self._logger.debug('Deleting task %s' % task_id) - task_api.tasks().delete(project=project, taskqueue=queue_name, - task=task_id).execute() - self._logger.info('Finished task %s' % task_id) - self._Finalize() - - def _GetFailureDatabase(self): - """Downloads the failure database from CloudStorage.""" - self._logger.info('Downloading failure database') - failure_database_string = self._google_storage_accessor.DownloadAsString( - self._failure_database_path) - return FailureDatabase(failure_database_string) - - def _UploadFailureDatabase(self): - """Uploads the failure database to CloudStorage.""" - if not self._failure_database.is_dirty: - return - self._logger.info('Uploading failure database') - self._google_storage_accessor.UploadString( - self._failure_database.ToJsonString(), - self._failure_database_path) - self._failure_database.is_dirty = False - - def _FetchClovisTask(self, project_name, task_api, queue_name): - """Fetches a ClovisTask from the task queue. - - Params: - project_name(str): The name of the Google Cloud project. - task_api: The TaskQueue service. - queue_name(str): The name of the task queue. - - Returns: - (ClovisTask, str): The fetched ClovisTask and its task ID, or (None, None) - if no tasks are found. - """ - response = task_api.tasks().lease( - project=project_name, taskqueue=queue_name, numTasks=1, leaseSecs=600, - groupByTag=True, tag=self._taskqueue_tag).execute() - if (not response.get('items')) or (len(response['items']) < 1): - return (None, None) # The task queue is empty. - - google_task = response['items'][0] - task_id = google_task['id'] - - # Delete the task without processing if it already failed multiple times. - # TODO(droger): This is a workaround for internal bug b/28442122, revisit - # once it is fixed. - retry_count = google_task['retry_count'] - max_retry_count = 3 - skip_task = retry_count >= max_retry_count - if skip_task: - task_api.tasks().delete(project=project_name, taskqueue=queue_name, - task=task_id).execute() - - clovis_task = ClovisTask.FromBase64(google_task['payloadBase64']) - - if retry_count > 0: - self._failure_database.AddFailure('task_queue_retry', - clovis_task.ToJsonString()) - self._UploadFailureDatabase() - - if skip_task: - return self._FetchClovisTask(project_name, task_api, queue_name) - - return (clovis_task, task_id) - - def _Finalize(self): - """Called before exiting.""" - self._logger.info('Done') - self._clovis_task_handler.Finalize() - # Upload the worker log. - if self._worker_log_path: - self._logger.info('Uploading worker log.') - remote_log_path = os.path.join(self._base_path_in_bucket, 'worker_log') - if self._instance_name: - remote_log_path += '_' + self._instance_name - self._google_storage_accessor.UploadFile(self._worker_log_path, - remote_log_path) - # Self destruct. - if self._self_destruct: - # Workaround for ComputeEngine internal bug b/28760288. - random_delay = random.random() * 600.0 # Up to 10 minutes. - self._logger.info( - 'Wait %.0fs to avoid load spikes on compute engine.' % random_delay) - time.sleep(random_delay) - - self._logger.info('Starting instance destruction: ' + self._instance_name) - google_instance_helper = GoogleInstanceHelper( - self._credentials, self._project_name, self._logger) - success = google_instance_helper.DeleteInstance(self._taskqueue_tag, - self._instance_name) - if not success: - self._logger.error('Self destruction failed.') - # Do not add anything after this line, as the instance might be killed at - # any time. - -if __name__ == '__main__': - parser = argparse.ArgumentParser( - description='ComputeEngine Worker for Clovis') - parser.add_argument('--config', required=True, - help='Path to the configuration file.') - args = parser.parse_args() - - # Configure logging. - logging.basicConfig(level=logging.WARNING, - format='[%(asctime)s][%(levelname)s] %(message)s', - datefmt='%y-%m-%d %H:%M:%S') - logging.Formatter.converter = time.gmtime - worker_logger = logging.getLogger('worker') - worker_logger.setLevel(logging.INFO) - - worker_logger.info('Reading configuration') - with open(args.config) as config_json: - worker = Worker(json.load(config_json), worker_logger) - worker.Start()
diff --git a/tools/android/loading/cloud/common/__init__.py b/tools/android/loading/cloud/common/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/tools/android/loading/cloud/common/__init__.py +++ /dev/null
diff --git a/tools/android/loading/cloud/common/clovis_paths.py b/tools/android/loading/cloud/common/clovis_paths.py deleted file mode 100644 index 1ee10e4..0000000 --- a/tools/android/loading/cloud/common/clovis_paths.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2016 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. - -# Trace path constants. - -# Prefix for the loading trace database files. -TRACE_DATABASE_PREFIX = 'trace_database'
diff --git a/tools/android/loading/cloud/common/clovis_task.py b/tools/android/loading/cloud/common/clovis_task.py deleted file mode 100644 index 97c88a53..0000000 --- a/tools/android/loading/cloud/common/clovis_task.py +++ /dev/null
@@ -1,91 +0,0 @@ -# Copyright 2016 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. - -import base64 -import json -import uuid - -class ClovisTask(object): - """Generic task, generated by the AppEngine frontend and consumed by the - ComputeEngine backend. - """ - - def __init__(self, action, action_params, backend_params): - """ See tools/android/loading/cloud/frontend/README.md for a specification - of the parameters. - - Args: - action(str): Action accomplished by this task. - action_params(dict): Parameters of task. - backend_params(dict): Parameters of the instances running the task. - If this is None, no instances are created. If this dictionary has no - 'tag' key, a unique tag will be generated. - """ - self._action = action - self._action_params = action_params or {} - self._backend_params = backend_params or {} - # If no tag is specified, generate a unique tag. - if not self._backend_params.get('tag'): - self._backend_params.update({'tag': str(uuid.uuid1())}) - - @classmethod - def FromJsonDict(cls, json_dict): - """Loads a ClovisTask from a JSON dictionary. - - Returns: - ClovisTask: The task, or None if the string is invalid. - """ - try: - action = json_dict['action'] - action_params = json_dict['action_params'] - # Vaidate the format. - if action == 'trace': - urls = action_params['urls'] - if (type(urls) is not list) or (len(urls) == 0): - return None - elif action == 'report': - if not action_params.get('trace_bucket'): - return None - else: - # When more actions are supported, check that they are valid here. - return None - return cls(action, action_params, json_dict.get('backend_params')) - except Exception: - return None - - @classmethod - def FromJsonString(cls, json_string): - """Loads a ClovisTask from a JSON string. - - Returns: - ClovisTask: The task, or None if the string is invalid. - """ - try: - return cls.FromJsonDict(json.loads(json_string)) - except Exception: - return None - - @classmethod - def FromBase64(cls, base64_string): - """Loads a ClovisTask from a base 64 string.""" - return ClovisTask.FromJsonString(base64.b64decode(base64_string)) - - def ToJsonDict(self): - """Returns the JSON representation of the task as a dictionary.""" - return {'action': self._action, 'action_params': self._action_params, - 'backend_params': self._backend_params} - - def ToJsonString(self): - """Returns the JSON representation of the task as a string.""" - return json.dumps(self.ToJsonDict()) - - def Action(self): - return self._action - - def ActionParams(self): - return self._action_params - - def BackendParams(self): - return self._backend_params -
diff --git a/tools/android/loading/cloud/common/google_bigquery_helper.py b/tools/android/loading/cloud/common/google_bigquery_helper.py deleted file mode 100644 index 547c434..0000000 --- a/tools/android/loading/cloud/common/google_bigquery_helper.py +++ /dev/null
@@ -1,109 +0,0 @@ -# Copyright 2016 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. - -import os -import uuid - -from googleapiclient import (discovery, errors) - -import common.google_error_helper as google_error_helper - -# Name of the dataset. -BIGQUERY_DATASET = 'clovis_dataset' -# Name of the table used as a template for new tables. -BIGQUERY_TABLE_TEMPLATE = 'report' - - -def GetBigQueryService(credentials): - """Returns the BigQuery service.""" - return discovery.build('bigquery', 'v2', credentials=credentials) - - -def GetBigQueryTableID(clovis_report_task): - """Returns the ID of the BigQuery table associated with the task. - This ID is appended at the end of the table name. - - Args: - clovis_report_task: (ClovisTask) The task, must be a 'report' task. - - Returns: - str: The table ID. - """ - assert (clovis_report_task.Action() == 'report') - # Name the table after the last path component of the trace bucket. - trace_bucket = clovis_report_task.ActionParams()['trace_bucket'] - table_id = os.path.basename(os.path.normpath(trace_bucket)) - task_name = clovis_report_task.BackendParams().get('task_name') - if task_name is not None: - table_id += '_' + task_name - # BigQuery table names can contain only alpha numeric characters and - # underscores. - return ''.join(c for c in table_id if c.isalnum() or c == '_') - - -def GetBigQueryTableURL(project_name, table_id): - """Returns the full URL for the BigQuery table associated with table_id.""" - return 'https://bigquery.cloud.google.com/table/%s:%s.%s_%s' % ( - project_name, BIGQUERY_DATASET, BIGQUERY_TABLE_TEMPLATE, table_id) - - -def InsertInTemplatedBigQueryTable(bigquery_service, project_name, table_id, - rows, logger): - """Inserts rows in the BigQuery table corresponding to table_id. - Assumes that the BigQuery dataset and table template already exist. - - Args: - bigquery_service: The BigQuery service. - project_name: (str) Name of the Google Cloud project. - table_id: (str) table_id as returned by GetBigQueryTableID(). - rows: (list) Rows to insert in the table. - logger: (logging.Logger) The logger. - - Returns: - dict: The BigQuery service response. - """ - rows_data = [{'json': row, 'insertId': str(uuid.uuid4())} for row in rows] - body = {'rows': rows_data, 'templateSuffix':'_'+table_id} - logger.info('BigQuery API request:\n' + str(body)) - response = bigquery_service.tabledata().insertAll( - projectId=project_name, datasetId=BIGQUERY_DATASET, - tableId=BIGQUERY_TABLE_TEMPLATE, body=body).execute() - logger.info('BigQuery API response:\n' + str(response)) - return response - - -def DoesBigQueryTableExist(bigquery_service, project_name, table_id, logger): - """Returns wether the BigQuery table identified by table_id exists. - - Raises a HttpError exception if the call to BigQuery API fails. - - Args: - bigquery_service: The BigQuery service. - project_name: (str) Name of the Google Cloud project. - table_id: (str) table_id as returned by GetBigQueryTableID(). - - Returns: - bool: True if the table exists. - """ - table_name = BIGQUERY_TABLE_TEMPLATE + '_' + table_id - logger.info('Getting table information for %s.' % table_name) - try: - table = bigquery_service.tables().get(projectId=project_name, - datasetId=BIGQUERY_DATASET, - tableId=table_name).execute() - return bool(table) - - except errors.HttpError as http_error: - error_content = google_error_helper.GetErrorContent(http_error) - error_reason = google_error_helper.GetErrorReason(error_content) - if error_reason == google_error_helper.REASON_NOT_FOUND: - return False - else: - logger.error('BigQuery API error (reason: "%s"):\n%s' % ( - error_reason, http_error)) - if error_content: - logger.error('Error details:\n%s' % error_content) - raise # Re-raise the exception. - - return False
diff --git a/tools/android/loading/cloud/common/google_error_helper.py b/tools/android/loading/cloud/common/google_error_helper.py deleted file mode 100644 index eac968a..0000000 --- a/tools/android/loading/cloud/common/google_error_helper.py +++ /dev/null
@@ -1,33 +0,0 @@ -# Copyright 2016 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. - -"""Helper functions to manage errors returned by Google Compute APIs.""" - -import json - - -# Error reason returned by GetErrorReason() when a resource is not found. -REASON_NOT_FOUND = 'notFound' - - -def GetErrorContent(error): - """Returns the contents of an error returned by Google Compute APIs as a - dictionary or None. - """ - if not error.resp.get('content-type', '').startswith('application/json'): - return None - return json.loads(error.content) - - -def GetErrorReason(error_content): - """Returns the error reason as a string.""" - if not error_content: - return None - if (not error_content.get('error') or - not error_content['error'].get('errors')): - return None - error_list = error_content['error']['errors'] - if not error_list: - return None - return error_list[0].get('reason')
diff --git a/tools/android/loading/cloud/common/google_instance_helper.py b/tools/android/loading/cloud/common/google_instance_helper.py deleted file mode 100644 index e4199b51..0000000 --- a/tools/android/loading/cloud/common/google_instance_helper.py +++ /dev/null
@@ -1,210 +0,0 @@ -# Copyright 2016 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. - -import json -import time - -from googleapiclient import (discovery, errors) - -import common.google_error_helper as google_error_helper - - -class GoogleInstanceHelper(object): - """Helper class for the Google Compute API, allowing to manage groups of - instances more easily. Groups of instances are identified by a tag.""" - _COMPUTE_API_ROOT = 'https://www.googleapis.com/compute/v1/projects/' - - def __init__(self, credentials, project, logger): - self._compute_api = discovery.build('compute','v1', credentials=credentials) - self._project = project - self._project_api_url = self._COMPUTE_API_ROOT + project - self._region = 'europe-west1' - self._zone = 'europe-west1-c' - self._logger = logger - - def _ExecuteApiRequest(self, request, retry_count=3): - """ Executes a Compute API request and returns True on success. - - Returns: - (True, Response) in case of success, or (False, error_content) otherwise. - """ - self._logger.info('Compute API request:\n' + request.to_json()) - try: - response = request.execute() - self._logger.info('Compute API response:\n' + str(response)) - return (True, response) - except errors.HttpError as err: - error_content = google_error_helper.GetErrorContent(err) - error_reason = google_error_helper.GetErrorReason(error_content) - if error_reason == 'resourceNotReady' and retry_count > 0: - # Retry after a delay - delay_seconds = 1 - self._logger.info( - 'Resource not ready, retrying in %i seconds.' % delay_seconds) - time.sleep(delay_seconds) - return self._ExecuteApiRequest(request, retry_count - 1) - else: - self._logger.error('Compute API error (reason: "%s"):\n%s' % ( - error_reason, err)) - if error_content: - self._logger.error('Error details:\n%s' % error_content) - return (False, error_content) - - def _GetTemplateName(self, tag): - """Returns the name of the instance template associated with tag.""" - return 'template-' + tag - - def _GetInstanceGroupName(self, tag): - """Returns the name of the instance group associated with tag.""" - return 'group-' + tag - - def CreateTemplate(self, tag, bucket, task_dir): - """Creates an instance template for instances identified by tag. - - Args: - tag: (string) Tag associated to a task. - bucket: (string) Root bucket where the deployment is located. - task_dir: (string) Subdirectory of |bucket| where task data is read and - written. - - Returns: - boolean: True if successful. - """ - image_url = self._COMPUTE_API_ROOT + \ - 'ubuntu-os-cloud/global/images/ubuntu-1404-trusty-v20160406' - request_body = { - 'name': self._GetTemplateName(tag), - 'properties': { - 'machineType': 'n1-standard-1', - 'networkInterfaces': [{ - 'network': self._project_api_url + '/global/networks/default', - 'accessConfigs': [{ - 'name': 'external-IP', - 'type': 'ONE_TO_ONE_NAT' - }]}], - 'disks': [{ - 'type': 'PERSISTENT', - 'boot': True, - 'autoDelete': True, - 'mode': 'READ_WRITE', - 'initializeParams': {'sourceImage': image_url}}], - 'canIpForward': False, - 'scheduling': { - 'automaticRestart': True, - 'onHostMaintenance': 'MIGRATE', - 'preemptible': False}, - 'serviceAccounts': [{ - 'scopes': [ - 'https://www.googleapis.com/auth/cloud-platform', - 'https://www.googleapis.com/auth/cloud-taskqueue'], - 'email': 'default'}], - 'metadata': { 'items': [ - {'key': 'cloud-storage-path', - 'value': bucket}, - {'key': 'task-dir', - 'value': task_dir}, - {'key': 'startup-script-url', - 'value': 'gs://%s/deployment/startup-script.sh' % bucket}, - {'key': 'taskqueue-tag', 'value': tag}]}}} - request = self._compute_api.instanceTemplates().insert( - project=self._project, body=request_body) - return self._ExecuteApiRequest(request)[0] - - def DeleteTemplate(self, tag): - """Deletes the instance template associated with tag. Returns True if - successful. - """ - template_name = self._GetTemplateName(tag) - request = self._compute_api.instanceTemplates().delete( - project=self._project, instanceTemplate=template_name) - (success, result) = self._ExecuteApiRequest(request) - if success: - return True - if google_error_helper.GetErrorReason(result) == \ - google_error_helper.REASON_NOT_FOUND: - # The template does not exist, nothing to do. - self._logger.warning('Template not found: ' + template_name) - return True - return False - - def CreateInstances(self, tag, instance_count): - """Creates an instance group associated with tag. The instance template must - exist for this to succeed. Returns True if successful. - """ - template_url = '%s/global/instanceTemplates/%s' % ( - self._project_api_url, self._GetTemplateName(tag)) - request_body = { - 'zone': self._zone, 'targetSize': instance_count, - 'baseInstanceName': 'instance-' + tag, - 'instanceTemplate': template_url, - 'name': self._GetInstanceGroupName(tag)} - request = self._compute_api.instanceGroupManagers().insert( - project=self._project, zone=self._zone, - body=request_body) - return self._ExecuteApiRequest(request)[0] - - def DeleteInstance(self, tag, instance_hostname): - """Deletes one instance from the instance group identified by tag. Returns - True if successful. - """ - # The instance hostname may be of the form <name>.c.<project>.internal but - # only the <name> part should be passed to the compute API. - name = instance_hostname.split('.')[0] - instance_url = self._project_api_url + ( - "/zones/%s/instances/%s" % (self._zone, name)) - request = self._compute_api.instanceGroupManagers().deleteInstances( - project=self._project, zone=self._zone, - instanceGroupManager=self._GetInstanceGroupName(tag), - body={'instances': [instance_url]}) - return self._ExecuteApiRequest(request)[0] - - def DeleteInstanceGroup(self, tag): - """Deletes the instance group identified by tag. If instances are still - running in this group, they are deleted as well. - """ - group_name = self._GetInstanceGroupName(tag) - request = self._compute_api.instanceGroupManagers().delete( - project=self._project, zone=self._zone, - instanceGroupManager=group_name) - (success, result) = self._ExecuteApiRequest(request) - if success: - return True - if google_error_helper.GetErrorReason(result) == \ - google_error_helper.REASON_NOT_FOUND: - # The group does not exist, nothing to do. - self._logger.warning('Instance group not found: ' + group_name) - return True - return False - - def GetInstanceCount(self, tag): - """Returns the number of instances in the instance group identified by - tag, or -1 in case of failure. - """ - request = self._compute_api.instanceGroupManagers().listManagedInstances( - project=self._project, zone=self._zone, - instanceGroupManager=self._GetInstanceGroupName(tag)) - (success, response) = self._ExecuteApiRequest(request) - if not success: - return -1 - return len(response.get('managedInstances', [])) - - - def GetAvailableInstanceCount(self): - """Returns the number of instances that can be created, according to the - ComputeEngine quotas, or -1 on failure. - """ - request = self._compute_api.regions().get(project=self._project, - region=self._region) - (success, response) = self._ExecuteApiRequest(request) - if not success: - self._logger.error('Could not get ComputeEngine region information.') - return -1 - metric_name = 'IN_USE_ADDRESSES' - for quota in response.get('quotas', []): - if quota['metric'] == metric_name: - return quota['limit'] - quota['usage'] - self._logger.error( - metric_name + ' quota not found in ComputeEngine response.') - return -1 -
diff --git a/tools/android/loading/cloud/common/loading_trace_database.py b/tools/android/loading/cloud/common/loading_trace_database.py deleted file mode 100644 index f6e946a..0000000 --- a/tools/android/loading/cloud/common/loading_trace_database.py +++ /dev/null
@@ -1,57 +0,0 @@ -# Copyright 2016 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. - -"""Represents a database of on-disk traces.""" - -import json - - -class LoadingTraceDatabase(object): - def __init__(self, traces_dict): - """traces_dict is a dictionary mapping filenames of traces to metadata - about those traces.""" - self._traces_dict = traces_dict - - def SetTrace(self, filename, trace_dict): - """Sets a mapping from |filename| to |trace_dict| into the database. - If there is an existing mapping for filename, it is replaced. - """ - self._traces_dict[filename] = trace_dict - - def GetTraceFilesForURL(self, url): - """Given a URL, returns the set of filenames of traces that were generated - for this URL.""" - trace_files = [f for f in self._traces_dict.keys() - if self._traces_dict[f]["url"] == url] - return trace_files - - def ToJsonDict(self): - """Returns a dict representing this instance.""" - return self._traces_dict - - def ToJsonString(self): - """Returns a string representing this instance.""" - return json.dumps(self._traces_dict, indent=2) - - def ToJsonFile(self, json_path): - """Saves a json file representing this instance.""" - json_dict = self.ToJsonDict() - with open(json_path, 'w') as output_file: - json.dump(json_dict, output_file, indent=2) - - @classmethod - def FromJsonDict(cls, json_dict): - """Returns an instance from a dict returned by ToJsonDict().""" - return LoadingTraceDatabase(json_dict) - - @classmethod - def FromJsonString(cls, json_string): - """Returns an instance from a string returned by ToJsonString().""" - return LoadingTraceDatabase(json.loads(json_string)) - - @classmethod - def FromJsonFile(cls, json_path): - """Returns an instance from a json file saved by ToJsonFile().""" - with open(json_path) as input_file: - return cls.FromJsonDict(json.load(input_file))
diff --git a/tools/android/loading/cloud/common/loading_trace_database_unittest.py b/tools/android/loading/cloud/common/loading_trace_database_unittest.py deleted file mode 100644 index 72ffcba..0000000 --- a/tools/android/loading/cloud/common/loading_trace_database_unittest.py +++ /dev/null
@@ -1,45 +0,0 @@ -# Copyright 2016 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. - -import unittest - -from cloud.common.loading_trace_database import LoadingTraceDatabase - - -class LoadingTraceDatabaseUnittest(unittest.TestCase): - _JSON_DATABASE = { - "traces/trace1.json" : { "url" : "http://bar.html", }, - "traces/trace2.json" : { "url" : "http://bar.html", }, - "traces/trace3.json" : { "url" : "http://qux.html", }, - } - - def setUp(self): - self.database = LoadingTraceDatabase.FromJsonDict(self._JSON_DATABASE) - - def testGetTraceFilesForURL(self): - # Test a URL with no matching traces. - self.assertEqual( - self.database.GetTraceFilesForURL("http://foo.html"), - []) - - # Test a URL with matching traces. - self.assertEqual( - set(self.database.GetTraceFilesForURL("http://bar.html")), - set(["traces/trace1.json", "traces/trace2.json"])) - - def testSerialization(self): - self.assertEqual( - self._JSON_DATABASE, self.database.ToJsonDict()) - - def testSetTrace(self): - dummy_url = "http://dummy.com" - new_trace_file = "traces/new_trace.json" - self.assertEqual(self.database.GetTraceFilesForURL(dummy_url), []) - self.database.SetTrace(new_trace_file, {"url" : dummy_url}) - self.assertEqual(self.database.GetTraceFilesForURL(dummy_url), - [new_trace_file]) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/cloud/frontend/.gitignore b/tools/android/loading/cloud/frontend/.gitignore deleted file mode 100644 index c3af857..0000000 --- a/tools/android/loading/cloud/frontend/.gitignore +++ /dev/null
@@ -1 +0,0 @@ -lib/
diff --git a/tools/android/loading/cloud/frontend/README.md b/tools/android/loading/cloud/frontend/README.md deleted file mode 100644 index ec9b8d9..0000000 --- a/tools/android/loading/cloud/frontend/README.md +++ /dev/null
@@ -1,171 +0,0 @@ -# Appengine Frontend for Clovis - -[TOC] - -## Usage - -Visit the application URL in your browser, and upload a JSON dictionary with the -following keys: - -- `action` (string): the action to perform. Only `trace` and `report` are - supported. -- `action_params` (dictionary): the parameters associated to the action. - See below for more details. -- `backend_params` (dictionary): the parameters configuring the backend for - this task. See below for more details. - -### Parameters for `backend_params` - -- `storage_bucket` (string): Name of the storage bucket used by the backend - instances. Backend code and data must have been previously deployed to this - bucket using the `deploy.sh` [script][4]. -- `instance_count` (int, optional): Number of Compute Engine instances that - will be started for this task. If not specified, the number of instances is - determined automatically depending on the size of the task and the number - of available instances. -- `task_name` (string, opitonal): Name of the task, used to build the name of - the output directory. -- `tag` (string, optional): tag internally used to associate tasks to backend - ComputeEngine instances. This parameter should not be set in general, as it - is mostly exposed for development purposes. If this parameter is not - specified, a unique tag will be generated. -- `timeout_hours` (int, optional): if workers are still alive after this - delay, they will be forcibly killed, to avoid wasting Compute Engine - resources. If not specified, the timeout is determined automatically. - -### Parameters for the `trace` action - -The trace action takes a list of URLs as input and generates a list of traces by -running Chrome. - -- `urls` (list of strings): the list of URLs to process. -- `repeat_count` (integer, optional): the number of traces to be generated - for each URL. Defaults to 1. -- `emulate_device` (string, optional): the device to emulate (e.g. `Nexus 4`). -- `emulate_network` (string, optional): the network to emulate. - -### Parameters for the `report` action - -Finds all the traces in the specified bucket and generates a report in BigQuery. - -- `trace_bucket` (string): Name of the storage bucket where trace databases can - be found. It can be either absolute or relative to the `storage_bucket` - specified in the backend parameters. - -This requires an existing `clovis_dataset.report` BigQuery table that will be -used as a template. The schema of this template is not updated automatically and -must match the format of the report (as generated by `report.py`). -See [how to update the schema manually][7]. - -## Development - -### Design overview - -This is a [python AppEngine][5] application using [Flask][6]. - -- Appengine configuration: - - `app.yaml` defines the handlers. There is a static handler for all URLs - in the `static/` directory, and all other URLs are handled by the - `clovis_frontend.py` script. - - `queue.yaml` defines the task queues associated with the application. In - particular, the `clovis-queue` is a pull-queue where tasks are added by - the AppEngine frontend and consummed by the ComputeEngine backend. - See the [TaskQueue documentation][2] for more details. -- `templates/form.html` is a static HTML document allowing the user to upload - a JSON file. `clovis_frontend.py` is then invoked with the contents of the - file (see the `/form_sent` handler). -- `clovis_task.py` defines a task to be run by the backend. It is sent through - the `clovis-queue` task queue. -- `clovis_frontend.py` is the script that processes the file uploaded by the - form, creates the tasks and enqueues them in `clovis-queue`. - -### Prerequisites - -- Install the gcloud [tool][1] -- Add a `queue.yaml` file in the application directory (i.e. next to - `app.yaml`) defining a `clovis-queue` pull queue that can be accessed by the - ComputeEngine service worker associated to the project. Add your email too - if you want to run the application locally. See the [TaskQueue configuration - documentation][3] for more details. Example: - -``` -# queue.yaml -- name: clovis-queue - mode: pull - acl: - - user_email: me@address.com # For local development. - - user_email: 123456789-compute@developer.gserviceaccount.com -``` - -### Run Locally - -```shell -# Install dependencies in the lib/ directory. Note that this will pollute your -# Chromium checkout, see the cleanup intructions below. -pip install -r requirements.txt -t lib -# Start the local server. -dev_appserver.py -A $PROJECT_NAME . -``` - -Visit the application [http://localhost:8080](http://localhost:8080). - -After you are done, cleanup your Chromium checkout: - -```shell -rm -rf $CHROMIUM_SRC/tools/android/loading/frontend/lib -``` - -### Deploy - -```shell -# Install dependencies in the lib/ directory. -pip install -r requirements.txt -t lib -# Deploy. -gcloud preview app deploy app.yaml -``` - -To deploy to a staging/test version of the server, you can do: - -```shell -gcloud preview app deploy --no-promote --version $MY_VERSION -``` - -where `MY_VERSION` can be something like `staging` or something more unique to -ensure there is no name collision. You can then access the application live on -the web by prefixing the URL of the service with `$MY_VERSION-dot-`. - -### Updating the Database Schema - -When a change is made to the dictionary returned by report.py, the BigQuery -database schema must be updated accordingly. - -To update the schema, run: - -```shell -bq update \ - --schema \ - $CHROMIUM_SRC/tools/android/loading/cloud/frontend/bigquery_schema.json \ - -t clovis_dataset.report -``` - -Adding a new field is harmless, but don't modify existing ones. - -If the above command does not work, this is probably because you are doing more -than adding fields. -In this case, you can delete and recreate the `clovis_dataset.report` table from -the [BigQuery web interface][8]: -- Expand `clovis_dataset` from the left menu, and delete the `report` table. -- Create a new table in `clovis_dataset`, and call it `report`. -- Set `Location` to `None` in order to create an empty table. -- Click `Edit as Text` in the `Schema` section , and paste the contents of - `bigquery_schema.json` there. - - -[1]: https://cloud.google.com/sdk -[2]: https://cloud.google.com/appengine/docs/python/taskqueue -[3]: https://cloud.google.com/appengine/docs/python/config/queue -[4]: ../backend/README.md#Deploy-the-code -[5]: https://cloud.google.com/appengine/docs/python -[6]: http://flask.pocoo.org -[7]: #Updating-the-Database-Schema -[8]: https://bigquery.cloud.google.com
diff --git a/tools/android/loading/cloud/frontend/app.yaml b/tools/android/loading/cloud/frontend/app.yaml deleted file mode 100644 index 48bf775..0000000 --- a/tools/android/loading/cloud/frontend/app.yaml +++ /dev/null
@@ -1,25 +0,0 @@ -runtime: python27 -api_version: 1 -threadsafe: yes -instance_class: F4_1G - -builtins: -- deferred: on - -handlers: - -- url: /_ah/queue/deferred - # For the deferred API (https://cloud.google.com/appengine/articles/deferred). - script: google.appengine.ext.deferred.deferred.application - login: admin - -- url: /static - # Static content. - static_dir: static - -- url: .* - script: clovis_frontend.app - -libraries: -- name: ssl - version: latest
diff --git a/tools/android/loading/cloud/frontend/appengine_config.py b/tools/android/loading/cloud/frontend/appengine_config.py deleted file mode 100644 index 608cd73..0000000 --- a/tools/android/loading/cloud/frontend/appengine_config.py +++ /dev/null
@@ -1,6 +0,0 @@ -# Copyright 2016 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. - -from google.appengine.ext import vendor -vendor.add('lib')
diff --git a/tools/android/loading/cloud/frontend/bigquery_schema.json b/tools/android/loading/cloud/frontend/bigquery_schema.json deleted file mode 100644 index 254e475..0000000 --- a/tools/android/loading/cloud/frontend/bigquery_schema.json +++ /dev/null
@@ -1,275 +0,0 @@ -[ - { - "name": "url", - "type": "STRING", - "mode": "REQUIRED" - }, - { - "name": "ad_or_tracking_initiated_requests", - "type": "INTEGER" - }, - { - "name": "ad_or_tracking_initiated_transfer_size", - "type": "INTEGER" - }, - { - "name": "ad_or_tracking_parsing_frac", - "type": "FLOAT" - }, - { - "name": "ad_or_tracking_requests", - "type": "INTEGER" - }, - { - "name": "ad_or_tracking_script_frac", - "type": "FLOAT" - }, - { - "name": "ad_requests", - "type": "INTEGER" - }, - { - "name": "connection_cost_ms", - "type": "FLOAT" - }, - { - "name": "connections", - "type": "INTEGER" - }, - { - "name": "contentful_activity_frac", - "type": "FLOAT" - }, - { - "name": "contentful_byte_frac", - "type": "FLOAT" - }, - { - "name": "contentful_inversion", - "type": "STRING" - }, - { - "name": "contentful_ms", - "type": "FLOAT" - }, - { - "name": "contentful_parsing_frac", - "type": "FLOAT" - }, - { - "name": "contentful_predicted_no_state_prefetch_ms", - "type": "FLOAT" - }, - { - "name": "contentful_preloaded_requests", - "type": "INTEGER" - }, - { - "name": "contentful_preloaded_requests_cost", - "type": "FLOAT" - }, - { - "name": "contentful_requests", - "type": "INTEGER" - }, - { - "name": "contentful_requests_cost", - "type": "FLOAT" - }, - { - "name": "contentful_script_frac", - "type": "FLOAT" - }, - { - "name": "data_requests", - "type": "INTEGER" - }, - { - "name": "dns_cost_ms", - "type": "FLOAT" - }, - { - "name": "dns_requests", - "type": "INTEGER" - }, - { - "name": "domains", - "type": "INTEGER" - }, - { - "name": "first_text_activity_frac", - "type": "FLOAT" - }, - { - "name": "first_text_byte_frac", - "type": "FLOAT" - }, - { - "name": "first_text_inversion", - "type": "STRING" - }, - { - "name": "first_text_ms", - "type": "FLOAT" - }, - { - "name": "first_text_parsing_frac", - "type": "FLOAT" - }, - { - "name": "first_text_predicted_no_state_prefetch_ms", - "type": "FLOAT" - }, - { - "name": "first_text_preloaded_requests", - "type": "INTEGER" - }, - { - "name": "first_text_preloaded_requests_cost", - "type": "FLOAT" - }, - { - "name": "first_text_requests", - "type": "INTEGER" - }, - { - "name": "first_text_requests_cost", - "type": "FLOAT" - }, - { - "name": "first_text_script_frac", - "type": "FLOAT" - }, - { - "name": "h2_requests", - "type": "INTEGER" - }, - { - "name": "http11_requests", - "type": "INTEGER" - }, - { - "name": "plt_activity_frac", - "type": "FLOAT" - }, - { - "name": "plt_byte_frac", - "type": "FLOAT" - }, - { - "name": "plt_inversion", - "type": "STRING" - }, - { - "name": "plt_ms", - "type": "FLOAT" - }, - { - "name": "plt_parsing_frac", - "type": "FLOAT" - }, - { - "name": "plt_predicted_no_state_prefetch_ms", - "type": "FLOAT" - }, - { - "name": "plt_preloaded_requests", - "type": "INTEGER" - }, - { - "name": "plt_preloaded_requests_cost", - "type": "FLOAT" - }, - { - "name": "plt_requests", - "type": "INTEGER" - }, - { - "name": "plt_requests_cost", - "type": "FLOAT" - }, - { - "name": "plt_script_frac", - "type": "FLOAT" - }, - { - "name": "significant_activity_frac", - "type": "FLOAT" - }, - { - "name": "significant_byte_frac", - "type": "FLOAT" - }, - { - "name": "significant_inversion", - "type": "STRING" - }, - { - "name": "significant_ms", - "type": "FLOAT" - }, - { - "name": "significant_parsing_frac", - "type": "FLOAT" - }, - { - "name": "significant_predicted_no_state_prefetch_ms", - "type": "FLOAT" - }, - { - "name": "significant_preloaded_requests", - "type": "INTEGER" - }, - { - "name": "significant_preloaded_requests_cost", - "type": "FLOAT" - }, - { - "name": "significant_requests", - "type": "INTEGER" - }, - { - "name": "significant_requests_cost", - "type": "FLOAT" - }, - { - "name": "significant_script_frac", - "type": "FLOAT" - }, - { - "name": "ssl_connections", - "type": "INTEGER" - }, - { - "name": "ssl_cost_ms", - "type": "FLOAT" - }, - { - "name": "tracking_requests", - "type": "INTEGER" - }, - { - "name": "transfer_size", - "type": "INTEGER" - }, - { - "name": "total_queuing_blocked_msec", - "type": "FLOAT" - }, - { - "name": "total_queuing_load_msec", - "type": "FLOAT" - }, - { - "name": "average_blocking_request_count", - "type": "FLOAT" - }, - { - "name": "median_blocking_request_count", - "type": "FLOAT" - }, - { - "name": "total_requests", - "type": "INTEGER" - } -]
diff --git a/tools/android/loading/cloud/frontend/clovis_frontend.py b/tools/android/loading/cloud/frontend/clovis_frontend.py deleted file mode 100644 index 675e2af..0000000 --- a/tools/android/loading/cloud/frontend/clovis_frontend.py +++ /dev/null
@@ -1,604 +0,0 @@ -# Copyright 2016 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. - -import logging -import datetime -import math -import os -import sys -import time -import traceback - -import cloudstorage -import flask -from google.appengine.api import (app_identity, taskqueue) -from google.appengine.ext import deferred -from oauth2client.client import GoogleCredentials - -import common.clovis_paths -from common.clovis_task import ClovisTask -import common.google_bigquery_helper -import common.google_instance_helper -from common.loading_trace_database import LoadingTraceDatabase -import email_helper -from frontend_job import FrontendJob -from memory_logs import MemoryLogs - - -# Global variables. -logging.Formatter.converter = time.gmtime -clovis_logger = logging.getLogger('clovis_frontend') -clovis_logger.setLevel(logging.DEBUG) -project_name = app_identity.get_application_id() -instance_helper = common.google_instance_helper.GoogleInstanceHelper( - credentials=GoogleCredentials.get_application_default(), - project=project_name, - logger=clovis_logger) -app = flask.Flask(__name__) - - -def RenderJobCreationPage(message, memory_logs=None): - """Renders the log.html template. - - Args: - message (str): Main content of the page. - memory_logs (MemoryLogs): Optional logs. - """ - log = None - if memory_logs: - log = memory_logs.Flush().split('\n') - return flask.render_template('log.html', body=message, log=log, - title='Job Creation Status') - - -def PollWorkers(tag, start_time, timeout_hours, email_address, task_url): - """Checks if there are workers associated with tag, by polling the instance - group. When all workers are finished, the instance group and the instance - template are destroyed. - After some timeout delay, the instance group is destroyed even if there are - still workers associated to it, which has the effect of killing all these - workers. - - Args: - tag (string): Tag of the task that is polled. - start_time (float): Time when the polling started, as returned by - time.time(). - timeout_hours (int): Timeout after which workers are terminated. - email_address (str): Email address to notify when the task is complete. - task_url (str): URL where the results of the task can be found. - """ - if (time.time() - start_time) > (3600 * timeout_hours): - clovis_logger.error('Worker timeout for tag %s, shuting down.' % tag) - Finalize(tag, email_address, 'TIMEOUT', task_url) - return - - clovis_logger.info('Polling workers for tag: ' + tag) - live_instance_count = instance_helper.GetInstanceCount(tag) - clovis_logger.info('%i live instances for tag %s.' % ( - live_instance_count, tag)) - - if live_instance_count > 0 or live_instance_count == -1: - clovis_logger.info('Retry later, instances still alive for tag: ' + tag) - poll_interval_minutes = 10 - deferred.defer(PollWorkers, tag, start_time, timeout_hours, email_address, - task_url, _countdown=(60 * poll_interval_minutes)) - return - - Finalize(tag, email_address, 'SUCCESS', task_url) - - -def Finalize(tag, email_address, status, task_url): - """Cleans up the remaining ComputeEngine resources and notifies the user. - - Args: - tag (str): Tag of the task to finalize. - email_address (str): Email address of the user to be notified. - status (str): Status of the task, indicating the success or the cause of - failure. - task_url (str): URL where the results of the task can be found. - """ - email_helper.SendEmailTaskComplete( - to_address=email_address, tag=tag, status=status, task_url=task_url, - logger=clovis_logger) - clovis_logger.info('Scheduling instance group destruction for tag: ' + tag) - deferred.defer(DeleteInstanceGroup, tag) - FrontendJob.DeleteForTag(tag) - - -def GetEstimatedTaskDurationInSeconds(task): - """Returns an estimation of the time required to run the task. - - Args: - task: (ClovisTask) The task. - - Returns: - float: Time estimation in seconds, or -1 in case of failure. - """ - action_params = task.ActionParams() - if task.Action() == 'trace': - estimated_trace_time_s = 40.0 - return (len(action_params['urls']) * action_params.get('repeat_count', 1) * - estimated_trace_time_s) - elif task.Action() == 'report': - estimated_report_time_s = 20.0 - return len(action_params['traces']) * estimated_report_time_s - else: - clovis_logger.error('Unexpected action.') - return -1 - - -def CreateInstanceTemplate(task, task_dir): - """Create the Compute Engine instance template that will be used to create the - instances. - """ - backend_params = task.BackendParams() - instance_count = backend_params.get('instance_count', 0) - if instance_count <= 0: - clovis_logger.info('No template required.') - return True - bucket = backend_params.get('storage_bucket') - if not bucket: - clovis_logger.error('Missing bucket in backend_params.') - return False - return instance_helper.CreateTemplate(task.BackendParams()['tag'], bucket, - task_dir) - - -def CreateInstances(task): - """Creates the Compute engine requested by the task.""" - backend_params = task.BackendParams() - instance_count = backend_params.get('instance_count', 0) - if instance_count <= 0: - clovis_logger.info('No instances to create.') - return True - return instance_helper.CreateInstances(backend_params['tag'], instance_count) - - -def DeleteInstanceGroup(tag, try_count=0): - """Deletes the instance group associated with tag, and schedules the deletion - of the instance template.""" - clovis_logger.info('Instance group destruction for tag: ' + tag) - if not instance_helper.DeleteInstanceGroup(tag): - clovis_logger.info('Instance group destruction failed for: ' + tag) - if try_count <= 5: - deferred.defer(DeleteInstanceGroup, tag, try_count + 1, _countdown=60) - return - clovis_logger.error('Giving up group destruction for: ' + tag) - clovis_logger.info('Scheduling instance template destruction for tag: ' + tag) - # Wait a little before deleting the instance template, because it may still be - # considered in use, causing failures. - deferred.defer(DeleteInstanceTemplate, tag, _countdown=30) - - -def DeleteInstanceTemplate(tag, try_count=0): - """Deletes the instance template associated with tag.""" - clovis_logger.info('Instance template destruction for tag: ' + tag) - if not instance_helper.DeleteTemplate(tag): - clovis_logger.info('Instance template destruction failed for: ' + tag) - if try_count <= 5: - deferred.defer(DeleteInstanceTemplate, tag, try_count + 1, _countdown=60) - return - clovis_logger.error('Giving up template destruction for: ' + tag) - clovis_logger.info('Cleanup complete for tag: ' + tag) - - -def SplitClovisTask(task): - """Splits a ClovisTask in smaller ClovisTasks. - - Args: - task: (ClovisTask) The task to split. - - Returns: - list: The list of ClovisTasks. - """ - # For report task, need to find the traces first. - if task.Action() == 'report': - trace_bucket = task.ActionParams().get('trace_bucket') - if not trace_bucket: - clovis_logger.error('Missing trace bucket for report task.') - return None - - # Allow passing the trace bucket as absolute or relative to the base bucket. - base_bucket = task.BackendParams().get('storage_bucket', '') - if not trace_bucket.startswith(base_bucket): - trace_bucket = os.path.join(base_bucket, trace_bucket) - - traces = GetTracePaths(trace_bucket) - if not traces: - clovis_logger.error('No traces found in bucket: ' + trace_bucket) - return None - task.ActionParams()['traces'] = traces - - # Compute the split key. - # Keep the tasks small, but large enough to avoid "rate exceeded" errors when - # pulling them from the TaskQueue. - split_params_for_action = {'trace': ('urls', 3), 'report': ('traces', 5)} - (split_key, slice_size) = split_params_for_action.get(task.Action(), - (None, 0)) - if not split_key: - clovis_logger.error('Cannot split task with action: ' + task.Action()) - return None - - # Split the task using the split key. - clovis_logger.debug('Splitting task by: ' + split_key) - action_params = task.ActionParams() - values = action_params[split_key] - sub_tasks = [] - for i in range(0, len(values), slice_size): - sub_task_params = action_params.copy() - sub_task_params[split_key] = [v for v in values[i:i+slice_size]] - sub_tasks.append(ClovisTask(task.Action(), sub_task_params, - task.BackendParams())) - return sub_tasks - - -def GetTracePaths(bucket): - """Returns a list of trace files in a bucket. - - Finds and loads the trace databases, and returns their content as a list of - paths. - - This function assumes a specific structure for the files in the bucket. These - assumptions must match the behavior of the backend: - - The trace databases are located in the bucket. - - The trace databases files are the only objects with the - TRACE_DATABASE_PREFIX prefix in their name. - - Returns: - list: The list of paths to traces, as strings. - """ - traces = [] - prefix = os.path.join('/', bucket, common.clovis_paths.TRACE_DATABASE_PREFIX) - file_stats = cloudstorage.listbucket(prefix) - - for file_stat in file_stats: - database_file = file_stat.filename - clovis_logger.info('Loading trace database: ' + database_file) - - with cloudstorage.open(database_file) as remote_file: - json_string = remote_file.read() - if not json_string: - clovis_logger.warning('Failed to download: ' + database_file) - continue - - database = LoadingTraceDatabase.FromJsonString(json_string) - if not database: - clovis_logger.warning('Failed to parse: ' + database_file) - continue - - for path in database.ToJsonDict(): - traces.append(path) - - return traces - - -def GetTaskURL(task, task_dir): - """Returns the URL where the task output are generated, or None. - - Args: - task: (ClovisTask) The task. - task_dir: (str) Working directory for the backend, it is a subdirectory of - the deployment bucket. - - Returns: - str: The URL. - """ - clovis_logger.info('Building task result URL.') - - if task.Action() == 'trace': - storage_bucket = task.BackendParams().get('storage_bucket') - if not storage_bucket: - clovis_logger.error('Missing storage_bucket for trace action.') - return None - return 'https://console.cloud.google.com/storage/%s/%s' % (storage_bucket, - task_dir) - - elif task.Action() == 'report': - table_id = common.google_bigquery_helper.GetBigQueryTableID(task) - task_url = common.google_bigquery_helper.GetBigQueryTableURL(project_name, - table_id) - # Abort if the table already exists. - bigquery_service = common.google_bigquery_helper.GetBigQueryService( - GoogleCredentials.get_application_default()) - try: - table_exists = common.google_bigquery_helper.DoesBigQueryTableExist( - bigquery_service, project_name, table_id, clovis_logger) - except Exception: - return None - if table_exists: - clovis_logger.error('BigQuery table %s already exists.' % task_url) - return None - return task_url - - else: - clovis_logger.error('Unsupported action: %s.' % task.Action()) - return None - - -def StartFromJsonString(http_body_str): - """Main function handling a JSON task posted by the user.""" - # Set up logging. - memory_logs = MemoryLogs(clovis_logger) - memory_logs.Start() - - # Load the task from JSON. - task = ClovisTask.FromJsonString(http_body_str) - if not task: - clovis_logger.error('Invalid JSON task.') - return RenderJobCreationPage( - 'Invalid JSON task:\n' + http_body_str, memory_logs) - - task_tag = task.BackendParams()['tag'] - clovis_logger.info('Start processing %s task with tag %s.' % (task.Action(), - task_tag)) - user_email = email_helper.GetUserEmail() - - # Write the job to the datastore. - frontend_job = FrontendJob.CreateForTag(task_tag) - frontend_job.email = user_email - frontend_job.status = 'not_started' - frontend_job.clovis_task = task.ToJsonString() - frontend_job.put() - - # Process the job on the queue, to avoid timeout issues. - deferred.defer(SpawnTasksOnBackgroundQueue, task_tag) - - return RenderJobCreationPage( - flask.Markup( - '<a href="%s">See progress.</a>' % FrontendJob.GetJobURL(task_tag)), - memory_logs) - - -def SpawnTasksOnBackgroundQueue(task_tag): - """Spawns Clovis tasks associated with task_tag from the backgound queue. - - This function is mostly a wrapper around SpawnTasks() that catches exceptions. - It is assumed that a FrontendJob for task_tag exists. - """ - memory_logs = MemoryLogs(clovis_logger) - memory_logs.Start() - clovis_logger.info('Spawning tasks on background queue.') - - try: - frontend_job = FrontendJob.GetFromTag(task_tag) - frontend_job.status = 'will_start' - SpawnTasks(frontend_job) - except Exception as e: - clovis_logger.error('Exception spawning tasks: ' + str(e)) - clovis_logger.error(traceback.print_exc()) - - # Update the task. - if frontend_job: - frontend_job.log = memory_logs.Flush() - frontend_job.put() - - -def SpawnTasks(frontend_job): - """ Spawns Clovis tasks associated with the frontend job.""" - user_email = frontend_job.email - task = ClovisTask.FromJsonString(frontend_job.clovis_task) - task_tag = task.BackendParams()['tag'] - - # Delete the clovis task from the FrontendJob because it can make the object - # very heavy and it is no longer needed. - frontend_job.clovis_task = None - - # Compute the task directory. - frontend_job.status = 'building_task_dir' - task_dir_components = [] - user_name = None - if user_email: - user_name = user_email[:user_email.find('@')] - if user_name: - task_dir_components.append(user_name) - task_name = task.BackendParams().get('task_name') - if task_name: - task_dir_components.append(task_name) - task_dir_components.append(task_tag) - task_dir = os.path.join(task.Action(), '_'.join(task_dir_components)) - - # Build the URL where the result will live. - frontend_job.status = 'building_task_url' - task_url = GetTaskURL(task, task_dir) - if task_url: - clovis_logger.info('Task result URL: ' + task_url) - frontend_job.task_url = task_url - else: - frontend_job.status = 'task_url_error' - return - - # Split the task in smaller tasks. - frontend_job.status = 'splitting_task' - frontend_job.put() - sub_tasks = SplitClovisTask(task) - if not sub_tasks: - frontend_job.status = 'task_split_error' - return - - # Compute estimates for the work duration, in order to compute the instance - # count and the timeout. - frontend_job.status = 'estimating_duration' - sequential_duration_s = \ - GetEstimatedTaskDurationInSeconds(sub_tasks[0]) * len(sub_tasks) - if sequential_duration_s <= 0: - frontend_job.status = 'time_estimation_error' - return - - # Compute the number of required instances if not specified. - if task.BackendParams().get('instance_count') is None: - frontend_job.status = 'estimating_instance_count' - target_parallel_duration_s = 1800.0 # 30 minutes. - task.BackendParams()['instance_count'] = math.ceil( - sequential_duration_s / target_parallel_duration_s) - - # Check the instance quotas. - clovis_logger.info( - 'Requesting %i instances.' % task.BackendParams()['instance_count']) - frontend_job.status = 'checking_instance_quotas' - max_instances = instance_helper.GetAvailableInstanceCount() - if max_instances == -1: - frontend_job.status = 'instance_count_error' - return - elif max_instances == 0 and task.BackendParams()['instance_count'] > 0: - frontend_job.status = 'no_instance_available_error' - return - elif max_instances < task.BackendParams()['instance_count']: - clovis_logger.warning( - 'Instance count limited by quota: %i available / %i requested.' % ( - max_instances, task.BackendParams()['instance_count'])) - task.BackendParams()['instance_count'] = max_instances - - # Compute the timeout if there is none specified. - expected_duration_s = sequential_duration_s / ( - task.BackendParams()['instance_count']) - frontend_job.eta = datetime.datetime.now() + datetime.timedelta( - seconds=expected_duration_s) - if not task.BackendParams().get('timeout_hours'): - # Timeout is at least 1 hour. - task.BackendParams()['timeout_hours'] = max( - 1, 5 * expected_duration_s / 3600.0) - clovis_logger.info( - 'Timeout delay: %.1f hours. ' % task.BackendParams()['timeout_hours']) - - frontend_job.status = 'queueing_tasks' - if not EnqueueTasks(sub_tasks, task_tag): - frontend_job.status = 'task_creation_error' - return - - # Start polling the progress. - clovis_logger.info('Creating worker polling task.') - first_poll_delay_minutes = 10 - deferred.defer(PollWorkers, task_tag, time.time(), - task.BackendParams()['timeout_hours'], user_email, - task_url, _countdown=(60 * first_poll_delay_minutes)) - - # Start the instances if required. - frontend_job.status = 'creating_instances' - frontend_job.put() - if not CreateInstanceTemplate(task, task_dir): - frontend_job.status = 'instance_template_error' - return - if not CreateInstances(task): - frontend_job.status = 'instance_creation_error' - return - - frontend_job.status = 'started' - -def EnqueueTasks(tasks, task_tag): - """Enqueues a list of tasks in the Google Cloud task queue, for consumption by - Google Compute Engine. - """ - q = taskqueue.Queue('clovis-queue') - # Add tasks to the queue by groups. - # TODO(droger): This supports thousands of tasks, but maybe not millions. - # Defer the enqueuing if it times out. - group_size = 100 - callbacks = [] - try: - for i in range(0, len(tasks), group_size): - group = tasks[i:i+group_size] - taskqueue_tasks = [ - taskqueue.Task(payload=task.ToJsonString(), method='PULL', - tag=task_tag) - for task in group] - rpc = taskqueue.create_rpc() - q.add_async(task=taskqueue_tasks, rpc=rpc) - callbacks.append(rpc) - for callback in callbacks: - callback.get_result() - except Exception as e: - clovis_logger.error('Exception:' + type(e).__name__ + ' ' + str(e.args)) - return False - clovis_logger.info('Pushed %i tasks with tag: %s.' % (len(tasks), task_tag)) - return True - - -@app.route('/') -def Root(): - """Home page: show the new task form.""" - return flask.render_template('form.html') - - -@app.route('/form_sent', methods=['POST']) -def StartFromForm(): - """HTML form endpoint.""" - data_stream = flask.request.files.get('json_task') - if not data_stream: - return RenderJobCreationPage('Failed, no content.') - http_body_str = data_stream.read() - return StartFromJsonString(http_body_str) - - -@app.route('/kill_job') -def KillJob(): - tag = flask.request.args.get('tag') - page_title = 'Kill Job' - if not tag: - return flask.render_template('log.html', body='Failed: Invalid tag.', - title=page_title) - - frontend_job = FrontendJob.GetFromTag(tag) - - if not frontend_job: - return flask.render_template('log.html', body='Job not found.', - title=page_title) - Finalize(tag, frontend_job.email, 'CANCELED', frontend_job.task_url) - - body = 'Killed job %s.' % tag - return flask.render_template('log.html', body=body, title=page_title) - - -@app.route('/list_jobs') -def ShowJobList(): - """Shows a list of all active jobs.""" - tags = FrontendJob.ListJobs() - page_title = 'Active Jobs' - - if not tags: - return flask.render_template('log.html', body='No active job.', - title=page_title) - - html = '' - for tag in tags: - html += flask.Markup( - '<li><a href="%s">%s</a></li>') % (FrontendJob.GetJobURL(tag), tag) - html += flask.Markup('</ul>') - return flask.render_template('log.html', body=html, title=page_title) - - -@app.route(FrontendJob.SHOW_JOB_URL) -def ShowJob(): - """Shows basic information abour a job.""" - tag = flask.request.args.get('tag') - page_title = 'Job Information' - if not tag: - return flask.render_template('log.html', body='Invalid tag.', - title=page_title) - - frontend_job = FrontendJob.GetFromTag(tag) - - if not frontend_job: - return flask.render_template('log.html', body='Job not found.', - title=page_title) - - log = None - if frontend_job.log: - log = frontend_job.log.split('\n') - - body = flask.Markup(frontend_job.RenderAsHtml()) - body += flask.Markup('<a href="/kill_job?tag=%s">Kill</a>' % tag) - return flask.render_template('log.html', log=log, title=page_title, - body=body) - - -@app.errorhandler(404) -def PageNotFound(e): # pylint: disable=unused-argument - """Return a custom 404 error.""" - return 'Sorry, Nothing at this URL.', 404 - - -@app.errorhandler(500) -def ApplicationError(e): - """Return a custom 500 error.""" - return 'Sorry, unexpected error: {}'.format(e), 499
diff --git a/tools/android/loading/cloud/frontend/common b/tools/android/loading/cloud/frontend/common deleted file mode 120000 index 60d3b0a..0000000 --- a/tools/android/loading/cloud/frontend/common +++ /dev/null
@@ -1 +0,0 @@ -../common \ No newline at end of file
diff --git a/tools/android/loading/cloud/frontend/email_helper.py b/tools/android/loading/cloud/frontend/email_helper.py deleted file mode 100644 index dd82ee7..0000000 --- a/tools/android/loading/cloud/frontend/email_helper.py +++ /dev/null
@@ -1,42 +0,0 @@ -# Copyright 2016 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. - -from google.appengine.api import (mail, users) - - -def GetUserEmail(): - """Returns the email address of the user currently making the request or None. - """ - user = users.get_current_user() - if user: - return user.email() - return None - - -def SendEmailTaskComplete(to_address, tag, status, task_url, logger): - """Sends an email to to_address notifying that the task identified by tag is - complete. - - Args: - to_address (str): The email address to notify. - tag (str): The tag of the task. - status (str): Status of the task. - task_url (str): URL where the results of the task can be found. - logger (logging.logger): Used for logging. - """ - if not to_address: - logger.error('No email address to notify for task ' + tag) - return - - logger.info('Notify task %s complete to %s.' % (tag, to_address)) - # The sender address must be in the "Email API authorized senders", configured - # in the Application Settings of AppEngine. - sender_address = 'clovis-noreply@google.com' - subject = 'Task %s complete' % tag - body = 'Your Clovis task %s is now complete with status: %s.' % (tag, status) - if task_url: - body += '\nCheck the results at ' + task_url - mail.send_mail(sender=sender_address, to=to_address, subject=subject, - body=body) -
diff --git a/tools/android/loading/cloud/frontend/frontend_job.py b/tools/android/loading/cloud/frontend/frontend_job.py deleted file mode 100644 index 0c5783e..0000000 --- a/tools/android/loading/cloud/frontend/frontend_job.py +++ /dev/null
@@ -1,90 +0,0 @@ -# Copyright 2016 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. - -from google.appengine.ext import ndb - - -class FrontendJob(ndb.Model): - """Class representing a frontend job. - - A frontend job is a Clovis task sent by the user, and associated metadata - (such as the username, the start time...). - It is persisted in the Google Cloud datastore. - - All frontend jobs are ancestors of a single entity called 'FrontendJobList'. - This allows to benefit from strong consistency when querying the job - associated to a tag. - """ - # Base URL path to get information about a job. - SHOW_JOB_URL = '/show_job' - - # ndb properties persisted in the datastore. Indexing is not needed. - email = ndb.StringProperty(indexed=False) - status = ndb.StringProperty(indexed=False) - task_url = ndb.StringProperty(indexed=False) - eta = ndb.DateTimeProperty(indexed=False) - start_time = ndb.DateTimeProperty(auto_now_add=True, indexed=False) - # Not indexed by default. - clovis_task = ndb.TextProperty(compressed=True, indexed=False) - log = ndb.TextProperty(indexed=False) - - @classmethod - def _GetParentKeyFromTag(cls, tag): - """Gets the key that can be used to retrieve a frontend job from the job - list. - """ - return ndb.Key('FrontendJobList', tag) - - @classmethod - def CreateForTag(cls, tag): - """Creates a frontend job associated with tag.""" - parent_key = cls._GetParentKeyFromTag(tag) - return cls(parent=parent_key) - - @classmethod - def GetFromTag(cls, tag): - """Gets the frontend job associated with tag.""" - parent_key = cls._GetParentKeyFromTag(tag) - return cls.query(ancestor=parent_key).get() - - @classmethod - def DeleteForTag(cls, tag): - """Deletes the frontend job assowiated with tag.""" - parent_key = cls._GetParentKeyFromTag(tag) - frontend_job = cls.query(ancestor=parent_key).get(keys_only=True) - if frontend_job: - frontend_job.delete() - - @classmethod - def ListJobs(cls): - """Lists all the frontend jobs. - - Returns: - list of strings: The list of tags corresponding to existing frontend jobs. - """ - return [key.parent().string_id() for key in cls.query().fetch( - 100, keys_only=True)] - - @classmethod - def GetJobURL(cls, tag): - """Gets the URL that can be used to get information about a specific job.""" - return cls.SHOW_JOB_URL + '?tag=' + tag - - def RenderAsHtml(self): - """Render a short job description as a HTML table. - - The log and ClovisTask are not included, because they are potentially very - large. - """ - html = '<table>' - - for p in FrontendJob._properties: - if p == 'log' or p == 'clovis_task': - continue - value = getattr(self, p) - if value: - html += '<tr><td>' + p + '</td><td>' + str(value) + '</td></tr>' - - html += '</table>' - return html
diff --git a/tools/android/loading/cloud/frontend/lib/common b/tools/android/loading/cloud/frontend/lib/common deleted file mode 120000 index dc879abe..0000000 --- a/tools/android/loading/cloud/frontend/lib/common +++ /dev/null
@@ -1 +0,0 @@ -../../common \ No newline at end of file
diff --git a/tools/android/loading/cloud/frontend/memory_logs.py b/tools/android/loading/cloud/frontend/memory_logs.py deleted file mode 100644 index afd1897..0000000 --- a/tools/android/loading/cloud/frontend/memory_logs.py +++ /dev/null
@@ -1,34 +0,0 @@ -# Copyright 2016 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. - -import logging -from StringIO import StringIO - - -class MemoryLogs(object): - """Collects logs in memory.""" - - def __init__(self, logger): - self._logger = logger - self._log_buffer = StringIO() - self._log_handler = logging.StreamHandler(self._log_buffer) - formatter = logging.Formatter("[%(asctime)s][%(levelname)s] %(message)s", - "%y-%m-%d %H:%M:%S") - self._log_handler.setFormatter(formatter) - - def Start(self): - """Starts collecting the logs.""" - self._logger.addHandler(self._log_handler) - - def Flush(self): - """Stops collecting the logs and returns the logs collected since Start() - was called. - """ - self._logger.removeHandler(self._log_handler) - self._log_handler.flush() - self._log_buffer.flush() - result = self._log_buffer.getvalue() - self._log_buffer.truncate(0) - return result -
diff --git a/tools/android/loading/cloud/frontend/requirements.txt b/tools/android/loading/cloud/frontend/requirements.txt deleted file mode 100644 index 4d9f882..0000000 --- a/tools/android/loading/cloud/frontend/requirements.txt +++ /dev/null
@@ -1,3 +0,0 @@ -Flask==0.10 -google-api-python-client -GoogleAppEngineCloudStorageClient
diff --git a/tools/android/loading/cloud/frontend/static/base.css b/tools/android/loading/cloud/frontend/static/base.css deleted file mode 100644 index 3a5dfbf..0000000 --- a/tools/android/loading/cloud/frontend/static/base.css +++ /dev/null
@@ -1,46 +0,0 @@ -/* Copyright 2016 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. */ - -body { - font-family:'Arial', sans-serif; -} - -.menu { - margin-bottom: 1em; - --padding: 14px 16px; - border: 1px solid #e7e7e7; -} - -.menu div { - padding: var(--padding); - font-weight:bold; - color: #ffca00; - background-color: #cc0000; - cursor: default; -} - -.menu ul { - list-style-type: none; - margin: 0; - padding: 0; - overflow: hidden; -} - -.menu li { - float: left; - text-align: center; -} - -.menu li a { - color: #666; - background-color: #f3f3f3; - text-decoration: none; - display: block; - padding: var(--padding); -} - -.menu li a:hover { - background-color: #ddd; -} -
diff --git a/tools/android/loading/cloud/frontend/static/crown_icon.png b/tools/android/loading/cloud/frontend/static/crown_icon.png deleted file mode 100644 index 2d5ac45..0000000 --- a/tools/android/loading/cloud/frontend/static/crown_icon.png +++ /dev/null Binary files differ
diff --git a/tools/android/loading/cloud/frontend/templates/base.html b/tools/android/loading/cloud/frontend/templates/base.html deleted file mode 100644 index 72d732c..0000000 --- a/tools/android/loading/cloud/frontend/templates/base.html +++ /dev/null
@@ -1,35 +0,0 @@ -{# Copyright 2016 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. -#} - -<!DOCTYPE html> -<html> - -<head> - <meta charset="utf-8"> - <title>Clovis</title> - <link rel="stylesheet" type="text/css" href="/static/base.css"/> - <link rel="icon" href="/static/crown_icon.png"/> -</head> - -<body> -<header> - <div class="menu"> - <ul style="border: 1px solid #e7e7e7; background-color: #f3f3f3;"> - <li> <div> Clovis </div> - <li> <a href="/">New Job</a> - <li> <a href="/list_jobs">Active Jobs</a> - <li> <a href="https://chromium.googlesource.com/chromium/src/+/master/tools/android/loading/cloud/frontend/README.md"> - Documentation - </a> - </ul> - </div> -</header> - -{# The main content of the page goes here #} -{% block content %} -{% endblock %} - -</body> -</html>
diff --git a/tools/android/loading/cloud/frontend/templates/form.html b/tools/android/loading/cloud/frontend/templates/form.html deleted file mode 100644 index 9003259..0000000 --- a/tools/android/loading/cloud/frontend/templates/form.html +++ /dev/null
@@ -1,15 +0,0 @@ -{# Copyright 2016 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. -#} - -{% extends "base.html" %} - -{% block content %} -<h2>Submit New Task</h2> -<p> Select JSON file </p> -<form action="/form_sent" method="POST" enctype="multipart/form-data"> - <input type="file" name="json_task"/> - <input type="submit" name="submit" value="Upload"/> -</form> -{% endblock %}
diff --git a/tools/android/loading/cloud/frontend/templates/log.html b/tools/android/loading/cloud/frontend/templates/log.html deleted file mode 100644 index 9b43f87..0000000 --- a/tools/android/loading/cloud/frontend/templates/log.html +++ /dev/null
@@ -1,42 +0,0 @@ -{# Copyright 2016 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. -#} - -{# Template for a page displaying a body and logs (optional) under a collapsible - section. -#} -{% extends "base.html" %} - -{% block content %} - -<h2> {{ title }} </h2> - -{{ body }} - -{% if log %} - -<p><a onclick="javascript:ShowHide('HiddenDiv'); return false;" href="#"> - Show/hide details -</a></p> - -<div id="HiddenDiv" - style="display:none; font: 0.8em 'Droid Sans Mono', monospace;"> - -{# Loop over the lines of the log to add linebreaks. #} -{%- for line in log -%} - {{ line }}<br/> -{%- endfor -%} - -</div> - -<script type="text/javascript"> -function ShowHide(divId) { - element = document.getElementById(divId) - element.style.display = (element.style.display == 'none') ? 'block' : 'none'; -} -</script> - -{% endif %} - -{% endblock %}
diff --git a/tools/android/loading/clovis_constants.py b/tools/android/loading/clovis_constants.py deleted file mode 100644 index e64ddf0..0000000 --- a/tools/android/loading/clovis_constants.py +++ /dev/null
@@ -1,21 +0,0 @@ -# Copyright (c) 2016 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. - -"""Provides common constants for Clovis.""" - -QUEUING_CATEGORY = 'disabled-by-default-loading.resource' - -# Categories to enable or disable for all traces collected. Disabled categories -# are prefixed with '-'. -DEFAULT_CATEGORIES = [ - QUEUING_CATEGORY, - 'blink', - 'blink.net', - 'blink.user_timing', - 'devtools.timeline', - 'disabled-by-default-blink.debug.layout', - 'toplevel', - 'v8', - '-cc', # Contains a lot of events, none of which we use. -]
diff --git a/tools/android/loading/common_util.py b/tools/android/loading/common_util.py deleted file mode 100644 index 899062cb..0000000 --- a/tools/android/loading/common_util.py +++ /dev/null
@@ -1,150 +0,0 @@ -# Copyright (c) 2016 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. - -import contextlib -import json -import logging -import os -import re -import shutil -import signal -import subprocess -import sys -import tempfile -import time - - -def VerboseCompileRegexOrAbort(regex): - """Compiles a user-provided regular expression, exits the program on error.""" - try: - return re.compile(regex) - except re.error as e: - sys.stderr.write('invalid regex: {}\n{}\n'.format(regex, e)) - sys.exit(2) - - -def PollFor(condition, condition_name, interval=5): - """Polls for a function to return true. - - Args: - condition: Function to wait its return to be True. - condition_name: The condition's name used for logging. - interval: Periods to wait between tries in seconds. - - Returns: - What condition has returned to stop waiting. - """ - while True: - result = condition() - logging.info('Polling condition %s is %s' % ( - condition_name, 'met' if result else 'not met')) - if result: - return result - time.sleep(interval) - - -def SerializeAttributesToJsonDict(json_dict, instance, attributes): - """Adds the |attributes| from |instance| to a |json_dict|. - - Args: - json_dict: (dict) Dict to update. - instance: (object) instance to take the values from. - attributes: ([str]) List of attributes to serialize. - - Returns: - json_dict - """ - json_dict.update({attr: getattr(instance, attr) for attr in attributes}) - return json_dict - - -def DeserializeAttributesFromJsonDict(json_dict, instance, attributes): - """Sets a list of |attributes| in |instance| according to their value in - |json_dict|. - - Args: - json_dict: (dict) Dict containing values dumped by - SerializeAttributesToJsonDict. - instance: (object) instance to modify. - attributes: ([str]) List of attributes to set. - - Raises: - AttributeError if one of the attribute doesn't exist in |instance|. - - Returns: - instance - """ - for attr in attributes: - getattr(instance, attr) # To raise AttributeError if attr doesn't exist. - setattr(instance, attr, json_dict[attr]) - return instance - - -@contextlib.contextmanager -def TemporaryDirectory(suffix='', prefix='tmp'): - """Returns a freshly-created directory that gets automatically deleted after - usage. - """ - name = tempfile.mkdtemp(suffix=suffix, prefix=prefix) - try: - yield name - finally: - shutil.rmtree(name) - - -def EnsureParentDirectoryExists(path): - """Verifies that the parent directory exists or creates it if missing.""" - parent_directory_path = os.path.abspath(os.path.dirname(path)) - if not os.path.isdir(parent_directory_path): - os.makedirs(parent_directory_path) - - -def GetCommandLineForLogging(cmd, env_diff=None): - """Get command line string. - - Args: - cmd: Command line argument - env_diff: Environment modification for the command line. - - Returns: - Command line string. - """ - cmd_str = '' - if env_diff: - for key, value in env_diff.iteritems(): - cmd_str += '{}={} '.format(key, value) - return cmd_str + subprocess.list2cmdline(cmd) - - -# TimeoutError inherit from BaseException to pass through DevUtils' retries -# decorator that catches only exceptions inheriting from Exception. -class TimeoutError(BaseException): - pass - - -# If this exception is ever raised, then might be better to replace this -# implementation with Thread.join(timeout=XXX). -class TimeoutCollisionError(Exception): - pass - - -@contextlib.contextmanager -def TimeoutScope(seconds, error_name): - """Raises TimeoutError if the with statement is finished within |seconds|.""" - assert seconds > 0 - def _signal_callback(signum, frame): - del signum, frame # unused. - raise TimeoutError(error_name) - - try: - signal.signal(signal.SIGALRM, _signal_callback) - if signal.alarm(seconds) != 0: - raise TimeoutCollisionError( - 'Discarding an alarm that was scheduled before.') - yield - finally: - signal.alarm(0) - if signal.getsignal(signal.SIGALRM) != _signal_callback: - raise TimeoutCollisionError('Looks like there is a signal.signal(signal.' - 'SIGALRM) made within the with statement.')
diff --git a/tools/android/loading/common_util_unittest.py b/tools/android/loading/common_util_unittest.py deleted file mode 100644 index 62ddaee..0000000 --- a/tools/android/loading/common_util_unittest.py +++ /dev/null
@@ -1,98 +0,0 @@ -# Copyright 2016 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. - -import signal -import time -import unittest - -import common_util - - -class SerializeAttributesTestCase(unittest.TestCase): - class Foo(object): - def __init__(self, foo_fighters, whisky_bar): - # Pylint doesn't like foo and bar, but I guess musical references are OK. - self.foo_fighters = foo_fighters - self.whisky_bar = whisky_bar - - def testSerialization(self): - foo_fighters = self.Foo('1', 2) - json_dict = common_util.SerializeAttributesToJsonDict( - {}, foo_fighters, ['foo_fighters', 'whisky_bar']) - self.assertDictEqual({'foo_fighters': '1', 'whisky_bar': 2}, json_dict) - # Partial update - json_dict = common_util.SerializeAttributesToJsonDict( - {'baz': 42}, foo_fighters, ['whisky_bar']) - self.assertDictEqual({'baz': 42, 'whisky_bar': 2}, json_dict) - # Non-existing attribute. - with self.assertRaises(AttributeError): - json_dict = common_util.SerializeAttributesToJsonDict( - {}, foo_fighters, ['foo_fighters', 'whisky_bar', 'baz']) - - def testDeserialization(self): - foo_fighters = self.Foo('hello', 'world') - json_dict = {'foo_fighters': 12, 'whisky_bar': 42} - # Partial. - foo_fighters = common_util.DeserializeAttributesFromJsonDict( - json_dict, foo_fighters, ['foo_fighters']) - self.assertEqual(12, foo_fighters.foo_fighters) - self.assertEqual('world', foo_fighters.whisky_bar) - # Complete. - foo_fighters = common_util.DeserializeAttributesFromJsonDict( - json_dict, foo_fighters, ['foo_fighters', 'whisky_bar']) - self.assertEqual(42, foo_fighters.whisky_bar) - # Non-existing attribute. - with self.assertRaises(AttributeError): - json_dict['baz'] = 'bad' - foo_fighters = common_util.DeserializeAttributesFromJsonDict( - json_dict, foo_fighters, ['foo_fighters', 'whisky_bar', 'baz']) - - -class TimeoutScopeTestCase(unittest.TestCase): - def testTimeoutRaise(self): - self.assertEquals(0, signal.alarm(0)) - - with self.assertRaisesRegexp(common_util.TimeoutError, 'hello'): - with common_util.TimeoutScope(seconds=1, error_name='hello'): - signal.pause() - self.fail() - self.assertEquals(0, signal.alarm(0)) - - with self.assertRaisesRegexp(common_util.TimeoutError, 'world'): - with common_util.TimeoutScope(seconds=1, error_name='world'): - time.sleep(2) - self.assertEquals(0, signal.alarm(0)) - - def testCollisionDetection(self): - ONE_YEAR = 365 * 24 * 60 * 60 - - def _mock_callback(signum, frame): - del signum, frame # unused. - - flag = False - with self.assertRaises(common_util.TimeoutCollisionError): - with common_util.TimeoutScope(seconds=ONE_YEAR, error_name=''): - flag = True - signal.signal(signal.SIGALRM, _mock_callback) - self.assertTrue(flag) - self.assertEquals(0, signal.alarm(0)) - - flag = False - with self.assertRaises(common_util.TimeoutCollisionError): - with common_util.TimeoutScope(seconds=ONE_YEAR, error_name=''): - flag = True - with common_util.TimeoutScope(seconds=ONE_YEAR, error_name=''): - self.fail() - self.assertTrue(flag) - self.assertEquals(0, signal.alarm(0)) - - signal.alarm(ONE_YEAR) - with self.assertRaises(common_util.TimeoutCollisionError): - with common_util.TimeoutScope(seconds=ONE_YEAR, error_name=''): - self.fail() - self.assertEquals(0, signal.alarm(0)) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/content_classification_lens.py b/tools/android/loading/content_classification_lens.py deleted file mode 100644 index 89f40e2..0000000 --- a/tools/android/loading/content_classification_lens.py +++ /dev/null
@@ -1,192 +0,0 @@ -# Copyright 2016 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. - -"""Labels requests according to the type of content they represent.""" - -import collections -import logging -import operator -import os -import urlparse - -import loading_trace -import request_track - - -class ContentClassificationLens(object): - """Associates requests and frames with the type of content they represent.""" - def __init__(self, trace, ad_rules, tracking_rules): - """Initializes an instance of ContentClassificationLens. - - Args: - trace: (LoadingTrace) loading trace. - ad_rules: ([str]) List of Adblock+ compatible rules used to classify ads. - tracking_rules: ([str]) List of Adblock+ compatible rules used to - classify tracking and analytics. - """ - self._trace = trace - self._requests = trace.request_track.GetEvents() - self._requests_by_id = {r.request_id: r for r in self._requests} - self._main_frame_id = trace.page_track.GetEvents()[0]['frame_id'] - self._frame_to_requests = collections.defaultdict(list) - self._ad_requests = set() - self._tracking_requests = set() - self._ad_matcher = _RulesMatcher(ad_rules, True) - self._tracking_matcher = _RulesMatcher(tracking_rules, True) - self._document_url = self._GetDocumentUrl() - self._GroupRequestsByFrameId() - self._LabelRequests() - - def IsAdRequest(self, request): - """Returns True iff the request matches one of the ad_rules.""" - return request.request_id in self._ad_requests - - def IsTrackingRequest(self, request): - """Returns True iff the request matches one of the tracking_rules.""" - return request.request_id in self._tracking_requests - - def IsAdOrTrackingFrame(self, frame_id): - """A Frame is an Ad frame if it's not the main frame and its main resource - is ad or tracking-related. - """ - if (frame_id not in self._frame_to_requests - or frame_id == self._main_frame_id): - return False - frame_requests = [self._requests_by_id[request_id] - for request_id in self._frame_to_requests[frame_id]] - sorted_frame_resources = sorted( - frame_requests, key=operator.attrgetter('start_msec')) - frame_main_resource = sorted_frame_resources[0] - return (frame_main_resource.request_id in self._ad_requests - or frame_main_resource.request_id in self._tracking_requests) - - def AdAndTrackingRequests(self): - """Returns a list of requests linked to ads and tracking. - - Returns the union of: - - Requests tagged as ad or tracking. - - Requests originating from an ad frame. - """ - frame_ids = {r.frame_id for r in self._requests} - ad_frame_ids = filter(self.IsAdOrTrackingFrame, frame_ids) - return filter(lambda r: self.IsAdRequest(r) or self.IsTrackingRequest(r) - or r.frame_id in ad_frame_ids, self._requests) - - @classmethod - def WithRulesFiles(cls, trace, ad_rules_filename, tracking_rules_filename): - """Returns an instance of ContentClassificationLens with the rules read - from files. - """ - ad_rules = [] - tracking_rules = [] - if os.path.exists(ad_rules_filename): - ad_rules = open(ad_rules_filename, 'r').readlines() - if os.path.exists(tracking_rules_filename): - tracking_rules = open(tracking_rules_filename, 'r').readlines() - return ContentClassificationLens(trace, ad_rules, tracking_rules) - - def _GroupRequestsByFrameId(self): - for request in self._requests: - frame_id = request.frame_id - self._frame_to_requests[frame_id].append(request.request_id) - - def _LabelRequests(self): - for request in self._requests: - request_id = request.request_id - if self._ad_matcher.Matches(request, self._document_url): - self._ad_requests.add(request_id) - if self._tracking_matcher.Matches(request, self._document_url): - self._tracking_requests.add(request_id) - - def _GetDocumentUrl(self): - main_frame_id = self._trace.page_track.GetMainFrameId() - # Take the last one as JS redirects can change the document URL. - document_url = None - for r in self._requests: - # 304: not modified. - if r.frame_id == main_frame_id and r.status in (200, 304): - document_url = r.document_url - return document_url - - -class _RulesMatcher(object): - """Matches requests with rules in Adblock+ format.""" - _WHITELIST_PREFIX = '@@' - _RESOURCE_TYPE_TO_OPTIONS_KEY = { - 'Script': 'script', 'Stylesheet': 'stylesheet', 'Image': 'image', - 'XHR': 'xmlhttprequest'} - def __init__(self, rules, no_whitelist): - """Initializes an instance of _RulesMatcher. - - Args: - rules: ([str]) list of rules. - no_whitelist: (bool) Whether the whitelisting rules should be ignored. - """ - self._rules = self._FilterRules(rules, no_whitelist) - if self._rules: - try: - import adblockparser - self._matcher = adblockparser.AdblockRules(self._rules) - except ImportError: - logging.critical('Likely you need to install adblockparser. Try:\n' - ' pip install --user adblockparser\n' - 'For 10-100x better performance, also try:\n' - " pip install --user 're2 >= 0.2.21'") - raise - else: - self._matcher = None - - def Matches(self, request, document_url): - """Returns whether a request matches one of the rules.""" - if self._matcher is None: - return False - url = request.url - return self._matcher.should_block( - url, self._GetOptions(request, document_url)) - - @classmethod - def _GetOptions(cls, request, document_url): - options = {} - resource_type = request.resource_type - option = cls._RESOURCE_TYPE_TO_OPTIONS_KEY.get(resource_type) - if option: - options[option] = True - if cls._IsThirdParty(request.url, document_url): - options['third-party'] = True - return options - - @classmethod - def _FilterRules(cls, rules, no_whitelist): - if not no_whitelist: - return rules - else: - return [rule for rule in rules - if not rule.startswith(cls._WHITELIST_PREFIX)] - - @classmethod - def _IsThirdParty(cls, url, document_url): - # Common definition of "third-party" is "not from the same TLD+1". - # Unfortunately, knowing what is a TLD is not trivial. To do it without a - # database, we use the following simple (and incorrect) rules: - # - co.{in,uk,jp,hk} is a TLD - # - com.{au,hk} is a TLD - # Otherwise, this is the part after the last dot. - return cls._GetTldPlusOne(url) != cls._GetTldPlusOne(document_url) - - @classmethod - def _GetTldPlusOne(cls, url): - hostname = urlparse.urlparse(url).hostname - if not hostname: - return hostname - parts = hostname.split('.') - if len(parts) <= 2: - return hostname - tld_parts_count = 1 - may_be_tld = parts[-2:] - if may_be_tld[0] == 'co' and may_be_tld[1] in ('in', 'uk', 'jp'): - tld_parts_count = 2 - elif may_be_tld[0] == 'com' and may_be_tld[1] in ('au', 'hk'): - tld_parts_count = 2 - tld_plus_one = '.'.join(parts[-(tld_parts_count + 1):]) - return tld_plus_one
diff --git a/tools/android/loading/content_classification_lens_unittest.py b/tools/android/loading/content_classification_lens_unittest.py deleted file mode 100644 index 18025b0a..0000000 --- a/tools/android/loading/content_classification_lens_unittest.py +++ /dev/null
@@ -1,165 +0,0 @@ -# Copyright 2016 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. - -import copy -import unittest - -from content_classification_lens import (ContentClassificationLens, - _RulesMatcher) -from request_track import Request -import test_utils - - -class ContentClassificationLensTestCase(unittest.TestCase): - _DOCUMENT_URL = 'http://bla.com' - _MAIN_FRAME_ID = '123.1' - _REQUEST = Request.FromJsonDict({'url': _DOCUMENT_URL, - 'document_url': _DOCUMENT_URL, - 'request_id': '1234.1', - 'frame_id': _MAIN_FRAME_ID, - 'initiator': {'type': 'other'}, - 'timestamp': 2, - 'status': 200, - 'timing': {}, - 'resource_type': 'Document'}) - _PAGE_EVENTS = [{'method': 'Page.frameStartedLoading', - 'frame_id': _MAIN_FRAME_ID}, - {'method': 'Page.frameAttached', - 'frame_id': '123.13', 'parent_frame_id': _MAIN_FRAME_ID}] - _RULES = ['bla.com'] - - def testGetDocumentUrl(self): - trace = test_utils.LoadingTraceFromEvents( - [self._REQUEST], self._PAGE_EVENTS) - lens = ContentClassificationLens(trace, [], []) - self.assertEquals(self._DOCUMENT_URL, lens._GetDocumentUrl()) - # Don't be fooled by redirects. - request = copy.deepcopy(self._REQUEST) - request.status = 302 - request.document_url = 'http://www.bla.com' - trace = test_utils.LoadingTraceFromEvents( - [request, self._REQUEST], self._PAGE_EVENTS) - lens = ContentClassificationLens(trace, [], []) - self.assertEquals(self._DOCUMENT_URL, lens._GetDocumentUrl()) - - def testGetDocumentUrlSeveralChanges(self): - request = copy.deepcopy(self._REQUEST) - request.status = 200 - request.document_url = 'http://www.blabla.com' - request2 = copy.deepcopy(request) - request2.document_url = 'http://www.blablabla.com' - trace = test_utils.LoadingTraceFromEvents( - [self._REQUEST, request, request2], self._PAGE_EVENTS) - lens = ContentClassificationLens(trace, [], []) - self.assertEquals(request2.document_url, lens._GetDocumentUrl()) - - def testNoRules(self): - trace = test_utils.LoadingTraceFromEvents( - [self._REQUEST], self._PAGE_EVENTS) - lens = ContentClassificationLens(trace, [], []) - self.assertFalse(lens.IsAdRequest(self._REQUEST)) - self.assertFalse(lens.IsTrackingRequest(self._REQUEST)) - - def testAdRequest(self): - trace = test_utils.LoadingTraceFromEvents( - [self._REQUEST], self._PAGE_EVENTS) - lens = ContentClassificationLens(trace, self._RULES, []) - self.assertTrue(lens.IsAdRequest(self._REQUEST)) - self.assertFalse(lens.IsTrackingRequest(self._REQUEST)) - - def testTrackingRequest(self): - trace = test_utils.LoadingTraceFromEvents( - [self._REQUEST], self._PAGE_EVENTS) - lens = ContentClassificationLens(trace, [], self._RULES) - self.assertFalse(lens.IsAdRequest(self._REQUEST)) - self.assertTrue(lens.IsTrackingRequest(self._REQUEST)) - - def testMainFrameIsNotAnAdFrame(self): - trace = test_utils.LoadingTraceFromEvents( - [self._REQUEST], self._PAGE_EVENTS) - lens = ContentClassificationLens(trace, self._RULES, []) - self.assertFalse(lens.IsAdOrTrackingFrame(self._MAIN_FRAME_ID)) - - def testAdFrame(self): - request = copy.deepcopy(self._REQUEST) - request.request_id = '1234.2' - request.frame_id = '123.123' - trace = test_utils.LoadingTraceFromEvents( - [self._REQUEST, request], self._PAGE_EVENTS) - lens = ContentClassificationLens(trace, self._RULES, []) - self.assertTrue(lens.IsAdOrTrackingFrame(request.frame_id)) - - def testAdAndTrackingRequests(self): - ad_request = copy.deepcopy(self._REQUEST) - ad_request.request_id = '1234.2' - ad_request.frame_id = '123.123' - non_ad_request_non_ad_frame = copy.deepcopy(self._REQUEST) - non_ad_request_non_ad_frame.request_id = '1234.3' - non_ad_request_non_ad_frame.url = 'http://www.example.com' - non_ad_request_non_ad_frame.frame_id = '123.456' - non_ad_request_ad_frame = copy.deepcopy(self._REQUEST) - non_ad_request_ad_frame.request_id = '1234.4' - non_ad_request_ad_frame.url = 'http://www.example.com' - non_ad_request_ad_frame.frame_id = ad_request.frame_id - - trace = test_utils.LoadingTraceFromEvents( - [self._REQUEST, ad_request, non_ad_request_non_ad_frame, - non_ad_request_ad_frame], self._PAGE_EVENTS) - lens = ContentClassificationLens(trace, self._RULES, []) - self.assertSetEqual( - set([self._REQUEST, ad_request, non_ad_request_ad_frame]), - set(lens.AdAndTrackingRequests())) - - -class _MatcherTestCase(unittest.TestCase): - _RULES_WITH_WHITELIST = ['/thisisanad.', '@@myadvertisingdomain.com/*', - '@@||www.mydomain.com/ads/$elemhide'] - _SCRIPT_RULE = 'domainwithscripts.com/*$script' - _THIRD_PARTY_RULE = 'domainwithscripts.com/*$third-party' - _SCRIPT_REQUEST = Request.FromJsonDict( - {'url': 'http://domainwithscripts.com/bla.js', - 'resource_type': 'Script', - 'request_id': '1234.1', - 'frame_id': '123.1', - 'initiator': {'type': 'other'}, - 'timestamp': 2, - 'timing': {}}) - - def testRemovesWhitelistRules(self): - matcher = _RulesMatcher(self._RULES_WITH_WHITELIST, False) - self.assertEquals(3, len(matcher._rules)) - matcher = _RulesMatcher(self._RULES_WITH_WHITELIST, True) - self.assertEquals(1, len(matcher._rules)) - - def testScriptRule(self): - matcher = _RulesMatcher([self._SCRIPT_RULE], False) - request = copy.deepcopy(self._SCRIPT_REQUEST) - request.resource_type = 'Stylesheet' - self.assertFalse(matcher.Matches( - request, ContentClassificationLensTestCase._DOCUMENT_URL)) - self.assertTrue(matcher.Matches( - self._SCRIPT_REQUEST, ContentClassificationLensTestCase._DOCUMENT_URL)) - - def testGetTldPlusOne(self): - self.assertEquals( - 'easy.com', - _RulesMatcher._GetTldPlusOne('http://www.easy.com/hello/you')) - self.assertEquals( - 'not-so-easy.co.uk', - _RulesMatcher._GetTldPlusOne('http://www.not-so-easy.co.uk/hello/you')) - self.assertEquals( - 'hard.co.uk', - _RulesMatcher._GetTldPlusOne('http://hard.co.uk/')) - - def testThirdPartyRule(self): - matcher = _RulesMatcher([self._THIRD_PARTY_RULE], False) - request = copy.deepcopy(self._SCRIPT_REQUEST) - document_url = 'http://www.domainwithscripts.com/good-morning' - self.assertFalse(matcher.Matches(request, document_url)) - document_url = 'http://anotherdomain.com/good-morning' - self.assertTrue(matcher.Matches(request, document_url)) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/controller.py b/tools/android/loading/controller.py deleted file mode 100644 index 0cad7f15..0000000 --- a/tools/android/loading/controller.py +++ /dev/null
@@ -1,630 +0,0 @@ -# Copyright 2016 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. - -"""Controller objects that control the context in which chrome runs. - -This is responsible for the setup necessary for launching chrome, and for -creating a DevToolsConnection. There are remote device and local -desktop-specific versions. -""" - -import contextlib -import copy -import datetime -import errno -import logging -import os -import platform -import shutil -import socket -import subprocess -import sys -import tempfile -import time -import traceback - -import psutil - -import chrome_cache -import chrome_setup -import common_util -import device_setup -import devtools_monitor -import emulation -from options import OPTIONS - -_SRC_DIR = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..', '..', '..')) -_CATAPULT_DIR = os.path.join(_SRC_DIR, 'third_party', 'catapult') - -sys.path.append(os.path.join(_CATAPULT_DIR, 'devil')) -from devil.android import device_errors -from devil.android import flag_changer -from devil.android.sdk import intent - -sys.path.append( - os.path.join(_CATAPULT_DIR, 'telemetry', 'third_party', 'websocket-client')) -import websocket - - -class ChromeControllerMetadataGatherer(object): - """Gather metadata for the ChromeControllerBase.""" - - def __init__(self): - self._chromium_commit = None - - def GetMetadata(self): - """Gets metadata to update in the ChromeControllerBase""" - if self._chromium_commit is None: - def _GitCommand(subcmd): - return subprocess.check_output(['git', '-C', _SRC_DIR] + subcmd).strip() - try: - self._chromium_commit = _GitCommand(['merge-base', 'master', 'HEAD']) - if self._chromium_commit != _GitCommand(['rev-parse', 'HEAD']): - self._chromium_commit = 'unknown' - except subprocess.CalledProcessError: - self._chromium_commit = 'git_error' - return { - 'chromium_commit': self._chromium_commit, - 'date': datetime.datetime.utcnow().isoformat(), - 'seconds_since_epoch': time.time() - } - - -class ChromeControllerInternalError(Exception): - pass - - -def _AllocateTcpListeningPort(): - """Allocates a TCP listening port. - - Note: The use of this function is inherently OS level racy because the - port returned by this function might be re-used by another running process. - """ - temp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - temp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - temp_socket.bind(('', 0)) - return temp_socket.getsockname()[1] - finally: - temp_socket.close() - - -class ChromeControllerError(Exception): - """Chrome error with detailed log. - - Note: - Some of these errors might be known intermittent errors that can usually be - retried by the caller after re-doing any specific setup again. - """ - _INTERMITTENT_WHITE_LIST = {websocket.WebSocketTimeoutException, - devtools_monitor.DevToolsConnectionTargetCrashed} - _PASSTHROUGH_WHITE_LIST = (MemoryError, SyntaxError) - - def __init__(self, log): - """Constructor - - Args: - log: String containing the log of the running Chrome instance that was - running. It will be interleaved with any other running Android - package. - """ - self.error_type, self.error_value, self.error_traceback = sys.exc_info() - super(ChromeControllerError, self).__init__(repr(self.error_value)) - self.parent_stack = traceback.extract_stack() - self.log = log - - def Dump(self, output): - """Dumps the entire error's infos into file-like object.""" - output.write('-' * 60 + ' {}:\n'.format(self.__class__.__name__)) - output.write(repr(self) + '\n') - output.write('{} is {}known as intermittent.\n'.format( - self.error_type.__name__, '' if self.IsIntermittent() else 'NOT ')) - output.write( - '-' * 60 + ' {}\'s full traceback:\n'.format(self.error_type.__name__)) - output.write(''.join(traceback.format_list(self.parent_stack))) - traceback.print_tb(self.error_traceback, file=output) - output.write('-' * 60 + ' Begin log\n') - output.write(self.log) - output.write('-' * 60 + ' End log\n') - - def IsIntermittent(self): - """Returns whether the error is an known intermittent error.""" - return self.error_type in self._INTERMITTENT_WHITE_LIST - - def RaiseOriginal(self): - """Raises the original exception that has caused <self>.""" - raise self.error_type, self.error_value, self.error_traceback - - -class ChromeControllerBase(object): - """Base class for all controllers. - - Defines common operations but should not be created directly. - """ - METADATA_GATHERER = ChromeControllerMetadataGatherer() - DEVTOOLS_CONNECTION_ATTEMPTS = 10 - DEVTOOLS_CONNECTION_ATTEMPT_INTERVAL_SECONDS = 1 - - def __init__(self): - self._chrome_args = chrome_setup.CHROME_ARGS + [ - # Tests & dev-tools related stuff. - '--enable-test-events', - '--remote-debugging-port=%d' % OPTIONS.devtools_port, - - # Detailed log. - '--enable-logging=stderr', - '--v=1', - ] - self._wpr_attributes = None - self._metadata = {} - self._emulated_device = None - self._network_name = None - self._slow_death = False - - def AddChromeArguments(self, args): - """Add command-line arguments to the chrome execution.""" - self._chrome_args.extend(args) - - @contextlib.contextmanager - def Open(self): - """Context that returns a connection/chrome instance. - - Returns: - DevToolsConnection instance for which monitoring has been set up but not - started. - """ - raise NotImplementedError - - def ChromeMetadata(self): - """Return metadata such as emulation information. - - Returns: - Metadata as JSON dictionary. - """ - return self._metadata - - def GetDevice(self): - """Returns an android device, or None if chrome is local.""" - return None - - def SetDeviceEmulation(self, device_name): - """Set device emulation. - - Args: - device_name: (str) Key from --devices_file. - """ - devices = emulation.LoadEmulatedDevices(file(OPTIONS.devices_file)) - self._emulated_device = devices[device_name] - - def SetNetworkEmulation(self, network_name): - """Set network emulation. - - Args: - network_name: (str) Key from emulation.NETWORK_CONDITIONS or None to - disable network emulation. - """ - assert network_name in emulation.NETWORK_CONDITIONS or network_name is None - self._network_name = network_name - - def ResetBrowserState(self): - """Resets the chrome's browser state.""" - raise NotImplementedError - - def PushBrowserCache(self, cache_path): - """Pushes the HTTP chrome cache to the profile directory. - - Caution: - The chrome cache backend type differ according to the platform. On - desktop, the cache backend type is `blockfile` versus `simple` on Android. - This method assumes that your are pushing a cache with the correct backend - type, and will NOT verify for you. - - Args: - cache_path: The directory's path containing the cache locally. - """ - raise NotImplementedError - - def PullBrowserCache(self): - """Pulls the HTTP chrome cache from the profile directory. - - Returns: - Temporary directory containing all the browser cache. Caller will need to - remove this directory manually. - """ - raise NotImplementedError - - def SetSlowDeath(self, slow_death=True): - """Set to pause before final kill of chrome. - - Gives time for caches to write. - - Args: - slow_death: (bool) True if you want that which comes to all who live, to - be slow. - """ - self._slow_death = slow_death - - @contextlib.contextmanager - def OpenWprHost(self, wpr_archive_path, record=False, - network_condition_name=None, - disable_script_injection=False, - out_log_path=None): - """Opens a Web Page Replay host context. - - Args: - wpr_archive_path: host sided WPR archive's path. - record: Enables or disables WPR archive recording. - network_condition_name: Network condition name available in - emulation.NETWORK_CONDITIONS. - disable_script_injection: Disable JavaScript file injections that is - fighting against resources name entropy. - out_log_path: Path of the WPR host's log. - """ - raise NotImplementedError - - def _StartConnection(self, connection): - """This should be called after opening an appropriate connection.""" - if self._emulated_device: - self._metadata.update(emulation.SetUpDeviceEmulationAndReturnMetadata( - connection, self._emulated_device)) - if self._network_name: - network_condition = emulation.NETWORK_CONDITIONS[self._network_name] - logging.info('Set up network emulation %s (latency=%dms, down=%d, up=%d)' - % (self._network_name, network_condition['latency'], - network_condition['download'], network_condition['upload'])) - emulation.SetUpNetworkEmulation(connection, **network_condition) - self._metadata['network_emulation'] = copy.copy(network_condition) - self._metadata['network_emulation']['name'] = self._network_name - else: - self._metadata['network_emulation'] = \ - {k: 'disabled' for k in ['name', 'download', 'upload', 'latency']} - self._metadata.update(self.METADATA_GATHERER.GetMetadata()) - logging.info('Devtools connection success') - - def _GetChromeArguments(self): - """Get command-line arguments for the chrome execution.""" - chrome_args = self._chrome_args[:] - if self._wpr_attributes: - chrome_args.extend(self._wpr_attributes.chrome_args) - return chrome_args - - -class RemoteChromeController(ChromeControllerBase): - """A controller for an android device, aka remote chrome instance.""" - # An estimate of time to wait for the device to become idle after expensive - # operations, such as opening the launcher activity. - TIME_TO_IDLE_SECONDS = 2 - - def __init__(self, device): - """Initialize the controller. - - Caution: The browser state might need to be manually reseted. - - Args: - device: (device_utils.DeviceUtils) an android device. - """ - assert device is not None, 'Should you be using LocalController instead?' - super(RemoteChromeController, self).__init__() - self._device = device - self._metadata['platform'] = { - 'os': 'A-' + device.build_id, - 'product_model': device.product_model - } - self._InitDevice() - - def GetDevice(self): - """Overridden android device.""" - return self._device - - @contextlib.contextmanager - def Open(self): - """Overridden connection creation.""" - if self._wpr_attributes: - assert self._wpr_attributes.chrome_env_override == {}, \ - 'Remote controller doesn\'t support chrome environment variables.' - package_info = OPTIONS.ChromePackage() - self._device.ForceStop(package_info.package) - with flag_changer.CustomCommandLineFlags( - self._device, package_info.cmdline_file, self._GetChromeArguments()): - self._DismissCrashDialogIfNeeded() - start_intent = intent.Intent( - package=package_info.package, activity=package_info.activity, - data='about:blank') - self._device.adb.Logcat(clear=True, dump=True) - self._device.StartActivity(start_intent, blocking=True) - try: - for attempt_id in xrange(self.DEVTOOLS_CONNECTION_ATTEMPTS): - logging.info('Devtools connection attempt %d' % attempt_id) - # Adb forwarding does not provide a way to print the port number if - # it is allocated atomically by the OS by passing port=0, but we need - # dynamically allocated listening port here to handle parallel run on - # different devices. - host_side_port = _AllocateTcpListeningPort() - logging.info('Allocated host sided listening port for devtools ' - 'connection: %d', host_side_port) - try: - with device_setup.ForwardPort( - self._device, 'tcp:%d' % host_side_port, - 'localabstract:chrome_devtools_remote'): - try: - connection = devtools_monitor.DevToolsConnection( - OPTIONS.devtools_hostname, host_side_port) - self._StartConnection(connection) - except socket.error as e: - if e.errno != errno.ECONNRESET: - raise - time.sleep(self.DEVTOOLS_CONNECTION_ATTEMPT_INTERVAL_SECONDS) - continue - yield connection - if self._slow_death: - self._device.adb.Shell('am start com.google.android.launcher') - time.sleep(self.TIME_TO_IDLE_SECONDS) - break - except device_errors.AdbCommandFailedError as error: - _KNOWN_ADB_FORWARDER_FAILURES = [ - 'cannot bind to socket: Address already in use', - 'cannot rebind existing socket: Resource temporarily unavailable'] - for message in _KNOWN_ADB_FORWARDER_FAILURES: - if message in error.message: - break - else: - raise - continue - else: - raise ChromeControllerInternalError( - 'Failed to connect to Chrome devtools after {} ' - 'attempts.'.format(self.DEVTOOLS_CONNECTION_ATTEMPTS)) - except ChromeControllerError._PASSTHROUGH_WHITE_LIST: - raise - except Exception: - logcat = ''.join([l + '\n' for l in self._device.adb.Logcat(dump=True)]) - raise ChromeControllerError(log=logcat) - finally: - self._device.ForceStop(package_info.package) - self._DismissCrashDialogIfNeeded() - - def ResetBrowserState(self): - """Override resetting Chrome local state.""" - logging.info('Resetting Chrome local state') - chrome_setup.ResetChromeLocalState(self._device, - OPTIONS.ChromePackage().package) - - - def RebootDevice(self): - """Reboot the remote device.""" - assert self._wpr_attributes is None, 'WPR should be closed before rebooting' - logging.warning('Rebooting the device') - device_setup.Reboot(self._device) - self._InitDevice() - - def PushBrowserCache(self, cache_path): - """Override for chrome cache pushing.""" - logging.info('Push cache from %s' % cache_path) - chrome_cache.PushBrowserCache(self._device, cache_path) - - def PullBrowserCache(self): - """Override for chrome cache pulling.""" - assert self._slow_death, 'Must do SetSlowDeath() before opening chrome.' - logging.info('Pull cache from device') - return chrome_cache.PullBrowserCache(self._device) - - @contextlib.contextmanager - def OpenWprHost(self, wpr_archive_path, record=False, - network_condition_name=None, - disable_script_injection=False, - out_log_path=None): - """Starts a WPR host, overrides Chrome flags until contextmanager exit.""" - assert not self._wpr_attributes, 'WPR is already running.' - with device_setup.RemoteWprHost(self._device, wpr_archive_path, - record=record, - network_condition_name=network_condition_name, - disable_script_injection=disable_script_injection, - out_log_path=out_log_path) as wpr_attributes: - self._wpr_attributes = wpr_attributes - yield - self._wpr_attributes = None - - def _DismissCrashDialogIfNeeded(self): - for _ in xrange(10): - if not self._device.DismissCrashDialogIfNeeded(): - break - - def _InitDevice(self): - self._device.EnableRoot() - - -class LocalChromeController(ChromeControllerBase): - """Controller for a local (desktop) chrome instance.""" - - def __init__(self): - """Initialize the controller. - - Caution: The browser state might need to be manually reseted. - """ - super(LocalChromeController, self).__init__() - if OPTIONS.no_sandbox: - self.AddChromeArguments(['--no-sandbox']) - self._profile_dir = OPTIONS.local_profile_dir - self._using_temp_profile_dir = self._profile_dir is None - if self._using_temp_profile_dir: - self._profile_dir = tempfile.mkdtemp(suffix='.profile') - self._chrome_env_override = {} - self._metadata['platform'] = { - 'os': platform.system()[0] + '-' + platform.release(), - 'product_model': 'unknown' - } - - def __del__(self): - if self._using_temp_profile_dir: - shutil.rmtree(self._profile_dir) - - @staticmethod - def KillChromeProcesses(): - """Kills all the running instances of Chrome. - - Returns: (int) The number of processes that were killed. - """ - killed_count = 0 - chrome_path = OPTIONS.LocalBinary('chrome') - for process in psutil.process_iter(): - try: - process_bin_path = None - # In old versions of psutil, process.exe is a member, in newer ones it's - # a method. - if type(process.exe) == str: - process_bin_path = process.exe - else: - process_bin_path = process.exe() - if os.path.abspath(process_bin_path) == os.path.abspath(chrome_path): - process.terminate() - killed_count += 1 - try: - process.wait(timeout=10) - except psutil.TimeoutExpired: - process.kill() - except psutil.AccessDenied: - pass - except psutil.NoSuchProcess: - pass - return killed_count - - def SetChromeEnvOverride(self, env): - """Set the environment for Chrome. - - Args: - env: (dict) Environment. - """ - self._chrome_env_override = env - - @contextlib.contextmanager - def Open(self): - """Overridden connection creation.""" - # Kill all existing Chrome instances. - killed_count = LocalChromeController.KillChromeProcesses() - if killed_count > 0: - logging.warning('Killed existing Chrome instance.') - - chrome_cmd = [OPTIONS.LocalBinary('chrome')] - chrome_cmd.extend(self._GetChromeArguments()) - # Force use of simple cache. - chrome_cmd.append('--use-simple-cache-backend=on') - chrome_cmd.append('--user-data-dir=%s' % self._profile_dir) - # Navigates to about:blank for couples of reasons: - # - To find the correct target descriptor at devtool connection; - # - To avoid cache and WPR pollution by the NTP. - chrome_cmd.append('about:blank') - - tmp_log = \ - tempfile.NamedTemporaryFile(prefix="chrome_controller_", suffix='.log') - chrome_process = None - try: - chrome_env_override = self._chrome_env_override.copy() - if self._wpr_attributes: - chrome_env_override.update(self._wpr_attributes.chrome_env_override) - - chrome_env = os.environ.copy() - chrome_env.update(chrome_env_override) - - # Launch Chrome. - logging.info(common_util.GetCommandLineForLogging(chrome_cmd, - chrome_env_override)) - chrome_process = subprocess.Popen(chrome_cmd, stdout=tmp_log.file, - stderr=tmp_log.file, env=chrome_env) - # Attempt to connect to Chrome's devtools - for attempt_id in xrange(self.DEVTOOLS_CONNECTION_ATTEMPTS): - logging.info('Devtools connection attempt %d' % attempt_id) - process_result = chrome_process.poll() - if process_result is not None: - raise ChromeControllerInternalError( - 'Unexpected Chrome exit: {}'.format(process_result)) - try: - connection = devtools_monitor.DevToolsConnection( - OPTIONS.devtools_hostname, OPTIONS.devtools_port) - break - except socket.error as e: - if e.errno != errno.ECONNREFUSED: - raise - time.sleep(self.DEVTOOLS_CONNECTION_ATTEMPT_INTERVAL_SECONDS) - else: - raise ChromeControllerInternalError( - 'Failed to connect to Chrome devtools after {} ' - 'attempts.'.format(self.DEVTOOLS_CONNECTION_ATTEMPTS)) - # Start and yield the devtool connection. - self._StartConnection(connection) - yield connection - if self._slow_death: - connection.Close() - chrome_process.wait() - chrome_process = None - except ChromeControllerError._PASSTHROUGH_WHITE_LIST: - raise - except Exception: - raise ChromeControllerError(log=open(tmp_log.name).read()) - finally: - if OPTIONS.local_noisy: - sys.stderr.write(open(tmp_log.name).read()) - del tmp_log - if chrome_process: - try: - chrome_process.kill() - except OSError: - pass # Chrome is already dead. - - def ResetBrowserState(self): - """Override for chrome state reseting.""" - assert os.path.isdir(self._profile_dir) - logging.info('Reset chrome\'s profile') - # Don't do a rmtree(self._profile_dir) because it might be a temp directory. - for filename in os.listdir(self._profile_dir): - path = os.path.join(self._profile_dir, filename) - if os.path.isdir(path): - shutil.rmtree(path) - else: - os.remove(path) - - def PushBrowserCache(self, cache_path): - """Override for chrome cache pushing.""" - self._EnsureProfileDirectory() - profile_cache_path = self._GetCacheDirectoryPath() - logging.info('Copy cache directory from %s to %s.' % ( - cache_path, profile_cache_path)) - chrome_cache.CopyCacheDirectory(cache_path, profile_cache_path) - - def PullBrowserCache(self): - """Override for chrome cache pulling.""" - cache_path = tempfile.mkdtemp() - profile_cache_path = self._GetCacheDirectoryPath() - logging.info('Copy cache directory from %s to %s.' % ( - profile_cache_path, cache_path)) - chrome_cache.CopyCacheDirectory(profile_cache_path, cache_path) - return cache_path - - @contextlib.contextmanager - def OpenWprHost(self, wpr_archive_path, record=False, - network_condition_name=None, - disable_script_injection=False, - out_log_path=None): - """Override for WPR context.""" - assert not self._wpr_attributes, 'WPR is already running.' - with device_setup.LocalWprHost(wpr_archive_path, - record=record, - network_condition_name=network_condition_name, - disable_script_injection=disable_script_injection, - out_log_path=out_log_path) as wpr_attributes: - self._wpr_attributes = wpr_attributes - yield - self._wpr_attributes = None - - def _EnsureProfileDirectory(self): - if (not os.path.isdir(self._profile_dir) or - os.listdir(self._profile_dir) == []): - # Launch chrome so that it populates the profile directory. - with self.Open(): - pass - assert os.path.isdir(self._profile_dir) - assert os.path.isdir(os.path.dirname(self._GetCacheDirectoryPath())) - - def _GetCacheDirectoryPath(self): - return os.path.join(self._profile_dir, 'Default', 'Cache')
diff --git a/tools/android/loading/core_set.py b/tools/android/loading/core_set.py deleted file mode 100644 index 910c280..0000000 --- a/tools/android/loading/core_set.py +++ /dev/null
@@ -1,169 +0,0 @@ -# Copyright 2016 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. - -"""Compute core set for a page. - -This script is a collection of utilities for working with core sets. -""" - -import argparse -import glob -import json -import logging -import multiprocessing -import os -import sys - -import dependency_graph -import loading_trace -import request_dependencies_lens -import resource_sack - - -def _Progress(x): - sys.stderr.write(x + '\n') - - -def _PageCore(prefix, graph_set_names, output): - """Compute the page core over sets defined by graph_set_names.""" - assert graph_set_names - graph_sets = [] - sack = resource_sack.GraphSack() - for name in graph_set_names: - name_graphs = [] - _Progress('Processing %s' % name) - for filename in glob.iglob('-'.join([prefix, name, '*.trace'])): - _Progress('Reading %s' % filename) - trace = loading_trace.LoadingTrace.FromJsonFile(filename) - graph = dependency_graph.RequestDependencyGraph( - trace.request_track.GetEvents(), - request_dependencies_lens.RequestDependencyLens(trace)) - sack.ConsumeGraph(graph) - name_graphs.append(graph) - graph_sets.append(name_graphs) - core = sack.CoreSet(*graph_sets) - json.dump({'page_core': [{'label': b.label, - 'name': b.name, - 'count': b.num_nodes} - for b in core], - 'non_core': [{'label': b.label, - 'name': b.name, - 'count': b.num_nodes} - for b in sack.bags if b not in core], - 'threshold': sack.CORE_THRESHOLD}, - output, sort_keys=True, indent=2) - output.write('\n') - - -def _DoSite(site, graph_sets, input_dir, output_dir): - """Compute the appropriate page core for a site. - - Used by _Spawn. - """ - _Progress('Doing %s on %s' % (site, '/'.join(graph_sets))) - prefix = os.path.join(input_dir, site) - with file(os.path.join(output_dir, - '%s-%s.json' % (site, '.'.join(graph_sets))), - 'w') as output: - _PageCore(prefix, graph_sets, output) - - -def _DoSiteRedirect(t): - """Unpack arguments for map call. - - Note that multiprocessing.Pool.map cannot use a lambda (as it needs to be - serialized into the executing process). - """ - _DoSite(*t) - - -def _Spawn(site_list_file, graph_sets, input_dir, output_dir, workers): - """Spool site computation out to a multiprocessing pool.""" - with file(site_list_file) as site_file: - sites = [l.strip() for l in site_file.readlines()] - _Progress('Using sites:\n %s' % '\n '.join(sites)) - pool = multiprocessing.Pool(workers, maxtasksperchild=1) - pool.map(_DoSiteRedirect, [(s, graph_sets, input_dir, output_dir) - for s in sites]) - - -def _ReadCoreSet(filename): - data = json.load(open(filename)) - return set(page['name'] for page in data['page_core']) - - -def _Compare(a_name, b_name, csv): - """Compare two core sets.""" - a = _ReadCoreSet(a_name) - b = _ReadCoreSet(b_name) - result = (resource_sack.GraphSack.CoreSimilarity(a, b), - ' Equal' if a == b else 'UnEqual', - 'a<=b' if a <= b else 'a!<b', - 'a>=b' if b <= a else 'a!>b') - if csv: - print '%s,%s,%s,%s' % result - else: - print '%.2f %s %s %s' % result - - -if __name__ == '__main__': - logging.basicConfig(level=logging.ERROR) - parser = argparse.ArgumentParser() - subparsers = parser.add_subparsers() - - spawn = subparsers.add_parser( - 'spawn', help=('spawn page core set computation from a sites list.\n' - 'A core set will be computed for each site by ' - 'combining all run indicies from site traces for each ' - '--set, then computing the page core over the sets. ' - 'Assumes trace file names in form {input-dir}/' - '{site}-{set}-{run index}.trace')) - spawn.add_argument('--sets', required=True, - help='sets to combine, comma-separated') - spawn.add_argument('--sites', required=True, help='file containing sites') - spawn.add_argument('--workers', default=8, type=int, - help=('number of parallel workers. Each worker seems to ' - 'use about 0.5-1G/trace when processing. Total ' - 'memory usage should be kept less than physical ' - 'memory for the job to run in a reasonable time')) - spawn.add_argument('--input_dir', required=True, - help='trace input directory') - spawn.add_argument('--output_dir', required=True, - help=('core set output directory. Each site will have one ' - 'JSON file generated listing the core set as well ' - 'as some metadata like the threshold used')) - spawn.set_defaults(executor=lambda args: - _Spawn(site_list_file=args.sites, - graph_sets=args.sets.split(','), - input_dir=args.input_dir, - output_dir=args.output_dir, - workers=args.workers)) - - page_core = subparsers.add_parser( - 'page_core', - help=('compute page core set for a group of files of form ' - '{--prefix}{set}*.trace over each set in --sets')) - page_core.add_argument('--sets', required=True, - help='sets to combine, comma-separated') - page_core.add_argument('--prefix', required=True, - help='trace file prefix') - page_core.add_argument('--output', required=True, - help='JSON output file name') - page_core.set_defaults(executor=lambda args: - _PageCore(args.prefix, args.sets.split(','), - file(args.output, 'w'))) - - compare = subparsers.add_parser( - 'compare', - help=('compare two core sets (as output by spawn, page_core or ' - 'all_cores) using Jaccard index. Outputs on stdout')) - compare.add_argument('--a', required=True, help='the first core set JSON') - compare.add_argument('--b', required=True, help='the second core set JSON') - compare.add_argument('--csv', action='store_true', help='output as CSV') - compare.set_defaults( - executor=lambda args: - _Compare(args.a, args.b, args.csv)) - - args = parser.parse_args() - args.executor(args)
diff --git a/tools/android/loading/cost_to_csv.py b/tools/android/loading/cost_to_csv.py deleted file mode 100755 index d271d06..0000000 --- a/tools/android/loading/cost_to_csv.py +++ /dev/null
@@ -1,43 +0,0 @@ -#! /usr/bin/python -# 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. - -import argparse -import logging -import os -import sys - -from processing import (SitesFromDir, WarmGraph, ColdGraph) - - -def main(): - logging.basicConfig(level=logging.ERROR) - parser = argparse.ArgumentParser( - description=('Convert a directory created by ./analyze.py fetch ' - 'to a CSV.')) - parser.add_argument('--datadir', required=True) - parser.add_argument('--csv', required=True) - parser.add_argument('--noads', action='store_true') - args = parser.parse_args() - sites = SitesFromDir(args.datadir) - with open(args.csv, 'w') as output: - output.write('site,kind,cost\n') - for site in sites: - print site - warm = WarmGraph(args.datadir, site) - if args.noads: - warm.Set(node_filter=warm.FilterAds) - cold = ColdGraph(args.datadir, site) - if args.noads: - cold.Set(node_filter=cold.FilterAds) - output.write('%s,%s,%s\n' % (site, 'warm', warm.Cost())) - warm.Set(cache_all=True) - output.write('%s,%s,%s\n' % (site, 'warm-cache', warm.Cost())) - output.write('%s,%s,%s\n' % (site, 'cold', cold.Cost())) - cold.Set(cache_all=True) - output.write('%s,%s,%s\n' % (site, 'cold-cache', cold.Cost())) - - -if __name__ == '__main__': - main()
diff --git a/tools/android/loading/csv_util.py b/tools/android/loading/csv_util.py deleted file mode 100644 index ccdfb92..0000000 --- a/tools/android/loading/csv_util.py +++ /dev/null
@@ -1,53 +0,0 @@ -# Copyright 2016 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. - -import csv -import logging -import os - - -def CollectCSVsFromDirectory(directory_path, file_output): - """Collects recursively all .csv files from directory into one. - - Note: The list of CSV columns must be identical across all files. - - Args: - directory_path: Path of the directory to collect from. - file_output: File-like object to dump the CSV to. - """ - # List CSVs. - csv_list = [] - for root, _, files in os.walk(directory_path): - for file_name in files: - file_path = os.path.join(root, file_name) - if os.path.abspath(file_path) == os.path.abspath(file_output.name): - continue - if file_name.endswith('.csv'): - csv_list.append(os.path.join(root, file_name)) - if not csv_list: - logging.error('No CSV files found in %s' % directory_path) - return False - - # List rows. - csv_list.sort() - csv_field_names = None - csv_rows = [] - for csv_file in csv_list: - logging.info('collecting %s' % csv_file) - with open(csv_file) as csvfile: - reader = csv.DictReader(csvfile) - if csv_field_names is None: - csv_field_names = reader.fieldnames - else: - assert reader.fieldnames == csv_field_names, ( - 'Different field names in: {}'.format(csv_file)) - for row in reader: - csv_rows.append(row) - - # Export rows. - writer = csv.DictWriter(file_output, fieldnames=csv_field_names) - writer.writeheader() - for row in csv_rows: - writer.writerow(row) - return True
diff --git a/tools/android/loading/dag.py b/tools/android/loading/dag.py deleted file mode 100644 index 2eacd3ab..0000000 --- a/tools/android/loading/dag.py +++ /dev/null
@@ -1,116 +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. - -"""Support for directed acyclic graphs. - -Used in the ResourceGraph model for chrome loading. -""" - -class Node(object): - """A node in a DAG. - - We do not enforce at a node level that a graph is a DAG. Methods like - TopologicalSort will assume a DAG and may fail if that's not the case. - - Nodes are identified with an index that must be unique for a particular graph - (it is used for hashing and equality). A graph is represented as a list of - nodes, for example in the TopologicalSort class method. By convention a node's - index is its position in this list, making it easy to store auxillary - information. - """ - def __init__(self, index): - """Create a new node. - - Args: - index: index of the node. We assume these indicies uniquely identify a - node (and so use it for hashing and equality). - """ - self._predecessors = set() - self._successors = set() - self._index = index - - def Predecessors(self): - return self._predecessors - - def Successors(self): - return self._successors - - def AddSuccessor(self, s): - """Add a successor. - - Updates appropriate links. Any existing parents of s are unchanged; to move - a node you must do a combination of RemoveSuccessor and AddSuccessor. - - Args: - s: the node to add as a successor. - """ - self._successors.add(s) - s._predecessors.add(self) - - def RemoveSuccessor(self, s): - """Removes a successor. - - Updates appropriate links. - - Args: - s: the node to remove as a successor. Will raise a set exception if s is - not an existing successor. - """ - self._successors.remove(s) - s._predecessors.remove(self) - - def SortedSuccessors(self): - children = [c for c in self.Successors()] - children.sort(key=lambda c: c.Index()) - return children - - def Index(self): - return self._index - - def __eq__(self, o): - return self.Index() == o.Index() - - def __hash__(self): - return hash(self.Index()) - - -def TopologicalSort(nodes, node_filter=None): - """Topological sort. - - We use a BFS-like walk which ensures that sibling are always grouped - together in the output. This is more convenient for some later analyses. - - Args: - nodes: [Node, ...] Nodes to sort. - node_filter: a filter Node->boolean to restrict the graph. A node passes the - filter on a return value of True. Only the subgraph reachable from a root - passing the filter is considered. - - Returns: - A list of Nodes in topological order. Note that node indicies are - unchanged; the original list nodes is not modified. - """ - if node_filter is None: - node_filter = lambda _: True - sorted_nodes = [] - sources = [] - remaining_in_edges = {} - for n in nodes: - if n.Predecessors(): - remaining_in_edges[n] = len(n.Predecessors()) - elif node_filter(n): - sources.append(n) - while sources: - n = sources.pop(0) - assert node_filter(n) - sorted_nodes.append(n) - # We sort by index to get consistent sorts across runs/machines. - for c in n.SortedSuccessors(): - assert remaining_in_edges[c] > 0 - if not node_filter(c): - continue - remaining_in_edges[c] -= 1 - if not remaining_in_edges[c]: - sources.append(c) - return sorted_nodes
diff --git a/tools/android/loading/dag_unittest.py b/tools/android/loading/dag_unittest.py deleted file mode 100644 index 6701c9e..0000000 --- a/tools/android/loading/dag_unittest.py +++ /dev/null
@@ -1,92 +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. - -import os -import sys -import unittest - -import dag - -class DagTestCase(unittest.TestCase): - - def MakeDag(self, links): - """Make a graph from a description of links. - - Args: - links: A list of (index, (successor index...)) tuples. Index must equal - the location of the tuple in the list and are provided to make it easier - to read. - - Returns: - A list of Nodes. - """ - nodes = [] - for i in xrange(len(links)): - assert i == links[i][0] - nodes.append(dag.Node(i)) - for l in links: - for s in l[1]: - nodes[l[0]].AddSuccessor(nodes[s]) - return nodes - - def SortedIndicies(self, graph, node_filter=None): - return [n.Index() for n in dag.TopologicalSort(graph, node_filter)] - - def SuccessorIndicies(self, node): - return [c.Index() for c in node.SortedSuccessors()] - - def test_SimpleSorting(self): - graph = self.MakeDag([(0, (1,2)), - (1, (3,)), - (2, ()), - (3, (4,)), - (4, ()), - (5, (6,)), - (6, ())]) - self.assertEqual(self.SuccessorIndicies(graph[0]), [1, 2]) - self.assertEqual(self.SuccessorIndicies(graph[1]), [3]) - self.assertEqual(self.SuccessorIndicies(graph[2]), []) - self.assertEqual(self.SuccessorIndicies(graph[3]), [4]) - self.assertEqual(self.SuccessorIndicies(graph[4]), []) - self.assertEqual(self.SuccessorIndicies(graph[5]), [6]) - self.assertEqual(self.SuccessorIndicies(graph[6]), []) - self.assertEqual(self.SortedIndicies(graph), [0, 5, 1, 2, 6, 3, 4]) - - def test_SortSiblingsAreGrouped(self): - graph = self.MakeDag([(0, (1, 2, 3)), - (1, (4,)), - (2, (5, 6)), - (3, (7, 8)), - (4, ()), - (5, ()), - (6, ()), - (7, ()), - (8, ())]) - self.assertEqual(self.SortedIndicies(graph), [0, 1, 2, 3, 4, 5, 6, 7, 8]) - - def test_FilteredSorting(self): - # 0 is a filtered-out root, which means the subgraph containing 1, 2, 3 and - # 4 should be ignored. 5 is an unfiltered root, and the subgraph containing - # 6, 7, 8 and 10 should be sorted. 9 and 11 are filtered out, and should - # exclude the unfiltred node 12. - graph = self.MakeDag([(0, (1,)), - (1, (2, 3)), - (2, ()), - (3, (4,)), - (4, ()), - (5, (6, 7)), - (6, (11,)), - (7, (8,)), - (8, (9, 10)), - (9, ()), - (10, ()), - (11, (12,)), - (12, ())]) - self.assertEqual(self.SortedIndicies( - graph, lambda n: n.Index() not in (0, 3, 9, 11)), - [5, 6, 7, 8, 10]) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/dependency_graph.py b/tools/android/loading/dependency_graph.py deleted file mode 100644 index a2c1f17..0000000 --- a/tools/android/loading/dependency_graph.py +++ /dev/null
@@ -1,243 +0,0 @@ -# Copyright 2016 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. - -"""Request dependency graph.""" - -import logging -import sys - -import common_util -import graph -import request_track - - -class RequestNode(graph.Node): - def __init__(self, request=None): - super(RequestNode, self).__init__() - self.request = request - self.cost = request.Cost() if request else None # Deserialization. - - def ToJsonDict(self): - json_dict = super(RequestNode, self).ToJsonDict() - json_dict.update({'request': self.request.ToJsonDict()}) - return json_dict - - @classmethod - def FromJsonDict(cls, json_dict): - result = super(RequestNode, cls).FromJsonDict(json_dict) - result.request = request_track.Request.FromJsonDict(json_dict['request']) - return common_util.DeserializeAttributesFromJsonDict( - json_dict, result, ['cost']) - - -class Edge(graph.Edge): - def __init__(self, from_node, to_node, reason=None): - super(Edge, self).__init__(from_node, to_node) - self.reason = reason - self.cost = None - self.is_timing = None - if from_node is None: # Deserialization. - return - self.reason = reason - self.cost = request_track.TimeBetween( - self.from_node.request, self.to_node.request, self.reason) - self.is_timing = False - - def ToJsonDict(self): - result = {} - return common_util.SerializeAttributesToJsonDict( - result, self, ['reason', 'cost', 'is_timing']) - - @classmethod - def FromJsonDict(cls, json_dict): - result = cls(None, None, None) - return common_util.DeserializeAttributesFromJsonDict( - json_dict, result, ['reason', 'cost', 'is_timing']) - - -class RequestDependencyGraph(object): - """Request dependency graph.""" - # This resource type may induce a timing dependency. See _SplitChildrenByTime - # for details. - # TODO(lizeb,mattcary): are these right? - _CAN_BE_TIMING_PARENT = set(['script', 'magic-debug-content']) - _CAN_MAKE_TIMING_DEPENDENCE = set(['json', 'other', 'magic-debug-content']) - - def __init__(self, requests, dependencies_lens, - node_class=RequestNode, edge_class=Edge): - """Creates a request dependency graph. - - Args: - requests: ([Request]) a list of requests. - dependencies_lens: (RequestDependencyLens) - node_class: (subclass of RequestNode) - edge_class: (subclass of Edge) - """ - self._requests = None - self._first_request_node = None - self._deps_graph = None - self._nodes_by_id = None - if requests is None: # Deserialization. - return - assert issubclass(node_class, RequestNode) - assert issubclass(edge_class, Edge) - self._requests = requests - deps = dependencies_lens.GetRequestDependencies() - self._nodes_by_id = {r.request_id : node_class(r) for r in self._requests} - edges = [] - for (parent_request, child_request, reason) in deps: - if (parent_request.request_id not in self._nodes_by_id - or child_request.request_id not in self._nodes_by_id): - continue - parent_node = self._nodes_by_id[parent_request.request_id] - child_node = self._nodes_by_id[child_request.request_id] - edges.append(edge_class(parent_node, child_node, reason)) - self._first_request_node = self._nodes_by_id[self._requests[0].request_id] - self._deps_graph = graph.DirectedGraph(self._nodes_by_id.values(), edges) - self._HandleTimingDependencies() - - @property - def graph(self): - """Return the Graph we're based on.""" - return self._deps_graph - - def UpdateRequestsCost(self, request_id_to_cost): - """Updates the cost of the nodes identified by their request ID. - - Args: - request_id_to_cost: ({request_id: new_cost}) Can be a superset of the - requests actually present in the graph. - """ - for node in self._deps_graph.Nodes(): - request_id = node.request.request_id - if request_id in request_id_to_cost: - node.cost = request_id_to_cost[request_id] - - def Cost(self, from_first_request=True, path_list=None, costs_out=None): - """Returns the cost of the graph, that is the costliest path. - - Args: - from_first_request: (boolean) If True, only considers paths that originate - from the first request node. - path_list: (list) See graph.Cost(). - costs_out: (list) See graph.Cost(). - """ - if from_first_request: - return self._deps_graph.Cost( - [self._first_request_node], path_list, costs_out) - else: - return self._deps_graph.Cost(path_list=path_list, costs_out=costs_out) - - def AncestorRequests(self, descendants): - """Return requests that are ancestors of a set of requests. - - Args: - descendants: ([Request]) List of requests. - - Returns: - List of Requests that are ancestors of descendants. - """ - return [n.request for n in self.graph.AncestorNodes( - self._nodes_by_id[r.request_id] for r in descendants)] - - def _HandleTimingDependencies(self): - try: - for n in self._deps_graph.TopologicalSort(): - self._SplitChildrenByTime(n) - except AssertionError as exc: - sys.stderr.write('Bad topological sort: %s\n' - 'Skipping child split\n' % str(exc)) - - def _SplitChildrenByTime(self, parent): - """Splits children of a node by request times. - - The initiator of a request may not be the true dependency of a request. For - example, a script may appear to load several resources independently, but in - fact one of them may be a JSON data file, and the remaining resources assets - described in the JSON. The assets should be dependent upon the JSON data - file, and not the original script. - - This function approximates that by rearranging the children of a node - according to their request times. The predecessor of each child is made to - be the node with the greatest finishing time, that is before the start time - of the child. - - We do this by sorting the nodes twice, once by start time and once by end - time. We mark the earliest end time, and then we walk the start time list, - advancing the end time mark when it is less than our current start time. - - This is refined by only considering assets which we believe actually create - a dependency. We only split if the original parent is a script, and the new - parent a data file. - We incorporate this heuristic by skipping over any non-script/json resources - when moving the end mark. - - TODO(mattcary): More heuristics, like incorporating cachability somehow, and - not just picking arbitrarily if there are two nodes with the same end time - (does that ever really happen?) - - Args: - parent: (_RequestNode) The children of this node are processed by this - function. - """ - if parent.request.GetContentType() not in self._CAN_BE_TIMING_PARENT: - return - edges = self._deps_graph.OutEdges(parent) - edges_by_start_time = sorted( - edges, key=lambda e: e.to_node.request.start_msec) - edges_by_end_time = sorted( - edges, key=lambda e: e.to_node.request.end_msec) - end_mark = 0 - for current in edges_by_start_time: - assert current.from_node is parent - if current.to_node.request.start_msec < parent.request.end_msec - 1e-5: - parent_url = parent.request.url - child_url = current.to_node.request.url - logging.warning('Child loaded before parent finished: %s -> %s', - request_track.ShortName(parent_url), - request_track.ShortName(child_url)) - go_to_next_child = False - while end_mark < len(edges_by_end_time): - if edges_by_end_time[end_mark] == current: - go_to_next_child = True - break - elif (edges_by_end_time[end_mark].to_node.request.GetContentType() - not in self._CAN_MAKE_TIMING_DEPENDENCE): - end_mark += 1 - elif (end_mark < len(edges_by_end_time) - 1 and - edges_by_end_time[end_mark + 1].to_node.request.end_msec - < current.to_node.request.start_msec): - end_mark += 1 - else: - break - if end_mark >= len(edges_by_end_time): - break # It's not possible to rearrange any more children. - if go_to_next_child: - continue # We can't rearrange this child, but the next child may be - # eligible. - if (edges_by_end_time[end_mark].to_node.request.end_msec - <= current.to_node.request.start_msec): - current.is_timing = True - self._deps_graph.UpdateEdge( - current, edges_by_end_time[end_mark].to_node, - current.to_node) - - def ToJsonDict(self): - result = {'graph': self.graph.ToJsonDict()} - result['requests'] = [r.ToJsonDict() for r in self._requests] - return result - - @classmethod - def FromJsonDict(cls, json_dict, node_class, edge_class): - result = cls(None, None) - graph_dict = json_dict['graph'] - g = graph.DirectedGraph.FromJsonDict(graph_dict, node_class, edge_class) - result._requests = [request_track.Request.FromJsonDict(r) - for r in json_dict['requests']] - result._nodes_by_id = {node.request.request_id: node - for node in g.Nodes()} - result._first_request_node = result._nodes_by_id[ - result._requests[0].request_id] - result._deps_graph = g - return result
diff --git a/tools/android/loading/dependency_graph_unittest.py b/tools/android/loading/dependency_graph_unittest.py deleted file mode 100644 index 23441f4b..0000000 --- a/tools/android/loading/dependency_graph_unittest.py +++ /dev/null
@@ -1,164 +0,0 @@ -# Copyright 2016 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. - -import unittest - -import dependency_graph -import request_dependencies_lens -from request_dependencies_lens_unittest import TestRequests -import request_track -import test_utils - - -class RequestDependencyGraphTestCase(unittest.TestCase): - def setUp(self): - super(RequestDependencyGraphTestCase, self).setUp() - self.trace = TestRequests.CreateLoadingTrace() - - def testUpdateRequestCost(self, serialize=False): - requests = self.trace.request_track.GetEvents() - requests[0].timing = request_track.Timing.FromDevToolsDict( - {'requestTime': 12, 'loadingFinished': 10}) - dependencies_lens = request_dependencies_lens.RequestDependencyLens( - self.trace) - g = dependency_graph.RequestDependencyGraph(requests, dependencies_lens) - if serialize: - g = self._SerializeDeserialize(g) - self.assertEqual(10, g.Cost()) - request_id = requests[0].request_id - g.UpdateRequestsCost({request_id: 100}) - self.assertEqual(100, g.Cost()) - g.UpdateRequestsCost({'unrelated_id': 1000}) - self.assertEqual(100, g.Cost()) - - def testCost(self, serialize=False): - requests = self.trace.request_track.GetEvents() - for (index, request) in enumerate(requests): - request.timing = request_track.Timing.FromDevToolsDict( - {'requestTime': index, 'receiveHeadersEnd': 10, - 'loadingFinished': 10}) - dependencies_lens = request_dependencies_lens.RequestDependencyLens( - self.trace) - g = dependency_graph.RequestDependencyGraph(requests, dependencies_lens) - if serialize: - g = self._SerializeDeserialize(g) - # First redirect -> Second redirect -> Redirected Request -> Request -> - # JS Request 2 - self.assertEqual(7010, g.Cost()) - # Not on the critical path - g.UpdateRequestsCost({TestRequests.JS_REQUEST.request_id: 0}) - self.assertEqual(7010, g.Cost()) - g.UpdateRequestsCost({TestRequests.FIRST_REDIRECT_REQUEST.request_id: 0}) - self.assertEqual(7000, g.Cost()) - g.UpdateRequestsCost({TestRequests.SECOND_REDIRECT_REQUEST.request_id: 0}) - self.assertEqual(6990, g.Cost()) - - def testHandleTimingDependencies(self, serialize=False): - # Timing adds node 1 as a parent to 2 but not 3. - requests = [ - test_utils.MakeRequest(0, 'null', 100, 110, 110, - magic_content_type=True), - test_utils.MakeRequest(1, 0, 115, 120, 120, - magic_content_type=True), - test_utils.MakeRequest(2, 0, 121, 122, 122, - magic_content_type=True), - test_utils.MakeRequest(3, 0, 112, 119, 119, - magic_content_type=True), - test_utils.MakeRequest(4, 2, 122, 126, 126), - test_utils.MakeRequest(5, 2, 122, 126, 126)] - - g = self._GraphFromRequests(requests) - if serialize: - g = self._SerializeDeserialize(g) - self.assertSetEqual( - self._Successors(g, requests[0]), set([requests[1], requests[3]])) - self.assertSetEqual( - self._Successors(g, requests[1]), set([requests[2]])) - self.assertSetEqual( - self._Successors(g, requests[2]), set([requests[4], requests[5]])) - self.assertSetEqual(self._Successors(g, requests[3]), set()) - self.assertSetEqual(self._Successors(g, requests[4]), set()) - self.assertSetEqual(self._Successors(g, requests[5]), set()) - - # Change node 1 so it is a parent of 3, which becomes the parent of 2. - requests[1] = test_utils.MakeRequest( - 1, 0, 110, 111, 111, magic_content_type=True) - g = self._GraphFromRequests(requests) - self.assertSetEqual(self._Successors(g, requests[0]), set([requests[1]])) - self.assertSetEqual(self._Successors(g, requests[1]), set([requests[3]])) - self.assertSetEqual(self._Successors(g, requests[2]), - set([requests[4], requests[5]])) - self.assertSetEqual(self._Successors(g, requests[3]), set([requests[2]])) - self.assertSetEqual(self._Successors(g, requests[4]), set()) - self.assertSetEqual(self._Successors(g, requests[5]), set()) - - # Add an initiator dependence to 1 that will become the parent of 3. - requests[1] = test_utils.MakeRequest( - 1, 0, 110, 111, 111, magic_content_type=True) - requests.append(test_utils.MakeRequest(6, 1, 111, 112, 112)) - g = self._GraphFromRequests(requests) - # Check it doesn't change until we change the content type of 6. - self.assertEqual(self._Successors(g, requests[6]), set()) - requests[6] = test_utils.MakeRequest(6, 1, 111, 112, 112, - magic_content_type=True) - g = self._GraphFromRequests(requests) - self.assertSetEqual(self._Successors(g, requests[0]), set([requests[1]])) - self.assertSetEqual(self._Successors(g, requests[1]), set([requests[6]])) - self.assertSetEqual(self._Successors(g, requests[2]), - set([requests[4], requests[5]])) - self.assertSetEqual(self._Successors(g, requests[3]), set([requests[2]])) - self.assertSetEqual(self._Successors(g, requests[4]), set()) - self.assertSetEqual(self._Successors(g, requests[5]), set()) - self.assertSetEqual(self._Successors(g, requests[6]), set([requests[3]])) - - def testHandleTimingDependenciesImages(self, serialize=False): - # If we're all image types, then we shouldn't split by timing. - requests = [test_utils.MakeRequest(0, 'null', 100, 110, 110), - test_utils.MakeRequest(1, 0, 115, 120, 120), - test_utils.MakeRequest(2, 0, 121, 122, 122), - test_utils.MakeRequest(3, 0, 112, 119, 119), - test_utils.MakeRequest(4, 2, 122, 126, 126), - test_utils.MakeRequest(5, 2, 122, 126, 126)] - for r in requests: - r.response_headers['Content-Type'] = 'image/gif' - g = self._GraphFromRequests(requests) - if serialize: - g = self._SerializeDeserialize(g) - self.assertSetEqual(self._Successors(g, requests[0]), - set([requests[1], requests[2], requests[3]])) - self.assertSetEqual(self._Successors(g, requests[1]), set()) - self.assertSetEqual(self._Successors(g, requests[2]), - set([requests[4], requests[5]])) - self.assertSetEqual(self._Successors(g, requests[3]), set()) - self.assertSetEqual(self._Successors(g, requests[4]), set()) - self.assertSetEqual(self._Successors(g, requests[5]), set()) - - def testSerializeDeserialize(self): - # Redo the tests, with a graph that has been serialized / deserialized. - self.testUpdateRequestCost(True) - self.testCost(True) - self.testHandleTimingDependencies(True) - self.testHandleTimingDependenciesImages(True) - - @classmethod - def _SerializeDeserialize(cls, g): - json_dict = g.ToJsonDict() - return dependency_graph.RequestDependencyGraph.FromJsonDict( - json_dict, dependency_graph.RequestNode, dependency_graph.Edge) - - @classmethod - def _GraphFromRequests(cls, requests): - trace = test_utils.LoadingTraceFromEvents(requests) - deps_lens = test_utils.SimpleLens(trace) - return dependency_graph.RequestDependencyGraph(requests, deps_lens) - - @classmethod - def _Successors(cls, g, parent_request): - parent_node = g._nodes_by_id[parent_request.request_id] - edges = g._deps_graph.OutEdges(parent_node) - return set(e.to_node.request for e in edges) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/device_setup.py b/tools/android/loading/device_setup.py deleted file mode 100644 index cfa19bf0..0000000 --- a/tools/android/loading/device_setup.py +++ /dev/null
@@ -1,411 +0,0 @@ -# Copyright 2016 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. - -import collections -import contextlib -import logging -import os -import shutil -import subprocess -import sys -import tempfile -import time - -_SRC_DIR = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..', '..', '..')) - -_CATAPULT_DIR = os.path.join(_SRC_DIR, 'third_party', 'catapult') -sys.path.append(os.path.join(_CATAPULT_DIR, 'devil')) -from devil.android import device_utils -from devil.android import forwarder -from devil.android.sdk import adb_wrapper -from devil.android.sdk import intent -from devil.android.sdk import keyevent - -sys.path.append(os.path.join(_SRC_DIR, 'build', 'android')) -from pylib import constants -from video_recorder import video_recorder - -sys.path.append(os.path.join(_SRC_DIR, 'tools', 'perf')) -from core import path_util -sys.path.append(path_util.GetTelemetryDir()) - -from telemetry.internal.image_processing import video -from telemetry.internal.util import wpr_server - -sys.path.append(os.path.join( - _CATAPULT_DIR, 'telemetry', 'third_party', 'webpagereplay')) -import adb_install_cert -import certutils - -import common_util -import devtools_monitor -import emulation -import options - - -OPTIONS = options.OPTIONS - -# The speed index's video recording's bit rate in Mb/s. -_SPEED_INDEX_VIDEO_BITRATE = 4 - - -class DeviceSetupException(Exception): - def __init__(self, msg): - super(DeviceSetupException, self).__init__(msg) - logging.error(msg) - - -def GetFirstDevice(): - """Returns the first connected device. - - Raises: - DeviceSetupException if there is no such device. - """ - devices = device_utils.DeviceUtils.HealthyDevices() - if not devices: - raise DeviceSetupException('No devices found') - return devices[0] - - -def GetDeviceFromSerial(android_device_serial): - """Returns the DeviceUtils instance.""" - devices = device_utils.DeviceUtils.HealthyDevices() - for device in devices: - if device.adb._device_serial == android_device_serial: - return device - raise DeviceSetupException( - 'Device {} not found'.format(android_device_serial)) - - -def Reboot(device): - """Reboot the device. - - Args: - device: Device to reboot, from DeviceUtils. - """ - # Kills the device -> host forwarder running on the device so that - # forwarder.Forwarder have correct state tracking after having rebooted. - forwarder.Forwarder.UnmapAllDevicePorts(device) - # Reboot the device. - device.Reboot() - # Pass through the lock screen. - time.sleep(3) - device.SendKeyEvent(keyevent.KEYCODE_MENU) - - -def DeviceSubmitShellCommandQueue(device, command_queue): - """Executes on the device a command queue. - - Args: - device: The device to execute the shell commands to. - command_queue: a list of commands to be executed in that order. - """ - REMOTE_COMMAND_FILE_PATH = '/data/local/tmp/adb_command_file.sh' - if not command_queue: - return - with tempfile.NamedTemporaryFile(prefix='adb_command_file_', - suffix='.sh') as command_file: - command_file.write('#!/bin/sh\n') - command_file.write('# Shell file generated by {}\'s {}\n'.format( - __file__, DeviceSubmitShellCommandQueue.__name__)) - command_file.write('set -e\n') - for command in command_queue: - command_file.write(subprocess.list2cmdline(command) + ' ;\n') - command_file.write('exit 0;\n'.format( - REMOTE_COMMAND_FILE_PATH)) - command_file.flush() - device.adb.Push(command_file.name, REMOTE_COMMAND_FILE_PATH) - device.adb.Shell('sh {p} && rm {p}'.format(p=REMOTE_COMMAND_FILE_PATH)) - - -@contextlib.contextmanager -def ForwardPort(device, local, remote): - """Forwards a local port to a remote one on a device in a context.""" - # If we're logging requests from a local desktop chrome instance there is no - # device. - if not device: - yield - return - device.adb.Forward(local, remote) - try: - yield - finally: - device.adb.ForwardRemove(local) - - -# WPR specific attributes to set up chrome. -# -# Members: -# chrome_args: Additional flags list that may be used for chromium to load web -# page through the running web page replay host. -# chrome_env_override: Dictionary of environment variables to override at -# Chrome's launch time. -WprAttribute = collections.namedtuple('WprAttribute', - ['chrome_args', 'chrome_env_override']) - - -@contextlib.contextmanager -def _WprHost(wpr_archive_path, record=False, - network_condition_name=None, - disable_script_injection=False, - wpr_ca_cert_path=None, - out_log_path=None): - assert wpr_archive_path - - def PathWorkaround(path): - # webpagereplay.ReplayServer is doing a os.path.exist(os.path.dirname(p)) - # that fails if p = 'my_file.txt' because os.path.dirname(p) = '' != '.'. - # This workaround just sends absolute path to work around this bug. - return os.path.abspath(path) - - wpr_server_args = ['--use_closest_match'] - if record: - wpr_server_args.append('--record') - if os.path.exists(wpr_archive_path): - os.remove(wpr_archive_path) - else: - assert os.path.exists(wpr_archive_path) - if network_condition_name: - condition = emulation.NETWORK_CONDITIONS[network_condition_name] - if record: - logging.warning('WPR network condition is ignored when recording.') - else: - wpr_server_args.extend([ - '--down', emulation.BandwidthToString(condition['download']), - '--up', emulation.BandwidthToString(condition['upload']), - '--delay_ms', str(condition['latency']), - '--shaping_type', 'proxy']) - - if disable_script_injection: - # Remove default WPR injected scripts like deterministic.js which - # overrides Math.random. - wpr_server_args.extend(['--inject_scripts', '']) - if wpr_ca_cert_path: - wpr_server_args.extend(['--should_generate_certs', - '--https_root_ca_cert_path=' + PathWorkaround(wpr_ca_cert_path)]) - if out_log_path: - # --log_level debug to extract the served URLs requests from the log. - wpr_server_args.extend(['--log_level', 'debug', - '--log_file', PathWorkaround(out_log_path)]) - # Don't append to previously existing log. - if os.path.exists(out_log_path): - os.remove(out_log_path) - - # Set up WPR server and device forwarder. - server = wpr_server.ReplayServer(PathWorkaround(wpr_archive_path), - '127.0.0.1', 0, 0, None, wpr_server_args) - http_port, https_port = server.StartServer()[:-1] - - logging.info('WPR server listening on HTTP=%s, HTTPS=%s (options=%s)' % ( - http_port, https_port, wpr_server_args)) - try: - yield http_port, https_port - finally: - server.StopServer() - - -def _VerifySilentWprHost(record, network_condition_name): - assert not record, 'WPR cannot record without a specified archive.' - assert not network_condition_name, ('WPR cannot emulate network condition' + - ' without a specified archive.') - - -def _FormatWPRRelatedChromeArgumentFor(http_port, https_port): - HOST_RULES='MAP * 127.0.0.1,EXCLUDE localhost' - return [ - '--testing-fixed-http-port={}'.format(http_port), - '--testing-fixed-https-port={}'.format(https_port), - '--host-resolver-rules={}'.format(HOST_RULES)] - - -@contextlib.contextmanager -def LocalWprHost(wpr_archive_path, record=False, - network_condition_name=None, - disable_script_injection=False, - out_log_path=None): - """Launches web page replay host. - - Args: - wpr_archive_path: host sided WPR archive's path. - record: Enables or disables WPR archive recording. - network_condition_name: Network condition name available in - emulation.NETWORK_CONDITIONS. - disable_script_injection: Disable JavaScript file injections that is - fighting against resources name entropy. - out_log_path: Path of the WPR host's log. - - Returns: - WprAttribute - """ - if wpr_archive_path == None: - _VerifySilentWprHost(record, network_condition_name) - yield [] - return - - with common_util.TemporaryDirectory() as temp_home_dir: - # Generate a root certification authority certificate for WPR. - private_ca_cert_path = os.path.join(temp_home_dir, 'wpr.pem') - ca_cert_path = os.path.join(temp_home_dir, 'wpr-cert.pem') - certutils.write_dummy_ca_cert(*certutils.generate_dummy_ca_cert(), - cert_path=private_ca_cert_path) - assert os.path.isfile(ca_cert_path) - certutils.install_cert_in_nssdb(temp_home_dir, ca_cert_path) - - with _WprHost( - wpr_archive_path, - record=record, - network_condition_name=network_condition_name, - disable_script_injection=disable_script_injection, - wpr_ca_cert_path=private_ca_cert_path, - out_log_path=out_log_path) as (http_port, https_port): - chrome_args = _FormatWPRRelatedChromeArgumentFor(http_port, https_port) - yield WprAttribute(chrome_args=chrome_args, - chrome_env_override={'HOME': temp_home_dir}) - - -@contextlib.contextmanager -def RemoteWprHost(device, wpr_archive_path, record=False, - network_condition_name=None, - disable_script_injection=False, - out_log_path=None): - """Launches web page replay host. - - Args: - device: Android device. - wpr_archive_path: host sided WPR archive's path. - record: Enables or disables WPR archive recording. - network_condition_name: Network condition name available in - emulation.NETWORK_CONDITIONS. - disable_script_injection: Disable JavaScript file injections that is - fighting against resources name entropy. - out_log_path: Path of the WPR host's log. - - Returns: - WprAttribute - """ - assert device - if wpr_archive_path == None: - _VerifySilentWprHost(record, network_condition_name) - yield [] - return - # Deploy certification authority to the device. - temp_certificate_dir = tempfile.mkdtemp() - wpr_ca_cert_path = os.path.join(temp_certificate_dir, 'testca.pem') - certutils.write_dummy_ca_cert(*certutils.generate_dummy_ca_cert(), - cert_path=wpr_ca_cert_path) - device_cert_util = adb_install_cert.AndroidCertInstaller( - device.adb.GetDeviceSerial(), None, wpr_ca_cert_path, - adb_wrapper.AdbWrapper.GetAdbPath()) - device_cert_util.install_cert(overwrite_cert=True) - try: - # Set up WPR server - with _WprHost( - wpr_archive_path, - record=record, - network_condition_name=network_condition_name, - disable_script_injection=disable_script_injection, - wpr_ca_cert_path=wpr_ca_cert_path, - out_log_path=out_log_path) as (http_port, https_port): - # Set up the forwarder. - forwarder.Forwarder.Map([(0, http_port), (0, https_port)], device) - device_http_port = forwarder.Forwarder.DevicePortForHostPort(http_port) - device_https_port = forwarder.Forwarder.DevicePortForHostPort(https_port) - try: - chrome_args = _FormatWPRRelatedChromeArgumentFor(device_http_port, - device_https_port) - yield WprAttribute(chrome_args=chrome_args, chrome_env_override={}) - finally: - # Tear down the forwarder. - forwarder.Forwarder.UnmapDevicePort(device_http_port, device) - forwarder.Forwarder.UnmapDevicePort(device_https_port, device) - finally: - # Remove certification authority from the device. - device_cert_util.remove_cert() - shutil.rmtree(temp_certificate_dir) - - -# Deprecated -@contextlib.contextmanager -def _RemoteVideoRecorder(device, local_output_path, megabits_per_second): - """Record a video on Device. - - Args: - device: (device_utils.DeviceUtils) Android device to connect to. - local_output_path: Output path were to save the video locally. - megabits_per_second: Video recorder Mb/s. - - Yields: - None - """ - assert device - if megabits_per_second > 100: - raise ValueError('Android video capture cannot capture at %dmbps. ' - 'Max capture rate is 100mbps.' % megabits_per_second) - assert local_output_path.endswith('.mp4') - recorder = video_recorder.VideoRecorder(device, megabits_per_second) - recorder.Start() - try: - yield - recorder.Stop() - recorder.Pull(host_file=local_output_path) - recorder = None - finally: - if recorder: - recorder.Stop() - - -@contextlib.contextmanager -def RemoteSpeedIndexRecorder(device, connection, local_output_path): - """Records on a device a video compatible for speed-index computation. - - Note: - Chrome should be opened with the --disable-infobars command line argument to - avoid web page viewport size to be changed, that can change speed-index - value. - - Args: - device: (device_utils.DeviceUtils) Android device to connect to. - connection: devtools connection. - local_output_path: Output path were to save the video locally. - - Yields: - None - """ - # Paint the current HTML document with the ORANGE that video is detecting with - # the view-port position and size. - color = video.HIGHLIGHT_ORANGE_FRAME - connection.ExecuteJavaScript(""" - (function() { - var screen = document.createElement('div'); - screen.style.background = 'rgb(%d, %d, %d)'; - screen.style.position = 'fixed'; - screen.style.top = '0'; - screen.style.left = '0'; - screen.style.width = '100%%'; - screen.style.height = '100%%'; - screen.style.zIndex = '2147483638'; - document.body.appendChild(screen); - requestAnimationFrame(function() { - requestAnimationFrame(function() { - window.__speedindex_screen = screen; - }); - }); - })(); - """ % (color.r, color.g, color.b)) - connection.PollForJavaScriptExpression('!!window.__speedindex_screen', 1) - - with _RemoteVideoRecorder(device, local_output_path, - megabits_per_second=_SPEED_INDEX_VIDEO_BITRATE): - # Paint the current HTML document with white so that it is not troubling the - # speed index measurement. - connection.ExecuteJavaScript(""" - (function() { - requestAnimationFrame(function() { - var screen = window.__speedindex_screen; - screen.style.background = 'rgb(255, 255, 255)'; - }); - })(); - """) - yield
diff --git a/tools/android/loading/devtools_monitor.py b/tools/android/loading/devtools_monitor.py deleted file mode 100644 index 6a5ed10..0000000 --- a/tools/android/loading/devtools_monitor.py +++ /dev/null
@@ -1,494 +0,0 @@ -# Copyright (c) 2016 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. - -"""Library handling DevTools websocket interaction. -""" - -import datetime -import httplib -import json -import logging -import os -import sys -import time - -file_dir = os.path.dirname(__file__) -sys.path.append(os.path.join(file_dir, '..', '..', 'perf')) -from core import path_util -sys.path.append(path_util.GetTelemetryDir()) - -from telemetry.internal.backends.chrome_inspector import inspector_websocket -from telemetry.internal.backends.chrome_inspector import websocket - -import common_util - - -DEFAULT_TIMEOUT_SECONDS = 10 - -_WEBSOCKET_TIMEOUT_SECONDS = 10 - - -class DevToolsConnectionException(Exception): - def __init__(self, message): - super(DevToolsConnectionException, self).__init__(message) - logging.warning("DevToolsConnectionException: " + message) - -class DevToolsConnectionTargetCrashed(DevToolsConnectionException): - pass - - -# Taken from telemetry.internal.backends.chrome_inspector.tracing_backend. -# TODO(mattcary): combine this with the above and export? -class _StreamReader(object): - def __init__(self, inspector, stream_handle): - self._inspector_websocket = inspector - self._handle = stream_handle - self._callback = None - self._data = None - - def Read(self, callback): - # Do not allow the instance of this class to be reused, as - # we only read data sequentially at the moment, so a stream - # can only be read once. - assert not self._callback - self._data = [] - self._callback = callback - self._ReadChunkFromStream() - # Queue one extra read ahead to avoid latency. - self._ReadChunkFromStream() - - def _ReadChunkFromStream(self): - # Limit max block size to avoid fragmenting memory in sock.recv(), - # (see https://github.com/liris/websocket-client/issues/163 for details) - req = {'method': 'IO.read', 'params': { - 'handle': self._handle, 'size': 32768}} - self._inspector_websocket.AsyncRequest(req, self._GotChunkFromStream) - - def _GotChunkFromStream(self, response): - # Quietly discard responses from reads queued ahead after EOF. - if self._data is None: - return - if 'error' in response: - raise DevToolsConnectionException( - 'Reading trace failed: %s' % response['error']['message']) - result = response['result'] - self._data.append(result['data']) - if not result.get('eof', False): - self._ReadChunkFromStream() - return - req = {'method': 'IO.close', 'params': {'handle': self._handle}} - self._inspector_websocket.SendAndIgnoreResponse(req) - trace_string = ''.join(self._data) - self._data = None - self._callback(trace_string) - - -class DevToolsConnection(object): - """Handles the communication with a DevTools server. - """ - TRACING_DOMAIN = 'Tracing' - TRACING_END_METHOD = 'Tracing.end' - TRACING_DATA_METHOD = 'Tracing.dataCollected' - TRACING_DONE_EVENT = 'Tracing.tracingComplete' - TRACING_STREAM_EVENT = 'Tracing.tracingComplete' # Same as TRACING_DONE. - TRACING_TIMEOUT = 300 - HTTP_ATTEMPTS = 10 - HTTP_ATTEMPT_INTERVAL_SECONDS = 0.1 - - def __init__(self, hostname, port): - """Initializes the connection with a DevTools server. - - Args: - hostname: server hostname. - port: port number. - """ - self._http_hostname = hostname - self._http_port = port - self._event_listeners = {} - self._domain_listeners = {} - self._scoped_states = {} - self._domains_to_enable = set() - self._tearing_down_tracing = False - self._ws = None - self._target_descriptor = None - self._stop_delay_multiplier = 0 - self._monitoring_start_timestamp = None - self._monitoring_stop_timestamp = None - - self._Connect() - self.RegisterListener('Inspector.targetCrashed', self) - - def RegisterListener(self, name, listener): - """Registers a listener for an event. - - Also takes care of enabling the relevant domain before starting monitoring. - - Args: - name: (str) Domain or event the listener wants to listen to, e.g. - "Network.requestWillBeSent" or "Tracing". - listener: (Listener) listener instance. - """ - if '.' in name: - domain = name[:name.index('.')] - self._event_listeners[name] = listener - else: - domain = name - self._domain_listeners[domain] = listener - self._domains_to_enable.add(domain) - - def UnregisterListener(self, listener): - """Unregisters a listener. - - Args: - listener: (Listener) listener to unregister. - """ - keys = ([k for k, l in self._event_listeners if l is listener] + - [k for k, l in self._domain_listeners if l is listener]) - assert keys, "Removing non-existent listener" - for key in keys: - if key in self._event_listeners: - del(self._event_listeners[key]) - if key in self._domain_listeners: - del(self._domain_listeners[key]) - - def SetScopedState(self, method, params, default_params, enable_domain): - """Changes state at the beginning the monitoring and resets it at the end. - - |method| is called with |params| at the beginning of the monitoring. After - the monitoring completes, the state is reset by calling |method| with - |default_params|. - - Args: - method: (str) Method. - params: (dict) Parameters to set when the monitoring starts. - default_params: (dict) Parameters to reset the state at the end. - enable_domain: (bool) True if enabling the domain is required. - """ - if enable_domain: - if '.' in method: - domain = method[:method.index('.')] - assert domain, 'No valid domain' - self._domains_to_enable.add(domain) - scoped_state_value = (params, default_params) - if self._scoped_states.has_key(method): - assert self._scoped_states[method] == scoped_state_value - else: - self._scoped_states[method] = scoped_state_value - - def SyncRequest(self, method, params=None): - """Issues a synchronous request to the DevTools server. - - Args: - method: (str) Method. - params: (dict) Optional parameters to the request. - - Returns: - The answer. - """ - request = {'method': method} - if params: - request['params'] = params - return self._ws.SyncRequest(request, timeout=_WEBSOCKET_TIMEOUT_SECONDS) - - def SendAndIgnoreResponse(self, method, params=None): - """Issues a request to the DevTools server, do not wait for the response. - - Args: - method: (str) Method. - params: (dict) Optional parameters to the request. - """ - request = {'method': method} - if params: - request['params'] = params - self._ws.SendAndIgnoreResponse(request) - - def SyncRequestNoResponse(self, method, params=None): - """As SyncRequest, but asserts that no meaningful response was received. - - Args: - method: (str) Method. - params: (dict) Optional parameters to the request. - """ - result = self.SyncRequest(method, params) - if 'error' in result or ('result' in result and - result['result']): - raise DevToolsConnectionException( - 'Unexpected response for %s: %s' % (method, result)) - - def ClearCache(self): - """Clears buffer cache. - - Will assert that the browser supports cache clearing. - """ - res = self.SyncRequest('Network.canClearBrowserCache') - assert res['result'], 'Cache clearing is not supported by this browser.' - self.SyncRequest('Network.clearBrowserCache') - - def MonitorUrl(self, url, timeout_seconds=DEFAULT_TIMEOUT_SECONDS, - stop_delay_multiplier=0): - """Navigate to url and dispatch monitoring loop. - - Unless you have registered a listener that will call StopMonitoring, this - will run until timeout from chrome. - - Args: - url: (str) a URL to navigate to before starting monitoring loop. - timeout_seconds: timeout in seconds for monitoring loop. - stop_delay_multiplier: (float) How long to wait after page load completed - before tearing down, relative to the time it took to reach the page load - to complete. - """ - for domain in self._domains_to_enable: - self._ws.RegisterDomain(domain, self._OnDataReceived) - if domain != self.TRACING_DOMAIN: - self.SyncRequestNoResponse('%s.enable' % domain) - # Tracing setup must be done by the tracing track to control filtering - # and output. - for scoped_state in self._scoped_states: - self.SyncRequestNoResponse(scoped_state, - self._scoped_states[scoped_state][0]) - self._tearing_down_tracing = False - - logging.info('Navigate to %s' % url) - self.SendAndIgnoreResponse('Page.navigate', {'url': url}) - self._monitoring_start_timestamp = datetime.datetime.now() - self._Dispatch(timeout=timeout_seconds, - stop_delay_multiplier=stop_delay_multiplier) - self._monitoring_start_timestamp = None - logging.info('Tearing down monitoring.') - self._TearDownMonitoring() - - def StopMonitoring(self): - """Sets the timestamp when to stop monitoring. - - Args: - address_delayed_stop: Whether the MonitorUrl()'s stop_delay_multiplier - should be addressed or not. - """ - if self._stop_delay_multiplier == 0: - self._StopMonitoringImmediately() - elif self._monitoring_stop_timestamp is None: - assert self._monitoring_start_timestamp is not None - current_time = datetime.datetime.now() - stop_delay_duration_seconds = self._stop_delay_multiplier * ( - current_time - self._monitoring_start_timestamp).seconds - logging.info('Delaying monitoring stop for %.1fs', - stop_delay_duration_seconds) - self._monitoring_stop_timestamp = ( - current_time + datetime.timedelta( - seconds=stop_delay_duration_seconds)) - - def ExecuteJavaScript(self, expression): - """Run JavaScript expression. - - Args: - expression: JavaScript expression to run. - - Returns: - The return value from the JavaScript expression. - """ - # Note: Clients may be tempted to do naive string interpolation to inject - # Python values into the JavaScript expression, which could lead to syntax - # errors during evaluation (e.g. injecting strings with special characters). - # If this becomes an issue, consider extending the interface of this method - # as in: https://github.com/catapult-project/catapult/issues/3028 - response = self.SyncRequest('Runtime.evaluate', { - 'expression': expression, - 'returnByValue': True}) - if 'error' in response: - raise Exception(response['error']['message']) - if 'wasThrown' in response['result'] and response['result']['wasThrown']: - raise Exception(response['error']['result']['description']) - if response['result']['result']['type'] == 'undefined': - return None - return response['result']['result']['value'] - - def PollForJavaScriptExpression(self, expression, interval): - """Wait until JavaScript expression is true. - - Args: - expression: JavaScript expression to run. - interval: Period between expression evaluation in seconds. - """ - common_util.PollFor(lambda: bool(self.ExecuteJavaScript(expression)), - 'JavaScript: {}'.format(expression), - interval) - - def Close(self): - """Cleanly close chrome by closing the only tab.""" - assert self._ws - response = self._HttpRequest('/close/' + self._target_descriptor['id']) - assert response == 'Target is closing' - self._ws = None - - def _StopMonitoringImmediately(self): - self._monitoring_stop_timestamp = datetime.datetime.now() - - def _Dispatch(self, timeout, kind='Monitoring', stop_delay_multiplier=0): - self._monitoring_stop_timestamp = None - self._stop_delay_multiplier = stop_delay_multiplier - while True: - try: - self._ws.DispatchNotifications(timeout=timeout) - except websocket.WebSocketTimeoutException: - if self._monitoring_stop_timestamp is None: - logging.warning('%s stopped on a timeout.' % kind) - break - if self._monitoring_stop_timestamp: - # After the first timeout reduce the timeout to check when to stop - # monitoring more often, because the page at this moment can already be - # loaded and not many events would be arriving from it. - timeout = 1 - if datetime.datetime.now() >= self._monitoring_stop_timestamp: - break - - def Handle(self, method, event): - del event # unused - if method == 'Inspector.targetCrashed': - raise DevToolsConnectionTargetCrashed('Renderer crashed.') - - def _TearDownMonitoring(self): - if self.TRACING_DOMAIN in self._domains_to_enable: - logging.info('Fetching tracing') - self.SyncRequestNoResponse(self.TRACING_END_METHOD) - self._tearing_down_tracing = True - self._Dispatch(timeout=self.TRACING_TIMEOUT, kind='Tracing') - for scoped_state in self._scoped_states: - self.SyncRequestNoResponse(scoped_state, - self._scoped_states[scoped_state][1]) - for domain in self._domains_to_enable: - if domain != self.TRACING_DOMAIN: - self.SyncRequest('%s.disable' % domain) - self._ws.UnregisterDomain(domain) - self._domains_to_enable.clear() - self._domain_listeners.clear() - self._event_listeners.clear() - self._scoped_states.clear() - - def _OnDataReceived(self, msg): - if 'method' not in msg: - raise DevToolsConnectionException('Malformed message: %s' % msg) - method = msg['method'] - domain = method[:method.index('.')] - - if self._tearing_down_tracing and method == self.TRACING_STREAM_EVENT: - stream_handle = msg.get('params', {}).get('stream') - if not stream_handle: - self._tearing_down_tracing = False - self._StopMonitoringImmediately() - # Fall through to regular dispatching. - else: - _StreamReader(self._ws, stream_handle).Read(self._TracingStreamDone) - # Skip regular dispatching. - return - - if (method not in self._event_listeners and - domain not in self._domain_listeners): - return - if method in self._event_listeners: - self._event_listeners[method].Handle(method, msg) - if domain in self._domain_listeners: - self._domain_listeners[domain].Handle(method, msg) - if self._tearing_down_tracing and method == self.TRACING_DONE_EVENT: - self._tearing_down_tracing = False - self._StopMonitoringImmediately() - - def _TracingStreamDone(self, data): - tracing_events = json.loads(data) - for evt in tracing_events: - self._OnDataReceived({'method': self.TRACING_DATA_METHOD, - 'params': {'value': [evt]}}) - if self._please_stop: - break - self._tearing_down_tracing = False - self._StopMonitoringImmediately() - - def _HttpRequest(self, path): - assert path[0] == '/' - for _ in xrange(self.HTTP_ATTEMPTS): - r = httplib.HTTPConnection(self._http_hostname, self._http_port) - try: - r.request('GET', '/json' + path) - response = r.getresponse() - if response.status != 200: - raise DevToolsConnectionException( - 'Cannot connect to DevTools, reponse code %d' % response.status) - return response.read() - except httplib.BadStatusLine as exception: - logging.warning('Devtools HTTP connection failed: %s' % repr(exception)) - time.sleep(self.HTTP_ATTEMPT_INTERVAL_SECONDS) - finally: - r.close() - # Raise the exception that has failed the last attempt. - raise - - def _Connect(self): - assert not self._ws - assert not self._target_descriptor - for target_descriptor in json.loads(self._HttpRequest('/list')): - if target_descriptor['type'] == 'page': - self._target_descriptor = target_descriptor - break - if not self._target_descriptor: - raise DevToolsConnectionException( - 'No pages are open, connected to a wrong instance?') - if self._target_descriptor['url'] != 'about:blank': - raise DevToolsConnectionException( - 'Looks like devtools connection was made to a different instance.') - self._ws = inspector_websocket.InspectorWebsocket() - self._ws.Connect(self._target_descriptor['webSocketDebuggerUrl'], - timeout=_WEBSOCKET_TIMEOUT_SECONDS) - - -class Listener(object): - """Listens to events forwarded by a DevToolsConnection instance.""" - def __init__(self, connection): - """Initializes a Listener instance. - - Args: - connection: (DevToolsConnection). - """ - pass - - def Handle(self, method, msg): - """Handles an event this instance listens for. - - Args: - event_name: (str) Event name, as registered. - event: (dict) complete event. - """ - raise NotImplementedError - - -class Track(Listener): - """Collects data from a DevTools server.""" - def GetEvents(self): - """Returns a list of collected events, finalizing the state if necessary.""" - raise NotImplementedError - - def ToJsonDict(self): - """Serializes to a dictionary, to be dumped as JSON. - - Returns: - A dict that can be dumped by the json module, and loaded by - FromJsonDict(). - """ - raise NotImplementedError - - @classmethod - def FromJsonDict(cls, _json_dict): - """Returns a Track instance constructed from data dumped by - Track.ToJsonDict(). - - Args: - json_data: (dict) Parsed from a JSON file using the json module. - - Returns: - a Track instance. - """ - # There is no sensible way to deserialize this abstract class, but - # subclasses are not required to define a deserialization method. For - # example, for testing we have a FakeRequestTrack which is never - # deserialized; instead fake instances are deserialized as RequestTracks. - assert False
diff --git a/tools/android/loading/emulation.py b/tools/android/loading/emulation.py deleted file mode 100644 index d7f05c6..0000000 --- a/tools/android/loading/emulation.py +++ /dev/null
@@ -1,124 +0,0 @@ -# Copyright 2016 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. - -"""Device and network emulation utilities via devtools.""" - -import json - -# Copied from -# WebKit/Source/devtools/front_end/network/NetworkConditionsSelector.js -# Units: -# download/upload: byte/s -# latency: ms -NETWORK_CONDITIONS = { - 'GPRS': { - 'download': 50 * 1024 / 8, 'upload': 20 * 1024 / 8, 'latency': 500}, - 'Regular2G': { - 'download': 250 * 1024 / 8, 'upload': 50 * 1024 / 8, 'latency': 300}, - 'Good2G': { - 'download': 450 * 1024 / 8, 'upload': 150 * 1024 / 8, 'latency': 150}, - 'Regular3G': { - 'download': 750 * 1024 / 8, 'upload': 250 * 1024 / 8, 'latency': 100}, - 'Good3G': { - 'download': 1.5 * 1024 * 1024 / 8, 'upload': 750 * 1024 / 8, - 'latency': 40}, - 'Regular4G': { - 'download': 4 * 1024 * 1024 / 8, 'upload': 3 * 1024 * 1024 / 8, - 'latency': 20}, - 'DSL': { - 'download': 2 * 1024 * 1024 / 8, 'upload': 1 * 1024 * 1024 / 8, - 'latency': 5}, - 'WiFi': { - 'download': 30 * 1024 * 1024 / 8, 'upload': 15 * 1024 * 1024 / 8, - 'latency': 2} -} - - -def LoadEmulatedDevices(registry): - """Loads a list of emulated devices from the DevTools JSON registry. - - See, for example, third_party/WebKit/Source/devtools/front_end - /emulated_devices/module.json. - - Args: - registry: A file-like object for the device registry (should be JSON). - - Returns: - {'device_name': device} - """ - json_dict = json.load(registry) - devices = {} - for device in json_dict['extensions']: - device = device['device'] - devices[device['title']] = device - return devices - - -def SetUpDeviceEmulationAndReturnMetadata(connection, device): - """Configures an instance of Chrome for device emulation. - - Args: - connection: (DevToolsConnection) - device: (dict) An entry from LoadEmulatedDevices(). - - Returns: - A dict containing the device emulation metadata. - """ - res = connection.SyncRequest('Emulation.canEmulate') - assert res['result'], 'Cannot set device emulation.' - data = _GetDeviceEmulationMetadata(device) - connection.SyncRequestNoResponse( - 'Emulation.setDeviceMetricsOverride', - {'width': data['width'], - 'height': data['height'], - 'deviceScaleFactor': data['deviceScaleFactor'], - 'mobile': data['mobile'], - 'fitWindow': True}) - connection.SyncRequestNoResponse('Network.setUserAgentOverride', - {'userAgent': data['userAgent']}) - return data - - -def SetUpNetworkEmulation(connection, latency, download, upload): - """Configures an instance of Chrome for network emulation. - - See NETWORK_CONDITIONS for example (or valid?) emulation options. - - Args: - connection: (DevToolsConnection) - latency: (float) Latency in ms. - download: (float) Download speed (Bytes / s). - upload: (float) Upload speed (Bytes / s). - """ - res = connection.SyncRequest('Network.canEmulateNetworkConditions') - assert res['result'], 'Cannot set network emulation.' - connection.SyncRequestNoResponse( - 'Network.emulateNetworkConditions', - {'offline': False, 'latency': latency, 'downloadThroughput': download, - 'uploadThroughput': upload}) - - -def BandwidthToString(bandwidth): - """Converts a bandwidth to string. - - Args: - bandwidth: The bandwidth to convert in byte/s. Must be a multiple of 1024/8. - - Returns: - A string compatible with wpr --{up,down} command line flags. - """ - assert bandwidth % (1024/8) == 0 - bandwidth_kbps = (int(bandwidth) * 8) / 1024 - if bandwidth_kbps % 1024: - return '{}Kbit/s'.format(bandwidth_kbps) - return '{}Mbit/s'.format(bandwidth_kbps / 1024) - - -def _GetDeviceEmulationMetadata(device): - """Returns the metadata associated with a given device.""" - return {'width': device['screen']['vertical']['width'], - 'height': device['screen']['vertical']['height'], - 'deviceScaleFactor': device['screen']['device-pixel-ratio'], - 'mobile': 'mobile' in device['capabilities'], - 'userAgent': device['user-agent']}
diff --git a/tools/android/loading/emulation_unittest.py b/tools/android/loading/emulation_unittest.py deleted file mode 100644 index 44bd5ff..0000000 --- a/tools/android/loading/emulation_unittest.py +++ /dev/null
@@ -1,81 +0,0 @@ -# Copyright 2016 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. - -import os -from StringIO import StringIO -import unittest - -import emulation -import test_utils - - -_SRC_DIR = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..', '..', '..')) - - -class EmulationTestCase(unittest.TestCase): - def testLoadDevices(self): - devices = emulation.LoadEmulatedDevices(file(os.path.join( - _SRC_DIR, 'third_party/blink/renderer/devtools/front_end', - 'emulated_devices/module.json'))) - # Just check we have something. We'll assume that if we were able to read - # the file without dying we must be ok. - self.assertTrue(devices) - - def testSetUpDevice(self): - registry = StringIO("""{ - "extensions": [ - { - "type": "emulated-device", - "device": { - "show-by-default": false, - "title": "mattPhone" , - "screen": { - "horizontal": { - "width": 480, - "height": 320 - }, - "device-pixel-ratio": 2, - "vertical": { - "width": 320, - "height": 480 - } - }, - "capabilities": [ - "touch", - "mobile" - ], - "user-agent": "James Bond" - } - } ]}""") - devices = emulation.LoadEmulatedDevices(registry) - connection = test_utils.MockConnection(self) - connection.ExpectSyncRequest({'result': True}, 'Emulation.canEmulate') - metadata = emulation.SetUpDeviceEmulationAndReturnMetadata( - connection, devices['mattPhone']) - self.assertEqual(320, metadata['width']) - self.assertEqual('James Bond', metadata['userAgent']) - self.assertTrue(connection.AllExpectationsUsed()) - self.assertEqual('Emulation.setDeviceMetricsOverride', - connection.no_response_requests_seen[0][0]) - - def testSetUpNetwork(self): - connection = test_utils.MockConnection(self) - connection.ExpectSyncRequest({'result': True}, - 'Network.canEmulateNetworkConditions') - emulation.SetUpNetworkEmulation(connection, 120, 2048, 1024) - self.assertTrue(connection.AllExpectationsUsed()) - self.assertEqual('Network.emulateNetworkConditions', - connection.no_response_requests_seen[0][0]) - self.assertEqual( - 1024, - connection.no_response_requests_seen[0][1]['uploadThroughput']) - - def testBandwidthToString(self): - self.assertEqual('16Kbit/s', emulation.BandwidthToString(2048)) - self.assertEqual('8Mbit/s', emulation.BandwidthToString(1024 * 1024)) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/frame_load_lens.py b/tools/android/loading/frame_load_lens.py deleted file mode 100644 index e0479ab..0000000 --- a/tools/android/loading/frame_load_lens.py +++ /dev/null
@@ -1,109 +0,0 @@ -# Copyright 2016 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. - -"""Gathers and infers dependencies between requests. - -When executed as a script, loads a trace and outputs synthetic frame load nodes -and the new introduced dependencies. -""" - -import bisect -import collections -import logging -import operator - -import loading_trace - - -class FrameLoadLens(object): - """Analyses and creates request dependencies for inferred frame events.""" - _FRAME_EVENT = 'RenderFrameImpl::didFinishLoad' - _REQUEST_TO_LOAD_GAP_MSEC = 100 - _LOAD_TO_REQUEST_GAP_MSEC = 100 - def __init__(self, trace): - """Instance initialization. - - Args: - trace: (LoadingTrace) Loading trace. - """ - self._frame_load_events = self._GetFrameLoadEvents(trace.tracing_track) - self._request_track = trace.request_track - self._tracing_track = trace.tracing_track - self._load_dependencies = [] - self._request_dependencies = [] - for i, load in enumerate(self._frame_load_events): - self._load_dependencies.extend( - [(i, r) for r in self._GetLoadDependencies(load)]) - self._request_dependencies.extend( - [(r, i) for r in self._GetRequestDependencies(load)]) - - def GetFrameLoadInfo(self): - """Returns [(index, msec)].""" - return [collections.namedtuple('LoadInfo', ['index', 'msec'])._make( - (i, self._frame_load_events[i].start_msec)) - for i in xrange(len(self._frame_load_events))] - - def GetFrameResourceComplete(self, request_track): - """Returns [(frame id, msec)].""" - frame_to_end_msec = collections.defaultdict(int) - for r in request_track.GetEvents(): - if r.end_msec > frame_to_end_msec[r.frame_id]: - frame_to_end_msec[r.frame_id] = r.end_msec - loads = [] - for f in sorted(frame_to_end_msec.keys()): - loads.append((f, frame_to_end_msec[f])) - return loads - - def GetFrameLoadDependencies(self): - """Returns a list of frame load dependencies. - - Returns: - ([(frame load index, request), ...], - [(request, frame load index), ...]), where request are instances of - request_trace.Request, and frame load index is an integer. The first list - in the tuple gives the requests that are dependent on the given frame - load, and the second list gives the frame loads that are dependent on the - given request. - """ - return (self._load_dependencies, self._request_dependencies) - - def _GetFrameLoadEvents(self, tracing_track): - events = [] - for e in tracing_track.GetEvents(): - if e.tracing_event['name'] == self._FRAME_EVENT: - events.append(e) - return events - - def _GetLoadDependencies(self, load): - for r in self._request_track.GetEventsStartingBetween( - load.start_msec, load.start_msec + self._LOAD_TO_REQUEST_GAP_MSEC): - yield r - - def _GetRequestDependencies(self, load): - for r in self._request_track.GetEventsEndingBetween( - load.start_msec - self._REQUEST_TO_LOAD_GAP_MSEC, load.start_msec): - yield r - - -if __name__ == '__main__': - import loading_trace - import json - import sys - lens = FrameLoadLens(loading_trace.LoadingTrace.FromJsonDict( - json.load(open(sys.argv[1])))) - load_times = lens.GetFrameLoadInfo() - for t in load_times: - print t - print (lens._request_track.GetFirstRequestMillis(), - lens._request_track.GetLastRequestMillis()) - load_dep, request_dep = lens.GetFrameLoadDependencies() - rq_str = lambda r: '%s (%d-%d)' % ( - r.request_id, - r.start_msec - lens._request_track.GetFirstRequestMillis(), - r.end_msec - lens._request_track.GetFirstRequestMillis()) - load_str = lambda i: '%s (%d)' % (i, load_times[i][1]) - for load_idx, request in load_dep: - print '%s -> %s' % (load_str(load_idx), rq_str(request)) - for request, load_idx in request_dep: - print '%s -> %s' % (rq_str(request), load_str(load_idx))
diff --git a/tools/android/loading/graph.py b/tools/android/loading/graph.py deleted file mode 100644 index 684fee65..0000000 --- a/tools/android/loading/graph.py +++ /dev/null
@@ -1,277 +0,0 @@ -# Copyright 2016 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. - -"""Support for graphs.""" - -import collections - -import common_util - - -class Node(object): - """A node in a Graph. - - Nodes are identified within a graph using object identity. - """ - def __init__(self): - """Create a new node.""" - self.cost = 0 - - def ToJsonDict(self): - return common_util.SerializeAttributesToJsonDict({}, self, ['cost']) - - @classmethod - def FromJsonDict(cls, json_dict): - return common_util.DeserializeAttributesFromJsonDict( - json_dict, cls(), ['cost']) - - -class Edge(object): - """Represents an edge in a graph.""" - def __init__(self, from_node, to_node): - """Creates an Edge. - - Args: - from_node: (Node) Start node. - to_node: (Node) End node. - """ - self.from_node = from_node - self.to_node = to_node - self.cost = 0 - - def ToJsonDict(self): - return common_util.SerializeAttributesToJsonDict( - {}, self, ['from_node', 'to_node', 'cost']) - - @classmethod - def FromJsonDict(cls, json_dict): - result = cls(None, None) - return common_util.DeserializeAttributesFromJsonDict( - json_dict, result, ['from_node', 'to_node', 'cost']) - - -class DirectedGraph(object): - """Directed graph. - - A graph is identified by a list of nodes and a list of edges. It does not need - to be acyclic, but then some methods will fail. - """ - __GRAPH_NODE_INDEX = '__graph_node_index' - __TO_NODE_INDEX = '__to_node_index' - __FROM_NODE_INDEX = '__from_node_index' - - def __init__(self, nodes, edges): - """Builds a graph from a set of node and edges. - - Note that the edges referencing a node not in the provided list are dropped. - - Args: - nodes: ([Node]) Sequence of Nodes. - edges: ([Edge]) Sequence of Edges. - """ - self._nodes = set(nodes) - self._edges = set(filter( - lambda e: e.from_node in self._nodes and e.to_node in self._nodes, - edges)) - assert all(isinstance(node, Node) for node in self._nodes) - assert all(isinstance(edge, Edge) for edge in self._edges) - self._in_edges = {n: [] for n in self._nodes} - self._out_edges = {n: [] for n in self._nodes} - for edge in self._edges: - self._out_edges[edge.from_node].append(edge) - self._in_edges[edge.to_node].append(edge) - - def OutEdges(self, node): - """Returns a list of edges starting from a node. - """ - return self._out_edges[node] - - def InEdges(self, node): - """Returns a list of edges ending at a node.""" - return self._in_edges[node] - - def Nodes(self): - """Returns the set of nodes of this graph.""" - return self._nodes - - def Edges(self): - """Returns the set of edges of this graph.""" - return self._edges - - def RootNodes(self): - """Returns an iterable of nodes that have no incoming edges.""" - return filter(lambda n: not self.InEdges(n), self._nodes) - - def UpdateEdge(self, edge, new_from_node, new_to_node): - """Updates an edge. - - Args: - edge: - new_from_node: - new_to_node: - """ - assert edge in self._edges - assert new_from_node in self._nodes - assert new_to_node in self._nodes - self._in_edges[edge.to_node].remove(edge) - self._out_edges[edge.from_node].remove(edge) - edge.from_node = new_from_node - edge.to_node = new_to_node - # TODO(lizeb): Check for duplicate edges? - self._in_edges[edge.to_node].append(edge) - self._out_edges[edge.from_node].append(edge) - - def TopologicalSort(self, roots=None): - """Returns a list of nodes, in topological order. - - Args: - roots: ([Node]) If set, the topological sort will only consider nodes - reachable from this list of sources. - """ - sorted_nodes = [] - if roots is None: - nodes_subset = self._nodes - else: - nodes_subset = self.ReachableNodes(roots) - remaining_in_edges = {n: 0 for n in nodes_subset} - for edge in self._edges: - if edge.from_node in nodes_subset and edge.to_node in nodes_subset: - remaining_in_edges[edge.to_node] += 1 - sources = [node for (node, count) in remaining_in_edges.items() - if count == 0] - while sources: - node = sources.pop(0) - sorted_nodes.append(node) - for e in self.OutEdges(node): - successor = e.to_node - if successor not in nodes_subset: - continue - assert remaining_in_edges[successor] > 0 - remaining_in_edges[successor] -= 1 - if remaining_in_edges[successor] == 0: - sources.append(successor) - return sorted_nodes - - def ReachableNodes(self, roots, should_stop=lambda n: False): - """Returns a list of nodes from a set of root nodes. - - Args: - roots: ([Node]) List of roots to start from. - should_stop: (callable) Returns True when a node should stop the - exploration and be skipped. - """ - return self._ExploreFrom( - roots, lambda n: (e.to_node for e in self.OutEdges(n)), - should_stop=should_stop) - - def AncestorNodes(self, descendants): - """Returns a set of nodes that are ancestors of a set of nodes. - - This is not quite the opposite of ReachableNodes, because (in a tree) it - will not include |descendants|. - - Args: - descendants: ([Node]) List of nodes to start from. - - """ - return set(self._ExploreFrom( - descendants, - lambda n: (e.from_node for e in self.InEdges(n)))) - set(descendants) - - def Cost(self, roots=None, path_list=None, costs_out=None): - """Compute the cost of the graph. - - Args: - roots: ([Node]) If set, only compute the cost of the paths reachable - from this list of nodes. - path_list: if not None, gets a list of nodes in the longest path. - costs_out: if not None, gets a vector of node costs by node. - - Returns: - Cost of the longest path. - """ - if not self._nodes: - return 0 - costs = {n: 0 for n in self._nodes} - for node in self.TopologicalSort(roots): - cost = 0 - if self.InEdges(node): - cost = max([costs[e.from_node] + e.cost for e in self.InEdges(node)]) - costs[node] = cost + node.cost - max_cost = max(costs.values()) - if costs_out is not None: - del costs_out[:] - costs_out.extend(costs) - if path_list is not None: - del path_list[:] - node = (i for i in self._nodes if costs[i] == max_cost).next() - path_list.append(node) - while self.InEdges(node): - predecessors = [e.from_node for e in self.InEdges(node)] - node = reduce( - lambda costliest_node, next_node: - next_node if costs[next_node] > costs[costliest_node] - else costliest_node, predecessors) - path_list.insert(0, node) - return max_cost - - def ToJsonDict(self): - node_dicts = [] - node_to_index = {node: index for (index, node) in enumerate(self._nodes)} - for (node, index) in node_to_index.items(): - node_dict = node.ToJsonDict() - assert self.__GRAPH_NODE_INDEX not in node_dict - node_dict.update({self.__GRAPH_NODE_INDEX: index}) - node_dicts.append(node_dict) - edge_dicts = [] - for edge in self._edges: - edge_dict = edge.ToJsonDict() - assert self.__TO_NODE_INDEX not in edge_dict - assert self.__FROM_NODE_INDEX not in edge_dict - edge_dict.update({self.__TO_NODE_INDEX: node_to_index[edge.to_node], - self.__FROM_NODE_INDEX: node_to_index[edge.from_node]}) - edge_dicts.append(edge_dict) - return {'nodes': node_dicts, 'edges': edge_dicts} - - @classmethod - def FromJsonDict(cls, json_dict, node_class, edge_class): - """Returns an instance from a dict. - - Note that the classes of the nodes and edges need to be specified here. - This is done to reduce the likelihood of error. - """ - index_to_node = { - node_dict[cls.__GRAPH_NODE_INDEX]: node_class.FromJsonDict(node_dict) - for node_dict in json_dict['nodes']} - edges = [] - for edge_dict in json_dict['edges']: - edge = edge_class.FromJsonDict(edge_dict) - edge.from_node = index_to_node[edge_dict[cls.__FROM_NODE_INDEX]] - edge.to_node = index_to_node[edge_dict[cls.__TO_NODE_INDEX]] - edges.append(edge) - result = DirectedGraph(index_to_node.values(), edges) - return result - - def _ExploreFrom(self, initial, expand, should_stop=lambda n: False): - """Explore from a set of nodes. - - Args: - initial: ([Node]) List of nodes to start from. - expand: (callable) Given a node, return an iterator of nodes to explore - from that node. - should_stop: (callable) Returns True when a node should stop the - exploration and be skipped. - """ - visited = set() - fifo = collections.deque([n for n in initial if not should_stop(n)]) - while fifo: - node = fifo.pop() - if should_stop(node): - continue - visited.add(node) - for n in expand(node): - if n not in visited and not should_stop(n): - visited.add(n) - fifo.appendleft(n) - return list(visited)
diff --git a/tools/android/loading/graph_unittest.py b/tools/android/loading/graph_unittest.py deleted file mode 100644 index 28e9e21..0000000 --- a/tools/android/loading/graph_unittest.py +++ /dev/null
@@ -1,228 +0,0 @@ -# Copyright 2016 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. - -import operator -import os -import sys -import unittest - -import common_util -import graph - - -class _IndexedNode(graph.Node): - def __init__(self, index=None): - super(_IndexedNode, self).__init__() - self.index = index - - def ToJsonDict(self): - return common_util.SerializeAttributesToJsonDict( - super(_IndexedNode, self).ToJsonDict(), self, ['index']) - - @classmethod - def FromJsonDict(cls, json_dict): - result = super(_IndexedNode, cls).FromJsonDict(json_dict) - return common_util.DeserializeAttributesFromJsonDict( - json_dict, result, ['index']) - - -class GraphTestCase(unittest.TestCase): - @classmethod - def MakeGraph(cls, count, edge_tuples, serialize=False): - """Makes a graph from a list of edges. - - Args: - count: Number of nodes. - edge_tuples: (from_index, to_index). Both indices must be in [0, count), - and uniquely identify a node. Must be sorted - lexicographically by node indices. - """ - nodes = [_IndexedNode(i) for i in xrange(count)] - edges = [graph.Edge(nodes[from_index], nodes[to_index]) - for (from_index, to_index) in edge_tuples] - g = graph.DirectedGraph(nodes, edges) - if serialize: - g = graph.DirectedGraph.FromJsonDict( - g.ToJsonDict(), _IndexedNode, graph.Edge) - nodes = sorted(g.Nodes(), key=operator.attrgetter('index')) - edges = sorted(g.Edges(), key=operator.attrgetter( - 'from_node.index', 'to_node.index')) - return (nodes, edges, g) - - @classmethod - def _NodesIndices(cls, g): - return map(operator.attrgetter('index'), g.Nodes()) - - def testBuildGraph(self, serialize=False): - (nodes, edges, g) = self.MakeGraph( - 7, - [(0, 1), - (0, 2), - (1, 3), - (3, 4), - (5, 6)], serialize) - self.assertListEqual(range(7), sorted(self._NodesIndices(g))) - self.assertSetEqual(set(edges), set(g.Edges())) - - self.assertSetEqual(set([edges[0], edges[1]]), set(g.OutEdges(nodes[0]))) - self.assertFalse(g.InEdges(nodes[0])) - self.assertSetEqual(set([edges[2]]), set(g.OutEdges(nodes[1]))) - self.assertSetEqual(set([edges[0]]), set(g.InEdges(nodes[1]))) - self.assertFalse(g.OutEdges(nodes[2])) - self.assertSetEqual(set([edges[1]]), set(g.InEdges(nodes[2]))) - self.assertSetEqual(set([edges[3]]), set(g.OutEdges(nodes[3]))) - self.assertSetEqual(set([edges[2]]), set(g.InEdges(nodes[3]))) - self.assertFalse(g.OutEdges(nodes[4])) - self.assertSetEqual(set([edges[3]]), set(g.InEdges(nodes[4]))) - self.assertSetEqual(set([edges[4]]), set(g.OutEdges(nodes[5]))) - self.assertFalse(g.InEdges(nodes[5])) - self.assertFalse(g.OutEdges(nodes[6])) - self.assertSetEqual(set([edges[4]]), set(g.InEdges(nodes[6]))) - - def testIgnoresUnknownEdges(self): - nodes = [_IndexedNode(i) for i in xrange(7)] - edges = [graph.Edge(nodes[from_index], nodes[to_index]) - for (from_index, to_index) in [ - (0, 1), (0, 2), (1, 3), (3, 4), (5, 6)]] - edges.append(graph.Edge(nodes[4], _IndexedNode(42))) - edges.append(graph.Edge(_IndexedNode(42), nodes[5])) - g = graph.DirectedGraph(nodes, edges) - self.assertListEqual(range(7), sorted(self._NodesIndices(g))) - self.assertEqual(5, len(g.Edges())) - - def testUpdateEdge(self, serialize=False): - (nodes, edges, g) = self.MakeGraph( - 7, - [(0, 1), - (0, 2), - (1, 3), - (3, 4), - (5, 6)], serialize) - edge = edges[1] - self.assertTrue(edge in g.OutEdges(nodes[0])) - self.assertTrue(edge in g.InEdges(nodes[2])) - g.UpdateEdge(edge, nodes[2], nodes[3]) - self.assertFalse(edge in g.OutEdges(nodes[0])) - self.assertFalse(edge in g.InEdges(nodes[2])) - self.assertTrue(edge in g.OutEdges(nodes[2])) - self.assertTrue(edge in g.InEdges(nodes[3])) - - def testTopologicalSort(self, serialize=False): - (_, edges, g) = self.MakeGraph( - 7, - [(0, 1), - (0, 2), - (1, 3), - (3, 4), - (5, 6)], serialize) - sorted_nodes = g.TopologicalSort() - node_to_sorted_index = dict(zip(sorted_nodes, xrange(len(sorted_nodes)))) - for e in edges: - self.assertTrue( - node_to_sorted_index[e.from_node] < node_to_sorted_index[e.to_node]) - - def testReachableNodes(self, serialize=False): - (nodes, _, g) = self.MakeGraph( - 7, - [(0, 1), - (0, 2), - (1, 3), - (3, 4), - (5, 6)], serialize) - self.assertSetEqual( - set([0, 1, 2, 3, 4]), - set(n.index for n in g.ReachableNodes([nodes[0]]))) - self.assertSetEqual( - set([0, 1, 2, 3, 4]), - set(n.index for n in g.ReachableNodes([nodes[0], nodes[1]]))) - self.assertSetEqual( - set([5, 6]), - set(n.index for n in g.ReachableNodes([nodes[5]]))) - self.assertSetEqual( - set([6]), - set(n.index for n in g.ReachableNodes([nodes[6]]))) - - def testAncestorNodes(self, serialize=False): - (nodes, _, g) = self.MakeGraph( - 7, - [(0, 1), - (0, 2), - (1, 3), - (3, 4), - (5, 6)], serialize) - self.assertSetEqual( - set([0, 1, 3]), - set(n.index for n in g.AncestorNodes([nodes[4]]))) - self.assertSetEqual( - set([0, 1]), - set(n.index for n in g.AncestorNodes([nodes[3]]))) - self.assertSetEqual( - set([0]), - set(n.index for n in g.AncestorNodes([nodes[1]]))) - self.assertSetEqual( - set(), - set(n.index for n in g.AncestorNodes([nodes[0]]))) - self.assertSetEqual( - set([0]), - set(n.index for n in g.AncestorNodes([nodes[2]]))) - self.assertSetEqual( - set([5]), - set(n.index for n in g.AncestorNodes([nodes[6]]))) - self.assertSetEqual( - set(), - set(n.index for n in g.AncestorNodes([nodes[5]]))) - - def testCost(self, serialize=False): - (nodes, edges, g) = self.MakeGraph( - 7, - [(0, 1), - (0, 2), - (1, 3), - (3, 4), - (5, 6)], serialize) - for (i, node) in enumerate(nodes): - node.cost = i + 1 - nodes[6].cost = 6 - for edge in edges: - edge.cost = 1 - self.assertEqual(15, g.Cost()) - path_list = [] - g.Cost(path_list=path_list) - self.assertListEqual([nodes[i] for i in (0, 1, 3, 4)], path_list) - nodes[6].cost = 9 - self.assertEqual(16, g.Cost()) - g.Cost(path_list=path_list) - self.assertListEqual([nodes[i] for i in (5, 6)], path_list) - - def testCostWithRoots(self, serialize=False): - (nodes, edges, g) = self.MakeGraph( - 7, - [(0, 1), - (0, 2), - (1, 3), - (3, 4), - (5, 6)], serialize) - for (i, node) in enumerate(nodes): - node.cost = i + 1 - nodes[6].cost = 9 - for edge in edges: - edge.cost = 1 - path_list = [] - self.assertEqual(16, g.Cost(path_list=path_list)) - self.assertListEqual([nodes[i] for i in (5, 6)], path_list) - self.assertEqual(15, g.Cost(roots=[nodes[0]], path_list=path_list)) - self.assertListEqual([nodes[i] for i in (0, 1, 3, 4)], path_list) - - def testSerialize(self): - # Re-do tests with a deserialized graph. - self.testBuildGraph(True) - self.testUpdateEdge(True) - self.testTopologicalSort(True) - self.testReachableNodes(True) - self.testCost(True) - self.testCostWithRoots(True) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/loading_graph_view.py b/tools/android/loading/loading_graph_view.py deleted file mode 100644 index 67c993c..0000000 --- a/tools/android/loading/loading_graph_view.py +++ /dev/null
@@ -1,122 +0,0 @@ -# Copyright 2016 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. - -"""Views a trace as an annotated request dependency graph.""" - -import dependency_graph -import request_dependencies_lens - - -class RequestNode(dependency_graph.RequestNode): - """Represents a request in the graph. - - is_ad and is_tracking are set according to the ContentClassificationLens - passed to LoadingGraphView. - """ - def __init__(self, request): - super(RequestNode, self).__init__(request) - self.is_ad = False - self.is_tracking = False - - -class Edge(dependency_graph.Edge): - """Represents a dependency between two nodes. - - activity is set according to the ActivityLens passed to LoadingGraphView. - """ - def __init__(self, from_node, to_node, reason): - super(Edge, self).__init__(from_node, to_node, reason) - self.activity = {} - - -class LoadingGraphView(object): - """Represents a trace as a dependency graph. The graph is annotated using - optional lenses passed to it. - """ - def __init__(self, trace, dependencies_lens, content_lens=None, - frame_lens=None, activity=None): - """Initalizes a LoadingGraphView instance. - - Args: - trace: (LoadingTrace) a loading trace. - dependencies_lens: (RequestDependencyLens) - content_lens: (ContentClassificationLens) - frame_lens: (FrameLoadLens) - activity: (ActivityLens) - """ - self._requests = trace.request_track.GetEvents() - self._deps_lens = dependencies_lens - self._content_lens = content_lens - self._frame_lens = frame_lens - self._activity_lens = activity - self._graph = None - self._BuildGraph() - - @classmethod - def FromTrace(cls, trace): - """Create a graph from a trace with no additional annotation.""" - return cls(trace, request_dependencies_lens.RequestDependencyLens(trace)) - - def RemoveAds(self): - """Updates the graph to remove the Ads. - - Nodes that are only reachable through ad nodes are excluded as well. - """ - roots = self._graph.graph.RootNodes() - self._requests = [n.request for n in self._graph.graph.ReachableNodes( - roots, should_stop=lambda n: n.is_ad or n.is_tracking)] - self._BuildGraph() - - def GetInversionsAtTime(self, msec): - """Return the inversions, if any for an event. - - An inversion is when a node is finished before an event, but an ancestor is - not finished. For example, an image is loaded before a first paint, but the - HTML which requested the image has not finished loading at the time of the - paint due to incremental parsing. - - Args: - msec: the time of the event, from the same base as requests. - - Returns: - The inverted Requests, ordered by start time, or None if there is no - inversion. - """ - completed_requests = [] - for rq in self._requests: - if rq.end_msec <= msec: - completed_requests.append(rq) - inversions = [] - for rq in self._graph.AncestorRequests(completed_requests): - if rq.end_msec > msec: - inversions.append(rq) - if inversions: - inversions.sort(key=lambda rq: rq.start_msec) - return inversions - return None - - @property - def deps_graph(self): - return self._graph - - def _BuildGraph(self): - self._graph = dependency_graph.RequestDependencyGraph( - self._requests, self._deps_lens, RequestNode, Edge) - self._AnnotateNodes() - self._AnnotateEdges() - - def _AnnotateNodes(self): - if self._content_lens is None: - return - for node in self._graph.graph.Nodes(): - node.is_ad = self._content_lens.IsAdRequest(node.request) - node.is_tracking = self._content_lens.IsTrackingRequest(node.request) - - def _AnnotateEdges(self): - if self._activity_lens is None: - return - for edge in self._graph.graph.Edges(): - dep = (edge.from_node.request, edge.to_node.request, edge.reason) - activity = self._activity_lens.BreakdownEdgeActivityByInitiator(dep) - edge.activity = activity
diff --git a/tools/android/loading/loading_graph_view_unittest.py b/tools/android/loading/loading_graph_view_unittest.py deleted file mode 100644 index d134d8e..0000000 --- a/tools/android/loading/loading_graph_view_unittest.py +++ /dev/null
@@ -1,107 +0,0 @@ -# Copyright 2016 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. - -import unittest - -import loading_graph_view -import request_dependencies_lens -from request_dependencies_lens_unittest import TestRequests - - -class MockContentClassificationLens(object): - def __init__(self, ad_request_ids, tracking_request_ids): - self._ad_requests_ids = ad_request_ids - self._tracking_request_ids = tracking_request_ids - - def IsAdRequest(self, request): - return request.request_id in self._ad_requests_ids - - def IsTrackingRequest(self, request): - return request.request_id in self._tracking_request_ids - - -class LoadingGraphViewTestCase(unittest.TestCase): - def setUp(self): - super(LoadingGraphViewTestCase, self).setUp() - self.trace = TestRequests.CreateLoadingTrace() - self.deps_lens = request_dependencies_lens.RequestDependencyLens(self.trace) - - def testAnnotateNodesNoLenses(self): - graph_view = loading_graph_view.LoadingGraphView(self.trace, self.deps_lens) - for node in graph_view.deps_graph.graph.Nodes(): - self.assertFalse(node.is_ad) - self.assertFalse(node.is_tracking) - for edge in graph_view.deps_graph.graph.Edges(): - self.assertFalse(edge.is_timing) - - def testAnnotateNodesContentLens(self): - ad_request_ids = set([TestRequests.JS_REQUEST_UNRELATED_FRAME.request_id]) - tracking_request_ids = set([TestRequests.JS_REQUEST.request_id]) - content_lens = MockContentClassificationLens( - ad_request_ids, tracking_request_ids) - graph_view = loading_graph_view.LoadingGraphView(self.trace, self.deps_lens, - content_lens) - for node in graph_view.deps_graph.graph.Nodes(): - request_id = node.request.request_id - self.assertEqual(request_id in ad_request_ids, node.is_ad) - self.assertEqual(request_id in tracking_request_ids, node.is_tracking) - - def testRemoveAds(self): - ad_request_ids = set([TestRequests.JS_REQUEST_UNRELATED_FRAME.request_id]) - tracking_request_ids = set([TestRequests.JS_REQUEST.request_id]) - content_lens = MockContentClassificationLens( - ad_request_ids, tracking_request_ids) - graph_view = loading_graph_view.LoadingGraphView(self.trace, self.deps_lens, - content_lens) - graph_view.RemoveAds() - request_ids = set([n.request.request_id - for n in graph_view.deps_graph.graph.Nodes()]) - expected_request_ids = set([r.request_id for r in [ - TestRequests.FIRST_REDIRECT_REQUEST, - TestRequests.SECOND_REDIRECT_REQUEST, - TestRequests.REDIRECTED_REQUEST, - TestRequests.REQUEST, - TestRequests.JS_REQUEST_OTHER_FRAME]]) - self.assertSetEqual(expected_request_ids, request_ids) - - def testRemoveAdsPruneGraph(self): - ad_request_ids = set([TestRequests.SECOND_REDIRECT_REQUEST.request_id]) - tracking_request_ids = set([]) - content_lens = MockContentClassificationLens( - ad_request_ids, tracking_request_ids) - graph_view = loading_graph_view.LoadingGraphView( - self.trace, self.deps_lens, content_lens) - graph_view.RemoveAds() - request_ids = set([n.request.request_id - for n in graph_view.deps_graph.graph.Nodes()]) - expected_request_ids = set( - [TestRequests.FIRST_REDIRECT_REQUEST.request_id]) - self.assertSetEqual(expected_request_ids, request_ids) - - def testEventInversion(self): - self._UpdateRequestTiming({ - '1234.redirect.1': (0, 0), - '1234.redirect.2': (0, 0), - '1234.1': (10, 100), - '1234.12': (20, 50), - '1234.42': (40, 70), - '1234.56': (40, 150)}) - graph_view = loading_graph_view.LoadingGraphView( - self.trace, self.deps_lens) - self.assertEqual(None, graph_view.GetInversionsAtTime(40)) - self.assertEqual('1234.1', graph_view.GetInversionsAtTime(60)[0].request_id) - self.assertEqual('1234.1', graph_view.GetInversionsAtTime(80)[0].request_id) - self.assertEqual(None, graph_view.GetInversionsAtTime(110)) - self.assertEqual(None, graph_view.GetInversionsAtTime(160)) - - def _UpdateRequestTiming(self, changes): - for rq in self.trace.request_track.GetEvents(): - if rq.request_id in changes: - start_msec, end_msec = changes[rq.request_id] - rq.timing.request_time = float(start_msec) / 1000 - rq.timing.loading_finished = end_msec - start_msec - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/loading_graph_view_visualization.py b/tools/android/loading/loading_graph_view_visualization.py deleted file mode 100644 index 7a89f6bf..0000000 --- a/tools/android/loading/loading_graph_view_visualization.py +++ /dev/null
@@ -1,198 +0,0 @@ -# Copyright 2016 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. - -"""Visualize a loading_graph_view.LoadingGraphView. - -When executed as a script, takes a loading trace and generates a png of the -loading graph.""" - -import activity_lens -import request_track - - -class LoadingGraphViewVisualization(object): - """Manipulate visual representations of a request graph. - - Currently only DOT output is supported. - """ - _LONG_EDGE_THRESHOLD_MS = 2000 # Time in milliseconds. - - _CONTENT_KIND_TO_COLOR = { - 'application': 'blue', # Scripts. - 'font': 'grey70', - 'image': 'orange', # This probably catches gifs? - 'video': 'hotpink1', - 'audio': 'hotpink2', - } - - _CONTENT_TYPE_TO_COLOR = { - 'html': 'red', - 'css': 'green', - 'script': 'blue', - 'javascript': 'blue', - 'json': 'purple', - 'gif': 'grey', - 'image': 'orange', - 'jpeg': 'orange', - 'ping': 'cyan', # Empty response - 'redirect': 'forestgreen', - 'png': 'orange', - 'plain': 'brown3', - 'octet-stream': 'brown3', - 'other': 'white', - } - - _EDGE_REASON_TO_COLOR = { - 'redirect': 'black', - 'parser': 'red', - 'script': 'blue', - 'script_inferred': 'purple', - } - - _ACTIVITY_TYPE_LABEL = ( - ('idle', 'I'), ('unrelated_work', 'W'), ('script', 'S'), - ('parsing', 'P'), ('other_url', 'O'), ('unknown_url', 'U')) - - def __init__(self, graph_view): - """Initialize. - - Args: - graph_view: (loading_graph_view.LoadingGraphView) the graph to visualize. - """ - self._graph_view = graph_view - self._global_start = None - - def OutputDot(self, output): - """Output DOT (graphviz) representation. - - Args: - output: a file-like output stream to receive the dot file. - """ - nodes = self._graph_view.deps_graph.graph.Nodes() - self._global_start = min(n.request.start_msec for n in nodes) - g = self._graph_view.deps_graph.graph - - output.write("""digraph dependencies { - rankdir = LR; - """) - - isolated_nodes = [ - n for n in nodes if ( - len(g.InEdges(n)) == 0 and len(g.OutEdges(n)) == 0)] - if isolated_nodes: - output.write("""subgraph cluster_isolated { - color=black; - label="Isolated Nodes"; - """) - for n in isolated_nodes: - output.write(self._DotNode(n)) - output.write('}\n') - - output.write("""subgraph cluster_nodes { - color=invis; - """) - for n in nodes: - if n in isolated_nodes: - continue - output.write(self._DotNode(n)) - - edges = g.Edges() - for edge in edges: - output.write(self._DotEdge(edge)) - - output.write('}\n') - output.write('}\n') - - def _ContentTypeToColor(self, content_type): - if not content_type: - type_str = 'other' - elif '/' in content_type: - kind, type_str = content_type.split('/', 1) - if kind in self._CONTENT_KIND_TO_COLOR: - return self._CONTENT_KIND_TO_COLOR[kind] - else: - type_str = content_type - return self._CONTENT_TYPE_TO_COLOR[type_str] - - def _DotNode(self, node): - """Returns a graphviz node description for a given node. - - Args: - node: (RequestNode) - - Returns: - A string describing the resource in graphviz format. - The resource is color-coded according to its content type, and its shape - is oval if its max-age is less than 300s (or if it's not cacheable). - """ - color = self._ContentTypeToColor(node.request.GetContentType()) - request = node.request - max_age = request.MaxAge() - shape = 'polygon' if max_age > 300 else 'oval' - styles = ['filled'] - if node.is_ad or node.is_tracking: - styles += ['bold', 'diagonals'] - return ('"%s" [label = "%s\\n%.2f->%.2f (%.2f)"; style = "%s"; ' - 'fillcolor = %s; shape = %s];\n' - % (request.request_id, request_track.ShortName(request.url), - request.start_msec - self._global_start, - request.end_msec - self._global_start, - request.end_msec - request.start_msec, - ','.join(styles), color, shape)) - - def _DotEdge(self, edge): - """Returns a graphviz edge description for a given edge. - - Args: - edge: (Edge) - - Returns: - A string encoding the graphviz representation of the edge. - """ - style = {'color': 'orange'} - label = '%.02f' % edge.cost - if edge.is_timing: - style['style'] = 'dashed' - style['color'] = self._EDGE_REASON_TO_COLOR[edge.reason] - if edge.cost > self._LONG_EDGE_THRESHOLD_MS: - style['penwidth'] = '5' - style['weight'] = '2' - style_str = '; '.join('%s=%s' % (k, v) for (k, v) in style.items()) - - label = '%.02f' % edge.cost - if edge.activity: - separator = ' - ' - for activity_type, activity_label in self._ACTIVITY_TYPE_LABEL: - label += '%s%s:%.02f ' % ( - separator, activity_label, edge.activity[activity_type]) - separator = ' ' - arrow = '[%s; label="%s"]' % (style_str, label) - from_request_id = edge.from_node.request.request_id - to_request_id = edge.to_node.request.request_id - return '"%s" -> "%s" %s;\n' % (from_request_id, to_request_id, arrow) - -def main(trace_file): - import subprocess - - import loading_graph_view - import loading_trace - import request_dependencies_lens - - trace = loading_trace.LoadingTrace.FromJsonFile(trace_file) - dependencies_lens = request_dependencies_lens.RequestDependencyLens(trace) - activity = activity_lens.ActivityLens(trace) - graph_view = loading_graph_view.LoadingGraphView(trace, dependencies_lens, - activity=activity) - visualization = LoadingGraphViewVisualization(graph_view) - - dotfile = trace_file + '.dot' - pngfile = trace_file + '.png' - with file(dotfile, 'w') as output: - visualization.OutputDot(output) - subprocess.check_call(['dot', '-Tpng', dotfile, '-o', pngfile]) - - -if __name__ == '__main__': - import sys - main(sys.argv[1])
diff --git a/tools/android/loading/loading_trace.py b/tools/android/loading/loading_trace.py deleted file mode 100644 index cad3f306..0000000 --- a/tools/android/loading/loading_trace.py +++ /dev/null
@@ -1,132 +0,0 @@ -# Copyright (c) 2016 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. - -"""Represents the trace of a page load.""" - -import datetime -try: - import ujson as json -except ImportError: - import json -import time - -import devtools_monitor -import page_track -import request_track -import tracing_track - - -class LoadingTrace(object): - """Represents the trace of a page load.""" - _URL_KEY = 'url' - _METADATA_KEY = 'metadata' - _PAGE_KEY = 'page_track' - _REQUEST_KEY = 'request_track' - _TRACING_KEY = 'tracing_track' - - def __init__(self, url, metadata, page, request, track): - """Initializes a loading trace instance. - - Args: - url: (str) URL that has been loaded - metadata: (dict) Metadata associated with the load. - page: (PageTrack) instance of PageTrack. - request: (RequestTrack) instance of RequestTrack. - track: (TracingTrack) instance of TracingTrack. - """ - self.url = url - self.metadata = metadata - self.page_track = page - self.request_track = request - self._tracing_track = track - self._tracing_json_str = None - - def ToJsonDict(self): - """Returns a dictionary representing this instance.""" - result = {self._URL_KEY: self.url, self._METADATA_KEY: self.metadata, - self._PAGE_KEY: self.page_track.ToJsonDict(), - self._REQUEST_KEY: self.request_track.ToJsonDict(), - self._TRACING_KEY: (self.tracing_track.ToJsonDict() - if self.tracing_track else None)} - return result - - def ToJsonFile(self, json_path): - """Save a json file representing this instance.""" - json_dict = self.ToJsonDict() - with open(json_path, 'w') as output_file: - json.dump(json_dict, output_file) - - @classmethod - def FromJsonDict(cls, json_dict): - """Returns an instance from a dictionary returned by ToJsonDict().""" - keys = (cls._URL_KEY, cls._METADATA_KEY, cls._PAGE_KEY, cls._REQUEST_KEY, - cls._TRACING_KEY) - assert all(key in json_dict for key in keys) - page = page_track.PageTrack.FromJsonDict(json_dict[cls._PAGE_KEY]) - request = request_track.RequestTrack.FromJsonDict( - json_dict[cls._REQUEST_KEY]) - track = tracing_track.TracingTrack.FromJsonDict( - json_dict[cls._TRACING_KEY]) - return LoadingTrace(json_dict[cls._URL_KEY], json_dict[cls._METADATA_KEY], - page, request, track) - - @classmethod - def FromJsonFile(cls, json_path): - """Returns an instance from a json file saved by ToJsonFile().""" - with open(json_path) as input_file: - return cls.FromJsonDict(json.load(input_file)) - - @classmethod - def RecordUrlNavigation( - cls, url, connection, chrome_metadata, categories, - timeout_seconds=devtools_monitor.DEFAULT_TIMEOUT_SECONDS, - stop_delay_multiplier=0): - """Create a loading trace by using controller to fetch url. - - Args: - url: (str) url to fetch. - connection: An opened devtools connection. - chrome_metadata: Dictionary of chrome metadata. - categories: as in tracing_track.TracingTrack - timeout_seconds: monitoring connection timeout in seconds. - stop_delay_multiplier: How long to wait after page load completed before - tearing down, relative to the time it took to reach the page load to - complete. - - Returns: - LoadingTrace instance. - """ - page = page_track.PageTrack(connection) - request = request_track.RequestTrack(connection) - trace = tracing_track.TracingTrack(connection, categories) - start_date_str = datetime.datetime.utcnow().isoformat() - seconds_since_epoch=time.time() - connection.MonitorUrl(url, - timeout_seconds=timeout_seconds, - stop_delay_multiplier=stop_delay_multiplier) - trace = cls(url, chrome_metadata, page, request, trace) - trace.metadata.update(date=start_date_str, - seconds_since_epoch=seconds_since_epoch) - return trace - - @property - def tracing_track(self): - if not self._tracing_track: - self._RestoreTracingTrack() - return self._tracing_track - - def Slim(self): - """Slims the memory usage of a trace by dropping the TraceEvents from it. - - The tracing track is restored on-demand when accessed. - """ - self._tracing_json_str = json.dumps(self._tracing_track.ToJsonDict()) - self._tracing_track = None - - def _RestoreTracingTrack(self): - if not self._tracing_json_str: - return None - self._tracing_track = tracing_track.TracingTrack.FromJsonDict( - json.loads(self._tracing_json_str)) - self._tracing_json_str = None
diff --git a/tools/android/loading/loading_trace_analyzer.py b/tools/android/loading/loading_trace_analyzer.py deleted file mode 100755 index 3c7882d..0000000 --- a/tools/android/loading/loading_trace_analyzer.py +++ /dev/null
@@ -1,178 +0,0 @@ -#! /usr/bin/env python -# Copyright 2016 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. - -import argparse -import json -import re -import sys - -from loading_trace import LoadingTrace -import request_track - - -def _ArgumentParser(): - """Builds a command line argument's parser. - """ - parser = argparse.ArgumentParser() - subparsers = parser.add_subparsers(dest='subcommand', help='subcommand line') - - # requests listing subcommand. - requests_parser = subparsers.add_parser('requests', - help='Lists all request from the loading trace.') - requests_parser.add_argument('loading_trace', type=str, - help='Input loading trace to see the cache usage from.') - requests_parser.add_argument('--output', - type=argparse.FileType('w'), - default=sys.stdout, - help='Output destination path if different from stdout.') - requests_parser.add_argument('--output-format', type=str, default='{url}', - help='Output line format (Default to "{url}")') - requests_parser.add_argument('--where', - dest='where_statement', type=str, - nargs=2, metavar=('FORMAT', 'REGEX'), default=[], - help='Where statement to filter such as: --where "{protocol}" "https?"') - - # requests listing subcommand. - prune_parser = subparsers.add_parser('prune', - help='Prunes some stuff from traces to make them small.') - prune_parser.add_argument('loading_trace', type=file, - help='Input path of the loading trace.') - prune_parser.add_argument('-t', '--trace-filters', - type=str, nargs='+', metavar='REGEX', default=[], - help='Regex filters to whitelist trace events.') - prune_parser.add_argument('-r', '--request-member-filter', - type=str, nargs='+', metavar='REGEX', default=[], - help='Regex filters to whitelist requests\' members.') - prune_parser.add_argument('-i', '--indent', type=int, default=2, - help='Number of space to indent the output.') - prune_parser.add_argument('-o', '--output', - type=argparse.FileType('w'), default=sys.stdout, - help='Output destination path if different from stdout.') - return parser - - -def ListRequests(loading_trace_path, - output_format='{url}', - where_format='{url}', - where_statement=None): - """`loading_trace_analyzer.py requests` Command line tool entry point. - - Args: - loading_trace_path: Path of the loading trace. - output_format: Output format of the generated strings. - where_format: String formated to be regex tested with <where_statement> - where_statement: Regex for selecting request event. - - Yields: - Formated string of the selected request event. - - Example: - Lists all request with timing: - ... requests --output-format "{timing} {url}" - - Lists HTTP/HTTPS requests that have used the cache: - ... requests --where "{protocol} {from_disk_cache}" "https?\S* True" - """ - if where_statement: - where_statement = re.compile(where_statement) - loading_trace = LoadingTrace.FromJsonFile(loading_trace_path) - for request_event in loading_trace.request_track.GetEvents(): - request_event_json = request_event.ToJsonDict() - if where_statement != None: - where_in = where_format.format(**request_event_json) - if not where_statement.match(where_in): - continue - yield output_format.format(**request_event_json) - - -def _PruneMain(args): - """`loading_trace_analyzer.py requests` Command line tool entry point. - - Args: - args: Command line parsed arguments. - - Example: - Keep only blink.net trace event category: - ... prune -t "blink.net" - - Keep only requestStart trace events: - ... prune -t "requestStart" - - Keep only requestStart trace events of the blink.user_timing category: - ... prune -t "blink.user_timing:requestStart" - - Keep only all blink trace event categories: - ... prune -t "^blink\.*" - - Keep only requests' url member: - ... prune -r "^url$" - - Keep only requests' url and document_url members: - ... prune -r "^./url$" - - Keep only requests' url, document_url and initiator members: - ... prune -r "^./url$" "initiator" - """ - trace_json = json.load(args.loading_trace) - - # Filter trace events. - regexes = [re.compile(f) for f in args.trace_filters] - events = [] - for event in trace_json['tracing_track']['events']: - prune = True - for cat in event['cat'].split(','): - event_name = cat + ':' + event['name'] - for regex in regexes: - if regex.search(event_name): - prune = False - break - if not prune: - events.append(event) - break - trace_json['tracing_track']['events'] = events - - # Filter members of requests. - regexes = [re.compile(f) for f in args.request_member_filter] - for request in trace_json['request_track']['events']: - for key in request.keys(): - prune = True - for regex in regexes: - if regex.search(key): - prune = False - break - if prune: - del request[key] - - json.dump(trace_json, args.output, indent=args.indent) - return 0 - - -def main(command_line_args): - """Command line tool entry point.""" - args = _ArgumentParser().parse_args(command_line_args) - if args.subcommand == 'requests': - try: - where_format = None - where_statement = None - if args.where_statement: - where_format = args.where_statement[0] - where_statement = args.where_statement[1] - for output_line in ListRequests(loading_trace_path=args.loading_trace, - output_format=args.output_format, - where_format=where_format, - where_statement=where_statement): - args.output.write(output_line + '\n') - return 0 - except re.error as e: - sys.stderr.write("Invalid where statement REGEX: {}\n{}\n".format( - where_statement[1], str(e))) - return 1 - elif args.subcommand == 'prune': - return _PruneMain(args) - assert False - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:]))
diff --git a/tools/android/loading/metrics.py b/tools/android/loading/metrics.py deleted file mode 100644 index 3a82d1e..0000000 --- a/tools/android/loading/metrics.py +++ /dev/null
@@ -1,204 +0,0 @@ -# Copyright 2016 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. - -"""Descriptive metrics for Clovis. - -When executed as a script, prints the amount of data attributed to Ads, and -shows a graph of the amount of data to download for a new visit to the same -page, with a given time interval. -""" - -import collections -import urlparse - -import content_classification_lens -from request_track import CachingPolicy - -HTTP_OK_LENGTH = len("HTTP/1.1 200 OK\r\n") - -def _RequestTransferSize(request): - def HeadersSize(headers): - # 4: ':', ' ', '\r', '\n' - return sum(len(k) + len(v) + 4 for (k, v) in headers.items()) - if request.protocol == 'data': - return {'get': 0, 'request_headers': 0, 'response_headers': 0, 'body': 0} - return {'get': len('GET ') + len(request.url) + 2, - 'request_headers': HeadersSize(request.request_headers or {}), - 'response_headers': HeadersSize(request.response_headers or {}), - 'body': request.encoded_data_length} - - -def TransferSize(requests): - """Returns the total transfer size (uploaded, downloaded) of requests. - - This is an estimate as we assume: - - 200s (for the size computation) - - GET only. - - Args: - requests: ([Request]) List of requests. - - Returns: - (uploaded_bytes (int), downloaded_bytes (int)) - """ - uploaded_bytes = 0 - downloaded_bytes = 0 - for request in requests: - request_bytes = _RequestTransferSize(request) - uploaded_bytes += request_bytes['get'] + request_bytes['request_headers'] - downloaded_bytes += (HTTP_OK_LENGTH - + request_bytes['response_headers'] - + request_bytes['body']) - return (uploaded_bytes, downloaded_bytes) - - -def TotalTransferSize(trace): - """Returns the total transfer size (uploaded, downloaded) from a trace.""" - return TransferSize(trace.request_track.GetEvents()) - - -def TransferredDataRevisit(trace, after_time_s, assume_validation_ok=False): - """Returns the amount of data transferred for a revisit. - - Args: - trace: (LoadingTrace) loading trace. - after_time_s: (float) Time in s after which the site is revisited. - assume_validation_ok: (bool) Assumes that the resources to validate return - 304s. - - Returns: - (uploaded_bytes, downloaded_bytes) - """ - uploaded_bytes = 0 - downloaded_bytes = 0 - for request in trace.request_track.GetEvents(): - caching_policy = CachingPolicy(request) - policy = caching_policy.PolicyAtDate(request.wall_time + after_time_s) - request_bytes = _RequestTransferSize(request) - if policy == CachingPolicy.VALIDATION_NONE: - continue - uploaded_bytes += request_bytes['get'] + request_bytes['request_headers'] - if (policy in (CachingPolicy.VALIDATION_SYNC, - CachingPolicy.VALIDATION_ASYNC) - and caching_policy.HasValidators() and assume_validation_ok): - downloaded_bytes += len('HTTP/1.1 304 NOT MODIFIED\r\n') - continue - downloaded_bytes += (HTTP_OK_LENGTH - + request_bytes['response_headers'] - + request_bytes['body']) - return (uploaded_bytes, downloaded_bytes) - - -def AdsAndTrackingTransferSize(trace, ad_rules_filename, - tracking_rules_filename): - """Returns the transfer size attributed to ads and tracking. - - Args: - trace: (LoadingTrace) a loading trace. - ad_rules_filename: (str) Path to an ad rules file. - tracking_rules_filename: (str) Path to a tracking rules file. - - Returns: - (uploaded_bytes (int), downloaded_bytes (int)) - """ - content_lens = ( - content_classification_lens.ContentClassificationLens.WithRulesFiles( - trace, ad_rules_filename, tracking_rules_filename)) - requests = content_lens.AdAndTrackingRequests() - return TransferSize(requests) - - -def DnsRequestsAndCost(trace): - """Returns the number and cost of DNS requests for a trace.""" - requests = trace.request_track.GetEvents() - requests_with_dns = [r for r in requests if r.timing.dns_start != -1] - dns_requests_count = len(requests_with_dns) - dns_cost = sum(r.timing.dns_end - r.timing.dns_start - for r in requests_with_dns) - return (dns_requests_count, dns_cost) - - -def ConnectionMetrics(trace): - """Returns the connection metrics for a given trace. - - Returns: - { - 'connections': int, - 'connection_cost_ms': float, - 'ssl_connections': int, - 'ssl_cost_ms': float, - 'http11_requests': int, - 'h2_requests': int, - 'data_requests': int, - 'domains': int - } - """ - requests = trace.request_track.GetEvents() - requests_with_connect = [r for r in requests if r.timing.connect_start != -1] - requests_with_connect_count = len(requests_with_connect) - connection_cost = sum(r.timing.connect_end - r.timing.connect_start - for r in requests_with_connect) - ssl_requests = [r for r in requests if r.timing.ssl_start != -1] - ssl_requests_count = len(ssl_requests) - ssl_cost = sum(r.timing.ssl_end - r.timing.ssl_start for r in ssl_requests) - requests_per_protocol = collections.defaultdict(int) - for r in requests: - requests_per_protocol[r.protocol] += 1 - - domains = set() - for r in requests: - if r.protocol == 'data': - continue - domain = urlparse.urlparse(r.url).hostname - domains.add(domain) - - return { - 'connections': requests_with_connect_count, - 'connection_cost_ms': connection_cost, - 'ssl_connections': ssl_requests_count, - 'ssl_cost_ms': ssl_cost, - 'http11_requests': requests_per_protocol['http/1.1'], - 'h2_requests': requests_per_protocol['h2'], - 'data_requests': requests_per_protocol['data'], - 'domains': len(domains) - } - - -def PlotTransferSizeVsTimeBetweenVisits(trace): - times = [10, 60, 300, 600, 3600, 4 * 3600, 12 * 3600, 24 * 3600] - labels = ['10s', '1m', '10m', '1h', '4h', '12h', '1d'] - (_, total_downloaded) = TotalTransferSize(trace) - downloaded = [TransferredDataRevisit(trace, delta_t)[1] for delta_t in times] - plt.figure() - plt.title('Amount of data to download for a revisit - %s' % trace.url) - plt.xlabel('Time between visits (log)') - plt.ylabel('Amount of data (bytes)') - plt.plot(times, downloaded, 'k+--') - plt.axhline(total_downloaded, color='k', linewidth=2) - plt.xscale('log') - plt.xticks(times, labels) - plt.show() - - -def main(trace_filename, ad_rules_filename, tracking_rules_filename): - trace = loading_trace.LoadingTrace.FromJsonFile(trace_filename) - (_, ads_downloaded_bytes) = AdsAndTrackingTransferSize( - trace, ad_rules_filename, tracking_rules_filename) - (_, total_downloaded_bytes) = TotalTransferSize(trace) - print '%e bytes linked to Ads/Tracking (%.02f%%)' % ( - ads_downloaded_bytes, - (100. * ads_downloaded_bytes) / total_downloaded_bytes) - PlotTransferSizeVsTimeBetweenVisits(trace) - - -if __name__ == '__main__': - import sys - from matplotlib import pylab as plt - import loading_trace - if len(sys.argv) != 4: - print ( - 'Usage: %s trace_filename ad_rules_filename tracking_rules_filename' - % sys.argv[0]) - sys.exit(0) - main(*sys.argv[1:])
diff --git a/tools/android/loading/metrics_unittest.py b/tools/android/loading/metrics_unittest.py deleted file mode 100644 index b10a529..0000000 --- a/tools/android/loading/metrics_unittest.py +++ /dev/null
@@ -1,120 +0,0 @@ -# Copyright 2016 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. - -import copy -import unittest - -import metrics -import request_track -import test_utils - - -class MetricsTestCase(unittest.TestCase): - _BODY_SIZE = 14187 - _URL = 'http://www.example.com/' - _REQUEST_HEADERS_SIZE = (len(_URL) + len('GET ') + 2 - + len('Accept: Everything\r\n')) - _RESPONSE_HEADERS_SIZE = 124 - _REQUEST = { - 'encoded_data_length': _BODY_SIZE, - 'request_id': '2291.1', - 'request_headers': { - 'Accept': 'Everything', - }, - 'response_headers': { - 'Age': '866', - 'Content-Length': str(_BODY_SIZE), - 'Etag': 'ABCD', - 'Date': 'Fri, 22 Apr 2016 08:56:19 -0200', - 'Vary': 'Accept-Encoding', - }, - 'timestamp': 5535648.730768, - 'timing': { - 'receive_headers_end': 47.0650000497699, - 'request_time': 5535648.73264, - }, - 'url': _URL, - 'status': 200, - 'wall_time': 1461322579.59422} - - def testTransferredDataRevisitNoCache(self): - trace = self._MakeTrace() - (uploaded, downloaded) = metrics.TransferredDataRevisit(trace, 10) - self.assertEqual(self._REQUEST_HEADERS_SIZE, uploaded) - self.assertEqual(self._BODY_SIZE + self._RESPONSE_HEADERS_SIZE, downloaded) - - def testTransferredDataRevisitNoCacheAssumeValidates(self): - trace = self._MakeTrace() - (uploaded, downloaded) = metrics.TransferredDataRevisit(trace, 10, True) - self.assertEqual(self._REQUEST_HEADERS_SIZE, uploaded) - not_modified_length = len('HTTP/1.1 304 NOT MODIFIED\r\n') - self.assertEqual(not_modified_length, downloaded) - - def testTransferredDataRevisitCacheable(self): - trace = self._MakeTrace() - r = trace.request_track.GetEvents()[0] - r.response_headers['Cache-Control'] = 'max-age=1000' - (uploaded, downloaded) = metrics.TransferredDataRevisit(trace, 10) - self.assertEqual(0, uploaded) - self.assertEqual(0, downloaded) - (uploaded, downloaded) = metrics.TransferredDataRevisit(trace, 1000) - self.assertEqual(self._REQUEST_HEADERS_SIZE, uploaded) - cache_control_length = len('Cache-Control: max-age=1000\r\n') - self.assertEqual( - self._BODY_SIZE + self._RESPONSE_HEADERS_SIZE + cache_control_length, - downloaded) - - def testTransferSize(self): - trace = self._MakeTrace() - r = trace.request_track.GetEvents()[0] - (_, downloaded) = metrics.TransferSize([r]) - self.assertEqual(self._BODY_SIZE + self._RESPONSE_HEADERS_SIZE, - downloaded) - - def testDnsRequestsAndCost(self): - trace = self._MakeTrace() - (count, cost) = metrics.DnsRequestsAndCost(trace) - self.assertEqual(0, count) - self.assertEqual(0, cost) - r = trace.request_track.GetEvents()[0] - r.timing.dns_end = 12 - r.timing.dns_start = 4 - (count, cost) = metrics.DnsRequestsAndCost(trace) - self.assertEqual(1, count) - self.assertEqual(8, cost) - - def testConnectionMetrics(self): - requests = [request_track.Request.FromJsonDict(copy.deepcopy(self._REQUEST)) - for _ in xrange(3)] - requests[0].url = 'http://chromium.org/' - requests[0].protocol = 'http/1.1' - requests[0].timing.connect_start = 12 - requests[0].timing.connect_end = 42 - requests[0].timing.ssl_start = 50 - requests[0].timing.ssl_end = 70 - requests[1].url = 'https://chromium.org/where-am-i/' - requests[1].protocol = 'h2' - requests[1].timing.connect_start = 22 - requests[1].timing.connect_end = 73 - requests[2].url = 'http://www.chromium.org/here/' - requests[2].protocol = 'http/42' - trace = test_utils.LoadingTraceFromEvents(requests) - stats = metrics.ConnectionMetrics(trace) - self.assertEqual(2, stats['connections']) - self.assertEqual(81, stats['connection_cost_ms']) - self.assertEqual(1, stats['ssl_connections']) - self.assertEqual(20, stats['ssl_cost_ms']) - self.assertEqual(1, stats['http11_requests']) - self.assertEqual(1, stats['h2_requests']) - self.assertEqual(0, stats['data_requests']) - self.assertEqual(2, stats['domains']) - - @classmethod - def _MakeTrace(cls): - request = request_track.Request.FromJsonDict(copy.deepcopy(cls._REQUEST)) - return test_utils.LoadingTraceFromEvents([request]) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/network_activity_lens.py b/tools/android/loading/network_activity_lens.py deleted file mode 100644 index 7e087e4..0000000 --- a/tools/android/loading/network_activity_lens.py +++ /dev/null
@@ -1,240 +0,0 @@ -# Copyright 2016 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. - -"""Gives a picture of the network activity between timestamps.""" - -import bisect -import collections -import itertools -import operator - - -class NetworkActivityLens(object): - """Reconstructs the network activity during a trace. - - The {uploaded,downloaded}_bytes_timeline timelines are: - ([timestamp_msec], [value_at_timestamp]). Bytes are counted when a - network event completes. - - The rate timelines are: - ([timestamp_msec], [rate]), where the rate is computed over the time - period ending at timestamp_msec. - - For all the timelines, the list of timestamps are identical. - """ - def __init__(self, trace): - """Initializes a NetworkActivityLens instance. - - Args: - trace: (LoadingTrace) - """ - self._trace = trace - self._start_end_times = [] - self._active_events_list = [] - self._uploaded_bytes_timeline = [] - self._downloaded_bytes_timeline = [] - self._upload_rate_timeline = [] - self._download_rate_timeline = [] - self._total_downloaded_bytes = 0 - requests = trace.request_track.GetEvents() - self._network_events = list(itertools.chain.from_iterable( - NetworkEvent.EventsFromRequest(request) for request in requests)) - self._IndexEvents() - self._CreateTimelines() - - @property - def uploaded_bytes_timeline(self): # (timestamps, data) - return (self._start_end_times, self._uploaded_bytes_timeline) - - @property - def downloaded_bytes_timeline(self): - return (self._start_end_times, self._downloaded_bytes_timeline) - - @property - def upload_rate_timeline(self): - return (self._start_end_times, self._upload_rate_timeline) - - @property - def download_rate_timeline(self): - return (self._start_end_times, self._download_rate_timeline) - - @property - def total_download_bytes(self): - return self._total_downloaded_bytes - - def DownloadedBytesAt(self, time_msec): - """Return the the downloaded bytes at a given timestamp. - - Args: - time_msec: a timestamp, in the same scale as the timelines. - - Returns: - The total bytes downloaded up until the time period ending at time_msec. - """ - # We just do a linear cumulative sum. Currently this is only called a couple - # of times, so making an indexed cumulative sum does not seem to be worth - # the bother. - total_bytes = 0 - previous_msec = self.downloaded_bytes_timeline[0][0] - for msec, nbytes in zip(*self.downloaded_bytes_timeline): - if msec < time_msec: - total_bytes += nbytes - previous_msec = msec - else: - if time_msec > previous_msec: - fraction_of_chunk = ((time_msec - previous_msec) - / (msec - previous_msec)) - total_bytes += float(nbytes) * fraction_of_chunk - break - return total_bytes - - def _IndexEvents(self): - start_end_times_set = set() - for event in self._network_events: - start_end_times_set.add(event.start_msec) - start_end_times_set.add(event.end_msec) - self._start_end_times = sorted(list(start_end_times_set)) - self._active_events_list = [[] for _ in self._start_end_times] - for event in self._network_events: - start_index = bisect.bisect_right( - self._start_end_times, event.start_msec) - 1 - end_index = bisect.bisect_right( - self._start_end_times, event.end_msec) - for index in range(start_index, end_index): - self._active_events_list[index].append(event) - - def _CreateTimelines(self): - for (index, timestamp) in enumerate(self._start_end_times): - upload_rate = sum( - e.UploadRate() for e in self._active_events_list[index] - if timestamp != e.end_msec) - download_rate = sum( - e.DownloadRate() for e in self._active_events_list[index] - if timestamp != e.end_msec) - uploaded_bytes = sum( - e.UploadedBytes() for e in self._active_events_list[index] - if timestamp == e.end_msec) - downloaded_bytes = sum( - e.DownloadedBytes() for e in self._active_events_list[index] - if timestamp == e.end_msec) - self._total_downloaded_bytes += downloaded_bytes - self._uploaded_bytes_timeline.append(uploaded_bytes) - self._downloaded_bytes_timeline.append(downloaded_bytes) - self._upload_rate_timeline.append(upload_rate) - self._download_rate_timeline.append(download_rate) - - -class NetworkEvent(object): - """Represents a network event.""" - KINDS = set( - ('dns', 'connect', 'send', 'receive_headers', 'receive_body')) - def __init__(self, request, kind, start_msec, end_msec, chunk_index=None): - """Creates a NetworkEvent.""" - self._request = request - self._kind = kind - self.start_msec = start_msec - self.end_msec = end_msec - self._chunk_index = chunk_index - - @classmethod - def _GetStartEndOffsetsMsec(cls, request, kind, index=None): - start_offset, end_offset = (0, 0) - r = request - if kind == 'dns': - start_offset = r.timing.dns_start - end_offset = r.timing.dns_end - elif kind == 'connect': - start_offset = r.timing.connect_start - end_offset = r.timing.connect_end - elif kind == 'send': - start_offset = r.timing.send_start - end_offset = r.timing.send_end - elif kind == 'receive_headers': # There is no responseReceived timing. - start_offset = r.timing.send_end - end_offset = r.timing.receive_headers_end - elif kind == 'receive_body': - if index is None: - start_offset = r.timing.receive_headers_end - end_offset = r.timing.loading_finished - else: - # Some chunks can correspond to no data. - i = index - 1 - while i >= 0: - (offset, size) = r.data_chunks[i] - if size != 0: - previous_chunk_start = offset - break - i -= 1 - else: - previous_chunk_start = r.timing.receive_headers_end - start_offset = previous_chunk_start - end_offset = r.data_chunks[index][0] - return (start_offset, end_offset) - - @classmethod - def EventsFromRequest(cls, request): - # TODO(lizeb): This ignore forced revalidations. - if (request.from_disk_cache or request.served_from_cache - or request.IsDataRequest()): - return [] - events = [] - for kind in cls.KINDS - set(['receive_body']): - event = cls._EventWithKindFromRequest(request, kind) - if event: - events.append(event) - kind = 'receive_body' - if request.data_chunks: - for (index, chunk) in enumerate(request.data_chunks): - if chunk[0] != 0: - event = cls._EventWithKindFromRequest(request, kind, index) - if event: - events.append(event) - else: - event = cls._EventWithKindFromRequest(request, kind, None) - if event: - events.append(event) - return events - - @classmethod - def _EventWithKindFromRequest(cls, request, kind, index=None): - (start_offset, end_offset) = cls._GetStartEndOffsetsMsec( - request, kind, index) - event = cls(request, kind, request.start_msec + start_offset, - request.start_msec + end_offset, index) - if start_offset == -1 or end_offset == -1: - return None - return event - - def UploadedBytes(self): - """Returns the number of bytes uploaded during this event.""" - if self._kind not in ('send'): - return 0 - # Headers are not compressed (ignoring SPDY / HTTP/2) - if not self._request.request_headers: - return 0 - return sum(len(k) + len(str(v)) for (k, v) - in self._request.request_headers.items()) - - def DownloadedBytes(self): - """Returns the number of bytes downloaded during this event.""" - if self._kind not in ('receive_headers', 'receive_body'): - return 0 - if self._kind == 'receive_headers': - return sum(len(k) + len(str(v)) for (k, v) - in self._request.response_headers.items()) - else: - if self._chunk_index is None: - return self._request.encoded_data_length - else: - return self._request.data_chunks[self._chunk_index][1] - - def UploadRate(self): - """Returns the upload rate of this event in Bytes / s.""" - return 1000 * self.UploadedBytes() / float(self.end_msec - self.start_msec) - - def DownloadRate(self): - """Returns the download rate of this event in Bytes / s.""" - downloaded_bytes = self.DownloadedBytes() - value = 1000 * downloaded_bytes / float(self.end_msec - self.start_msec) - return value
diff --git a/tools/android/loading/network_activity_lens_unittest.py b/tools/android/loading/network_activity_lens_unittest.py deleted file mode 100644 index 7b2031e..0000000 --- a/tools/android/loading/network_activity_lens_unittest.py +++ /dev/null
@@ -1,138 +0,0 @@ -# Copyright 2016 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. - -import copy -import unittest - -from network_activity_lens import NetworkActivityLens -import test_utils - - -class NetworkActivityLensTestCase(unittest.TestCase): - def testTimeline(self): - timing_dict = { - 'requestTime': 1.2, - 'dnsStart': 20, 'dnsEnd': 30, - 'connectStart': 50, 'connectEnd': 60, - 'sendStart': 70, 'sendEnd': 80, - 'receiveHeadersEnd': 90, - 'loadingFinished': 100} - request = test_utils.MakeRequestWithTiming(1, 2, timing_dict) - lens = self._NetworkActivityLens([request]) - start_end_times = lens.uploaded_bytes_timeline[0] - expected_start_times = [ - 1220., 1230., 1250., 1260., 1270., 1280., 1290., 1300.] - self.assertListEqual(expected_start_times, start_end_times) - timing_dict = copy.copy(timing_dict) - timing_dict['requestTime'] += .005 - second_request = test_utils.MakeRequestWithTiming(1, 2, timing_dict) - lens = self._NetworkActivityLens([request, second_request]) - start_end_times = lens.uploaded_bytes_timeline[0] - expected_start_times = sorted( - expected_start_times + [x + 5. for x in expected_start_times]) - for (expected, actual) in zip(expected_start_times, start_end_times): - self.assertAlmostEquals(expected, actual) - - def testTransferredBytes(self): - timing_dict = { - 'requestTime': 1.2, - 'dnsStart': 20, 'dnsEnd': 30, - 'connectStart': 50, 'connectEnd': 60, - 'sendStart': 70, 'sendEnd': 80, - 'receiveHeadersEnd': 90, - 'loadingFinished': 100} - request = test_utils.MakeRequestWithTiming(1, 2, timing_dict) - request.request_headers = {'a': 'b'} - request.response_headers = {'c': 'def'} - lens = self._NetworkActivityLens([request]) - # Upload - upload_timeline = lens.uploaded_bytes_timeline - self.assertEquals(1270, upload_timeline[0][4]) - self.assertEquals(1280, upload_timeline[0][5]) - self.assertEquals(0, upload_timeline[1][4]) - self.assertEquals(2, upload_timeline[1][5]) - self.assertEquals(0, upload_timeline[1][6]) - upload_rate = lens.upload_rate_timeline - self.assertEquals(2 / 10e-3, upload_rate[1][4]) - self.assertEquals(0, upload_rate[1][5]) - # Download - download_timeline = lens.downloaded_bytes_timeline - download_rate = lens.download_rate_timeline - self.assertEquals(1280, download_timeline[0][5]) - self.assertEquals(1290, download_timeline[0][6]) - self.assertEquals(0, download_timeline[1][5]) - self.assertEquals(4, download_timeline[1][6]) - self.assertEquals(0, download_timeline[1][7]) - download_rate = lens.download_rate_timeline - self.assertEquals(4 / 10e-3, download_rate[1][5]) - self.assertEquals(0, download_rate[1][6]) - self.assertAlmostEquals(4, lens.total_download_bytes) - - def testLongRequest(self): - timing_dict = { - 'requestTime': 1200, - 'dnsStart': 20, 'dnsEnd': 30, - 'connectStart': 50, 'connectEnd': 60, - 'sendStart': 70, 'sendEnd': 80, - 'receiveHeadersEnd': 90, - 'loadingFinished': 100} - request = test_utils.MakeRequestWithTiming(1, 2, timing_dict) - request.response_headers = {} - timing_dict = { - 'requestTime': 1200, - 'dnsStart': 2, 'dnsEnd': 3, - 'connectStart': 5, 'connectEnd': 6, - 'sendStart': 7, 'sendEnd': 8, - 'receiveHeadersEnd': 10, - 'loadingFinished': 1000} - long_request = test_utils.MakeRequestWithTiming(1, 2, timing_dict) - long_request.response_headers = {} - long_request.encoded_data_length = 1000 - lens = self._NetworkActivityLens([request, long_request]) - (timestamps, downloaded_bytes) = lens.downloaded_bytes_timeline - (_, download_rate) = lens.download_rate_timeline - start_receive = (long_request.start_msec - + long_request.timing.receive_headers_end) - end_receive = (long_request.start_msec - + long_request.timing.loading_finished) - self.assertEquals(1000, downloaded_bytes[-1]) - for (index, timestamp) in enumerate(timestamps): - if start_receive < timestamp < end_receive: - self.assertAlmostEqual(1000 / 990e-3, download_rate[index]) - self.assertEquals(0, downloaded_bytes[index]) - self.assertEquals(1000, downloaded_bytes[-1]) - - def testDownloadedBytesAt(self): - timing_dict = { - 'requestTime': 1.2, - 'dnsStart': 20, 'dnsEnd': 30, - 'connectStart': 50, 'connectEnd': 60, - 'sendStart': 70, 'sendEnd': 80, - 'receiveHeadersEnd': 90, - 'loadingFinished': 100} - request = test_utils.MakeRequestWithTiming(1, 2, timing_dict) - lens = self._NetworkActivityLens([request]) - # See testTransferredBytes for key events times. We test around events at - # the start, middle and end of the data transfer as well as for the - # interpolation. - self.assertEquals(0, lens.DownloadedBytesAt(1219)) - self.assertEquals(0, lens.DownloadedBytesAt(1220)) - self.assertEquals(0, lens.DownloadedBytesAt(1225)) - self.assertEquals(0, lens.DownloadedBytesAt(1280)) - self.assertEquals(1.6, lens.DownloadedBytesAt(1281)) - self.assertEquals(8, lens.DownloadedBytesAt(1285)) - self.assertEquals(14.4, lens.DownloadedBytesAt(1289)) - self.assertEquals(16, lens.DownloadedBytesAt(1290)) - self.assertEquals(16, lens.DownloadedBytesAt(1291)) - self.assertEquals(16, lens.DownloadedBytesAt(1295)) - self.assertEquals(16, lens.DownloadedBytesAt(1300)) - self.assertEquals(16, lens.DownloadedBytesAt(1400)) - - def _NetworkActivityLens(self, requests): - trace = test_utils.LoadingTraceFromEvents(requests) - return NetworkActivityLens(trace) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/network_cpu_activity_view.py b/tools/android/loading/network_cpu_activity_view.py deleted file mode 100755 index a118823..0000000 --- a/tools/android/loading/network_cpu_activity_view.py +++ /dev/null
@@ -1,73 +0,0 @@ -#!/usr/bin/python -# Copyright 2016 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. - -"""Graphs the CPU and network activity during a load.""" - -import numpy as np -import matplotlib -from matplotlib import pylab as plt -import sys - -import activity_lens -import loading_trace -import network_activity_lens - - -def _CpuActivityTimeline(cpu_lens, start_msec, end_msec, granularity): - cpu_timestamps = np.arange(start_msec, end_msec, granularity) - busy_percentage = [] - print len(cpu_timestamps) - for i in range(len(cpu_timestamps) - 1): - (start, end) = (cpu_timestamps[i], cpu_timestamps[i + 1]) - duration = end - start - busy_ms = cpu_lens.MainRendererThreadBusyness(start, end) - busy_percentage.append(100 * busy_ms / float(duration)) - return (cpu_timestamps[:-1], np.array(busy_percentage)) - - -def GraphTimelines(trace): - """Creates a figure of Network and CPU activity for a trace. - - Args: - trace: (LoadingTrace) - - Returns: - A matplotlib.pylab.figure. - """ - cpu_lens = activity_lens.ActivityLens(trace) - network_lens = network_activity_lens.NetworkActivityLens(trace) - matplotlib.rc('font', size=14) - figure, (network, cpu) = plt.subplots(2, sharex = True, figsize=(14, 10)) - figure.suptitle('Network and CPU Activity - %s' % trace.url) - upload_timeline = network_lens.uploaded_bytes_timeline - download_timeline = network_lens.downloaded_bytes_timeline - start_time = upload_timeline[0][0] - end_time = upload_timeline[0][-1] - times = np.array(upload_timeline[0]) - start_time - network.step(times, np.cumsum(download_timeline[1]) / 1e6, label='Download') - network.step(times, np.cumsum(upload_timeline[1]) / 1e6, label='Upload') - network.legend(loc='lower right') - network.set_xlabel('Time (ms)') - network.set_ylabel('Total Data Transferred (MB)') - - (cpu_timestamps, cpu_busyness) = _CpuActivityTimeline( - cpu_lens, start_time, end_time, 100) - cpu.step(cpu_timestamps - start_time, cpu_busyness) - cpu.set_ylim(ymin=0, ymax=100) - cpu.set_xlabel('Time (ms)') - cpu.set_ylabel('Main Renderer Thread Busyness (%)') - return figure - - -def main(): - filename = sys.argv[1] - trace = loading_trace.LoadingTrace.FromJsonFile(filename) - figure = GraphTimelines(trace, filename + '.pdf') - output_filename = filename + '.pdf' - figure.savefig(output_filename, dpi=300) - - -if __name__ == '__main__': - main()
diff --git a/tools/android/loading/node_cost_csv.py b/tools/android/loading/node_cost_csv.py deleted file mode 100755 index 79d3b06..0000000 --- a/tools/android/loading/node_cost_csv.py +++ /dev/null
@@ -1,61 +0,0 @@ -#! /usr/bin/python -# 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. - -import argparse -import logging -import os -import sys - -from processing import (SitesFromDir, WarmGraph, ColdGraph) - - -def main(): - logging.basicConfig(level=logging.ERROR) - parser = argparse.ArgumentParser( - description=('Convert a directory created by ./analyze.py fetch ' - 'to a node cost CSV which compares cold and warm total ' - 'node costs.')) - parser.add_argument('--datadir', required=True) - parser.add_argument('--csv', required=True) - parser.add_argument('--noads', action='store_true') - args = parser.parse_args() - sites = SitesFromDir(args.datadir) - with open(args.csv, 'w') as output: - output.write('site,cold.total,warm.total,cold.common,warm.common,' - 'cold.node.count,common.cold.node.count,' - 'cold.all.edges,warm.all.edges,' - 'cold.common.edges,warm.common.edges,' - 'cold.edge.fraction,common.cold.edge.fraction\n') - for site in sites: - print site - warm = WarmGraph(args.datadir, site) - if args.noads: - warm.Set(node_filter=warm.FilterAds) - cold = ColdGraph(args.datadir, site) - if args.noads: - cold.Set(node_filter=cold.FilterAds) - common = [p for p in cold.Intersect(warm.Nodes())] - common_cold = set([c.Node() for c, w in common]) - common_warm = set([w.Node() for c, w in common]) - output.write(','.join([str(s) for s in [ - site, - sum((n.NodeCost() for n in cold.Nodes())), - sum((n.NodeCost() for n in warm.Nodes())), - sum((c.NodeCost() for c, w in common)), - sum((w.NodeCost() for c, w in common)), - sum((1 for n in cold.Nodes())), - len(common), - cold.EdgeCosts(), warm.EdgeCosts(), - cold.EdgeCosts(lambda n: n in common_cold), - warm.EdgeCosts(lambda n: n in common_warm), - (cold.EdgeCosts() / - sum((n.NodeCost() for n in cold.Nodes()))), - (cold.EdgeCosts(lambda n: n in common_cold) / - sum((c.NodeCost() for c, w in common))) - ]]) + '\n') - - -if __name__ == '__main__': - main()
diff --git a/tools/android/loading/options.py b/tools/android/loading/options.py deleted file mode 100644 index 5c6234cb..0000000 --- a/tools/android/loading/options.py +++ /dev/null
@@ -1,174 +0,0 @@ -# Copyright 2016 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. - -import argparse -import os.path -import sys - -_SRC_DIR = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..', '..', '..')) -sys.path.append(os.path.join(_SRC_DIR, 'build', 'android')) -from pylib import constants - -class Options(object): - """Global options repository. - - ParseArgs must be called before use. See _ARGS for common members, these will - be available as instance attributes (eg, OPTIONS.clear_cache). - """ - # Tuples of (argument name, default value, help string). - _ARGS = [ ('chrome_package_name', 'chrome', - 'build/android/pylib/constants package description'), - ('devtools_hostname', 'localhost', - 'hostname for devtools websocket connection'), - ('devtools_port', 9222, - 'port for devtools websocket connection'), - ('local_build_dir', None, - 'Build directory for local binary files such as chrome'), - ('local_noisy', False, - 'Enable local chrome console output'), - ('local_profile_dir', None, - 'profile directory to use for local runs'), - ('no_sandbox', False, - 'pass --no-sandbox to browser (local run only; see also ' - 'https://chromium.googlesource.com/chromium/src/+/master/' - 'docs/linux_suid_sandbox_development.md)'), - ('devices_file', _SRC_DIR + '/third_party/blink/renderer/devtools' - '/front_end/emulated_devices/module.json', 'File containing a' - ' list of emulated devices characteristics.') - ] - - - def __init__(self): - self._arg_set = set() - self._parsed_args = None - - def AddGlobalArgument(self, arg_name, default, help_str): - """Add a global argument. - - Args: - arg_name: the name of the argument. This will be used as an optional -- - argument. - default: the default value for the argument. The type of this default will - be used as the type of the argument. - help_str: the argument help string. - """ - self._ARGS.append((arg_name, default, help_str)) - - def ParseArgs(self, arg_list, description=None, extra=None): - """Parse command line arguments. - - Args: - arg_list: command line argument list. - description: description to use in argument parser. - extra: additional required arguments to add. These will be exposed as - instance attributes. This is either a list of extra arguments, or a - single string or tuple. If a tuple, the first item is the argument and - the second a default, otherwise the argument is required. Arguments are - used as in argparse, ie those beginning with -- are named, and those - without a dash are positional. Don't use a single dash. - """ - parser = self._MakeParser(description, extra) - self._parsed_args = parser.parse_args(arg_list) - - def ExtractArgs(self, arg_list): - """Extract arguments from arg_str. - - Args: - arg_list: command line argument list. It will be changed so that arguments - used by this options instance are removed. - """ - parser = self._MakeParser() - (self._parsed_args, unused) = parser.parse_known_args(arg_list) - del arg_list[:] - arg_list.extend(unused) - - def GetParentParser(self, group_name='Global'): - """Returns a parser suitable for passing in as a parent to argparse. - - Args: - group_name: A group name for the parser (see argparse's - add_argument_group). - - Returns: - An argparse parser instance. - """ - return self._MakeParser(group=group_name) - - def SetParsedArgs(self, parsed_args): - """Set parsed args. Used with GetParentParser. - - Args: - parsed_args: the result of argparse.parse_args or similar. - """ - self._parsed_args = parsed_args - - def _MakeParser(self, description=None, extra=None, group=None): - self._arg_set = set() - add_help = True if group is None else False - parser = argparse.ArgumentParser( - description=description, add_help=add_help) - container = parser if group is None else parser.add_argument_group(group) - for arg, default, help_str in self._ARGS: - # All global options are named. - arg = '--' + arg - self._AddArg(container, arg, default, help_str=help_str) - if extra is not None: - if type(extra) is not list: - extra = [extra] - for arg in extra: - if type(arg) is tuple: - argname, default = arg - self._AddArg(container, argname, default) - else: - self._AddArg(container, arg, None, required=True) - return parser - - def _AddArg(self, container, arg, default, required=False, help_str=None): - assert not arg.startswith('-') or arg.startswith('--'), \ - "Single dash arguments aren't supported: %s" % arg - arg_name = arg - if arg.startswith('--'): - arg_name = arg[2:] - assert arg_name not in self._arg_set, \ - '%s extra arg is a duplicate' % arg_name - self._arg_set.add(arg_name) - - kwargs = {} - if required and arg.startswith('--'): - kwargs['required'] = required - if help_str is not None: - kwargs['help'] = help_str - if default is not None: - if type(default) is bool: - # If the default of a switch is true, setting the flag stores false. - if default: - kwargs['action'] = 'store_false' - else: - kwargs['action'] = 'store_true' - else: - kwargs['default'] = default - kwargs['type'] = type(default) - - container.add_argument(arg, **kwargs) - - def __getattr__(self, name): - if name in self._arg_set: - assert self._parsed_args, 'Option requested before ParseArgs called' - return getattr(self._parsed_args, name) - raise AttributeError(name) - - def ChromePackage(self): - return constants.PACKAGE_INFO[self.chrome_package_name] - - def LocalBinary(self, binary_name): - """Get local binary path from its name.""" - assert self.local_build_dir, '--local_build_dir needs to be set.' - path = os.path.join(self.local_build_dir, binary_name) - assert os.path.isfile(path), \ - 'Missing binary file {} (wrong --local_build_dir?).'.format(path) - return path - - -OPTIONS = Options()
diff --git a/tools/android/loading/options_unittest.py b/tools/android/loading/options_unittest.py deleted file mode 100644 index 9ecca66..0000000 --- a/tools/android/loading/options_unittest.py +++ /dev/null
@@ -1,32 +0,0 @@ -# Copyright 2016 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. - -import argparse -import unittest - -import options - - -class OptionsTestCase(unittest.TestCase): - def testExtract(self): - args = ['--A', 'foo', '--devtools_port', '2000', '--B=20', - '--no_sandbox', '--C', '30', 'baz'] - opts = options.Options() - opts.ExtractArgs(args) - self.assertEqual(['--A', 'foo', '--B=20', '--C', '30', 'baz'], args) - self.assertEqual(2000, opts.devtools_port) - self.assertTrue(opts.no_sandbox) - - def testParent(self): - opts = options.Options() - parser = argparse.ArgumentParser(parents=[opts.GetParentParser()]) - parser.add_argument('--foo', type=int) - parsed_args = parser.parse_args(['--foo=4', '--devtools_port', '2000']) - self.assertEqual(4, parsed_args.foo) - opts.SetParsedArgs(parsed_args) - self.assertEqual(2000, opts.devtools_port) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/page_track.py b/tools/android/loading/page_track.py deleted file mode 100644 index bc904ba..0000000 --- a/tools/android/loading/page_track.py +++ /dev/null
@@ -1,71 +0,0 @@ -# Copyright 2016 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. - -import devtools_monitor - - -class PageTrack(devtools_monitor.Track): - """Records the events from the page track.""" - _METHODS = ('Page.frameStartedLoading', 'Page.frameStoppedLoading', - 'Page.frameAttached') - FRAME_STARTED_LOADING = 'Page.frameStartedLoading' - def __init__(self, connection): - super(PageTrack, self).__init__(connection) - self._connection = connection - self._events = [] - self._pending_frames = set() - self._known_frames = set() - self._main_frame_id = None - if self._connection: - for method in PageTrack._METHODS: - self._connection.RegisterListener(method, self) - - def Handle(self, method, msg): - assert method in PageTrack._METHODS - params = msg['params'] - frame_id = params['frameId'] - should_stop = False - event = {'method': method, 'frame_id': frame_id} - if method == self.FRAME_STARTED_LOADING: - if self._main_frame_id is None: - self._main_frame_id = params['frameId'] - self._pending_frames.add(frame_id) - self._known_frames.add(frame_id) - elif method == 'Page.frameStoppedLoading': - assert frame_id in self._pending_frames - self._pending_frames.remove(frame_id) - if frame_id == self._main_frame_id: - should_stop = True - elif method == 'Page.frameAttached': - self._known_frames.add(frame_id) - parent_frame = params['parentFrameId'] - assert parent_frame in self._known_frames - event['parent_frame_id'] = parent_frame - self._events.append(event) - if should_stop and self._connection: - self._connection.StopMonitoring() - - def GetEvents(self): - #TODO(lizeb): Add more checks here (child frame stops loading before parent, - #for instance). - return self._events - - def ToJsonDict(self): - return {'events': [event for event in self._events]} - - def GetMainFrameId(self): - """Returns the Id (str) of the main frame, or raises a ValueError.""" - for event in self._events: - if event['method'] == self.FRAME_STARTED_LOADING: - return event['frame_id'] - else: - raise ValueError('No frame loads in the track.') - - @classmethod - def FromJsonDict(cls, json_dict): - assert 'events' in json_dict - result = PageTrack(None) - events = [event for event in json_dict['events']] - result._events = events - return result
diff --git a/tools/android/loading/page_track_unittest.py b/tools/android/loading/page_track_unittest.py deleted file mode 100644 index 3056d99f..0000000 --- a/tools/android/loading/page_track_unittest.py +++ /dev/null
@@ -1,65 +0,0 @@ -# Copyright 2016 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. - -import unittest - -import devtools_monitor -from page_track import PageTrack - -class MockDevToolsConnection(object): - def __init__(self): - self.stop_has_been_called = False - - def RegisterListener(self, name, listener): - pass - - def StopMonitoring(self): - self.stop_has_been_called = True - - -class PageTrackTest(unittest.TestCase): - _EVENTS = [{'method': 'Page.frameStartedLoading', - 'params': {'frameId': '1234.1'}}, - {'method': 'Page.frameAttached', - 'params': {'frameId': '1234.12', 'parentFrameId': '1234.1'}}, - {'method': 'Page.frameStartedLoading', - 'params': {'frameId': '1234.12'}}, - {'method': 'Page.frameStoppedLoading', - 'params': {'frameId': '1234.12'}}, - {'method': 'Page.frameStoppedLoading', - 'params': {'frameId': '1234.1'}}] - def testAsksMonitoringToStop(self): - devtools_connection = MockDevToolsConnection() - page_track = PageTrack(devtools_connection) - for msg in PageTrackTest._EVENTS[:-1]: - page_track.Handle(msg['method'], msg) - self.assertFalse(devtools_connection.stop_has_been_called) - msg = PageTrackTest._EVENTS[-1] - page_track.Handle(msg['method'], msg) - self.assertTrue(devtools_connection.stop_has_been_called) - - def testUnknownParent(self): - page_track = PageTrack(None) - msg = {'method': 'Page.frameAttached', - 'params': {'frameId': '1234.12', 'parentFrameId': '1234.1'}} - with self.assertRaises(AssertionError): - page_track.Handle(msg['method'], msg) - - def testStopsLoadingUnknownFrame(self): - page_track = PageTrack(None) - msg = {'method': 'Page.frameStoppedLoading', - 'params': {'frameId': '1234.12'}} - with self.assertRaises(AssertionError): - page_track.Handle(msg['method'], msg) - - def testGetMainFrameId(self): - devtools_connection = MockDevToolsConnection() - page_track = PageTrack(devtools_connection) - for msg in PageTrackTest._EVENTS: - page_track.Handle(msg['method'], msg) - self.assertEquals('1234.1', page_track.GetMainFrameId()) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/prefetch_view.py b/tools/android/loading/prefetch_view.py deleted file mode 100644 index cbd882a..0000000 --- a/tools/android/loading/prefetch_view.py +++ /dev/null
@@ -1,191 +0,0 @@ -# Copyright 2016 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. - -"""Models the effect of prefetching resources from a loading trace. - -For example, this can be used to evaluate NoState Prefetch -(https://goo.gl/B3nRUR). - -When executed as a script, takes a trace as a command-line arguments and shows -statistics about it. -""" - -import itertools -import operator - -import common_util -import dependency_graph -import graph -import loading_trace -import user_satisfied_lens -import request_dependencies_lens -import request_track - - -class RequestNode(dependency_graph.RequestNode): - """Simulates the effect of prefetching resources discoverable by the preload - scanner. - """ - _ATTRS = ['preloaded', 'before'] - def __init__(self, request=None): - super(RequestNode, self).__init__(request) - self.preloaded = False - self.before = False - - def ToJsonDict(self): - result = super(RequestNode, self).ToJsonDict() - return common_util.SerializeAttributesToJsonDict(result, self, self._ATTRS) - - @classmethod - def FromJsonDict(cls, json_dict): - result = super(RequestNode, cls).FromJsonDict(json_dict) - return common_util.DeserializeAttributesFromJsonDict( - json_dict, result, cls._ATTRS) - - -class PrefetchSimulationView(object): - """Simulates the effect of prefetch.""" - def __init__(self, trace, dependencies_lens, user_lens): - self.postload_msec = None - self.graph = None - if trace is None: - return - requests = trace.request_track.GetEvents() - critical_requests_ids = user_lens.CriticalRequestIds() - self.postload_msec = user_lens.PostloadTimeMsec() - self.graph = dependency_graph.RequestDependencyGraph( - requests, dependencies_lens, node_class=RequestNode) - preloaded_requests = [r.request_id for r in self.PreloadedRequests( - requests[0], dependencies_lens, trace)] - self._AnnotateNodes(self.graph.graph.Nodes(), preloaded_requests, - critical_requests_ids) - - def Cost(self): - """Returns the cost of the graph, restricted to the critical requests.""" - pruned_graph = self._PrunedGraph() - return pruned_graph.Cost() + self.postload_msec - - def UpdateNodeCosts(self, node_to_cost): - """Updates the cost of nodes, according to |node_to_cost|. - - Args: - node_to_cost: (Callable) RequestNode -> float. Callable returning the cost - of a node. - """ - pruned_graph = self._PrunedGraph() - for node in pruned_graph.Nodes(): - node.cost = node_to_cost(node) - - def ToJsonDict(self): - """Returns a dict representing this instance.""" - result = {'graph': self.graph.ToJsonDict()} - return common_util.SerializeAttributesToJsonDict( - result, self, ['postload_msec']) - - @classmethod - def FromJsonDict(cls, json_dict): - """Returns an instance of PrefetchSimulationView from a dict dumped by - ToJSonDict(). - """ - result = cls(None, None, None) - result.graph = dependency_graph.RequestDependencyGraph.FromJsonDict( - json_dict['graph'], RequestNode, dependency_graph.Edge) - return common_util.DeserializeAttributesFromJsonDict( - json_dict, result, ['postload_msec']) - - @classmethod - def _AnnotateNodes(cls, nodes, preloaded_requests_ids, - critical_requests_ids,): - for node in nodes: - node.preloaded = node.request.request_id in preloaded_requests_ids - node.before = node.request.request_id in critical_requests_ids - - @classmethod - def ParserDiscoverableRequests( - cls, request, dependencies_lens, recurse=False): - """Returns a list of requests IDs dicovered by the parser. - - Args: - request: (Request) Root request. - - Returns: - [Request] - """ - # TODO(lizeb): handle the recursive case. - assert not recurse - discoverable_requests = [request] - first_request = dependencies_lens.GetRedirectChain(request)[-1] - deps = dependencies_lens.GetRequestDependencies() - for (first, second, reason) in deps: - if first.request_id == first_request.request_id and reason == 'parser': - discoverable_requests.append(second) - return discoverable_requests - - @classmethod - def _ExpandRedirectChains(cls, requests, dependencies_lens): - return list(itertools.chain.from_iterable( - [dependencies_lens.GetRedirectChain(r) for r in requests])) - - @classmethod - def PreloadedRequests(cls, request, dependencies_lens, trace): - """Returns the requests that have been preloaded from a given request. - - This list is the set of request that are: - - Discoverable by the parser - - Found in the trace log. - - Before looking for dependencies, this follows the redirect chain. - - Args: - request: (Request) Root request. - - Returns: - A list of Request. Does not include the root request. This list is a - subset of the one returned by ParserDiscoverableRequests(). - """ - # Preload step events are emitted in ResourceFetcher::preloadStarted(). - resource_events = trace.tracing_track.Filter( - categories=set([u'blink.net'])) - preload_step_events = filter( - lambda e: e.args.get('step') == 'Preload', - resource_events.GetEvents()) - preloaded_urls = set() - for preload_step_event in preload_step_events: - preload_event = resource_events.EventFromStep(preload_step_event) - if preload_event: - preloaded_urls.add(preload_event.args['data']['url']) - parser_requests = cls.ParserDiscoverableRequests( - request, dependencies_lens) - preloaded_root_requests = filter( - lambda r: r.url in preloaded_urls, parser_requests) - # We can actually fetch the whole redirect chain. - return [request] + list(itertools.chain.from_iterable( - [dependencies_lens.GetRedirectChain(r) - for r in preloaded_root_requests])) - - def _PrunedGraph(self): - roots = self.graph.graph.RootNodes() - nodes = self.graph.graph.ReachableNodes( - roots, should_stop=lambda n: not n.before) - return graph.DirectedGraph(nodes, self.graph.graph.Edges()) - - -def _PrintSumamry(trace, dependencies_lens, user_lens): - prefetch_view = PrefetchSimulationView(trace, dependencies_lens, user_lens) - print 'Time to First Contentful Paint = %.02fms' % prefetch_view.Cost() - print 'Set costs of prefetched requests to 0.' - prefetch_view.UpdateNodeCosts(lambda n: 0 if n.preloaded else n.cost) - print 'Time to First Contentful Paint = %.02fms' % prefetch_view.Cost() - - -def main(filename): - trace = loading_trace.LoadingTrace.FromJsonFile(filename) - dependencies_lens = request_dependencies_lens.RequestDependencyLens(trace) - user_lens = user_satisfied_lens.FirstContentfulPaintLens(trace) - _PrintSumamry(trace, dependencies_lens, user_lens) - - -if __name__ == '__main__': - import sys - main(sys.argv[1])
diff --git a/tools/android/loading/prefetch_view_unittest.py b/tools/android/loading/prefetch_view_unittest.py deleted file mode 100644 index 1f85019..0000000 --- a/tools/android/loading/prefetch_view_unittest.py +++ /dev/null
@@ -1,95 +0,0 @@ -# Copyright 2016 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. - -import unittest - -from prefetch_view import PrefetchSimulationView -import request_dependencies_lens -from request_dependencies_lens_unittest import TestRequests -import request_track -import test_utils - - -class PrefetchSimulationViewTestCase(unittest.TestCase): - def setUp(self): - super(PrefetchSimulationViewTestCase, self).setUp() - self._SetUp() - - def testExpandRedirectChains(self): - self.assertListEqual( - [TestRequests.FIRST_REDIRECT_REQUEST, - TestRequests.SECOND_REDIRECT_REQUEST, TestRequests.REDIRECTED_REQUEST], - PrefetchSimulationView._ExpandRedirectChains( - [TestRequests.FIRST_REDIRECT_REQUEST], self.dependencies_lens)) - - def testParserDiscoverableRequests(self): - first_request = TestRequests.FIRST_REDIRECT_REQUEST - discovered_requests = PrefetchSimulationView.ParserDiscoverableRequests( - first_request, self.dependencies_lens) - self.assertListEqual( - [TestRequests.FIRST_REDIRECT_REQUEST, - TestRequests.JS_REQUEST, TestRequests.JS_REQUEST_OTHER_FRAME, - TestRequests.JS_REQUEST_UNRELATED_FRAME], discovered_requests) - - def testPreloadedRequests(self): - first_request = TestRequests.FIRST_REDIRECT_REQUEST - preloaded_requests = PrefetchSimulationView.PreloadedRequests( - first_request, self.dependencies_lens, self.trace) - self.assertListEqual([first_request], preloaded_requests) - self._SetUp( - [{'args': {'data': {'url': 'http://bla.com/nyancat.js'}}, - 'cat': 'blink.net', 'id': '0xaf9f14fa9dd6c314', 'name': 'Resource', - 'ph': 'X', 'ts': 1, 'dur': 120, 'pid': 12, 'tid': 12}, - {'args': {'step': 'Preload'}, 'cat': 'blink.net', - 'id': '0xaf9f14fa9dd6c314', 'name': 'Resource', 'ph': 'T', - 'ts': 12, 'pid': 12, 'tid': 12}]) - preloaded_requests = PrefetchSimulationView.PreloadedRequests( - first_request, self.dependencies_lens, self.trace) - self.assertListEqual([TestRequests.FIRST_REDIRECT_REQUEST, - TestRequests.JS_REQUEST, TestRequests.JS_REQUEST_OTHER_FRAME, - TestRequests.JS_REQUEST_UNRELATED_FRAME], preloaded_requests) - - def testCost(self): - self.assertEqual(40 + 12, self.prefetch_view.Cost()) - - def testUpdateNodeCosts(self): - self.prefetch_view.UpdateNodeCosts(lambda _: 100) - self.assertEqual(500 + 40 + 12, self.prefetch_view.Cost()) - - def testUpdateNodeCostsPartial(self): - self.prefetch_view.UpdateNodeCosts( - lambda n: 100 if (n.request.request_id - == TestRequests.REDIRECTED_REQUEST.request_id) else 0) - self.assertEqual(100 + 40 + 12, self.prefetch_view.Cost()) - - def testToFromJsonDict(self): - self.assertEqual(40 + 12, self.prefetch_view.Cost()) - json_dict = self.prefetch_view.ToJsonDict() - new_view = PrefetchSimulationView.FromJsonDict(json_dict) - self.assertEqual(40 + 12, new_view.Cost()) - # Updated Costs. - self.prefetch_view.UpdateNodeCosts(lambda _: 100) - self.assertEqual(500 + 40 + 12, self.prefetch_view.Cost()) - json_dict = self.prefetch_view.ToJsonDict() - new_view = PrefetchSimulationView.FromJsonDict(json_dict) - self.assertEqual(500 + 40 + 12, new_view.Cost()) - - def _SetUp(self, added_trace_events=None): - trace_events = [ - {'ts': 5, 'ph': 'X', 'dur': 10, 'pid': 2, 'tid': 1, 'cat': 'blink.net'}] - if added_trace_events is not None: - trace_events += added_trace_events - self.trace = TestRequests.CreateLoadingTrace(trace_events) - self.dependencies_lens = request_dependencies_lens.RequestDependencyLens( - self.trace) - self.user_satisfied_lens = test_utils.MockUserSatisfiedLens(self.trace) - self.user_satisfied_lens._postload_msec = 12 - self.prefetch_view = PrefetchSimulationView( - self.trace, self.dependencies_lens, self.user_satisfied_lens) - for e in self.prefetch_view.graph.graph.Edges(): - e.cost = 10 - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/processing.py b/tools/android/loading/processing.py deleted file mode 100644 index 7c00951..0000000 --- a/tools/android/loading/processing.py +++ /dev/null
@@ -1,75 +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. - -import json -import os -import os.path -import sys - -import loading_model -import loading_trace - - -def SitesFromDir(directory): - """Extract sites from a data directory. - - Based on ./analyze.py fetch file name conventions. We assume each site - corresponds to two files, <site>.json and <site>.json.cold, and that no other - kind of file appears in the data directory. - - Args: - directory: the directory to process. - - Returns: - A list of sites as strings. - - """ - files = set(os.listdir(directory)) - assert files - sites = [] - for f in files: - if f.endswith('.png'): - continue - assert f.endswith('.json') or f.endswith('.json.cold'), f - if f.endswith('.json'): - assert f + '.cold' in files - sites.append(f[:f.rfind('.json')]) - elif f.endswith('.cold'): - assert f[:f.rfind('.cold')] in files - sites.sort() - return sites - - -def WarmGraph(datadir, site): - """Return a loading model graph for the warm pull of site. - - Based on ./analyze.py fetch file name conventions. - - Args: - datadir: the directory containing site JSON data. - site: a site string. - - Returns: - A loading model object. - """ - with file(os.path.join(datadir, site + '.json')) as f: - return loading_model.ResourceGraph(loading_trace.LoadingTrace.FromJsonDict( - json.load(f))) - - -def ColdGraph(datadir, site): - """Return a loading model graph for the cold pull of site. - - Based on ./analyze.py fetch file name conventions. - - Args: - datadir: the directory containing site JSON data. - site: a site string. - - Returns: - A loading model object. - """ - with file(os.path.join(datadir, site + '.json.cold')) as f: - return loading_model.ResourceGraph(loading_trace.LoadingTrace.FromJsonDict( - json.load(f)))
diff --git a/tools/android/loading/queuing_lens.py b/tools/android/loading/queuing_lens.py deleted file mode 100644 index e29ce7a..0000000 --- a/tools/android/loading/queuing_lens.py +++ /dev/null
@@ -1,161 +0,0 @@ -# Copyright 2016 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. - -"""Lens for resource load queuing. - -When executed as a script, takes a loading trace and prints queuing information -for each request. -""" - -import collections -import itertools -import logging - -import clovis_constants - - -class QueuingLens(object): - """Attaches queuing related trace events to request objects.""" - QUEUING_CATEGORY = clovis_constants.QUEUING_CATEGORY - ASYNC_NAME = 'ScheduledResourceRequest' - READY_NAME = 'ScheduledResourceRequest.Ready' - SET_PRIORITY_NAME = 'ScheduledResourceRequest.SetPriority' - QUEUING_NAMES = set([ASYNC_NAME, - READY_NAME, - SET_PRIORITY_NAME]) - - IN_FLIGHT_NAME = 'ResourceScheduler::Client.InFlightRequests' - SHOULD_START_NAME = 'ResourceScheduler::Client::ShouldStartRequestInfo' - - def __init__(self, trace): - self._request_track = trace.request_track - self._queuing_events_by_id = self._GetQueuingEvents(trace.tracing_track) - self._source_id_to_url = {} - for source_id, events in self._queuing_events_by_id.iteritems(): - self._source_id_to_url[source_id] = self._GetQueuingEventUrl(events) - - def GenerateRequestQueuing(self): - """Computes queuing information for each request. - - We determine blocking requests by looking at which urls are in-flight - (created but not yet destroyed) at the time of the creation of each - request. This means that a request that we list as blocking may just be - queued (throttled) at the same time as our request, and not actually - blocking. - - The lifetime of the queuing events extends from when a resource is first - slotted into the sytem until the request is complete. The main interesting - queuing events are begin, end (which define the lifetime) and ready, an - instant event that is usually within a millisecond after the request_time of - the Request. - - Returns: - {request_track.Request: - (start_msec: throttle start, end_msec: throttle end, - ready_msec: ready, - blocking: [blocking requests], - source_ids: [source ids of the request])}, where the map values are - a named tuple with the specified fields. - """ - url_to_requests = collections.defaultdict(list) - for rq in self._request_track.GetEvents(): - url_to_requests[rq.url].append(rq) - # Queuing events are organized by source id, which corresponds to a load of - # a url. First collect timing information for each source id, then associate - # with each request. - timing_by_source_id = {} - for source_id, events in self._queuing_events_by_id.iteritems(): - assert all(e.end_msec is None for e in events), \ - 'Unexpected end_msec for nested async queuing events' - ready_times = [e.start_msec for e in events if e.name == self.READY_NAME] - if not ready_times: - ready_msec = None - else: - assert len(ready_times) == 1, events - ready_msec = ready_times[0] - timing_by_source_id[source_id] = ( - min(e.start_msec for e in events), - max(e.start_msec for e in events), - ready_msec) - queue_info = {} - for request_url, requests in url_to_requests.iteritems(): - matching_source_ids = set( - source_id for source_id, url in self._source_id_to_url.iteritems() - if url == request_url) - if len(matching_source_ids) > 1: - logging.warning('Multiple matching source ids, probably duplicated' - 'urls: %s', [rq.url for rq in requests]) - # Get first source id. - sid = next(s for s in matching_source_ids) \ - if matching_source_ids else None - (throttle_start_msec, throttle_end_msec, ready_msec) = \ - timing_by_source_id[sid] if matching_source_ids else (-1, -1, -1) - - blocking_requests = [] - for sid, (flight_start_msec, - flight_end_msec, _) in timing_by_source_id.iteritems(): - if (flight_start_msec < throttle_start_msec and - flight_end_msec > throttle_start_msec and - flight_end_msec < throttle_end_msec): - blocking_requests.extend( - url_to_requests.get(self._source_id_to_url[sid], [])) - - info = collections.namedtuple( - 'QueueInfo', ['start_msec', 'end_msec', 'ready_msec', 'blocking' - 'source_ids']) - info.start_msec = throttle_start_msec - info.end_msec = throttle_end_msec - info.ready_msec = ready_msec - current_request_ids = set(rq.request_id for rq in requests) - info.blocking = [b for b in blocking_requests - if b is not None and - b.request_id not in current_request_ids] - info.source_ids = matching_source_ids - for rq in requests: - queue_info[rq] = info - return queue_info - - def _GetQueuingEvents(self, tracing_track): - events = collections.defaultdict(list) - for e in tracing_track.GetEvents(): - if (e.category == self.QUEUING_CATEGORY and - e.name in self.QUEUING_NAMES): - events[e.args['data']['source_id']].append(e) - return events - - def _GetQueuingEventUrl(self, events): - urls = set() - for e in events: - if 'request_url' in e.args['data']: - urls.add(e.args['data']['request_url']) - assert len(urls) == 1, urls - return urls.pop() - - def _GetEventsForRequest(self, request): - request_events = [] - for source_id, url in self._source_id_to_url: - if url == request.url: - request_events.extend(self._queuing_events_by_id[source_id]) - return request_events - - -def _Main(trace_file): - import loading_trace - trace = loading_trace.LoadingTrace.FromJsonFile(trace_file) - lens = QueuingLens(trace) - queue_info = lens.GenerateRequestQueuing() - base_msec = trace.request_track.GetFirstRequestMillis() - mkmsec = lambda ms: ms - base_msec if ms > 0 else -1 - for rq, info in queue_info.iteritems(): - print '{fp} ({ts}->{te})[{rs}->{re}] {ids} {url}'.format( - fp=rq.fingerprint, - ts=mkmsec(info.start_msec), te=mkmsec(info.end_msec), - rs=mkmsec(rq.start_msec), re=mkmsec(rq.end_msec), - ids=info.source_ids, url=rq.url) - for blocking_request in info.blocking: - print ' {} {}'.format(blocking_request.fingerprint, blocking_request.url) - -if __name__ == '__main__': - import sys - _Main(sys.argv[1])
diff --git a/tools/android/loading/queuing_lens_unittest.py b/tools/android/loading/queuing_lens_unittest.py deleted file mode 100644 index 2b0a8d7..0000000 --- a/tools/android/loading/queuing_lens_unittest.py +++ /dev/null
@@ -1,114 +0,0 @@ -# Copyright 2016 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. - -import unittest - -from queuing_lens import QueuingLens -import request_track -import test_utils - -class QueuingLensTestCase(unittest.TestCase): - MILLIS_TO_MICROS = 1000 - MILLIS_TO_SECONDS = 0.001 - URL_1 = 'http://1' - URL_2 = 'http://2' - - def testRequestQueuing(self): - # http://1: queued at 5ms, request start at 10ms, ready at 11ms, - # done at 12ms; blocked by 2. - # http://2: queued at 4ms, request start at 4ms, ready at 5 ms, done at 9ms. - trace_events = [ - {'args': { - 'data': { - 'request_url': self.URL_1, - 'source_id': 1 - } - }, - 'cat': QueuingLens.QUEUING_CATEGORY, - 'id': 1, - 'name': QueuingLens.ASYNC_NAME, - 'ph': 'b', - 'ts': 5 * self.MILLIS_TO_MICROS - }, - {'args': { - 'data': { - 'source_id': 1 - } - }, - 'cat': QueuingLens.QUEUING_CATEGORY, - 'id': 1, - 'name': QueuingLens.READY_NAME, - 'ph': 'n', - 'ts': 10 * self.MILLIS_TO_MICROS - }, - {'args': { - 'data': { - 'source_id': 1 - } - }, - 'cat': QueuingLens.QUEUING_CATEGORY, - 'id': 1, - 'name': QueuingLens.ASYNC_NAME, - 'ph': 'e', - 'ts': 12 * self.MILLIS_TO_MICROS - }, - - {'args': { - 'data': { - 'request_url': self.URL_2, - 'source_id': 2 - } - }, - 'cat': QueuingLens.QUEUING_CATEGORY, - 'id': 2, - 'name': QueuingLens.ASYNC_NAME, - 'ph': 'b', - 'ts': 4 * self.MILLIS_TO_MICROS - }, - {'args': { - 'data': { - 'source_id': 2 - } - }, - 'cat': QueuingLens.QUEUING_CATEGORY, - 'id': 2, - 'name': QueuingLens.READY_NAME, - 'ph': 'n', - 'ts': 5 * self.MILLIS_TO_MICROS - }, - {'args': { - 'data': { - 'source_id': 2 - } - }, - 'cat': QueuingLens.QUEUING_CATEGORY, - 'id': 2, - 'name': QueuingLens.ASYNC_NAME, - 'ph': 'e', - 'ts': 9 * self.MILLIS_TO_MICROS - }] - requests = [ - request_track.Request.FromJsonDict( - {'url': self.URL_1, - 'request_id': '0.1', - 'timing': {'request_time': 10 * self.MILLIS_TO_SECONDS, - 'loading_finished': 2}}), - request_track.Request.FromJsonDict( - {'url': self.URL_2, - 'request_id': '0.2', - 'timing': {'request_time': 4 * self.MILLIS_TO_SECONDS, - 'loading_finished': 5}})] - trace = test_utils.LoadingTraceFromEvents( - requests=requests, trace_events=trace_events) - queue_info = QueuingLens(trace).GenerateRequestQueuing() - self.assertEqual(set(['0.2']), - set(rq.request_id - for rq in queue_info[requests[0]].blocking)) - self.assertEqual((5., 10., 12.), (queue_info[requests[0]].start_msec, - queue_info[requests[0]].ready_msec, - queue_info[requests[0]].end_msec)) - self.assertEqual(0, len(queue_info[requests[1]].blocking)) - self.assertEqual((4., 5., 9.), (queue_info[requests[1]].start_msec, - queue_info[requests[1]].ready_msec, - queue_info[requests[1]].end_msec))
diff --git a/tools/android/loading/report.py b/tools/android/loading/report.py deleted file mode 100644 index 23a39a4..0000000 --- a/tools/android/loading/report.py +++ /dev/null
@@ -1,298 +0,0 @@ -# Copyright 2016 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. - -"""Generates a loading report. - -When executed as a script, takes a trace filename and print the report. -""" - -from activity_lens import ActivityLens -from content_classification_lens import ContentClassificationLens -from loading_graph_view import LoadingGraphView -import loading_trace -import metrics -from network_activity_lens import NetworkActivityLens -from prefetch_view import PrefetchSimulationView -from queuing_lens import QueuingLens -import request_dependencies_lens -from user_satisfied_lens import ( - FirstTextPaintLens, FirstContentfulPaintLens, FirstSignificantPaintLens, - PLTLens) - - -def _ComputeCpuBusyness(activity, load_start, satisfied_end): - """Generates a breakdown of CPU activity between |load_start| and - |satisfied_end|.""" - duration = float(satisfied_end - load_start) - result = { - 'activity_frac': ( - activity.MainRendererThreadBusyness(load_start, satisfied_end) - / duration), - } - - activity_breakdown = activity.ComputeActivity(load_start, satisfied_end) - result['parsing_frac'] = ( - sum(activity_breakdown['parsing'].values()) / duration) - result['script_frac'] = ( - sum(activity_breakdown['script'].values()) / duration) - return result - - -class PerUserLensReport(object): - """Generates a variety of metrics relative to a passed in user lens.""" - - def __init__(self, trace, user_lens, activity_lens, network_lens, - navigation_start_msec): - requests = trace.request_track.GetEvents() - dependencies_lens = request_dependencies_lens.RequestDependencyLens( - trace) - prefetch_view = PrefetchSimulationView(trace, dependencies_lens, user_lens) - preloaded_requests = prefetch_view.PreloadedRequests( - requests[0], dependencies_lens, trace) - - self._navigation_start_msec = navigation_start_msec - - self._satisfied_msec = user_lens.SatisfiedMs() - - graph = LoadingGraphView.FromTrace(trace) - self._inversions = graph.GetInversionsAtTime(self._satisfied_msec) - - self._byte_frac = self._GenerateByteFrac(network_lens) - - self._requests = user_lens.CriticalRequests() - self._preloaded_requests = ( - [r for r in preloaded_requests if r in self._requests]) - - self._cpu_busyness = _ComputeCpuBusyness(activity_lens, - navigation_start_msec, - self._satisfied_msec) - prefetch_view.UpdateNodeCosts(lambda n: 0 if n.preloaded else n.cost) - self._no_state_prefetch_ms = prefetch_view.Cost() - - def GenerateReport(self): - report = {} - - report['ms'] = self._satisfied_msec - self._navigation_start_msec - report['byte_frac'] = self._byte_frac - - report['requests'] = len(self._requests) - report['preloaded_requests'] = len(self._preloaded_requests) - report['requests_cost'] = reduce(lambda x,y: x + y.Cost(), - self._requests, 0) - report['preloaded_requests_cost'] = reduce(lambda x,y: x + y.Cost(), - self._preloaded_requests, 0) - report['predicted_no_state_prefetch_ms'] = self._no_state_prefetch_ms - - # Take the first (earliest) inversion. - report['inversion'] = self._inversions[0].url if self._inversions else '' - - report.update(self._cpu_busyness) - return report - - def _GenerateByteFrac(self, network_lens): - if not network_lens.total_download_bytes: - return float('Nan') - byte_frac = (network_lens.DownloadedBytesAt(self._satisfied_msec) - / float(network_lens.total_download_bytes)) - return byte_frac - - -class LoadingReport(object): - """Generates a loading report from a loading trace.""" - def __init__(self, trace, ad_rules=None, tracking_rules=None): - """Constructor. - - Args: - trace: (LoadingTrace) a loading trace. - ad_rules: ([str]) List of ad filtering rules. - tracking_rules: ([str]) List of tracking filtering rules. - """ - self.trace = trace - - navigation_start_events = trace.tracing_track.GetMatchingEvents( - 'blink.user_timing', 'navigationStart') - self._navigation_start_msec = min( - e.start_msec for e in navigation_start_events) - - self._dns_requests, self._dns_cost_msec = metrics.DnsRequestsAndCost(trace) - self._connection_stats = metrics.ConnectionMetrics(trace) - - self._user_lens_reports = {} - plt_lens = PLTLens(self.trace) - first_text_paint_lens = FirstTextPaintLens(self.trace) - first_contentful_paint_lens = FirstContentfulPaintLens(self.trace) - first_significant_paint_lens = FirstSignificantPaintLens(self.trace) - activity = ActivityLens(trace) - network_lens = NetworkActivityLens(self.trace) - for key, user_lens in [['plt', plt_lens], - ['first_text', first_text_paint_lens], - ['contentful', first_contentful_paint_lens], - ['significant', first_significant_paint_lens]]: - self._user_lens_reports[key] = PerUserLensReport(self.trace, - user_lens, activity, network_lens, self._navigation_start_msec) - - self._transfer_size = metrics.TotalTransferSize(trace)[1] - self._request_count = len(trace.request_track.GetEvents()) - - content_lens = ContentClassificationLens( - trace, ad_rules or [], tracking_rules or []) - has_ad_rules = bool(ad_rules) - has_tracking_rules = bool(tracking_rules) - self._ad_report = self._AdRequestsReport( - trace, content_lens, has_ad_rules, has_tracking_rules) - self._ads_cost = self._AdsAndTrackingCpuCost( - self._navigation_start_msec, - (self._navigation_start_msec - + self._user_lens_reports['plt'].GenerateReport()['ms']), - content_lens, activity, has_tracking_rules or has_ad_rules) - - self._queue_stats = self._ComputeQueueStats(QueuingLens(trace)) - - def GenerateReport(self): - """Returns a report as a dict.""" - # NOTE: When changing the return value here, also update the schema - # (bigquery_schema.json) accordingly. See cloud/frontend/README.md for - # details. - report = { - 'url': self.trace.url, - 'transfer_size': self._transfer_size, - 'dns_requests': self._dns_requests, - 'dns_cost_ms': self._dns_cost_msec, - 'total_requests': self._request_count} - - for user_lens_type, user_lens_report in self._user_lens_reports.iteritems(): - for key, value in user_lens_report.GenerateReport().iteritems(): - report[user_lens_type + '_' + key] = value - - report.update(self._ad_report) - report.update(self._ads_cost) - report.update(self._connection_stats) - report.update(self._queue_stats) - return report - - @classmethod - def FromTraceFilename(cls, filename, ad_rules_filename, - tracking_rules_filename): - """Returns a LoadingReport from a trace filename.""" - trace = loading_trace.LoadingTrace.FromJsonFile(filename) - return LoadingReport(trace, ad_rules_filename, tracking_rules_filename) - - @classmethod - def _AdRequestsReport( - cls, trace, content_lens, has_ad_rules, has_tracking_rules): - requests = trace.request_track.GetEvents() - has_rules = has_ad_rules or has_tracking_rules - result = { - 'ad_requests': 0 if has_ad_rules else None, - 'tracking_requests': 0 if has_tracking_rules else None, - 'ad_or_tracking_requests': 0 if has_rules else None, - 'ad_or_tracking_initiated_requests': 0 if has_rules else None, - 'ad_or_tracking_initiated_transfer_size': 0 if has_rules else None} - if not has_rules: - return result - for request in requests: - is_ad = content_lens.IsAdRequest(request) - is_tracking = content_lens.IsTrackingRequest(request) - if has_ad_rules: - result['ad_requests'] += int(is_ad) - if has_tracking_rules: - result['tracking_requests'] += int(is_tracking) - result['ad_or_tracking_requests'] += int(is_ad or is_tracking) - ad_tracking_requests = content_lens.AdAndTrackingRequests() - result['ad_or_tracking_initiated_requests'] = len(ad_tracking_requests) - result['ad_or_tracking_initiated_transfer_size'] = metrics.TransferSize( - ad_tracking_requests)[1] - return result - - @classmethod - def _ComputeQueueStats(cls, queue_lens): - queuing_info = queue_lens.GenerateRequestQueuing() - total_blocked_msec = 0 - total_loading_msec = 0 - num_blocking_requests = [] - for queue_info in queuing_info.itervalues(): - try: - total_blocked_msec += max(0, queue_info.ready_msec - - queue_info.start_msec) - total_loading_msec += max(0, queue_info.end_msec - - queue_info.start_msec) - except TypeError: - pass # Invalid queue info timings. - num_blocking_requests.append(len(queue_info.blocking)) - if num_blocking_requests: - num_blocking_requests.sort() - avg_blocking = (float(sum(num_blocking_requests)) / - len(num_blocking_requests)) - mid = len(num_blocking_requests) / 2 - if len(num_blocking_requests) & 1: - median_blocking = num_blocking_requests[mid] - else: - median_blocking = (num_blocking_requests[mid-1] + - num_blocking_requests[mid]) / 2 - else: - avg_blocking = 0 - median_blocking = 0 - return { - 'total_queuing_blocked_msec': int(total_blocked_msec), - 'total_queuing_load_msec': int(total_loading_msec), - 'average_blocking_request_count': avg_blocking, - 'median_blocking_request_count': median_blocking, - } - - @classmethod - def _AdsAndTrackingCpuCost( - cls, start_msec, end_msec, content_lens, activity, has_rules): - """Returns the CPU cost associated with Ads and tracking between timestamps. - - Can return an overestimate, as execution slices are tagged by URL, and not - by requests. - - Args: - start_msec: (float) - end_msec: (float) - content_lens: (ContentClassificationLens) - activity: (ActivityLens) - - Returns: - {'ad_and_tracking_script_frac': float, - 'ad_and_tracking_parsing_frac': float} - """ - result = {'ad_or_tracking_script_frac': None, - 'ad_or_tracking_parsing_frac': None} - if not has_rules: - return result - - duration = float(end_msec - start_msec) - requests = content_lens.AdAndTrackingRequests() - urls = {r.url for r in requests} - cpu_breakdown = activity.ComputeActivity(start_msec, end_msec) - result['ad_or_tracking_script_frac'] = sum( - value for (url, value) in cpu_breakdown['script'].items() - if url in urls) / duration - result['ad_or_tracking_parsing_frac'] = sum( - value for (url, value) in cpu_breakdown['parsing'].items() - if url in urls) / duration - return result - - -def _Main(args): - if len(args) not in (2, 4): - print 'Usage: report.py trace.json (ad_rules tracking_rules)' - sys.exit(1) - trace_filename = args[1] - ad_rules = None - tracking_rules = None - if len(args) == 4: - ad_rules = open(args[2]).readlines() - tracking_rules = open(args[3]).readlines() - report = LoadingReport.FromTraceFilename( - trace_filename, ad_rules, tracking_rules) - print json.dumps(report.GenerateReport(), indent=2, sort_keys=True) - - -if __name__ == '__main__': - import sys - import json - - _Main(sys.argv)
diff --git a/tools/android/loading/report_unittest.py b/tools/android/loading/report_unittest.py deleted file mode 100644 index ef430149..0000000 --- a/tools/android/loading/report_unittest.py +++ /dev/null
@@ -1,298 +0,0 @@ -# Copyright 2016 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. - -import unittest - -import metrics -import report -from queuing_lens import QueuingLens -import test_utils -import user_satisfied_lens_unittest - - -class LoadingReportTestCase(unittest.TestCase): - MILLI_TO_MICRO = 1000 - _NAVIGATION_START_TIME = 12 - _FIRST_REQUEST_TIME = 15 - _CONTENTFUL_PAINT = 120 - _TEXT_PAINT = 30 - _SIGNIFICANT_PAINT = 50 - _DURATION = 400 - _REQUEST_OFFSET = 5 - _LOAD_END_TIME = 1280 - _MAIN_FRAME_ID = 1 - _FIRST_REQUEST_DATA_LENGTH = 128 - _SECOND_REQUEST_DATA_LENGTH = 1024 - _TOPLEVEL_EVENT_OFFSET = 10 - _TOPLEVEL_EVENT_DURATION = 100 - _SCRIPT_EVENT_DURATION = 50 - _PARSING_EVENT_DURATION = 60 - - def setUp(self): - self.trace_creator = test_utils.TraceCreator() - self.requests = [ - self.trace_creator.RequestAt(self._FIRST_REQUEST_TIME, frame_id=1), - self.trace_creator.RequestAt( - self._NAVIGATION_START_TIME + self._REQUEST_OFFSET, self._DURATION)] - self.requests[0].timing.receive_headers_end = 0 - self.requests[1].timing.receive_headers_end = 0 - self.requests[0].encoded_data_length = self._FIRST_REQUEST_DATA_LENGTH - self.requests[1].encoded_data_length = self._SECOND_REQUEST_DATA_LENGTH - - self.ad_domain = 'i-ve-got-the-best-ads.com' - self.ad_url = 'http://www.' + self.ad_domain + '/i-m-really-rich.js' - self.requests[0].url = self.ad_url - - self.trace_events = [ - {'args': {'name': 'CrRendererMain'}, 'cat': '__metadata', - 'name': 'thread_name', 'ph': 'M', 'pid': 1, 'tid': 1, 'ts': 0}, - {'ts': self._NAVIGATION_START_TIME * self.MILLI_TO_MICRO, 'ph': 'R', - 'cat': 'blink.user_timing', 'pid': 1, 'tid': 1, - 'name': 'navigationStart', - 'args': {'frame': 1}}, - {'ts': self._LOAD_END_TIME * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'devtools.timeline', 'pid': 1, 'tid': 1, - 'name': 'MarkLoad', - 'args': {'data': {'isMainFrame': True}}}, - {'ts': self._CONTENTFUL_PAINT * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'blink.user_timing', 'pid': 1, 'tid': 1, - 'name': 'firstContentfulPaint', - 'args': {'frame': self._MAIN_FRAME_ID}}, - {'ts': self._TEXT_PAINT * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'blink.user_timing', 'pid': 1, 'tid': 1, - 'name': 'firstPaint', - 'args': {'frame': self._MAIN_FRAME_ID}}, - {'ts': 90 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'blink', 'pid': 1, 'tid': 1, - 'name': 'FrameView::paintTree'}, - {'ts': self._SIGNIFICANT_PAINT * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'foobar', 'name': 'biz', 'pid': 1, 'tid': 1, - 'args': {'counters': { - 'LayoutObjectsThatHadNeverHadLayout': 10}}}, - {'ts': (self._NAVIGATION_START_TIME - self._TOPLEVEL_EVENT_OFFSET) - * self.MILLI_TO_MICRO, - 'pid': 1, 'tid': 1, 'ph': 'X', - 'dur': self._TOPLEVEL_EVENT_DURATION * self.MILLI_TO_MICRO, - 'cat': 'toplevel', 'name': 'MessageLoop::RunTask'}, - {'ts': self._NAVIGATION_START_TIME * self.MILLI_TO_MICRO, - 'pid': 1, 'tid': 1, 'ph': 'X', - 'dur': self._PARSING_EVENT_DURATION * self.MILLI_TO_MICRO, - 'cat': 'devtools.timeline', 'name': 'ParseHTML', - 'args': {'beginData': {'url': ''}}}, - {'ts': self._NAVIGATION_START_TIME * self.MILLI_TO_MICRO, - 'pid': 1, 'tid': 1, 'ph': 'X', - 'dur': self._SCRIPT_EVENT_DURATION * self.MILLI_TO_MICRO, - 'cat': 'devtools.timeline', 'name': 'EvaluateScript', - 'args': {'data': {'scriptName': ''}}}] - - def _MakeTrace(self): - trace = self.trace_creator.CreateTrace( - self.requests, self.trace_events, self._MAIN_FRAME_ID) - return trace - - def _AddQueuingEvents(self, source_id, url, start_msec, ready_msec, end_msec): - self.trace_events.extend([ - {'args': { - 'data': { - 'request_url': url, - 'source_id': source_id - } - }, - 'cat': QueuingLens.QUEUING_CATEGORY, - 'id': source_id, - 'pid': 1, 'tid': 10, - 'name': QueuingLens.ASYNC_NAME, - 'ph': 'b', - 'ts': start_msec * self.MILLI_TO_MICRO - }, - {'args': { - 'data': { - 'source_id': source_id - } - }, - 'cat': QueuingLens.QUEUING_CATEGORY, - 'id': source_id, - 'pid': 1, 'tid': 10, - 'name': QueuingLens.READY_NAME, - 'ph': 'n', - 'ts': ready_msec * self.MILLI_TO_MICRO - }, - {'args': { - 'data': { - 'source_id': source_id - } - }, - 'cat': QueuingLens.QUEUING_CATEGORY, - 'id': source_id, - 'pid': 1, 'tid': 10, - 'name': QueuingLens.ASYNC_NAME, - 'ph': 'e', - 'ts': end_msec * self.MILLI_TO_MICRO - }]) - - def testGenerateReport(self): - trace = self._MakeTrace() - loading_report = report.LoadingReport(trace).GenerateReport() - self.assertEqual(trace.url, loading_report['url']) - self.assertEqual(self._TEXT_PAINT - self._NAVIGATION_START_TIME, - loading_report['first_text_ms']) - self.assertEqual(self._SIGNIFICANT_PAINT - self._NAVIGATION_START_TIME, - loading_report['significant_ms']) - self.assertEqual(self._CONTENTFUL_PAINT - self._NAVIGATION_START_TIME, - loading_report['contentful_ms']) - self.assertAlmostEqual(self._LOAD_END_TIME - self._NAVIGATION_START_TIME, - loading_report['plt_ms']) - self.assertEqual(2, loading_report['total_requests']) - self.assertAlmostEqual(0.34, loading_report['contentful_byte_frac'], 2) - self.assertAlmostEqual(0.1844, loading_report['significant_byte_frac'], 2) - self.assertEqual(2, loading_report['plt_requests']) - self.assertEqual(1, loading_report['first_text_requests']) - self.assertEqual(1, loading_report['contentful_requests']) - self.assertEqual(1, loading_report['significant_requests']) - self.assertEqual(1, loading_report['plt_preloaded_requests']) - self.assertEqual(1, loading_report['first_text_preloaded_requests']) - self.assertEqual(1, loading_report['contentful_preloaded_requests']) - self.assertEqual(1, loading_report['significant_preloaded_requests']) - self.assertEqual(401, loading_report['plt_requests_cost']) - self.assertEqual(1, loading_report['first_text_requests_cost']) - self.assertEqual(1, loading_report['contentful_requests_cost']) - self.assertEqual(1, loading_report['significant_requests_cost']) - self.assertEqual(1, loading_report['plt_preloaded_requests_cost']) - self.assertEqual(1, loading_report['first_text_preloaded_requests_cost']) - self.assertEqual(1, loading_report['contentful_preloaded_requests_cost']) - self.assertEqual(1, loading_report['significant_preloaded_requests_cost']) - self.assertEqual(400, loading_report['plt_predicted_no_state_prefetch_ms']) - self.assertEqual(14, - loading_report['first_text_predicted_no_state_prefetch_ms']) - self.assertEqual(104, - loading_report['contentful_predicted_no_state_prefetch_ms']) - self.assertEqual(74, - loading_report['significant_predicted_no_state_prefetch_ms']) - self.assertEqual('', loading_report['contentful_inversion']) - self.assertEqual('', loading_report['significant_inversion']) - self.assertIsNone(loading_report['ad_requests']) - self.assertIsNone(loading_report['ad_or_tracking_requests']) - self.assertIsNone(loading_report['ad_or_tracking_initiated_requests']) - self.assertIsNone(loading_report['ad_or_tracking_initiated_transfer_size']) - self.assertIsNone(loading_report['ad_or_tracking_script_frac']) - self.assertIsNone(loading_report['ad_or_tracking_parsing_frac']) - self.assertEqual( - self._FIRST_REQUEST_DATA_LENGTH + self._SECOND_REQUEST_DATA_LENGTH - + metrics.HTTP_OK_LENGTH * 2, - loading_report['transfer_size']) - self.assertEqual(0, loading_report['total_queuing_blocked_msec']) - self.assertEqual(0, loading_report['total_queuing_load_msec']) - self.assertEqual(0, loading_report['average_blocking_request_count']) - self.assertEqual(0, loading_report['median_blocking_request_count']) - - def testInversion(self): - self.requests[0].timing.loading_finished = 4 * ( - self._REQUEST_OFFSET + self._DURATION) - self.requests[1].initiator['type'] = 'parser' - self.requests[1].initiator['url'] = self.requests[0].url - for e in self.trace_events: - if e['name'] == 'firstContentfulPaint': - e['ts'] = self.MILLI_TO_MICRO * ( - self._FIRST_REQUEST_TIME + self._REQUEST_OFFSET + - self._DURATION + 1) - break - loading_report = report.LoadingReport(self._MakeTrace()).GenerateReport() - self.assertEqual(self.requests[0].url, - loading_report['contentful_inversion']) - self.assertEqual('', loading_report['significant_inversion']) - - def testPltNoLoadEvents(self): - trace = self._MakeTrace() - # Change the MarkLoad events. - for e in trace.tracing_track.GetEvents(): - if e.name == 'MarkLoad': - e.tracing_event['name'] = 'dummy' - loading_report = report.LoadingReport(trace).GenerateReport() - self.assertAlmostEqual(self._REQUEST_OFFSET + self._DURATION, - loading_report['plt_ms']) - - def testAdTrackingRules(self): - trace = self._MakeTrace() - loading_report = report.LoadingReport( - trace, [self.ad_domain], []).GenerateReport() - self.assertEqual(1, loading_report['ad_requests']) - self.assertEqual(1, loading_report['ad_or_tracking_requests']) - self.assertEqual(1, loading_report['ad_or_tracking_initiated_requests']) - self.assertIsNone(loading_report['tracking_requests']) - self.assertEqual( - self._FIRST_REQUEST_DATA_LENGTH + metrics.HTTP_OK_LENGTH, - loading_report['ad_or_tracking_initiated_transfer_size']) - - def testThreadBusyness(self): - loading_report = report.LoadingReport(self._MakeTrace()).GenerateReport() - self.assertAlmostEqual( - 1., loading_report['significant_activity_frac']) - self.assertAlmostEqual( - float(self._TOPLEVEL_EVENT_DURATION - self._TOPLEVEL_EVENT_OFFSET) - / (self._CONTENTFUL_PAINT - self._NAVIGATION_START_TIME), - loading_report['contentful_activity_frac']) - self.assertAlmostEqual( - float(self._TOPLEVEL_EVENT_DURATION - self._TOPLEVEL_EVENT_OFFSET) - / (self._LOAD_END_TIME - self._NAVIGATION_START_TIME), - loading_report['plt_activity_frac']) - - def testActivityBreakdown(self): - loading_report = report.LoadingReport(self._MakeTrace()).GenerateReport() - load_time = float(self._LOAD_END_TIME - self._NAVIGATION_START_TIME) - contentful_time = float( - self._CONTENTFUL_PAINT - self._NAVIGATION_START_TIME) - - self.assertAlmostEqual(self._SCRIPT_EVENT_DURATION / load_time, - loading_report['plt_script_frac']) - self.assertAlmostEqual( - (self._PARSING_EVENT_DURATION - self._SCRIPT_EVENT_DURATION) - / load_time, - loading_report['plt_parsing_frac']) - - self.assertAlmostEqual(1., loading_report['significant_script_frac']) - self.assertAlmostEqual(0., loading_report['significant_parsing_frac']) - - self.assertAlmostEqual(self._SCRIPT_EVENT_DURATION / contentful_time, - loading_report['contentful_script_frac']) - self.assertAlmostEqual( - (self._PARSING_EVENT_DURATION - self._SCRIPT_EVENT_DURATION) - / contentful_time, loading_report['contentful_parsing_frac']) - - def testAdsAndTrackingCost(self): - load_time = float(self._LOAD_END_TIME - self._NAVIGATION_START_TIME) - self.trace_events.append( - {'ts': load_time / 3. * self.MILLI_TO_MICRO, - 'pid': 1, 'tid': 1, 'ph': 'X', - 'dur': load_time / 2. * self.MILLI_TO_MICRO, - 'cat': 'devtools.timeline', 'name': 'EvaluateScript', - 'args': {'data': {'scriptName': self.ad_url}}}) - loading_report = report.LoadingReport( - self._MakeTrace(), [self.ad_domain]).GenerateReport() - self.assertAlmostEqual(.5, loading_report['ad_or_tracking_script_frac'], 2) - self.assertAlmostEqual(0., loading_report['ad_or_tracking_parsing_frac']) - - def testQueueStats(self): - # We use three requests, A, B and C. A is not blocked, B is blocked by A, - # and C blocked by A and B. - BASE_MSEC = self._FIRST_REQUEST_TIME + 4 * self._DURATION - self.requests = [] - request_A = self.trace_creator.RequestAt(BASE_MSEC, 5) - request_B = self.trace_creator.RequestAt(BASE_MSEC + 6, 5) - request_C = self.trace_creator.RequestAt(BASE_MSEC + 12, 10) - self.requests.extend([request_A, request_B, request_C]) - self._AddQueuingEvents(10, request_A.url, - BASE_MSEC, BASE_MSEC, BASE_MSEC + 5) - self._AddQueuingEvents(20, request_B.url, - BASE_MSEC + 1, BASE_MSEC + 6, BASE_MSEC + 11) - self._AddQueuingEvents(30, request_C.url, - BASE_MSEC + 2, BASE_MSEC + 12, BASE_MSEC + 22) - loading_report = report.LoadingReport(self._MakeTrace()).GenerateReport() - self.assertEqual(15, loading_report['total_queuing_blocked_msec']) - self.assertEqual(35, loading_report['total_queuing_load_msec']) - self.assertAlmostEqual(1, loading_report['average_blocking_request_count']) - self.assertEqual(1, loading_report['median_blocking_request_count']) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/request_dependencies_lens.py b/tools/android/loading/request_dependencies_lens.py deleted file mode 100644 index 1689547..0000000 --- a/tools/android/loading/request_dependencies_lens.py +++ /dev/null
@@ -1,249 +0,0 @@ -# Copyright 2016 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. - -"""Gathers and infers dependencies between requests. - -When executed as a script, loads a trace and outputs the dependencies. -""" - -import collections -import copy -import logging -import operator - -import loading_trace -import request_track - - -class RequestDependencyLens(object): - """Analyses and infers request dependencies.""" - DEPENDENCIES = ('redirect', 'parser', 'script', 'inferred', 'other') - CALLFRAMES_KEY = 'callFrames' - def __init__(self, trace): - """Initializes an instance of RequestDependencyLens. - - Args: - trace: (LoadingTrace) Loading trace. - """ - self.loading_trace = trace - self._requests = self.loading_trace.request_track.GetEvents() - self._requests_by_id = {r.request_id: r for r in self._requests} - self._requests_by_url = collections.defaultdict(list) - self._deps = None - for request in self._requests: - self._requests_by_url[request.url].append(request) - self._frame_to_parent = {} - for event in self.loading_trace.page_track.GetEvents(): - if event['method'] == 'Page.frameAttached': - self._frame_to_parent[event['frame_id']] = event['parent_frame_id'] - - def GetRequestDependencies(self): - """Returns a list of request dependencies. - - Returns: - [(first, second, reason), ...] where first and second are instances of - request_track.Request, and reason is in DEPENDENCIES. The second request - depends on the first one, with the listed reason. - """ - self._ComputeRequestDependencies() - return copy.copy(self._deps) - - def GetRedirectChain(self, request): - """Returns the whole redirect chain for a given request. - - Note that this misses some JS-based redirects. - - Returns: - A list of request, containing the request passed as a parameter. - """ - self._ComputeRequestDependencies() - chain = [request] - while True: - for (first_request, second_request, why) in self._deps: - if first_request == request and why == 'redirect': - chain.append(second_request) - request = second_request - break - else: - return chain - - def _ComputeRequestDependencies(self): - if self._deps is not None: - return - self._deps = [] - for request in self._requests: - dependency = self._GetDependency(request) - if dependency: - self._deps.append(dependency) - - def _GetDependency(self, request): - """Returns (first, second, reason), or None. - - |second| depends on |first|. - - Args: - request: (Request) the request we wish to get the initiator of. - - Returns: - None if no dependency is found from this request, or - (initiator (Request), blocked_request (Request), reason (str)). - """ - reason = request.initiator['type'] - assert reason in request_track.Request.INITIATORS - if reason == 'redirect': - return self._GetInitiatingRequestRedirect(request) - elif reason == 'parser': - return self._GetInitiatingRequestParser(request) - elif reason == 'script': - return self._GetInitiatingRequestScript(request) - else: - assert reason == 'other' - return self._GetInitiatingRequestOther(request) - - def _GetInitiatingRequestRedirect(self, request): - assert request_track.Request.INITIATING_REQUEST in request.initiator - initiating_request_id = request.initiator[ - request_track.Request.INITIATING_REQUEST] - assert initiating_request_id in self._requests_by_id - return (self._requests_by_id[initiating_request_id], request, 'redirect') - - def _GetInitiatingRequestParser(self, request): - url = request.initiator['url'] - candidates = self._FindMatchingRequests(url, request.timing.request_time) - if not candidates: - return None - initiating_request = self._FindBestMatchingInitiator(request, candidates) - return (initiating_request, request, 'parser') - - def _FlattenScriptStack(self, stack): - """Recursively collapses the stack of asynchronous callstacks. - - A stack has a list of call frames and optionnally a "parent" stack. - This function recursively folds the parent stacks into the root stack by - concatening all the call frames. - - Args: - stack: (dict) the stack that must be flattened - - Returns: - A stack with no parent, which is a dictionary with a single "callFrames" - key, and no "parent" key. - """ - PARENT_KEY = 'parent' - if not PARENT_KEY in stack: - return stack - stack[self.CALLFRAMES_KEY] += stack[PARENT_KEY][self.CALLFRAMES_KEY] - if not PARENT_KEY in stack[PARENT_KEY]: - stack.pop(PARENT_KEY) - else: - stack[PARENT_KEY] = stack[PARENT_KEY][PARENT_KEY] - return self._FlattenScriptStack(stack) - - def _GetInitiatingRequestScript(self, request): - STACK_KEY = 'stack' - if not STACK_KEY in request.initiator: - logging.warning('Script initiator but no stack trace.') - return None - initiating_request = None - timestamp = request.timing.request_time - # Deep copy the initiator's stack to avoid mutating the input request. - stack = self._FlattenScriptStack( - copy.deepcopy(request.initiator[STACK_KEY])) - call_frames = stack[self.CALLFRAMES_KEY] - for frame in call_frames: - url = frame['url'] - candidates = self._FindMatchingRequests(url, timestamp) - if candidates: - initiating_request = self._FindBestMatchingInitiator( - request, candidates) - if initiating_request: - break - else: - for frame in call_frames: - if not frame.get('url', None) and frame.get( - 'functionName', None) == 'window.onload': - logging.warning('Unmatched request for onload handler.') - break - else: - logging.warning('Unmatched request.') - return None - return (initiating_request, request, 'script') - - def _GetInitiatingRequestOther(self, _): - # TODO(lizeb): Infer "other" initiator types. - return None - - def _FindMatchingRequests(self, url, before_timestamp): - """Returns a list of requests matching a URL, before a timestamp. - - Args: - url: (str) URL to match in requests. - before_timestamp: (int) Only keep requests submitted before a given - timestamp. - - Returns: - A list of candidates, ordered by timestamp. - """ - candidates = self._requests_by_url.get(url, []) - candidates = [r for r in candidates if ( - r.timing.request_time + max( - 0, r.timing.receive_headers_end / 1000) <= before_timestamp)] - candidates.sort(key=lambda r: r.timing.request_time) - return candidates - - def _FindBestMatchingInitiator(self, request, matches): - """Returns the best matching request within a list of matches. - - Iteratively removes candidates until one is left: - - With the same parent frame. - - From the same frame. - - If this is not successful, takes the most recent request. - - Args: - request: (Request) Request. - matches: [Request] As returned by _FindMatchingRequests(), that is - sorted by timestamp. - - Returns: - The best matching initiating request, or None. - """ - if not matches: - return None - if len(matches) == 1: - return matches[0] - # Several matches, try to reduce this number to 1. Otherwise, return the - # most recent one. - if request.frame_id in self._frame_to_parent: # Main frame has no parent. - parent_frame_id = self._frame_to_parent[request.frame_id] - same_parent_matches = [ - r for r in matches - if r.frame_id in self._frame_to_parent and - self._frame_to_parent[r.frame_id] == parent_frame_id] - if not same_parent_matches: - logging.warning('All matches are from non-sibling frames.') - return matches[-1] - if len(same_parent_matches) == 1: - return same_parent_matches[0] - same_frame_matches = [r for r in matches if r.frame_id == request.frame_id] - if not same_frame_matches: - logging.warning('All matches are from non-sibling frames.') - return matches[-1] - if len(same_frame_matches) == 1: - return same_frame_matches[0] - else: - logging.warning('Several matches') - return same_frame_matches[-1] - - -if __name__ == '__main__': - import json - import sys - trace_filename = sys.argv[1] - json_dict = json.load(open(trace_filename, 'r')) - lens = RequestDependencyLens( - loading_trace.LoadingTrace.FromJsonDict(json_dict)) - depedencies = lens.GetRequestDependencies() - for (first, second, dep_reason) in depedencies: - print '%s -> %s\t(%s)' % (first.request_id, second.request_id, dep_reason)
diff --git a/tools/android/loading/request_dependencies_lens_unittest.py b/tools/android/loading/request_dependencies_lens_unittest.py deleted file mode 100644 index bf2d858..0000000 --- a/tools/android/loading/request_dependencies_lens_unittest.py +++ /dev/null
@@ -1,233 +0,0 @@ -# Copyright 2016 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. - -import unittest - -import devtools_monitor -from loading_trace import LoadingTrace -from request_dependencies_lens import RequestDependencyLens -from request_track import Request -import test_utils - - -class TestRequests(object): - FIRST_REDIRECT_REQUEST = Request.FromJsonDict( - {'url': 'http://bla.com', 'request_id': '1234.redirect.1', - 'initiator': {'type': 'other'}, - 'timestamp': 0.5, 'timing': {}}) - SECOND_REDIRECT_REQUEST = Request.FromJsonDict( - {'url': 'http://bla.com/redirect1', 'request_id': '1234.redirect.2', - 'initiator': {'type': 'redirect', - 'initiating_request': '1234.redirect.1'}, - 'timestamp': 1, 'timing': {}}) - REDIRECTED_REQUEST = Request.FromJsonDict({ - 'url': 'http://bla.com/index.html', - 'request_id': '1234.1', - 'frame_id': '123.1', - 'initiator': {'type': 'redirect', - 'initiating_request': '1234.redirect.2'}, - 'timestamp': 2, - 'timing': {}}) - REQUEST = Request.FromJsonDict({'url': 'http://bla.com/index.html', - 'request_id': '1234.1', - 'frame_id': '123.1', - 'initiator': {'type': 'other'}, - 'timestamp': 2, - 'timing': {}}) - JS_REQUEST = Request.FromJsonDict({'url': 'http://bla.com/nyancat.js', - 'request_id': '1234.12', - 'frame_id': '123.123', - 'initiator': { - 'type': 'parser', - 'url': 'http://bla.com/index.html'}, - 'timestamp': 3, - 'timing': {}}) - JS_REQUEST_OTHER_FRAME = Request.FromJsonDict( - {'url': 'http://bla.com/nyancat.js', - 'request_id': '1234.42', - 'frame_id': '123.13', - 'initiator': {'type': 'parser', - 'url': 'http://bla.com/index.html'}, - 'timestamp': 4, 'timing': {}}) - JS_REQUEST_UNRELATED_FRAME = Request.FromJsonDict( - {'url': 'http://bla.com/nyancat.js', - 'request_id': '1234.56', - 'frame_id': '123.99', - 'initiator': {'type': 'parser', - 'url': 'http://bla.com/index.html'}, - 'timestamp': 5, 'timing': {}}) - JS_REQUEST_2 = Request.FromJsonDict( - {'url': 'http://bla.com/cat.js', 'request_id': '1234.13', - 'frame_id': '123.123', - 'initiator': {'type': 'script', - 'stack': {'callFrames': [ - {'url': 'unknown'}, - {'url': 'http://bla.com/nyancat.js'}]}}, - 'timestamp': 10, 'timing': {}}) - PAGE_EVENTS = [{'method': 'Page.frameAttached', - 'frame_id': '123.13', 'parent_frame_id': '123.1'}, - {'method': 'Page.frameAttached', - 'frame_id': '123.123', 'parent_frame_id': '123.1'}] - - @classmethod - def CreateLoadingTrace(cls, trace_events=None): - # This creates a set of requests with the following dependency structure. - # - # 1234.redirect.1 -> 1234.redirect.2 - # 1234.redirect.2 -> 1234.1 - # 1234.1 -> 1234.12 - # 1234.1 -> 1234.42 - # 1234.1 -> 1234.56 - # 1234.12 -> 1234.13 - - trace = test_utils.LoadingTraceFromEvents( - [cls.FIRST_REDIRECT_REQUEST, cls.SECOND_REDIRECT_REQUEST, - cls.REDIRECTED_REQUEST, cls.REQUEST, cls.JS_REQUEST, cls.JS_REQUEST_2, - cls.JS_REQUEST_OTHER_FRAME, cls.JS_REQUEST_UNRELATED_FRAME], - cls.PAGE_EVENTS, trace_events) - # Serialize and deserialize so that clients can change events without - # affecting future tests. - return LoadingTrace.FromJsonDict(trace.ToJsonDict()) - - -class RequestDependencyLensTestCase(unittest.TestCase): - def testRedirectDependency(self): - loading_trace = test_utils.LoadingTraceFromEvents( - [TestRequests.FIRST_REDIRECT_REQUEST, - TestRequests.SECOND_REDIRECT_REQUEST, TestRequests.REDIRECTED_REQUEST]) - request_dependencies_lens = RequestDependencyLens(loading_trace) - deps = request_dependencies_lens.GetRequestDependencies() - self.assertEquals(2, len(deps)) - (first, second, reason) = deps[0] - self.assertEquals('redirect', reason) - self.assertEquals(TestRequests.FIRST_REDIRECT_REQUEST.request_id, - first.request_id) - self.assertEquals(TestRequests.SECOND_REDIRECT_REQUEST.request_id, - second.request_id) - (first, second, reason) = deps[1] - self.assertEquals('redirect', reason) - self.assertEquals(TestRequests.SECOND_REDIRECT_REQUEST.request_id, - first.request_id) - self.assertEquals(TestRequests.REQUEST.request_id, second.request_id) - - def testGetRedirectChain(self): - loading_trace = test_utils.LoadingTraceFromEvents( - [TestRequests.FIRST_REDIRECT_REQUEST, - TestRequests.SECOND_REDIRECT_REQUEST, TestRequests.REDIRECTED_REQUEST]) - request_dependencies_lens = RequestDependencyLens(loading_trace) - whole_chain = [TestRequests.FIRST_REDIRECT_REQUEST, - TestRequests.SECOND_REDIRECT_REQUEST, - TestRequests.REDIRECTED_REQUEST] - chain = request_dependencies_lens.GetRedirectChain( - TestRequests.FIRST_REDIRECT_REQUEST) - self.assertListEqual(whole_chain, chain) - chain = request_dependencies_lens.GetRedirectChain( - TestRequests.SECOND_REDIRECT_REQUEST) - self.assertListEqual(whole_chain[1:], chain) - chain = request_dependencies_lens.GetRedirectChain( - TestRequests.REDIRECTED_REQUEST) - self.assertEquals(whole_chain[2:], chain) - - def testScriptDependency(self): - loading_trace = test_utils.LoadingTraceFromEvents( - [TestRequests.JS_REQUEST, TestRequests.JS_REQUEST_2]) - request_dependencies_lens = RequestDependencyLens(loading_trace) - deps = request_dependencies_lens.GetRequestDependencies() - self.assertEquals(1, len(deps)) - self._AssertDependencyIs( - deps[0], - TestRequests.JS_REQUEST.request_id, - TestRequests.JS_REQUEST_2.request_id, 'script') - - def testAsyncScriptDependency(self): - JS_REQUEST_WITH_ASYNC_STACK = Request.FromJsonDict( - {'url': 'http://bla.com/cat.js', 'request_id': '1234.14', - 'initiator': { - 'type': 'script', - 'stack': {'callFrames': [], - 'parent': {'callFrames': [ - {'url': 'http://bla.com/nyancat.js'}]}}}, - 'timestamp': 10, 'timing': {}}) - loading_trace = test_utils.LoadingTraceFromEvents( - [TestRequests.JS_REQUEST, JS_REQUEST_WITH_ASYNC_STACK]) - request_dependencies_lens = RequestDependencyLens(loading_trace) - deps = request_dependencies_lens.GetRequestDependencies() - self.assertEquals(1, len(deps)) - self._AssertDependencyIs( - deps[0], TestRequests.JS_REQUEST.request_id, - JS_REQUEST_WITH_ASYNC_STACK.request_id, 'script') - - def testParserDependency(self): - loading_trace = test_utils.LoadingTraceFromEvents( - [TestRequests.REQUEST, TestRequests.JS_REQUEST]) - request_dependencies_lens = RequestDependencyLens(loading_trace) - deps = request_dependencies_lens.GetRequestDependencies() - self.assertEquals(1, len(deps)) - self._AssertDependencyIs( - deps[0], - TestRequests.REQUEST.request_id, TestRequests.JS_REQUEST.request_id, - 'parser') - - def testSeveralDependencies(self): - loading_trace = test_utils.LoadingTraceFromEvents( - [TestRequests.FIRST_REDIRECT_REQUEST, - TestRequests.SECOND_REDIRECT_REQUEST, - TestRequests.REDIRECTED_REQUEST, - TestRequests.JS_REQUEST, TestRequests.JS_REQUEST_2]) - request_dependencies_lens = RequestDependencyLens(loading_trace) - deps = request_dependencies_lens.GetRequestDependencies() - self.assertEquals(4, len(deps)) - self._AssertDependencyIs( - deps[0], TestRequests.FIRST_REDIRECT_REQUEST.request_id, - TestRequests.SECOND_REDIRECT_REQUEST.request_id, 'redirect') - self._AssertDependencyIs( - deps[1], TestRequests.SECOND_REDIRECT_REQUEST.request_id, - TestRequests.REQUEST.request_id, 'redirect') - self._AssertDependencyIs( - deps[2], - TestRequests.REQUEST.request_id, TestRequests.JS_REQUEST.request_id, - 'parser') - self._AssertDependencyIs( - deps[3], - TestRequests.JS_REQUEST.request_id, - TestRequests.JS_REQUEST_2.request_id, 'script') - - def testDependencyDifferentFrame(self): - """Checks that a more recent request from another frame is ignored.""" - loading_trace = test_utils.LoadingTraceFromEvents( - [TestRequests.JS_REQUEST, TestRequests.JS_REQUEST_OTHER_FRAME, - TestRequests.JS_REQUEST_2]) - request_dependencies_lens = RequestDependencyLens(loading_trace) - deps = request_dependencies_lens.GetRequestDependencies() - self.assertEquals(1, len(deps)) - self._AssertDependencyIs( - deps[0], - TestRequests.JS_REQUEST.request_id, - TestRequests.JS_REQUEST_2.request_id, 'script') - - def testDependencySameParentFrame(self): - """Checks that a more recent request from an unrelated frame is ignored - if there is one from a related frame.""" - loading_trace = test_utils.LoadingTraceFromEvents( - [TestRequests.JS_REQUEST_OTHER_FRAME, - TestRequests.JS_REQUEST_UNRELATED_FRAME, TestRequests.JS_REQUEST_2], - TestRequests.PAGE_EVENTS) - request_dependencies_lens = RequestDependencyLens(loading_trace) - deps = request_dependencies_lens.GetRequestDependencies() - self.assertEquals(1, len(deps)) - self._AssertDependencyIs( - deps[0], - TestRequests.JS_REQUEST_OTHER_FRAME.request_id, - TestRequests.JS_REQUEST_2.request_id, 'script') - - def _AssertDependencyIs( - self, dep, first_request_id, second_request_id, reason): - (first, second, dependency_reason) = dep - self.assertEquals(reason, dependency_reason) - self.assertEquals(first_request_id, first.request_id) - self.assertEquals(second_request_id, second.request_id) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/request_track.py b/tools/android/loading/request_track.py deleted file mode 100644 index be62cd1..0000000 --- a/tools/android/loading/request_track.py +++ /dev/null
@@ -1,873 +0,0 @@ -# Copyright (c) 2016 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. - -"""The request data track. - -When executed, parses a JSON dump of DevTools messages. -""" - -import bisect -import collections -import copy -import datetime -import email.utils -import hashlib -import json -import logging -import re -import sys -import urlparse - -import devtools_monitor - - -class Timing(object): - """Collects the timing data for a request.""" - UNVAILABLE = -1 - _TIMING_NAMES = ( - ('connectEnd', 'connect_end'), ('connectStart', 'connect_start'), - ('dnsEnd', 'dns_end'), ('dnsStart', 'dns_start'), - ('proxyEnd', 'proxy_end'), ('proxyStart', 'proxy_start'), - ('receiveHeadersEnd', 'receive_headers_end'), - ('requestTime', 'request_time'), ('sendEnd', 'send_end'), - ('sendStart', 'send_start'), ('sslEnd', 'ssl_end'), - ('sslStart', 'ssl_start'), ('workerReady', 'worker_ready'), - ('workerStart', 'worker_start'), - ('loadingFinished', 'loading_finished'), ('pushStart', 'push_start'), - ('pushEnd', 'push_end')) - _TIMING_NAMES_MAPPING = dict(_TIMING_NAMES) - __slots__ = tuple(x[1] for x in _TIMING_NAMES) - - def __init__(self, **kwargs): - """Constructor. - - Initialize with keywords arguments from __slots__. - """ - for slot in self.__slots__: - setattr(self, slot, self.UNVAILABLE) - for (attr, value) in kwargs.items(): - setattr(self, attr, value) - - def __eq__(self, o): - return all(getattr(self, attr) == getattr(o, attr) - for attr in self.__slots__) - - def __str__(self): - return str(self.ToJsonDict()) - - def LargestOffset(self): - """Returns the largest offset in the available timings.""" - return max(0, max( - getattr(self, attr) for attr in self.__slots__ - if attr != 'request_time')) - - def ToJsonDict(self): - return {attr: getattr(self, attr) - for attr in self.__slots__ if getattr(self, attr) != -1} - - @classmethod - def FromJsonDict(cls, json_dict): - return cls(**json_dict) - - @classmethod - def FromDevToolsDict(cls, json_dict): - """Returns an instance of Timing from a dict, as passed by DevTools.""" - timing_dict = { - cls._TIMING_NAMES_MAPPING[k]: v for (k, v) in json_dict.items()} - return cls(**timing_dict) - - -def ShortName(url): - """Returns a shortened version of a URL.""" - parsed = urlparse.urlparse(url) - path = parsed.path - hostname = parsed.hostname if parsed.hostname else '?.?.?' - if path != '' and path != '/': - last_path = parsed.path.split('/')[-1] - if len(last_path) < 10: - if len(path) < 10: - return hostname + '/' + path - else: - return hostname + '/..' + parsed.path[-10:] - else: - return hostname + '/..' + last_path[:5] - else: - return hostname - - -def IntervalBetween(first, second, reason): - """Returns the start and end of the inteval between two requests, in ms. - - This is defined as: - - [first.headers, second.start] if reason is 'parser'. This is to account - for incremental parsing. - - [first.end, second.start] if reason is 'script', 'redirect' or 'other'. - - Args: - first: (Request) First request. - second: (Request) Second request. - reason: (str) Link between the two requests, in Request.INITIATORS. - - Returns: - (start_msec (float), end_msec (float)), - """ - assert reason in Request.INITIATORS - second_ms = second.timing.request_time * 1000 - if reason == 'parser': - first_offset_ms = first.timing.receive_headers_end - else: - first_offset_ms = first.timing.LargestOffset() - return (first.timing.request_time * 1000 + first_offset_ms, second_ms) - - -def TimeBetween(first, second, reason): - """(end_msec - start_msec), with the values as returned by IntervalBetween(). - """ - (first_ms, second_ms) = IntervalBetween(first, second, reason) - return second_ms - first_ms - - -def TimingAsList(timing): - """Transform Timing to a list, eg as is used in JSON output. - - Args: - timing: a Timing. - - Returns: - A list identical to what the eventual JSON output will be (eg, - Request.ToJsonDict). - """ - return json.loads(json.dumps(timing)) - - -class Request(object): - """Represents a single request. - - Generally speaking, fields here closely mirror those documented in - third_party/blink/renderer/devtools/protocol.json. - - Fields: - request_id: (str) unique request ID. Postfixed with _REDIRECT_SUFFIX for - redirects. - frame_id: (str) unique frame identifier. - loader_id: (str) unique frame identifier. - document_url: (str) URL of the document this request is loaded for. - url: (str) Request URL. - protocol: (str) protocol used for the request. - method: (str) HTTP method, such as POST or GET. - request_headers: (dict) {'header': 'value'} Request headers. - response_headers: (dict) {'header': 'value'} Response headers. - initial_priority: (str) Initial request priority, in REQUEST_PRIORITIES. - timestamp: (float) Request timestamp, in s. - wall_time: (float) Request timestamp, UTC timestamp in s. - initiator: (dict) Request initiator, in INITIATORS. - resource_type: (str) Resource type, in RESOURCE_TYPES - served_from_cache: (bool) Whether the request was served from cache. - from_disk_cache: (bool) Whether the request was served from the disk cache. - from_service_worker: (bool) Whether the request was served by a Service - Worker. - timing: (Timing) Request timing, extended with loading_finished. - status: (int) Response status code. - status_text: (str) Response status text received in the status line. - encoded_data_length: (int) Total encoded data length. - data_chunks: (list) [(offset, encoded_data_length), ...] List of data - chunks received, with their offset in ms relative to - Timing.requestTime. - failed: (bool) Whether the request failed. - error_text: (str) User friendly error message when request failed. - start_msec: (float) Request start time, in milliseconds from chrome start. - end_msec: (float) Request end time, in milliseconds from chrome start. - start_msec. - """ - REQUEST_PRIORITIES = ('VeryLow', 'Low', 'Medium', 'High', 'VeryHigh') - RESOURCE_TYPES = ('Document', 'Stylesheet', 'Image', 'Media', 'Font', - 'Script', 'TextTrack', 'XHR', 'Fetch', 'EventSource', - 'WebSocket', 'Manifest', 'Other') - INITIATORS = ('parser', 'script', 'other', 'redirect') - INITIATING_REQUEST = 'initiating_request' - ORIGINAL_INITIATOR = 'original_initiator' - def __init__(self): - self.request_id = None - self.frame_id = None - self.loader_id = None - self.document_url = None - self.url = None - self.protocol = None - self.method = None - self.mime_type = None - self.request_headers = None - self.response_headers = None - self.initial_priority = None - self.timestamp = -1 - self.wall_time = -1 - self.initiator = None - self.resource_type = None - self.served_from_cache = False - self.from_disk_cache = False - self.from_service_worker = False - self.timing = None - self.status = None - self.status_text = None - self.response_headers_length = 0 - self.encoded_data_length = 0 - self.data_chunks = [] - self.failed = False - self.error_text = None - - @property - def start_msec(self): - return self.timing.request_time * 1000 - - @property - def end_msec(self): - if self.start_msec is None: - return None - return self.start_msec + self.timing.LargestOffset() - - @property - def fingerprint(self): - h = hashlib.sha256() - h.update(self.url) - return h.hexdigest()[:10] - - def _TimestampOffsetFromStartMs(self, timestamp): - assert self.timing.request_time != -1 - request_time = self.timing.request_time - return (timestamp - request_time) * 1000 - - def ToJsonDict(self): - result = copy.deepcopy(self.__dict__) - result['timing'] = self.timing.ToJsonDict() if self.timing else {} - return result - - @classmethod - def FromJsonDict(cls, data_dict): - result = Request() - for (k, v) in data_dict.items(): - setattr(result, k, v) - if not result.response_headers: - result.response_headers = {} - if result.timing: - result.timing = Timing.FromJsonDict(result.timing) - else: - result.timing = Timing(request_time=result.timestamp) - return result - - def GetResponseTransportLength(self): - """Get the total amount of encoded data no matter whether load has finished - or not. - """ - assert self.HasReceivedResponse() - assert not self.from_disk_cache and not self.served_from_cache - assert self.protocol not in {'about', 'blob', 'data'} - if self.timing.loading_finished != Timing.UNVAILABLE: - encoded_data_length = self.encoded_data_length - else: - encoded_data_length = sum( - [chunk_size for _, chunk_size in self.data_chunks]) - assert encoded_data_length > 0 or len(self.data_chunks) == 0 - return encoded_data_length + self.response_headers_length - - def GetHTTPResponseHeader(self, header_name): - """Gets the value of a HTTP response header. - - Does a case-insensitive search for the header name in the HTTP response - headers, in order to support servers that use a wrong capitalization. - """ - lower_case_name = header_name.lower() - result = None - for name, value in self.response_headers.iteritems(): - if name.lower() == lower_case_name: - result = value - break - return result - - def SetHTTPResponseHeader(self, header, header_value): - """Sets the value of a HTTP response header.""" - assert header.islower() - for name in self.response_headers.keys(): - if name.lower() == header: - del self.response_headers[name] - self.response_headers[header] = header_value - - def GetResponseHeaderValue(self, header, value): - """Returns a copy of |value| iff response |header| contains it.""" - header_values = self.GetHTTPResponseHeader(header) - if not header_values: - return None - values = header_values.split(',') - for header_value in values: - if header_value.lower() == value.lower(): - return header_value - return None - - def HasResponseHeaderValue(self, header, value): - """Returns True iff the response headers |header| contains |value|.""" - return self.GetResponseHeaderValue(header, value) is not None - - def GetContentType(self): - """Returns the content type, or None.""" - # Check for redirects. Use the "Location" header, because the HTTP status is - # not reliable. - if self.GetHTTPResponseHeader('Location') is not None: - return 'redirect' - - # Check if the response is empty. - if (self.GetHTTPResponseHeader('Content-Length') == '0' or - self.status == 204): - return 'ping' - - if self.mime_type: - return self.mime_type - - content_type = self.GetHTTPResponseHeader('Content-Type') - if not content_type or ';' not in content_type: - return content_type - else: - return content_type[:content_type.index(';')] - - def IsDataRequest(self): - return self.protocol == 'data' - - def HasReceivedResponse(self): - return self.status is not None - - def GetCacheControlDirective(self, directive_name): - """Returns the value of a Cache-Control directive, or None.""" - cache_control_str = self.GetHTTPResponseHeader('Cache-Control') - if cache_control_str is None: - return None - directives = [s.strip() for s in cache_control_str.split(',')] - for directive in directives: - parts = directive.split('=') - if len(parts) != 2: - continue - (name, value) = parts - if name == directive_name: - return value - return None - - def MaxAge(self): - """Returns the max-age of a resource, or -1.""" - # TODO(lizeb): Handle the "Expires" header as well. - cache_control = {} - if not self.response_headers: - return -1 - - cache_control_str = self.GetHTTPResponseHeader('Cache-Control') - if cache_control_str is not None: - directives = [s.strip() for s in cache_control_str.split(',')] - for directive in directives: - parts = [s.strip() for s in directive.split('=')] - if len(parts) == 1: - cache_control[parts[0]] = True - else: - cache_control[parts[0]] = parts[1] - if (u'no-store' in cache_control - or u'no-cache' in cache_control - or len(cache_control) == 0): - return -1 - max_age = self.GetCacheControlDirective('max-age') - if max_age: - return int(max_age) - return -1 - - def Cost(self): - """Returns the cost of this request in ms, defined as time between - request_time and the latest timing event. - """ - # All fields in timing are millis relative to request_time. - return self.timing.LargestOffset() - - def GetRawResponseHeaders(self): - """Gets the request's raw response headers compatible with - net::HttpResponseHeaders's constructor. - """ - assert not self.IsDataRequest() - assert self.HasReceivedResponse() - headers = bytes('{} {} {}\x00'.format( - self.protocol.upper(), self.status, self.status_text)) - for key in sorted(self.response_headers.keys()): - headers += (bytes(key.encode('latin-1')) + b': ' + - bytes(self.response_headers[key].encode('latin-1')) + b'\x00') - return headers - - def __eq__(self, o): - return self.__dict__ == o.__dict__ - - def __hash__(self): - return hash(self.request_id) - - def __str__(self): - return json.dumps(self.ToJsonDict(), sort_keys=True, indent=2) - - -def _ParseStringToInt(string): - """Parses a string to an integer like base::StringToInt64(). - - Returns: - Parsed integer. - """ - string = string.strip() - while string: - try: - parsed_integer = int(string) - if parsed_integer > sys.maxint: - return sys.maxint - if parsed_integer < -sys.maxint - 1: - return -sys.maxint - 1 - return parsed_integer - except ValueError: - string = string[:-1] - return 0 - - -class CachingPolicy(object): - """Represents the caching policy at an arbitrary time for a cached response. - """ - FETCH = 'FETCH' - VALIDATION_NONE = 'VALIDATION_NONE' - VALIDATION_SYNC = 'VALIDATION_SYNC' - VALIDATION_ASYNC = 'VALIDATION_ASYNC' - POLICIES = (FETCH, VALIDATION_NONE, VALIDATION_SYNC, VALIDATION_ASYNC) - def __init__(self, request): - """Constructor. - - Args: - request: (Request) - """ - assert request.response_headers is not None - self.request = request - # This is incorrect, as the timestamp corresponds to when devtools is made - # aware of the request, not when it was sent. However, this is good enough - # for computing cache expiration, which doesn't need sub-second precision. - self._request_time = self.request.wall_time - # Used when the date is not available. - self._response_time = ( - self._request_time + self.request.timing.receive_headers_end) - - def HasValidators(self): - """Returns wether the request has a validator.""" - # Assuming HTTP 1.1+. - return (self.request.GetHTTPResponseHeader('Last-Modified') - or self.request.GetHTTPResponseHeader('Etag')) - - def IsCacheable(self): - """Returns whether the request could be stored in the cache.""" - return not self.request.HasResponseHeaderValue('Cache-Control', 'no-store') - - def PolicyAtDate(self, timestamp): - """Returns the caching policy at an aribitrary timestamp. - - Args: - timestamp: (float) Seconds since Epoch. - - Returns: - A policy in POLICIES. - """ - # Note: the implementation is largely transcribed from - # net/http/http_response_headers.cc, itself following RFC 2616. - if not self.IsCacheable(): - return self.FETCH - freshness = self.GetFreshnessLifetimes() - if freshness[0] == 0 and freshness[1] == 0: - return self.VALIDATION_SYNC - age = self._GetCurrentAge(timestamp) - if freshness[0] > age: - return self.VALIDATION_NONE - if (freshness[0] + freshness[1]) > age: - return self.VALIDATION_ASYNC - return self.VALIDATION_SYNC - - def GetFreshnessLifetimes(self): - """Returns [freshness, stale-while-revalidate freshness] in seconds.""" - # This is adapted from GetFreshnessLifetimes() in - # //net/http/http_response_headers.cc (which follows the RFC). - r = self.request - result = [0, 0] - if (r.HasResponseHeaderValue('Cache-Control', 'no-cache') - or r.HasResponseHeaderValue('Cache-Control', 'no-store') - or r.HasResponseHeaderValue('Vary', '*')): # RFC 2616, 13.6. - return result - must_revalidate = r.HasResponseHeaderValue( - 'Cache-Control', 'must-revalidate') - swr_header = r.GetCacheControlDirective('stale-while-revalidate') - if not must_revalidate and swr_header: - result[1] = _ParseStringToInt(swr_header) - - max_age_header = r.GetCacheControlDirective('max-age') - if max_age_header: - result[0] = _ParseStringToInt(max_age_header) - return result - - date = self._GetDateValue('Date') or self._response_time - expires = self._GetDateValue('Expires') - if expires: - result[0] = expires - date - return result - - if self.request.status in (200, 203, 206) and not must_revalidate: - last_modified = self._GetDateValue('Last-Modified') - if last_modified and last_modified < date: - result[0] = (date - last_modified) / 10 - return result - - if self.request.status in (300, 301, 308, 410): - return [2**48, 0] # ~forever. - # No header -> not fresh. - return result - - def _GetDateValue(self, name): - date_str = self.request.GetHTTPResponseHeader(name) - if not date_str: - return None - parsed_date = email.utils.parsedate_tz(date_str) - if parsed_date is None: - return None - return email.utils.mktime_tz(parsed_date) - - def _GetCurrentAge(self, current_time): - # See GetCurrentAge() in //net/http/http_response_headers.cc. - r = self.request - date_value = self._GetDateValue('Date') or self._response_time - age_value = int(r.GetHTTPResponseHeader('Age') or '0') - - apparent_age = max(0, self._response_time - date_value) - corrected_received_age = max(apparent_age, age_value) - response_delay = self._response_time - self._request_time - corrected_initial_age = corrected_received_age + response_delay - resident_time = current_time - self._response_time - current_age = corrected_initial_age + resident_time - - return current_age - - -class RequestTrack(devtools_monitor.Track): - """Aggregates request data.""" - _REDIRECT_SUFFIX = '.redirect' - # Request status - _STATUS_SENT = 0 - _STATUS_RESPONSE = 1 - _STATUS_DATA = 2 - _STATUS_FINISHED = 3 - _STATUS_FAILED = 4 - # Serialization KEYS - _EVENTS_KEY = 'events' - _METADATA_KEY = 'metadata' - _DUPLICATES_KEY = 'duplicates_count' - _INCONSISTENT_INITIATORS_KEY = 'inconsistent_initiators' - def __init__(self, connection): - super(RequestTrack, self).__init__(connection) - self._connection = connection - self._requests = [] - self._requests_in_flight = {} # requestId -> (request, status) - self._completed_requests_by_id = {} - self._redirects_count_by_id = collections.defaultdict(int) - self._indexed = False - self._request_start_timestamps = None - self._request_end_timestamps = None - self._requests_by_start = None - self._requests_by_end = None - if connection: # Optional for testing. - for method in RequestTrack._METHOD_TO_HANDLER: - self._connection.RegisterListener(method, self) - # Enable asynchronous callstacks to get full javascript callstacks in - # initiators - self._connection.SetScopedState('Debugger.setAsyncCallStackDepth', - {'maxDepth': 4}, {'maxDepth': 0}, True) - # responseReceived message are sometimes duplicated. Records the message to - # detect this. - self._request_id_to_response_received = {} - self.duplicates_count = 0 - self.inconsistent_initiators_count = 0 - - def Handle(self, method, msg): - assert method in RequestTrack._METHOD_TO_HANDLER - self._indexed = False - params = msg['params'] - request_id = params['requestId'] - RequestTrack._METHOD_TO_HANDLER[method](self, request_id, params) - - def GetEvents(self): - if self._requests_in_flight: - logging.warning('Number of requests still in flight: %d.' - % len(self._requests_in_flight)) - return self._requests - - def GetFirstResourceRequest(self): - return self.GetEvents()[0] - - def GetFirstRequestMillis(self): - """Find the canonical start time for this track. - - Returns: - The millisecond timestamp of the first request. - """ - assert self._requests, "No requests to analyze." - self._IndexRequests() - return self._request_start_timestamps[0] - - def GetLastRequestMillis(self): - """Find the canonical start time for this track. - - Returns: - The millisecond timestamp of the first request. - """ - assert self._requests, "No requests to analyze." - self._IndexRequests() - return self._request_end_timestamps[-1] - - def GetEventsStartingBetween(self, start_ms, end_ms): - """Return events that started in a range. - - Args: - start_ms: the start time to query, in milliseconds from the first request. - end_ms: the end time to query, in milliseconds from the first request. - - Returns: - A list of requests whose start time is in [start_ms, end_ms]. - """ - self._IndexRequests() - low = bisect.bisect_left(self._request_start_timestamps, start_ms) - high = bisect.bisect_right(self._request_start_timestamps, end_ms) - return self._requests_by_start[low:high] - - def GetEventsEndingBetween(self, start_ms, end_ms): - """Return events that ended in a range. - - Args: - start_ms: the start time to query, in milliseconds from the first request. - end_ms: the end time to query, in milliseconds from the first request. - - Returns: - A list of requests whose end time is in [start_ms, end_ms]. - """ - self._IndexRequests() - low = bisect.bisect_left(self._request_end_timestamps, start_ms) - high = bisect.bisect_right(self._request_end_timestamps, end_ms) - return self._requests_by_end[low:high] - - def ToJsonDict(self): - if self._requests_in_flight: - logging.warning('Requests in flight, will be ignored in the dump') - return {self._EVENTS_KEY: [ - request.ToJsonDict() for request in self._requests], - self._METADATA_KEY: { - self._DUPLICATES_KEY: self.duplicates_count, - self._INCONSISTENT_INITIATORS_KEY: - self.inconsistent_initiators_count}} - - @classmethod - def FromJsonDict(cls, json_dict): - assert cls._EVENTS_KEY in json_dict - assert cls._METADATA_KEY in json_dict - result = RequestTrack(None) - requests = [Request.FromJsonDict(request) - for request in json_dict[cls._EVENTS_KEY]] - result._requests = requests - metadata = json_dict[cls._METADATA_KEY] - result.duplicates_count = metadata.get(cls._DUPLICATES_KEY, 0) - result.inconsistent_initiators_count = metadata.get( - cls._INCONSISTENT_INITIATORS_KEY, 0) - return result - - def _IndexRequests(self): - # TODO(mattcary): if we ever have requests without timing then we either - # need a default, or to make an index that only includes requests with - # timings. - if self._indexed: - return - valid_requests = [r for r in self._requests - if r.start_msec is not None] - self._requests_by_start = sorted(valid_requests, - key=lambda r: r.start_msec) - self._request_start_timestamps = [r.start_msec - for r in self._requests_by_start] - self._requests_by_end = sorted(valid_requests, - key=lambda r: r.end_msec) - self._request_end_timestamps = [r.end_msec - for r in self._requests_by_end] - self._indexed = True - - def _RequestWillBeSent(self, request_id, params): - # Several "requestWillBeSent" events can be dispatched in a row in the case - # of redirects. - redirect_initiator = None - if request_id in self._completed_requests_by_id: - assert request_id not in self._requests_in_flight - return - if request_id in self._requests_in_flight: - redirect_initiator = self._HandleRedirect(request_id, params) - assert (request_id not in self._requests_in_flight) - r = Request() - r.request_id = request_id - _CopyFromDictToObject( - params, r, (('frameId', 'frame_id'), ('loaderId', 'loader_id'), - ('documentURL', 'document_url'), - ('timestamp', 'timestamp'), ('wallTime', 'wall_time'), - ('initiator', 'initiator'))) - request = params['request'] - _CopyFromDictToObject( - request, r, (('url', 'url'), ('method', 'method'), - ('headers', 'headers'), - ('initialPriority', 'initial_priority'))) - r.resource_type = params.get('type', 'Other') - if redirect_initiator: - original_initiator = r.initiator - r.initiator = redirect_initiator - r.initiator[Request.ORIGINAL_INITIATOR] = original_initiator - initiating_request = self._completed_requests_by_id[ - redirect_initiator[Request.INITIATING_REQUEST]] - initiating_initiator = initiating_request.initiator.get( - Request.ORIGINAL_INITIATOR, initiating_request.initiator) - if initiating_initiator != original_initiator: - self.inconsistent_initiators_count += 1 - self._requests_in_flight[request_id] = (r, RequestTrack._STATUS_SENT) - - def _HandleRedirect(self, request_id, params): - (r, status) = self._requests_in_flight[request_id] - assert status == RequestTrack._STATUS_SENT - # The second request contains timing information pertaining to the first - # one. Finalize the first request. - assert 'redirectResponse' in params - redirect_response = params['redirectResponse'] - - _CopyFromDictToObject(redirect_response, r, - (('headers', 'response_headers'), - ('encodedDataLength', 'response_headers_length'), - ('fromDiskCache', 'from_disk_cache'), - ('protocol', 'protocol'), ('status', 'status'), - ('statusText', 'status_text'))) - r.timing = Timing.FromDevToolsDict(redirect_response['timing']) - - redirect_index = self._redirects_count_by_id[request_id] - self._redirects_count_by_id[request_id] += 1 - r.request_id = '%s%s.%d' % (request_id, self._REDIRECT_SUFFIX, - redirect_index + 1) - initiator = { - 'type': 'redirect', Request.INITIATING_REQUEST: r.request_id} - self._requests_in_flight[r.request_id] = (r, RequestTrack._STATUS_FINISHED) - del self._requests_in_flight[request_id] - self._FinalizeRequest(r.request_id) - return initiator - - def _RequestServedFromCache(self, request_id, _): - if request_id not in self._requests_in_flight: - return - (request, status) = self._requests_in_flight[request_id] - assert status == RequestTrack._STATUS_SENT - request.served_from_cache = True - - def _ResponseReceived(self, request_id, params): - if request_id in self._completed_requests_by_id: - assert request_id not in self._requests_in_flight - return - assert request_id in self._requests_in_flight - (r, status) = self._requests_in_flight[request_id] - if status == RequestTrack._STATUS_RESPONSE: - # Duplicated messages (apart from the timestamp) are OK. - old_params = self._request_id_to_response_received[request_id] - params_copy = copy.deepcopy(params) - params_copy['timestamp'] = None - old_params['timestamp'] = None - assert params_copy == old_params - self.duplicates_count += 1 - return - assert status == RequestTrack._STATUS_SENT - assert (r.frame_id == params['frameId'] or - params['response']['protocol'] == 'data') - assert r.timestamp <= params['timestamp'] - if r.resource_type == 'Other': - r.resource_type = params.get('type', 'Other') - else: - assert r.resource_type == params.get('type', 'Other') - response = params['response'] - _CopyFromDictToObject( - response, r, (('status', 'status'), ('mimeType', 'mime_type'), - ('fromDiskCache', 'from_disk_cache'), - ('fromServiceWorker', 'from_service_worker'), - ('protocol', 'protocol'), ('statusText', 'status_text'), - # Actual request headers are not known before reaching the - # network stack. - ('requestHeaders', 'request_headers'), - ('encodedDataLength', 'response_headers_length'), - ('headers', 'response_headers'))) - timing_dict = {} - # Some URLs don't have a timing dict (e.g. data URLs), and timings for - # cached requests are stale. - # TODO(droger): the timestamp is inacurate, get the real timings instead. - if not response.get('timing') or r.served_from_cache: - timing_dict = {'requestTime': r.timestamp} - else: - timing_dict = response['timing'] - r.timing = Timing.FromDevToolsDict(timing_dict) - self._requests_in_flight[request_id] = (r, RequestTrack._STATUS_RESPONSE) - self._request_id_to_response_received[request_id] = params - - def _DataReceived(self, request_id, params): - if request_id not in self._requests_in_flight: - return - (r, status) = self._requests_in_flight[request_id] - assert (status == RequestTrack._STATUS_RESPONSE - or status == RequestTrack._STATUS_DATA) - offset = r._TimestampOffsetFromStartMs(params['timestamp']) - r.data_chunks.append((offset, params['encodedDataLength'])) - self._requests_in_flight[request_id] = (r, RequestTrack._STATUS_DATA) - - def _LoadingFinished(self, request_id, params): - if request_id not in self._requests_in_flight: - return - (r, status) = self._requests_in_flight[request_id] - assert (status == RequestTrack._STATUS_RESPONSE - or status == RequestTrack._STATUS_DATA) - r.encoded_data_length = params['encodedDataLength'] - r.timing.loading_finished = r._TimestampOffsetFromStartMs( - params['timestamp']) - self._requests_in_flight[request_id] = (r, RequestTrack._STATUS_FINISHED) - self._FinalizeRequest(request_id) - - def _LoadingFailed(self, request_id, params): - if request_id not in self._requests_in_flight: - logging.warning('An unknown request failed: %s' % request_id) - return - (r, _) = self._requests_in_flight[request_id] - r.failed = True - r.error_text = params['errorText'] - self._requests_in_flight[request_id] = (r, RequestTrack._STATUS_FINISHED) - self._FinalizeRequest(request_id) - - def _FinalizeRequest(self, request_id): - (request, status) = self._requests_in_flight[request_id] - assert status == RequestTrack._STATUS_FINISHED - del self._requests_in_flight[request_id] - self._completed_requests_by_id[request_id] = request - self._requests.append(request) - - def __eq__(self, o): - return self._requests == o._requests - - -RequestTrack._METHOD_TO_HANDLER = { - 'Network.requestWillBeSent': RequestTrack._RequestWillBeSent, - 'Network.requestServedFromCache': RequestTrack._RequestServedFromCache, - 'Network.responseReceived': RequestTrack._ResponseReceived, - 'Network.dataReceived': RequestTrack._DataReceived, - 'Network.loadingFinished': RequestTrack._LoadingFinished, - 'Network.loadingFailed': RequestTrack._LoadingFailed} - - -def _CopyFromDictToObject(d, o, key_attrs): - for (key, attr) in key_attrs: - if key in d: - setattr(o, attr, d[key]) - - -if __name__ == '__main__': - import json - import sys - events = json.load(open(sys.argv[1], 'r')) - request_track = RequestTrack(None) - for event in events: - event_method = event['method'] - request_track.Handle(event_method, event)
diff --git a/tools/android/loading/request_track_unittest.py b/tools/android/loading/request_track_unittest.py deleted file mode 100644 index 3f0baea..0000000 --- a/tools/android/loading/request_track_unittest.py +++ /dev/null
@@ -1,636 +0,0 @@ -# Copyright 2016 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. - -import copy -import json -import sys -import unittest - -from request_track import (TimeBetween, Request, CachingPolicy, RequestTrack, - Timing, _ParseStringToInt) - - -class TimeBetweenTestCase(unittest.TestCase): - _REQUEST = Request.FromJsonDict({'url': 'http://bla.com', - 'request_id': '1234.1', - 'frame_id': '123.1', - 'initiator': {'type': 'other'}, - 'timestamp': 2, - 'timing': {}}) - def setUp(self): - super(TimeBetweenTestCase, self).setUp() - self.first = copy.deepcopy(self._REQUEST) - self.first.timing = Timing.FromDevToolsDict({'requestTime': 123456, - 'receiveHeadersEnd': 100, - 'loadingFinished': 500}) - self.second = copy.deepcopy(self._REQUEST) - self.second.timing = Timing.FromDevToolsDict({'requestTime': 123456 + 1, - 'receiveHeadersEnd': 200, - 'loadingFinished': 600}) - - def testTimeBetweenParser(self): - self.assertEquals(900, TimeBetween(self.first, self.second, 'parser')) - - def testTimeBetweenScript(self): - self.assertEquals(500, TimeBetween(self.first, self.second, 'script')) - - -class RequestTestCase(unittest.TestCase): - def testContentType(self): - r = Request() - r.response_headers = {} - self.assertEquals(None, r.GetContentType()) - r.response_headers = {'Content-Type': 'application/javascript'} - self.assertEquals('application/javascript', r.GetContentType()) - # Case-insensitive match. - r.response_headers = {'content-type': 'application/javascript'} - self.assertEquals('application/javascript', r.GetContentType()) - # Parameters are filtered out. - r.response_headers = {'Content-Type': 'application/javascript;bla'} - self.assertEquals('application/javascript', r.GetContentType()) - # MIME type takes precedence over 'Content-Type' header. - r.mime_type = 'image/webp' - self.assertEquals('image/webp', r.GetContentType()) - r.mime_type = None - # Test for 'ping' type. - r.status = 204 - self.assertEquals('ping', r.GetContentType()) - r.status = None - r.response_headers = {'Content-Type': 'application/javascript', - 'content-length': '0'} - self.assertEquals('ping', r.GetContentType()) - # Test for 'redirect' type. - r.response_headers = {'Content-Type': 'application/javascript', - 'location': 'http://foo', - 'content-length': '0'} - self.assertEquals('redirect', r.GetContentType()) - - def testGetHTTPResponseHeader(self): - r = Request() - r.response_headers = {} - self.assertEquals(None, r.GetHTTPResponseHeader('Foo')) - r.response_headers = {'Foo': 'Bar', 'Baz': 'Foo'} - self.assertEquals('Bar', r.GetHTTPResponseHeader('Foo')) - r.response_headers = {'foo': 'Bar', 'Baz': 'Foo'} - self.assertEquals('Bar', r.GetHTTPResponseHeader('Foo')) - - def testGetRawResponseHeaders(self): - r = Request() - r.protocol = 'http/1.1' - r.status = 200 - r.status_text = 'Hello world' - r.response_headers = {'Foo': 'Bar', 'Baz': 'Foo'} - self.assertEquals('HTTP/1.1 200 Hello world\x00Baz: Foo\x00Foo: Bar\x00', - r.GetRawResponseHeaders()) - - -class ParseStringToIntTestCase(unittest.TestCase): - def runTest(self): - MININT = -sys.maxint - 1 - # Same test cases as in string_number_conversions_unittest.cc - CASES = [ - ("0", 0), - ("42", 42), - ("-2147483648", -2147483648), - ("2147483647", 2147483647), - ("-2147483649", -2147483649), - ("-99999999999", -99999999999), - ("2147483648", 2147483648), - ("99999999999", 99999999999), - ("9223372036854775807", sys.maxint), - ("-9223372036854775808", MININT), - ("09", 9), - ("-09", -9), - ("", 0), - (" 42", 42), - ("42 ", 42), - ("0x42", 0), - ("\t\n\v\f\r 42", 42), - ("blah42", 0), - ("42blah", 42), - ("blah42blah", 0), - ("-273.15", -273), - ("+98.6", 98), - ("--123", 0), - ("++123", 0), - ("-+123", 0), - ("+-123", 0), - ("-", 0), - ("-9223372036854775809", MININT), - ("-99999999999999999999", MININT), - ("9223372036854775808", sys.maxint), - ("99999999999999999999", sys.maxint)] - for string, expected_int in CASES: - parsed_int = _ParseStringToInt(string) - self.assertEquals(expected_int, parsed_int) - - -class CachingPolicyTestCase(unittest.TestCase): - _REQUEST = { - 'encoded_data_length': 14726, - 'request_id': '2291.1', - 'response_headers': { - 'Age': '866', - 'Content-Length': '14187', - 'Date': 'Fri, 22 Apr 2016 08:56:19 -0200', - 'Vary': 'Accept-Encoding', - }, - 'timestamp': 5535648.730768, - 'timing': { - 'connect_end': 34.0510001406074, - 'connect_start': 21.6859998181462, - 'dns_end': 21.6859998181462, - 'dns_start': 0, - 'loading_finished': 58.76399949193001, - 'receive_headers_end': 47.0650000497699, - 'request_time': 5535648.73264, - 'send_end': 34.6099995076656, - 'send_start': 34.2979999259114 - }, - 'url': 'http://www.example.com/', - 'status': 200, - 'wall_time': 1461322579.59422} - - def testHasValidators(self): - r = self._MakeRequest() - self.assertFalse(CachingPolicy(r).HasValidators()) - r.response_headers['Last-Modified'] = 'Yesterday all my troubles' - self.assertTrue(CachingPolicy(r).HasValidators()) - r = self._MakeRequest() - r.response_headers['ETAG'] = 'ABC' - self.assertTrue(CachingPolicy(r).HasValidators()) - - def testIsCacheable(self): - r = self._MakeRequest() - self.assertTrue(CachingPolicy(r).IsCacheable()) - r.response_headers['Cache-Control'] = 'Whatever,no-store' - self.assertFalse(CachingPolicy(r).IsCacheable()) - - def testPolicyNoStore(self): - r = self._MakeRequest() - r.response_headers['Cache-Control'] = 'Whatever,no-store' - self.assertEqual(CachingPolicy.FETCH, CachingPolicy(r).PolicyAtDate(0)) - - def testPolicyMaxAge(self): - r = self._MakeRequest() - r.response_headers['Cache-Control'] = 'whatever,max-age= 1000,whatever' - self.assertEqual( - CachingPolicy.VALIDATION_NONE, - CachingPolicy(r).PolicyAtDate(r.wall_time)) - self.assertEqual( - CachingPolicy.VALIDATION_SYNC, - CachingPolicy(r).PolicyAtDate(r.wall_time + 10000)) - # Take current age into account. - self.assertEqual( - CachingPolicy.VALIDATION_SYNC, - CachingPolicy(r).PolicyAtDate(r.wall_time + 500)) - # Max-Age before Expires. - r.response_headers['Expires'] = 'Thu, 21 Apr 2016 00:00:00 -0200' - self.assertEqual( - CachingPolicy.VALIDATION_NONE, - CachingPolicy(r).PolicyAtDate(r.wall_time)) - # Max-Age < age - r.response_headers['Cache-Control'] = 'whatever,max-age=100crap,whatever' - self.assertEqual( - CachingPolicy.VALIDATION_SYNC, - CachingPolicy(r).PolicyAtDate(r.wall_time + 2)) - - def testPolicyExpires(self): - r = self._MakeRequest() - # Already expired - r.response_headers['Expires'] = 'Thu, 21 Apr 2016 00:00:00 -0200' - self.assertEqual( - CachingPolicy.VALIDATION_SYNC, - CachingPolicy(r).PolicyAtDate(r.wall_time)) - r.response_headers['Expires'] = 'Thu, 25 Apr 2016 00:00:00 -0200' - self.assertEqual( - CachingPolicy.VALIDATION_NONE,\ - CachingPolicy(r).PolicyAtDate(r.wall_time)) - self.assertEqual( - CachingPolicy.VALIDATION_NONE, - CachingPolicy(r).PolicyAtDate(r.wall_time + 86400)) - self.assertEqual(CachingPolicy.VALIDATION_SYNC, - CachingPolicy(r).PolicyAtDate(r.wall_time + 86400 * 5)) - - def testStaleWhileRevalidate(self): - r = self._MakeRequest() - r.response_headers['Cache-Control'] = ( - 'whatever,max-age=1000,stale-while-revalidate=2000') - self.assertEqual( - CachingPolicy.VALIDATION_ASYNC, - CachingPolicy(r).PolicyAtDate(r.wall_time + 200)) - self.assertEqual( - CachingPolicy.VALIDATION_ASYNC, - CachingPolicy(r).PolicyAtDate(r.wall_time + 2000)) - self.assertEqual( - CachingPolicy.VALIDATION_SYNC, - CachingPolicy(r).PolicyAtDate(r.wall_time + 3100)) - # must-revalidate overrides stale-while-revalidate. - r.response_headers['Cache-Control'] += ',must-revalidate' - self.assertEqual( - CachingPolicy.VALIDATION_SYNC, - CachingPolicy(r).PolicyAtDate(r.wall_time + 200)) - - def test301NeverExpires(self): - r = self._MakeRequest() - r.status = 301 - self.assertEqual( - CachingPolicy.VALIDATION_NONE, - CachingPolicy(r).PolicyAtDate(r.wall_time + 2000)) - - def testLastModifiedHeuristic(self): - r = self._MakeRequest() - # 8 hours ago. - r.response_headers['Last-Modified'] = 'Fri, 22 Apr 2016 00:56:19 -0200' - del r.response_headers['Age'] - self.assertEqual( - CachingPolicy.VALIDATION_NONE, - CachingPolicy(r).PolicyAtDate(r.wall_time + 60)) - self.assertEqual( - CachingPolicy.VALIDATION_SYNC, - CachingPolicy(r).PolicyAtDate(r.wall_time + 3600)) - - @classmethod - def _MakeRequest(cls): - return Request.FromJsonDict(copy.deepcopy(cls._REQUEST)) - - -class RequestTrackTestCase(unittest.TestCase): - _REQUEST_WILL_BE_SENT = { - 'method': 'Network.requestWillBeSent', - 'params': { - 'documentURL': 'http://example.com/', - 'frameId': '32493.1', - 'initiator': { - 'type': 'other' - }, - 'loaderId': '32493.3', - 'request': { - 'headers': { - 'Accept': 'text/html', - 'Upgrade-Insecure-Requests': '1', - 'User-Agent': 'Mozilla/5.0' - }, - 'initialPriority': 'VeryHigh', - 'method': 'GET', - 'mixedContentType': 'none', - 'url': 'http://example.com/' - }, - 'requestId': '32493.1', - 'timestamp': 5571441.535053, - 'type': 'Document', - 'wallTime': 1452691674.08878}} - _REDIRECT = { - 'method': 'Network.requestWillBeSent', - 'params': { - 'documentURL': 'http://www.example.com/', - 'frameId': '32493.1', - 'initiator': { - 'type': 'other' - }, - 'loaderId': '32493.3', - 'redirectResponse': { - 'connectionId': 18, - 'connectionReused': False, - 'encodedDataLength': 198, - 'fromDiskCache': False, - 'fromServiceWorker': False, - 'headers': {}, - 'headersText': 'HTTP/1.1 301 Moved Permanently\r\n', - 'mimeType': 'text/html', - 'protocol': 'http/1.1', - 'remoteIPAddress': '216.146.46.10', - 'remotePort': 80, - 'requestHeaders': { - 'Accept': 'text/html', - 'User-Agent': 'Mozilla/5.0' - }, - 'securityState': 'neutral', - 'status': 301, - 'statusText': 'Moved Permanently', - 'timing': { - 'connectEnd': 137.435999698937, - 'connectStart': 51.1459996923804, - 'dnsEnd': 51.1459996923804, - 'dnsStart': 0, - 'proxyEnd': -1, - 'proxyStart': -1, - 'receiveHeadersEnd': 228.187000378966, - 'requestTime': 5571441.55002, - 'sendEnd': 138.841999694705, - 'sendStart': 138.031999580562, - 'sslEnd': -1, - 'sslStart': -1, - 'workerReady': -1, - 'workerStart': -1 - }, - 'url': 'http://example.com/' - }, - 'request': { - 'headers': { - 'Accept': 'text/html', - 'User-Agent': 'Mozilla/5.0' - }, - 'initialPriority': 'VeryLow', - 'method': 'GET', - 'mixedContentType': 'none', - 'url': 'http://www.example.com/' - }, - 'requestId': '32493.1', - 'timestamp': 5571441.795948, - 'type': 'Document', - 'wallTime': 1452691674.34968}} - _RESPONSE_RECEIVED = { - 'method': 'Network.responseReceived', - 'params': { - 'frameId': '32493.1', - 'loaderId': '32493.3', - 'requestId': '32493.1', - 'response': { - 'connectionId': 26, - 'connectionReused': False, - 'encodedDataLength': -1, - 'fromDiskCache': False, - 'fromServiceWorker': False, - 'headers': { - 'Age': '67', - 'Cache-Control': 'max-age=0,must-revalidate', - }, - 'headersText': 'HTTP/1.1 200 OK\r\n', - 'mimeType': 'text/html', - 'protocol': 'http/1.1', - 'requestHeaders': { - 'Accept': 'text/html', - 'Host': 'www.example.com', - 'User-Agent': 'Mozilla/5.0' - }, - 'status': 200, - 'timing': { - 'connectEnd': 37.9800004884601, - 'connectStart': 26.8250005319715, - 'dnsEnd': 26.8250005319715, - 'dnsStart': 0, - 'proxyEnd': -1, - 'proxyStart': -1, - 'receiveHeadersEnd': 54.9750002101064, - 'requestTime': 5571441.798671, - 'sendEnd': 38.3980004116893, - 'sendStart': 38.1810003891587, - 'sslEnd': -1, - 'sslStart': -1, - 'workerReady': -1, - 'workerStart': -1 - }, - 'url': 'http://www.example.com/' - }, - 'timestamp': 5571441.865639, - 'type': 'Document'}} - _DATA_RECEIVED_1 = { - "method": "Network.dataReceived", - "params": { - "dataLength": 1803, - "encodedDataLength": 1326, - "requestId": "32493.1", - "timestamp": 5571441.867347}} - _DATA_RECEIVED_2 = { - "method": "Network.dataReceived", - "params": { - "dataLength": 32768, - "encodedDataLength": 32768, - "requestId": "32493.1", - "timestamp": 5571441.893121}} - _SERVED_FROM_CACHE = { - "method": "Network.requestServedFromCache", - "params": { - "requestId": "32493.1"}} - _LOADING_FINISHED = {'method': 'Network.loadingFinished', - 'params': { - 'encodedDataLength': 101829, - 'requestId': '32493.1', - 'timestamp': 5571441.891189}} - _LOADING_FAILED = {'method': 'Network.loadingFailed', - 'params': { - 'canceled': False, - 'blockedReason': None, - 'encodedDataLength': 101829, - 'errorText': 'net::ERR_TOO_MANY_REDIRECTS', - 'requestId': '32493.1', - 'timestamp': 5571441.891189, - 'type': 'Document'}} - - def setUp(self): - self.request_track = RequestTrack(None) - - def testParseRequestWillBeSent(self): - msg = RequestTrackTestCase._REQUEST_WILL_BE_SENT - request_id = msg['params']['requestId'] - self.request_track.Handle('Network.requestWillBeSent', msg) - self.assertTrue(request_id in self.request_track._requests_in_flight) - (_, status) = self.request_track._requests_in_flight[request_id] - self.assertEquals(RequestTrack._STATUS_SENT, status) - - def testRejectsUnknownMethod(self): - with self.assertRaises(AssertionError): - self.request_track.Handle( - 'unknown', RequestTrackTestCase._REQUEST_WILL_BE_SENT) - - def testHandleRedirect(self): - self.request_track.Handle('Network.requestWillBeSent', - RequestTrackTestCase._REQUEST_WILL_BE_SENT) - self.request_track.Handle('Network.requestWillBeSent', - RequestTrackTestCase._REDIRECT) - self.assertEquals(1, len(self.request_track._requests_in_flight)) - self.assertEquals(1, len(self.request_track.GetEvents())) - redirect_request = self.request_track.GetEvents()[0] - self.assertTrue(redirect_request.request_id.endswith( - RequestTrack._REDIRECT_SUFFIX + '.1')) - request = self.request_track._requests_in_flight.values()[0][0] - self.assertEquals('redirect', request.initiator['type']) - self.assertEquals( - redirect_request.request_id, - request.initiator[Request.INITIATING_REQUEST]) - self.assertEquals(0, self.request_track.inconsistent_initiators_count) - - def testMultipleRedirects(self): - self.request_track.Handle('Network.requestWillBeSent', - RequestTrackTestCase._REQUEST_WILL_BE_SENT) - self.request_track.Handle('Network.requestWillBeSent', - RequestTrackTestCase._REDIRECT) - self.request_track.Handle('Network.requestWillBeSent', - RequestTrackTestCase._REDIRECT) - self.assertEquals(1, len(self.request_track._requests_in_flight)) - self.assertEquals(2, len(self.request_track.GetEvents())) - first_redirect_request = self.request_track.GetEvents()[0] - self.assertTrue(first_redirect_request.request_id.endswith( - RequestTrack._REDIRECT_SUFFIX + '.1')) - second_redirect_request = self.request_track.GetEvents()[1] - self.assertTrue(second_redirect_request.request_id.endswith( - RequestTrack._REDIRECT_SUFFIX + '.2')) - self.assertEquals('redirect', second_redirect_request.initiator['type']) - self.assertEquals( - first_redirect_request.request_id, - second_redirect_request.initiator[Request.INITIATING_REQUEST]) - request = self.request_track._requests_in_flight.values()[0][0] - self.assertEquals('redirect', request.initiator['type']) - self.assertEquals( - second_redirect_request.request_id, - request.initiator[Request.INITIATING_REQUEST]) - self.assertEquals(0, self.request_track.inconsistent_initiators_count) - - def testInconsistentInitiators(self): - self.request_track.Handle('Network.requestWillBeSent', - RequestTrackTestCase._REQUEST_WILL_BE_SENT) - request = copy.deepcopy(RequestTrackTestCase._REDIRECT) - request['params']['initiator']['type'] = 'script' - self.request_track.Handle('Network.requestWillBeSent', request) - self.assertEquals(1, self.request_track.inconsistent_initiators_count) - - def testRejectDuplicates(self): - msg = RequestTrackTestCase._REQUEST_WILL_BE_SENT - self.request_track.Handle('Network.requestWillBeSent', msg) - with self.assertRaises(AssertionError): - self.request_track.Handle('Network.requestWillBeSent', msg) - - def testIgnoreCompletedDuplicates(self): - self.request_track.Handle('Network.requestWillBeSent', - RequestTrackTestCase._REQUEST_WILL_BE_SENT) - self.request_track.Handle('Network.responseReceived', - RequestTrackTestCase._RESPONSE_RECEIVED) - self.request_track.Handle('Network.loadingFinished', - RequestTrackTestCase._LOADING_FINISHED) - # Should not raise an AssertionError. - self.request_track.Handle('Network.requestWillBeSent', - RequestTrackTestCase._REQUEST_WILL_BE_SENT) - - def testSequenceOfGeneratedResponse(self): - self.request_track.Handle('Network.requestServedFromCache', - RequestTrackTestCase._SERVED_FROM_CACHE) - self.request_track.Handle('Network.loadingFinished', - RequestTrackTestCase._LOADING_FINISHED) - self.assertEquals(0, len(self.request_track.GetEvents())) - - def testInvalidSequence(self): - msg1 = RequestTrackTestCase._REQUEST_WILL_BE_SENT - msg2 = RequestTrackTestCase._LOADING_FINISHED - self.request_track.Handle('Network.requestWillBeSent', msg1) - with self.assertRaises(AssertionError): - self.request_track.Handle('Network.loadingFinished', msg2) - - def testValidSequence(self): - self._ValidSequence(self.request_track) - self.assertEquals(1, len(self.request_track.GetEvents())) - self.assertEquals(0, len(self.request_track._requests_in_flight)) - r = self.request_track.GetEvents()[0] - self.assertEquals('32493.1', r.request_id) - self.assertEquals('32493.1', r.frame_id) - self.assertEquals('32493.3', r.loader_id) - self.assertEquals('http://example.com/', r.document_url) - self.assertEquals('http://example.com/', r.url) - self.assertEquals('http/1.1', r.protocol) - self.assertEquals('GET', r.method) - response = RequestTrackTestCase._RESPONSE_RECEIVED['params']['response'] - self.assertEquals(response['requestHeaders'], r.request_headers) - self.assertEquals(response['headers'], r.response_headers) - self.assertEquals('VeryHigh', r.initial_priority) - request_will_be_sent = ( - RequestTrackTestCase._REQUEST_WILL_BE_SENT['params']) - self.assertEquals(request_will_be_sent['timestamp'], r.timestamp) - self.assertEquals(request_will_be_sent['wallTime'], r.wall_time) - self.assertEquals(request_will_be_sent['initiator'], r.initiator) - self.assertEquals(request_will_be_sent['type'], r.resource_type) - self.assertEquals(False, r.served_from_cache) - self.assertEquals(False, r.from_disk_cache) - self.assertEquals(False, r.from_service_worker) - timing = Timing.FromDevToolsDict(response['timing']) - loading_finished = RequestTrackTestCase._LOADING_FINISHED['params'] - loading_finished_offset = r._TimestampOffsetFromStartMs( - loading_finished['timestamp']) - timing.loading_finished = loading_finished_offset - self.assertEquals(timing, r.timing) - self.assertEquals(200, r.status) - self.assertEquals( - loading_finished['encodedDataLength'], r.encoded_data_length) - self.assertEquals(False, r.failed) - - def testDataReceived(self): - self._ValidSequence(self.request_track) - self.assertEquals(1, len(self.request_track.GetEvents())) - r = self.request_track.GetEvents()[0] - self.assertEquals(2, len(r.data_chunks)) - self.assertEquals( - RequestTrackTestCase._DATA_RECEIVED_1['params']['encodedDataLength'], - r.data_chunks[0][1]) - self.assertEquals( - RequestTrackTestCase._DATA_RECEIVED_2['params']['encodedDataLength'], - r.data_chunks[1][1]) - - def testDuplicatedResponseReceived(self): - msg1 = RequestTrackTestCase._REQUEST_WILL_BE_SENT - msg2 = copy.deepcopy(RequestTrackTestCase._RESPONSE_RECEIVED) - msg2_other_timestamp = copy.deepcopy(msg2) - msg2_other_timestamp['params']['timestamp'] += 12 - msg2_different = copy.deepcopy(msg2) - msg2_different['params']['response']['encodedDataLength'] += 1 - self.request_track.Handle('Network.requestWillBeSent', msg1) - self.request_track.Handle('Network.responseReceived', msg2) - # Should not raise an AssertionError. - self.request_track.Handle('Network.responseReceived', msg2) - self.assertEquals(1, self.request_track.duplicates_count) - with self.assertRaises(AssertionError): - self.request_track.Handle('Network.responseReceived', msg2_different) - - def testLoadingFailed(self): - self.request_track.Handle('Network.requestWillBeSent', - RequestTrackTestCase._REQUEST_WILL_BE_SENT) - self.request_track.Handle('Network.responseReceived', - RequestTrackTestCase._RESPONSE_RECEIVED) - self.request_track.Handle('Network.loadingFailed', - RequestTrackTestCase._LOADING_FAILED) - r = self.request_track.GetEvents()[0] - self.assertTrue(r.failed) - self.assertEquals('net::ERR_TOO_MANY_REDIRECTS', r.error_text) - - def testCanSerialize(self): - self._ValidSequence(self.request_track) - json_dict = self.request_track.ToJsonDict() - _ = json.dumps(json_dict) # Should not raise an exception. - - def testCanDeserialize(self): - self._ValidSequence(self.request_track) - self.request_track.duplicates_count = 142 - self.request_track.inconsistent_initiators_count = 123 - json_dict = self.request_track.ToJsonDict() - request_track = RequestTrack.FromJsonDict(json_dict) - self.assertEquals(self.request_track, request_track) - - def testMaxAge(self): - rq = Request() - self.assertEqual(-1, rq.MaxAge()) - rq.response_headers = {} - self.assertEqual(-1, rq.MaxAge()) - rq.response_headers[ - 'Cache-Control'] = 'private,s-maxage=0,max-age=0,must-revalidate' - self.assertEqual(0, rq.MaxAge()) - rq.response_headers[ - 'Cache-Control'] = 'private,s-maxage=0,no-store,max-age=100' - self.assertEqual(-1, rq.MaxAge()) - rq.response_headers[ - 'Cache-Control'] = 'private,s-maxage=0' - self.assertEqual(-1, rq.MaxAge()) - # Case-insensitive match. - rq.response_headers['cache-control'] = 'max-age=600' - self.assertEqual(600, rq.MaxAge()) - - - @classmethod - def _ValidSequence(cls, request_track): - request_track.Handle( - 'Network.requestWillBeSent', cls._REQUEST_WILL_BE_SENT) - request_track.Handle('Network.responseReceived', cls._RESPONSE_RECEIVED) - request_track.Handle('Network.dataReceived', cls._DATA_RECEIVED_1) - request_track.Handle('Network.dataReceived', cls._DATA_RECEIVED_2) - request_track.Handle('Network.loadingFinished', cls._LOADING_FINISHED) - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/resource_sack.py b/tools/android/loading/resource_sack.py deleted file mode 100644 index d7fe331..0000000 --- a/tools/android/loading/resource_sack.py +++ /dev/null
@@ -1,224 +0,0 @@ -# Copyright 2016 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. - -"""A collection of ResourceGraphs. - -Processes multiple ResourceGraphs, all presumably from requests to the same -site. Common urls are collected in Bags and different statistics on the -relationship between bags are collected. -""" - -import collections -import json -import sys -import urlparse - -from collections import defaultdict - -import content_classification_lens -import graph -import user_satisfied_lens - -class GraphSack(object): - """Aggreate of RequestDependencyGraphs. - - Collects RequestDependencyGraph nodes into bags, where each bag contains the - nodes with common urls. Dependency edges are tracked between bags (so that - each bag may be considered as a node of a graph). This graph of bags is - referred to as a sack. - - Each bag is associated with a dag.Node, even though the bag graph may not be a - DAG. The edges are annotated with list of graphs and nodes that generated - them. - """ - # See CoreSet(). - CORE_THRESHOLD = 0.8 - - _GraphInfo = collections.namedtuple('_GraphInfo', ( - 'cost', # The graph cost (aka critical path length). - )) - - def __init__(self): - # Each bag in our sack is named as indicated by this map. - self._name_to_bag = {} - # List our edges by bag pairs: (from_bag, to_bag) -> graph.Edge. - self._edges = {} - # Maps graph -> _GraphInfo structures for each graph we've consumed. - self._graph_info = {} - - # How we generate names. - self._name_generator = lambda n: n.request.url - - # Our graph, updated after each ConsumeGraph. - self._graph = None - - def SetNameGenerator(self, generator): - """Set the generator we use for names. - - This will define the equivalence class of requests we use to define sacks. - - Args: - generator: a function taking a RequestDependencyGraph node and returning a - string. - """ - self._name_generator = generator - - def ConsumeGraph(self, request_graph): - """Add a graph and process. - - Args: - graph: (RequestDependencyGraph) the graph to add. - """ - assert graph not in self._graph_info - cost = request_graph.Cost() - self._graph_info[request_graph] = self._GraphInfo(cost=cost) - for n in request_graph.graph.Nodes(): - self.AddNode(request_graph, n) - - # TODO(mattcary): this is inefficient but our current API doesn't require an - # explicit graph creation from the client. - self._graph = graph.DirectedGraph(self.bags, self._edges.itervalues()) - - def GetBag(self, node): - """Find the bag for a node, or None if not found.""" - return self._name_to_bag.get(self._name_generator(node), None) - - def AddNode(self, request_graph, node): - """Add a node to our collection. - - Args: - graph: (RequestDependencyGraph) the graph in which the node lives. - node: (RequestDependencyGraph node) the node to add. - - Returns: - The Bag containing the node. - """ - sack_name = self._name_generator(node) - if sack_name not in self._name_to_bag: - self._name_to_bag[sack_name] = Bag(self, sack_name) - bag = self._name_to_bag[sack_name] - bag.AddNode(request_graph, node) - return bag - - def AddEdge(self, from_bag, to_bag): - """Add an edge between two bags.""" - if (from_bag, to_bag) not in self._edges: - self._edges[(from_bag, to_bag)] = graph.Edge(from_bag, to_bag) - - def CoreSet(self, *graph_sets): - """Compute the core set of this sack. - - The core set of a sack is the set of resource that are common to most of the - graphs in the sack. A core set of a set of graphs are the resources that - appear with frequency at least CORE_THRESHOLD. For a collection of graph - sets, for instance pulling the same page under different network - connections, we intersect the core sets to produce a page core set that - describes the key resources used by the page. See https://goo.gl/LmqQRS for - context and discussion. - - Args: - graph_sets: one or more collection of graphs to compute core sets. If one - graph set is given, its core set is computed. If more than one set is - given, the page core set of all sets is computed (the intersection of - core sets). If no graph set is given, the core of all graphs is - computed. - - Returns: - A set of bags in the core set. - """ - if not graph_sets: - graph_sets = [self._graph_info.keys()] - return reduce(lambda a, b: a & b, - (self._SingleCore(s) for s in graph_sets)) - - @classmethod - def CoreSimilarity(cls, a, b): - """Compute the similarity of two core sets. - - We use the Jaccard index. See https://goo.gl/LmqQRS for discussion. - - Args: - a: The first core set, as a set of strings. - b: The second core set, as a set of strings. - - Returns: - A similarity score between zero and one. If both sets are empty the - similarity is zero. - """ - if not a and not b: - return 0 - return float(len(a & b)) / len(a | b) - - @property - def num_graphs(self): - return len(self.graph_info) - - @property - def graph_info(self): - return self._graph_info - - @property - def bags(self): - return self._name_to_bag.values() - - def _SingleCore(self, graph_set): - core = set() - graph_set = set(graph_set) - num_graphs = len(graph_set) - for b in self.bags: - count = sum([g in graph_set for g in b.graphs]) - if float(count) / num_graphs > self.CORE_THRESHOLD: - core.add(b) - return core - - @classmethod - def _MakeShortname(cls, url): - # TODO(lizeb): Move this method to a convenient common location. - parsed = urlparse.urlparse(url) - if parsed.scheme == 'data': - if ';' in parsed.path: - kind, _ = parsed.path.split(';', 1) - else: - kind, _ = parsed.path.split(',', 1) - return 'data:' + kind - path = parsed.path[:10] - hostname = parsed.hostname if parsed.hostname else '?.?.?' - return hostname + '/' + path - - -class Bag(graph.Node): - def __init__(self, sack, name): - super(Bag, self).__init__() - self._sack = sack - self._name = name - self._label = GraphSack._MakeShortname(name) - # Maps a ResourceGraph to its Nodes contained in this Bag. - self._graphs = defaultdict(set) - - @property - def name(self): - return self._name - - @property - def label(self): - return self._label - - @property - def graphs(self): - return self._graphs.iterkeys() - - @property - def num_nodes(self): - return sum(len(g) for g in self._graphs.itervalues()) - - def GraphNodes(self, g): - return self._graphs.get(g, set()) - - def AddNode(self, request_graph, node): - if node in self._graphs[request_graph]: - return # Already added. - self._graphs[request_graph].add(node) - for edge in request_graph.graph.OutEdges(node): - out_bag = self._sack.AddNode(request_graph, edge.to_node) - self._sack.AddEdge(self, out_bag)
diff --git a/tools/android/loading/resource_sack_unittest.py b/tools/android/loading/resource_sack_unittest.py deleted file mode 100644 index 30c1d0e..0000000 --- a/tools/android/loading/resource_sack_unittest.py +++ /dev/null
@@ -1,121 +0,0 @@ -# Copyright 2016 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. - -import unittest - -import resource_sack -from test_utils import (MakeRequest, - TestDependencyGraph) - - -class ResourceSackTestCase(unittest.TestCase): - def SimpleGraph(self, node_names): - """Create a simple graph from a list of nodes.""" - requests = [MakeRequest(node_names[0], 'null')] - for n in node_names[1:]: - requests.append(MakeRequest(n, node_names[0])) - return TestDependencyGraph(requests) - - def test_NodeMerge(self): - g1 = TestDependencyGraph([ - MakeRequest(0, 'null'), - MakeRequest(1, 0), - MakeRequest(2, 0), - MakeRequest(3, 1)]) - g2 = TestDependencyGraph([ - MakeRequest(0, 'null'), - MakeRequest(1, 0), - MakeRequest(2, 0), - MakeRequest(4, 2)]) - sack = resource_sack.GraphSack() - sack.ConsumeGraph(g1) - sack.ConsumeGraph(g2) - self.assertEqual(5, len(sack.bags)) - for bag in sack.bags: - if bag.label not in ('3/', '4/'): - self.assertEqual(2, bag.num_nodes) - else: - self.assertEqual(1, bag.num_nodes) - - def test_MultiParents(self): - g1 = TestDependencyGraph([ - MakeRequest(0, 'null'), - MakeRequest(2, 0)]) - g2 = TestDependencyGraph([ - MakeRequest(1, 'null'), - MakeRequest(2, 1)]) - sack = resource_sack.GraphSack() - sack.ConsumeGraph(g1) - sack.ConsumeGraph(g2) - self.assertEqual(3, len(sack.bags)) - labels = {bag.label: bag for bag in sack.bags} - def Predecessors(label): - bag = labels['%s/' % label] - return [e.from_node - for e in bag._sack._graph.InEdges(bag)] - self.assertEqual( - set(['0/', '1/']), - set([bag.label for bag in Predecessors(2)])) - self.assertFalse(Predecessors(0)) - self.assertFalse(Predecessors(1)) - - def test_Shortname(self): - root = MakeRequest(0, 'null') - shortname = MakeRequest(1, 0) - shortname.url = 'data:fake/content;' + 'lotsand' * 50 + 'lotsofdata' - g1 = TestDependencyGraph([root, shortname]) - sack = resource_sack.GraphSack() - sack.ConsumeGraph(g1) - self.assertEqual(set(['0/', 'data:fake/content']), - set([bag.label for bag in sack.bags])) - - def test_Core(self): - # We will use a core threshold of 0.5 to make it easier to define - # graphs. Resources 0 and 1 are core and others are not. We check full names - # and node counts as we output that for core set analysis. In subsequent - # tests we just check labels to make the tests easier to read. - graphs = [self.SimpleGraph([0, 1, 2]), - self.SimpleGraph([0, 1, 3]), - self.SimpleGraph([0, 1, 4]), - self.SimpleGraph([0, 5])] - sack = resource_sack.GraphSack() - sack.CORE_THRESHOLD = 0.5 - for g in graphs: - sack.ConsumeGraph(g) - self.assertEqual(set([('http://0', 4), ('http://1', 3)]), - set((b.name, b.num_nodes) for b in sack.CoreSet())) - - def test_IntersectingCore(self): - # Graph set A has core set {0, 1} and B {0, 2} so the final core set should - # be {0}. Set C makes sure we restrict core computation to tags A and B. - set_A = [self.SimpleGraph([0, 1, 2]), - self.SimpleGraph([0, 1, 3])] - set_B = [self.SimpleGraph([0, 2, 3]), - self.SimpleGraph([0, 2, 1])] - set_C = [self.SimpleGraph([2 * i + 4, 2 * i + 5]) for i in xrange(5)] - sack = resource_sack.GraphSack() - sack.CORE_THRESHOLD = 0.5 - for g in set_A + set_B + set_C: - sack.ConsumeGraph(g) - self.assertEqual(set(), sack.CoreSet()) - self.assertEqual(set(['0/', '1/']), - set(b.label for b in sack.CoreSet(set_A))) - self.assertEqual(set(['0/', '2/']), - set(b.label for b in sack.CoreSet(set_B))) - self.assertEqual(set(), sack.CoreSet(set_C)) - self.assertEqual(set(['0/']), - set(b.label for b in sack.CoreSet(set_A, set_B))) - self.assertEqual(set(), sack.CoreSet(set_A, set_B, set_C)) - - def test_Simililarity(self): - self.assertAlmostEqual( - 0.5, - resource_sack.GraphSack.CoreSimilarity( - set([1, 2, 3]), set([1, 3, 4]))) - self.assertEqual( - 0, resource_sack.GraphSack.CoreSimilarity(set(), set())) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/run_tests b/tools/android/loading/run_tests deleted file mode 100755 index 1f04f05..0000000 --- a/tools/android/loading/run_tests +++ /dev/null
@@ -1,32 +0,0 @@ -#!/usr/bin/env python -# Copyright 2016 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. - -import logging -import os -import sys -import unittest - - -if __name__ == '__main__': - logging.basicConfig( - level=logging.DEBUG if '-v' in sys.argv else logging.WARNING, - format='%(levelname)5s %(filename)15s(%(lineno)3d): %(message)s') - - suite = unittest.TestSuite() - loader = unittest.TestLoader() - root_dir = os.path.dirname(os.path.realpath(__file__)) - if len(sys.argv) < 2: - cases = loader.discover(start_dir=root_dir, pattern='*_unittest.py') - else: - cases = [] - for module in sys.argv[1:]: - pattern = '{}_unittest.py'.format(module) - cases.extend(loader.discover(start_dir=root_dir, pattern=pattern)) - suite.addTests(cases) - res = unittest.TextTestRunner(verbosity=2).run(suite) - if res.wasSuccessful(): - sys.exit(0) - else: - sys.exit(1)
diff --git a/tools/android/loading/sandwich.py b/tools/android/loading/sandwich.py deleted file mode 100755 index ffd7b00..0000000 --- a/tools/android/loading/sandwich.py +++ /dev/null
@@ -1,300 +0,0 @@ -#! /usr/bin/env python -# Copyright 2016 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. - -"""Instructs Chrome to load series of web pages and reports results. - -When running Chrome is sandwiched between preprocessed disk caches and -WepPageReplay serving all connections. -""" - -import argparse -import csv -import json -import logging -import os -import re -import sys -from urlparse import urlparse -import yaml - -_SRC_DIR = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..', '..', '..')) - -sys.path.append(os.path.join(_SRC_DIR, 'third_party', 'catapult', 'devil')) -from devil.android import device_utils - -sys.path.append(os.path.join(_SRC_DIR, 'build', 'android')) -from pylib import constants -import devil_chromium - -import csv_util -import device_setup -import options -import sandwich_prefetch -import sandwich_swr -import sandwich_utils -import task_manager - - -# Use options layer to access constants. -OPTIONS = options.OPTIONS - -_SPEED_INDEX_MEASUREMENT = 'speed-index' -_MEMORY_MEASUREMENT = 'memory' -_TTFMP_MEASUREMENT = 'ttfmp' -_CORPUS_DIR = 'sandwich_corpuses' -_SANDWICH_SETUP_FILENAME = 'sandwich_setup.yaml' - -_MAIN_TRANSFORMER_LIST_NAME = 'no-network-emulation' - - -def ReadUrlsFromCorpus(corpus_path): - """Retrieves the list of URLs associated with the corpus name.""" - try: - # Attempt to read by regular file name. - json_file_name = corpus_path - with open(json_file_name) as f: - json_data = json.load(f) - except IOError: - # Extra sugar: attempt to load from _CORPUS_DIR. - json_file_name = os.path.join( - os.path.dirname(__file__), _CORPUS_DIR, corpus_path) - with open(json_file_name) as f: - json_data = json.load(f) - - key = 'urls' - if json_data and key in json_data: - url_list = json_data[key] - if isinstance(url_list, list) and len(url_list) > 0: - return [str(u) for u in url_list] - raise Exception( - 'File {} does not define a list named "urls"'.format(json_file_name)) - - -def _GenerateUrlDirectoryMap(urls): - domain_times_encountered_per_domain = {} - url_directories = {} - for url in urls: - domain = '.'.join(urlparse(url).netloc.split('.')[-2:]) - domain_times_encountered = domain_times_encountered_per_domain.get( - domain, 0) - output_subdirectory = '{}.{}'.format(domain, domain_times_encountered) - domain_times_encountered_per_domain[domain] = domain_times_encountered + 1 - url_directories[output_subdirectory] = url - return url_directories - - -def _ArgumentParser(): - """Build a command line argument's parser.""" - # Command line parser when dealing with _SetupBenchmarkMain. - sandwich_setup_parser = argparse.ArgumentParser(add_help=False) - sandwich_setup_parser.add_argument('--android', default=None, type=str, - dest='android_device_serial', help='Android device\'s serial to use.') - sandwich_setup_parser.add_argument('-c', '--corpus', required=True, - help='Path to a JSON file with a corpus such as in %s/.' % _CORPUS_DIR) - sandwich_setup_parser.add_argument('-m', '--measure', default=[], nargs='+', - choices=[_SPEED_INDEX_MEASUREMENT, - _MEMORY_MEASUREMENT, - _TTFMP_MEASUREMENT], - dest='optional_measures', help='Enable optional measurements.') - sandwich_setup_parser.add_argument('-o', '--output', type=str, required=True, - help='Path of the output directory to setup.') - sandwich_setup_parser.add_argument('-r', '--url-repeat', default=1, type=int, - help='How many times to repeat the urls.') - - # Plumbing parser to configure OPTIONS. - plumbing_parser = OPTIONS.GetParentParser('plumbing options') - - # Main parser - parser = argparse.ArgumentParser(parents=[plumbing_parser], - fromfile_prefix_chars=task_manager.FROMFILE_PREFIX_CHARS) - subparsers = parser.add_subparsers(dest='subcommand', help='subcommand line') - - # Setup NoState-Prefetch benchmarks subcommand. - subparsers.add_parser('setup-prefetch', parents=[sandwich_setup_parser], - help='Setup all NoState-Prefetch benchmarks.') - - # Setup Stale-While-Revalidate benchmarks subcommand. - swr_setup_parser = subparsers.add_parser('setup-swr', - parents=[sandwich_setup_parser], - help='Setup all Stale-While-Revalidate benchmarks.') - swr_setup_parser.add_argument('-d', '--domains-csv', - type=argparse.FileType('r'), required=True, - help='Path of the CSV containing the pattern of domains in a ' - '`domain-patterns` column and a `usage` column in percent in how ' - 'likely they are in a page load.') - - # Run benchmarks subcommand (used in _RunBenchmarkMain). - subparsers.add_parser('run', parents=[task_manager.CommandLineParser()], - help='Run benchmarks steps using the task manager infrastructure.') - - # Collect subcommand. - collect_csv_parser = subparsers.add_parser('collect-csv', - help='Collects all CSVs from Sandwich output directory into a single ' - 'CSV.') - collect_csv_parser.add_argument('output_dir', type=str, - help='Path to the run output directory.') - collect_csv_parser.add_argument('output_csv', type=argparse.FileType('w'), - help='Path to the output CSV.') - - return parser - - -def _SetupNoStatePrefetchBenchmark(args): - del args # unused. - return { - 'network_conditions': ['Regular4G', 'Regular3G', 'Regular2G'], - 'subresource_discoverers': [ - e for e in sandwich_prefetch.SUBRESOURCE_DISCOVERERS - if e != sandwich_prefetch.Discoverer.FullCache] - } - - -def _GenerateNoStatePrefetchBenchmarkTasks( - common_builder, main_transformer, benchmark_setup): - builder = sandwich_prefetch.PrefetchBenchmarkBuilder(common_builder) - builder.PopulateLoadBenchmark(sandwich_prefetch.Discoverer.EmptyCache, - _MAIN_TRANSFORMER_LIST_NAME, - transformer_list=[main_transformer]) - builder.PopulateLoadBenchmark(sandwich_prefetch.Discoverer.FullCache, - _MAIN_TRANSFORMER_LIST_NAME, - transformer_list=[main_transformer]) - for network_condition in benchmark_setup['network_conditions']: - transformer_list_name = network_condition.lower() - network_transformer = \ - sandwich_utils.NetworkSimulationTransformer(network_condition) - transformer_list = [main_transformer, network_transformer] - for subresource_discoverer in benchmark_setup['subresource_discoverers']: - builder.PopulateLoadBenchmark( - subresource_discoverer, transformer_list_name, transformer_list) - - -def _SetupStaleWhileRevalidateBenchmark(args): - domain_regexes = [] - for row in csv.DictReader(args.domains_csv): - domain_patterns = json.loads('[{}]'.format(row['domain-patterns'])) - for domain_pattern in domain_patterns: - domain_pattern_escaped = r'(\.|^){}$'.format(re.escape(domain_pattern)) - domain_regexes.append({ - 'usage': float(row['usage']), - 'domain_regex': domain_pattern_escaped.replace(r'\?', r'\w*')}) - return { - 'domain_regexes': domain_regexes, - 'network_conditions': ['Regular3G', 'Regular2G'], - 'usage_thresholds': [1, 3, 5, 10] - } - - -def _GenerateStaleWhileRevalidateBenchmarkTasks( - common_builder, main_transformer, benchmark_setup): - # Compile domain regexes. - domain_regexes = [] - for e in benchmark_setup['domain_regexes']: - domain_regexes.append({ - 'usage': e['usage'], - 'domain_regex': re.compile(e['domain_regex'])}) - - # Build tasks. - builder = sandwich_swr.StaleWhileRevalidateBenchmarkBuilder(common_builder) - for network_condition in benchmark_setup['network_conditions']: - transformer_list_name = network_condition.lower() - network_transformer = \ - sandwich_utils.NetworkSimulationTransformer(network_condition) - transformer_list = [main_transformer, network_transformer] - builder.PopulateBenchmark( - 'no-swr', [], transformer_list_name, transformer_list) - for usage_threshold in benchmark_setup['usage_thresholds']: - benchmark_name = 'threshold{}'.format(usage_threshold) - selected_domain_regexes = [e['domain_regex'] for e in domain_regexes - if e['usage'] > usage_threshold] - builder.PopulateBenchmark( - benchmark_name, selected_domain_regexes, - transformer_list_name, transformer_list) - - -_TASK_GENERATORS = { - 'prefetch': _GenerateNoStatePrefetchBenchmarkTasks, - 'swr': _GenerateStaleWhileRevalidateBenchmarkTasks -} - - -def _SetupBenchmarkMain(args, benchmark_type, benchmark_specific_handler): - assert benchmark_type in _TASK_GENERATORS - urls = ReadUrlsFromCorpus(args.corpus) - setup = { - 'benchmark_type': benchmark_type, - 'benchmark_setup': benchmark_specific_handler(args), - 'sandwich_runner': { - 'record_video': _SPEED_INDEX_MEASUREMENT in args.optional_measures, - 'record_memory_dumps': _MEMORY_MEASUREMENT in args.optional_measures, - 'record_first_meaningful_paint': ( - _TTFMP_MEASUREMENT in args.optional_measures), - 'repeat': args.url_repeat, - 'android_device_serial': args.android_device_serial - }, - 'urls': _GenerateUrlDirectoryMap(urls) - } - if not os.path.isdir(args.output): - os.makedirs(args.output) - setup_path = os.path.join(args.output, _SANDWICH_SETUP_FILENAME) - with open(setup_path, 'w') as file_output: - yaml.dump(setup, file_output, default_flow_style=False) - - -def _RunBenchmarkMain(args): - setup_path = os.path.join(args.output, _SANDWICH_SETUP_FILENAME) - with open(setup_path) as file_input: - setup = yaml.load(file_input) - android_device = None - if setup['sandwich_runner']['android_device_serial']: - android_device = device_setup.GetDeviceFromSerial( - setup['sandwich_runner']['android_device_serial']) - task_generator = _TASK_GENERATORS[setup['benchmark_type']] - - def MainTransformer(runner): - runner.record_video = setup['sandwich_runner']['record_video'] - runner.record_memory_dumps = setup['sandwich_runner']['record_memory_dumps'] - runner.record_first_meaningful_paint = ( - setup['sandwich_runner']['record_first_meaningful_paint']) - runner.repeat = setup['sandwich_runner']['repeat'] - - default_final_tasks = [] - for output_subdirectory, url in setup['urls'].iteritems(): - common_builder = sandwich_utils.SandwichCommonBuilder( - android_device=android_device, - url=url, - output_directory=args.output, - output_subdirectory=output_subdirectory) - common_builder.PopulateWprRecordingTask() - task_generator(common_builder, MainTransformer, setup['benchmark_setup']) - default_final_tasks.extend(common_builder.default_final_tasks) - return task_manager.ExecuteWithCommandLine(args, default_final_tasks) - - -def main(command_line_args): - logging.basicConfig(level=logging.INFO) - devil_chromium.Initialize() - - args = _ArgumentParser().parse_args(command_line_args) - OPTIONS.SetParsedArgs(args) - - if args.subcommand == 'setup-prefetch': - return _SetupBenchmarkMain( - args, 'prefetch', _SetupNoStatePrefetchBenchmark) - if args.subcommand == 'setup-swr': - return _SetupBenchmarkMain( - args, 'swr', _SetupStaleWhileRevalidateBenchmark) - if args.subcommand == 'run': - return _RunBenchmarkMain(args) - if args.subcommand == 'collect-csv': - with args.output_csv as output_file: - if not csv_util.CollectCSVsFromDirectory(args.output_dir, output_file): - return 1 - return 0 - assert False - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:]))
diff --git a/tools/android/loading/sandwich_corpuses/mobile.json b/tools/android/loading/sandwich_corpuses/mobile.json deleted file mode 100644 index d6ad19c..0000000 --- a/tools/android/loading/sandwich_corpuses/mobile.json +++ /dev/null
@@ -1,9 +0,0 @@ -{ - "urls": [ - "http://www.bbc.com/", - "http://cnn.com", - "https://en.m.wikipedia.org/wiki/Main_Page", - "https://en.m.wikipedia.org/wiki/Science", - "https://en.m.wikipedia.org/wiki/Wassily_Kandinsky" - ] -}
diff --git a/tools/android/loading/sandwich_metrics.py b/tools/android/loading/sandwich_metrics.py deleted file mode 100644 index bceb690..0000000 --- a/tools/android/loading/sandwich_metrics.py +++ /dev/null
@@ -1,345 +0,0 @@ -# Copyright 2016 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. - -"""Pull a sandwich run's output directory's metrics from traces into a CSV. - -python pull_sandwich_metrics.py -h -""" - -import collections -import json -import logging -import os -import shutil -import subprocess -import sys -import tempfile - -_SRC_DIR = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..', '..', '..')) - -sys.path.append(os.path.join(_SRC_DIR, 'tools', 'perf')) -from core import path_util -sys.path.append(path_util.GetTelemetryDir()) - -from telemetry.internal.image_processing import video -from telemetry.util import image_util -from telemetry.util import rgba_color - -import common_util -import loading_trace as loading_trace_module -import sandwich_runner -import tracing_track - - -COMMON_CSV_COLUMN_NAMES = [ - 'chromium_commit', - 'platform', - 'first_layout', - 'first_contentful_paint', - 'first_meaningful_paint', - 'total_load', - 'js_onload_event', - 'browser_malloc_avg', - 'browser_malloc_max', - 'speed_index', - 'net_emul.name', # Should be in emulation.NETWORK_CONDITIONS.keys() - 'net_emul.download', - 'net_emul.upload', - 'net_emul.latency'] - -_UNAVAILABLE_CSV_VALUE = 'unavailable' - -_FAILED_CSV_VALUE = 'failed' - -_TRACKED_EVENT_NAMES = set([ - 'requestStart', - 'loadEventStart', - 'loadEventEnd', - 'firstContentfulPaint', - 'firstLayout']) - -# Points of a completeness record. -# -# Members: -# |time| is in milliseconds, -# |frame_completeness| value representing how complete the frame is at a given -# |time|. Caution: this completeness might be negative. -CompletenessPoint = collections.namedtuple('CompletenessPoint', - ('time', 'frame_completeness')) - - -def _GetBrowserPID(track): - """Get the browser PID from a trace. - - Args: - track: The tracing_track.TracingTrack. - - Returns: - The browser's PID as an integer. - """ - for event in track.GetEvents(): - if event.category != '__metadata' or event.name != 'process_name': - continue - if event.args['name'] == 'Browser': - return event.pid - raise ValueError('couldn\'t find browser\'s PID') - - -def _GetBrowserDumpEvents(track): - """Get the browser memory dump events from a tracing track. - - Args: - track: The tracing_track.TracingTrack. - - Returns: - List of memory dump events. - """ - assert sandwich_runner.MEMORY_DUMP_CATEGORY in track.Categories() - browser_pid = _GetBrowserPID(track) - browser_dumps_events = [] - for event in track.GetEvents(): - if event.category != 'disabled-by-default-memory-infra': - continue - if event.type != 'v' or event.name != 'periodic_interval': - continue - # Ignore dump events for processes other than the browser process - if event.pid != browser_pid: - continue - browser_dumps_events.append(event) - if len(browser_dumps_events) == 0: - raise ValueError('No browser dump events found.') - return browser_dumps_events - - -def _GetWebPageTrackedEvents(track): - """Get the web page's tracked events from a tracing track. - - Args: - track: The tracing_track.TracingTrack. - - Returns: - A dict mapping event.name -> tracing_track.Event for each first occurrence - of a tracked event. - """ - main_frame_id = None - tracked_events = {} - sorted_events = sorted(track.GetEvents(), - key=lambda event: event.start_msec) - for event in sorted_events: - if event.category != 'blink.user_timing': - continue - event_name = event.name - - # Find the id of the main frame. Skip all events until it is found. - if not main_frame_id: - # Tracing (in Sandwich) is started after about:blank is fully loaded, - # hence the first navigationStart in the trace registers the correct frame - # id. - if event_name == 'navigationStart': - logging.info(' Found navigationStart at: %f', event.start_msec) - main_frame_id = event.args['frame'] - continue - - # Ignore events with frame id attached, but not being the main frame. - if 'frame' in event.args and event.args['frame'] != main_frame_id: - continue - - # Capture trace events by the first time of their appearance. Note: some - # important events (like requestStart) do not have a frame id attached. - if event_name in _TRACKED_EVENT_NAMES and event_name not in tracked_events: - tracked_events[event_name] = event - logging.info(' Event %s first appears at: %f', event_name, - event.start_msec) - return tracked_events - - -def _ExtractDefaultMetrics(loading_trace): - """Extracts all the default metrics from a given trace. - - Args: - loading_trace: loading_trace.LoadingTrace. - - Returns: - Dictionary with all trace extracted fields set. - """ - END_REQUEST_EVENTS = [ - ('first_layout', 'requestStart', 'firstLayout'), - ('first_contentful_paint', 'requestStart', 'firstContentfulPaint'), - ('total_load', 'requestStart', 'loadEventEnd'), - ('js_onload_event', 'loadEventStart', 'loadEventEnd')] - web_page_tracked_events = _GetWebPageTrackedEvents( - loading_trace.tracing_track) - metrics = {} - for metric_name, start_event_name, end_event_name in END_REQUEST_EVENTS: - try: - metrics[metric_name] = ( - web_page_tracked_events[end_event_name].start_msec - - web_page_tracked_events[start_event_name].start_msec) - except KeyError as error: - logging.error('could not extract metric %s: missing trace event: %s' % ( - metric_name, str(error))) - metrics[metric_name] = _FAILED_CSV_VALUE - return metrics - - -def _ExtractTimeToFirstMeaningfulPaint(loading_trace): - """Extracts the time to first meaningful paint from a given trace. - - Args: - loading_trace: loading_trace_module.LoadingTrace. - - Returns: - Time to first meaningful paint in milliseconds. - """ - required_categories = set(sandwich_runner.TTFMP_ADDITIONAL_CATEGORIES) - if not required_categories.issubset(loading_trace.tracing_track.Categories()): - return _UNAVAILABLE_CSV_VALUE - logging.info(' Extracting first_meaningful_paint') - events = [e.ToJsonDict() for e in loading_trace.tracing_track.GetEvents()] - with common_util.TemporaryDirectory(prefix='sandwich_tmp_') as tmp_dir: - chrome_trace_path = os.path.join(tmp_dir, 'chrome_trace.json') - with open(chrome_trace_path, 'w') as output_file: - json.dump({'traceEvents': events, 'metadata': {}}, output_file) - catapult_run_metric_bin_path = os.path.join( - _SRC_DIR, 'third_party', 'catapult', 'tracing', 'bin', 'run_metric') - output = subprocess.check_output( - [catapult_run_metric_bin_path, 'firstPaintMetric', chrome_trace_path]) - json_output = json.loads(output) - for metric in json_output[chrome_trace_path]['pairs']['values']: - if metric['name'] == 'firstMeaningfulPaint_avg': - return metric['numeric']['value'] - logging.info(' Extracting first_meaningful_paint: failed') - return _FAILED_CSV_VALUE - - -def _ExtractMemoryMetrics(loading_trace): - """Extracts all the memory metrics from a given trace. - - Args: - loading_trace: loading_trace_module.LoadingTrace. - - Returns: - Dictionary with all trace extracted fields set. - """ - if (sandwich_runner.MEMORY_DUMP_CATEGORY not in - loading_trace.tracing_track.Categories()): - return { - 'browser_malloc_avg': _UNAVAILABLE_CSV_VALUE, - 'browser_malloc_max': _UNAVAILABLE_CSV_VALUE - } - browser_dump_events = _GetBrowserDumpEvents(loading_trace.tracing_track) - browser_malloc_sum = 0 - browser_malloc_max = 0 - for dump_event in browser_dump_events: - attr = dump_event.args['dumps']['allocators']['malloc']['attrs']['size'] - assert attr['units'] == 'bytes' - size = int(attr['value'], 16) - browser_malloc_sum += size - browser_malloc_max = max(browser_malloc_max, size) - return { - 'browser_malloc_avg': browser_malloc_sum / float(len(browser_dump_events)), - 'browser_malloc_max': browser_malloc_max - } - - -def _ExtractCompletenessRecordFromVideo(video_path): - """Extracts the completeness record from a video. - - The video must start with a filled rectangle of orange (RGB: 222, 100, 13), to - give the view-port size/location from where to compute the completeness. - - Args: - video_path: Path of the video to extract the completeness list from. - - Returns: - list(CompletenessPoint) - """ - video_file = tempfile.NamedTemporaryFile() - shutil.copy(video_path, video_file.name) - video_capture = video.Video(video_file) - - histograms = [ - (time, image_util.GetColorHistogram( - image, ignore_color=rgba_color.WHITE, tolerance=8)) - for time, image in video_capture.GetVideoFrameIter() - ] - - start_histogram = histograms[1][1] - final_histogram = histograms[-1][1] - total_distance = start_histogram.Distance(final_histogram) - - def FrameProgress(histogram): - if total_distance == 0: - if histogram.Distance(final_histogram) == 0: - return 1.0 - else: - return 0.0 - return 1 - histogram.Distance(final_histogram) / total_distance - - return [(time, FrameProgress(hist)) for time, hist in histograms] - - -def _ComputeSpeedIndex(completeness_record): - """Computes the speed-index from a completeness record. - - Args: - completeness_record: list(CompletenessPoint) - - Returns: - Speed-index value. - """ - speed_index = 0.0 - last_time = completeness_record[0][0] - last_completness = completeness_record[0][1] - for time, completeness in completeness_record: - if time < last_time: - raise ValueError('Completeness record must be sorted by timestamps.') - elapsed = time - last_time - speed_index += elapsed * (1.0 - last_completness) - last_time = time - last_completness = completeness - return speed_index - - -def ExtractCommonMetricsFromRepeatDirectory(repeat_dir, trace): - """Extracts all the metrics from traces and video of a sandwich run repeat - directory. - - Args: - repeat_dir: Path of the repeat directory within a run directory. - trace: preloaded LoadingTrace in |repeat_dir| - - Contract: - trace == LoadingTrace.FromJsonFile( - os.path.join(repeat_dir, sandwich_runner.TRACE_FILENAME)) - - Returns: - Dictionary of extracted metrics. - """ - run_metrics = { - 'chromium_commit': trace.metadata['chromium_commit'], - 'platform': (trace.metadata['platform']['os'] + '-' + - trace.metadata['platform']['product_model']) - } - run_metrics.update(_ExtractDefaultMetrics(trace)) - run_metrics.update(_ExtractMemoryMetrics(trace)) - run_metrics['first_meaningful_paint'] = _ExtractTimeToFirstMeaningfulPaint( - trace) - video_path = os.path.join(repeat_dir, sandwich_runner.VIDEO_FILENAME) - if os.path.isfile(video_path): - logging.info('processing speed-index video \'%s\'' % video_path) - try: - completeness_record = _ExtractCompletenessRecordFromVideo(video_path) - run_metrics['speed_index'] = _ComputeSpeedIndex(completeness_record) - except video.BoundingBoxNotFoundException: - # Sometimes the bounding box for the web content area is not present. Skip - # calculating Speed Index. - run_metrics['speed_index'] = _FAILED_CSV_VALUE - else: - run_metrics['speed_index'] = _UNAVAILABLE_CSV_VALUE - for key, value in trace.metadata['network_emulation'].iteritems(): - run_metrics['net_emul.' + key] = value - assert set(run_metrics.keys()) == set(COMMON_CSV_COLUMN_NAMES) - return run_metrics
diff --git a/tools/android/loading/sandwich_metrics_unittest.py b/tools/android/loading/sandwich_metrics_unittest.py deleted file mode 100644 index 19520b5..0000000 --- a/tools/android/loading/sandwich_metrics_unittest.py +++ /dev/null
@@ -1,258 +0,0 @@ -# Copyright 2016 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. - -import copy -import json -import os -import shutil -import subprocess -import tempfile -import unittest - -import loading_trace -import page_track -import sandwich_metrics as puller -import sandwich_runner -import request_track -import tracing_track - - -_BLINK_CAT = 'blink.user_timing' -_MEM_CAT = sandwich_runner.MEMORY_DUMP_CATEGORY -_START = 'requestStart' -_LOADS = 'loadEventStart' -_LOADE = 'loadEventEnd' -_NAVIGATION_START = 'navigationStart' -_PAINT = 'firstContentfulPaint' -_LAYOUT = 'firstLayout' - -_MINIMALIST_TRACE_EVENTS = [ - {'ph': 'R', 'cat': _BLINK_CAT, 'name': _NAVIGATION_START, 'ts': 10000, - 'args': {'frame': '0'}}, - {'ph': 'R', 'cat': _BLINK_CAT, 'name': _START, 'ts': 20000, - 'args': {}}, - {'cat': _MEM_CAT, 'name': 'periodic_interval', 'pid': 1, 'ph': 'v', - 'ts': 1, 'args': {'dumps': {'allocators': {'malloc': {'attrs': {'size':{ - 'units': 'bytes', 'value': '1af2', }}}}}}}, - {'ph': 'R', 'cat': _BLINK_CAT, 'name': _LAYOUT, 'ts': 24000, - 'args': {'frame': '0'}}, - {'ph': 'R', 'cat': _BLINK_CAT, 'name': _PAINT, 'ts': 31000, - 'args': {'frame': '0'}}, - {'ph': 'R', 'cat': _BLINK_CAT, 'name': _LOADS, 'ts': 35000, - 'args': {'frame': '0'}}, - {'ph': 'R', 'cat': _BLINK_CAT, 'name': _LOADE, 'ts': 40000, - 'args': {'frame': '0'}}, - {'cat': _MEM_CAT, 'name': 'periodic_interval', 'pid': 1, 'ph': 'v', - 'ts': 1, 'args': {'dumps': {'allocators': {'malloc': {'attrs': {'size':{ - 'units': 'bytes', 'value': 'd704', }}}}}}}, - {'ph': 'M', 'cat': '__metadata', 'pid': 1, 'name': 'process_name', 'ts': 1, - 'args': {'name': 'Browser'}}] - - -def TracingTrack(events): - return tracing_track.TracingTrack.FromJsonDict({ - 'events': events, - 'categories': (sandwich_runner._TRACING_CATEGORIES + - [sandwich_runner.MEMORY_DUMP_CATEGORY])}) - - -def LoadingTrace(events): - return loading_trace.LoadingTrace('http://a.com/', {}, - page_track.PageTrack(None), - request_track.RequestTrack(None), - TracingTrack(events)) - - -class PageTrackTest(unittest.TestCase): - def testGetBrowserPID(self): - def RunHelper(expected, events): - self.assertEquals(expected, puller._GetBrowserPID(TracingTrack(events))) - - RunHelper(123, [ - {'ph': 'M', 'ts': 0, 'pid': 354, 'cat': 'whatever0'}, - {'ph': 'M', 'ts': 0, 'pid': 354, 'cat': 'whatever1'}, - {'ph': 'M', 'ts': 0, 'pid': 354, 'cat': '__metadata', - 'name': 'thread_name'}, - {'ph': 'M', 'ts': 0, 'pid': 354, 'cat': '__metadata', - 'name': 'process_name', 'args': {'name': 'Renderer'}}, - {'ph': 'M', 'ts': 0, 'pid': 123, 'cat': '__metadata', - 'name': 'process_name', 'args': {'name': 'Browser'}}, - {'ph': 'M', 'ts': 0, 'pid': 354, 'cat': 'whatever0'}]) - - with self.assertRaises(ValueError): - RunHelper(123, [ - {'ph': 'M', 'ts': 0, 'pid': 354, 'cat': 'whatever0'}, - {'ph': 'M', 'ts': 0, 'pid': 354, 'cat': 'whatever1'}]) - - def testGetBrowserDumpEvents(self): - NAME = 'periodic_interval' - - def RunHelper(trace_events, browser_pid): - trace_events = copy.copy(trace_events) - trace_events.append({ - 'pid': browser_pid, - 'cat': '__metadata', - 'name': 'process_name', - 'ph': 'M', - 'ts': 0, - 'args': {'name': 'Browser'}}) - return puller._GetBrowserDumpEvents(TracingTrack(trace_events)) - - TRACE_EVENTS = [ - {'pid': 354, 'ts': 1000, 'cat': _MEM_CAT, 'ph': 'v', 'name': NAME}, - {'pid': 354, 'ts': 2000, 'cat': _MEM_CAT, 'ph': 'V'}, - {'pid': 672, 'ts': 3000, 'cat': _MEM_CAT, 'ph': 'v', 'name': NAME}, - {'pid': 123, 'ts': 4000, 'cat': _MEM_CAT, 'ph': 'v', 'name': 'foo'}, - {'pid': 123, 'ts': 5000, 'cat': _MEM_CAT, 'ph': 'v', 'name': NAME}, - {'pid': 123, 'ts': 6000, 'cat': _MEM_CAT, 'ph': 'V'}, - {'pid': 672, 'ts': 7000, 'cat': _MEM_CAT, 'ph': 'v', 'name': NAME}, - {'pid': 354, 'ts': 8000, 'cat': _MEM_CAT, 'ph': 'v', 'name': 'foo'}, - {'pid': 123, 'ts': 9000, 'cat': 'whatever1', 'ph': 'v', 'name': NAME}, - {'pid': 123, 'ts': 10000, 'cat': _MEM_CAT, 'ph': 'v', 'name': NAME}, - {'pid': 354, 'ts': 11000, 'cat': 'whatever0', 'ph': 'R'}, - {'pid': 672, 'ts': 12000, 'cat': _MEM_CAT, 'ph': 'v', 'name': NAME}] - - bump_events = RunHelper(TRACE_EVENTS, 123) - self.assertEquals(2, len(bump_events)) - self.assertEquals(5, bump_events[0].start_msec) - self.assertEquals(10, bump_events[1].start_msec) - - bump_events = RunHelper(TRACE_EVENTS, 354) - self.assertEquals(1, len(bump_events)) - self.assertEquals(1, bump_events[0].start_msec) - - bump_events = RunHelper(TRACE_EVENTS, 672) - self.assertEquals(3, len(bump_events)) - self.assertEquals(3, bump_events[0].start_msec) - self.assertEquals(7, bump_events[1].start_msec) - self.assertEquals(12, bump_events[2].start_msec) - - with self.assertRaises(ValueError): - RunHelper(TRACE_EVENTS, 895) - - def testGetWebPageTrackedEvents(self): - trace_events = puller._GetWebPageTrackedEvents(TracingTrack([ - {'ph': 'R', 'ts': 0000, 'args': {}, 'cat': 'whatever', - 'name': _START}, - {'ph': 'R', 'ts': 1000, 'args': {'frame': '0'}, 'cat': 'whatever', - 'name': _LOADS}, - {'ph': 'R', 'ts': 2000, 'args': {'frame': '0'}, 'cat': 'whatever', - 'name': _LOADE}, - {'ph': 'R', 'ts': 3000, 'args': {}, 'cat': _BLINK_CAT, - 'name': _START}, - {'ph': 'R', 'ts': 4000, 'args': {'frame': '0'}, 'cat': _BLINK_CAT, - 'name': _LOADS}, - {'ph': 'R', 'ts': 5000, 'args': {'frame': '0'}, 'cat': _BLINK_CAT, - 'name': _LOADE}, - {'ph': 'R', 'ts': 7000, 'args': {}, 'cat': _BLINK_CAT, - 'name': _START}, - {'ph': 'R', 'ts': 8000, 'args': {'frame': '0'}, 'cat': _BLINK_CAT, - 'name': _LOADS}, - {'ph': 'R', 'ts': 9000, 'args': {'frame': '0'}, 'cat': _BLINK_CAT, - 'name': _LOADE}, - {'ph': 'R', 'ts': 11000, 'args': {'frame': '0'}, 'cat': 'whatever', - 'name': _START}, - {'ph': 'R', 'ts': 12000, 'args': {'frame': '0'}, 'cat': 'whatever', - 'name': _LOADS}, - {'ph': 'R', 'ts': 13000, 'args': {'frame': '0'}, 'cat': 'whatever', - 'name': _LOADE}, - {'ph': 'R', 'ts': 14000, 'args': {}, 'cat': _BLINK_CAT, - 'name': _START}, - {'ph': 'R', 'ts': 10000, 'args': {'frame': '0'}, 'cat': _BLINK_CAT, - 'name': _NAVIGATION_START}, # Event out of |start_msec| order. - {'ph': 'R', 'ts': 6000, 'args': {'frame': '0'}, 'cat': 'whatever', - 'name': _NAVIGATION_START}, - {'ph': 'R', 'ts': 15000, 'args': {}, 'cat': _BLINK_CAT, - 'name': _START}, - {'ph': 'R', 'ts': 16000, 'args': {'frame': '1'}, 'cat': _BLINK_CAT, - 'name': _LOADS}, - {'ph': 'R', 'ts': 17000, 'args': {'frame': '0'}, 'cat': _BLINK_CAT, - 'name': _LOADS}, - {'ph': 'R', 'ts': 18000, 'args': {'frame': '1'}, 'cat': _BLINK_CAT, - 'name': _LOADE}, - {'ph': 'R', 'ts': 19000, 'args': {'frame': '0'}, 'cat': _BLINK_CAT, - 'name': _LOADE}, - {'ph': 'R', 'ts': 20000, 'args': {}, 'cat': 'whatever', - 'name': _START}, - {'ph': 'R', 'ts': 21000, 'args': {'frame': '0'}, 'cat': 'whatever', - 'name': _LOADS}, - {'ph': 'R', 'ts': 22000, 'args': {'frame': '0'}, 'cat': 'whatever', - 'name': _LOADE}, - {'ph': 'R', 'ts': 23000, 'args': {}, 'cat': _BLINK_CAT, - 'name': _START}, - {'ph': 'R', 'ts': 24000, 'args': {'frame': '0'}, 'cat': _BLINK_CAT, - 'name': _LOADS}, - {'ph': 'R', 'ts': 25000, 'args': {'frame': '0'}, 'cat': _BLINK_CAT, - 'name': _LOADE}])) - - self.assertEquals(3, len(trace_events)) - self.assertEquals(14, trace_events['requestStart'].start_msec) - self.assertEquals(17, trace_events['loadEventStart'].start_msec) - self.assertEquals(19, trace_events['loadEventEnd'].start_msec) - - def testExtractDefaultMetrics(self): - metrics = puller._ExtractDefaultMetrics(LoadingTrace( - _MINIMALIST_TRACE_EVENTS)) - self.assertEquals(4, len(metrics)) - self.assertEquals(20, metrics['total_load']) - self.assertEquals(5, metrics['js_onload_event']) - self.assertEquals(4, metrics['first_layout']) - self.assertEquals(11, metrics['first_contentful_paint']) - - def testExtractDefaultMetricsBestEffort(self): - metrics = puller._ExtractDefaultMetrics(LoadingTrace([ - {'ph': 'R', 'ts': 10000, 'args': {'frame': '0'}, 'cat': _BLINK_CAT, - 'name': _NAVIGATION_START}, - {'ph': 'R', 'ts': 11000, 'args': {'frame': '0'}, 'cat': 'whatever', - 'name': _START}])) - self.assertEquals(4, len(metrics)) - self.assertEquals(puller._FAILED_CSV_VALUE, metrics['total_load']) - self.assertEquals(puller._FAILED_CSV_VALUE, metrics['js_onload_event']) - self.assertEquals(puller._FAILED_CSV_VALUE, metrics['first_layout']) - self.assertEquals(puller._FAILED_CSV_VALUE, - metrics['first_contentful_paint']) - - def testExtractMemoryMetrics(self): - metrics = puller._ExtractMemoryMetrics(LoadingTrace( - _MINIMALIST_TRACE_EVENTS)) - self.assertEquals(2, len(metrics)) - self.assertEquals(30971, metrics['browser_malloc_avg']) - self.assertEquals(55044, metrics['browser_malloc_max']) - - def testComputeSpeedIndex(self): - def point(time, frame_completeness): - return puller.CompletenessPoint(time=time, - frame_completeness=frame_completeness) - completness_record = [ - point(0, 0.0), - point(120, 0.4), - point(190, 0.75), - point(280, 1.0), - point(400, 1.0), - ] - self.assertEqual(120 + 70 * 0.6 + 90 * 0.25, - puller._ComputeSpeedIndex(completness_record)) - - completness_record = [ - point(70, 0.0), - point(150, 0.3), - point(210, 0.6), - point(220, 0.9), - point(240, 1.0), - ] - self.assertEqual(80 + 60 * 0.7 + 10 * 0.4 + 20 * 0.1, - puller._ComputeSpeedIndex(completness_record)) - - completness_record = [ - point(90, 0.0), - point(200, 0.6), - point(150, 0.3), - point(230, 1.0), - ] - with self.assertRaises(ValueError): - puller._ComputeSpeedIndex(completness_record) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/sandwich_prefetch.py b/tools/android/loading/sandwich_prefetch.py deleted file mode 100644 index 0f53263..0000000 --- a/tools/android/loading/sandwich_prefetch.py +++ /dev/null
@@ -1,678 +0,0 @@ -# Copyright 2016 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. - -""" -Implements a task builder for benchmarking effects of NoState Prefetch. -Noticeable steps of the task pipeline: - * Save a WPR archive - * Process the WPR archive to make all resources cacheable - * Process cache archive to patch response headers back to their original - values. - * Find out which resources are discoverable by NoState Prefetch - (HTMLPreloadScanner) - * Load pages with empty/full/prefetched cache - * Extract most important metrics to a CSV -""" - -import csv -import logging -import json -import os -import re -import shutil -import urlparse - -import chrome_cache -import common_util -import loading_trace -from prefetch_view import PrefetchSimulationView -from request_dependencies_lens import RequestDependencyLens -import sandwich_metrics -import sandwich_runner -import sandwich_utils -import task_manager -import wpr_backend - - -class Discoverer(object): - # Do not prefetch anything. - EmptyCache = 'empty-cache' - - # Prefetches everything to load fully from cache (impossible in practice). - FullCache = 'full-cache' - - # Prefetches the first resource following the redirection chain. - MainDocument = 'main-document' - - # All resources which are fetched from the main document and their - # redirections. - Parser = 'parser' - - # Simulation of HTMLPreloadScanner on the main document and their - # redirections and subsets: - # Store: only resources that don't have Cache-Control: No-Store. - HTMLPreloadScanner = 'html-scanner' - HTMLPreloadScannerStore = 'html-scanner-store' - - -# List of all available sub-resource discoverers. -SUBRESOURCE_DISCOVERERS = set([ - Discoverer.EmptyCache, - Discoverer.FullCache, - Discoverer.MainDocument, - Discoverer.Parser, - Discoverer.HTMLPreloadScanner, - Discoverer.HTMLPreloadScannerStore, -]) - - -_UPLOAD_DATA_STREAM_REQUESTS_REGEX = re.compile(r'^\d+/(?P<url>.*)$') - - -def _NormalizeUrl(url): - """Returns normalized URL such as removing trailing slashes.""" - parsed_url = list(urlparse.urlparse(url)) - parsed_url[2] = re.sub(r'/{2,}', r'/', parsed_url[2]) - return urlparse.urlunparse(parsed_url) - - -def _PatchCacheArchive(cache_archive_path, loading_trace_path, - cache_archive_dest_path): - """Patch the cache archive. - - Note: This method update the raw response headers of cache entries' to store - the ones such as Set-Cookie that were pruned by the - net::HttpCacheTransaction, and remove the stream index 2 holding resource's - compile meta data. - - Args: - cache_archive_path: Input archive's path to patch. - loading_trace_path: Path of the loading trace that have recorded the cache - archive <cache_archive_path>. - cache_archive_dest_path: Archive destination's path. - """ - trace = loading_trace.LoadingTrace.FromJsonFile(loading_trace_path) - with common_util.TemporaryDirectory(prefix='sandwich_tmp') as tmp_path: - cache_path = os.path.join(tmp_path, 'cache') - chrome_cache.UnzipDirectoryContent(cache_archive_path, cache_path) - cache_backend = chrome_cache.CacheBackend(cache_path, 'simple') - cache_entries = set(cache_backend.ListKeys()) - logging.info('Original cache size: %d bytes' % cache_backend.GetSize()) - for request in sandwich_utils.FilterOutDataAndIncompleteRequests( - trace.request_track.GetEvents()): - # On requests having an upload data stream such as POST requests, - # net::HttpCache::GenerateCacheKey() prefixes the cache entry's key with - # the upload data stream's session unique identifier. - # - # It is fine to not patch these requests since when reopening Chrome, - # there is no way the entry can be reused since the upload data stream's - # identifier will be different. - # - # The fact that these entries are kept in the cache after closing Chrome - # properly by closing the Chrome tab as the ChromeControler.SetSlowDeath() - # do is known chrome bug (crbug.com/610725). - if request.url not in cache_entries: - continue - # Chrome prunes Set-Cookie from response headers before storing them in - # disk cache. Also, it adds implicit "Vary: cookie" header to all redirect - # response headers. Sandwich manages the cache, but between recording the - # cache and benchmarking the cookie jar is invalidated. This leads to - # invalidation of all cacheable redirects. - raw_headers = request.GetRawResponseHeaders() - cache_backend.UpdateRawResponseHeaders(request.url, raw_headers) - # NoState-Prefetch would only fetch the resources, but not parse them. - cache_backend.DeleteStreamForKey(request.url, 2) - chrome_cache.ZipDirectoryContent(cache_path, cache_archive_dest_path) - logging.info('Patched cache size: %d bytes' % cache_backend.GetSize()) - - -def _DiscoverRequests(dependencies_lens, subresource_discoverer): - trace = dependencies_lens.loading_trace - first_resource_request = trace.request_track.GetFirstResourceRequest() - - if subresource_discoverer == Discoverer.EmptyCache: - requests = [] - elif subresource_discoverer == Discoverer.FullCache: - requests = dependencies_lens.loading_trace.request_track.GetEvents() - elif subresource_discoverer == Discoverer.MainDocument: - requests = [dependencies_lens.GetRedirectChain(first_resource_request)[-1]] - elif subresource_discoverer == Discoverer.Parser: - requests = PrefetchSimulationView.ParserDiscoverableRequests( - first_resource_request, dependencies_lens) - elif subresource_discoverer == Discoverer.HTMLPreloadScanner: - requests = PrefetchSimulationView.PreloadedRequests( - first_resource_request, dependencies_lens, trace) - else: - assert False - logging.info('number of requests discovered by %s: %d', - subresource_discoverer, len(requests)) - return requests - - -def _PruneOutOriginalNoStoreRequests(original_headers_path, requests): - with open(original_headers_path) as file_input: - original_headers = json.load(file_input) - pruned_requests = set() - for request in requests: - url = _NormalizeUrl(request.url) - if url not in original_headers: - # TODO(gabadie): Investigate why these requests were not in WPR. - assert request.failed - logging.warning( - 'could not find original headers for: %s (failure: %s)', - url, request.error_text) - continue - request_original_headers = original_headers[url] - if ('cache-control' in request_original_headers and - 'no-store' in request_original_headers['cache-control'].lower()): - pruned_requests.add(request) - return [r for r in requests if r not in pruned_requests] - - -def _ExtractDiscoverableUrls( - original_headers_path, loading_trace_path, subresource_discoverer): - """Extracts discoverable resource urls from a loading trace according to a - sub-resource discoverer. - - Args: - original_headers_path: Path of JSON containing the original headers. - loading_trace_path: Path of the loading trace recorded at original cache - creation. - subresource_discoverer: The sub-resources discoverer that should white-list - the resources to keep in cache for the NoState-Prefetch benchmarks. - - Returns: - A set of urls. - """ - assert subresource_discoverer in SUBRESOURCE_DISCOVERERS, \ - 'unknown prefetch simulation {}'.format(subresource_discoverer) - logging.info('loading %s', loading_trace_path) - trace = loading_trace.LoadingTrace.FromJsonFile(loading_trace_path) - dependencies_lens = RequestDependencyLens(trace) - - # Build the list of discovered requests according to the desired simulation. - discovered_requests = [] - if subresource_discoverer == Discoverer.HTMLPreloadScannerStore: - requests = _DiscoverRequests( - dependencies_lens, Discoverer.HTMLPreloadScanner) - discovered_requests = _PruneOutOriginalNoStoreRequests( - original_headers_path, requests) - else: - discovered_requests = _DiscoverRequests( - dependencies_lens, subresource_discoverer) - - whitelisted_urls = set() - for request in sandwich_utils.FilterOutDataAndIncompleteRequests( - discovered_requests): - logging.debug('white-listing %s', request.url) - whitelisted_urls.add(request.url) - logging.info('number of white-listed resources: %d', len(whitelisted_urls)) - return whitelisted_urls - - -def _PrintUrlSetComparison(ref_url_set, url_set, url_set_name): - """Compare URL sets and log the diffs. - - Args: - ref_url_set: Set of reference urls. - url_set: Set of urls to compare to the reference. - url_set_name: The set name for logging purposes. - """ - assert type(ref_url_set) == set - assert type(url_set) == set - if ref_url_set == url_set: - logging.info(' %d %s are matching.' % (len(ref_url_set), url_set_name)) - return - missing_urls = ref_url_set.difference(url_set) - unexpected_urls = url_set.difference(ref_url_set) - logging.error(' %s are not matching (expected %d, had %d)' % \ - (url_set_name, len(ref_url_set), len(url_set))) - logging.error(' List of %d missing resources:' % len(missing_urls)) - for url in sorted(missing_urls): - logging.error('- ' + url) - logging.error(' List of %d unexpected resources:' % len(unexpected_urls)) - for url in sorted(unexpected_urls): - logging.error('+ ' + url) - - -class _RunOutputVerifier(object): - """Object to verify benchmark run from traces and WPR log stored in the - runner output directory. - """ - - def __init__(self, cache_validation_result, benchmark_setup): - """Constructor. - - Args: - cache_validation_result: JSON of the cache validation task. - benchmark_setup: JSON of the benchmark setup. - """ - self._cache_whitelist = set(benchmark_setup['cache_whitelist']) - self._original_requests = set( - cache_validation_result['effective_encoded_data_lengths'].keys()) - self._original_post_requests = set( - cache_validation_result['effective_post_requests']) - self._original_cached_requests = self._original_requests.intersection( - self._cache_whitelist) - self._original_uncached_requests = self._original_requests.difference( - self._cache_whitelist) - self._all_sent_url_requests = set() - - def VerifyTrace(self, trace): - """Verifies a trace with the cache validation result and the benchmark - setup. - """ - effective_requests = sandwich_utils.ListUrlRequests( - trace, sandwich_utils.RequestOutcome.All) - effective_post_requests = sandwich_utils.ListUrlRequests( - trace, sandwich_utils.RequestOutcome.Post) - effective_cached_requests = sandwich_utils.ListUrlRequests( - trace, sandwich_utils.RequestOutcome.ServedFromCache) - effective_uncached_requests = sandwich_utils.ListUrlRequests( - trace, sandwich_utils.RequestOutcome.NotServedFromCache) - - missing_requests = self._original_requests.difference(effective_requests) - unexpected_requests = effective_requests.difference(self._original_requests) - expected_cached_requests = \ - self._original_cached_requests.difference(missing_requests) - expected_uncached_requests = self._original_uncached_requests.union( - unexpected_requests).difference(missing_requests) - - # POST requests are known to be unable to use the cache. - expected_cached_requests.difference_update(effective_post_requests) - expected_uncached_requests.update(effective_post_requests) - - _PrintUrlSetComparison(self._original_requests, effective_requests, - 'All resources') - _PrintUrlSetComparison(set(), effective_post_requests, 'POST resources') - _PrintUrlSetComparison(expected_cached_requests, effective_cached_requests, - 'Cached resources') - _PrintUrlSetComparison(expected_uncached_requests, - effective_uncached_requests, 'Non cached resources') - - self._all_sent_url_requests.update(effective_uncached_requests) - - def VerifyWprLog(self, wpr_log_path): - """Verifies WPR log with previously verified traces.""" - all_wpr_requests = wpr_backend.ExtractRequestsFromLog(wpr_log_path) - all_wpr_urls = set() - unserved_wpr_urls = set() - wpr_command_colliding_urls = set() - - for request in all_wpr_requests: - if request.is_wpr_host: - continue - if urlparse.urlparse(request.url).path.startswith('/web-page-replay'): - wpr_command_colliding_urls.add(request.url) - elif request.is_served is False: - unserved_wpr_urls.add(request.url) - all_wpr_urls.add(request.url) - - _PrintUrlSetComparison(set(), unserved_wpr_urls, - 'Distinct unserved resources from WPR') - _PrintUrlSetComparison(set(), wpr_command_colliding_urls, - 'Distinct resources colliding to WPR commands') - _PrintUrlSetComparison(all_wpr_urls, self._all_sent_url_requests, - 'Distinct resource requests to WPR') - - -def _ValidateCacheArchiveContent(cache_build_trace_path, cache_archive_path): - """Validates a cache archive content. - - Args: - cache_build_trace_path: Path of the generated trace at the cache build time. - cache_archive_path: Cache archive's path to validate. - - Returns: - { - 'effective_encoded_data_lengths': - {URL of all requests: encoded_data_length}, - 'effective_post_requests': [URLs of POST requests], - 'expected_cached_resources': [URLs of resources expected to be cached], - 'successfully_cached': [URLs of cached sub-resources] - } - """ - # TODO(gabadie): What's the best way of propagating errors happening in here? - logging.info('lists cached urls from %s' % cache_archive_path) - with common_util.TemporaryDirectory() as cache_directory: - chrome_cache.UnzipDirectoryContent(cache_archive_path, cache_directory) - cache_keys = set( - chrome_cache.CacheBackend(cache_directory, 'simple').ListKeys()) - trace = loading_trace.LoadingTrace.FromJsonFile(cache_build_trace_path) - effective_requests = sandwich_utils.ListUrlRequests( - trace, sandwich_utils.RequestOutcome.All) - effective_post_requests = sandwich_utils.ListUrlRequests( - trace, sandwich_utils.RequestOutcome.Post) - effective_encoded_data_lengths = {} - for request in sandwich_utils.FilterOutDataAndIncompleteRequests( - trace.request_track.GetEvents()): - if request.from_disk_cache or request.served_from_cache: - # At cache archive creation time, a request might be loaded several times, - # but avoid the request.encoded_data_length == 0 if loaded from cache. - continue - if request.url in effective_encoded_data_lengths: - effective_encoded_data_lengths[request.url] = max( - effective_encoded_data_lengths[request.url], - request.GetResponseTransportLength()) - else: - effective_encoded_data_lengths[request.url] = ( - request.GetResponseTransportLength()) - - upload_data_stream_cache_entry_keys = set() - upload_data_stream_requests = set() - for cache_entry_key in cache_keys: - match = _UPLOAD_DATA_STREAM_REQUESTS_REGEX.match(cache_entry_key) - if not match: - continue - upload_data_stream_cache_entry_keys.add(cache_entry_key) - upload_data_stream_requests.add(match.group('url')) - - expected_cached_requests = effective_requests.difference( - effective_post_requests) - effective_cache_keys = cache_keys.difference( - upload_data_stream_cache_entry_keys) - - _PrintUrlSetComparison(effective_post_requests, upload_data_stream_requests, - 'POST resources') - _PrintUrlSetComparison(expected_cached_requests, effective_cache_keys, - 'Cached resources') - - return { - 'effective_encoded_data_lengths': effective_encoded_data_lengths, - 'effective_post_requests': [url for url in effective_post_requests], - 'expected_cached_resources': [url for url in expected_cached_requests], - 'successfully_cached_resources': [url for url in effective_cache_keys] - } - - -def _ProcessRunOutputDir( - cache_validation_result, benchmark_setup, runner_output_dir): - """Process benchmark's run output directory. - - Args: - cache_validation_result: Same as for _RunOutputVerifier - benchmark_setup: Same as for _RunOutputVerifier - runner_output_dir: Same as for SandwichRunner.output_dir - - Returns: - List of dictionary. - """ - run_metrics_list = [] - run_output_verifier = _RunOutputVerifier( - cache_validation_result, benchmark_setup) - cached_encoded_data_lengths = ( - cache_validation_result['effective_encoded_data_lengths']) - for repeat_id, repeat_dir in sandwich_runner.WalkRepeatedRuns( - runner_output_dir): - trace_path = os.path.join(repeat_dir, sandwich_runner.TRACE_FILENAME) - - logging.info('loading trace: %s', trace_path) - trace = loading_trace.LoadingTrace.FromJsonFile(trace_path) - - logging.info('verifying trace: %s', trace_path) - run_output_verifier.VerifyTrace(trace) - - logging.info('extracting metrics from trace: %s', trace_path) - - # Gather response size per URLs. - response_sizes = {} - for request in sandwich_utils.FilterOutDataAndIncompleteRequests( - trace.request_track.GetEvents()): - # Ignore requests served from the blink's cache. - if request.served_from_cache: - continue - if request.from_disk_cache: - if request.url in cached_encoded_data_lengths: - response_size = cached_encoded_data_lengths[request.url] - else: - # Some fat webpages may overflow the Memory cache, and so some - # requests might be served from disk cache couple of times per page - # load. - logging.warning('Looks like could be served from memory cache: %s', - request.url) - if request.url in response_sizes: - response_size = response_sizes[request.url] - else: - response_size = request.GetResponseTransportLength() - response_sizes[request.url] = response_size - - # Sums the served from cache/network bytes. - served_from_network_bytes = 0 - served_from_cache_bytes = 0 - urls_hitting_network = set() - for request in sandwich_utils.FilterOutDataAndIncompleteRequests( - trace.request_track.GetEvents()): - # Ignore requests served from the blink's cache. - if request.served_from_cache: - continue - urls_hitting_network.add(request.url) - if request.from_disk_cache: - served_from_cache_bytes += response_sizes[request.url] - else: - served_from_network_bytes += response_sizes[request.url] - - # Make sure the served from blink's cache requests have at least one - # corresponding request that was not served from the blink's cache. - for request in sandwich_utils.FilterOutDataAndIncompleteRequests( - trace.request_track.GetEvents()): - assert (request.url in urls_hitting_network or - not request.served_from_cache) - - run_metrics = { - 'url': trace.url, - 'repeat_id': repeat_id, - 'subresource_discoverer': benchmark_setup['subresource_discoverer'], - 'cache_recording.subresource_count': - len(cache_validation_result['effective_encoded_data_lengths']), - 'cache_recording.cached_subresource_count_theoretic': - len(cache_validation_result['successfully_cached_resources']), - 'cache_recording.cached_subresource_count': - len(cache_validation_result['expected_cached_resources']), - 'benchmark.subresource_count': len(sandwich_utils.ListUrlRequests( - trace, sandwich_utils.RequestOutcome.All)), - 'benchmark.served_from_cache_count_theoretic': - len(benchmark_setup['cache_whitelist']), - 'benchmark.served_from_cache_count': len(sandwich_utils.ListUrlRequests( - trace, sandwich_utils.RequestOutcome.ServedFromCache)), - 'benchmark.served_from_network_bytes': served_from_network_bytes, - 'benchmark.served_from_cache_bytes': served_from_cache_bytes - } - run_metrics.update( - sandwich_metrics.ExtractCommonMetricsFromRepeatDirectory( - repeat_dir, trace)) - run_metrics_list.append(run_metrics) - run_metrics_list.sort(key=lambda e: e['repeat_id']) - - wpr_log_path = os.path.join( - runner_output_dir, sandwich_runner.WPR_LOG_FILENAME) - logging.info('verifying wpr log: %s', wpr_log_path) - run_output_verifier.VerifyWprLog(wpr_log_path) - return run_metrics_list - - -class PrefetchBenchmarkBuilder(task_manager.Builder): - """A builder for a graph of tasks for NoState-Prefetch emulated benchmarks.""" - - def __init__(self, common_builder): - task_manager.Builder.__init__(self, - common_builder.output_directory, - common_builder.output_subdirectory) - self._common_builder = common_builder - - self._original_headers_path = None - self._wpr_archive_path = None - self._cache_path = None - self._trace_from_grabbing_reference_cache = None - self._cache_validation_task = None - self._PopulateCommonPipelines() - - def _PopulateCommonPipelines(self): - """Creates necessary tasks to produce initial cache archive. - - Also creates a task for producing a json file with a mapping of URLs to - subresources (urls-resources.json). - - Here is the full dependency tree for the returned task: - common/patched-cache-validation.json - depends on: common/patched-cache.zip - depends on: common/original-cache.zip - depends on: common/webpages-patched.wpr - depends on: common/webpages.wpr - """ - self._original_headers_path = self.RebaseOutputPath( - 'common/response-headers.json') - - @self.RegisterTask('common/webpages-patched.wpr', - dependencies=[self._common_builder.original_wpr_task]) - def BuildPatchedWpr(): - shutil.copyfile( - self._common_builder.original_wpr_task.path, BuildPatchedWpr.path) - wpr_archive = wpr_backend.WprArchiveBackend(BuildPatchedWpr.path) - - # Save up original response headers. - original_response_headers = {e.url: e.GetResponseHeadersDict() \ - for e in wpr_archive.ListUrlEntries()} - logging.info('save up response headers for %d resources', - len(original_response_headers)) - if not original_response_headers: - # TODO(gabadie): How is it possible to not even have the main resource - # in the WPR archive? Example URL can be found in: - # http://crbug.com/623966#c5 - raise Exception( - 'Looks like no resources were recorded in WPR during: {}'.format( - self._common_builder.original_wpr_task.name)) - with open(self._original_headers_path, 'w') as file_output: - json.dump(original_response_headers, file_output) - - # Patch WPR. - wpr_url_entries = wpr_archive.ListUrlEntries() - for wpr_url_entry in wpr_url_entries: - sandwich_utils.PatchWprEntryToBeCached(wpr_url_entry) - logging.info('number of patched entries: %d', len(wpr_url_entries)) - wpr_archive.Persist() - - @self.RegisterTask('common/original-cache.zip', [BuildPatchedWpr]) - def BuildOriginalCache(): - runner = self._common_builder.CreateSandwichRunner() - runner.wpr_archive_path = BuildPatchedWpr.path - runner.cache_archive_path = BuildOriginalCache.path - runner.cache_operation = sandwich_runner.CacheOperation.SAVE - runner.output_dir = BuildOriginalCache.run_path - runner.Run() - BuildOriginalCache.run_path = BuildOriginalCache.path[:-4] + '-run' - original_cache_trace_path = os.path.join( - BuildOriginalCache.run_path, '0', sandwich_runner.TRACE_FILENAME) - - @self.RegisterTask('common/patched-cache.zip', [BuildOriginalCache]) - def BuildPatchedCache(): - _PatchCacheArchive(BuildOriginalCache.path, - original_cache_trace_path, BuildPatchedCache.path) - - @self.RegisterTask('common/patched-cache-validation.json', - [BuildPatchedCache]) - def ValidatePatchedCache(): - cache_validation_result = _ValidateCacheArchiveContent( - original_cache_trace_path, BuildPatchedCache.path) - with open(ValidatePatchedCache.path, 'w') as output: - json.dump(cache_validation_result, output) - - self._wpr_archive_path = BuildPatchedWpr.path - self._trace_from_grabbing_reference_cache = original_cache_trace_path - self._cache_path = BuildPatchedCache.path - self._cache_validation_task = ValidatePatchedCache - - self._common_builder.default_final_tasks.append(ValidatePatchedCache) - - def PopulateLoadBenchmark(self, subresource_discoverer, - transformer_list_name, transformer_list): - """Populate benchmarking tasks from its setup tasks. - - Args: - subresource_discoverer: Name of a subresources discoverer. - transformer_list_name: A string describing the transformers, will be used - in Task names (prefer names without spaces and special characters). - transformer_list: An ordered list of function that takes an instance of - SandwichRunner as parameter, would be applied immediately before - SandwichRunner.Run() in the given order. - - Here is the full dependency of the added tree for the returned task: - <transformer_list_name>/<subresource_discoverer>-metrics.csv - depends on: <transformer_list_name>/<subresource_discoverer>-run/ - depends on: common/<subresource_discoverer>-cache.zip - depends on: common/<subresource_discoverer>-setup.json - depends on: common/patched-cache-validation.json - """ - additional_column_names = [ - 'url', - 'repeat_id', - 'subresource_discoverer', - 'cache_recording.subresource_count', - 'cache_recording.cached_subresource_count_theoretic', - 'cache_recording.cached_subresource_count', - 'benchmark.subresource_count', - 'benchmark.served_from_cache_count_theoretic', - 'benchmark.served_from_cache_count', - 'benchmark.served_from_network_bytes', - 'benchmark.served_from_cache_bytes'] - - assert subresource_discoverer in SUBRESOURCE_DISCOVERERS - assert 'common' not in SUBRESOURCE_DISCOVERERS - shared_task_prefix = os.path.join('common', subresource_discoverer) - task_prefix = os.path.join(transformer_list_name, subresource_discoverer) - - @self.RegisterTask(shared_task_prefix + '-setup.json', merge=True, - dependencies=[self._cache_validation_task]) - def SetupBenchmark(): - whitelisted_urls = _ExtractDiscoverableUrls( - original_headers_path=self._original_headers_path, - loading_trace_path=self._trace_from_grabbing_reference_cache, - subresource_discoverer=subresource_discoverer) - - common_util.EnsureParentDirectoryExists(SetupBenchmark.path) - with open(SetupBenchmark.path, 'w') as output: - json.dump({ - 'cache_whitelist': [url for url in whitelisted_urls], - 'subresource_discoverer': subresource_discoverer, - }, output) - - @self.RegisterTask(shared_task_prefix + '-cache.zip', merge=True, - dependencies=[SetupBenchmark]) - def BuildBenchmarkCacheArchive(): - benchmark_setup = json.load(open(SetupBenchmark.path)) - chrome_cache.ApplyUrlWhitelistToCacheArchive( - cache_archive_path=self._cache_path, - whitelisted_urls=benchmark_setup['cache_whitelist'], - output_cache_archive_path=BuildBenchmarkCacheArchive.path) - - @self.RegisterTask(task_prefix + '-run/', - dependencies=[BuildBenchmarkCacheArchive]) - def RunBenchmark(): - runner = self._common_builder.CreateSandwichRunner() - for transformer in transformer_list: - transformer(runner) - runner.wpr_archive_path = self._common_builder.original_wpr_task.path - runner.wpr_out_log_path = os.path.join( - RunBenchmark.path, sandwich_runner.WPR_LOG_FILENAME) - runner.cache_archive_path = BuildBenchmarkCacheArchive.path - runner.cache_operation = sandwich_runner.CacheOperation.PUSH - runner.output_dir = RunBenchmark.path - runner.Run() - - @self.RegisterTask(task_prefix + '-metrics.csv', - dependencies=[RunBenchmark]) - def ProcessRunOutputDir(): - benchmark_setup = json.load(open(SetupBenchmark.path)) - cache_validation_result = json.load( - open(self._cache_validation_task.path)) - - run_metrics_list = _ProcessRunOutputDir( - cache_validation_result, benchmark_setup, RunBenchmark.path) - with open(ProcessRunOutputDir.path, 'w') as csv_file: - writer = csv.DictWriter(csv_file, fieldnames=(additional_column_names + - sandwich_metrics.COMMON_CSV_COLUMN_NAMES)) - writer.writeheader() - for trace_metrics in run_metrics_list: - writer.writerow(trace_metrics) - - self._common_builder.default_final_tasks.append(ProcessRunOutputDir)
diff --git a/tools/android/loading/sandwich_prefetch_unittest.py b/tools/android/loading/sandwich_prefetch_unittest.py deleted file mode 100644 index 0d69a47..0000000 --- a/tools/android/loading/sandwich_prefetch_unittest.py +++ /dev/null
@@ -1,111 +0,0 @@ -# Copyright 2016 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. - -import json -import os -import shutil -import tempfile -import unittest -import urlparse - -import sandwich_prefetch - - -LOADING_DIR = os.path.dirname(__file__) -TEST_DATA_DIR = os.path.join(LOADING_DIR, 'testdata') - - -class SandwichPrefetchTestCase(unittest.TestCase): - _TRACE_PATH = os.path.join(TEST_DATA_DIR, 'scanner_vs_parser.trace') - - def setUp(self): - self._tmp_dir = tempfile.mkdtemp() - - def tearDown(self): - shutil.rmtree(self._tmp_dir) - - def GetTmpPath(self, file_name): - return os.path.join(self._tmp_dir, file_name) - - def GetResourceUrl(self, path): - return urlparse.urljoin('http://l/', path) - - def testEmptyCacheWhitelisting(self): - url_set = sandwich_prefetch._ExtractDiscoverableUrls(None, - self._TRACE_PATH, sandwich_prefetch.Discoverer.EmptyCache) - self.assertEquals(set(), url_set) - - def testFullCacheWhitelisting(self): - reference_url_set = set([self.GetResourceUrl('./'), - self.GetResourceUrl('0.png'), - self.GetResourceUrl('1.png'), - self.GetResourceUrl('0.css'), - self.GetResourceUrl('favicon.ico')]) - url_set = sandwich_prefetch._ExtractDiscoverableUrls(None, - self._TRACE_PATH, sandwich_prefetch.Discoverer.FullCache) - self.assertEquals(reference_url_set, url_set) - - def testMainDocumentWhitelisting(self): - reference_url_set = set([self.GetResourceUrl('./')]) - url_set = sandwich_prefetch._ExtractDiscoverableUrls(None, - self._TRACE_PATH, sandwich_prefetch.Discoverer.MainDocument) - self.assertEquals(reference_url_set, url_set) - - def testParserDiscoverableWhitelisting(self): - reference_url_set = set([self.GetResourceUrl('./'), - self.GetResourceUrl('0.png'), - self.GetResourceUrl('1.png'), - self.GetResourceUrl('0.css')]) - url_set = sandwich_prefetch._ExtractDiscoverableUrls(None, - self._TRACE_PATH, sandwich_prefetch.Discoverer.Parser) - self.assertEquals(reference_url_set, url_set) - - def testHTMLPreloadScannerWhitelisting(self): - reference_url_set = set([self.GetResourceUrl('./'), - self.GetResourceUrl('0.png'), - self.GetResourceUrl('0.css')]) - url_set = sandwich_prefetch._ExtractDiscoverableUrls(None, - self._TRACE_PATH, sandwich_prefetch.Discoverer.HTMLPreloadScanner) - self.assertEquals(reference_url_set, url_set) - - def testHTMLPreloadScannerStoreWhitelisting(self): - original_headers_path = self.GetTmpPath('original_headers.json') - - def RunTest(reference_urls): - url_set = sandwich_prefetch._ExtractDiscoverableUrls( - original_headers_path, self._TRACE_PATH, - sandwich_prefetch.Discoverer.HTMLPreloadScannerStore) - self.assertEquals(set(reference_urls), url_set) - - with open(original_headers_path, 'w') as output_file: - json.dump({ - self.GetResourceUrl('./'): {}, - self.GetResourceUrl('0.png'): {'cache-control': 'max-age=0'}, - self.GetResourceUrl('0.css'): {} - }, output_file) - RunTest([self.GetResourceUrl('./'), - self.GetResourceUrl('0.png'), - self.GetResourceUrl('0.css')]) - - with open(original_headers_path, 'w') as output_file: - json.dump({ - self.GetResourceUrl('./'): {}, - self.GetResourceUrl('0.png'): {'cache-control': 'private, no-store'}, - self.GetResourceUrl('0.css'): {} - }, output_file) - RunTest([self.GetResourceUrl('./'), - self.GetResourceUrl('0.css')]) - - with open(original_headers_path, 'w') as output_file: - json.dump({ - self.GetResourceUrl('./'): {'cache-control': 'private, no-store'}, - self.GetResourceUrl('0.png'): {}, - self.GetResourceUrl('0.css'): {} - }, output_file) - RunTest([self.GetResourceUrl('0.png'), - self.GetResourceUrl('0.css')]) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/sandwich_runner.py b/tools/android/loading/sandwich_runner.py deleted file mode 100644 index 5c3bb949..0000000 --- a/tools/android/loading/sandwich_runner.py +++ /dev/null
@@ -1,376 +0,0 @@ -# Copyright 2016 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. - -import logging -import os -import shutil -import sys -import tempfile - -_SRC_DIR = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..', '..', '..')) - -sys.path.append(os.path.join(_SRC_DIR, 'third_party', 'catapult', 'devil')) -from devil.android import device_utils - -sys.path.append(os.path.join(_SRC_DIR, 'third_party', 'catapult', 'telemetry', - 'third_party', 'websocket-client')) -import websocket - -import chrome_cache -import common_util -import controller -import devtools_monitor -import device_setup -import loading_trace - - -# Standard filenames in the sandwich runner's output directory. -ERROR_FILENAME = 'error' -TRACE_FILENAME = 'trace.json' -VIDEO_FILENAME = 'video.mp4' -WPR_LOG_FILENAME = 'wpr.log' - -# Memory dump category used to get memory metrics. -MEMORY_DUMP_CATEGORY = 'disabled-by-default-memory-infra' - -# Devtools timeout of 1 minute to avoid websocket timeout on slow -# network condition. -_DEVTOOLS_TIMEOUT = 60 - -# Categories to enable or disable for all traces collected. Disabled categories -# are prefixed with '-'. -_TRACING_CATEGORIES = [ - 'blink', - 'blink.net', - 'blink.user_timing', - 'devtools.timeline', - 'java', - 'navigation', - 'toplevel', - 'v8', - '-cc', # A lot of unnecessary events are enabled by default in "cc". -] - -TTFMP_ADDITIONAL_CATEGORIES = [ - 'loading', - 'disabled-by-default-blink.debug.layout', -] - -def _CleanArtefactsFromPastRuns(output_directories_path): - """Cleans artifacts generated from past run in the output directory. - - Args: - output_directories_path: The output directory path where to clean the - previous traces. - """ - for dirname in os.listdir(output_directories_path): - directory_path = os.path.join(output_directories_path, dirname) - if not os.path.isdir(directory_path): - continue - try: - int(dirname) - except ValueError: - continue - shutil.rmtree(directory_path) - - -class CacheOperation(object): - CLEAR, SAVE, PUSH = range(3) - - -class SandwichRunnerError(Exception): - pass - - -class SandwichRunner(object): - """Sandwich runner. - - This object is meant to be configured first and then run using the Run() - method. - """ - _ATTEMPT_COUNT = 3 - _STOP_DELAY_MULTIPLIER = 2 - _ABORT_RUN_TIMEOUT_SECONDS = 30 * 60 - - def __init__(self): - """Configures a sandwich runner out of the box. - - Public members are meant to be configured before calling Run(). - """ - # Cache operation to do before doing the chrome navigation. - self.cache_operation = CacheOperation.CLEAR - - # The cache archive's path to save to or push from. Is str or None. - self.cache_archive_path = None - - # List of additional chrome command line flags. - self.chrome_args = [] - - # Controls whether the WPR server should do script injection. - self.disable_wpr_script_injection = False - - # Number of times to repeat the url. - self.repeat = 1 - - # Network conditions to emulate. None if no emulation. - self.network_condition = None - - # Network condition emulator. Can be: browser,wpr - self.network_emulator = 'browser' - - # Output directory where to save the traces, videos, etc. Is str or None. - self.output_dir = None - - # URL to navigate to. - self.url = None - - # Configures whether to record speed-index video. - self.record_video = False - - # Configures whether to record memory dumps. - self.record_memory_dumps = False - - # Configures whether to record tracing categories needed for TTFMP. - self.record_first_meaningful_paint = False - - # Path to the WPR archive to load or save. Is str or None. - self.wpr_archive_path = None - - # Configures whether the WPR archive should be read or generated. - self.wpr_record = False - - # The android DeviceUtils to run sandwich on or None to run it locally. - self.android_device = None - - self._chrome_ctl = None - self._local_cache_directory_path = None - - def _CleanTraceOutputDirectory(self): - assert self.output_dir - if not os.path.isdir(self.output_dir): - try: - os.makedirs(self.output_dir) - except OSError: - logging.error('Cannot create directory for results: %s', - self.output_dir) - raise - else: - _CleanArtefactsFromPastRuns(self.output_dir) - - def _GetEmulatorNetworkCondition(self, emulator): - if self.network_emulator == emulator: - return self.network_condition - return None - - def _RunNavigation(self, clear_cache, repeat_id=None): - """Run a page navigation to the given URL. - - Args: - clear_cache: Whether if the cache should be cleared before navigation. - repeat_id: Id of the run in the output directory. If it is None, then no - trace or video will be saved. - """ - run_path = None - if repeat_id is not None: - run_path = os.path.join(self.output_dir, str(repeat_id)) - if not os.path.isdir(run_path): - os.makedirs(run_path) - self._chrome_ctl.SetNetworkEmulation( - self._GetEmulatorNetworkCondition('browser')) - categories = _TRACING_CATEGORIES - if self.record_memory_dumps: - categories += [MEMORY_DUMP_CATEGORY] - if self.record_first_meaningful_paint: - categories += TTFMP_ADDITIONAL_CATEGORIES - stop_delay_multiplier = 0 - if self.wpr_record or self.cache_operation == CacheOperation.SAVE: - stop_delay_multiplier = self._STOP_DELAY_MULTIPLIER - # TODO(gabadie): add a way to avoid recording a trace. - with common_util.TimeoutScope( - self._ABORT_RUN_TIMEOUT_SECONDS, 'Sandwich run overdue.'): - with self._chrome_ctl.Open() as connection: - if clear_cache: - connection.ClearCache() - - # Binds all parameters of RecordUrlNavigation() to avoid repetition. - def RecordTrace(): - return loading_trace.LoadingTrace.RecordUrlNavigation( - url=self.url, - connection=connection, - chrome_metadata=self._chrome_ctl.ChromeMetadata(), - categories=categories, - timeout_seconds=_DEVTOOLS_TIMEOUT, - stop_delay_multiplier=stop_delay_multiplier) - - if run_path is not None and self.record_video: - device = self._chrome_ctl.GetDevice() - if device is None: - raise RuntimeError('Can only record video on a remote device.') - video_recording_path = os.path.join(run_path, VIDEO_FILENAME) - with device_setup.RemoteSpeedIndexRecorder(device, connection, - video_recording_path): - trace = RecordTrace() - else: - trace = RecordTrace() - for event in trace.request_track.GetEvents(): - if event.failed: - logging.warning( - 'request to %s failed: %s', event.url, event.error_text) - if not trace.tracing_track.HasLoadingSucceeded(): - raise SandwichRunnerError('Page load has failed.') - if run_path is not None: - trace_path = os.path.join(run_path, TRACE_FILENAME) - trace.ToJsonFile(trace_path) - - def _RunInRetryLoop(self, repeat_id, perform_dry_run_before): - """Attempts to run monitoring navigation. - - Args: - repeat_id: Id of the run in the output directory. - perform_dry_run_before: Whether it should do a dry run attempt before the - actual monitoring run. - - Returns: - Whether the device should be rebooted to continue attempting for that - given |repeat_id|. - """ - resume_attempt_id = 0 - if perform_dry_run_before: - resume_attempt_id = 1 - for attempt_id in xrange(resume_attempt_id, self._ATTEMPT_COUNT): - try: - if perform_dry_run_before: - logging.info('Do sandwich dry run attempt %d', attempt_id) - else: - logging.info('Do sandwich run attempt %d', attempt_id) - self._chrome_ctl.ResetBrowserState() - clear_cache = False - if self.cache_operation == CacheOperation.CLEAR: - clear_cache = True - elif self.cache_operation == CacheOperation.PUSH: - self._chrome_ctl.PushBrowserCache(self._local_cache_directory_path) - elif self.cache_operation == CacheOperation.SAVE: - clear_cache = repeat_id == 0 - self._RunNavigation(clear_cache=clear_cache, repeat_id=repeat_id) - if not perform_dry_run_before or attempt_id > resume_attempt_id: - break - except controller.ChromeControllerError as error: - request_reboot = False - is_intermittent = error.IsIntermittent() - if (self.android_device and - attempt_id == 0 and - error.error_type is websocket.WebSocketConnectionClosedException): - assert not perform_dry_run_before - # On Android, the first socket connection closure is likely caused by - # memory pressure on the device and therefore considered intermittent, - # and therefore request a reboot of the device to the caller. - request_reboot = True - is_intermittent = True - if is_intermittent and attempt_id + 1 != self._ATTEMPT_COUNT: - dump_filename = '{}_intermittent_failure'.format(attempt_id) - dump_path = os.path.join( - self.output_dir, str(repeat_id), dump_filename) - else: - dump_path = os.path.join(self.output_dir, ERROR_FILENAME) - with open(dump_path, 'w') as dump_output: - error.Dump(dump_output) - if not is_intermittent: - error.RaiseOriginal() - if request_reboot: - assert resume_attempt_id is 0 - return True - else: - logging.error('Failed to navigate to %s after %d attemps' % \ - (self.url, self._ATTEMPT_COUNT)) - error.RaiseOriginal() - return False - - def _RunWithWpr(self, resume_repeat_id, perform_dry_run_before): - """Opens WPR and attempts to run repeated monitoring navigation. - - Args: - resume_repeat_id: Id of the run to resume. - perform_dry_run_before: Whether the repeated run to resume should first do - a dry run navigation attempt. - - Returns: - Number of repeat performed. If < self.repeat, then it means that the - device should be rebooted. - """ - with self._chrome_ctl.OpenWprHost(self.wpr_archive_path, - record=self.wpr_record, - network_condition_name=self._GetEmulatorNetworkCondition('wpr'), - disable_script_injection=self.disable_wpr_script_injection, - out_log_path=os.path.join(self.output_dir, WPR_LOG_FILENAME)): - for repeat_id in xrange(resume_repeat_id, self.repeat): - reboot_requested = self._RunInRetryLoop( - repeat_id, perform_dry_run_before) - if reboot_requested: - return repeat_id - return self.repeat - - def _PullCacheFromDevice(self): - assert self.cache_operation == CacheOperation.SAVE - assert self.cache_archive_path, 'Need to specify where to save the cache' - - cache_directory_path = self._chrome_ctl.PullBrowserCache() - chrome_cache.ZipDirectoryContent( - cache_directory_path, self.cache_archive_path) - shutil.rmtree(cache_directory_path) - - def Run(self): - """SandwichRunner main entry point meant to be called once configured.""" - assert self.output_dir is not None - assert self._chrome_ctl == None - assert self._local_cache_directory_path == None - self._CleanTraceOutputDirectory() - - if self.android_device: - self._chrome_ctl = controller.RemoteChromeController(self.android_device) - else: - self._chrome_ctl = controller.LocalChromeController() - self._chrome_ctl.AddChromeArguments(['--disable-infobars']) - self._chrome_ctl.AddChromeArguments(self.chrome_args) - if self.cache_operation == CacheOperation.SAVE: - self._chrome_ctl.SetSlowDeath() - try: - if self.cache_operation == CacheOperation.PUSH: - assert os.path.isfile(self.cache_archive_path) - self._local_cache_directory_path = tempfile.mkdtemp(suffix='.cache') - chrome_cache.UnzipDirectoryContent( - self.cache_archive_path, self._local_cache_directory_path) - times_repeated = self._RunWithWpr(0, False) - if times_repeated < self.repeat: - self._chrome_ctl.RebootDevice() - self._RunWithWpr(times_repeated, True) - finally: - if self._local_cache_directory_path: - shutil.rmtree(self._local_cache_directory_path) - self._local_cache_directory_path = None - if self.cache_operation == CacheOperation.SAVE: - self._PullCacheFromDevice() - - self._chrome_ctl = None - - -def WalkRepeatedRuns(runner_output_dir): - """Yields unordered (repeat id, path of the repeat directory). - - Args: - runner_output_dir: Same as for SandwichRunner.output_dir. - """ - repeated_run_count = 0 - for node_name in os.listdir(runner_output_dir): - repeat_dir = os.path.join(runner_output_dir, node_name) - if not os.path.isdir(repeat_dir): - continue - try: - repeat_id = int(node_name) - except ValueError: - continue - yield repeat_id, repeat_dir - repeated_run_count += 1 - assert repeated_run_count > 0, ('Error: not a sandwich runner output ' - 'directory: {}').format(runner_output_dir)
diff --git a/tools/android/loading/sandwich_swr.py b/tools/android/loading/sandwich_swr.py deleted file mode 100644 index e6b3736..0000000 --- a/tools/android/loading/sandwich_swr.py +++ /dev/null
@@ -1,323 +0,0 @@ -# Copyright 2016 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. - -""" This module implements the Stale-While-Revalidate performance improvement -experiment on third parties' resources. - -The top level operations of the experiment are: - 1. Record WPR archive; - 2. Create a patched WPR archive so that all resource are getting cached; - 3. Record original cache using the patched WPR archive; - 4. Setup the benchmark producing the list of URL to enable SWR in a JSON file; - 5. Create the benchmark cache by: - - Remove No-Store resources; - - Adding the SWR header on resources that are experimentally required to - have it; - - Patch SWR header on resources that already had it to make sure the - the SWR freshness is not out of date; - - And restore all other headers so that response headers such as - Set-Cookie are still in the cache to avoid entropy caused by - different cookie values. - 6. Run the benchmark; - 7. Extract metrics into CSV files. -""" - -import csv -import json -import logging -import os -import shutil -from urlparse import urlparse - -import chrome_cache -import common_util -import loading_trace -import request_track -import sandwich_metrics -import sandwich_runner -import sandwich_utils -import task_manager -import wpr_backend - - -def _ExtractRegexMatchingUrls(urls, domain_regexes): - urls_to_enable = set() - for url in urls: - if url in urls_to_enable: - continue - parsed_url = urlparse(url) - for domain_regex in domain_regexes: - if domain_regex.search(parsed_url.netloc): - urls_to_enable.add(url) - break - return urls_to_enable - - -def _BuildBenchmarkCache( - original_wpr_trace_path, urls_to_enable_swr, - original_cache_trace_path, original_cache_archive_path, - cache_archive_dest_path): - # Load trace that was generated at original cache creation. - logging.info('loading %s', original_wpr_trace_path) - trace = loading_trace.LoadingTrace.FromJsonFile(original_wpr_trace_path) - - # Lists URLs that should not be in the cache or already have SWR headers. - urls_should_not_be_cached = set() - urls_already_with_swr = set() - for request in trace.request_track.GetEvents(): - caching_policy = request_track.CachingPolicy(request) - if not caching_policy.IsCacheable(): - urls_should_not_be_cached.add(request.url) - elif caching_policy.GetFreshnessLifetimes()[1] > 0: - urls_already_with_swr.add(request.url) - # Trace are fat, kill this one to save up memory for the next one to load in - # this scope. - del trace - - # Load trace that was generated at original cache creation. - logging.info('loading %s', original_cache_trace_path) - trace = loading_trace.LoadingTrace.FromJsonFile(original_cache_trace_path) - - # Create cache contents. - delete_count = 0 - swr_patch_count = 0 - originaly_swr_patch_count = 0 - noswr_patch_count = 0 - with common_util.TemporaryDirectory(prefix='sandwich_tmp') as tmp_path: - cache_path = os.path.join(tmp_path, 'cache') - chrome_cache.UnzipDirectoryContent(original_cache_archive_path, cache_path) - cache_backend = chrome_cache.CacheBackend(cache_path, 'simple') - cache_keys = set(cache_backend.ListKeys()) - for request in trace.request_track.GetEvents(): - if request.url not in cache_keys: - continue - if request.url in urls_should_not_be_cached: - cache_backend.DeleteKey(request.url) - delete_count += 1 - continue - if not request.HasReceivedResponse(): - continue - if request.url in urls_to_enable_swr: - request.SetHTTPResponseHeader( - 'cache-control', 'max-age=0,stale-while-revalidate=315360000') - request.SetHTTPResponseHeader( - 'last-modified', 'Thu, 23 Jun 2016 11:30:00 GMT') - swr_patch_count += 1 - elif request.url in urls_already_with_swr: - # Force to use SWR on resources that originally attempted to use it. - request.SetHTTPResponseHeader( - 'cache-control', 'max-age=0,stale-while-revalidate=315360000') - # The resource originally had SWR enabled therefore we don't - # Last-Modified to repro exactly the performance impact in case these - # headers were not set properly causing an invalidation instead of a - # revalidation. - originaly_swr_patch_count += 1 - else: - # Force synchronous revalidation. - request.SetHTTPResponseHeader('cache-control', 'max-age=0') - noswr_patch_count += 1 - raw_headers = request.GetRawResponseHeaders() - cache_backend.UpdateRawResponseHeaders(request.url, raw_headers) - chrome_cache.ZipDirectoryContent(cache_path, cache_archive_dest_path) - logging.info('patched %d cached resources with forced SWR', swr_patch_count) - logging.info('patched %d cached resources with original SWR', - originaly_swr_patch_count) - logging.info('patched %d cached resources without SWR', noswr_patch_count) - logging.info('deleted %d cached resources', delete_count) - - -def _ProcessRunOutputDir(benchmark_setup, runner_output_dir): - """Process benchmark's run output directory. - - Args: - cache_validation_result: Same as for _RunOutputVerifier - benchmark_setup: Same as for _RunOutputVerifier - runner_output_dir: Same as for SandwichRunner.output_dir - - Returns: - List of dictionary. - """ - run_metrics_list = [] - for repeat_id, repeat_dir in sandwich_runner.WalkRepeatedRuns( - runner_output_dir): - trace_path = os.path.join(repeat_dir, sandwich_runner.TRACE_FILENAME) - logging.info('processing trace: %s', trace_path) - trace = loading_trace.LoadingTrace.FromJsonFile(trace_path) - served_from_cache_urls = sandwich_utils.ListUrlRequests( - trace, sandwich_utils.RequestOutcome.ServedFromCache) - matching_subresource_count_used_from_cache = ( - served_from_cache_urls.intersection( - set(benchmark_setup['urls_to_enable_swr']))) - run_metrics = { - 'url': trace.url, - 'repeat_id': repeat_id, - 'benchmark_name': benchmark_setup['benchmark_name'], - 'cache_recording.subresource_count': - len(benchmark_setup['effective_subresource_urls']), - 'cache_recording.matching_subresource_count': - len(benchmark_setup['urls_to_enable_swr']), - 'benchmark.matching_subresource_count_used_from_cache': - len(matching_subresource_count_used_from_cache) - } - run_metrics.update( - sandwich_metrics.ExtractCommonMetricsFromRepeatDirectory( - repeat_dir, trace)) - run_metrics_list.append(run_metrics) - return run_metrics_list - - -class StaleWhileRevalidateBenchmarkBuilder(task_manager.Builder): - """A builder for a graph of tasks for Stale-While-Revalidate study benchmarks. - """ - - def __init__(self, common_builder): - task_manager.Builder.__init__(self, - common_builder.output_directory, - common_builder.output_subdirectory) - self._common_builder = common_builder - self._patched_wpr_path = None - self._original_cache_task = None - self._original_cache_trace_path = None - self._PopulateCommonPipelines() - - def _PopulateCommonPipelines(self): - """Creates necessary tasks to produce initial cache archives. - - Here is the full dependency tree for the returned task: - depends on: common/original-cache.zip - depends on: common/webpages-patched.wpr - depends on: common/webpages.wpr - """ - @self.RegisterTask('common/webpages-patched.wpr', - dependencies=[self._common_builder.original_wpr_task]) - def BuildPatchedWpr(): - shutil.copyfile( - self._common_builder.original_wpr_task.path, BuildPatchedWpr.path) - wpr_archive = wpr_backend.WprArchiveBackend(BuildPatchedWpr.path) - wpr_url_entries = wpr_archive.ListUrlEntries() - for wpr_url_entry in wpr_url_entries: - sandwich_utils.PatchWprEntryToBeCached(wpr_url_entry) - logging.info('number of patched entries: %d', len(wpr_url_entries)) - wpr_archive.Persist() - - @self.RegisterTask('common/original-cache.zip', - dependencies=[BuildPatchedWpr]) - def BuildOriginalCache(): - runner = self._common_builder.CreateSandwichRunner() - runner.wpr_archive_path = BuildPatchedWpr.path - runner.cache_archive_path = BuildOriginalCache.path - runner.cache_operation = sandwich_runner.CacheOperation.SAVE - runner.output_dir = BuildOriginalCache.run_path - runner.Run() - BuildOriginalCache.run_path = BuildOriginalCache.path[:-4] + '-run' - - self._original_cache_trace_path = os.path.join( - BuildOriginalCache.run_path, '0', sandwich_runner.TRACE_FILENAME) - self._patched_wpr_path = BuildPatchedWpr.path - self._original_cache_task = BuildOriginalCache - - def PopulateBenchmark(self, benchmark_name, domain_regexes, - transformer_list_name, transformer_list): - """Populate benchmarking tasks. - - Args: - benchmark_name: Name of the benchmark. - domain_regexes: Compiled regexes of domains to enable SWR. - transformer_list_name: A string describing the transformers, will be used - in Task names (prefer names without spaces and special characters). - transformer_list: An ordered list of function that takes an instance of - SandwichRunner as parameter, would be applied immediately before - SandwichRunner.Run() in the given order. - - - Here is the full dependency of the added tree for the returned task: - <transformer_list_name>/<benchmark_name>-metrics.csv - depends on: <transformer_list_name>/<benchmark_name>-run/ - depends on: common/<benchmark_name>-cache.zip - depends on: common/<benchmark_name>-setup.json - depends on: common/patched-cache.zip - """ - additional_column_names = [ - 'url', - 'repeat_id', - 'benchmark_name', - - # Number of resources of the page. - 'cache_recording.subresource_count', - - # Number of resources matching at least one domain regex, to give an - # idea in the CSV how much the threshold influence additional SWR uses. - 'cache_recording.matching_subresource_count', - - # Number of resources fetched from cache matching at least one domain - # regex, to give an actual idea if it is possible to have performance - # improvement on the web page (or not because only XHR), but also tells - # if the page loading time should see a performance improvement or not - # compared with a different thresholds. - 'benchmark.matching_subresource_count_used_from_cache'] - shared_task_prefix = os.path.join('common', benchmark_name) - task_prefix = os.path.join(transformer_list_name, benchmark_name) - - @self.RegisterTask(shared_task_prefix + '-setup.json', merge=True, - dependencies=[self._original_cache_task]) - def SetupBenchmark(): - logging.info('loading %s', self._original_cache_trace_path) - trace = loading_trace.LoadingTrace.FromJsonFile( - self._original_cache_trace_path) - logging.info('generating %s', SetupBenchmark.path) - effective_subresource_urls = sandwich_utils.ListUrlRequests( - trace, sandwich_utils.RequestOutcome.All) - urls_to_enable_swr = _ExtractRegexMatchingUrls( - effective_subresource_urls, domain_regexes) - logging.info( - 'count of urls to enable SWR: %s', len(urls_to_enable_swr)) - with open(SetupBenchmark.path, 'w') as output: - json.dump({ - 'benchmark_name': benchmark_name, - 'urls_to_enable_swr': [url for url in urls_to_enable_swr], - 'effective_subresource_urls': - [url for url in effective_subresource_urls] - }, output) - - @self.RegisterTask(shared_task_prefix + '-cache.zip', merge=True, - dependencies=[SetupBenchmark]) - def BuildBenchmarkCacheArchive(): - benchmark_setup = json.load(open(SetupBenchmark.path)) - _BuildBenchmarkCache( - original_wpr_trace_path=( - self._common_builder.original_wpr_recording_trace_path), - urls_to_enable_swr=set(benchmark_setup['urls_to_enable_swr']), - original_cache_trace_path=self._original_cache_trace_path, - original_cache_archive_path=self._original_cache_task.path, - cache_archive_dest_path=BuildBenchmarkCacheArchive.path) - - @self.RegisterTask(task_prefix + '-run/', [BuildBenchmarkCacheArchive]) - def RunBenchmark(): - runner = self._common_builder.CreateSandwichRunner() - for transformer in transformer_list: - transformer(runner) - runner.wpr_archive_path = self._patched_wpr_path - runner.wpr_out_log_path = os.path.join( - RunBenchmark.path, sandwich_runner.WPR_LOG_FILENAME) - runner.cache_archive_path = BuildBenchmarkCacheArchive.path - runner.cache_operation = sandwich_runner.CacheOperation.PUSH - runner.output_dir = RunBenchmark.path - runner.chrome_args.append('--enable-features=StaleWhileRevalidate2') - runner.Run() - - @self.RegisterTask(task_prefix + '-metrics.csv', [RunBenchmark]) - def ExtractMetrics(): - benchmark_setup = json.load(open(SetupBenchmark.path)) - run_metrics_list = _ProcessRunOutputDir( - benchmark_setup, RunBenchmark.path) - - run_metrics_list.sort(key=lambda e: e['repeat_id']) - with open(ExtractMetrics.path, 'w') as csv_file: - writer = csv.DictWriter(csv_file, fieldnames=(additional_column_names + - sandwich_metrics.COMMON_CSV_COLUMN_NAMES)) - writer.writeheader() - for run_metrics in run_metrics_list: - writer.writerow(run_metrics) - - self._common_builder.default_final_tasks.append(ExtractMetrics)
diff --git a/tools/android/loading/sandwich_utils.py b/tools/android/loading/sandwich_utils.py deleted file mode 100644 index eda55e0..0000000 --- a/tools/android/loading/sandwich_utils.py +++ /dev/null
@@ -1,153 +0,0 @@ -# Copyright 2016 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. - -import os - -import common_util -import emulation -import sandwich_runner -import task_manager - - -def NetworkSimulationTransformer(network_condition): - """Creates a function that accepts a SandwichRunner as a parameter and sets - network emulation options on it. - - Args: - network_condition: The network condition to apply to the sandwich runner. - - Returns: - A callback transforming the SandwichRunner given in argument accordingly - """ - assert network_condition in emulation.NETWORK_CONDITIONS - def Transformer(runner): - assert isinstance(runner, sandwich_runner.SandwichRunner) - runner.network_condition = network_condition - return Transformer - - -def FilterOutDataAndIncompleteRequests(requests): - for request in filter(lambda r: not r.IsDataRequest(), requests): - # The protocol is only known once the response has been received. But the - # trace recording might have been stopped with still some JavaScript - # originated requests that have not received any responses yet. - if request.protocol is None: - assert not request.HasReceivedResponse() - continue - if request.protocol in {'about'}: - continue - if request.protocol not in {'http/0.9', 'http/1.0', 'http/1.1'}: - raise RuntimeError('Unknown request protocol {}'.format(request.protocol)) - yield request - - -class RequestOutcome: - All, ServedFromCache, NotServedFromCache, Post = range(4) - - -def ListUrlRequests(trace, request_kind): - """Lists requested URLs from a trace. - - Args: - trace: (loading_trace.LoadingTrace) loading trace. - request_kind: RequestOutcome.* indicating the subset of requests to output. - - Returns: - set([str]) - """ - urls = set() - for request_event in FilterOutDataAndIncompleteRequests( - trace.request_track.GetEvents()): - if (request_kind == RequestOutcome.ServedFromCache and - request_event.from_disk_cache): - urls.add(request_event.url) - elif (request_kind == RequestOutcome.Post and - request_event.method.upper().strip() == 'POST'): - urls.add(request_event.url) - elif (request_kind == RequestOutcome.NotServedFromCache and - not request_event.from_disk_cache): - urls.add(request_event.url) - elif request_kind == RequestOutcome.All: - urls.add(request_event.url) - return urls - - -def PatchWprEntryToBeCached(wpr_url_entry): - """Patches a WprUrlEntry to ensure the resources to go into the HTTP cache and - avoid invalidation and revalidations. - - Args: - wpr_url_entry: Wpr url entry of the resource to put into the cache. - """ - MAX_AGE = 10 * 365 * 24 * 60 * 60 - CACHE_CONTROL = 'public, max-age={}'.format(MAX_AGE) - - # TODO(gabadie): may need to patch Last-Modified and If-Modified-Since. - # TODO(gabadie): may need to delete ETag. - # TODO(gabadie): may need to take care of x-cache. - # - # Override the cache-control header to set the resources max age to MAX_AGE. - # - # Important note: Some resources holding sensitive information might have - # cache-control set to no-store which allow the resource to be cached but - # not cached in the file system. NoState-Prefetch is going to take care of - # this case. But in here, to simulate NoState-Prefetch, we don't have other - # choices but save absolutely all cached resources on disk so they survive - # after killing chrome for cache save, modification and push. - wpr_url_entry.SetResponseHeader('cache-control', CACHE_CONTROL) - - # TODO(gabadie): May need to extend Vary blacklist (referer?) - # - # All of these Vary and Pragma possibilities need to be removed from - # response headers in order for Chrome to store a resource in HTTP cache and - # not to invalidate it. - wpr_url_entry.RemoveResponseHeaderDirectives('vary', {'*', 'cookie'}) - wpr_url_entry.RemoveResponseHeaderDirectives('pragma', {'no-cache'}) - - -class SandwichCommonBuilder(task_manager.Builder): - """A builder for a graph of tasks, each prepares or invokes a SandwichRunner. - """ - - def __init__(self, android_device, url, output_directory, - output_subdirectory): - """Constructor. - - Args: - android_device: The android DeviceUtils to run sandwich on or None to run - it locally. - url: URL to benchmark. - output_directory: As in task_manager.Builder.__init__ - output_subdirectory: As in task_manager.Builder.__init__ - """ - task_manager.Builder.__init__(self, output_directory, output_subdirectory) - self._android_device = android_device - self._url = url - self.default_final_tasks = [] - - self.original_wpr_task = None - self.original_wpr_recording_trace_path = None - - def CreateSandwichRunner(self): - """Create a runner for non benchmark purposes.""" - runner = sandwich_runner.SandwichRunner() - runner.url = self._url - runner.android_device = self._android_device - return runner - - def PopulateWprRecordingTask(self): - """Records the original WPR archive.""" - @self.RegisterTask('common/webpages.wpr') - def BuildOriginalWpr(): - common_util.EnsureParentDirectoryExists(BuildOriginalWpr.path) - runner = self.CreateSandwichRunner() - runner.wpr_archive_path = BuildOriginalWpr.path - runner.wpr_record = True - runner.output_dir = BuildOriginalWpr.run_path - runner.Run() - BuildOriginalWpr.run_path = BuildOriginalWpr.path[:-4] + '-run' - - self.original_wpr_task = BuildOriginalWpr - self.original_wpr_recording_trace_path = os.path.join( - BuildOriginalWpr.run_path, '0', sandwich_runner.TRACE_FILENAME)
diff --git a/tools/android/loading/task_manager.py b/tools/android/loading/task_manager.py deleted file mode 100644 index f132eb1..0000000 --- a/tools/android/loading/task_manager.py +++ /dev/null
@@ -1,519 +0,0 @@ -# Copyright 2016 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. - -"""API that build and execute recipes wrapped into a task dependency graph. - -A Task consists of a 'recipe' (a closure to be executed) and a list of refs to -tasks that should be executed prior to executing this Task (i.e. dependencies). -The responsibility of the recipe of a task is to produce the file with the name -assigned at task creation. - -A scenario is a ordered list of tasks to execute such that the dependencies of a -given task are execute before the said task. The scenario is built from a list -of final tasks and a list of frozen tasks: - - A final task is a task to execute ultimately. Therefore the scenario is - composed of final tasks and their required intermediary tasks. - - A frozen task is task to not execute. This is a mechanism to morph a task - that may have dependencies to a task with no dependency at scenario - generation time, injecting what the task have already produced before as an - input of the smaller tasks dependency graph covered by the scenario. - -Example: - # -------------------------------------------------- Build my dependency graph - builder = Builder('my/output/dir') - - @builder.RegisterTask('out0') - def BuildOut0(): - Produce(out=BuildOut0.path) - - @builder.RegisterTask('out1') - def BuildOut1(): - Produce(out=BuildOut1.path) - - @builder.RegisterTask('out2', dependencies=[BuildOut0, BuildOut1]) - def BuildOut2(): - DoStuff(BuildOut0.path, BuildOut1.path, out=BuildOut2.path) - - @builder.RegisterTask('out3', dependencies=[BuildOut0]) - def BuildOut3(): - DoStuff(BuildOut0.path, out=BuildOut3.path) - - # ---------------------------- Case 1: Execute BuildOut3 and its dependencies. - for task in GenerateScenario(final_tasks=[BuildOut3], frozen_tasks=[]) - task.Execute() - - # ---------- Case 2: Execute BuildOut2 and its dependencies but not BuildOut1. - # It is required that BuildOut1.path is already existing. - for task in GenerateScenario(final_tasks=[BuildOut2], - frozen_tasks=[BuildOut1]) - task.Execute() -""" - - -import argparse -import collections -import datetime -import errno -import logging -import os -import re -import subprocess -import sys - -import common_util - - -_TASK_LOGS_DIR_NAME = 'logs' -_TASK_GRAPH_DOTFILE_NAME = 'tasks_graph.dot' -_TASK_GRAPH_PNG_NAME = 'tasks_graph.png' -_TASK_RESUME_ARGUMENTS_FILE = 'resume.txt' -_TASK_EXECUTION_LOG_NAME_FORMAT = 'task-execution-%Y-%m-%d-%H-%M-%S.log' - -FROMFILE_PREFIX_CHARS = '@' - - -class TaskError(Exception): - pass - - -class Task(object): - """Task with a recipe.""" - - def __init__(self, name, path, dependencies, recipe): - """Constructor. - - Args: - name: The name of the task. - path: Path to the file or directory that this task produces. - dependencies: List of parent task to execute before. - recipe: Function to execute. - """ - self.name = name - self.path = path - self._dependencies = dependencies - self._recipe = recipe - self._is_done = recipe == None - - def Execute(self): - """Executes this task.""" - if not self._is_done: - self._recipe() - self._is_done = True - - -class Builder(object): - """Utilities for creating sub-graphs of tasks with dependencies.""" - - def __init__(self, output_directory, output_subdirectory): - """Constructor. - - Args: - output_directory: Output directory where the tasks work. - output_subdirectory: Subdirectory to put all created tasks in or None. - """ - self.output_directory = output_directory - self.output_subdirectory = output_subdirectory - self._tasks = {} - - # Caution: - # This decorator may not create a task in the case where merge=True and - # another task having the same name have already been created. In this case, - # it will just reuse the former task. This is at the user responsibility to - # ensure that merged tasks would do the exact same thing. - # - # @builder.RegisterTask('hello') - # def TaskA(): - # my_object.a = 1 - # - # @builder.RegisterTask('hello', merge=True) - # def TaskB(): - # # This function won't be executed ever. - # my_object.a = 2 # <------- Wrong because different from what TaskA do. - # - # assert TaskA == TaskB - # TaskB.Execute() # Sets set my_object.a == 1 - def RegisterTask(self, task_name, dependencies=None, merge=False): - """Decorator that wraps a function into a task. - - Args: - task_name: The name of this new task to register. - dependencies: List of SandwichTarget to build before this task. - merge: If a task already have this name, don't create a new one and - reuse the existing one. - - Returns: - A Task that was created by wrapping the function or an existing registered - wrapper (that have wrapped a different function). - """ - rebased_task_name = self._RebaseTaskName(task_name) - dependencies = dependencies or [] - def InnerAddTaskWithNewPath(recipe): - if rebased_task_name in self._tasks: - if not merge: - raise TaskError('Task {} already exists.'.format(rebased_task_name)) - task = self._tasks[rebased_task_name] - return task - task_path = self.RebaseOutputPath(task_name) - task = Task(rebased_task_name, task_path, dependencies, recipe) - self._tasks[rebased_task_name] = task - return task - return InnerAddTaskWithNewPath - - def RebaseOutputPath(self, builder_relative_path): - """Rebases buider relative path.""" - return os.path.join( - self.output_directory, self._RebaseTaskName(builder_relative_path)) - - def _RebaseTaskName(self, task_name): - if self.output_subdirectory: - return os.path.join(self.output_subdirectory, task_name) - return task_name - - -def GenerateScenario(final_tasks, frozen_tasks): - """Generates a list of tasks to execute in order of dependencies-first. - - Args: - final_tasks: The final tasks to generate the scenario from. - frozen_tasks: Sets of task to freeze. - - Returns: - [Task] - """ - scenario = [] - task_paths = {} - def InternalAppendTarget(task): - if task in frozen_tasks: - if not os.path.exists(task.path): - raise TaskError('Frozen target `{}`\'s path doesn\'t exist.'.format( - task.name)) - return - if task.path in task_paths: - if task_paths[task.path] == None: - raise TaskError('Target `{}` depends on itself.'.format(task.name)) - if task_paths[task.path] != task: - raise TaskError( - 'Tasks `{}` and `{}` produce the same file: `{}`.'.format( - task.name, task_paths[task.path].name, task.path)) - return - task_paths[task.path] = None - for dependency in task._dependencies: - InternalAppendTarget(dependency) - task_paths[task.path] = task - scenario.append(task) - - for final_task in final_tasks: - InternalAppendTarget(final_task) - return scenario - - -def GenerateDependentSetPerTask(scenario): - """Maps direct dependents per tasks of scenario. - - Args: - scenario: The scenario containing the Tasks to map. - - Returns: - {Task: set(Task)} - """ - task_set = set(scenario) - task_children = collections.defaultdict(set) - for task in scenario: - for parent in task._dependencies: - if parent in task_set: - task_children[parent].add(task) - return task_children - - -def ListResumingTasksToFreeze(scenario, final_tasks, skipped_tasks): - """Lists the tasks that one needs to freeze to be able to resume the scenario - after failure. - - Args: - scenario: The scenario (list of Task) to be resumed. - final_tasks: The list of final Task used to generate the scenario. - skipped_tasks: Set of Tasks in the scenario that were skipped. - - Returns: - [Task] - """ - scenario_tasks = set(scenario) - assert skipped_tasks.issubset(scenario_tasks) - frozen_tasks = [] - frozen_task_set = set() - walked_tasks = set() - - def InternalWalk(task): - if task in walked_tasks: - return - walked_tasks.add(task) - if task not in scenario_tasks or task not in skipped_tasks: - if task not in frozen_task_set: - frozen_task_set.add(task) - frozen_tasks.append(task) - else: - for dependency in task._dependencies: - InternalWalk(dependency) - - for final_task in final_tasks: - InternalWalk(final_task) - return frozen_tasks - - -def OutputGraphViz(scenario, final_tasks, output): - """Outputs the build dependency graph covered by this scenario. - - Args: - scenario: The generated scenario. - final_tasks: The final tasks used to generate the scenario. - output: A file-like output stream to receive the dot file. - - Graph interpretations: - - Final tasks (the one that where directly appended) are box shaped. - - Non final tasks are ellipse shaped. - - Frozen tasks have a blue shape. - """ - task_execution_ids = {t: i for i, t in enumerate(scenario)} - tasks_node_ids = dict() - - def GetTaskNodeId(task): - if task in tasks_node_ids: - return tasks_node_ids[task] - node_id = len(tasks_node_ids) - node_label = task.name - node_color = 'blue' - node_shape = 'ellipse' - if task in task_execution_ids: - node_color = 'black' - node_label = str(task_execution_ids[task]) + ': ' + node_label - if task in final_tasks: - node_shape = 'box' - output.write(' n{} [label="{}", color={}, shape={}];\n'.format( - node_id, node_label, node_color, node_shape)) - tasks_node_ids[task] = node_id - return node_id - - output.write('digraph graphname {\n') - for task in scenario: - task_node_id = GetTaskNodeId(task) - for dep in task._dependencies: - dep_node_id = GetTaskNodeId(dep) - output.write(' n{} -> n{};\n'.format(dep_node_id, task_node_id)) - output.write('}\n') - - -def CommandLineParser(): - """Creates command line arguments parser meant to be used as a parent parser - for any entry point that use the ExecuteWithCommandLine() function. - - The root parser must be created with: - fromfile_prefix_chars=FROMFILE_PREFIX_CHARS. - - Returns: - The command line arguments parser. - """ - parser = argparse.ArgumentParser(add_help=False) - parser.add_argument('-d', '--dry-run', action='store_true', - help='Only prints the tasks to build.') - parser.add_argument('-e', '--to-execute', metavar='REGEX', type=str, - action='append', dest='run_regexes', default=[], - help='Regex selecting tasks to execute.') - parser.add_argument('-f', '--to-freeze', metavar='REGEX', type=str, - action='append', dest='frozen_regexes', default=[], - help='Regex selecting tasks to not execute.') - parser.add_argument('-k', '--keep-going', action='store_true', default=False, - help='Keep going when some targets can\'t be made.') - parser.add_argument('-o', '--output', type=str, required=True, - help='Path of the output directory.') - parser.add_argument('-v', '--output-graphviz', action='store_true', - help='Outputs the {} and {} file in the output directory.' - ''.format(_TASK_GRAPH_DOTFILE_NAME, _TASK_GRAPH_PNG_NAME)) - return parser - - -def _SelectTasksFromCommandLineRegexes(args, default_final_tasks): - frozen_regexes = [common_util.VerboseCompileRegexOrAbort(e) - for e in args.frozen_regexes] - run_regexes = [common_util.VerboseCompileRegexOrAbort(e) - for e in args.run_regexes] - - # Lists final tasks. - final_tasks = default_final_tasks - if run_regexes: - final_tasks = [] - # Traverse the graph in the normal execution order starting from - # |default_final_tasks| in case of command line regex selection. - tasks = GenerateScenario(default_final_tasks, frozen_tasks=set()) - # Order of run regexes prevails on the traversing order of tasks. - for regex in run_regexes: - for task in tasks: - if regex.search(task.name): - final_tasks.append(task) - - # Lists parents of |final_tasks| to freeze. - frozen_tasks = set() - impossible_tasks = set() - if frozen_regexes: - complete_scenario = GenerateScenario(final_tasks, frozen_tasks=set()) - dependents_per_task = GenerateDependentSetPerTask(complete_scenario) - def MarkTaskAsImpossible(task): - if task in impossible_tasks: - return - impossible_tasks.add(task) - for dependent in dependents_per_task[task]: - MarkTaskAsImpossible(dependent) - - for task in complete_scenario: - for regex in frozen_regexes: - if regex.search(task.name): - if os.path.exists(task.path): - frozen_tasks.add(task) - else: - MarkTaskAsImpossible(task) - break - - return [t for t in final_tasks if t not in impossible_tasks], frozen_tasks - - -class _ResumingFileBuilder(object): - def __init__(self, args): - resume_path = os.path.join(args.output, _TASK_RESUME_ARGUMENTS_FILE) - self._resume_output = open(resume_path, 'w') - # List initial freezing regexes not to loose track of final targets to - # freeze in case of severals resume attempts caused by sudden death. - for regex in args.frozen_regexes: - self._resume_output.write('-f\n{}\n'.format(regex)) - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, exc_traceback): - del exc_type, exc_value, exc_traceback # unused - self._resume_output.close() - - def OnTaskSuccess(self, task): - # Log the succeed tasks so that they are ensured to be frozen in case - # of a sudden death. - self._resume_output.write('-f\n^{}$\n'.format(re.escape(task.name))) - # Makes sure the task freezing command line make it to the disk. - self._resume_output.flush() - os.fsync(self._resume_output.fileno()) - - def OnScenarioFinish( - self, scenario, final_tasks, failed_tasks, skipped_tasks): - resume_additonal_arguments = [] - for task in ListResumingTasksToFreeze( - scenario, final_tasks, skipped_tasks): - resume_additonal_arguments.extend( - ['-f', '^{}$'.format(re.escape(task.name))]) - self._resume_output.seek(0) - self._resume_output.truncate() - self._resume_output.write('\n'.join(resume_additonal_arguments)) - print '# Looks like something went wrong in tasks:' - for failed_task in failed_tasks: - print '# {}'.format(failed_task.name) - print '#' - print '# To resume, append the following parameter:' - print '# ' + FROMFILE_PREFIX_CHARS + self._resume_output.name - - -def ExecuteWithCommandLine(args, default_final_tasks): - """Helper to execute tasks using command line arguments. - - Args: - args: Command line argument parsed with CommandLineParser(). - default_final_tasks: Default final tasks if there is no -r command - line arguments. - - Returns: - 0 if success or 1 otherwise - """ - # Builds the scenario. - final_tasks, frozen_tasks = _SelectTasksFromCommandLineRegexes( - args, default_final_tasks) - scenario = GenerateScenario(final_tasks, frozen_tasks) - if len(scenario) == 0: - logging.error('No tasks to build.') - return 1 - - if not os.path.isdir(args.output): - os.makedirs(args.output) - - # Print the task dependency graph visualization. - if args.output_graphviz: - graphviz_path = os.path.join(args.output, _TASK_GRAPH_DOTFILE_NAME) - png_graph_path = os.path.join(args.output, _TASK_GRAPH_PNG_NAME) - with open(graphviz_path, 'w') as output: - OutputGraphViz(scenario, final_tasks, output) - subprocess.check_call(['dot', '-Tpng', graphviz_path, '-o', png_graph_path]) - - # Use the build scenario. - if args.dry_run: - for task in scenario: - print task.name - return 0 - - # Run the Scenario while saving intermediate state to be able to resume later. - failed_tasks = [] - tasks_to_skip = set() - dependents_per_task = GenerateDependentSetPerTask(scenario) - - def MarkTaskNotToExecute(task): - if task not in tasks_to_skip: - logging.warning('can not execute task: %s', task.name) - tasks_to_skip.add(task) - for dependent in dependents_per_task[task]: - MarkTaskNotToExecute(dependent) - - log_filename = datetime.datetime.now().strftime( - _TASK_EXECUTION_LOG_NAME_FORMAT) - log_path = os.path.join(args.output, _TASK_LOGS_DIR_NAME, log_filename) - if not os.path.isdir(os.path.dirname(log_path)): - os.makedirs(os.path.dirname(log_path)) - formatter = logging.Formatter('[%(asctime)s] %(levelname)s: %(message)s') - handler = logging.FileHandler(log_path, mode='a') - handler.setFormatter(formatter) - logging.getLogger().addHandler(handler) - logging.info( - '%s %s', '-' * 60, common_util.GetCommandLineForLogging(sys.argv)) - try: - with _ResumingFileBuilder(args) as resume_file_builder: - for task_execute_id, task in enumerate(scenario): - if task in tasks_to_skip: - continue - logging.info('%s %s', '-' * 60, task.name) - try: - task.Execute() - except (MemoryError, SyntaxError): - raise - except BaseException: - # The resuming file being incrementally generated by - # resume_file_builder.OnTaskSuccess() is automatically fsynced(). - # But resume_file_builder.OnScenarioFinish() completely rewrite - # this file with the mininal subset of task to freeze, and in case - # of an ENOSPC, we don't want to touch the resuming file at all so - # that it remains uncorrupted. - if (sys.exc_info()[0] == IOError and - sys.exc_info()[1].errno == errno.ENOSPC): - raise - logging.exception('%s %s failed', '-' * 60, task.name) - failed_tasks.append(task) - if args.keep_going and sys.exc_info()[0] != KeyboardInterrupt: - MarkTaskNotToExecute(task) - else: - tasks_to_skip.update(set(scenario[task_execute_id:])) - break - else: - resume_file_builder.OnTaskSuccess(task) - if tasks_to_skip: - assert failed_tasks - resume_file_builder.OnScenarioFinish( - scenario, final_tasks, failed_tasks, tasks_to_skip) - if sys.exc_info()[0] == KeyboardInterrupt: - raise - return 1 - finally: - logging.getLogger().removeHandler(handler) - assert not failed_tasks - return 0
diff --git a/tools/android/loading/task_manager_unittest.py b/tools/android/loading/task_manager_unittest.py deleted file mode 100644 index f6e9788..0000000 --- a/tools/android/loading/task_manager_unittest.py +++ /dev/null
@@ -1,541 +0,0 @@ -# Copyright 2016 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. - -import argparse -import contextlib -import errno -import os -import re -import shutil -import StringIO -import sys -import tempfile -import unittest - -import common_util -import task_manager - - -_GOLDEN_GRAPHVIZ = """digraph graphname { - n0 [label="0: b", color=black, shape=ellipse]; - n1 [label="1: a", color=black, shape=ellipse]; - n2 [label="2: c", color=black, shape=ellipse]; - n0 -> n2; - n1 -> n2; - n3 [label="3: d", color=black, shape=ellipse]; - n2 -> n3; - n4 [label="4: f", color=black, shape=box]; - n3 -> n4; - n5 [label="e", color=blue, shape=ellipse]; - n5 -> n4; -}\n""" - - -@contextlib.contextmanager -def EatStdoutAndStderr(): - """Overrides sys.std{out,err} to intercept write calls.""" - sys.stdout.flush() - sys.stderr.flush() - original_stdout = sys.stdout - original_stderr = sys.stderr - try: - sys.stdout = StringIO.StringIO() - sys.stderr = StringIO.StringIO() - yield - finally: - sys.stdout = original_stdout - sys.stderr = original_stderr - - -class TestException(Exception): - pass - - -class TaskManagerTestCase(unittest.TestCase): - def setUp(self): - self.output_directory = tempfile.mkdtemp() - - def tearDown(self): - shutil.rmtree(self.output_directory) - - def OutputPath(self, file_path): - return os.path.join(self.output_directory, file_path) - - def TouchOutputFile(self, file_path): - with open(self.OutputPath(file_path), 'w') as output: - output.write(file_path + '\n') - - -class TaskTest(TaskManagerTestCase): - def testTaskExecution(self): - def Recipe(): - Recipe.counter += 1 - Recipe.counter = 0 - task = task_manager.Task('hello.json', 'what/ever/hello.json', [], Recipe) - self.assertFalse(task._is_done) - self.assertEqual(0, Recipe.counter) - task.Execute() - self.assertEqual(1, Recipe.counter) - task.Execute() - self.assertEqual(1, Recipe.counter) - - def testTaskExecutionWithUnexecutedDeps(self): - def RecipeA(): - self.fail() - - def RecipeB(): - RecipeB.counter += 1 - RecipeB.counter = 0 - - a = task_manager.Task('hello.json', 'out/hello.json', [], RecipeA) - b = task_manager.Task('hello.json', 'out/hello.json', [a], RecipeB) - self.assertEqual(0, RecipeB.counter) - b.Execute() - self.assertEqual(1, RecipeB.counter) - - -class BuilderTest(TaskManagerTestCase): - def testRegisterTask(self): - builder = task_manager.Builder(self.output_directory, None) - @builder.RegisterTask('hello.txt') - def TaskA(): - TaskA.executed = True - TaskA.executed = False - self.assertEqual(os.path.join(self.output_directory, 'hello.txt'), - TaskA.path) - self.assertFalse(TaskA.executed) - TaskA.Execute() - self.assertTrue(TaskA.executed) - - def testRegisterDuplicateTask(self): - builder = task_manager.Builder(self.output_directory, None) - @builder.RegisterTask('hello.txt') - def TaskA(): - pass - del TaskA # unused - with self.assertRaises(task_manager.TaskError): - @builder.RegisterTask('hello.txt') - def TaskB(): - pass - del TaskB # unused - - def testTaskMerging(self): - builder = task_manager.Builder(self.output_directory, None) - @builder.RegisterTask('hello.txt') - def TaskA(): - pass - @builder.RegisterTask('hello.txt', merge=True) - def TaskB(): - pass - self.assertEqual(TaskA, TaskB) - - def testOutputSubdirectory(self): - builder = task_manager.Builder(self.output_directory, 'subdir') - - @builder.RegisterTask('world.txt') - def TaskA(): - pass - del TaskA # unused - - self.assertIn('subdir/world.txt', builder._tasks) - self.assertNotIn('subdir/subdir/world.txt', builder._tasks) - self.assertNotIn('world.txt', builder._tasks) - - @builder.RegisterTask('subdir/world.txt') - def TaskB(): - pass - del TaskB # unused - self.assertIn('subdir/subdir/world.txt', builder._tasks) - self.assertNotIn('world.txt', builder._tasks) - - -class GenerateScenarioTest(TaskManagerTestCase): - def testParents(self): - builder = task_manager.Builder(self.output_directory, None) - @builder.RegisterTask('a') - def TaskA(): - pass - @builder.RegisterTask('b', dependencies=[TaskA]) - def TaskB(): - pass - @builder.RegisterTask('c', dependencies=[TaskB]) - def TaskC(): - pass - scenario = task_manager.GenerateScenario([TaskA, TaskB, TaskC], set()) - self.assertListEqual([TaskA, TaskB, TaskC], scenario) - - scenario = task_manager.GenerateScenario([TaskB], set()) - self.assertListEqual([TaskA, TaskB], scenario) - - scenario = task_manager.GenerateScenario([TaskC], set()) - self.assertListEqual([TaskA, TaskB, TaskC], scenario) - - scenario = task_manager.GenerateScenario([TaskC, TaskB], set()) - self.assertListEqual([TaskA, TaskB, TaskC], scenario) - - def testFreezing(self): - builder = task_manager.Builder(self.output_directory, None) - @builder.RegisterTask('a') - def TaskA(): - pass - @builder.RegisterTask('b', dependencies=[TaskA]) - def TaskB(): - pass - @builder.RegisterTask('c') - def TaskC(): - pass - @builder.RegisterTask('d', dependencies=[TaskB, TaskC]) - def TaskD(): - pass - - # assert no exception raised. - task_manager.GenerateScenario([TaskB], set([TaskC])) - - with self.assertRaises(task_manager.TaskError): - task_manager.GenerateScenario([TaskD], set([TaskA])) - - self.TouchOutputFile('a') - scenario = task_manager.GenerateScenario([TaskD], set([TaskA])) - self.assertListEqual([TaskB, TaskC, TaskD], scenario) - - self.TouchOutputFile('b') - scenario = task_manager.GenerateScenario([TaskD], set([TaskB])) - self.assertListEqual([TaskC, TaskD], scenario) - - def testCycleError(self): - builder = task_manager.Builder(self.output_directory, None) - @builder.RegisterTask('a') - def TaskA(): - pass - @builder.RegisterTask('b', dependencies=[TaskA]) - def TaskB(): - pass - @builder.RegisterTask('c', dependencies=[TaskB]) - def TaskC(): - pass - @builder.RegisterTask('d', dependencies=[TaskC]) - def TaskD(): - pass - TaskA._dependencies.append(TaskC) - with self.assertRaises(task_manager.TaskError): - task_manager.GenerateScenario([TaskD], set()) - - def testCollisionError(self): - builder_a = task_manager.Builder(self.output_directory, None) - builder_b = task_manager.Builder(self.output_directory, None) - @builder_a.RegisterTask('a') - def TaskA(): - pass - @builder_b.RegisterTask('a') - def TaskB(): - pass - with self.assertRaises(task_manager.TaskError): - task_manager.GenerateScenario([TaskA, TaskB], set()) - - def testGenerateDependentSetPerTask(self): - builder = task_manager.Builder(self.output_directory, None) - @builder.RegisterTask('a') - def TaskA(): - pass - @builder.RegisterTask('b') - def TaskB(): - pass - @builder.RegisterTask('c', dependencies=[TaskA, TaskB]) - def TaskC(): - pass - @builder.RegisterTask('d', dependencies=[TaskA]) - def TaskD(): - pass - - def RunSubTest(expected, scenario, task): - self.assertEqual( - expected, task_manager.GenerateDependentSetPerTask(scenario)[task]) - - RunSubTest(set([]), [TaskA], TaskA) - RunSubTest(set([]), [TaskA, TaskB], TaskA) - RunSubTest(set([TaskC]), [TaskA, TaskB, TaskC], TaskA) - RunSubTest(set([TaskC, TaskD]), [TaskA, TaskB, TaskC, TaskD], TaskA) - RunSubTest(set([]), [TaskA, TaskD], TaskD) - - def testGraphVizOutput(self): - builder = task_manager.Builder(self.output_directory, None) - @builder.RegisterTask('a') - def TaskA(): - pass - @builder.RegisterTask('b') - def TaskB(): - pass - @builder.RegisterTask('c', dependencies=[TaskB, TaskA]) - def TaskC(): - pass - @builder.RegisterTask('d', dependencies=[TaskC]) - def TaskD(): - pass - @builder.RegisterTask('e') - def TaskE(): - pass - @builder.RegisterTask('f', dependencies=[TaskD, TaskE]) - def TaskF(): - pass - self.TouchOutputFile('e') - scenario = task_manager.GenerateScenario([TaskF], set([TaskE])) - output = StringIO.StringIO() - task_manager.OutputGraphViz(scenario, [TaskF], output) - self.assertEqual(_GOLDEN_GRAPHVIZ, output.getvalue()) - - def testListResumingTasksToFreeze(self): - TaskManagerTestCase.setUp(self) - builder = task_manager.Builder(self.output_directory, None) - @builder.RegisterTask('a') - def TaskA(): - pass - @builder.RegisterTask('b') - def TaskB(): - pass - @builder.RegisterTask('c', dependencies=[TaskA, TaskB]) - def TaskC(): - pass - @builder.RegisterTask('d', dependencies=[TaskA]) - def TaskD(): - pass - @builder.RegisterTask('e', dependencies=[TaskC]) - def TaskE(): - pass - @builder.RegisterTask('f', dependencies=[TaskC]) - def TaskF(): - pass - - for k in 'abcdef': - self.TouchOutputFile(k) - - def RunSubTest( - final_tasks, initial_frozen_tasks, skipped_tasks, reference): - scenario = task_manager.GenerateScenario( - final_tasks, initial_frozen_tasks) - resume_frozen_tasks = task_manager.ListResumingTasksToFreeze( - scenario, final_tasks, skipped_tasks) - self.assertEqual(reference, resume_frozen_tasks) - - new_scenario = \ - task_manager.GenerateScenario(final_tasks, resume_frozen_tasks) - self.assertEqual(skipped_tasks, set(new_scenario)) - - RunSubTest([TaskA], set([]), set([TaskA]), []) - RunSubTest([TaskD], set([]), set([TaskA, TaskD]), []) - RunSubTest([TaskD], set([]), set([TaskD]), [TaskA]) - RunSubTest([TaskE, TaskF], set([TaskA]), set([TaskB, TaskC, TaskE, TaskF]), - [TaskA]) - RunSubTest([TaskE, TaskF], set([TaskA]), set([TaskC, TaskE, TaskF]), - [TaskA, TaskB]) - RunSubTest([TaskE, TaskF], set([TaskA]), set([TaskE, TaskF]), [TaskC]) - RunSubTest([TaskE, TaskF], set([TaskA]), set([TaskF]), [TaskE, TaskC]) - RunSubTest([TaskD, TaskE, TaskF], set([]), set([TaskD, TaskF]), - [TaskA, TaskE, TaskC]) - - -class CommandLineControlledExecutionTest(TaskManagerTestCase): - def setUp(self): - TaskManagerTestCase.setUp(self) - self.with_raise_exception_tasks = False - self.task_execution_history = None - - def Execute(self, command_line_args): - self.task_execution_history = [] - builder = task_manager.Builder(self.output_directory, None) - @builder.RegisterTask('a') - def TaskA(): - self.task_execution_history.append(TaskA.name) - @builder.RegisterTask('b') - def TaskB(): - self.task_execution_history.append(TaskB.name) - @builder.RegisterTask('c', dependencies=[TaskA, TaskB]) - def TaskC(): - self.task_execution_history.append(TaskC.name) - @builder.RegisterTask('d', dependencies=[TaskA]) - def TaskD(): - self.task_execution_history.append(TaskD.name) - @builder.RegisterTask('e', dependencies=[TaskC]) - def TaskE(): - self.task_execution_history.append(TaskE.name) - @builder.RegisterTask('raise_exception', dependencies=[TaskD]) - def RaiseExceptionTask(): - self.task_execution_history.append(RaiseExceptionTask.name) - raise TestException('Expected error.') - @builder.RegisterTask('raise_keyboard_interrupt', dependencies=[TaskD]) - def RaiseKeyboardInterruptTask(): - self.task_execution_history.append(RaiseKeyboardInterruptTask.name) - raise KeyboardInterrupt - @builder.RegisterTask('sudden_death', dependencies=[TaskD]) - def SimulateKillTask(): - self.task_execution_history.append(SimulateKillTask.name) - raise MemoryError - @builder.RegisterTask('timeout_error', dependencies=[TaskD]) - def SimulateTimeoutError(): - self.task_execution_history.append(SimulateTimeoutError.name) - raise common_util.TimeoutError - @builder.RegisterTask('errno_ENOSPC', dependencies=[TaskD]) - def SimulateENOSPC(): - self.task_execution_history.append(SimulateENOSPC.name) - raise IOError(errno.ENOSPC, os.strerror(errno.ENOSPC)) - @builder.RegisterTask('errno_EPERM', dependencies=[TaskD]) - def SimulateEPERM(): - self.task_execution_history.append(SimulateEPERM.name) - raise IOError(errno.EPERM, os.strerror(errno.EPERM)) - - default_final_tasks = [TaskD, TaskE] - if self.with_raise_exception_tasks: - default_final_tasks.extend([ - RaiseExceptionTask, - RaiseKeyboardInterruptTask, - SimulateKillTask, - SimulateTimeoutError, - SimulateENOSPC, - SimulateEPERM]) - task_parser = task_manager.CommandLineParser() - parser = argparse.ArgumentParser(parents=[task_parser], - fromfile_prefix_chars=task_manager.FROMFILE_PREFIX_CHARS) - cmd = ['-o', self.output_directory] - cmd.extend([i for i in command_line_args]) - args = parser.parse_args(cmd) - with EatStdoutAndStderr(): - return task_manager.ExecuteWithCommandLine(args, default_final_tasks) - - def ResumeFilePath(self): - return self.OutputPath(task_manager._TASK_RESUME_ARGUMENTS_FILE) - - def ResumeCmd(self): - return task_manager.FROMFILE_PREFIX_CHARS + self.ResumeFilePath() - - def testSimple(self): - self.assertEqual(0, self.Execute([])) - self.assertListEqual(['a', 'd', 'b', 'c', 'e'], self.task_execution_history) - - def testDryRun(self): - self.assertEqual(0, self.Execute(['-d'])) - self.assertListEqual([], self.task_execution_history) - - def testRegex(self): - self.assertEqual(0, self.Execute(['-e', 'b', '-e', 'd'])) - self.assertListEqual(['b', 'a', 'd'], self.task_execution_history) - self.assertEqual(1, self.Execute(['-e', r'\d'])) - self.assertListEqual([], self.task_execution_history) - - def testFreezing(self): - self.assertEqual(0, self.Execute(['-f', r'\d'])) - self.assertListEqual(['a', 'd', 'b', 'c', 'e'], self.task_execution_history) - self.TouchOutputFile('c') - self.assertEqual(0, self.Execute(['-f', 'c'])) - self.assertListEqual(['a', 'd', 'e'], self.task_execution_history) - - def testDontFreezeUnreachableTasks(self): - self.TouchOutputFile('c') - self.assertEqual(0, self.Execute(['-e', 'e', '-f', 'c', '-f', 'd'])) - - def testAbortOnFirstError(self): - ARGS = ['-e', 'exception', '-e', r'^b$'] - self.with_raise_exception_tasks = True - self.assertEqual(1, self.Execute(ARGS)) - self.assertListEqual( - ['a', 'd', 'raise_exception'], self.task_execution_history) - with open(self.ResumeFilePath()) as resume_input: - self.assertEqual('-f\n^d$', resume_input.read()) - - self.TouchOutputFile('d') - self.assertEqual(1, self.Execute(ARGS + [self.ResumeCmd()])) - self.assertListEqual(['raise_exception'], self.task_execution_history) - - self.assertEqual(1, self.Execute(ARGS + [self.ResumeCmd()])) - self.assertListEqual(['raise_exception'], self.task_execution_history) - - self.assertEqual(1, self.Execute(ARGS + [self.ResumeCmd(), '-k'])) - self.assertListEqual(['raise_exception', 'b'], self.task_execution_history) - - def testKeepGoing(self): - ARGS = ['-k', '-e', 'exception', '-e', r'^b$'] - self.with_raise_exception_tasks = True - self.assertEqual(1, self.Execute(ARGS)) - self.assertListEqual( - ['a', 'd', 'raise_exception', 'b'], self.task_execution_history) - with open(self.ResumeFilePath()) as resume_input: - self.assertEqual('-f\n^d$\n-f\n^b$', resume_input.read()) - - self.TouchOutputFile('d') - self.TouchOutputFile('b') - self.assertEqual(1, self.Execute(ARGS + [self.ResumeCmd()])) - self.assertListEqual(['raise_exception'], self.task_execution_history) - - self.assertEqual(1, self.Execute(ARGS + [self.ResumeCmd()])) - self.assertListEqual(['raise_exception'], self.task_execution_history) - - def testKeyboardInterrupt(self): - self.with_raise_exception_tasks = True - with self.assertRaises(KeyboardInterrupt): - self.Execute( - ['-k', '-e', 'raise_keyboard_interrupt', '-e', r'^b$']) - self.assertListEqual(['a', 'd', 'raise_keyboard_interrupt'], - self.task_execution_history) - with open(self.ResumeFilePath()) as resume_input: - self.assertEqual('-f\n^d$', resume_input.read()) - - def testResumeAfterSuddenDeath(self): - EXPECTED_RESUME_FILE_CONTENT = '-f\n^a$\n-f\n^d$\n' - ARGS = ['-k', '-e', 'sudden_death', '-e', r'^a$'] - self.with_raise_exception_tasks = True - with self.assertRaises(MemoryError): - self.Execute(ARGS) - self.assertListEqual( - ['a', 'd', 'sudden_death'], self.task_execution_history) - with open(self.ResumeFilePath()) as resume_input: - self.assertEqual(EXPECTED_RESUME_FILE_CONTENT, resume_input.read()) - - self.TouchOutputFile('a') - self.TouchOutputFile('d') - with self.assertRaises(MemoryError): - self.Execute(ARGS + [self.ResumeCmd()]) - self.assertListEqual(['sudden_death'], self.task_execution_history) - with open(self.ResumeFilePath()) as resume_input: - self.assertEqual(EXPECTED_RESUME_FILE_CONTENT, resume_input.read()) - - with self.assertRaises(MemoryError): - self.Execute(ARGS + [self.ResumeCmd()]) - self.assertListEqual(['sudden_death'], self.task_execution_history) - with open(self.ResumeFilePath()) as resume_input: - self.assertEqual(EXPECTED_RESUME_FILE_CONTENT, resume_input.read()) - - def testTimeoutError(self): - self.with_raise_exception_tasks = True - self.Execute(['-k', '-e', 'timeout_error', '-e', r'^b$']) - self.assertListEqual(['a', 'd', 'timeout_error', 'b'], - self.task_execution_history) - with open(self.ResumeFilePath()) as resume_input: - self.assertEqual('-f\n^d$\n-f\n^b$', resume_input.read()) - - def testENOSPC(self): - self.with_raise_exception_tasks = True - with self.assertRaises(IOError): - self.Execute(['-k', '-e', 'errno_ENOSPC', '-e', r'^a$']) - self.assertListEqual( - ['a', 'd', 'errno_ENOSPC'], self.task_execution_history) - with open(self.ResumeFilePath()) as resume_input: - self.assertEqual('-f\n^a$\n-f\n^d$\n', resume_input.read()) - - def testEPERM(self): - self.with_raise_exception_tasks = True - self.Execute(['-k', '-e', 'errno_EPERM', '-e', r'^b$']) - self.assertListEqual(['a', 'd', 'errno_EPERM', 'b'], - self.task_execution_history) - with open(self.ResumeFilePath()) as resume_input: - self.assertEqual('-f\n^d$\n-f\n^b$', resume_input.read()) - - def testImpossibleTasks(self): - self.assertEqual(1, self.Execute(['-f', r'^a$', '-e', r'^c$'])) - self.assertListEqual([], self.task_execution_history) - - self.assertEqual(0, self.Execute( - ['-f', r'^a$', '-e', r'^c$', '-e', r'^b$'])) - self.assertListEqual(['b'], self.task_execution_history) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/test_utils.py b/tools/android/loading/test_utils.py deleted file mode 100644 index 2b2479cd..0000000 --- a/tools/android/loading/test_utils.py +++ /dev/null
@@ -1,257 +0,0 @@ -# Copyright 2016 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. - -"""Common utilities used in unit tests, within this directory.""" - -import clovis_constants -import dependency_graph -import devtools_monitor -import loading_trace -import page_track -import request_track -import tracing_track -import user_satisfied_lens - - -class FakeRequestTrack(devtools_monitor.Track): - def __init__(self, events): - super(FakeRequestTrack, self).__init__(None) - self._events = events - for e in self._events: - e.timing.request_time = e.timestamp - - def Handle(self, _method, _msg): - assert False # Should never be called. - - def GetEvents(self): - return self._events - - def ToJsonDict(self): - cls = request_track.RequestTrack - return {cls._EVENTS_KEY: [ - rq.ToJsonDict() for rq in self.GetEvents()], - cls._METADATA_KEY: { - cls._DUPLICATES_KEY: 0, - cls._INCONSISTENT_INITIATORS_KEY: 0}} - - -class FakePageTrack(devtools_monitor.Track): - def __init__(self, events): - super(FakePageTrack, self).__init__(None) - self._events = events - - def Handle(self, _method, _msg): - assert False # Should never be called. - - def GetEvents(self): - return self._events - - def GetMainFrameId(self): - event = self._events[0] - # Make sure our laziness is not an issue here. - assert event['method'] == page_track.PageTrack.FRAME_STARTED_LOADING - return event['frame_id'] - - def ToJsonDict(self): - return {'events': [event for event in self._events]} - - -def MakeRequestWithTiming( - url, source_url, timing_dict, magic_content_type=False, - initiator_type='other'): - """Make a dependent request. - - Args: - url: a url, or number which will be used as a url. - source_url: a url or number which will be used as the source (initiating) - url. If the source url is not present, then url will be a root. The - convention in tests is to use a source_url of 'null' in this case. - timing_dict: (dict) Suitable to be passed to request_track.Timing(). - initiator_type: the initiator type to use. - - Returns: - A request_track.Request. - """ - assert initiator_type in ('other', 'parser') - timing = request_track.Timing.FromDevToolsDict(timing_dict) - rq = request_track.Request.FromJsonDict({ - 'timestamp': timing.request_time, - 'request_id': str(MakeRequestWithTiming._next_request_id), - 'url': 'http://' + str(url), - 'initiator': {'type': initiator_type, 'url': 'http://' + str(source_url)}, - 'response_headers': {'Content-Type': - 'null' if not magic_content_type - else 'magic-debug-content' }, - 'timing': timing.ToJsonDict() - }) - MakeRequestWithTiming._next_request_id += 1 - return rq - - -MakeRequestWithTiming._next_request_id = 0 - - -def MakeRequest( - url, source_url, start_time=None, headers_time=None, end_time=None, - magic_content_type=False, initiator_type='other'): - """Make a dependent request. - - Args: - url: a url, or number which will be used as a url. - source_url: a url or number which will be used as the source (initiating) - url. If the source url is not present, then url will be a root. The - convention in tests is to use a source_url of 'null' in this case. - start_time: The request start time in milliseconds. If None, this is set to - the current request id in seconds. If None, the two other time parameters - below must also be None. - headers_time: The timestamp when resource headers were received, or None. - end_time: The timestamp when the resource was finished, or None. - magic_content_type (bool): if true, set a magic content type that makes url - always be detected as a valid source and destination request. - initiator_type: the initiator type to use. - - Returns: - A request_track.Request. - """ - assert ((start_time is None and - headers_time is None and - end_time is None) or - (start_time is not None and - headers_time is not None and - end_time is not None)), \ - 'Need no time specified or all times specified' - if start_time is None: - # Use the request id in seconds for timestamps. This guarantees increasing - # times which makes request dependencies behave as expected. - start_time = headers_time = end_time = ( - MakeRequestWithTiming._next_request_id * 1000) - timing_dict = { - # connectEnd should be ignored. - 'connectEnd': (end_time - start_time) / 2, - 'receiveHeadersEnd': headers_time - start_time, - 'loadingFinished': end_time - start_time, - 'requestTime': start_time / 1000.0} - return MakeRequestWithTiming( - url, source_url, timing_dict, magic_content_type, initiator_type) - - -def LoadingTraceFromEvents(requests, page_events=None, trace_events=None): - """Returns a LoadingTrace instance from various events.""" - request = FakeRequestTrack(requests) - page_event_track = FakePageTrack(page_events if page_events else []) - if trace_events is not None: - track = tracing_track.TracingTrack(None, - clovis_constants.DEFAULT_CATEGORIES) - track.Handle('Tracing.dataCollected', - {'params': {'value': [e for e in trace_events]}}) - else: - track = None - return loading_trace.LoadingTrace( - None, None, page_event_track, request, track) - - -class SimpleLens(object): - """A simple replacement for RequestDependencyLens. - - Uses only the initiator url of a request for determining a dependency. - """ - def __init__(self, trace): - self._trace = trace - - def GetRequestDependencies(self): - url_to_rq = {} - deps = [] - for rq in self._trace.request_track.GetEvents(): - assert rq.url not in url_to_rq - url_to_rq[rq.url] = rq - for rq in self._trace.request_track.GetEvents(): - initiating_url = rq.initiator['url'] - if initiating_url in url_to_rq: - deps.append((url_to_rq[initiating_url], rq, rq.initiator['type'])) - return deps - - -class TestDependencyGraph(dependency_graph.RequestDependencyGraph): - """A dependency graph created from requests using a simple lens.""" - def __init__(self, requests): - lens = SimpleLens(LoadingTraceFromEvents(requests)) - super(TestDependencyGraph, self).__init__(requests, lens) - - -class MockConnection(object): - """Mock out connection for testing. - - Use Expect* for requests expecting a repsonse. SyncRequestNoResponse puts - requests into no_response_requests_seen. - - TODO(mattcary): use a standard mock system (the back-ported python3 - unittest.mock? devil.utils.mock_calls?) - - """ - def __init__(self, test_case): - # List of (method, params) tuples. - self.no_response_requests_seen = [] - - self._test_case = test_case - self._expected_responses = {} - - def ExpectSyncRequest(self, response, method, params=None): - """Test method when the connection is expected to make a SyncRequest. - - Args: - response: (dict) the response to generate. - method: (str) the expected method in the call. - params: (dict) the expected params in the call. - """ - self._expected_responses.setdefault(method, []).append((params, response)) - - def AllExpectationsUsed(self): - """Returns true when all expectations where used.""" - return not self._expected_responses - - def SyncRequestNoResponse(self, method, params): - """Mocked method.""" - self.no_response_requests_seen.append((method, params)) - - def SyncRequest(self, method, params=None): - """Mocked method.""" - expected_params, response = self._expected_responses[method].pop(0) - if not self._expected_responses[method]: - del self._expected_responses[method] - self._test_case.assertEqual(expected_params, params) - return response - - -class MockUserSatisfiedLens(user_satisfied_lens._FirstEventLens): - def _CalculateTimes(self, _): - self._satisfied_msec = float('inf') - self._event_msec = float('inf') - - -class TraceCreator(object): - def __init__(self): - self._request_index = 1 - - def RequestAt(self, timestamp_msec, duration=1, frame_id=None): - timestamp_sec = float(timestamp_msec) / 1000 - rq = request_track.Request.FromJsonDict({ - 'url': 'http://bla-%s-.com' % timestamp_msec, - 'document_url': 'http://bla.com', - 'request_id': '0.%s' % self._request_index, - 'frame_id': frame_id or '123.%s' % timestamp_msec, - 'initiator': {'type': 'other'}, - 'timestamp': timestamp_sec, - 'timing': {'request_time': timestamp_sec, - 'loading_finished': duration}, - 'status': 200}) - self._request_index += 1 - return rq - - def CreateTrace(self, requests, events, main_frame_id): - page_event = {'method': 'Page.frameStartedLoading', - 'frame_id': main_frame_id} - trace = LoadingTraceFromEvents( - requests, trace_events=events, page_events=[page_event]) - trace.tracing_track.SetMainFrameID(main_frame_id) - return trace
diff --git a/tools/android/loading/testdata/scanner_vs_parser.trace b/tools/android/loading/testdata/scanner_vs_parser.trace deleted file mode 100644 index 991fe8b..0000000 --- a/tools/android/loading/testdata/scanner_vs_parser.trace +++ /dev/null
@@ -1,231 +0,0 @@ -{ - "metadata": {}, - "page_track": { - "events": [] - }, - "request_track": { - "events": [ - { - "initiator": { - "type": "other" - }, - "protocol": "http/1.0", - "url": "http://l/" - }, - { - "initiator": { - "lineNumber": 28, - "type": "parser", - "url": "http://l/" - }, - "protocol": "data", - "url": "data:image/png;base64,iVBO[PRUNED]" - }, - { - "initiator": { - "lineNumber": 21, - "type": "parser", - "url": "http://l/" - }, - "protocol": "http/1.0", - "url": "http://l/0.png" - }, - { - "initiator": { - "type": "parser", - "url": "http://l/" - }, - "protocol": "http/1.0", - "url": "http://l/1.png" - }, - { - "initiator": { - "lineNumber": 22, - "type": "parser", - "url": "http://l/" - }, - "protocol": "http/1.0", - "url": "http://l/0.css" - }, - { - "initiator": { - "type": "other" - }, - "protocol": "http/1.0", - "url": "http://l/favicon.ico" - } - ], - "metadata": { - "duplicates_count": 0, - "inconsistent_initiators": 0 - } - }, - "tracing_track": { - "categories": [], - "events": [ - { - "args": { - "data": { - "priority": 4, - "url": "http://l/" - } - }, - "cat": "blink.net", - "name": "Resource", - "ph": "S", - "pid": 3, - "ts": 1213697828839, - "id": 0 - }, - { - "args": {}, - "cat": "blink.net", - "name": "Resource", - "ph": "F", - "pid": 3, - "ts": 1213697889955, - "id": 0 - }, - { - "args": { - "data": { - "priority": 1, - "url": "http://l/0.png" - } - }, - "cat": "blink.net", - "name": "Resource", - "ph": "S", - "pid": 3, - "ts": 1213697891911, - "id": 1 - }, - { - "args": { - "step": "Preload" - }, - "cat": "blink.net", - "name": "Resource", - "ph": "T", - "pid": 3, - "ts": 1213697892658, - "id": 1 - }, - { - "args": { - "data": { - "priority": 1, - "url": "http://l/0.css" - } - }, - "cat": "blink.net", - "name": "Resource", - "ph": "S", - "pid": 3, - "ts": 1213697892660, - "id": 2 - }, - { - "args": { - "step": "Preload" - }, - "cat": "blink.net", - "name": "Resource", - "ph": "T", - "pid": 3, - "ts": 1213697892661, - "id": 2 - }, - { - "args": { - "data": { - "priority": 1, - "url": "http://l/1.png" - } - }, - "cat": "blink.net", - "name": "Resource", - "ph": "S", - "pid": 3, - "ts": 1213697934273, - "id": 3 - }, - { - "args": { - "priority": 3, - "step": "ChangePriority" - }, - "cat": "blink.net", - "name": "Resource", - "ph": "T", - "pid": 3, - "ts": 1213697984606, - "id": 0 - }, - { - "args": {}, - "cat": "blink.net", - "name": "Resource", - "ph": "F", - "pid": 3, - "ts": 1213697943810, - "id": 1 - }, - { - "args": { - "priority": 3, - "step": "ChangePriority" - }, - "cat": "blink.net", - "name": "Resource", - "ph": "T", - "pid": 3, - "ts": 1213697984875, - "id": 1 - }, - { - "args": { - "priority": 3, - "step": "ChangePriority" - }, - "cat": "blink.net", - "name": "Resource", - "ph": "T", - "pid": 3, - "ts": 1213697985346, - "id": 2 - }, - { - "args": { - "priority": 3, - "step": "ChangePriority" - }, - "cat": "blink.net", - "name": "Resource", - "ph": "T", - "pid": 3, - "ts": 1213697985346, - "id": 3 - }, - { - "args": {}, - "cat": "blink.net", - "name": "Resource", - "ph": "F", - "pid": 3, - "ts": 1213698035637, - "id": 2 - }, - { - "args": {}, - "cat": "blink.net", - "name": "Resource", - "ph": "F", - "pid": 3, - "ts": 1213698035637, - "id": 3 - } - ] - }, - "url": "http://l/" -}
diff --git a/tools/android/loading/trace_test/README.md b/tools/android/loading/trace_test/README.md deleted file mode 100644 index c16e472..0000000 --- a/tools/android/loading/trace_test/README.md +++ /dev/null
@@ -1,8 +0,0 @@ -Trace Integration Tests - -This directory defines integration tests which verify traces in various corners -of the HTML/JS/CSS world. - -The unittests in this directory are run as part of -tools/android/loading/run_tests. The integration tests are only run -manually. See webserver_test.py for details.
diff --git a/tools/android/loading/trace_test/__init__.py b/tools/android/loading/trace_test/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/tools/android/loading/trace_test/__init__.py +++ /dev/null
diff --git a/tools/android/loading/trace_test/results/1.result b/tools/android/loading/trace_test/results/1.result deleted file mode 100644 index 0b445dc2..0000000 --- a/tools/android/loading/trace_test/results/1.result +++ /dev/null
@@ -1,7 +0,0 @@ -parser (no stack) 1.css -parser (no stack) 1a.js -parser (no stack) 1a.png -parser (no stack) 1b.png -script (1a.js:9) 1b.js -script (1b.js:54) 1.ttf -script (1b.js:54) application/font-wof...Zk73/mAw==
diff --git a/tools/android/loading/trace_test/results/2.result b/tools/android/loading/trace_test/results/2.result deleted file mode 100644 index 6fe8a06f..0000000 --- a/tools/android/loading/trace_test/results/2.result +++ /dev/null
@@ -1,5 +0,0 @@ -parser (no stack) 1.css -parser (no stack) 1a.png -parser (no stack) 1b.js -parser (no stack) 1b.png -parser (no stack) application/font-wof...Zk73/mAw==
diff --git a/tools/android/loading/trace_test/results/3.result b/tools/android/loading/trace_test/results/3.result deleted file mode 100644 index 196a88d..0000000 --- a/tools/android/loading/trace_test/results/3.result +++ /dev/null
@@ -1,6 +0,0 @@ -parser (no stack) 3a.js -parser (no stack) 3c.js -script (3a.js:10/3a.js:14/3.html:20) 3a.jpg -script (3a.js:20) 3b.js -script (3b.js:9) 3b.jpg -script (3c.js:7/3.html:21) 3c.jpg
diff --git a/tools/android/loading/trace_test/test_server.py b/tools/android/loading/trace_test/test_server.py deleted file mode 100755 index 45517f7e..0000000 --- a/tools/android/loading/trace_test/test_server.py +++ /dev/null
@@ -1,110 +0,0 @@ -#! /usr/bin/python -# Copyright 2016 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. - -"""A simple http server for running local integration tests. - -This chooses a port dynamically and so can communicate that back to its spawner -via a named pipe at --fifo. Sources are served from the tree named at ---source_dir. -""" - - -import argparse -import cgi -import json -import os.path -import logging -import re -import time -import wsgiref.simple_server - - -_CONTENT_TYPE_FOR_SUFFIX = { - 'css': 'text/css', - 'html': 'text/html', - 'jpg': 'image/jpeg', - 'js': 'text/javascript', - 'json': 'application/json', - 'png': 'image/png', - 'ttf': 'font/ttf',} - -# Name of the JSON file containing per file custom response headers located in -# the --source_dir. -# This file should structured like: -# { -# 'mydocument.html': [ -# ['Cache-Control', 'max-age=3600'], -# ['Content-Encoding', 'gzip'], -# ] -# } -RESPONSE_HEADERS_PATH = 'RESPONSE_HEADERS.json' - - -class ServerApp(object): - """WSGI App. - - Dispatches by matching, in order, against GetPaths. - """ - def __init__(self, source_dir): - self._source_dir = source_dir - self._response_headers = {} - response_header_path = os.path.join(source_dir, RESPONSE_HEADERS_PATH) - if os.path.exists(response_header_path): - with open(response_header_path) as response_headers_file: - self._response_headers = json.load(response_headers_file) - - def __call__(self, environ, start_response): - """WSGI dispatch. - - Args: - environ: environment list. - start_response: WSGI response start. - - Returns: - Iterable server result. - """ - path = environ.get('PATH_INFO', '') - while path.startswith('/'): - path = path[1:] - filename = os.path.join(self._source_dir, path) - if not os.path.exists(filename): - logging.info('%s not found', filename) - start_response('404 Not Found', [('Content-Type', 'text/html')]) - return ["""<!DOCTYPE html> -<html> -<head> -<title>Not Found</title> -<body>%s not found</body> -</html>""" % path] - - logging.info('responding with %s', filename) - suffix = path[path.rfind('.') + 1:] - headers = [('Content-Type', _CONTENT_TYPE_FOR_SUFFIX[suffix])] - if path in self._response_headers: - for header in self._response_headers[path]: - headers.append((str(header[0]), str(header[1]))) - start_response('200 OK', headers) - return [file(filename).read()] - - -if __name__ == '__main__': - logging.basicConfig(level=logging.INFO) - parser = argparse.ArgumentParser() - parser.add_argument('--fifo', default=None, - help='Named pipe used to communicate port') - parser.add_argument('--source_dir', required=True, - help='Directory holding sources to serve.') - args = parser.parse_args() - server_app = ServerApp(args.source_dir) - server = wsgiref.simple_server.make_server( - 'localhost', 0, server_app) - ip, port = server.server_address - logging.info('Listening on port %s at %s', port, args.source_dir) - if args.fifo: - fifo = file(args.fifo, 'w') - fifo.write('%s\n' % port) - fifo.flush() - fifo.close() - server.serve_forever()
diff --git a/tools/android/loading/trace_test/tests/1.css b/tools/android/loading/trace_test/tests/1.css deleted file mode 100644 index 5ae3598..0000000 --- a/tools/android/loading/trace_test/tests/1.css +++ /dev/null
@@ -1,9 +0,0 @@ -/* Copyright 2016 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. - */ - -.outside { - font-family: inline; - color: red; -}
diff --git a/tools/android/loading/trace_test/tests/1.html b/tools/android/loading/trace_test/tests/1.html deleted file mode 100644 index 5dd15ce..0000000 --- a/tools/android/loading/trace_test/tests/1.html +++ /dev/null
@@ -1,43 +0,0 @@ -<!DOCTYPE html> -<!-- - Test Javascript Redirection in <head> - - In <head> we have a CSS, a javascript file and a <style> tag. The javascript - file inserts another javascript file into head, which itself inserts a <style> - tag containing an inline font. The static <style> tag below has a font - resource. We expect the static font resource to have an initiator with a stack - trace incorrectly attached from the javascript. - - TODO(mattcary): It also appears that if resources are found in the cache we - get different intiators: namely both the fonts have a parser initiator with no - stack. This is not exactly the problem, as occasionally the initiator sequence - changes, but can become consistent again by switching binaries with each run - (eg, out/Debug vs out/Release). ---> -<html> -<head> -<title>Test Javascript Redirection</title> -<link rel='stylesheet' type='text/css' href='1.css'> -<script type='text/javascript' src='1a.js'></script> -<style> -/* Custom font */ -@font-face { - font-family: 'test1'; - font-style: normal; - font-weight: normal; - src: local('test1'), local(test1), url(1.ttf) format('truetype'); -} -</style> -<style> -div { - background: url('1a.png') -} -</style> -</head> -<body> -<img src='1b.png' alt=''> - -<div class="outside">ABCpqrst</div> -<div class="inside">ABCpqrst</div> -</body> -</html>
diff --git a/tools/android/loading/trace_test/tests/1.ttf b/tools/android/loading/trace_test/tests/1.ttf deleted file mode 100644 index d268785..0000000 --- a/tools/android/loading/trace_test/tests/1.ttf +++ /dev/null Binary files differ
diff --git a/tools/android/loading/trace_test/tests/1a.js b/tools/android/loading/trace_test/tests/1a.js deleted file mode 100644 index 496cebb..0000000 --- a/tools/android/loading/trace_test/tests/1a.js +++ /dev/null
@@ -1,9 +0,0 @@ -/* Copyright 2016 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. - */ - -var scr = document.createElement('script'); -scr.setAttribute('type', 'text/javascript'); -scr.setAttribute('src', '1b.js'); -document.getElementsByTagName('head')[0].appendChild(scr)
diff --git a/tools/android/loading/trace_test/tests/1a.png b/tools/android/loading/trace_test/tests/1a.png deleted file mode 100644 index 88a0325..0000000 --- a/tools/android/loading/trace_test/tests/1a.png +++ /dev/null Binary files differ
diff --git a/tools/android/loading/trace_test/tests/1b.js b/tools/android/loading/trace_test/tests/1b.js deleted file mode 100644 index eaf905d..0000000 --- a/tools/android/loading/trace_test/tests/1b.js +++ /dev/null
@@ -1,60 +0,0 @@ -/* Copyright 2016 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. - */ - -/* Droid Sans from Google Fonts */ -var font = '@font-face { font-family: "inline"; ' + - 'src: url(data:application/font-woff2;charset=utf-8;base64,' + - 'd09GMgABAAAAAAboABEAAAAADcgAAAaGAAEAAAAAAAAAAAAAAAAAAAAAAA' + - 'AAAAAAP0ZGVE0cGigGVgCCeggUCYRlEQgKiDSIWgE2AiQDWAsuAAQgBYJ+B' + - '4FVDHg/d2ViZgYbkQxRlC1Sm+yLArvh2MHKbfiAVIG+Knex+u6x+Pyd0L+n' + - '4Cl0n74VfYIZH6AMqEOdEag0hxQqkzJcpeRdedy7DCB9T9LF3Y3l8976Xbg' + - 'X6AArK4qytKYdx2UW4LK8xGbPr2v+AmhM4aV1UgMv5btaum+17iX0YpGGCG' + - 'EYLIOf7Zf340t4NJtpeX7PFhBmixQP5C/r1GtZokUUskL2f9fU3r93GZDv8' + - '+jM5uzlH7wmKVHaEV07AFCtGtkaPQtEalMT1s5gePQ3sRnV4Ie/BQjAB0te' + - '/QV450a0AsBn99o2dz6vCnQQAg6CMAHBq5hchnij85b8j4/nx/4LIH3J2e5' + - 'XnHWa4BC4kDXZW4H4ypUcLmTqeMADwE+YsRuLDoNQTwOuCFHme+wHNKnjeQ' + - '4VQlZxh0I4HB6bOp5lQIUVVdi92f3s9+zLil/yP//x853/zhXWky0SLJ0S5' + - '4zrezfa/qbk/3t+wEvL5BhOBEmi7632G4otEyCtC2O/ot+wANdlQyrVGts8' + - 'YN/SC/C0smwfFwt9QSr1wUnXoLawNbial7VsAvWrAVkfgrAdYtjs6G/3rQ1' + - 'prtX/7j8bsoFYqqg3bKtO6FyHi5IwOe5DkoPCi688Potvk0Fgih5ZDqp6NR' + - '2tSGoKVcR8qEL7C7Ab4UkZ+PwOJggFnUA/cz93Uzq5PGiMDbqKNoiLBbWdd' + - 'SUHk81sPbrQ01ECBl4Qg1w6qURt3Dq3TkqL8+xIw81VqTxILmtzfUV2mSuX' + - '4jxxDKTSs2EtB1oqUXphrTK/5i3bmCC9uSugDMMdBIzsS5gxw7YwvS18KJN' + - '2DQUNmFV3mLEd7EpyXcjnRpsqxjkfzhOAwd3NY1rOA3dxgOWS2VOgLH2hnf' + - 'P/lR3auchORtav1cGLzmsDOUK9VN/Y6HWdO4EFRDgyvioOmZTnCeDGoKywg' + - 'MUlNKiHoEBT0njIyMNMZAtIl0LryFDQIRkIr/M9BUGyDBuANvmGAaAEfAh8' + - 'Dxn1wNn1oazEwf00PlI8b3EQVsszOvJSeki/GZNCuSSCHSolHeYacwCKIkV' + - 'gk0lGdQlFrwAlijFrUPfCPiHBEieVgkVuOoyOOaMxTXcR3AqCGkGfJQCoYX' + - 'DR0JjAYqMqiuIQszkxdjNRcCh0k26crIa2hwb7S6x64eeF5UQEQuWvZN80m' + - 'wrN8Xqyl8cyNI2QiZ/ARSYML05ZL/9fbIz/Q15LOjnMbVPpwZQNCuOmwM3L' + - 'UiDSG5Te4UTpIZyv1JidE620EGKWp6qyYKVa2kGqomYifgQbFl05rNhXdk2' + - '39FozuhTZgW7ZxrT0CHrQTGiwxf6RRbMBj8ykW+lgFqPbD7MqhUhzUFOzSI' + - 'y0Bgv5lRBu4PGKZ4kYGSXtw4jSajk1kHG6FI6ayMYtqVtyIPfmKDtmhsA5s' + - 'IsBVWRHjmKyii7cJGTPWkAzzVY8Mn5iHJvJtlTehFLHzNU61VhdMNiyC1a7' + - '/o0MazQ1udRV1/RSwbgdhHPmTmlfgHUljaZl+YIF21T7wXFURxbqSgaPMXu' + - 'AKkHFhRQaoCcoQsY5NxVP+7KyQxe8OGLMrp1iuoqu33iNFHQxsQnbG9dkX+' + - 'mmSC6pbrljMi3Tu7p0zSqlUK3aoeOw827lGNdLWkAuD+wzpiunoecYa+ppN' + - 'g0uIIfopXHHsrt7Fi0+0zg9123bWyYiwx5W2Asewfq7ckv+qphwrLb4fr4/' + - 'D/zVWZssC/ATIP8Nc5KAn2R/ECQDG/9xOKzN+ZfVAJzXgmMS8CHxEqHmDhJ' + - '3mc9OTpEvQY4D3BOWKkgnsBXYnXT/WbePNtZ/v0kHCURbm/UROYYyz+EiXm' + - 'G3IQoQks87lP8mIdwuTXrcHm0MuX1CVrsD8px2v0Mbl93vMsIT7veoksL72' + - 't1Dv3Xp4iOukLFEdgL+7JSKja5Z3qEopSoEbFbnVwz0UEa8/ChDiY5IyMFC' + - 'IR+TUyC/aWEHS0WxdgAFMY/fmcdC4oqzkDFiW8Qzyrmchn9OxEYbGteVGVs' + - 'U8eYdv4uJjapb93SE21+g2IOMb1Pj79pAHHFxmcJUpoknvgSSk7wUpCglKU' + - 'tFqlKTujSkGZxrr7E0c1f7yiDB1UndihFm1SyQURKTMTKbzCFzyTwynyzQV' + - 'jTEa7U5uvS0VS+ePQ15hk3KbWcPLs8esLd/QzHV/ujFrK/UOR3oVeZfxDPA' + - 'nXCNktFqJcM1KVF3ohJQDWSpTdTvBwboLiPX7iqwaaZUPuIAt0Zk73/mAw==) ' + - 'format("woff2"); font-weight: normal; font-style: normal;} ' + - '.inside { font-family: test1; color: green;}'; - -var sty = document.createElement('style'); -sty.appendChild(document.createTextNode(font)); -document.getElementsByTagName('head')[0].appendChild(sty); - -var dummyToCheckStackIsnotJustEndOfFile = 0; -function makingTheStackTraceReallyInteresting(x) { - dummyToCheckStackIsnotJustEndOfFile = x + 3; -} -makingTheStackTraceReallyInteresting(5);
diff --git a/tools/android/loading/trace_test/tests/1b.png b/tools/android/loading/trace_test/tests/1b.png deleted file mode 100644 index dca89e0..0000000 --- a/tools/android/loading/trace_test/tests/1b.png +++ /dev/null Binary files differ
diff --git a/tools/android/loading/trace_test/tests/2.html b/tools/android/loading/trace_test/tests/2.html deleted file mode 100644 index 1d79ff3..0000000 --- a/tools/android/loading/trace_test/tests/2.html +++ /dev/null
@@ -1,36 +0,0 @@ -<!DOCTYPE html> -<!-- - Test Less Javascript Redirection in <head> - - Like 1.html, in <head> we have a CSS, a javascript file and a <style> tag. In - this case, the javacript file directly inserts a <style> tag into <head>. This - causes the subsequently loaded font to not be associated with a stack trace, - but also causes the dynamically loaded static font from 1b.js to also not have - a stack trace. ---> -<html> -<head> -<title>As 1.html, but one less redirection</title> -<link rel='stylesheet' type='text/css' href='1.css'> -<script type='text/javascript' src='1b.js'></script> -<style> -@font-face { - font-family: 'indie'; - font-style: normal; - font-weight: normal; - src: local('Indie Flower'), local('IndieFlower'), url(1.ttf) format('truetype'); -} -</style> -<style> -div { - background: url('1a.png') -} -</style> -</head> -<body> -<img src='1b.png' alt=''> - -<div class="outside">Outside</div> -<div class="inside">Inside</div> -</body> -</html>
diff --git a/tools/android/loading/trace_test/tests/3.html b/tools/android/loading/trace_test/tests/3.html deleted file mode 100644 index f6850eb..0000000 --- a/tools/android/loading/trace_test/tests/3.html +++ /dev/null
@@ -1,24 +0,0 @@ -<!DOCTYPE html> -<!-- - Javascript indirect image loading. - - 3a.js defines fn1(), which adds an <img> tag to the body. 3a.js also - inserts a script tag with 3b.js into head (between the scripts for - 3a and 3c). 3b.js itself creates an <img> tag which directly adds it - to the body. Finally, 3c.js defines fn3(), which - modifies <img id='img3'>. - - Note that as 3b.js adds a tag to the body, it is executed only after - the body has been parsed. No, I don't know how that works either. ---> -<html> -<head> -<script type='text/javascript' src='3a.js'></script> -<script type='text/javascript' src='3c.js'></script> -<img src='' alt='' id='img3'> -<script type='text/javascript'> - fn1(); - fn3(); -</script> -</body> -</html>
diff --git a/tools/android/loading/trace_test/tests/3a.jpg b/tools/android/loading/trace_test/tests/3a.jpg deleted file mode 100644 index 25f3a43..0000000 --- a/tools/android/loading/trace_test/tests/3a.jpg +++ /dev/null Binary files differ
diff --git a/tools/android/loading/trace_test/tests/3a.js b/tools/android/loading/trace_test/tests/3a.js deleted file mode 100644 index 31f6dca..0000000 --- a/tools/android/loading/trace_test/tests/3a.js +++ /dev/null
@@ -1,21 +0,0 @@ -/* Copyright 2016 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. - */ - -function addImg(img_link) { - var img = document.createElement('img'); - img.setAttribute('src', img_link); - img.setAttribute('alt', ''); - document.body.appendChild(img); -} - -function fn1() { - addImg('3a.jpg'); -} - -var scr = document.createElement('script'); -scr.setAttribute('src', '3b.js'); -scr.setAttribute('type', 'text/javascript'); -document.getElementsByTagName('head')[0].insertBefore( - scr, document.getElementsByTagName('script')[0].nextSibling);
diff --git a/tools/android/loading/trace_test/tests/3b.jpg b/tools/android/loading/trace_test/tests/3b.jpg deleted file mode 100644 index de44b66..0000000 --- a/tools/android/loading/trace_test/tests/3b.jpg +++ /dev/null Binary files differ
diff --git a/tools/android/loading/trace_test/tests/3b.js b/tools/android/loading/trace_test/tests/3b.js deleted file mode 100644 index 9ccc020..0000000 --- a/tools/android/loading/trace_test/tests/3b.js +++ /dev/null
@@ -1,9 +0,0 @@ -/* Copyright 2016 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. - */ - -var img = document.createElement('img'); -img.setAttribute('src', '3b.jpg'); -img.setAttribute('alt', ''); -document.body.appendChild(img);
diff --git a/tools/android/loading/trace_test/tests/3c.jpg b/tools/android/loading/trace_test/tests/3c.jpg deleted file mode 100644 index 688b70b..0000000 --- a/tools/android/loading/trace_test/tests/3c.jpg +++ /dev/null Binary files differ
diff --git a/tools/android/loading/trace_test/tests/3c.js b/tools/android/loading/trace_test/tests/3c.js deleted file mode 100644 index b34da79..0000000 --- a/tools/android/loading/trace_test/tests/3c.js +++ /dev/null
@@ -1,8 +0,0 @@ -/* Copyright 2016 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. - */ - -function fn3() { - document.getElementById('img3').setAttribute('src', '3c.jpg'); -}
diff --git a/tools/android/loading/trace_test/webserver_test.py b/tools/android/loading/trace_test/webserver_test.py deleted file mode 100755 index f6dbf96..0000000 --- a/tools/android/loading/trace_test/webserver_test.py +++ /dev/null
@@ -1,291 +0,0 @@ -#! /usr/bin/python -# Copyright 2016 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. - -"""An integration test for tracing. - -This is not run as part of unittests and is executed directly. In normal -operation it can be run with no arguments (or perhaps --no_sandbox depending on -how you have chrome set up). When debugging or adding tests, setting ---failed_trace_dir could be useful. - -The integration test spawns a local http server to serve web pages. The trace -generated by each file in tests/*.html will be compared with the corresponding -results/*.result. Each test should have a detailed comment explaining its -organization and what the important part of the test result is. - -By default this will use a release version of chrome built in this same -code tree (out/Release/chrome), see --local_binary to override. - -See InitiatorSequence for what the integration tests verify. The idea is to -capture a sketch of the initiator and call stack relationship. The output is -human-readable. To create a new test, first run test_server.py locally with ---source_dir pointing to tests/, and verify that the test page works as expected -by pointing a browser to localhost:XXX/your_new_test.html (with XXX the port -reported in the console output of test_server.py). Then run this -webserver_test.py with --failed_trace_dir set. Verify that the actual output is -what you expect it to be, then copy it to results/. If your test is 7.html, you -should copy to results/7.result. -""" - -import argparse -import contextlib -import json -import os -import shutil -import subprocess -import sys -import tempfile -import urlparse - -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) - -import clovis_constants -import controller -import loading_trace -import options - - -OPTIONS = options.OPTIONS -WEBSERVER = os.path.join(os.path.dirname(__file__), 'test_server.py') -TESTDIR = os.path.join(os.path.dirname(__file__), 'tests') -RESULTDIR = os.path.join(os.path.dirname(__file__), 'results') - - -@contextlib.contextmanager -def TemporaryDirectory(): - """Returns a freshly-created directory that gets automatically deleted after - usage. - """ - name = tempfile.mkdtemp() - try: - yield name - finally: - shutil.rmtree(name) - - -class WebServer(object): - """Wrap the webserver.""" - def __init__(self, source_dir, communication_dir): - """Initialize the server but does not start it. - - Args: - source_dir: the directory where source data (html, js, etc) will be found. - communication_dir: a directory to use for IPC (eg, discovering the - port, which is dynamically allocated). This should probably be a - temporary directory. - """ - self._source_dir = source_dir - self._communication_dir = communication_dir - self._fifo = None - self._server_process = None - self._port = None - - @classmethod - @contextlib.contextmanager - def Context(cls, *args, **kwargs): - """Creates a webserver as a context manager. - - Args: - As in __init__. - - Returns: - A context manager for an instance of a WebServer. - """ - try: - server = cls(*args, **kwargs) - server.Start() - yield server - finally: - server.Stop() - - def Start(self): - """Start the server by spawning a process.""" - fifo_name = os.path.join(self._communication_dir, 'from_server') - os.mkfifo(fifo_name) - server_out = None if OPTIONS.local_noisy else file('/dev/null', 'w') - self._server_process = subprocess.Popen( - [WEBSERVER, - '--source_dir=%s' % self._source_dir, - '--fifo=%s' % fifo_name], - shell=False, stdout=server_out, stderr=server_out) - fifo = file(fifo_name) - # TODO(mattcary): timeout? - self._port = int(fifo.readline()) - fifo.close() - - def Stop(self): - """Stops the server, waiting for it to complete. - - Returns: - True if the server stopped correctly. - """ - if self._server_process is None: - return False - self._server_process.kill() - # TODO(mattcary): timeout & error? - self._server_process.wait() - return True - - def Address(self): - """Returns a host:port string suitable for an http request.""" - assert self._port is not None, \ - "No port exists until the server is started." - return 'localhost:%s' % self._port - - -class InitiatorSequence(object): - """The interesting parts of the initiator dependancies that are tested.""" - def __init__(self, trace): - """Create. - - Args: - trace: a LoadingTrace. - """ - self._seq = [] - # ReadFromFile will initialize without a trace. - if trace is None: - return - for rq in trace.request_track.GetEvents(): - if rq.initiator['type'] in ('parser', 'script'): - stack_string = '' - stack = rq.initiator.get('stack') - # Iteratively walk the stack and its parents. - while stack: - current_string = '/'.join( - ['%s:%s' % (self._ShortUrl(frame['url']), frame['lineNumber']) - for frame in stack['callFrames']]) - if len(current_string) and len(stack_string): - stack_string += '/' - stack_string += current_string - stack = stack.get('parent') - - if stack_string == '': - stack_string = 'no stack' - - self._seq.append('%s (%s) %s' % ( - rq.initiator['type'], - stack_string, - self._ShortUrl(rq.url))) - self._seq.sort() - - @classmethod - def ReadFromFile(cls, input_file): - """Read a file from DumpToFile. - - Args: - input_file: a file-like object. - - Returns: - An InitiatorSequence instance. - """ - seq = cls(None) - seq._seq = sorted([l.strip() for l in input_file.readlines() if l]) - return seq - - def DumpToFile(self, output): - """Write to a file. - - Args: - output: a writeable file-like object. - """ - output.write('\n'.join(self._seq) + '\n') - - def __eq__(self, other): - if other is None: - return False - assert type(other) is InitiatorSequence - if len(self._seq) != len(other._seq): - return False - for a, b in zip(self._seq, other._seq): - if a != b: - return False - return True - - def _ShortUrl(self, url): - short = urlparse.urlparse(url).path - while short.startswith('/'): - short = short[1:] - if len(short) > 40: - short = '...'.join((short[:20], short[-10:])) - return short - - -def RunTest(webserver, test_page, expected): - """Run an webserver test. - - The expected result can be None, in which case --failed_trace_dir can be set - to output the observed trace. - - Args: - webserver [WebServer]: the webserver to use for the test. It must be - started. - test_page: the name of the page to load. - expected [InitiatorSequence]: expected initiator sequence. - - Returns: - True if the test passed and false otherwise. Status is printed to stdout. - """ - url = 'http://%s/%s' % (webserver.Address(), test_page) - sys.stdout.write('Testing %s...' % url) - chrome_controller = controller.LocalChromeController() - - with chrome_controller.Open() as connection: - connection.ClearCache() - observed_seq = InitiatorSequence( - loading_trace.LoadingTrace.RecordUrlNavigation( - url, connection, chrome_controller.ChromeMetadata(), - categories=clovis_constants.DEFAULT_CATEGORIES)) - if observed_seq == expected: - sys.stdout.write(' ok\n') - return True - else: - sys.stdout.write(' FAILED!\n') - if OPTIONS.failed_trace_dir: - outname = os.path.join(OPTIONS.failed_trace_dir, - test_page + '.observed_result') - with file(outname, 'w') as output: - observed_seq.DumpToFile(output) - sys.stdout.write('Wrote observed result to %s\n' % outname) - return False - - -def RunAllTests(): - """Run all tests in TESTDIR. - - All tests must have a corresponding result in RESULTDIR unless - --failed_trace_dir is set. - """ - test_filter = set(OPTIONS.test_filter.split(',')) \ - if OPTIONS.test_filter else None - - with TemporaryDirectory() as temp_dir, \ - WebServer.Context(TESTDIR, temp_dir) as webserver: - failure = False - for test in sorted(os.listdir(TESTDIR)): - if test.endswith('.html'): - if test_filter and test not in test_filter: - continue - result = os.path.join(RESULTDIR, test[:test.rfind('.')] + '.result') - assert OPTIONS.failed_trace_dir or os.path.exists(result), \ - 'No result found for test' - expected = None - if os.path.exists(result): - with file(result) as result_file: - expected = InitiatorSequence.ReadFromFile(result_file) - if not RunTest(webserver, test, expected): - failure = True - if failure: - print 'FAILED!' - else: - print 'all tests passed' - - -if __name__ == '__main__': - OPTIONS.ParseArgs(sys.argv[1:], - description='Run webserver integration test', - extra=[('--failed_trace_dir', ''), - ('--noisy', False), - ('--test_filter', None)]) - RunAllTests()
diff --git a/tools/android/loading/trace_test/webserver_unittest.py b/tools/android/loading/trace_test/webserver_unittest.py deleted file mode 100644 index f4b232c..0000000 --- a/tools/android/loading/trace_test/webserver_unittest.py +++ /dev/null
@@ -1,115 +0,0 @@ -# Copyright 2016 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. - -import httplib -import json -import os -import shutil -import sys -import tempfile -import unittest - -_SRC_DIR = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..', '..', '..', '..')) -sys.path.append(os.path.join(_SRC_DIR, 'tools', 'android', 'loading')) - -import options -from trace_test import test_server -from trace_test import webserver_test - - -OPTIONS = options.OPTIONS - - -class WebServerTestCase(unittest.TestCase): - def setUp(self): - OPTIONS.ParseArgs('', extra=[('--noisy', False)]) - self._temp_dir = tempfile.mkdtemp() - self._server = webserver_test.WebServer(self._temp_dir, self._temp_dir) - - def tearDown(self): - self.assertTrue(self._server.Stop()) - shutil.rmtree(self._temp_dir) - - def StartServer(self): - self._server.Start() - - def WriteFile(self, path, file_content): - with open(os.path.join(self._temp_dir, path), 'w') as file_output: - file_output.write(file_content) - - def Request(self, path): - host, port = self._server.Address().split(':') - connection = httplib.HTTPConnection(host, int(port)) - connection.request('GET', path) - response = connection.getresponse() - connection.close() - return response - - def testWebserverBasic(self): - self.WriteFile('test.html', - '<!DOCTYPE html><html><head><title>Test</title></head>' - '<body><h1>Test Page</h1></body></html>') - self.StartServer() - - response = self.Request('test.html') - self.assertEqual(200, response.status) - - response = self.Request('/test.html') - self.assertEqual(200, response.status) - - response = self.Request('///test.html') - self.assertEqual(200, response.status) - - def testWebserver404(self): - self.StartServer() - - response = self.Request('null') - self.assertEqual(404, response.status) - self.assertEqual('text/html', response.getheader('content-type')) - - def testContentType(self): - self.WriteFile('test.html', - '<!DOCTYPE html><html><head><title>Test</title></head>' - '<body><h1>Test Page</h1></body></html>') - self.WriteFile('blobfile', - 'whatever') - self.StartServer() - - response = self.Request('test.html') - self.assertEqual(200, response.status) - self.assertEqual('text/html', response.getheader('content-type')) - - response = self.Request('blobfile') - self.assertEqual(500, response.status) - - def testCustomResponseHeader(self): - self.WriteFile('test.html', - '<!DOCTYPE html><html><head><title>Test</title></head>' - '<body><h1>Test Page</h1></body></html>') - self.WriteFile('test2.html', - '<!DOCTYPE html><html><head><title>Test 2</title></head>' - '<body><h1>Test Page 2</h1></body></html>') - self.WriteFile(test_server.RESPONSE_HEADERS_PATH, - json.dumps({'test2.html': [['Cache-Control', 'no-store']]})) - self.StartServer() - - response = self.Request('test.html') - self.assertEqual(200, response.status) - self.assertEqual('text/html', response.getheader('content-type')) - self.assertEqual(None, response.getheader('cache-control')) - - response = self.Request('test2.html') - self.assertEqual(200, response.status) - self.assertEqual('text/html', response.getheader('content-type')) - self.assertEqual('no-store', response.getheader('cache-control')) - - response = self.Request(test_server.RESPONSE_HEADERS_PATH) - self.assertEqual(200, response.status) - self.assertEqual('application/json', response.getheader('content-type')) - self.assertEqual(None, response.getheader('cache-control')) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/trace_to_chrome_trace.py b/tools/android/loading/trace_to_chrome_trace.py deleted file mode 100755 index 23c3632..0000000 --- a/tools/android/loading/trace_to_chrome_trace.py +++ /dev/null
@@ -1,22 +0,0 @@ -#! /usr/bin/python -# 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. - -"""Convert trace output for Chrome. - -Takes a loading trace from 'analyze.py log_requests' and outputs a json file -that can be loaded by chrome's about:tracing.. -""" - -import argparse -import json - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('input') - parser.add_argument('output') - args = parser.parse_args() - with file(args.output, 'w') as output_f, file(args.input) as input_f: - events = json.load(input_f)['tracing_track']['events'] - json.dump({'traceEvents': events, 'metadata': {}}, output_f)
diff --git a/tools/android/loading/tracing_track.py b/tools/android/loading/tracing_track.py deleted file mode 100644 index f69392d..0000000 --- a/tools/android/loading/tracing_track.py +++ /dev/null
@@ -1,571 +0,0 @@ -# Copyright 2016 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. - -"""Monitor tracing events on chrome via chrome remote debugging.""" - -import itertools -import logging -import operator - -import clovis_constants -import devtools_monitor - - -class TracingTrack(devtools_monitor.Track): - """Grabs and processes trace event messages. - - See https://goo.gl/Qabkqk for details on the protocol. - """ - def __init__(self, connection, categories, fetch_stream=False): - """Initialize this TracingTrack. - - Args: - connection: a DevToolsConnection. - categories: ([str] or None) If set, a list of categories to enable or - disable in Chrome tracing. Categories prefixed with '-' are - disabled. - fetch_stream: if true, use a websocket stream to fetch tracing data rather - than dataCollected events. It appears based on very limited testing that - a stream is slower than the default reporting as dataCollected events. - """ - super(TracingTrack, self).__init__(connection) - if connection: - connection.RegisterListener('Tracing.dataCollected', self) - - self._categories = set(categories) - params = {} - params['categories'] = ','.join(self._categories) - if fetch_stream: - params['transferMode'] = 'ReturnAsStream' - - if connection: - connection.SyncRequestNoResponse('Tracing.start', params) - - self._events = [] - self._base_msec = None - self._interval_tree = None - self._main_frame_id = None - - def Handle(self, method, event): - for e in event['params']['value']: - event = Event(e) - self._events.append(event) - if self._base_msec is None or event.start_msec < self._base_msec: - self._base_msec = event.start_msec - # Invalidate our index rather than trying to be fancy and incrementally - # update. - self._interval_tree = None - - def Categories(self): - """Returns the set of categories in this trace.""" - return self._categories - - def GetFirstEventMillis(self): - """Find the canonical start time for this track. - - Returns: - The millisecond timestamp of the first request. - """ - return self._base_msec - - def GetEvents(self): - """Returns a list of tracing.Event. Not sorted.""" - return self._events - - def GetMatchingEvents(self, category, name): - """Gets events matching |category| and |name|.""" - return [e for e in self.GetEvents() if e.Matches(category, name)] - - def GetMatchingMainFrameEvents(self, category, name): - """Gets events matching |category| and |name| that occur in the main frame. - - Events without a 'frame' key in their |args| are discarded. - """ - matching_events = self.GetMatchingEvents(category, name) - return [e for e in matching_events - if 'frame' in e.args and e.args['frame'] == self.GetMainFrameID()] - - def GetMainFrameRoutingID(self): - """Returns the main frame routing ID.""" - for event in self.GetMatchingEvents( - 'navigation', 'RenderFrameImpl::OnNavigate'): - return event.args['id'] - assert False - - def GetMainFrameID(self): - """Returns the main frame ID.""" - if not self._main_frame_id: - navigation_start_events = self.GetMatchingEvents( - 'blink.user_timing', 'navigationStart') - first_event = min(navigation_start_events, key=lambda e: e.start_msec) - self._main_frame_id = first_event.args['frame'] - - return self._main_frame_id - - def SetMainFrameID(self, frame_id): - """Set the main frame ID. Normally this is used only for testing.""" - self._main_frame_id = frame_id - - def EventsAt(self, msec): - """Gets events active at a timestamp. - - Args: - msec: tracing milliseconds to query. Tracing milliseconds appears to be - since chrome startup (ie, arbitrary epoch). - - Returns: - List of events active at that timestamp. Instantaneous (ie, instant, - sample and counter) events are never included. Event end times are - exclusive, so that an event ending at the usec parameter will not be - returned. - """ - self._IndexEvents() - return self._interval_tree.EventsAt(msec) - - def Filter(self, pid=None, tid=None, categories=None): - """Returns a new TracingTrack with a subset of the events. - - Args: - pid: (int or None) Selects events from this PID. - tid: (int or None) Selects events from this TID. - categories: (set([str]) or None) Selects events belonging to one of the - categories. - """ - events = self._events - if pid is not None: - events = filter(lambda e : e.tracing_event['pid'] == pid, events) - if tid is not None: - events = filter(lambda e : e.tracing_event['tid'] == tid, events) - if categories is not None: - events = filter( - lambda e : set(e.category.split(',')).intersection(categories), - events) - tracing_track = TracingTrack(None, clovis_constants.DEFAULT_CATEGORIES) - tracing_track._events = events - tracing_track._categories = self._categories - if categories is not None: - tracing_track._categories = self._categories.intersection(categories) - return tracing_track - - def ToJsonDict(self): - return {'categories': list(self._categories), - 'events': [e.ToJsonDict() for e in self._events]} - - @classmethod - def FromJsonDict(cls, json_dict): - if not json_dict: - return None - assert 'events' in json_dict - events = [Event(e) for e in json_dict['events']] - tracing_track = TracingTrack(None, clovis_constants.DEFAULT_CATEGORIES) - tracing_track._categories = set(json_dict.get('categories', [])) - tracing_track._events = events - tracing_track._base_msec = events[0].start_msec if events else 0 - for e in events[1:]: - if e.type == 'M': - continue # No timestamp for metadata events. - assert e.start_msec > 0 - if e.start_msec < tracing_track._base_msec: - tracing_track._base_msec = e.start_msec - return tracing_track - - def OverlappingEvents(self, start_msec, end_msec): - self._IndexEvents() - return self._interval_tree.OverlappingEvents(start_msec, end_msec) - - def EventsEndingBetween(self, start_msec, end_msec): - """Gets the list of events ending within an interval. - - Args: - start_msec: the start of the range to query, in milliseconds, inclusive. - end_msec: the end of the range to query, in milliseconds, inclusive. - - Returns: - See OverlappingEvents() above. - """ - overlapping_events = self.OverlappingEvents(start_msec, end_msec) - return [e for e in overlapping_events - if start_msec <= e.end_msec <= end_msec] - - def EventFromStep(self, step_event): - """Returns the Event associated with a step event, or None. - - Args: - step_event: (Event) Step event. - - Returns: - an Event that matches the step event, or None. - """ - self._IndexEvents() - assert 'step' in step_event.args and step_event.tracing_event['ph'] == 'T' - candidates = self._interval_tree.EventsAt(step_event.start_msec) - for event in candidates: - # IDs are only unique within a process (often they are pointers). - if (event.pid == step_event.pid and event.tracing_event['ph'] != 'T' - and event.name == step_event.name and event.id == step_event.id): - return event - return None - - def _IndexEvents(self, strict=False): - if self._interval_tree: - return - complete_events = [] - spanning_events = self._SpanningEvents() - for event in self._events: - if not event.IsIndexable(): - continue - if event.IsComplete(): - complete_events.append(event) - continue - matched_event = spanning_events.Match(event, strict) - if matched_event is not None: - complete_events.append(matched_event) - self._interval_tree = _IntervalTree.FromEvents(complete_events) - - if strict and spanning_events.HasPending(): - raise devtools_monitor.DevToolsConnectionException( - 'Pending spanning events: %s' % - '\n'.join([str(e) for e in spanning_events.PendingEvents()])) - - def _GetEvents(self): - self._IndexEvents() - return self._interval_tree.GetEvents() - - def HasLoadingSucceeded(self): - """Returns whether the loading has succeed at recording time.""" - main_frame_id = self.GetMainFrameRoutingID() - for event in self.GetMatchingEvents( - 'navigation', 'RenderFrameImpl::didFailProvisionalLoad'): - if event.args['id'] == main_frame_id: - return False - for event in self.GetMatchingEvents( - 'navigation', 'RenderFrameImpl::didFailLoad'): - if event.args['id'] == main_frame_id: - return False - return True - - class _SpanningEvents(object): - def __init__(self): - self._duration_stack = [] - self._async_stacks = {} - self._objects = {} - self._MATCH_HANDLER = { - 'B': self._DurationBegin, - 'E': self._DurationEnd, - 'b': self._AsyncStart, - 'e': self._AsyncEnd, - 'S': self._AsyncStart, - 'F': self._AsyncEnd, - 'N': self._ObjectCreated, - 'D': self._ObjectDestroyed, - 'M': self._Ignore, - 'X': self._Ignore, - 'R': self._Ignore, - 'p': self._Ignore, - '(': self._Ignore, # Context events. - ')': self._Ignore, # Ditto. - None: self._Ignore, - } - - def Match(self, event, strict=False): - return self._MATCH_HANDLER.get( - event.type, self._Unsupported)(event, strict) - - def HasPending(self): - return (self._duration_stack or - self._async_stacks or - self._objects) - - def PendingEvents(self): - return itertools.chain( - (e for e in self._duration_stack), - (o for o in self._objects), - itertools.chain.from_iterable(( - (e for e in s) for s in self._async_stacks.itervalues()))) - - def _AsyncKey(self, event, _): - return (event.tracing_event['cat'], event.id) - - def _Ignore(self, _event, _): - return None - - def _Unsupported(self, event, _): - raise devtools_monitor.DevToolsConnectionException( - 'Unsupported spanning event type: %s' % event) - - def _DurationBegin(self, event, _): - self._duration_stack.append(event) - return None - - def _DurationEnd(self, event, _): - if not self._duration_stack: - raise devtools_monitor.DevToolsConnectionException( - 'Unmatched duration end: %s' % event) - start = self._duration_stack.pop() - start.SetClose(event) - return start - - def _AsyncStart(self, event, strict): - key = self._AsyncKey(event, strict) - self._async_stacks.setdefault(key, []).append(event) - return None - - def _AsyncEnd(self, event, strict): - key = self._AsyncKey(event, strict) - if key not in self._async_stacks: - message = 'Unmatched async end %s: %s' % (key, event) - if strict: - raise devtools_monitor.DevToolsConnectionException(message) - else: - logging.warning(message) - return None - stack = self._async_stacks[key] - start = stack.pop() - if not stack: - del self._async_stacks[key] - start.SetClose(event) - return start - - def _ObjectCreated(self, event, _): - # The tracing event format has object deletion timestamps being exclusive, - # that is the timestamp for a deletion my equal that of the next create at - # the same address. This asserts that does not happen in practice as it is - # inconvenient to handle that correctly here. - if event.id in self._objects: - raise devtools_monitor.DevToolsConnectionException( - 'Multiple objects at same address: %s, %s' % - (event, self._objects[event.id])) - self._objects[event.id] = event - return None - - def _ObjectDestroyed(self, event, _): - if event.id not in self._objects: - raise devtools_monitor.DevToolsConnectionException( - 'Missing object creation for %s' % event) - start = self._objects[event.id] - del self._objects[event.id] - start.SetClose(event) - return start - - -class Event(object): - """Wraps a tracing event.""" - CLOSING_EVENTS = {'E': 'B', - 'e': 'b', - 'F': 'S', - 'D': 'N'} - __slots__ = ('_tracing_event', 'start_msec', 'end_msec', '_synthetic') - def __init__(self, tracing_event, synthetic=False): - """Creates Event. - - Intended to be created only by TracingTrack. - - Args: - tracing_event: JSON tracing event, as defined in https://goo.gl/Qabkqk. - synthetic: True if the event is synthetic. This is only used for indexing - internal to TracingTrack. - """ - if not synthetic and tracing_event['ph'] in ['s', 't', 'f']: - raise devtools_monitor.DevToolsConnectionException( - 'Unsupported event: %s' % tracing_event) - - self._tracing_event = tracing_event - # Note tracing event times are in microseconds. - self.start_msec = tracing_event['ts'] / 1000.0 - self.end_msec = None - self._synthetic = synthetic - if self.type == 'X': - # Some events don't have a duration. - duration = (tracing_event['dur'] - if 'dur' in tracing_event else tracing_event['tdur']) - self.end_msec = self.start_msec + duration / 1000.0 - - @property - def type(self): - if self._synthetic: - return None - return self._tracing_event['ph'] - - @property - def category(self): - return self._tracing_event['cat'] - - @property - def pid(self): - return self._tracing_event['pid'] - - @property - def args(self): - return self._tracing_event.get('args', {}) - - @property - def id(self): - return self._tracing_event.get('id') - - @property - def name(self): - return self._tracing_event['name'] - - @property - def tracing_event(self): - return self._tracing_event - - @property - def synthetic(self): - return self._synthetic - - def __str__(self): - return ''.join([str(self._tracing_event), - '[%s,%s]' % (self.start_msec, self.end_msec)]) - - def Matches(self, category, name): - """Match tracing events. - - Args: - category: a tracing category (event['cat']). - name: the tracing event name (event['name']). - - Returns: - True if the event matches and False otherwise. - """ - if name != self.name: - return False - categories = self.category.split(',') - return category in categories - - def IsIndexable(self): - """True iff the event can be indexed by time.""" - return self._synthetic or self.type not in [ - 'I', 'P', 'c', 'C', - 'n', 'T', 'p', # TODO(mattcary): ?? instant types of async events. - 'O', # TODO(mattcary): ?? object snapshot - 'M' # Metadata - ] - - def IsComplete(self): - return self.type == 'X' - - def Synthesize(self): - """Expand into synthetic events. - - Returns: - A list of events, possibly some synthetic, whose start times are all - interesting for purposes of indexing. If the event is not indexable the - set may be empty. - """ - if not self.IsIndexable(): - return [] - if self.IsComplete(): - # Tracing event timestamps are microseconds! - return [self, Event({'ts': self.end_msec * 1000}, synthetic=True)] - return [self] - - def SetClose(self, closing): - """Close a spanning event. - - Args: - closing: The closing event. - - Raises: - devtools_monitor.DevToolsConnectionException if closing can't property - close this event. - """ - if self.type != self.CLOSING_EVENTS.get(closing.type): - raise devtools_monitor.DevToolsConnectionException( - 'Bad closing: %s --> %s' % (self, closing)) - if self.type in ['b', 'S'] and ( - self.tracing_event['cat'] != closing.tracing_event['cat'] or - self.id != closing.id): - raise devtools_monitor.DevToolsConnectionException( - 'Bad async closing: %s --> %s' % (self, closing)) - self.end_msec = closing.start_msec - if 'args' in closing.tracing_event: - self.tracing_event.setdefault( - 'args', {}).update(closing.tracing_event['args']) - - def ToJsonDict(self): - return self._tracing_event - - @classmethod - def FromJsonDict(cls, json_dict): - return Event(json_dict) - - -class _IntervalTree(object): - """Simple interval tree. This is not an optimal one, as the split is done with - an equal number of events on each side, according to start time. - """ - _TRESHOLD = 100 - def __init__(self, start, end, events): - """Builds an interval tree. - - Args: - start: start timestamp of this node, in ms. - end: end timestamp covered by this node, in ms. - events: Iterable of objects having start_msec and end_msec fields. Has to - be sorted by start_msec. - """ - self.start = start - self.end = end - self._events = events - self._left = self._right = None - if len(self._events) > self._TRESHOLD: - self._Divide() - - @classmethod - def FromEvents(cls, events): - """Returns an IntervalTree instance from a list of events.""" - filtered_events = [e for e in events - if e.start_msec is not None and e.end_msec is not None] - filtered_events.sort(key=operator.attrgetter('start_msec')) - start = min(event.start_msec for event in filtered_events) - end = max(event.end_msec for event in filtered_events) - return _IntervalTree(start, end, filtered_events) - - def OverlappingEvents(self, start, end): - """Returns a set of events overlapping with [start, end).""" - if min(end, self.end) - max(start, self.start) <= 0: - return set() - elif self._IsLeaf(): - result = set() - for event in self._events: - if self._Overlaps(event, start, end): - result.add(event) - return result - else: - return (self._left.OverlappingEvents(start, end) - | self._right.OverlappingEvents(start, end)) - - def EventsAt(self, timestamp): - result = set() - if self._IsLeaf(): - for event in self._events: - if event.start_msec <= timestamp < event.end_msec: - result.add(event) - else: - if self._left.start <= timestamp < self._left.end: - result |= self._left.EventsAt(timestamp) - if self._right.start <= timestamp < self._right.end: - result |= self._right.EventsAt(timestamp) - return result - - def GetEvents(self): - return self._events - - def _Divide(self): - middle = len(self._events) / 2 - left_events = self._events[:middle] - right_events = self._events[middle:] - left_end = max(e.end_msec for e in left_events) - right_start = min(e.start_msec for e in right_events) - self._left = _IntervalTree(self.start, left_end, left_events) - self._right = _IntervalTree(right_start, self.end, right_events) - - def _IsLeaf(self): - return self._left is None - - @classmethod - def _Overlaps(cls, event, start, end): - return (min(end, event.end_msec) - max(start, event.start_msec) > 0 - or start <= event.start_msec < end) # For instant events.
diff --git a/tools/android/loading/tracing_track_unittest.py b/tools/android/loading/tracing_track_unittest.py deleted file mode 100644 index b10083f..0000000 --- a/tools/android/loading/tracing_track_unittest.py +++ /dev/null
@@ -1,493 +0,0 @@ -# Copyright 2016 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. - -import collections -import copy -import logging -import operator -import unittest - -import devtools_monitor - -from tracing_track import (Event, TracingTrack, _IntervalTree) - - -class TracingTrackTestCase(unittest.TestCase): - _MIXED_EVENTS = [ - {'ts': 3, 'ph': 'N', 'id': 1, 'args': {'name': 'A'}}, - {'ts': 5, 'ph': 'X', 'dur': 1, 'args': {'name': 'B'}}, - {'ts': 7, 'ph': 'D', 'id': 1}, - {'ts': 10, 'ph': 'B', 'args': {'name': 'D'}}, - {'ts': 10, 'ph': 'b', 'cat': 'X', 'id': 1, 'args': {'name': 'C'}}, - {'ts': 11, 'ph': 'e', 'cat': 'X', 'id': 1}, - {'ts': 12, 'ph': 'E'}, - {'ts': 12, 'ph': 'N', 'id': 1, 'args': {'name': 'E'}}, - {'ts': 13, 'ph': 'b', 'cat': 'X', 'id': 2, 'args': {'name': 'F'}}, - {'ts': 14, 'ph': 'e', 'cat': 'X', 'id': 2}, - {'ts': 15, 'ph': 'D', 'id': 1}] - - _EVENTS = [ - {'ts': 5, 'ph': 'X', 'dur': 1, 'pid': 2, 'tid': 1, 'args': {'name': 'B'}}, - {'ts': 3, 'ph': 'X', 'dur': 4, 'pid': 2, 'tid': 1, 'args': {'name': 'A'}}, - {'ts': 10, 'ph': 'X', 'dur': 1, 'pid': 2, 'tid': 2, - 'args': {'name': 'C'}}, - {'ts': 10, 'ph': 'X', 'dur': 2, 'pid': 2, 'tid': 2, - 'args': {'name': 'D'}}, - {'ts': 13, 'ph': 'X', 'dur': 1, 'pid': 2, 'tid': 1, - 'args': {'name': 'F'}}, - {'ts': 12, 'ph': 'X', 'dur': 3, 'pid': 2, 'tid': 1, - 'args': {'name': 'E'}}] - - def setUp(self): - self.tree_threshold = _IntervalTree._TRESHOLD - _IntervalTree._TRESHOLD = 2 # Expose more edge cases in the tree. - self.track = TracingTrack(None, ['A', 'B', 'C', 'D']) - - def tearDown(self): - _IntervalTree._TRESHOLD = self.tree_threshold - - def EventToMicroseconds(self, event): - result = copy.deepcopy(event) - if 'ts' in result: - result['ts'] *= 1000 - if 'dur' in result: - result['dur'] *= 1000 - return result - - def CheckTrack(self, timestamp, names): - self.track._IndexEvents(strict=True) - self.assertEqual( - set((e.args['name'] for e in self.track.EventsAt(timestamp))), - set(names)) - - def CheckIntervals(self, events): - """All tests should produce the following sequence of intervals, each - identified by a 'name' in the event args. - - Timestamp - 3 | A - 4 | - 5 | | B - 6 | - 7 - .. - 10 | | C, D - 11 | - 12 | E - 13 | | F - 14 | - """ - self.track.Handle('Tracing.dataCollected', - {'params': {'value': [self.EventToMicroseconds(e) - for e in events]}}) - self.CheckTrack(0, '') - self.CheckTrack(2, '') - self.CheckTrack(3, 'A') - self.CheckTrack(4, 'A') - self.CheckTrack(5, 'AB') - self.CheckTrack(6, 'A') - self.CheckTrack(7, '') - self.CheckTrack(9, '') - self.CheckTrack(10, 'CD') - self.CheckTrack(11, 'D') - self.CheckTrack(12, 'E') - self.CheckTrack(13, 'EF') - self.CheckTrack(14, 'E') - self.CheckTrack(15, '') - self.CheckTrack(100, '') - - def testComplete(self): - # These are deliberately out of order. - self.CheckIntervals([ - {'ts': 5, 'ph': 'X', 'dur': 1, 'args': {'name': 'B'}}, - {'ts': 3, 'ph': 'X', 'dur': 4, 'args': {'name': 'A'}}, - {'ts': 10, 'ph': 'X', 'dur': 1, 'args': {'name': 'C'}}, - {'ts': 10, 'ph': 'X', 'dur': 2, 'args': {'name': 'D'}}, - {'ts': 13, 'ph': 'X', 'dur': 1, 'args': {'name': 'F'}}, - {'ts': 12, 'ph': 'X', 'dur': 3, 'args': {'name': 'E'}}]) - - def testDuration(self): - self.CheckIntervals([ - {'ts': 3, 'ph': 'B', 'args': {'name': 'A'}}, - {'ts': 5, 'ph': 'B', 'args': {'name': 'B'}}, - {'ts': 6, 'ph': 'E'}, - {'ts': 7, 'ph': 'E'}, - # Since async intervals aren't named and must be nested, we fudge the - # beginning of D by a tenth to ensure it's consistently detected as the - # outermost event. - {'ts': 9.9, 'ph': 'B', 'args': {'name': 'D'}}, - {'ts': 10, 'ph': 'B', 'args': {'name': 'C'}}, - {'ts': 11, 'ph': 'E'}, - # End of D. As end times are exclusive this should not conflict with the - # start of E. - {'ts': 12, 'ph': 'E'}, - {'ts': 12, 'ph': 'B', 'args': {'name': 'E'}}, - {'ts': 13, 'ph': 'B', 'args': {'name': 'F'}}, - {'ts': 14, 'ph': 'E'}, - {'ts': 15, 'ph': 'E'}]) - - def testBadDurationExtraBegin(self): - self.assertRaises(devtools_monitor.DevToolsConnectionException, - self.CheckIntervals, - [{'ts': 3, 'ph': 'B'}, - {'ts': 4, 'ph': 'B'}, - {'ts': 5, 'ph': 'E'}]) - - def testBadDurationExtraEnd(self): - self.assertRaises(devtools_monitor.DevToolsConnectionException, - self.CheckIntervals, - [{'ts': 3, 'ph': 'B'}, - {'ts': 4, 'ph': 'E'}, - {'ts': 5, 'ph': 'E'}]) - - def testAsync(self): - self.CheckIntervals([ - # A, B and F have the same category/id (so that A & B nest); C-E do not. - {'ts': 3, 'ph': 'b', 'cat': 'A', 'id': 1, 'args': {'name': 'A'}}, - {'ts': 5, 'ph': 'b', 'cat': 'A', 'id': 1, 'args': {'name': 'B'}}, - # Not indexable. - {'ts': 4, 'ph': 'n', 'cat': 'A', 'id': 1, 'args': {'name': 'A'}}, - {'ts': 6, 'ph': 'e', 'cat': 'A', 'id': 1}, - {'ts': 7, 'ph': 'e', 'cat': 'A', 'id': 1}, - {'ts': 10, 'ph': 'b', 'cat': 'B', 'id': 2, 'args': {'name': 'D'}}, - {'ts': 10, 'ph': 'b', 'cat': 'B', 'id': 3, 'args': {'name': 'C'}}, - {'ts': 11, 'ph': 'e', 'cat': 'B', 'id': 3}, - {'ts': 12, 'ph': 'e', 'cat': 'B', 'id': 2}, - {'ts': 12, 'ph': 'b', 'cat': 'A', 'id': 2, 'args': {'name': 'E'}}, - {'ts': 13, 'ph': 'b', 'cat': 'A', 'id': 1, 'args': {'name': 'F'}}, - {'ts': 14, 'ph': 'e', 'cat': 'A', 'id': 1}, - {'ts': 15, 'ph': 'e', 'cat': 'A', 'id': 2}]) - - def testBadAsyncIdMismatch(self): - self.assertRaises( - devtools_monitor.DevToolsConnectionException, - self.CheckIntervals, - [{'ts': 3, 'ph': 'b', 'cat': 'A', 'id': 1, 'args': {'name': 'A'}}, - {'ts': 5, 'ph': 'b', 'cat': 'A', 'id': 1, 'args': {'name': 'B'}}, - {'ts': 6, 'ph': 'e', 'cat': 'A', 'id': 2}, - {'ts': 7, 'ph': 'e', 'cat': 'A', 'id': 1}]) - - def testBadAsyncExtraBegin(self): - self.assertRaises( - devtools_monitor.DevToolsConnectionException, - self.CheckIntervals, - [{'ts': 3, 'ph': 'b', 'cat': 'A', 'id': 1, 'args': {'name': 'A'}}, - {'ts': 5, 'ph': 'b', 'cat': 'A', 'id': 1, 'args': {'name': 'B'}}, - {'ts': 6, 'ph': 'e', 'cat': 'A', 'id': 1}]) - - def testBadAsyncExtraEnd(self): - self.assertRaises( - devtools_monitor.DevToolsConnectionException, - self.CheckIntervals, - [{'ts': 3, 'ph': 'b', 'cat': 'A', 'id': 1, 'args': {'name': 'A'}}, - {'ts': 5, 'ph': 'e', 'cat': 'A', 'id': 1}, - {'ts': 6, 'ph': 'e', 'cat': 'A', 'id': 1}]) - - def testObject(self): - # A and E share ids, which is okay as their scopes are disjoint. - self.CheckIntervals([ - {'ts': 3, 'ph': 'N', 'id': 1, 'args': {'name': 'A'}}, - {'ts': 5, 'ph': 'N', 'id': 2, 'args': {'name': 'B'}}, - {'ts': 6, 'ph': 'D', 'id': 2}, - {'ts': 6, 'ph': 'O', 'id': 2}, # Ignored. - {'ts': 7, 'ph': 'D', 'id': 1}, - {'ts': 10, 'ph': 'N', 'id': 3, 'args': {'name': 'D'}}, - {'ts': 10, 'ph': 'N', 'id': 4, 'args': {'name': 'C'}}, - {'ts': 11, 'ph': 'D', 'id': 4}, - {'ts': 12, 'ph': 'D', 'id': 3}, - {'ts': 12, 'ph': 'N', 'id': 1, 'args': {'name': 'E'}}, - {'ts': 13, 'ph': 'N', 'id': 5, 'args': {'name': 'F'}}, - {'ts': 14, 'ph': 'D', 'id': 5}, - {'ts': 15, 'ph': 'D', 'id': 1}]) - - def testMixed(self): - # A and E are objects, B complete, D a duration, and C and F async. - self.CheckIntervals(self._MIXED_EVENTS) - - def testEventSerialization(self): - for e in self._MIXED_EVENTS: - event = Event(e) - json_dict = event.ToJsonDict() - deserialized_event = Event.FromJsonDict(json_dict) - self.assertEquals( - event.tracing_event, deserialized_event.tracing_event) - - def testTracingTrackSerialization(self): - self._HandleEvents(self._MIXED_EVENTS) - json_dict = self.track.ToJsonDict() - self.assertTrue('events' in json_dict) - deserialized_track = TracingTrack.FromJsonDict(json_dict) - self.assertEquals( - len(self.track._events), len(deserialized_track._events)) - for (e1, e2) in zip(self.track._events, deserialized_track._events): - self.assertEquals(e1.tracing_event, e2.tracing_event) - - def testEventsEndingBetween(self): - self._HandleEvents(self._EVENTS) - self.assertEqual(set('ABCDEF'), - set([e.args['name'] - for e in self.track.EventsEndingBetween(0, 100)])) - self.assertFalse([e.args['name'] - for e in self.track.EventsEndingBetween(3, 5)]) - self.assertTrue('B' in set([e.args['name'] - for e in self.track.EventsEndingBetween(3, 6)])) - self.assertEqual(set('B'), - set([e.args['name'] - for e in self.track.EventsEndingBetween(3, 6)])) - - def testOverlappingEvents(self): - self._HandleEvents(self._EVENTS) - self.assertEqual(set('ABCDEF'), - set([e.args['name'] - for e in self.track.OverlappingEvents(0, 100)])) - self.assertFalse([e.args['name'] - for e in self.track.OverlappingEvents(0, 2)]) - self.assertEqual(set('BA'), - set([e.args['name'] - for e in self.track.OverlappingEvents(4, 5.1)])) - self.assertEqual(set('ACD'), - set([e.args['name'] - for e in self.track.OverlappingEvents(6, 10.1)])) - - def testEventFromStep(self): - events = [ - {'ts': 5, 'ph': 'X', 'dur': 10, 'pid': 2, 'tid': 1, 'id': '0x123', - 'name': 'B'}, - {'ts': 5, 'ph': 'X', 'dur': 2, 'pid': 2, 'tid': 1, 'id': '0x12343', - 'name': 'A'}] - step_events = [{'ts': 6, 'ph': 'T', 'pid': 2, 'tid': 1, 'id': '0x123', - 'name': 'B', 'args': {'step': 'Bla'}}, - {'ts': 4, 'ph': 'T', 'pid': 2, 'tid': 1, 'id': '0x123', - 'name': 'B', 'args': {'step': 'Bla'}}, - {'ts': 6, 'ph': 'T', 'pid': 12, 'tid': 1, 'id': '0x123', - 'name': 'B', 'args': {'step': 'Bla'}}, - {'ts': 6, 'ph': 'T', 'pid': 2, 'tid': 1, 'id': '0x1234', - 'name': 'B', 'args': {'step': 'Bla'}}, - {'ts': 6, 'ph': 'T', 'pid': 2, 'tid': 1, 'id': '0x123', - 'name': 'A', 'args': {'step': 'Bla'}}, - {'ts': 6, 'ph': 'n', 'pid': 2, 'tid': 1, 'id': '0x123', - 'name': 'B', 'args': {'step': 'Bla'}}, - {'ts': 6, 'ph': 'n', 'pid': 2, 'tid': 1, 'id': '0x123', - 'name': 'B', 'args': {}}] - self._HandleEvents(events + step_events) - trace_events = self.track.GetEvents() - self.assertEquals(9, len(trace_events)) - # pylint: disable=unbalanced-tuple-unpacking - (event, _, step_event, outside, wrong_pid, wrong_id, wrong_name, - wrong_phase, no_step) = trace_events - self.assertEquals(event, self.track.EventFromStep(step_event)) - self.assertIsNone(self.track.EventFromStep(outside)) - self.assertIsNone(self.track.EventFromStep(wrong_pid)) - self.assertIsNone(self.track.EventFromStep(wrong_id)) - self.assertIsNone(self.track.EventFromStep(wrong_name)) - # Invalid events - with self.assertRaises(AssertionError): - self.track.EventFromStep(wrong_phase) - with self.assertRaises(AssertionError): - self.track.EventFromStep(no_step) - - def testFilterPidTid(self): - self._HandleEvents(self._EVENTS) - tracing_track = self.track.Filter(2, 1) - self.assertTrue(tracing_track is not self.track) - self.assertEquals(4, len(tracing_track.GetEvents())) - tracing_track = self.track.Filter(2, 42) - self.assertEquals(0, len(tracing_track.GetEvents())) - - def testGetMainFrameID(self): - _MAIN_FRAME_ID = 0xffff - _SUBFRAME_ID = 0xaaaa - events = [ - {'ts': 7, 'ph': 'X', 'dur': 10, 'pid': 2, 'tid': 1, 'id': '0x123', - 'name': 'navigationStart', 'cat': 'blink.user_timing', - 'args': {'frame': _SUBFRAME_ID}}, - {'ts': 8, 'ph': 'X', 'dur': 2, 'pid': 2, 'tid': 1, 'id': '0x12343', - 'name': 'A'}, - {'ts': 3, 'ph': 'X', 'dur': 10, 'pid': 2, 'tid': 1, 'id': '0x125', - 'name': 'navigationStart', 'cat': 'blink.user_timing', - 'args': {'frame': _MAIN_FRAME_ID}}, - ] - self._HandleEvents(events) - self.assertEquals(_MAIN_FRAME_ID, self.track.GetMainFrameID()) - - def testGetMatchingEvents(self): - _MAIN_FRAME_ID = 0xffff - _SUBFRAME_ID = 0xaaaa - events = [ - {'ts': 7, 'ph': 'X', 'dur': 10, 'pid': 2, 'tid': 1, 'id': '0x123', - 'name': 'navigationStart', 'cat': 'blink.user_timing', - 'args': {'frame': _SUBFRAME_ID}}, - {'ts': 8, 'ph': 'X', 'dur': 2, 'pid': 2, 'tid': 1, 'id': '0x12343', - 'name': 'A'}, - {'ts': 3, 'ph': 'X', 'dur': 10, 'pid': 2, 'tid': 1, 'id': '0x125', - 'name': 'navigationStart', 'cat': 'blink.user_timing', - 'args': {'frame': _MAIN_FRAME_ID}}, - ] - self._HandleEvents(events) - matching_events = self.track.GetMatchingEvents('blink.user_timing', - 'navigationStart') - self.assertEquals(2, len(matching_events)) - self.assertListEqual([self.track.GetEvents()[0], - self.track.GetEvents()[2]], matching_events) - - matching_main_frame_events = self.track.GetMatchingMainFrameEvents( - 'blink.user_timing', 'navigationStart') - self.assertEquals(1, len(matching_main_frame_events)) - self.assertListEqual([self.track.GetEvents()[2]], - matching_main_frame_events) - - def testFilterCategories(self): - events = [ - {'ts': 5, 'ph': 'X', 'dur': 10, 'pid': 2, 'tid': 1, 'cat': 'A'}, - {'ts': 5, 'ph': 'X', 'dur': 10, 'pid': 2, 'tid': 1, 'cat': 'B'}, - {'ts': 5, 'ph': 'X', 'dur': 10, 'pid': 2, 'tid': 1, 'cat': 'C,D'}, - {'ts': 5, 'ph': 'X', 'dur': 10, 'pid': 2, 'tid': 1, 'cat': 'A,B,C,D'}] - self._HandleEvents(events) - tracing_events = self.track.GetEvents() - self.assertEquals(4, len(tracing_events)) - filtered_events = self.track.Filter(categories=None).GetEvents() - self.assertListEqual(tracing_events, filtered_events) - filtered_events = self.track.Filter(categories=set(['A'])).GetEvents() - self.assertEquals(2, len(filtered_events)) - self.assertListEqual([tracing_events[0], tracing_events[3]], - filtered_events) - filtered_events = self.track.Filter(categories=set(['Z'])).GetEvents() - self.assertEquals(0, len(filtered_events)) - filtered_events = self.track.Filter(categories=set(['B', 'C'])).GetEvents() - self.assertEquals(3, len(filtered_events)) - self.assertListEqual(tracing_events[1:], filtered_events) - self.assertSetEqual( - set('A'), self.track.Filter(categories=set('A')).Categories()) - - def testHasLoadingSucceeded(self): - cat = 'navigation' - on_navigate = 'RenderFrameImpl::OnNavigate' - fail_provisional = 'RenderFrameImpl::didFailProvisionalLoad' - fail_load = 'RenderFrameImpl::didFailLoad' - - track = TracingTrack.FromJsonDict({'categories': [cat], 'events': []}) - with self.assertRaises(AssertionError): - track.HasLoadingSucceeded() - - track = TracingTrack.FromJsonDict({'categories': [cat], 'events': [ - {'cat': cat, 'name': on_navigate, 'args': {'id': 1}, - 'ts': 5, 'ph': 'X', 'dur': 10, 'pid': 1, 'tid': 1}]}) - self.assertTrue(track.HasLoadingSucceeded()) - - track = TracingTrack.FromJsonDict({'categories': [cat], 'events': [ - {'cat': cat, 'name': on_navigate, 'args': {'id': 1}, - 'ts': 5, 'ph': 'X', 'dur': 10, 'pid': 1, 'tid': 1}, - {'cat': cat, 'name': on_navigate, 'args': {'id': 2}, - 'ts': 5, 'ph': 'X', 'dur': 10, 'pid': 1, 'tid': 1}, - {'cat': cat, 'name': fail_provisional, 'args': {'id': 2}, - 'ts': 5, 'ph': 'X', 'dur': 10, 'pid': 1, 'tid': 1}]}) - self.assertTrue(track.HasLoadingSucceeded()) - - track = TracingTrack.FromJsonDict({'categories': [cat], 'events': [ - {'cat': cat, 'name': on_navigate, 'args': {'id': 1}, - 'ts': 5, 'ph': 'X', 'dur': 10, 'pid': 1, 'tid': 1}, - {'cat': cat, 'name': fail_provisional, 'args': {'id': 1}, - 'ts': 5, 'ph': 'X', 'dur': 10, 'pid': 1, 'tid': 1}]}) - self.assertFalse(track.HasLoadingSucceeded()) - - track = TracingTrack.FromJsonDict({'categories': [cat], 'events': [ - {'cat': cat, 'name': on_navigate, 'args': {'id': 1}, - 'ts': 5, 'ph': 'X', 'dur': 10, 'pid': 1, 'tid': 1}, - {'cat': cat, 'name': fail_load, 'args': {'id': 1}, - 'ts': 5, 'ph': 'X', 'dur': 10, 'pid': 1, 'tid': 1}]}) - self.assertFalse(track.HasLoadingSucceeded()) - - track = TracingTrack.FromJsonDict({'categories': [cat], 'events': [ - {'cat': cat, 'name': on_navigate, 'args': {'id': 1}, - 'ts': 5, 'ph': 'X', 'dur': 10, 'pid': 1, 'tid': 1}, - {'cat': cat, 'name': fail_load, 'args': {'id': 1}, - 'ts': 5, 'ph': 'X', 'dur': 10, 'pid': 1, 'tid': 1}]}) - self.assertFalse(track.HasLoadingSucceeded()) - - def _HandleEvents(self, events): - self.track.Handle('Tracing.dataCollected', {'params': {'value': [ - self.EventToMicroseconds(e) for e in events]}}) - - -class IntervalTreeTestCase(unittest.TestCase): - class FakeEvent(object): - def __init__(self, start_msec, end_msec): - self.start_msec = start_msec - self.end_msec = end_msec - - def __eq__(self, o): - return self.start_msec == o.start_msec and self.end_msec == o.end_msec - - _COUNT = 1000 - - def testCreateTree(self): - events = [self.FakeEvent(100 * i, 100 * (i + 1)) - for i in range(self._COUNT)] - tree = _IntervalTree.FromEvents(events) - self.assertEquals(0, tree.start) - self.assertEquals(100 * self._COUNT, tree.end) - self.assertFalse(tree._IsLeaf()) - - def testEventsAt(self): - events = ([self.FakeEvent(100 * i, 100 * (i + 1)) - for i in range(self._COUNT)] - + [self.FakeEvent(100 * i + 50, 100 * i + 150) - for i in range(self._COUNT)]) - tree = _IntervalTree.FromEvents(events) - self.assertEquals(0, tree.start) - self.assertEquals(100 * self._COUNT + 50, tree.end) - self.assertFalse(tree._IsLeaf()) - for i in range(self._COUNT): - self.assertEquals(2, len(tree.EventsAt(100 * i + 75))) - # Add instant events, check that they are excluded. - events += [self.FakeEvent(100 * i + 75, 100 * i + 75) - for i in range(self._COUNT)] - tree = _IntervalTree.FromEvents(events) - self.assertEquals(3 * self._COUNT, len(tree._events)) - for i in range(self._COUNT): - self.assertEquals(2, len(tree.EventsAt(100 * i + 75))) - - def testOverlappingEvents(self): - events = ([self.FakeEvent(100 * i, 100 * (i + 1)) - for i in range(self._COUNT)] - + [self.FakeEvent(100 * i + 50, 100 * i + 150) - for i in range(self._COUNT)]) - tree = _IntervalTree.FromEvents(events) - self.assertEquals(0, tree.start) - self.assertEquals(100 * self._COUNT + 50, tree.end) - self.assertFalse(tree._IsLeaf()) - # 400 -> 500, 450 -> 550, 500 -> 600 - self.assertEquals(3, len(tree.OverlappingEvents(450, 550))) - overlapping = sorted( - tree.OverlappingEvents(450, 550), key=operator.attrgetter('start_msec')) - self.assertEquals(self.FakeEvent(400, 500), overlapping[0]) - self.assertEquals(self.FakeEvent(450, 550), overlapping[1]) - self.assertEquals(self.FakeEvent(500, 600), overlapping[2]) - self.assertEquals(8, len(tree.OverlappingEvents(450, 800))) - # Add instant events, check that they are included. - events += [self.FakeEvent(500, 500) for i in range(10)] - tree = _IntervalTree.FromEvents(events) - self.assertEquals(3 + 10, len(tree.OverlappingEvents(450, 550))) - self.assertEquals(8 + 10, len(tree.OverlappingEvents(450, 800))) - - def testEventMatches(self): - event = Event({'name': 'foo', - 'cat': 'bar', - 'ph': 'X', - 'ts': 0, 'dur': 0}) - self.assertTrue(event.Matches('bar', 'foo')) - self.assertFalse(event.Matches('bar', 'biz')) - self.assertFalse(event.Matches('biz', 'foo')) - - event = Event({'name': 'foo', - 'cat': 'bar,baz,bizbiz', - 'ph': 'X', - 'ts': 0, 'dur': 0}) - self.assertTrue(event.Matches('bar', 'foo')) - self.assertTrue(event.Matches('baz', 'foo')) - self.assertFalse(event.Matches('bar', 'biz')) - self.assertFalse(event.Matches('biz', 'foo')) - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/unmaintained/README.md b/tools/android/loading/unmaintained/README.md deleted file mode 100644 index 295323b7..0000000 --- a/tools/android/loading/unmaintained/README.md +++ /dev/null
@@ -1,2 +0,0 @@ -This directory contains unmaintained code that still has value, such as -experimental or temporary scripts.
diff --git a/tools/android/loading/unmaintained/gce_validation_collect.sh b/tools/android/loading/unmaintained/gce_validation_collect.sh deleted file mode 100755 index ec85dca..0000000 --- a/tools/android/loading/unmaintained/gce_validation_collect.sh +++ /dev/null
@@ -1,48 +0,0 @@ -#!/bin/bash -# Copyright 2016 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. - -# Takes a list of URLs (infile), and runs analyse.py on them in parallel on a -# device and on GCE, in a sychronized manner (the task is started on both -# platforms at the same time). - -infile=$1 -outdir=$2 -instance_ip=$3 -repeat_count=$4 - -for site in $(< $infile); do - echo $site - output_subdir=$(echo "$site"|tr "/:" "_") - echo 'Start remote task' - cat >urls.json << EOF - { - "urls" : [ - "$site" - ], - "repeat_count" : "$repeat_count", - "emulate_device" : "Nexus 4" - } -EOF - - while [ "$(curl http://$instance_ip:8080/status)" != "Idle" ]; do - echo 'Waiting for instance to be ready, retry in 5s' - sleep 5 - done - curl -X POST -d @urls.json http://$instance_ip:8080/set_tasks - - echo 'Run on device' - mkdir $outdir/$output_subdir - for ((run=0;run<$repeat_count;++run)); do - echo '****' $run - tools/android/loading/analyze.py log_requests \ - --devtools_port 9222 \ - --url $site \ - --output $outdir/${output_subdir}/${run} - if [ $? -ne 0 ]; then - echo "Analyze failed. Wait a bit for device to recover." - sleep 3 - fi - done -done
diff --git a/tools/android/loading/unmaintained/gce_validation_compare.sh b/tools/android/loading/unmaintained/gce_validation_compare.sh deleted file mode 100755 index 88e26df1..0000000 --- a/tools/android/loading/unmaintained/gce_validation_compare.sh +++ /dev/null
@@ -1,75 +0,0 @@ -#!/bin/bash -# Copyright 2016 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. - -# gce_validation_compare.sh rootdir compare_filename -# root_dir: root directory for the experiment. -# compare_filename: file where the comparison breakdown is output. -# -# Computes core sets from GCE and device experiment resutls, and compare them. -# The expected directory structure is: -# -# root_dir/ -# cloud/ -# url1/ # Can be any name as long as it is mirrored under device/. -# run1.trace # Can be any name. -# run2.trace -# ... -# url2/ -# ... -# device/ -# url1/ -# run1.trace -# run2.trace -# ... -# url2/ -# ... - -root_dir=$1 -compare_filename=$2 - -rm $compare_filename - -# Check directory structure. -if [ ! -d $root_dir/cloud ]; then - echo "$root_dir/cloud missing!" - exit 1 -fi - -if [ ! -d $root_dir/device ]; then - echo "$root_dir/device missing!" - exit 1 -fi - -for device_file in $root_dir/device/*/ ; do - cloud_file=$root_dir/cloud/$(basename $device_file) - if [ ! -d $cloud_file ]; then - echo "$cloud_file not found" - fi -done - -for cloud_file in $root_dir/cloud/*/ ; do - device_file=$root_dir/device/$(basename $device_file) - if [ ! -d $device_file ]; then - echo "$device_file not found" - fi -done - -# Loop through all the subdirectories, compute the core sets and compare them. -for device_file in $root_dir/device/*/ ; do - base_name=$(basename $device_file) - python tools/android/loading/core_set.py page_core --sets device/$base_name \ - --output $device_file/core_set.json --prefix $device_file - - cloud_file=$root_dir/cloud/$base_name - if [ -d $cloud_file ]; then - python tools/android/loading/core_set.py page_core --sets cloud/$base_name \ - --output $cloud_file/core_set.json --prefix $cloud_file - - compare_result=$(python tools/android/loading/core_set.py compare \ - --a $cloud_file/core_set.json --b $device_file/core_set.json) - compare_result+=" $base_name" - echo $compare_result >> $compare_filename - fi -done
diff --git a/tools/android/loading/user_satisfied_lens.py b/tools/android/loading/user_satisfied_lens.py deleted file mode 100644 index 2e0b4be..0000000 --- a/tools/android/loading/user_satisfied_lens.py +++ /dev/null
@@ -1,253 +0,0 @@ -# Copyright 2016 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. - -"""Identifies key events related to user satisfaction. - -Several lenses are defined, for example FirstTextPaintLens and -FirstSignificantPaintLens. - -When run from the command line, takes a lens name and a trace, and prints the -fingerprints of the critical resources to stdout. -""" -import logging -import operator - -import common_util - - -class _UserSatisfiedLens(object): - """A base class for all user satisfaction metrics. - - All of these work by identifying a user satisfaction event from the trace, and - then building a set of request ids whose loading is needed to achieve that - event. Subclasses need only provide the time computation. The base class will - use that to construct the request ids. - """ - _ATTRS = ['_satisfied_msec', '_event_msec', '_postload_msec', - '_critical_request_ids'] - - def CriticalRequests(self): - """Critical requests. - - Returns: - A sequence of request_track.Request objects representing an estimate of - all requests that are necessary for the user satisfaction defined by this - class. - """ - raise NotImplementedError - - def CriticalRequestIds(self): - """Ids of critical requests.""" - return set(rq.request_id for rq in self.CriticalRequests()) - - def CriticalFingerprints(self): - """Fingerprints of critical requests.""" - return set(rq.fingerprint for rq in self.CriticalRequests()) - - def PostloadTimeMsec(self): - """Return postload time. - - The postload time is an estimate of the amount of time needed by chrome to - transform the critical results into the satisfying event. - - Returns: - Postload time in milliseconds. - """ - return 0 - - def SatisfiedMs(self): - """Returns user satisfied timestamp, in ms. - - This is *not* a unix timestamp. It is relative to the same point in time - as the request_time field in request_track.Timing. - """ - return self._satisfied_msec - - @classmethod - def RequestsBefore(cls, request_track, time_ms): - return [rq for rq in request_track.GetEvents() - if rq.end_msec <= time_ms] - - -class PLTLens(_UserSatisfiedLens): - """A lens built using page load time (PLT) as the metric of user satisfaction. - """ - def __init__(self, trace): - self._satisfied_msec = PLTLens._ComputePlt(trace) - self._critical_requests = _UserSatisfiedLens.RequestsBefore( - trace.request_track, self._satisfied_msec) - - def CriticalRequests(self): - return self._critical_requests - - @classmethod - def _ComputePlt(cls, trace): - mark_load_events = trace.tracing_track.GetMatchingEvents( - 'devtools.timeline', 'MarkLoad') - # Some traces contain several load events for the main frame. - main_frame_load_events = filter( - lambda e: e.args['data']['isMainFrame'], mark_load_events) - if main_frame_load_events: - return max(e.start_msec for e in main_frame_load_events) - # Main frame onLoad() didn't finish. Take the end of the last completed - # request. - return max(r.end_msec or -1 for r in trace.request_track.GetEvents()) - - -class RequestFingerprintLens(_UserSatisfiedLens): - """A lens built using requests in a trace that match a set of fingerprints.""" - def __init__(self, trace, fingerprints): - fingerprints = set(fingerprints) - self._critical_requests = [rq for rq in trace.request_track.GetEvents() - if rq.fingerprint in fingerprints] - - def CriticalRequests(self): - """Ids of critical requests.""" - return set(self._critical_requests) - - -class _FirstEventLens(_UserSatisfiedLens): - """Helper abstract subclass that defines users first event manipulations.""" - # pylint can't handle abstract subclasses. - # pylint: disable=abstract-method - - def __init__(self, trace): - """Initialize the lens. - - Args: - trace: (LoadingTrace) the trace to use in the analysis. - """ - self._satisfied_msec = None - self._event_msec = None - self._postload_msec = None - self._critical_request_ids = None - if trace is None: - return - self._CalculateTimes(trace) - self._critical_requests = _UserSatisfiedLens.RequestsBefore( - trace.request_track, self._satisfied_msec) - self._critical_request_ids = set(rq.request_id - for rq in self._critical_requests) - if self._critical_requests: - last_load = max(rq.end_msec for rq in self._critical_requests) - else: - last_load = float('inf') - self._postload_msec = self._event_msec - last_load - - def CriticalRequests(self): - """Override.""" - return self._critical_requests - - def PostloadTimeMsec(self): - """Override.""" - return self._postload_msec - - def ToJsonDict(self): - return common_util.SerializeAttributesToJsonDict({}, self, self._ATTRS) - - @classmethod - def FromJsonDict(cls, json_dict): - result = cls(None) - return common_util.DeserializeAttributesFromJsonDict( - json_dict, result, cls._ATTRS) - - def _CalculateTimes(self, trace): - """Subclasses should implement to set _satisfied_msec and _event_msec.""" - raise NotImplementedError - - @classmethod - def _CheckCategory(cls, tracing_track, category): - assert category in tracing_track.Categories(), ( - 'The "%s" category must be enabled.' % category) - - @classmethod - def _ExtractBestTiming(cls, times): - if not times: - return float('inf') - assert len(times) == 1, \ - 'Unexpected duplicate {}: {} with spread of {}'.format( - str(cls), len(times), max(times) - min(times)) - return float(max(times)) - - -class FirstTextPaintLens(_FirstEventLens): - """Define satisfaction by the first text paint. - - This event is taken directly from a trace. - """ - _EVENT_CATEGORY = 'blink.user_timing' - def _CalculateTimes(self, trace): - self._CheckCategory(trace.tracing_track, self._EVENT_CATEGORY) - first_paints = [ - e.start_msec for e in trace.tracing_track.GetMatchingMainFrameEvents( - 'blink.user_timing', 'firstPaint')] - self._satisfied_msec = self._event_msec = \ - self._ExtractBestTiming(first_paints) - - -class FirstContentfulPaintLens(_FirstEventLens): - """Define satisfaction by the first contentful paint. - - This event is taken directly from a trace. Internally to chrome it's computed - by filtering out things like background paint from firstPaint. - """ - _EVENT_CATEGORY = 'blink.user_timing' - def _CalculateTimes(self, trace): - self._CheckCategory(trace.tracing_track, self._EVENT_CATEGORY) - first_paints = [ - e.start_msec for e in trace.tracing_track.GetMatchingMainFrameEvents( - 'blink.user_timing', 'firstContentfulPaint')] - self._satisfied_msec = self._event_msec = \ - self._ExtractBestTiming(first_paints) - - -class FirstSignificantPaintLens(_FirstEventLens): - """Define satisfaction by the first paint after a big layout change. - - Our satisfaction time is that of the layout change, as all resources must have - been loaded to compute the layout. Our event time is that of the next paint as - that is the observable event. - """ - _FIRST_LAYOUT_COUNTER = 'LayoutObjectsThatHadNeverHadLayout' - _EVENT_CATEGORIES = ['blink', 'disabled-by-default-blink.debug.layout'] - def _CalculateTimes(self, trace): - for cat in self._EVENT_CATEGORIES: - self._CheckCategory(trace.tracing_track, cat) - paint_tree_times = [] - layouts = [] # (layout item count, msec). - for e in trace.tracing_track.GetEvents(): - if ('frame' in e.args and - e.args['frame'] != trace.tracing_track.GetMainFrameID()): - continue - # If we don't know have a frame id, we assume it applies to all events. - - if e.Matches('blink', 'FrameView::paintTree'): - paint_tree_times.append(e.start_msec) - if ('counters' in e.args and - self._FIRST_LAYOUT_COUNTER in e.args['counters']): - layouts.append((e.args['counters'][self._FIRST_LAYOUT_COUNTER], - e.start_msec)) - assert layouts, 'No layout events' - assert paint_tree_times,'No paintTree times' - layouts.sort(key=operator.itemgetter(0), reverse=True) - self._satisfied_msec = layouts[0][1] - self._event_msec = min(t for t in paint_tree_times - if t > self._satisfied_msec) - - -def main(lens_name, trace_file): - assert (lens_name in globals() and - not lens_name.startswith('_') and - lens_name.endswith('Lens')), 'Bad lens %s' % lens_name - lens_cls = globals()[lens_name] - trace = loading_trace.LoadingTrace.FromJsonFile(trace_file) - lens = lens_cls(trace) - for fp in sorted(lens.CriticalFingerprints()): - print fp - - -if __name__ == '__main__': - import sys - import loading_trace - main(sys.argv[1], sys.argv[2])
diff --git a/tools/android/loading/user_satisfied_lens_unittest.py b/tools/android/loading/user_satisfied_lens_unittest.py deleted file mode 100644 index ed6c753..0000000 --- a/tools/android/loading/user_satisfied_lens_unittest.py +++ /dev/null
@@ -1,209 +0,0 @@ -# Copyright 2016 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. - -import unittest - -import request_track -import test_utils -import user_satisfied_lens - - -class TraceCreator(object): - def __init__(self): - self._request_index = 1 - - def RequestAt(self, timestamp_msec, duration=1): - timestamp_sec = float(timestamp_msec) / 1000 - rq = request_track.Request.FromJsonDict({ - 'url': 'http://bla-%s-.com' % timestamp_msec, - 'request_id': '0.%s' % self._request_index, - 'frame_id': '123.%s' % timestamp_msec, - 'initiator': {'type': 'other'}, - 'timestamp': timestamp_sec, - 'timing': {'request_time': timestamp_sec, - 'loading_finished': duration} - }) - self._request_index += 1 - return rq - - def CreateTrace(self, requests, events, main_frame_id): - loading_trace = test_utils.LoadingTraceFromEvents( - requests, trace_events=events) - loading_trace.tracing_track.SetMainFrameID(main_frame_id) - loading_trace.url = 'http://www.dummy.com' - return loading_trace - - -class UserSatisfiedLensTestCase(unittest.TestCase): - # We track all times in milliseconds, but raw trace events are in - # microseconds. - MILLI_TO_MICRO = 1000 - - def setUp(self): - super(UserSatisfiedLensTestCase, self).setUp() - - def testPLTLens(self): - MAINFRAME = 1 - trace_creator = test_utils.TraceCreator() - requests = [trace_creator.RequestAt(1), trace_creator.RequestAt(10), - trace_creator.RequestAt(20)] - loading_trace = trace_creator.CreateTrace( - requests, - [{'ts': 5 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'devtools.timeline', 'pid': 1, 'tid': 1, - 'name': 'MarkLoad', - 'args': {'data': {'isMainFrame': True}}}, - {'ts': 10 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'devtools.timeline', 'pid': 1, 'tid': 1, - 'name': 'MarkLoad', - 'args': {'data': {'isMainFrame': True}}}, - {'ts': 20 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'devtools.timeline', 'pid': 1, 'tid': 1, - 'name': 'MarkLoad', - 'args': {'data': {'isMainFrame': False}}}], MAINFRAME) - lens = user_satisfied_lens.PLTLens(loading_trace) - self.assertEqual(set(['0.1']), lens.CriticalRequestIds()) - self.assertEqual(10, lens.SatisfiedMs()) - - def testFirstContentfulPaintLens(self): - MAINFRAME = 1 - SUBFRAME = 2 - trace_creator = test_utils.TraceCreator() - requests = [trace_creator.RequestAt(1), trace_creator.RequestAt(10), - trace_creator.RequestAt(20)] - loading_trace = trace_creator.CreateTrace( - requests, - [{'ts': 0, 'ph': 'I', - 'cat': 'blink.some_other_user_timing', - 'name': 'firstContentfulPaint'}, - {'ts': 30 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'blink.user_timing', - 'name': 'firstDiscontentPaint'}, - {'ts': 5 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'blink.user_timing', - 'name': 'firstContentfulPaint', - 'args': {'frame': SUBFRAME} }, - {'ts': 12 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'blink.user_timing', - 'name': 'firstContentfulPaint', - 'args': {'frame': MAINFRAME}}], MAINFRAME) - lens = user_satisfied_lens.FirstContentfulPaintLens(loading_trace) - self.assertEqual(set(['0.1', '0.2']), lens.CriticalRequestIds()) - self.assertEqual(1, lens.PostloadTimeMsec()) - - def testCantGetNoSatisfaction(self): - MAINFRAME = 1 - trace_creator = test_utils.TraceCreator() - requests = [trace_creator.RequestAt(1), trace_creator.RequestAt(10), - trace_creator.RequestAt(20)] - loading_trace = trace_creator.CreateTrace( - requests, - [{'ts': 0, 'ph': 'I', - 'cat': 'not_my_cat', - 'name': 'someEvent', - 'args': {'frame': MAINFRAME}}], MAINFRAME) - loading_trace.tracing_track.SetMainFrameID(MAINFRAME) - lens = user_satisfied_lens.FirstContentfulPaintLens(loading_trace) - self.assertEqual(set(['0.1', '0.2', '0.3']), lens.CriticalRequestIds()) - self.assertEqual(float('inf'), lens.PostloadTimeMsec()) - - def testFirstTextPaintLens(self): - MAINFRAME = 1 - SUBFRAME = 2 - trace_creator = test_utils.TraceCreator() - requests = [trace_creator.RequestAt(1), trace_creator.RequestAt(10), - trace_creator.RequestAt(20)] - loading_trace = trace_creator.CreateTrace( - requests, - [{'ts': 0, 'ph': 'I', - 'cat': 'blink.some_other_user_timing', - 'name': 'firstPaint'}, - {'ts': 30 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'blink.user_timing', - 'name': 'firstishPaint', - 'args': {'frame': MAINFRAME}}, - {'ts': 3 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'blink.user_timing', - 'name': 'firstPaint', - 'args': {'frame': SUBFRAME}}, - {'ts': 12 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'blink.user_timing', - 'name': 'firstPaint', - 'args': {'frame': MAINFRAME}}], MAINFRAME) - loading_trace.tracing_track.SetMainFrameID(MAINFRAME) - lens = user_satisfied_lens.FirstTextPaintLens(loading_trace) - self.assertEqual(set(['0.1', '0.2']), lens.CriticalRequestIds()) - self.assertEqual(1, lens.PostloadTimeMsec()) - - def testFirstSignificantPaintLens(self): - MAINFRAME = 1 - trace_creator = test_utils.TraceCreator() - requests = [trace_creator.RequestAt(1), trace_creator.RequestAt(10), - trace_creator.RequestAt(15), trace_creator.RequestAt(20)] - loading_trace = trace_creator.CreateTrace( - requests, - [{'ts': 0, 'ph': 'I', - 'cat': 'blink', - 'name': 'firstPaint'}, - {'ts': 9 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'blink.user_timing', - 'name': 'FrameView::paintTree'}, - {'ts': 18 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'blink', - 'name': 'FrameView::paintTree'}, - {'ts': 22 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'blink', - 'name': 'FrameView::paintTree'}, - {'ts': 5 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'foobar', 'name': 'biz', - 'args': {'counters': { - 'LayoutObjectsThatHadNeverHadLayout': 10 - } } }, - {'ts': 12 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'foobar', 'name': 'biz', - 'args': {'counters': { - 'LayoutObjectsThatHadNeverHadLayout': 12 - } } }, - {'ts': 15 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'foobar', 'name': 'biz', - 'args': {'counters': { - 'LayoutObjectsThatHadNeverHadLayout': 10 - } } } ], MAINFRAME) - lens = user_satisfied_lens.FirstSignificantPaintLens(loading_trace) - self.assertEqual(set(['0.1', '0.2']), lens.CriticalRequestIds()) - self.assertEqual(7, lens.PostloadTimeMsec()) - - def testRequestFingerprintLens(self): - MAINFRAME = 1 - SUBFRAME = 2 - trace_creator = test_utils.TraceCreator() - requests = [trace_creator.RequestAt(1), trace_creator.RequestAt(10), - trace_creator.RequestAt(20)] - loading_trace = trace_creator.CreateTrace( - requests, - [{'ts': 0, 'ph': 'I', - 'cat': 'blink.some_other_user_timing', - 'name': 'firstContentfulPaint'}, - {'ts': 30 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'blink.user_timing', - 'name': 'firstDiscontentPaint'}, - {'ts': 5 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'blink.user_timing', - 'name': 'firstContentfulPaint', - 'args': {'frame': SUBFRAME} }, - {'ts': 12 * self.MILLI_TO_MICRO, 'ph': 'I', - 'cat': 'blink.user_timing', - 'name': 'firstContentfulPaint', - 'args': {'frame': MAINFRAME}}], MAINFRAME) - lens = user_satisfied_lens.FirstContentfulPaintLens(loading_trace) - self.assertEqual(set(['0.1', '0.2']), lens.CriticalRequestIds()) - self.assertEqual(1, lens.PostloadTimeMsec()) - request_lens = user_satisfied_lens.RequestFingerprintLens( - loading_trace, lens.CriticalFingerprints()) - self.assertEqual(set(['0.1', '0.2']), request_lens.CriticalRequestIds()) - self.assertEqual(0, request_lens.PostloadTimeMsec()) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/util.r b/tools/android/loading/util.r deleted file mode 100644 index a65c572..0000000 --- a/tools/android/loading/util.r +++ /dev/null
@@ -1,47 +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. - -# Useful R routines for analyzing output from several cost_to_csv.py -# output and producing interesting graphs. - -combine.runs <- function(times, prefix, suffix) - do.call("rbind", lapply(times, function (t) - with(read.csv(paste0(prefix, t, suffix)), - data.frame(site, kind, cost, time=t)))) - -get.ordered.names <- function(runs) { - means <- with(runs, tapply(cost, list(site, kind), mean)) - return(names(means[,"cold"])[order(means[,"cold"])]) -} - -plot.warm.cold <- function(runs, main="") { - ordered.names <- get.ordered.names(runs) - n <- length(ordered.names) - par(mar=c(8,4,4,4), bg="white") - plot(NULL, xlim=c(1,25), ylim=range(runs$cost), xaxt="n", - ylab="ms", xlab="", main=main) - axis(1, 1:n, labels=ordered.names, las=2) - getdata <- function(k, t) sapply( - ordered.names, function (s) with(runs, cost[site==s & kind==k & time==t])) - for (t in unique(runs$time)) { - points(1:n, getdata("cold", t), pch=1) - points(1:n, getdata("warm", t), pch=3) - } - legend("topleft", pch=c(1, 3), legend=c("cold", "warm")) -} - -plot.relative.sds <- function(runs, main="") { - sds <- with(runs, tapply(cost, list(site, kind), sd)) - means <- with(runs, tapply(cost, list(site, kind), mean)) - ordered.names <- get.ordered.names(runs) - n <- length(ordered.names) - par(mar=c(8,4,4,4), bg="white") - plot(NULL, xlim=c(1,25), ylim=c(0,.8), - xaxt="n", ylab="Relative SD", xlab="", main=main) - axis(1, 1:n, labels=ordered.names, las=2) - getdata <- function(k) sapply(ordered.names, function(s) (sds/means)[s, k]) - points(1:n, getdata("cold"), pch=1) - points(1:n, getdata("warm"), pch=3) - legend("topleft", pch=c(1, 3), legend=c("cold", "warm")) -}
diff --git a/tools/android/loading/wpr_backend.py b/tools/android/loading/wpr_backend.py deleted file mode 100644 index 25f753c..0000000 --- a/tools/android/loading/wpr_backend.py +++ /dev/null
@@ -1,206 +0,0 @@ -# Copyright 2016 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. - -"""Opens and modifies WPR archive. -""" - -import collections -import os -import re -import sys -from urlparse import urlparse - - -_SRC_DIR = os.path.abspath(os.path.join( - os.path.dirname(__file__), '..', '..', '..')) - -_WEBPAGEREPLAY_DIR = os.path.join(_SRC_DIR, 'third_party', 'webpagereplay') -_WEBPAGEREPLAY_HTTPARCHIVE = os.path.join(_WEBPAGEREPLAY_DIR, 'httparchive.py') - -sys.path.append(os.path.join(_SRC_DIR, 'third_party', 'webpagereplay')) -import httparchive - -# Regex used to parse httparchive.py stdout's when listing all urls. -_PARSE_WPR_REQUEST_REGEX = re.compile(r'^\S+\s+(?P<url>\S+)') - -# Regex used to extract WPR domain from WPR log. -_PARSE_WPR_DOMAIN_REGEX = re.compile(r'^\(WARNING\)\s.*\sHTTP server started on' - r' (?P<netloc>\S+)\s*$') - -# Regex used to extract URLs requests from WPR log. -_PARSE_WPR_URL_REGEX = re.compile( - r'^\((?P<level>\S+)\)\s.*\shttpproxy\..*\s(?P<method>[A-Z]+)\s+' - r'(?P<url>https?://[a-zA-Z0-9\-_:.]+/?\S*)\s.*$') - - -class WprUrlEntry(object): - """Wpr url entry holding request and response infos. """ - - def __init__(self, wpr_request, wpr_response): - self._wpr_response = wpr_response - self.url = self._ExtractUrl(str(wpr_request)) - - def GetResponseHeadersDict(self): - """Get a copied dictionary of available headers. - - Returns: - dict(name -> value) - """ - headers = collections.defaultdict(list) - for (key, value) in self._wpr_response.original_headers: - headers[key.lower()].append(value) - return {k: ','.join(v) for (k, v) in headers.items()} - - def SetResponseHeader(self, name, value): - """Set a header value. - - In the case where the <name> response header is present more than once - in the response header list, then the given value is set only to the first - occurrence of that given headers, and the next ones are removed. - - Args: - name: The name of the response header to set. - value: The value of the response header to set. - """ - assert name.islower() - new_headers = [] - new_header_set = False - for header in self._wpr_response.original_headers: - if header[0].lower() != name: - new_headers.append(header) - elif not new_header_set: - new_header_set = True - new_headers.append((header[0], value)) - if new_header_set: - self._wpr_response.original_headers = new_headers - else: - self._wpr_response.original_headers.append((name, value)) - - def DeleteResponseHeader(self, name): - """Delete a header. - - In the case where the <name> response header is present more than once - in the response header list, this method takes care of removing absolutely - all them. - - Args: - name: The name of the response header field to delete. - """ - assert name.islower() - self._wpr_response.original_headers = \ - [x for x in self._wpr_response.original_headers if x[0].lower() != name] - - def RemoveResponseHeaderDirectives(self, name, directives_blacklist): - """Removed a set of directives from response headers. - - Also removes the cache header in case no more directives are left. - It is useful, for example, to remove 'no-cache' from 'pragma: no-cache'. - - Args: - name: The name of the response header field to modify. - directives_blacklist: Set of lowered directives to remove from list. - """ - response_headers = self.GetResponseHeadersDict() - if name not in response_headers: - return - new_value = [] - for header_name in response_headers[name].split(','): - if header_name.strip().lower() not in directives_blacklist: - new_value.append(header_name) - if new_value: - self.SetResponseHeader(name, ','.join(new_value)) - else: - self.DeleteResponseHeader(name) - - @classmethod - def _ExtractUrl(cls, request_string): - match = _PARSE_WPR_REQUEST_REGEX.match(request_string) - assert match, 'Looks like there is an issue with: {}'.format(request_string) - return match.group('url') - - -class WprArchiveBackend(object): - """WPR archive back-end able to read and modify. """ - - def __init__(self, wpr_archive_path): - """Constructor: - - Args: - wpr_archive_path: The path of the WPR archive to read/modify. - """ - self._wpr_archive_path = wpr_archive_path - self._http_archive = httparchive.HttpArchive.Load(wpr_archive_path) - - def ListUrlEntries(self): - """Iterates over all url entries - - Returns: - A list of WprUrlEntry. - """ - return [WprUrlEntry(request, self._http_archive[request]) - for request in self._http_archive.get_requests()] - - def Persist(self): - """Persists the archive to disk. """ - for request in self._http_archive.get_requests(): - response = self._http_archive[request] - response.headers = response._TrimHeaders(response.original_headers) - self._http_archive.Persist(self._wpr_archive_path) - - -# WPR request seen by the WPR's HTTP proxy. -# is_served: Boolean whether WPR has found a matching resource in the archive. -# method: HTTP method of the request ['GET', 'POST' and so on...]. -# url: The requested URL. -# is_wpr_host: Whether the requested url have WPR has an host such as: -# http://127.0.0.1:<WPR's HTTP listening port>/web-page-replay-command-exit -WprRequest = collections.namedtuple('WprRequest', - ['is_served', 'method', 'url', 'is_wpr_host']) - - -def ExtractRequestsFromLog(log_path): - """Extract list of requested handled by the WPR's HTTP proxy from a WPR log. - - Args: - log_path: The path of the WPR log to parse. - - Returns: - List of WprRequest. - """ - requests = [] - wpr_http_netloc = None - with open(log_path) as log_file: - for line in log_file.readlines(): - # Extract WPR's HTTP proxy's listening network location. - match = _PARSE_WPR_DOMAIN_REGEX.match(line) - if match: - wpr_http_netloc = match.group('netloc') - assert wpr_http_netloc.startswith('127.0.0.1:') - continue - # Extract the WPR requested URLs. - match = _PARSE_WPR_URL_REGEX.match(line) - if match: - parsed_url = urlparse(match.group('url')) - # Ignore strange URL requests such as http://ousvtzkizg/ - # TODO(gabadie): Find and terminate the location where they are queried. - if '.' not in parsed_url.netloc and ':' not in parsed_url.netloc: - continue - assert wpr_http_netloc - request = WprRequest(is_served=(match.group('level') == 'DEBUG'), - method=match.group('method'), url=match.group('url'), - is_wpr_host=parsed_url.netloc == wpr_http_netloc) - requests.append(request) - return requests - - -if __name__ == '__main__': - import argparse - parser = argparse.ArgumentParser(description='Tests cache back-end.') - parser.add_argument('wpr_archive', type=str) - command_line_args = parser.parse_args() - - wpr_backend = WprArchiveBackend(command_line_args.wpr_archive) - url_entries = wpr_backend.ListUrlEntries() - print url_entries[0].url - wpr_backend.Persist()
diff --git a/tools/android/loading/wpr_backend_unittest.py b/tools/android/loading/wpr_backend_unittest.py deleted file mode 100644 index fbcb517..0000000 --- a/tools/android/loading/wpr_backend_unittest.py +++ /dev/null
@@ -1,273 +0,0 @@ -# Copyright 2016 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. - -import contextlib -import httplib -import os -import shutil -import tempfile -import unittest - -from device_setup import _WprHost -from options import OPTIONS -from trace_test.webserver_test import WebServer -from wpr_backend import WprUrlEntry, WprRequest, ExtractRequestsFromLog - - -LOADING_DIR = os.path.dirname(__file__) - - -class MockWprResponse(object): - def __init__(self, headers): - self.original_headers = headers - -class WprUrlEntryTest(unittest.TestCase): - - @classmethod - def _CreateWprUrlEntry(cls, headers): - wpr_response = MockWprResponse(headers) - return WprUrlEntry('GET http://a.com/', wpr_response) - - def testExtractUrl(self): - self.assertEquals('http://aa.bb/c', - WprUrlEntry._ExtractUrl('GET http://aa.bb/c')) - self.assertEquals('http://aa.b/c', - WprUrlEntry._ExtractUrl('POST http://aa.b/c')) - self.assertEquals('http://a.bb/c', - WprUrlEntry._ExtractUrl('WHATEVER http://a.bb/c')) - self.assertEquals('https://aa.bb/c', - WprUrlEntry._ExtractUrl('GET https://aa.bb/c')) - self.assertEquals('http://aa.bb', - WprUrlEntry._ExtractUrl('GET http://aa.bb')) - self.assertEquals('http://aa.bb', - WprUrlEntry._ExtractUrl('GET http://aa.bb FOO BAR')) - - def testGetResponseHeadersDict(self): - entry = self._CreateWprUrlEntry([('header0', 'value0'), - ('header1', 'value1'), - ('header0', 'value2'), - ('header2', 'value3'), - ('header0', 'value4'), - ('HEadEr3', 'VaLue4')]) - headers = entry.GetResponseHeadersDict() - self.assertEquals(4, len(headers)) - self.assertEquals('value0,value2,value4', headers['header0']) - self.assertEquals('value1', headers['header1']) - self.assertEquals('value3', headers['header2']) - self.assertEquals('VaLue4', headers['header3']) - - def testSetResponseHeader(self): - entry = self._CreateWprUrlEntry([('header0', 'value0'), - ('header1', 'value1')]) - entry.SetResponseHeader('new_header0', 'new_value0') - headers = entry.GetResponseHeadersDict() - self.assertEquals(3, len(headers)) - self.assertEquals('new_value0', headers['new_header0']) - self.assertEquals('new_header0', entry._wpr_response.original_headers[2][0]) - - entry = self._CreateWprUrlEntry([('header0', 'value0'), - ('header1', 'value1'), - ('header2', 'value1'),]) - entry.SetResponseHeader('header1', 'new_value1') - headers = entry.GetResponseHeadersDict() - self.assertEquals(3, len(headers)) - self.assertEquals('new_value1', headers['header1']) - self.assertEquals('header1', entry._wpr_response.original_headers[1][0]) - - entry = self._CreateWprUrlEntry([('header0', 'value0'), - ('hEADEr1', 'value1'), - ('header2', 'value1'),]) - entry.SetResponseHeader('header1', 'new_value1') - headers = entry.GetResponseHeadersDict() - self.assertEquals(3, len(headers)) - self.assertEquals('new_value1', headers['header1']) - self.assertEquals('hEADEr1', entry._wpr_response.original_headers[1][0]) - - entry = self._CreateWprUrlEntry([('header0', 'value0'), - ('header1', 'value1'), - ('header2', 'value2'), - ('header1', 'value3'), - ('header3', 'value4'), - ('heADer1', 'value5')]) - entry.SetResponseHeader('header1', 'new_value2') - headers = entry.GetResponseHeadersDict() - self.assertEquals(4, len(headers)) - self.assertEquals('new_value2', headers['header1']) - self.assertEquals('header1', entry._wpr_response.original_headers[1][0]) - self.assertEquals('header3', entry._wpr_response.original_headers[3][0]) - self.assertEquals('value4', entry._wpr_response.original_headers[3][1]) - - entry = self._CreateWprUrlEntry([('header0', 'value0'), - ('heADer1', 'value1'), - ('header2', 'value2'), - ('HEader1', 'value3'), - ('header3', 'value4'), - ('header1', 'value5')]) - entry.SetResponseHeader('header1', 'new_value2') - headers = entry.GetResponseHeadersDict() - self.assertEquals(4, len(headers)) - self.assertEquals('new_value2', headers['header1']) - self.assertEquals('heADer1', entry._wpr_response.original_headers[1][0]) - self.assertEquals('header3', entry._wpr_response.original_headers[3][0]) - self.assertEquals('value4', entry._wpr_response.original_headers[3][1]) - - def testDeleteResponseHeader(self): - entry = self._CreateWprUrlEntry([('header0', 'value0'), - ('header1', 'value1'), - ('header0', 'value2'), - ('header2', 'value3')]) - entry.DeleteResponseHeader('header1') - self.assertNotIn('header1', entry.GetResponseHeadersDict()) - self.assertEquals(2, len(entry.GetResponseHeadersDict())) - entry.DeleteResponseHeader('header0') - self.assertNotIn('header0', entry.GetResponseHeadersDict()) - self.assertEquals(1, len(entry.GetResponseHeadersDict())) - - entry = self._CreateWprUrlEntry([('header0', 'value0'), - ('hEAder1', 'value1'), - ('header0', 'value2'), - ('heaDEr2', 'value3')]) - entry.DeleteResponseHeader('header1') - self.assertNotIn('header1', entry.GetResponseHeadersDict()) - self.assertEquals(2, len(entry.GetResponseHeadersDict())) - - def testRemoveResponseHeaderDirectives(self): - entry = self._CreateWprUrlEntry([('hEAder0', 'keyWOrd0,KEYword1'), - ('heaDER1', 'value1'), - ('headeR2', 'value3')]) - entry.RemoveResponseHeaderDirectives('header0', {'keyword1', 'keyword0'}) - self.assertNotIn('header0', entry.GetResponseHeadersDict()) - - entry = self._CreateWprUrlEntry([('heADEr0', 'keYWOrd0'), - ('hEADERr1', 'value1'), - ('HEAder0', 'keywoRD1,keYwoRd2'), - ('hEADer2', 'value3')]) - entry.RemoveResponseHeaderDirectives('header0', {'keyword1'}) - self.assertEquals( - 'keYWOrd0,keYwoRd2', entry.GetResponseHeadersDict()['header0']) - self.assertEquals(3, len(entry._wpr_response.original_headers)) - self.assertEquals( - 'keYWOrd0,keYwoRd2', entry._wpr_response.original_headers[0][1]) - - -class WprHostTest(unittest.TestCase): - def setUp(self): - OPTIONS.ParseArgs([]) - self._server_address = None - self._wpr_http_port = None - self._tmp_directory = tempfile.mkdtemp(prefix='tmp_test_') - - def tearDown(self): - shutil.rmtree(self._tmp_directory) - - def _TmpPath(self, name): - return os.path.join(self._tmp_directory, name) - - def _LogPath(self): - return self._TmpPath('wpr.log') - - def _ArchivePath(self): - return self._TmpPath('wpr') - - @contextlib.contextmanager - def RunWebServer(self): - assert self._server_address is None - with WebServer.Context( - source_dir=os.path.join(LOADING_DIR, 'trace_test', 'tests'), - communication_dir=self._tmp_directory) as server: - self._server_address = server.Address() - yield - - @contextlib.contextmanager - def RunWpr(self, record): - assert self._server_address is not None - assert self._wpr_http_port is None - with _WprHost(self._ArchivePath(), record=record, - out_log_path=self._LogPath()) as (http_port, https_port): - del https_port # unused - self._wpr_http_port = http_port - yield http_port - - def DoHttpRequest(self, path, expected_status=200, destination='wpr'): - assert self._server_address is not None - if destination == 'wpr': - assert self._wpr_http_port is not None - connection = httplib.HTTPConnection('127.0.0.1', self._wpr_http_port) - elif destination == 'server': - connection = httplib.HTTPConnection(self._server_address) - else: - assert False - try: - connection.request( - "GET", '/' + path, headers={'Host': self._server_address}) - response = connection.getresponse() - finally: - connection.close() - self.assertEquals(expected_status, response.status) - - def _GenRawWprRequest(self, path): - assert self._wpr_http_port is not None - url = 'http://127.0.0.1:{}/web-page-replay-{}'.format( - self._wpr_http_port, path) - return WprRequest(is_served=True, method='GET', is_wpr_host=True, url=url) - - def GenRawRequest(self, path, is_served): - assert self._server_address is not None - return WprRequest(is_served=is_served, method='GET', is_wpr_host=False, - url='http://{}/{}'.format(self._server_address, path)) - - def AssertWprParsedRequests(self, ref_requests): - all_ref_requests = [] - all_ref_requests.append(self._GenRawWprRequest('generate-200')) - all_ref_requests.extend(ref_requests) - all_ref_requests.append(self._GenRawWprRequest('generate-200')) - all_ref_requests.append(self._GenRawWprRequest('command-exit')) - requests = ExtractRequestsFromLog(self._LogPath()) - self.assertEquals(all_ref_requests, requests) - self._wpr_http_port = None - - def testExtractRequestsFromLog(self): - with self.RunWebServer(): - with self.RunWpr(record=True): - self.DoHttpRequest('1.html') - self.DoHttpRequest('2.html') - ref_requests = [ - self.GenRawRequest('1.html', is_served=True), - self.GenRawRequest('2.html', is_served=True)] - self.AssertWprParsedRequests(ref_requests) - - with self.RunWpr(record=False): - self.DoHttpRequest('2.html') - self.DoHttpRequest('1.html') - ref_requests = [ - self.GenRawRequest('2.html', is_served=True), - self.GenRawRequest('1.html', is_served=True)] - self.AssertWprParsedRequests(ref_requests) - - def testExtractRequestsFromLogHaveCorrectIsServed(self): - with self.RunWebServer(): - with self.RunWpr(record=True): - self.DoHttpRequest('4.html', expected_status=404) - ref_requests = [self.GenRawRequest('4.html', is_served=True)] - self.AssertWprParsedRequests(ref_requests) - - with self.RunWpr(record=False): - self.DoHttpRequest('4.html', expected_status=404) - self.DoHttpRequest('5.html', expected_status=404) - ref_requests = [self.GenRawRequest('4.html', is_served=True), - self.GenRawRequest('5.html', is_served=False)] - self.AssertWprParsedRequests(ref_requests) - - def testExtractRequestsFromLogHaveCorrectIsWprHost(self): - PATH = 'web-page-replay-generate-200' - with self.RunWebServer(): - self.DoHttpRequest(PATH, expected_status=404, destination='server') - with self.RunWpr(record=True): - self.DoHttpRequest(PATH) - ref_requests = [self.GenRawRequest(PATH, is_served=True)] - self.AssertWprParsedRequests(ref_requests) - - -if __name__ == '__main__': - unittest.main()
diff --git a/tools/android/loading/wpr_helper.py b/tools/android/loading/wpr_helper.py deleted file mode 100755 index b509d117b..0000000 --- a/tools/android/loading/wpr_helper.py +++ /dev/null
@@ -1,126 +0,0 @@ -#!/usr/bin/python -# -# Copyright 2017 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. - -"""Helper script to launch Chrome on device and WebPageReplay on host.""" - -import logging -import optparse -import os -import sys -import time - -_SRC_PATH = os.path.abspath(os.path.join( - os.path.dirname(__file__), os.pardir, os.pardir, os.pardir)) - -sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'catapult', 'devil')) -from devil.android import device_utils -from devil.android import flag_changer -from devil.android.constants import chrome -from devil.android.perf import cache_control -from devil.android.sdk import intent - -sys.path.append(os.path.join(_SRC_PATH, 'build', 'android')) -import devil_chromium - -import chrome_setup -import device_setup - - -def RunChrome(device, cold, chrome_args, package_info): - """Runs Chrome on the device. - - Args: - device: (DeviceUtils) device to run the tests on. - cold: (bool) Whether caches should be dropped. - chrome_args: ([str]) List of arguments to pass to Chrome. - package_info: (PackageInfo) Chrome package info. - """ - if not device.HasRoot(): - device.EnableRoot() - - cmdline_file = package_info.cmdline_file - package = package_info.package - with flag_changer.CustomCommandLineFlags(device, cmdline_file, chrome_args): - device.ForceStop(package) - - if cold: - chrome_setup.ResetChromeLocalState(device, package) - cache_control.CacheControl(device).DropRamCaches() - - start_intent = intent.Intent(package=package, data='about:blank', - activity=package_info.activity) - try: - device.StartActivity(start_intent, blocking=True) - print ( - '\n\n' - ' +---------------------------------------------+\n' - ' | Chrome launched, press Ctrl-C to interrupt. |\n' - ' +---------------------------------------------+') - while True: - time.sleep(1) - except KeyboardInterrupt: - pass - finally: - device.ForceStop(package) - - -def _CreateOptionParser(): - description = 'Launches Chrome on a device, connected to a WebPageReplay ' \ - 'instance running on the host. The WPR archive must be ' \ - 'passed as parameter.' - parser = optparse.OptionParser(description=description, - usage='Usage: %prog [options] wpr_archive') - - # Device-related options. - d = optparse.OptionGroup(parser, 'Device options') - d.add_option('--device', help='Device ID') - d.add_option('--cold', help='Purge all caches before running Chrome.', - default=False, action='store_true') - d.add_option('--chrome_package_name', - help='Chrome package name (e.g. "chrome" or "chromium") ' - '[default: %default].', default='chrome') - parser.add_option_group(d) - - # WebPageReplay-related options. - w = optparse.OptionGroup(parser, 'WebPageReplay options') - w.add_option('--record', - help='Enable this to record a new WPR archive.', - action='store_true', default=False) - w.add_option('--wpr_log', help='WPR log path.') - w.add_option('--network_condition', help='Network condition for emulation.') - parser.add_option_group(w) - - return parser - - -def main(): - parser = _CreateOptionParser() - options, args = parser.parse_args() - if len(args) != 1: - parser.error("Incorrect number of arguments.") - devil_chromium.Initialize() - devices = device_utils.DeviceUtils.HealthyDevices() - device = devices[0] - if len(devices) != 1 and options.device is None: - logging.error('Several devices attached, must specify one with --device.') - sys.exit(0) - if options.device is not None: - matching_devices = [d for d in devices if str(d) == options.device] - if not matching_devices: - logging.error('Device not found.') - sys.exit(0) - device = matching_devices[0] - - with device_setup.RemoteWprHost(device, args[0], options.record, - options.network_condition, - out_log_path=options.wpr_log) as wpr_attr: - RunChrome(device, options.cold, - chrome_setup.CHROME_ARGS + wpr_attr.chrome_args, - chrome.PACKAGE_INFO[options.chrome_package_name]) - - -if __name__ == '__main__': - main()
diff --git a/tools/android/loading/xvfb_helper.py b/tools/android/loading/xvfb_helper.py deleted file mode 100644 index 4939e76..0000000 --- a/tools/android/loading/xvfb_helper.py +++ /dev/null
@@ -1,19 +0,0 @@ -# Copyright 2016 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. - -import os -import subprocess - - -def LaunchXvfb(): - """Launches Xvfb for running Chrome in headless mode, and returns the - subprocess.""" - xvfb_cmd = ['Xvfb', ':99', '-screen', '0', '1600x1200x24'] - return subprocess.Popen(xvfb_cmd, stdout=open(os.devnull, 'wb'), - stderr=subprocess.STDOUT) - - -def GetChromeEnvironment(): - """Returns the environment for Chrome to run in headless mode with Xvfb.""" - return {'DISPLAY': 'localhost:99'}
diff --git a/tools/binary_size/libsupersize/generate_milestone_report.py b/tools/binary_size/libsupersize/generate_milestone_report.py index 79d8516..955ed06b5 100755 --- a/tools/binary_size/libsupersize/generate_milestone_report.py +++ b/tools/binary_size/libsupersize/generate_milestone_report.py
@@ -60,8 +60,9 @@ '67.0.3396.87', '68.0.3440.85', '69.0.3497.91', - '70.0.3538.17', # Beta - '71.0.3574.0', # Dev + '70.0.3538.64', + '71.0.3578.83', # Beta + '72.0.3626.7', # Beta ]
diff --git a/tools/clang/blink_gc_plugin/BadPatternFinder.cpp b/tools/clang/blink_gc_plugin/BadPatternFinder.cpp index ef1da662..5dfcfb0 100644 --- a/tools/clang/blink_gc_plugin/BadPatternFinder.cpp +++ b/tools/clang/blink_gc_plugin/BadPatternFinder.cpp
@@ -100,8 +100,10 @@ isDerivedFrom(cxxRecordDecl(decl().bind("mixin_base_class"), hasName("::blink::GarbageCollectedMixin"))), // ...and doesn't use USING_GARBAGE_COLLECTED_MIXIN - unless(isSameOrDerivedFrom( - has(fieldDecl(hasName("mixin_constructor_marker_"))))), + unless(anyOf(isSameOrDerivedFrom(has(typedefNameDecl( + hasName("HasUsingGarbageCollectedMixinMacro")))), + isSameOrDerivedFrom(has( + fieldDecl(hasName("mixin_constructor_marker_")))))), // ...and might end up actually being constructed unless(hasMethod(isPure())), unless(matchesName("::SameSizeAs"))); match_finder.addDynamicMatcher(class_missing_mixin_marker, this);
diff --git a/tools/clang/blink_gc_plugin/tests/heap/stubs.h b/tools/clang/blink_gc_plugin/tests/heap/stubs.h index eafea1c..81a9ee5 100644 --- a/tools/clang/blink_gc_plugin/tests/heap/stubs.h +++ b/tools/clang/blink_gc_plugin/tests/heap/stubs.h
@@ -198,6 +198,12 @@ virtual bool IsHeapObjectAlive(Visitor*) const override { return 0; } \ void* mixin_constructor_marker_; +#define USING_GARBAGE_COLLECTED_MIXIN_NEW(type) \ + public: \ + virtual void AdjustAndMark(Visitor*) const override {} \ + virtual bool IsHeapObjectAlive(Visitor*) const override { return 0; } \ + typedef int HasUsingGarbageCollectedMixinMacro; + #define EAGERLY_FINALIZED() typedef int IsEagerlyFinalizedMarker template<typename T> class GarbageCollected { };
diff --git a/tools/clang/blink_gc_plugin/tests/missing_mixin_marker.cpp b/tools/clang/blink_gc_plugin/tests/missing_mixin_marker.cpp index a10e767..2040ed99 100644 --- a/tools/clang/blink_gc_plugin/tests/missing_mixin_marker.cpp +++ b/tools/clang/blink_gc_plugin/tests/missing_mixin_marker.cpp
@@ -35,6 +35,13 @@ }; class GoodDerived; +// Same macro providing only a typedef is also ok. +class GoodDerivedMacroUsingTypedef : public GarbageCollected<GoodDerived>, + public Mixin { + USING_GARBAGE_COLLECTED_MIXIN_NEW(GoodDerivedMacroUsingTypedef); +}; +class GoodDerivedMacroUsingTypedef; + // Abstract classes (i.e. ones with pure virtual methods) can't be constructed // and so it's assumed their derived classes will have // USING_GARBAGE_COLLECTED_MIXIN.
diff --git a/tools/clang/blink_gc_plugin/tests/missing_mixin_marker.txt b/tools/clang/blink_gc_plugin/tests/missing_mixin_marker.txt index 692f7d6..03c239b 100644 --- a/tools/clang/blink_gc_plugin/tests/missing_mixin_marker.txt +++ b/tools/clang/blink_gc_plugin/tests/missing_mixin_marker.txt
@@ -10,10 +10,10 @@ missing_mixin_marker.cpp:20:27: note: [blink-gc] Mixin base class derived here: class Supplement : public GarbageCollectedMixin { ~~~~~~~^~~~~~~~~~~~~~~~~~~~~ -missing_mixin_marker.cpp:46:35: warning: [blink-gc] Garbage-collected class 'PureVirtualDerived' derives mixin class 'Mixin'. You must add USING_GARBAGE_COLLECTED_MIXIN(PureVirtualDerived). +missing_mixin_marker.cpp:53:35: warning: [blink-gc] Garbage-collected class 'PureVirtualDerived' derives mixin class 'Mixin'. You must add USING_GARBAGE_COLLECTED_MIXIN(PureVirtualDerived). class PureVirtualDerived : public PureVirtual { ~~~~~~~^~~~~~~~~~~ -missing_mixin_marker.cpp:41:66: note: [blink-gc] Mixin base class derived here: +missing_mixin_marker.cpp:48:66: note: [blink-gc] Mixin base class derived here: class PureVirtual : public GarbageCollected<PureVirtual>, public Mixin { ~~~~~~~^~~~~ missing_mixin_marker.cpp:9:22: note: [blink-gc] Mixin base class derived here:
diff --git a/tools/cygprofile/orderfile_generator_backend.py b/tools/cygprofile/orderfile_generator_backend.py index 05cb027..8e3799df0f 100755 --- a/tools/cygprofile/orderfile_generator_backend.py +++ b/tools/cygprofile/orderfile_generator_backend.py
@@ -808,8 +808,8 @@ '--use-goma', action='store_true', help='Enable GOMA.', default=False) parser.add_argument('--adb-path', help='Path to the adb binary.') - parser.add_argument('--system-health-orderfile', action='store_true', - dest='system_health_orderfile', default=False, + parser.add_argument('--nosystem-health-orderfile', action='store_false', + dest='system_health_orderfile', default=True, help=('Create an orderfile based on an about:blank ' 'startup benchmark instead of system health ' 'benchmarks.'))
diff --git a/tools/determinism/deterministic_build_whitelist.pyl b/tools/determinism/deterministic_build_whitelist.pyl index 78d8002..ddee0bb 100644 --- a/tools/determinism/deterministic_build_whitelist.pyl +++ b/tools/determinism/deterministic_build_whitelist.pyl
@@ -63,6 +63,9 @@ 'nacl_helper', 'nacl_helper_bootstrap', 'nacl_loader_unittests', + + # https://crbug.com/913204 + 'captured_sites_interactive_tests', ], # https://crbug.com/330262
diff --git a/tools/generate_stubs/rules.gni b/tools/generate_stubs/rules.gni index 548efd6..c4ea1f9 100644 --- a/tools/generate_stubs/rules.gni +++ b/tools/generate_stubs/rules.gni
@@ -11,6 +11,7 @@ # extra_header: prepend the contents of this file to the generated .cc file # logging_function: override the used logging function (default: VLOG(1)) # logging_include: override the additional include (default: base/logging.h) +# path_from_source: relative path of generated files from the project root # # Example # generate_stubs("libfoo_stubs") { @@ -52,6 +53,17 @@ "--path_from_source", rebase_path(_gen_dir, root_gen_dir), ] + if (defined(invoker.path_from_source)) { + args += [ + "--path_from_source", + invoker.path_from_source, + ] + } else { + args += [ + "--path_from_source", + rebase_path(_gen_dir, root_gen_dir), + ] + } if (defined(invoker.logging_function)) { args += [ "--logging-function", @@ -84,5 +96,8 @@ ] libs = [ "dl" ] include_dirs = [ target_gen_dir ] + if (defined(invoker.configs)) { + configs += invoker.configs + } } }
diff --git a/tools/idl_parser/idl_parser.py b/tools/idl_parser/idl_parser.py index 97c2e1d0..d614245 100755 --- a/tools/idl_parser/idl_parser.py +++ b/tools/idl_parser/idl_parser.py
@@ -1034,19 +1034,9 @@ else: p[0] = '' - # Add unqualified Promise def p_PromiseType(self, p): - """PromiseType : PROMISE '<' ReturnType '>' - | PROMISE""" - if len(p) == 2: - # Promise without resolution type is not specified in the Web IDL spec. - # As it is used in some specs and in the blink implementation, - # we allow that here. - resolution_type = self.BuildProduction('Type', p, 1, - self.BuildProduction('Any', p, 1)) - p[0] = self.BuildNamed('Promise', p, 1, resolution_type) - else: - p[0] = self.BuildNamed('Promise', p, 1, p[3]) + """PromiseType : PROMISE '<' ReturnType '>'""" + p[0] = self.BuildNamed('Promise', p, 1, p[3]) def p_Null(self, p): """Null : '?'
diff --git a/tools/idl_parser/test_parser/interface_web.idl b/tools/idl_parser/test_parser/interface_web.idl index a2808367..555e5d1c 100644 --- a/tools/idl_parser/test_parser/interface_web.idl +++ b/tools/idl_parser/test_parser/interface_web.idl
@@ -342,12 +342,7 @@ * Promise(Promise) * Type() * Any() - * Operation(method4) - * Arguments() - * Type() - * Promise(Promise) - * Type() - * Any() + * Error(Unexpected identifier "method4" after keyword "Promise".) */ interface MyIfacePromise { Promise<void> method1();
diff --git a/tools/luci-go/.gitignore b/tools/luci-go/.gitignore index 2934681..38af367 100644 --- a/tools/luci-go/.gitignore +++ b/tools/luci-go/.gitignore
@@ -1,10 +1,7 @@ +/.versions /isolate /isolate.exe /isolated /isolated.exe -/linux64/isolate -/mac64/isolate /swarming /swarming.exe -/win64/isolate.exe -.versions
diff --git a/tools/luci-go/linux64/isolate.sha1 b/tools/luci-go/linux64/isolate.sha1 deleted file mode 100644 index 1610657..0000000 --- a/tools/luci-go/linux64/isolate.sha1 +++ /dev/null
@@ -1 +0,0 @@ -9734e966a14f9e26f86e38a020fcd7584248d285
diff --git a/tools/luci-go/mac64/isolate.sha1 b/tools/luci-go/mac64/isolate.sha1 deleted file mode 100644 index a61e43ab..0000000 --- a/tools/luci-go/mac64/isolate.sha1 +++ /dev/null
@@ -1 +0,0 @@ -18561de57e944d096521838b4e6cb49e0cc1df23
diff --git a/tools/luci-go/win64/isolate.exe.sha1 b/tools/luci-go/win64/isolate.exe.sha1 deleted file mode 100644 index 5ac52a0..0000000 --- a/tools/luci-go/win64/isolate.exe.sha1 +++ /dev/null
@@ -1 +0,0 @@ -af227603890ea1d8c082b5caf15e46a6bf060a2e
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 539083b..1bf1599 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -204,6 +204,7 @@ 'Linux x64 Goma Latest Client (clobber)': 'release_bot', 'Linux x64 Goma Latest Client LocalOutputCache': 'release_bot', + 'mac-hermetic-upgrade-rel': 'release_bot', 'mac-views-rel': 'mac_views_browser_release_bot', 'Chromium Mac 10.13': 'release_bot', @@ -294,6 +295,8 @@ 'Chromium Linux Goma RBE Staging (dbg) (clobber)': 'debug_bot', 'Chromium Linux Goma RBE Staging (dbg)': 'debug_bot', 'Chromium Mac Goma RBE Staging (clobber)': 'release_bot', + 'Chromium Mac Goma RBE Staging': 'release_bot', + 'Chromium Mac Goma RBE Staging (dbg)': 'debug_bot', 'Chromium Android ARM 32-bit Goma RBE Staging': 'android_release_bot_minimal_symbols', }, @@ -677,8 +680,8 @@ 'linux_chromium_rel_ng': 'gpu_tests_release_trybot_no_symbols_use_dummy_lastchange', 'linux_chromium_tsan_rel_ng': 'tsan_disable_nacl_release_trybot', 'linux_chromium_ubsan_rel_ng': 'ubsan_vptr_release_trybot', + 'linux_layout_tests_composite_after_paint': 'release_trybot', 'linux_layout_tests_layout_ng': 'release_trybot', - 'linux_layout_tests_slimming_paint_v2': 'release_trybot', 'linux_mojo': 'release_trybot', 'linux_mojo_chromeos': 'chromeos_with_codecs_release_trybot', 'linux_optional_gpu_tests_rel': 'gpu_fyi_tests_release_trybot', @@ -768,7 +771,7 @@ # bots all using the 'release_bot' config). 'configs': { 'afl_asan_release_bot': [ - 'afl', 'asan', 'release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', + 'afl', 'asan', 'shared_release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', ], 'android_binary_size': [ @@ -1162,14 +1165,6 @@ 'clang_tot', 'msan', 'release', ], - 'clang_tot_shared_debug': [ - 'clang_tot', 'shared', 'debug', - ], - - 'clang_tot_shared_debug_x86': [ - 'clang_tot', 'shared', 'debug', 'x86', - ], - 'clang_tot_minimal_symbols_shared_release': [ 'clang_tot', 'minimal_symbols', 'shared', 'release', ], @@ -1214,6 +1209,10 @@ 'clang_tot', 'shared', 'debug', ], + 'clang_tot_shared_debug_x86': [ + 'clang_tot', 'shared', 'debug', 'x86', + ], + 'closure_compilation': [ # The closure bots run their own recipe and shouldn't go through MB. 'error', @@ -1281,7 +1280,7 @@ ], 'libfuzzer_asan_debug_bot': [ - 'libfuzzer', 'asan', 'debug_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', + 'libfuzzer', 'asan', 'debug_bot', 'shared', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', ], 'debug_trybot': [ @@ -1469,23 +1468,33 @@ ], 'libfuzzer_asan_debug_bot': [ - 'libfuzzer', 'asan', 'debug_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', + 'libfuzzer', 'asan', 'debug_bot', 'shared', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', ], + 'libfuzzer_chromeos_asan_release_bot': [ - 'libfuzzer', 'asan', 'chromeos_with_codecs', 'shared_release_bot', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', + 'libfuzzer', 'asan', 'shared_release_bot', 'chromeos_with_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', ], + 'libfuzzer_asan_release_bot': [ - 'libfuzzer', 'asan', 'release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', + 'libfuzzer', 'asan', 'shared_release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', ], 'libfuzzer_asan_release_trybot': [ - 'libfuzzer', 'asan', 'release_trybot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', + 'libfuzzer', 'asan', 'shared_release_trybot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', ], 'libfuzzer_asan_clang_tot_release': [ 'libfuzzer', 'asan', 'clang_tot', 'release', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', ], + 'libfuzzer_msan_release_bot': [ + 'libfuzzer', 'msan', 'shared_release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', + ], + + 'libfuzzer_ubsan_release_bot': [ + 'libfuzzer', 'ubsan_security', 'release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', + ], + 'libfuzzer_mac_asan_release_bot': [ 'libfuzzer', 'asan', 'release_bot', 'chrome_with_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', ], @@ -1496,21 +1505,15 @@ 'libfuzzer_windows_asan_release_bot': [ 'libfuzzer', 'asan', 'release_bot', 'chrome_with_codecs', 'pdf_xfa', 'disable_nacl', 'minimal_symbols', ], + 'libfuzzer_windows_asan_clang_tot_release_bot': [ 'libfuzzer', 'asan', 'clang_tot', 'release', 'chrome_with_codecs', 'pdf_xfa', 'disable_nacl', 'minimal_symbols', ], + 'libfuzzer_windows_asan_release_trybot': [ 'libfuzzer', 'asan', 'release_trybot', 'chrome_with_codecs', 'pdf_xfa', 'disable_nacl', 'minimal_symbols', ], - 'libfuzzer_msan_release_bot': [ - 'libfuzzer', 'msan', 'release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', - ], - - 'libfuzzer_ubsan_release_bot': [ - 'libfuzzer', 'ubsan_security', 'release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing', - ], - 'linux_chromium_analysis': [ 'analysis' ], @@ -2152,7 +2155,11 @@ }, 'shared_release_bot': { - 'mixins': ['shared', 'release', 'goma'] + 'mixins': ['shared', 'release', 'goma'], + }, + + 'shared_release_trybot': { + 'mixins': ['shared_release_bot', 'minimal_symbols', 'dcheck_always_on'], }, 'static': {
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 6d9a7d9..cb28fdd 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -4420,6 +4420,13 @@ </description> </action> +<action name="ContextualSuggestions"> + <owner>huayinz@chromium.org</owner> + <owner>twellington@chromium.com</owner> + <owner>wylieb@chromium.com</owner> + <description>Android: User interacts with the feature directly.</description> +</action> + <action name="ContextualSuggestions.ContextMenu"> <owner>huayinz@chromium.org</owner> <owner>twellington@chromium.com</owner> @@ -21057,4 +21064,11 @@ <affected-action name="Android.DownloadManager.Menu.Action"/> </action-suffix> +<action-suffix separator="." ordering="suffix"> + <suffix name="SuggestionClicked" + label="The suggestion was clicked directly."/> + <suffix name="ToolbarButtonClicked" label="The toolbar button was shown."/> + <affected-action name="ContextualSuggestions"/> +</action-suffix> + </actions>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index e01de14b..24cbef7 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -3991,6 +3991,9 @@ 31-bit hash of the service UUID. Values here are populated from https://www.bluetooth.com/specifications/assigned-numbers/service-discovery </summary> + <obsolete> + No longer used by active histograms in M73. + </obsolete> <int value="27577045" label="SIM_Access; 0000112d-0000-1000-8000-00805f9b34fb"/> <int value="46048502" @@ -5007,6 +5010,11 @@ <int value="1" label="Opened"/> </enum> +<enum name="BooleanOptionConditionsChanged"> + <int value="0" label="Conditions unchanged"/> + <int value="1" label="Conditions changed"/> +</enum> + <enum name="BooleanOriginHeaderSameAsRequestOrigin"> <int value="0" label="Headers differ"/> <int value="1" label="Headers match"/> @@ -15029,6 +15037,7 @@ <int value="504" label="PluginVmImage"/> <int value="505" label="CloudManagementEnrollmentMandatory"/> <int value="506" label="PrintingSendUsernameAndFilenameEnabled"/> + <int value="507" label="ParentAccessCodeConfig"/> </enum> <enum name="EnterprisePolicyInvalidations"> @@ -16057,6 +16066,8 @@ <int value="426" label="FILE_MANAGER_PRIVATE_ON_CROSTINI_SHARED_PATHS_CHANGED"/> <int value="427" label="AUTOMATION_INTERNAL_ON_GET_TEXT_LOCATION_RESULT"/> + <int value="428" label="INPUT_METHOD_PRIVATE_ON_SETTINGS_CHANGED"/> + <int value="429" label="INPUT_METHOD_PRIVATE_ON_SCREEN_PROJECTION_CHANGED"/> </enum> <enum name="ExtensionFileWriteResult"> @@ -27026,6 +27037,9 @@ <int value="6" label="Enabling hotspot timed out"/> <int value="7" label="No response"/> <int value="8" label="Invalid hotspot credentials"/> + <int value="9" + label="Successful request but no ConnectTetheringResponse message"/> + <int value="10" label="Unrecognized response error"/> </enum> <enum name="InstantTethering_ConnectionToHostResult_Failure_ClientConnection"> @@ -29271,6 +29285,7 @@ <int value="-2133892372" label="ResamplingInputEvents:disabled"/> <int value="-2133277113" label="CCTModuleCustomHeader:disabled"/> <int value="-2132591642" label="enable-input-view"/> + <int value="-2128705444" label="AssistantAppSupport:enabled"/> <int value="-2124839789" label="OmniboxUIExperimentHideSteadyStateUrlSchemeAndSubdomains:enabled"/> <int value="-2124685253" label="USBGuard:enabled"/> @@ -29416,6 +29431,8 @@ <int value="-1930720286" label="nacl-debug-mask"/> <int value="-1928198763" label="enable-async-dns"/> <int value="-1925117279" label="disable-quic-https"/> + <int value="-1919199528" + label="AlwaysShowServerCardsInSyncTransport:disabled"/> <int value="-1916060206" label="enable-display-zoom-setting"/> <int value="-1915854488" label="enable-offline-pages"/> <int value="-1913801713" @@ -29900,6 +29917,7 @@ <int value="-1122853453" label="LazyImageLoading:enabled"/> <int value="-1121931029" label="DownloadsForeground:enabled"/> <int value="-1119700637" label="ui-disable-partial-swap"/> + <int value="-1118921985" label="ForceEnableSystemAec:enabled"/> <int value="-1114080030" label="ResourceLoadingHints:enabled"/> <int value="-1112782121" label="AndroidSigninPromos:disabled"/> <int value="-1107762575" label="enable-data-reduction-proxy-config-client"/> @@ -30115,6 +30133,7 @@ <int value="-718884399" label="NewTabPageUIMd:enabled"/> <int value="-718626298" label="SysInternals:enabled"/> <int value="-716953514" label="disable-password-separated-signin-flow"/> + <int value="-716272467" label="AssistantAppSupport:disabled"/> <int value="-715733307" label="force-effective-connection-type"/> <int value="-714712077" label="ClickToOpenPDFPlaceholder:disabled"/> <int value="-714710496" label="VideoFullscreenOrientationLock:disabled"/> @@ -30252,6 +30271,7 @@ <int value="-460081932" label="CustomFeedbackUi:disabled"/> <int value="-457292000" label="HappinessTrackingSurveysForDesktop:enabled"/> <int value="-457174225" label="Av1Decoder:enabled"/> + <int value="-456321929" label="ForceEnableSystemAec:disabled"/> <int value="-455203267" label="use_new_features_summary"/> <int value="-449465495" label="disable-browser-task-scheduler"/> <int value="-436470115" label="TouchpadAndWheelScrollLatching:enabled"/> @@ -30908,6 +30928,7 @@ <int value="772348426" label="AffiliationBasedMatching:enabled"/> <int value="772360813" label="enable-fullscreen-handwriting-virtual-keyboard:enabled"/> + <int value="773070364" label="AlwaysShowServerCardsInSyncTransport:enabled"/> <int value="773563826" label="CrostiniUsbSupport:disabled"/> <int value="773743944" label="show-android-files-in-files-app"/> <int value="773919225" label="disable-office-editing-component-extension"/> @@ -32288,6 +32309,7 @@ <int value="3" label="Password Dropdown"/> <int value="4" label="Password Generation Confirmation"/> <int value="5" label="Profile Chooser"/> + <int value="6" label="Passwords Accessory Sheet"/> </enum> <enum name="ManifestFetchResultType"> @@ -36872,7 +36894,7 @@ <enum name="NewTabPageLogoDownloadOutcome"> <summary> These values are defined in LogoDownloadOutcome enum in - components/search_provider_logos/logo_tracker.h. + components/search_provider_logos/logo_service_impl.h. </summary> <int value="0" label="New logo success"/> <int value="1" label="No logo today"/> @@ -37389,6 +37411,8 @@ <int value="6" label="Clicked disabled next button then navigated away"/> <int value="7" label="Clicked disabled next button then chose skip"/> <int value="8" label="Clicked disabled next button then chose next"/> + <int value="9" label="Did nothing and clicked next"/> + <int value="10" label="Navigated away through browser history"/> </enum> <enum name="NuxEmailProvidersSelections"> @@ -37404,9 +37428,19 @@ <summary> The button that a user pressed when interacting with the Google Apps NUX. </summary> - <int value="0" label="Prompt Seen"/> - <int value="1" label="No Thanks"/> - <int value="2" label="Get Started"/> + <int value="0" label="Page Shown"/> + <int value="1" label="No Thanks (deprecated)"/> + <int value="2" label="Get Started (deprecated)"/> + <int value="3" label="Did nothing and navigated away"/> + <int value="4" label="Did nothing and clicked skip"/> + <int value="5" label="Chose an option then navigated away"/> + <int value="6" label="Chose an option then chose skip"/> + <int value="7" label="Chose an option then chose next"/> + <int value="8" label="Clicked disabled next button then navigated away"/> + <int value="9" label="Clicked disabled next button then chose skip"/> + <int value="10" label="Clicked disabled next button then chose next"/> + <int value="11" label="Did nothing and clicked next"/> + <int value="12" label="Navigated away through browser history"/> </enum> <enum name="NuxGoogleAppsSelections"> @@ -41908,6 +41942,7 @@ opt-out). </int> <int value="14" label="Network is not slow per session threshold."/> + <int value="15" label="Device was reported as offline."/> </enum> <enum name="PreviewsInfoBarAction"> @@ -43927,7 +43962,7 @@ </summary> <int value="39256405" label="device.mojom.Geolocation"/> <int value="81966276" label="blink.mojom.KeyboardLockService"/> - <int value="112672197" label="content.mojom.SharedWorkerConnector"/> + <int value="112672197" label="blink.mojom.SharedWorkerConnector"/> <int value="141486647" label="webauth.mojom.Authenticator"/> <int value="155545232" label="blink.mojom.GeolocationService"/> <int value="188516542" label="content.mojom.MediaStreamDispatcherHost"/> @@ -44212,6 +44247,28 @@ <int value="5" label="Docked window state"/> </enum> +<enum name="RequestInitiatorOriginLockCompatibility"> + <int value="0" label="BrowserProcess"> + Request came from a browser process and so the |request_initiator_site_lock| + doesn't apply. + </int> + <int value="1" label="NoLock"> + |request_initiator_site_lock| is missing - see https://crbug.com/891872 and + RenderProcessHostImpl::CreateURLLoaderFactoryWithOptionalOrigin. + </int> + <int value="2" label="NoInitiator">|request_initiator| is missing.</int> + <int value="3" label="CompatibleLock"> + |request.request_initiator| is compatible with + |factory_params_.request_initiator_site_lock| - either + |request.request_initiator| is opaque or it is equal to + |request_initiator_site_lock|. + </int> + <int value="4" label="IncorrectLock"> + |request.request_initiator| is non-opaque/unique and differs from + |factory_params_.request_initiator_site_lock|. + </int> +</enum> + <enum name="RequestMediaKeySystemAccessStatus"> <int value="0" label="Requested"/> <int value="1" label="Supported"/> @@ -51390,7 +51447,7 @@ <int value="35370363" label="suggestions_service"/> <int value="35380758" label="download_manager_resume"/> <int value="35565745" label="gaia_auth_list_accounts"/> - <int value="36859107" label="logo_tracker"/> + <int value="36859107" label="logo_service"/> <int value="37249086" label="android_device_manager_socket"/> <int value="37531401" label="proxy_script_fetcher"/> <int value="38670228" label="download_internals_webui_source"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index a604041..fae1d72c 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -9027,6 +9027,16 @@ </summary> </histogram> +<histogram name="BackgroundSync.OptionConditionsChanged" + enum="BooleanOptionConditionsChanged" expires_after="M74"> + <owner>rayankans@chromium.org</owner> + <summary> + Whether the Background Sync dispatch conditions changed between scheduling + the operation and dispatching the event. This is collected right before the + event is dispatched. + </summary> +</histogram> + <histogram name="BackgroundSync.Registration.OneShot" enum="BackgroundSyncStatus"> <owner>iclelland@chromium.org</owner> @@ -9899,8 +9909,8 @@ <owner>paint-dev@chromium.org</owner> <summary> Time spent updating and pushing layers at the end of the paint step in the - Blink document lifecycle. This is the new compositing approach in slimming - paint V2 and is largely implemented by PaintArtifactCompositor. + Blink document lifecycle. This is the new compositing approach in + CompositeAfterPaint and is largely implemented by PaintArtifactCompositor. BlinkGenPropertyTrees is an incremental launch of part of the new compositing approach and will use both this and Blink.Compositing.UpdateTime. @@ -31013,6 +31023,9 @@ <histogram name="Extensions.BluetoothSocket.Connect.Service" enum="BluetoothSocketServiceHash" expires_after="M72"> + <obsolete> + Removed in M73 after collecting the data necessary. + </obsolete> <owner>ortuno@chromium.org</owner> <owner>reillyg@chromium.org</owner> <summary> @@ -31025,6 +31038,9 @@ <histogram name="Extensions.BluetoothSocket.ListenL2CAP.Service" enum="BluetoothSocketServiceHash" expires_after="M72"> + <obsolete> + Removed in M73 after collecting the data necessary. + </obsolete> <owner>ortuno@chromium.org</owner> <owner>reillyg@chromium.org</owner> <summary> @@ -31037,6 +31053,9 @@ <histogram name="Extensions.BluetoothSocket.ListenRFCOMM.Service" enum="BluetoothSocketServiceHash" expires_after="M72"> + <obsolete> + Removed in M73 after collecting the data necessary. + </obsolete> <owner>ortuno@chromium.org</owner> <owner>reillyg@chromium.org</owner> <summary> @@ -66713,6 +66732,23 @@ </histogram> <histogram + name="NetworkService.URLLoader.RequestInitiatorOriginLockCompatibility" + enum="RequestInitiatorOriginLockCompatibility" expires_after="2019-06-30"> + <owner>creis@chromium.org</owner> + <owner>jam@chromium.org</owner> + <owner>lukasza@chromium.org</owner> + <summary> + Whether the request origin (i.e. + network::ResourceRequest::request_initiator) matches the origin that the + browser process expected when creating the URLLoaderFactory (i.e. whether it + matches URLLoaderFactoryParams::request_initiator_site_lock). + + Recorded when a request is started (i.e. at the time of constructing + network::URLLoader). + </summary> +</histogram> + +<histogram name="NetworkService.URLLoaderFactory.OriginHeaderSameAsRequestOrigin" enum="BooleanOriginHeaderSameAsRequestOrigin" expires_after="2019-06-30"> <owner>jam@chromium.org</owner> @@ -68204,6 +68240,16 @@ <summary>Histogram for NTP notification promo activity.</summary> </histogram> +<histogram name="NewTabPage.Promos.RequestLatency" units="ms" + expires_after="M76"> + <owner>kmilka@chromium.org</owner> + <owner>ramyan@chromium.org</owner> + <summary> + The time it took until a request from the New Tab page for the middle slot + promo script was served. Recorded only on the local NTP. + </summary> +</histogram> + <histogram name="NewTabPage.RecentTabsPage.TimeVisibleAndroid" units="ms"> <owner>pkotwicz@chromium.org</owner> <summary> @@ -69423,6 +69469,18 @@ </summary> </histogram> +<histogram name="Notifications.Windows.CreateToastManagerErrorCode" + enum="Hresult"> + <owner>finnur@chromium.org</owner> + <owner>peter@chromium.org</owner> + <summary> + The HRESULT returned by the Windows Action Center, when trying to create a + toast manager fails. This provides a more detailed error in the cases the + histogram Notifications.Windows.DisplayStatus reported + CREATE_TOAST_NOTIFIER_WITH_ID_FAILED. + </summary> +</histogram> + <histogram name="Notifications.Windows.DisplayFailure" enum="Hresult"> <owner>finnur@chromium.org</owner> <owner>peter@chromium.org</owner> @@ -69438,7 +69496,10 @@ <owner>peter@chromium.org</owner> <summary> The status of Display requests in NotificationPlatformBridgeWin (Windows - only). Logged whenever a notification is displayed. + only). Logged whenever a notification is displayed. For a more detailed + error about CREATE_TOAST_NOTIFIER_WITH_ID_FAILED and SHOWING_TOAST_FAILED, + see Notification.Windows histograms CreateToastManagerErrorCode and + ShowFailedErrorCode (respectively). </summary> </histogram> @@ -69596,6 +69657,16 @@ </summary> </histogram> +<histogram name="Notifications.Windows.ShowFailedErrorCode" enum="Hresult"> + <owner>finnur@chromium.org</owner> + <owner>peter@chromium.org</owner> + <summary> + The HRESULT returned by the Windows Action Center, when trying to create a + toast manager fails. This provides a more detailed error in the cases the + histogram Notifications.Windows.DisplayStatus reported SHOWING_TOAST_FAILED. + </summary> +</histogram> + <histogram name="Notifications.Windows.StartMenuShortcutStatus" enum="WindowsNotificationStartMenuShortcutStatus"> <owner>chengx@chromium.org</owner> @@ -70919,7 +70990,7 @@ </histogram> <histogram name="OfflinePages.CanSaveRecentPage" enum="Boolean" - expires_after="2018-12-31"> + expires_after="2019-05-31"> <owner>carlosk@chromium.org</owner> <owner>fgorski@chromium.org</owner> <summary> @@ -71438,7 +71509,7 @@ </histogram> <histogram name="OfflinePages.LastN.IsSavingSamePage" - enum="OfflinePagesLastNIsSavingSamePageEnum" expires_after="2018-12-31"> + enum="OfflinePagesLastNIsSavingSamePageEnum" expires_after="2019-05-31"> <owner>carlosk@chromium.org</owner> <summary> Upon starting saving a new last_n offline page snapshot, report if that is @@ -75267,6 +75338,17 @@ </summary> </histogram> +<histogram name="PageLoad.Experimental.Bytes.NetworkIncludingHeaders" + units="KB"> + <owner>jkarlin@chromium.org</owner> + <summary> + The number of prefiltered (e.g., compressed) KiloBytes loaded over the + network via the browser process for a page load. This includes network + headers/overhead. Recorded when the page load is terminated. Recorded for + incomplete resources. + </summary> +</histogram> + <histogram name="PageLoad.Experimental.Bytes.Total" units="KB"> <owner>jkarlin@chromium.org</owner> <summary> @@ -77935,6 +78017,17 @@ </summary> </histogram> +<histogram name="PasswordManager.ManagePasswordsReferrerSignedInAndSyncing" + enum="ManagePasswordsReferrer"> + <owner>ioanap@chromium.org</owner> + <owner>vasilii@chromium.org</owner> + <summary> + Referrer of a navigation to the "Manage Passwords" page. Recorded + only for signed in users syncing passwords without a custom passprase, when + the user attempts to see their list of passwords. + </summary> +</histogram> + <histogram name="PasswordManager.MediationOptional" enum="CredentialManagerGetResult"> <owner>jdoerrie@chromium.org</owner> @@ -85818,6 +85911,21 @@ </summary> </histogram> +<histogram name="Prerender.PrerenderLoadedOnFirstNTP" enum="Boolean"> + <owner>justincohen@chromium.org</owner> + <summary> + Whether or not a successful prerender happens on a NTP with no history. + </summary> +</histogram> + +<histogram name="Prerender.PrerenderLoadedOnIndex"> + <owner>justincohen@chromium.org</owner> + <summary> + The last comitted index before a successful preload is committed. Recorded + only on iOS. + </summary> +</histogram> + <histogram name="Prerender.PrerenderNotSwappedInPLT" units="ms"> <obsolete> Deprecated 2017-03. @@ -85837,6 +85945,16 @@ </summary> </histogram> +<histogram name="Prerender.PrerenderStartToReleaseContentsTime" units="ms" + expires_after="2019-12-06"> + <owner>justincohen@chromium.org</owner> + <summary> + This is the time from when a prerendered page begins to load to when it is + swapped in as the main page load. Recorded when the swap occurs, only on + iOS. + </summary> +</histogram> + <histogram name="Prerender.RelTypesLinkAdded" enum="PrerenderRelTypes"> <owner>pasko@chromium.org</owner> <summary> @@ -95292,6 +95410,10 @@ </histogram> <histogram name="SBClientDownload.ZipFileContainsAppDirectory" enum="Boolean"> + <obsolete> + Removed in 12/2018 during a refactoring. The data was not being actively + used. + </obsolete> <owner>jialiul@chromium.org</owner> <summary> A Mac-only metric that records whether a downloaded zip file contains an @@ -100198,6 +100320,25 @@ <histogram name="ServiceWorker.LoadTiming.MainFrame.MainResource.ForwardServiceWorkerToWorkerReady" + units="ms"> + <obsolete> + Removed 2018-11 in favor of + ServiceWorker.LoadTiming.MainFrame.MainResource.ForwardServiceWorkerToWorkerReady2. + </obsolete> + <owner>bashi@chromium.org</owner> + <owner>chrome-worker@google.com</owner> + <summary> + The time taken from (a) a resource loading request is routed to service + worker path, to (b) a service worker is ready to handle the request. + + Recorded for each navigation request (including redirects) where there is a + fetch event handler and the fetch event was successfully dispatched to the + service worker. + </summary> +</histogram> + +<histogram + name="ServiceWorker.LoadTiming.MainFrame.MainResource.ForwardServiceWorkerToWorkerReady2" units="ms" expires_after="2021-10-31"> <owner>bashi@chromium.org</owner> <owner>chrome-worker@google.com</owner> @@ -100316,25 +100457,6 @@ <histogram name="ServiceWorker.LoadTiming.Subresource.ForwardServiceWorkerToWorkerReady" units="ms" expires_after="2021-10-31"> - <obsolete> - Deprecated 2018-11 in favor of - ServiceWorker.LoadTiming.Subresource.ForwardServiceWorkerToWorkerReady2. - </obsolete> - <owner>bashi@chromium.org</owner> - <owner>chrome-worker@google.com</owner> - <summary> - The time taken from (a) a subresource request is routed to the URLLoader (on - a background thread) for service worker controlled loads starts handling a - subresource request, to (b) a service worker is ready to handle the request. - - Recorded for each subresource request where there is a fetch event handler - and the fetch event was successfully dispatched to the service worker. - </summary> -</histogram> - -<histogram - name="ServiceWorker.LoadTiming.Subresource.ForwardServiceWorkerToWorkerReady2" - units="ms" expires_after="2021-10-31"> <owner>bashi@chromium.org</owner> <owner>chrome-worker@google.com</owner> <summary> @@ -100349,6 +100471,25 @@ <histogram name="ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted" + units="ms"> + <obsolete> + Removed 2018-12 in favor of + ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted2. + </obsolete> + <owner>bashi@chromium.org</owner> + <owner>chrome-worker@google.com</owner> + <summary> + The time taken from (a) response headers from service worker are received, + to (b) reading response body is completed. Only recorded when a fetch event + handler handled the request. + + Recorded for each subresource request where there is a fetch event handler + and the fetch event was successfully dispatched to the service worker. + </summary> +</histogram> + +<histogram + name="ServiceWorker.LoadTiming.Subresource.ResponseReceivedToCompleted2" units="ms" expires_after="2021-10-31"> <owner>bashi@chromium.org</owner> <owner>chrome-worker@google.com</owner> @@ -106300,6 +106441,15 @@ </summary> </histogram> +<histogram name="SmartLock.AuthResult.SignIn.Failure.UserControllerAuth" + enum="LoginFailureReason"> + <owner>hansberry@chromium.org</owner> + <summary> + An enumerated histogram that breaks down why the UserController could not + decrypt the account. + </summary> +</histogram> + <histogram name="SmartLock.AuthResult.Unlock" enum="BooleanSuccess"> <owner>hansberry@chromium.org</owner> <summary> @@ -128133,6 +128283,19 @@ <affected-histogram name="Autofill.StoredServerCreditCardCount"/> </histogram_suffixes> +<histogram_suffixes name="AutofillSyncState" separator="."> + <suffix name="SignedIn" label="Signed in"/> + <suffix name="SignedInAndSyncFeature" label="Signed in and sync feature"/> + <suffix name="SignedInAndWalletSyncTransportEnabled" + label="Signed in and sync transport enabled for Wallet data types"/> + <suffix name="SignedOut" label="Signed out"/> + <suffix name="Unknown" label="Unknown"/> + <affected-histogram name="Autofill.FormEvents.Address"/> + <affected-histogram name="Autofill.FormEvents.CreditCard"/> + <affected-histogram name="Autofill.IsEnabled.PageLoad"/> + <affected-histogram name="Autofill.SaveCreditCardPrompt"/> +</histogram_suffixes> + <histogram_suffixes name="AutofillUnmaskPromptCloseReasonEvents" separator="."> <suffix name="AbandonUnmasking" label="Abandon unmasking"/> <suffix name="Failure" label="Failure"/> @@ -134423,6 +134586,12 @@ <affected-histogram name="NewTabPage.OneGoogleBar.RequestLatency"/> </histogram_suffixes> +<histogram_suffixes name="NewTabPage.Promos.RequestLatency" separator="."> + <suffix name="Failure" label="Failed to fetch middle-slot Promo"/> + <suffix name="Success" label="Successfully fetched middle-slot Promo"/> + <affected-histogram name="NewTabPage.Promos.RequestLatency"/> +</histogram_suffixes> + <histogram_suffixes name="NewTabPageIconTypes" separator="."> <suffix name="IconsColor" label="Icons using a fallback color (favicon resolution too low)."/>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index 3a847ba..b3b0c252 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -2980,6 +2980,14 @@ </metric> </event> +<event name="Net.LegacyTLSVersion"> + <owner>davidben@chromium.org</owner> + <summary> + Recorded when a page is loaded whose main frame load used TLS 1.0 or TLS + 1.1. + </summary> +</event> + <event name="Notification"> <owner>peter@chromium.org</owner> <summary>
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index 49d55fd..2f98a84 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -17,9 +17,9 @@ import filecmp import json import os -import re import sys import tempfile +import textwrap from core import benchmark_finders from core import benchmark_utils @@ -580,9 +580,6 @@ with open(file_path, 'w') as fp: json.dump(tests, fp, indent=2, separators=(',', ': '), sort_keys=True) fp.write('\n') - verify_all_tests_in_benchmark_csv( - tests, ALL_PERF_WATERFALL_BENCHMARKS_METADATA) - def merge_dicts(*dict_args): result = {} @@ -679,7 +676,7 @@ add_benchmarks_from_sharding_map( tests, "shard_maps/linux-perf_map.json") add_benchmarks_from_sharding_map( - tests, "shard_maps/pixel2_7_shard_map.json") + tests, "shard_maps/android-pixel2-perf_map.json") return tests @@ -695,41 +692,79 @@ tests.add(benchmark) -def verify_all_tests_in_benchmark_csv(tests, benchmark_metadatas): - benchmark_names = set(benchmark_metadatas) - test_names = get_telemetry_tests_in_performance_test_suite() +def get_scheduled_non_telemetry_benchmarks(perf_waterfall_file): + test_names = set() + with open(perf_waterfall_file) as f: + tests_by_builder = json.load(f) - for t in tests: - scripts = [] - if 'isolated_scripts' in tests[t]: - scripts = tests[t]['isolated_scripts'] - elif 'scripts' in tests[t]: - scripts = tests[t]['scripts'] - else: - assert(t in BUILDER_ADDITIONAL_COMPILE_TARGETS - or t.startswith('AAAAA')), 'Unknown test data %s' % t - for s in scripts: - name = s['name'] - name = re.sub('\\.reference$', '', name) - # TODO(eyaich): Determine new way to generate ownership based - # on the benchmark bot map instead of on the generated tests - # for new perf recipe. - if (name is 'performance_test_suite' - or name is 'performance_webview_test_suite'): - continue + script_tests = [] + for tests in tests_by_builder.values(): + if 'isolated_scripts' in tests: + script_tests += tests['isolated_scripts'] + if 'scripts' in tests: + script_tests += tests['scripts'] + + for s in script_tests: + name = s['name'] + # TODO(eyaich): Determine new way to generate ownership based + # on the benchmark bot map instead of on the generated tests + # for new perf recipe. + if not name in ('performance_test_suite', + 'performance_webview_test_suite'): test_names.add(name) + return test_names + + +def is_perf_benchmarks_scheduling_valid( + perf_waterfall_file, outstream): + """Validates that all existing benchmarks are properly scheduled. + + Return: True if all benchmarks are properly scheduled, False otherwise. + """ + scheduled_telemetry_tests = get_telemetry_tests_in_performance_test_suite() + scheduled_non_telemetry_tests = get_scheduled_non_telemetry_benchmarks( + perf_waterfall_file) + + all_perf_telemetry_tests = set(TELEMETRY_PERF_BENCHMARKS) + all_perf_non_telemetry_tests = set(NON_TELEMETRY_BENCHMARKS) + error_messages = [] - for test in benchmark_names - test_names: - error_messages.append('Remove ' + test + ' from NON_TELEMETRY_BENCHMARKS') - for test in test_names - benchmark_names: - error_messages.append('Add ' + test + ' to NON_TELEMETRY_BENCHMARKS') - assert benchmark_names == test_names, ('Please update ' - 'NON_TELEMETRY_BENCHMARKS as below:\n' + '\n'.join(error_messages)) + for test_name in all_perf_telemetry_tests - scheduled_telemetry_tests: + if not test_name.startswith('UNSCHEDULED_'): + error_messages.append( + 'Telemetry benchmark %s exists but is not scheduled to run. Rename ' + 'it to UNSCHEDULED_%s, then file a crbug against Telemetry and ' + 'Chrome Client Infrastructure team to schedule the benchmark on the ' + 'perf waterfall.' % (test_name, test_name)) - _verify_benchmark_owners(benchmark_metadatas) + for test_name in scheduled_telemetry_tests - all_perf_telemetry_tests: + error_messages.append( + 'Telemetry benchmark %s no longer exists but is scheduled. File a bug ' + 'against Telemetry and/or Chrome Client Infrastructure team to remove ' + 'the corresponding benchmark class and deschedule the benchmark on the ' + "perf waterfall. After that, you can safely remove the benchmark's " + 'dependency code, e.g: stories, WPR archives, metrics, etc.' % + test_name) + + for test_name in all_perf_non_telemetry_tests - scheduled_non_telemetry_tests: + error_messages.append( + 'Benchmark %s is tracked but not scheduled on any perf waterfall ' + 'builders. Either schedule or remove it from NON_TELEMETRY_BENCHMARKS.' + % test_name) + + for test_name in scheduled_non_telemetry_tests - all_perf_non_telemetry_tests: + error_messages.append( + 'Benchmark %s is scheduled on perf waterfall but not tracked. Please ' + 'add an entry for it in ' + 'perf.core.perf_data_generator.NON_TELEMETRY_BENCHMARKS.' % test_name) + + for message in error_messages: + print >> outstream, '*', textwrap.fill(message, 70), '\n' + + return not error_messages # Verify that all benchmarks have owners except those on the whitelist. @@ -992,7 +1027,7 @@ 'configs')) options = parser.parse_args(args) - waterfall_file = os.path.join( + perf_waterfall_file = os.path.join( path_util.GetChromiumSrcDir(), 'testing', 'buildbot', 'chromium.perf.json') fyi_waterfall_file = os.path.join( @@ -1005,9 +1040,11 @@ labs_docs_file = os.path.join( path_util.GetChromiumSrcDir(), 'docs', 'speed', 'perf_lab_platforms.md') + return_code = 0 + if options.validate_only: if validate_tests(get_waterfall_builder_config(), - waterfall_file, benchmark_file, labs_docs_file): + perf_waterfall_file, benchmark_file, labs_docs_file): print 'All the perf config files are up-to-date. \\o/' return 0 else: @@ -1016,7 +1053,11 @@ return 1 else: load_and_update_fyi_json(fyi_waterfall_file) - update_all_tests(get_waterfall_builder_config(), waterfall_file) + update_all_tests(get_waterfall_builder_config(), perf_waterfall_file) update_benchmark_csv(benchmark_file) update_labs_docs_md(labs_docs_file) - return 0 + if not is_perf_benchmarks_scheduling_valid( + perf_waterfall_file, outstream=sys.stderr): + return_code = 1 + + return return_code
diff --git a/tools/perf/core/perf_data_generator_unittest.py b/tools/perf/core/perf_data_generator_unittest.py index 693ff68..9925042 100644 --- a/tools/perf/core/perf_data_generator_unittest.py +++ b/tools/perf/core/perf_data_generator_unittest.py
@@ -1,14 +1,18 @@ # Copyright 2017 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. -import json +import copy +import cStringIO import unittest +import tempfile +import json +import os + +import mock from core import perf_data_generator from core.perf_data_generator import BenchmarkMetadata -import mock - class PerfDataGeneratorTest(unittest.TestCase): def setUp(self): @@ -16,73 +20,37 @@ # diff when assertEquals fails. self.maxDiff = None - def testVerifyAllTestsInBenchmarkCsvPassesWithCorrectInput(self): - tests = { - 'AAAAA1 AUTOGENERATED': {}, - 'Android Nexus5 Perf (2)': { - 'scripts': [ - {'name': 'benchmark_name_1'}, - {'name': 'benchmark_name_2'} - ] - }, - 'Linux Perf': { - 'isolated_scripts': [ - {'name': 'benchmark_name_2.reference'}, - {'name': 'benchmark_name_3'} - ] - } - } - benchmarks = { - 'benchmark_name_1': BenchmarkMetadata('foo@bar.com'), - 'benchmark_name_2': - BenchmarkMetadata('darth@deathstar'), - 'benchmark_name_3': - BenchmarkMetadata('neo@matrix.org') - } + def test_get_scheduled_non_telemetry_benchmarks(self): + tmpfile = tempfile.NamedTemporaryFile(delete=False) + tmpfile.close() + fake_perf_waterfall_file = tmpfile.name - # Mock out content of unowned_benchmarks.txt and sharding map data = { - "0": { - "benchmarks": { - "benchmark_name_2": {} + 'builder 1': { + 'isolated_scripts': [ + {'name': 'test_dancing'}, + {'name': 'test_singing'}, + {'name': 'performance_test_suite'}, + ], + 'scripts': [ + {'name': 'ninja_test'}, + ] + }, + 'builder 2': { + 'scripts': [ + {'name': 'gun_slinger'}, + ] } } - } - with mock.patch('__builtin__.open', - mock.mock_open(read_data=json.dumps(data))): - perf_data_generator.verify_all_tests_in_benchmark_csv(tests, benchmarks) - - - def testVerifyAllTestsInBenchmarkCsvCatchesMismatchedTests(self): - tests = { - 'Android Nexus5 Perf (2)': { - 'scripts': [ - {'name': 'benchmark_name_1'}, - {'name': 'benchmark_name_2'} - ] - } - } - benchmarks = { - 'benchmark_name_2': BenchmarkMetadata('baz@foo.com'), - 'benchmark_name_3': BenchmarkMetadata('darth@vader.com'), - } - - with self.assertRaises(AssertionError) as context: - perf_data_generator.verify_all_tests_in_benchmark_csv(tests, benchmarks) - exception = context.exception.message - self.assertTrue('Add benchmark_name_1' in exception) - self.assertTrue('Remove benchmark_name_3' in exception) - - - def testVerifyAllTestsInBenchmarkCsvFindsFakeTest(self): - tests = {'Random fake test': {}} - benchmarks = { - 'benchmark_name_1': BenchmarkMetadata('deathstar@empire.com') - } - - with self.assertRaises(AssertionError) as context: - perf_data_generator.verify_all_tests_in_benchmark_csv(tests, benchmarks) - self.assertTrue('Unknown test' in context.exception.message) + try: + with open(fake_perf_waterfall_file, 'w') as f: + json.dump(data, f) + self.assertEquals( + perf_data_generator.get_scheduled_non_telemetry_benchmarks( + fake_perf_waterfall_file), + {'ninja_test', 'gun_slinger', 'test_dancing', 'test_singing'}) + finally: + os.remove(fake_perf_waterfall_file) def testGenerateCPlusPlusTestSuite(self): @@ -229,3 +197,119 @@ } self.assertEquals(returned_test, expected_generated_test) + +class TestIsPerfBenchmarksSchedulingValid(unittest.TestCase): + def setUp(self): + self.maxDiff = None + self.original_NON_TELEMETRY_BENCHMARKS = copy.deepcopy( + perf_data_generator.NON_TELEMETRY_BENCHMARKS) + self.original_TELEMETRY_PERF_BENCHMARKS = copy.deepcopy( + perf_data_generator.NON_TELEMETRY_BENCHMARKS) + self.test_stream = cStringIO.StringIO() + self.mock_get_telemetry_benchmarks = mock.patch( + 'core.perf_data_generator.get_telemetry_tests_in_performance_test_suite' + ) + self.get_telemetry_benchmarks = ( + self.mock_get_telemetry_benchmarks.start()) + self.mock_get_non_telemetry_benchmarks = mock.patch( + 'core.perf_data_generator.get_scheduled_non_telemetry_benchmarks') + self.get_non_telemetry_benchmarks = ( + self.mock_get_non_telemetry_benchmarks.start()) + + def tearDown(self): + perf_data_generator.TELEMETRY_PERF_BENCHMARKS = ( + self.original_TELEMETRY_PERF_BENCHMARKS) + perf_data_generator.NON_TELEMETRY_BENCHMARKS = ( + self.original_NON_TELEMETRY_BENCHMARKS) + self.mock_get_telemetry_benchmarks.stop() + self.mock_get_non_telemetry_benchmarks.stop() + + def test_returnTrue(self): + self.get_telemetry_benchmarks.return_value = {'t_foo', 't_bar'} + self.get_non_telemetry_benchmarks.return_value = {'honda'} + + perf_data_generator.TELEMETRY_PERF_BENCHMARKS = { + 't_foo': BenchmarkMetadata('t@foo.com'), + 't_bar': BenchmarkMetadata('t@bar.com'), + } + perf_data_generator.NON_TELEMETRY_BENCHMARKS = { + 'honda': BenchmarkMetadata('baz@foo.com'), + } + valid = perf_data_generator.is_perf_benchmarks_scheduling_valid( + 'dummy', self.test_stream) + + self.assertEquals(valid, True) + self.assertEquals(self.test_stream.getvalue(), '') + + def test_UnscheduledTelemetryBenchmarks( + self): + self.get_telemetry_benchmarks.return_value = {'t_bar'} + self.get_non_telemetry_benchmarks.return_value = {'honda'} + + perf_data_generator.TELEMETRY_PERF_BENCHMARKS = { + 'darth.vader': BenchmarkMetadata('death@star.com'), + 't_bar': BenchmarkMetadata('t@bar.com'), + } + perf_data_generator.NON_TELEMETRY_BENCHMARKS = { + 'honda': BenchmarkMetadata('baz@foo.com'), + } + valid = perf_data_generator.is_perf_benchmarks_scheduling_valid( + 'dummy', self.test_stream) + + self.assertEquals(valid, False) + self.assertIn('Telemetry benchmark darth.vader exists but is not scheduled', + self.test_stream.getvalue()) + + def test_UnscheduledCppBenchmarks(self): + self.get_telemetry_benchmarks.return_value = {'t_bar'} + self.get_non_telemetry_benchmarks.return_value = {'honda'} + + perf_data_generator.TELEMETRY_PERF_BENCHMARKS = { + 't_bar': BenchmarkMetadata('t@bar.com'), + } + perf_data_generator.NON_TELEMETRY_BENCHMARKS = { + 'honda': BenchmarkMetadata('baz@foo.com'), + 'toyota': BenchmarkMetadata('baz@foo.com'), + } + valid = perf_data_generator.is_perf_benchmarks_scheduling_valid( + 'dummy', self.test_stream) + + self.assertEquals(valid, False) + self.assertIn('Benchmark toyota is tracked but not scheduled', + self.test_stream.getvalue()) + + def test_UntrackedTelemetryBenchmarks( + self): + self.get_telemetry_benchmarks.return_value = {'t_bar', 'darth.vader'} + self.get_non_telemetry_benchmarks.return_value = {'honda'} + + perf_data_generator.TELEMETRY_PERF_BENCHMARKS = { + 't_bar': BenchmarkMetadata('t@bar.com'), + } + perf_data_generator.NON_TELEMETRY_BENCHMARKS = { + 'honda': BenchmarkMetadata('baz@foo.com'), + } + valid = perf_data_generator.is_perf_benchmarks_scheduling_valid( + 'dummy', self.test_stream) + + self.assertEquals(valid, False) + self.assertIn('Telemetry benchmark darth.vader no longer exists', + self.test_stream.getvalue()) + + def test_UntrackedCppBenchmarks(self): + self.get_telemetry_benchmarks.return_value = {'t_bar'} + self.get_non_telemetry_benchmarks.return_value = {'honda', 'tesla'} + + perf_data_generator.TELEMETRY_PERF_BENCHMARKS = { + 't_bar': BenchmarkMetadata('t@bar.com'), + } + perf_data_generator.NON_TELEMETRY_BENCHMARKS = { + 'honda': BenchmarkMetadata('baz@foo.com'), + } + valid = perf_data_generator.is_perf_benchmarks_scheduling_valid( + 'dummy', self.test_stream) + + self.assertEquals(valid, False) + self.assertIn( + 'Benchmark tesla is scheduled on perf waterfall but not tracked', + self.test_stream.getvalue())
diff --git a/tools/perf/core/results_dashboard.py b/tools/perf/core/results_dashboard.py index 0189908..cb257400 100755 --- a/tools/perf/core/results_dashboard.py +++ b/tools/perf/core/results_dashboard.py
@@ -24,12 +24,8 @@ import httplib2 -from telemetry.internal.util import external_modules - from core import path_util -psutil = external_modules.ImportOptionalModule('psutil') - # The paths in the results dashboard URLs for sending results. SEND_RESULTS_PATH = '/add_point'
diff --git a/tools/perf/core/retrieve_story_timing.py b/tools/perf/core/retrieve_story_timing.py index 963029a..6d8e044c 100755 --- a/tools/perf/core/retrieve_story_timing.py +++ b/tools/perf/core/retrieve_story_timing.py
@@ -10,12 +10,13 @@ import sys +_CLOUD_PROJECT_ID = 'test-results-hrd' QUERY_BY_BUILD_NUMBER = """ SELECT run.name AS name, SUM(run.times) AS duration FROM - [test-results-hrd:events.test_results] + [%s:events.test_results] WHERE buildbot_info.builder_name IN ({}) AND buildbot_info.build_number = {} @@ -23,9 +24,7 @@ name ORDER BY name -""" - - +""" % _CLOUD_PROJECT_ID QUERY_STORY_AVG_RUNTIME = """ SELECT name, @@ -36,7 +35,7 @@ start_time, AVG(run.times) AS time FROM - [test-results-hrd:events.test_results] + [%s:events.test_results] WHERE buildbot_info.builder_name IN ({configuration_names}) AND run.time IS NOT NULL @@ -52,8 +51,7 @@ name ORDER BY name -""" - +""" % _CLOUD_PROJECT_ID QUERY_STORY_TOTAL_RUNTIME = """ SELECT name, @@ -64,7 +62,7 @@ start_time, SUM(run.times) AS time FROM - [test-results-hrd:events.test_results] + [%s:events.test_results] WHERE buildbot_info.builder_name IN ({configuration_names}) AND run.time IS NOT NULL @@ -80,7 +78,7 @@ name ORDER BY name -""" +""" % _CLOUD_PROJECT_ID _BQ_SETUP_INSTRUCTION = """ @@ -105,7 +103,8 @@ subprocess.check_call(['which', 'bq']) except subprocess.CalledProcessError: raise RuntimeError(_BQ_SETUP_INSTRUCTION) - args = ["bq", "query", "--format=json", "--max_rows=100000", query] + args = ["bq", "query", "--project_id="+_CLOUD_PROJECT_ID, "--format=json", + "--max_rows=100000", query] p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate()
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 473df42..f3c86896 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -142,7 +142,8 @@ <item id="intranet_redirect_detector" hash_code="21785164" type="0" content_hash_code="62025595" os_list="linux,windows" file_path="chrome/browser/intranet_redirect_detector.cc"/> <item id="invalidation_service" hash_code="72354423" type="0" content_hash_code="78425687" os_list="linux,windows" file_path="components/invalidation/impl/gcm_network_channel.cc"/> <item id="lib_address_input" hash_code="50816767" type="0" content_hash_code="57977576" os_list="linux,windows" file_path="third_party/libaddressinput/chromium/chrome_metadata_source.cc"/> - <item id="logo_tracker" hash_code="36859107" type="0" content_hash_code="67588075" os_list="linux,windows" file_path="components/search_provider_logos/logo_tracker.cc"/> + <item id="logo_service" hash_code="35473769" type="0" content_hash_code="20271299" os_list="linux,windows" file_path="components/search_provider_logos/logo_service_impl.cc"/> + <item id="logo_tracker" hash_code="36859107" type="0" deprecated="2018-12-07" content_hash_code="67588075" file_path=""/> <item id="md_downloads_dom_handler" hash_code="65603364" type="0" content_hash_code="134779147" os_list="linux,windows" file_path="chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc"/> <item id="metrics_report_ukm" hash_code="727478" type="0" content_hash_code="40919254" os_list="linux,windows" file_path="components/metrics/net/net_metrics_log_uploader.cc"/> <item id="metrics_report_uma" hash_code="727528" type="0" content_hash_code="10176197" os_list="linux,windows" file_path="components/metrics/net/net_metrics_log_uploader.cc"/>
diff --git a/ui/accessibility/ax_node.cc b/ui/accessibility/ax_node.cc index 565c95eb..f4c85b0 100644 --- a/ui/accessibility/ax_node.cc +++ b/ui/accessibility/ax_node.cc
@@ -588,6 +588,12 @@ case ax::mojom::Role::kRadioGroup: return item_role == ax::mojom::Role::kRadioButton; + case ax::mojom::Role::kDescriptionList: + // Only the term for each description list entry should receive posinset + // and setsize. + return item_role == ax::mojom::Role::kDescriptionListTerm || + item_role == ax::mojom::Role::kTerm; + default: return false; }
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc index 7dfeb256..ffb5653 100644 --- a/ui/accessibility/ax_node_data.cc +++ b/ui/accessibility/ax_node_data.cc
@@ -413,41 +413,96 @@ void AXNodeData::AddStringAttribute(ax::mojom::StringAttribute attribute, const std::string& value) { + DCHECK_NE(attribute, ax::mojom::StringAttribute::kNone); + if (HasStringAttribute(attribute)) + RemoveStringAttribute(attribute); string_attributes.push_back(std::make_pair(attribute, value)); } void AXNodeData::AddIntAttribute(ax::mojom::IntAttribute attribute, int value) { + DCHECK_NE(attribute, ax::mojom::IntAttribute::kNone); + if (HasIntAttribute(attribute)) + RemoveIntAttribute(attribute); int_attributes.push_back(std::make_pair(attribute, value)); } -void AXNodeData::RemoveIntAttribute(ax::mojom::IntAttribute attribute) { - DCHECK_GE(static_cast<int>(attribute), 0); - base::EraseIf(int_attributes, [attribute](const auto& int_attribute) { - return int_attribute.first == attribute; - }); -} - void AXNodeData::AddFloatAttribute(ax::mojom::FloatAttribute attribute, float value) { + DCHECK_NE(attribute, ax::mojom::FloatAttribute::kNone); + if (HasFloatAttribute(attribute)) + RemoveFloatAttribute(attribute); float_attributes.push_back(std::make_pair(attribute, value)); } void AXNodeData::AddBoolAttribute(ax::mojom::BoolAttribute attribute, bool value) { + DCHECK_NE(attribute, ax::mojom::BoolAttribute::kNone); + if (HasBoolAttribute(attribute)) + RemoveBoolAttribute(attribute); bool_attributes.push_back(std::make_pair(attribute, value)); } void AXNodeData::AddIntListAttribute(ax::mojom::IntListAttribute attribute, const std::vector<int32_t>& value) { + DCHECK_NE(attribute, ax::mojom::IntListAttribute::kNone); + if (HasIntListAttribute(attribute)) + RemoveIntListAttribute(attribute); intlist_attributes.push_back(std::make_pair(attribute, value)); } void AXNodeData::AddStringListAttribute( ax::mojom::StringListAttribute attribute, const std::vector<std::string>& value) { + DCHECK_NE(attribute, ax::mojom::StringListAttribute::kNone); + if (HasStringListAttribute(attribute)) + RemoveStringListAttribute(attribute); stringlist_attributes.push_back(std::make_pair(attribute, value)); } +void AXNodeData::RemoveStringAttribute(ax::mojom::StringAttribute attribute) { + DCHECK_NE(attribute, ax::mojom::StringAttribute::kNone); + base::EraseIf(string_attributes, [attribute](const auto& string_attribute) { + return string_attribute.first == attribute; + }); +} + +void AXNodeData::RemoveIntAttribute(ax::mojom::IntAttribute attribute) { + DCHECK_NE(attribute, ax::mojom::IntAttribute::kNone); + base::EraseIf(int_attributes, [attribute](const auto& int_attribute) { + return int_attribute.first == attribute; + }); +} + +void AXNodeData::RemoveFloatAttribute(ax::mojom::FloatAttribute attribute) { + DCHECK_NE(attribute, ax::mojom::FloatAttribute::kNone); + base::EraseIf(float_attributes, [attribute](const auto& float_attribute) { + return float_attribute.first == attribute; + }); +} + +void AXNodeData::RemoveBoolAttribute(ax::mojom::BoolAttribute attribute) { + DCHECK_NE(attribute, ax::mojom::BoolAttribute::kNone); + base::EraseIf(bool_attributes, [attribute](const auto& bool_attribute) { + return bool_attribute.first == attribute; + }); +} + +void AXNodeData::RemoveIntListAttribute(ax::mojom::IntListAttribute attribute) { + DCHECK_NE(attribute, ax::mojom::IntListAttribute::kNone); + base::EraseIf(intlist_attributes, [attribute](const auto& intlist_attribute) { + return intlist_attribute.first == attribute; + }); +} + +void AXNodeData::RemoveStringListAttribute( + ax::mojom::StringListAttribute attribute) { + DCHECK_NE(attribute, ax::mojom::StringListAttribute::kNone); + base::EraseIf(stringlist_attributes, + [attribute](const auto& stringlist_attribute) { + return stringlist_attribute.first == attribute; + }); +} + void AXNodeData::SetName(const std::string& name) { auto iter = std::find_if(string_attributes.begin(), string_attributes.end(), [](const auto& string_attribute) {
diff --git a/ui/accessibility/ax_node_data.h b/ui/accessibility/ax_node_data.h index 232d562..5aebdf41 100644 --- a/ui/accessibility/ax_node_data.h +++ b/ui/accessibility/ax_node_data.h
@@ -93,11 +93,17 @@ bool GetHtmlAttribute(const char* attribute, base::string16* value) const; bool GetHtmlAttribute(const char* attribute, std::string* value) const; + // // Setting accessibility attributes. + // + // Replaces an attribute if not present. This is safer than crashing via a + // DCHECK or doing nothing, because most likely that's what the caller would + // have wanted or what existing code already assumes. + // + void AddStringAttribute(ax::mojom::StringAttribute attribute, const std::string& value); void AddIntAttribute(ax::mojom::IntAttribute attribute, int32_t value); - void RemoveIntAttribute(ax::mojom::IntAttribute attribute); void AddFloatAttribute(ax::mojom::FloatAttribute attribute, float value); void AddBoolAttribute(ax::mojom::BoolAttribute attribute, bool value); void AddIntListAttribute(ax::mojom::IntListAttribute attribute, @@ -106,6 +112,17 @@ const std::vector<std::string>& value); // + // Removing accessibility attributes. + // + + void RemoveStringAttribute(ax::mojom::StringAttribute attribute); + void RemoveIntAttribute(ax::mojom::IntAttribute attribute); + void RemoveFloatAttribute(ax::mojom::FloatAttribute attribute); + void RemoveBoolAttribute(ax::mojom::BoolAttribute attribute); + void RemoveIntListAttribute(ax::mojom::IntListAttribute attribute); + void RemoveStringListAttribute(ax::mojom::StringListAttribute attribute); + + // // Convenience functions. //
diff --git a/ui/accessibility/ax_role_properties.cc b/ui/accessibility/ax_role_properties.cc index a73a9e6..61496f3 100644 --- a/ui/accessibility/ax_role_properties.cc +++ b/ui/accessibility/ax_role_properties.cc
@@ -171,6 +171,8 @@ case ax::mojom::Role::kTreeItem: case ax::mojom::Role::kListBoxOption: case ax::mojom::Role::kRadioButton: + case ax::mojom::Role::kDescriptionListTerm: + case ax::mojom::Role::kTerm: return true; default: return false; @@ -269,6 +271,7 @@ case ax::mojom::Role::kTree: case ax::mojom::Role::kListBox: case ax::mojom::Role::kRadioGroup: + case ax::mojom::Role::kDescriptionList: return true; default: return false;
diff --git a/ui/android/build/create_ui_locale_resources.py b/ui/android/build/create_ui_locale_resources.py index 62943353..d62f636 100755 --- a/ui/android/build/create_ui_locale_resources.py +++ b/ui/android/build/create_ui_locale_resources.py
@@ -77,8 +77,7 @@ _AddLocaleResourceFileToZip(out_zip, '', _DEFAULT_CHROME_LOCALE) for locale in locale_list: - android_locale = \ - resource_utils.CHROME_TO_ANDROID_LOCALE_MAP.get(locale, locale) + android_locale = resource_utils.ToAndroidLocaleName(locale) _AddLocaleResourceFileToZip(out_zip, android_locale, locale) if args.depfile:
diff --git a/ui/android/delegated_frame_host_android_unittest.cc b/ui/android/delegated_frame_host_android_unittest.cc index 2a52e65..994438f 100644 --- a/ui/android/delegated_frame_host_android_unittest.cc +++ b/ui/android/delegated_frame_host_android_unittest.cc
@@ -4,11 +4,13 @@ #include "ui/android/delegated_frame_host_android.h" #include "base/android/build_info.h" +#include "base/test/scoped_feature_list.h" #include "base/test/test_mock_time_task_runner.h" #include "cc/layers/layer.h" #include "cc/layers/solid_color_layer.h" #include "cc/layers/surface_layer.h" #include "cc/trees/layer_tree_host.h" +#include "components/viz/common/features.h" #include "components/viz/common/hit_test/hit_test_region_list.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "components/viz/host/host_frame_sink_manager.h" @@ -87,13 +89,11 @@ view_.SetLayer(cc::SolidColorLayer::Create()); frame_host_ = std::make_unique<DelegatedFrameHostAndroid>( &view_, &host_frame_sink_manager_, &client_, frame_sink_id_, - ShouldEnableSurfaceSynchronization()); + features::IsSurfaceSynchronizationEnabled()); } void TearDown() override { frame_host_.reset(); } - virtual bool ShouldEnableSurfaceSynchronization() const { return false; } - ui::CompositorLock* GetLock(CompositorLockClient* client, base::TimeDelta time_delta) { return lock_manager_.GetCompositorLock(client, time_delta, nullptr) @@ -139,13 +139,63 @@ CompositorLockManager lock_manager_; }; -class DelegatedFrameHostAndroidSurfaceSynchronizationTest +class DelegatedFrameHostAndroidVizTest : public DelegatedFrameHostAndroidTest { + public: + DelegatedFrameHostAndroidVizTest() = default; + ~DelegatedFrameHostAndroidVizTest() override = default; + + void SetUp() override { + // Enable both Viz and SurfaceSync. + scoped_feature_list_.InitWithFeatures( + {features::kVizDisplayCompositor, + features::kEnableSurfaceSynchronization}, + {}); + + DelegatedFrameHostAndroidTest::SetUp(); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +// TODO(ericrk): Remove these tests once Viz OOP-D has launched. +class DelegatedFrameHostAndroidSurfaceSynchronizationOnlyTest : public DelegatedFrameHostAndroidTest { public: - DelegatedFrameHostAndroidSurfaceSynchronizationTest() = default; - ~DelegatedFrameHostAndroidSurfaceSynchronizationTest() override = default; + DelegatedFrameHostAndroidSurfaceSynchronizationOnlyTest() = default; + ~DelegatedFrameHostAndroidSurfaceSynchronizationOnlyTest() override = default; - bool ShouldEnableSurfaceSynchronization() const override { return true; } + void SetUp() override { + // Enable SurfaceSync without Viz. + scoped_feature_list_.InitWithFeatures( + {features::kEnableSurfaceSynchronization}, + {features::kVizDisplayCompositor}); + + DelegatedFrameHostAndroidTest::SetUp(); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +// TODO(ericrk): Remove these tests once Viz OOP-D has launched. +class DelegatedFrameHostAndroidLegacyNonVizTest + : public DelegatedFrameHostAndroidTest { + public: + DelegatedFrameHostAndroidLegacyNonVizTest() = default; + ~DelegatedFrameHostAndroidLegacyNonVizTest() override = default; + + void SetUp() override { + // Disable both Viz and SurfaceSync. + scoped_feature_list_.InitWithFeatures( + {}, {features::kVizDisplayCompositor, + features::kEnableSurfaceSynchronization}); + + DelegatedFrameHostAndroidTest::SetUp(); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; }; // Resize lock is only enabled on O+. @@ -154,10 +204,9 @@ base::android::SDK_VERSION_OREO; } -// If surface synchronization is enabled then we should not be acquiring a -// compositor lock on attach. -TEST_F(DelegatedFrameHostAndroidSurfaceSynchronizationTest, - NoCompositorLockOnAttach) { +// If OOP-D is enabled then we should not be acquiring a compositor lock on +// attach. +TEST_F(DelegatedFrameHostAndroidVizTest, NoCompositorLockOnAttach) { EXPECT_CALL(compositor_, IsDrawingFirstVisibleFrame()).Times(0); EXPECT_CALL(compositor_, DoGetCompositorLock(_, _)).Times(0); frame_host_->AttachToCompositor(&compositor_); @@ -166,7 +215,8 @@ // If surface synchronization is off, and we are doing a cross-process // navigation, then both the primary and fallback surface IDs need to be // updated together. -TEST_F(DelegatedFrameHostAndroidTest, TakeFallbackContentFromUpdatesPrimary) { +TEST_F(DelegatedFrameHostAndroidLegacyNonVizTest, + TakeFallbackContentFromUpdatesPrimary) { EXPECT_FALSE(frame_host_->SurfaceId().is_valid()); // Submit a compositor frame to ensure we have delegated content. SubmitCompositorFrame(); @@ -175,7 +225,7 @@ std::unique_ptr<DelegatedFrameHostAndroid> other_frame_host = std::make_unique<DelegatedFrameHostAndroid>( &view_, &host_frame_sink_manager_, &client_, viz::FrameSinkId(2, 2), - ShouldEnableSurfaceSynchronization()); + features::IsSurfaceSynchronizationEnabled()); EXPECT_FALSE(other_frame_host->SurfaceId().is_valid()); @@ -187,7 +237,8 @@ ->oldest_acceptable_fallback()); } -TEST_F(DelegatedFrameHostAndroidTest, CompositorLockDuringFirstFrame) { +TEST_F(DelegatedFrameHostAndroidLegacyNonVizTest, + CompositorLockDuringFirstFrame) { // Attach during the first frame, lock will be taken. EXPECT_CALL(compositor_, IsDrawingFirstVisibleFrame()).WillOnce(Return(true)); EXPECT_CALL(compositor_, DoGetCompositorLock(frame_host_.get(), _)) @@ -200,7 +251,8 @@ EXPECT_FALSE(IsLocked()); } -TEST_F(DelegatedFrameHostAndroidTest, CompositorLockDuringLaterFrame) { +TEST_F(DelegatedFrameHostAndroidLegacyNonVizTest, + CompositorLockDuringLaterFrame) { // Attach after the first frame, lock will not be taken. EXPECT_CALL(compositor_, IsDrawingFirstVisibleFrame()) .WillOnce(Return(false)); @@ -208,7 +260,8 @@ frame_host_->AttachToCompositor(&compositor_); } -TEST_F(DelegatedFrameHostAndroidTest, CompositorLockWithDelegatedContent) { +TEST_F(DelegatedFrameHostAndroidLegacyNonVizTest, + CompositorLockWithDelegatedContent) { // Submit a compositor frame to ensure we have delegated content. SubmitCompositorFrame(); @@ -219,7 +272,8 @@ frame_host_->AttachToCompositor(&compositor_); } -TEST_F(DelegatedFrameHostAndroidTest, CompositorLockReleasedWithDetach) { +TEST_F(DelegatedFrameHostAndroidLegacyNonVizTest, + CompositorLockReleasedWithDetach) { // Attach during the first frame, lock will be taken. EXPECT_CALL(compositor_, IsDrawingFirstVisibleFrame()).WillOnce(Return(true)); EXPECT_CALL(compositor_, DoGetCompositorLock(frame_host_.get(), _)) @@ -232,7 +286,7 @@ EXPECT_FALSE(IsLocked()); } -TEST_F(DelegatedFrameHostAndroidTest, ResizeLockBasic) { +TEST_F(DelegatedFrameHostAndroidLegacyNonVizTest, ResizeLockBasic) { // Resize lock is only enabled on O+. if (!IsResizeLockEnabled()) return; @@ -254,7 +308,8 @@ EXPECT_FALSE(IsLocked()); } -TEST_F(DelegatedFrameHostAndroidTest, ResizeLockNotTakenIfNoSizeChange) { +TEST_F(DelegatedFrameHostAndroidLegacyNonVizTest, + ResizeLockNotTakenIfNoSizeChange) { // Resize lock is only enabled on O+. if (!IsResizeLockEnabled()) return; @@ -266,7 +321,8 @@ EXPECT_FALSE(IsLocked()); } -TEST_F(DelegatedFrameHostAndroidTest, ResizeLockReleasedWithDetach) { +TEST_F(DelegatedFrameHostAndroidLegacyNonVizTest, + ResizeLockReleasedWithDetach) { // Resize lock is only enabled on O+. if (!IsResizeLockEnabled()) return; @@ -284,7 +340,7 @@ EXPECT_FALSE(IsLocked()); } -TEST_F(DelegatedFrameHostAndroidTest, TestBothCompositorLocks) { +TEST_F(DelegatedFrameHostAndroidLegacyNonVizTest, TestBothCompositorLocks) { // Resize lock is only enabled on O+. if (!IsResizeLockEnabled()) return; @@ -309,7 +365,7 @@ // Make sure frame evictor is notified of the newly embedded surface after // WasShown. -TEST_F(DelegatedFrameHostAndroidSurfaceSynchronizationTest, EmbedWhileHidden) { +TEST_F(DelegatedFrameHostAndroidVizTest, EmbedWhileHidden) { { EXPECT_CALL(client_, WasEvicted()); frame_host_->EvictDelegatedFrame(); @@ -329,7 +385,7 @@ // Verify that when a source rect or output size is not provided to // CopyFromCompositingSurface, the corresponding values in CopyOutputRequest // are also not initialized. -TEST_F(DelegatedFrameHostAndroidSurfaceSynchronizationTest, +TEST_F(DelegatedFrameHostAndroidSurfaceSynchronizationOnlyTest, FullSurfaceCapture) { // First embed a surface to make sure we have something to copy from. allocator_.GenerateId();
diff --git a/ui/aura/mus/in_flight_change.cc b/ui/aura/mus/in_flight_change.cc index fe5ed31..fc0aa17 100644 --- a/ui/aura/mus/in_flight_change.cc +++ b/ui/aura/mus/in_flight_change.cc
@@ -145,7 +145,10 @@ } void CrashInFlightChange::ChangeFailed() { - CHECK(false) << "change failed, type=" << static_cast<int>(change_type()); + // TODO(crbug.com/912228): remove LOG(). Used to figure out why this is being + // hit. + LOG(ERROR) << "change failed, type=" << static_cast<int>(change_type()); + CHECK(false); } void CrashInFlightChange::Revert() {
diff --git a/ui/aura/test/ui_controls_factory_ozone.cc b/ui/aura/test/ui_controls_factory_ozone.cc index 2c6070f..be92029e 100644 --- a/ui/aura/test/ui_controls_factory_ozone.cc +++ b/ui/aura/test/ui_controls_factory_ozone.cc
@@ -20,6 +20,7 @@ #include "ui/aura/window_tree_host.h" #include "ui/base/test/ui_controls_aura.h" #include "ui/display/display.h" +#include "ui/display/display_observer.h" #include "ui/display/screen.h" #include "ui/events/event_utils.h" #include "ui/events/test/events_test_utils.h" @@ -37,9 +38,16 @@ std::move(closure).Run(); } -class UIControlsOzone : public ui_controls::UIControlsAura { +class UIControlsOzone : public ui_controls::UIControlsAura, + display::DisplayObserver { public: - UIControlsOzone(WindowTreeHost* host) : host_(host) {} + UIControlsOzone(WindowTreeHost* host) : host_(host) { + MaybeInitializeEventInjector(); + display::Screen::GetScreen()->AddObserver(this); + } + ~UIControlsOzone() override { + display::Screen::GetScreen()->RemoveObserver(this); + } private: // ui_controls::UIControlsAura: @@ -60,40 +68,43 @@ bool command, base::OnceClosure closure) override { int flags = button_down_mask_; + int64_t display_id = + display::Screen::GetScreen()->GetDisplayNearestWindow(window).id(); if (control) { flags |= ui::EF_CONTROL_DOWN; - PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, flags, + PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, flags, display_id, base::OnceClosure()); } if (shift) { flags |= ui::EF_SHIFT_DOWN; - PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, flags, + PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, flags, display_id, base::OnceClosure()); } if (alt) { flags |= ui::EF_ALT_DOWN; - PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_MENU, flags, + PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_MENU, flags, display_id, base::OnceClosure()); } if (command) { flags |= ui::EF_COMMAND_DOWN; - PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_LWIN, flags, + PostKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_LWIN, flags, display_id, base::OnceClosure()); } - PostKeyEvent(ui::ET_KEY_PRESSED, key, flags, base::OnceClosure()); + PostKeyEvent(ui::ET_KEY_PRESSED, key, flags, display_id, + base::OnceClosure()); const bool has_modifier = control || shift || alt || command; // Pass the real closure to the last generated KeyEvent. - PostKeyEvent(ui::ET_KEY_RELEASED, key, flags, + PostKeyEvent(ui::ET_KEY_RELEASED, key, flags, display_id, has_modifier ? base::OnceClosure() : std::move(closure)); if (alt) { flags &= ~ui::EF_ALT_DOWN; - PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_MENU, flags, + PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_MENU, flags, display_id, (shift || control || command) ? base::OnceClosure() : std::move(closure)); } @@ -101,19 +112,19 @@ if (shift) { flags &= ~ui::EF_SHIFT_DOWN; PostKeyEvent( - ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, flags, + ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, flags, display_id, (control || command) ? base::OnceClosure() : std::move(closure)); } if (control) { flags &= ~ui::EF_CONTROL_DOWN; - PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, flags, + PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, flags, display_id, command ? base::OnceClosure() : std::move(closure)); } if (command) { flags &= ~ui::EF_COMMAND_DOWN; - PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_LWIN, flags, + PostKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_LWIN, flags, display_id, std::move(closure)); } @@ -127,9 +138,11 @@ long screen_y, base::OnceClosure closure) override { gfx::Point host_location(screen_x, screen_y); - if (!ScreenDIPToHostPixels(&host_location)) + int64_t display_id = display::kInvalidDisplayId; + if (!ScreenDIPToHostPixels(&host_location, &display_id)) return false; last_mouse_location_ = host_location; + last_mouse_display_id_ = display_id; ui::EventType event_type; @@ -138,7 +151,7 @@ else event_type = ui::ET_MOUSE_MOVED; - PostMouseEvent(event_type, host_location, button_down_mask_, 0, + PostMouseEvent(event_type, host_location, button_down_mask_, 0, display_id, std::move(closure)); return true; @@ -154,11 +167,13 @@ base::OnceClosure closure, int accelerator_state) override { gfx::Point host_location; + int64_t display_id = display::kInvalidDisplayId; if (last_mouse_location_.has_value()) { host_location = last_mouse_location_.value(); + display_id = last_mouse_display_id_; } else { host_location = host_->window()->env()->last_mouse_location(); - if (!ScreenDIPToHostPixels(&host_location)) + if (!ScreenDIPToHostPixels(&host_location, &display_id)) return false; } @@ -194,14 +209,14 @@ button_down_mask_ |= flag; // Pass the real closure to the last generated MouseEvent. PostMouseEvent(ui::ET_MOUSE_PRESSED, host_location, - button_down_mask_ | flag, changed_button_flag, + button_down_mask_ | flag, changed_button_flag, display_id, (button_state & ui_controls::UP) ? base::OnceClosure() : std::move(closure)); } if (button_state & ui_controls::UP) { button_down_mask_ &= ~flag; PostMouseEvent(ui::ET_MOUSE_RELEASED, host_location, - button_down_mask_ | flag, changed_button_flag, + button_down_mask_ | flag, changed_button_flag, display_id, std::move(closure)); } @@ -222,7 +237,8 @@ base::OnceClosure task) override { DCHECK_NE(0, action); gfx::Point host_location(x, y); - if (!ScreenDIPToHostPixels(&host_location)) + int64_t display_id = display::kInvalidDisplayId; + if (!ScreenDIPToHostPixels(&host_location, &display_id)) return false; bool has_move = action & ui_controls::MOVE; bool has_release = action & ui_controls::RELEASE; @@ -231,28 +247,39 @@ if (action & ui_controls::PRESS) { ui::TouchEvent event(ui::ET_TOUCH_PRESSED, host_location, base::TimeTicks::Now(), details); - SendEventToSink(&event, (has_move || has_release) ? base::OnceClosure() - : std::move(task)); + SendEventToSink( + &event, display_id, + (has_move || has_release) ? base::OnceClosure() : std::move(task)); } if (has_move) { ui::TouchEvent event(ui::ET_TOUCH_MOVED, host_location, base::TimeTicks::Now(), details); - SendEventToSink(&event, + SendEventToSink(&event, display_id, has_release ? base::OnceClosure() : std::move(task)); } if (has_release) { ui::TouchEvent event(ui::ET_TOUCH_RELEASED, host_location, base::TimeTicks::Now(), details); - SendEventToSink(&event, std::move(task)); + SendEventToSink(&event, display_id, std::move(task)); } return true; } #endif - void SendEventToSink(ui::Event* event, base::OnceClosure closure) { - if (host_->window()->env()->mode() == aura::Env::Mode::MUS) { - GetEventInjector()->InjectEvent( - host_->GetDisplayId(), ui::Event::Clone(*event), + // display::DisplayObserver: + void OnDisplayRemoved(const display::Display& old_display) override { + if (last_mouse_display_id_ == old_display.id()) { + last_mouse_display_id_ = display::kInvalidDisplayId; + last_mouse_location_.reset(); + } + } + + void SendEventToSink(ui::Event* event, + int64_t display_id, + base::OnceClosure closure) { + if (event_injector_) { + event_injector_->InjectEvent( + display_id, ui::Event::Clone(*event), base::BindOnce(&OnWindowServiceProcessedEvent, std::move(closure))); return; } @@ -271,40 +298,44 @@ void PostKeyEvent(ui::EventType type, ui::KeyboardCode key_code, int flags, + int64_t display_id, base::OnceClosure closure) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&UIControlsOzone::PostKeyEventTask, base::Unretained(this), type, key_code, flags, - std::move(closure))); + display_id, std::move(closure))); } void PostKeyEventTask(ui::EventType type, ui::KeyboardCode key_code, int flags, + int64_t display_id, base::OnceClosure closure) { // Do not rewrite injected events. See crbug.com/136465. flags |= ui::EF_FINAL; ui::KeyEvent key_event(type, key_code, flags); - SendEventToSink(&key_event, std::move(closure)); + SendEventToSink(&key_event, display_id, std::move(closure)); } void PostMouseEvent(ui::EventType type, const gfx::Point& host_location, int flags, int changed_button_flags, + int64_t display_id, base::OnceClosure closure) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&UIControlsOzone::PostMouseEventTask, base::Unretained(this), type, host_location, flags, - changed_button_flags, std::move(closure))); + changed_button_flags, display_id, std::move(closure))); } void PostMouseEventTask(ui::EventType type, const gfx::Point& host_location, int flags, int changed_button_flags, + int64_t display_id, base::OnceClosure closure) { ui::MouseEvent mouse_event(type, host_location, host_location, ui::EventTimeForNow(), flags, @@ -313,33 +344,34 @@ // This hack is necessary to set the repeat count for clicks. ui::MouseEvent mouse_event2(&mouse_event); - SendEventToSink(&mouse_event2, std::move(closure)); + SendEventToSink(&mouse_event2, display_id, std::move(closure)); } - // Returns the ws::mojom::EventInjector, which is used to send events - // to the Window Service for dispatch. - ws::mojom::EventInjector* GetEventInjector() { - DCHECK_EQ(aura::Env::Mode::MUS, host_->window()->env()->mode()); - if (!event_injector_) { - DCHECK(aura::test::EnvTestHelper().GetWindowTreeClient()); - aura::test::EnvTestHelper() - .GetWindowTreeClient() - ->connector() - ->BindInterface(ws::mojom::kServiceName, &event_injector_); - } - return event_injector_.get(); + // Initializes EventInjector when Mus. Otherwise do nothing. + void MaybeInitializeEventInjector() { + if (host_->window()->env()->mode() != Env::Mode::MUS) + return; + + DCHECK(aura::test::EnvTestHelper().GetWindowTreeClient()); + aura::test::EnvTestHelper() + .GetWindowTreeClient() + ->connector() + ->BindInterface(ws::mojom::kServiceName, &event_injector_); } - bool ScreenDIPToHostPixels(gfx::Point* location) { + bool ScreenDIPToHostPixels(gfx::Point* location, int64_t* display_id) { // The location needs to be in display's coordinate. - display::Display display; - if (!display::Screen::GetScreen()->GetDisplayWithDisplayId( - host_->GetDisplayId(), &display)) { - LOG(ERROR) << "Failed to find the display for " << host_->GetDisplayId(); + display::Display display = + display::Screen::GetScreen()->GetDisplayNearestPoint(*location); + if (!display.is_valid()) { + LOG(ERROR) << "Failed to find the display for " << location->ToString(); return false; } + *display_id = display.id(); *location -= display.bounds().OffsetFromOrigin(); - host_->ConvertDIPToPixels(location); + *location = + gfx::ScaleToFlooredPoint(*location, display.device_scale_factor(), + display.device_scale_factor()); return true; } @@ -351,6 +383,11 @@ // is updated asynchronously with mus. base::Optional<gfx::Point> last_mouse_location_; + // The display ID where the last SendMouseEventsNotifyWhenDone occurred. This + // is used along with |last_mouse_location_| to send the mouse event to the + // event injector. Not used when Mus is not enabled. + int64_t last_mouse_display_id_ = display::kInvalidDisplayId; + // Mask of the mouse buttons currently down. This is static as it needs to // track the state globally for all displays. A UIControlsOzone instance is // created for each display host.
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 3343696..85cf181 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -811,6 +811,20 @@ ] } +if (is_android) { + android_assets("ui_base_test_android_assets") { + testonly = true + + # Use $target_gen_dir so the associated .pak.info file is available. + sources = [ + "$target_gen_dir/ui_base_test_resources.pak", + ] + deps = [ + ":ui_base_test_resources_grit", + ] + } +} + if (is_ios) { bundle_data("ui_base_test_bundle_data") { testonly = true @@ -953,9 +967,13 @@ "//url", ] - if (is_ios) { + # Include the correct ui_base_test resources per platform. + if (is_android) { + deps += [ ":ui_base_test_android_assets" ] + data_deps += [ ":ui_base_test_resources_pak" ] + } else if (is_ios) { deps += [ ":ui_base_test_bundle_data" ] - } else if (!is_android) { + } else { data += [ "$root_out_dir/ui_base_test_resources.pak" ] data_deps += [ ":ui_base_test_resources_pak" ] }
diff --git a/ui/base/clipboard/clipboard.cc b/ui/base/clipboard/clipboard.cc index 3866526..a621d64 100644 --- a/ui/base/clipboard/clipboard.cc +++ b/ui/base/clipboard/clipboard.cc
@@ -64,6 +64,24 @@ } // static +std::unique_ptr<Clipboard> Clipboard::TakeForCurrentThread() { + base::AutoLock lock(clipboard_map_lock_.Get()); + + ClipboardMap* clipboard_map = clipboard_map_.Pointer(); + base::PlatformThreadId id = base::PlatformThread::CurrentId(); + + Clipboard* clipboard = nullptr; + + auto it = clipboard_map->find(id); + if (it != clipboard_map->end()) { + clipboard = it->second.release(); + clipboard_map->erase(it); + } + + return base::WrapUnique(clipboard); +} + +// static void Clipboard::OnPreShutdownForCurrentThread() { base::AutoLock lock(clipboard_map_lock_.Get()); base::PlatformThreadId id = GetAndValidateThreadID();
diff --git a/ui/base/clipboard/clipboard.h b/ui/base/clipboard/clipboard.h index d76a66d6..60410973 100644 --- a/ui/base/clipboard/clipboard.h +++ b/ui/base/clipboard/clipboard.h
@@ -142,6 +142,10 @@ // the IO thread. static Clipboard* GetForCurrentThread(); + // Removes and transfers ownership of the current thread's clipboard to the + // caller. If the clipboard was never initialized, returns nullptr. + static std::unique_ptr<Clipboard> TakeForCurrentThread(); + // Does any work necessary prior to Chrome shutdown for the current thread. // All platforms but Windows have a single clipboard shared accross all // threads. This function is a no-op on Windows. On Desktop Linux, if Chrome
diff --git a/ui/base/clipboard/clipboard_aura.cc b/ui/base/clipboard/clipboard_aura.cc index 9233b0f89..a70dcb97 100644 --- a/ui/base/clipboard/clipboard_aura.cc +++ b/ui/base/clipboard/clipboard_aura.cc
@@ -152,6 +152,8 @@ DISALLOW_COPY_AND_ASSIGN(ClipboardData); }; +} // namespace + // Platform clipboard implementation for Aura. This handles things like format // conversion, versioning of clipboard items etc. The goal is to roughly provide // a substitute to platform clipboards on other platforms such as GtkClipboard @@ -330,24 +332,11 @@ DISALLOW_COPY_AND_ASSIGN(AuraClipboard); }; -AuraClipboard* g_aura_clipboard = NULL; - -AuraClipboard* GetClipboard() { - if (!g_aura_clipboard) - g_aura_clipboard = new AuraClipboard(); - return g_aura_clipboard; -} - -void DeleteClipboard() { - delete g_aura_clipboard; - g_aura_clipboard = NULL; -} - // Helper class to build a ClipboardData object and write it to clipboard. class ClipboardDataBuilder { public: - static void CommitToClipboard() { - GetClipboard()->WriteData(TakeCurrentData()); + static void CommitToClipboard(AuraClipboard* clipboard) { + clipboard->WriteData(TakeCurrentData()); } static void WriteText(const char* text_data, size_t text_len) { @@ -414,8 +403,6 @@ ClipboardData* ClipboardDataBuilder::current_data_ = nullptr; -} // namespace - // Clipboard::FormatType implementation. Clipboard::FormatType::FormatType() { } @@ -533,49 +520,45 @@ } // ClipboardAura implementation. -ClipboardAura::ClipboardAura() { +ClipboardAura::ClipboardAura() + : clipboard_internal_(std::make_unique<AuraClipboard>()) { DCHECK(CalledOnValidThread()); - // Make sure clipboard is created. - GetClipboard(); } ClipboardAura::~ClipboardAura() { DCHECK(CalledOnValidThread()); - DeleteClipboard(); } void ClipboardAura::OnPreShutdown() {} uint64_t ClipboardAura::GetSequenceNumber(ClipboardType type) const { DCHECK(CalledOnValidThread()); - return GetClipboard()->sequence_number(); + return clipboard_internal_->sequence_number(); } bool ClipboardAura::IsFormatAvailable(const FormatType& format, ClipboardType type) const { DCHECK(CalledOnValidThread()); DCHECK(IsSupportedClipboardType(type)); - AuraClipboard* clipboard = GetClipboard(); if (GetPlainTextFormatType().Equals(format) || GetUrlFormatType().Equals(format)) - return clipboard->IsFormatAvailable(TEXT); + return clipboard_internal_->IsFormatAvailable(TEXT); if (GetHtmlFormatType().Equals(format)) - return clipboard->IsFormatAvailable(HTML); + return clipboard_internal_->IsFormatAvailable(HTML); if (GetRtfFormatType().Equals(format)) - return clipboard->IsFormatAvailable(RTF); + return clipboard_internal_->IsFormatAvailable(RTF); if (GetBitmapFormatType().Equals(format)) - return clipboard->IsFormatAvailable(BITMAP); + return clipboard_internal_->IsFormatAvailable(BITMAP); if (GetWebKitSmartPasteFormatType().Equals(format)) - return clipboard->IsFormatAvailable(WEB); - const ClipboardData* data = clipboard->GetData(); + return clipboard_internal_->IsFormatAvailable(WEB); + const ClipboardData* data = clipboard_internal_->GetData(); return data && data->custom_data_format() == format.ToString(); } void ClipboardAura::Clear(ClipboardType type) { DCHECK(CalledOnValidThread()); DCHECK(IsSupportedClipboardType(type)); - AuraClipboard* clipboard = GetClipboard(); - clipboard->Clear(); + clipboard_internal_->Clear(); } void ClipboardAura::ReadAvailableTypes(ClipboardType type, @@ -598,22 +581,23 @@ if (IsFormatAvailable(GetBitmapFormatType(), type)) types->push_back(base::UTF8ToUTF16(kMimeTypePNG)); - AuraClipboard* clipboard = GetClipboard(); - if (clipboard->IsFormatAvailable(CUSTOM) && clipboard->GetData()) { - ui::ReadCustomDataTypes(clipboard->GetData()->custom_data_data().c_str(), - clipboard->GetData()->custom_data_data().size(), types); + if (clipboard_internal_->IsFormatAvailable(CUSTOM) && + clipboard_internal_->GetData()) { + ui::ReadCustomDataTypes( + clipboard_internal_->GetData()->custom_data_data().c_str(), + clipboard_internal_->GetData()->custom_data_data().size(), types); } } void ClipboardAura::ReadText(ClipboardType type, base::string16* result) const { DCHECK(CalledOnValidThread()); - GetClipboard()->ReadText(result); + clipboard_internal_->ReadText(result); } void ClipboardAura::ReadAsciiText(ClipboardType type, std::string* result) const { DCHECK(CalledOnValidThread()); - GetClipboard()->ReadAsciiText(result); + clipboard_internal_->ReadAsciiText(result); } void ClipboardAura::ReadHTML(ClipboardType type, @@ -622,36 +606,36 @@ uint32_t* fragment_start, uint32_t* fragment_end) const { DCHECK(CalledOnValidThread()); - GetClipboard()->ReadHTML(markup, src_url, fragment_start, fragment_end); + clipboard_internal_->ReadHTML(markup, src_url, fragment_start, fragment_end); } void ClipboardAura::ReadRTF(ClipboardType type, std::string* result) const { DCHECK(CalledOnValidThread()); - GetClipboard()->ReadRTF(result); + clipboard_internal_->ReadRTF(result); } SkBitmap ClipboardAura::ReadImage(ClipboardType type) const { DCHECK(CalledOnValidThread()); - return GetClipboard()->ReadImage(); + return clipboard_internal_->ReadImage(); } void ClipboardAura::ReadCustomData(ClipboardType clipboard_type, const base::string16& type, base::string16* result) const { DCHECK(CalledOnValidThread()); - GetClipboard()->ReadCustomData(type, result); + clipboard_internal_->ReadCustomData(type, result); } void ClipboardAura::ReadBookmark(base::string16* title, std::string* url) const { DCHECK(CalledOnValidThread()); - GetClipboard()->ReadBookmark(title, url); + clipboard_internal_->ReadBookmark(title, url); } void ClipboardAura::ReadData(const FormatType& format, std::string* result) const { DCHECK(CalledOnValidThread()); - GetClipboard()->ReadData(format.ToString(), result); + clipboard_internal_->ReadData(format.ToString(), result); } void ClipboardAura::WriteObjects(ClipboardType type, const ObjectMap& objects) { @@ -659,7 +643,7 @@ DCHECK(IsSupportedClipboardType(type)); for (const auto& object : objects) DispatchObject(static_cast<ObjectType>(object.first), object.second); - ClipboardDataBuilder::CommitToClipboard(); + ClipboardDataBuilder::CommitToClipboard(clipboard_internal_.get()); } void ClipboardAura::WriteText(const char* text_data, size_t text_len) {
diff --git a/ui/base/clipboard/clipboard_aura.h b/ui/base/clipboard/clipboard_aura.h index dc65413..1d3b208 100644 --- a/ui/base/clipboard/clipboard_aura.h +++ b/ui/base/clipboard/clipboard_aura.h
@@ -13,10 +13,11 @@ namespace ui { +class AuraClipboard; + class ClipboardAura : public Clipboard { private: friend class Clipboard; - ClipboardAura(); ~ClipboardAura() override; @@ -60,6 +61,8 @@ const char* data_data, size_t data_len) override; + const std::unique_ptr<AuraClipboard> clipboard_internal_; + DISALLOW_COPY_AND_ASSIGN(ClipboardAura); };
diff --git a/ui/base/ime/chromeos/input_method_manager.h b/ui/base/ime/chromeos/input_method_manager.h index 4050381..2cb04e5 100644 --- a/ui/base/ime/chromeos/input_method_manager.h +++ b/ui/base/ime/chromeos/input_method_manager.h
@@ -214,9 +214,9 @@ // Switches the current input method (or keyboard layout) to the next one. virtual void SwitchToNextInputMethod() = 0; - // Switches the current input method (or keyboard layout) to the previous + // Switches the current input method (or keyboard layout) to the last used // one. - virtual void SwitchToPreviousInputMethod() = 0; + virtual void SwitchToLastUsedInputMethod() = 0; // Gets the descriptor of the input method which is currently selected. virtual InputMethodDescriptor GetCurrentInputMethod() const = 0;
diff --git a/ui/base/ime/chromeos/mock_ime_engine_handler.cc b/ui/base/ime/chromeos/mock_ime_engine_handler.cc index 413bb44..7d3144b 100644 --- a/ui/base/ime/chromeos/mock_ime_engine_handler.cc +++ b/ui/base/ime/chromeos/mock_ime_engine_handler.cc
@@ -77,6 +77,10 @@ const std::vector<gfx::Rect>& bounds) { } +void MockIMEEngineHandler::SetMirroringEnabled(bool mirroring_enabled) {} + +void MockIMEEngineHandler::SetCastingEnabled(bool casting_enabled) {} + bool MockIMEEngineHandler::ClearComposition(int context_id, std::string* error) { return false;
diff --git a/ui/base/ime/chromeos/mock_ime_engine_handler.h b/ui/base/ime/chromeos/mock_ime_engine_handler.h index 805e562..001ec7a4 100644 --- a/ui/base/ime/chromeos/mock_ime_engine_handler.h +++ b/ui/base/ime/chromeos/mock_ime_engine_handler.h
@@ -35,6 +35,8 @@ uint32_t anchor_pos, uint32_t offset_pos) override; void SetCompositionBounds(const std::vector<gfx::Rect>& bounds) override; + void SetMirroringEnabled(bool mirroring_enabled) override; + void SetCastingEnabled(bool casting_enabled) override; int focus_in_call_count() const { return focus_in_call_count_; } int focus_out_call_count() const { return focus_out_call_count_; }
diff --git a/ui/base/ime/chromeos/mock_input_method_manager.cc b/ui/base/ime/chromeos/mock_input_method_manager.cc index f39e3d9..cad118e 100644 --- a/ui/base/ime/chromeos/mock_input_method_manager.cc +++ b/ui/base/ime/chromeos/mock_input_method_manager.cc
@@ -79,7 +79,7 @@ void MockInputMethodManager::State::SwitchToNextInputMethod() {} -void MockInputMethodManager::State::SwitchToPreviousInputMethod() {} +void MockInputMethodManager::State::SwitchToLastUsedInputMethod() {} InputMethodDescriptor MockInputMethodManager::State::GetCurrentInputMethod() const {
diff --git a/ui/base/ime/chromeos/mock_input_method_manager.h b/ui/base/ime/chromeos/mock_input_method_manager.h index 6bd58cc..fb6c4131 100644 --- a/ui/base/ime/chromeos/mock_input_method_manager.h +++ b/ui/base/ime/chromeos/mock_input_method_manager.h
@@ -53,7 +53,7 @@ void SetInputMethodLoginDefaultFromVPD(const std::string& locale, const std::string& layout) override; void SwitchToNextInputMethod() override; - void SwitchToPreviousInputMethod() override; + void SwitchToLastUsedInputMethod() override; InputMethodDescriptor GetCurrentInputMethod() const override; bool ReplaceEnabledInputMethods( const std::vector<std::string>& new_active_input_method_ids) override;
diff --git a/ui/base/ime/ime_engine_handler_interface.h b/ui/base/ime/ime_engine_handler_interface.h index fdca0ee..f437af5 100644 --- a/ui/base/ime/ime_engine_handler_interface.h +++ b/ui/base/ime/ime_engine_handler_interface.h
@@ -162,6 +162,10 @@ // Hides the input view window (from API call). virtual void HideInputView() = 0; + // Sets the mirroring/casting enable states. + virtual void SetMirroringEnabled(bool mirroring_enabled) = 0; + virtual void SetCastingEnabled(bool casting_enabled) = 0; + #elif defined(OS_LINUX) || defined(OS_WIN) // Get the id of the IME extension.
diff --git a/ui/base/l10n/l10n_util_unittest.cc b/ui/base/l10n/l10n_util_unittest.cc index 66bddc5..167b32c 100644 --- a/ui/base/l10n/l10n_util_unittest.cc +++ b/ui/base/l10n/l10n_util_unittest.cc
@@ -51,13 +51,7 @@ class L10nUtilTest : public PlatformTest { }; -#if defined(OS_ANDROID) -// TODO(http://crbug.com/911191): Android resources don't load properly. -#define MAYBE_GetString DISABLED_GetString -#else -#define MAYBE_GetString GetString -#endif -TEST_F(L10nUtilTest, MAYBE_GetString) { +TEST_F(L10nUtilTest, GetString) { std::string s = l10n_util::GetStringUTF8(IDS_SIMPLE); EXPECT_EQ(std::string("Hello World!"), s);
diff --git a/ui/base/resource/resource_bundle_android.cc b/ui/base/resource/resource_bundle_android.cc index 5fdfaea..6686f17a 100644 --- a/ui/base/resource/resource_bundle_android.cc +++ b/ui/base/resource/resource_bundle_android.cc
@@ -83,13 +83,13 @@ base::FilePath disk_path; base::PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID, &disk_path); disk_path = disk_path.AppendASCII("chrome_100_percent.pak"); - if (LoadFromApkOrFile("assets/chrome_100_percent.pak", - &disk_path, - &g_chrome_100_percent_fd, - &g_chrome_100_percent_region)) { - AddDataPackFromFileRegion(base::File(g_chrome_100_percent_fd), - g_chrome_100_percent_region, SCALE_FACTOR_100P); - } + bool success = + LoadFromApkOrFile("assets/chrome_100_percent.pak", &disk_path, + &g_chrome_100_percent_fd, &g_chrome_100_percent_region); + DCHECK(success); + + AddDataPackFromFileRegion(base::File(g_chrome_100_percent_fd), + g_chrome_100_percent_region, SCALE_FACTOR_100P); } // static
diff --git a/ui/base/test/run_all_unittests.cc b/ui/base/test/run_all_unittests.cc index 3eb24c2..0383e55 100644 --- a/ui/base/test/run_all_unittests.cc +++ b/ui/base/test/run_all_unittests.cc
@@ -67,7 +67,7 @@ // resources built in. On Android, ui_base_unittests_apk provides the // necessary framework. ui::ResourceBundle::InitSharedInstanceWithLocale( - "en-US", NULL, ui::ResourceBundle::LOAD_COMMON_RESOURCES); + "en-US", NULL, ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES); #else // On other platforms, the (hardcoded) paths for chrome_100_percent.pak and @@ -83,10 +83,12 @@ base::PathService::Override(ui::DIR_LOCALES, assets_path.AppendASCII("ui")); #endif -#if !defined(OS_ANDROID) base::FilePath dir_resources; bool result; -#if defined(OS_MACOSX) || defined(OS_IOS) +#if defined(OS_ANDROID) + result = + base::PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID, &dir_resources); +#elif defined(OS_MACOSX) || defined(OS_IOS) result = base::PathService::Get(base::DIR_MODULE, &dir_resources); #else dir_resources = assets_path; @@ -97,7 +99,6 @@ dir_resources.Append(FILE_PATH_LITERAL("ui_base_test_resources.pak")); ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath( ui_base_test_resources_pak, ui::SCALE_FACTOR_NONE); -#endif // !defined(OS_ANDROID) } void UIBaseTestSuite::Shutdown() {
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc index 548c51dc..73a1b48 100644 --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc
@@ -59,14 +59,6 @@ const base::Feature kSystemKeyboardLock{"SystemKeyboardLock", base::FEATURE_ENABLED_BY_DEFAULT}; -const base::Feature kTouchableAppContextMenu = { - "EnableTouchableAppContextMenu", base::FEATURE_ENABLED_BY_DEFAULT}; - -bool IsTouchableAppContextMenuEnabled() { - return base::FeatureList::IsEnabled(kTouchableAppContextMenu) || - switches::IsTouchableAppContextMenuEnabled(); -} - const base::Feature kNotificationIndicator = { "EnableNotificationIndicator", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h index 2a3e2546..0da6ef6d 100644 --- a/ui/base/ui_base_features.h +++ b/ui/base/ui_base_features.h
@@ -24,11 +24,9 @@ #endif // defined(OS_CHROMEOS) UI_BASE_EXPORT extern const base::Feature kInputMethodSettingsUiUpdate; UI_BASE_EXPORT extern const base::Feature kSystemKeyboardLock; -UI_BASE_EXPORT extern const base::Feature kTouchableAppContextMenu; UI_BASE_EXPORT extern const base::Feature kNotificationIndicator; UI_BASE_EXPORT extern const base::Feature kUiCompositorScrollWithLayers; -UI_BASE_EXPORT bool IsTouchableAppContextMenuEnabled(); UI_BASE_EXPORT bool IsNotificationIndicatorEnabled(); UI_BASE_EXPORT bool IsUiGpuRasterizationEnabled();
diff --git a/ui/chromeos/BUILD.gn b/ui/chromeos/BUILD.gn index 7c4de18..0282601 100644 --- a/ui/chromeos/BUILD.gn +++ b/ui/chromeos/BUILD.gn
@@ -69,6 +69,7 @@ ":chromeos", "//base/test:test_support", "//chromeos", + "//chromeos:chromeos_buildflags", "//mojo/core/embedder", "//skia", "//testing/gtest",
diff --git a/ui/chromeos/run_all_unittests.cc b/ui/chromeos/run_all_unittests.cc index bc4c83cd..6b56127 100644 --- a/ui/chromeos/run_all_unittests.cc +++ b/ui/chromeos/run_all_unittests.cc
@@ -10,6 +10,7 @@ #include "base/path_service.h" #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" +#include "chromeos/chromeos_buildflags.h" #include "mojo/core/embedder/embedder.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/env.h" @@ -17,6 +18,11 @@ #include "ui/base/ui_base_paths.h" #include "ui/gl/test/gl_surface_test_support.h" +#if BUILDFLAG(IS_CROS_CHROME_SDK) +#error This test target only builds with linux-chromeos, not cros chrome-sdk.\ + See comment in build/config/chromeos/rules.gni. +#endif + namespace { class UIChromeOSTestSuite : public base::TestSuite {
diff --git a/ui/file_manager/BUILD.gn b/ui/file_manager/BUILD.gn index 9749301..a0c3ecd 100644 --- a/ui/file_manager/BUILD.gn +++ b/ui/file_manager/BUILD.gn
@@ -59,6 +59,7 @@ "base/js:unit_tests", "file_manager/background/js:unit_tests", "file_manager/common/js:unit_tests", + "file_manager/foreground/elements:unit_tests", "file_manager/foreground/js:unit_tests", "file_manager/foreground/js/metadata:unit_tests", "file_manager/foreground/js/ui:unit_tests",
diff --git a/ui/file_manager/base/js/filtered_volume_manager.js b/ui/file_manager/base/js/filtered_volume_manager.js index 3694590..c23228d 100644 --- a/ui/file_manager/base/js/filtered_volume_manager.js +++ b/ui/file_manager/base/js/filtered_volume_manager.js
@@ -124,6 +124,7 @@ FilteredVolumeManager.prototype.isAllowedVolumeType_ = function(volumeType) { switch (this.allowedPaths_) { case AllowedPaths.ANY_PATH: + case AllowedPaths.ANY_PATH_OR_URL: return true; case AllowedPaths.NATIVE_OR_DRIVE_PATH: return (VolumeManagerCommon.VolumeType.isNative(volumeType) ||
diff --git a/ui/file_manager/base/js/volume_manager_types.js b/ui/file_manager/base/js/volume_manager_types.js index ab4eb07..1ff1cae 100644 --- a/ui/file_manager/base/js/volume_manager_types.js +++ b/ui/file_manager/base/js/volume_manager_types.js
@@ -15,7 +15,8 @@ var AllowedPaths = { NATIVE_PATH: 'nativePath', NATIVE_OR_DRIVE_PATH: 'nativeOrDrivePath', - ANY_PATH: 'anyPath' + ANY_PATH: 'anyPath', + ANY_PATH_OR_URL: 'anyPathOrUrl', }; /**
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css index fd34cb3..55bc7d1 100644 --- a/ui/file_manager/file_manager/foreground/css/file_manager.css +++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -1635,6 +1635,7 @@ } #share-menu cr-menu-item, +#share-sub-menu cr-menu-item, #tasks-menu cr-menu-item:not(.change-default) { background-position: left 10px center; padding-left: 32px; @@ -1673,7 +1674,8 @@ body[type='folder'] .file, body[type='upload-folder'] .file, -.dialog-container[connection='offline'] .dim-offline { +.dialog-container[connection='offline'] .dim-offline, +body[block-hosted-docs] .file.dim-hosted { opacity: 0.4; }
diff --git a/ui/file_manager/file_manager/foreground/elements/BUILD.gn b/ui/file_manager/file_manager/foreground/elements/BUILD.gn index b1ecbbc..d8e8fbb 100644 --- a/ui/file_manager/file_manager/foreground/elements/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/elements/BUILD.gn
@@ -3,10 +3,20 @@ # found in the LICENSE file. import("//third_party/closure_compiler/compile_js.gni") +import("//third_party/closure_compiler/js_unit_tests.gni") visibility = [ "//ui/file_manager/file_manager/foreground/*" ] -js_type_check("closure_compile") { +group("closure_compile") { + testonly = true + visibility += [ "//ui/file_manager:closure_compile" ] + deps = [ + ":closure_compile_module", + ":unit_tests_type_check", + ] +} + +js_type_check("closure_compile_module") { deps = [ ":files_icon_button", ":files_metadata_box", @@ -68,3 +78,16 @@ js_library("files_tooltip") { visibility += [ "//ui/file_manager/gallery/*" ] } + +js_unittest("files_tooltip_unittest") { + deps = [ + ":files_tooltip", + "//ui/file_manager/base/js:test_error_reporting", + ] +} + +js_unit_tests("unit_tests") { + deps = [ + ":files_tooltip_unittest", + ] +}
diff --git a/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.html b/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.html index 07e5bcf..4548367 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.html +++ b/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.html
@@ -4,43 +4,6 @@ -- found in the LICENSE file. --> -<!-- Since resources under chrome://resources are not accessible from unittest, - -- we need to load them with relative paths. --> -<link rel="import" href="../../../../../third_party/polymer/v1_0/components-chromium/polymer/polymer.html"> -<link rel="import" href="files_tooltip.html"> - -<style type="text/css"> - button { - display: flex; - height: 32px; - margin: 30px; - width: 32px; - } - - #container { - display: flex; - justify-content: space-between; - } - - files-tooltip { - background: yellow; - box-sizing: border-box; - position: absolute; - text-align: center; - width: 100px; - } -</style> - -<div id="container"> - <button id="chocolate" aria-label="Chocolate!"></button> - <button id="cherries" aria-label="Cherries!"></button> -</div> - -<!-- Button without a tooltip. --> -<button id="other"></button> - -<files-tooltip></files-tooltip> - <script src="../../../../webui/resources/js/assert.js"></script> <script src="../../../../webui/resources/js/util.js"></script> <script src="../../../base/js/test_error_reporting.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.js b/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.js index 7b25e8e7..9f260d3 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.js +++ b/ui/file_manager/file_manager/foreground/elements/files_tooltip_unittest.js
@@ -2,11 +2,98 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +/** @const {Array<string>} */ +const testPage = [ + '<style type="text/css">', + ' button {', + ' display: flex;', + ' height: 32px;', + ' margin: 30px;', + ' width: 32px;', + ' }', + '', + ' #container {', + ' display: flex;', + ' justify-content: space-between;', + ' }', + '', + ' files-tooltip {', + ' background: yellow;', + ' box-sizing: border-box;', + ' position: absolute;', + ' text-align: center;', + ' width: 100px;', + ' }', + '</style>', + '', + '<!-- Targets for tooltip testing. -->', + '<div id="container">', + ' <button id="chocolate" aria-label="Chocolate!"></button>', + ' <button id="cherries" aria-label="Cherries!"></button>', + '</div>', + '', + '<!-- Button without a tooltip. -->', + '<button id="other"></button>', + '', + '<!-- Polymer files tooltip element. -->', + '<files-tooltip></files-tooltip>', + '', +]; + +/** @type {Element} */ var chocolateButton; + +/** @type {Element} */ var cherriesButton; + +/** @type {Element} */ var otherButton; + +/** @type {FilesTooltip|Element} */ var tooltip; +function setUpPage() { + console.log('setUpPage'); + + const importElements = (src) => { + var link = document.createElement('link'); + link.rel = 'import'; + link.onload = onLinkLoaded; + document.head.appendChild(link); + const sourceRoot = '../../../../../../../../'; + link.href = sourceRoot + src; + }; + + let linksLoaded = 0; + + const onLinkLoaded = () => { + if (++linksLoaded < 2) + return; + document.body.innerHTML += testPage.join('\n'); + window.waitUser = false; + }; + + const polymer = + 'third_party/polymer/v1_0/components-chromium/polymer/polymer.html'; + importElements(polymer); + + const filesTooltip = + 'ui/file_manager/file_manager/foreground/elements/files_tooltip.html'; + importElements(filesTooltip); + + // Make the test harness pause until out test page is fully loaded. + window.waitUser = true; +} + +function setUp() { + chocolateButton = document.querySelector('#chocolate'); + cherriesButton = document.querySelector('#cherries'); + otherButton = document.querySelector('#other'); + + tooltip = document.querySelector('files-tooltip'); + tooltip.addTargets([chocolateButton, cherriesButton]); +} + function waitForMutation(target) { return new Promise(function(fulfill, reject) { var observer = new MutationObserver(function(mutations) { @@ -17,14 +104,6 @@ }); } -function setUp() { - chocolateButton = document.querySelector('#chocolate'); - cherriesButton = document.querySelector('#cherries'); - otherButton = document.querySelector('#other'); - tooltip = document.querySelector('files-tooltip'); - tooltip.addTargets([chocolateButton, cherriesButton]); -} - function testFocus(callback) { chocolateButton.focus();
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn index cb6f7b5..83607dc 100644 --- a/ui/file_manager/file_manager/foreground/js/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -485,6 +485,15 @@ ] } +js_unittest("list_thumbnail_loader_unittest") { + deps = [ + ":list_thumbnail_loader", + ":mock_thumbnail_loader", + "//ui/file_manager/base/js:test_error_reporting", + "//ui/file_manager/file_manager/common/js:mock_entry", + ] +} + js_library("main") { deps = [ ":file_manager", @@ -748,6 +757,7 @@ ":actions_model_unittest", ":file_list_model_unittest", ":file_tasks_unittest", + ":list_thumbnail_loader_unittest", ":navigation_list_model_unittest", ":progress_center_item_group_unittest", ":providers_model_unittest",
diff --git a/ui/file_manager/file_manager/foreground/js/constants.js b/ui/file_manager/file_manager/foreground/js/constants.js index a74e4ae..7e0cb67 100644 --- a/ui/file_manager/file_manager/foreground/js/constants.js +++ b/ui/file_manager/file_manager/foreground/js/constants.js
@@ -36,6 +36,7 @@ constants.FILE_SELECTION_METADATA_PREFETCH_PROPERTY_NAMES = [ 'availableOffline', 'contentMimeType', + 'hosted', ]; /**
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager.js b/ui/file_manager/file_manager/foreground/js/file_manager.js index a9ebd48c..af5237f 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager.js
@@ -1089,10 +1089,11 @@ this.folderShortcutsModel_ = new FolderShortcutsDataModel( this.volumeManager_); + assert(this.launchParams_); this.selectionHandler_ = new FileSelectionHandler( assert(this.directoryModel_), assert(this.fileOperationManager_), assert(this.ui_.listContainer), assert(this.metadataModel_), - assert(this.volumeManager_)); + assert(this.volumeManager_), this.launchParams_.allowedPaths); this.directoryModel_.getFileListSelection().addEventListener('change', this.selectionHandler_.onFileSelectionChanged.bind( @@ -1159,7 +1160,6 @@ this.spinnerController_.blink(); // Create dialog action controller. - assert(this.launchParams_); this.dialogActionController_ = new DialogActionController( this.dialogType, this.ui_.dialogFooter,
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js index 2887c1e6..ef51c51 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -1369,6 +1369,29 @@ }); /** + * Displays any available (child) sub menu for current selection. + * @type {Command} + */ +CommandHandler.COMMANDS_['show-submenu'] = /** @type {Command} */ ({ + /** + * @param {!Event} event Command event. + * @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use. + */ + execute: function(event, fileManager) { + fileManager.ui.shareMenuButton.showSubMenu(); + }, + /** + * @param {!Event} event Command event. + * @param {!CommandHandlerDeps} fileManager CommandHandlerDeps to use. + */ + canExecute: function(event, fileManager) { + var canExecute = fileManager.taskController.canExecuteShowOverflow(); + event.canExecute = canExecute; + event.command.setHidden(!canExecute); + } +}); + +/** * Displays QuickView for current selection. * @type {Command} */
diff --git a/ui/file_manager/file_manager/foreground/js/file_selection.js b/ui/file_manager/file_manager/foreground/js/file_selection.js index 77c6bfb..5ef0eb0 100644 --- a/ui/file_manager/file_manager/foreground/js/file_selection.js +++ b/ui/file_manager/file_manager/foreground/js/file_selection.js
@@ -45,7 +45,12 @@ /** * @public {boolean} */ - this.allFilesPresent = false; + this.anyFilesNotInCache = true; + + /** + * @public {boolean} + */ + this.anyFilesHosted = true; /** * @public {?string} @@ -87,7 +92,11 @@ // If no availableOffline property, then assume it's available. return !('availableOffline' in p) || p.availableOffline; }); - this.allFilesPresent = present.length === props.length; + const hosted = props.filter(function(p) { + return p.hosted; + }); + this.anyFilesNotInCache = present.length !== props.length; + this.anyFilesHosted = !!hosted.length; this.mimeTypes = props.map(function(value) { return value.contentMimeType || ''; }); @@ -105,13 +114,14 @@ * @param {!ListContainer} listContainer * @param {!MetadataModel} metadataModel * @param {!VolumeManager} volumeManager + * @param {!AllowedPaths} allowedPaths * @extends {cr.EventTarget} * @constructor * @struct */ function FileSelectionHandler( directoryModel, fileOperationManager, listContainer, metadataModel, - volumeManager) { + volumeManager, allowedPaths) { cr.EventTarget.call(this); /** @@ -153,6 +163,12 @@ */ this.lastFileSelectionTime_ = Date.now(); + /** + * @private {AllowedPaths} + * @const + */ + this.allowedPaths_ = allowedPaths; + util.addEventListenerToBackgroundComponent( assert(fileOperationManager), 'entries-changed', this.onFileSelectionChanged.bind(this)); @@ -262,13 +278,39 @@ }; /** - * Returns whether all the selected files are available currently or not. - * Should be called after the selection initialized. + * Returns true if all files in the selection files are selectable. * @return {boolean} */ FileSelectionHandler.prototype.isAvailable = function() { - return !this.directoryModel_.isOnDrive() || - this.volumeManager_.getDriveConnectionState().type !== - VolumeManagerCommon.DriveConnectionType.OFFLINE || - this.selection.allFilesPresent; + if (!this.directoryModel_.isOnDrive()) { + return true; + } + + return !( + this.isOfflineWithUncachedFilesSelected_() || + this.isDialogWithHostedFilesSelected_()); +}; + + +/** + * Returns true if we're offline with any selected files absent from the cache. + * @return {boolean} + * @private + */ +FileSelectionHandler.prototype.isOfflineWithUncachedFilesSelected_ = + function() { + return this.volumeManager_.getDriveConnectionState().type === + VolumeManagerCommon.DriveConnectionType.OFFLINE && + this.selection.anyFilesNotInCache; +}; + +/** + * Returns true if we're a dialog requiring real files with hosted files + * selected. + * @return {boolean} + * @private + */ +FileSelectionHandler.prototype.isDialogWithHostedFilesSelected_ = function() { + return this.allowedPaths_ !== AllowedPaths.ANY_PATH_OR_URL && + this.selection.anyFilesHosted; };
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks.js b/ui/file_manager/file_manager/foreground/js/file_tasks.js index 80950ff8..fca454d 100644 --- a/ui/file_manager/file_manager/foreground/js/file_tasks.js +++ b/ui/file_manager/file_manager/foreground/js/file_tasks.js
@@ -1048,7 +1048,7 @@ * options menu. * * @param {!cr.ui.ComboButton} openCombobutton The open task picker combobutton. - * @param {!cr.ui.MenuButton} shareMenuButton The menu button for share options. + * @param {!cr.ui.MultiMenuButton} shareMenuButton Button for share options. * @public */ FileTasks.prototype.display = function(openCombobutton, shareMenuButton) { @@ -1111,25 +1111,51 @@ }; /** + * The number of menu-item entries in the top level menu + * before we split and show the 'More actions' option + * @const {number} + */ +const NUM_TOP_LEVEL_ENTRIES = 6; +/** + * Don't split the menu if the number of entries is smaller + * than this. e.g. with 7 entries it'd be poor to show a + * sub-menu with a single entry. + * @const {number} + */ +const MAX_NON_SPLIT_ENTRIES = 10; + +/** * Setup a menu button for sharing options based on the given tasks. - * @param {!cr.ui.MenuButton} shareMenuButton + * @param {!cr.ui.MultiMenuButton} shareMenuButton * @param {!Array<!chrome.fileManagerPrivate.FileTask>} tasks */ FileTasks.prototype.updateShareMenuButton_ = function(shareMenuButton, tasks) { - var driveShareCommand = + let driveShareCommand = shareMenuButton.menu.querySelector('cr-menu-item[command="#share"]'); - var driveShareCommandSeparator = + let driveShareCommandSeparator = shareMenuButton.menu.querySelector('#drive-share-separator'); + let moreActionsSeparator = + shareMenuButton.menu.querySelector('#more-actions-separator'); // Hide share icon for New Folder creation. See https://crbug.com/571355. shareMenuButton.hidden = (driveShareCommand.disabled && tasks.length == 0) || this.namingController_.isRenamingInProgress(); + moreActionsSeparator.hidden = true; // Show the separator if Drive share command is enabled and there is at least // one other share actions. driveShareCommandSeparator.hidden = driveShareCommand.disabled || tasks.length == 0; + // Temporarily remove the more actions item while the rest of the menu + // items are being cleared out so we don't lose it and make it hidden for now + let moreActions = shareMenuButton.menu.querySelector( + 'cr-menu-item[command="#show-submenu"]'); + moreActions.remove(); + moreActions.setAttribute('hidden', ''); + // Remove the separator as well + moreActionsSeparator.remove(); + // Clear menu items except for drive share menu and a separator for it. // As querySelectorAll() returns live NodeList, we need to copy elements to // Array object to modify DOM in the for loop. @@ -1139,11 +1165,25 @@ var item = itemsToRemove[i]; item.parentNode.removeChild(item); } + // Clear menu items in the overflow sub-menu since we'll repopulate it + // with any relevant items below. + if (shareMenuButton.overflow !== null) { + while (shareMenuButton.overflow.firstChild !== null) { + shareMenuButton.overflow.removeChild(shareMenuButton.overflow.firstChild); + } + } // Add menu items for the new tasks. var items = this.createItems_(tasks); + let menu = shareMenuButton.menu; for (var i = 0; i < items.length; i++) { - var menuitem = shareMenuButton.menu.addMenuItem(items[i]); + // If we have at least 10 entries, split off into a sub-menu + if (i == NUM_TOP_LEVEL_ENTRIES && MAX_NON_SPLIT_ENTRIES <= items.length) { + moreActions.removeAttribute('hidden'); + moreActionsSeparator.hidden = false; + menu = shareMenuButton.overflow; + } + var menuitem = menu.addMenuItem(items[i]); cr.ui.decorate(menuitem, cr.ui.FilesMenuItem); menuitem.data = items[i]; if (items[i].iconType) { @@ -1151,6 +1191,9 @@ menuitem.setAttribute('file-type-icon', items[i].iconType); } } + // Replace the more actions menu item and separator + shareMenuButton.menu.appendChild(moreActionsSeparator); + shareMenuButton.menu.appendChild(moreActions); }; /**
diff --git a/ui/file_manager/file_manager/foreground/js/launch_param.js b/ui/file_manager/file_manager/foreground/js/launch_param.js index 47f121a..43ab710 100644 --- a/ui/file_manager/file_manager/foreground/js/launch_param.js +++ b/ui/file_manager/file_manager/foreground/js/launch_param.js
@@ -65,7 +65,8 @@ * @const */ this.allowedPaths = unformatted['allowedPaths'] ? - unformatted['allowedPaths'] : AllowedPaths.ANY_PATH; + unformatted['allowedPaths'] : + AllowedPaths.ANY_PATH_OR_URL; /** * @type {!SuggestAppDialogState}
diff --git a/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.html b/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.html deleted file mode 100644 index 89b9e2b..0000000 --- a/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.html +++ /dev/null
@@ -1,24 +0,0 @@ -<!DOCTYPE html> -<!-- 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. - --> - -<script src="../../../../webui/resources/js/assert.js"></script> -<script src="../../../../webui/resources/js/cr.js"></script> -<script src="../../../../webui/resources/js/cr/event_target.js"></script> -<script src="../../../../webui/resources/js/cr/ui.js"></script> -<script src="../../../../webui/resources/js/cr/ui/array_data_model.js"></script> -<script src="../../common/js/file_type.js"></script> -<script src="../../common/js/lru_cache.js"></script> -<script src="../../common/js/util.js"></script> -<script src="../../common/js/mock_entry.js"></script> -<script src="../../../base/js/test_error_reporting.js"></script> -<script src="../../../base/js/volume_manager_types.js"></script> -<script src="directory_contents.js"></script> -<script src="file_list_model.js"></script> -<script src="thumbnail_loader.js"></script> -<script src="mock_thumbnail_loader.js"></script> -<script src="list_thumbnail_loader.js"></script> - -<script src="list_thumbnail_loader_unittest.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.js b/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.js index 1482b0e0..b73cbf9f 100644 --- a/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/list_thumbnail_loader_unittest.js
@@ -2,92 +2,121 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/** - * Generates a data url of a sample image for testing. - * TODO(yawano) Consider to share image generation logic with - * gallery/js/image_editor/test_util.js. - * - * @param {Document} document Document. - * @return {string} Data url of a sample image. - */ -function generateSampleImageDataUrl(document) { - var canvas = document.createElement('canvas'); - canvas.width = 160; - canvas.height = 160; - - var context = canvas.getContext('2d'); - context.fillStyle = 'black'; - context.fillRect(0, 0, 80, 80); - context.fillRect(80, 80, 80, 80); - - return canvas.toDataURL('image/jpeg', 0.5); -} - -var listThumbnailLoader; -var getCallbacks; -var thumbnailLoadedEvents; -var thumbnailModel; -var metadataModel; -var fileListModel; -var directoryModel; +/** @type {string} */ var currentVolumeType; -var isScanningForTest = false; + +/** @type {!ListThumbnailLoader} */ +var listThumbnailLoader; + +/** @type {!Object} */ +var getCallbacks; + +/** @type {!Array<Event>} */ +var thumbnailLoadedEvents; + +/** @type {!ThumbnailModel} */ +var thumbnailModel; + +/** @type {!MetadataModel} */ +var metadataModel; + +/** @type {!FileListModel} */ +var fileListModel; + +/** @type {!DirectoryModel} */ +var directoryModel; + +/** @type {boolean} */ +var isScanningForTest; + +/** @type {!MockFileSystem} */ var fileSystem = new MockFileSystem('volume-id'); + +/** @type {!MockDirectoryEntry} */ var directory1 = new MockDirectoryEntry(fileSystem, '/TestDirectory'); + +/** @type {!MockEntry} */ var entry1 = new MockEntry(fileSystem, '/Test1.jpg'); +/** @type {!MockEntry} */ var entry2 = new MockEntry(fileSystem, '/Test2.jpg'); +/** @type {!MockEntry} */ var entry3 = new MockEntry(fileSystem, '/Test3.jpg'); +/** @type {!MockEntry} */ var entry4 = new MockEntry(fileSystem, '/Test4.jpg'); +/** @type {!MockEntry} */ var entry5 = new MockEntry(fileSystem, '/Test5.jpg'); +/** @type {!MockEntry} */ var entry6 = new MockEntry(fileSystem, '/Test6.jpg'); function setUp() { currentVolumeType = ListThumbnailLoader.TEST_VOLUME_TYPE; + /** @suppress {const} */ ListThumbnailLoader.CACHE_SIZE = 5; + /** @suppress {const} */ ListThumbnailLoader.numOfMaxActiveTasksForTest = 2; + + /** @suppress {const} */ MockThumbnailLoader.errorUrls = []; - MockThumbnailLoader.testImageDataUrl = generateSampleImageDataUrl(document); + /** @suppress {const} */ MockThumbnailLoader.testImageWidth = 160; + /** @suppress {const} */ MockThumbnailLoader.testImageHeight = 160; + // Create an image dataURL for testing. + var canvas = document.createElement('canvas'); + canvas.width = MockThumbnailLoader.testImageWidth; + canvas.height = MockThumbnailLoader.testImageHeight; + var context = canvas.getContext('2d'); + context.fillStyle = 'black'; + context.fillRect(0, 0, 80, 80); + context.fillRect(80, 80, 80, 80); + /** @const {string} */ + var testImageDataUrl = canvas.toDataURL('image/jpeg', 0.5); + + /** @suppress {const} */ + MockThumbnailLoader.testImageDataUrl = testImageDataUrl; + getCallbacks = {}; - thumbnailModel = { + + thumbnailModel = /** @type {!ThumbnailModel} */ ({ get: function(entries) { return new Promise(function(fulfill) { getCallbacks[getKeyOfGetCallback_(entries)] = fulfill; }); - } - }; + }, + }); - metadataModel = { + metadataModel = /** @type {!MetadataModel} */ ({ get: function() {}, getCache: function(entries, names) { return [{}]; - } - }; + }, + }); fileListModel = new FileListModel(metadataModel); - directoryModel = { + isScanningForTest = false; + + directoryModel = /** @type {!DirectoryModel} */ ({ __proto__: cr.EventTarget.prototype, getFileList: function() { return fileListModel; }, isScanning: function() { return isScanningForTest; - } - }; + }, + }); + + var fakeVolumeManager = /** @type {!VolumeManager} */ ({ + getVolumeInfo: function(entry) { + return { + volumeType: currentVolumeType, + }; + }, + }); listThumbnailLoader = new ListThumbnailLoader( - directoryModel, - thumbnailModel, - // Mocking volume manager - { - getVolumeInfo: function(entry) { - return { volumeType: currentVolumeType }; - } - }, - MockThumbnailLoader); + directoryModel, thumbnailModel, fakeVolumeManager, MockThumbnailLoader); thumbnailLoadedEvents = []; listThumbnailLoader.addEventListener('thumbnailLoaded', function(event) { @@ -366,24 +395,24 @@ function testExifIOError(callback) { var task = new ListThumbnailLoader.Task( entry1, - // Mocking volume manager. - { + /** @type {!VolumeManager} */ ({ getVolumeInfo: function(entry) { - return { volumeType: currentVolumeType }; - } - }, - // Mocking thumbnail model. - { + return { + volumeType: currentVolumeType + }; + }, + }), + /** @type {!ThumbnailModel} */ ({ get: function(entries) { return Promise.resolve([{ thumbnail: { urlError: { errorDescription: 'Error: Unexpected EOF @0' - } - } + }, + }, }]); - } - }, + }, + }), function() { // Thumbnails should be fetched only from EXIF on IO error. assertTrue(false);
diff --git a/ui/file_manager/file_manager/foreground/js/main_scripts.js b/ui/file_manager/file_manager/foreground/js/main_scripts.js index 224b199..60990b54 100644 --- a/ui/file_manager/file_manager/foreground/js/main_scripts.js +++ b/ui/file_manager/file_manager/foreground/js/main_scripts.js
@@ -174,6 +174,7 @@ // <include src="ui/list_container.js"> // <include src="ui/location_line.js"> // <include src="ui/multi_profile_share_dialog.js"> +// <include src="ui/multi_menu.js"> // <include src="ui/progress_center_panel.js"> // <include src="ui/providers_menu.js"> // <include src="ui/search_box.js">
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn b/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn index 484fd96..fa2e8ae 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn
@@ -55,6 +55,13 @@ ] } +js_unittest("content_metadata_provider_unittest") { + deps = [ + ":content_metadata_provider", + "//ui/file_manager/base/js:test_error_reporting", + ] +} + js_library("exif_constants") { } @@ -62,11 +69,18 @@ deps = [ ":exif_constants", ":image_parsers", - ":metadata_parser", ] externs_list = [ "../../../../externs/exif_entry.js" ] } +js_unittest("exif_parser_unittest") { + deps = [ + ":exif_parser", + "//ui/file_manager/base/js:test_error_reporting", + "//ui/file_manager/gallery/js/image_editor:exif_encoder", + ] +} + js_library("external_metadata_provider") { deps = [ ":metadata_provider", @@ -79,6 +93,13 @@ ] } +js_unittest("file_system_metadata_provider_unittest") { + deps = [ + ":file_system_metadata_provider", + "//ui/file_manager/base/js:test_error_reporting", + ] +} + js_library("function_parallel") { deps = [ ":metadata_parser", @@ -142,6 +163,13 @@ ] } +js_unittest("metadata_cache_set_unittest") { + deps = [ + ":metadata_cache_set", + "//ui/file_manager/base/js:test_error_reporting", + ] +} + js_library("metadata_dispatcher") { deps = [ ":metadata_parser", @@ -165,6 +193,13 @@ ] } +js_unittest("metadata_model_unittest") { + deps = [ + ":metadata_model", + "//ui/file_manager/base/js:test_error_reporting", + ] +} + js_library("metadata_parser") { deps = [ ":byte_reader", @@ -204,6 +239,13 @@ ] } +js_unittest("multi_metadata_provider_unittest") { + deps = [ + ":multi_metadata_provider", + "//ui/file_manager/base/js:test_error_reporting", + ] +} + js_library("thumbnail_model") { deps = [ ":metadata_model", @@ -220,8 +262,14 @@ js_unit_tests("unit_tests") { deps = [ + ":content_metadata_provider_unittest", + ":exif_parser_unittest", + ":file_system_metadata_provider_unittest", ":image_orientation_unittest", ":metadata_cache_item_unittest", + ":metadata_cache_set_unittest", + ":metadata_model_unittest", + ":multi_metadata_provider_unittest", ":thumbnail_model_unittest", ] }
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.html b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.html deleted file mode 100644 index 66638da..0000000 --- a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.html +++ /dev/null
@@ -1,22 +0,0 @@ -<!DOCTYPE html> -<!-- 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. - --> -<!-- Base classes --> -<script src="../../../../../webui/resources/js/cr.js"></script> -<script src="../../../../../webui/resources/js/cr/event_target.js"></script> -<script src="metadata_cache_set.js"></script> -<script src="metadata_provider.js"></script> -<script src="metadata_request.js"></script> - -<!-- Others --> -<script src="../../../../../webui/resources/js/assert.js"></script> -<script src="../../../common/js/lru_cache.js"></script> -<script src="../../../../base/js/test_error_reporting.js"></script> -<script src="../../../common/js/file_type.js"></script> -<script src="content_metadata_provider.js"></script> -<script src="metadata_cache_item.js"></script> -<script src="metadata_item.js"></script> - -<script src="content_metadata_provider_unittest.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.js index 9fe9618..acfba873 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/content_metadata_provider_unittest.js
@@ -58,25 +58,25 @@ function testExternalMetadataProviderBasic(callback) { // Mocking SharedWorker's port. - var port = { + var port = /** @type {!MessagePort} */ ({ postMessage: function(message) { if (message.verb === 'request') { - this.onmessage({ + port.onmessage(/** @type {!MessageEvent} */ ({ data: { verb: 'result', arguments: [ - message.arguments[0], - { + message.arguments[0], { thumbnailURL: message.arguments[0] + ',url', thumbnailTransform: message.arguments[0] + ',transform' } ] } - }); + })); } }, start: function() {} - }; + }); + // TODO(ryoh): chrome.mediaGalleries API is not available in unit tests. var provider = new ContentMetadataProvider(port); reportPromise(provider.get([
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.html b/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.html deleted file mode 100644 index 0d96a8b..0000000 --- a/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.html +++ /dev/null
@@ -1,20 +0,0 @@ -<!DOCTYPE html> -<!-- 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. - --> - -<script type="text/javascript"> - function importScripts(script) {} -</script> - -<script src="../../../../gallery/js/image_editor/image_encoder.js"></script> -<script src="../../../../gallery/js/image_editor/exif_encoder.js"></script> - -<script src="metadata_dispatcher.js"></script> -<script src="metadata_parser.js"></script> -<script src="byte_reader.js"></script> -<script src="exif_constants.js"></script> -<script src="exif_parser.js"></script> - -<script src="exif_parser_unittest.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.js index eefe242..89291eb 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/exif_parser_unittest.js
@@ -3,8 +3,42 @@ // found in the LICENSE file. /** + * Parser unittest BUILD rules may cause script(s) under test to load, and call + * dependent script methods, before the dependent scripts have loaded. Fix this + * by creating fakes to avoid any undefined call exceptions, then synchronously + * reload the affected script(s). + */ +window.addEventListener( + 'load', /** @type {Function} */ (async () => { + // Fake parser importScripts calls. + window.importScripts = (script) => {}; + + // Fake metadata dispatcher parser registry. + window.registerParserClass = (parser) => {}; + + // Reload an existing <script> element. + let reloadScript = (src) => { + let element = document.querySelector('script[src$="' + src + '"]'); + if (!(element instanceof HTMLScriptElement)) + return Promise.reject('reloading script: ' + src + ' not found'); + element.remove(); + return new Promise((resolve, reject) => { + let script = document.createElement('script'); + script.onload = resolve; + script.onerror = reject; + document.body.appendChild(script); + script.src = element.src; + }); + }; + + await Promise.all([ + reloadScript('exif_parser.js'), + ]); + })); + +/** * Creates a directory with specified tag. This method only supports string - * format tag which is longer than 4 characters. + * format tag, which is longer than 4 characters. * @param {!TypedArray} bytes Bytes to be written. * @param {!ExifEntry} tag An exif entry which will be written. */ @@ -12,7 +46,7 @@ assertEquals(2, tag.format); assertTrue(tag.componentCount > 4); - var byteWriter = new ByteWriter(bytes.buffer, 0); + let byteWriter = new ByteWriter(bytes.buffer, 0); byteWriter.writeScalar(1, 2); // Number of fields. byteWriter.writeScalar(tag.id, 2); @@ -23,45 +57,46 @@ byteWriter.writeScalar(0, 4); // Offset to next IFD. byteWriter.resolveOffset(tag.id); - byteWriter.writeString(tag.value); + const string = /** @type {string} */ (tag.value); + byteWriter.writeString(string); byteWriter.checkResolved(); } /** - * Parses exif data and return parsed tags. + * Parses exif data bytes (with logging) and returns the parsed tags. * @param {!TypedArray} bytes Bytes to be read. * @return {!Object<!Exif.Tag, !ExifEntry>} Tags. */ function parseExifData_(bytes) { - var exifParser = new ExifParser(this); + let exifParser = new ExifParser(this); exifParser.log = function(arg) { console.log(arg); }; exifParser.vlog = function(arg) { console.log(arg); }; - var tags = {}; - var byteReader = new ByteReader(bytes.buffer); + let tags = {}; + let byteReader = new ByteReader(bytes.buffer); assertEquals(0, exifParser.readDirectory(byteReader, tags)); return tags; } /** - * Test case a string doest not end with null character termination. + * Tests that parsed exif strings have a null character termination. */ function testWithoutNullCharacterTermination() { - // Create a data which doesn't end with null character. - var bytes = new Uint8Array(0x10000); - writeDirectory_(bytes, { - id: 0x10f, // Manufacture. - format: 2, // String. - componentCount: 11, - value: 'Manufacture' - }); + // Create exif with a value that does not end with null character. + let data = new Uint8Array(0x10000); + writeDirectory_(data, /** @type {!ExifEntry} */ ({ + id: 0x10f, // Manufacturer Id. + format: 2, // String format. + componentCount: 8, // Length of value 'Manufact'. + value: 'Manufact', + })); - // Parse the data. - var tags = parseExifData_(bytes); + // Parse the exif data. + const tags = parseExifData_(data); - // Null character should be added at the end of value. - var manufactureTag = tags[0x10f]; - assertEquals(12, manufactureTag.componentCount); - assertEquals('Manufacture\0', manufactureTag.value); + // The parsed value should end in a null character. + const parsedTag = tags[/** @type {!Exif.Tag<number>} */ (0x10f)]; + assertEquals(9, parsedTag.componentCount); + assertEquals('Manufact\0', parsedTag.value); }
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.html b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.html deleted file mode 100644 index 7136ed0..0000000 --- a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!DOCTYPE html> -<!-- 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. - --> -<!-- Base classes --> -<script src="../../../../../webui/resources/js/cr.js"></script> -<script src="../../../../../webui/resources/js/cr/event_target.js"></script> -<script src="metadata_cache_set.js"></script> -<script src="metadata_provider.js"></script> - -<!-- Others --> -<script src="../../../../../webui/resources/js/assert.js"></script> -<script src="../../../common/js/lru_cache.js"></script> -<script src="../../../../base/js/test_error_reporting.js"></script> -<script src="file_system_metadata_provider.js"></script> -<script src="metadata_cache_item.js"></script> -<script src="metadata_item.js"></script> -<script src="metadata_request.js"></script> - -<script src="file_system_metadata_provider_unittest.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.js index 4ed6af4..75b5d51 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/file_system_metadata_provider_unittest.js
@@ -2,21 +2,27 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -var entryA = { - toURL: function() { return "filesystem://A"; }, +/** @const {!Entry} */ +const entryA = /** @type {!Entry} */ ({ + toURL: function() { + return "filesystem://A"; + }, getMetadata: function(fulfill, reject) { Promise.resolve({modificationTime: new Date(2015, 1, 1), size: 1024}).then( fulfill, reject); } -}; +}); -var entryB = { - toURL: function() { return "filesystem://B"; }, +/** @const {!Entry} */ +const entryB = /** @type {!Entry} */ ({ + toURL: function() { + return "filesystem://B"; + }, getMetadata: function(fulfill, reject) { Promise.resolve({modificationTime: new Date(2015, 2, 2), size: 2048}).then( fulfill, reject); } -}; +}); function testFileSystemMetadataProviderBasic(callback) { var provider = new FileSystemMetadataProvider(); @@ -32,14 +38,14 @@ new Date(2015, 1, 1).toString(), results[0].modificationTime.toString()); assertEquals(1024, results[0].size); - assertTrue(results[0].present); - assertTrue(results[0].availableOffline); + assertTrue(!!results[0].present); + assertTrue(!!results[0].availableOffline); assertEquals( new Date(2015, 2, 2).toString(), results[1].modificationTime.toString()); assertEquals(2048, results[1].size); - assertTrue(results[1].present); - assertTrue(results[1].availableOffline); + assertTrue(!!results[1].present); + assertTrue(!!results[1].availableOffline); }), callback); }
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.html b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.html deleted file mode 100644 index b697c34..0000000 --- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.html +++ /dev/null
@@ -1,20 +0,0 @@ -<!DOCTYPE html> -<!-- 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. - --> - -<!-- Base class --> -<script src="../../../../../webui/resources/js/cr.js"></script> -<script src="../../../../../webui/resources/js/cr/event_target.js"></script> - -<!-- Others --> -<script src="../../../../../webui/resources/js/assert.js"></script> -<script src="../../../../base/js/test_error_reporting.js"></script> -<script src="../../../common/js/util.js"></script> -<script src="metadata_cache_item.js"></script> -<script src="metadata_cache_set.js"></script> -<script src="metadata_item.js"></script> -<script src="metadata_request.js"></script> - -<script src="metadata_cache_set_unittest.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.js index 1653b267..7347746 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_cache_set_unittest.js
@@ -2,17 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -const entryA = { +/** @const {!Entry} */ +const entryA = /** @type {!Entry} */ ({ toURL: function() { return 'filesystem://A'; - } -}; + }, +}); -const entryB = { +/** @const {!Entry} */ +const entryB = /** @type {!Entry} */ ({ toURL: function() { return 'filesystem://B'; - } -}; + }, +}); function testMetadataCacheSetBasic() { var set = new MetadataCacheSet(new MetadataCacheSetStorageForObject({})); @@ -27,7 +29,7 @@ set.startRequests(1, loadRequested); assertTrue(set.storeProperties( - 1, [entryA, entryB], [{property: 'valueA'}, {property: 'valueB'}])); + 1, [entryA, entryB], [{property: 'valueA'}, {property: 'valueB'}], [])); var results = set.get([entryA, entryB], ['property']); assertEquals(2, results.length); @@ -39,15 +41,13 @@ var set = new MetadataCacheSet(new MetadataCacheSetStorageForObject({})); set.startRequests(1, set.createRequests([entryA, entryB], ['property'])); - assertTrue(set.storeProperties( - 1, [entryA], [{property: 'valueA'}])); + assertTrue(set.storeProperties(1, [entryA], [{property: 'valueA'}], [])); var results = set.get([entryA, entryB], ['property']); assertEquals(2, results.length); assertEquals('valueA', results[0].property); assertEquals(null, results[1].property); - assertTrue(set.storeProperties( - 1, [entryB], [{property: 'valueB'}])); + assertTrue(set.storeProperties(1, [entryB], [{property: 'valueB'}], [])); var results = set.get([entryA, entryB], ['property']); assertEquals(2, results.length); assertEquals('valueA', results[0].property); @@ -57,7 +57,7 @@ function testMetadataCacheSetCachePartial() { var set = new MetadataCacheSet(new MetadataCacheSetStorageForObject({})); set.startRequests(1, set.createRequests([entryA], ['property'])); - set.storeProperties(1, [entryA], [{property: 'valueA'}]); + set.storeProperties(1, [entryA], [{property: 'valueA'}], []); // entryA has already been cached. var loadRequested = set.createRequests([entryA, entryB], ['property']); @@ -73,7 +73,7 @@ set.invalidate(2, [entryA]); assertTrue(set.storeProperties( - 1, [entryA, entryB], [{property: 'valueA'}, {property: 'valueB'}])); + 1, [entryA, entryB], [{property: 'valueA'}, {property: 'valueB'}], [])); var results = set.get([entryA, entryB], ['property']); assertEquals(2, results.length); @@ -92,14 +92,14 @@ setA.startRequests(1, setA.createRequests([entryA, entryB], ['property'])); var setB = setA.createSnapshot([entryA]); setA.storeProperties( - 1, [entryA, entryB], [{property: 'valueA'}, {property: 'valueB'}]); + 1, [entryA, entryB], [{property: 'valueA'}, {property: 'valueB'}], []); var results = setB.get([entryA, entryB], ['property']); assertEquals(2, results.length); assertEquals(null, results[0].property); assertEquals(undefined, results[1].property); setB.storeProperties( - 1, [entryA, entryB], [{property: 'valueA'}, {property: 'valueB'}]); + 1, [entryA, entryB], [{property: 'valueA'}, {property: 'valueB'}], []); var results = setB.get([entryA, entryB], ['property']); assertEquals(2, results.length); assertEquals('valueA', results[0].property); @@ -118,7 +118,7 @@ set.startRequests(1, set.createRequests([entryA, entryB], ['property'])); set.storeProperties( - 1, [entryA, entryB], [{property: 'valueA'}, {property: 'valueB'}]); + 1, [entryA, entryB], [{property: 'valueA'}, {property: 'valueB'}], []); assertTrue(set.hasFreshCache([entryA, entryB], ['property'])); set.invalidate(2, [entryB]); @@ -135,13 +135,13 @@ function testMetadataCacheSetClear() { var set = new MetadataCacheSet(new MetadataCacheSetStorageForObject({})); set.startRequests(1, set.createRequests([entryA], ['propertyA'])); - set.storeProperties(1, [entryA], [{propertyA: 'value'}]); + set.storeProperties(1, [entryA], [{propertyA: 'value'}], []); assertTrue(set.hasFreshCache([entryA], ['propertyA'])); set.startRequests(1, set.createRequests([entryA], ['propertyB'])); set.clear([entryA.toURL()]); // PropertyB should not be stored because it is requsted before clear. - set.storeProperties(1, [entryA], [{propertyB: 'value'}]); + set.storeProperties(1, [entryA], [{propertyB: 'value'}], []); assertFalse(set.hasFreshCache([entryA], ['propertyA'])); assertFalse(set.hasFreshCache([entryA], ['propertyB'])); @@ -154,7 +154,7 @@ event = inEvent; }); set.startRequests(1, set.createRequests([entryA], ['propertyA'])); - set.storeProperties(1, [entryA], [{propertyA: 'value'}]); + set.storeProperties(1, [entryA], [{propertyA: 'value'}], []); assertEquals(1, event.entries.length); assertEquals(entryA, event.entries[0]); assertTrue(event.entriesMap.has(entryA.toURL())); @@ -166,7 +166,7 @@ var set = new MetadataCacheSet(new MetadataCacheSetStorageForObject({})); set.startRequests(1, set.createRequests([entryA, entryB], ['propertyA'])); set.storeProperties( - 1, [entryA, entryB], [{propertyA: 'value'}, {propertyA: 'value'}]); + 1, [entryA, entryB], [{propertyA: 'value'}, {propertyA: 'value'}], []); assertTrue(set.hasFreshCache([entryA, entryB], ['propertyA'])); set.clearAll();
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.html b/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.html deleted file mode 100644 index 3906cb1..0000000 --- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.html +++ /dev/null
@@ -1,22 +0,0 @@ -<!DOCTYPE html> -<!-- 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. - --> -<!-- Base class --> -<script src="../../../../../webui/resources/js/cr.js"></script> -<script src="../../../../../webui/resources/js/cr/event_target.js"></script> -<script src="metadata_cache_set.js"></script> - -<!-- Others --> -<script src="../../../../../webui/resources/js/assert.js"></script> -<script src="../../../common/js/lru_cache.js"></script> -<script src="../../../../base/js/test_error_reporting.js"></script> -<script src="../../../common/js/util.js"></script> -<script src="metadata_cache_item.js"></script> -<script src="metadata_item.js"></script> -<script src="metadata_model.js"></script> -<script src="metadata_provider.js"></script> -<script src="metadata_request.js"></script> - -<script src="metadata_model_unittest.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.js index 4e980b6..a5e22f4 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/metadata_model_unittest.js
@@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +/** + * TestMetadataProvider + * @constructor + * @extends {MetadataProvider} + */ function TestMetadataProvider() { MetadataProvider.call(this, ['property', 'propertyA', 'propertyB']); this.requestCount = 0; @@ -22,6 +27,11 @@ })); }; +/** + * TestEmptyMetadataProvider + * @constructor + * @extends {MetadataProvider} + */ function TestEmptyMetadataProvider() { MetadataProvider.call(this, ['property']); } @@ -34,9 +44,13 @@ })); }; +/** + * ManualTestMetadataProvider + * @constructor + * @extends {MetadataProvider} + */ function ManualTestMetadataProvider() { - MetadataProvider.call( - this, ['propertyA', 'propertyB', 'propertyC']); + MetadataProvider.call(this, ['propertyA', 'propertyB', 'propertyC']); this.callback = []; } @@ -48,125 +62,205 @@ }.bind(this)); }; -var entryA = { - toURL: function() { return "filesystem://A"; } -}; +/** @type {!Entry} */ +var entryA = /** @type {!Entry} */ ({ + toURL: function() { + return 'filesystem://A'; + }, +}); -var entryB = { - toURL: function() { return "filesystem://B"; } -}; +/** @type {!Entry} */ +var entryB = /** @type {!Entry} */ ({ + toURL: function() { + return 'filesystem://B'; + }, +}); + +/** + * Returns a property of a Metadata result object. + * @param {Object} result Metadata result + * @param {string} property Property name to return. + * @return {string} + */ +function getProperty(result, property) { + if (!result) + throw new Error('Fail: Metadata result is undefined'); + return result[property]; +} function testMetadataModelBasic(callback) { - var model = new MetadataModel(new TestMetadataProvider()); - reportPromise(model.get([entryA, entryB], ['property']).then( - function(results) { - assertEquals(1, model.getProvider().requestCount); - assertEquals('filesystem://A:property', results[0].property); - assertEquals('filesystem://B:property', results[1].property); - }), callback); + var provider = new TestMetadataProvider(); + var model = new MetadataModel(provider); + + reportPromise( + model.get([entryA, entryB], ['property']).then(function(results) { + provider = /** @type {!TestMetadataProvider} */ (model.getProvider()); + assertEquals(1, provider.requestCount); + assertEquals( + 'filesystem://A:property', getProperty(results[0], 'property')); + assertEquals( + 'filesystem://B:property', getProperty(results[1], 'property')); + }), + callback); } function testMetadataModelRequestForCachedProperty(callback) { - var model = new MetadataModel(new TestMetadataProvider()); - reportPromise(model.get([entryA, entryB], ['property']).then( - function() { - // All the result should be cached here. - return model.get([entryA, entryB], ['property']); - }).then(function(results) { - assertEquals(1, model.getProvider().requestCount); - assertEquals('filesystem://A:property', results[0].property); - assertEquals('filesystem://B:property', results[1].property); - }), callback); + var provider = new TestMetadataProvider(); + var model = new MetadataModel(provider); + + reportPromise( + model.get([entryA, entryB], ['property']) + .then(function() { + // All the results should be cached here. + return model.get([entryA, entryB], ['property']); + }) + .then(function(results) { + provider = + /** @type {!TestMetadataProvider} */ (model.getProvider()); + assertEquals(1, provider.requestCount); + assertEquals( + 'filesystem://A:property', getProperty(results[0], 'property')); + assertEquals( + 'filesystem://B:property', getProperty(results[1], 'property')); + }), + callback); } function testMetadataModelRequestForCachedAndNonCachedProperty(callback) { - var model = new MetadataModel(new TestMetadataProvider()); - reportPromise(model.get([entryA, entryB], ['propertyA']).then( - function() { - assertEquals(1, model.getProvider().requestCount); - // propertyB has not been cached here. - return model.get([entryA, entryB], ['propertyA', 'propertyB']); - }).then(function(results) { - assertEquals(2, model.getProvider().requestCount); - assertEquals('filesystem://A:propertyA', results[0].propertyA); - assertEquals('filesystem://A:propertyB', results[0].propertyB); - assertEquals('filesystem://B:propertyA', results[1].propertyA); - assertEquals('filesystem://B:propertyB', results[1].propertyB); - }), callback); + var provider = new TestMetadataProvider(); + var model = new MetadataModel(provider); + + reportPromise( + model.get([entryA, entryB], ['propertyA']) + .then(function() { + provider = + /** @type {!TestMetadataProvider} */ (model.getProvider()); + assertEquals(1, provider.requestCount); + // propertyB has not been cached here. + return model.get([entryA, entryB], ['propertyA', 'propertyB']); + }) + .then(function(results) { + provider = + /** @type {!TestMetadataProvider} */ (model.getProvider()); + assertEquals(2, provider.requestCount); + assertEquals( + 'filesystem://A:propertyA', + getProperty(results[0], 'propertyA')); + assertEquals( + 'filesystem://A:propertyB', + getProperty(results[0], 'propertyB')); + assertEquals( + 'filesystem://B:propertyA', + getProperty(results[1], 'propertyA')); + assertEquals( + 'filesystem://B:propertyB', + getProperty(results[1], 'propertyB')); + }), + callback); } function testMetadataModelRequestForCachedAndNonCachedEntry(callback) { - var model = new MetadataModel(new TestMetadataProvider()); - reportPromise(model.get([entryA], ['property']).then( - function() { - assertEquals(1, model.getProvider().requestCount); - // entryB has not been cached here. - return model.get([entryA, entryB], ['property']); - }).then(function(results) { - assertEquals(2, model.getProvider().requestCount); - assertEquals('filesystem://A:property', results[0].property); - assertEquals('filesystem://B:property', results[1].property); - }), callback); + var provider = new TestMetadataProvider(); + var model = new MetadataModel(provider); + + reportPromise( + model.get([entryA], ['property']) + .then(function() { + provider = + /** @type {!TestMetadataProvider} */ (model.getProvider()); + assertEquals(1, provider.requestCount); + // entryB has not been cached here. + return model.get([entryA, entryB], ['property']); + }) + .then(function(results) { + provider = + /** @type {!TestMetadataProvider} */ (model.getProvider()); + assertEquals(2, provider.requestCount); + assertEquals( + 'filesystem://A:property', getProperty(results[0], 'property')); + assertEquals( + 'filesystem://B:property', getProperty(results[1], 'property')); + }), + callback); } -function testMetadataModelRequestBeforeCompletingPreviousRequest( - callback) { - var model = new MetadataModel(new TestMetadataProvider()); +function testMetadataModelRequestBeforeCompletingPreviousRequest(callback) { + var provider = new TestMetadataProvider(); + var model = new MetadataModel(provider); + model.get([entryA], ['property']); - assertEquals(1, model.getProvider().requestCount); + provider = /** @type {!TestMetadataProvider} */ (model.getProvider()); + assertEquals(1, provider.requestCount); + // The result of first call has not been fetched yet. - reportPromise(model.get([entryA], ['property']).then( - function(results) { - assertEquals(1, model.getProvider().requestCount); - assertEquals('filesystem://A:property', results[0].property); - }), callback); + reportPromise( + model.get([entryA], ['property']).then(function(results) { + provider = /** @type {!TestMetadataProvider} */ (model.getProvider()); + assertEquals(1, provider.requestCount); + assertEquals( + 'filesystem://A:property', getProperty(results[0], 'property')); + }), + callback); } -function testMetadataModelNotUpdateCachedResultAfterRequest( - callback) { - var model = new MetadataModel(new ManualTestMetadataProvider()); +function testMetadataModelNotUpdateCachedResultAfterRequest(callback) { + var provider = new ManualTestMetadataProvider(); + var model = new MetadataModel(provider); + var promise = model.get([entryA], ['propertyA']); - model.getProvider().callback[0]([{propertyA: 'valueA1'}]); + provider = /** @type {!ManualTestMetadataProvider} */ (model.getProvider()); + provider.callback[0]([{propertyA: 'valueA1'}]); + reportPromise(promise.then(function() { // 'propertyA' is cached here. var promise1 = model.get([entryA], ['propertyA', 'propertyB']); var promise2 = model.get([entryA], ['propertyC']); // Returns propertyC. - model.getProvider().callback[2]( - [{propertyA: 'valueA2', propertyC: 'valueC'}]); - model.getProvider().callback[1]([{propertyB: 'valueB'}]); + provider = /** @type {!ManualTestMetadataProvider} */ (model.getProvider()); + provider.callback[2]([{propertyA: 'valueA2', propertyC: 'valueC'}]); + provider.callback[1]([{propertyB: 'valueB'}]); return Promise.all([promise1, promise2]); }).then(function(results) { // The result should be cached value at the time when get was called. - assertEquals('valueA1', results[0][0].propertyA); - assertEquals('valueB', results[0][0].propertyB); - assertEquals('valueC', results[1][0].propertyC); + assertEquals('valueA1', getProperty(results[0][0], 'propertyA')); + assertEquals('valueB', getProperty(results[0][0], 'propertyB')); + assertEquals('valueC', getProperty(results[1][0], 'propertyC')); }), callback); } function testMetadataModelGetCache(callback) { - var model = new MetadataModel(new TestMetadataProvider()); + var provider = new TestMetadataProvider(); + var model = new MetadataModel(provider); + var promise = model.get([entryA], ['property']); var cache = model.getCache([entryA], ['property']); - assertEquals(null, cache[0].property); + assertEquals(null, getProperty(cache[0], 'property')); + reportPromise(promise.then(function() { var cache = model.getCache([entryA], ['property']); - assertEquals(1, model.getProvider().requestCount); - assertEquals('filesystem://A:property', cache[0].property); + provider = /** @type {!TestMetadataProvider} */ (model.getProvider()); + assertEquals(1, provider.requestCount); + assertEquals('filesystem://A:property', getProperty(cache[0], 'property')); }), callback); } function testMetadataModelUnknownProperty() { - var model = new MetadataModel(new TestMetadataProvider()); + var provider = new TestMetadataProvider(); + var model = new MetadataModel(provider); + assertThrows(function() { model.get([entryA], ['unknown']); }); } function testMetadataModelEmptyResult(callback) { - var model = new MetadataModel(new TestEmptyMetadataProvider()); + var provider = new TestEmptyMetadataProvider(); + var model = new MetadataModel(provider); + // getImpl returns empty result. - reportPromise(model.get([entryA], ['property']).then(function(results) { - assertEquals(undefined, results[0].property); - }), callback); + reportPromise( + model.get([entryA], ['property']).then(function(results) { + assertEquals(undefined, getProperty(results[0], 'property')); + }), + callback); }
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.html b/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.html deleted file mode 100644 index 13875ba..0000000 --- a/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!DOCTYPE html> -<!-- 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. - --> -<!-- Base classes --> -<script src="../../../../../webui/resources/js/cr.js"></script> -<script src="../../../../../webui/resources/js/cr/event_target.js"></script> -<script src="metadata_cache_set.js"></script> -<script src="metadata_provider.js"></script> -<script src="metadata_request.js"></script> - -<!-- Others --> -<script src="../../../../../webui/resources/js/assert.js"></script> -<script src="../../../common/js/lru_cache.js"></script> -<script src="../../../../base/js/test_error_reporting.js"></script> -<script src="../../../../base/js/volume_manager_types.js"></script> -<script src="content_metadata_provider.js"></script> -<script src="external_metadata_provider.js"></script> -<script src="file_system_metadata_provider.js"></script> -<script src="metadata_cache_item.js"></script> -<script src="metadata_item.js"></script> -<script src="multi_metadata_provider.js"></script> - -<script src="multi_metadata_provider_unittest.js"></script>
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.js b/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.js index 1f367a8..77292d71 100644 --- a/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/metadata/multi_metadata_provider_unittest.js
@@ -2,41 +2,46 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -var entryA = { - toURL: function() { return 'filesystem://A'; } -}; +var entryA = /** @type {!Entry} */ ({ + toURL: function() { + return 'filesystem://A'; + }, +}); -var entryB = { - toURL: function() { return 'filesystem://B'; } -}; +var entryB = /** @type {!Entry} */ ({ + toURL: function() { + return 'filesystem://B'; + }, +}); -var entryC = { - toURL: function() { return 'filesystem://C'; } -}; +var entryC = /** @type {!Entry} */ ({ + toURL: function() { + return 'filesystem://C'; + }, +}); -var volumeManager = { +var volumeManager = /** @type {!VolumeManager} */ ({ getVolumeInfo: function(entry) { if (entry.toURL() === 'filesystem://A') { return { - volumeType: VolumeManagerCommon.VolumeType.DOWNLOADS + volumeType: VolumeManagerCommon.VolumeType.DOWNLOADS, }; } else if (entry.toURL() === 'filesystem://B') { return { - volumeType: VolumeManagerCommon.VolumeType.DRIVE + volumeType: VolumeManagerCommon.VolumeType.DRIVE, }; } else if (entry.toURL() === 'filesystem://C') { return { - volumeType: VolumeManagerCommon.VolumeType.DRIVE + volumeType: VolumeManagerCommon.VolumeType.DRIVE, }; } assertNotReached(); } -}; +}); function testMultiMetadataProviderBasic(callback) { var model = new MultiMetadataProvider( - // Mocking FileSystemMetadataProvider. - { + /** @type {!FileSystemMetadataProvider} */ ({ get: function(requests) { assertEquals(1, requests.length); assertEquals('filesystem://A', requests[0].entry.toURL()); @@ -44,9 +49,8 @@ return Promise.resolve( [{modificationTime: new Date(2015, 0, 1), size: 1024}]); } - }, - // Mocking ExternalMetadataProvider. - { + }), + /** @type {!ExternalMetadataProvider} */ ({ get: function(requests) { assertEquals(1, requests.length); assertEquals('filesystem://B', requests[0].entry.toURL()); @@ -54,9 +58,8 @@ return Promise.resolve( [{modificationTime: new Date(2015, 1, 2), size: 2048}]); } - }, - // Mocking ContentMetadataProvider. - { + }), + /** @type {!ContentMetadataProvider} */ ({ get: function(requests) { if (requests.length === 0) return Promise.resolve([]); @@ -70,9 +73,9 @@ {contentThumbnailUrl: 'THUMBNAIL_URL_B'} ]); } - }, - // Mocking VolumeManager. + }), volumeManager); + reportPromise(model.get([ new MetadataRequest( entryA, ['size', 'modificationTime', 'contentThumbnailUrl']), @@ -95,15 +98,13 @@ function testMultiMetadataProviderExternalAndContentProperty(callback) { var model = new MultiMetadataProvider( - // Mocking FileSystemMetadataProvider. - { + /** @type {!FileSystemMetadataProvider} */ ({ get: function(requests) { assertEquals(0, requests.length); return Promise.resolve([]); } - }, - // Mocking ExternalMetadataProvider. - { + }), + /** @type {!ExternalMetadataProvider} */ ({ get: function(requests) { assertEquals(2, requests.length); assertEquals('filesystem://B', requests[0].entry.toURL()); @@ -115,23 +116,20 @@ {present: true, imageWidth: 400} ]); } - }, - // Mocking ContentMetadataProvider. - { + }), + /** @type {!ContentMetadataProvider} */ ({ get: function(requests) { + const results = { + 'filesystem://A': {imageWidth: 100}, + 'filesystem://C': {imageWidth: 300}, + }; assertEquals(1, requests.length); - assertTrue(requests[0].entry.toURL() in this.results_); - return Promise.resolve([ - this.results_[requests[0].entry.toURL()] - ]); + assertTrue(requests[0].entry.toURL() in results); + return Promise.resolve([results[requests[0].entry.toURL()]]); }, - results_: { - 'filesystem://A': {imageWidth: 100}, - 'filesystem://C': {imageWidth: 300} - } - }, - // Mocking VolumeManager. + }), volumeManager); + reportPromise(model.get([ new MetadataRequest(entryA, ['imageWidth']), new MetadataRequest(entryB, ['imageWidth']),
diff --git a/ui/file_manager/file_manager/foreground/js/task_controller.js b/ui/file_manager/file_manager/foreground/js/task_controller.js index 233c987..f734af2 100644 --- a/ui/file_manager/file_manager/foreground/js/task_controller.js +++ b/ui/file_manager/file_manager/foreground/js/task_controller.js
@@ -122,6 +122,14 @@ assertInstanceof(document.querySelector('#more-actions'), cr.ui.Command); /** + * Show sub menu command that uses #show-submenu as selector. + * @private {!cr.ui.Command} + * @const + */ + this.showSubMenuCommand_ = + assertInstanceof(document.querySelector('#show-submenu'), cr.ui.Command); + + /** * @private {Promise<!FileTasks>} */ this.tasks_ = null; @@ -142,6 +150,8 @@ 'select', this.onTaskItemClicked_.bind(this)); ui.shareMenuButton.menu.addEventListener( 'activate', this.onTaskItemClicked_.bind(this)); + ui.shareSubMenu.addEventListener( + 'activate', this.onTaskItemClicked_.bind(this)); this.selectionHandler_.addEventListener( FileSelectionHandler.EventType.CHANGE, this.onSelectionChanged_.bind(this)); @@ -401,6 +411,15 @@ }; /** + * Returns whether open with command can be executed or not. + * @return {boolean} True if open with command is executable. + */ +TaskController.prototype.canExecuteShowOverflow = function() { + // TODO (adanilo@) same logic as more actions now, extend + return this.canExecuteMoreActions_; +}; + +/** * Updates tasks menu item to match passed task items. * * @param {!Array<!Object>} openTasks List of OPEN tasks.
diff --git a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.js b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.js index bc054bf5..1673596 100644 --- a/ui/file_manager/file_manager/foreground/js/task_controller_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/task_controller_unittest.js
@@ -31,9 +31,6 @@ callback(false); }, }, - fileManagerPrivate: { - // Test cases set this object as needed. - }, runtime: { id: 'test-extension-id', lastError: null, @@ -51,6 +48,7 @@ }, }; + setupFileManagerPrivate(); installMockChrome(mockChrome); // Install cr.ui <command> elements on the page. @@ -58,6 +56,7 @@ '<command id="default-task">', '<command id="open-with">', '<command id="more-actions">', + '<command id="show-submenu">', ].join(''); // Initialize cr.ui.Command with the <command>s. @@ -93,6 +92,7 @@ fileContextMenu: { defaultActionMenuItem: document.createElement('div'), }, + shareSubMenu: document.createElement('div'), speakA11yMessage: text => {}, }), new MockMetadataModel({}), @@ -101,8 +101,7 @@ }), fileSelectionHandler, /** @type {!MetadataUpdateController} */ ({}), - /** @type {!NamingController} */ ({}), - createCrostiniForTest()); + /** @type {!NamingController} */ ({}), createCrostiniForTest()); return taskController; } @@ -166,9 +165,8 @@ * Tests that executeEntryTask() runs the expected task. */ function testExecuteEntryTask(callback) { - setupFileManagerPrivate(); - var selectionHandler = new MockFileSelectionHandler(); + var fileSystem = new MockFileSystem('volumeId'); fileSystem.entries['/test.png'] = new MockFileEntry(fileSystem, '/test.png'); var taskController = createTaskController(selectionHandler); @@ -190,9 +188,8 @@ * multiple times when the selected entries are not changed. */ function testGetFileTasksShouldNotBeCalledMultipleTimes(callback) { - setupFileManagerPrivate(); - var selectionHandler = new MockFileSelectionHandler(); + var fileSystem = new MockFileSystem('volumeId'); selectionHandler.updateSelection( [new MockFileEntry(fileSystem, '/test.png')], ['image/png']); @@ -228,9 +225,8 @@ * called. */ function testGetFileTasksShouldNotReturnObsoletePromise(callback) { - setupFileManagerPrivate(); - var selectionHandler = new MockFileSelectionHandler(); + var fileSystem = new MockFileSystem('volumeId'); selectionHandler.updateSelection( [new MockFileEntry(fileSystem, '/test.png')], ['image/png']); @@ -260,9 +256,8 @@ * the getFileTasks() promise to reject. */ function testGetFileTasksShouldNotCacheRejectedPromise(callback) { - setupFileManagerPrivate(); - var selectionHandler = new MockFileSelectionHandler(); + var fileSystem = new MockFileSystem('volumeId'); selectionHandler.updateSelection( [new MockFileEntry(fileSystem, '/test.png')], ['image/png']);
diff --git a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn index 3e554d0..a160281 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
@@ -44,6 +44,7 @@ ":install_linux_package_dialog", ":list_container", ":location_line", + ":multi_menu", ":multi_profile_share_dialog", ":progress_center_panel", ":providers_menu", @@ -154,6 +155,18 @@ ] } +js_unittest("directory_tree_unittest") { + deps = [ + ":directory_tree", + "//ui/file_manager/base/js:mock_chrome", + "//ui/file_manager/base/js:test_error_reporting", + "//ui/file_manager/file_manager/background/js:mock_volume_manager", + "//ui/file_manager/file_manager/foreground/js:mock_directory_model", + "//ui/file_manager/file_manager/foreground/js:mock_folder_shortcut_data_model", + "//ui/file_manager/file_manager/foreground/js:mock_navigation_list_model", + ] +} + js_library("drag_selector") { deps = [ "//ui/webui/resources/js/cr:ui", @@ -229,6 +242,7 @@ ":install_linux_package_dialog", ":list_container", ":location_line", + ":multi_menu", ":multi_profile_share_dialog", ":progress_center_panel", ":providers_menu", @@ -356,6 +370,14 @@ ] } +js_library("multi_menu") { + deps = [ + "//ui/webui/resources/js:event_tracker", + "//ui/webui/resources/js/cr/ui:menu", + "//ui/webui/resources/js/cr/ui:menu_item", + ] +} + js_library("multi_profile_share_dialog") { deps = [ ":file_manager_dialog_base", @@ -417,6 +439,7 @@ js_unit_tests("unit_tests") { deps = [ ":actions_submenu_unittest", + ":directory_tree_unittest", ":file_list_selection_model_unittest", ":file_table_unittest", ":file_tap_handler_unittest",
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.html b/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.html deleted file mode 100644 index 236761a4..0000000 --- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.html +++ /dev/null
@@ -1,43 +0,0 @@ -<!DOCTYPE html> -<!-- Copyright 2014 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. - --> - -<html> -<body> - <script src="../../../../../../ui/webui/resources/js/cr.js"></script> - <script src="../../../../../../ui/webui/resources/js/cr/event_target.js"></script> - <script src="../../../../../../ui/webui/resources/js/cr/ui.js"></script> - <script src="../../../../../../ui/webui/resources/js/cr/ui/array_data_model.js"></script> - <script src="../../../../../../ui/webui/resources/js/cr/ui/tree.js"></script> - <script src="../../../../../../ui/webui/resources/js/load_time_data.js"></script> - <script src="../../../../../../ui/webui/resources/js/assert.js"></script> - <script src="../../../../../../ui/webui/resources/js/util.js"></script> - - <script src="../../../common/js/async_util.js"></script> - <script src="../../../common/js/mock_entry.js"></script> - <script src="../../../../base/js/test_error_reporting.js"></script> - <script src="../../../../base/js/mock_chrome.js"></script> - <script src="../../../common/js/unittest_util.js"></script> - <script src="../../../common/js/files_app_entry_types.js"></script> - <script src="../../../common/js/util.js"></script> - <script src="../../../../base/js/volume_manager_types.js"></script> - - <script src="../../../background/js/entry_location_impl.js"></script> - <script src="../../../background/js/volume_info_impl.js"></script> - <script src="../../../background/js/volume_info_list_impl.js"></script> - <script src="../../../background/js/volume_manager_factory.js"></script> - <script src="../../../background/js/volume_manager_impl.js"></script> - <script src="../../../background/js/volume_manager_util.js"></script> - <script src="../../../background/js/mock_volume_manager.js"></script> - <script src="../mock_directory_model.js"></script> - <script src="../mock_navigation_list_model.js"></script> - <script src="../mock_folder_shortcut_data_model.js"></script> - <script src="../navigation_list_model.js"></script> - <script src="../constants.js"></script> - <script src="directory_tree.js"></script> - - <script src="directory_tree_unittest.js"></script> -</body> -</html>
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js index 1edf08f7..2a3d6ad 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree_unittest.js
@@ -2,64 +2,113 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -var chrome; -var mockCommandLinePrivate; -var metrics; -var onDirectoryChangedListeners; +/** @type {!MockVolumeManager} */ +var volumeManager; +/** @type {!DirectoryModel} */ +var directoryModel; + +/** @type {!MetadataModel} */ +var metadataModel; + +/** @type {!FileOperationManager} */ +var fileOperationManager; + +/** @type {!Array} */ +var directoryChangedListeners; + +/** @type {!Object<string,!MockDirectoryEntry>} */ +var fakeFileSystemURLEntries; + +/** + * Mock metrics. + * @type {!Object} + */ +window.metrics = { + recordSmallCount: function() {}, +}; + +/** + * Mock Chrome APIs + * @type {!Object} + */ +var mockChrome; + +// Set up test components. function setUp() { + // Mock LoadTimeData strings. window.loadTimeData.getString = id => id; window.loadTimeData.data = {}; - chrome = { + + // Setup mock chrome APIs. + directoryChangedListeners = []; + mockChrome = { fileManagerPrivate: { onDirectoryChanged: { - addListener: function(listener) { - onDirectoryChangedListeners.push(listener); - } - } - } + addListener: (listener) => { + directoryChangedListeners.push(listener); + }, + }, + }, }; - onDirectoryChangedListeners = []; - mockCommandLinePrivate = new MockCommandLinePrivate(); + installMockChrome(mockChrome); + new MockCommandLinePrivate(); - metrics = {recordSmallCount: function() {}}; + // Setup mock components. + volumeManager = new MockVolumeManager(); + directoryModel = new MockDirectoryModel(); + metadataModel = /** @type {!MetadataModel} */ ({}); + fileOperationManager = /** @type {!FileOperationManager} */ ({ + addEventListener: (name, callback) => {}, + }); - window.webkitResolveLocalFileSystemURLEntries = {}; - window.webkitResolveLocalFileSystemURL = function(url, callback) { - callback(webkitResolveLocalFileSystemURLEntries[url]); + // Setup fake file system URL resolver. + fakeFileSystemURLEntries = {}; + window.webkitResolveLocalFileSystemURL = (url, callback) => { + callback(fakeFileSystemURLEntries[url]); }; } /** - * Creates a plain object that can be used as mock for MetadataModel. + * Creates the DOM element structure of the directory tree and returns the + * directory tree DOM element from within that structure. + * @return {!HTMLElement} */ -function mockMetadataModel() { - const mock = { +function createElements() { + let parent = document.createElement('div'); + let tree = document.createElement('div'); + parent.appendChild(tree); + return /** @type {!HTMLElement} */ (tree); +} + +/** + * Returns a mock MetadataModel. + * @return {!MetadataModel} + */ +function createMockMetadataModel() { + return /** @type {!MetadataModel} */ ({ notifyEntriesChanged: () => {}, - get: function(entries, labels) { - // Mock a non-shared directory. + // get and getCache mock a non-shared directory. + get: (entries, labels) => { return Promise.resolve([{shared: false}]); }, - getCache: function(entries, labels) { + getCache: (entries, labels) => { return [{shared: false}]; }, - }; - return mock; + }); } /** - * Returns item labels of a directory tree as a list. + * Returns the directory tree item labels. * - * @param {DirectoryTree} directoryTree A directory tree. - * @return {Array<string>} List of labels. + * @param {!DirectoryTree} directoryTree The directory tree object. + * @return {!Array<string>} Array of label strings. */ -function getDirectoryTreeItemLabelsAsAList(directoryTree) { - var result = []; - for (var i = 0; i < directoryTree.items.length; i++) { - var item = directoryTree.items[i]; - result.push(item.label); - } - return result; +function getDirectoryTreeItemLabels(directoryTree) { + let labels = []; + for (let item of directoryTree.items) + labels.push(item.label); + return labels; } /** @@ -76,27 +125,20 @@ * test result. */ function testCreateDirectoryTree(callback) { - // Create elements. - var parentElement = document.createElement('div'); - var directoryTree = document.createElement('div'); - parentElement.appendChild(directoryTree); - - // Create mocks. - var directoryModel = new MockDirectoryModel(); - var volumeManager = new MockVolumeManager(); - var fileOperationManager = { - addEventListener: function(name, callback) {} - }; - - // Set entry which is returned by - // window.webkitResolveLocalFileSystemURLResults. + // Setup entries returned by fakeFileSystemURLResults. var driveFileSystem = volumeManager.volumeInfoList.item(0).fileSystem; - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/root'] = + fakeFileSystemURLEntries['filesystem:drive/root'] = new MockDirectoryEntry(driveFileSystem, '/root'); - DirectoryTree.decorate(directoryTree, directoryModel, volumeManager, - null, fileOperationManager, true); + // Populate the directory tree with the mock filesystem. + var directoryTree = createElements(); + DirectoryTree.decorate( + directoryTree, directoryModel, volumeManager, metadataModel, + fileOperationManager, true); directoryTree.dataModel = new MockNavigationListModel(volumeManager); + + // Coerce to DirectoryTree type and draw the tree. + directoryTree = /** @type {!DirectoryTree} */ (directoryTree); directoryTree.redraw(true); // At top level, Drive and downloads should be listed. @@ -137,34 +179,25 @@ * test result. */ function testCreateDirectoryTreeWithTeamDrive(callback) { - // Create elements. - var parentElement = document.createElement('div'); - var directoryTree = document.createElement('div'); - directoryTree.metadataModel = mockMetadataModel(); - - parentElement.appendChild(directoryTree); - - // Create mocks. - var directoryModel = new MockDirectoryModel(); - var volumeManager = new MockVolumeManager(); - var fileOperationManager = {addEventListener: function(name, callback) {}}; - - // Set entry which is returned by - // window.webkitResolveLocalFileSystemURLResults. + // Setup entries returned by fakeFileSystemURLResults. var driveFileSystem = volumeManager.volumeInfoList.item(0).fileSystem; - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/root'] = + fakeFileSystemURLEntries['filesystem:drive/root'] = new MockDirectoryEntry(driveFileSystem, '/root'); - window - .webkitResolveLocalFileSystemURLEntries['filesystem:drive/team_drives'] = + fakeFileSystemURLEntries['filesystem:drive/team_drives'] = new MockDirectoryEntry(driveFileSystem, '/team_drives'); - window.webkitResolveLocalFileSystemURLEntries - ['filesystem:drive/team_drives/a'] = + fakeFileSystemURLEntries['filesystem:drive/team_drives/a'] = new MockDirectoryEntry(driveFileSystem, '/team_drives/a'); + // Populate the directory tree with the mock filesystem. + var directoryTree = createElements(); + directoryTree.metadataModel = createMockMetadataModel(); DirectoryTree.decorate( - directoryTree, directoryModel, volumeManager, null, fileOperationManager, - true); + directoryTree, directoryModel, volumeManager, metadataModel, + fileOperationManager, true); directoryTree.dataModel = new MockNavigationListModel(volumeManager); + + // Coerce to DirectoryTree type and draw the tree. + directoryTree = /** @type {!DirectoryTree} */ (directoryTree); directoryTree.redraw(true); // At top level, Drive and downloads should be listed. @@ -199,32 +232,24 @@ * test result. */ function testCreateDirectoryTreeWithEmptyTeamDrive(callback) { - // Create elements. - var parentElement = document.createElement('div'); - var directoryTree = document.createElement('div'); - directoryTree.metadataModel = mockMetadataModel(); - - parentElement.appendChild(directoryTree); - - // Create mocks. - var directoryModel = new MockDirectoryModel(); - var volumeManager = new MockVolumeManager(); - var fileOperationManager = {addEventListener: function(name, callback) {}}; - - // Set entry which is returned by - // window.webkitResolveLocalFileSystemURLResults. + // Setup entries returned by fakeFileSystemURLResults. var driveFileSystem = volumeManager.volumeInfoList.item(0).fileSystem; - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/root'] = + fakeFileSystemURLEntries['filesystem:drive/root'] = new MockDirectoryEntry(driveFileSystem, '/root'); - window - .webkitResolveLocalFileSystemURLEntries['filesystem:drive/team_drives'] = + fakeFileSystemURLEntries['filesystem:drive/team_drives'] = new MockDirectoryEntry(driveFileSystem, '/team_drives'); // No directories exist under Team Drives + // Populate the directory tree with the mock filesystem. + var directoryTree = createElements(); + directoryTree.metadataModel = createMockMetadataModel(); DirectoryTree.decorate( - directoryTree, directoryModel, volumeManager, null, fileOperationManager, - true); + directoryTree, directoryModel, volumeManager, metadataModel, + fileOperationManager, true); directoryTree.dataModel = new MockNavigationListModel(volumeManager); + + // Coerce to DirectoryTree type and draw the tree. + directoryTree = /** @type {!DirectoryTree} */ (directoryTree); directoryTree.redraw(true); var driveItem = directoryTree.items[0]; @@ -263,34 +288,25 @@ * test result. */ function testCreateDirectoryTreeWithComputers(callback) { - // Create elements. - let parentElement = document.createElement('div'); - let directoryTree = document.createElement('div'); - directoryTree.metadataModel = mockMetadataModel(); - - parentElement.appendChild(directoryTree); - - // Create mocks. - let directoryModel = new MockDirectoryModel(); - let volumeManager = new MockVolumeManager(); - const fileOperationManager = {addEventListener: function(name, callback) {}}; - - // Set entry which is returned by - // window.webkitResolveLocalFileSystemURLResults. + // Setup entries returned by fakeFileSystemURLResults. const driveFileSystem = volumeManager.volumeInfoList.item(0).fileSystem; - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/root'] = + fakeFileSystemURLEntries['filesystem:drive/root'] = new MockDirectoryEntry(driveFileSystem, '/root'); - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/Computers'] = + fakeFileSystemURLEntries['filesystem:drive/Computers'] = new MockDirectoryEntry(driveFileSystem, '/Computers'); - window.webkitResolveLocalFileSystemURLEntries - ['filesystem:drive/Comuters/My Laptop'] = + fakeFileSystemURLEntries['filesystem:drive/Comuters/My Laptop'] = new MockDirectoryEntry(driveFileSystem, '/Computers/My Laptop'); // Populate the directory tree with the mock filesystem. + var directoryTree = createElements(); + directoryTree.metadataModel = createMockMetadataModel(); DirectoryTree.decorate( - directoryTree, directoryModel, volumeManager, null, fileOperationManager, - true); + directoryTree, directoryModel, volumeManager, metadataModel, + fileOperationManager, true); directoryTree.dataModel = new MockNavigationListModel(volumeManager); + + // Coerce to DirectoryTree type and draw the tree. + directoryTree = /** @type {!DirectoryTree} */ (directoryTree); directoryTree.redraw(true); // At top level, Drive and downloads should be listed. @@ -325,32 +341,24 @@ * test result. */ function testCreateDirectoryTreeWithEmptyComputers(callback) { - // Create elements. - let parentElement = document.createElement('div'); - let directoryTree = document.createElement('div'); - directoryTree.metadataModel = mockMetadataModel(); - - parentElement.appendChild(directoryTree); - - // Create mocks. - let directoryModel = new MockDirectoryModel(); - let volumeManager = new MockVolumeManager(); - const fileOperationManager = {addEventListener: function(name, callback) {}}; - - // Set entry which is returned by - // window.webkitResolveLocalFileSystemURLResults. + // Setup entries returned by fakeFileSystemURLResults. const driveFileSystem = volumeManager.volumeInfoList.item(0).fileSystem; - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/root'] = + fakeFileSystemURLEntries['filesystem:drive/root'] = new MockDirectoryEntry(driveFileSystem, '/root'); - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/Computers'] = + fakeFileSystemURLEntries['filesystem:drive/Computers'] = new MockDirectoryEntry(driveFileSystem, '/Computers'); // No directories exist under Team Drives // Populate the directory tree with the mock filesystem. + var directoryTree = createElements(); + directoryTree.metadataModel = createMockMetadataModel(); DirectoryTree.decorate( - directoryTree, directoryModel, volumeManager, null, fileOperationManager, - true); + directoryTree, directoryModel, volumeManager, metadataModel, + fileOperationManager, true); directoryTree.dataModel = new MockNavigationListModel(volumeManager); + + // Coerce to DirectoryTree type and draw the tree. + directoryTree = /** @type {!DirectoryTree} */ (directoryTree); directoryTree.redraw(true); const driveItem = directoryTree.items[0]; @@ -392,40 +400,29 @@ * test result. */ function testCreateDirectoryTreeWithTeamDrivesAndComputers(callback) { - // Create elements. - let parentElement = document.createElement('div'); - let directoryTree = document.createElement('div'); - directoryTree.metadataModel = mockMetadataModel(); - - parentElement.appendChild(directoryTree); - - // Create mocks. - let directoryModel = new MockDirectoryModel(); - let volumeManager = new MockVolumeManager(); - const fileOperationManager = {addEventListener: function(name, callback) {}}; - - // Set entry which is returned by - // window.webkitResolveLocalFileSystemURLResults. + // Setup entries returned by fakeFileSystemURLResults. const driveFileSystem = volumeManager.volumeInfoList.item(0).fileSystem; - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/root'] = + fakeFileSystemURLEntries['filesystem:drive/root'] = new MockDirectoryEntry(driveFileSystem, '/root'); - window - .webkitResolveLocalFileSystemURLEntries['filesystem:drive/team_drives'] = + fakeFileSystemURLEntries['filesystem:drive/team_drives'] = new MockDirectoryEntry(driveFileSystem, '/team_drives'); - window.webkitResolveLocalFileSystemURLEntries - ['filesystem:drive/team_drives/a'] = + fakeFileSystemURLEntries ['filesystem:drive/team_drives/a'] = new MockDirectoryEntry(driveFileSystem, '/team_drives/a'); - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/Computers'] = + fakeFileSystemURLEntries['filesystem:drive/Computers'] = new MockDirectoryEntry(driveFileSystem, '/Computers'); - window.webkitResolveLocalFileSystemURLEntries - ['filesystem:drive/Comuters/My Laptop'] = + fakeFileSystemURLEntries['filesystem:drive/Comuters/My Laptop'] = new MockDirectoryEntry(driveFileSystem, '/Computers/My Laptop'); // Populate the directory tree with the mock filesystem. + var directoryTree = createElements(); + directoryTree.metadataModel = createMockMetadataModel(); DirectoryTree.decorate( - directoryTree, directoryModel, volumeManager, null, fileOperationManager, - true); + directoryTree, directoryModel, volumeManager, metadataModel, + fileOperationManager, true); directoryTree.dataModel = new MockNavigationListModel(volumeManager); + + // Coerce to DirectoryTree type and draw the tree. + directoryTree = /** @type {!DirectoryTree} */ (directoryTree); directoryTree.redraw(true); // At top level, Drive and downloads should be listed. @@ -460,33 +457,26 @@ * "sections" in the directory tree. This is calculated in NavigationListModel. */ function testUpdateSubElementsFromListSections() { - // Creates elements. - const parentElement = document.createElement('div'); - const directoryTree = document.createElement('div'); - parentElement.appendChild(directoryTree); - - // Creates mocks. - const directoryModel = new MockDirectoryModel(); - const volumeManager = new MockVolumeManager(); - const fileOperationManager = { - addEventListener: function(name, callback) {} - }; - + const recentItem = null; const treeModel = new NavigationListModel( - volumeManager, new MockFolderShortcutDataModel([]), null /* recentItem */, + volumeManager, new MockFolderShortcutDataModel([]), recentItem, new MockDirectoryModel()); - const myFilesItem = treeModel.item(0); const driveItem = treeModel.item(1); assertEquals(NavigationSection.MY_FILES, myFilesItem.section); assertEquals(NavigationSection.CLOUD, driveItem.section); - const metadataModel = mockMetadataModel(); + // Populate the directory tree with the mock filesystem. + var directoryTree = createElements(); + const mockMetadata = createMockMetadataModel(); DirectoryTree.decorate( - directoryTree, directoryModel, volumeManager, metadataModel, + directoryTree, directoryModel, volumeManager, mockMetadata, fileOperationManager, true); directoryTree.dataModel = treeModel; + + // Coerce to DirectoryTree type and update the tree. + directoryTree = /** @type {!DirectoryTree} */ (directoryTree); directoryTree.updateSubElementsFromList(false); // First element should not have section-start attribute, to not display a @@ -506,7 +496,6 @@ assertEquals( NavigationSection.CLOUD, directoryTree.items[1].getAttribute('section-start')); - } /** @@ -516,34 +505,27 @@ * up to/disappear from the list correctly. */ function testUpdateSubElementsFromList() { - // Creates elements. - var parentElement = document.createElement('div'); - var directoryTree = document.createElement('div'); - parentElement.appendChild(directoryTree); - - // Creates mocks. - var directoryModel = new MockDirectoryModel(); - var volumeManager = new MockVolumeManager(); - var fileOperationManager = { - addEventListener: function(name, callback) {} - }; - - // Sets entry which is returned by - // window.webkitResolveLocalFileSystemURLResults. + // Setup entries returned by fakeFileSystemURLResults. var driveFileSystem = volumeManager.volumeInfoList.item(0).fileSystem; - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/root'] = + fakeFileSystemURLEntries['filesystem:drive/root'] = new MockDirectoryEntry(driveFileSystem, '/root'); - DirectoryTree.decorate(directoryTree, directoryModel, volumeManager, - null, fileOperationManager, true); + // Populate the directory tree with the mock filesystem. + var directoryTree = createElements(); + DirectoryTree.decorate( + directoryTree, directoryModel, volumeManager, metadataModel, + fileOperationManager, true); directoryTree.dataModel = new MockNavigationListModel(volumeManager); + + // Coerce to DirectoryTree type and update the tree. + directoryTree = /** @type {!DirectoryTree} */ (directoryTree); directoryTree.updateSubElementsFromList(true); // There are 2 volumes, Drive and Downloads, at first. assertArrayEquals([ str('DRIVE_DIRECTORY_LABEL'), str('DOWNLOADS_DIRECTORY_LABEL') - ], getDirectoryTreeItemLabelsAsAList(directoryTree)); + ], getDirectoryTreeItemLabels(directoryTree)); // Mounts a removable volume. var removableVolume = MockVolumeManager.createMockVolumeInfo( @@ -555,7 +537,7 @@ assertArrayEquals([ str('DRIVE_DIRECTORY_LABEL'), str('DOWNLOADS_DIRECTORY_LABEL') - ], getDirectoryTreeItemLabelsAsAList(directoryTree)); + ], getDirectoryTreeItemLabels(directoryTree)); // Asserts that a removable directory is added after the update. directoryTree.updateSubElementsFromList(false); @@ -563,7 +545,7 @@ str('DRIVE_DIRECTORY_LABEL'), str('DOWNLOADS_DIRECTORY_LABEL'), str('REMOVABLE_DIRECTORY_LABEL') - ], getDirectoryTreeItemLabelsAsAList(directoryTree)); + ], getDirectoryTreeItemLabels(directoryTree)); // Mounts an archive volume. var archiveVolume = MockVolumeManager.createMockVolumeInfo( @@ -576,7 +558,7 @@ str('DRIVE_DIRECTORY_LABEL'), str('DOWNLOADS_DIRECTORY_LABEL'), str('REMOVABLE_DIRECTORY_LABEL') - ], getDirectoryTreeItemLabelsAsAList(directoryTree)); + ], getDirectoryTreeItemLabels(directoryTree)); // Asserts that an archive directory is added before the removable directory. directoryTree.updateSubElementsFromList(false); @@ -587,7 +569,7 @@ str('REMOVABLE_DIRECTORY_LABEL'), str('ARCHIVE_DIRECTORY_LABEL'), ], - getDirectoryTreeItemLabelsAsAList(directoryTree)); + getDirectoryTreeItemLabels(directoryTree)); // Deletes an archive directory. volumeManager.volumeInfoList.remove('archive'); @@ -600,7 +582,7 @@ str('REMOVABLE_DIRECTORY_LABEL'), str('ARCHIVE_DIRECTORY_LABEL'), ], - getDirectoryTreeItemLabelsAsAList(directoryTree)); + getDirectoryTreeItemLabels(directoryTree)); // Asserts that an archive directory is deleted. directoryTree.updateSubElementsFromList(false); @@ -608,7 +590,7 @@ str('DRIVE_DIRECTORY_LABEL'), str('DOWNLOADS_DIRECTORY_LABEL'), str('REMOVABLE_DIRECTORY_LABEL') - ], getDirectoryTreeItemLabelsAsAList(directoryTree)); + ], getDirectoryTreeItemLabels(directoryTree)); } /** @@ -620,32 +602,24 @@ * test result. */ function testAddFirstTeamDrive(callback) { - // Create elements. - var parentElement = document.createElement('div'); - var directoryTree = document.createElement('div'); - directoryTree.metadataModel = mockMetadataModel(); - - parentElement.appendChild(directoryTree); - - // Create mocks. - var directoryModel = new MockDirectoryModel(); - var volumeManager = new MockVolumeManager(); - var fileOperationManager = {addEventListener: function(name, callback) {}}; - - // Set entry which is returned by - // window.webkitResolveLocalFileSystemURLResults. + // Setup entries returned by fakeFileSystemURLResults. var driveFileSystem = volumeManager.volumeInfoList.item(0).fileSystem; - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/root'] = + fakeFileSystemURLEntries['filesystem:drive/root'] = new MockDirectoryEntry(driveFileSystem, '/root'); - window - .webkitResolveLocalFileSystemURLEntries['filesystem:drive/team_drives'] = + fakeFileSystemURLEntries['filesystem:drive/team_drives'] = new MockDirectoryEntry(driveFileSystem, '/team_drives'); // No directories exist under Team Drives + // Populate the directory tree with the mock filesystem. + var directoryTree = createElements(); + directoryTree.metadataModel = createMockMetadataModel(); DirectoryTree.decorate( - directoryTree, directoryModel, volumeManager, null, fileOperationManager, - true); + directoryTree, directoryModel, volumeManager, metadataModel, + fileOperationManager, true); directoryTree.dataModel = new MockNavigationListModel(volumeManager); + + // Coerce to DirectoryTree type and draw the tree. + directoryTree = /** @type {!DirectoryTree} */ (directoryTree); directoryTree.redraw(true); var driveItem = directoryTree.items[0]; @@ -655,15 +629,13 @@ return driveItem.items.length == 3; }) .then(() => { - window.webkitResolveLocalFileSystemURLEntries - ['filesystem:drive/team_drives/a'] = + fakeFileSystemURLEntries['filesystem:drive/team_drives/a'] = new MockDirectoryEntry(driveFileSystem, '/team_drives/a'); let event = { - entry: window.webkitResolveLocalFileSystemURLEntries - ['filesystem:drive/team_drives'], + entry: fakeFileSystemURLEntries['filesystem:drive/team_drives'], eventType: 'changed', }; - for (let listener of onDirectoryChangedListeners) { + for (let listener of directoryChangedListeners) { listener(event); } }) @@ -690,34 +662,25 @@ * test result. */ function testRemoveLastTeamDrive(callback) { - // Create elements. - var parentElement = document.createElement('div'); - var directoryTree = document.createElement('div'); - directoryTree.metadataModel = mockMetadataModel(); - - parentElement.appendChild(directoryTree); - - // Create mocks. - var directoryModel = new MockDirectoryModel(); - var volumeManager = new MockVolumeManager(); - var fileOperationManager = {addEventListener: function(name, callback) {}}; - - // Set entry which is returned by - // window.webkitResolveLocalFileSystemURLResults. + // Setup entries returned by fakeFileSystemURLResults. var driveFileSystem = volumeManager.volumeInfoList.item(0).fileSystem; - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/root'] = + fakeFileSystemURLEntries['filesystem:drive/root'] = new MockDirectoryEntry(driveFileSystem, '/root'); - window - .webkitResolveLocalFileSystemURLEntries['filesystem:drive/team_drives'] = + fakeFileSystemURLEntries['filesystem:drive/team_drives'] = new MockDirectoryEntry(driveFileSystem, '/team_drives'); - window.webkitResolveLocalFileSystemURLEntries - ['filesystem:drive/team_drives/a'] = + fakeFileSystemURLEntries['filesystem:drive/team_drives/a'] = new MockDirectoryEntry(driveFileSystem, '/team_drives/a'); + // Populate the directory tree with the mock filesystem. + var directoryTree = createElements(); + directoryTree.metadataModel = createMockMetadataModel(); DirectoryTree.decorate( - directoryTree, directoryModel, volumeManager, null, fileOperationManager, - true); + directoryTree, directoryModel, volumeManager, metadataModel, + fileOperationManager, true); directoryTree.dataModel = new MockNavigationListModel(volumeManager); + + // Coerce to DirectoryTree type and draw the tree. + directoryTree = /** @type {!DirectoryTree} */ (directoryTree); directoryTree.redraw(true); var driveItem = directoryTree.items[0]; @@ -728,19 +691,16 @@ }) .then(() => { return new Promise(resolve => { - window - .webkitResolveLocalFileSystemURLEntries - ['filesystem:drive/team_drives/a'] + fakeFileSystemURLEntries['filesystem:drive/team_drives/a'] .remove(resolve); }); }) .then(() => { let event = { - entry: window.webkitResolveLocalFileSystemURLEntries - ['filesystem:drive/team_drives'], + entry: fakeFileSystemURLEntries['filesystem:drive/team_drives'], eventType: 'changed', }; - for (let listener of onDirectoryChangedListeners) { + for (let listener of directoryChangedListeners) { listener(event); } }) @@ -768,53 +728,44 @@ * test result. */ function testAddFirstComputer(callback) { - // Create elements. - let parentElement = document.createElement('div'); - let directoryTree = document.createElement('div'); - directoryTree.metadataModel = mockMetadataModel(); - - parentElement.appendChild(directoryTree); - - // Create mocks. - let directoryModel = new MockDirectoryModel(); - let volumeManager = new MockVolumeManager(); - const fileOperationManager = {addEventListener: function(name, callback) {}}; - - // Set entry which is returned by - // window.webkitResolveLocalFileSystemURLResults. + // Setup entries returned by fakeFileSystemURLResults. var driveFileSystem = volumeManager.volumeInfoList.item(0).fileSystem; - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/root'] = + fakeFileSystemURLEntries['filesystem:drive/root'] = new MockDirectoryEntry(driveFileSystem, '/root'); - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/Computers'] = + fakeFileSystemURLEntries['filesystem:drive/Computers'] = new MockDirectoryEntry(driveFileSystem, '/Computers'); // No directories exist under Computers // Populate the directory tree with the mock filesystem. + var directoryTree = createElements(); + directoryTree.metadataModel = createMockMetadataModel(); DirectoryTree.decorate( - directoryTree, directoryModel, volumeManager, null, fileOperationManager, - true); + directoryTree, directoryModel, volumeManager, metadataModel, + fileOperationManager, true); directoryTree.dataModel = new MockNavigationListModel(volumeManager); + + // Coerce to DirectoryTree type and draw the tree. + directoryTree = /** @type {!DirectoryTree} */ (directoryTree); directoryTree.redraw(true); let driveItem = directoryTree.items[0]; - // Test that we initially do not have a Computers item under druve, and that + // Test that we initially do not have a Computers item under Drive, and that // adding a filesystem "/Computers/a" results in the Computers item being - // displayed under drive. + // displayed under Drive. + reportPromise( waitUntil(() => { return driveItem.items.length == 3; }) .then(() => { - window.webkitResolveLocalFileSystemURLEntries - ['filesystem:drive/Computers/a'] = + fakeFileSystemURLEntries['filesystem:drive/Computers/a'] = new MockDirectoryEntry(driveFileSystem, '/Computers/a'); let event = { - entry: window.webkitResolveLocalFileSystemURLEntries - ['filesystem:drive/Computers'], + entry: fakeFileSystemURLEntries['filesystem:drive/Computers'], eventType: 'changed', }; - for (let listener of onDirectoryChangedListeners) { + for (let listener of directoryChangedListeners) { listener(event); } }) @@ -840,34 +791,25 @@ * test result. */ function testRemoveLastComputer(callback) { - // Create elements. - let parentElement = document.createElement('div'); - let directoryTree = document.createElement('div'); - directoryTree.metadataModel = mockMetadataModel(); - - parentElement.appendChild(directoryTree); - - // Create mocks. - let directoryModel = new MockDirectoryModel(); - let volumeManager = new MockVolumeManager(); - const fileOperationManager = {addEventListener: function(name, callback) {}}; - - // Set entry which is returned by - // window.webkitResolveLocalFileSystemURLResults. + // Setup entries returned by fakeFileSystemURLResults. var driveFileSystem = volumeManager.volumeInfoList.item(0).fileSystem; - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/root'] = + fakeFileSystemURLEntries['filesystem:drive/root'] = new MockDirectoryEntry(driveFileSystem, '/root'); - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/Computers'] = + fakeFileSystemURLEntries['filesystem:drive/Computers'] = new MockDirectoryEntry(driveFileSystem, '/Computers'); - window - .webkitResolveLocalFileSystemURLEntries['filesystem:drive/Computers/a'] = + fakeFileSystemURLEntries['filesystem:drive/Computers/a'] = new MockDirectoryEntry(driveFileSystem, '/Computers/a'); // Populate the directory tree with the mock filesystem. + var directoryTree = createElements(); + directoryTree.metadataModel = createMockMetadataModel(); DirectoryTree.decorate( - directoryTree, directoryModel, volumeManager, null, fileOperationManager, - true); + directoryTree, directoryModel, volumeManager, metadataModel, + fileOperationManager, true); directoryTree.dataModel = new MockNavigationListModel(volumeManager); + + // Coerce to DirectoryTree type and draw the tree. + directoryTree = /** @type {!DirectoryTree} */ (directoryTree); directoryTree.redraw(true); const driveItem = directoryTree.items[0]; @@ -880,19 +822,16 @@ }) .then(() => { return new Promise(resolve => { - window - .webkitResolveLocalFileSystemURLEntries - ['filesystem:drive/Computers/a'] + fakeFileSystemURLEntries['filesystem:drive/Computers/a'] .remove(resolve); }); }) .then(() => { let event = { - entry: window.webkitResolveLocalFileSystemURLEntries - ['filesystem:drive/Computers'], + entry: fakeFileSystemURLEntries['filesystem:drive/Computers'], eventType: 'changed', }; - for (let listener of onDirectoryChangedListeners) { + for (let listener of directoryChangedListeners) { listener(event); } }) @@ -919,33 +858,27 @@ * test result. */ function testInsideMyDriveAndInsideDrive(callback) { - const parentElement = document.createElement('div'); - const directoryTree = document.createElement('div'); - directoryTree.metadataModel = mockMetadataModel(); - parentElement.appendChild(directoryTree); - - // Create mocks. - const directoryModel = new MockDirectoryModel(); - const volumeManager = new MockVolumeManager(); - const fileOperationManager = {addEventListener: function(name, callback) {}}; - // Setup My Drive and Downloads and one folder inside each of them. const driveFileSystem = volumeManager.volumeInfoList.item(0).fileSystem; - const downloadsFileSystem = volumeManager.volumeInfoList.item(1).fileSystem; - window.webkitResolveLocalFileSystemURLEntries['filesystem:drive/root'] = + fakeFileSystemURLEntries['filesystem:drive/root'] = new MockDirectoryEntry(driveFileSystem, '/root'); - window - .webkitResolveLocalFileSystemURLEntries['filesystem:drive/root/folder1'] = + fakeFileSystemURLEntries['filesystem:drive/root/folder1'] = new MockDirectoryEntry(driveFileSystem, '/root/folder1'); - window - .webkitResolveLocalFileSystemURLEntries['filesystem:downloads/folder1'] = + const downloadsFileSystem = volumeManager.volumeInfoList.item(1).fileSystem; + fakeFileSystemURLEntries['filesystem:downloads/folder1'] = new MockDirectoryEntry(downloadsFileSystem, '/folder1'); - const metadataModel = mockMetadataModel(); + // Populate the directory tree with the mock filesystem. + var directoryTree = createElements(); + directoryTree.metadataModel = createMockMetadataModel(); + const mockMetadata = createMockMetadataModel(); DirectoryTree.decorate( - directoryTree, directoryModel, volumeManager, metadataModel, + directoryTree, directoryModel, volumeManager, mockMetadata, fileOperationManager, true); directoryTree.dataModel = new MockNavigationListModel(volumeManager); + + // Coerce to DirectoryTree type and draw the tree. + directoryTree = /** @type {!DirectoryTree} */ (directoryTree); directoryTree.redraw(true); const driveItem = directoryTree.items[0];
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js index 7ab8e9d..ea7b035 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
@@ -306,11 +306,11 @@ /** * The menu button for share options - * @type {!cr.ui.MenuButton} + * @type {!cr.ui.MultiMenuButton} * @const */ this.shareMenuButton = - util.queryDecoratedElement('#share-menu-button', cr.ui.MenuButton); + util.queryDecoratedElement('#share-menu-button', cr.ui.MultiMenuButton); var shareMenuButtonToggleRipple = /** @type {!FilesToggleRipple} */ ( queryRequiredElement('files-toggle-ripple', this.shareMenuButton)); @@ -322,6 +322,13 @@ }); /** + * @type {!cr.ui.Menu} + * @const + */ + this.shareSubMenu = util.queryDecoratedElement('#share-sub-menu', cr.ui.Menu); + this.shareMenuButton.overflow = this.shareSubMenu; + + /** * Banners in the file list. * @type {Banners} */ @@ -371,6 +378,9 @@ // Initialize attributes. this.element.setAttribute('type', this.dialogType_); + if (launchParam.allowedPaths !== AllowedPaths.ANY_PATH_OR_URL) { + this.element.setAttribute('block-hosted-docs', ''); + } // Hack: make menuitems focusable. Since the menuitems in the Files app is not // button so it doesn't have a tabfocus in nature. It prevents Chromevox from
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table.js b/ui/file_manager/file_manager/foreground/js/ui/file_table.js index 4edff6f..512338e 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_table.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_table.js
@@ -963,7 +963,7 @@ [entry], [ 'availableOffline', 'customIconUrl', 'shared', 'isMachineRoot', - 'isExternalMedia' + 'isExternalMedia', 'hosted' ])[0], util.isTeamDriveRoot(entry)); });
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js b/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js index e531020d..70de83c 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_table_list.js
@@ -213,6 +213,11 @@ // TODO(mtomasz): Consider adding some vidual indication for files which // are not cached on LTE. Currently we show them as normal files. // crbug.com/246611. + + if (externalProps.hosted === true) + li.classList.add('dim-hosted'); + else + li.classList.remove('dim-hosted'); } var iconDiv = li.querySelector('.detail-icon');
diff --git a/ui/file_manager/file_manager/foreground/js/ui/files_menu.js b/ui/file_manager/file_manager/foreground/js/ui/files_menu.js index d12598d8..08bce50 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/files_menu.js +++ b/ui/file_manager/file_manager/foreground/js/ui/files_menu.js
@@ -79,6 +79,13 @@ // Perform fade out animation. var menu = assertInstanceof(this.parentNode, cr.ui.Menu); + // If activation was on a menu-item that hosts a sub-menu, don't animate + const subMenuId = event.target.getAttribute('sub-menu'); + if (subMenuId !== null) { + if (document.querySelector(subMenuId) !== null) { + return; + } + } this.setMenuAsAnimating_(menu, true /* animating */); var player = menu.animate([{
diff --git a/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js b/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js new file mode 100644 index 0000000..e2fdf5db --- /dev/null +++ b/ui/file_manager/file_manager/foreground/js/ui/multi_menu.js
@@ -0,0 +1,481 @@ +// Copyright (c) 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. + +cr.exportPath('cr.ui'); + +cr.define('cr.ui', function() { + /** @const */ + const Menu = cr.ui.Menu; + + /** @const */ + const HideType = cr.ui.HideType; + + /** @const */ + const positionPopupAroundElement = cr.ui.positionPopupAroundElement; + + /** + * Creates a new menu button element. + * @param {Object=} opt_propertyBag Optional properties. + * @constructor + * @extends {HTMLButtonElement} + * @implements {EventListener} + */ + const MultiMenuButton = cr.ui.define('button'); + + MultiMenuButton.prototype = { + __proto__: HTMLButtonElement.prototype, + + /** + * Initializes the menu button. + */ + decorate: function() { + // Listen to the touch events on the document so that we can handle it + // before cancelled by other UI components. + this.ownerDocument.addEventListener('touchstart', this); + this.addEventListener('mousedown', this); + this.addEventListener('keydown', this); + this.addEventListener('dblclick', this); + this.addEventListener('blur', this); + + // Adding the 'custom-appearance' class prevents widgets.css from changing + // the appearance of this element. + this.classList.add('custom-appearance'); + this.classList.add('menu-button'); // For styles in menu_button.css. + + let menu; + if ((menu = this.getAttribute('menu'))) + this.menu = menu; + + // An event tracker for events we only connect to while the menu is + // displayed. + this.showingEvents_ = new EventTracker(); + + this.anchorType = cr.ui.AnchorType.BELOW; + this.invertLeftRight = false; + }, + + /** + * The menu associated with the menu button. + * @type {cr.ui.Menu} + */ + get menu() { + return this.menu_; + }, + set menu(menu) { + if (typeof menu == 'string' && menu[0] == '#') { + menu = assert(this.ownerDocument.getElementById(menu.slice(1))); + cr.ui.decorate(menu, Menu); + } + + this.menu_ = menu; + if (menu) { + if (menu.id) + this.setAttribute('menu', '#' + menu.id); + } + }, + + /** + * Whether to show the menu on press of the Up or Down arrow keys. + */ + respondToArrowKeys: true, + + /** + * Property that hosts sub-menus for filling with overflow items. + * @type {cr.ui.Menu|null} Used for menu-items that overflow parent menu. + * @public + */ + overflow: null, + + /** + * Checks if the menu(s) should be closed based on the target of a mouse + * click or a touch event target. + * @param {Event} e The event object. + * @return {boolean} + * @private + */ + shouldDismissMenu_: function(e) { + // All menus are dismissed when clicking outside the menus. If we are + // showing a sub-menu, we need to detect if the target is the top + // level menu, or in the sub menu when the sub menu is being shown. + // The button is excluded here because it should toggle show/hide the + // menu and handled separately. + return e.target instanceof Node && !this.contains(e.target) && + !this.menu.contains(e.target) && + !(this.menu.subMenu && this.menu.subMenu.contains(e.target)); + }, + + /** + * Position the sub menu adjacent to the cr-menu-item that triggered it. + * @param {cr.ui.MenuItem} item The menu item to position against. + * @param {cr.ui.Menu} subMenu The child (sub) menu to be positioned. + */ + positionSubMenu_: function(item, subMenu) { + // The sub-menu needs to sit aligned to the top and side of + // the menu-item passed in. It also needs to fit inside the viewport + const itemRect = item.getBoundingClientRect(); + const viewportWidth = window.innerWidth; + const viewportHeight = window.innerHeight; + const childRect = subMenu.getBoundingClientRect(); + const style = subMenu.style; + // See if it fits on the right, if not position on the left + style.left = style.right = style.top = style.bottom = 'auto'; + if ((itemRect.right + childRect.width) > viewportWidth) { + style.left = (itemRect.left - childRect.width) + 'px'; + } else { + style.left = itemRect.right + 'px'; + } + style.top = itemRect.top + 'px'; + // Size the subMenu to fit inside the height of the viewport + const menuEndGap = 18; // padding on cr.menu + 2px + if ((itemRect.top + childRect.height + menuEndGap) > viewportHeight) { + style.maxHeight = (viewportHeight - itemRect.top - menuEndGap) + 'px'; + style.overflowY = 'scroll'; + } + }, + + /** + * Get the subMenu hanging off a menu-item if it exists. + * @param {cr.ui.MenuItem} item The menu item. + * @return {cr.ui.Menu|null} + */ + getSubMenuFromItem: function(item) { + if (!item) { + return null; + } + const subMenuId = item.getAttribute('sub-menu'); + if (subMenuId === null) { + return null; + } + return /** @type {!cr.ui.Menu|null} */ ( + document.querySelector(subMenuId)); + }, + + /** + * Display any sub-menu hanging off the current selection. + */ + showSubMenu: function() { + if (!this.isMenuShown()) + return; + const item = this.menu.selectedItem; + const subMenu = this.getSubMenuFromItem(item); + if (subMenu) { + this.menu.subMenu = subMenu; + item.setAttribute('sub-menu-shown', 'shown'); + this.positionSubMenu_(item, subMenu); + subMenu.show(); + } + }, + + /** + * Find any sub-menu hanging off the event target and show/hide it. + * @param {Event} e The event object. + */ + manageSubMenu: function(e) { + const item = this.menu.findMenuItem_(e.target); + const subMenu = this.getSubMenuFromItem(item); + if (!subMenu) { + return; + } + this.menu.subMenu = subMenu; + switch (e.type) { + case 'mouseover': + item.setAttribute('sub-menu-shown', 'shown'); + this.positionSubMenu_(item, subMenu); + subMenu.show(); + break; + case 'mouseout': + // If we're on top of the sub-menu, we don't want to dismiss it + const childRect = subMenu.getBoundingClientRect(); + if (childRect.left <= e.x && e.x < childRect.right && + childRect.top <= e.y && e.y < childRect.bottom) { + break; + } + item.removeAttribute('sub-menu-shown'); + subMenu.hide(); + this.menu.subMenu = null; + break; + } + }, + + /** + * Handles event callbacks. + * @param {Event} e The event object. + */ + handleEvent: function(e) { + if (!this.menu) + return; + + switch (e.type) { + case 'touchstart': + // Touch on the menu button itself is ignored to avoid that the menu + // opened again by the mousedown event following the touch events. + if (this.shouldDismissMenu_(e)) { + this.hideMenuWithoutTakingFocus_(); + } + break; + case 'mousedown': + if (e.currentTarget == this.ownerDocument) { + if (this.shouldDismissMenu_(e)) { + this.hideMenuWithoutTakingFocus_(); + } else { + e.preventDefault(); + } + } else { + if (this.isMenuShown()) { + this.hideMenuWithoutTakingFocus_(); + } else if (e.button == 0) { // Only show the menu when using left + // mouse button. + this.showMenu(false, {x: e.screenX, y: e.screenY}); + + // Prevent the button from stealing focus on mousedown. + e.preventDefault(); + } + } + + // Hide the focus ring on mouse click. + this.classList.add('using-mouse'); + break; + case 'keydown': + this.handleKeyDown(e); + // If the menu is visible we let it handle all the keyboard events. + if (this.isMenuShown() && e.currentTarget == this.ownerDocument) { + this.menu.handleKeyDown(e); + e.preventDefault(); + e.stopPropagation(); + } + + // Show the focus ring on keypress. + this.classList.remove('using-mouse'); + break; + case 'focus': + if (this.shouldDismissMenu_(e)) { + this.hideMenu(); + // Show the focus ring on focus - if it's come from a mouse event, + // the focus ring will be hidden in the mousedown event handler, + // executed after this. + this.classList.remove('using-mouse'); + } + break; + case 'blur': + // No need to hide the focus ring anymore, without having focus. + this.classList.remove('using-mouse'); + break; + case 'activate': + const hideDelayed = + e.target instanceof cr.ui.MenuItem && e.target.checkable; + const hideType = hideDelayed ? HideType.DELAYED : HideType.INSTANT; + // If the menu-item hosts a sub-menu, don't hide + if (this.getSubMenuFromItem( + /** @type {!cr.ui.MenuItem} */ (e.target)) !== null) { + break; + } + if (e.originalEvent instanceof MouseEvent || + e.originalEvent instanceof TouchEvent) { + this.hideMenuWithoutTakingFocus_(hideType); + } else { + // Keyboard. Take focus to continue keyboard operation. + this.hideMenu(hideType); + } + break; + case 'popstate': + case 'resize': + this.hideMenu(); + break; + case 'contextmenu': + if ((!this.menu || !this.menu.contains(e.target)) && + (!this.hideTimestamp_ || Date.now() - this.hideTimestamp_ > 50)) + this.showMenu(true, {x: e.screenX, y: e.screenY}); + e.preventDefault(); + // Don't allow elements further up in the DOM to show their menus. + e.stopPropagation(); + break; + case 'dblclick': + // Don't allow double click events to propagate. + e.preventDefault(); + e.stopPropagation(); + break; + case 'mouseover': + case 'mouseout': + this.manageSubMenu(e); + break; + } + }, + + /** + * Add event listeners to any sub menus. + */ + addSubMenuListeners: function() { + const items = this.menu.querySelectorAll('cr-menu-item[sub-menu]'); + items.forEach((menuItem) => { + const subMenuId = menuItem.getAttribute('sub-menu'); + if (subMenuId) { + const subMenu = document.querySelector(subMenuId); + if (subMenu) { + this.showingEvents_.add(subMenu, 'activate', this); + } + } + }); + }, + + /** + * Shows the menu. + * @param {boolean} shouldSetFocus Whether to set focus on the + * selected menu item. + * @param {{x: number, y: number}=} opt_mousePos The position of the mouse + * when shown (in screen coordinates). + */ + showMenu: function(shouldSetFocus, opt_mousePos) { + this.hideMenu(); + + this.menu.updateCommands(this); + + const event = new UIEvent( + 'menushow', {bubbles: true, cancelable: true, view: window}); + if (!this.dispatchEvent(event)) + return; + + this.menu.show(opt_mousePos); + + this.setAttribute('menu-shown', ''); + // Handle mouse-over to trigger sub menu opening on hover. + this.showingEvents_.add(this.menu, 'mouseover', this); + this.showingEvents_.add(this.menu, 'mouseout', this); + this.addSubMenuListeners(); + + // When the menu is shown we steal all keyboard events. + const doc = this.ownerDocument; + const win = doc.defaultView; + this.showingEvents_.add(doc, 'keydown', this, true); + this.showingEvents_.add(doc, 'mousedown', this, true); + this.showingEvents_.add(doc, 'focus', this, true); + this.showingEvents_.add(doc, 'scroll', this, true); + this.showingEvents_.add(win, 'popstate', this); + this.showingEvents_.add(win, 'resize', this); + this.showingEvents_.add(this.menu, 'contextmenu', this); + this.showingEvents_.add(this.menu, 'activate', this); + this.positionMenu_(); + + if (shouldSetFocus) + this.menu.focusSelectedItem(); + }, + + /** + * Hides any sub-menu that is active. + */ + hideSubMenu_: function() { + const items = + this.menu.querySelectorAll('cr-menu-item[sub-menu][sub-menu-shown]'); + items.forEach((menuItem) => { + const subMenuId = menuItem.getAttribute('sub-menu'); + if (subMenuId) { + const subMenu = /** @type {!cr.ui.Menu|null} */ + (document.querySelector(subMenuId)); + if (subMenu) { + subMenu.hide(); + } + menuItem.removeAttribute('sub-menu-shown'); + } + }); + }, + + /** + * Hides the menu. If your menu can go out of scope, make sure to call this + * first. + * @param {cr.ui.HideType=} opt_hideType Type of hide. + * default: cr.ui.HideType.INSTANT. + */ + hideMenu: function(opt_hideType) { + this.hideMenuInternal_(true, opt_hideType); + }, + + /** + * Hides the menu. If your menu can go out of scope, make sure to call this + * first. + * @param {cr.ui.HideType=} opt_hideType Type of hide. + * default: cr.ui.HideType.INSTANT. + */ + hideMenuWithoutTakingFocus_: function(opt_hideType) { + this.hideMenuInternal_(false, opt_hideType); + }, + + /** + * Hides the menu. If your menu can go out of scope, make sure to call this + * first. + * @param {boolean} shouldTakeFocus Moves the focus to the button if true. + * @param {cr.ui.HideType=} opt_hideType Type of hide. + * default: cr.ui.HideType.INSTANT. + */ + hideMenuInternal_: function(shouldTakeFocus, opt_hideType) { + if (!this.isMenuShown()) + return; + + // Hide any visible sub-menus first + this.hideSubMenu_(); + + this.removeAttribute('menu-shown'); + if (opt_hideType == HideType.DELAYED) + this.menu.classList.add('hide-delayed'); + else + this.menu.classList.remove('hide-delayed'); + this.menu.hide(); + + this.showingEvents_.removeAll(); + if (shouldTakeFocus) + this.focus(); + + const event = new UIEvent( + 'menuhide', {bubbles: true, cancelable: false, view: window}); + this.dispatchEvent(event); + + // On windows we might hide the menu in a right mouse button up and if + // that is the case we wait some short period before we allow the menu + // to be shown again. + this.hideTimestamp_ = cr.isWindows ? Date.now() : 0; + }, + + /** + * Whether the menu is shown. + */ + isMenuShown: function() { + return this.hasAttribute('menu-shown'); + }, + + /** + * Positions the menu below the menu button. At this point we do not use any + * advanced positioning logic to ensure the menu fits in the viewport. + * @private + */ + positionMenu_: function() { + positionPopupAroundElement( + this, this.menu, this.anchorType, this.invertLeftRight); + }, + + /** + * Handles the keydown event for the menu button. + */ + handleKeyDown: function(e) { + switch (e.key) { + case 'ArrowDown': + case 'ArrowUp': + if (!this.respondToArrowKeys) + break; + case 'Enter': + case ' ': + if (!this.isMenuShown()) + this.showMenu(true); + e.preventDefault(); + break; + case 'Escape': + case 'Tab': + this.hideMenu(); + break; + } + } + }; + + // Export + return { + MultiMenuButton: MultiMenuButton, + }; +});
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html index 82a3824..7538270 100644 --- a/ui/file_manager/file_manager/main.html +++ b/ui/file_manager/file_manager/main.html
@@ -158,6 +158,7 @@ <command id="default-task"> <command id="open-with" i18n-values="label:OPEN_WITH_BUTTON_LABEL"> <command id="more-actions" i18n-values="label:MORE_ACTIONS_BUTTON_LABEL"> + <command id="show-submenu" i18n-values="label:MORE_ACTIONS_BUTTON_LABEL"> <command id="zip-selection" i18n-values="label:ZIP_SELECTION_BUTTON_LABEL"> <command id="set-wallpaper" @@ -302,6 +303,10 @@ <cr-menu-item command="#share"></cr-menu-item> <cr-menu-item command="#share-with-linux"></cr-menu-item> <hr id="drive-share-separator"> + <hr id="more-actions-separator"> + <cr-menu-item command="#show-submenu" + visibleif="full-page" class="hide-on-toolbar" + sub-menu="#share-sub-menu" hidden></cr-menu-item> </cr-menu> <cr-menu id="add-new-services-menu" @@ -317,6 +322,10 @@ <cr-menu-item command="#delete" i18n-content="DELETE_BUTTON_LABEL"></cr-menu-item> </cr-menu> + <cr-menu id="share-sub-menu" class="chrome-menu files-menu" + menu-item-selector="cr-menu-item"> + </cr-menu> + <div class="dialog-header"> <div id="location-breadcrumbs" class="breadcrumbs"></div> <div id="cancel-selection-button-wrapper">
diff --git a/ui/file_manager/integration_tests/.eslintrc.js b/ui/file_manager/integration_tests/.eslintrc.js deleted file mode 100644 index a6962800..0000000 --- a/ui/file_manager/integration_tests/.eslintrc.js +++ /dev/null
@@ -1,7 +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. - -module.exports = { - 'parserOptions': {'ecmaVersion': 8}, -};
diff --git a/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js b/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js index ab90d09..b3c1e04 100644 --- a/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js +++ b/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js
@@ -50,7 +50,7 @@ chrome.test.assertTrue( !!await remoteCall.callRemoteTestUtil('focus', appId, [pathQuery]), - 'focus failed'); + 'focus failed: ' + pathQuery); // Right click photos directory. chrome.test.assertTrue( @@ -156,7 +156,7 @@ } else { const downloadsQuery = '#directory-tree [entry-label="My files"] [entry-label="Downloads"]'; - await remoteCall.expandDirectoryTreeFor(appId, downloadsQuery); + await remoteCall.expandTreeItemInDirectoryTree(appId, downloadsQuery); } if (useKeyboardShortcut) { await remoteCall.callRemoteTestUtil( @@ -325,12 +325,7 @@ '#directory-tree [entry-label="My files"] [entry-label="Downloads"]'; const appId = await setupForDirectoryTreeContextMenuTest(); - await remoteCall.expandDirectoryTreeFor(appId, downloadsQuery); - chrome.test.assertTrue( - await remoteCall.callRemoteTestUtil( - 'fakeMouseClick', appId, [`${downloadsQuery} .expand-icon`]), - 'click on expand icon failed'); - await remoteCall.waitForElement(appId, downloadsQuery + '[expanded]'); + await remoteCall.expandTreeItemInDirectoryTree(appId, downloadsQuery); await remoteCall.callRemoteTestUtil('focus', appId, ['#directory-tree']); await clickDirectoryTreeContextMenuItem( appId, RootPath.DOWNLOADS_PATH + '/photos', 'copy');
diff --git a/ui/file_manager/integration_tests/file_manager/file_dialog.js b/ui/file_manager/integration_tests/file_manager/file_dialog.js index dcd8944..2e66e20 100644 --- a/ui/file_manager/integration_tests/file_manager/file_dialog.js +++ b/ui/file_manager/integration_tests/file_manager/file_dialog.js
@@ -76,21 +76,24 @@ * * @param {!string} volume Volume name for openAndWaitForClosingDialog. * @param {!string} name File name to select in the dialog. + * @param {boolean} useBrowserOpen Whether to launch the dialog from the + * browser. * @return {!Promise} Promise to be fulfilled on success. */ async function openFileDialogClickOkButton( - volume, name, expectedUrl = undefined) { + volume, name, useBrowserOpen = false) { const okButton = '.button-panel button.ok:enabled'; let closer = clickOpenFileDialogButton.bind(null, name, okButton); const entrySet = await setUpFileEntrySet(volume); const result = await openAndWaitForClosingDialog( - {type: 'openFile'}, volume, entrySet, closer, !!expectedUrl); - if (expectedUrl) { - chrome.test.assertEq(expectedUrl, result); - } else { + {type: 'openFile'}, volume, entrySet, closer, useBrowserOpen); + // If the file is opened via the filesystem API, check the name matches. + // Otherwise, the caller is responsible for verifying the returned URL. + if (!useBrowserOpen) { chrome.test.assertEq(name, result.name); } + return result; } /** @@ -299,16 +302,52 @@ }; /** + * Tests opening a file from Drive in the browser, ensuring it correctly + * opens the file URL. + */ +testcase.openFileDialogDriveFromBrowser = async function() { + const url = new URL( + await openFileDialogClickOkButton('drive', TEST_DRIVE_FILE, true)); + + const isDriveFsEnabled = + await sendTestMessage({name: 'getDriveFsEnabled'}) === 'true'; + + chrome.test.assertEq( + url.protocol, isDriveFsEnabled ? 'file:' : 'externalfile:'); + chrome.test.assertTrue( + url.pathname.endsWith(`/root/${TEST_DRIVE_FILE}`), url.pathname); +}; + +/** * Tests opening a hosted doc in the browser, ensuring it correctly navigates to * the doc's URL. */ -testcase.openFileDialogDriveHostedDoc = function() { - return openFileDialogClickOkButton( - 'drive', ENTRIES.testDocument.nameText, +testcase.openFileDialogDriveHostedDoc = async function() { + chrome.test.assertEq( + await openFileDialogClickOkButton( + 'drive', ENTRIES.testDocument.nameText, true), 'https://document_alternate_link/Test%20Document'); }; /** + * Tests that selecting a hosted doc from a dialog requiring a real file is + * disabled. + */ +testcase.openFileDialogDriveHostedNeedsFile = function() { + return openFileDialogExpectOkButtonDisabled( + 'drive', ENTRIES.testDocument.nameText, TEST_DRIVE_FILE); +}; + +/** + * Tests that selecting a hosted doc from a dialog requiring a real file is + * disabled. + */ +testcase.saveFileDialogDriveHostedNeedsFile = function() { + return openFileDialogExpectOkButtonDisabled( + 'drive', ENTRIES.testDocument.nameText, TEST_DRIVE_FILE, 'saveFile'); +}; + +/** * Tests opening file dialog on Drive and closing it with Cancel button. */ testcase.openFileDialogCancelDrive = function() {
diff --git a/ui/file_manager/integration_tests/remote_call.js b/ui/file_manager/integration_tests/remote_call.js index bc4f4c2f..2d68c3a 100644 --- a/ui/file_manager/integration_tests/remote_call.js +++ b/ui/file_manager/integration_tests/remote_call.js
@@ -331,6 +331,25 @@ }; /** + * Shorthand for clicking an element. + * @param {AppWindow} appWindow Application window. + * @param {string|!Array<string>} query Query to specify the element. + * If query is an array, |query[0]| specifies the first + * element(s), |query[1]| specifies elements inside the shadow DOM of + * the first element, and so on. + * @param {Promise} Promise to be fulfilled with the clicked element. + */ +RemoteCall.prototype.waitAndClickElement = function(windowId, query) { + return this.waitForElement(windowId, query).then(element => { + return this.callRemoteTestUtil('fakeMouseClick', windowId, [query]) + .then((result) => { + chrome.test.assertTrue(result, 'mouse click failed.'); + return element; + }); + }); +}; + +/** * Class to manipulate the window in the remote extension. * * @param {string} extensionId ID of extension to be manipulated. @@ -486,6 +505,8 @@ /** * Expands tree item. + * @param {string} windowId Target window ID. + * @param {string} query Query to the <tree-item> element. */ RemoteCallFilesApp.prototype.expandTreeItemInDirectoryTree = function( windowId, query) { @@ -500,11 +521,14 @@ return this.callRemoteTestUtil( 'focus', windowId, ['#directory-tree']); } - // Expand directory volume and set the focus to directory tree. - // Focus to directory tree. - return this - .callRemoteTestUtil( - 'fakeMouseClick', windowId, [`${query} .expand-icon`]) + + // We must wait until <tree-item> has attribute [has-children=true] + // otherwise it won't expand. We must also to account for the case + // :not([expanded]) to ensure it has NOT been expanded by some async + // operation since the [expanded] checks above. + const expandIcon = query + + ':not([expanded]) > .tree-row[has-children=true] > .expand-icon'; + return this.waitAndClickElement(windowId, expandIcon) .then(() => { // Wait for the expansion to finish. return this.waitForElement(windowId, query + '[expanded]'); @@ -534,13 +558,14 @@ if (index >= components.length - 1) return Promise.resolve(); + // First time we should expand the root/volume first. if (index === 0) { return this.expandVolumeInDirectoryTree(windowId, volumeType).then(() => { return this.expandDirectoryTreeForInternal_( windowId, components, index + 1, volumeType); }); } - const path = `/${components.slice(1, index + 1).join('/')}`; + const path = '/' + components.slice(1, index + 1).join('/'); return this .expandTreeItemInDirectoryTree( windowId, `[full-path-for-testing="${path}"]`) @@ -668,22 +693,6 @@ }; /** - * Shorthand for clicking an element. - * @param {AppWindow} appWindow Application window. - * @param {string|!Array<string>} query Query to specify the element. - * If query is an array, |query[0]| specifies the first - * element(s), |query[1]| specifies elements inside the shadow DOM of - * the first element, and so on. - * @param {Promise} Promise to be fulfilled with the clicked element. - */ -RemoteCallGallery.prototype.waitAndClickElement = function(windowId, query) { - return this.waitForElement(windowId, query).then(function(element) { - return this.callRemoteTestUtil('fakeMouseClick', windowId, [query]) - .then(function() { return element; }); - }.bind(this)); -}; - -/** * Waits for the "Press Enter" message. * * @param {AppWindow} appWindow App window.
diff --git a/ui/gfx/win/singleton_hwnd.cc b/ui/gfx/win/singleton_hwnd.cc index d97adfa..28e567bb 100644 --- a/ui/gfx/win/singleton_hwnd.cc +++ b/ui/gfx/win/singleton_hwnd.cc
@@ -21,6 +21,16 @@ LPARAM lparam, LRESULT& result, DWORD msg_map_id) { + if (!base::MessageLoopCurrentForUI::IsSet()) { + // If there is no MessageLoop and SingletonHwnd is receiving messages, this + // means it is receiving messages via an external message pump such as COM + // uninitialization. + // + // It is unsafe to forward these messages as observers may depend on the + // existence of a MessageLoop to proceed. + return false; + } + for (SingletonHwndObserver& observer : observer_list_) observer.OnWndProc(window, message, wparam, lparam); return false;
diff --git a/ui/gl/init/create_gr_gl_interface.cc b/ui/gl/init/create_gr_gl_interface.cc index 69512fb..69a65d0 100644 --- a/ui/gl/init/create_gr_gl_interface.cc +++ b/ui/gl/init/create_gr_gl_interface.cc
@@ -523,9 +523,6 @@ // functions->fCreateImage = nullptr; // functions->fDestroyImage = nullptr; - // GL 4.0 or GL_ARB_sample_shading or ES+GL_OES_sample_shading - functions->fMinSampleShading = gl->glMinSampleShadingFn; - functions->fFenceSync = gl->glFenceSyncFn; functions->fIsSync = gl->glIsSyncFn; functions->fClientWaitSync = gl->glClientWaitSyncFn;
diff --git a/ui/keyboard/BUILD.gn b/ui/keyboard/BUILD.gn index e35899d..a1c52d46 100644 --- a/ui/keyboard/BUILD.gn +++ b/ui/keyboard/BUILD.gn
@@ -87,6 +87,8 @@ sources = [ "test/keyboard_test_util.cc", "test/keyboard_test_util.h", + "test/test_keyboard_ui.cc", + "test/test_keyboard_ui.h", ] deps = [ ":keyboard",
diff --git a/ui/keyboard/keyboard_controller_unittest.cc b/ui/keyboard/keyboard_controller_unittest.cc index aed5e65c..603ab85 100644 --- a/ui/keyboard/keyboard_controller_unittest.cc +++ b/ui/keyboard/keyboard_controller_unittest.cc
@@ -35,6 +35,7 @@ #include "ui/keyboard/keyboard_ui.h" #include "ui/keyboard/keyboard_util.h" #include "ui/keyboard/test/keyboard_test_util.h" +#include "ui/keyboard/test/test_keyboard_ui.h" #include "ui/wm/core/default_activation_client.h" #if defined(USE_OZONE)
diff --git a/ui/keyboard/keyboard_util_unittest.cc b/ui/keyboard/keyboard_util_unittest.cc index b216525..3fda956 100644 --- a/ui/keyboard/keyboard_util_unittest.cc +++ b/ui/keyboard/keyboard_util_unittest.cc
@@ -11,6 +11,7 @@ #include "ui/keyboard/keyboard_ui.h" #include "ui/keyboard/keyboard_util.h" #include "ui/keyboard/test/keyboard_test_util.h" +#include "ui/keyboard/test/test_keyboard_ui.h" namespace keyboard { namespace {
diff --git a/ui/keyboard/test/keyboard_test_util.cc b/ui/keyboard/test/keyboard_test_util.cc index cd3e3f6..efeda891 100644 --- a/ui/keyboard/test/keyboard_test_util.cc +++ b/ui/keyboard/test/keyboard_test_util.cc
@@ -5,7 +5,6 @@ #include "ui/keyboard/test/keyboard_test_util.h" #include "base/run_loop.h" -#include "base/threading/sequenced_task_runner_handle.h" #include "base/time/time.h" #include "ui/display/screen.h" #include "ui/keyboard/keyboard_controller.h" @@ -88,38 +87,4 @@ root_bounds.width(), keyboard_height); } -TestKeyboardUI::TestKeyboardUI(ui::InputMethod* input_method) - : input_method_(input_method) {} - -TestKeyboardUI::~TestKeyboardUI() { - // Destroy the window before the delegate. - window_.reset(); -} - -aura::Window* TestKeyboardUI::LoadKeyboardWindow(LoadCallback callback) { - DCHECK(!window_); - window_ = std::make_unique<aura::Window>(&delegate_); - window_->Init(ui::LAYER_NOT_DRAWN); - window_->set_owned_by_parent(false); - - // Set a default size for the keyboard. - display::Screen* screen = display::Screen::GetScreen(); - window_->SetBounds( - KeyboardBoundsFromRootBounds(screen->GetPrimaryDisplay().bounds())); - - // Simulate an asynchronous load. - base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE, - std::move(callback)); - - return window_.get(); -} - -aura::Window* TestKeyboardUI::GetKeyboardWindow() const { - return window_.get(); -} - -ui::InputMethod* TestKeyboardUI::GetInputMethod() { - return input_method_; -} - } // namespace keyboard
diff --git a/ui/keyboard/test/keyboard_test_util.h b/ui/keyboard/test/keyboard_test_util.h index 48a01e75..0cacd08 100644 --- a/ui/keyboard/test/keyboard_test_util.h +++ b/ui/keyboard/test/keyboard_test_util.h
@@ -5,7 +5,6 @@ #ifndef UI_KEYBOARD_TEST_KEYBOARD_TEST_UTIL_H_ #define UI_KEYBOARD_TEST_KEYBOARD_TEST_UTIL_H_ -#include "ui/aura/test/test_window_delegate.h" #include "ui/keyboard/keyboard_ui.h" namespace gfx { @@ -31,25 +30,6 @@ gfx::Rect KeyboardBoundsFromRootBounds(const gfx::Rect& root_bounds, int keyboard_height = 100); -class TestKeyboardUI : public KeyboardUI { - public: - TestKeyboardUI(ui::InputMethod* input_method); - ~TestKeyboardUI() override; - - // Overridden from KeyboardUI: - aura::Window* LoadKeyboardWindow(LoadCallback callback) override; - aura::Window* GetKeyboardWindow() const override; - ui::InputMethod* GetInputMethod() override; - void ReloadKeyboardIfNeeded() override {} - - private: - std::unique_ptr<aura::Window> window_; - aura::test::TestWindowDelegate delegate_; - ui::InputMethod* input_method_; - - DISALLOW_COPY_AND_ASSIGN(TestKeyboardUI); -}; - } // namespace keyboard #endif // UI_KEYBOARD_TEST_KEYBOARD_TEST_UTIL_H_
diff --git a/ui/keyboard/test/test_keyboard_ui.cc b/ui/keyboard/test/test_keyboard_ui.cc new file mode 100644 index 0000000..98690159 --- /dev/null +++ b/ui/keyboard/test/test_keyboard_ui.cc
@@ -0,0 +1,48 @@ +// 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 "ui/keyboard/test/test_keyboard_ui.h" + +#include "base/threading/sequenced_task_runner_handle.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" +#include "ui/keyboard/test/keyboard_test_util.h" + +namespace keyboard { + +TestKeyboardUI::TestKeyboardUI(ui::InputMethod* input_method) + : input_method_(input_method) {} + +TestKeyboardUI::~TestKeyboardUI() { + // Destroy the window before the delegate. + window_.reset(); +} + +aura::Window* TestKeyboardUI::LoadKeyboardWindow(LoadCallback callback) { + DCHECK(!window_); + window_ = std::make_unique<aura::Window>(&delegate_); + window_->Init(ui::LAYER_NOT_DRAWN); + window_->set_owned_by_parent(false); + + // Set a default size for the keyboard. + display::Screen* screen = display::Screen::GetScreen(); + window_->SetBounds( + KeyboardBoundsFromRootBounds(screen->GetPrimaryDisplay().bounds())); + + // Simulate an asynchronous load. + base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE, + std::move(callback)); + + return window_.get(); +} + +aura::Window* TestKeyboardUI::GetKeyboardWindow() const { + return window_.get(); +} + +ui::InputMethod* TestKeyboardUI::GetInputMethod() { + return input_method_; +} + +} // namespace keyboard
diff --git a/ui/keyboard/test/test_keyboard_ui.h b/ui/keyboard/test/test_keyboard_ui.h new file mode 100644 index 0000000..9bb3080d --- /dev/null +++ b/ui/keyboard/test/test_keyboard_ui.h
@@ -0,0 +1,44 @@ +// 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 UI_KEYBOARD_TEST_TEST_KEYBOARD_UI_H_ +#define UI_KEYBOARD_TEST_TEST_KEYBOARD_UI_H_ + +#include <memory> + +#include "ui/aura/test/test_window_delegate.h" +#include "ui/keyboard/keyboard_ui.h" + +namespace aura { +class Window; +} + +namespace ui { +class InputMethod; +} + +namespace keyboard { + +class TestKeyboardUI : public KeyboardUI { + public: + TestKeyboardUI(ui::InputMethod* input_method); + ~TestKeyboardUI() override; + + // Overridden from KeyboardUI: + aura::Window* LoadKeyboardWindow(LoadCallback callback) override; + aura::Window* GetKeyboardWindow() const override; + ui::InputMethod* GetInputMethod() override; + void ReloadKeyboardIfNeeded() override {} + + private: + std::unique_ptr<aura::Window> window_; + aura::test::TestWindowDelegate delegate_; + ui::InputMethod* input_method_; + + DISALLOW_COPY_AND_ASSIGN(TestKeyboardUI); +}; + +} // namespace keyboard + +#endif
diff --git a/ui/shell_dialogs/BUILD.gn b/ui/shell_dialogs/BUILD.gn index bd4d92a1..b12b525 100644 --- a/ui/shell_dialogs/BUILD.gn +++ b/ui/shell_dialogs/BUILD.gn
@@ -45,6 +45,7 @@ "//skia", "//ui/base", "//ui/strings", + "//url", ] if (use_aura) {
diff --git a/ui/shell_dialogs/select_file_dialog.h b/ui/shell_dialogs/select_file_dialog.h index e8a4088..f8b7aea 100644 --- a/ui/shell_dialogs/select_file_dialog.h +++ b/ui/shell_dialogs/select_file_dialog.h
@@ -141,7 +141,12 @@ // NATIVE_PATH, the dialog creates a native replica of the non-native file // and returns its path, so that the caller can use it without any // difference than when it were local. - enum AllowedPaths { ANY_PATH, NATIVE_PATH, NATIVE_OR_DRIVE_PATH }; + enum AllowedPaths { + ANY_PATH, + NATIVE_PATH, + NATIVE_OR_DRIVE_PATH, + ANY_PATH_OR_URL + }; AllowedPaths allowed_paths; };
diff --git a/ui/shell_dialogs/selected_file_info.cc b/ui/shell_dialogs/selected_file_info.cc index 054c511..852eda6d 100644 --- a/ui/shell_dialogs/selected_file_info.cc +++ b/ui/shell_dialogs/selected_file_info.cc
@@ -15,6 +15,14 @@ display_name = in_file_path.BaseName().value(); } +SelectedFileInfo::SelectedFileInfo(const SelectedFileInfo& other) = default; +SelectedFileInfo::SelectedFileInfo(SelectedFileInfo&& other) = default; + SelectedFileInfo::~SelectedFileInfo() {} +SelectedFileInfo& SelectedFileInfo::operator=(const SelectedFileInfo& other) = + default; +SelectedFileInfo& SelectedFileInfo::operator=(SelectedFileInfo&& other) = + default; + } // namespace ui
diff --git a/ui/shell_dialogs/selected_file_info.h b/ui/shell_dialogs/selected_file_info.h index a1789c97..89de4e2f 100644 --- a/ui/shell_dialogs/selected_file_info.h +++ b/ui/shell_dialogs/selected_file_info.h
@@ -8,8 +8,10 @@ #include <vector> #include "base/files/file_path.h" +#include "base/optional.h" #include "base/strings/string16.h" #include "ui/shell_dialogs/shell_dialogs_export.h" +#include "url/gurl.h" namespace ui { @@ -31,10 +33,20 @@ // |path| is used for displaying. base::FilePath::StringType display_name; + // If set, this URL may be used to access the file. If the user is capable of + // using a URL to access the file, it should be used in preference to + // |local_path|. + base::Optional<GURL> url; + SelectedFileInfo(); SelectedFileInfo(const base::FilePath& in_file_path, const base::FilePath& in_local_path); + SelectedFileInfo(const SelectedFileInfo& other); + SelectedFileInfo(SelectedFileInfo&& other); ~SelectedFileInfo(); + + SelectedFileInfo& operator=(const SelectedFileInfo& other); + SelectedFileInfo& operator=(SelectedFileInfo&& other); }; } // namespace ui
diff --git a/ui/strings/ui_strings.grd b/ui/strings/ui_strings.grd index 146d3fe..b262891 100644 --- a/ui/strings/ui_strings.grd +++ b/ui/strings/ui_strings.grd
@@ -780,7 +780,7 @@ Back </message> <message name="IDS_APP_LIST_FOLDER_NAME_PLACEHOLDER" desc="The placeholder text for app list folder name."> - Unnamed Folder + Unnamed </message> <message name="IDS_APP_LIST_FOLDER_BUTTON_ACCESSIBILE_NAME" desc="The spoken feedback text for navigating to a folder button in top level app list"> Folder <ph name="folder_name">$1<ex>OEM Apps</ex></ph>
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index aea5b0fc..8a048ce 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -1133,6 +1133,7 @@ if (use_aura) { sources += [ "accessibility/ax_aura_obj_cache_unittest.cc", + "accessibility/ax_aura_window_utils_unittest.cc", "accessibility/ax_tree_source_views_unittest.cc", "controls/native/native_view_host_aura_unittest.cc", "corewm/tooltip_controller_unittest.cc", @@ -1175,9 +1176,6 @@ # are only useful for views_unittests, and not in views_mus_unittests. "touchui/touch_selection_controller_impl_unittest.cc", "widget/native_widget_aura_unittest.cc", - - # Doesn't work in views_mus_unittests yet. crbug.com/911945 - "accessibility/ax_aura_window_utils_unittest.cc", ] if (is_mac) {
diff --git a/ui/views/accessibility/ax_aura_obj_cache.cc b/ui/views/accessibility/ax_aura_obj_cache.cc index 7c840f0..4a1567a 100644 --- a/ui/views/accessibility/ax_aura_obj_cache.cc +++ b/ui/views/accessibility/ax_aura_obj_cache.cc
@@ -207,7 +207,7 @@ if (it != aura_view_to_id_map.end()) return Get(it->second); - auto wrapper = std::make_unique<AuraViewWrapper>(aura_view); + auto wrapper = std::make_unique<AuraViewWrapper>(this, aura_view); int32_t id = wrapper->GetUniqueId(); aura_view_to_id_map[aura_view] = id; cache_[id] = std::move(wrapper);
diff --git a/ui/views/accessibility/ax_view_obj_wrapper.cc b/ui/views/accessibility/ax_view_obj_wrapper.cc index d8c900e..2100f6b 100644 --- a/ui/views/accessibility/ax_view_obj_wrapper.cc +++ b/ui/views/accessibility/ax_view_obj_wrapper.cc
@@ -14,9 +14,10 @@ namespace views { -AXViewObjWrapper::AXViewObjWrapper(View* view) : view_(view) { +AXViewObjWrapper::AXViewObjWrapper(AXAuraObjCache* aura_obj_cache, View* view) + : aura_obj_cache_(aura_obj_cache), view_(view) { if (view->GetWidget()) - AXAuraObjCache::GetInstance()->GetOrCreate(view->GetWidget()); + aura_obj_cache_->GetOrCreate(view->GetWidget()); view->AddObserver(this); } @@ -35,12 +36,11 @@ if (!view_) return nullptr; - AXAuraObjCache* cache = AXAuraObjCache::GetInstance(); if (view_->parent()) - return cache->GetOrCreate(view_->parent()); + return aura_obj_cache_->GetOrCreate(view_->parent()); if (view_->GetWidget()) - return cache->GetOrCreate(view_->GetWidget()); + return aura_obj_cache_->GetOrCreate(view_->GetWidget()); return nullptr; } @@ -58,8 +58,7 @@ if (!view_->child_at(i)->visible()) continue; - AXAuraObjWrapper* child = - AXAuraObjCache::GetInstance()->GetOrCreate(view_->child_at(i)); + AXAuraObjWrapper* child = aura_obj_cache_->GetOrCreate(view_->child_at(i)); out_children->push_back(child); } }
diff --git a/ui/views/accessibility/ax_view_obj_wrapper.h b/ui/views/accessibility/ax_view_obj_wrapper.h index 5a16030..545468ee 100644 --- a/ui/views/accessibility/ax_view_obj_wrapper.h +++ b/ui/views/accessibility/ax_view_obj_wrapper.h
@@ -12,12 +12,14 @@ #include "ui/views/view_observer.h" namespace views { +class AXAuraObjCache; class View; // Describes a |View| for use with other AX classes. class AXViewObjWrapper : public AXAuraObjWrapper, public ViewObserver { public: - explicit AXViewObjWrapper(View* view); + // |aura_obj_cache| must outlive this object. + AXViewObjWrapper(AXAuraObjCache* aura_obj_cache, View* view); ~AXViewObjWrapper() override; View* view() { return view_; } @@ -34,6 +36,8 @@ void OnViewIsDeleting(View* observed_view) override; private: + AXAuraObjCache* const aura_obj_cache_; + View* view_; DISALLOW_COPY_AND_ASSIGN(AXViewObjWrapper);
diff --git a/ui/views/accessibility/ax_widget_obj_wrapper.cc b/ui/views/accessibility/ax_widget_obj_wrapper.cc index e3cd96c..d584b14 100644 --- a/ui/views/accessibility/ax_widget_obj_wrapper.cc +++ b/ui/views/accessibility/ax_widget_obj_wrapper.cc
@@ -13,13 +13,15 @@ namespace views { -AXWidgetObjWrapper::AXWidgetObjWrapper(Widget* widget) : widget_(widget) { +AXWidgetObjWrapper::AXWidgetObjWrapper(AXAuraObjCache* aura_obj_cache, + Widget* widget) + : aura_obj_cache_(aura_obj_cache), widget_(widget) { widget->AddObserver(this); widget->AddRemovalsObserver(this); } AXWidgetObjWrapper::~AXWidgetObjWrapper() { - if (!AXAuraObjCache::GetInstance()->is_destroying()) { + if (!aura_obj_cache_->is_destroying()) { widget_->RemoveObserver(this); widget_->RemoveRemovalsObserver(this); } @@ -31,7 +33,7 @@ } AXAuraObjWrapper* AXWidgetObjWrapper::GetParent() { - return AXAuraObjCache::GetInstance()->GetOrCreate(widget_->GetNativeView()); + return aura_obj_cache_->GetOrCreate(widget_->GetNativeView()); } void AXWidgetObjWrapper::GetChildren( @@ -41,8 +43,7 @@ return; } - out_children->push_back( - AXAuraObjCache::GetInstance()->GetOrCreate(widget_->GetRootView())); + out_children->push_back(aura_obj_cache_->GetOrCreate(widget_->GetRootView())); } void AXWidgetObjWrapper::Serialize(ui::AXNodeData* out_node_data) { @@ -62,21 +63,21 @@ } void AXWidgetObjWrapper::OnWidgetDestroying(Widget* widget) { - AXAuraObjCache::GetInstance()->Remove(widget); + aura_obj_cache_->Remove(widget); } void AXWidgetObjWrapper::OnWidgetClosing(Widget* widget) { - AXAuraObjCache::GetInstance()->Remove(widget); + aura_obj_cache_->Remove(widget); } void AXWidgetObjWrapper::OnWidgetVisibilityChanged(Widget*, bool) { // If a widget changes visibility it may affect what's focused, in particular // when a widget that contains the focused view gets hidden. - AXAuraObjCache::GetInstance()->OnFocusedViewChanged(); + aura_obj_cache_->OnFocusedViewChanged(); } void AXWidgetObjWrapper::OnWillRemoveView(Widget* widget, View* view) { - AXAuraObjCache::GetInstance()->RemoveViewSubtree(view); + aura_obj_cache_->RemoveViewSubtree(view); } } // namespace views
diff --git a/ui/views/accessibility/ax_widget_obj_wrapper.h b/ui/views/accessibility/ax_widget_obj_wrapper.h index 283efcb7..080c21a 100644 --- a/ui/views/accessibility/ax_widget_obj_wrapper.h +++ b/ui/views/accessibility/ax_widget_obj_wrapper.h
@@ -14,6 +14,7 @@ #include "ui/views/widget/widget_removals_observer.h" namespace views { +class AXAuraObjCache; class Widget; // Describes a |Widget| for use with other AX classes. @@ -21,7 +22,8 @@ public WidgetObserver, public WidgetRemovalsObserver { public: - explicit AXWidgetObjWrapper(Widget* widget); + // |aura_obj_cache| must outlive this object. + AXWidgetObjWrapper(AXAuraObjCache* aura_obj_cache, Widget* widget); ~AXWidgetObjWrapper() override; // AXAuraObjWrapper overrides. @@ -40,6 +42,8 @@ void OnWillRemoveView(Widget* widget, View* view) override; private: + AXAuraObjCache* const aura_obj_cache_; + Widget* widget_; const ui::AXUniqueId unique_id_;
diff --git a/ui/views/accessibility/ax_window_obj_wrapper.cc b/ui/views/accessibility/ax_window_obj_wrapper.cc index c61835e6..72fbca0 100644 --- a/ui/views/accessibility/ax_window_obj_wrapper.cc +++ b/ui/views/accessibility/ax_window_obj_wrapper.cc
@@ -18,45 +18,45 @@ #include "ui/views/widget/widget.h" namespace views { +namespace { -// A helper to fire an event on a window, taking into account its associated -// widget and that widget's root view. -void FireEvent(aura::Window* window, ax::mojom::Event event_type) { - AXAuraObjCache::GetInstance()->FireEvent( - AXAuraObjCache::GetInstance()->GetOrCreate(window), event_type); - +Widget* GetWidgetForWindow(aura::Window* window) { Widget* widget = Widget::GetWidgetForNativeView(window); - if (widget) { - AXAuraObjCache::GetInstance()->FireEvent( - AXAuraObjCache::GetInstance()->GetOrCreate(widget), event_type); + if (!widget) + return nullptr; - views::View* root_view = widget->GetRootView(); - if (root_view) - root_view->NotifyAccessibilityEvent(event_type, true); + // Under mus/mash both the WindowTreeHost's root aura::Window and the content + // aura::Window will return the same Widget for GetWidgetForNativeView(). Only + // return the Widget for the content window, not the root, since otherwise + // we'll end up with two children in the AX node tree that have the same + // parent. + if (widget->GetNativeWindow() != window) { + DCHECK(window->IsRootWindow()); + return nullptr; } - aura::Window::Windows children = - AXAuraWindowUtils::Get()->GetChildren(window); - for (size_t i = 0; i < children.size(); ++i) - FireEvent(children[i], ax::mojom::Event::kLocationChanged); + return widget; } -AXWindowObjWrapper::AXWindowObjWrapper(aura::Window* window) - : window_(window), +} // namespace + +AXWindowObjWrapper::AXWindowObjWrapper(AXAuraObjCache* aura_obj_cache, + aura::Window* window) + : aura_obj_cache_(aura_obj_cache), + window_(window), is_alert_(false), is_root_window_(window->IsRootWindow()) { window->AddObserver(this); if (is_root_window_) - AXAuraObjCache::GetInstance()->OnRootWindowObjCreated(window); + aura_obj_cache_->OnRootWindowObjCreated(window); } AXWindowObjWrapper::~AXWindowObjWrapper() { if (is_root_window_) - AXAuraObjCache::GetInstance()->OnRootWindowObjDestroyed(window_); + aura_obj_cache_->OnRootWindowObjDestroyed(window_); window_->RemoveObserver(this); - window_ = NULL; } bool AXWindowObjWrapper::IsIgnored() { @@ -68,7 +68,7 @@ if (!parent) return nullptr; - return AXAuraObjCache::GetInstance()->GetOrCreate(parent); + return aura_obj_cache_->GetOrCreate(parent); } void AXWindowObjWrapper::GetChildren( @@ -76,14 +76,13 @@ aura::Window::Windows children = AXAuraWindowUtils::Get()->GetChildren(window_); for (size_t i = 0; i < children.size(); ++i) { - out_children->push_back( - AXAuraObjCache::GetInstance()->GetOrCreate(children[i])); + out_children->push_back(aura_obj_cache_->GetOrCreate(children[i])); } // Also consider any associated widgets as children. - Widget* widget = Widget::GetWidgetForNativeView(window_); + Widget* widget = GetWidgetForWindow(window_); if (widget && widget->IsVisible()) - out_children->push_back(AXAuraObjCache::GetInstance()->GetOrCreate(widget)); + out_children->push_back(aura_obj_cache_->GetOrCreate(widget)); } void AXWindowObjWrapper::Serialize(ui::AXNodeData* out_node_data) { @@ -111,7 +110,7 @@ // To avoid this double-parenting, only add the child tree ID of this // window if the top-level window doesn't have an associated Widget. if (!window_->GetToplevelWindow() || - Widget::GetWidgetForNativeView(window_->GetToplevelWindow())) { + GetWidgetForWindow(window_->GetToplevelWindow())) { return; } @@ -125,19 +124,19 @@ } void AXWindowObjWrapper::OnWindowDestroyed(aura::Window* window) { - AXAuraObjCache::GetInstance()->Remove(window, nullptr); + aura_obj_cache_->Remove(window, nullptr); } void AXWindowObjWrapper::OnWindowDestroying(aura::Window* window) { - Widget* widget = Widget::GetWidgetForNativeView(window); + Widget* widget = GetWidgetForWindow(window); if (widget) - AXAuraObjCache::GetInstance()->Remove(widget); + aura_obj_cache_->Remove(widget); } void AXWindowObjWrapper::OnWindowHierarchyChanged( const HierarchyChangeParams& params) { if (params.phase == WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED) - AXAuraObjCache::GetInstance()->Remove(params.target, params.old_parent); + aura_obj_cache_->Remove(params.target, params.old_parent); } void AXWindowObjWrapper::OnWindowBoundsChanged( @@ -155,15 +154,13 @@ const void* key, intptr_t old) { if (window == window_ && key == ui::kChildAXTreeID) { - AXAuraObjCache::GetInstance()->FireEvent( - this, ax::mojom::Event::kChildrenChanged); + aura_obj_cache_->FireEvent(this, ax::mojom::Event::kChildrenChanged); } } void AXWindowObjWrapper::OnWindowVisibilityChanged(aura::Window* window, bool visible) { - AXAuraObjCache::GetInstance()->FireEvent(this, - ax::mojom::Event::kStateChanged); + aura_obj_cache_->FireEvent(this, ax::mojom::Event::kStateChanged); } void AXWindowObjWrapper::OnWindowTransformed(aura::Window* window, @@ -178,4 +175,24 @@ FireEvent(window, ax::mojom::Event::kTextChanged); } +void AXWindowObjWrapper::FireEvent(aura::Window* window, + ax::mojom::Event event_type) { + aura_obj_cache_->FireEvent(aura_obj_cache_->GetOrCreate(window), event_type); + + Widget* widget = GetWidgetForWindow(window); + if (widget) { + aura_obj_cache_->FireEvent(aura_obj_cache_->GetOrCreate(widget), + event_type); + + views::View* root_view = widget->GetRootView(); + if (root_view) + root_view->NotifyAccessibilityEvent(event_type, true); + } + + aura::Window::Windows children = + AXAuraWindowUtils::Get()->GetChildren(window); + for (size_t i = 0; i < children.size(); ++i) + FireEvent(children[i], ax::mojom::Event::kLocationChanged); +} + } // namespace views
diff --git a/ui/views/accessibility/ax_window_obj_wrapper.h b/ui/views/accessibility/ax_window_obj_wrapper.h index de81358..d0e3a797 100644 --- a/ui/views/accessibility/ax_window_obj_wrapper.h +++ b/ui/views/accessibility/ax_window_obj_wrapper.h
@@ -8,6 +8,7 @@ #include <stdint.h> #include "base/macros.h" +#include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/platform/ax_unique_id.h" #include "ui/aura/window_observer.h" #include "ui/views/accessibility/ax_aura_obj_wrapper.h" @@ -17,12 +18,14 @@ } // namespace aura namespace views { +class AXAuraObjCache; // Describes a |Window| for use with other AX classes. class AXWindowObjWrapper : public AXAuraObjWrapper, public aura::WindowObserver { public: - explicit AXWindowObjWrapper(aura::Window* window); + // |aura_obj_cache| and |window| must outlive this object. + AXWindowObjWrapper(AXAuraObjCache* aura_obj_cache, aura::Window* window); ~AXWindowObjWrapper() override; // Whether this window is an alert window. @@ -55,6 +58,12 @@ void OnWindowTitleChanged(aura::Window* window) override; private: + // Fires an event on a window, taking into account its associated widget and + // that widget's root view. + void FireEvent(aura::Window* window, ax::mojom::Event event_type); + + AXAuraObjCache* const aura_obj_cache_; + aura::Window* window_; bool is_alert_;
diff --git a/ui/views/accessibility/view_accessibility.cc b/ui/views/accessibility/view_accessibility.cc index cc6ede1..226bda50 100644 --- a/ui/views/accessibility/view_accessibility.cc +++ b/ui/views/accessibility/view_accessibility.cc
@@ -225,7 +225,7 @@ gfx::NativeViewAccessible ViewAccessibility::GetFocusedDescendant() { if (focused_virtual_child_) return focused_virtual_child_->GetNativeObject(); - return GetNativeObject(); + return view_->GetNativeViewAccessible(); } } // namespace views
diff --git a/ui/views/cocoa/bridged_native_widget_unittest.mm b/ui/views/cocoa/bridged_native_widget_unittest.mm index 00df4d7..8f19410 100644 --- a/ui/views/cocoa/bridged_native_widget_unittest.mm +++ b/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -299,7 +299,7 @@ explicit MockNativeWidgetMac(internal::NativeWidgetDelegate* delegate) : NativeWidgetMac(delegate) {} using NativeWidgetMac::bridge_impl; - using NativeWidgetMac::bridge_host_for_testing; + using NativeWidgetMac::bridge_host; // internal::NativeWidgetPrivate: void InitNativeWidget(const Widget::InitParams& params) override { @@ -311,19 +311,19 @@ styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]); - bridge_host_for_testing()->CreateLocalBridge(window); + bridge_host()->CreateLocalBridge(window); if (auto* parent = BridgedNativeWidgetHostImpl::GetFromNativeView(params.parent)) { - bridge_host_for_testing()->SetParent(parent); + bridge_host()->SetParent(parent); } - bridge_host_for_testing()->InitWindow(params); + bridge_host()->InitWindow(params); // Usually the bridge gets initialized here. It is skipped to run extra // checks in tests, and so that a second window isn't created. delegate()->OnNativeWidgetCreated(true); // To allow events to dispatch to a view, it needs a way to get focus. - bridge_host_for_testing()->SetFocusManager(GetWidget()->GetFocusManager()); + bridge_host()->SetFocusManager(GetWidget()->GetFocusManager()); } void ReorderNativeViews() override { @@ -350,7 +350,7 @@ return native_widget_mac_->bridge_impl(); } BridgedNativeWidgetHostImpl* bridge_host() { - return native_widget_mac_->bridge_host_for_testing(); + return native_widget_mac_->bridge_host(); } // Generate an autoreleased KeyDown NSEvent* in |widget_| for pressing the
diff --git a/ui/views/layout/layout_manager.cc b/ui/views/layout/layout_manager.cc index 877a9f31..db1a13f 100644 --- a/ui/views/layout/layout_manager.cc +++ b/ui/views/layout/layout_manager.cc
@@ -4,6 +4,7 @@ #include "ui/views/layout/layout_manager.h" +#include "base/auto_reset.h" #include "ui/views/view.h" namespace views { @@ -39,4 +40,12 @@ void LayoutManager::ViewRemoved(View* host, View* view) { } +void LayoutManager::ViewVisibilitySet(View* host, View* view, bool visible) {} + +void LayoutManager::SetViewVisibility(View* view, bool visible) { + DCHECK_EQ(view->parent()->GetLayoutManager(), this); + base::AutoReset<View*> setter(&view_setting_visibility_on_, view); + view->SetVisible(visible); +} + } // namespace views
diff --git a/ui/views/layout/layout_manager.h b/ui/views/layout/layout_manager.h index ee1bfda..4cd0e8a4 100644 --- a/ui/views/layout/layout_manager.h +++ b/ui/views/layout/layout_manager.h
@@ -71,6 +71,20 @@ // been installed on. This function allows the LayoutManager to cleanup any // state it has kept specific to a View. virtual void ViewRemoved(View* host, View* view); + + // Called when View::SetVisible() is called by external code. Classes derived + // from LayoutManager can call SetViewVisibility() below to avoid triggering + // this event. + virtual void ViewVisibilitySet(View* host, View* view, bool visible); + + protected: + // Sets the visibility of a view without triggering ViewVisibilitySet(). + // During Layout(), use this method instead of View::SetVisibility(). + void SetViewVisibility(View* view, bool visible); + + private: + friend class views::View; + View* view_setting_visibility_on_ = nullptr; }; } // namespace views
diff --git a/ui/views/view.cc b/ui/views/view.cc index 922e1cdf..6c1764f 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc
@@ -155,85 +155,6 @@ return const_cast<Widget*>(const_cast<const View*>(this)->GetWidget()); } -void View::AddChildView(View* view) { - if (view->parent_ == this) - return; - AddChildViewAt(view, child_count()); -} - -void View::AddChildViewAt(View* view, int index) { - CHECK_NE(view, this) << "You cannot add a view as its own child"; - DCHECK_GE(index, 0); - DCHECK_LE(index, child_count()); - - // If |view| has a parent, remove it from its parent. - View* parent = view->parent_; - ui::NativeTheme* old_theme = nullptr; - Widget* old_widget = nullptr; - if (parent) { - old_theme = view->GetNativeTheme(); - old_widget = view->GetWidget(); - if (parent == this) { - ReorderChildView(view, index); - return; - } - parent->DoRemoveChildView(view, true, true, false, this); - } - - // Sets the prev/next focus views. - InitFocusSiblings(view, index); - - view->parent_ = this; -#if DCHECK_IS_ON() - DCHECK(!iterating_); -#endif - children_.insert(children_.begin() + index, view); - - // Ensure the layer tree matches the view tree before calling to any client - // code. This way if client code further modifies the view tree we are in a - // sane state. - const bool did_reparent_any_layers = view->UpdateParentLayers(); - Widget* widget = GetWidget(); - if (did_reparent_any_layers && widget) - widget->LayerTreeChanged(); - - ReorderLayers(); - - // Make sure the visibility of the child layers are correct. - // If any of the parent View is hidden, then the layers of the subtree - // rooted at |this| should be hidden. Otherwise, all the child layers should - // inherit the visibility of the owner View. - view->UpdateLayerVisibility(); - - if (widget) { - const ui::NativeTheme* new_theme = view->GetNativeTheme(); - if (new_theme != old_theme) - view->PropagateNativeThemeChanged(new_theme); - } - - ViewHierarchyChangedDetails details(true, this, view, parent); - - for (View* v = this; v; v = v->parent_) - v->ViewHierarchyChangedImpl(false, details); - - view->PropagateAddNotifications(details, widget && widget != old_widget); - - UpdateTooltip(); - - if (widget) { - RegisterChildrenForVisibleBoundsNotification(view); - - if (view->visible()) - view->SchedulePaint(); - } - - if (layout_manager_.get()) - layout_manager_->ViewAdded(this, view); - - for (ViewObserver& observer : observers_) - observer.OnChildViewAdded(this, view); -} - void View::ReorderChildView(View* view, int index) { DCHECK_EQ(view->parent_, this); if (index < 0) @@ -266,6 +187,7 @@ observer.OnChildViewReordered(this, view); ReorderLayers(); + InvalidateLayout(); } void View::RemoveChildView(View* view) { @@ -439,6 +361,12 @@ } void View::SetVisible(bool visible) { + if (parent_) { + LayoutManager* const layout_manager = parent_->GetLayoutManager(); + if (layout_manager && layout_manager->view_setting_visibility_on_ != this) + layout_manager->ViewVisibilitySet(parent_, this, visible); + } + if (visible != visible_) { // If the View is currently visible, schedule paint to refresh parent. // TODO(beng): not sure we should be doing this if we have a layer. @@ -1973,6 +1901,79 @@ // Tree operations ------------------------------------------------------------- +void View::AddChildViewAtImpl(View* view, int index) { + CHECK_NE(view, this) << "You cannot add a view as its own child"; + DCHECK_GE(index, 0); + DCHECK_LE(index, child_count()); + + // If |view| has a parent, remove it from its parent. + View* parent = view->parent_; + ui::NativeTheme* old_theme = nullptr; + Widget* old_widget = nullptr; + if (parent) { + old_theme = view->GetNativeTheme(); + old_widget = view->GetWidget(); + if (parent == this) { + ReorderChildView(view, index); + return; + } + parent->DoRemoveChildView(view, true, true, false, this); + } + + // Sets the prev/next focus views. + InitFocusSiblings(view, index); + + view->parent_ = this; +#if DCHECK_IS_ON() + DCHECK(!iterating_); +#endif + children_.insert(children_.begin() + index, view); + + // Ensure the layer tree matches the view tree before calling to any client + // code. This way if client code further modifies the view tree we are in a + // sane state. + const bool did_reparent_any_layers = view->UpdateParentLayers(); + Widget* widget = GetWidget(); + if (did_reparent_any_layers && widget) + widget->LayerTreeChanged(); + + ReorderLayers(); + + // Make sure the visibility of the child layers are correct. + // If any of the parent View is hidden, then the layers of the subtree + // rooted at |this| should be hidden. Otherwise, all the child layers should + // inherit the visibility of the owner View. + view->UpdateLayerVisibility(); + + if (widget) { + const ui::NativeTheme* new_theme = view->GetNativeTheme(); + if (new_theme != old_theme) + view->PropagateNativeThemeChanged(new_theme); + } + + ViewHierarchyChangedDetails details(true, this, view, parent); + + for (View* v = this; v; v = v->parent_) + v->ViewHierarchyChangedImpl(false, details); + + view->PropagateAddNotifications(details, widget && widget != old_widget); + + UpdateTooltip(); + + if (widget) { + RegisterChildrenForVisibleBoundsNotification(view); + + if (view->visible()) + view->SchedulePaint(); + } + + if (layout_manager_.get()) + layout_manager_->ViewAdded(this, view); + + for (ViewObserver& observer : observers_) + observer.OnChildViewAdded(this, view); +} + void View::DoRemoveChildView(View* view, bool update_focus_cycle, bool update_tool_tip,
diff --git a/ui/views/view.h b/ui/views/view.h index 998c87a3..6cecb0d 100644 --- a/ui/views/view.h +++ b/ui/views/view.h
@@ -273,8 +273,37 @@ virtual Widget* GetWidget(); // Adds |view| as a child of this view, optionally at |index|. - void AddChildView(View* view); - void AddChildViewAt(View* view, int index); + // Returns the raw pointer for callers which want to hold a pointer to the + // added view. This requires declaring the function as a template in order to + // return the actual passed-in type. + template <typename T> + T* AddChildView(std::unique_ptr<T> view) { + DCHECK(!view->owned_by_client()) + << "This should only be called if the client is passing ownership of " + "|view| to the parent View."; + return AddChildView<T>(view.release()); + } + template <typename T> + T* AddChildViewAt(std::unique_ptr<T> view, int index) { + DCHECK(!view->owned_by_client()) + << "This should only be called if the client is passing ownership of " + "|view| to the parent View."; + return AddChildViewAt<T>(view.release(), index); + } + + // Prefer using the AddChildView(std::unique_ptr) overloads over raw pointers + // for new code. + template <typename T> + T* AddChildView(T* view) { + if (static_cast<View*>(view)->parent_ != this) + AddChildViewAtImpl(view, child_count()); + return view; + } + template <typename T> + T* AddChildViewAt(T* view, int index) { + AddChildViewAtImpl(view, index); + return view; + } // Moves |view| to the specified |index|. A negative value for |index| moves // the view at the end. @@ -1461,6 +1490,9 @@ // Tree operations ----------------------------------------------------------- + // Adds |view| as a child of this view at |index|. + void AddChildViewAtImpl(View* view, int index); + // Removes |view| from the hierarchy tree. If |update_focus_cycle| is true, // the next and previous focusable views of views pointing to this view are // updated. If |update_tool_tip| is true, the tooltip is updated. If
diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc index ed53e0c..00223d3 100644 --- a/ui/views/view_unittest.cc +++ b/ui/views/view_unittest.cc
@@ -3573,15 +3573,11 @@ TEST_F(ViewTest, ReorderChildren) { View root; - View* child = new View(); - root.AddChildView(child); + View* child = root.AddChildView(std::make_unique<View>()); - View* foo1 = new View(); - child->AddChildView(foo1); - View* foo2 = new View(); - child->AddChildView(foo2); - View* foo3 = new View(); - child->AddChildView(foo3); + View* foo1 = child->AddChildView(std::make_unique<View>()); + View* foo2 = child->AddChildView(std::make_unique<View>()); + View* foo3 = child->AddChildView(std::make_unique<View>()); foo1->SetFocusBehavior(View::FocusBehavior::ALWAYS); foo2->SetFocusBehavior(View::FocusBehavior::ALWAYS); foo3->SetFocusBehavior(View::FocusBehavior::ALWAYS); @@ -3728,13 +3724,11 @@ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; widget.Init(params); - View* view1 = new View(); + View* view1 = widget.GetRootView()->AddChildView(std::make_unique<View>()); view1->SetFocusBehavior(View::FocusBehavior::ALWAYS); - widget.GetRootView()->AddChildView(view1); - View* view2 = new View(); + View* view2 = widget.GetRootView()->AddChildView(std::make_unique<View>()); view2->SetFocusBehavior(View::FocusBehavior::ALWAYS); - widget.GetRootView()->AddChildView(view2); FocusManager* focus_manager = widget.GetFocusManager(); ASSERT_TRUE(focus_manager); @@ -3905,16 +3899,13 @@ widget()->SetContentsView(content_view); // Create v1, give it a bounds and verify everything is set up correctly. - View* v1 = new View; - content_view->AddChildView(v1); + View* v1 = content_view->AddChildView(std::make_unique<View>()); v1->SetBoundsRect(gfx::Rect(20, 30, 140, 150)); - View* v2 = new View; - v1->AddChildView(v2); + View* v2 = v1->AddChildView(std::make_unique<View>()); - View* v3 = new View; + View* v3 = v2->AddChildView(std::make_unique<View>()); v3->SetPaintToLayer(); - v2->AddChildView(v3); ASSERT_TRUE(v3->layer() != NULL); // At this point we have v1-v2-v3. v3 has a layer, v1 and v2 don't. @@ -3927,8 +3918,7 @@ View* content_view = new View; widget()->SetContentsView(content_view); - View* v1 = new View; - content_view->AddChildView(v1); + View* v1 = content_view->AddChildView(std::make_unique<View>()); v1->SetPaintToLayer(); EXPECT_TRUE(v1->layer() != NULL); @@ -3948,13 +3938,11 @@ View* content_view = new View; widget()->SetContentsView(content_view); - View* v1 = new View; - content_view->AddChildView(v1); + View* v1 = content_view->AddChildView(std::make_unique<View>()); v1->SetBoundsRect(gfx::Rect(20, 30, 140, 150)); - View* v2 = new View; + View* v2 = v1->AddChildView(std::make_unique<View>()); v2->SetBoundsRect(gfx::Rect(10, 11, 40, 50)); - v1->AddChildView(v2); v2->SetPaintToLayer(); ASSERT_TRUE(v2->layer() != NULL); EXPECT_EQ(gfx::Rect(30, 41, 40, 50), v2->layer()->bounds()); @@ -4038,10 +4026,9 @@ int content_width = view->width(); // Create a paints-to-layer view |v1|. - View* v1 = new View; + View* v1 = view->AddChildView(std::make_unique<View>()); v1->SetPaintToLayer(); v1->SetBounds(10, 10, 20, 10); - view->AddChildView(v1); EXPECT_EQ(gfx::Rect(content_width - 30, 10, 20, 10), v1->layer()->bounds()); @@ -4239,9 +4226,8 @@ TestView parent_view; parent_view.SetBounds(10, 10, 100, 100); - TestView* child_view = new TestView; + TestView* child_view = parent_view.AddChildView(std::make_unique<TestView>()); child_view->SetBounds(5, 6, 10, 20); - parent_view.AddChildView(child_view); parent_view.scheduled_paint_rects_.clear(); SchedulePaintOnParent(child_view); @@ -4254,8 +4240,7 @@ TestView parent_view; parent_view.SetBounds(10, 11, 12, 13); - TestView* child_view = new TestView; - parent_view.AddChildView(child_view); + TestView* child_view = parent_view.AddChildView(std::make_unique<TestView>()); parent_view.scheduled_paint_rects_.clear(); child_view->SetPaintToLayer(); @@ -4266,9 +4251,8 @@ TestView parent_view; parent_view.SetBounds(10, 11, 12, 13); - TestView* child_view = new TestView; + TestView* child_view = parent_view.AddChildView(std::make_unique<TestView>()); child_view->SetPaintToLayer(); - parent_view.AddChildView(child_view); parent_view.scheduled_paint_rects_.clear(); EXPECT_EQ(0U, parent_view.scheduled_paint_rects_.size()); @@ -4281,16 +4265,13 @@ v1->SetPaintToLayer(); widget()->SetContentsView(v1); - View* v2 = new View; - v1->AddChildView(v2); + View* v2 = v1->AddChildView(std::make_unique<View>()); - View* v3 = new View; - v2->AddChildView(v3); + View* v3 = v2->AddChildView(std::make_unique<View>()); v3->SetVisible(false); - View* v4 = new View; + View* v4 = v3->AddChildView(std::make_unique<View>()); v4->SetPaintToLayer(); - v3->AddChildView(v4); EXPECT_TRUE(v1->layer()->IsDrawn()); EXPECT_FALSE(v4->layer()->IsDrawn()); @@ -4347,12 +4328,10 @@ TEST_F(ViewLayerTest, ReorderUnderWidget) { View* content = new View; widget()->SetContentsView(content); - View* c1 = new View; + View* c1 = content->AddChildView(std::make_unique<View>()); c1->SetPaintToLayer(); - content->AddChildView(c1); - View* c2 = new View; + View* c2 = content->AddChildView(std::make_unique<View>()); c2->SetPaintToLayer(); - content->AddChildView(c2); ui::Layer* parent_layer = c1->layer()->parent(); ASSERT_TRUE(parent_layer); @@ -4390,12 +4369,10 @@ std::unique_ptr<View> v(new View()); v->SetPaintToLayer(); - View* v1 = new View(); + View* v1 = v->AddChildView(std::make_unique<View>()); v1->SetPaintToLayer(); - v->AddChildView(v1); - View* v2 = new View(); + View* v2 = v->AddChildView(std::make_unique<View>()); v2->SetPaintToLayer(); - v->AddChildView(v2); // Test the initial z-order. const std::vector<ui::Layer*>& child_layers_pre = v->layer()->children(); @@ -4420,12 +4397,10 @@ View* v = new View(); widget()->SetContentsView(v); - View* v1 = new View(); + View* v1 = v->AddChildView(std::make_unique<View>()); v1->SetPaintToLayer(); - v->AddChildView(v1); - View* v2 = new View(); + View* v2 = v->AddChildView(std::make_unique<View>()); v2->SetPaintToLayer(); - v->AddChildView(v2); ui::Layer* root_layer = GetRootLayer(); @@ -4488,8 +4463,7 @@ TEST_F(ViewLayerTest, SnapLayerToPixel) { View* v1 = new View; - View* v11 = new View; - v1->AddChildView(v11); + View* v11 = v1->AddChildView(std::make_unique<View>()); widget()->SetContentsView(v1); @@ -4585,10 +4559,8 @@ TEST_F(ViewLayerPixelCanvasTest, SnapLayerToPixel) { View* v1 = new View; - View* v2 = new View; - PaintLayerView* v3 = new PaintLayerView; - v1->AddChildView(v2); - v2->AddChildView(v3); + View* v2 = v1->AddChildView(std::make_unique<View>()); + PaintLayerView* v3 = v2->AddChildView(std::make_unique<PaintLayerView>()); widget()->SetContentsView(v1); @@ -4670,12 +4642,12 @@ TEST_F(ViewTest, OnNativeThemeChanged) { TestView* test_view = new TestView(); EXPECT_FALSE(test_view->native_theme_); - TestView* test_view_child = new TestView(); - EXPECT_FALSE(test_view_child->native_theme_); // Child view added before the widget hierarchy exists should get the // new native theme notification. - test_view->AddChildView(test_view_child); + TestView* test_view_child = + test_view->AddChildView(std::make_unique<TestView>()); + EXPECT_FALSE(test_view_child->native_theme_); std::unique_ptr<Widget> widget(new Widget); Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); @@ -4690,8 +4662,8 @@ // Child view added after the widget hierarchy exists should also get the // notification. - TestView* test_view_child_2 = new TestView(); - test_view->AddChildView(test_view_child_2); + TestView* test_view_child_2 = + test_view->AddChildView(std::make_unique<TestView>()); EXPECT_TRUE(test_view_child_2->native_theme_); EXPECT_EQ(widget->GetNativeTheme(), test_view_child_2->native_theme_); @@ -4714,16 +4686,14 @@ }; TEST_F(ViewTest, ScopedTargetHandlerReceivesEvents) { - TestView* v = new TestView(); - v->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); - std::unique_ptr<Widget> widget(new Widget); Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; params.bounds = gfx::Rect(50, 50, 350, 350); widget->Init(params); View* root = widget->GetRootView(); - root->AddChildView(v); + TestView* v = root->AddChildView(std::make_unique<TestView>()); + v->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); v->Reset(); { TestEventHandler handler(v); @@ -4779,7 +4749,7 @@ // View: void OnNativeThemeChanged(const ui::NativeTheme* theme) override { on_native_theme_changed_called_ = true; - GetWidget()->GetRootView()->AddChildView(new View); + GetWidget()->GetRootView()->AddChildView(std::make_unique<View>()); } private: @@ -4790,9 +4760,8 @@ // Creates and adds a new child view to |parent| that has a layer. void AddViewWithChildLayer(View* parent) { - View* child = new View; + View* child = parent->AddChildView(std::make_unique<View>()); child->SetPaintToLayer(); - parent->AddChildView(child); } // This test does the following: @@ -4813,8 +4782,8 @@ AddViewWithChildLayer(widget.GetRootView()); ViewThatAddsViewInOnNativeThemeChanged* v = - new ViewThatAddsViewInOnNativeThemeChanged; - widget.GetRootView()->AddChildView(v); + widget.GetRootView()->AddChildView( + std::make_unique<ViewThatAddsViewInOnNativeThemeChanged>()); EXPECT_TRUE(v->on_native_theme_changed_called()); } @@ -4937,18 +4906,15 @@ parent_view->SetPaintToLayer(); // child_view1 has layer and has id OrderableView::VIEW_ID_RAISED. - View* child_view1 = new View; + View* child_view1 = parent_view->AddChildView(std::make_unique<View>()); child_view1->SetPaintToLayer(); child_view1->set_id(OrderableView::VIEW_ID_RAISED); - parent_view->AddChildView(child_view1); // child_view2 has no layer. - View* child_view2 = new View; + View* child_view2 = parent_view->AddChildView(std::make_unique<View>()); // grand_child_view has layer. - View* grand_child_view = new View(); + View* grand_child_view = child_view2->AddChildView(std::make_unique<View>()); grand_child_view->SetPaintToLayer(); - child_view2->AddChildView(grand_child_view); - parent_view->AddChildView(child_view2); const std::vector<ui::Layer*>& layers = parent_view->layer()->children(); EXPECT_EQ(2u, layers.size()); EXPECT_EQ(layers[0], grand_child_view->layer()); @@ -5124,12 +5090,10 @@ TEST_F(ViewObserverTest, ChildViewReordered) { std::unique_ptr<View> view = NewView(); - std::unique_ptr<View> child_view = NewView(); - std::unique_ptr<View> child_view2 = NewView(); - view->AddChildView(child_view.get()); - view->AddChildView(child_view2.get()); - view->ReorderChildView(child_view2.get(), 0); - EXPECT_EQ(child_view2.get(), view_reordered()); + view->AddChildView(NewView()); + View* child_view2 = view->AddChildView(NewView()); + view->ReorderChildView(child_view2, 0); + EXPECT_EQ(child_view2, view_reordered()); } // Provides a simple parent view implementation which tracks layer change
diff --git a/ui/views/widget/native_widget_mac.h b/ui/views/widget/native_widget_mac.h index ca2c9cb..6201956 100644 --- a/ui/views/widget/native_widget_mac.h +++ b/ui/views/widget/native_widget_mac.h
@@ -202,7 +202,7 @@ internal::NativeWidgetDelegate* delegate() { return delegate_; } views_bridge_mac::mojom::BridgedNativeWidget* bridge() const; BridgedNativeWidgetImpl* bridge_impl() const; - BridgedNativeWidgetHostImpl* bridge_host_for_testing() const { + BridgedNativeWidgetHostImpl* bridge_host() const { return bridge_host_.get(); }
diff --git a/ui/views/window/frame_caption_button.h b/ui/views/window/frame_caption_button.h index d8262521..54726e9 100644 --- a/ui/views/window/frame_caption_button.h +++ b/ui/views/window/frame_caption_button.h
@@ -77,10 +77,6 @@ bool paint_as_active() const { return paint_as_active_; } - SkColor background_color() const { return background_color_; } - - ColorMode color_mode() const { return color_mode_; } - CaptionButtonIcon icon() const { return icon_; } const gfx::ImageSkia& icon_image() const { return icon_image_; }
diff --git a/ui/views_bridge_mac/bridged_native_widget_impl.mm b/ui/views_bridge_mac/bridged_native_widget_impl.mm index 2a9d077f..1ec64c2 100644 --- a/ui/views_bridge_mac/bridged_native_widget_impl.mm +++ b/ui/views_bridge_mac/bridged_native_widget_impl.mm
@@ -1037,12 +1037,7 @@ } bool BridgedNativeWidgetImpl::RedispatchKeyEvent(NSEvent* event) { - NSWindow* window = ns_window(); - DCHECK([window.class conformsToProtocol:@protocol(CommandDispatchingWindow)]); - NSObject<CommandDispatchingWindow>* command_dispatching_window = - base::mac::ObjCCastStrict<NSObject<CommandDispatchingWindow>>(window); - return - [[command_dispatching_window commandDispatcher] redispatchKeyEvent:event]; + return [[window_ commandDispatcher] redispatchKeyEvent:event]; } NSWindow* BridgedNativeWidgetImpl::ns_window() {
diff --git a/ui/webui/resources/PRESUBMIT.py b/ui/webui/resources/PRESUBMIT.py index 5252e6b..92ee47d 100644 --- a/ui/webui/resources/PRESUBMIT.py +++ b/ui/webui/resources/PRESUBMIT.py
@@ -15,7 +15,7 @@ def _CheckForTranslations(input_api, output_api): shared_keywords = ['i18n('] html_keywords = shared_keywords + ['$118n{'] - js_keywords = shared_keywords + ['I18nBehavior', 'loadTimeData.'] + js_keywords = shared_keywords + ['I18nBehavior', 'loadTimeData.get'] errors = []
diff --git a/ui/webui/resources/cr_components/certificate_manager/certificate_subentry.html b/ui/webui/resources/cr_components/certificate_manager/certificate_subentry.html index 2407809..ee947c42 100644 --- a/ui/webui/resources/cr_components/certificate_manager/certificate_subentry.html +++ b/ui/webui/resources/cr_components/certificate_manager/certificate_subentry.html
@@ -42,21 +42,21 @@ <cr-lazy-render id="menu"> <template> <cr-action-menu> - <button slot="item" class="dropdown-item" id="view" + <button class="dropdown-item" id="view" on-tap="onViewTap_"> [[i18n('certificateManagerView')]] </button> - <button slot="item" class="dropdown-item" id="edit" + <button class="dropdown-item" id="edit" hidden$="[[!canEdit_(certificateType, model)]]" on-tap="onEditTap_"> [[i18n('edit')]] </button> - <button slot="item" class="dropdown-item" id="export" + <button class="dropdown-item" id="export" hidden$="[[!canExport_(certificateType, model)]]" on-tap="onExportTap_"> [[i18n('certificateManagerExport')]] </button> - <button slot="item" class="dropdown-item" id="delete" + <button class="dropdown-item" id="delete" hidden$="[[!canDelete_(model)]]" on-tap="onDeleteTap_"> [[i18n('certificateManagerDelete')]]
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn b/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn index 616ad6e..a83ed92 100644 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn
@@ -31,12 +31,14 @@ ] extra_deps = [ + "//chromeos/components/multidevice/mojom:mojom_js", "//chromeos/services/device_sync/public/mojom:mojom_js", "//chromeos/services/multidevice_setup/public/mojom:mojom_js", "//mojo/public/mojom/base:base_js", ] externs_list = [ + "$root_gen_dir/chromeos/components/multidevice/mojom/multidevice_types.mojom.externs.js", "$root_gen_dir/chromeos/services/device_sync/public/mojom/device_sync.mojom.externs.js", "$root_gen_dir/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.externs.js", "$root_gen_dir/mojo/public/mojom/base/time.mojom.externs.js", @@ -65,12 +67,14 @@ ] extra_deps = [ + "//chromeos/components/multidevice/mojom:mojom_js", "//chromeos/services/device_sync/public/mojom:mojom_js", "//chromeos/services/multidevice_setup/public/mojom:mojom_js", "//mojo/public/mojom/base:base_js", ] externs_list = [ + "$root_gen_dir/chromeos/components/multidevice/mojom/multidevice_types.mojom.externs.js", "$root_gen_dir/chromeos/services/device_sync/public/mojom/device_sync.mojom.externs.js", "$root_gen_dir/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.externs.js", "$root_gen_dir/mojo/public/mojom/base/time.mojom.externs.js",
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/mojo_api.html b/ui/webui/resources/cr_components/chromeos/multidevice_setup/mojo_api.html index 2bcb1bbc..770e2c0 100644 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/mojo_api.html +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/mojo_api.html
@@ -1,6 +1,8 @@ <link rel="import" href="chrome://resources/html/cr.html"> <script src="chrome://resources/js/mojo_bindings.js"></script> <script src="chrome://resources/js/time.mojom.js"></script> +<script src="chrome://resources/js/chromeos/multidevice_types.mojom.js"> +</script> <script src="chrome://resources/js/chromeos/device_sync.mojom.js"></script> <script src="chrome://resources/js/chromeos/multidevice_setup.mojom.js"> </script>
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js index 9be02cb2..b5466fbe 100644 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js
@@ -95,7 +95,7 @@ /** * Array of objects representing all potential MultiDevice hosts. * - * @private {!Array<!chromeos.deviceSync.mojom.RemoteDevice>} + * @private {!Array<!chromeos.multidevice.mojom.RemoteDevice>} */ devices_: Array,
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.js b/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.js index d9f6db48..d5db5941 100644 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.js +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.js
@@ -33,7 +33,7 @@ /** * Array of objects representing all potential MultiDevice hosts. * - * @type {!Array<!chromeos.deviceSync.mojom.RemoteDevice>} + * @type {!Array<!chromeos.multidevice.mojom.RemoteDevice>} */ devices: { type: Array, @@ -99,7 +99,7 @@ }, /** - * @param {!Array<!chromeos.deviceSync.mojom.RemoteDevice>} devices + * @param {!Array<!chromeos.multidevice.mojom.RemoteDevice>} devices * @return {string} Label for devices selection content. * @private */ @@ -115,7 +115,7 @@ }, /** - * @param {!Array<!chromeos.deviceSync.mojom.RemoteDevice>} devices + * @param {!Array<!chromeos.multidevice.mojom.RemoteDevice>} devices * @return {boolean} True if there are more than one potential host devices. * @private */ @@ -124,7 +124,7 @@ }, /** - * @param {!Array<!chromeos.deviceSync.mojom.RemoteDevice>} devices + * @param {!Array<!chromeos.multidevice.mojom.RemoteDevice>} devices * @return {boolean} True if there is exactly one potential host device. * @private */ @@ -133,7 +133,7 @@ }, /** - * @param {!Array<!chromeos.deviceSync.mojom.RemoteDevice>} devices + * @param {!Array<!chromeos.multidevice.mojom.RemoteDevice>} devices * @return {string} Name of the first device in device list if there are any. * Returns an empty string otherwise. * @private
diff --git a/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.html b/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.html index 4b59b25..33c9faad 100644 --- a/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.html +++ b/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.html
@@ -63,7 +63,7 @@ <dialog id="dialog" tabindex="0" on-close="onNativeDialogClose_" role="menu" aria-label$="[[ariaLabel]]"> <div class="item-wrapper" tabindex="-1"> - <slot name="item" id="contentNode"></slot> + <slot id="contentNode"></slot> </div> </dialog> </template>
diff --git a/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js b/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js index 477e0ed..11f4ade92 100644 --- a/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js +++ b/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js
@@ -237,10 +237,27 @@ return; } - if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp') + let selectNext = e.key == 'ArrowDown'; + if (e.key == 'Enter') { + // If a menu item has focus, don't change focus or close menu on 'Enter'. + const options = this.querySelectorAll('.dropdown-item'); + let focusedIndex = + Array.prototype.indexOf.call(options, getDeepActiveElement()); + if (focusedIndex != -1) + return; + + if (cr.isWindows || cr.isMac) { + this.close(); + e.preventDefault(); + return; + } + selectNext = true; + } + + if (e.key !== 'ArrowUp' && !selectNext) return; - const nextOption = this.getNextOption_(e.key == 'ArrowDown' ? 1 : -1); + const nextOption = this.getNextOption_(selectNext ? 1 : -1); if (nextOption) { if (!this.hasMousemoveListener_) { this.hasMousemoveListener_ = true;
diff --git a/ui/webui/resources/cr_elements/cr_slider/cr_slider.html b/ui/webui/resources/cr_elements/cr_slider/cr_slider.html index 7990d0c..1bf1ad04 100644 --- a/ui/webui/resources/cr_elements/cr_slider/cr_slider.html +++ b/ui/webui/resources/cr_elements/cr_slider/cr_slider.html
@@ -200,7 +200,7 @@ <div id="bar"></div> <div id="markers" hidden$="[[!markerCount]]"> <template is="dom-repeat" items="[[getMarkers_(markerCount)]]"> - <div class$="[[getMarkerClass_(index, immediateValue_, min, max, + <div class$="[[getMarkerClass_(index, value, min, max, markerCount)]]"></div> </template> </div>
diff --git a/ui/webui/resources/cr_elements/cr_slider/cr_slider.js b/ui/webui/resources/cr_elements/cr_slider/cr_slider.js index 54d9c39..c08f454c 100644 --- a/ui/webui/resources/cr_elements/cr_slider/cr_slider.js +++ b/ui/webui/resources/cr_elements/cr_slider/cr_slider.js
@@ -120,26 +120,6 @@ observer: 'onValueChanged_', }, - /** - * If true, |value| is updated while dragging happens. If false, |value| - * is updated only once, when drag gesture finishes. - */ - updateValueInstantly: { - type: Boolean, - value: true, - }, - - /** - * |immediateValue_| has the most up-to-date value and is used to render - * the slider UI. When dragging, |immediateValue_| is always updated, and - * |value| is updated at least once when dragging is stopped. - * @private - */ - immediateValue_: { - type: Number, - value: 0, - }, - /** @private */ holdDown_: { type: Boolean, @@ -182,8 +162,8 @@ observers: [ 'onTicksChanged_(ticks.*)', - 'updateLabelAndAria_(immediateValue_, min, max)', - 'updateKnobAndBar_(immediateValue_, min, max)', + 'updateLabelAndAria_(value, min, max)', + 'updateKnobAndBar_(value, min, max)', ], listeners: { @@ -250,18 +230,16 @@ * @return {number} */ getRatio: function() { - return (this.immediateValue_ - this.min) / (this.max - this.min); + return (this.value - this.min) / (this.max - this.min); }, /** @private */ ensureValidValue_: function() { - if (this.immediateValue_ == undefined || this.value == undefined) + if (this.value == undefined) return; - let validValue = clamp(this.min, this.max, this.immediateValue_); + let validValue = clamp(this.min, this.max, this.value); validValue = this.snaps ? Math.round(validValue) : validValue; - this.immediateValue_ = validValue; - if (!this.dragging || this.updateValueInstantly) - this.value = validValue; + this.value = validValue; }, /** @@ -270,9 +248,6 @@ * @private */ stopDragging_: function(pointerId) { - // Update |value| before updating |dragging| so dragging-changed event - // handlers will have access to the updated |value|. - this.value = this.immediateValue_; this.draggingEventTracker_.removeAll(); this.releasePointerCapture(pointerId); this.dragging = false; @@ -317,18 +292,17 @@ let handled = true; if (event.key == 'Home') { - this.immediateValue_ = this.min; + this.value = this.min; } else if (event.key == 'End') { - this.immediateValue_ = this.max; + this.value = this.max; } else if (this.deltaKeyMap_.has(event.key)) { - const value = this.value + this.deltaKeyMap_.get(event.key); - this.immediateValue_ = clamp(this.min, this.max, value); + const newValue = this.value + this.deltaKeyMap_.get(event.key); + this.value = clamp(this.min, this.max, newValue); } else { handled = false; } if (handled) { - this.value = this.immediateValue_; this.fire('cr-slider-value-changed-from-ui'); event.preventDefault(); event.stopPropagation(); @@ -399,16 +373,11 @@ }, /** - * Update |immediateValue_| which is used for rendering when |value| is - * updated either programmatically or from a keyboard input or a mouse drag - * (when |updateValueInstantly| is true). + * Update |value| which is used for rendering when |value| is + * updated either programmatically or from a keyboard input or a mouse drag. * @private */ onValueChanged_: function() { - if (this.immediateValue_ == this.value) - return; - - this.immediateValue_ = this.value; this.ensureValidValue_(); }, @@ -422,7 +391,7 @@ /** @private */ updateLabelAndAria_: function() { const ticks = this.ticks; - const index = this.immediateValue_; + const index = this.value; if (!ticks || ticks.length == 0 || index >= ticks.length || !Number.isInteger(index) || !this.snaps) { this.setAttribute('aria-valuetext', index); @@ -472,8 +441,7 @@ let ratio = (clientX - rect.left) / rect.width; if (this.isRtl_) ratio = 1 - ratio; - this.immediateValue_ = ratio * (this.max - this.min) + this.min; - this.ensureValidValue_(); + this.value = ratio * (this.max - this.min) + this.min; this.fire('cr-slider-value-changed-from-ui'); },
diff --git a/ui/webui/resources/html/cr/ui/focus_row_behavior.html b/ui/webui/resources/html/cr/ui/focus_row_behavior.html new file mode 100644 index 0000000..3b50f73f --- /dev/null +++ b/ui/webui/resources/html/cr/ui/focus_row_behavior.html
@@ -0,0 +1,2 @@ +<link rel="import" href="focus_row.html"> +<script src="../../../js/cr/ui/focus_row_behavior.js"></script>
diff --git a/ui/webui/resources/html/dark_mode.html b/ui/webui/resources/html/dark_mode.html new file mode 100644 index 0000000..b652ff82 --- /dev/null +++ b/ui/webui/resources/html/dark_mode.html
@@ -0,0 +1,2 @@ +<link rel="import" href="chrome://resources/html/cr.html"> +<script src="chrome://resources/js/dark_mode.js"></script>
diff --git a/ui/webui/resources/js/BUILD.gn b/ui/webui/resources/js/BUILD.gn index 3c1eb17b..6ad7c092 100644 --- a/ui/webui/resources/js/BUILD.gn +++ b/ui/webui/resources/js/BUILD.gn
@@ -17,6 +17,7 @@ ":action_link", ":assert", ":cr", + ":dark_mode", ":event_tracker", ":i18n_behavior", ":i18n_template", @@ -48,6 +49,14 @@ externs_list = [ "$externs_path/chrome_send.js" ] } +js_library("dark_mode") { + deps = [ + ":cr", + ":load_time_data", + ] + externs_list = [ "$externs_path/pending.js" ] +} + js_library("event_tracker") { }
diff --git a/ui/webui/resources/js/cr/ui/BUILD.gn b/ui/webui/resources/js/cr/ui/BUILD.gn index 86b41a08..45ca6b5a 100644 --- a/ui/webui/resources/js/cr/ui/BUILD.gn +++ b/ui/webui/resources/js/cr/ui/BUILD.gn
@@ -17,6 +17,7 @@ ":focus_manager", ":focus_outline_manager", ":focus_row", + ":focus_row_behavior", ":focus_without_ink", ":grid", ":list", @@ -109,6 +110,12 @@ ] } +js_library("focus_row_behavior") { + deps = [ + ":focus_row", + ] +} + js_library("focus_row") { deps = [ "../..:assert",
diff --git a/ui/webui/resources/js/cr/ui/focus_grid.js b/ui/webui/resources/js/cr/ui/focus_grid.js index de710112..1fc48c9 100644 --- a/ui/webui/resources/js/cr/ui/focus_grid.js +++ b/ui/webui/resources/js/cr/ui/focus_grid.js
@@ -75,6 +75,11 @@ return false; }, + /** @override */ + getCustomEquivalent: function(sampleElement) { + return null; + }, + /** * Unregisters event handlers and removes all |this.rows|. */
diff --git a/ui/webui/resources/js/cr/ui/focus_row.js b/ui/webui/resources/js/cr/ui/focus_row.js index 8915b114..b2ca8ae6 100644 --- a/ui/webui/resources/js/cr/ui/focus_row.js +++ b/ui/webui/resources/js/cr/ui/focus_row.js
@@ -300,6 +300,13 @@ * @param {!Event} e */ onFocus(row, e) {} + + /** + * @param {!Element} sampleElement An element to find an equivalent for. + * @return {?Element} An equivalent element to focus, or null to use the + * default FocusRow element. + */ + getCustomEquivalent(sampleElement) {} } return {
diff --git a/ui/webui/resources/js/cr/ui/focus_row_behavior.js b/ui/webui/resources/js/cr/ui/focus_row_behavior.js new file mode 100644 index 0000000..0b83321 --- /dev/null +++ b/ui/webui/resources/js/cr/ui/focus_row_behavior.js
@@ -0,0 +1,317 @@ +// Copyright 2017 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. + +cr.define('cr.ui', function() { + /** @implements {cr.ui.FocusRowDelegate} */ + class FocusRowBehaviorDelegate { + /** + * @param {{lastFocused: Object, + * overrideCustomEquivalent: boolean, + * getCustomEquivalent: (Function|undefined)}} listItem + */ + constructor(listItem) { + /** @private */ + this.listItem_ = listItem; + } + + /** + * This function gets called when the [focus-row-control] element receives + * the focus event. + * @override + * @param {!cr.ui.FocusRow} row + * @param {!Event} e + */ + onFocus(row, e) { + this.listItem_.lastFocused = e.path[0]; + } + + /** + * @override + * @param {!cr.ui.FocusRow} row The row that detected a keydown. + * @param {!Event} e + * @return {boolean} Whether the event was handled. + */ + onKeydown(row, e) { + // Prevent iron-list from changing the focus on enter. + if (e.key == 'Enter') + e.stopPropagation(); + + return false; + } + + /** @override */ + getCustomEquivalent(sampleElement) { + return this.listItem_.overrideCustomEquivalent ? + this.listItem_.getCustomEquivalent(sampleElement) : + null; + } + } + + /** @extends {cr.ui.FocusRow} */ + class VirtualFocusRow extends cr.ui.FocusRow { + /** + * @param {!Element} root + * @param {cr.ui.FocusRowDelegate} delegate + */ + constructor(root, delegate) { + super(root, /* boundary */ null, delegate); + } + + /** @override */ + getCustomEquivalent(sampleElement) { + return this.delegate.getCustomEquivalent(sampleElement) || + super.getCustomEquivalent(sampleElement); + } + } + + /** + * Any element that is being used as an iron-list row item can extend this + * behavior, which encapsulates focus controls of mouse and keyboards. + * To use this behavior: + * - The parent element should pass a "last-focused" attribute double-bound + * to the row items, to track the last-focused element across rows, and + * a "list-blurred" attribute double-bound to the row items, to track + * whether the list of row items has been blurred. + * - There must be a container in the extending element with the + * [focus-row-container] attribute that contains all focusable controls. + * - On each of the focusable controls, there must be a [focus-row-control] + * attribute, and a [focus-type=] attribute unique for each control. + * + * @polymerBehavior + */ + const FocusRowBehavior = { + properties: { + /** @private {cr.ui.VirtualFocusRow} */ + row_: Object, + + /** @private {boolean} */ + mouseFocused_: Boolean, + + /** @type {Element} */ + lastFocused: { + type: Object, + notify: true, + }, + + /** + * This is different from tabIndex, since the template only does a one-way + * binding on both attributes, and the behavior actually make use of this + * fact. For example, when a control within a row is focused, it will have + * tabIndex = -1 and ironListTabIndex = 0. + * @type {number} + */ + ironListTabIndex: { + type: Number, + observer: 'ironListTabIndexChanged_', + }, + + listBlurred: { + type: Boolean, + notify: true, + }, + }, + + /** @private {?Element} */ + firstControl_: null, + + /** @private {!Array<!MutationObserver>} */ + controlObservers_: [], + + /** @override */ + attached: function() { + this.classList.add('no-outline'); + + Polymer.RenderStatus.afterNextRender(this, function() { + const rowContainer = this.root.querySelector('[focus-row-container]'); + assert(!!rowContainer); + this.row_ = new VirtualFocusRow( + rowContainer, new FocusRowBehaviorDelegate(this)); + this.ironListTabIndexChanged_(); + this.addItems_(); + + // Adding listeners asynchronously to reduce blocking time, since this + // behavior will be used by items in potentially long lists. + this.listen(this, 'focus', 'onFocus_'); + this.listen(this, 'dom-change', 'addItems_'); + this.listen(this, 'mousedown', 'onMouseDown_'); + this.listen(this, 'blur', 'onBlur_'); + }); + }, + + /** @override */ + detached: function() { + this.unlisten(this, 'focus', 'onFocus_'); + this.unlisten(this, 'dom-change', 'addItems_'); + this.unlisten(this, 'mousedown', 'onMouseDown_'); + this.unlisten(this, 'blur', 'onBlur_'); + this.removeObservers_(); + if (this.row_) + this.row_.destroy(); + }, + + /** @private */ + updateFirstControl_: function() { + const newFirstControl = this.row_.getFirstFocusable(); + if (newFirstControl === this.firstControl_) + return; + + if (this.firstControl_) + this.unlisten(this.firstControl_, 'keydown', 'onFirstControlKeydown_'); + this.firstControl_ = newFirstControl; + if (this.firstControl_) { + this.listen( + /** @type {!Element} */ (this.firstControl_), 'keydown', + 'onFirstControlKeydown_'); + } + }, + + /** @private */ + removeObservers_: function() { + if (this.firstControl_) + this.unlisten(this.firstControl_, 'keydown', 'onFirstControlKeydown_'); + if (this.controlObservers_.length > 0) + this.controlObservers_.forEach(observer => { + observer.disconnect(); + }); + this.controlObservers_ = []; + }, + + /** @private */ + addItems_: function() { + if (this.row_) { + this.removeObservers_(); + this.row_.destroy(); + + const controls = this.root.querySelectorAll('[focus-row-control]'); + + controls.forEach(control => { + this.row_.addItem( + control.getAttribute('focus-type'), + /** @type {!HTMLElement} */ + (cr.ui.FocusRow.getFocusableElement(control))); + this.addMutationObservers_(assert(control)); + }); + this.updateFirstControl_(); + } + }, + + /** + * @return {!MutationObserver} + * @private + */ + createObserver_: function() { + return new MutationObserver(mutations => { + const mutation = mutations[0]; + if (mutation.attributeName === 'style' && mutation.oldValue) { + const newStyle = window.getComputedStyle( + /** @type {!Element} */ (mutation.target)); + const oldDisplayValue = mutation.oldValue.match(/^display:(.*)(?=;)/); + const oldVisibilityValue = + mutation.oldValue.match(/^visibility:(.*)(?=;)/); + // Return early if display and visibility have not changed. + if (oldDisplayValue && + newStyle.display === oldDisplayValue[1].trim() && + oldVisibilityValue && + newStyle.visibility === oldVisibilityValue[1].trim()) { + return; + } + } + this.updateFirstControl_(); + }); + }, + + /** + * The first focusable control changes if hidden, disabled, or style.display + * changes for the control or any of its ancestors. Add mutation observers + * to watch for these changes in order to ensure the first control keydown + * listener is always on the correct element. + * @param {!Element} control + * @private + */ + addMutationObservers_: function(control) { + let current = control; + while (current && current != this.root) { + const currentObserver = this.createObserver_(); + currentObserver.observe(current, { + attributes: true, + attributeFilter: ['hidden', 'disabled', 'style'], + attributeOldValue: true, + }); + this.controlObservers_.push(currentObserver); + current = current.parentNode; + } + }, + + /** + * This function gets called when the row itself receives the focus event. + * @param {!Event} e The focus event + * @private + */ + onFocus_: function(e) { + if (this.mouseFocused_) { + this.mouseFocused_ = false; // Consume and reset flag. + return; + } + + // If focus is being restored from outside the item and the event is fired + // by the list item itself, focus the first control so that the user can + // tab through all the controls. When the user shift-tabs back to the row, + // or focus is restored to the row from a dropdown on the last item, the + // last child item will be focused before the row itself. Since this is + // the desired behavior, do not shift focus to the first item in these + // cases. + const restoreFocusToFirst = + this.listBlurred && e.composedPath()[0] === this; + + if (this.lastFocused && !restoreFocusToFirst) { + this.row_.getEquivalentElement(this.lastFocused).focus(); + } else { + const firstFocusable = assert(this.firstControl_); + firstFocusable.focus(); + } + this.listBlurred = false; + }, + + /** @param {!KeyboardEvent} e */ + onFirstControlKeydown_: function(e) { + if (e.shiftKey && e.key === 'Tab') + this.focus(); + }, + + /** @private */ + ironListTabIndexChanged_: function() { + if (this.row_) + this.row_.makeActive(this.ironListTabIndex == 0); + + // If a new row is being focused, reset listBlurred. This means an item + // has been removed and iron-list is about to focus the next item. + if (this.ironListTabIndex == 0) + this.listBlurred = false; + }, + + /** @private */ + onMouseDown_: function() { + this.mouseFocused_ = true; // Set flag to not do any control-focusing. + }, + + /** + * @param {!Event} e + * @private + */ + onBlur_: function(e) { + this.mouseFocused_ = false; // Reset flag since it's not active anymore. + + const node = + e.relatedTarget ? /** @type {!Node} */ (e.relatedTarget) : null; + if (!this.parentNode.contains(node)) + this.listBlurred = true; + }, + }; + + return { + FocusRowBehaviorDelegate, + VirtualFocusRow, + FocusRowBehavior, + }; +});
diff --git a/ui/webui/resources/js/dark_mode.js b/ui/webui/resources/js/dark_mode.js new file mode 100644 index 0000000..0ba4cb62 --- /dev/null +++ b/ui/webui/resources/js/dark_mode.js
@@ -0,0 +1,10 @@ +// 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. + +cr.addWebUIListener('dark-mode-changed', darkMode => { + loadTimeData.overrideValues({'darkMode': darkMode}); + document.documentElement.toggleAttribute('dark', darkMode); +}); + +chrome.send('observeDarkMode');
diff --git a/ui/webui/resources/js/promise_resolver.js b/ui/webui/resources/js/promise_resolver.js index 64501d6..d19f7f73 100644 --- a/ui/webui/resources/js/promise_resolver.js +++ b/ui/webui/resources/js/promise_resolver.js
@@ -27,14 +27,31 @@ /** @private {function(*=): void} */ this.reject_; + /** @private {boolean} */ + this.isFulfilled_ = false; + /** @private {!Promise<T>} */ this.promise_ = new Promise(function(resolve, reject) { - this.resolve_ = resolve; - this.reject_ = reject; + this.resolve_ = /** @param {T=} resolution */ function(resolution) { + resolve(resolution); + this.isFulfilled_ = true; + }; + this.reject_ = /** @param {*=} reason */ function(reason) { + reject(reason); + this.isFulfilled_ = true; + }; }.bind(this)); } PromiseResolver.prototype = { + /** @return {boolean} Whether this resolver has been resolved or rejected. */ + get isFulfilled() { + return this.isFulfilled_; + }, + set isFulfilled(i) { + assertNotReached(); + }, + /** @return {!Promise<T>} */ get promise() { return this.promise_;
diff --git a/ui/webui/resources/webui_resources.grd b/ui/webui/resources/webui_resources.grd index 46c8b37..15eb1c7 100644 --- a/ui/webui/resources/webui_resources.grd +++ b/ui/webui/resources/webui_resources.grd
@@ -308,6 +308,9 @@ <structure name="IDR_WEBUI_HTML_CR_UI_FOCUS_ROW" file="html/cr/ui/focus_row.html" type="chrome_html" compress="gzip" /> + <structure name="IDR_WEBUI_HTML_CR_UI_FOCUS_ROW_BEHAVIOR" + file="html/cr/ui/focus_row_behavior.html" type="chrome_html" + compress="gzip" /> <structure name="IDR_WEBUI_HTML_CR_UI_LIST" file="html/cr/ui/list.html" type="chrome_html" compress="gzip" /> @@ -344,6 +347,8 @@ <structure name="IDR_WEBUI_HTML_CR_UI_SPLITTER" file="html/cr/ui/splitter.html" type="chrome_html" compress="gzip" /> + <structure name="IDR_WEBUI_HTML_DARK_MODE" + file="html/dark_mode.html" type="chrome_html" compress="gzip" /> <structure name="IDR_WEBUI_HTML_EVENT_TRACKER" file="html/event_tracker.html" type="chrome_html" compress="gzip" /> @@ -426,6 +431,9 @@ <structure name="IDR_WEBUI_JS_CR_UI_FOCUS_ROW" file="js/cr/ui/focus_row.js" type="chrome_html" compress="gzip" /> + <structure name="IDR_WEBUI_JS_CR_UI_FOCUS_ROW_BEHAVIOR" + file="js/cr/ui/focus_row_behavior.js" type="chrome_html" + compress="gzip" /> <structure name="IDR_WEBUI_JS_CR_UI_LIST" file="js/cr/ui/list.js" type="chrome_html" compress="gzip" /> <structure name="IDR_WEBUI_JS_CR_UI_LIST_ITEM" @@ -495,6 +503,9 @@ <structure name="IDR_WEBUI_JS_CR_UI_TOUCH_HANDLER" file="js/cr/ui/touch_handler.js" type="chrome_html" compress="gzip" /> + <structure name="IDR_WEBUI_JS_DARK_MODE" + file="js/dark_mode.js" type="chrome_html" + compress="gzip" /> <structure name="IDR_WEBUI_JS_EVENT_TRACKER" file="js/event_tracker.js" type="chrome_html" compress="gzip" />
diff --git a/url/origin.cc b/url/origin.cc index f6403f5..59573faa 100644 --- a/url/origin.cc +++ b/url/origin.cc
@@ -52,7 +52,7 @@ } Origin Origin::Resolve(const GURL& url, const Origin& base_origin) { - if (url.IsAboutBlank()) + if (url.SchemeIs(kAboutScheme)) return base_origin; Origin result = Origin::Create(url); if (!result.opaque())
diff --git a/url/origin_unittest.cc b/url/origin_unittest.cc index 5f889c09..99ff2aee 100644 --- a/url/origin_unittest.cc +++ b/url/origin_unittest.cc
@@ -178,6 +178,7 @@ EXPECT_LT(opaque_b, url::Origin::Create(GURL("http://www.google.com"))); EXPECT_EQ(opaque_b, url::Origin::Resolve(GURL("about:blank"), opaque_b)); + EXPECT_EQ(opaque_b, url::Origin::Resolve(GURL("about:srcdoc"), opaque_b)); EXPECT_EQ(opaque_b, url::Origin::Resolve(GURL("about:blank?hello#whee"), opaque_b));
diff --git a/webrunner/BUILD.gn b/webrunner/BUILD.gn index 61266d5..4b2851e 100644 --- a/webrunner/BUILD.gn +++ b/webrunner/BUILD.gn
@@ -31,18 +31,44 @@ ] ] } -executable("castrunner_exe") { +source_set("castrunner_common") { sources = [ "app/cast/cast_runner.cc", "app/cast/cast_runner.h", - "app/cast/main.cc", ] deps = [ ":web_fidl", - ":webrunner_common", "//base", "//url", ] + public_deps = [ + ":webrunner_common", + ] +} + +executable("castrunner_exe") { + sources = [ + "app/cast/main.cc", + ] + deps = [ + ":castrunner_common", + ":webrunner_common", + "//base", + ] +} + +test("castrunner_unittests") { + sources = [ + "app/cast/cast_runner_unittest.cc", + ] + deps = [ + ":castrunner_common", + ":test_support", + "//base/test:run_all_unittests", + "//base/test:test_support", + "//testing/gmock", + "//testing/gtest", + ] } fuchsia_package("webrunner_pkg") { @@ -75,6 +101,9 @@ "//third_party/fuchsia-sdk/sdk:viewsv1", "//url", ] + public_deps = [ + "//third_party/fuchsia-sdk/sdk:sys", + ] } executable("webrunner_exe") { @@ -150,6 +179,7 @@ "//content/public/renderer", "//mojo/public/cpp/bindings", "//services/network/public/cpp", + "//services/service_manager/sandbox", "//skia/public/interfaces", "//third_party/blink/public/common", "//ui/aura",
diff --git a/webrunner/app/cast/cast_runner_unittest.cc b/webrunner/app/cast/cast_runner_unittest.cc new file mode 100644 index 0000000..d9e52a9e --- /dev/null +++ b/webrunner/app/cast/cast_runner_unittest.cc
@@ -0,0 +1,135 @@ +// 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 "webrunner/app/cast/cast_runner.h" + +#include <lib/fidl/cpp/binding.h> +#include <lib/zx/channel.h> +#include <zircon/status.h> + +#include "base/fuchsia/component_context.h" +#include "base/fuchsia/fuchsia_logging.h" +#include "base/fuchsia/service_directory.h" +#include "base/message_loop/message_loop.h" +#include "base/strings/string_piece.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webrunner/fidl/chromium/web/cpp/fidl.h" +#include "webrunner/test/fake_context.h" + +namespace castrunner { + +class CastRunnerTest : public testing::Test { + public: + CastRunnerTest() + : fake_context_binding_(&fake_context_, fake_context_ptr_.NewRequest()) { + // Create a new ServiceDirectory, and a scoped default ComponentContext + // connected to it, for the test to use to drive the CastRunner. + zx::channel service_directory_request, service_directory_client; + zx_status_t status = zx::channel::create(0, &service_directory_client, + &service_directory_request); + ZX_CHECK(status == ZX_OK, status) << "zx_channel_create"; + + service_directory_ = std::make_unique<base::fuchsia::ServiceDirectory>( + std::move(service_directory_request)); + scoped_default_component_context_ = + std::make_unique<base::fuchsia::ScopedDefaultComponentContext>( + std::move(service_directory_client)); + + // Create the CastRunner, published into |service_directory_|. + cast_runner_ = std::make_unique<CastRunner>( + service_directory_.get(), std::move(fake_context_ptr_), + until_runner_idle_loop_.QuitClosure()); + + // Connect to the CastRunner's fuchsia.sys.Runner interface. + cast_runner_ptr_ = base::fuchsia::ComponentContext::GetDefault() + ->ConnectToService<fuchsia::sys::Runner>(); + cast_runner_ptr_.set_error_handler([this](zx_status_t status) { + ADD_FAILURE() << "CastRunner closed channel."; + until_runner_idle_loop_.Quit(); + }); + } + + zx::channel StartCastComponent( + const base::StringPiece& cast_url, + fidl::InterfaceRequest<fuchsia::sys::ComponentController> + component_controller_request) { + fuchsia::sys::LaunchInfo launch_info; + launch_info.url.reset(cast_url.as_string()); + + // Create a channel to pass to the Runner, through which to expose the new + // component's ServiceDirectory. + zx::channel service_directory_client; + zx_status_t status = zx::channel::create(0, &service_directory_client, + &launch_info.directory_request); + ZX_CHECK(status == ZX_OK, status) << "zx_channel_create"; + + fuchsia::sys::StartupInfo startup_info; + startup_info.launch_info = std::move(launch_info); + + // The FlatNamespace vectors must be non-null, but may be empty. + startup_info.flat_namespace.paths.resize(0); + startup_info.flat_namespace.directories.resize(0); + + fuchsia::sys::Package package; + package.resolved_url.reset(cast_url.as_string()); + + cast_runner_ptr_->StartComponent(std::move(package), + std::move(startup_info), + std::move(component_controller_request)); + return service_directory_client; + } + + void RunUntilCastRunnerIsIdle() { until_runner_idle_loop_.Run(); } + + protected: + base::MessageLoopForIO message_loop_; + base::RunLoop until_runner_idle_loop_; + + // Temporarily holds the InterfacePtr to the FakeContext, until it is passed + // to the CastRunner. + chromium::web::ContextPtr fake_context_ptr_; + + // Fake web::Context, and binding to the client CastRunner. + webrunner::FakeContext fake_context_; + fidl::Binding<chromium::web::Context> fake_context_binding_; + + // ServiceDirectory into which the CastRunner will publish itself. + std::unique_ptr<base::fuchsia::ServiceDirectory> service_directory_; + std::unique_ptr<base::fuchsia::ScopedDefaultComponentContext> + scoped_default_component_context_; + + std::unique_ptr<CastRunner> cast_runner_; + fuchsia::sys::RunnerPtr cast_runner_ptr_; + + DISALLOW_COPY_AND_ASSIGN(CastRunnerTest); +}; + +TEST_F(CastRunnerTest, TeardownOnClientUnbind) { + // Disconnect from the CastRunner and wait for it to terminate. + cast_runner_ptr_.Unbind(); + RunUntilCastRunnerIsIdle(); +} + +TEST_F(CastRunnerTest, TeardownOnComponentControllerUnbind) { + // Create a ComponentController pointer, to manage the component lifetime. + fuchsia::sys::ComponentControllerPtr component_controller_ptr; + + // Launch the test-app component, passing a ComponentController request. + base::fuchsia::ComponentContext component_services(StartCastComponent( + "cast:00000000", component_controller_ptr.NewRequest())); + + // Pump the message-loop to process StartComponent(). If the call is rejected + // then the ComponentControllerPtr's error-handler will be invoked at this + // point. + component_controller_ptr.set_error_handler([](zx_status_t status) { + ZX_LOG(FATAL, status) << "Component launch failed"; + }); + base::RunLoop().RunUntilIdle(); + + // Disconnect ComponentController and expect the CastRunner will terminate. + component_controller_ptr.Unbind(); + RunUntilCastRunnerIsIdle(); +} + +} // namespace castrunner
diff --git a/webrunner/service/context_provider_impl.cc b/webrunner/service/context_provider_impl.cc index ca21845..1031d952 100644 --- a/webrunner/service/context_provider_impl.cc +++ b/webrunner/service/context_provider_impl.cc
@@ -25,6 +25,7 @@ #include "base/logging.h" #include "base/path_service.h" #include "base/process/launch.h" +#include "services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.h" #include "webrunner/service/common.h" namespace webrunner { @@ -93,20 +94,10 @@ base::LaunchOptions launch_options; - // Clone job because the context needs to be able to spawn child processes. - launch_options.spawn_flags = FDIO_SPAWN_CLONE_JOB; - - // Clone stdout/stderr to get logs in system debug log. - launch_options.fds_to_remap.push_back( - std::make_pair(STDERR_FILENO, STDERR_FILENO)); - launch_options.fds_to_remap.push_back( - std::make_pair(STDOUT_FILENO, STDOUT_FILENO)); - - // Context and child processes need access to the read-only package files. - launch_options.paths_to_clone.push_back(base::FilePath("/pkg")); - - // Context needs access to the read-only SSL root certificates list. - launch_options.paths_to_clone.push_back(base::FilePath("/config/ssl")); + service_manager::SandboxPolicyFuchsia sandbox_policy; + sandbox_policy.Initialize(service_manager::SANDBOX_TYPE_WEB_CONTEXT); + sandbox_policy.SetServiceDirectory(std::move(params.service_directory)); + sandbox_policy.UpdateLaunchOptionsForSandbox(&launch_options); if (use_shared_tmp_) launch_options.paths_to_clone.push_back(base::FilePath("/tmp")); @@ -117,10 +108,6 @@ launch_options.handles_to_transfer.push_back( {kContextRequestHandleId, context_handle.get()}); - // Pass /svc directory specified by the caller. - launch_options.paths_to_transfer.push_back(base::PathToTransfer{ - base::FilePath("/svc"), std::move(params.service_directory.release())}); - // Bind |data_directory| to /data directory, if provided. if (params.data_directory) { if (!IsValidDirectory(params.data_directory.get()))
diff --git a/webrunner/test/fake_context.cc b/webrunner/test/fake_context.cc index bb898746..b4890eb8 100644 --- a/webrunner/test/fake_context.cc +++ b/webrunner/test/fake_context.cc
@@ -15,10 +15,19 @@ FakeFrame::~FakeFrame() = default; +void FakeFrame::GetNavigationController( + fidl::InterfaceRequest<chromium::web::NavigationController> controller) { + if (navigation_controller_) { + navigation_controller_bindings_.AddBinding(navigation_controller_, + std::move(controller)); + } +} + void FakeFrame::SetNavigationEventObserver( fidl::InterfaceHandle<chromium::web::NavigationEventObserver> observer) { observer_.Bind(std::move(observer)); - std::move(on_set_observer_callback_).Run(); + if (on_set_observer_callback_) + std::move(on_set_observer_callback_).Run(); } void FakeFrame::NotImplemented_(const std::string& name) { @@ -31,7 +40,8 @@ void FakeContext::CreateFrame( fidl::InterfaceRequest<chromium::web::Frame> frame_request) { FakeFrame* new_frame = new FakeFrame(std::move(frame_request)); - on_create_frame_callback_.Run(new_frame); + if (on_create_frame_callback_) + on_create_frame_callback_.Run(new_frame); // |new_frame| owns itself, so we intentionally leak the pointer. }
diff --git a/webrunner/test/fake_context.h b/webrunner/test/fake_context.h index 5f305de1..b4236d4 100644 --- a/webrunner/test/fake_context.h +++ b/webrunner/test/fake_context.h
@@ -6,6 +6,7 @@ #define WEBRUNNER_TEST_FAKE_CONTEXT_H_ #include <lib/fidl/cpp/binding.h> +#include <lib/fidl/cpp/binding_set.h> #include <utility> @@ -26,9 +27,19 @@ on_set_observer_callback_ = std::move(callback); } + // Tests can provide e.g a mock NavigationController, which the FakeFrame will + // pass bind GetNavigationController() requests to. + void set_navigation_controller( + chromium::web::NavigationController* controller) { + navigation_controller_ = controller; + } + chromium::web::NavigationEventObserver* observer() { return observer_.get(); } // chromium::web::Frame implementation. + void GetNavigationController( + fidl::InterfaceRequest<chromium::web::NavigationController> controller) + override; void SetNavigationEventObserver( fidl::InterfaceHandle<chromium::web::NavigationEventObserver> observer) override; @@ -41,6 +52,10 @@ chromium::web::NavigationEventObserverPtr observer_; base::OnceClosure on_set_observer_callback_; + chromium::web::NavigationController* navigation_controller_ = nullptr; + fidl::BindingSet<chromium::web::NavigationController> + navigation_controller_bindings_; + DISALLOW_COPY_AND_ASSIGN(FakeFrame); };